fix: prevent auto-mode model switches from persisting as global default (#30) and harden resume resilience (#16)
Patch SDK setModel() to accept { persist: false } so per-unit model
switching in auto-mode no longer overwrites the user's global default.
Add state rebuild + doctor on resume, guard logging for silent dispatch
failures, and active-state check before prompt injection.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
f4c46516a6
commit
1872e8db78
2 changed files with 77 additions and 3 deletions
|
|
@ -1,3 +1,63 @@
|
|||
diff --git a/node_modules/@mariozechner/pi-coding-agent/dist/core/agent-session.js b/node_modules/@mariozechner/pi-coding-agent/dist/core/agent-session.js
|
||||
index 90622c2..cff094b 100644
|
||||
--- a/node_modules/@mariozechner/pi-coding-agent/dist/core/agent-session.js
|
||||
+++ b/node_modules/@mariozechner/pi-coding-agent/dist/core/agent-session.js
|
||||
@@ -1007,7 +1007,7 @@ export class AgentSession {
|
||||
* Validates API key, saves to session and settings.
|
||||
* @throws Error if no API key available for the model
|
||||
*/
|
||||
- async setModel(model) {
|
||||
+ async setModel(model, options) {
|
||||
const apiKey = await this._modelRegistry.getApiKey(model);
|
||||
if (!apiKey) {
|
||||
throw new Error(`No API key for ${model.provider}/${model.id}`);
|
||||
@@ -1016,7 +1016,9 @@ export class AgentSession {
|
||||
const thinkingLevel = this._getThinkingLevelForModelSwitch();
|
||||
this.agent.setModel(model);
|
||||
this.sessionManager.appendModelChange(model.provider, model.id);
|
||||
- this.settingsManager.setDefaultModelAndProvider(model.provider, model.id);
|
||||
+ if (options?.persist !== false) {
|
||||
+ this.settingsManager.setDefaultModelAndProvider(model.provider, model.id);
|
||||
+ }
|
||||
// Re-clamp thinking level for new model's capabilities
|
||||
this.setThinkingLevel(thinkingLevel);
|
||||
await this._emitModelSelect(model, previousModel, "set");
|
||||
@@ -1067,7 +1069,9 @@ export class AgentSession {
|
||||
// Apply model
|
||||
this.agent.setModel(next.model);
|
||||
this.sessionManager.appendModelChange(next.model.provider, next.model.id);
|
||||
- this.settingsManager.setDefaultModelAndProvider(next.model.provider, next.model.id);
|
||||
+ if (options?.persist !== false) {
|
||||
+ this.settingsManager.setDefaultModelAndProvider(next.model.provider, next.model.id);
|
||||
+ }
|
||||
// Apply thinking level.
|
||||
// - Explicit scoped model thinking level overrides current session level
|
||||
// - Undefined scoped model thinking level inherits the current session preference
|
||||
@@ -1094,7 +1098,9 @@ export class AgentSession {
|
||||
const thinkingLevel = this._getThinkingLevelForModelSwitch();
|
||||
this.agent.setModel(nextModel);
|
||||
this.sessionManager.appendModelChange(nextModel.provider, nextModel.id);
|
||||
- this.settingsManager.setDefaultModelAndProvider(nextModel.provider, nextModel.id);
|
||||
+ if (options?.persist !== false) {
|
||||
+ this.settingsManager.setDefaultModelAndProvider(nextModel.provider, nextModel.id);
|
||||
+ }
|
||||
// Re-clamp thinking level for new model's capabilities
|
||||
this.setThinkingLevel(thinkingLevel);
|
||||
await this._emitModelSelect(nextModel, currentModel, "cycle");
|
||||
@@ -1659,11 +1665,11 @@ export class AgentSession {
|
||||
setActiveTools: (toolNames) => this.setActiveToolsByName(toolNames),
|
||||
refreshTools: () => this._refreshToolRegistry(),
|
||||
getCommands,
|
||||
- setModel: async (model) => {
|
||||
+ setModel: async (model, options) => {
|
||||
const key = await this.modelRegistry.getApiKey(model);
|
||||
if (!key)
|
||||
return false;
|
||||
- await this.setModel(model);
|
||||
+ await this.setModel(model, options);
|
||||
return true;
|
||||
},
|
||||
getThinkingLevel: () => this.thinkingLevel,
|
||||
diff --git a/node_modules/@mariozechner/pi-coding-agent/dist/core/tools/bash.js b/node_modules/@mariozechner/pi-coding-agent/dist/core/tools/bash.js
|
||||
index 27fe820..68f277f 100644
|
||||
--- a/node_modules/@mariozechner/pi-coding-agent/dist/core/tools/bash.js
|
||||
|
|
|
|||
|
|
@ -247,6 +247,14 @@ export async function startAuto(
|
|||
if (!getLedger()) initMetrics(base);
|
||||
ctx.ui.setStatus("gsd-auto", stepMode ? "next" : "auto");
|
||||
ctx.ui.notify(stepMode ? "Step-mode resumed." : "Auto-mode resumed.", "info");
|
||||
// Rebuild disk state before resuming — user interaction during pause may have changed files
|
||||
try { await rebuildState(base); } catch { /* non-fatal */ }
|
||||
try {
|
||||
const report = await runGSDDoctor(base, { fix: true });
|
||||
if (report.fixesApplied.length > 0) {
|
||||
ctx.ui.notify(`Resume: applied ${report.fixesApplied.length} fix(es) to state.`, "info");
|
||||
}
|
||||
} catch { /* non-fatal */ }
|
||||
await dispatchNextUnit(ctx, pi);
|
||||
return;
|
||||
}
|
||||
|
|
@ -758,7 +766,12 @@ async function dispatchNextUnit(
|
|||
ctx: ExtensionContext,
|
||||
pi: ExtensionAPI,
|
||||
): Promise<void> {
|
||||
if (!active || !cmdCtx) return;
|
||||
if (!active || !cmdCtx) {
|
||||
if (active && !cmdCtx) {
|
||||
ctx.ui.notify("Auto-mode dispatch failed: no command context. Run /gsd auto to restart.", "error");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
let state = await deriveState(basePath);
|
||||
let mid = state.activeMilestone?.id;
|
||||
|
|
@ -1086,7 +1099,7 @@ async function dispatchNextUnit(
|
|||
const allModels = ctx.modelRegistry.getAll();
|
||||
const model = allModels.find(m => m.id === preferredModelId);
|
||||
if (model) {
|
||||
const ok = await pi.setModel(model);
|
||||
const ok = await pi.setModel(model, { persist: false });
|
||||
if (ok) {
|
||||
ctx.ui.notify(`Model: ${preferredModelId}`, "info");
|
||||
}
|
||||
|
|
@ -1186,7 +1199,8 @@ async function dispatchNextUnit(
|
|||
await pauseAuto(ctx, pi);
|
||||
}, hardTimeoutMs);
|
||||
|
||||
// Inject prompt
|
||||
// Inject prompt — verify auto-mode still active (guards against race with timeout/pause)
|
||||
if (!active) return;
|
||||
pi.sendMessage(
|
||||
{ customType: "gsd-auto", content: finalPrompt, display: verbose },
|
||||
{ triggerTurn: true },
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue