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>
108 lines
5.6 KiB
Diff
108 lines
5.6 KiB
Diff
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
|
|
+++ b/node_modules/@mariozechner/pi-coding-agent/dist/core/tools/bash.js
|
|
@@ -1,11 +1,35 @@
|
|
import { randomBytes } from "node:crypto";
|
|
import { createWriteStream, existsSync } from "node:fs";
|
|
+import { createRequire } from "node:module";
|
|
import { tmpdir } from "node:os";
|
|
import { join } from "node:path";
|
|
import { Type } from "@sinclair/typebox";
|
|
import { spawn } from "child_process";
|
|
import { getShellConfig, getShellEnv, killProcessTree } from "../../utils/shell.js";
|
|
import { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize, truncateTail } from "./truncate.js";
|
|
+// Cached Win32 FFI handles for restoring VT input after child processes
|
|
+let _vtHandles = null;
|
|
+function restoreWindowsVTInput() {
|
|
+ if (process.platform !== "win32") return;
|
|
+ try {
|
|
+ if (!_vtHandles) {
|
|
+ const cjsRequire = createRequire(import.meta.url);
|
|
+ const koffi = cjsRequire("koffi");
|
|
+ const k32 = koffi.load("kernel32.dll");
|
|
+ const GetStdHandle = k32.func("void* __stdcall GetStdHandle(int)");
|
|
+ const GetConsoleMode = k32.func("bool __stdcall GetConsoleMode(void*, _Out_ uint32_t*)");
|
|
+ const SetConsoleMode = k32.func("bool __stdcall SetConsoleMode(void*, uint32_t)");
|
|
+ const handle = GetStdHandle(-10);
|
|
+ _vtHandles = { GetConsoleMode, SetConsoleMode, handle };
|
|
+ }
|
|
+ const ENABLE_VIRTUAL_TERMINAL_INPUT = 0x0200;
|
|
+ const mode = new Uint32Array(1);
|
|
+ _vtHandles.GetConsoleMode(_vtHandles.handle, mode);
|
|
+ if (!(mode[0] & ENABLE_VIRTUAL_TERMINAL_INPUT)) {
|
|
+ _vtHandles.SetConsoleMode(_vtHandles.handle, mode[0] | ENABLE_VIRTUAL_TERMINAL_INPUT);
|
|
+ }
|
|
+ } catch { }
|
|
+}
|
|
/**
|
|
* Generate a unique temp file path for bash output
|
|
*/
|
|
@@ -76,6 +100,7 @@ const defaultBashOperations = {
|
|
}
|
|
// Handle process exit
|
|
child.on("close", (code) => {
|
|
+ restoreWindowsVTInput();
|
|
if (timeoutHandle)
|
|
clearTimeout(timeoutHandle);
|
|
if (signal)
|