From bf5f4b17c0b78f823aec1eabcf8ddf084bda34a9 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Tue, 11 Nov 2025 23:56:08 +0100 Subject: [PATCH] Add custom session events for thinking level and model changes Session manager changes: - Add ThinkingLevelChangeEntry and ModelChangeEntry types - Add saveThinkingLevelChange() and saveModelChange() methods - Update loadThinkingLevel() to also check for thinking_level_change events (not just session headers) TUI changes: - Pass SessionManager to TuiRenderer constructor - Call saveThinkingLevelChange() when user changes thinking level via /thinking - Store session manager as instance variable for future use This ensures thinking level changes during a session are persisted and correctly restored on --continue. --- packages/coding-agent/src/main.ts | 4 +-- packages/coding-agent/src/session-manager.ts | 34 ++++++++++++++++++- packages/coding-agent/src/tui/tui-renderer.ts | 8 ++++- 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/packages/coding-agent/src/main.ts b/packages/coding-agent/src/main.ts index f9a30ad0..83931196 100644 --- a/packages/coding-agent/src/main.ts +++ b/packages/coding-agent/src/main.ts @@ -114,8 +114,8 @@ Guidelines: Current directory: ${process.cwd()}`; -async function runInteractiveMode(agent: Agent, _sessionManager: SessionManager, version: string): Promise { - const renderer = new TuiRenderer(agent, version); +async function runInteractiveMode(agent: Agent, sessionManager: SessionManager, version: string): Promise { + const renderer = new TuiRenderer(agent, sessionManager, version); // Initialize TUI await renderer.init(); diff --git a/packages/coding-agent/src/session-manager.ts b/packages/coding-agent/src/session-manager.ts index df084a3a..e0219c86 100644 --- a/packages/coding-agent/src/session-manager.ts +++ b/packages/coding-agent/src/session-manager.ts @@ -34,6 +34,18 @@ export interface SessionEventEntry { event: AgentEvent; } +export interface ThinkingLevelChangeEntry { + type: "thinking_level_change"; + timestamp: string; + thinkingLevel: string; +} + +export interface ModelChangeEntry { + type: "model_change"; + timestamp: string; + model: string; +} + export class SessionManager { private sessionId!: string; private sessionFile!: string; @@ -139,6 +151,24 @@ export class SessionManager { appendFileSync(this.sessionFile, JSON.stringify(entry) + "\n"); } + saveThinkingLevelChange(thinkingLevel: string): void { + const entry: ThinkingLevelChangeEntry = { + type: "thinking_level_change", + timestamp: new Date().toISOString(), + thinkingLevel, + }; + appendFileSync(this.sessionFile, JSON.stringify(entry) + "\n"); + } + + saveModelChange(model: string): void { + const entry: ModelChangeEntry = { + type: "model_change", + timestamp: new Date().toISOString(), + model, + }; + appendFileSync(this.sessionFile, JSON.stringify(entry) + "\n"); + } + loadMessages(): any[] { if (!existsSync(this.sessionFile)) return []; @@ -164,13 +194,15 @@ export class SessionManager { const lines = readFileSync(this.sessionFile, "utf8").trim().split("\n"); - // Find the most recent session header with thinking level + // Find the most recent thinking level (from session header or change event) let lastThinkingLevel = "off"; for (const line of lines) { try { const entry = JSON.parse(line); if (entry.type === "session" && entry.thinkingLevel) { lastThinkingLevel = entry.thinkingLevel; + } else if (entry.type === "thinking_level_change" && entry.thinkingLevel) { + lastThinkingLevel = entry.thinkingLevel; } } catch { // Skip malformed lines diff --git a/packages/coding-agent/src/tui/tui-renderer.ts b/packages/coding-agent/src/tui/tui-renderer.ts index a0a008c1..6e0bac2e 100644 --- a/packages/coding-agent/src/tui/tui-renderer.ts +++ b/packages/coding-agent/src/tui/tui-renderer.ts @@ -11,6 +11,7 @@ import { TUI, } from "@mariozechner/pi-tui"; import chalk from "chalk"; +import type { SessionManager } from "../session-manager.js"; import { AssistantMessageComponent } from "./assistant-message.js"; import { CustomEditor } from "./custom-editor.js"; import { FooterComponent } from "./footer.js"; @@ -29,6 +30,7 @@ export class TuiRenderer { private editorContainer: Container; // Container to swap between editor and selector private footer: FooterComponent; private agent: Agent; + private sessionManager: SessionManager; private version: string; private isInitialized = false; private onInputCallback?: (text: string) => void; @@ -48,8 +50,9 @@ export class TuiRenderer { // Track if this is the first user message (to skip spacer) private isFirstUserMessage = true; - constructor(agent: Agent, version: string) { + constructor(agent: Agent, sessionManager: SessionManager, version: string) { this.agent = agent; + this.sessionManager = sessionManager; this.version = version; this.ui = new TUI(new ProcessTerminal()); this.chatContainer = new Container(); @@ -409,6 +412,9 @@ export class TuiRenderer { // Apply the selected thinking level this.agent.setThinkingLevel(level); + // Save thinking level change to session + this.sessionManager.saveThinkingLevelChange(level); + // Show confirmation message with proper spacing this.chatContainer.addChild(new Spacer(1)); const confirmText = new Text(chalk.dim(`Thinking level: ${level}`), 1, 0);