@caupulican/pi-adaptative 0.80.103 → 0.81.0
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 +120 -0
- package/dist/cli/session-picker.d.ts +1 -1
- package/dist/cli/session-picker.d.ts.map +1 -1
- package/dist/cli/session-picker.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +7 -1
- package/dist/cli.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts +1 -1
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +6 -6
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session-services.d.ts +1 -1
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +152 -512
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +635 -4590
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/autonomy/session-lane-record.d.ts +1 -1
- package/dist/core/autonomy/session-lane-record.d.ts.map +1 -1
- package/dist/core/autonomy/session-lane-record.js.map +1 -1
- package/dist/core/autonomy/status.d.ts +1 -0
- package/dist/core/autonomy/status.d.ts.map +1 -1
- package/dist/core/autonomy/status.js +1 -0
- package/dist/core/autonomy/status.js.map +1 -1
- package/dist/core/autonomy-telemetry.d.ts +80 -0
- package/dist/core/autonomy-telemetry.d.ts.map +1 -0
- package/dist/core/autonomy-telemetry.js +266 -0
- package/dist/core/autonomy-telemetry.js.map +1 -0
- package/dist/core/background-lane-controller.d.ts +186 -0
- package/dist/core/background-lane-controller.d.ts.map +1 -0
- package/dist/core/background-lane-controller.js +691 -0
- package/dist/core/background-lane-controller.js.map +1 -0
- package/dist/core/bash-execution-controller.d.ts +51 -0
- package/dist/core/bash-execution-controller.d.ts.map +1 -0
- package/dist/core/bash-execution-controller.js +96 -0
- package/dist/core/bash-execution-controller.js.map +1 -0
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js +9 -2
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/compaction-support.d.ts +56 -0
- package/dist/core/compaction-support.d.ts.map +1 -0
- package/dist/core/compaction-support.js +99 -0
- package/dist/core/compaction-support.js.map +1 -0
- package/dist/core/context/artifact-retrieval.d.ts +1 -1
- package/dist/core/context/artifact-retrieval.d.ts.map +1 -1
- package/dist/core/context/artifact-retrieval.js +1 -1
- package/dist/core/context/artifact-retrieval.js.map +1 -1
- package/dist/core/context/context-composition.d.ts.map +1 -1
- package/dist/core/context/context-composition.js +1 -1
- package/dist/core/context/context-composition.js.map +1 -1
- package/dist/core/context/tool-output-packer.d.ts +1 -1
- package/dist/core/context/tool-output-packer.d.ts.map +1 -1
- package/dist/core/context/tool-output-packer.js +1 -1
- package/dist/core/context/tool-output-packer.js.map +1 -1
- package/dist/core/context-gc.d.ts.map +1 -1
- package/dist/core/context-gc.js +1 -1
- package/dist/core/context-gc.js.map +1 -1
- package/dist/core/context-pipeline.d.ts +223 -0
- package/dist/core/context-pipeline.d.ts.map +1 -0
- package/dist/core/context-pipeline.js +594 -0
- package/dist/core/context-pipeline.js.map +1 -0
- package/dist/core/cost/daily-usage.d.ts +1 -1
- package/dist/core/cost/daily-usage.d.ts.map +1 -1
- package/dist/core/cost/daily-usage.js +1 -1
- package/dist/core/cost/daily-usage.js.map +1 -1
- package/dist/core/cost/session-usage.d.ts +1 -1
- package/dist/core/cost/session-usage.d.ts.map +1 -1
- package/dist/core/cost/session-usage.js +1 -1
- package/dist/core/cost/session-usage.js.map +1 -1
- package/dist/core/delegation/session-worker-result.d.ts +1 -1
- package/dist/core/delegation/session-worker-result.d.ts.map +1 -1
- package/dist/core/delegation/session-worker-result.js.map +1 -1
- package/dist/core/exec.d.ts +2 -0
- package/dist/core/exec.d.ts.map +1 -1
- package/dist/core/exec.js +15 -9
- package/dist/core/exec.js.map +1 -1
- package/dist/core/export-html/index.d.ts +1 -1
- package/dist/core/export-html/index.d.ts.map +1 -1
- package/dist/core/export-html/index.js +2 -2
- package/dist/core/export-html/index.js.map +1 -1
- package/dist/core/extensions/builtin.d.ts.map +1 -1
- package/dist/core/extensions/builtin.js +2 -2
- package/dist/core/extensions/builtin.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +1 -1
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +2 -4
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/goal-loop-controller.d.ts +24 -0
- package/dist/core/goal-loop-controller.d.ts.map +1 -0
- package/dist/core/goal-loop-controller.js +83 -0
- package/dist/core/goal-loop-controller.js.map +1 -0
- package/dist/core/goals/goal-runtime-snapshot.d.ts +1 -1
- package/dist/core/goals/goal-runtime-snapshot.d.ts.map +1 -1
- package/dist/core/goals/goal-runtime-snapshot.js.map +1 -1
- package/dist/core/goals/session-goal-state.d.ts +1 -1
- package/dist/core/goals/session-goal-state.d.ts.map +1 -1
- package/dist/core/goals/session-goal-state.js.map +1 -1
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/learning/learning-audit.d.ts +1 -1
- package/dist/core/learning/learning-audit.d.ts.map +1 -1
- package/dist/core/learning/learning-audit.js.map +1 -1
- package/dist/core/learning/session-learning-decision.d.ts +1 -1
- package/dist/core/learning/session-learning-decision.d.ts.map +1 -1
- package/dist/core/learning/session-learning-decision.js.map +1 -1
- package/dist/core/local-runtime-controller.d.ts +99 -0
- package/dist/core/local-runtime-controller.d.ts.map +1 -0
- package/dist/core/local-runtime-controller.js +214 -0
- package/dist/core/local-runtime-controller.js.map +1 -0
- package/dist/core/memory/providers/transcript-recall.d.ts.map +1 -1
- package/dist/core/memory/providers/transcript-recall.js +1 -1
- package/dist/core/memory/providers/transcript-recall.js.map +1 -1
- package/dist/core/memory-controller.d.ts +139 -0
- package/dist/core/memory-controller.d.ts.map +1 -0
- package/dist/core/memory-controller.js +323 -0
- package/dist/core/memory-controller.js.map +1 -0
- package/dist/core/model-router/status.d.ts +1 -1
- package/dist/core/model-router/status.d.ts.map +1 -1
- package/dist/core/model-router/status.js.map +1 -1
- package/dist/core/model-router-controller.d.ts +140 -0
- package/dist/core/model-router-controller.d.ts.map +1 -0
- package/dist/core/model-router-controller.js +623 -0
- package/dist/core/model-router-controller.js.map +1 -0
- package/dist/core/model-selection-controller.d.ts +95 -0
- package/dist/core/model-selection-controller.d.ts.map +1 -0
- package/dist/core/model-selection-controller.js +252 -0
- package/dist/core/model-selection-controller.js.map +1 -0
- package/dist/core/models/model-ref.d.ts +13 -0
- package/dist/core/models/model-ref.d.ts.map +1 -1
- package/dist/core/models/model-ref.js +22 -0
- package/dist/core/models/model-ref.js.map +1 -1
- package/dist/core/profile-filter-controller.d.ts +77 -0
- package/dist/core/profile-filter-controller.d.ts.map +1 -0
- package/dist/core/profile-filter-controller.js +159 -0
- package/dist/core/profile-filter-controller.js.map +1 -0
- package/dist/core/reflection-controller.d.ts +111 -0
- package/dist/core/reflection-controller.d.ts.map +1 -0
- package/dist/core/reflection-controller.js +412 -0
- package/dist/core/reflection-controller.js.map +1 -0
- package/dist/core/research/model-fitness.d.ts +12 -0
- package/dist/core/research/model-fitness.d.ts.map +1 -1
- package/dist/core/research/model-fitness.js +21 -0
- package/dist/core/research/model-fitness.js.map +1 -1
- package/dist/core/research/session-evidence-bundle.d.ts +1 -1
- package/dist/core/research/session-evidence-bundle.d.ts.map +1 -1
- package/dist/core/research/session-evidence-bundle.js.map +1 -1
- package/dist/core/runtime-builder.d.ts +222 -0
- package/dist/core/runtime-builder.d.ts.map +1 -0
- package/dist/core/runtime-builder.js +640 -0
- package/dist/core/runtime-builder.js.map +1 -0
- package/dist/core/sdk.d.ts +2 -2
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +3 -4
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-analytics.d.ts +96 -0
- package/dist/core/session-analytics.d.ts.map +1 -0
- package/dist/core/session-analytics.js +331 -0
- package/dist/core/session-analytics.js.map +1 -0
- package/dist/core/session-manager-factory.d.ts +18 -0
- package/dist/core/session-manager-factory.d.ts.map +1 -0
- package/dist/core/session-manager-factory.js +32 -0
- package/dist/core/session-manager-factory.js.map +1 -0
- package/dist/core/session-tree-navigator.d.ts +68 -0
- package/dist/core/session-tree-navigator.d.ts.map +1 -0
- package/dist/core/session-tree-navigator.js +217 -0
- package/dist/core/session-tree-navigator.js.map +1 -0
- package/dist/core/system-prompt-builder.d.ts +63 -0
- package/dist/core/system-prompt-builder.d.ts.map +1 -0
- package/dist/core/system-prompt-builder.js +181 -0
- package/dist/core/system-prompt-builder.js.map +1 -0
- package/dist/core/tool-gate-controller.d.ts +36 -0
- package/dist/core/tool-gate-controller.d.ts.map +1 -0
- package/dist/core/tool-gate-controller.js +94 -0
- package/dist/core/tool-gate-controller.js.map +1 -0
- package/dist/core/tools/artifact-retrieve.d.ts.map +1 -1
- package/dist/core/tools/artifact-retrieve.js +1 -1
- package/dist/core/tools/artifact-retrieve.js.map +1 -1
- package/dist/core/tools/bash.d.ts +4 -2
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +49 -7
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/file-mutation-queue.d.ts +6 -0
- package/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
- package/dist/core/tools/file-mutation-queue.js +61 -1
- package/dist/core/tools/file-mutation-queue.js.map +1 -1
- package/dist/core/tools/find.d.ts +1 -1
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +1 -1
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/grep.d.ts +1 -1
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +1 -1
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/index.d.ts +1 -1
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +1 -1
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/ls.d.ts +1 -1
- package/dist/core/tools/ls.d.ts.map +1 -1
- package/dist/core/tools/ls.js +1 -1
- package/dist/core/tools/ls.js.map +1 -1
- package/dist/core/tools/output-accumulator.d.ts +1 -1
- package/dist/core/tools/output-accumulator.d.ts.map +1 -1
- package/dist/core/tools/output-accumulator.js +1 -1
- package/dist/core/tools/output-accumulator.js.map +1 -1
- package/dist/core/tools/read.d.ts +1 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +1 -1
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/render-utils.d.ts.map +1 -1
- package/dist/core/tools/render-utils.js +1 -1
- package/dist/core/tools/render-utils.js.map +1 -1
- package/dist/index.d.ts +2 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -4
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +13 -12
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/auth-dialogs-controller.d.ts +59 -0
- package/dist/modes/interactive/auth-dialogs-controller.d.ts.map +1 -0
- package/dist/modes/interactive/auth-dialogs-controller.js +398 -0
- package/dist/modes/interactive/auth-dialogs-controller.js.map +1 -0
- package/dist/modes/interactive/auto-learn-controller.d.ts +168 -0
- package/dist/modes/interactive/auto-learn-controller.d.ts.map +1 -0
- package/dist/modes/interactive/auto-learn-controller.js +1239 -0
- package/dist/modes/interactive/auto-learn-controller.js.map +1 -0
- package/dist/modes/interactive/autocomplete-provider.d.ts +26 -0
- package/dist/modes/interactive/autocomplete-provider.d.ts.map +1 -0
- package/dist/modes/interactive/autocomplete-provider.js +103 -0
- package/dist/modes/interactive/autocomplete-provider.js.map +1 -0
- package/dist/modes/interactive/autonomy-commands.d.ts +38 -0
- package/dist/modes/interactive/autonomy-commands.d.ts.map +1 -0
- package/dist/modes/interactive/autonomy-commands.js +142 -0
- package/dist/modes/interactive/autonomy-commands.js.map +1 -0
- package/dist/modes/interactive/clipboard-input.d.ts +37 -0
- package/dist/modes/interactive/clipboard-input.d.ts.map +1 -0
- package/dist/modes/interactive/clipboard-input.js +59 -0
- package/dist/modes/interactive/clipboard-input.js.map +1 -0
- package/dist/modes/interactive/compaction-queue.d.ts +30 -0
- package/dist/modes/interactive/compaction-queue.d.ts.map +1 -0
- package/dist/modes/interactive/compaction-queue.js +91 -0
- package/dist/modes/interactive/compaction-queue.js.map +1 -0
- package/dist/modes/interactive/components/bash-execution.d.ts +1 -1
- package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/bash-execution.js +1 -1
- package/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.d.ts +1 -1
- package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.d.ts +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/custom-message.d.ts +1 -1
- package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-message.js.map +1 -1
- package/dist/modes/interactive/components/session-selector-search.d.ts +1 -1
- package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +2 -2
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/tree-selector.d.ts +1 -1
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-selector.js.map +1 -1
- package/dist/modes/interactive/config-backup.d.ts +27 -0
- package/dist/modes/interactive/config-backup.d.ts.map +1 -0
- package/dist/modes/interactive/config-backup.js +146 -0
- package/dist/modes/interactive/config-backup.js.map +1 -0
- package/dist/modes/interactive/editor-overlay-host.d.ts +48 -0
- package/dist/modes/interactive/editor-overlay-host.d.ts.map +1 -0
- package/dist/modes/interactive/editor-overlay-host.js +43 -0
- package/dist/modes/interactive/editor-overlay-host.js.map +1 -0
- package/dist/modes/interactive/extension-ui-host.d.ts +165 -0
- package/dist/modes/interactive/extension-ui-host.d.ts.map +1 -0
- package/dist/modes/interactive/extension-ui-host.js +610 -0
- package/dist/modes/interactive/extension-ui-host.js.map +1 -0
- package/dist/modes/interactive/external-editor.d.ts +18 -0
- package/dist/modes/interactive/external-editor.d.ts.map +1 -0
- package/dist/modes/interactive/external-editor.js +107 -0
- package/dist/modes/interactive/external-editor.js.map +1 -0
- package/dist/modes/interactive/history-reload-math.d.ts +24 -0
- package/dist/modes/interactive/history-reload-math.d.ts.map +1 -0
- package/dist/modes/interactive/history-reload-math.js +129 -0
- package/dist/modes/interactive/history-reload-math.js.map +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts +22 -238
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +714 -5910
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/key-handlers.d.ts +46 -0
- package/dist/modes/interactive/key-handlers.d.ts.map +1 -0
- package/dist/modes/interactive/key-handlers.js +80 -0
- package/dist/modes/interactive/key-handlers.js.map +1 -0
- package/dist/modes/interactive/local-model-commands.d.ts +68 -0
- package/dist/modes/interactive/local-model-commands.d.ts.map +1 -0
- package/dist/modes/interactive/local-model-commands.js +288 -0
- package/dist/modes/interactive/local-model-commands.js.map +1 -0
- package/dist/modes/interactive/profile-menu-controller.d.ts +77 -0
- package/dist/modes/interactive/profile-menu-controller.d.ts.map +1 -0
- package/dist/modes/interactive/profile-menu-controller.js +917 -0
- package/dist/modes/interactive/profile-menu-controller.js.map +1 -0
- package/dist/modes/interactive/report-commands.d.ts +46 -0
- package/dist/modes/interactive/report-commands.d.ts.map +1 -0
- package/dist/modes/interactive/report-commands.js +255 -0
- package/dist/modes/interactive/report-commands.js.map +1 -0
- package/dist/modes/interactive/resource-display.d.ts +73 -0
- package/dist/modes/interactive/resource-display.d.ts.map +1 -0
- package/dist/modes/interactive/resource-display.js +278 -0
- package/dist/modes/interactive/resource-display.js.map +1 -0
- package/dist/modes/interactive/resource-shell-commands.d.ts +64 -0
- package/dist/modes/interactive/resource-shell-commands.d.ts.map +1 -0
- package/dist/modes/interactive/resource-shell-commands.js +202 -0
- package/dist/modes/interactive/resource-shell-commands.js.map +1 -0
- package/dist/modes/interactive/session-flow-commands.d.ts +139 -0
- package/dist/modes/interactive/session-flow-commands.d.ts.map +1 -0
- package/dist/modes/interactive/session-flow-commands.js +458 -0
- package/dist/modes/interactive/session-flow-commands.js.map +1 -0
- package/dist/modes/interactive/session-io-commands.d.ts +73 -0
- package/dist/modes/interactive/session-io-commands.d.ts.map +1 -0
- package/dist/modes/interactive/session-io-commands.js +202 -0
- package/dist/modes/interactive/session-io-commands.js.map +1 -0
- package/dist/modes/interactive/settings-selector-flow.d.ts +42 -0
- package/dist/modes/interactive/settings-selector-flow.d.ts.map +1 -0
- package/dist/modes/interactive/settings-selector-flow.js +287 -0
- package/dist/modes/interactive/settings-selector-flow.js.map +1 -0
- package/dist/modes/interactive/signal-lifecycle.d.ts +55 -0
- package/dist/modes/interactive/signal-lifecycle.d.ts.map +1 -0
- package/dist/modes/interactive/signal-lifecycle.js +177 -0
- package/dist/modes/interactive/signal-lifecycle.js.map +1 -0
- package/dist/modes/interactive/startup-checks.d.ts +38 -0
- package/dist/modes/interactive/startup-checks.d.ts.map +1 -0
- package/dist/modes/interactive/startup-checks.js +189 -0
- package/dist/modes/interactive/startup-checks.js.map +1 -0
- package/dist/modes/rpc/rpc-client.d.ts +1 -1
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +1 -1
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/utils/paths.d.ts +2 -14
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js +5 -30
- package/dist/utils/paths.js.map +1 -1
- package/dist/utils/process-memory.d.ts +8 -0
- package/dist/utils/process-memory.d.ts.map +1 -0
- package/dist/utils/process-memory.js +11 -0
- package/dist/utils/process-memory.js.map +1 -0
- package/dist/utils/shell.d.ts +0 -9
- package/dist/utils/shell.d.ts.map +1 -1
- package/dist/utils/shell.js +0 -37
- package/dist/utils/shell.js.map +1 -1
- 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/examples/sdk/11-sessions.ts +8 -8
- package/examples/sdk/13-session-runtime.ts +1 -1
- package/npm-shrinkwrap.json +12 -12
- package/package.json +4 -4
- package/dist/core/compaction/branch-summarization.d.ts +0 -88
- package/dist/core/compaction/branch-summarization.d.ts.map +0 -1
- package/dist/core/compaction/branch-summarization.js +0 -243
- package/dist/core/compaction/branch-summarization.js.map +0 -1
- package/dist/core/compaction/compaction.d.ts +0 -143
- package/dist/core/compaction/compaction.d.ts.map +0 -1
- package/dist/core/compaction/compaction.js +0 -659
- package/dist/core/compaction/compaction.js.map +0 -1
- package/dist/core/compaction/index.d.ts +0 -7
- package/dist/core/compaction/index.d.ts.map +0 -1
- package/dist/core/compaction/index.js +0 -7
- package/dist/core/compaction/index.js.map +0 -1
- package/dist/core/compaction/utils.d.ts +0 -38
- package/dist/core/compaction/utils.d.ts.map +0 -1
- package/dist/core/compaction/utils.js +0 -153
- package/dist/core/compaction/utils.js.map +0 -1
- package/dist/core/message-retention.d.ts +0 -26
- package/dist/core/message-retention.d.ts.map +0 -1
- package/dist/core/message-retention.js +0 -95
- package/dist/core/message-retention.js.map +0 -1
- package/dist/core/messages.d.ts +0 -77
- package/dist/core/messages.d.ts.map +0 -1
- package/dist/core/messages.js +0 -123
- package/dist/core/messages.js.map +0 -1
- package/dist/core/session-manager.d.ts +0 -337
- package/dist/core/session-manager.d.ts.map +0 -1
- package/dist/core/session-manager.js +0 -1328
- package/dist/core/session-manager.js.map +0 -1
- package/dist/core/tools/truncate.d.ts +0 -70
- package/dist/core/tools/truncate.d.ts.map +0 -1
- package/dist/core/tools/truncate.js +0 -215
- package/dist/core/tools/truncate.js.map +0 -1
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resource-install and shell/compaction command bodies extracted from
|
|
3
|
+
* interactive-mode.
|
|
4
|
+
*
|
|
5
|
+
* `/install-resources` copies a trusted external resource tree into the agent
|
|
6
|
+
* dir; `/curate` proposes/applies skill-curation actions; `!`/`!!` bash runs a
|
|
7
|
+
* shell command (rendering a BashExecutionComponent, deferred while streaming);
|
|
8
|
+
* `/compact` triggers manual compaction. Each takes a narrow host seam;
|
|
9
|
+
* `copyResourcesRecursively` stays host-side (referenced directly by the
|
|
10
|
+
* install-resources test), so interactive-mode keeps thin delegating wrappers.
|
|
11
|
+
*/
|
|
12
|
+
import * as fs from "node:fs";
|
|
13
|
+
import * as path from "node:path";
|
|
14
|
+
import { getAgentDir } from "../../config.js";
|
|
15
|
+
import { BashExecutionComponent } from "./components/bash-execution.js";
|
|
16
|
+
import { SelectSubmenu } from "./components/settings-selector.js";
|
|
17
|
+
export async function handleInstallResourcesCommand(host, argsString) {
|
|
18
|
+
try {
|
|
19
|
+
const tokens = argsString.split(/\s+/).filter(Boolean);
|
|
20
|
+
let force = false;
|
|
21
|
+
let dir = "";
|
|
22
|
+
for (const t of tokens) {
|
|
23
|
+
if (t === "--force") {
|
|
24
|
+
force = true;
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
dir = t;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
if (!dir) {
|
|
31
|
+
host.showError("Usage: /install-resources <dir> [--force]");
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const canonical = host.settingsManager.canonicalizePath(dir);
|
|
35
|
+
if (!canonical || !fs.existsSync(canonical)) {
|
|
36
|
+
host.showError(`Source directory does not exist: ${dir}`);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const trustedRoots = host.settingsManager.getTrustedResourceRoots();
|
|
40
|
+
const trusted = trustedRoots.includes(canonical);
|
|
41
|
+
if (!trusted) {
|
|
42
|
+
const trust = await new Promise((resolve) => {
|
|
43
|
+
host.showSelector((done) => {
|
|
44
|
+
const submenu = new SelectSubmenu("Trust external source for installation?", `The directory "${canonical}" contains extensions/resources to install. Extensions can execute arbitrary code on your machine. Do you trust it?`, [
|
|
45
|
+
{
|
|
46
|
+
value: "yes",
|
|
47
|
+
label: "Yes",
|
|
48
|
+
description: "Trust this directory and proceed with installation.",
|
|
49
|
+
},
|
|
50
|
+
{ value: "no", label: "No", description: "Do not trust this directory. Abort." },
|
|
51
|
+
], "no", (value) => {
|
|
52
|
+
done();
|
|
53
|
+
resolve(value === "yes");
|
|
54
|
+
}, () => {
|
|
55
|
+
done();
|
|
56
|
+
resolve(false);
|
|
57
|
+
});
|
|
58
|
+
return { component: submenu, focus: submenu.getSelectList() };
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
if (!trust) {
|
|
62
|
+
host.showStatus("Installation aborted. Source directory was not trusted.");
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
host.settingsManager.addTrustedResourceRoot(canonical, "global");
|
|
66
|
+
}
|
|
67
|
+
const subdirs = ["skills", "extensions", "prompts", "themes", "profiles", "agents"];
|
|
68
|
+
const stats = { installed: [], skipped: [] };
|
|
69
|
+
const userAgentDir = getAgentDir();
|
|
70
|
+
for (const sub of subdirs) {
|
|
71
|
+
const srcSub = path.join(canonical, sub);
|
|
72
|
+
const destSub = path.join(userAgentDir, sub);
|
|
73
|
+
if (fs.existsSync(srcSub)) {
|
|
74
|
+
host.copyResourcesRecursively(srcSub, destSub, force, stats);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
const installedCount = stats.installed.length;
|
|
78
|
+
const skippedCount = stats.skipped.length;
|
|
79
|
+
host.showStatus(`Installation complete: ${installedCount} resources installed, ${skippedCount} skipped.`);
|
|
80
|
+
await host.handleReloadCommand();
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
host.showError(error instanceof Error ? error.message : String(error));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* `/curate` — skill curator (#32). With no args, lists reflection-promoted skills proposed for
|
|
88
|
+
* archival (stale/unused) and pairs proposed for consolidation (overlapping). PROPOSE-ONLY: the user
|
|
89
|
+
* applies actions explicitly via `/curate archive <name>` / `/curate restore <name>`. Never touches
|
|
90
|
+
* hand-authored skills; archival is restorable.
|
|
91
|
+
*/
|
|
92
|
+
export function handleCurateCommand(host, args) {
|
|
93
|
+
const [sub, name] = args.split(/\s+/, 2);
|
|
94
|
+
if (sub === "archive" && name) {
|
|
95
|
+
host.showStatus(host.session.archivePromotedSkill(name)
|
|
96
|
+
? `Archived promoted skill '${name}'`
|
|
97
|
+
: `Could not archive '${name}' (not a promoted skill?)`);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
if (sub === "restore" && name) {
|
|
101
|
+
host.showStatus(host.session.restorePromotedSkill(name) ? `Restored skill '${name}'` : `Could not restore '${name}'`);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
const proposals = host.session.proposeSkillCuration();
|
|
105
|
+
if (proposals.archive.length === 0 && proposals.consolidate.length === 0) {
|
|
106
|
+
host.showStatus("Curator: no stale or overlapping promoted skills. Nothing to propose.");
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
const lines = ["Skill curator proposals (nothing applied automatically):"];
|
|
110
|
+
for (const a of proposals.archive) {
|
|
111
|
+
lines.push(` • archive '${a.name}' — ${a.reason} → /curate archive ${a.name}`);
|
|
112
|
+
}
|
|
113
|
+
for (const c of proposals.consolidate) {
|
|
114
|
+
lines.push(` • consider merging '${c.names[0]}' + '${c.names[1]}' (overlap ${(c.overlap * 100) | 0}%)`);
|
|
115
|
+
}
|
|
116
|
+
host.showStatus(lines.join("\n"));
|
|
117
|
+
}
|
|
118
|
+
export async function handleBashCommand(host, command, excludeFromContext = false) {
|
|
119
|
+
const extensionRunner = host.session.extensionRunner;
|
|
120
|
+
// Emit user_bash event to let extensions intercept
|
|
121
|
+
const eventResult = await extensionRunner.emitUserBash({
|
|
122
|
+
type: "user_bash",
|
|
123
|
+
command,
|
|
124
|
+
excludeFromContext,
|
|
125
|
+
cwd: host.sessionManager.getCwd(),
|
|
126
|
+
});
|
|
127
|
+
// If extension returned a full result, use it directly
|
|
128
|
+
if (eventResult?.result) {
|
|
129
|
+
const result = eventResult.result;
|
|
130
|
+
// Create UI component for display
|
|
131
|
+
host.bashComponent = new BashExecutionComponent(command, host.ui, excludeFromContext);
|
|
132
|
+
if (host.session.isStreaming) {
|
|
133
|
+
host.pendingMessagesContainer.addChild(host.bashComponent);
|
|
134
|
+
host.pendingBashComponents.push(host.bashComponent);
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
host.chatContainer.addChild(host.bashComponent);
|
|
138
|
+
}
|
|
139
|
+
// Show output and complete
|
|
140
|
+
if (result.output) {
|
|
141
|
+
host.bashComponent.appendOutput(result.output);
|
|
142
|
+
}
|
|
143
|
+
host.bashComponent.setComplete(result.exitCode, result.cancelled, result.truncated ? { truncated: true, content: result.output } : undefined, result.fullOutputPath);
|
|
144
|
+
// Record the result in session
|
|
145
|
+
host.session.recordBashResult(command, result, { excludeFromContext });
|
|
146
|
+
host.bashComponent = undefined;
|
|
147
|
+
host.ui.requestRender();
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
// Normal execution path (possibly with custom operations)
|
|
151
|
+
const isDeferred = host.session.isStreaming;
|
|
152
|
+
host.bashComponent = new BashExecutionComponent(command, host.ui, excludeFromContext);
|
|
153
|
+
if (isDeferred) {
|
|
154
|
+
// Show in pending area when agent is streaming
|
|
155
|
+
host.pendingMessagesContainer.addChild(host.bashComponent);
|
|
156
|
+
host.pendingBashComponents.push(host.bashComponent);
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
// Show in chat immediately when agent is idle
|
|
160
|
+
host.chatContainer.addChild(host.bashComponent);
|
|
161
|
+
}
|
|
162
|
+
host.ui.requestRender();
|
|
163
|
+
try {
|
|
164
|
+
const result = await host.session.executeBash(command, (chunk) => {
|
|
165
|
+
if (host.bashComponent) {
|
|
166
|
+
host.bashComponent.appendOutput(chunk);
|
|
167
|
+
host.ui.requestRender();
|
|
168
|
+
}
|
|
169
|
+
}, { excludeFromContext, operations: eventResult?.operations });
|
|
170
|
+
if (host.bashComponent) {
|
|
171
|
+
host.bashComponent.setComplete(result.exitCode, result.cancelled, result.truncated ? { truncated: true, content: result.output } : undefined, result.fullOutputPath);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
catch (error) {
|
|
175
|
+
if (host.bashComponent) {
|
|
176
|
+
host.bashComponent.setComplete(undefined, false);
|
|
177
|
+
}
|
|
178
|
+
host.showError(`Bash command failed: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
179
|
+
}
|
|
180
|
+
host.bashComponent = undefined;
|
|
181
|
+
host.ui.requestRender();
|
|
182
|
+
}
|
|
183
|
+
export async function handleCompactCommand(host, customInstructions) {
|
|
184
|
+
const entries = host.sessionManager.getEntries();
|
|
185
|
+
const messageCount = entries.filter((e) => e.type === "message").length;
|
|
186
|
+
if (messageCount < 2) {
|
|
187
|
+
host.showWarning("Nothing to compact (no messages yet)");
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
if (host.loadingAnimation) {
|
|
191
|
+
host.loadingAnimation.stop();
|
|
192
|
+
host.loadingAnimation = undefined;
|
|
193
|
+
}
|
|
194
|
+
host.statusContainer.clear();
|
|
195
|
+
try {
|
|
196
|
+
await host.session.compact(customInstructions);
|
|
197
|
+
}
|
|
198
|
+
catch {
|
|
199
|
+
// Ignore, will be emitted as an event
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
//# sourceMappingURL=resource-shell-commands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource-shell-commands.js","sourceRoot":"","sources":["../../../src/modes/interactive/resource-shell-commands.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Resource-install and shell/compaction command bodies extracted from\n * interactive-mode.\n *\n * `/install-resources` copies a trusted external resource tree into the agent\n * dir; `/curate` proposes/applies skill-curation actions; `!`/`!!` bash runs a\n * shell command (rendering a BashExecutionComponent, deferred while streaming);\n * `/compact` triggers manual compaction. Each takes a narrow host seam;\n * `copyResourcesRecursively` stays host-side (referenced directly by the\n * install-resources test), so interactive-mode keeps thin delegating wrappers.\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport type { SessionManager, TruncationResult } from \"@caupulican/pi-agent-core/node\";\nimport type { Component, Container, Loader, TUI } from \"@caupulican/pi-tui\";\nimport { getAgentDir } from \"../../config.ts\";\nimport type { AgentSession } from \"../../core/agent-session.ts\";\nimport type { SettingsManager } from \"../../core/settings-manager.ts\";\nimport { BashExecutionComponent } from \"./components/bash-execution.ts\";\nimport { SelectSubmenu } from \"./components/settings-selector.ts\";\n\nexport interface InstallResourcesHost {\n\treadonly settingsManager: Pick<\n\t\tSettingsManager,\n\t\t\"canonicalizePath\" | \"getTrustedResourceRoots\" | \"addTrustedResourceRoot\"\n\t>;\n\tshowError(message: string): void;\n\tshowStatus(message: string): void;\n\tshowSelector(create: (done: () => void) => { component: Component; focus: Component }): void;\n\thandleReloadCommand(): Promise<void>;\n\tcopyResourcesRecursively(\n\t\tsrc: string,\n\t\tdest: string,\n\t\tforce: boolean,\n\t\tstats: { installed: string[]; skipped: string[] },\n\t): void;\n}\n\nexport interface CurateCommandHost {\n\treadonly session: Pick<AgentSession, \"archivePromotedSkill\" | \"restorePromotedSkill\" | \"proposeSkillCuration\">;\n\tshowStatus(message: string): void;\n}\n\nexport interface BashCommandHost {\n\treadonly session: Pick<AgentSession, \"extensionRunner\" | \"isStreaming\" | \"recordBashResult\" | \"executeBash\">;\n\treadonly sessionManager: Pick<SessionManager, \"getCwd\">;\n\treadonly ui: TUI;\n\treadonly chatContainer: Container;\n\treadonly pendingMessagesContainer: Container;\n\treadonly pendingBashComponents: BashExecutionComponent[];\n\tbashComponent: BashExecutionComponent | undefined;\n\tshowError(message: string): void;\n}\n\nexport interface CompactCommandHost {\n\treadonly sessionManager: Pick<SessionManager, \"getEntries\">;\n\tshowWarning(message: string): void;\n\tloadingAnimation: Loader | undefined;\n\treadonly statusContainer: { clear: () => void };\n\treadonly session: Pick<AgentSession, \"compact\">;\n}\n\nexport async function handleInstallResourcesCommand(host: InstallResourcesHost, argsString: string): Promise<void> {\n\ttry {\n\t\tconst tokens = argsString.split(/\\s+/).filter(Boolean);\n\t\tlet force = false;\n\t\tlet dir = \"\";\n\t\tfor (const t of tokens) {\n\t\t\tif (t === \"--force\") {\n\t\t\t\tforce = true;\n\t\t\t} else {\n\t\t\t\tdir = t;\n\t\t\t}\n\t\t}\n\n\t\tif (!dir) {\n\t\t\thost.showError(\"Usage: /install-resources <dir> [--force]\");\n\t\t\treturn;\n\t\t}\n\n\t\tconst canonical = host.settingsManager.canonicalizePath(dir);\n\t\tif (!canonical || !fs.existsSync(canonical)) {\n\t\t\thost.showError(`Source directory does not exist: ${dir}`);\n\t\t\treturn;\n\t\t}\n\n\t\tconst trustedRoots = host.settingsManager.getTrustedResourceRoots();\n\t\tconst trusted = trustedRoots.includes(canonical);\n\n\t\tif (!trusted) {\n\t\t\tconst trust = await new Promise<boolean>((resolve) => {\n\t\t\t\thost.showSelector((done) => {\n\t\t\t\t\tconst submenu = new SelectSubmenu(\n\t\t\t\t\t\t\"Trust external source for installation?\",\n\t\t\t\t\t\t`The directory \"${canonical}\" contains extensions/resources to install. Extensions can execute arbitrary code on your machine. Do you trust it?`,\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tvalue: \"yes\",\n\t\t\t\t\t\t\t\tlabel: \"Yes\",\n\t\t\t\t\t\t\t\tdescription: \"Trust this directory and proceed with installation.\",\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{ value: \"no\", label: \"No\", description: \"Do not trust this directory. Abort.\" },\n\t\t\t\t\t\t],\n\t\t\t\t\t\t\"no\",\n\t\t\t\t\t\t(value) => {\n\t\t\t\t\t\t\tdone();\n\t\t\t\t\t\t\tresolve(value === \"yes\");\n\t\t\t\t\t\t},\n\t\t\t\t\t\t() => {\n\t\t\t\t\t\t\tdone();\n\t\t\t\t\t\t\tresolve(false);\n\t\t\t\t\t\t},\n\t\t\t\t\t);\n\t\t\t\t\treturn { component: submenu, focus: submenu.getSelectList() };\n\t\t\t\t});\n\t\t\t});\n\n\t\t\tif (!trust) {\n\t\t\t\thost.showStatus(\"Installation aborted. Source directory was not trusted.\");\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\thost.settingsManager.addTrustedResourceRoot(canonical, \"global\");\n\t\t}\n\n\t\tconst subdirs = [\"skills\", \"extensions\", \"prompts\", \"themes\", \"profiles\", \"agents\"];\n\t\tconst stats = { installed: [] as string[], skipped: [] as string[] };\n\t\tconst userAgentDir = getAgentDir();\n\n\t\tfor (const sub of subdirs) {\n\t\t\tconst srcSub = path.join(canonical, sub);\n\t\t\tconst destSub = path.join(userAgentDir, sub);\n\t\t\tif (fs.existsSync(srcSub)) {\n\t\t\t\thost.copyResourcesRecursively(srcSub, destSub, force, stats);\n\t\t\t}\n\t\t}\n\n\t\tconst installedCount = stats.installed.length;\n\t\tconst skippedCount = stats.skipped.length;\n\t\thost.showStatus(`Installation complete: ${installedCount} resources installed, ${skippedCount} skipped.`);\n\n\t\tawait host.handleReloadCommand();\n\t} catch (error) {\n\t\thost.showError(error instanceof Error ? error.message : String(error));\n\t}\n}\n\n/**\n * `/curate` — skill curator (#32). With no args, lists reflection-promoted skills proposed for\n * archival (stale/unused) and pairs proposed for consolidation (overlapping). PROPOSE-ONLY: the user\n * applies actions explicitly via `/curate archive <name>` / `/curate restore <name>`. Never touches\n * hand-authored skills; archival is restorable.\n */\nexport function handleCurateCommand(host: CurateCommandHost, args: string): void {\n\tconst [sub, name] = args.split(/\\s+/, 2);\n\tif (sub === \"archive\" && name) {\n\t\thost.showStatus(\n\t\t\thost.session.archivePromotedSkill(name)\n\t\t\t\t? `Archived promoted skill '${name}'`\n\t\t\t\t: `Could not archive '${name}' (not a promoted skill?)`,\n\t\t);\n\t\treturn;\n\t}\n\tif (sub === \"restore\" && name) {\n\t\thost.showStatus(\n\t\t\thost.session.restorePromotedSkill(name) ? `Restored skill '${name}'` : `Could not restore '${name}'`,\n\t\t);\n\t\treturn;\n\t}\n\tconst proposals = host.session.proposeSkillCuration();\n\tif (proposals.archive.length === 0 && proposals.consolidate.length === 0) {\n\t\thost.showStatus(\"Curator: no stale or overlapping promoted skills. Nothing to propose.\");\n\t\treturn;\n\t}\n\tconst lines: string[] = [\"Skill curator proposals (nothing applied automatically):\"];\n\tfor (const a of proposals.archive) {\n\t\tlines.push(` • archive '${a.name}' — ${a.reason} → /curate archive ${a.name}`);\n\t}\n\tfor (const c of proposals.consolidate) {\n\t\tlines.push(` • consider merging '${c.names[0]}' + '${c.names[1]}' (overlap ${(c.overlap * 100) | 0}%)`);\n\t}\n\thost.showStatus(lines.join(\"\\n\"));\n}\n\nexport async function handleBashCommand(\n\thost: BashCommandHost,\n\tcommand: string,\n\texcludeFromContext = false,\n): Promise<void> {\n\tconst extensionRunner = host.session.extensionRunner;\n\n\t// Emit user_bash event to let extensions intercept\n\tconst eventResult = await extensionRunner.emitUserBash({\n\t\ttype: \"user_bash\",\n\t\tcommand,\n\t\texcludeFromContext,\n\t\tcwd: host.sessionManager.getCwd(),\n\t});\n\n\t// If extension returned a full result, use it directly\n\tif (eventResult?.result) {\n\t\tconst result = eventResult.result;\n\n\t\t// Create UI component for display\n\t\thost.bashComponent = new BashExecutionComponent(command, host.ui, excludeFromContext);\n\t\tif (host.session.isStreaming) {\n\t\t\thost.pendingMessagesContainer.addChild(host.bashComponent);\n\t\t\thost.pendingBashComponents.push(host.bashComponent);\n\t\t} else {\n\t\t\thost.chatContainer.addChild(host.bashComponent);\n\t\t}\n\n\t\t// Show output and complete\n\t\tif (result.output) {\n\t\t\thost.bashComponent.appendOutput(result.output);\n\t\t}\n\t\thost.bashComponent.setComplete(\n\t\t\tresult.exitCode,\n\t\t\tresult.cancelled,\n\t\t\tresult.truncated ? ({ truncated: true, content: result.output } as TruncationResult) : undefined,\n\t\t\tresult.fullOutputPath,\n\t\t);\n\n\t\t// Record the result in session\n\t\thost.session.recordBashResult(command, result, { excludeFromContext });\n\t\thost.bashComponent = undefined;\n\t\thost.ui.requestRender();\n\t\treturn;\n\t}\n\n\t// Normal execution path (possibly with custom operations)\n\tconst isDeferred = host.session.isStreaming;\n\thost.bashComponent = new BashExecutionComponent(command, host.ui, excludeFromContext);\n\n\tif (isDeferred) {\n\t\t// Show in pending area when agent is streaming\n\t\thost.pendingMessagesContainer.addChild(host.bashComponent);\n\t\thost.pendingBashComponents.push(host.bashComponent);\n\t} else {\n\t\t// Show in chat immediately when agent is idle\n\t\thost.chatContainer.addChild(host.bashComponent);\n\t}\n\thost.ui.requestRender();\n\n\ttry {\n\t\tconst result = await host.session.executeBash(\n\t\t\tcommand,\n\t\t\t(chunk) => {\n\t\t\t\tif (host.bashComponent) {\n\t\t\t\t\thost.bashComponent.appendOutput(chunk);\n\t\t\t\t\thost.ui.requestRender();\n\t\t\t\t}\n\t\t\t},\n\t\t\t{ excludeFromContext, operations: eventResult?.operations },\n\t\t);\n\n\t\tif (host.bashComponent) {\n\t\t\thost.bashComponent.setComplete(\n\t\t\t\tresult.exitCode,\n\t\t\t\tresult.cancelled,\n\t\t\t\tresult.truncated ? ({ truncated: true, content: result.output } as TruncationResult) : undefined,\n\t\t\t\tresult.fullOutputPath,\n\t\t\t);\n\t\t}\n\t} catch (error) {\n\t\tif (host.bashComponent) {\n\t\t\thost.bashComponent.setComplete(undefined, false);\n\t\t}\n\t\thost.showError(`Bash command failed: ${error instanceof Error ? error.message : \"Unknown error\"}`);\n\t}\n\n\thost.bashComponent = undefined;\n\thost.ui.requestRender();\n}\n\nexport async function handleCompactCommand(host: CompactCommandHost, customInstructions?: string): Promise<void> {\n\tconst entries = host.sessionManager.getEntries();\n\tconst messageCount = entries.filter((e) => e.type === \"message\").length;\n\n\tif (messageCount < 2) {\n\t\thost.showWarning(\"Nothing to compact (no messages yet)\");\n\t\treturn;\n\t}\n\n\tif (host.loadingAnimation) {\n\t\thost.loadingAnimation.stop();\n\t\thost.loadingAnimation = undefined;\n\t}\n\thost.statusContainer.clear();\n\n\ttry {\n\t\tawait host.session.compact(customInstructions);\n\t} catch {\n\t\t// Ignore, will be emitted as an event\n\t}\n}\n"]}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Session-picker, tree/fork navigation, and model-selector flows extracted from
|
|
3
|
+
* interactive-mode.
|
|
4
|
+
*
|
|
5
|
+
* Each entry opens a selector overlay (via `host.showSelector`) or renders a
|
|
6
|
+
* session-info block, driving `AgentSession`/`AgentSessionRuntime` navigation and
|
|
7
|
+
* the fork/resume/clone/goal-continuation paths. The interdependent selector
|
|
8
|
+
* flows share one narrow `SessionFlowHost` seam; the three prototype-tested leaf
|
|
9
|
+
* commands (`handleCloneCommand`, `handleGoalContinueCommand`,
|
|
10
|
+
* `handleSessionCommand`) take their own minimal host shapes so their behaviour
|
|
11
|
+
* tests keep exercising them through interactive-mode's thin wrappers unchanged.
|
|
12
|
+
*/
|
|
13
|
+
import type { SessionManager } from "@caupulican/pi-agent-core/node";
|
|
14
|
+
import type { Model } from "@caupulican/pi-ai";
|
|
15
|
+
import type { EditorComponent } from "@caupulican/pi-tui";
|
|
16
|
+
import { type Component, type Container, Loader, type TUI } from "@caupulican/pi-tui";
|
|
17
|
+
import type { AgentSession, GoalContinuationLoopOptions, GoalContinuationLoopResult } from "../../core/agent-session.ts";
|
|
18
|
+
import type { AgentSessionRuntime } from "../../core/agent-session-runtime.ts";
|
|
19
|
+
import type { ExtensionCommandContext } from "../../core/extensions/index.ts";
|
|
20
|
+
import type { KeybindingsManager } from "../../core/keybindings.ts";
|
|
21
|
+
import { MissingSessionCwdError } from "../../core/session-cwd.ts";
|
|
22
|
+
import type { SettingsManager } from "../../core/settings-manager.ts";
|
|
23
|
+
import type { CustomEditor } from "./components/custom-editor.ts";
|
|
24
|
+
import type { FooterComponent } from "./components/footer.ts";
|
|
25
|
+
import type { ExtensionUiHost } from "./extension-ui-host.ts";
|
|
26
|
+
/** Shared seam for the interdependent selector/navigation flows. */
|
|
27
|
+
export interface SessionFlowHost {
|
|
28
|
+
readonly session: AgentSession;
|
|
29
|
+
readonly sessionManager: SessionManager;
|
|
30
|
+
readonly settingsManager: SettingsManager;
|
|
31
|
+
readonly runtimeHost: AgentSessionRuntime;
|
|
32
|
+
readonly ui: TUI;
|
|
33
|
+
readonly chatContainer: Container;
|
|
34
|
+
readonly statusContainer: Container;
|
|
35
|
+
readonly editor: EditorComponent;
|
|
36
|
+
readonly defaultEditor: CustomEditor;
|
|
37
|
+
readonly footer: FooterComponent;
|
|
38
|
+
readonly extensionUiHost: ExtensionUiHost;
|
|
39
|
+
readonly keybindings: KeybindingsManager;
|
|
40
|
+
loadingAnimation: Loader | undefined;
|
|
41
|
+
showSelector(create: (done: () => void) => {
|
|
42
|
+
component: Component;
|
|
43
|
+
focus: Component;
|
|
44
|
+
}): void;
|
|
45
|
+
showStatus(message: string): void;
|
|
46
|
+
showError(message: string): void;
|
|
47
|
+
renderCurrentSessionState(): void;
|
|
48
|
+
renderInitialMessages(options?: {
|
|
49
|
+
forceHistoryLoad?: boolean;
|
|
50
|
+
}): Promise<void>;
|
|
51
|
+
flushCompactionQueue(options?: {
|
|
52
|
+
willRetry?: boolean;
|
|
53
|
+
}): Promise<void>;
|
|
54
|
+
handleFatalRuntimeError(prefix: string, error: unknown): Promise<never>;
|
|
55
|
+
promptForMissingSessionCwd(error: MissingSessionCwdError): Promise<string | undefined>;
|
|
56
|
+
updateEditorBorderColor(): void;
|
|
57
|
+
updateAvailableProviderCount(): Promise<void>;
|
|
58
|
+
maybeWarnAboutAnthropicSubscriptionAuth(model?: Model<any>): Promise<void>;
|
|
59
|
+
checkDaxnutsEasterEgg(model: {
|
|
60
|
+
provider: string;
|
|
61
|
+
id: string;
|
|
62
|
+
}): void;
|
|
63
|
+
getModelCandidates(): Promise<Model<any>[]>;
|
|
64
|
+
shutdown(options?: {
|
|
65
|
+
fromSignal?: boolean;
|
|
66
|
+
}): Promise<void>;
|
|
67
|
+
}
|
|
68
|
+
export declare function showModelSelector(host: SessionFlowHost, initialSearchInput?: string): Promise<void>;
|
|
69
|
+
export declare function showModelsSelector(host: SessionFlowHost): Promise<void>;
|
|
70
|
+
export declare function showUserMessageSelector(host: SessionFlowHost, newSessionName?: string): void;
|
|
71
|
+
export declare function showTreeSelector(host: SessionFlowHost, initialSelectedId?: string): void;
|
|
72
|
+
export declare function showTrustSelector(host: SessionFlowHost): void;
|
|
73
|
+
export declare function showSessionSelector(host: SessionFlowHost): void;
|
|
74
|
+
export declare function handleResumeSession(host: SessionFlowHost, sessionPath: string, options?: Parameters<ExtensionCommandContext["switchSession"]>[1]): Promise<{
|
|
75
|
+
cancelled: boolean;
|
|
76
|
+
}>;
|
|
77
|
+
export declare function handleModelCommand(host: SessionFlowHost, searchTerm?: string): Promise<void>;
|
|
78
|
+
export declare function findExactModelMatch(host: SessionFlowHost, searchTerm: string): Promise<Model<any> | undefined>;
|
|
79
|
+
export interface CloneCommandHost {
|
|
80
|
+
readonly sessionManager: {
|
|
81
|
+
getLeafId: () => string | null;
|
|
82
|
+
};
|
|
83
|
+
readonly runtimeHost: {
|
|
84
|
+
fork: (entryId: string, options?: {
|
|
85
|
+
position?: "before" | "at";
|
|
86
|
+
}) => Promise<{
|
|
87
|
+
cancelled: boolean;
|
|
88
|
+
}>;
|
|
89
|
+
};
|
|
90
|
+
renderCurrentSessionState(): void;
|
|
91
|
+
readonly editor: {
|
|
92
|
+
setText: (text: string) => void;
|
|
93
|
+
};
|
|
94
|
+
readonly session: {
|
|
95
|
+
setSessionName: (name: string) => void;
|
|
96
|
+
};
|
|
97
|
+
showStatus(message: string): void;
|
|
98
|
+
showError(message: string): void;
|
|
99
|
+
readonly ui: {
|
|
100
|
+
requestRender: () => void;
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
export declare function handleCloneCommand(host: CloneCommandHost, newSessionName?: string): Promise<void>;
|
|
104
|
+
export type ParsedGoalContinueCommand = {
|
|
105
|
+
ok: true;
|
|
106
|
+
maxTurns: number;
|
|
107
|
+
maxStallTurns: number;
|
|
108
|
+
maxWallClockMinutes: number;
|
|
109
|
+
} | {
|
|
110
|
+
ok: false;
|
|
111
|
+
error: string;
|
|
112
|
+
};
|
|
113
|
+
export interface GoalContinueCommandHost {
|
|
114
|
+
readonly session: {
|
|
115
|
+
continueGoalLoop: (options: GoalContinuationLoopOptions) => Promise<GoalContinuationLoopResult>;
|
|
116
|
+
};
|
|
117
|
+
parseGoalContinueCommand(text: string): ParsedGoalContinueCommand;
|
|
118
|
+
showStatus(message: string): void;
|
|
119
|
+
showError(message: string): void;
|
|
120
|
+
refreshAutonomyFooterStatus(): void;
|
|
121
|
+
}
|
|
122
|
+
export declare function handleGoalContinueCommand(host: GoalContinueCommandHost, text: string): Promise<void>;
|
|
123
|
+
export interface SessionInfoCommandHost {
|
|
124
|
+
readonly session: {
|
|
125
|
+
getSessionStats: () => ReturnType<AgentSession["getSessionStats"]>;
|
|
126
|
+
getDailyUsageTotals: () => ReturnType<AgentSession["getDailyUsageTotals"]>;
|
|
127
|
+
getDailyUsageBreakdown: (formatLabel: (label: string) => string) => string;
|
|
128
|
+
getModelRouterStatus: (formatLabel: (label: string) => string) => string;
|
|
129
|
+
};
|
|
130
|
+
readonly sessionManager: {
|
|
131
|
+
getSessionName: () => string | undefined;
|
|
132
|
+
};
|
|
133
|
+
readonly chatContainer: Container;
|
|
134
|
+
readonly ui: {
|
|
135
|
+
requestRender: () => void;
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
export declare function handleSessionCommand(host: SessionInfoCommandHost): void;
|
|
139
|
+
//# sourceMappingURL=session-flow-commands.d.ts.map
|
|
@@ -0,0 +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 { 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 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"]}
|