@caupulican/pi-adaptative 0.81.40 → 0.81.42
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 +41 -0
- package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.d.ts.map +1 -1
- package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.js +1 -0
- package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.js.map +1 -1
- package/dist/bundled-resources/extensions/tmux-agent-manager/dispatch-grant.ts +1 -0
- package/dist/bundled-resources/runtimes/pi-shell-engine/commands/text.py +5 -1
- package/dist/bundled-resources/runtimes/pi-shell-engine/context.py +3 -3
- package/dist/bundled-resources/runtimes/pi-shell-engine/errors.py +8 -0
- package/dist/bundled-resources/runtimes/pi-shell-engine/exec.py +26 -3
- package/dist/bundled-resources/runtimes/pi-shell-engine/expand.py +3 -0
- package/dist/bundled-resources/runtimes/pi-shell-engine/main.py +4 -1
- package/dist/bundled-resources/runtimes/pi-shell-engine/state.py +2 -1
- package/dist/bundled-resources/runtimes/pi-shell-engine/tokens.py +2 -0
- package/dist/cli/args.d.ts +2 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +22 -1
- package/dist/cli/args.js.map +1 -1
- package/dist/core/agent-paths.d.ts +38 -0
- package/dist/core/agent-paths.d.ts.map +1 -1
- package/dist/core/agent-paths.js +77 -0
- package/dist/core/agent-paths.js.map +1 -1
- package/dist/core/agent-session-contracts.d.ts +311 -0
- package/dist/core/agent-session-contracts.d.ts.map +1 -0
- package/dist/core/agent-session-contracts.js +26 -0
- package/dist/core/agent-session-contracts.js.map +1 -0
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +3 -0
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session.d.ts +26 -405
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +90 -316
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +3 -1
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/autonomy/contracts.d.ts +2 -0
- package/dist/core/autonomy/contracts.d.ts.map +1 -1
- package/dist/core/autonomy/contracts.js.map +1 -1
- package/dist/core/autonomy/envelope-enforcement.d.ts.map +1 -1
- package/dist/core/autonomy/envelope-enforcement.js +4 -9
- package/dist/core/autonomy/envelope-enforcement.js.map +1 -1
- package/dist/core/autonomy/lane-tool-surface.d.ts +3 -1
- package/dist/core/autonomy/lane-tool-surface.d.ts.map +1 -1
- package/dist/core/autonomy/lane-tool-surface.js +19 -5
- package/dist/core/autonomy/lane-tool-surface.js.map +1 -1
- package/dist/core/autonomy/path-scope.d.ts +14 -0
- package/dist/core/autonomy/path-scope.d.ts.map +1 -1
- package/dist/core/autonomy/path-scope.js +37 -6
- package/dist/core/autonomy/path-scope.js.map +1 -1
- package/dist/core/background-lane-controller.d.ts +30 -2
- package/dist/core/background-lane-controller.d.ts.map +1 -1
- package/dist/core/background-lane-controller.js +33 -1
- package/dist/core/background-lane-controller.js.map +1 -1
- package/dist/core/bedrock-sso-login.d.ts +16 -0
- package/dist/core/bedrock-sso-login.d.ts.map +1 -0
- package/dist/core/bedrock-sso-login.js +98 -0
- package/dist/core/bedrock-sso-login.js.map +1 -0
- package/dist/core/compaction-controller.d.ts.map +1 -1
- package/dist/core/compaction-controller.js +1 -1
- package/dist/core/compaction-controller.js.map +1 -1
- package/dist/core/compaction-support.d.ts +3 -8
- package/dist/core/compaction-support.d.ts.map +1 -1
- package/dist/core/compaction-support.js +3 -3
- package/dist/core/compaction-support.js.map +1 -1
- package/dist/core/context-pipeline.d.ts +1 -1
- package/dist/core/context-pipeline.d.ts.map +1 -1
- package/dist/core/context-pipeline.js +7 -33
- package/dist/core/context-pipeline.js.map +1 -1
- package/dist/core/cost/cost-summary.d.ts.map +1 -1
- package/dist/core/cost/cost-summary.js +5 -3
- package/dist/core/cost/cost-summary.js.map +1 -1
- package/dist/core/cost/daily-usage.d.ts.map +1 -1
- package/dist/core/cost/daily-usage.js +4 -5
- package/dist/core/cost/daily-usage.js.map +1 -1
- package/dist/core/default-tool-surface.d.ts.map +1 -1
- package/dist/core/default-tool-surface.js +1 -0
- package/dist/core/default-tool-surface.js.map +1 -1
- package/dist/core/delegation/managed-lane-controller.d.ts +11 -1
- package/dist/core/delegation/managed-lane-controller.d.ts.map +1 -1
- package/dist/core/delegation/managed-lane-controller.js +84 -41
- package/dist/core/delegation/managed-lane-controller.js.map +1 -1
- package/dist/core/delegation/session-worker-claim.d.ts.map +1 -1
- package/dist/core/delegation/session-worker-claim.js +4 -3
- package/dist/core/delegation/session-worker-claim.js.map +1 -1
- package/dist/core/delegation/worker-action-journal.d.ts +73 -0
- package/dist/core/delegation/worker-action-journal.d.ts.map +1 -0
- package/dist/core/delegation/worker-action-journal.js +297 -0
- package/dist/core/delegation/worker-action-journal.js.map +1 -0
- package/dist/core/delegation/worker-actions.d.ts +36 -1
- package/dist/core/delegation/worker-actions.d.ts.map +1 -1
- package/dist/core/delegation/worker-actions.js +171 -46
- package/dist/core/delegation/worker-actions.js.map +1 -1
- package/dist/core/delegation/worker-agent-control-coordinator.d.ts +75 -0
- package/dist/core/delegation/worker-agent-control-coordinator.d.ts.map +1 -0
- package/dist/core/delegation/worker-agent-control-coordinator.js +218 -0
- package/dist/core/delegation/worker-agent-control-coordinator.js.map +1 -0
- package/dist/core/delegation/worker-agent-control.d.ts +66 -0
- package/dist/core/delegation/worker-agent-control.d.ts.map +1 -0
- package/dist/core/delegation/worker-agent-control.js +163 -0
- package/dist/core/delegation/worker-agent-control.js.map +1 -0
- package/dist/core/delegation/worker-attempt-executor.d.ts +80 -0
- package/dist/core/delegation/worker-attempt-executor.d.ts.map +1 -0
- package/dist/core/delegation/worker-attempt-executor.js +343 -0
- package/dist/core/delegation/worker-attempt-executor.js.map +1 -0
- package/dist/core/delegation/worker-claim.d.ts +30 -0
- package/dist/core/delegation/worker-claim.d.ts.map +1 -1
- package/dist/core/delegation/worker-claim.js +205 -53
- package/dist/core/delegation/worker-claim.js.map +1 -1
- package/dist/core/delegation/worker-conversation-store.d.ts +116 -0
- package/dist/core/delegation/worker-conversation-store.d.ts.map +1 -0
- package/dist/core/delegation/worker-conversation-store.js +442 -0
- package/dist/core/delegation/worker-conversation-store.js.map +1 -0
- package/dist/core/delegation/worker-delegation-controller.d.ts +21 -5
- package/dist/core/delegation/worker-delegation-controller.d.ts.map +1 -1
- package/dist/core/delegation/worker-delegation-controller.js +386 -251
- package/dist/core/delegation/worker-delegation-controller.js.map +1 -1
- package/dist/core/delegation/worker-delegation-request.d.ts +14 -0
- package/dist/core/delegation/worker-delegation-request.d.ts.map +1 -1
- package/dist/core/delegation/worker-delegation-request.js.map +1 -1
- package/dist/core/delegation/worker-dispatch-scheduler.d.ts +4 -2
- package/dist/core/delegation/worker-dispatch-scheduler.d.ts.map +1 -1
- package/dist/core/delegation/worker-dispatch-scheduler.js +16 -6
- package/dist/core/delegation/worker-dispatch-scheduler.js.map +1 -1
- package/dist/core/delegation/worker-execution-policy.d.ts +2 -1
- package/dist/core/delegation/worker-execution-policy.d.ts.map +1 -1
- package/dist/core/delegation/worker-execution-policy.js +5 -7
- package/dist/core/delegation/worker-execution-policy.js.map +1 -1
- package/dist/core/delegation/worker-lifecycle.d.ts +44 -1
- package/dist/core/delegation/worker-lifecycle.d.ts.map +1 -1
- package/dist/core/delegation/worker-lifecycle.js +120 -0
- package/dist/core/delegation/worker-lifecycle.js.map +1 -1
- package/dist/core/delegation/worker-process-owner.d.ts +18 -0
- package/dist/core/delegation/worker-process-owner.d.ts.map +1 -0
- package/dist/core/delegation/worker-process-owner.js +54 -0
- package/dist/core/delegation/worker-process-owner.js.map +1 -0
- package/dist/core/delegation/worker-profile-resolver.d.ts +5 -1
- package/dist/core/delegation/worker-profile-resolver.d.ts.map +1 -1
- package/dist/core/delegation/worker-profile-resolver.js +8 -0
- package/dist/core/delegation/worker-profile-resolver.js.map +1 -1
- package/dist/core/delegation/worker-recovery-coordinator.d.ts +54 -0
- package/dist/core/delegation/worker-recovery-coordinator.d.ts.map +1 -0
- package/dist/core/delegation/worker-recovery-coordinator.js +181 -0
- package/dist/core/delegation/worker-recovery-coordinator.js.map +1 -0
- package/dist/core/delegation/worker-resource-catalog.d.ts +32 -0
- package/dist/core/delegation/worker-resource-catalog.d.ts.map +1 -0
- package/dist/core/delegation/worker-resource-catalog.js +116 -0
- package/dist/core/delegation/worker-resource-catalog.js.map +1 -0
- package/dist/core/delegation/worker-resource-materializer.d.ts +47 -0
- package/dist/core/delegation/worker-resource-materializer.d.ts.map +1 -0
- package/dist/core/delegation/worker-resource-materializer.js +137 -0
- package/dist/core/delegation/worker-resource-materializer.js.map +1 -0
- package/dist/core/delegation/worker-runner.d.ts +3 -1
- package/dist/core/delegation/worker-runner.d.ts.map +1 -1
- package/dist/core/delegation/worker-runner.js +189 -54
- package/dist/core/delegation/worker-runner.js.map +1 -1
- package/dist/core/delegation/worker-terminal-finalizer.d.ts +23 -0
- package/dist/core/delegation/worker-terminal-finalizer.d.ts.map +1 -0
- package/dist/core/delegation/worker-terminal-finalizer.js +12 -0
- package/dist/core/delegation/worker-terminal-finalizer.js.map +1 -0
- package/dist/core/delegation/worker-write-reservation-coordinator.d.ts +38 -0
- package/dist/core/delegation/worker-write-reservation-coordinator.d.ts.map +1 -0
- package/dist/core/delegation/worker-write-reservation-coordinator.js +107 -0
- package/dist/core/delegation/worker-write-reservation-coordinator.js.map +1 -0
- package/dist/core/delegation/worker-write-reservation.d.ts +90 -0
- package/dist/core/delegation/worker-write-reservation.d.ts.map +1 -0
- package/dist/core/delegation/worker-write-reservation.js +348 -0
- package/dist/core/delegation/worker-write-reservation.js.map +1 -0
- package/dist/core/extension-import-authority.d.ts +6 -0
- package/dist/core/extension-import-authority.d.ts.map +1 -0
- package/dist/core/extension-import-authority.js +10 -0
- package/dist/core/extension-import-authority.js.map +1 -0
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +2 -3
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +3 -0
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +14 -5
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/stale-context.d.ts +2 -0
- package/dist/core/extensions/stale-context.d.ts.map +1 -0
- package/dist/core/extensions/stale-context.js +2 -0
- package/dist/core/extensions/stale-context.js.map +1 -0
- package/dist/core/extensions/types.d.ts +8 -0
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/foreground-recovery-controller.d.ts +1 -0
- package/dist/core/foreground-recovery-controller.d.ts.map +1 -1
- package/dist/core/foreground-recovery-controller.js +13 -13
- package/dist/core/foreground-recovery-controller.js.map +1 -1
- package/dist/core/goal-loop-controller.d.ts +14 -9
- package/dist/core/goal-loop-controller.d.ts.map +1 -1
- package/dist/core/goal-loop-controller.js +47 -75
- package/dist/core/goal-loop-controller.js.map +1 -1
- package/dist/core/goals/compact-goal-context.d.ts +11 -0
- package/dist/core/goals/compact-goal-context.d.ts.map +1 -0
- package/dist/core/goals/compact-goal-context.js +59 -0
- package/dist/core/goals/compact-goal-context.js.map +1 -0
- package/dist/core/goals/goal-acceptance.d.ts.map +1 -1
- package/dist/core/goals/goal-acceptance.js +2 -0
- package/dist/core/goals/goal-acceptance.js.map +1 -1
- package/dist/core/goals/goal-auto-continue-controller.d.ts +2 -1
- package/dist/core/goals/goal-auto-continue-controller.d.ts.map +1 -1
- package/dist/core/goals/goal-auto-continue-controller.js +5 -8
- package/dist/core/goals/goal-auto-continue-controller.js.map +1 -1
- package/dist/core/goals/goal-continuation-controller.d.ts +2 -2
- package/dist/core/goals/goal-continuation-controller.d.ts.map +1 -1
- package/dist/core/goals/goal-continuation-controller.js +42 -11
- package/dist/core/goals/goal-continuation-controller.js.map +1 -1
- package/dist/core/goals/goal-continuation-defaults.d.ts +4 -29
- package/dist/core/goals/goal-continuation-defaults.d.ts.map +1 -1
- package/dist/core/goals/goal-continuation-defaults.js +4 -32
- package/dist/core/goals/goal-continuation-defaults.js.map +1 -1
- package/dist/core/goals/goal-continuation-prompt.d.ts +8 -18
- package/dist/core/goals/goal-continuation-prompt.d.ts.map +1 -1
- package/dist/core/goals/goal-continuation-prompt.js +9 -179
- package/dist/core/goals/goal-continuation-prompt.js.map +1 -1
- package/dist/core/goals/goal-lifecycle.d.ts +35 -12
- package/dist/core/goals/goal-lifecycle.d.ts.map +1 -1
- package/dist/core/goals/goal-lifecycle.js +98 -13
- package/dist/core/goals/goal-lifecycle.js.map +1 -1
- package/dist/core/goals/goal-record.d.ts +17 -0
- package/dist/core/goals/goal-record.d.ts.map +1 -0
- package/dist/core/goals/goal-record.js +31 -0
- package/dist/core/goals/goal-record.js.map +1 -0
- package/dist/core/goals/goal-session-controller.d.ts +42 -0
- package/dist/core/goals/goal-session-controller.d.ts.map +1 -0
- package/dist/core/goals/goal-session-controller.js +128 -0
- package/dist/core/goals/goal-session-controller.js.map +1 -0
- package/dist/core/goals/goal-state.d.ts +45 -25
- package/dist/core/goals/goal-state.d.ts.map +1 -1
- package/dist/core/goals/goal-state.js +85 -15
- package/dist/core/goals/goal-state.js.map +1 -1
- package/dist/core/goals/goal-tool-core.d.ts +1 -4
- package/dist/core/goals/goal-tool-core.d.ts.map +1 -1
- package/dist/core/goals/goal-tool-core.js +49 -34
- package/dist/core/goals/goal-tool-core.js.map +1 -1
- package/dist/core/goals/session-goal-state.d.ts +18 -8
- package/dist/core/goals/session-goal-state.d.ts.map +1 -1
- package/dist/core/goals/session-goal-state.js +134 -11
- package/dist/core/goals/session-goal-state.js.map +1 -1
- package/dist/core/human-input-controller.d.ts +47 -0
- package/dist/core/human-input-controller.d.ts.map +1 -0
- package/dist/core/human-input-controller.js +181 -0
- package/dist/core/human-input-controller.js.map +1 -0
- package/dist/core/local-runtime-controller.d.ts +1 -1
- package/dist/core/local-runtime-controller.d.ts.map +1 -1
- package/dist/core/local-runtime-controller.js.map +1 -1
- package/dist/core/model-capability.d.ts +0 -19
- package/dist/core/model-capability.d.ts.map +1 -1
- package/dist/core/model-capability.js +0 -19
- package/dist/core/model-capability.js.map +1 -1
- package/dist/core/model-registry.d.ts +6 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +13 -5
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts +16 -1
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +32 -16
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/model-router-controller.d.ts +1 -1
- package/dist/core/model-router-controller.d.ts.map +1 -1
- package/dist/core/model-router-controller.js.map +1 -1
- package/dist/core/model-selection-controller.d.ts +1 -1
- package/dist/core/model-selection-controller.d.ts.map +1 -1
- package/dist/core/model-selection-controller.js.map +1 -1
- package/dist/core/models/model-endpoint.d.ts +3 -0
- package/dist/core/models/model-endpoint.d.ts.map +1 -0
- package/dist/core/models/model-endpoint.js +11 -0
- package/dist/core/models/model-endpoint.js.map +1 -0
- package/dist/core/orchestration/agent-resume.d.ts +2 -0
- package/dist/core/orchestration/agent-resume.d.ts.map +1 -1
- package/dist/core/orchestration/agent-resume.js +7 -0
- package/dist/core/orchestration/agent-resume.js.map +1 -1
- package/dist/core/orchestration/attempt-usage.d.ts +28 -0
- package/dist/core/orchestration/attempt-usage.d.ts.map +1 -0
- package/dist/core/orchestration/attempt-usage.js +168 -0
- package/dist/core/orchestration/attempt-usage.js.map +1 -0
- package/dist/core/orchestration/capability-gateway.d.ts +19 -1
- package/dist/core/orchestration/capability-gateway.d.ts.map +1 -1
- package/dist/core/orchestration/capability-gateway.js +128 -28
- package/dist/core/orchestration/capability-gateway.js.map +1 -1
- package/dist/core/orchestration/contracts.d.ts +35 -0
- package/dist/core/orchestration/contracts.d.ts.map +1 -1
- package/dist/core/orchestration/contracts.js +17 -0
- package/dist/core/orchestration/contracts.js.map +1 -1
- package/dist/core/orchestration/delegation-ledger.d.ts +17 -2
- package/dist/core/orchestration/delegation-ledger.d.ts.map +1 -1
- package/dist/core/orchestration/delegation-ledger.js +81 -3
- package/dist/core/orchestration/delegation-ledger.js.map +1 -1
- package/dist/core/orchestration/event-store.d.ts +1 -0
- package/dist/core/orchestration/event-store.d.ts.map +1 -1
- package/dist/core/orchestration/event-store.js +78 -38
- package/dist/core/orchestration/event-store.js.map +1 -1
- package/dist/core/orchestration/profile-registry.d.ts.map +1 -1
- package/dist/core/orchestration/profile-registry.js +81 -41
- package/dist/core/orchestration/profile-registry.js.map +1 -1
- package/dist/core/orchestration/profile-store.d.ts.map +1 -1
- package/dist/core/orchestration/profile-store.js +18 -4
- package/dist/core/orchestration/profile-store.js.map +1 -1
- package/dist/core/orchestration/risk-budget.d.ts +2 -0
- package/dist/core/orchestration/risk-budget.d.ts.map +1 -1
- package/dist/core/orchestration/risk-budget.js +26 -0
- package/dist/core/orchestration/risk-budget.js.map +1 -1
- package/dist/core/orchestration/task-runtime.d.ts +13 -1
- package/dist/core/orchestration/task-runtime.d.ts.map +1 -1
- package/dist/core/orchestration/task-runtime.js +127 -16
- package/dist/core/orchestration/task-runtime.js.map +1 -1
- package/dist/core/orchestration/work-state-projection.d.ts.map +1 -1
- package/dist/core/orchestration/work-state-projection.js +1 -1
- package/dist/core/orchestration/work-state-projection.js.map +1 -1
- package/dist/core/orchestration/worker-execution-contract.d.ts +3 -1
- package/dist/core/orchestration/worker-execution-contract.d.ts.map +1 -1
- package/dist/core/orchestration/worker-execution-contract.js +75 -23
- package/dist/core/orchestration/worker-execution-contract.js.map +1 -1
- package/dist/core/orchestration/worker-result-adapter.d.ts +9 -3
- package/dist/core/orchestration/worker-result-adapter.d.ts.map +1 -1
- package/dist/core/orchestration/worker-result-adapter.js +167 -14
- package/dist/core/orchestration/worker-result-adapter.js.map +1 -1
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +20 -3
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/profile-filter-controller.d.ts +8 -1
- package/dist/core/profile-filter-controller.d.ts.map +1 -1
- package/dist/core/profile-filter-controller.js +23 -5
- package/dist/core/profile-filter-controller.js.map +1 -1
- package/dist/core/prompt-templates.d.ts +1 -0
- package/dist/core/prompt-templates.d.ts.map +1 -1
- package/dist/core/prompt-templates.js +18 -29
- package/dist/core/prompt-templates.js.map +1 -1
- package/dist/core/reflection-controller.d.ts +2 -2
- package/dist/core/reflection-controller.d.ts.map +1 -1
- package/dist/core/reflection-controller.js +92 -54
- package/dist/core/reflection-controller.js.map +1 -1
- package/dist/core/request-auth.d.ts +7 -0
- package/dist/core/request-auth.d.ts.map +1 -0
- package/dist/core/request-auth.js +8 -0
- package/dist/core/request-auth.js.map +1 -0
- package/dist/core/research/evidence-bundle.d.ts +20 -0
- package/dist/core/research/evidence-bundle.d.ts.map +1 -1
- package/dist/core/research/evidence-bundle.js +173 -69
- package/dist/core/research/evidence-bundle.js.map +1 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +16 -6
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/risk-classifier.d.ts.map +1 -1
- package/dist/core/risk-classifier.js +8 -0
- package/dist/core/risk-classifier.js.map +1 -1
- package/dist/core/runtime-builder.d.ts +22 -3
- package/dist/core/runtime-builder.d.ts.map +1 -1
- package/dist/core/runtime-builder.js +147 -80
- package/dist/core/runtime-builder.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +7 -1
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/secrets/credential-exposure-guard.d.ts +9 -0
- package/dist/core/secrets/credential-exposure-guard.d.ts.map +1 -0
- package/dist/core/secrets/credential-exposure-guard.js +241 -0
- package/dist/core/secrets/credential-exposure-guard.js.map +1 -0
- package/dist/core/secrets/secret-dotenv.d.ts +27 -0
- package/dist/core/secrets/secret-dotenv.d.ts.map +1 -0
- package/dist/core/secrets/secret-dotenv.js +183 -0
- package/dist/core/secrets/secret-dotenv.js.map +1 -0
- package/dist/core/secrets/secret-vault-format.d.ts +112 -0
- package/dist/core/secrets/secret-vault-format.d.ts.map +1 -0
- package/dist/core/secrets/secret-vault-format.js +397 -0
- package/dist/core/secrets/secret-vault-format.js.map +1 -0
- package/dist/core/secrets/secret-vault.d.ts +72 -0
- package/dist/core/secrets/secret-vault.d.ts.map +1 -0
- package/dist/core/secrets/secret-vault.js +671 -0
- package/dist/core/secrets/secret-vault.js.map +1 -0
- package/dist/core/session-analytics.d.ts +4 -23
- package/dist/core/session-analytics.d.ts.map +1 -1
- package/dist/core/session-analytics.js +39 -69
- package/dist/core/session-analytics.js.map +1 -1
- package/dist/core/session-artifact-bundle.d.ts +35 -0
- package/dist/core/session-artifact-bundle.d.ts.map +1 -0
- package/dist/core/session-artifact-bundle.js +61 -0
- package/dist/core/session-artifact-bundle.js.map +1 -0
- package/dist/core/session-role.d.ts +5 -0
- package/dist/core/session-role.d.ts.map +1 -1
- package/dist/core/session-role.js +14 -1
- package/dist/core/session-role.js.map +1 -1
- package/dist/core/session-tree-navigator.d.ts +4 -6
- package/dist/core/session-tree-navigator.d.ts.map +1 -1
- package/dist/core/session-tree-navigator.js +4 -1
- package/dist/core/session-tree-navigator.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 +1 -1
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +2 -2
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/tool-capability-policy.d.ts.map +1 -1
- package/dist/core/tool-capability-policy.js +1 -0
- package/dist/core/tool-capability-policy.js.map +1 -1
- package/dist/core/tool-gate-controller.d.ts.map +1 -1
- package/dist/core/tool-gate-controller.js +8 -2
- package/dist/core/tool-gate-controller.js.map +1 -1
- package/dist/core/tool-protocol-controller.d.ts +2 -4
- package/dist/core/tool-protocol-controller.d.ts.map +1 -1
- package/dist/core/tool-protocol-controller.js.map +1 -1
- package/dist/core/tool-recovery-stats.d.ts +21 -1
- package/dist/core/tool-recovery-stats.d.ts.map +1 -1
- package/dist/core/tool-recovery-stats.js.map +1 -1
- package/dist/core/tools/bash.d.ts +5 -0
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +59 -5
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/delegate-status.d.ts +6 -1
- package/dist/core/tools/delegate-status.d.ts.map +1 -1
- package/dist/core/tools/delegate-status.js +106 -25
- package/dist/core/tools/delegate-status.js.map +1 -1
- package/dist/core/tools/delegate.d.ts +9 -1
- package/dist/core/tools/delegate.d.ts.map +1 -1
- package/dist/core/tools/delegate.js +329 -69
- package/dist/core/tools/delegate.js.map +1 -1
- package/dist/core/tools/git-filter.d.ts +1 -8
- package/dist/core/tools/git-filter.d.ts.map +1 -1
- package/dist/core/tools/git-filter.js +2 -63
- package/dist/core/tools/git-filter.js.map +1 -1
- package/dist/core/tools/goal.d.ts +5 -3
- package/dist/core/tools/goal.d.ts.map +1 -1
- package/dist/core/tools/goal.js +97 -19
- package/dist/core/tools/goal.js.map +1 -1
- package/dist/core/tools/index.d.ts +1 -0
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +1 -0
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/orchestration-panel.d.ts +1 -4
- package/dist/core/tools/orchestration-panel.d.ts.map +1 -1
- package/dist/core/tools/orchestration-panel.js +0 -44
- package/dist/core/tools/orchestration-panel.js.map +1 -1
- package/dist/core/tools/output-accumulator.d.ts +11 -0
- package/dist/core/tools/output-accumulator.d.ts.map +1 -1
- package/dist/core/tools/output-accumulator.js +36 -3
- package/dist/core/tools/output-accumulator.js.map +1 -1
- package/dist/core/tools/python.d.ts +2 -0
- package/dist/core/tools/python.d.ts.map +1 -1
- package/dist/core/tools/python.js +3 -1
- package/dist/core/tools/python.js.map +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/run-process.d.ts +1 -1
- package/dist/core/tools/run-process.d.ts.map +1 -1
- package/dist/core/tools/run-process.js +69 -9
- package/dist/core/tools/run-process.js.map +1 -1
- package/dist/core/tools/search-command-guard.d.ts +14 -0
- package/dist/core/tools/search-command-guard.d.ts.map +1 -0
- package/dist/core/tools/search-command-guard.js +333 -0
- package/dist/core/tools/search-command-guard.js.map +1 -0
- package/dist/core/tools/secret-store.d.ts +38 -0
- package/dist/core/tools/secret-store.d.ts.map +1 -0
- package/dist/core/tools/secret-store.js +412 -0
- package/dist/core/tools/secret-store.js.map +1 -0
- package/dist/core/tools/shell-command-parser.d.ts +16 -0
- package/dist/core/tools/shell-command-parser.d.ts.map +1 -0
- package/dist/core/tools/shell-command-parser.js +113 -0
- package/dist/core/tools/shell-command-parser.js.map +1 -0
- package/dist/core/tools/shell-contract-router.d.ts.map +1 -1
- package/dist/core/tools/shell-contract-router.js +12 -5
- package/dist/core/tools/shell-contract-router.js.map +1 -1
- package/dist/core/tools/task-steps.d.ts.map +1 -1
- package/dist/core/tools/task-steps.js +4 -7
- package/dist/core/tools/task-steps.js.map +1 -1
- package/dist/core/util/atomic-file.d.ts +6 -2
- package/dist/core/util/atomic-file.d.ts.map +1 -1
- package/dist/core/util/atomic-file.js +4 -4
- package/dist/core/util/atomic-file.js.map +1 -1
- package/dist/core/util/bounded-file.d.ts +15 -0
- package/dist/core/util/bounded-file.d.ts.map +1 -0
- package/dist/core/util/bounded-file.js +120 -0
- package/dist/core/util/bounded-file.js.map +1 -0
- package/dist/core/util/bounded-jsonl.d.ts.map +1 -1
- package/dist/core/util/bounded-jsonl.js +119 -9
- package/dist/core/util/bounded-jsonl.js.map +1 -1
- package/dist/core/util/bounded-value.d.ts +3 -0
- package/dist/core/util/bounded-value.d.ts.map +1 -0
- package/dist/core/util/bounded-value.js +12 -0
- package/dist/core/util/bounded-value.js.map +1 -0
- package/dist/core/util/value-guards.d.ts +2 -0
- package/dist/core/util/value-guards.d.ts.map +1 -1
- package/dist/core/util/value-guards.js +5 -0
- package/dist/core/util/value-guards.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +25 -11
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/auth-dialogs-controller.d.ts +4 -0
- package/dist/modes/interactive/auth-dialogs-controller.d.ts.map +1 -1
- package/dist/modes/interactive/auth-dialogs-controller.js +60 -1
- package/dist/modes/interactive/auth-dialogs-controller.js.map +1 -1
- package/dist/modes/interactive/components/activity-lane.d.ts +55 -0
- package/dist/modes/interactive/components/activity-lane.d.ts.map +1 -0
- package/dist/modes/interactive/components/activity-lane.js +304 -0
- package/dist/modes/interactive/components/activity-lane.js.map +1 -0
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +19 -10
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/expandable-text.d.ts +12 -0
- package/dist/modes/interactive/components/expandable-text.d.ts.map +1 -0
- package/dist/modes/interactive/components/expandable-text.js +17 -0
- package/dist/modes/interactive/components/expandable-text.js.map +1 -0
- package/dist/modes/interactive/components/extension-editor.d.ts +15 -1
- package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-editor.js +30 -21
- package/dist/modes/interactive/components/extension-editor.js.map +1 -1
- package/dist/modes/interactive/components/extension-input.d.ts +1 -0
- package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-input.js +6 -1
- package/dist/modes/interactive/components/extension-input.js.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.d.ts +2 -2
- package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.js +23 -14
- package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js +27 -44
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +4 -4
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts +19 -11
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +53 -20
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/tool-group.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-group.js +3 -0
- package/dist/modes/interactive/components/tool-group.js.map +1 -1
- package/dist/modes/interactive/components/usage-action-selector.d.ts +16 -0
- package/dist/modes/interactive/components/usage-action-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/usage-action-selector.js +46 -0
- package/dist/modes/interactive/components/usage-action-selector.js.map +1 -0
- package/dist/modes/interactive/extension-ui-host.d.ts.map +1 -1
- package/dist/modes/interactive/extension-ui-host.js +1 -0
- package/dist/modes/interactive/extension-ui-host.js.map +1 -1
- package/dist/modes/interactive/external-editor.d.ts +15 -0
- package/dist/modes/interactive/external-editor.d.ts.map +1 -1
- package/dist/modes/interactive/external-editor.js +27 -19
- package/dist/modes/interactive/external-editor.js.map +1 -1
- package/dist/modes/interactive/history-reload-math.d.ts +6 -2
- package/dist/modes/interactive/history-reload-math.d.ts.map +1 -1
- package/dist/modes/interactive/history-reload-math.js +10 -5
- package/dist/modes/interactive/history-reload-math.js.map +1 -1
- package/dist/modes/interactive/interactive-event-controller.d.ts +74 -0
- package/dist/modes/interactive/interactive-event-controller.d.ts.map +1 -0
- package/dist/modes/interactive/interactive-event-controller.js +328 -0
- package/dist/modes/interactive/interactive-event-controller.js.map +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts +20 -25
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +196 -608
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/loaded-resources-view.d.ts +20 -0
- package/dist/modes/interactive/loaded-resources-view.d.ts.map +1 -0
- package/dist/modes/interactive/loaded-resources-view.js +147 -0
- package/dist/modes/interactive/loaded-resources-view.js.map +1 -0
- package/dist/modes/interactive/resource-display.d.ts.map +1 -1
- package/dist/modes/interactive/resource-display.js +8 -2
- package/dist/modes/interactive/resource-display.js.map +1 -1
- package/dist/modes/interactive/resource-shell-commands.d.ts +1 -5
- package/dist/modes/interactive/resource-shell-commands.d.ts.map +1 -1
- package/dist/modes/interactive/resource-shell-commands.js +0 -5
- package/dist/modes/interactive/resource-shell-commands.js.map +1 -1
- package/dist/modes/interactive/session-flow-commands.d.ts +10 -6
- package/dist/modes/interactive/session-flow-commands.d.ts.map +1 -1
- package/dist/modes/interactive/session-flow-commands.js +123 -70
- package/dist/modes/interactive/session-flow-commands.js.map +1 -1
- package/dist/modes/interactive/usage-commands.d.ts +34 -0
- package/dist/modes/interactive/usage-commands.d.ts.map +1 -0
- package/dist/modes/interactive/usage-commands.js +225 -0
- package/dist/modes/interactive/usage-commands.js.map +1 -0
- package/dist/utils/shell.d.ts.map +1 -1
- package/dist/utils/shell.js +5 -3
- package/dist/utils/shell.js.map +1 -1
- package/dist/utils/version-check.d.ts.map +1 -1
- package/dist/utils/version-check.js +3 -1
- package/dist/utils/version-check.js.map +1 -1
- package/docs/UI_POLISH_ORCHESTRATION.md +25 -31
- package/docs/UI_QUALITY_ORCHESTRATION.md +22 -24
- package/docs/providers.md +9 -1
- package/docs/tool-repair.md +3 -0
- package/docs/ui-reference/README.md +6 -6
- package/docs/ui-reference/orchestration-after.txt +14 -7
- package/docs/ui-reference/orchestration-before.txt +12 -6
- package/docs/ui-reference/orchestration-reference.txt +15 -5
- package/docs/usage.md +9 -1
- package/docs/windows.md +4 -2
- 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 +13 -13
- package/package.json +4 -4
|
@@ -1 +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(\n\t\tcreate: (done: () => void) => {\n\t\t\tcomponent: Component;\n\t\t\tfocus: Component;\n\t\t\tonSuperseded?: () => void;\n\t\t},\n\t): 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 {\n\t\t\t\t\t\tcomponent: submenu,\n\t\t\t\t\t\tfocus: submenu.getSelectList(),\n\t\t\t\t\t\tonSuperseded: () => resolve(false),\n\t\t\t\t\t};\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"]}
|
|
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, 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(\n\t\tcreate: (done: () => void) => {\n\t\t\tcomponent: Component;\n\t\t\tfocus: Component;\n\t\t\tonSuperseded?: () => void;\n\t\t},\n\t): 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\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 {\n\t\t\t\t\t\tcomponent: submenu,\n\t\t\t\t\t\tfocus: submenu.getSelectList(),\n\t\t\t\t\t\tonSuperseded: () => resolve(false),\n\t\t\t\t\t};\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\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"]}
|
|
@@ -11,12 +11,13 @@
|
|
|
11
11
|
* tests keep exercising them through interactive-mode's thin wrappers unchanged.
|
|
12
12
|
*/
|
|
13
13
|
import type { SessionManager } from "@caupulican/pi-agent-core/node";
|
|
14
|
-
import type { Model } from "@caupulican/pi-ai";
|
|
14
|
+
import type { Api, Model } from "@caupulican/pi-ai";
|
|
15
15
|
import type { EditorComponent } from "@caupulican/pi-tui";
|
|
16
16
|
import { type Component, type Container, Loader, type TUI } from "@caupulican/pi-tui";
|
|
17
17
|
import type { AgentSession, GoalContinuationLoopOptions, GoalContinuationLoopResult } from "../../core/agent-session.ts";
|
|
18
18
|
import type { AgentSessionRuntime } from "../../core/agent-session-runtime.ts";
|
|
19
19
|
import type { ExtensionCommandContext } from "../../core/extensions/index.ts";
|
|
20
|
+
import { type GoalStateRevision } from "../../core/goals/goal-lifecycle.ts";
|
|
20
21
|
import type { GoalState } from "../../core/goals/goal-state.ts";
|
|
21
22
|
import type { KeybindingsManager } from "../../core/keybindings.ts";
|
|
22
23
|
import { MissingSessionCwdError } from "../../core/session-cwd.ts";
|
|
@@ -58,12 +59,12 @@ export interface SessionFlowHost {
|
|
|
58
59
|
promptForMissingSessionCwd(error: MissingSessionCwdError): Promise<string | undefined>;
|
|
59
60
|
updateEditorBorderColor(): void;
|
|
60
61
|
updateAvailableProviderCount(): Promise<void>;
|
|
61
|
-
maybeWarnAboutAnthropicSubscriptionAuth(model?: Model<
|
|
62
|
+
maybeWarnAboutAnthropicSubscriptionAuth(model?: Model<Api>): Promise<void>;
|
|
62
63
|
checkDaxnutsEasterEgg(model: {
|
|
63
64
|
provider: string;
|
|
64
65
|
id: string;
|
|
65
66
|
}): void;
|
|
66
|
-
getModelCandidates(): Promise<Model<
|
|
67
|
+
getModelCandidates(): Promise<Model<Api>[]>;
|
|
67
68
|
shutdown(options?: {
|
|
68
69
|
fromSignal?: boolean;
|
|
69
70
|
}): Promise<void>;
|
|
@@ -78,7 +79,7 @@ export declare function handleResumeSession(host: SessionFlowHost, sessionPath:
|
|
|
78
79
|
cancelled: boolean;
|
|
79
80
|
}>;
|
|
80
81
|
export declare function handleModelCommand(host: SessionFlowHost, searchTerm?: string): Promise<void>;
|
|
81
|
-
export declare function findExactModelMatch(host: SessionFlowHost, searchTerm: string): Promise<Model<
|
|
82
|
+
export declare function findExactModelMatch(host: SessionFlowHost, searchTerm: string): Promise<Model<Api> | undefined>;
|
|
82
83
|
export interface CloneCommandHost {
|
|
83
84
|
readonly sessionManager: {
|
|
84
85
|
getLeafId: () => string | null;
|
|
@@ -116,18 +117,21 @@ export type ParsedGoalContinueCommand = {
|
|
|
116
117
|
export interface GoalResumeHost {
|
|
117
118
|
readonly session: {
|
|
118
119
|
getGoalStateSnapshot: () => GoalState | undefined;
|
|
119
|
-
saveGoalStateSnapshot: (state: GoalState) => string;
|
|
120
|
+
saveGoalStateSnapshot: (state: GoalState, expected?: GoalStateRevision) => string;
|
|
121
|
+
clearGoalStateSnapshot?: (state: GoalState, now: string) => string;
|
|
122
|
+
restoreGoalRuntimeAfterResume: () => void;
|
|
120
123
|
};
|
|
121
124
|
refreshAutonomyFooterStatus(): void;
|
|
122
125
|
}
|
|
123
126
|
export interface GoalCommandHost extends GoalResumeHost {
|
|
124
127
|
readonly session: GoalResumeHost["session"] & {
|
|
125
|
-
sendUserMessage: (content: string) => Promise<void>;
|
|
126
128
|
continueGoalLoop: (options: GoalContinuationLoopOptions) => Promise<GoalContinuationLoopResult>;
|
|
127
129
|
getGoalRuntimeSnapshot: (settings: {
|
|
128
130
|
maxStallTurns: number;
|
|
129
131
|
}) => ReturnType<AgentSession["getGoalRuntimeSnapshot"]>;
|
|
130
132
|
};
|
|
133
|
+
promptForGoalEdit?(currentObjective: string): Promise<string | undefined>;
|
|
134
|
+
getMaxStallTurns?(): number;
|
|
131
135
|
showStatus(message: string): void;
|
|
132
136
|
showError(message: string): void;
|
|
133
137
|
}
|
|
@@ -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 { resumeBlockedPersistedGoal, resumePersistedGoal } from \"../../core/goals/goal-lifecycle.ts\";\nimport type { GoalState } from \"../../core/goals/goal-state.ts\";\nimport { applyGoalAction, completeGoalManually } 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 { parseTaskCommand } from \"../../core/tasks/task-command.ts\";\nimport {\n\taddTaskStep,\n\tclearTaskSteps,\n\tcompactTaskSteps,\n\tcreateTaskStepsState,\n\tformatTaskSteps,\n\ttype TaskStepsState,\n\tupdateTaskStep,\n} from \"../../core/tasks/task-state.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 { handleNonFatalSessionReplacementError } from \"./session-replacement-errors.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\trefreshAutonomyFooterStatus(): 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\ntype SessionGoalResumeResult = { ok: true; resumed: boolean };\n\nasync function switchSessionAndResumeGoal(\n\thost: SessionFlowHost,\n\tsessionPath: string,\n\toptions: Parameters<ExtensionCommandContext[\"switchSession\"]>[1] | undefined,\n\tcwdOverride?: string,\n): Promise<{ cancelled: boolean; goalResume: SessionGoalResumeResult }> {\n\tlet goalResume: SessionGoalResumeResult = { ok: true, resumed: false };\n\tconst result = await host.runtimeHost.switchSession(sessionPath, {\n\t\tcwdOverride,\n\t\tbeforeSessionResourcesStart: (session) => {\n\t\t\tconst resumed = resumeBlockedGoalAfterSessionSwitch(session, () => host.refreshAutonomyFooterStatus());\n\t\t\tif (!resumed.ok) throw new Error(`Goal resume failed: ${resumed.error}`);\n\t\t\tgoalResume = resumed;\n\t\t},\n\t\twithSession: options?.withSession,\n\t});\n\treturn { ...result, goalResume };\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 switchSessionAndResumeGoal(host, sessionPath, options);\n\t\tif (result.cancelled) {\n\t\t\treturn result;\n\t\t}\n\t\thost.renderCurrentSessionState();\n\t\thost.showStatus(result.goalResume.resumed ? \"Resumed session and goal\" : \"Resumed session\");\n\t\treturn result;\n\t} catch (error: unknown) {\n\t\tconst disposition = handleNonFatalSessionReplacementError(host, error);\n\t\tif (disposition) return { cancelled: disposition === \"previous_restored\" };\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\ttry {\n\t\t\t\tconst result = await switchSessionAndResumeGoal(host, sessionPath, options, selectedCwd);\n\t\t\t\tif (result.cancelled) {\n\t\t\t\t\treturn result;\n\t\t\t\t}\n\t\t\t\thost.renderCurrentSessionState();\n\t\t\t\thost.showStatus(\n\t\t\t\t\tresult.goalResume.resumed ? \"Resumed session and goal in current cwd\" : \"Resumed session in current cwd\",\n\t\t\t\t);\n\t\t\t\treturn result;\n\t\t\t} catch (retryError: unknown) {\n\t\t\t\tconst retryDisposition = handleNonFatalSessionReplacementError(host, retryError);\n\t\t\t\tif (retryDisposition) return { cancelled: retryDisposition === \"previous_restored\" };\n\t\t\t\treturn host.handleFatalRuntimeError(\"Failed to resume session\", retryError);\n\t\t\t}\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 GoalResumeHost {\n\treadonly session: {\n\t\tgetGoalStateSnapshot: () => GoalState | undefined;\n\t\tsaveGoalStateSnapshot: (state: GoalState) => string;\n\t};\n\trefreshAutonomyFooterStatus(): void;\n}\n\nexport interface GoalCommandHost extends GoalResumeHost {\n\treadonly session: GoalResumeHost[\"session\"] & {\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}\n\nexport type GoalResumeResult = { ok: true; resumed: true; state: GoalState } | { ok: false; error: string };\n\n/** Canonical persisted transition used by both `/goal resume` and session `/resume`. */\nexport function resumeCurrentGoal(host: GoalResumeHost, now = new Date().toISOString()): GoalResumeResult {\n\tconst resumed = resumePersistedGoal(host.session, now);\n\tif (!resumed.ok) return resumed;\n\thost.refreshAutonomyFooterStatus();\n\treturn { ok: true, resumed: true, state: resumed.state };\n}\n\nfunction resumeBlockedGoalAfterSessionSwitch(\n\tsession: GoalResumeHost[\"session\"],\n\trefreshAutonomyFooterStatus: () => void,\n): { ok: true; resumed: boolean } | { ok: false; error: string } {\n\tconst resumed = resumeBlockedPersistedGoal(session);\n\tif (resumed.ok && resumed.resumed) refreshAutonomyFooterStatus();\n\treturn resumed;\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\tconst requirements = state.requirements.map((requirement) => {\n\t\tconst blockedReason = requirement.blockedReason ? ` — ${requirement.blockedReason}` : \"\";\n\t\treturn `- ${requirement.id}: ${requirement.status}${blockedReason}`;\n\t});\n\tconst blockedReason = state.blockedReason ? `\\nBlocked reason: ${state.blockedReason}` : \"\";\n\tconst requirementDetails = requirements.length > 0 ? `\\n${requirements.join(\"\\n\")}` : \"\";\n\treturn `Goal: ${state.userGoal}\\nStatus: ${state.status}${blockedReason}\\nRequirements: open ${snapshot.continuation.openRequirementIds.length}, blocked ${snapshot.continuation.blockedRequirementIds.length}, satisfied ${snapshot.continuation.satisfiedRequirementIds.length}${requirementDetails}\\nContinuation: ${snapshot.continuation.action}/${snapshot.continuation.reasonCode}\\nControls: /goal resume | /goal reopen <requirement-id> | /goal complete | /goal close | /goal override <text>`;\n}\n\nexport async function handleGoalCommand(host: GoalCommandHost, text: string): Promise<void> {\n\tconst input = text.replace(/^\\/goal\\s*/, \"\").trim();\n\tif (!input || input === \"status\") {\n\t\thost.showStatus(formatGoalStatus(host.session.getGoalRuntimeSnapshot({ maxStallTurns: 20 })));\n\t\treturn;\n\t}\n\n\tconst now = new Date().toISOString();\n\tconst current = host.session.getGoalStateSnapshot();\n\tif (input === \"resume\") {\n\t\tconst resumed = resumeCurrentGoal(host, now);\n\t\tif (!resumed.ok) {\n\t\t\thost.showError(resumed.error);\n\t\t\treturn;\n\t\t}\n\t\thost.showStatus(\"Goal resumed.\");\n\t\treturn;\n\t}\n\n\tif (input === \"complete\") {\n\t\tconst completed = completeGoalManually(current, now);\n\t\tif (!completed.ok) {\n\t\t\thost.showError(completed.error);\n\t\t\treturn;\n\t\t}\n\t\thost.session.saveGoalStateSnapshot(completed.state);\n\t\thost.showStatus(\"Goal completed manually.\");\n\t\thost.refreshAutonomyFooterStatus();\n\t\treturn;\n\t}\n\n\tif (input === \"close\" || input === \"cancel\") {\n\t\tconst cancelled = applyGoalAction(current, { action: \"cancel\" }, now);\n\t\tif (!cancelled.ok) {\n\t\t\thost.showError(cancelled.error);\n\t\t\treturn;\n\t\t}\n\t\thost.session.saveGoalStateSnapshot(cancelled.state);\n\t\thost.showStatus(\"Goal closed.\");\n\t\thost.refreshAutonomyFooterStatus();\n\t\treturn;\n\t}\n\n\tif (input === \"reopen\" || input.startsWith(\"reopen \")) {\n\t\tconst requirementId = input.slice(\"reopen\".length).trim();\n\t\tif (!requirementId) {\n\t\t\thost.showError(\"Usage: /goal reopen <requirement-id>\");\n\t\t\treturn;\n\t\t}\n\t\tif (!current) {\n\t\t\thost.showError(\"No goal exists to update.\");\n\t\t\treturn;\n\t\t}\n\t\tconst requirement = current.requirements.find((candidate) => candidate.id === requirementId);\n\t\tif (!requirement || requirement.status !== \"blocked\") {\n\t\t\thost.showError(\n\t\t\t\trequirement\n\t\t\t\t\t? `Requirement '${requirementId}' is ${requirement.status}; only blocked requirements can be reopened.`\n\t\t\t\t\t: `Unknown requirement '${requirementId}'.`,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tlet active = current;\n\t\tif (active.status === \"blocked\") {\n\t\t\tconst resumed = resumePersistedGoal(host.session, now);\n\t\t\tif (!resumed.ok) {\n\t\t\t\thost.showError(resumed.error);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tactive = resumed.state;\n\t\t}\n\t\tconst reopened = applyGoalAction(active, { action: \"reopen_requirement\", requirementId }, now);\n\t\tif (!reopened.ok) {\n\t\t\thost.showError(reopened.error);\n\t\t\treturn;\n\t\t}\n\t\thost.session.saveGoalStateSnapshot(reopened.state);\n\t\thost.showStatus(\n\t\t\t`Requirement '${requirementId}' reopened${current.status === \"blocked\" ? \" and goal resumed\" : \"\"}.`,\n\t\t);\n\t\thost.refreshAutonomyFooterStatus();\n\t\treturn;\n\t}\n\n\tconst overriding = input === \"override\" || input.startsWith(\"override \");\n\tconst goalText = overriding ? input.slice(\"override\".length).trim() : input;\n\tif (!goalText) {\n\t\thost.showError(\"Usage: /goal override <text>\");\n\t\treturn;\n\t}\n\tlet startFrom = current;\n\tif (overriding && startFrom && (startFrom.status === \"active\" || startFrom.status === \"blocked\")) {\n\t\tconst cancelled = applyGoalAction(startFrom, { action: \"cancel\" }, now);\n\t\tif (!cancelled.ok) {\n\t\t\thost.showError(cancelled.error);\n\t\t\treturn;\n\t\t}\n\t\tstartFrom = cancelled.state;\n\t\thost.session.saveGoalStateSnapshot(startFrom);\n\t}\n\n\tconst goalId = `goal-${Date.now().toString(36)}`;\n\tconst started = applyGoalAction(startFrom, { action: \"start\", goalId, userGoal: goalText }, now);\n\tif (!started.ok) {\n\t\thost.showError(`${started.error} Use /goal override <text> to replace it explicitly.`);\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 verb = overriding ? \"overridden\" : \"started\";\n\ttry {\n\t\tconst result = await host.session.continueGoalLoop({ maxTurns: 1, maxStallTurns: 20, maxWallClockMinutes: 0 });\n\t\tif (result.stopReason === \"already_continuing\") {\n\t\t\t// The idle autosteer timer armed by `sendUserMessage` above already won the single-flight\n\t\t\t// guard (`BackgroundLaneController.continueGoalLoopExclusive`) — this request never ran a\n\t\t\t// pass, so reporting `finalSnapshot.continuation` here would misleadingly imply a fresh\n\t\t\t// decision was made.\n\t\t\thost.showStatus(`Goal ${verb}: the autonomy loop is already continuing this goal.`);\n\t\t} else if (result.stopReason === \"session_disposed\") {\n\t\t\thost.showStatus(`Goal ${verb}, but the session was disposed before continuation could run.`);\n\t\t} else {\n\t\t\tconst continuation = result.finalSnapshot.continuation;\n\t\t\thost.showStatus(`Goal ${verb}: ${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 TaskCommandHost {\n\treadonly session: {\n\t\tgetTaskStepsStateSnapshot: () => TaskStepsState | undefined;\n\t\tsaveTaskStepsStateSnapshot: (state: TaskStepsState) => string;\n\t};\n\tshowStatus(message: string): void;\n\tshowError(message: string): void;\n}\n\nexport function handleTaskCommand(host: TaskCommandHost, text: string): void {\n\tconst parsed = parseTaskCommand(text);\n\tif (!parsed.ok) {\n\t\thost.showError(parsed.error);\n\t\treturn;\n\t}\n\tif (parsed.command.type === \"retired_execution\") {\n\t\thost.showStatus(\n\t\t\t`/task ${parsed.command.operation} was retired with the detached extension runner. Ask Pi to use native delegate/delegate_status; session-owned worker lanes notify on completion without polling.`,\n\t\t);\n\t\treturn;\n\t}\n\n\tconst now = new Date().toISOString();\n\tlet state = host.session.getTaskStepsStateSnapshot() ?? createTaskStepsState(now);\n\ttry {\n\t\tswitch (parsed.command.type) {\n\t\t\tcase \"list\":\n\t\t\t\thost.showStatus(formatTaskSteps(state, { includeTerminal: parsed.command.includeTerminal }));\n\t\t\t\treturn;\n\t\t\tcase \"add\":\n\t\t\t\tstate = addTaskStep(state, { content: parsed.command.content }, now);\n\t\t\t\tbreak;\n\t\t\tcase \"update\":\n\t\t\t\tstate = updateTaskStep(\n\t\t\t\t\tstate,\n\t\t\t\t\tparsed.command.selector,\n\t\t\t\t\t{\n\t\t\t\t\t\tstatus: parsed.command.status,\n\t\t\t\t\t\tnote: parsed.command.note,\n\t\t\t\t\t\tevidence: parsed.command.evidence ? [parsed.command.evidence] : undefined,\n\t\t\t\t\t},\n\t\t\t\t\tnow,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"clear\":\n\t\t\t\tstate = clearTaskSteps(state, now);\n\t\t\t\tbreak;\n\t\t\tcase \"compact\":\n\t\t\t\tstate = compactTaskSteps(state, now);\n\t\t\t\tbreak;\n\t\t}\n\t\thost.session.saveTaskStepsStateSnapshot(state);\n\t\thost.showStatus(formatTaskSteps(state));\n\t} catch (error) {\n\t\thost.showError(error instanceof Error ? error.message : String(error));\n\t}\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"]}
|
|
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 { randomUUID } from \"node:crypto\";\nimport type { SessionManager } from \"@caupulican/pi-agent-core/node\";\nimport type { Api, 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 {\n\tcancelPersistedGoal,\n\tclearPersistedGoal,\n\teditPersistedGoal,\n\ttype GoalStateRevision,\n\tgetGoalStateRevision,\n\tpausePersistedGoal,\n\treplaceGoal,\n\tresumeGoal,\n\tresumePersistedGoal,\n} from \"../../core/goals/goal-lifecycle.ts\";\nimport type { GoalState } from \"../../core/goals/goal-state.ts\";\nimport { applyGoalAction, completeGoalManually } from \"../../core/goals/goal-tool-core.ts\";\nimport type { KeybindingsManager } from \"../../core/keybindings.ts\";\nimport {\n\tfindExactModelReferenceMatch,\n\tresolveModelScope,\n\tresolveModelScopeWithDiagnostics,\n} 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 { parseTaskCommand } from \"../../core/tasks/task-command.ts\";\nimport {\n\taddTaskStep,\n\tclearTaskSteps,\n\tcompactTaskSteps,\n\tcreateTaskStepsState,\n\tformatTaskSteps,\n\ttype TaskStepsState,\n\tupdateTaskStep,\n} from \"../../core/tasks/task-state.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 { handleNonFatalSessionReplacementError } from \"./session-replacement-errors.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\trefreshAutonomyFooterStatus(): 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<Api>): Promise<void>;\n\tcheckDaxnutsEasterEgg(model: { provider: string; id: string }): void;\n\tgetModelCandidates(): Promise<Model<Api>[]>;\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\tconst allModelIds = new Set(allModels.map((model) => `${model.provider}/${model.id}`));\n\tconst configuredPatterns = host.settingsManager.getEnabledModels();\n\tconst sessionScopedModels = host.session.scopedModels;\n\n\tif (allModels.length === 0 && !configuredPatterns?.length && sessionScopedModels.length === 0) {\n\t\thost.showStatus(\"No models available\");\n\t\treturn;\n\t}\n\tconst configuredScope = configuredPatterns?.length\n\t\t? await resolveModelScopeWithDiagnostics(configuredPatterns, host.session.modelRegistry)\n\t\t: undefined;\n\n\t// Check if session has scoped models (from previous session-only changes or CLI --models)\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 if (configuredScope) {\n\t\tcurrentEnabledIds = configuredScope.scopedModels.map((scoped) => `${scoped.model.provider}/${scoped.model.id}`);\n\t}\n\n\tfor (const diagnostic of configuredScope?.diagnostics ?? []) {\n\t\tif (diagnostic.code !== \"no-match\") continue;\n\t\tcurrentEnabledIds ??= [];\n\t\tif (!currentEnabledIds.includes(diagnostic.pattern)) currentEnabledIds.push(diagnostic.pattern);\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\tconst hasEnabledAvailableModel = enabledIds?.some((id) => allModelIds.has(id)) ?? false;\n\t\tconst allAvailableModelsEnabled = enabledIds !== null && [...allModelIds].every((id) => enabledIds.includes(id));\n\t\tif (enabledIds && hasEnabledAvailableModel && !allAvailableModelsEnabled) {\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 allEnabled =\n\t\t\t\t\t\tenabledIds !== null &&\n\t\t\t\t\t\tenabledIds.length === allModels.length &&\n\t\t\t\t\t\tenabledIds.every((id) => allModelIds.has(id));\n\t\t\t\t\tconst newPatterns = enabledIds === null || allEnabled ? undefined : 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\nasync function switchSession(\n\thost: SessionFlowHost,\n\tsessionPath: string,\n\toptions: Parameters<ExtensionCommandContext[\"switchSession\"]>[1] | undefined,\n\tcwdOverride?: string,\n): Promise<{ cancelled: boolean }> {\n\treturn host.runtimeHost.switchSession(sessionPath, {\n\t\tcwdOverride,\n\t\twithSession: options?.withSession,\n\t});\n}\n\nasync function offerRestoredGoalResume(host: SessionFlowHost): Promise<boolean> {\n\tconst state = host.session.getGoalStateSnapshot();\n\tif (!state || (state.status !== \"paused\" && state.status !== \"blocked\" && state.status !== \"usage_limited\")) {\n\t\thost.session.restoreGoalRuntimeAfterResume();\n\t\treturn false;\n\t}\n\tconst choice = await host.extensionUiHost?.showExtensionSelector(\"Resume stopped goal?\", [\n\t\t\"Resume goal\",\n\t\t\"Leave stopped\",\n\t]);\n\tif (choice !== \"Resume goal\") return false;\n\tconst resumed = resumePersistedGoal(host.session);\n\tif (!resumed.ok) throw new Error(`Goal resume failed: ${resumed.error}`);\n\thost.session.restoreGoalRuntimeAfterResume();\n\thost.refreshAutonomyFooterStatus();\n\treturn true;\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 switchSession(host, sessionPath, options);\n\t\tif (result.cancelled) {\n\t\t\treturn result;\n\t\t}\n\t\thost.renderCurrentSessionState();\n\t\tconst goalResumed = await offerRestoredGoalResume(host);\n\t\thost.showStatus(goalResumed ? \"Resumed session and goal\" : \"Resumed session; goal state preserved\");\n\t\treturn result;\n\t} catch (error: unknown) {\n\t\tconst disposition = handleNonFatalSessionReplacementError(host, error);\n\t\tif (disposition) return { cancelled: disposition === \"previous_restored\" };\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\ttry {\n\t\t\t\tconst result = await switchSession(host, sessionPath, options, selectedCwd);\n\t\t\t\tif (result.cancelled) {\n\t\t\t\t\treturn result;\n\t\t\t\t}\n\t\t\t\thost.renderCurrentSessionState();\n\t\t\t\tconst goalResumed = await offerRestoredGoalResume(host);\n\t\t\t\thost.showStatus(\n\t\t\t\t\tgoalResumed\n\t\t\t\t\t\t? \"Resumed session and goal in current cwd\"\n\t\t\t\t\t\t: \"Resumed session in current cwd; goal state preserved\",\n\t\t\t\t);\n\t\t\t\treturn result;\n\t\t\t} catch (retryError: unknown) {\n\t\t\t\tconst retryDisposition = handleNonFatalSessionReplacementError(host, retryError);\n\t\t\t\tif (retryDisposition) return { cancelled: retryDisposition === \"previous_restored\" };\n\t\t\t\treturn host.handleFatalRuntimeError(\"Failed to resume session\", retryError);\n\t\t\t}\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<Api> | 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 GoalResumeHost {\n\treadonly session: {\n\t\tgetGoalStateSnapshot: () => GoalState | undefined;\n\t\tsaveGoalStateSnapshot: (state: GoalState, expected?: GoalStateRevision) => string;\n\t\tclearGoalStateSnapshot?: (state: GoalState, now: string) => string;\n\t\trestoreGoalRuntimeAfterResume: () => void;\n\t};\n\trefreshAutonomyFooterStatus(): void;\n}\n\nexport interface GoalCommandHost extends GoalResumeHost {\n\treadonly session: GoalResumeHost[\"session\"] & {\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\tpromptForGoalEdit?(currentObjective: string): Promise<string | undefined>;\n\tgetMaxStallTurns?(): number;\n\tshowStatus(message: string): void;\n\tshowError(message: string): void;\n}\n\nexport type GoalResumeResult = { ok: true; resumed: true; state: GoalState } | { ok: false; error: string };\n\n/** Canonical persisted transition used by both `/goal resume` and session `/resume`. */\nexport function resumeCurrentGoal(host: GoalResumeHost, now = new Date().toISOString()): GoalResumeResult {\n\tconst resumed = resumePersistedGoal(host.session, now);\n\tif (!resumed.ok) return resumed;\n\thost.session.restoreGoalRuntimeAfterResume();\n\thost.refreshAutonomyFooterStatus();\n\treturn { ok: true, resumed: true, state: resumed.state };\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\tconst requirements = state.requirements.map((requirement) => {\n\t\tconst blockedReason = requirement.blockedReason ? ` — ${requirement.blockedReason}` : \"\";\n\t\treturn `- ${requirement.id}: ${requirement.status}${blockedReason}`;\n\t});\n\tconst blockedReason = state.blockedReason ? `\\nBlocked reason: ${state.blockedReason}` : \"\";\n\tconst requirementDetails = requirements.length > 0 ? `\\n${requirements.join(\"\\n\")}` : \"\";\n\tconst tokenUsage =\n\t\tstate.tokenBudget !== undefined\n\t\t\t? `\\nTokens: ${state.tokensUsed ?? 0}/${state.tokenBudget}`\n\t\t\t: (state.tokensUsed ?? 0) > 0\n\t\t\t\t? `\\nTokens: ${state.tokensUsed ?? 0}`\n\t\t\t\t: \"\";\n\treturn `Goal: ${state.userGoal}\\nStatus: ${state.status}${blockedReason}${tokenUsage}\\nRequirements: open ${snapshot.continuation.openRequirementIds.length}, blocked ${snapshot.continuation.blockedRequirementIds.length}, satisfied ${snapshot.continuation.satisfiedRequirementIds.length}${requirementDetails}\\nContinuation: ${snapshot.continuation.action}/${snapshot.continuation.reasonCode}\\nControls: /goal edit | /goal pause | /goal resume | /goal reopen <requirement-id> | /goal complete | /goal clear | /goal override <text>`;\n}\n\nexport async function handleGoalCommand(host: GoalCommandHost, text: string): Promise<void> {\n\tconst input = text.replace(/^\\/goal\\s*/, \"\").trim();\n\tif (!input || input === \"status\") {\n\t\thost.showStatus(\n\t\t\tformatGoalStatus(host.session.getGoalRuntimeSnapshot({ maxStallTurns: host.getMaxStallTurns?.() ?? 20 })),\n\t\t);\n\t\treturn;\n\t}\n\n\tconst now = new Date().toISOString();\n\tconst current = host.session.getGoalStateSnapshot();\n\tif (input === \"resume\") {\n\t\tconst resumed = resumeCurrentGoal(host, now);\n\t\tif (!resumed.ok) {\n\t\t\thost.showError(resumed.error);\n\t\t\treturn;\n\t\t}\n\t\thost.showStatus(\"Goal resumed.\");\n\t\treturn;\n\t}\n\n\tif (input === \"pause\") {\n\t\tconst paused = pausePersistedGoal(host.session, now);\n\t\tif (!paused.ok) {\n\t\t\thost.showError(paused.error);\n\t\t\treturn;\n\t\t}\n\t\thost.showStatus(\"Goal paused.\");\n\t\thost.refreshAutonomyFooterStatus();\n\t\treturn;\n\t}\n\n\tif (input === \"edit\" || input.startsWith(\"edit \")) {\n\t\tconst inlineObjective = input.slice(\"edit\".length).trim();\n\t\tconst objective = inlineObjective || (current ? await host.promptForGoalEdit?.(current.userGoal) : undefined);\n\t\tif (!objective) {\n\t\t\thost.showError(current ? \"Usage: /goal edit <objective>\" : \"No goal exists to edit.\");\n\t\t\treturn;\n\t\t}\n\t\tconst edited = editPersistedGoal(host.session, { userGoal: objective }, now);\n\t\tif (!edited.ok) {\n\t\t\thost.showError(edited.error);\n\t\t\treturn;\n\t\t}\n\t\tif (edited.state.status === \"active\") host.session.restoreGoalRuntimeAfterResume();\n\t\thost.showStatus(\"Goal updated.\");\n\t\thost.refreshAutonomyFooterStatus();\n\t\treturn;\n\t}\n\n\tif (input === \"complete\") {\n\t\tconst completed = completeGoalManually(current, now);\n\t\tif (!completed.ok) {\n\t\t\thost.showError(completed.error);\n\t\t\treturn;\n\t\t}\n\t\thost.session.saveGoalStateSnapshot(completed.state, current ? getGoalStateRevision(current) : undefined);\n\t\thost.showStatus(\"Goal completed manually.\");\n\t\thost.refreshAutonomyFooterStatus();\n\t\treturn;\n\t}\n\n\tif (input === \"clear\") {\n\t\tconst cleared = clearPersistedGoal(host.session, now);\n\t\tif (!cleared.ok) {\n\t\t\thost.showError(cleared.error);\n\t\t\treturn;\n\t\t}\n\t\thost.showStatus(cleared.cleared ? \"Goal cleared.\" : \"No goal exists to clear.\");\n\t\thost.refreshAutonomyFooterStatus();\n\t\treturn;\n\t}\n\n\tif (input === \"close\" || input === \"cancel\") {\n\t\tconst cancelled = cancelPersistedGoal(host.session, now);\n\t\tif (!cancelled.ok) {\n\t\t\thost.showError(cancelled.error);\n\t\t\treturn;\n\t\t}\n\t\thost.showStatus(\"Goal closed.\");\n\t\thost.refreshAutonomyFooterStatus();\n\t\treturn;\n\t}\n\n\tif (input === \"reopen\" || input.startsWith(\"reopen \")) {\n\t\tconst requirementId = input.slice(\"reopen\".length).trim();\n\t\tif (!requirementId) {\n\t\t\thost.showError(\"Usage: /goal reopen <requirement-id>\");\n\t\t\treturn;\n\t\t}\n\t\tif (!current) {\n\t\t\thost.showError(\"No goal exists to update.\");\n\t\t\treturn;\n\t\t}\n\t\tconst requirement = current.requirements.find((candidate) => candidate.id === requirementId);\n\t\tif (!requirement || requirement.status !== \"blocked\") {\n\t\t\thost.showError(\n\t\t\t\trequirement\n\t\t\t\t\t? `Requirement '${requirementId}' is ${requirement.status}; only blocked requirements can be reopened.`\n\t\t\t\t\t: `Unknown requirement '${requirementId}'.`,\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tlet active = current;\n\t\tif (active.status === \"blocked\") {\n\t\t\tconst resumed = resumeGoal(active, now);\n\t\t\tif (!resumed.ok) {\n\t\t\t\thost.showError(resumed.error);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tactive = resumed.state;\n\t\t}\n\t\tconst reopened = applyGoalAction(active, { action: \"reopen_requirement\", requirementId }, now);\n\t\tif (!reopened.ok) {\n\t\t\thost.showError(reopened.error);\n\t\t\treturn;\n\t\t}\n\t\thost.session.saveGoalStateSnapshot(reopened.state, getGoalStateRevision(current));\n\t\tif (reopened.state.status === \"active\") host.session.restoreGoalRuntimeAfterResume();\n\t\thost.showStatus(\n\t\t\t`Requirement '${requirementId}' reopened${current.status === \"blocked\" ? \" and goal resumed\" : \"\"}.`,\n\t\t);\n\t\thost.refreshAutonomyFooterStatus();\n\t\treturn;\n\t}\n\n\tconst overriding = input === \"override\" || input.startsWith(\"override \");\n\tconst goalText = overriding ? input.slice(\"override\".length).trim() : input;\n\tif (!goalText) {\n\t\thost.showError(\"Usage: /goal override <text>\");\n\t\treturn;\n\t}\n\tconst goalId = `goal-${randomUUID()}`;\n\tconst started = overriding\n\t\t? replaceGoal({ goalId, userGoal: goalText }, now)\n\t\t: applyGoalAction(current, { action: \"start\", goalId, userGoal: goalText }, now);\n\tif (!started.ok) {\n\t\thost.showError(`${started.error} Use /goal override <text> to replace it explicitly.`);\n\t\treturn;\n\t}\n\thost.session.saveGoalStateSnapshot(started.state, current ? getGoalStateRevision(current) : undefined);\n\tconst verb = overriding ? \"overridden\" : \"started\";\n\ttry {\n\t\t// Submit one bootstrap pass, then yield to the event-driven idle scheduler. This is a scheduling\n\t\t// quantum, not a goal ceiling: an active goal is immediately rearmed and the configured goal turn\n\t\t// limit (unbounded by default) governs subsequent continuation.\n\t\tconst result = await host.session.continueGoalLoop({\n\t\t\tmaxTurns: 1,\n\t\t\tmaxStallTurns: host.getMaxStallTurns?.() ?? 20,\n\t\t\tmaxWallClockMinutes: 0,\n\t\t});\n\t\tif (result.stopReason === \"already_continuing\") {\n\t\t\thost.showStatus(`Goal ${verb}: the autonomy loop is already continuing this goal.`);\n\t\t} else if (result.stopReason === \"session_disposed\") {\n\t\t\thost.showStatus(`Goal ${verb}, but the session was disposed before continuation could run.`);\n\t\t} else {\n\t\t\tconst continuation = result.finalSnapshot.continuation;\n\t\t\thost.showStatus(`Goal ${verb}: ${continuation.action}/${continuation.reasonCode}.`);\n\t\t\tif (continuation.action === \"continue\") host.session.restoreGoalRuntimeAfterResume();\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 TaskCommandHost {\n\treadonly session: {\n\t\tgetTaskStepsStateSnapshot: () => TaskStepsState | undefined;\n\t\tsaveTaskStepsStateSnapshot: (state: TaskStepsState) => string;\n\t};\n\tshowStatus(message: string): void;\n\tshowError(message: string): void;\n}\n\nexport function handleTaskCommand(host: TaskCommandHost, text: string): void {\n\tconst parsed = parseTaskCommand(text);\n\tif (!parsed.ok) {\n\t\thost.showError(parsed.error);\n\t\treturn;\n\t}\n\tif (parsed.command.type === \"retired_execution\") {\n\t\thost.showStatus(\n\t\t\t`/task ${parsed.command.operation} was retired with the detached extension runner. Ask Pi to use native delegate/delegate_status; session-owned worker lanes notify on completion without polling.`,\n\t\t);\n\t\treturn;\n\t}\n\n\tconst now = new Date().toISOString();\n\tlet state = host.session.getTaskStepsStateSnapshot() ?? createTaskStepsState(now);\n\ttry {\n\t\tswitch (parsed.command.type) {\n\t\t\tcase \"list\":\n\t\t\t\thost.showStatus(formatTaskSteps(state, { includeTerminal: parsed.command.includeTerminal }));\n\t\t\t\treturn;\n\t\t\tcase \"add\":\n\t\t\t\tstate = addTaskStep(state, { content: parsed.command.content }, now);\n\t\t\t\tbreak;\n\t\t\tcase \"update\":\n\t\t\t\tstate = updateTaskStep(\n\t\t\t\t\tstate,\n\t\t\t\t\tparsed.command.selector,\n\t\t\t\t\t{\n\t\t\t\t\t\tstatus: parsed.command.status,\n\t\t\t\t\t\tnote: parsed.command.note,\n\t\t\t\t\t\tevidence: parsed.command.evidence ? [parsed.command.evidence] : undefined,\n\t\t\t\t\t},\n\t\t\t\t\tnow,\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\tcase \"clear\":\n\t\t\t\tstate = clearTaskSteps(state, now);\n\t\t\t\tbreak;\n\t\t\tcase \"compact\":\n\t\t\t\tstate = compactTaskSteps(state, now);\n\t\t\t\tbreak;\n\t\t}\n\t\thost.session.saveTaskStepsStateSnapshot(state);\n\t\thost.showStatus(formatTaskSteps(state));\n\t} catch (error) {\n\t\thost.showError(error instanceof Error ? error.message : String(error));\n\t}\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: ${parsed.maxTurns === 0 ? \"unbounded turns\" : `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"]}
|