@caupulican/pi-adaptative 0.81.22 → 0.81.24
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/dist/core/agent-session.d.ts +5 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +28 -20
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/autonomy/status.d.ts +2 -3
- package/dist/core/autonomy/status.d.ts.map +1 -1
- package/dist/core/autonomy/status.js +3 -12
- package/dist/core/autonomy/status.js.map +1 -1
- package/dist/core/autonomy-telemetry.d.ts +3 -8
- package/dist/core/autonomy-telemetry.d.ts.map +1 -1
- package/dist/core/autonomy-telemetry.js +15 -20
- package/dist/core/autonomy-telemetry.js.map +1 -1
- package/dist/core/cost/cost-summary.d.ts +26 -0
- package/dist/core/cost/cost-summary.d.ts.map +1 -0
- package/dist/core/cost/cost-summary.js +85 -0
- package/dist/core/cost/cost-summary.js.map +1 -0
- package/dist/core/cost/session-usage.d.ts.map +1 -1
- package/dist/core/cost/session-usage.js +8 -2
- package/dist/core/cost/session-usage.js.map +1 -1
- package/dist/core/failure-corpus.d.ts +10 -1
- package/dist/core/failure-corpus.d.ts.map +1 -1
- package/dist/core/failure-corpus.js +32 -26
- package/dist/core/failure-corpus.js.map +1 -1
- package/dist/core/session-analytics.d.ts +10 -2
- package/dist/core/session-analytics.d.ts.map +1 -1
- package/dist/core/session-analytics.js +75 -29
- package/dist/core/session-analytics.js.map +1 -1
- package/dist/core/settings-manager.d.ts +1 -1
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/tool-recovery-log-records.d.ts +24 -0
- package/dist/core/tool-recovery-log-records.d.ts.map +1 -0
- package/dist/core/tool-recovery-log-records.js +63 -0
- package/dist/core/tool-recovery-log-records.js.map +1 -0
- package/dist/core/tool-recovery-log-worker.d.ts +2 -0
- package/dist/core/tool-recovery-log-worker.d.ts.map +1 -0
- package/dist/core/tool-recovery-log-worker.js +44 -0
- package/dist/core/tool-recovery-log-worker.js.map +1 -0
- package/dist/core/tool-recovery-logger.d.ts +59 -0
- package/dist/core/tool-recovery-logger.d.ts.map +1 -0
- package/dist/core/tool-recovery-logger.js +197 -0
- package/dist/core/tool-recovery-logger.js.map +1 -0
- package/dist/core/tool-repair-health.d.ts +2 -1
- package/dist/core/tool-repair-health.d.ts.map +1 -1
- package/dist/core/tool-repair-health.js +13 -4
- package/dist/core/tool-repair-health.js.map +1 -1
- package/dist/core/tool-repair-settings.d.ts +1 -0
- package/dist/core/tool-repair-settings.d.ts.map +1 -1
- package/dist/core/tool-repair-settings.js +2 -1
- package/dist/core/tool-repair-settings.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +4 -20
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/report-commands.d.ts.map +1 -1
- package/dist/modes/interactive/report-commands.js +7 -8
- package/dist/modes/interactive/report-commands.js.map +1 -1
- package/dist/modes/interactive/session-flow-commands.d.ts +1 -2
- package/dist/modes/interactive/session-flow-commands.d.ts.map +1 -1
- package/dist/modes/interactive/session-flow-commands.js +8 -4
- package/dist/modes/interactive/session-flow-commands.js.map +1 -1
- package/docs/settings.md +6 -4
- package/docs/tool-repair.md +8 -7
- package/docs/usage.md +6 -0
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +12 -12
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-flow-commands.d.ts","sourceRoot":"","sources":["../../../src/modes/interactive/session-flow-commands.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Session-picker, tree/fork navigation, and model-selector flows extracted from\n * interactive-mode.\n *\n * Each entry opens a selector overlay (via `host.showSelector`) or renders a\n * session-info block, driving `AgentSession`/`AgentSessionRuntime` navigation and\n * the fork/resume/clone/goal-continuation paths. The interdependent selector\n * flows share one narrow `SessionFlowHost` seam; the three prototype-tested leaf\n * commands (`handleCloneCommand`, `handleGoalContinueCommand`,\n * `handleSessionCommand`) take their own minimal host shapes so their behaviour\n * tests keep exercising them through interactive-mode's thin wrappers unchanged.\n */\n\nimport type { SessionManager } from \"@caupulican/pi-agent-core/node\";\nimport type { Model } from \"@caupulican/pi-ai\";\nimport type { EditorComponent } from \"@caupulican/pi-tui\";\nimport { type Component, type Container, Loader, Spacer, Text, type TUI } from \"@caupulican/pi-tui\";\nimport type {\n\tAgentSession,\n\tGoalContinuationLoopOptions,\n\tGoalContinuationLoopResult,\n} from \"../../core/agent-session.ts\";\nimport type { AgentSessionRuntime } from \"../../core/agent-session-runtime.ts\";\nimport type { ExtensionCommandContext } from \"../../core/extensions/index.ts\";\nimport type { GoalState } from \"../../core/goals/goal-state.ts\";\nimport { applyGoalAction } from \"../../core/goals/goal-tool-core.ts\";\nimport type { KeybindingsManager } from \"../../core/keybindings.ts\";\nimport { findExactModelReferenceMatch, resolveModelScope } from \"../../core/model-resolver.ts\";\nimport { MissingSessionCwdError } from \"../../core/session-cwd.ts\";\nimport { listAllSessions, listSessions, openSession } from \"../../core/session-manager-factory.ts\";\nimport type { SettingsManager } from \"../../core/settings-manager.ts\";\nimport { ProjectTrustStore } from \"../../core/trust-manager.ts\";\nimport type { CustomEditor } from \"./components/custom-editor.ts\";\nimport type { FooterComponent } from \"./components/footer.ts\";\nimport { keyText } from \"./components/keybinding-hints.ts\";\nimport { ModelSelectorComponent } from \"./components/model-selector.ts\";\nimport { ScopedModelsSelectorComponent } from \"./components/scoped-models-selector.ts\";\nimport { SessionSelectorComponent } from \"./components/session-selector.ts\";\nimport { TreeSelectorComponent } from \"./components/tree-selector.ts\";\nimport { TrustSelectorComponent } from \"./components/trust-selector.ts\";\nimport { UserMessageSelectorComponent } from \"./components/user-message-selector.ts\";\nimport type { ExtensionUiHost } from \"./extension-ui-host.ts\";\nimport { theme } from \"./theme/theme.ts\";\n\n/** Shared seam for the interdependent selector/navigation flows. */\nexport interface SessionFlowHost {\n\treadonly session: AgentSession;\n\treadonly sessionManager: SessionManager;\n\treadonly settingsManager: SettingsManager;\n\treadonly runtimeHost: AgentSessionRuntime;\n\treadonly ui: TUI;\n\treadonly chatContainer: Container;\n\treadonly statusContainer: Container;\n\treadonly editor: EditorComponent;\n\treadonly defaultEditor: CustomEditor;\n\treadonly footer: FooterComponent;\n\treadonly extensionUiHost: ExtensionUiHost;\n\treadonly keybindings: KeybindingsManager;\n\tloadingAnimation: Loader | undefined;\n\tshowSelector(create: (done: () => void) => { component: Component; focus: Component }): void;\n\tshowStatus(message: string): void;\n\tshowError(message: string): void;\n\trenderCurrentSessionState(): void;\n\trenderInitialMessages(options?: { forceHistoryLoad?: boolean }): Promise<void>;\n\tflushCompactionQueue(options?: { willRetry?: boolean }): Promise<void>;\n\thandleFatalRuntimeError(prefix: string, error: unknown): Promise<never>;\n\tpromptForMissingSessionCwd(error: MissingSessionCwdError): Promise<string | undefined>;\n\tupdateEditorBorderColor(): void;\n\tupdateAvailableProviderCount(): Promise<void>;\n\tmaybeWarnAboutAnthropicSubscriptionAuth(model?: Model<any>): Promise<void>;\n\tcheckDaxnutsEasterEgg(model: { provider: string; id: string }): void;\n\tgetModelCandidates(): Promise<Model<any>[]>;\n\tshutdown(options?: { fromSignal?: boolean }): Promise<void>;\n}\n\nexport async function showModelSelector(host: SessionFlowHost, initialSearchInput?: string): Promise<void> {\n\ttry {\n\t\tawait host.session.extensionRunner.emit({\n\t\t\ttype: \"model_selector_open\",\n\t\t\tcurrentModel: host.session.model,\n\t\t\tscopedModels: host.session.scopedModels,\n\t\t\tinitialSearchInput,\n\t\t});\n\t} catch (error) {\n\t\thost.showError(error instanceof Error ? error.message : String(error));\n\t\treturn;\n\t}\n\n\thost.showSelector((done) => {\n\t\tconst selector = new ModelSelectorComponent(\n\t\t\thost.ui,\n\t\t\thost.session.model,\n\t\t\thost.settingsManager,\n\t\t\thost.session.modelRegistry,\n\t\t\thost.session.scopedModels,\n\t\t\tasync (model) => {\n\t\t\t\ttry {\n\t\t\t\t\tawait host.session.setModel(model);\n\t\t\t\t\thost.footer.invalidate();\n\t\t\t\t\thost.updateEditorBorderColor();\n\t\t\t\t\tdone();\n\t\t\t\t\thost.showStatus(`Model: ${model.id}`);\n\t\t\t\t\tvoid host.maybeWarnAboutAnthropicSubscriptionAuth(model);\n\t\t\t\t\thost.checkDaxnutsEasterEgg(model);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tdone();\n\t\t\t\t\thost.showError(error instanceof Error ? error.message : String(error));\n\t\t\t\t}\n\t\t\t},\n\t\t\t() => {\n\t\t\t\tdone();\n\t\t\t\thost.ui.requestRender();\n\t\t\t},\n\t\t\tinitialSearchInput,\n\t\t);\n\t\treturn { component: selector, focus: selector };\n\t});\n}\n\nexport async function showModelsSelector(host: SessionFlowHost): Promise<void> {\n\t// Get all available models\n\thost.session.modelRegistry.refresh();\n\tconst allModels = host.session.modelRegistry.getAvailable();\n\n\tif (allModels.length === 0) {\n\t\thost.showStatus(\"No models available\");\n\t\treturn;\n\t}\n\n\t// Check if session has scoped models (from previous session-only changes or CLI --models)\n\tconst sessionScopedModels = host.session.scopedModels;\n\tconst hasSessionScope = sessionScopedModels.length > 0;\n\n\t// Build enabled model IDs from session state or settings\n\tlet currentEnabledIds: string[] | null = null;\n\n\tif (hasSessionScope) {\n\t\t// Use current session's scoped models\n\t\tcurrentEnabledIds = sessionScopedModels.map((scoped) => `${scoped.model.provider}/${scoped.model.id}`);\n\t} else {\n\t\t// Fall back to settings\n\t\tconst patterns = host.settingsManager.getEnabledModels();\n\t\tif (patterns !== undefined && patterns.length > 0) {\n\t\t\tconst scopedModels = await resolveModelScope(patterns, host.session.modelRegistry);\n\t\t\tcurrentEnabledIds = scopedModels.map((scoped) => `${scoped.model.provider}/${scoped.model.id}`);\n\t\t}\n\t}\n\n\t// Helper to update session's scoped models (session-only, no persist)\n\tconst updateSessionModels = async (enabledIds: string[] | null) => {\n\t\tcurrentEnabledIds = enabledIds === null ? null : [...enabledIds];\n\t\tif (enabledIds && enabledIds.length > 0 && enabledIds.length < allModels.length) {\n\t\t\tconst newScopedModels = await resolveModelScope(enabledIds, host.session.modelRegistry);\n\t\t\thost.session.setScopedModels(\n\t\t\t\tnewScopedModels.map((sm) => ({\n\t\t\t\t\tmodel: sm.model,\n\t\t\t\t\tthinkingLevel: sm.thinkingLevel,\n\t\t\t\t})),\n\t\t\t);\n\t\t} else {\n\t\t\t// All enabled or none enabled = no filter\n\t\t\thost.session.setScopedModels([]);\n\t\t}\n\t\tawait host.updateAvailableProviderCount();\n\t\thost.ui.requestRender();\n\t};\n\n\thost.showSelector((done) => {\n\t\tconst selector = new ScopedModelsSelectorComponent(\n\t\t\t{\n\t\t\t\tallModels,\n\t\t\t\tenabledModelIds: currentEnabledIds,\n\t\t\t},\n\t\t\t{\n\t\t\t\tonChange: async (enabledIds) => {\n\t\t\t\t\tawait updateSessionModels(enabledIds);\n\t\t\t\t},\n\t\t\t\tonPersist: (enabledIds) => {\n\t\t\t\t\t// Persist to settings\n\t\t\t\t\tconst newPatterns =\n\t\t\t\t\t\tenabledIds === null || enabledIds.length === allModels.length\n\t\t\t\t\t\t\t? undefined // All enabled = clear filter\n\t\t\t\t\t\t\t: enabledIds;\n\t\t\t\t\thost.settingsManager.setEnabledModels(newPatterns ? [...newPatterns] : undefined);\n\t\t\t\t\thost.showStatus(\"Model selection saved to settings\");\n\t\t\t\t},\n\t\t\t\tonCancel: () => {\n\t\t\t\t\tdone();\n\t\t\t\t\thost.ui.requestRender();\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\t\treturn { component: selector, focus: selector };\n\t});\n}\n\nexport function showUserMessageSelector(host: SessionFlowHost, newSessionName?: string): void {\n\tconst userMessages = host.session.getUserMessagesForForking();\n\n\tif (userMessages.length === 0) {\n\t\thost.showStatus(\"No messages to fork from\");\n\t\treturn;\n\t}\n\n\tconst initialSelectedId = userMessages[userMessages.length - 1]?.entryId;\n\n\thost.showSelector((done) => {\n\t\tconst selector = new UserMessageSelectorComponent(\n\t\t\tuserMessages.map((m) => ({ id: m.entryId, text: m.text })),\n\t\t\tasync (entryId) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await host.runtimeHost.fork(entryId);\n\t\t\t\t\tif (result.cancelled) {\n\t\t\t\t\t\tdone();\n\t\t\t\t\t\thost.ui.requestRender();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\thost.renderCurrentSessionState();\n\t\t\t\t\tif (newSessionName) {\n\t\t\t\t\t\thost.session.setSessionName(newSessionName);\n\t\t\t\t\t}\n\t\t\t\t\thost.editor.setText(result.selectedText ?? \"\");\n\t\t\t\t\tdone();\n\t\t\t\t\thost.showStatus(newSessionName ? `Forked to new session: ${newSessionName}` : \"Forked to new session\");\n\t\t\t\t} catch (error: unknown) {\n\t\t\t\t\tdone();\n\t\t\t\t\thost.showError(error instanceof Error ? error.message : String(error));\n\t\t\t\t}\n\t\t\t},\n\t\t\t() => {\n\t\t\t\tdone();\n\t\t\t\thost.ui.requestRender();\n\t\t\t},\n\t\t\tinitialSelectedId,\n\t\t);\n\t\treturn { component: selector, focus: selector.getMessageList() };\n\t});\n}\n\nexport function showTreeSelector(host: SessionFlowHost, initialSelectedId?: string): void {\n\tconst tree = host.sessionManager.getTree();\n\tconst realLeafId = host.sessionManager.getLeafId();\n\tconst initialFilterMode = host.settingsManager.getTreeFilterMode();\n\n\tif (tree.length === 0) {\n\t\thost.showStatus(\"No entries in session\");\n\t\treturn;\n\t}\n\n\thost.showSelector((done) => {\n\t\tconst selector = new TreeSelectorComponent(\n\t\t\ttree,\n\t\t\trealLeafId,\n\t\t\thost.ui.terminal.rows,\n\t\t\tasync (entryId) => {\n\t\t\t\t// Selecting the current leaf is a no-op (already there)\n\t\t\t\tif (entryId === realLeafId) {\n\t\t\t\t\tdone();\n\t\t\t\t\thost.showStatus(\"Already at this point\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Ask about summarization\n\t\t\t\tdone(); // Close selector first\n\n\t\t\t\t// Loop until user makes a complete choice or cancels to tree\n\t\t\t\tlet wantsSummary = false;\n\t\t\t\tlet customInstructions: string | undefined;\n\n\t\t\t\t// Check if we should skip the prompt (user preference to always default to no summary)\n\t\t\t\tif (!host.settingsManager.getBranchSummarySkipPrompt()) {\n\t\t\t\t\twhile (true) {\n\t\t\t\t\t\tconst summaryChoice = await host.extensionUiHost.showExtensionSelector(\"Summarize branch?\", [\n\t\t\t\t\t\t\t\"No summary\",\n\t\t\t\t\t\t\t\"Summarize\",\n\t\t\t\t\t\t\t\"Summarize with custom prompt\",\n\t\t\t\t\t\t]);\n\n\t\t\t\t\t\tif (summaryChoice === undefined) {\n\t\t\t\t\t\t\t// User pressed escape - re-show tree selector with same selection\n\t\t\t\t\t\t\tshowTreeSelector(host, entryId);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\twantsSummary = summaryChoice !== \"No summary\";\n\n\t\t\t\t\t\tif (summaryChoice === \"Summarize with custom prompt\") {\n\t\t\t\t\t\t\tcustomInstructions = await host.extensionUiHost.showExtensionEditor(\n\t\t\t\t\t\t\t\t\"Custom summarization instructions\",\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tif (customInstructions === undefined) {\n\t\t\t\t\t\t\t\t// User cancelled - loop back to summary selector\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// User made a complete choice\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Set up escape handler and loader if summarizing\n\t\t\t\tlet summaryLoader: Loader | undefined;\n\t\t\t\tconst originalOnEscape = host.defaultEditor.onEscape;\n\n\t\t\t\tif (wantsSummary) {\n\t\t\t\t\thost.defaultEditor.onEscape = () => {\n\t\t\t\t\t\thost.session.abortBranchSummary();\n\t\t\t\t\t};\n\t\t\t\t\thost.chatContainer.addChild(new Spacer(1));\n\t\t\t\t\tsummaryLoader = new Loader(\n\t\t\t\t\t\thost.ui,\n\t\t\t\t\t\t(spinner) => theme.fg(\"accent\", spinner),\n\t\t\t\t\t\t(text) => theme.fg(\"muted\", text),\n\t\t\t\t\t\t`Summarizing branch... (${keyText(\"app.interrupt\")} to cancel)`,\n\t\t\t\t\t);\n\t\t\t\t\thost.statusContainer.addChild(summaryLoader);\n\t\t\t\t\thost.ui.requestRender();\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await host.session.navigateTree(entryId, {\n\t\t\t\t\t\tsummarize: wantsSummary,\n\t\t\t\t\t\tcustomInstructions,\n\t\t\t\t\t});\n\n\t\t\t\t\tif (result.aborted) {\n\t\t\t\t\t\t// Summarization aborted - re-show tree selector with same selection\n\t\t\t\t\t\thost.showStatus(\"Branch summarization cancelled\");\n\t\t\t\t\t\tshowTreeSelector(host, entryId);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (result.cancelled) {\n\t\t\t\t\t\thost.showStatus(\"Navigation cancelled\");\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Update UI\n\t\t\t\t\tawait host.renderInitialMessages();\n\t\t\t\t\tif (result.editorText && !host.editor.getText().trim()) {\n\t\t\t\t\t\thost.editor.setText(result.editorText);\n\t\t\t\t\t}\n\t\t\t\t\thost.showStatus(\"Navigated to selected point\");\n\t\t\t\t\tvoid host.flushCompactionQueue({ willRetry: false });\n\t\t\t\t} catch (error) {\n\t\t\t\t\thost.showError(error instanceof Error ? error.message : String(error));\n\t\t\t\t} finally {\n\t\t\t\t\tif (summaryLoader) {\n\t\t\t\t\t\tsummaryLoader.stop();\n\t\t\t\t\t\thost.statusContainer.clear();\n\t\t\t\t\t}\n\t\t\t\t\thost.defaultEditor.onEscape = originalOnEscape;\n\t\t\t\t}\n\t\t\t},\n\t\t\t() => {\n\t\t\t\tdone();\n\t\t\t\thost.ui.requestRender();\n\t\t\t},\n\t\t\t(entryId, label) => {\n\t\t\t\thost.sessionManager.appendLabelChange(entryId, label);\n\t\t\t\thost.ui.requestRender();\n\t\t\t},\n\t\t\tinitialSelectedId,\n\t\t\tinitialFilterMode,\n\t\t);\n\t\treturn { component: selector, focus: selector };\n\t});\n}\n\nexport function showTrustSelector(host: SessionFlowHost): void {\n\tconst cwd = host.sessionManager.getCwd();\n\tconst trustStore = new ProjectTrustStore(host.runtimeHost.services.agentDir);\n\tconst savedDecision = trustStore.get(cwd);\n\thost.showSelector((done) => {\n\t\tconst selector = new TrustSelectorComponent({\n\t\t\tcwd,\n\t\t\tsavedDecision,\n\t\t\tprojectTrusted: host.settingsManager.isProjectTrusted(),\n\t\t\tonSelect: (trusted) => {\n\t\t\t\ttrustStore.set(cwd, trusted);\n\t\t\t\tdone();\n\t\t\t\thost.showStatus(\n\t\t\t\t\t`Saved trust decision: ${trusted ? \"trusted\" : \"untrusted\"}. Restart pi for this to take effect.`,\n\t\t\t\t);\n\t\t\t},\n\t\t\tonCancel: () => {\n\t\t\t\tdone();\n\t\t\t\thost.ui.requestRender();\n\t\t\t},\n\t\t});\n\t\treturn { component: selector, focus: selector };\n\t});\n}\n\nexport function showSessionSelector(host: SessionFlowHost): void {\n\thost.showSelector((done) => {\n\t\tconst selector = new SessionSelectorComponent(\n\t\t\t(onProgress) => listSessions(host.sessionManager.getCwd(), host.sessionManager.getSessionDir(), onProgress),\n\t\t\t(onProgress) =>\n\t\t\t\thost.sessionManager.usesDefaultSessionDir()\n\t\t\t\t\t? listAllSessions(onProgress)\n\t\t\t\t\t: listAllSessions(host.sessionManager.getSessionDir(), onProgress),\n\t\t\tasync (sessionPath) => {\n\t\t\t\tdone();\n\t\t\t\tawait handleResumeSession(host, sessionPath);\n\t\t\t},\n\t\t\t() => {\n\t\t\t\tdone();\n\t\t\t\thost.ui.requestRender();\n\t\t\t},\n\t\t\t() => {\n\t\t\t\tvoid host.shutdown();\n\t\t\t},\n\t\t\t() => host.ui.requestRender(),\n\t\t\t{\n\t\t\t\trenameSession: async (sessionFilePath: string, nextName: string | undefined) => {\n\t\t\t\t\tconst next = (nextName ?? \"\").trim();\n\t\t\t\t\tif (!next) return;\n\t\t\t\t\tconst mgr = openSession(sessionFilePath);\n\t\t\t\t\tmgr.appendSessionInfo(next);\n\t\t\t\t},\n\t\t\t\tshowRenameHint: true,\n\t\t\t\tkeybindings: host.keybindings,\n\t\t\t},\n\n\t\t\thost.sessionManager.getSessionFile(),\n\t\t);\n\t\treturn { component: selector, focus: selector };\n\t});\n}\n\nexport async function handleResumeSession(\n\thost: SessionFlowHost,\n\tsessionPath: string,\n\toptions?: Parameters<ExtensionCommandContext[\"switchSession\"]>[1],\n): Promise<{ cancelled: boolean }> {\n\tif (host.loadingAnimation) {\n\t\thost.loadingAnimation.stop();\n\t\thost.loadingAnimation = undefined;\n\t}\n\thost.statusContainer.clear();\n\ttry {\n\t\tconst result = await host.runtimeHost.switchSession(sessionPath, {\n\t\t\twithSession: options?.withSession,\n\t\t});\n\t\tif (result.cancelled) {\n\t\t\treturn result;\n\t\t}\n\t\thost.renderCurrentSessionState();\n\t\thost.showStatus(\"Resumed session\");\n\t\treturn result;\n\t} catch (error: unknown) {\n\t\tif (error instanceof MissingSessionCwdError) {\n\t\t\tconst selectedCwd = await host.promptForMissingSessionCwd(error);\n\t\t\tif (!selectedCwd) {\n\t\t\t\thost.showStatus(\"Resume cancelled\");\n\t\t\t\treturn { cancelled: true };\n\t\t\t}\n\t\t\tconst result = await host.runtimeHost.switchSession(sessionPath, {\n\t\t\t\tcwdOverride: selectedCwd,\n\t\t\t\twithSession: options?.withSession,\n\t\t\t});\n\t\t\tif (result.cancelled) {\n\t\t\t\treturn result;\n\t\t\t}\n\t\t\thost.renderCurrentSessionState();\n\t\t\thost.showStatus(\"Resumed session in current cwd\");\n\t\t\treturn result;\n\t\t}\n\t\treturn host.handleFatalRuntimeError(\"Failed to resume session\", error);\n\t}\n}\n\nexport async function handleModelCommand(host: SessionFlowHost, searchTerm?: string): Promise<void> {\n\tif (!searchTerm) {\n\t\tawait showModelSelector(host);\n\t\treturn;\n\t}\n\n\tconst model = await findExactModelMatch(host, searchTerm);\n\tif (model) {\n\t\ttry {\n\t\t\tawait host.session.setModel(model);\n\t\t\thost.footer.invalidate();\n\t\t\thost.updateEditorBorderColor();\n\t\t\thost.showStatus(`Model: ${model.id}`);\n\t\t\tvoid host.maybeWarnAboutAnthropicSubscriptionAuth(model);\n\t\t\thost.checkDaxnutsEasterEgg(model);\n\t\t} catch (error) {\n\t\t\thost.showError(error instanceof Error ? error.message : String(error));\n\t\t}\n\t\treturn;\n\t}\n\n\tawait showModelSelector(host, searchTerm);\n}\n\nexport async function findExactModelMatch(host: SessionFlowHost, searchTerm: string): Promise<Model<any> | undefined> {\n\tconst models = await host.getModelCandidates();\n\treturn findExactModelReferenceMatch(searchTerm, models);\n}\n\n// ===========================================================================\n// Prototype-tested leaf commands — narrow host shapes matching their fakes.\n// ===========================================================================\n\nexport interface CloneCommandHost {\n\treadonly sessionManager: { getLeafId: () => string | null };\n\treadonly runtimeHost: {\n\t\tfork: (entryId: string, options?: { position?: \"before\" | \"at\" }) => Promise<{ cancelled: boolean }>;\n\t};\n\trenderCurrentSessionState(): void;\n\treadonly editor: { setText: (text: string) => void };\n\treadonly session: { setSessionName: (name: string) => void };\n\tshowStatus(message: string): void;\n\tshowError(message: string): void;\n\treadonly ui: { requestRender: () => void };\n}\n\nexport async function handleCloneCommand(host: CloneCommandHost, newSessionName?: string): Promise<void> {\n\tconst leafId = host.sessionManager.getLeafId();\n\tif (!leafId) {\n\t\thost.showStatus(\"Nothing to clone yet\");\n\t\treturn;\n\t}\n\n\ttry {\n\t\tconst result = await host.runtimeHost.fork(leafId, { position: \"at\" });\n\t\tif (result.cancelled) {\n\t\t\thost.ui.requestRender();\n\t\t\treturn;\n\t\t}\n\n\t\thost.renderCurrentSessionState();\n\t\tif (newSessionName) {\n\t\t\thost.session.setSessionName(newSessionName);\n\t\t}\n\t\thost.editor.setText(\"\");\n\t\thost.showStatus(newSessionName ? `Cloned to new session: ${newSessionName}` : \"Cloned to new session\");\n\t} catch (error: unknown) {\n\t\thost.showError(error instanceof Error ? error.message : String(error));\n\t}\n}\n\nexport type ParsedGoalContinueCommand =\n\t| { ok: true; maxTurns: number; maxStallTurns: number; maxWallClockMinutes: number }\n\t| { ok: false; error: string };\n\nexport interface GoalCommandHost {\n\treadonly session: {\n\t\tgetGoalStateSnapshot: () => GoalState | undefined;\n\t\tsaveGoalStateSnapshot: (state: GoalState) => string;\n\t\tsendUserMessage: (content: string) => Promise<void>;\n\t\tcontinueGoalLoop: (options: GoalContinuationLoopOptions) => Promise<GoalContinuationLoopResult>;\n\t\tgetGoalRuntimeSnapshot: (settings: {\n\t\t\tmaxStallTurns: number;\n\t\t}) => ReturnType<AgentSession[\"getGoalRuntimeSnapshot\"]>;\n\t};\n\tshowStatus(message: string): void;\n\tshowError(message: string): void;\n\trefreshAutonomyFooterStatus(): void;\n}\n\nfunction formatGoalStatus(snapshot: ReturnType<AgentSession[\"getGoalRuntimeSnapshot\"]>): string {\n\tconst state = snapshot.goalState;\n\tif (!state) return `Goal: none (${snapshot.continuation.action}/${snapshot.continuation.reasonCode})`;\n\treturn `Goal: ${state.userGoal}\\nStatus: ${state.status}\\nRequirements: open ${snapshot.continuation.openRequirementIds.length}, blocked ${snapshot.continuation.blockedRequirementIds.length}, satisfied ${snapshot.continuation.satisfiedRequirementIds.length}\\nContinuation: ${snapshot.continuation.action}/${snapshot.continuation.reasonCode}`;\n}\n\nexport async function handleGoalCommand(host: GoalCommandHost, text: string): Promise<void> {\n\tconst goalText = text.replace(/^\\/goal\\s*/, \"\").trim();\n\tif (!goalText) {\n\t\thost.showStatus(formatGoalStatus(host.session.getGoalRuntimeSnapshot({ maxStallTurns: 20 })));\n\t\treturn;\n\t}\n\tconst now = new Date().toISOString();\n\tconst goalId = `goal-${Date.now().toString(36)}`;\n\tconst started = applyGoalAction(\n\t\thost.session.getGoalStateSnapshot(),\n\t\t{ action: \"start\", goalId, userGoal: goalText },\n\t\tnow,\n\t);\n\tif (!started.ok) {\n\t\thost.showError(started.error);\n\t\treturn;\n\t}\n\thost.session.saveGoalStateSnapshot(started.state);\n\t// Deterministic producer completion: a goal with zero open requirements evaluates to\n\t// finalize/no_open_requirements, so the loop would be undrivable whenever the model skips\n\t// decomposition (observed in the field). Seed one requirement from the goal text itself —\n\t// the model's decomposition below refines alongside it.\n\tconst seeded = applyGoalAction(\n\t\tstarted.state,\n\t\t{ action: \"add_requirement\", requirementId: `${goalId}-r1`, text: goalText },\n\t\tnow,\n\t);\n\tif (seeded.ok) {\n\t\thost.session.saveGoalStateSnapshot(seeded.state);\n\t}\n\tawait host.session.sendUserMessage(\n\t\t`Start goal: ${goalText}\\n\\nUse the goal tool this turn to decompose this goal into concrete open requirements with add_requirement actions, and satisfy_requirement ${goalId}-r1 once the decomposed requirements cover it.`,\n\t);\n\tconst result = await host.session.continueGoalLoop({ maxTurns: 1, maxStallTurns: 20, maxWallClockMinutes: 0 });\n\tconst continuation = result.finalSnapshot.continuation;\n\thost.showStatus(`Goal started: ${continuation.action}/${continuation.reasonCode}.`);\n\thost.refreshAutonomyFooterStatus();\n}\n\nexport interface GoalContinueCommandHost {\n\treadonly session: {\n\t\tcontinueGoalLoop: (options: GoalContinuationLoopOptions) => Promise<GoalContinuationLoopResult>;\n\t};\n\tparseGoalContinueCommand(text: string): ParsedGoalContinueCommand;\n\tshowStatus(message: string): void;\n\tshowError(message: string): void;\n\trefreshAutonomyFooterStatus(): void;\n}\n\nexport async function handleGoalContinueCommand(host: GoalContinueCommandHost, text: string): Promise<void> {\n\tconst parsed = host.parseGoalContinueCommand(text);\n\tif (!parsed.ok) {\n\t\thost.showError(parsed.error);\n\t\treturn;\n\t}\n\n\thost.showStatus(\n\t\t`Goal continuation started: up to ${parsed.maxTurns} turn(s), stall limit ${parsed.maxStallTurns}, wall-clock limit ${parsed.maxWallClockMinutes || \"disabled\"} minute(s).`,\n\t);\n\ttry {\n\t\tconst result = await host.session.continueGoalLoop({\n\t\t\tmaxTurns: parsed.maxTurns,\n\t\t\tmaxStallTurns: parsed.maxStallTurns,\n\t\t\tmaxWallClockMinutes: parsed.maxWallClockMinutes,\n\t\t});\n\t\tconst continuation = result.finalSnapshot.continuation;\n\t\thost.showStatus(\n\t\t\t`Goal continuation stopped: ${result.stopReason}; submitted ${result.turnsSubmitted} turn(s); latest decision ${continuation.action}/${continuation.reasonCode}.`,\n\t\t);\n\t} catch (error) {\n\t\thost.showError(`Goal continuation failed: ${error instanceof Error ? error.message : String(error)}`);\n\t} finally {\n\t\thost.refreshAutonomyFooterStatus();\n\t}\n}\n\nexport interface SessionInfoCommandHost {\n\treadonly session: {\n\t\tgetSessionStats: () => ReturnType<AgentSession[\"getSessionStats\"]>;\n\t\tgetDailyUsageTotals: () => ReturnType<AgentSession[\"getDailyUsageTotals\"]>;\n\t\tgetDailyUsageBreakdown: (formatLabel: (label: string) => string) => string;\n\t\tgetModelRouterStatus: (formatLabel: (label: string) => string) => string;\n\t};\n\treadonly sessionManager: { getSessionName: () => string | undefined };\n\treadonly chatContainer: Container;\n\treadonly ui: { requestRender: () => void };\n}\n\nexport function handleSessionCommand(host: SessionInfoCommandHost): void {\n\tconst stats = host.session.getSessionStats();\n\tconst sessionName = host.sessionManager.getSessionName();\n\n\tlet info = `${theme.bold(\"Session Info\")}\\n\\n`;\n\tif (sessionName) {\n\t\tinfo += `${theme.fg(\"dim\", \"Name:\")} ${sessionName}\\n`;\n\t}\n\tinfo += `${theme.fg(\"dim\", \"File:\")} ${stats.sessionFile ?? \"In-memory\"}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"ID:\")} ${stats.sessionId}\\n\\n`;\n\tinfo += `${theme.bold(\"Messages\")}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"User:\")} ${stats.userMessages}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Assistant:\")} ${stats.assistantMessages}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Tool Calls:\")} ${stats.toolCalls}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Tool Results:\")} ${stats.toolResults}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Total:\")} ${stats.totalMessages}\\n\\n`;\n\tinfo += `${theme.bold(\"Tokens\")}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Input:\")} ${stats.tokens.input.toLocaleString()}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Output:\")} ${stats.tokens.output.toLocaleString()}\\n`;\n\tif (stats.tokens.cacheRead > 0) {\n\t\tinfo += `${theme.fg(\"dim\", \"Cache Read:\")} ${stats.tokens.cacheRead.toLocaleString()}\\n`;\n\t}\n\tif (stats.tokens.cacheWrite > 0) {\n\t\tinfo += `${theme.fg(\"dim\", \"Cache Write:\")} ${stats.tokens.cacheWrite.toLocaleString()}\\n`;\n\t}\n\tinfo += `${theme.fg(\"dim\", \"Total:\")} ${stats.tokens.total.toLocaleString()}\\n`;\n\n\tconst dailyUsage = host.session.getDailyUsageTotals();\n\tif (stats.cost > 0 || dailyUsage.totalCost > 0) {\n\t\tinfo += `\\n${theme.bold(\"Cost\")}\\n`;\n\t\tinfo += `${theme.fg(\"dim\", \"Total:\")} $${stats.cost.toFixed(4)}\\n`;\n\t\tinfo += `${host.session.getDailyUsageBreakdown((label) => theme.fg(\"dim\", label))}`;\n\t}\n\n\tinfo += `\\n\\n${theme.bold(\"Model Router\")}\\n`;\n\tinfo += host.session.getModelRouterStatus((label) => theme.fg(\"dim\", label));\n\n\thost.chatContainer.addChild(new Spacer(1));\n\thost.chatContainer.addChild(new Text(info, 1, 0));\n\thost.ui.requestRender();\n}\n"]}
|
|
1
|
+
{"version":3,"file":"session-flow-commands.d.ts","sourceRoot":"","sources":["../../../src/modes/interactive/session-flow-commands.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAC1D,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,MAAM,EAAgB,KAAK,GAAG,EAAE,MAAM,oBAAoB,CAAC;AACpG,OAAO,KAAK,EACX,YAAY,EACZ,2BAA2B,EAC3B,0BAA0B,EAC1B,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAC/E,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AAC9E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAC;AAEhE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAEpE,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAC;AAEnE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAEtE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAQ9D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAG9D,oEAAoE;AACpE,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IACxC,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC;IAC1C,QAAQ,CAAC,WAAW,EAAE,mBAAmB,CAAC;IAC1C,QAAQ,CAAC,EAAE,EAAE,GAAG,CAAC;IACjB,QAAQ,CAAC,aAAa,EAAE,SAAS,CAAC;IAClC,QAAQ,CAAC,eAAe,EAAE,SAAS,CAAC;IACpC,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IACjC,QAAQ,CAAC,aAAa,EAAE,YAAY,CAAC;IACrC,QAAQ,CAAC,MAAM,EAAE,eAAe,CAAC;IACjC,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC;IAC1C,QAAQ,CAAC,WAAW,EAAE,kBAAkB,CAAC;IACzC,gBAAgB,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,YAAY,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,IAAI,KAAK;QAAE,SAAS,EAAE,SAAS,CAAC;QAAC,KAAK,EAAE,SAAS,CAAA;KAAE,GAAG,IAAI,CAAC;IAC7F,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,yBAAyB,IAAI,IAAI,CAAC;IAClC,qBAAqB,CAAC,OAAO,CAAC,EAAE;QAAE,gBAAgB,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/E,oBAAoB,CAAC,OAAO,CAAC,EAAE;QAAE,SAAS,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvE,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;IACxE,0BAA0B,CAAC,KAAK,EAAE,sBAAsB,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACvF,uBAAuB,IAAI,IAAI,CAAC;IAChC,4BAA4B,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,uCAAuC,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3E,qBAAqB,CAAC,KAAK,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;IACrE,kBAAkB,IAAI,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC5C,QAAQ,CAAC,OAAO,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5D;AAED,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,eAAe,EAAE,kBAAkB,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA0CzG;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CA2E7E;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,eAAe,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CA0C5F;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,eAAe,EAAE,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAgIxF;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,CAuB7D;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,eAAe,GAAG,IAAI,CAmC/D;AAED,wBAAsB,mBAAmB,CACxC,IAAI,EAAE,eAAe,EACrB,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE,UAAU,CAAC,uBAAuB,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,GAC/D,OAAO,CAAC;IAAE,SAAS,EAAE,OAAO,CAAA;CAAE,CAAC,CAoCjC;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,eAAe,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAsBlG;AAED,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,SAAS,CAAC,CAGpH;AAMD,MAAM,WAAW,gBAAgB;IAChC,QAAQ,CAAC,cAAc,EAAE;QAAE,SAAS,EAAE,MAAM,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IAC5D,QAAQ,CAAC,WAAW,EAAE;QACrB,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;YAAE,QAAQ,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAA;SAAE,KAAK,OAAO,CAAC;YAAE,SAAS,EAAE,OAAO,CAAA;SAAE,CAAC,CAAC;KACrG,CAAC;IACF,yBAAyB,IAAI,IAAI,CAAC;IAClC,QAAQ,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE,CAAC;IACrD,QAAQ,CAAC,OAAO,EAAE;QAAE,cAAc,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;KAAE,CAAC;IAC7D,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,EAAE,EAAE;QAAE,aAAa,EAAE,MAAM,IAAI,CAAA;KAAE,CAAC;CAC3C;AAED,wBAAsB,kBAAkB,CAAC,IAAI,EAAE,gBAAgB,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAuBvG;AAED,MAAM,MAAM,yBAAyB,GAClC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,mBAAmB,EAAE,MAAM,CAAA;CAAE,GAClF;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhC,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,OAAO,EAAE;QACjB,oBAAoB,EAAE,MAAM,SAAS,GAAG,SAAS,CAAC;QAClD,qBAAqB,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,MAAM,CAAC;QACpD,eAAe,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;QACpD,gBAAgB,EAAE,CAAC,OAAO,EAAE,2BAA2B,KAAK,OAAO,CAAC,0BAA0B,CAAC,CAAC;QAChG,sBAAsB,EAAE,CAAC,QAAQ,EAAE;YAClC,aAAa,EAAE,MAAM,CAAC;SACtB,KAAK,UAAU,CAAC,YAAY,CAAC,wBAAwB,CAAC,CAAC,CAAC;KACzD,CAAC;IACF,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,2BAA2B,IAAI,IAAI,CAAC;CACpC;AAQD,wBAAsB,iBAAiB,CAAC,IAAI,EAAE,eAAe,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAqC1F;AAED,MAAM,WAAW,uBAAuB;IACvC,QAAQ,CAAC,OAAO,EAAE;QACjB,gBAAgB,EAAE,CAAC,OAAO,EAAE,2BAA2B,KAAK,OAAO,CAAC,0BAA0B,CAAC,CAAC;KAChG,CAAC;IACF,wBAAwB,CAAC,IAAI,EAAE,MAAM,GAAG,yBAAyB,CAAC;IAClE,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,2BAA2B,IAAI,IAAI,CAAC;CACpC;AAED,wBAAsB,yBAAyB,CAAC,IAAI,EAAE,uBAAuB,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAyB1G;AAED,MAAM,WAAW,sBAAsB;IACtC,QAAQ,CAAC,OAAO,EAAE;QACjB,eAAe,EAAE,MAAM,UAAU,CAAC,YAAY,CAAC,iBAAiB,CAAC,CAAC,CAAC;QACnE,cAAc,EAAE,MAAM,UAAU,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC,CAAC;QACjE,oBAAoB,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,KAAK,MAAM,CAAC;KACzE,CAAC;IACF,QAAQ,CAAC,cAAc,EAAE;QAAE,cAAc,EAAE,MAAM,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC;IACtE,QAAQ,CAAC,aAAa,EAAE,SAAS,CAAC;IAClC,QAAQ,CAAC,EAAE,EAAE;QAAE,aAAa,EAAE,MAAM,IAAI,CAAA;KAAE,CAAC;CAC3C;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,sBAAsB,GAAG,IAAI,CA4CvE","sourcesContent":["/**\n * Session-picker, tree/fork navigation, and model-selector flows extracted from\n * interactive-mode.\n *\n * Each entry opens a selector overlay (via `host.showSelector`) or renders a\n * session-info block, driving `AgentSession`/`AgentSessionRuntime` navigation and\n * the fork/resume/clone/goal-continuation paths. The interdependent selector\n * flows share one narrow `SessionFlowHost` seam; the three prototype-tested leaf\n * commands (`handleCloneCommand`, `handleGoalContinueCommand`,\n * `handleSessionCommand`) take their own minimal host shapes so their behaviour\n * tests keep exercising them through interactive-mode's thin wrappers unchanged.\n */\n\nimport type { SessionManager } from \"@caupulican/pi-agent-core/node\";\nimport type { Model } from \"@caupulican/pi-ai\";\nimport type { EditorComponent } from \"@caupulican/pi-tui\";\nimport { type Component, type Container, Loader, Spacer, Text, type TUI } from \"@caupulican/pi-tui\";\nimport type {\n\tAgentSession,\n\tGoalContinuationLoopOptions,\n\tGoalContinuationLoopResult,\n} from \"../../core/agent-session.ts\";\nimport type { AgentSessionRuntime } from \"../../core/agent-session-runtime.ts\";\nimport type { ExtensionCommandContext } from \"../../core/extensions/index.ts\";\nimport type { GoalState } from \"../../core/goals/goal-state.ts\";\nimport { applyGoalAction } from \"../../core/goals/goal-tool-core.ts\";\nimport type { KeybindingsManager } from \"../../core/keybindings.ts\";\nimport { findExactModelReferenceMatch, resolveModelScope } from \"../../core/model-resolver.ts\";\nimport { MissingSessionCwdError } from \"../../core/session-cwd.ts\";\nimport { listAllSessions, listSessions, openSession } from \"../../core/session-manager-factory.ts\";\nimport type { SettingsManager } from \"../../core/settings-manager.ts\";\nimport { ProjectTrustStore } from \"../../core/trust-manager.ts\";\nimport type { CustomEditor } from \"./components/custom-editor.ts\";\nimport type { FooterComponent } from \"./components/footer.ts\";\nimport { keyText } from \"./components/keybinding-hints.ts\";\nimport { ModelSelectorComponent } from \"./components/model-selector.ts\";\nimport { ScopedModelsSelectorComponent } from \"./components/scoped-models-selector.ts\";\nimport { SessionSelectorComponent } from \"./components/session-selector.ts\";\nimport { TreeSelectorComponent } from \"./components/tree-selector.ts\";\nimport { TrustSelectorComponent } from \"./components/trust-selector.ts\";\nimport { UserMessageSelectorComponent } from \"./components/user-message-selector.ts\";\nimport type { ExtensionUiHost } from \"./extension-ui-host.ts\";\nimport { theme } from \"./theme/theme.ts\";\n\n/** Shared seam for the interdependent selector/navigation flows. */\nexport interface SessionFlowHost {\n\treadonly session: AgentSession;\n\treadonly sessionManager: SessionManager;\n\treadonly settingsManager: SettingsManager;\n\treadonly runtimeHost: AgentSessionRuntime;\n\treadonly ui: TUI;\n\treadonly chatContainer: Container;\n\treadonly statusContainer: Container;\n\treadonly editor: EditorComponent;\n\treadonly defaultEditor: CustomEditor;\n\treadonly footer: FooterComponent;\n\treadonly extensionUiHost: ExtensionUiHost;\n\treadonly keybindings: KeybindingsManager;\n\tloadingAnimation: Loader | undefined;\n\tshowSelector(create: (done: () => void) => { component: Component; focus: Component }): void;\n\tshowStatus(message: string): void;\n\tshowError(message: string): void;\n\trenderCurrentSessionState(): void;\n\trenderInitialMessages(options?: { forceHistoryLoad?: boolean }): Promise<void>;\n\tflushCompactionQueue(options?: { willRetry?: boolean }): Promise<void>;\n\thandleFatalRuntimeError(prefix: string, error: unknown): Promise<never>;\n\tpromptForMissingSessionCwd(error: MissingSessionCwdError): Promise<string | undefined>;\n\tupdateEditorBorderColor(): void;\n\tupdateAvailableProviderCount(): Promise<void>;\n\tmaybeWarnAboutAnthropicSubscriptionAuth(model?: Model<any>): Promise<void>;\n\tcheckDaxnutsEasterEgg(model: { provider: string; id: string }): void;\n\tgetModelCandidates(): Promise<Model<any>[]>;\n\tshutdown(options?: { fromSignal?: boolean }): Promise<void>;\n}\n\nexport async function showModelSelector(host: SessionFlowHost, initialSearchInput?: string): Promise<void> {\n\ttry {\n\t\tawait host.session.extensionRunner.emit({\n\t\t\ttype: \"model_selector_open\",\n\t\t\tcurrentModel: host.session.model,\n\t\t\tscopedModels: host.session.scopedModels,\n\t\t\tinitialSearchInput,\n\t\t});\n\t} catch (error) {\n\t\thost.showError(error instanceof Error ? error.message : String(error));\n\t\treturn;\n\t}\n\n\thost.showSelector((done) => {\n\t\tconst selector = new ModelSelectorComponent(\n\t\t\thost.ui,\n\t\t\thost.session.model,\n\t\t\thost.settingsManager,\n\t\t\thost.session.modelRegistry,\n\t\t\thost.session.scopedModels,\n\t\t\tasync (model) => {\n\t\t\t\ttry {\n\t\t\t\t\tawait host.session.setModel(model);\n\t\t\t\t\thost.footer.invalidate();\n\t\t\t\t\thost.updateEditorBorderColor();\n\t\t\t\t\tdone();\n\t\t\t\t\thost.showStatus(`Model: ${model.id}`);\n\t\t\t\t\tvoid host.maybeWarnAboutAnthropicSubscriptionAuth(model);\n\t\t\t\t\thost.checkDaxnutsEasterEgg(model);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tdone();\n\t\t\t\t\thost.showError(error instanceof Error ? error.message : String(error));\n\t\t\t\t}\n\t\t\t},\n\t\t\t() => {\n\t\t\t\tdone();\n\t\t\t\thost.ui.requestRender();\n\t\t\t},\n\t\t\tinitialSearchInput,\n\t\t);\n\t\treturn { component: selector, focus: selector };\n\t});\n}\n\nexport async function showModelsSelector(host: SessionFlowHost): Promise<void> {\n\t// Get all available models\n\thost.session.modelRegistry.refresh();\n\tconst allModels = host.session.modelRegistry.getAvailable();\n\n\tif (allModels.length === 0) {\n\t\thost.showStatus(\"No models available\");\n\t\treturn;\n\t}\n\n\t// Check if session has scoped models (from previous session-only changes or CLI --models)\n\tconst sessionScopedModels = host.session.scopedModels;\n\tconst hasSessionScope = sessionScopedModels.length > 0;\n\n\t// Build enabled model IDs from session state or settings\n\tlet currentEnabledIds: string[] | null = null;\n\n\tif (hasSessionScope) {\n\t\t// Use current session's scoped models\n\t\tcurrentEnabledIds = sessionScopedModels.map((scoped) => `${scoped.model.provider}/${scoped.model.id}`);\n\t} else {\n\t\t// Fall back to settings\n\t\tconst patterns = host.settingsManager.getEnabledModels();\n\t\tif (patterns !== undefined && patterns.length > 0) {\n\t\t\tconst scopedModels = await resolveModelScope(patterns, host.session.modelRegistry);\n\t\t\tcurrentEnabledIds = scopedModels.map((scoped) => `${scoped.model.provider}/${scoped.model.id}`);\n\t\t}\n\t}\n\n\t// Helper to update session's scoped models (session-only, no persist)\n\tconst updateSessionModels = async (enabledIds: string[] | null) => {\n\t\tcurrentEnabledIds = enabledIds === null ? null : [...enabledIds];\n\t\tif (enabledIds && enabledIds.length > 0 && enabledIds.length < allModels.length) {\n\t\t\tconst newScopedModels = await resolveModelScope(enabledIds, host.session.modelRegistry);\n\t\t\thost.session.setScopedModels(\n\t\t\t\tnewScopedModels.map((sm) => ({\n\t\t\t\t\tmodel: sm.model,\n\t\t\t\t\tthinkingLevel: sm.thinkingLevel,\n\t\t\t\t})),\n\t\t\t);\n\t\t} else {\n\t\t\t// All enabled or none enabled = no filter\n\t\t\thost.session.setScopedModels([]);\n\t\t}\n\t\tawait host.updateAvailableProviderCount();\n\t\thost.ui.requestRender();\n\t};\n\n\thost.showSelector((done) => {\n\t\tconst selector = new ScopedModelsSelectorComponent(\n\t\t\t{\n\t\t\t\tallModels,\n\t\t\t\tenabledModelIds: currentEnabledIds,\n\t\t\t},\n\t\t\t{\n\t\t\t\tonChange: async (enabledIds) => {\n\t\t\t\t\tawait updateSessionModels(enabledIds);\n\t\t\t\t},\n\t\t\t\tonPersist: (enabledIds) => {\n\t\t\t\t\t// Persist to settings\n\t\t\t\t\tconst newPatterns =\n\t\t\t\t\t\tenabledIds === null || enabledIds.length === allModels.length\n\t\t\t\t\t\t\t? undefined // All enabled = clear filter\n\t\t\t\t\t\t\t: enabledIds;\n\t\t\t\t\thost.settingsManager.setEnabledModels(newPatterns ? [...newPatterns] : undefined);\n\t\t\t\t\thost.showStatus(\"Model selection saved to settings\");\n\t\t\t\t},\n\t\t\t\tonCancel: () => {\n\t\t\t\t\tdone();\n\t\t\t\t\thost.ui.requestRender();\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\t\treturn { component: selector, focus: selector };\n\t});\n}\n\nexport function showUserMessageSelector(host: SessionFlowHost, newSessionName?: string): void {\n\tconst userMessages = host.session.getUserMessagesForForking();\n\n\tif (userMessages.length === 0) {\n\t\thost.showStatus(\"No messages to fork from\");\n\t\treturn;\n\t}\n\n\tconst initialSelectedId = userMessages[userMessages.length - 1]?.entryId;\n\n\thost.showSelector((done) => {\n\t\tconst selector = new UserMessageSelectorComponent(\n\t\t\tuserMessages.map((m) => ({ id: m.entryId, text: m.text })),\n\t\t\tasync (entryId) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await host.runtimeHost.fork(entryId);\n\t\t\t\t\tif (result.cancelled) {\n\t\t\t\t\t\tdone();\n\t\t\t\t\t\thost.ui.requestRender();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\thost.renderCurrentSessionState();\n\t\t\t\t\tif (newSessionName) {\n\t\t\t\t\t\thost.session.setSessionName(newSessionName);\n\t\t\t\t\t}\n\t\t\t\t\thost.editor.setText(result.selectedText ?? \"\");\n\t\t\t\t\tdone();\n\t\t\t\t\thost.showStatus(newSessionName ? `Forked to new session: ${newSessionName}` : \"Forked to new session\");\n\t\t\t\t} catch (error: unknown) {\n\t\t\t\t\tdone();\n\t\t\t\t\thost.showError(error instanceof Error ? error.message : String(error));\n\t\t\t\t}\n\t\t\t},\n\t\t\t() => {\n\t\t\t\tdone();\n\t\t\t\thost.ui.requestRender();\n\t\t\t},\n\t\t\tinitialSelectedId,\n\t\t);\n\t\treturn { component: selector, focus: selector.getMessageList() };\n\t});\n}\n\nexport function showTreeSelector(host: SessionFlowHost, initialSelectedId?: string): void {\n\tconst tree = host.sessionManager.getTree();\n\tconst realLeafId = host.sessionManager.getLeafId();\n\tconst initialFilterMode = host.settingsManager.getTreeFilterMode();\n\n\tif (tree.length === 0) {\n\t\thost.showStatus(\"No entries in session\");\n\t\treturn;\n\t}\n\n\thost.showSelector((done) => {\n\t\tconst selector = new TreeSelectorComponent(\n\t\t\ttree,\n\t\t\trealLeafId,\n\t\t\thost.ui.terminal.rows,\n\t\t\tasync (entryId) => {\n\t\t\t\t// Selecting the current leaf is a no-op (already there)\n\t\t\t\tif (entryId === realLeafId) {\n\t\t\t\t\tdone();\n\t\t\t\t\thost.showStatus(\"Already at this point\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Ask about summarization\n\t\t\t\tdone(); // Close selector first\n\n\t\t\t\t// Loop until user makes a complete choice or cancels to tree\n\t\t\t\tlet wantsSummary = false;\n\t\t\t\tlet customInstructions: string | undefined;\n\n\t\t\t\t// Check if we should skip the prompt (user preference to always default to no summary)\n\t\t\t\tif (!host.settingsManager.getBranchSummarySkipPrompt()) {\n\t\t\t\t\twhile (true) {\n\t\t\t\t\t\tconst summaryChoice = await host.extensionUiHost.showExtensionSelector(\"Summarize branch?\", [\n\t\t\t\t\t\t\t\"No summary\",\n\t\t\t\t\t\t\t\"Summarize\",\n\t\t\t\t\t\t\t\"Summarize with custom prompt\",\n\t\t\t\t\t\t]);\n\n\t\t\t\t\t\tif (summaryChoice === undefined) {\n\t\t\t\t\t\t\t// User pressed escape - re-show tree selector with same selection\n\t\t\t\t\t\t\tshowTreeSelector(host, entryId);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\twantsSummary = summaryChoice !== \"No summary\";\n\n\t\t\t\t\t\tif (summaryChoice === \"Summarize with custom prompt\") {\n\t\t\t\t\t\t\tcustomInstructions = await host.extensionUiHost.showExtensionEditor(\n\t\t\t\t\t\t\t\t\"Custom summarization instructions\",\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tif (customInstructions === undefined) {\n\t\t\t\t\t\t\t\t// User cancelled - loop back to summary selector\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// User made a complete choice\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Set up escape handler and loader if summarizing\n\t\t\t\tlet summaryLoader: Loader | undefined;\n\t\t\t\tconst originalOnEscape = host.defaultEditor.onEscape;\n\n\t\t\t\tif (wantsSummary) {\n\t\t\t\t\thost.defaultEditor.onEscape = () => {\n\t\t\t\t\t\thost.session.abortBranchSummary();\n\t\t\t\t\t};\n\t\t\t\t\thost.chatContainer.addChild(new Spacer(1));\n\t\t\t\t\tsummaryLoader = new Loader(\n\t\t\t\t\t\thost.ui,\n\t\t\t\t\t\t(spinner) => theme.fg(\"accent\", spinner),\n\t\t\t\t\t\t(text) => theme.fg(\"muted\", text),\n\t\t\t\t\t\t`Summarizing branch... (${keyText(\"app.interrupt\")} to cancel)`,\n\t\t\t\t\t);\n\t\t\t\t\thost.statusContainer.addChild(summaryLoader);\n\t\t\t\t\thost.ui.requestRender();\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await host.session.navigateTree(entryId, {\n\t\t\t\t\t\tsummarize: wantsSummary,\n\t\t\t\t\t\tcustomInstructions,\n\t\t\t\t\t});\n\n\t\t\t\t\tif (result.aborted) {\n\t\t\t\t\t\t// Summarization aborted - re-show tree selector with same selection\n\t\t\t\t\t\thost.showStatus(\"Branch summarization cancelled\");\n\t\t\t\t\t\tshowTreeSelector(host, entryId);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (result.cancelled) {\n\t\t\t\t\t\thost.showStatus(\"Navigation cancelled\");\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Update UI\n\t\t\t\t\tawait host.renderInitialMessages();\n\t\t\t\t\tif (result.editorText && !host.editor.getText().trim()) {\n\t\t\t\t\t\thost.editor.setText(result.editorText);\n\t\t\t\t\t}\n\t\t\t\t\thost.showStatus(\"Navigated to selected point\");\n\t\t\t\t\tvoid host.flushCompactionQueue({ willRetry: false });\n\t\t\t\t} catch (error) {\n\t\t\t\t\thost.showError(error instanceof Error ? error.message : String(error));\n\t\t\t\t} finally {\n\t\t\t\t\tif (summaryLoader) {\n\t\t\t\t\t\tsummaryLoader.stop();\n\t\t\t\t\t\thost.statusContainer.clear();\n\t\t\t\t\t}\n\t\t\t\t\thost.defaultEditor.onEscape = originalOnEscape;\n\t\t\t\t}\n\t\t\t},\n\t\t\t() => {\n\t\t\t\tdone();\n\t\t\t\thost.ui.requestRender();\n\t\t\t},\n\t\t\t(entryId, label) => {\n\t\t\t\thost.sessionManager.appendLabelChange(entryId, label);\n\t\t\t\thost.ui.requestRender();\n\t\t\t},\n\t\t\tinitialSelectedId,\n\t\t\tinitialFilterMode,\n\t\t);\n\t\treturn { component: selector, focus: selector };\n\t});\n}\n\nexport function showTrustSelector(host: SessionFlowHost): void {\n\tconst cwd = host.sessionManager.getCwd();\n\tconst trustStore = new ProjectTrustStore(host.runtimeHost.services.agentDir);\n\tconst savedDecision = trustStore.get(cwd);\n\thost.showSelector((done) => {\n\t\tconst selector = new TrustSelectorComponent({\n\t\t\tcwd,\n\t\t\tsavedDecision,\n\t\t\tprojectTrusted: host.settingsManager.isProjectTrusted(),\n\t\t\tonSelect: (trusted) => {\n\t\t\t\ttrustStore.set(cwd, trusted);\n\t\t\t\tdone();\n\t\t\t\thost.showStatus(\n\t\t\t\t\t`Saved trust decision: ${trusted ? \"trusted\" : \"untrusted\"}. Restart pi for this to take effect.`,\n\t\t\t\t);\n\t\t\t},\n\t\t\tonCancel: () => {\n\t\t\t\tdone();\n\t\t\t\thost.ui.requestRender();\n\t\t\t},\n\t\t});\n\t\treturn { component: selector, focus: selector };\n\t});\n}\n\nexport function showSessionSelector(host: SessionFlowHost): void {\n\thost.showSelector((done) => {\n\t\tconst selector = new SessionSelectorComponent(\n\t\t\t(onProgress) => listSessions(host.sessionManager.getCwd(), host.sessionManager.getSessionDir(), onProgress),\n\t\t\t(onProgress) =>\n\t\t\t\thost.sessionManager.usesDefaultSessionDir()\n\t\t\t\t\t? listAllSessions(onProgress)\n\t\t\t\t\t: listAllSessions(host.sessionManager.getSessionDir(), onProgress),\n\t\t\tasync (sessionPath) => {\n\t\t\t\tdone();\n\t\t\t\tawait handleResumeSession(host, sessionPath);\n\t\t\t},\n\t\t\t() => {\n\t\t\t\tdone();\n\t\t\t\thost.ui.requestRender();\n\t\t\t},\n\t\t\t() => {\n\t\t\t\tvoid host.shutdown();\n\t\t\t},\n\t\t\t() => host.ui.requestRender(),\n\t\t\t{\n\t\t\t\trenameSession: async (sessionFilePath: string, nextName: string | undefined) => {\n\t\t\t\t\tconst next = (nextName ?? \"\").trim();\n\t\t\t\t\tif (!next) return;\n\t\t\t\t\tconst mgr = openSession(sessionFilePath);\n\t\t\t\t\tmgr.appendSessionInfo(next);\n\t\t\t\t},\n\t\t\t\tshowRenameHint: true,\n\t\t\t\tkeybindings: host.keybindings,\n\t\t\t},\n\n\t\t\thost.sessionManager.getSessionFile(),\n\t\t);\n\t\treturn { component: selector, focus: selector };\n\t});\n}\n\nexport async function handleResumeSession(\n\thost: SessionFlowHost,\n\tsessionPath: string,\n\toptions?: Parameters<ExtensionCommandContext[\"switchSession\"]>[1],\n): Promise<{ cancelled: boolean }> {\n\tif (host.loadingAnimation) {\n\t\thost.loadingAnimation.stop();\n\t\thost.loadingAnimation = undefined;\n\t}\n\thost.statusContainer.clear();\n\ttry {\n\t\tconst result = await host.runtimeHost.switchSession(sessionPath, {\n\t\t\twithSession: options?.withSession,\n\t\t});\n\t\tif (result.cancelled) {\n\t\t\treturn result;\n\t\t}\n\t\thost.renderCurrentSessionState();\n\t\thost.showStatus(\"Resumed session\");\n\t\treturn result;\n\t} catch (error: unknown) {\n\t\tif (error instanceof MissingSessionCwdError) {\n\t\t\tconst selectedCwd = await host.promptForMissingSessionCwd(error);\n\t\t\tif (!selectedCwd) {\n\t\t\t\thost.showStatus(\"Resume cancelled\");\n\t\t\t\treturn { cancelled: true };\n\t\t\t}\n\t\t\tconst result = await host.runtimeHost.switchSession(sessionPath, {\n\t\t\t\tcwdOverride: selectedCwd,\n\t\t\t\twithSession: options?.withSession,\n\t\t\t});\n\t\t\tif (result.cancelled) {\n\t\t\t\treturn result;\n\t\t\t}\n\t\t\thost.renderCurrentSessionState();\n\t\t\thost.showStatus(\"Resumed session in current cwd\");\n\t\t\treturn result;\n\t\t}\n\t\treturn host.handleFatalRuntimeError(\"Failed to resume session\", error);\n\t}\n}\n\nexport async function handleModelCommand(host: SessionFlowHost, searchTerm?: string): Promise<void> {\n\tif (!searchTerm) {\n\t\tawait showModelSelector(host);\n\t\treturn;\n\t}\n\n\tconst model = await findExactModelMatch(host, searchTerm);\n\tif (model) {\n\t\ttry {\n\t\t\tawait host.session.setModel(model);\n\t\t\thost.footer.invalidate();\n\t\t\thost.updateEditorBorderColor();\n\t\t\thost.showStatus(`Model: ${model.id}`);\n\t\t\tvoid host.maybeWarnAboutAnthropicSubscriptionAuth(model);\n\t\t\thost.checkDaxnutsEasterEgg(model);\n\t\t} catch (error) {\n\t\t\thost.showError(error instanceof Error ? error.message : String(error));\n\t\t}\n\t\treturn;\n\t}\n\n\tawait showModelSelector(host, searchTerm);\n}\n\nexport async function findExactModelMatch(host: SessionFlowHost, searchTerm: string): Promise<Model<any> | undefined> {\n\tconst models = await host.getModelCandidates();\n\treturn findExactModelReferenceMatch(searchTerm, models);\n}\n\n// ===========================================================================\n// Prototype-tested leaf commands — narrow host shapes matching their fakes.\n// ===========================================================================\n\nexport interface CloneCommandHost {\n\treadonly sessionManager: { getLeafId: () => string | null };\n\treadonly runtimeHost: {\n\t\tfork: (entryId: string, options?: { position?: \"before\" | \"at\" }) => Promise<{ cancelled: boolean }>;\n\t};\n\trenderCurrentSessionState(): void;\n\treadonly editor: { setText: (text: string) => void };\n\treadonly session: { setSessionName: (name: string) => void };\n\tshowStatus(message: string): void;\n\tshowError(message: string): void;\n\treadonly ui: { requestRender: () => void };\n}\n\nexport async function handleCloneCommand(host: CloneCommandHost, newSessionName?: string): Promise<void> {\n\tconst leafId = host.sessionManager.getLeafId();\n\tif (!leafId) {\n\t\thost.showStatus(\"Nothing to clone yet\");\n\t\treturn;\n\t}\n\n\ttry {\n\t\tconst result = await host.runtimeHost.fork(leafId, { position: \"at\" });\n\t\tif (result.cancelled) {\n\t\t\thost.ui.requestRender();\n\t\t\treturn;\n\t\t}\n\n\t\thost.renderCurrentSessionState();\n\t\tif (newSessionName) {\n\t\t\thost.session.setSessionName(newSessionName);\n\t\t}\n\t\thost.editor.setText(\"\");\n\t\thost.showStatus(newSessionName ? `Cloned to new session: ${newSessionName}` : \"Cloned to new session\");\n\t} catch (error: unknown) {\n\t\thost.showError(error instanceof Error ? error.message : String(error));\n\t}\n}\n\nexport type ParsedGoalContinueCommand =\n\t| { ok: true; maxTurns: number; maxStallTurns: number; maxWallClockMinutes: number }\n\t| { ok: false; error: string };\n\nexport interface GoalCommandHost {\n\treadonly session: {\n\t\tgetGoalStateSnapshot: () => GoalState | undefined;\n\t\tsaveGoalStateSnapshot: (state: GoalState) => string;\n\t\tsendUserMessage: (content: string) => Promise<void>;\n\t\tcontinueGoalLoop: (options: GoalContinuationLoopOptions) => Promise<GoalContinuationLoopResult>;\n\t\tgetGoalRuntimeSnapshot: (settings: {\n\t\t\tmaxStallTurns: number;\n\t\t}) => ReturnType<AgentSession[\"getGoalRuntimeSnapshot\"]>;\n\t};\n\tshowStatus(message: string): void;\n\tshowError(message: string): void;\n\trefreshAutonomyFooterStatus(): void;\n}\n\nfunction formatGoalStatus(snapshot: ReturnType<AgentSession[\"getGoalRuntimeSnapshot\"]>): string {\n\tconst state = snapshot.goalState;\n\tif (!state) return `Goal: none (${snapshot.continuation.action}/${snapshot.continuation.reasonCode})`;\n\treturn `Goal: ${state.userGoal}\\nStatus: ${state.status}\\nRequirements: open ${snapshot.continuation.openRequirementIds.length}, blocked ${snapshot.continuation.blockedRequirementIds.length}, satisfied ${snapshot.continuation.satisfiedRequirementIds.length}\\nContinuation: ${snapshot.continuation.action}/${snapshot.continuation.reasonCode}`;\n}\n\nexport async function handleGoalCommand(host: GoalCommandHost, text: string): Promise<void> {\n\tconst goalText = text.replace(/^\\/goal\\s*/, \"\").trim();\n\tif (!goalText) {\n\t\thost.showStatus(formatGoalStatus(host.session.getGoalRuntimeSnapshot({ maxStallTurns: 20 })));\n\t\treturn;\n\t}\n\tconst now = new Date().toISOString();\n\tconst goalId = `goal-${Date.now().toString(36)}`;\n\tconst started = applyGoalAction(\n\t\thost.session.getGoalStateSnapshot(),\n\t\t{ action: \"start\", goalId, userGoal: goalText },\n\t\tnow,\n\t);\n\tif (!started.ok) {\n\t\thost.showError(started.error);\n\t\treturn;\n\t}\n\thost.session.saveGoalStateSnapshot(started.state);\n\t// Deterministic producer completion: a goal with zero open requirements evaluates to\n\t// finalize/no_open_requirements, so the loop would be undrivable whenever the model skips\n\t// decomposition (observed in the field). Seed one requirement from the goal text itself —\n\t// the model's decomposition below refines alongside it.\n\tconst seeded = applyGoalAction(\n\t\tstarted.state,\n\t\t{ action: \"add_requirement\", requirementId: `${goalId}-r1`, text: goalText },\n\t\tnow,\n\t);\n\tif (seeded.ok) {\n\t\thost.session.saveGoalStateSnapshot(seeded.state);\n\t}\n\tawait host.session.sendUserMessage(\n\t\t`Start goal: ${goalText}\\n\\nUse the goal tool this turn to decompose this goal into concrete open requirements with add_requirement actions, and satisfy_requirement ${goalId}-r1 once the decomposed requirements cover it.`,\n\t);\n\tconst result = await host.session.continueGoalLoop({ maxTurns: 1, maxStallTurns: 20, maxWallClockMinutes: 0 });\n\tconst continuation = result.finalSnapshot.continuation;\n\thost.showStatus(`Goal started: ${continuation.action}/${continuation.reasonCode}.`);\n\thost.refreshAutonomyFooterStatus();\n}\n\nexport interface GoalContinueCommandHost {\n\treadonly session: {\n\t\tcontinueGoalLoop: (options: GoalContinuationLoopOptions) => Promise<GoalContinuationLoopResult>;\n\t};\n\tparseGoalContinueCommand(text: string): ParsedGoalContinueCommand;\n\tshowStatus(message: string): void;\n\tshowError(message: string): void;\n\trefreshAutonomyFooterStatus(): void;\n}\n\nexport async function handleGoalContinueCommand(host: GoalContinueCommandHost, text: string): Promise<void> {\n\tconst parsed = host.parseGoalContinueCommand(text);\n\tif (!parsed.ok) {\n\t\thost.showError(parsed.error);\n\t\treturn;\n\t}\n\n\thost.showStatus(\n\t\t`Goal continuation started: up to ${parsed.maxTurns} turn(s), stall limit ${parsed.maxStallTurns}, wall-clock limit ${parsed.maxWallClockMinutes || \"disabled\"} minute(s).`,\n\t);\n\ttry {\n\t\tconst result = await host.session.continueGoalLoop({\n\t\t\tmaxTurns: parsed.maxTurns,\n\t\t\tmaxStallTurns: parsed.maxStallTurns,\n\t\t\tmaxWallClockMinutes: parsed.maxWallClockMinutes,\n\t\t});\n\t\tconst continuation = result.finalSnapshot.continuation;\n\t\thost.showStatus(\n\t\t\t`Goal continuation stopped: ${result.stopReason}; submitted ${result.turnsSubmitted} turn(s); latest decision ${continuation.action}/${continuation.reasonCode}.`,\n\t\t);\n\t} catch (error) {\n\t\thost.showError(`Goal continuation failed: ${error instanceof Error ? error.message : String(error)}`);\n\t} finally {\n\t\thost.refreshAutonomyFooterStatus();\n\t}\n}\n\nexport interface SessionInfoCommandHost {\n\treadonly session: {\n\t\tgetSessionStats: () => ReturnType<AgentSession[\"getSessionStats\"]>;\n\t\tgetCostSummary: () => ReturnType<AgentSession[\"getCostSummary\"]>;\n\t\tgetModelRouterStatus: (formatLabel: (label: string) => string) => string;\n\t};\n\treadonly sessionManager: { getSessionName: () => string | undefined };\n\treadonly chatContainer: Container;\n\treadonly ui: { requestRender: () => void };\n}\n\nexport function handleSessionCommand(host: SessionInfoCommandHost): void {\n\tconst stats = host.session.getSessionStats();\n\tconst sessionName = host.sessionManager.getSessionName();\n\n\tlet info = `${theme.bold(\"Session Info\")}\\n\\n`;\n\tif (sessionName) {\n\t\tinfo += `${theme.fg(\"dim\", \"Name:\")} ${sessionName}\\n`;\n\t}\n\tinfo += `${theme.fg(\"dim\", \"File:\")} ${stats.sessionFile ?? \"In-memory\"}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"ID:\")} ${stats.sessionId}\\n\\n`;\n\tinfo += `${theme.bold(\"Messages\")}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"User:\")} ${stats.userMessages}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Assistant:\")} ${stats.assistantMessages}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Tool Calls:\")} ${stats.toolCalls}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Tool Results:\")} ${stats.toolResults}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Total:\")} ${stats.totalMessages}\\n\\n`;\n\tinfo += `${theme.bold(\"Tokens\")}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Input:\")} ${stats.tokens.input.toLocaleString()}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Output:\")} ${stats.tokens.output.toLocaleString()}\\n`;\n\tif (stats.tokens.cacheRead > 0) {\n\t\tinfo += `${theme.fg(\"dim\", \"Cache Read:\")} ${stats.tokens.cacheRead.toLocaleString()}\\n`;\n\t}\n\tif (stats.tokens.cacheWrite > 0) {\n\t\tinfo += `${theme.fg(\"dim\", \"Cache Write:\")} ${stats.tokens.cacheWrite.toLocaleString()}\\n`;\n\t}\n\tinfo += `${theme.fg(\"dim\", \"Total:\")} ${stats.tokens.total.toLocaleString()}\\n`;\n\n\tconst costs = host.session.getCostSummary();\n\tif (costs.currentCost > 0 || costs.todayCost > 0 || costs.subagentReports > 0) {\n\t\tinfo += `\\n${theme.bold(\"Cost\")}\\n`;\n\t\tinfo += `${theme.fg(\"dim\", \"CURRENT (session):\")} $${costs.currentCost.toFixed(4)}\\n`;\n\t\tif (costs.subagentReports > 0 || costs.subagentCost > 0) {\n\t\t\tinfo += `${theme.fg(\"dim\", \"SUBAGENTS (included in CURRENT):\")} $${costs.subagentCost.toFixed(4)} (${costs.subagentReports} reports)\\n`;\n\t\t}\n\t\tinfo += `${theme.fg(\"dim\", \"TODAY (host local day):\")} $${costs.todayCost.toFixed(4)}\\n`;\n\t\tinfo += `${theme.fg(\"dim\", \"Today rollover:\")} local midnight`;\n\t}\n\n\tinfo += `\\n\\n${theme.bold(\"Model Router\")}\\n`;\n\tinfo += host.session.getModelRouterStatus((label) => theme.fg(\"dim\", label));\n\n\thost.chatContainer.addChild(new Spacer(1));\n\thost.chatContainer.addChild(new Text(info, 1, 0));\n\thost.ui.requestRender();\n}\n"]}
|
|
@@ -478,11 +478,15 @@ export function handleSessionCommand(host) {
|
|
|
478
478
|
info += `${theme.fg("dim", "Cache Write:")} ${stats.tokens.cacheWrite.toLocaleString()}\n`;
|
|
479
479
|
}
|
|
480
480
|
info += `${theme.fg("dim", "Total:")} ${stats.tokens.total.toLocaleString()}\n`;
|
|
481
|
-
const
|
|
482
|
-
if (
|
|
481
|
+
const costs = host.session.getCostSummary();
|
|
482
|
+
if (costs.currentCost > 0 || costs.todayCost > 0 || costs.subagentReports > 0) {
|
|
483
483
|
info += `\n${theme.bold("Cost")}\n`;
|
|
484
|
-
info += `${theme.fg("dim", "
|
|
485
|
-
|
|
484
|
+
info += `${theme.fg("dim", "CURRENT (session):")} $${costs.currentCost.toFixed(4)}\n`;
|
|
485
|
+
if (costs.subagentReports > 0 || costs.subagentCost > 0) {
|
|
486
|
+
info += `${theme.fg("dim", "SUBAGENTS (included in CURRENT):")} $${costs.subagentCost.toFixed(4)} (${costs.subagentReports} reports)\n`;
|
|
487
|
+
}
|
|
488
|
+
info += `${theme.fg("dim", "TODAY (host local day):")} $${costs.todayCost.toFixed(4)}\n`;
|
|
489
|
+
info += `${theme.fg("dim", "Today rollover:")} local midnight`;
|
|
486
490
|
}
|
|
487
491
|
info += `\n\n${theme.bold("Model Router")}\n`;
|
|
488
492
|
info += host.session.getModelRouterStatus((label) => theme.fg("dim", label));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-flow-commands.js","sourceRoot":"","sources":["../../../src/modes/interactive/session-flow-commands.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Session-picker, tree/fork navigation, and model-selector flows extracted from\n * interactive-mode.\n *\n * Each entry opens a selector overlay (via `host.showSelector`) or renders a\n * session-info block, driving `AgentSession`/`AgentSessionRuntime` navigation and\n * the fork/resume/clone/goal-continuation paths. The interdependent selector\n * flows share one narrow `SessionFlowHost` seam; the three prototype-tested leaf\n * commands (`handleCloneCommand`, `handleGoalContinueCommand`,\n * `handleSessionCommand`) take their own minimal host shapes so their behaviour\n * tests keep exercising them through interactive-mode's thin wrappers unchanged.\n */\n\nimport type { SessionManager } from \"@caupulican/pi-agent-core/node\";\nimport type { Model } from \"@caupulican/pi-ai\";\nimport type { EditorComponent } from \"@caupulican/pi-tui\";\nimport { type Component, type Container, Loader, Spacer, Text, type TUI } from \"@caupulican/pi-tui\";\nimport type {\n\tAgentSession,\n\tGoalContinuationLoopOptions,\n\tGoalContinuationLoopResult,\n} from \"../../core/agent-session.ts\";\nimport type { AgentSessionRuntime } from \"../../core/agent-session-runtime.ts\";\nimport type { ExtensionCommandContext } from \"../../core/extensions/index.ts\";\nimport type { GoalState } from \"../../core/goals/goal-state.ts\";\nimport { applyGoalAction } from \"../../core/goals/goal-tool-core.ts\";\nimport type { KeybindingsManager } from \"../../core/keybindings.ts\";\nimport { findExactModelReferenceMatch, resolveModelScope } from \"../../core/model-resolver.ts\";\nimport { MissingSessionCwdError } from \"../../core/session-cwd.ts\";\nimport { listAllSessions, listSessions, openSession } from \"../../core/session-manager-factory.ts\";\nimport type { SettingsManager } from \"../../core/settings-manager.ts\";\nimport { ProjectTrustStore } from \"../../core/trust-manager.ts\";\nimport type { CustomEditor } from \"./components/custom-editor.ts\";\nimport type { FooterComponent } from \"./components/footer.ts\";\nimport { keyText } from \"./components/keybinding-hints.ts\";\nimport { ModelSelectorComponent } from \"./components/model-selector.ts\";\nimport { ScopedModelsSelectorComponent } from \"./components/scoped-models-selector.ts\";\nimport { SessionSelectorComponent } from \"./components/session-selector.ts\";\nimport { TreeSelectorComponent } from \"./components/tree-selector.ts\";\nimport { TrustSelectorComponent } from \"./components/trust-selector.ts\";\nimport { UserMessageSelectorComponent } from \"./components/user-message-selector.ts\";\nimport type { ExtensionUiHost } from \"./extension-ui-host.ts\";\nimport { theme } from \"./theme/theme.ts\";\n\n/** Shared seam for the interdependent selector/navigation flows. */\nexport interface SessionFlowHost {\n\treadonly session: AgentSession;\n\treadonly sessionManager: SessionManager;\n\treadonly settingsManager: SettingsManager;\n\treadonly runtimeHost: AgentSessionRuntime;\n\treadonly ui: TUI;\n\treadonly chatContainer: Container;\n\treadonly statusContainer: Container;\n\treadonly editor: EditorComponent;\n\treadonly defaultEditor: CustomEditor;\n\treadonly footer: FooterComponent;\n\treadonly extensionUiHost: ExtensionUiHost;\n\treadonly keybindings: KeybindingsManager;\n\tloadingAnimation: Loader | undefined;\n\tshowSelector(create: (done: () => void) => { component: Component; focus: Component }): void;\n\tshowStatus(message: string): void;\n\tshowError(message: string): void;\n\trenderCurrentSessionState(): void;\n\trenderInitialMessages(options?: { forceHistoryLoad?: boolean }): Promise<void>;\n\tflushCompactionQueue(options?: { willRetry?: boolean }): Promise<void>;\n\thandleFatalRuntimeError(prefix: string, error: unknown): Promise<never>;\n\tpromptForMissingSessionCwd(error: MissingSessionCwdError): Promise<string | undefined>;\n\tupdateEditorBorderColor(): void;\n\tupdateAvailableProviderCount(): Promise<void>;\n\tmaybeWarnAboutAnthropicSubscriptionAuth(model?: Model<any>): Promise<void>;\n\tcheckDaxnutsEasterEgg(model: { provider: string; id: string }): void;\n\tgetModelCandidates(): Promise<Model<any>[]>;\n\tshutdown(options?: { fromSignal?: boolean }): Promise<void>;\n}\n\nexport async function showModelSelector(host: SessionFlowHost, initialSearchInput?: string): Promise<void> {\n\ttry {\n\t\tawait host.session.extensionRunner.emit({\n\t\t\ttype: \"model_selector_open\",\n\t\t\tcurrentModel: host.session.model,\n\t\t\tscopedModels: host.session.scopedModels,\n\t\t\tinitialSearchInput,\n\t\t});\n\t} catch (error) {\n\t\thost.showError(error instanceof Error ? error.message : String(error));\n\t\treturn;\n\t}\n\n\thost.showSelector((done) => {\n\t\tconst selector = new ModelSelectorComponent(\n\t\t\thost.ui,\n\t\t\thost.session.model,\n\t\t\thost.settingsManager,\n\t\t\thost.session.modelRegistry,\n\t\t\thost.session.scopedModels,\n\t\t\tasync (model) => {\n\t\t\t\ttry {\n\t\t\t\t\tawait host.session.setModel(model);\n\t\t\t\t\thost.footer.invalidate();\n\t\t\t\t\thost.updateEditorBorderColor();\n\t\t\t\t\tdone();\n\t\t\t\t\thost.showStatus(`Model: ${model.id}`);\n\t\t\t\t\tvoid host.maybeWarnAboutAnthropicSubscriptionAuth(model);\n\t\t\t\t\thost.checkDaxnutsEasterEgg(model);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tdone();\n\t\t\t\t\thost.showError(error instanceof Error ? error.message : String(error));\n\t\t\t\t}\n\t\t\t},\n\t\t\t() => {\n\t\t\t\tdone();\n\t\t\t\thost.ui.requestRender();\n\t\t\t},\n\t\t\tinitialSearchInput,\n\t\t);\n\t\treturn { component: selector, focus: selector };\n\t});\n}\n\nexport async function showModelsSelector(host: SessionFlowHost): Promise<void> {\n\t// Get all available models\n\thost.session.modelRegistry.refresh();\n\tconst allModels = host.session.modelRegistry.getAvailable();\n\n\tif (allModels.length === 0) {\n\t\thost.showStatus(\"No models available\");\n\t\treturn;\n\t}\n\n\t// Check if session has scoped models (from previous session-only changes or CLI --models)\n\tconst sessionScopedModels = host.session.scopedModels;\n\tconst hasSessionScope = sessionScopedModels.length > 0;\n\n\t// Build enabled model IDs from session state or settings\n\tlet currentEnabledIds: string[] | null = null;\n\n\tif (hasSessionScope) {\n\t\t// Use current session's scoped models\n\t\tcurrentEnabledIds = sessionScopedModels.map((scoped) => `${scoped.model.provider}/${scoped.model.id}`);\n\t} else {\n\t\t// Fall back to settings\n\t\tconst patterns = host.settingsManager.getEnabledModels();\n\t\tif (patterns !== undefined && patterns.length > 0) {\n\t\t\tconst scopedModels = await resolveModelScope(patterns, host.session.modelRegistry);\n\t\t\tcurrentEnabledIds = scopedModels.map((scoped) => `${scoped.model.provider}/${scoped.model.id}`);\n\t\t}\n\t}\n\n\t// Helper to update session's scoped models (session-only, no persist)\n\tconst updateSessionModels = async (enabledIds: string[] | null) => {\n\t\tcurrentEnabledIds = enabledIds === null ? null : [...enabledIds];\n\t\tif (enabledIds && enabledIds.length > 0 && enabledIds.length < allModels.length) {\n\t\t\tconst newScopedModels = await resolveModelScope(enabledIds, host.session.modelRegistry);\n\t\t\thost.session.setScopedModels(\n\t\t\t\tnewScopedModels.map((sm) => ({\n\t\t\t\t\tmodel: sm.model,\n\t\t\t\t\tthinkingLevel: sm.thinkingLevel,\n\t\t\t\t})),\n\t\t\t);\n\t\t} else {\n\t\t\t// All enabled or none enabled = no filter\n\t\t\thost.session.setScopedModels([]);\n\t\t}\n\t\tawait host.updateAvailableProviderCount();\n\t\thost.ui.requestRender();\n\t};\n\n\thost.showSelector((done) => {\n\t\tconst selector = new ScopedModelsSelectorComponent(\n\t\t\t{\n\t\t\t\tallModels,\n\t\t\t\tenabledModelIds: currentEnabledIds,\n\t\t\t},\n\t\t\t{\n\t\t\t\tonChange: async (enabledIds) => {\n\t\t\t\t\tawait updateSessionModels(enabledIds);\n\t\t\t\t},\n\t\t\t\tonPersist: (enabledIds) => {\n\t\t\t\t\t// Persist to settings\n\t\t\t\t\tconst newPatterns =\n\t\t\t\t\t\tenabledIds === null || enabledIds.length === allModels.length\n\t\t\t\t\t\t\t? undefined // All enabled = clear filter\n\t\t\t\t\t\t\t: enabledIds;\n\t\t\t\t\thost.settingsManager.setEnabledModels(newPatterns ? [...newPatterns] : undefined);\n\t\t\t\t\thost.showStatus(\"Model selection saved to settings\");\n\t\t\t\t},\n\t\t\t\tonCancel: () => {\n\t\t\t\t\tdone();\n\t\t\t\t\thost.ui.requestRender();\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\t\treturn { component: selector, focus: selector };\n\t});\n}\n\nexport function showUserMessageSelector(host: SessionFlowHost, newSessionName?: string): void {\n\tconst userMessages = host.session.getUserMessagesForForking();\n\n\tif (userMessages.length === 0) {\n\t\thost.showStatus(\"No messages to fork from\");\n\t\treturn;\n\t}\n\n\tconst initialSelectedId = userMessages[userMessages.length - 1]?.entryId;\n\n\thost.showSelector((done) => {\n\t\tconst selector = new UserMessageSelectorComponent(\n\t\t\tuserMessages.map((m) => ({ id: m.entryId, text: m.text })),\n\t\t\tasync (entryId) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await host.runtimeHost.fork(entryId);\n\t\t\t\t\tif (result.cancelled) {\n\t\t\t\t\t\tdone();\n\t\t\t\t\t\thost.ui.requestRender();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\thost.renderCurrentSessionState();\n\t\t\t\t\tif (newSessionName) {\n\t\t\t\t\t\thost.session.setSessionName(newSessionName);\n\t\t\t\t\t}\n\t\t\t\t\thost.editor.setText(result.selectedText ?? \"\");\n\t\t\t\t\tdone();\n\t\t\t\t\thost.showStatus(newSessionName ? `Forked to new session: ${newSessionName}` : \"Forked to new session\");\n\t\t\t\t} catch (error: unknown) {\n\t\t\t\t\tdone();\n\t\t\t\t\thost.showError(error instanceof Error ? error.message : String(error));\n\t\t\t\t}\n\t\t\t},\n\t\t\t() => {\n\t\t\t\tdone();\n\t\t\t\thost.ui.requestRender();\n\t\t\t},\n\t\t\tinitialSelectedId,\n\t\t);\n\t\treturn { component: selector, focus: selector.getMessageList() };\n\t});\n}\n\nexport function showTreeSelector(host: SessionFlowHost, initialSelectedId?: string): void {\n\tconst tree = host.sessionManager.getTree();\n\tconst realLeafId = host.sessionManager.getLeafId();\n\tconst initialFilterMode = host.settingsManager.getTreeFilterMode();\n\n\tif (tree.length === 0) {\n\t\thost.showStatus(\"No entries in session\");\n\t\treturn;\n\t}\n\n\thost.showSelector((done) => {\n\t\tconst selector = new TreeSelectorComponent(\n\t\t\ttree,\n\t\t\trealLeafId,\n\t\t\thost.ui.terminal.rows,\n\t\t\tasync (entryId) => {\n\t\t\t\t// Selecting the current leaf is a no-op (already there)\n\t\t\t\tif (entryId === realLeafId) {\n\t\t\t\t\tdone();\n\t\t\t\t\thost.showStatus(\"Already at this point\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Ask about summarization\n\t\t\t\tdone(); // Close selector first\n\n\t\t\t\t// Loop until user makes a complete choice or cancels to tree\n\t\t\t\tlet wantsSummary = false;\n\t\t\t\tlet customInstructions: string | undefined;\n\n\t\t\t\t// Check if we should skip the prompt (user preference to always default to no summary)\n\t\t\t\tif (!host.settingsManager.getBranchSummarySkipPrompt()) {\n\t\t\t\t\twhile (true) {\n\t\t\t\t\t\tconst summaryChoice = await host.extensionUiHost.showExtensionSelector(\"Summarize branch?\", [\n\t\t\t\t\t\t\t\"No summary\",\n\t\t\t\t\t\t\t\"Summarize\",\n\t\t\t\t\t\t\t\"Summarize with custom prompt\",\n\t\t\t\t\t\t]);\n\n\t\t\t\t\t\tif (summaryChoice === undefined) {\n\t\t\t\t\t\t\t// User pressed escape - re-show tree selector with same selection\n\t\t\t\t\t\t\tshowTreeSelector(host, entryId);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\twantsSummary = summaryChoice !== \"No summary\";\n\n\t\t\t\t\t\tif (summaryChoice === \"Summarize with custom prompt\") {\n\t\t\t\t\t\t\tcustomInstructions = await host.extensionUiHost.showExtensionEditor(\n\t\t\t\t\t\t\t\t\"Custom summarization instructions\",\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tif (customInstructions === undefined) {\n\t\t\t\t\t\t\t\t// User cancelled - loop back to summary selector\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// User made a complete choice\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Set up escape handler and loader if summarizing\n\t\t\t\tlet summaryLoader: Loader | undefined;\n\t\t\t\tconst originalOnEscape = host.defaultEditor.onEscape;\n\n\t\t\t\tif (wantsSummary) {\n\t\t\t\t\thost.defaultEditor.onEscape = () => {\n\t\t\t\t\t\thost.session.abortBranchSummary();\n\t\t\t\t\t};\n\t\t\t\t\thost.chatContainer.addChild(new Spacer(1));\n\t\t\t\t\tsummaryLoader = new Loader(\n\t\t\t\t\t\thost.ui,\n\t\t\t\t\t\t(spinner) => theme.fg(\"accent\", spinner),\n\t\t\t\t\t\t(text) => theme.fg(\"muted\", text),\n\t\t\t\t\t\t`Summarizing branch... (${keyText(\"app.interrupt\")} to cancel)`,\n\t\t\t\t\t);\n\t\t\t\t\thost.statusContainer.addChild(summaryLoader);\n\t\t\t\t\thost.ui.requestRender();\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await host.session.navigateTree(entryId, {\n\t\t\t\t\t\tsummarize: wantsSummary,\n\t\t\t\t\t\tcustomInstructions,\n\t\t\t\t\t});\n\n\t\t\t\t\tif (result.aborted) {\n\t\t\t\t\t\t// Summarization aborted - re-show tree selector with same selection\n\t\t\t\t\t\thost.showStatus(\"Branch summarization cancelled\");\n\t\t\t\t\t\tshowTreeSelector(host, entryId);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (result.cancelled) {\n\t\t\t\t\t\thost.showStatus(\"Navigation cancelled\");\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Update UI\n\t\t\t\t\tawait host.renderInitialMessages();\n\t\t\t\t\tif (result.editorText && !host.editor.getText().trim()) {\n\t\t\t\t\t\thost.editor.setText(result.editorText);\n\t\t\t\t\t}\n\t\t\t\t\thost.showStatus(\"Navigated to selected point\");\n\t\t\t\t\tvoid host.flushCompactionQueue({ willRetry: false });\n\t\t\t\t} catch (error) {\n\t\t\t\t\thost.showError(error instanceof Error ? error.message : String(error));\n\t\t\t\t} finally {\n\t\t\t\t\tif (summaryLoader) {\n\t\t\t\t\t\tsummaryLoader.stop();\n\t\t\t\t\t\thost.statusContainer.clear();\n\t\t\t\t\t}\n\t\t\t\t\thost.defaultEditor.onEscape = originalOnEscape;\n\t\t\t\t}\n\t\t\t},\n\t\t\t() => {\n\t\t\t\tdone();\n\t\t\t\thost.ui.requestRender();\n\t\t\t},\n\t\t\t(entryId, label) => {\n\t\t\t\thost.sessionManager.appendLabelChange(entryId, label);\n\t\t\t\thost.ui.requestRender();\n\t\t\t},\n\t\t\tinitialSelectedId,\n\t\t\tinitialFilterMode,\n\t\t);\n\t\treturn { component: selector, focus: selector };\n\t});\n}\n\nexport function showTrustSelector(host: SessionFlowHost): void {\n\tconst cwd = host.sessionManager.getCwd();\n\tconst trustStore = new ProjectTrustStore(host.runtimeHost.services.agentDir);\n\tconst savedDecision = trustStore.get(cwd);\n\thost.showSelector((done) => {\n\t\tconst selector = new TrustSelectorComponent({\n\t\t\tcwd,\n\t\t\tsavedDecision,\n\t\t\tprojectTrusted: host.settingsManager.isProjectTrusted(),\n\t\t\tonSelect: (trusted) => {\n\t\t\t\ttrustStore.set(cwd, trusted);\n\t\t\t\tdone();\n\t\t\t\thost.showStatus(\n\t\t\t\t\t`Saved trust decision: ${trusted ? \"trusted\" : \"untrusted\"}. Restart pi for this to take effect.`,\n\t\t\t\t);\n\t\t\t},\n\t\t\tonCancel: () => {\n\t\t\t\tdone();\n\t\t\t\thost.ui.requestRender();\n\t\t\t},\n\t\t});\n\t\treturn { component: selector, focus: selector };\n\t});\n}\n\nexport function showSessionSelector(host: SessionFlowHost): void {\n\thost.showSelector((done) => {\n\t\tconst selector = new SessionSelectorComponent(\n\t\t\t(onProgress) => listSessions(host.sessionManager.getCwd(), host.sessionManager.getSessionDir(), onProgress),\n\t\t\t(onProgress) =>\n\t\t\t\thost.sessionManager.usesDefaultSessionDir()\n\t\t\t\t\t? listAllSessions(onProgress)\n\t\t\t\t\t: listAllSessions(host.sessionManager.getSessionDir(), onProgress),\n\t\t\tasync (sessionPath) => {\n\t\t\t\tdone();\n\t\t\t\tawait handleResumeSession(host, sessionPath);\n\t\t\t},\n\t\t\t() => {\n\t\t\t\tdone();\n\t\t\t\thost.ui.requestRender();\n\t\t\t},\n\t\t\t() => {\n\t\t\t\tvoid host.shutdown();\n\t\t\t},\n\t\t\t() => host.ui.requestRender(),\n\t\t\t{\n\t\t\t\trenameSession: async (sessionFilePath: string, nextName: string | undefined) => {\n\t\t\t\t\tconst next = (nextName ?? \"\").trim();\n\t\t\t\t\tif (!next) return;\n\t\t\t\t\tconst mgr = openSession(sessionFilePath);\n\t\t\t\t\tmgr.appendSessionInfo(next);\n\t\t\t\t},\n\t\t\t\tshowRenameHint: true,\n\t\t\t\tkeybindings: host.keybindings,\n\t\t\t},\n\n\t\t\thost.sessionManager.getSessionFile(),\n\t\t);\n\t\treturn { component: selector, focus: selector };\n\t});\n}\n\nexport async function handleResumeSession(\n\thost: SessionFlowHost,\n\tsessionPath: string,\n\toptions?: Parameters<ExtensionCommandContext[\"switchSession\"]>[1],\n): Promise<{ cancelled: boolean }> {\n\tif (host.loadingAnimation) {\n\t\thost.loadingAnimation.stop();\n\t\thost.loadingAnimation = undefined;\n\t}\n\thost.statusContainer.clear();\n\ttry {\n\t\tconst result = await host.runtimeHost.switchSession(sessionPath, {\n\t\t\twithSession: options?.withSession,\n\t\t});\n\t\tif (result.cancelled) {\n\t\t\treturn result;\n\t\t}\n\t\thost.renderCurrentSessionState();\n\t\thost.showStatus(\"Resumed session\");\n\t\treturn result;\n\t} catch (error: unknown) {\n\t\tif (error instanceof MissingSessionCwdError) {\n\t\t\tconst selectedCwd = await host.promptForMissingSessionCwd(error);\n\t\t\tif (!selectedCwd) {\n\t\t\t\thost.showStatus(\"Resume cancelled\");\n\t\t\t\treturn { cancelled: true };\n\t\t\t}\n\t\t\tconst result = await host.runtimeHost.switchSession(sessionPath, {\n\t\t\t\tcwdOverride: selectedCwd,\n\t\t\t\twithSession: options?.withSession,\n\t\t\t});\n\t\t\tif (result.cancelled) {\n\t\t\t\treturn result;\n\t\t\t}\n\t\t\thost.renderCurrentSessionState();\n\t\t\thost.showStatus(\"Resumed session in current cwd\");\n\t\t\treturn result;\n\t\t}\n\t\treturn host.handleFatalRuntimeError(\"Failed to resume session\", error);\n\t}\n}\n\nexport async function handleModelCommand(host: SessionFlowHost, searchTerm?: string): Promise<void> {\n\tif (!searchTerm) {\n\t\tawait showModelSelector(host);\n\t\treturn;\n\t}\n\n\tconst model = await findExactModelMatch(host, searchTerm);\n\tif (model) {\n\t\ttry {\n\t\t\tawait host.session.setModel(model);\n\t\t\thost.footer.invalidate();\n\t\t\thost.updateEditorBorderColor();\n\t\t\thost.showStatus(`Model: ${model.id}`);\n\t\t\tvoid host.maybeWarnAboutAnthropicSubscriptionAuth(model);\n\t\t\thost.checkDaxnutsEasterEgg(model);\n\t\t} catch (error) {\n\t\t\thost.showError(error instanceof Error ? error.message : String(error));\n\t\t}\n\t\treturn;\n\t}\n\n\tawait showModelSelector(host, searchTerm);\n}\n\nexport async function findExactModelMatch(host: SessionFlowHost, searchTerm: string): Promise<Model<any> | undefined> {\n\tconst models = await host.getModelCandidates();\n\treturn findExactModelReferenceMatch(searchTerm, models);\n}\n\n// ===========================================================================\n// Prototype-tested leaf commands — narrow host shapes matching their fakes.\n// ===========================================================================\n\nexport interface CloneCommandHost {\n\treadonly sessionManager: { getLeafId: () => string | null };\n\treadonly runtimeHost: {\n\t\tfork: (entryId: string, options?: { position?: \"before\" | \"at\" }) => Promise<{ cancelled: boolean }>;\n\t};\n\trenderCurrentSessionState(): void;\n\treadonly editor: { setText: (text: string) => void };\n\treadonly session: { setSessionName: (name: string) => void };\n\tshowStatus(message: string): void;\n\tshowError(message: string): void;\n\treadonly ui: { requestRender: () => void };\n}\n\nexport async function handleCloneCommand(host: CloneCommandHost, newSessionName?: string): Promise<void> {\n\tconst leafId = host.sessionManager.getLeafId();\n\tif (!leafId) {\n\t\thost.showStatus(\"Nothing to clone yet\");\n\t\treturn;\n\t}\n\n\ttry {\n\t\tconst result = await host.runtimeHost.fork(leafId, { position: \"at\" });\n\t\tif (result.cancelled) {\n\t\t\thost.ui.requestRender();\n\t\t\treturn;\n\t\t}\n\n\t\thost.renderCurrentSessionState();\n\t\tif (newSessionName) {\n\t\t\thost.session.setSessionName(newSessionName);\n\t\t}\n\t\thost.editor.setText(\"\");\n\t\thost.showStatus(newSessionName ? `Cloned to new session: ${newSessionName}` : \"Cloned to new session\");\n\t} catch (error: unknown) {\n\t\thost.showError(error instanceof Error ? error.message : String(error));\n\t}\n}\n\nexport type ParsedGoalContinueCommand =\n\t| { ok: true; maxTurns: number; maxStallTurns: number; maxWallClockMinutes: number }\n\t| { ok: false; error: string };\n\nexport interface GoalCommandHost {\n\treadonly session: {\n\t\tgetGoalStateSnapshot: () => GoalState | undefined;\n\t\tsaveGoalStateSnapshot: (state: GoalState) => string;\n\t\tsendUserMessage: (content: string) => Promise<void>;\n\t\tcontinueGoalLoop: (options: GoalContinuationLoopOptions) => Promise<GoalContinuationLoopResult>;\n\t\tgetGoalRuntimeSnapshot: (settings: {\n\t\t\tmaxStallTurns: number;\n\t\t}) => ReturnType<AgentSession[\"getGoalRuntimeSnapshot\"]>;\n\t};\n\tshowStatus(message: string): void;\n\tshowError(message: string): void;\n\trefreshAutonomyFooterStatus(): void;\n}\n\nfunction formatGoalStatus(snapshot: ReturnType<AgentSession[\"getGoalRuntimeSnapshot\"]>): string {\n\tconst state = snapshot.goalState;\n\tif (!state) return `Goal: none (${snapshot.continuation.action}/${snapshot.continuation.reasonCode})`;\n\treturn `Goal: ${state.userGoal}\\nStatus: ${state.status}\\nRequirements: open ${snapshot.continuation.openRequirementIds.length}, blocked ${snapshot.continuation.blockedRequirementIds.length}, satisfied ${snapshot.continuation.satisfiedRequirementIds.length}\\nContinuation: ${snapshot.continuation.action}/${snapshot.continuation.reasonCode}`;\n}\n\nexport async function handleGoalCommand(host: GoalCommandHost, text: string): Promise<void> {\n\tconst goalText = text.replace(/^\\/goal\\s*/, \"\").trim();\n\tif (!goalText) {\n\t\thost.showStatus(formatGoalStatus(host.session.getGoalRuntimeSnapshot({ maxStallTurns: 20 })));\n\t\treturn;\n\t}\n\tconst now = new Date().toISOString();\n\tconst goalId = `goal-${Date.now().toString(36)}`;\n\tconst started = applyGoalAction(\n\t\thost.session.getGoalStateSnapshot(),\n\t\t{ action: \"start\", goalId, userGoal: goalText },\n\t\tnow,\n\t);\n\tif (!started.ok) {\n\t\thost.showError(started.error);\n\t\treturn;\n\t}\n\thost.session.saveGoalStateSnapshot(started.state);\n\t// Deterministic producer completion: a goal with zero open requirements evaluates to\n\t// finalize/no_open_requirements, so the loop would be undrivable whenever the model skips\n\t// decomposition (observed in the field). Seed one requirement from the goal text itself —\n\t// the model's decomposition below refines alongside it.\n\tconst seeded = applyGoalAction(\n\t\tstarted.state,\n\t\t{ action: \"add_requirement\", requirementId: `${goalId}-r1`, text: goalText },\n\t\tnow,\n\t);\n\tif (seeded.ok) {\n\t\thost.session.saveGoalStateSnapshot(seeded.state);\n\t}\n\tawait host.session.sendUserMessage(\n\t\t`Start goal: ${goalText}\\n\\nUse the goal tool this turn to decompose this goal into concrete open requirements with add_requirement actions, and satisfy_requirement ${goalId}-r1 once the decomposed requirements cover it.`,\n\t);\n\tconst result = await host.session.continueGoalLoop({ maxTurns: 1, maxStallTurns: 20, maxWallClockMinutes: 0 });\n\tconst continuation = result.finalSnapshot.continuation;\n\thost.showStatus(`Goal started: ${continuation.action}/${continuation.reasonCode}.`);\n\thost.refreshAutonomyFooterStatus();\n}\n\nexport interface GoalContinueCommandHost {\n\treadonly session: {\n\t\tcontinueGoalLoop: (options: GoalContinuationLoopOptions) => Promise<GoalContinuationLoopResult>;\n\t};\n\tparseGoalContinueCommand(text: string): ParsedGoalContinueCommand;\n\tshowStatus(message: string): void;\n\tshowError(message: string): void;\n\trefreshAutonomyFooterStatus(): void;\n}\n\nexport async function handleGoalContinueCommand(host: GoalContinueCommandHost, text: string): Promise<void> {\n\tconst parsed = host.parseGoalContinueCommand(text);\n\tif (!parsed.ok) {\n\t\thost.showError(parsed.error);\n\t\treturn;\n\t}\n\n\thost.showStatus(\n\t\t`Goal continuation started: up to ${parsed.maxTurns} turn(s), stall limit ${parsed.maxStallTurns}, wall-clock limit ${parsed.maxWallClockMinutes || \"disabled\"} minute(s).`,\n\t);\n\ttry {\n\t\tconst result = await host.session.continueGoalLoop({\n\t\t\tmaxTurns: parsed.maxTurns,\n\t\t\tmaxStallTurns: parsed.maxStallTurns,\n\t\t\tmaxWallClockMinutes: parsed.maxWallClockMinutes,\n\t\t});\n\t\tconst continuation = result.finalSnapshot.continuation;\n\t\thost.showStatus(\n\t\t\t`Goal continuation stopped: ${result.stopReason}; submitted ${result.turnsSubmitted} turn(s); latest decision ${continuation.action}/${continuation.reasonCode}.`,\n\t\t);\n\t} catch (error) {\n\t\thost.showError(`Goal continuation failed: ${error instanceof Error ? error.message : String(error)}`);\n\t} finally {\n\t\thost.refreshAutonomyFooterStatus();\n\t}\n}\n\nexport interface SessionInfoCommandHost {\n\treadonly session: {\n\t\tgetSessionStats: () => ReturnType<AgentSession[\"getSessionStats\"]>;\n\t\tgetDailyUsageTotals: () => ReturnType<AgentSession[\"getDailyUsageTotals\"]>;\n\t\tgetDailyUsageBreakdown: (formatLabel: (label: string) => string) => string;\n\t\tgetModelRouterStatus: (formatLabel: (label: string) => string) => string;\n\t};\n\treadonly sessionManager: { getSessionName: () => string | undefined };\n\treadonly chatContainer: Container;\n\treadonly ui: { requestRender: () => void };\n}\n\nexport function handleSessionCommand(host: SessionInfoCommandHost): void {\n\tconst stats = host.session.getSessionStats();\n\tconst sessionName = host.sessionManager.getSessionName();\n\n\tlet info = `${theme.bold(\"Session Info\")}\\n\\n`;\n\tif (sessionName) {\n\t\tinfo += `${theme.fg(\"dim\", \"Name:\")} ${sessionName}\\n`;\n\t}\n\tinfo += `${theme.fg(\"dim\", \"File:\")} ${stats.sessionFile ?? \"In-memory\"}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"ID:\")} ${stats.sessionId}\\n\\n`;\n\tinfo += `${theme.bold(\"Messages\")}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"User:\")} ${stats.userMessages}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Assistant:\")} ${stats.assistantMessages}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Tool Calls:\")} ${stats.toolCalls}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Tool Results:\")} ${stats.toolResults}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Total:\")} ${stats.totalMessages}\\n\\n`;\n\tinfo += `${theme.bold(\"Tokens\")}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Input:\")} ${stats.tokens.input.toLocaleString()}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Output:\")} ${stats.tokens.output.toLocaleString()}\\n`;\n\tif (stats.tokens.cacheRead > 0) {\n\t\tinfo += `${theme.fg(\"dim\", \"Cache Read:\")} ${stats.tokens.cacheRead.toLocaleString()}\\n`;\n\t}\n\tif (stats.tokens.cacheWrite > 0) {\n\t\tinfo += `${theme.fg(\"dim\", \"Cache Write:\")} ${stats.tokens.cacheWrite.toLocaleString()}\\n`;\n\t}\n\tinfo += `${theme.fg(\"dim\", \"Total:\")} ${stats.tokens.total.toLocaleString()}\\n`;\n\n\tconst dailyUsage = host.session.getDailyUsageTotals();\n\tif (stats.cost > 0 || dailyUsage.totalCost > 0) {\n\t\tinfo += `\\n${theme.bold(\"Cost\")}\\n`;\n\t\tinfo += `${theme.fg(\"dim\", \"Total:\")} $${stats.cost.toFixed(4)}\\n`;\n\t\tinfo += `${host.session.getDailyUsageBreakdown((label) => theme.fg(\"dim\", label))}`;\n\t}\n\n\tinfo += `\\n\\n${theme.bold(\"Model Router\")}\\n`;\n\tinfo += host.session.getModelRouterStatus((label) => theme.fg(\"dim\", label));\n\n\thost.chatContainer.addChild(new Spacer(1));\n\thost.chatContainer.addChild(new Text(info, 1, 0));\n\thost.ui.requestRender();\n}\n"]}
|
|
1
|
+
{"version":3,"file":"session-flow-commands.js","sourceRoot":"","sources":["../../../src/modes/interactive/session-flow-commands.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Session-picker, tree/fork navigation, and model-selector flows extracted from\n * interactive-mode.\n *\n * Each entry opens a selector overlay (via `host.showSelector`) or renders a\n * session-info block, driving `AgentSession`/`AgentSessionRuntime` navigation and\n * the fork/resume/clone/goal-continuation paths. The interdependent selector\n * flows share one narrow `SessionFlowHost` seam; the three prototype-tested leaf\n * commands (`handleCloneCommand`, `handleGoalContinueCommand`,\n * `handleSessionCommand`) take their own minimal host shapes so their behaviour\n * tests keep exercising them through interactive-mode's thin wrappers unchanged.\n */\n\nimport type { SessionManager } from \"@caupulican/pi-agent-core/node\";\nimport type { Model } from \"@caupulican/pi-ai\";\nimport type { EditorComponent } from \"@caupulican/pi-tui\";\nimport { type Component, type Container, Loader, Spacer, Text, type TUI } from \"@caupulican/pi-tui\";\nimport type {\n\tAgentSession,\n\tGoalContinuationLoopOptions,\n\tGoalContinuationLoopResult,\n} from \"../../core/agent-session.ts\";\nimport type { AgentSessionRuntime } from \"../../core/agent-session-runtime.ts\";\nimport type { ExtensionCommandContext } from \"../../core/extensions/index.ts\";\nimport type { GoalState } from \"../../core/goals/goal-state.ts\";\nimport { applyGoalAction } from \"../../core/goals/goal-tool-core.ts\";\nimport type { KeybindingsManager } from \"../../core/keybindings.ts\";\nimport { findExactModelReferenceMatch, resolveModelScope } from \"../../core/model-resolver.ts\";\nimport { MissingSessionCwdError } from \"../../core/session-cwd.ts\";\nimport { listAllSessions, listSessions, openSession } from \"../../core/session-manager-factory.ts\";\nimport type { SettingsManager } from \"../../core/settings-manager.ts\";\nimport { ProjectTrustStore } from \"../../core/trust-manager.ts\";\nimport type { CustomEditor } from \"./components/custom-editor.ts\";\nimport type { FooterComponent } from \"./components/footer.ts\";\nimport { keyText } from \"./components/keybinding-hints.ts\";\nimport { ModelSelectorComponent } from \"./components/model-selector.ts\";\nimport { ScopedModelsSelectorComponent } from \"./components/scoped-models-selector.ts\";\nimport { SessionSelectorComponent } from \"./components/session-selector.ts\";\nimport { TreeSelectorComponent } from \"./components/tree-selector.ts\";\nimport { TrustSelectorComponent } from \"./components/trust-selector.ts\";\nimport { UserMessageSelectorComponent } from \"./components/user-message-selector.ts\";\nimport type { ExtensionUiHost } from \"./extension-ui-host.ts\";\nimport { theme } from \"./theme/theme.ts\";\n\n/** Shared seam for the interdependent selector/navigation flows. */\nexport interface SessionFlowHost {\n\treadonly session: AgentSession;\n\treadonly sessionManager: SessionManager;\n\treadonly settingsManager: SettingsManager;\n\treadonly runtimeHost: AgentSessionRuntime;\n\treadonly ui: TUI;\n\treadonly chatContainer: Container;\n\treadonly statusContainer: Container;\n\treadonly editor: EditorComponent;\n\treadonly defaultEditor: CustomEditor;\n\treadonly footer: FooterComponent;\n\treadonly extensionUiHost: ExtensionUiHost;\n\treadonly keybindings: KeybindingsManager;\n\tloadingAnimation: Loader | undefined;\n\tshowSelector(create: (done: () => void) => { component: Component; focus: Component }): void;\n\tshowStatus(message: string): void;\n\tshowError(message: string): void;\n\trenderCurrentSessionState(): void;\n\trenderInitialMessages(options?: { forceHistoryLoad?: boolean }): Promise<void>;\n\tflushCompactionQueue(options?: { willRetry?: boolean }): Promise<void>;\n\thandleFatalRuntimeError(prefix: string, error: unknown): Promise<never>;\n\tpromptForMissingSessionCwd(error: MissingSessionCwdError): Promise<string | undefined>;\n\tupdateEditorBorderColor(): void;\n\tupdateAvailableProviderCount(): Promise<void>;\n\tmaybeWarnAboutAnthropicSubscriptionAuth(model?: Model<any>): Promise<void>;\n\tcheckDaxnutsEasterEgg(model: { provider: string; id: string }): void;\n\tgetModelCandidates(): Promise<Model<any>[]>;\n\tshutdown(options?: { fromSignal?: boolean }): Promise<void>;\n}\n\nexport async function showModelSelector(host: SessionFlowHost, initialSearchInput?: string): Promise<void> {\n\ttry {\n\t\tawait host.session.extensionRunner.emit({\n\t\t\ttype: \"model_selector_open\",\n\t\t\tcurrentModel: host.session.model,\n\t\t\tscopedModels: host.session.scopedModels,\n\t\t\tinitialSearchInput,\n\t\t});\n\t} catch (error) {\n\t\thost.showError(error instanceof Error ? error.message : String(error));\n\t\treturn;\n\t}\n\n\thost.showSelector((done) => {\n\t\tconst selector = new ModelSelectorComponent(\n\t\t\thost.ui,\n\t\t\thost.session.model,\n\t\t\thost.settingsManager,\n\t\t\thost.session.modelRegistry,\n\t\t\thost.session.scopedModels,\n\t\t\tasync (model) => {\n\t\t\t\ttry {\n\t\t\t\t\tawait host.session.setModel(model);\n\t\t\t\t\thost.footer.invalidate();\n\t\t\t\t\thost.updateEditorBorderColor();\n\t\t\t\t\tdone();\n\t\t\t\t\thost.showStatus(`Model: ${model.id}`);\n\t\t\t\t\tvoid host.maybeWarnAboutAnthropicSubscriptionAuth(model);\n\t\t\t\t\thost.checkDaxnutsEasterEgg(model);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tdone();\n\t\t\t\t\thost.showError(error instanceof Error ? error.message : String(error));\n\t\t\t\t}\n\t\t\t},\n\t\t\t() => {\n\t\t\t\tdone();\n\t\t\t\thost.ui.requestRender();\n\t\t\t},\n\t\t\tinitialSearchInput,\n\t\t);\n\t\treturn { component: selector, focus: selector };\n\t});\n}\n\nexport async function showModelsSelector(host: SessionFlowHost): Promise<void> {\n\t// Get all available models\n\thost.session.modelRegistry.refresh();\n\tconst allModels = host.session.modelRegistry.getAvailable();\n\n\tif (allModels.length === 0) {\n\t\thost.showStatus(\"No models available\");\n\t\treturn;\n\t}\n\n\t// Check if session has scoped models (from previous session-only changes or CLI --models)\n\tconst sessionScopedModels = host.session.scopedModels;\n\tconst hasSessionScope = sessionScopedModels.length > 0;\n\n\t// Build enabled model IDs from session state or settings\n\tlet currentEnabledIds: string[] | null = null;\n\n\tif (hasSessionScope) {\n\t\t// Use current session's scoped models\n\t\tcurrentEnabledIds = sessionScopedModels.map((scoped) => `${scoped.model.provider}/${scoped.model.id}`);\n\t} else {\n\t\t// Fall back to settings\n\t\tconst patterns = host.settingsManager.getEnabledModels();\n\t\tif (patterns !== undefined && patterns.length > 0) {\n\t\t\tconst scopedModels = await resolveModelScope(patterns, host.session.modelRegistry);\n\t\t\tcurrentEnabledIds = scopedModels.map((scoped) => `${scoped.model.provider}/${scoped.model.id}`);\n\t\t}\n\t}\n\n\t// Helper to update session's scoped models (session-only, no persist)\n\tconst updateSessionModels = async (enabledIds: string[] | null) => {\n\t\tcurrentEnabledIds = enabledIds === null ? null : [...enabledIds];\n\t\tif (enabledIds && enabledIds.length > 0 && enabledIds.length < allModels.length) {\n\t\t\tconst newScopedModels = await resolveModelScope(enabledIds, host.session.modelRegistry);\n\t\t\thost.session.setScopedModels(\n\t\t\t\tnewScopedModels.map((sm) => ({\n\t\t\t\t\tmodel: sm.model,\n\t\t\t\t\tthinkingLevel: sm.thinkingLevel,\n\t\t\t\t})),\n\t\t\t);\n\t\t} else {\n\t\t\t// All enabled or none enabled = no filter\n\t\t\thost.session.setScopedModels([]);\n\t\t}\n\t\tawait host.updateAvailableProviderCount();\n\t\thost.ui.requestRender();\n\t};\n\n\thost.showSelector((done) => {\n\t\tconst selector = new ScopedModelsSelectorComponent(\n\t\t\t{\n\t\t\t\tallModels,\n\t\t\t\tenabledModelIds: currentEnabledIds,\n\t\t\t},\n\t\t\t{\n\t\t\t\tonChange: async (enabledIds) => {\n\t\t\t\t\tawait updateSessionModels(enabledIds);\n\t\t\t\t},\n\t\t\t\tonPersist: (enabledIds) => {\n\t\t\t\t\t// Persist to settings\n\t\t\t\t\tconst newPatterns =\n\t\t\t\t\t\tenabledIds === null || enabledIds.length === allModels.length\n\t\t\t\t\t\t\t? undefined // All enabled = clear filter\n\t\t\t\t\t\t\t: enabledIds;\n\t\t\t\t\thost.settingsManager.setEnabledModels(newPatterns ? [...newPatterns] : undefined);\n\t\t\t\t\thost.showStatus(\"Model selection saved to settings\");\n\t\t\t\t},\n\t\t\t\tonCancel: () => {\n\t\t\t\t\tdone();\n\t\t\t\t\thost.ui.requestRender();\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\t\treturn { component: selector, focus: selector };\n\t});\n}\n\nexport function showUserMessageSelector(host: SessionFlowHost, newSessionName?: string): void {\n\tconst userMessages = host.session.getUserMessagesForForking();\n\n\tif (userMessages.length === 0) {\n\t\thost.showStatus(\"No messages to fork from\");\n\t\treturn;\n\t}\n\n\tconst initialSelectedId = userMessages[userMessages.length - 1]?.entryId;\n\n\thost.showSelector((done) => {\n\t\tconst selector = new UserMessageSelectorComponent(\n\t\t\tuserMessages.map((m) => ({ id: m.entryId, text: m.text })),\n\t\t\tasync (entryId) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await host.runtimeHost.fork(entryId);\n\t\t\t\t\tif (result.cancelled) {\n\t\t\t\t\t\tdone();\n\t\t\t\t\t\thost.ui.requestRender();\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\thost.renderCurrentSessionState();\n\t\t\t\t\tif (newSessionName) {\n\t\t\t\t\t\thost.session.setSessionName(newSessionName);\n\t\t\t\t\t}\n\t\t\t\t\thost.editor.setText(result.selectedText ?? \"\");\n\t\t\t\t\tdone();\n\t\t\t\t\thost.showStatus(newSessionName ? `Forked to new session: ${newSessionName}` : \"Forked to new session\");\n\t\t\t\t} catch (error: unknown) {\n\t\t\t\t\tdone();\n\t\t\t\t\thost.showError(error instanceof Error ? error.message : String(error));\n\t\t\t\t}\n\t\t\t},\n\t\t\t() => {\n\t\t\t\tdone();\n\t\t\t\thost.ui.requestRender();\n\t\t\t},\n\t\t\tinitialSelectedId,\n\t\t);\n\t\treturn { component: selector, focus: selector.getMessageList() };\n\t});\n}\n\nexport function showTreeSelector(host: SessionFlowHost, initialSelectedId?: string): void {\n\tconst tree = host.sessionManager.getTree();\n\tconst realLeafId = host.sessionManager.getLeafId();\n\tconst initialFilterMode = host.settingsManager.getTreeFilterMode();\n\n\tif (tree.length === 0) {\n\t\thost.showStatus(\"No entries in session\");\n\t\treturn;\n\t}\n\n\thost.showSelector((done) => {\n\t\tconst selector = new TreeSelectorComponent(\n\t\t\ttree,\n\t\t\trealLeafId,\n\t\t\thost.ui.terminal.rows,\n\t\t\tasync (entryId) => {\n\t\t\t\t// Selecting the current leaf is a no-op (already there)\n\t\t\t\tif (entryId === realLeafId) {\n\t\t\t\t\tdone();\n\t\t\t\t\thost.showStatus(\"Already at this point\");\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// Ask about summarization\n\t\t\t\tdone(); // Close selector first\n\n\t\t\t\t// Loop until user makes a complete choice or cancels to tree\n\t\t\t\tlet wantsSummary = false;\n\t\t\t\tlet customInstructions: string | undefined;\n\n\t\t\t\t// Check if we should skip the prompt (user preference to always default to no summary)\n\t\t\t\tif (!host.settingsManager.getBranchSummarySkipPrompt()) {\n\t\t\t\t\twhile (true) {\n\t\t\t\t\t\tconst summaryChoice = await host.extensionUiHost.showExtensionSelector(\"Summarize branch?\", [\n\t\t\t\t\t\t\t\"No summary\",\n\t\t\t\t\t\t\t\"Summarize\",\n\t\t\t\t\t\t\t\"Summarize with custom prompt\",\n\t\t\t\t\t\t]);\n\n\t\t\t\t\t\tif (summaryChoice === undefined) {\n\t\t\t\t\t\t\t// User pressed escape - re-show tree selector with same selection\n\t\t\t\t\t\t\tshowTreeSelector(host, entryId);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\twantsSummary = summaryChoice !== \"No summary\";\n\n\t\t\t\t\t\tif (summaryChoice === \"Summarize with custom prompt\") {\n\t\t\t\t\t\t\tcustomInstructions = await host.extensionUiHost.showExtensionEditor(\n\t\t\t\t\t\t\t\t\"Custom summarization instructions\",\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\tif (customInstructions === undefined) {\n\t\t\t\t\t\t\t\t// User cancelled - loop back to summary selector\n\t\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// User made a complete choice\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Set up escape handler and loader if summarizing\n\t\t\t\tlet summaryLoader: Loader | undefined;\n\t\t\t\tconst originalOnEscape = host.defaultEditor.onEscape;\n\n\t\t\t\tif (wantsSummary) {\n\t\t\t\t\thost.defaultEditor.onEscape = () => {\n\t\t\t\t\t\thost.session.abortBranchSummary();\n\t\t\t\t\t};\n\t\t\t\t\thost.chatContainer.addChild(new Spacer(1));\n\t\t\t\t\tsummaryLoader = new Loader(\n\t\t\t\t\t\thost.ui,\n\t\t\t\t\t\t(spinner) => theme.fg(\"accent\", spinner),\n\t\t\t\t\t\t(text) => theme.fg(\"muted\", text),\n\t\t\t\t\t\t`Summarizing branch... (${keyText(\"app.interrupt\")} to cancel)`,\n\t\t\t\t\t);\n\t\t\t\t\thost.statusContainer.addChild(summaryLoader);\n\t\t\t\t\thost.ui.requestRender();\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await host.session.navigateTree(entryId, {\n\t\t\t\t\t\tsummarize: wantsSummary,\n\t\t\t\t\t\tcustomInstructions,\n\t\t\t\t\t});\n\n\t\t\t\t\tif (result.aborted) {\n\t\t\t\t\t\t// Summarization aborted - re-show tree selector with same selection\n\t\t\t\t\t\thost.showStatus(\"Branch summarization cancelled\");\n\t\t\t\t\t\tshowTreeSelector(host, entryId);\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t\tif (result.cancelled) {\n\t\t\t\t\t\thost.showStatus(\"Navigation cancelled\");\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Update UI\n\t\t\t\t\tawait host.renderInitialMessages();\n\t\t\t\t\tif (result.editorText && !host.editor.getText().trim()) {\n\t\t\t\t\t\thost.editor.setText(result.editorText);\n\t\t\t\t\t}\n\t\t\t\t\thost.showStatus(\"Navigated to selected point\");\n\t\t\t\t\tvoid host.flushCompactionQueue({ willRetry: false });\n\t\t\t\t} catch (error) {\n\t\t\t\t\thost.showError(error instanceof Error ? error.message : String(error));\n\t\t\t\t} finally {\n\t\t\t\t\tif (summaryLoader) {\n\t\t\t\t\t\tsummaryLoader.stop();\n\t\t\t\t\t\thost.statusContainer.clear();\n\t\t\t\t\t}\n\t\t\t\t\thost.defaultEditor.onEscape = originalOnEscape;\n\t\t\t\t}\n\t\t\t},\n\t\t\t() => {\n\t\t\t\tdone();\n\t\t\t\thost.ui.requestRender();\n\t\t\t},\n\t\t\t(entryId, label) => {\n\t\t\t\thost.sessionManager.appendLabelChange(entryId, label);\n\t\t\t\thost.ui.requestRender();\n\t\t\t},\n\t\t\tinitialSelectedId,\n\t\t\tinitialFilterMode,\n\t\t);\n\t\treturn { component: selector, focus: selector };\n\t});\n}\n\nexport function showTrustSelector(host: SessionFlowHost): void {\n\tconst cwd = host.sessionManager.getCwd();\n\tconst trustStore = new ProjectTrustStore(host.runtimeHost.services.agentDir);\n\tconst savedDecision = trustStore.get(cwd);\n\thost.showSelector((done) => {\n\t\tconst selector = new TrustSelectorComponent({\n\t\t\tcwd,\n\t\t\tsavedDecision,\n\t\t\tprojectTrusted: host.settingsManager.isProjectTrusted(),\n\t\t\tonSelect: (trusted) => {\n\t\t\t\ttrustStore.set(cwd, trusted);\n\t\t\t\tdone();\n\t\t\t\thost.showStatus(\n\t\t\t\t\t`Saved trust decision: ${trusted ? \"trusted\" : \"untrusted\"}. Restart pi for this to take effect.`,\n\t\t\t\t);\n\t\t\t},\n\t\t\tonCancel: () => {\n\t\t\t\tdone();\n\t\t\t\thost.ui.requestRender();\n\t\t\t},\n\t\t});\n\t\treturn { component: selector, focus: selector };\n\t});\n}\n\nexport function showSessionSelector(host: SessionFlowHost): void {\n\thost.showSelector((done) => {\n\t\tconst selector = new SessionSelectorComponent(\n\t\t\t(onProgress) => listSessions(host.sessionManager.getCwd(), host.sessionManager.getSessionDir(), onProgress),\n\t\t\t(onProgress) =>\n\t\t\t\thost.sessionManager.usesDefaultSessionDir()\n\t\t\t\t\t? listAllSessions(onProgress)\n\t\t\t\t\t: listAllSessions(host.sessionManager.getSessionDir(), onProgress),\n\t\t\tasync (sessionPath) => {\n\t\t\t\tdone();\n\t\t\t\tawait handleResumeSession(host, sessionPath);\n\t\t\t},\n\t\t\t() => {\n\t\t\t\tdone();\n\t\t\t\thost.ui.requestRender();\n\t\t\t},\n\t\t\t() => {\n\t\t\t\tvoid host.shutdown();\n\t\t\t},\n\t\t\t() => host.ui.requestRender(),\n\t\t\t{\n\t\t\t\trenameSession: async (sessionFilePath: string, nextName: string | undefined) => {\n\t\t\t\t\tconst next = (nextName ?? \"\").trim();\n\t\t\t\t\tif (!next) return;\n\t\t\t\t\tconst mgr = openSession(sessionFilePath);\n\t\t\t\t\tmgr.appendSessionInfo(next);\n\t\t\t\t},\n\t\t\t\tshowRenameHint: true,\n\t\t\t\tkeybindings: host.keybindings,\n\t\t\t},\n\n\t\t\thost.sessionManager.getSessionFile(),\n\t\t);\n\t\treturn { component: selector, focus: selector };\n\t});\n}\n\nexport async function handleResumeSession(\n\thost: SessionFlowHost,\n\tsessionPath: string,\n\toptions?: Parameters<ExtensionCommandContext[\"switchSession\"]>[1],\n): Promise<{ cancelled: boolean }> {\n\tif (host.loadingAnimation) {\n\t\thost.loadingAnimation.stop();\n\t\thost.loadingAnimation = undefined;\n\t}\n\thost.statusContainer.clear();\n\ttry {\n\t\tconst result = await host.runtimeHost.switchSession(sessionPath, {\n\t\t\twithSession: options?.withSession,\n\t\t});\n\t\tif (result.cancelled) {\n\t\t\treturn result;\n\t\t}\n\t\thost.renderCurrentSessionState();\n\t\thost.showStatus(\"Resumed session\");\n\t\treturn result;\n\t} catch (error: unknown) {\n\t\tif (error instanceof MissingSessionCwdError) {\n\t\t\tconst selectedCwd = await host.promptForMissingSessionCwd(error);\n\t\t\tif (!selectedCwd) {\n\t\t\t\thost.showStatus(\"Resume cancelled\");\n\t\t\t\treturn { cancelled: true };\n\t\t\t}\n\t\t\tconst result = await host.runtimeHost.switchSession(sessionPath, {\n\t\t\t\tcwdOverride: selectedCwd,\n\t\t\t\twithSession: options?.withSession,\n\t\t\t});\n\t\t\tif (result.cancelled) {\n\t\t\t\treturn result;\n\t\t\t}\n\t\t\thost.renderCurrentSessionState();\n\t\t\thost.showStatus(\"Resumed session in current cwd\");\n\t\t\treturn result;\n\t\t}\n\t\treturn host.handleFatalRuntimeError(\"Failed to resume session\", error);\n\t}\n}\n\nexport async function handleModelCommand(host: SessionFlowHost, searchTerm?: string): Promise<void> {\n\tif (!searchTerm) {\n\t\tawait showModelSelector(host);\n\t\treturn;\n\t}\n\n\tconst model = await findExactModelMatch(host, searchTerm);\n\tif (model) {\n\t\ttry {\n\t\t\tawait host.session.setModel(model);\n\t\t\thost.footer.invalidate();\n\t\t\thost.updateEditorBorderColor();\n\t\t\thost.showStatus(`Model: ${model.id}`);\n\t\t\tvoid host.maybeWarnAboutAnthropicSubscriptionAuth(model);\n\t\t\thost.checkDaxnutsEasterEgg(model);\n\t\t} catch (error) {\n\t\t\thost.showError(error instanceof Error ? error.message : String(error));\n\t\t}\n\t\treturn;\n\t}\n\n\tawait showModelSelector(host, searchTerm);\n}\n\nexport async function findExactModelMatch(host: SessionFlowHost, searchTerm: string): Promise<Model<any> | undefined> {\n\tconst models = await host.getModelCandidates();\n\treturn findExactModelReferenceMatch(searchTerm, models);\n}\n\n// ===========================================================================\n// Prototype-tested leaf commands — narrow host shapes matching their fakes.\n// ===========================================================================\n\nexport interface CloneCommandHost {\n\treadonly sessionManager: { getLeafId: () => string | null };\n\treadonly runtimeHost: {\n\t\tfork: (entryId: string, options?: { position?: \"before\" | \"at\" }) => Promise<{ cancelled: boolean }>;\n\t};\n\trenderCurrentSessionState(): void;\n\treadonly editor: { setText: (text: string) => void };\n\treadonly session: { setSessionName: (name: string) => void };\n\tshowStatus(message: string): void;\n\tshowError(message: string): void;\n\treadonly ui: { requestRender: () => void };\n}\n\nexport async function handleCloneCommand(host: CloneCommandHost, newSessionName?: string): Promise<void> {\n\tconst leafId = host.sessionManager.getLeafId();\n\tif (!leafId) {\n\t\thost.showStatus(\"Nothing to clone yet\");\n\t\treturn;\n\t}\n\n\ttry {\n\t\tconst result = await host.runtimeHost.fork(leafId, { position: \"at\" });\n\t\tif (result.cancelled) {\n\t\t\thost.ui.requestRender();\n\t\t\treturn;\n\t\t}\n\n\t\thost.renderCurrentSessionState();\n\t\tif (newSessionName) {\n\t\t\thost.session.setSessionName(newSessionName);\n\t\t}\n\t\thost.editor.setText(\"\");\n\t\thost.showStatus(newSessionName ? `Cloned to new session: ${newSessionName}` : \"Cloned to new session\");\n\t} catch (error: unknown) {\n\t\thost.showError(error instanceof Error ? error.message : String(error));\n\t}\n}\n\nexport type ParsedGoalContinueCommand =\n\t| { ok: true; maxTurns: number; maxStallTurns: number; maxWallClockMinutes: number }\n\t| { ok: false; error: string };\n\nexport interface GoalCommandHost {\n\treadonly session: {\n\t\tgetGoalStateSnapshot: () => GoalState | undefined;\n\t\tsaveGoalStateSnapshot: (state: GoalState) => string;\n\t\tsendUserMessage: (content: string) => Promise<void>;\n\t\tcontinueGoalLoop: (options: GoalContinuationLoopOptions) => Promise<GoalContinuationLoopResult>;\n\t\tgetGoalRuntimeSnapshot: (settings: {\n\t\t\tmaxStallTurns: number;\n\t\t}) => ReturnType<AgentSession[\"getGoalRuntimeSnapshot\"]>;\n\t};\n\tshowStatus(message: string): void;\n\tshowError(message: string): void;\n\trefreshAutonomyFooterStatus(): void;\n}\n\nfunction formatGoalStatus(snapshot: ReturnType<AgentSession[\"getGoalRuntimeSnapshot\"]>): string {\n\tconst state = snapshot.goalState;\n\tif (!state) return `Goal: none (${snapshot.continuation.action}/${snapshot.continuation.reasonCode})`;\n\treturn `Goal: ${state.userGoal}\\nStatus: ${state.status}\\nRequirements: open ${snapshot.continuation.openRequirementIds.length}, blocked ${snapshot.continuation.blockedRequirementIds.length}, satisfied ${snapshot.continuation.satisfiedRequirementIds.length}\\nContinuation: ${snapshot.continuation.action}/${snapshot.continuation.reasonCode}`;\n}\n\nexport async function handleGoalCommand(host: GoalCommandHost, text: string): Promise<void> {\n\tconst goalText = text.replace(/^\\/goal\\s*/, \"\").trim();\n\tif (!goalText) {\n\t\thost.showStatus(formatGoalStatus(host.session.getGoalRuntimeSnapshot({ maxStallTurns: 20 })));\n\t\treturn;\n\t}\n\tconst now = new Date().toISOString();\n\tconst goalId = `goal-${Date.now().toString(36)}`;\n\tconst started = applyGoalAction(\n\t\thost.session.getGoalStateSnapshot(),\n\t\t{ action: \"start\", goalId, userGoal: goalText },\n\t\tnow,\n\t);\n\tif (!started.ok) {\n\t\thost.showError(started.error);\n\t\treturn;\n\t}\n\thost.session.saveGoalStateSnapshot(started.state);\n\t// Deterministic producer completion: a goal with zero open requirements evaluates to\n\t// finalize/no_open_requirements, so the loop would be undrivable whenever the model skips\n\t// decomposition (observed in the field). Seed one requirement from the goal text itself —\n\t// the model's decomposition below refines alongside it.\n\tconst seeded = applyGoalAction(\n\t\tstarted.state,\n\t\t{ action: \"add_requirement\", requirementId: `${goalId}-r1`, text: goalText },\n\t\tnow,\n\t);\n\tif (seeded.ok) {\n\t\thost.session.saveGoalStateSnapshot(seeded.state);\n\t}\n\tawait host.session.sendUserMessage(\n\t\t`Start goal: ${goalText}\\n\\nUse the goal tool this turn to decompose this goal into concrete open requirements with add_requirement actions, and satisfy_requirement ${goalId}-r1 once the decomposed requirements cover it.`,\n\t);\n\tconst result = await host.session.continueGoalLoop({ maxTurns: 1, maxStallTurns: 20, maxWallClockMinutes: 0 });\n\tconst continuation = result.finalSnapshot.continuation;\n\thost.showStatus(`Goal started: ${continuation.action}/${continuation.reasonCode}.`);\n\thost.refreshAutonomyFooterStatus();\n}\n\nexport interface GoalContinueCommandHost {\n\treadonly session: {\n\t\tcontinueGoalLoop: (options: GoalContinuationLoopOptions) => Promise<GoalContinuationLoopResult>;\n\t};\n\tparseGoalContinueCommand(text: string): ParsedGoalContinueCommand;\n\tshowStatus(message: string): void;\n\tshowError(message: string): void;\n\trefreshAutonomyFooterStatus(): void;\n}\n\nexport async function handleGoalContinueCommand(host: GoalContinueCommandHost, text: string): Promise<void> {\n\tconst parsed = host.parseGoalContinueCommand(text);\n\tif (!parsed.ok) {\n\t\thost.showError(parsed.error);\n\t\treturn;\n\t}\n\n\thost.showStatus(\n\t\t`Goal continuation started: up to ${parsed.maxTurns} turn(s), stall limit ${parsed.maxStallTurns}, wall-clock limit ${parsed.maxWallClockMinutes || \"disabled\"} minute(s).`,\n\t);\n\ttry {\n\t\tconst result = await host.session.continueGoalLoop({\n\t\t\tmaxTurns: parsed.maxTurns,\n\t\t\tmaxStallTurns: parsed.maxStallTurns,\n\t\t\tmaxWallClockMinutes: parsed.maxWallClockMinutes,\n\t\t});\n\t\tconst continuation = result.finalSnapshot.continuation;\n\t\thost.showStatus(\n\t\t\t`Goal continuation stopped: ${result.stopReason}; submitted ${result.turnsSubmitted} turn(s); latest decision ${continuation.action}/${continuation.reasonCode}.`,\n\t\t);\n\t} catch (error) {\n\t\thost.showError(`Goal continuation failed: ${error instanceof Error ? error.message : String(error)}`);\n\t} finally {\n\t\thost.refreshAutonomyFooterStatus();\n\t}\n}\n\nexport interface SessionInfoCommandHost {\n\treadonly session: {\n\t\tgetSessionStats: () => ReturnType<AgentSession[\"getSessionStats\"]>;\n\t\tgetCostSummary: () => ReturnType<AgentSession[\"getCostSummary\"]>;\n\t\tgetModelRouterStatus: (formatLabel: (label: string) => string) => string;\n\t};\n\treadonly sessionManager: { getSessionName: () => string | undefined };\n\treadonly chatContainer: Container;\n\treadonly ui: { requestRender: () => void };\n}\n\nexport function handleSessionCommand(host: SessionInfoCommandHost): void {\n\tconst stats = host.session.getSessionStats();\n\tconst sessionName = host.sessionManager.getSessionName();\n\n\tlet info = `${theme.bold(\"Session Info\")}\\n\\n`;\n\tif (sessionName) {\n\t\tinfo += `${theme.fg(\"dim\", \"Name:\")} ${sessionName}\\n`;\n\t}\n\tinfo += `${theme.fg(\"dim\", \"File:\")} ${stats.sessionFile ?? \"In-memory\"}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"ID:\")} ${stats.sessionId}\\n\\n`;\n\tinfo += `${theme.bold(\"Messages\")}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"User:\")} ${stats.userMessages}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Assistant:\")} ${stats.assistantMessages}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Tool Calls:\")} ${stats.toolCalls}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Tool Results:\")} ${stats.toolResults}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Total:\")} ${stats.totalMessages}\\n\\n`;\n\tinfo += `${theme.bold(\"Tokens\")}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Input:\")} ${stats.tokens.input.toLocaleString()}\\n`;\n\tinfo += `${theme.fg(\"dim\", \"Output:\")} ${stats.tokens.output.toLocaleString()}\\n`;\n\tif (stats.tokens.cacheRead > 0) {\n\t\tinfo += `${theme.fg(\"dim\", \"Cache Read:\")} ${stats.tokens.cacheRead.toLocaleString()}\\n`;\n\t}\n\tif (stats.tokens.cacheWrite > 0) {\n\t\tinfo += `${theme.fg(\"dim\", \"Cache Write:\")} ${stats.tokens.cacheWrite.toLocaleString()}\\n`;\n\t}\n\tinfo += `${theme.fg(\"dim\", \"Total:\")} ${stats.tokens.total.toLocaleString()}\\n`;\n\n\tconst costs = host.session.getCostSummary();\n\tif (costs.currentCost > 0 || costs.todayCost > 0 || costs.subagentReports > 0) {\n\t\tinfo += `\\n${theme.bold(\"Cost\")}\\n`;\n\t\tinfo += `${theme.fg(\"dim\", \"CURRENT (session):\")} $${costs.currentCost.toFixed(4)}\\n`;\n\t\tif (costs.subagentReports > 0 || costs.subagentCost > 0) {\n\t\t\tinfo += `${theme.fg(\"dim\", \"SUBAGENTS (included in CURRENT):\")} $${costs.subagentCost.toFixed(4)} (${costs.subagentReports} reports)\\n`;\n\t\t}\n\t\tinfo += `${theme.fg(\"dim\", \"TODAY (host local day):\")} $${costs.todayCost.toFixed(4)}\\n`;\n\t\tinfo += `${theme.fg(\"dim\", \"Today rollover:\")} local midnight`;\n\t}\n\n\tinfo += `\\n\\n${theme.bold(\"Model Router\")}\\n`;\n\tinfo += host.session.getModelRouterStatus((label) => theme.fg(\"dim\", label));\n\n\thost.chatContainer.addChild(new Spacer(1));\n\thost.chatContainer.addChild(new Text(info, 1, 0));\n\thost.ui.requestRender();\n}\n"]}
|
package/docs/settings.md
CHANGED
|
@@ -150,20 +150,22 @@ Fitness applicability is intentionally split by autonomy level:
|
|
|
150
150
|
|
|
151
151
|
| Setting | Type | Default | Description |
|
|
152
152
|
|---------|------|---------|-------------|
|
|
153
|
-
| `toolRepair.repair` | boolean | `true` | Enable deterministic repair of invalid model-emitted tool arguments before execution |
|
|
154
153
|
| `toolRepair.teach` | boolean | `true` | Enable in-band repair teaching notes on repaired tool results |
|
|
155
154
|
| `toolRepair.textProtocol` | boolean | model-dependent | Emergency global override for text tool-call protocol calibration. Prefer per-model `textToolCallProtocol` in `models.json` for deterministic model setup. |
|
|
155
|
+
| `toolRepair.logging` | boolean | `true` | Enable background tool-recovery telemetry/failure-corpus logging. When `false`, repair still runs but Pi does not enqueue or write tool-recovery log records. |
|
|
156
|
+
|
|
157
|
+
Deterministic argument repair is built in and has no settings toggle; schema-valid calls still return unchanged without entering the repair layer. `PI_TOOL_REPAIR_DISABLED=1` remains only an emergency diagnostic kill switch.
|
|
156
158
|
|
|
157
159
|
Text protocol precedence is: `PI_TEXT_TOOL_CALL_PROTOCOL_DISABLED=1` kills it, then `toolRepair.textProtocol` force-enables or disables it globally, then per-model `textToolCallProtocol` applies, then a persisted `/toolprobe` text-protocol verdict applies to that exact model. Native provider tool calls still take precedence when the model emits them; the text protocol is the fallback lane for pure-text models. Failed calibration is stored per host/model and can be cleared with `/toolprotocol-reset <provider/model>`.
|
|
158
160
|
|
|
159
|
-
Environment kill switches override
|
|
161
|
+
Environment kill switches override their diagnostic layers: `PI_TOOL_REPAIR_DISABLED=1`, `PI_TOOL_REPAIR_TEACH_DISABLED=1`, and `PI_TEXT_TOOL_CALL_PROTOCOL_DISABLED=1`. See [Tool repair](tool-repair.md) for diagnostics, reset controls, and replay.
|
|
160
162
|
|
|
161
163
|
```json
|
|
162
164
|
{
|
|
163
165
|
"toolRepair": {
|
|
164
|
-
"repair": true,
|
|
165
166
|
"teach": true,
|
|
166
|
-
"textProtocol": true
|
|
167
|
+
"textProtocol": true,
|
|
168
|
+
"logging": true
|
|
167
169
|
}
|
|
168
170
|
}
|
|
169
171
|
```
|
package/docs/tool-repair.md
CHANGED
|
@@ -6,8 +6,9 @@ Pi validates every model-emitted tool call against its TypeBox schema before exe
|
|
|
6
6
|
|
|
7
7
|
- The shared validation choke point is `validateToolArguments` in `packages/ai/src/utils/validation.ts`.
|
|
8
8
|
- Repair is validate-then-repair: schema-valid arguments are returned unchanged; only invalid arguments enter the repair layer.
|
|
9
|
-
- Repair
|
|
9
|
+
- Repair is built-in and has no settings toggle. `PI_TOOL_REPAIR_DISABLED=1` is only an emergency diagnostic kill switch; normal configuration should leave repair on.
|
|
10
10
|
- Teaching can be disabled independently with `toolRepair.teach: false` or `PI_TOOL_REPAIR_TEACH_DISABLED=1`. Repairs can still execute; the in-band "Tool argument repair note" is suppressed.
|
|
11
|
+
- Tool-recovery logging can be disabled with `toolRepair.logging: false`. Repairs still run, but Pi does not enqueue recovery records or spawn the background recovery-log worker.
|
|
11
12
|
- Text tool-call protocol calibration can be enabled per model with `textToolCallProtocol: true` in `models.json`. `/toolprobe [provider/model]` can also persist a host-local text-protocol verdict for one model after a live probe. Use `toolRepair.textProtocol` only as a global emergency force/kill switch; `PI_TEXT_TOOL_CALL_PROTOCOL_DISABLED=1` always disables it.
|
|
12
13
|
|
|
13
14
|
Example project settings:
|
|
@@ -15,9 +16,9 @@ Example project settings:
|
|
|
15
16
|
```json
|
|
16
17
|
{
|
|
17
18
|
"toolRepair": {
|
|
18
|
-
"repair": true,
|
|
19
19
|
"teach": true,
|
|
20
|
-
"textProtocol": true
|
|
20
|
+
"textProtocol": true,
|
|
21
|
+
"logging": true
|
|
21
22
|
}
|
|
22
23
|
}
|
|
23
24
|
```
|
|
@@ -26,7 +27,7 @@ Example project settings:
|
|
|
26
27
|
|
|
27
28
|
- Interactive tool panels show `[repaired arguments]` when execution used repaired arguments.
|
|
28
29
|
- RPC `tool_execution_start`, `tool_execution_update`, and `tool_execution_end` events include a `repair` object when arguments were repaired.
|
|
29
|
-
- `/toolhealth` prints model adaptation records for this host: tool-probe verdicts, calibrated or failed text protocol, learned standing rules, and
|
|
30
|
+
- `/toolhealth` prints model adaptation records for this host: tool-probe verdicts, calibrated or failed text protocol, learned standing rules, teach statistics, and recovery-log worker counters.
|
|
30
31
|
- `/toolrule-remove <provider/model> <mode>` removes one learned standing rule from the host-local adaptation store.
|
|
31
32
|
- `/toolprotocol-reset <provider/model>` removes a stored text protocol calibration or failed-calibration record so the next turn can calibrate again.
|
|
32
33
|
- `/toolprobe [provider/model]` probes the current fleet or one explicit model for native tool calls first, then text-protocol fallback, persists the verdict in the host-local adaptation store, and prints a report table.
|
|
@@ -42,7 +43,7 @@ node scripts/tool-repair-replay.mjs ~/.pi/agent/state/failure-corpus.jsonl --jso
|
|
|
42
43
|
node scripts/tool-repair-replay.mjs ~/.pi/agent/sessions/<session>.jsonl --fixtures /tmp/tool-repair-fixtures.json
|
|
43
44
|
```
|
|
44
45
|
|
|
45
|
-
The replay helper reads `tool_validation` corpus records and bounced `tool_argument_validation` session entries. Records contain shape metadata, failure modes, and error keywords; they do not store full tool arguments.
|
|
46
|
+
The replay helper reads `tool_validation` corpus records and legacy bounced `tool_argument_validation` session entries. Current recovery telemetry is written by a dedicated `node:worker_threads` worker to `state/tool-recovery-events.jsonl`; bounced records also append sanitized `tool_validation` corpus rows. Records contain shape metadata, failure modes, and error keywords; they do not store full tool arguments.
|
|
46
47
|
|
|
47
48
|
## Repair modes
|
|
48
49
|
|
|
@@ -76,10 +77,10 @@ For a previously calibrated model, repeated live parse failures invalidate the s
|
|
|
76
77
|
|
|
77
78
|
Confirmed against current source:
|
|
78
79
|
|
|
79
|
-
- Shared validation and repair
|
|
80
|
+
- Shared validation and repair choke point: `packages/ai/src/utils/validation.ts`.
|
|
80
81
|
- Repair mode names and standing-rule text: `packages/ai/src/utils/tool-repair/registry.ts`.
|
|
81
82
|
- Agent repair event metadata and teach-note gate: `packages/agent/src/types.ts`, `packages/agent/src/agent-loop.ts`.
|
|
82
83
|
- Interactive marker: `packages/coding-agent/src/modes/interactive/components/tool-execution.ts`.
|
|
83
84
|
- Settings/env kill switches: `packages/coding-agent/src/core/settings-manager.ts`, `packages/coding-agent/src/core/tool-repair-settings.ts`.
|
|
84
85
|
- Health, tool probing, rule removal, and protocol reset: `packages/coding-agent/src/core/tool-repair-health.ts`, `packages/coding-agent/src/core/models/adaptation-store.ts`, `packages/coding-agent/src/core/slash-commands.ts`, `packages/coding-agent/src/modes/interactive/interactive-mode.ts`, `packages/coding-agent/src/modes/rpc/rpc-mode.ts`.
|
|
85
|
-
-
|
|
86
|
+
- Recovery logging, failure corpus, and replay: `packages/coding-agent/src/core/tool-recovery-logger.ts`, `packages/coding-agent/src/core/tool-recovery-log-worker.ts`, `packages/coding-agent/src/core/failure-corpus.ts`, `scripts/tool-repair-replay.mjs`.
|
package/docs/usage.md
CHANGED
|
@@ -13,6 +13,12 @@ The interface has four main areas:
|
|
|
13
13
|
- **Editor** - where you type; border color indicates the current thinking level
|
|
14
14
|
- **Footer** - working directory, session name, token/cache usage, cost, context usage, and current model
|
|
15
15
|
|
|
16
|
+
Footer cost labels match the `/usage`, `/session`, and autonomy status cost line:
|
|
17
|
+
|
|
18
|
+
- **CURRENT** is the current session file's total recorded cost, including assistant usage and any **SUBAGENTS** cost.
|
|
19
|
+
- **TODAY** is this host's active session-storage total for the local calendar day; it rolls over at local midnight.
|
|
20
|
+
- **SUBAGENTS** appears only when delegated/spawned workers reported cost in the current session, and that amount is already included in **CURRENT**.
|
|
21
|
+
|
|
16
22
|
The editor can be replaced temporarily by built-in UI such as `/settings` or by custom extension UI.
|
|
17
23
|
|
|
18
24
|
### Editor Features
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-extension-custom-provider",
|
|
3
|
-
"version": "0.81.
|
|
3
|
+
"version": "0.81.24",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "pi-extension-custom-provider",
|
|
9
|
-
"version": "0.81.
|
|
9
|
+
"version": "0.81.24",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@anthropic-ai/sdk": "^0.52.0"
|
|
12
12
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-extension-sandbox",
|
|
3
|
-
"version": "0.81.
|
|
3
|
+
"version": "0.81.24",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "pi-extension-sandbox",
|
|
9
|
-
"version": "0.81.
|
|
9
|
+
"version": "0.81.24",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@anthropic-ai/sandbox-runtime": "^0.0.26"
|
|
12
12
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-extension-with-deps",
|
|
3
|
-
"version": "0.81.
|
|
3
|
+
"version": "0.81.24",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "pi-extension-with-deps",
|
|
9
|
-
"version": "0.81.
|
|
9
|
+
"version": "0.81.24",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"ms": "^2.1.3"
|
|
12
12
|
},
|