@caupulican/pi-adaptative 0.80.102 → 0.81.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +131 -0
- package/dist/cli/session-picker.d.ts +1 -1
- package/dist/cli/session-picker.d.ts.map +1 -1
- package/dist/cli/session-picker.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +7 -1
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +11 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +17 -3
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts +1 -1
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +6 -6
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session-services.d.ts +1 -1
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +152 -512
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +635 -4590
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/autonomy/session-lane-record.d.ts +1 -1
- package/dist/core/autonomy/session-lane-record.d.ts.map +1 -1
- package/dist/core/autonomy/session-lane-record.js.map +1 -1
- package/dist/core/autonomy/status.d.ts +1 -0
- package/dist/core/autonomy/status.d.ts.map +1 -1
- package/dist/core/autonomy/status.js +1 -0
- package/dist/core/autonomy/status.js.map +1 -1
- package/dist/core/autonomy-telemetry.d.ts +80 -0
- package/dist/core/autonomy-telemetry.d.ts.map +1 -0
- package/dist/core/autonomy-telemetry.js +266 -0
- package/dist/core/autonomy-telemetry.js.map +1 -0
- package/dist/core/background-lane-controller.d.ts +186 -0
- package/dist/core/background-lane-controller.d.ts.map +1 -0
- package/dist/core/background-lane-controller.js +691 -0
- package/dist/core/background-lane-controller.js.map +1 -0
- package/dist/core/bash-execution-controller.d.ts +51 -0
- package/dist/core/bash-execution-controller.d.ts.map +1 -0
- package/dist/core/bash-execution-controller.js +96 -0
- package/dist/core/bash-execution-controller.js.map +1 -0
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js +9 -2
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/compaction-support.d.ts +56 -0
- package/dist/core/compaction-support.d.ts.map +1 -0
- package/dist/core/compaction-support.js +99 -0
- package/dist/core/compaction-support.js.map +1 -0
- package/dist/core/context/artifact-retrieval.d.ts +1 -1
- package/dist/core/context/artifact-retrieval.d.ts.map +1 -1
- package/dist/core/context/artifact-retrieval.js +1 -1
- package/dist/core/context/artifact-retrieval.js.map +1 -1
- package/dist/core/context/context-composition.d.ts.map +1 -1
- package/dist/core/context/context-composition.js +1 -1
- package/dist/core/context/context-composition.js.map +1 -1
- package/dist/core/context/tool-output-packer.d.ts +1 -1
- package/dist/core/context/tool-output-packer.d.ts.map +1 -1
- package/dist/core/context/tool-output-packer.js +1 -1
- package/dist/core/context/tool-output-packer.js.map +1 -1
- package/dist/core/context-gc.d.ts.map +1 -1
- package/dist/core/context-gc.js +1 -1
- package/dist/core/context-gc.js.map +1 -1
- package/dist/core/context-pipeline.d.ts +223 -0
- package/dist/core/context-pipeline.d.ts.map +1 -0
- package/dist/core/context-pipeline.js +594 -0
- package/dist/core/context-pipeline.js.map +1 -0
- package/dist/core/cost/daily-usage.d.ts +1 -1
- package/dist/core/cost/daily-usage.d.ts.map +1 -1
- package/dist/core/cost/daily-usage.js +1 -1
- package/dist/core/cost/daily-usage.js.map +1 -1
- package/dist/core/cost/session-usage.d.ts +1 -1
- package/dist/core/cost/session-usage.d.ts.map +1 -1
- package/dist/core/cost/session-usage.js +1 -1
- package/dist/core/cost/session-usage.js.map +1 -1
- package/dist/core/delegation/session-worker-result.d.ts +1 -1
- package/dist/core/delegation/session-worker-result.d.ts.map +1 -1
- package/dist/core/delegation/session-worker-result.js.map +1 -1
- package/dist/core/exec.d.ts +2 -0
- package/dist/core/exec.d.ts.map +1 -1
- package/dist/core/exec.js +15 -9
- package/dist/core/exec.js.map +1 -1
- package/dist/core/export-html/index.d.ts +1 -1
- package/dist/core/export-html/index.d.ts.map +1 -1
- package/dist/core/export-html/index.js +2 -2
- package/dist/core/export-html/index.js.map +1 -1
- package/dist/core/extensions/builtin.d.ts.map +1 -1
- package/dist/core/extensions/builtin.js +2 -2
- package/dist/core/extensions/builtin.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +1 -1
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +2 -4
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/goal-loop-controller.d.ts +24 -0
- package/dist/core/goal-loop-controller.d.ts.map +1 -0
- package/dist/core/goal-loop-controller.js +83 -0
- package/dist/core/goal-loop-controller.js.map +1 -0
- package/dist/core/goals/goal-runtime-snapshot.d.ts +1 -1
- package/dist/core/goals/goal-runtime-snapshot.d.ts.map +1 -1
- package/dist/core/goals/goal-runtime-snapshot.js.map +1 -1
- package/dist/core/goals/session-goal-state.d.ts +1 -1
- package/dist/core/goals/session-goal-state.d.ts.map +1 -1
- package/dist/core/goals/session-goal-state.js.map +1 -1
- package/dist/core/index.d.ts +1 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/learning/learning-audit.d.ts +1 -1
- package/dist/core/learning/learning-audit.d.ts.map +1 -1
- package/dist/core/learning/learning-audit.js.map +1 -1
- package/dist/core/learning/session-learning-decision.d.ts +1 -1
- package/dist/core/learning/session-learning-decision.d.ts.map +1 -1
- package/dist/core/learning/session-learning-decision.js.map +1 -1
- package/dist/core/local-runtime-controller.d.ts +99 -0
- package/dist/core/local-runtime-controller.d.ts.map +1 -0
- package/dist/core/local-runtime-controller.js +214 -0
- package/dist/core/local-runtime-controller.js.map +1 -0
- package/dist/core/memory/providers/transcript-recall.d.ts.map +1 -1
- package/dist/core/memory/providers/transcript-recall.js +1 -1
- package/dist/core/memory/providers/transcript-recall.js.map +1 -1
- package/dist/core/memory-controller.d.ts +139 -0
- package/dist/core/memory-controller.d.ts.map +1 -0
- package/dist/core/memory-controller.js +323 -0
- package/dist/core/memory-controller.js.map +1 -0
- package/dist/core/model-router/status.d.ts +1 -1
- package/dist/core/model-router/status.d.ts.map +1 -1
- package/dist/core/model-router/status.js.map +1 -1
- package/dist/core/model-router-controller.d.ts +140 -0
- package/dist/core/model-router-controller.d.ts.map +1 -0
- package/dist/core/model-router-controller.js +623 -0
- package/dist/core/model-router-controller.js.map +1 -0
- package/dist/core/model-selection-controller.d.ts +95 -0
- package/dist/core/model-selection-controller.d.ts.map +1 -0
- package/dist/core/model-selection-controller.js +252 -0
- package/dist/core/model-selection-controller.js.map +1 -0
- package/dist/core/models/model-ref.d.ts +13 -0
- package/dist/core/models/model-ref.d.ts.map +1 -1
- package/dist/core/models/model-ref.js +22 -0
- package/dist/core/models/model-ref.js.map +1 -1
- package/dist/core/profile-filter-controller.d.ts +77 -0
- package/dist/core/profile-filter-controller.d.ts.map +1 -0
- package/dist/core/profile-filter-controller.js +159 -0
- package/dist/core/profile-filter-controller.js.map +1 -0
- package/dist/core/reflection-controller.d.ts +111 -0
- package/dist/core/reflection-controller.d.ts.map +1 -0
- package/dist/core/reflection-controller.js +412 -0
- package/dist/core/reflection-controller.js.map +1 -0
- package/dist/core/research/model-fitness.d.ts +12 -0
- package/dist/core/research/model-fitness.d.ts.map +1 -1
- package/dist/core/research/model-fitness.js +21 -0
- package/dist/core/research/model-fitness.js.map +1 -1
- package/dist/core/research/session-evidence-bundle.d.ts +1 -1
- package/dist/core/research/session-evidence-bundle.d.ts.map +1 -1
- package/dist/core/research/session-evidence-bundle.js.map +1 -1
- package/dist/core/runtime-builder.d.ts +222 -0
- package/dist/core/runtime-builder.d.ts.map +1 -0
- package/dist/core/runtime-builder.js +640 -0
- package/dist/core/runtime-builder.js.map +1 -0
- package/dist/core/sdk.d.ts +2 -2
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +3 -4
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-analytics.d.ts +96 -0
- package/dist/core/session-analytics.d.ts.map +1 -0
- package/dist/core/session-analytics.js +331 -0
- package/dist/core/session-analytics.js.map +1 -0
- package/dist/core/session-manager-factory.d.ts +18 -0
- package/dist/core/session-manager-factory.d.ts.map +1 -0
- package/dist/core/session-manager-factory.js +32 -0
- package/dist/core/session-manager-factory.js.map +1 -0
- package/dist/core/session-tree-navigator.d.ts +68 -0
- package/dist/core/session-tree-navigator.d.ts.map +1 -0
- package/dist/core/session-tree-navigator.js +217 -0
- package/dist/core/session-tree-navigator.js.map +1 -0
- package/dist/core/system-prompt-builder.d.ts +63 -0
- package/dist/core/system-prompt-builder.d.ts.map +1 -0
- package/dist/core/system-prompt-builder.js +181 -0
- package/dist/core/system-prompt-builder.js.map +1 -0
- package/dist/core/tool-gate-controller.d.ts +36 -0
- package/dist/core/tool-gate-controller.d.ts.map +1 -0
- package/dist/core/tool-gate-controller.js +94 -0
- package/dist/core/tool-gate-controller.js.map +1 -0
- package/dist/core/tools/artifact-retrieve.d.ts.map +1 -1
- package/dist/core/tools/artifact-retrieve.js +1 -1
- package/dist/core/tools/artifact-retrieve.js.map +1 -1
- package/dist/core/tools/bash.d.ts +4 -2
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +49 -7
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/file-mutation-queue.d.ts +6 -0
- package/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
- package/dist/core/tools/file-mutation-queue.js +61 -1
- package/dist/core/tools/file-mutation-queue.js.map +1 -1
- package/dist/core/tools/find.d.ts +1 -1
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +1 -1
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/grep.d.ts +1 -1
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +1 -1
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/index.d.ts +1 -1
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +1 -1
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/ls.d.ts +1 -1
- package/dist/core/tools/ls.d.ts.map +1 -1
- package/dist/core/tools/ls.js +1 -1
- package/dist/core/tools/ls.js.map +1 -1
- package/dist/core/tools/output-accumulator.d.ts +1 -1
- package/dist/core/tools/output-accumulator.d.ts.map +1 -1
- package/dist/core/tools/output-accumulator.js +1 -1
- package/dist/core/tools/output-accumulator.js.map +1 -1
- package/dist/core/tools/read.d.ts +1 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +1 -1
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/render-utils.d.ts.map +1 -1
- package/dist/core/tools/render-utils.js +1 -1
- package/dist/core/tools/render-utils.js.map +1 -1
- package/dist/index.d.ts +2 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -4
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +13 -12
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/auth-dialogs-controller.d.ts +59 -0
- package/dist/modes/interactive/auth-dialogs-controller.d.ts.map +1 -0
- package/dist/modes/interactive/auth-dialogs-controller.js +398 -0
- package/dist/modes/interactive/auth-dialogs-controller.js.map +1 -0
- package/dist/modes/interactive/auto-learn-controller.d.ts +168 -0
- package/dist/modes/interactive/auto-learn-controller.d.ts.map +1 -0
- package/dist/modes/interactive/auto-learn-controller.js +1239 -0
- package/dist/modes/interactive/auto-learn-controller.js.map +1 -0
- package/dist/modes/interactive/autocomplete-provider.d.ts +26 -0
- package/dist/modes/interactive/autocomplete-provider.d.ts.map +1 -0
- package/dist/modes/interactive/autocomplete-provider.js +103 -0
- package/dist/modes/interactive/autocomplete-provider.js.map +1 -0
- package/dist/modes/interactive/autonomy-commands.d.ts +38 -0
- package/dist/modes/interactive/autonomy-commands.d.ts.map +1 -0
- package/dist/modes/interactive/autonomy-commands.js +142 -0
- package/dist/modes/interactive/autonomy-commands.js.map +1 -0
- package/dist/modes/interactive/clipboard-input.d.ts +37 -0
- package/dist/modes/interactive/clipboard-input.d.ts.map +1 -0
- package/dist/modes/interactive/clipboard-input.js +59 -0
- package/dist/modes/interactive/clipboard-input.js.map +1 -0
- package/dist/modes/interactive/compaction-queue.d.ts +30 -0
- package/dist/modes/interactive/compaction-queue.d.ts.map +1 -0
- package/dist/modes/interactive/compaction-queue.js +91 -0
- package/dist/modes/interactive/compaction-queue.js.map +1 -0
- package/dist/modes/interactive/components/bash-execution.d.ts +1 -1
- package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/bash-execution.js +1 -1
- package/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.d.ts +1 -1
- package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.d.ts +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/custom-message.d.ts +1 -1
- package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-message.js.map +1 -1
- package/dist/modes/interactive/components/session-selector-search.d.ts +1 -1
- package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +2 -2
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/tree-selector.d.ts +1 -1
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-selector.js.map +1 -1
- package/dist/modes/interactive/config-backup.d.ts +27 -0
- package/dist/modes/interactive/config-backup.d.ts.map +1 -0
- package/dist/modes/interactive/config-backup.js +146 -0
- package/dist/modes/interactive/config-backup.js.map +1 -0
- package/dist/modes/interactive/editor-overlay-host.d.ts +48 -0
- package/dist/modes/interactive/editor-overlay-host.d.ts.map +1 -0
- package/dist/modes/interactive/editor-overlay-host.js +43 -0
- package/dist/modes/interactive/editor-overlay-host.js.map +1 -0
- package/dist/modes/interactive/extension-ui-host.d.ts +165 -0
- package/dist/modes/interactive/extension-ui-host.d.ts.map +1 -0
- package/dist/modes/interactive/extension-ui-host.js +610 -0
- package/dist/modes/interactive/extension-ui-host.js.map +1 -0
- package/dist/modes/interactive/external-editor.d.ts +18 -0
- package/dist/modes/interactive/external-editor.d.ts.map +1 -0
- package/dist/modes/interactive/external-editor.js +107 -0
- package/dist/modes/interactive/external-editor.js.map +1 -0
- package/dist/modes/interactive/history-reload-math.d.ts +24 -0
- package/dist/modes/interactive/history-reload-math.d.ts.map +1 -0
- package/dist/modes/interactive/history-reload-math.js +129 -0
- package/dist/modes/interactive/history-reload-math.js.map +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts +22 -238
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +714 -5910
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/key-handlers.d.ts +46 -0
- package/dist/modes/interactive/key-handlers.d.ts.map +1 -0
- package/dist/modes/interactive/key-handlers.js +80 -0
- package/dist/modes/interactive/key-handlers.js.map +1 -0
- package/dist/modes/interactive/local-model-commands.d.ts +68 -0
- package/dist/modes/interactive/local-model-commands.d.ts.map +1 -0
- package/dist/modes/interactive/local-model-commands.js +288 -0
- package/dist/modes/interactive/local-model-commands.js.map +1 -0
- package/dist/modes/interactive/profile-menu-controller.d.ts +77 -0
- package/dist/modes/interactive/profile-menu-controller.d.ts.map +1 -0
- package/dist/modes/interactive/profile-menu-controller.js +917 -0
- package/dist/modes/interactive/profile-menu-controller.js.map +1 -0
- package/dist/modes/interactive/report-commands.d.ts +46 -0
- package/dist/modes/interactive/report-commands.d.ts.map +1 -0
- package/dist/modes/interactive/report-commands.js +255 -0
- package/dist/modes/interactive/report-commands.js.map +1 -0
- package/dist/modes/interactive/resource-display.d.ts +73 -0
- package/dist/modes/interactive/resource-display.d.ts.map +1 -0
- package/dist/modes/interactive/resource-display.js +278 -0
- package/dist/modes/interactive/resource-display.js.map +1 -0
- package/dist/modes/interactive/resource-shell-commands.d.ts +64 -0
- package/dist/modes/interactive/resource-shell-commands.d.ts.map +1 -0
- package/dist/modes/interactive/resource-shell-commands.js +202 -0
- package/dist/modes/interactive/resource-shell-commands.js.map +1 -0
- package/dist/modes/interactive/session-flow-commands.d.ts +139 -0
- package/dist/modes/interactive/session-flow-commands.d.ts.map +1 -0
- package/dist/modes/interactive/session-flow-commands.js +458 -0
- package/dist/modes/interactive/session-flow-commands.js.map +1 -0
- package/dist/modes/interactive/session-io-commands.d.ts +73 -0
- package/dist/modes/interactive/session-io-commands.d.ts.map +1 -0
- package/dist/modes/interactive/session-io-commands.js +202 -0
- package/dist/modes/interactive/session-io-commands.js.map +1 -0
- package/dist/modes/interactive/settings-selector-flow.d.ts +42 -0
- package/dist/modes/interactive/settings-selector-flow.d.ts.map +1 -0
- package/dist/modes/interactive/settings-selector-flow.js +287 -0
- package/dist/modes/interactive/settings-selector-flow.js.map +1 -0
- package/dist/modes/interactive/signal-lifecycle.d.ts +55 -0
- package/dist/modes/interactive/signal-lifecycle.d.ts.map +1 -0
- package/dist/modes/interactive/signal-lifecycle.js +177 -0
- package/dist/modes/interactive/signal-lifecycle.js.map +1 -0
- package/dist/modes/interactive/startup-checks.d.ts +38 -0
- package/dist/modes/interactive/startup-checks.d.ts.map +1 -0
- package/dist/modes/interactive/startup-checks.js +189 -0
- package/dist/modes/interactive/startup-checks.js.map +1 -0
- package/dist/modes/rpc/rpc-client.d.ts +1 -1
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +1 -1
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/utils/paths.d.ts +2 -14
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js +5 -30
- package/dist/utils/paths.js.map +1 -1
- package/dist/utils/process-memory.d.ts +8 -0
- package/dist/utils/process-memory.d.ts.map +1 -0
- package/dist/utils/process-memory.js +11 -0
- package/dist/utils/process-memory.js.map +1 -0
- package/dist/utils/shell.d.ts +0 -9
- package/dist/utils/shell.d.ts.map +1 -1
- package/dist/utils/shell.js +0 -37
- package/dist/utils/shell.js.map +1 -1
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/examples/sdk/11-sessions.ts +8 -8
- package/examples/sdk/13-session-runtime.ts +1 -1
- package/npm-shrinkwrap.json +12 -12
- package/package.json +4 -4
- package/dist/core/compaction/branch-summarization.d.ts +0 -88
- package/dist/core/compaction/branch-summarization.d.ts.map +0 -1
- package/dist/core/compaction/branch-summarization.js +0 -243
- package/dist/core/compaction/branch-summarization.js.map +0 -1
- package/dist/core/compaction/compaction.d.ts +0 -143
- package/dist/core/compaction/compaction.d.ts.map +0 -1
- package/dist/core/compaction/compaction.js +0 -659
- package/dist/core/compaction/compaction.js.map +0 -1
- package/dist/core/compaction/index.d.ts +0 -7
- package/dist/core/compaction/index.d.ts.map +0 -1
- package/dist/core/compaction/index.js +0 -7
- package/dist/core/compaction/index.js.map +0 -1
- package/dist/core/compaction/utils.d.ts +0 -38
- package/dist/core/compaction/utils.d.ts.map +0 -1
- package/dist/core/compaction/utils.js +0 -153
- package/dist/core/compaction/utils.js.map +0 -1
- package/dist/core/message-retention.d.ts +0 -26
- package/dist/core/message-retention.d.ts.map +0 -1
- package/dist/core/message-retention.js +0 -95
- package/dist/core/message-retention.js.map +0 -1
- package/dist/core/messages.d.ts +0 -77
- package/dist/core/messages.d.ts.map +0 -1
- package/dist/core/messages.js +0 -123
- package/dist/core/messages.js.map +0 -1
- package/dist/core/session-manager.d.ts +0 -337
- package/dist/core/session-manager.d.ts.map +0 -1
- package/dist/core/session-manager.js +0 -1328
- package/dist/core/session-manager.js.map +0 -1
- package/dist/core/tools/truncate.d.ts +0 -70
- package/dist/core/tools/truncate.d.ts.map +0 -1
- package/dist/core/tools/truncate.js +0 -215
- package/dist/core/tools/truncate.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"settings-selector-flow.js","sourceRoot":"","sources":["../../../src/modes/interactive/settings-selector-flow.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `/settings` selector flow extracted from interactive-mode.\n *\n * Builds the SettingsSelectorComponent model from the current settings/session\n * state and wires its change callbacks back through a `SettingsSelectorHost`\n * seam. Self-mod/auto-learn validation, autonomy-preset application, autocomplete\n * rebuild, and the resources-hub hand-off stay host-side (shared with other\n * flows); interactive-mode keeps a thin wrapper building the host once.\n */\n\nimport type { Component, Container, EditorComponent, SelectItem, TUI } from \"@caupulican/pi-tui\";\nimport type { AgentSession } from \"../../core/agent-session.ts\";\nimport { configureHttpDispatcher, formatHttpIdleTimeoutMs } from \"../../core/http-dispatcher.ts\";\nimport type {\n\tAutonomyMode,\n\tSelfModificationSettings,\n\tSettingsManager,\n\tSettingsScope,\n} from \"../../core/settings-manager.ts\";\nimport { AssistantMessageComponent } from \"./components/assistant-message.ts\";\nimport type { CustomEditor } from \"./components/custom-editor.ts\";\nimport type { FooterComponent } from \"./components/footer.ts\";\nimport { SettingsSelectorComponent } from \"./components/settings-selector.ts\";\nimport { ToolExecutionComponent } from \"./components/tool-execution.ts\";\nimport { ToolGroupComponent } from \"./components/tool-group.ts\";\nimport { getAvailableThemes, setTheme } from \"./theme/theme.ts\";\n\nexport interface SettingsSelectorHost {\n\treadonly session: AgentSession;\n\treadonly settingsManager: SettingsManager;\n\treadonly footer: FooterComponent;\n\treadonly chatContainer: Container;\n\treadonly ui: TUI;\n\treadonly defaultEditor: CustomEditor;\n\treadonly editor: EditorComponent;\n\thideThinkingBlock: boolean;\n\tshowSelector(create: (done: () => void) => { component: Component; focus: Component }): void;\n\tshowStatus(message: string): void;\n\tshowWarning(message: string): void;\n\tshowError(message: string): void;\n\tgetAutoLearnModelOptions(): SelectItem[];\n\tsetupAutocompleteProvider(): void;\n\tupdateEditorBorderColor(): void;\n\trebuildChatFromMessages(): Promise<void>;\n\tvalidateSelfModificationSource(settings: SelfModificationSettings): string | undefined;\n\tapplyAutonomyMode(mode: AutonomyMode, scope?: SettingsScope): void;\n\tvalidateAutoLearnModelValue(value: string | undefined): string | undefined;\n\tupdateAutoLearnFooter(): void;\n\thandleResourcesHubAction(action: string): Promise<void>;\n}\n\nexport function showSettingsSelector(host: SettingsSelectorHost): void {\n\thost.showSelector((done) => {\n\t\tconst projectSettings = host.settingsManager.getProjectSettings();\n\t\tconst profileOptions = [\n\t\t\t{\n\t\t\t\tvalue: \"(none)\",\n\t\t\t\tlabel: \"(none)\",\n\t\t\t\tdescription: \"Use configured profile selection (session default)\",\n\t\t\t},\n\t\t\t...host.settingsManager\n\t\t\t\t.getProfileRegistry()\n\t\t\t\t.listProfiles()\n\t\t\t\t.map((profile) => ({\n\t\t\t\t\tvalue: profile.name,\n\t\t\t\t\tlabel: profile.name,\n\t\t\t\t\tdescription: profile.description ?? profile.source,\n\t\t\t\t})),\n\t\t];\n\t\tconst selector = new SettingsSelectorComponent(\n\t\t\t{\n\t\t\t\tautoCompact: host.session.autoCompactionEnabled,\n\t\t\t\tshowImages: host.settingsManager.getShowImages(),\n\t\t\t\timageWidthCells: host.settingsManager.getImageWidthCells(),\n\t\t\t\tautoResizeImages: host.settingsManager.getImageAutoResize(),\n\t\t\t\tblockImages: host.settingsManager.getBlockImages(),\n\t\t\t\tenableSkillCommands: host.settingsManager.getEnableSkillCommands(),\n\t\t\t\tsteeringMode: host.session.steeringMode,\n\t\t\t\tfollowUpMode: host.session.followUpMode,\n\t\t\t\ttransport: host.settingsManager.getTransport(),\n\t\t\t\thttpIdleTimeoutMs: host.settingsManager.getHttpIdleTimeoutMs(),\n\t\t\t\tthinkingLevel: host.session.thinkingLevel,\n\t\t\t\tavailableThinkingLevels: host.session.getAvailableThinkingLevels(),\n\t\t\t\tcurrentTheme: host.settingsManager.getTheme() || \"dark\",\n\t\t\t\t// The picker offers only themes the active profile permits (no-bypass). The theme\n\t\t\t\t// registry/renderer keeps the full set, so an already-applied theme still renders\n\t\t\t\t// even if the profile would block re-selecting it.\n\t\t\t\tavailableThemes: getAvailableThemes().filter((name) =>\n\t\t\t\t\thost.settingsManager.isResourceAllowedByProfile(\"themes\", name),\n\t\t\t\t),\n\t\t\t\thideThinkingBlock: host.hideThinkingBlock,\n\t\t\t\tcollapseChangelog: host.settingsManager.getCollapseChangelog(),\n\t\t\t\tenableInstallTelemetry: host.settingsManager.getEnableInstallTelemetry(),\n\t\t\t\tdoubleEscapeAction: host.settingsManager.getDoubleEscapeAction(),\n\t\t\t\ttreeFilterMode: host.settingsManager.getTreeFilterMode(),\n\t\t\t\tshowHardwareCursor: host.settingsManager.getShowHardwareCursor(),\n\t\t\t\teditorPaddingX: host.settingsManager.getEditorPaddingX(),\n\t\t\t\tautocompleteMaxVisible: host.settingsManager.getAutocompleteMaxVisible(),\n\t\t\t\tquietStartup: host.settingsManager.getQuietStartup(),\n\t\t\t\tclearOnShrink: host.settingsManager.getClearOnShrink(),\n\t\t\t\tshowTerminalProgress: host.settingsManager.getShowTerminalProgress(),\n\t\t\t\twarnings: host.settingsManager.getWarnings(),\n\t\t\t\tselfModification: host.settingsManager.getSelfModificationSettings(),\n\t\t\t\tselfModificationScope: projectSettings.selfModification ? \"project\" : \"global\",\n\t\t\t\tautonomy: host.settingsManager.getAutonomySettings(),\n\t\t\t\tautonomyScope: projectSettings.autonomy ? \"project\" : \"global\",\n\t\t\t\tresearchLane: host.settingsManager.getResearchLaneSettings(),\n\t\t\t\tresearchLaneScope: projectSettings.researchLane ? \"project\" : \"global\",\n\t\t\t\tworkerDelegation: host.settingsManager.getWorkerDelegationSettings(),\n\t\t\t\tworkerDelegationScope: projectSettings.workerDelegation ? \"project\" : \"global\",\n\t\t\t\tcontextCuration: host.settingsManager.getContextCurationSettings(),\n\t\t\t\tcontextCurationScope: projectSettings.contextPolicy?.curation ? \"project\" : \"global\",\n\t\t\t\tlearningPolicy: host.settingsManager.getLearningPolicySettings(),\n\t\t\t\tlearningPolicyScope: projectSettings.learningPolicy ? \"project\" : \"global\",\n\t\t\t\tmodelCapability: host.settingsManager.getModelCapabilitySettings(),\n\t\t\t\tmodelCapabilityScope: projectSettings.modelCapability ? \"project\" : \"global\",\n\t\t\t\tmodelRouter: host.settingsManager.getModelRouterSettings(),\n\t\t\t\tmodelRouterScope: projectSettings.modelRouter ? \"project\" : \"global\",\n\t\t\t\tautoLearn: host.settingsManager.getAutoLearnSettings(),\n\t\t\t\tautoLearnScope: projectSettings.autoLearn ? \"project\" : \"global\",\n\t\t\t\tautoLearnModelOptions: host.getAutoLearnModelOptions(),\n\t\t\t\tcontextPolicyEnforcement: host.settingsManager.getContextPromptEnforcementSettings(),\n\t\t\t\tcontextPolicyEnforcementScope: projectSettings.contextPolicy?.enforcement ? \"project\" : \"global\",\n\t\t\t\tcontextMemoryRetrieval: host.settingsManager.getMemoryRetrievalSettings(),\n\t\t\t\tcontextMemoryRetrievalScope: projectSettings.contextPolicy?.memory ? \"project\" : \"global\",\n\t\t\t\tcurrentModelPattern: host.session.model\n\t\t\t\t\t? `${host.session.model.provider}/${host.session.model.id}`\n\t\t\t\t\t: undefined,\n\t\t\t\tactiveProfileName: host.settingsManager.getActiveResourceProfileNames()[0],\n\t\t\t\tprofileOptions,\n\t\t\t\texternalResourceRoots: host.settingsManager.getExternalResourceRoots(),\n\t\t\t\ttrustedResourceRoots: host.settingsManager.getTrustedResourceRoots(),\n\t\t\t},\n\t\t\t{\n\t\t\t\tonAutoCompactChange: (enabled) => {\n\t\t\t\t\thost.session.setAutoCompactionEnabled(enabled);\n\t\t\t\t\thost.footer.setAutoCompactEnabled(enabled);\n\t\t\t\t},\n\t\t\t\tonShowImagesChange: (enabled) => {\n\t\t\t\t\thost.settingsManager.setShowImages(enabled);\n\t\t\t\t\tfor (const child of host.chatContainer.children) {\n\t\t\t\t\t\tif (child instanceof ToolExecutionComponent || child instanceof ToolGroupComponent) {\n\t\t\t\t\t\t\tchild.setShowImages(enabled);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\thost.ui.requestRender();\n\t\t\t\t},\n\t\t\t\tonImageWidthCellsChange: (width) => {\n\t\t\t\t\thost.settingsManager.setImageWidthCells(width);\n\t\t\t\t\tfor (const child of host.chatContainer.children) {\n\t\t\t\t\t\tif (child instanceof ToolExecutionComponent || child instanceof ToolGroupComponent) {\n\t\t\t\t\t\t\tchild.setImageWidthCells(width);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\thost.ui.requestRender();\n\t\t\t\t},\n\t\t\t\tonAutoResizeImagesChange: (enabled) => {\n\t\t\t\t\thost.settingsManager.setImageAutoResize(enabled);\n\t\t\t\t},\n\t\t\t\tonBlockImagesChange: (blocked) => {\n\t\t\t\t\thost.settingsManager.setBlockImages(blocked);\n\t\t\t\t},\n\t\t\t\tonEnableSkillCommandsChange: (enabled) => {\n\t\t\t\t\thost.settingsManager.setEnableSkillCommands(enabled);\n\t\t\t\t\thost.setupAutocompleteProvider();\n\t\t\t\t},\n\t\t\t\tonSteeringModeChange: (mode) => {\n\t\t\t\t\thost.session.setSteeringMode(mode);\n\t\t\t\t},\n\t\t\t\tonFollowUpModeChange: (mode) => {\n\t\t\t\t\thost.session.setFollowUpMode(mode);\n\t\t\t\t},\n\t\t\t\tonTransportChange: (transport) => {\n\t\t\t\t\thost.settingsManager.setTransport(transport);\n\t\t\t\t\thost.session.agent.transport = transport;\n\t\t\t\t},\n\t\t\t\tonHttpIdleTimeoutMsChange: (timeoutMs) => {\n\t\t\t\t\thost.settingsManager.setHttpIdleTimeoutMs(timeoutMs);\n\t\t\t\t\tconfigureHttpDispatcher(timeoutMs);\n\t\t\t\t\thost.showStatus(`HTTP idle timeout: ${formatHttpIdleTimeoutMs(timeoutMs)}`);\n\t\t\t\t},\n\t\t\t\tonThinkingLevelChange: (level) => {\n\t\t\t\t\thost.session.setThinkingLevel(level);\n\t\t\t\t\thost.footer.invalidate();\n\t\t\t\t\thost.updateEditorBorderColor();\n\t\t\t\t},\n\t\t\t\tonThemeChange: (themeName) => {\n\t\t\t\t\tconst result = setTheme(themeName, true);\n\t\t\t\t\thost.settingsManager.setTheme(themeName);\n\t\t\t\t\thost.ui.invalidate();\n\t\t\t\t\tif (!result.success) {\n\t\t\t\t\t\thost.showError(`Failed to load theme \"${themeName}\": ${result.error}\\nFell back to dark theme.`);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tonThemePreview: (themeName) => {\n\t\t\t\t\tconst result = setTheme(themeName, true);\n\t\t\t\t\tif (result.success) {\n\t\t\t\t\t\thost.ui.invalidate();\n\t\t\t\t\t\thost.ui.requestRender();\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tonHideThinkingBlockChange: (hidden) => {\n\t\t\t\t\thost.hideThinkingBlock = hidden;\n\t\t\t\t\thost.settingsManager.setHideThinkingBlock(hidden);\n\t\t\t\t\tfor (const child of host.chatContainer.children) {\n\t\t\t\t\t\tif (child instanceof AssistantMessageComponent) {\n\t\t\t\t\t\t\tchild.setHideThinkingBlock(hidden);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tvoid host.rebuildChatFromMessages();\n\t\t\t\t},\n\t\t\t\tonCollapseChangelogChange: (collapsed) => {\n\t\t\t\t\thost.settingsManager.setCollapseChangelog(collapsed);\n\t\t\t\t},\n\t\t\t\tonEnableInstallTelemetryChange: (enabled) => {\n\t\t\t\t\thost.settingsManager.setEnableInstallTelemetry(enabled);\n\t\t\t\t},\n\t\t\t\tonQuietStartupChange: (enabled) => {\n\t\t\t\t\thost.settingsManager.setQuietStartup(enabled);\n\t\t\t\t},\n\t\t\t\tonDoubleEscapeActionChange: (action) => {\n\t\t\t\t\thost.settingsManager.setDoubleEscapeAction(action);\n\t\t\t\t},\n\t\t\t\tonTreeFilterModeChange: (mode) => {\n\t\t\t\t\thost.settingsManager.setTreeFilterMode(mode);\n\t\t\t\t},\n\t\t\t\tonShowHardwareCursorChange: (enabled) => {\n\t\t\t\t\thost.settingsManager.setShowHardwareCursor(enabled);\n\t\t\t\t\thost.ui.setShowHardwareCursor(enabled);\n\t\t\t\t},\n\t\t\t\tonEditorPaddingXChange: (padding) => {\n\t\t\t\t\thost.settingsManager.setEditorPaddingX(padding);\n\t\t\t\t\thost.defaultEditor.setPaddingX(padding);\n\t\t\t\t\tif (host.editor !== host.defaultEditor && host.editor.setPaddingX !== undefined) {\n\t\t\t\t\t\thost.editor.setPaddingX(padding);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tonAutocompleteMaxVisibleChange: (maxVisible) => {\n\t\t\t\t\thost.settingsManager.setAutocompleteMaxVisible(maxVisible);\n\t\t\t\t\thost.defaultEditor.setAutocompleteMaxVisible(maxVisible);\n\t\t\t\t\tif (host.editor !== host.defaultEditor && host.editor.setAutocompleteMaxVisible !== undefined) {\n\t\t\t\t\t\thost.editor.setAutocompleteMaxVisible(maxVisible);\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tonClearOnShrinkChange: (enabled) => {\n\t\t\t\t\thost.settingsManager.setClearOnShrink(enabled);\n\t\t\t\t\thost.ui.setClearOnShrink(enabled);\n\t\t\t\t},\n\t\t\t\tonShowTerminalProgressChange: (enabled) => {\n\t\t\t\t\thost.settingsManager.setShowTerminalProgress(enabled);\n\t\t\t\t},\n\t\t\t\tonWarningsChange: (warnings) => {\n\t\t\t\t\thost.settingsManager.setWarnings(warnings);\n\t\t\t\t},\n\t\t\t\tonSelfModificationChange: (settings, scope) => {\n\t\t\t\t\thost.settingsManager.setSelfModificationSettings(settings, scope);\n\t\t\t\t\tconst validationMessage = host.validateSelfModificationSource(settings);\n\t\t\t\t\tif (validationMessage) {\n\t\t\t\t\t\thost.showWarning(validationMessage);\n\t\t\t\t\t}\n\t\t\t\t\thost.showStatus(\n\t\t\t\t\t\t`Self modification settings saved to ${scope}. Start a new session or /reload for system-prompt guardrails to fully refresh.`,\n\t\t\t\t\t);\n\t\t\t\t},\n\t\t\t\tonAutonomyChange: (settings, scope) => {\n\t\t\t\t\thost.applyAutonomyMode(settings.mode ?? \"off\", scope);\n\t\t\t\t\thost.showStatus(`Autonomy mode ${settings.mode ?? \"off\"} saved to ${scope}. Use /autonomy status.`);\n\t\t\t\t},\n\t\t\t\tonResearchLaneChange: (settings, scope) => {\n\t\t\t\t\thost.settingsManager.setResearchLaneSettings(settings, scope);\n\t\t\t\t\thost.showStatus(\n\t\t\t\t\t\t`Research lane settings saved to ${scope}. Use /autonomy research or /autonomy diagnostics.`,\n\t\t\t\t\t);\n\t\t\t\t},\n\t\t\t\tonWorkerDelegationChange: (settings, scope) => {\n\t\t\t\t\thost.settingsManager.setWorkerDelegationSettings(settings, scope);\n\t\t\t\t\thost.showStatus(`Worker delegation settings saved to ${scope}. The delegate tool uses them.`);\n\t\t\t\t},\n\t\t\t\tonLearningPolicyChange: (settings, scope) => {\n\t\t\t\t\thost.settingsManager.setLearningPolicySettings(settings, scope);\n\t\t\t\t\thost.showStatus(`Learning policy saved to ${scope}.`);\n\t\t\t\t},\n\t\t\t\tonModelCapabilityChange: (settings, scope) => {\n\t\t\t\t\thost.settingsManager.setModelCapabilitySettings(settings, scope);\n\t\t\t\t\thost.showStatus(`Model capability mode saved to ${scope}. Applies on the next model switch or /reload.`);\n\t\t\t\t},\n\t\t\t\tonContextCurationChange: (settings, scope) => {\n\t\t\t\t\thost.settingsManager.setContextCurationSettings(settings, scope);\n\t\t\t\t\thost.showStatus(\n\t\t\t\t\t\t`Context curation settings saved to ${scope}. Run /fitness <model> first if the model is unprobed.`,\n\t\t\t\t\t);\n\t\t\t\t},\n\t\t\t\tonModelRouterChange: (settings, scope) => {\n\t\t\t\t\thost.settingsManager.setModelRouterSettings(settings, scope);\n\t\t\t\t\tfor (const value of [settings.cheapModel, settings.expensiveModel, settings.learningModel]) {\n\t\t\t\t\t\tconst validationMessage = host.validateAutoLearnModelValue(value);\n\t\t\t\t\t\tif (validationMessage) {\n\t\t\t\t\t\t\thost.showWarning(validationMessage.replace(\"Auto Learn model\", \"Model router model\"));\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\thost.updateAutoLearnFooter();\n\t\t\t\t\thost.showStatus(`Model Router settings saved to ${scope}. Use /session or /usage to inspect routing.`);\n\t\t\t\t},\n\t\t\t\tonAutoLearnChange: (settings, scope) => {\n\t\t\t\t\thost.settingsManager.setAutoLearnSettings(settings, scope);\n\t\t\t\t\tconst validationMessage = host.validateAutoLearnModelValue(settings.model);\n\t\t\t\t\tif (validationMessage) {\n\t\t\t\t\t\thost.showWarning(validationMessage);\n\t\t\t\t\t}\n\t\t\t\t\thost.updateAutoLearnFooter();\n\t\t\t\t\thost.showStatus(`Auto Learn settings saved to ${scope}. Use /auto-learn status or /auto-learn run.`);\n\t\t\t\t},\n\t\t\t\tonContextPolicyEnforcementChange: (settings, scope) => {\n\t\t\t\t\thost.settingsManager.setContextPromptEnforcementSettings(settings, scope);\n\t\t\t\t\thost.showStatus(`Context/prompt-policy settings saved to ${scope}.`);\n\t\t\t\t},\n\t\t\t\tonContextMemoryRetrievalChange: (settings, scope) => {\n\t\t\t\t\thost.settingsManager.setMemoryRetrievalSettings(settings, scope);\n\t\t\t\t\thost.showStatus(`Context/memory-retrieval settings saved to ${scope}.`);\n\t\t\t\t},\n\t\t\t\tonResourcesHubAction: (action) => {\n\t\t\t\t\tdone();\n\t\t\t\t\tvoid host.handleResourcesHubAction(action);\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.getSettingsList() };\n\t});\n}\n"]}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Process signal handling, shutdown, and crash/suspend lifecycle extracted from
|
|
3
|
+
* interactive-mode.
|
|
4
|
+
*
|
|
5
|
+
* These register SIGTERM/SIGHUP/uncaughtException/dead-terminal handlers, run the
|
|
6
|
+
* graceful and emergency shutdown paths (preserving the #4144/#5080 ordering
|
|
7
|
+
* where signal-triggered shutdown emits extension cleanup before terminal
|
|
8
|
+
* writes), and implement Ctrl+Z suspend/resume. They operate through a
|
|
9
|
+
* `SignalLifecycleHost` seam: `isShuttingDown`/`signalCleanupHandlers` are
|
|
10
|
+
* threaded via get/set, and the cross-cluster calls (shutdown, unregister,
|
|
11
|
+
* emergency, crash) go through host seams so interactive-mode's thin wrappers —
|
|
12
|
+
* and the #5080/suspend behaviour tests that stub them — keep working.
|
|
13
|
+
*/
|
|
14
|
+
import type { TUI } from "@caupulican/pi-tui";
|
|
15
|
+
import type { AgentSessionRuntime } from "../../core/agent-session-runtime.ts";
|
|
16
|
+
export interface SignalLifecycleHost {
|
|
17
|
+
isShuttingDown: boolean;
|
|
18
|
+
signalCleanupHandlers: Array<() => void>;
|
|
19
|
+
readonly shutdownRequested: boolean;
|
|
20
|
+
readonly runtimeHost: Pick<AgentSessionRuntime, "dispose">;
|
|
21
|
+
readonly ui: TUI;
|
|
22
|
+
stop(): void;
|
|
23
|
+
formatResumeCommand(): string | undefined;
|
|
24
|
+
showStatus(message: string): void;
|
|
25
|
+
shutdown(options?: {
|
|
26
|
+
fromSignal?: boolean;
|
|
27
|
+
}): Promise<void>;
|
|
28
|
+
unregisterSignalHandlers(): void;
|
|
29
|
+
emergencyTerminalExit(): never;
|
|
30
|
+
uncaughtCrash(error: Error): never;
|
|
31
|
+
}
|
|
32
|
+
export declare function shutdown(host: SignalLifecycleHost, options?: {
|
|
33
|
+
fromSignal?: boolean;
|
|
34
|
+
}): Promise<void>;
|
|
35
|
+
export declare function emergencyTerminalExit(host: SignalLifecycleHost): never;
|
|
36
|
+
/**
|
|
37
|
+
* Last-resort handler for uncaught exceptions. The TUI puts stdin into raw
|
|
38
|
+
* mode and hides the cursor; without this handler, an uncaught throw from
|
|
39
|
+
* anywhere (e.g. an extension's async `ChildProcess.on("exit")` callback)
|
|
40
|
+
* tears down the process while leaving the terminal in raw mode with no
|
|
41
|
+
* cursor, requiring `stty sane && reset` to recover.
|
|
42
|
+
*
|
|
43
|
+
* Unlike emergencyTerminalExit, the terminal is still alive here, so we
|
|
44
|
+
* call ui.stop() to restore cooked mode, the cursor, and disable bracketed
|
|
45
|
+
* paste / Kitty / modifyOtherKeys sequences.
|
|
46
|
+
*/
|
|
47
|
+
export declare function uncaughtCrash(host: SignalLifecycleHost, error: Error): never;
|
|
48
|
+
/**
|
|
49
|
+
* Check if shutdown was requested and perform shutdown if so.
|
|
50
|
+
*/
|
|
51
|
+
export declare function checkShutdownRequested(host: SignalLifecycleHost): Promise<void>;
|
|
52
|
+
export declare function registerSignalHandlers(host: SignalLifecycleHost): void;
|
|
53
|
+
export declare function unregisterSignalHandlers(host: SignalLifecycleHost): void;
|
|
54
|
+
export declare function handleCtrlZ(host: Pick<SignalLifecycleHost, "showStatus" | "ui">): void;
|
|
55
|
+
//# sourceMappingURL=signal-lifecycle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signal-lifecycle.d.ts","sourceRoot":"","sources":["../../../src/modes/interactive/signal-lifecycle.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AAE9C,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAa/E,MAAM,WAAW,mBAAmB;IACnC,cAAc,EAAE,OAAO,CAAC;IACxB,qBAAqB,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC;IACzC,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC;IACpC,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAC,mBAAmB,EAAE,SAAS,CAAC,CAAC;IAC3D,QAAQ,CAAC,EAAE,EAAE,GAAG,CAAC;IACjB,IAAI,IAAI,IAAI,CAAC;IACb,mBAAmB,IAAI,MAAM,GAAG,SAAS,CAAC;IAC1C,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,QAAQ,CAAC,OAAO,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5D,wBAAwB,IAAI,IAAI,CAAC;IACjC,qBAAqB,IAAI,KAAK,CAAC;IAC/B,aAAa,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,CAAC;CACnC;AAED,wBAAsB,QAAQ,CAAC,IAAI,EAAE,mBAAmB,EAAE,OAAO,CAAC,EAAE;IAAE,UAAU,CAAC,EAAE,OAAO,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAmC3G;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,mBAAmB,GAAG,KAAK,CAOtE;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,mBAAmB,EAAE,KAAK,EAAE,KAAK,GAAG,KAAK,CAiB5E;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAAC,IAAI,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CAGrF;AAED,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,mBAAmB,GAAG,IAAI,CAsCtE;AAED,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,mBAAmB,GAAG,IAAI,CAKxE;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,mBAAmB,EAAE,YAAY,GAAG,IAAI,CAAC,GAAG,IAAI,CAmCtF","sourcesContent":["/**\n * Process signal handling, shutdown, and crash/suspend lifecycle extracted from\n * interactive-mode.\n *\n * These register SIGTERM/SIGHUP/uncaughtException/dead-terminal handlers, run the\n * graceful and emergency shutdown paths (preserving the #4144/#5080 ordering\n * where signal-triggered shutdown emits extension cleanup before terminal\n * writes), and implement Ctrl+Z suspend/resume. They operate through a\n * `SignalLifecycleHost` seam: `isShuttingDown`/`signalCleanupHandlers` are\n * threaded via get/set, and the cross-cluster calls (shutdown, unregister,\n * emergency, crash) go through host seams so interactive-mode's thin wrappers —\n * and the #5080/suspend behaviour tests that stub them — keep working.\n */\n\nimport type { TUI } from \"@caupulican/pi-tui\";\nimport chalk from \"chalk\";\nimport type { AgentSessionRuntime } from \"../../core/agent-session-runtime.ts\";\nimport { killTrackedDetachedChildren } from \"../../utils/shell.ts\";\n\nconst DEAD_TERMINAL_ERROR_CODES = new Set([\"EIO\", \"EPIPE\", \"ENOTCONN\"]);\n\nfunction isDeadTerminalError(error: unknown): boolean {\n\tif (!error || typeof error !== \"object\" || !(\"code\" in error)) {\n\t\treturn false;\n\t}\n\tconst code = (error as NodeJS.ErrnoException).code;\n\treturn code !== undefined && DEAD_TERMINAL_ERROR_CODES.has(code);\n}\n\nexport interface SignalLifecycleHost {\n\tisShuttingDown: boolean;\n\tsignalCleanupHandlers: Array<() => void>;\n\treadonly shutdownRequested: boolean;\n\treadonly runtimeHost: Pick<AgentSessionRuntime, \"dispose\">;\n\treadonly ui: TUI;\n\tstop(): void;\n\tformatResumeCommand(): string | undefined;\n\tshowStatus(message: string): void;\n\tshutdown(options?: { fromSignal?: boolean }): Promise<void>;\n\tunregisterSignalHandlers(): void;\n\temergencyTerminalExit(): never;\n\tuncaughtCrash(error: Error): never;\n}\n\nexport async function shutdown(host: SignalLifecycleHost, options?: { fromSignal?: boolean }): Promise<void> {\n\tif (host.isShuttingDown) return;\n\thost.isShuttingDown = true;\n\thost.unregisterSignalHandlers();\n\n\tif (options?.fromSignal) {\n\t\t// Signal-triggered shutdown (SIGTERM/SIGHUP). Emit extension cleanup\n\t\t// (session_shutdown) BEFORE touching the terminal. Extension teardown\n\t\t// such as removing sockets does not write to the tty, so it must not be\n\t\t// skipped if a later terminal-restore write fails on a dead or stalled\n\t\t// terminal. If the terminal is gone, the restore writes below emit EIO,\n\t\t// which the stdout/stderr error handler turns into emergencyTerminalExit;\n\t\t// the render loop is already idle, so this cannot hot-spin (see #4144).\n\t\tawait host.runtimeHost.dispose();\n\t\tawait host.ui.terminal.drainInput(1000);\n\t\thost.stop();\n\t\tprocess.exit(0);\n\t}\n\n\t// Interactive quit (Ctrl+D, Ctrl+C, /quit, extension shutdown()). Stop the\n\t// TUI before emitting shutdown events so extension UI cleanup cannot repaint\n\t// the final frame while the process is exiting.\n\t// Drain any in-flight Kitty key release events before stopping.\n\t// This prevents escape sequences from leaking to the parent shell over slow SSH.\n\tawait host.ui.terminal.drainInput(1000);\n\n\thost.stop();\n\tawait host.runtimeHost.dispose();\n\n\tconst resumeCommand = host.formatResumeCommand();\n\tif (resumeCommand) {\n\t\tprocess.stdout.write(`${chalk.dim(\"To resume this session:\")} ${resumeCommand}\\n`);\n\t}\n\n\tprocess.exit(0);\n}\n\nexport function emergencyTerminalExit(host: SignalLifecycleHost): never {\n\thost.isShuttingDown = true;\n\thost.unregisterSignalHandlers();\n\tkillTrackedDetachedChildren();\n\t// The terminal is gone. Do not run normal shutdown because TUI and\n\t// extension cleanup can write restore sequences and re-trigger EIO.\n\tprocess.exit(129);\n}\n\n/**\n * Last-resort handler for uncaught exceptions. The TUI puts stdin into raw\n * mode and hides the cursor; without this handler, an uncaught throw from\n * anywhere (e.g. an extension's async `ChildProcess.on(\"exit\")` callback)\n * tears down the process while leaving the terminal in raw mode with no\n * cursor, requiring `stty sane && reset` to recover.\n *\n * Unlike emergencyTerminalExit, the terminal is still alive here, so we\n * call ui.stop() to restore cooked mode, the cursor, and disable bracketed\n * paste / Kitty / modifyOtherKeys sequences.\n */\nexport function uncaughtCrash(host: SignalLifecycleHost, error: Error): never {\n\tif (host.isShuttingDown) {\n\t\tprocess.exit(1);\n\t}\n\thost.isShuttingDown = true;\n\ttry {\n\t\thost.unregisterSignalHandlers();\n\t} catch {}\n\ttry {\n\t\tkillTrackedDetachedChildren();\n\t} catch {}\n\ttry {\n\t\thost.ui.stop();\n\t} catch {}\n\tconsole.error(\"pi exiting due to uncaughtException:\");\n\tconsole.error(error);\n\tprocess.exit(1);\n}\n\n/**\n * Check if shutdown was requested and perform shutdown if so.\n */\nexport async function checkShutdownRequested(host: SignalLifecycleHost): Promise<void> {\n\tif (!host.shutdownRequested) return;\n\tawait host.shutdown();\n}\n\nexport function registerSignalHandlers(host: SignalLifecycleHost): void {\n\thost.unregisterSignalHandlers();\n\n\tconst signals: NodeJS.Signals[] = [\"SIGTERM\"];\n\tif (process.platform !== \"win32\") {\n\t\tsignals.push(\"SIGHUP\");\n\t}\n\n\tfor (const signal of signals) {\n\t\tconst handler = () => {\n\t\t\t// SIGHUP no longer hard-exits: graceful shutdown emits session_shutdown\n\t\t\t// first, then attempts terminal restore. A genuinely dead terminal\n\t\t\t// surfaces as an EIO on the restore writes, which the stdout/stderr\n\t\t\t// error handler converts into emergencyTerminalExit (see #4144, #5080).\n\t\t\tkillTrackedDetachedChildren();\n\t\t\tvoid host.shutdown({ fromSignal: true });\n\t\t};\n\t\tprocess.prependListener(signal, handler);\n\t\thost.signalCleanupHandlers.push(() => process.off(signal, handler));\n\t}\n\n\tconst terminalErrorHandler = (error: Error) => {\n\t\tif (isDeadTerminalError(error)) {\n\t\t\thost.emergencyTerminalExit();\n\t\t}\n\t\tthrow error;\n\t};\n\tprocess.stdout.on(\"error\", terminalErrorHandler);\n\tprocess.stderr.on(\"error\", terminalErrorHandler);\n\thost.signalCleanupHandlers.push(() => process.stdout.off(\"error\", terminalErrorHandler));\n\thost.signalCleanupHandlers.push(() => process.stderr.off(\"error\", terminalErrorHandler));\n\n\t// Restore the terminal before the process dies on any uncaught throw.\n\t// Without this, an unhandled exception from extension code (or anywhere\n\t// in pi) leaves the terminal in raw mode with no cursor.\n\tconst uncaughtExceptionHandler = (error: Error) => host.uncaughtCrash(error);\n\tprocess.prependListener(\"uncaughtException\", uncaughtExceptionHandler);\n\thost.signalCleanupHandlers.push(() => process.off(\"uncaughtException\", uncaughtExceptionHandler));\n}\n\nexport function unregisterSignalHandlers(host: SignalLifecycleHost): void {\n\tfor (const cleanup of host.signalCleanupHandlers) {\n\t\tcleanup();\n\t}\n\thost.signalCleanupHandlers = [];\n}\n\nexport function handleCtrlZ(host: Pick<SignalLifecycleHost, \"showStatus\" | \"ui\">): void {\n\tif (process.platform === \"win32\") {\n\t\thost.showStatus(\"Suspend to background is not supported on Windows\");\n\t\treturn;\n\t}\n\n\t// Keep the event loop alive while suspended. Without this, stopping the TUI\n\t// can leave Node with no ref'ed handles, causing the process to exit on fg\n\t// before the SIGCONT handler gets a chance to restore the terminal.\n\tconst suspendKeepAlive = setInterval(() => {}, 2 ** 30);\n\n\t// Ignore SIGINT while suspended so Ctrl+C in the terminal does not\n\t// kill the backgrounded process. The handler is removed on resume.\n\tconst ignoreSigint = () => {};\n\tprocess.on(\"SIGINT\", ignoreSigint);\n\n\t// Set up handler to restore TUI when resumed\n\tprocess.once(\"SIGCONT\", () => {\n\t\tclearInterval(suspendKeepAlive);\n\t\tprocess.removeListener(\"SIGINT\", ignoreSigint);\n\t\thost.ui.start();\n\t\thost.ui.requestRender(true);\n\t});\n\n\ttry {\n\t\t// Stop the TUI (restore terminal to normal mode)\n\t\thost.ui.stop();\n\n\t\t// Send SIGTSTP to process group (pid=0 means all processes in group)\n\t\tprocess.kill(0, \"SIGTSTP\");\n\t} catch (error) {\n\t\tclearInterval(suspendKeepAlive);\n\t\tprocess.removeListener(\"SIGINT\", ignoreSigint);\n\t\tthrow error;\n\t}\n}\n"]}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Process signal handling, shutdown, and crash/suspend lifecycle extracted from
|
|
3
|
+
* interactive-mode.
|
|
4
|
+
*
|
|
5
|
+
* These register SIGTERM/SIGHUP/uncaughtException/dead-terminal handlers, run the
|
|
6
|
+
* graceful and emergency shutdown paths (preserving the #4144/#5080 ordering
|
|
7
|
+
* where signal-triggered shutdown emits extension cleanup before terminal
|
|
8
|
+
* writes), and implement Ctrl+Z suspend/resume. They operate through a
|
|
9
|
+
* `SignalLifecycleHost` seam: `isShuttingDown`/`signalCleanupHandlers` are
|
|
10
|
+
* threaded via get/set, and the cross-cluster calls (shutdown, unregister,
|
|
11
|
+
* emergency, crash) go through host seams so interactive-mode's thin wrappers —
|
|
12
|
+
* and the #5080/suspend behaviour tests that stub them — keep working.
|
|
13
|
+
*/
|
|
14
|
+
import chalk from "chalk";
|
|
15
|
+
import { killTrackedDetachedChildren } from "../../utils/shell.js";
|
|
16
|
+
const DEAD_TERMINAL_ERROR_CODES = new Set(["EIO", "EPIPE", "ENOTCONN"]);
|
|
17
|
+
function isDeadTerminalError(error) {
|
|
18
|
+
if (!error || typeof error !== "object" || !("code" in error)) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
const code = error.code;
|
|
22
|
+
return code !== undefined && DEAD_TERMINAL_ERROR_CODES.has(code);
|
|
23
|
+
}
|
|
24
|
+
export async function shutdown(host, options) {
|
|
25
|
+
if (host.isShuttingDown)
|
|
26
|
+
return;
|
|
27
|
+
host.isShuttingDown = true;
|
|
28
|
+
host.unregisterSignalHandlers();
|
|
29
|
+
if (options?.fromSignal) {
|
|
30
|
+
// Signal-triggered shutdown (SIGTERM/SIGHUP). Emit extension cleanup
|
|
31
|
+
// (session_shutdown) BEFORE touching the terminal. Extension teardown
|
|
32
|
+
// such as removing sockets does not write to the tty, so it must not be
|
|
33
|
+
// skipped if a later terminal-restore write fails on a dead or stalled
|
|
34
|
+
// terminal. If the terminal is gone, the restore writes below emit EIO,
|
|
35
|
+
// which the stdout/stderr error handler turns into emergencyTerminalExit;
|
|
36
|
+
// the render loop is already idle, so this cannot hot-spin (see #4144).
|
|
37
|
+
await host.runtimeHost.dispose();
|
|
38
|
+
await host.ui.terminal.drainInput(1000);
|
|
39
|
+
host.stop();
|
|
40
|
+
process.exit(0);
|
|
41
|
+
}
|
|
42
|
+
// Interactive quit (Ctrl+D, Ctrl+C, /quit, extension shutdown()). Stop the
|
|
43
|
+
// TUI before emitting shutdown events so extension UI cleanup cannot repaint
|
|
44
|
+
// the final frame while the process is exiting.
|
|
45
|
+
// Drain any in-flight Kitty key release events before stopping.
|
|
46
|
+
// This prevents escape sequences from leaking to the parent shell over slow SSH.
|
|
47
|
+
await host.ui.terminal.drainInput(1000);
|
|
48
|
+
host.stop();
|
|
49
|
+
await host.runtimeHost.dispose();
|
|
50
|
+
const resumeCommand = host.formatResumeCommand();
|
|
51
|
+
if (resumeCommand) {
|
|
52
|
+
process.stdout.write(`${chalk.dim("To resume this session:")} ${resumeCommand}\n`);
|
|
53
|
+
}
|
|
54
|
+
process.exit(0);
|
|
55
|
+
}
|
|
56
|
+
export function emergencyTerminalExit(host) {
|
|
57
|
+
host.isShuttingDown = true;
|
|
58
|
+
host.unregisterSignalHandlers();
|
|
59
|
+
killTrackedDetachedChildren();
|
|
60
|
+
// The terminal is gone. Do not run normal shutdown because TUI and
|
|
61
|
+
// extension cleanup can write restore sequences and re-trigger EIO.
|
|
62
|
+
process.exit(129);
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Last-resort handler for uncaught exceptions. The TUI puts stdin into raw
|
|
66
|
+
* mode and hides the cursor; without this handler, an uncaught throw from
|
|
67
|
+
* anywhere (e.g. an extension's async `ChildProcess.on("exit")` callback)
|
|
68
|
+
* tears down the process while leaving the terminal in raw mode with no
|
|
69
|
+
* cursor, requiring `stty sane && reset` to recover.
|
|
70
|
+
*
|
|
71
|
+
* Unlike emergencyTerminalExit, the terminal is still alive here, so we
|
|
72
|
+
* call ui.stop() to restore cooked mode, the cursor, and disable bracketed
|
|
73
|
+
* paste / Kitty / modifyOtherKeys sequences.
|
|
74
|
+
*/
|
|
75
|
+
export function uncaughtCrash(host, error) {
|
|
76
|
+
if (host.isShuttingDown) {
|
|
77
|
+
process.exit(1);
|
|
78
|
+
}
|
|
79
|
+
host.isShuttingDown = true;
|
|
80
|
+
try {
|
|
81
|
+
host.unregisterSignalHandlers();
|
|
82
|
+
}
|
|
83
|
+
catch { }
|
|
84
|
+
try {
|
|
85
|
+
killTrackedDetachedChildren();
|
|
86
|
+
}
|
|
87
|
+
catch { }
|
|
88
|
+
try {
|
|
89
|
+
host.ui.stop();
|
|
90
|
+
}
|
|
91
|
+
catch { }
|
|
92
|
+
console.error("pi exiting due to uncaughtException:");
|
|
93
|
+
console.error(error);
|
|
94
|
+
process.exit(1);
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Check if shutdown was requested and perform shutdown if so.
|
|
98
|
+
*/
|
|
99
|
+
export async function checkShutdownRequested(host) {
|
|
100
|
+
if (!host.shutdownRequested)
|
|
101
|
+
return;
|
|
102
|
+
await host.shutdown();
|
|
103
|
+
}
|
|
104
|
+
export function registerSignalHandlers(host) {
|
|
105
|
+
host.unregisterSignalHandlers();
|
|
106
|
+
const signals = ["SIGTERM"];
|
|
107
|
+
if (process.platform !== "win32") {
|
|
108
|
+
signals.push("SIGHUP");
|
|
109
|
+
}
|
|
110
|
+
for (const signal of signals) {
|
|
111
|
+
const handler = () => {
|
|
112
|
+
// SIGHUP no longer hard-exits: graceful shutdown emits session_shutdown
|
|
113
|
+
// first, then attempts terminal restore. A genuinely dead terminal
|
|
114
|
+
// surfaces as an EIO on the restore writes, which the stdout/stderr
|
|
115
|
+
// error handler converts into emergencyTerminalExit (see #4144, #5080).
|
|
116
|
+
killTrackedDetachedChildren();
|
|
117
|
+
void host.shutdown({ fromSignal: true });
|
|
118
|
+
};
|
|
119
|
+
process.prependListener(signal, handler);
|
|
120
|
+
host.signalCleanupHandlers.push(() => process.off(signal, handler));
|
|
121
|
+
}
|
|
122
|
+
const terminalErrorHandler = (error) => {
|
|
123
|
+
if (isDeadTerminalError(error)) {
|
|
124
|
+
host.emergencyTerminalExit();
|
|
125
|
+
}
|
|
126
|
+
throw error;
|
|
127
|
+
};
|
|
128
|
+
process.stdout.on("error", terminalErrorHandler);
|
|
129
|
+
process.stderr.on("error", terminalErrorHandler);
|
|
130
|
+
host.signalCleanupHandlers.push(() => process.stdout.off("error", terminalErrorHandler));
|
|
131
|
+
host.signalCleanupHandlers.push(() => process.stderr.off("error", terminalErrorHandler));
|
|
132
|
+
// Restore the terminal before the process dies on any uncaught throw.
|
|
133
|
+
// Without this, an unhandled exception from extension code (or anywhere
|
|
134
|
+
// in pi) leaves the terminal in raw mode with no cursor.
|
|
135
|
+
const uncaughtExceptionHandler = (error) => host.uncaughtCrash(error);
|
|
136
|
+
process.prependListener("uncaughtException", uncaughtExceptionHandler);
|
|
137
|
+
host.signalCleanupHandlers.push(() => process.off("uncaughtException", uncaughtExceptionHandler));
|
|
138
|
+
}
|
|
139
|
+
export function unregisterSignalHandlers(host) {
|
|
140
|
+
for (const cleanup of host.signalCleanupHandlers) {
|
|
141
|
+
cleanup();
|
|
142
|
+
}
|
|
143
|
+
host.signalCleanupHandlers = [];
|
|
144
|
+
}
|
|
145
|
+
export function handleCtrlZ(host) {
|
|
146
|
+
if (process.platform === "win32") {
|
|
147
|
+
host.showStatus("Suspend to background is not supported on Windows");
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
// Keep the event loop alive while suspended. Without this, stopping the TUI
|
|
151
|
+
// can leave Node with no ref'ed handles, causing the process to exit on fg
|
|
152
|
+
// before the SIGCONT handler gets a chance to restore the terminal.
|
|
153
|
+
const suspendKeepAlive = setInterval(() => { }, 2 ** 30);
|
|
154
|
+
// Ignore SIGINT while suspended so Ctrl+C in the terminal does not
|
|
155
|
+
// kill the backgrounded process. The handler is removed on resume.
|
|
156
|
+
const ignoreSigint = () => { };
|
|
157
|
+
process.on("SIGINT", ignoreSigint);
|
|
158
|
+
// Set up handler to restore TUI when resumed
|
|
159
|
+
process.once("SIGCONT", () => {
|
|
160
|
+
clearInterval(suspendKeepAlive);
|
|
161
|
+
process.removeListener("SIGINT", ignoreSigint);
|
|
162
|
+
host.ui.start();
|
|
163
|
+
host.ui.requestRender(true);
|
|
164
|
+
});
|
|
165
|
+
try {
|
|
166
|
+
// Stop the TUI (restore terminal to normal mode)
|
|
167
|
+
host.ui.stop();
|
|
168
|
+
// Send SIGTSTP to process group (pid=0 means all processes in group)
|
|
169
|
+
process.kill(0, "SIGTSTP");
|
|
170
|
+
}
|
|
171
|
+
catch (error) {
|
|
172
|
+
clearInterval(suspendKeepAlive);
|
|
173
|
+
process.removeListener("SIGINT", ignoreSigint);
|
|
174
|
+
throw error;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
//# sourceMappingURL=signal-lifecycle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signal-lifecycle.js","sourceRoot":"","sources":["../../../src/modes/interactive/signal-lifecycle.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Process signal handling, shutdown, and crash/suspend lifecycle extracted from\n * interactive-mode.\n *\n * These register SIGTERM/SIGHUP/uncaughtException/dead-terminal handlers, run the\n * graceful and emergency shutdown paths (preserving the #4144/#5080 ordering\n * where signal-triggered shutdown emits extension cleanup before terminal\n * writes), and implement Ctrl+Z suspend/resume. They operate through a\n * `SignalLifecycleHost` seam: `isShuttingDown`/`signalCleanupHandlers` are\n * threaded via get/set, and the cross-cluster calls (shutdown, unregister,\n * emergency, crash) go through host seams so interactive-mode's thin wrappers —\n * and the #5080/suspend behaviour tests that stub them — keep working.\n */\n\nimport type { TUI } from \"@caupulican/pi-tui\";\nimport chalk from \"chalk\";\nimport type { AgentSessionRuntime } from \"../../core/agent-session-runtime.ts\";\nimport { killTrackedDetachedChildren } from \"../../utils/shell.ts\";\n\nconst DEAD_TERMINAL_ERROR_CODES = new Set([\"EIO\", \"EPIPE\", \"ENOTCONN\"]);\n\nfunction isDeadTerminalError(error: unknown): boolean {\n\tif (!error || typeof error !== \"object\" || !(\"code\" in error)) {\n\t\treturn false;\n\t}\n\tconst code = (error as NodeJS.ErrnoException).code;\n\treturn code !== undefined && DEAD_TERMINAL_ERROR_CODES.has(code);\n}\n\nexport interface SignalLifecycleHost {\n\tisShuttingDown: boolean;\n\tsignalCleanupHandlers: Array<() => void>;\n\treadonly shutdownRequested: boolean;\n\treadonly runtimeHost: Pick<AgentSessionRuntime, \"dispose\">;\n\treadonly ui: TUI;\n\tstop(): void;\n\tformatResumeCommand(): string | undefined;\n\tshowStatus(message: string): void;\n\tshutdown(options?: { fromSignal?: boolean }): Promise<void>;\n\tunregisterSignalHandlers(): void;\n\temergencyTerminalExit(): never;\n\tuncaughtCrash(error: Error): never;\n}\n\nexport async function shutdown(host: SignalLifecycleHost, options?: { fromSignal?: boolean }): Promise<void> {\n\tif (host.isShuttingDown) return;\n\thost.isShuttingDown = true;\n\thost.unregisterSignalHandlers();\n\n\tif (options?.fromSignal) {\n\t\t// Signal-triggered shutdown (SIGTERM/SIGHUP). Emit extension cleanup\n\t\t// (session_shutdown) BEFORE touching the terminal. Extension teardown\n\t\t// such as removing sockets does not write to the tty, so it must not be\n\t\t// skipped if a later terminal-restore write fails on a dead or stalled\n\t\t// terminal. If the terminal is gone, the restore writes below emit EIO,\n\t\t// which the stdout/stderr error handler turns into emergencyTerminalExit;\n\t\t// the render loop is already idle, so this cannot hot-spin (see #4144).\n\t\tawait host.runtimeHost.dispose();\n\t\tawait host.ui.terminal.drainInput(1000);\n\t\thost.stop();\n\t\tprocess.exit(0);\n\t}\n\n\t// Interactive quit (Ctrl+D, Ctrl+C, /quit, extension shutdown()). Stop the\n\t// TUI before emitting shutdown events so extension UI cleanup cannot repaint\n\t// the final frame while the process is exiting.\n\t// Drain any in-flight Kitty key release events before stopping.\n\t// This prevents escape sequences from leaking to the parent shell over slow SSH.\n\tawait host.ui.terminal.drainInput(1000);\n\n\thost.stop();\n\tawait host.runtimeHost.dispose();\n\n\tconst resumeCommand = host.formatResumeCommand();\n\tif (resumeCommand) {\n\t\tprocess.stdout.write(`${chalk.dim(\"To resume this session:\")} ${resumeCommand}\\n`);\n\t}\n\n\tprocess.exit(0);\n}\n\nexport function emergencyTerminalExit(host: SignalLifecycleHost): never {\n\thost.isShuttingDown = true;\n\thost.unregisterSignalHandlers();\n\tkillTrackedDetachedChildren();\n\t// The terminal is gone. Do not run normal shutdown because TUI and\n\t// extension cleanup can write restore sequences and re-trigger EIO.\n\tprocess.exit(129);\n}\n\n/**\n * Last-resort handler for uncaught exceptions. The TUI puts stdin into raw\n * mode and hides the cursor; without this handler, an uncaught throw from\n * anywhere (e.g. an extension's async `ChildProcess.on(\"exit\")` callback)\n * tears down the process while leaving the terminal in raw mode with no\n * cursor, requiring `stty sane && reset` to recover.\n *\n * Unlike emergencyTerminalExit, the terminal is still alive here, so we\n * call ui.stop() to restore cooked mode, the cursor, and disable bracketed\n * paste / Kitty / modifyOtherKeys sequences.\n */\nexport function uncaughtCrash(host: SignalLifecycleHost, error: Error): never {\n\tif (host.isShuttingDown) {\n\t\tprocess.exit(1);\n\t}\n\thost.isShuttingDown = true;\n\ttry {\n\t\thost.unregisterSignalHandlers();\n\t} catch {}\n\ttry {\n\t\tkillTrackedDetachedChildren();\n\t} catch {}\n\ttry {\n\t\thost.ui.stop();\n\t} catch {}\n\tconsole.error(\"pi exiting due to uncaughtException:\");\n\tconsole.error(error);\n\tprocess.exit(1);\n}\n\n/**\n * Check if shutdown was requested and perform shutdown if so.\n */\nexport async function checkShutdownRequested(host: SignalLifecycleHost): Promise<void> {\n\tif (!host.shutdownRequested) return;\n\tawait host.shutdown();\n}\n\nexport function registerSignalHandlers(host: SignalLifecycleHost): void {\n\thost.unregisterSignalHandlers();\n\n\tconst signals: NodeJS.Signals[] = [\"SIGTERM\"];\n\tif (process.platform !== \"win32\") {\n\t\tsignals.push(\"SIGHUP\");\n\t}\n\n\tfor (const signal of signals) {\n\t\tconst handler = () => {\n\t\t\t// SIGHUP no longer hard-exits: graceful shutdown emits session_shutdown\n\t\t\t// first, then attempts terminal restore. A genuinely dead terminal\n\t\t\t// surfaces as an EIO on the restore writes, which the stdout/stderr\n\t\t\t// error handler converts into emergencyTerminalExit (see #4144, #5080).\n\t\t\tkillTrackedDetachedChildren();\n\t\t\tvoid host.shutdown({ fromSignal: true });\n\t\t};\n\t\tprocess.prependListener(signal, handler);\n\t\thost.signalCleanupHandlers.push(() => process.off(signal, handler));\n\t}\n\n\tconst terminalErrorHandler = (error: Error) => {\n\t\tif (isDeadTerminalError(error)) {\n\t\t\thost.emergencyTerminalExit();\n\t\t}\n\t\tthrow error;\n\t};\n\tprocess.stdout.on(\"error\", terminalErrorHandler);\n\tprocess.stderr.on(\"error\", terminalErrorHandler);\n\thost.signalCleanupHandlers.push(() => process.stdout.off(\"error\", terminalErrorHandler));\n\thost.signalCleanupHandlers.push(() => process.stderr.off(\"error\", terminalErrorHandler));\n\n\t// Restore the terminal before the process dies on any uncaught throw.\n\t// Without this, an unhandled exception from extension code (or anywhere\n\t// in pi) leaves the terminal in raw mode with no cursor.\n\tconst uncaughtExceptionHandler = (error: Error) => host.uncaughtCrash(error);\n\tprocess.prependListener(\"uncaughtException\", uncaughtExceptionHandler);\n\thost.signalCleanupHandlers.push(() => process.off(\"uncaughtException\", uncaughtExceptionHandler));\n}\n\nexport function unregisterSignalHandlers(host: SignalLifecycleHost): void {\n\tfor (const cleanup of host.signalCleanupHandlers) {\n\t\tcleanup();\n\t}\n\thost.signalCleanupHandlers = [];\n}\n\nexport function handleCtrlZ(host: Pick<SignalLifecycleHost, \"showStatus\" | \"ui\">): void {\n\tif (process.platform === \"win32\") {\n\t\thost.showStatus(\"Suspend to background is not supported on Windows\");\n\t\treturn;\n\t}\n\n\t// Keep the event loop alive while suspended. Without this, stopping the TUI\n\t// can leave Node with no ref'ed handles, causing the process to exit on fg\n\t// before the SIGCONT handler gets a chance to restore the terminal.\n\tconst suspendKeepAlive = setInterval(() => {}, 2 ** 30);\n\n\t// Ignore SIGINT while suspended so Ctrl+C in the terminal does not\n\t// kill the backgrounded process. The handler is removed on resume.\n\tconst ignoreSigint = () => {};\n\tprocess.on(\"SIGINT\", ignoreSigint);\n\n\t// Set up handler to restore TUI when resumed\n\tprocess.once(\"SIGCONT\", () => {\n\t\tclearInterval(suspendKeepAlive);\n\t\tprocess.removeListener(\"SIGINT\", ignoreSigint);\n\t\thost.ui.start();\n\t\thost.ui.requestRender(true);\n\t});\n\n\ttry {\n\t\t// Stop the TUI (restore terminal to normal mode)\n\t\thost.ui.stop();\n\n\t\t// Send SIGTSTP to process group (pid=0 means all processes in group)\n\t\tprocess.kill(0, \"SIGTSTP\");\n\t} catch (error) {\n\t\tclearInterval(suspendKeepAlive);\n\t\tprocess.removeListener(\"SIGINT\", ignoreSigint);\n\t\tthrow error;\n\t}\n}\n"]}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Startup notices and update/telemetry checks extracted from interactive-mode.
|
|
3
|
+
*
|
|
4
|
+
* These render the "What's New" changelog notice and the untrusted-project
|
|
5
|
+
* warning, probe for package/tmux configuration issues, surface update
|
|
6
|
+
* notifications, and report anonymous install telemetry. They read
|
|
7
|
+
* session/settings state and render into the chat container through a narrow
|
|
8
|
+
* `StartupChecksHost` seam (`startupNoticesShown` is threaded via get/set);
|
|
9
|
+
* interactive-mode keeps thin delegating wrappers.
|
|
10
|
+
*/
|
|
11
|
+
import type { SessionManager } from "@caupulican/pi-agent-core/node";
|
|
12
|
+
import type { Container, MarkdownTheme, TUI } from "@caupulican/pi-tui";
|
|
13
|
+
import type { AgentSession } from "../../core/agent-session.ts";
|
|
14
|
+
import type { SettingsManager } from "../../core/settings-manager.ts";
|
|
15
|
+
import type { LatestPiRelease } from "../../utils/version-check.ts";
|
|
16
|
+
export interface StartupChecksHost {
|
|
17
|
+
readonly sessionManager: Pick<SessionManager, "getCwd">;
|
|
18
|
+
readonly settingsManager: SettingsManager;
|
|
19
|
+
readonly session: Pick<AgentSession, "state">;
|
|
20
|
+
readonly chatContainer: Container;
|
|
21
|
+
readonly ui: Pick<TUI, "requestRender">;
|
|
22
|
+
readonly version: string;
|
|
23
|
+
readonly changelogMarkdown: string | undefined;
|
|
24
|
+
startupNoticesShown: boolean;
|
|
25
|
+
getMarkdownThemeWithSettings(): MarkdownTheme;
|
|
26
|
+
}
|
|
27
|
+
export declare function checkForPackageUpdates(host: StartupChecksHost): Promise<string[]>;
|
|
28
|
+
export declare function checkTmuxKeyboardSetup(): Promise<string | undefined>;
|
|
29
|
+
/**
|
|
30
|
+
* Get changelog entries to display on startup.
|
|
31
|
+
* Only shows new entries since last seen version, skips for resumed sessions.
|
|
32
|
+
*/
|
|
33
|
+
export declare function getChangelogForDisplay(host: StartupChecksHost): string | undefined;
|
|
34
|
+
export declare function showStartupNoticesIfNeeded(host: StartupChecksHost): void;
|
|
35
|
+
export declare function renderProjectTrustWarningIfNeeded(host: StartupChecksHost): void;
|
|
36
|
+
export declare function showNewVersionNotification(host: StartupChecksHost, release: LatestPiRelease): void;
|
|
37
|
+
export declare function showPackageUpdateNotification(host: StartupChecksHost, packages: string[]): void;
|
|
38
|
+
//# sourceMappingURL=startup-checks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"startup-checks.d.ts","sourceRoot":"","sources":["../../../src/modes/interactive/startup-checks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,oBAAoB,CAAC;AAGxE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAEhE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAC;AAKtE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAIpE,MAAM,WAAW,iBAAiB;IACjC,QAAQ,CAAC,cAAc,EAAE,IAAI,CAAC,cAAc,EAAE,QAAQ,CAAC,CAAC;IACxD,QAAQ,CAAC,eAAe,EAAE,eAAe,CAAC;IAC1C,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IAC9C,QAAQ,CAAC,aAAa,EAAE,SAAS,CAAC;IAClC,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC;IACxC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,iBAAiB,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/C,mBAAmB,EAAE,OAAO,CAAC;IAC7B,4BAA4B,IAAI,aAAa,CAAC;CAC9C;AAED,wBAAsB,sBAAsB,CAAC,IAAI,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAgBvF;AAED,wBAAsB,sBAAsB,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CA6C1E;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,iBAAiB,GAAG,MAAM,GAAG,SAAS,CAyBlF;AAqBD,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,iBAAiB,GAAG,IAAI,CA4BxE;AAED,wBAAgB,iCAAiC,CAAC,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAkB/E;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,eAAe,GAAG,IAAI,CA2BlG;AAED,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,iBAAiB,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,IAAI,CAgB/F","sourcesContent":["/**\n * Startup notices and update/telemetry checks extracted from interactive-mode.\n *\n * These render the \"What's New\" changelog notice and the untrusted-project\n * warning, probe for package/tmux configuration issues, surface update\n * notifications, and report anonymous install telemetry. They read\n * session/settings state and render into the chat container through a narrow\n * `StartupChecksHost` seam (`startupNoticesShown` is threaded via get/set);\n * interactive-mode keeps thin delegating wrappers.\n */\n\nimport { spawn } from \"node:child_process\";\nimport type { SessionManager } from \"@caupulican/pi-agent-core/node\";\nimport type { Container, MarkdownTheme, TUI } from \"@caupulican/pi-tui\";\nimport { getCapabilities, hyperlink, Markdown, Spacer, Text } from \"@caupulican/pi-tui\";\nimport { APP_NAME, getAgentDir, VERSION } from \"../../config.ts\";\nimport type { AgentSession } from \"../../core/agent-session.ts\";\nimport { DefaultPackageManager } from \"../../core/package-manager.ts\";\nimport type { SettingsManager } from \"../../core/settings-manager.ts\";\nimport { isInstallTelemetryEnabled } from \"../../core/telemetry.ts\";\nimport { hasProjectTrustInputs } from \"../../core/trust-manager.ts\";\nimport { getChangelogPath, getNewEntries, parseChangelog } from \"../../utils/changelog.ts\";\nimport { getPiUserAgent } from \"../../utils/pi-user-agent.ts\";\nimport type { LatestPiRelease } from \"../../utils/version-check.ts\";\nimport { DynamicBorder } from \"./components/dynamic-border.ts\";\nimport { theme } from \"./theme/theme.ts\";\n\nexport interface StartupChecksHost {\n\treadonly sessionManager: Pick<SessionManager, \"getCwd\">;\n\treadonly settingsManager: SettingsManager;\n\treadonly session: Pick<AgentSession, \"state\">;\n\treadonly chatContainer: Container;\n\treadonly ui: Pick<TUI, \"requestRender\">;\n\treadonly version: string;\n\treadonly changelogMarkdown: string | undefined;\n\tstartupNoticesShown: boolean;\n\tgetMarkdownThemeWithSettings(): MarkdownTheme;\n}\n\nexport async function checkForPackageUpdates(host: StartupChecksHost): Promise<string[]> {\n\tif (process.env.PI_OFFLINE) {\n\t\treturn [];\n\t}\n\n\ttry {\n\t\tconst packageManager = new DefaultPackageManager({\n\t\t\tcwd: host.sessionManager.getCwd(),\n\t\t\tagentDir: getAgentDir(),\n\t\t\tsettingsManager: host.settingsManager,\n\t\t});\n\t\tconst updates = await packageManager.checkForAvailableUpdates();\n\t\treturn updates.map((update) => update.displayName);\n\t} catch {\n\t\treturn [];\n\t}\n}\n\nexport async function checkTmuxKeyboardSetup(): Promise<string | undefined> {\n\tif (!process.env.TMUX) return undefined;\n\n\tconst runTmuxShow = (option: string): Promise<string | undefined> => {\n\t\treturn new Promise((resolve) => {\n\t\t\tconst proc = spawn(\"tmux\", [\"show\", \"-gv\", option], {\n\t\t\t\tstdio: [\"ignore\", \"pipe\", \"ignore\"],\n\t\t\t});\n\t\t\tlet stdout = \"\";\n\t\t\tconst timer = setTimeout(() => {\n\t\t\t\tproc.kill();\n\t\t\t\tresolve(undefined);\n\t\t\t}, 2000);\n\n\t\t\tproc.stdout?.on(\"data\", (data) => {\n\t\t\t\tstdout += data.toString();\n\t\t\t});\n\t\t\tproc.on(\"error\", () => {\n\t\t\t\tclearTimeout(timer);\n\t\t\t\tresolve(undefined);\n\t\t\t});\n\t\t\tproc.on(\"close\", (code) => {\n\t\t\t\tclearTimeout(timer);\n\t\t\t\tresolve(code === 0 ? stdout.trim() : undefined);\n\t\t\t});\n\t\t});\n\t};\n\n\tconst [extendedKeys, extendedKeysFormat] = await Promise.all([\n\t\trunTmuxShow(\"extended-keys\"),\n\t\trunTmuxShow(\"extended-keys-format\"),\n\t]);\n\n\t// If we couldn't query tmux (timeout, sandbox, etc.), don't warn\n\tif (extendedKeys === undefined) return undefined;\n\n\tif (extendedKeys !== \"on\" && extendedKeys !== \"always\") {\n\t\treturn \"tmux extended-keys is off. Modified Enter keys may not work. Add `set -g extended-keys on` to ~/.tmux.conf and restart tmux.\";\n\t}\n\n\tif (extendedKeysFormat === \"xterm\") {\n\t\treturn \"tmux extended-keys-format is xterm. Pi works best with csi-u. Add `set -g extended-keys-format csi-u` to ~/.tmux.conf and restart tmux.\";\n\t}\n\n\treturn undefined;\n}\n\n/**\n * Get changelog entries to display on startup.\n * Only shows new entries since last seen version, skips for resumed sessions.\n */\nexport function getChangelogForDisplay(host: StartupChecksHost): string | undefined {\n\t// Skip changelog for resumed/continued sessions (already have messages)\n\tif (host.session.state.messages.length > 0) {\n\t\treturn undefined;\n\t}\n\n\tconst lastVersion = host.settingsManager.getLastChangelogVersion();\n\tconst changelogPath = getChangelogPath();\n\tconst entries = parseChangelog(changelogPath);\n\n\tif (!lastVersion) {\n\t\t// Fresh install - record the version, send telemetry, don't show changelog\n\t\thost.settingsManager.setLastChangelogVersion(VERSION);\n\t\treportInstallTelemetry(host, VERSION);\n\t\treturn undefined;\n\t}\n\n\tconst newEntries = getNewEntries(entries, lastVersion);\n\tif (newEntries.length > 0) {\n\t\thost.settingsManager.setLastChangelogVersion(VERSION);\n\t\treportInstallTelemetry(host, VERSION);\n\t\treturn newEntries.map((e) => e.content).join(\"\\n\\n\");\n\t}\n\n\treturn undefined;\n}\n\nfunction reportInstallTelemetry(host: StartupChecksHost, version: string): void {\n\tif (process.env.PI_OFFLINE) {\n\t\treturn;\n\t}\n\n\tif (!isInstallTelemetryEnabled(host.settingsManager)) {\n\t\treturn;\n\t}\n\n\tvoid fetch(`https://pi.dev/api/report-install?version=${encodeURIComponent(version)}`, {\n\t\theaders: {\n\t\t\t\"User-Agent\": getPiUserAgent(version),\n\t\t},\n\t\tsignal: AbortSignal.timeout(5000),\n\t})\n\t\t.then(() => undefined)\n\t\t.catch(() => undefined);\n}\n\nexport function showStartupNoticesIfNeeded(host: StartupChecksHost): void {\n\tif (host.startupNoticesShown) {\n\t\treturn;\n\t}\n\thost.startupNoticesShown = true;\n\n\tif (!host.changelogMarkdown) {\n\t\treturn;\n\t}\n\n\tif (host.chatContainer.children.length > 0) {\n\t\thost.chatContainer.addChild(new Spacer(1));\n\t}\n\thost.chatContainer.addChild(new DynamicBorder());\n\tif (host.settingsManager.getCollapseChangelog()) {\n\t\tconst versionMatch = host.changelogMarkdown.match(/##\\s+\\[?(\\d+\\.\\d+\\.\\d+)\\]?/);\n\t\tconst latestVersion = versionMatch ? versionMatch[1] : host.version;\n\t\tconst condensedText = `Updated to v${latestVersion}. Use ${theme.bold(\"/changelog\")} to view full changelog.`;\n\t\thost.chatContainer.addChild(new Text(condensedText, 1, 0));\n\t} else {\n\t\thost.chatContainer.addChild(new Text(theme.bold(theme.fg(\"accent\", \"What's New\")), 1, 0));\n\t\thost.chatContainer.addChild(new Spacer(1));\n\t\thost.chatContainer.addChild(\n\t\t\tnew Markdown(host.changelogMarkdown.trim(), 1, 0, host.getMarkdownThemeWithSettings()),\n\t\t);\n\t\thost.chatContainer.addChild(new Spacer(1));\n\t}\n\thost.chatContainer.addChild(new DynamicBorder());\n}\n\nexport function renderProjectTrustWarningIfNeeded(host: StartupChecksHost): void {\n\tif (host.settingsManager.isProjectTrusted() || !hasProjectTrustInputs(host.sessionManager.getCwd())) {\n\t\treturn;\n\t}\n\n\tif (host.chatContainer.children.length > 0) {\n\t\thost.chatContainer.addChild(new Spacer(1));\n\t}\n\thost.chatContainer.addChild(\n\t\tnew Text(\n\t\t\ttheme.fg(\n\t\t\t\t\"warning\",\n\t\t\t\t\"This project is not trusted. Project instructions (AGENTS.md/CLAUDE.md/GEMINI.md), .pi resources, and project packages are ignored. Use /trust to save a trust decision, then restart pi.\",\n\t\t\t),\n\t\t\t1,\n\t\t\t0,\n\t\t),\n\t);\n}\n\nexport function showNewVersionNotification(host: StartupChecksHost, release: LatestPiRelease): void {\n\tconst action = theme.fg(\"accent\", `${APP_NAME} update`);\n\tconst updateInstruction = theme.fg(\"muted\", `New version ${release.version} is available. Run `) + action;\n\tconst changelogUrl = \"https://pi.dev/changelog\";\n\tconst changelogLink = getCapabilities().hyperlinks\n\t\t? hyperlink(theme.fg(\"accent\", \"open changelog\"), changelogUrl)\n\t\t: theme.fg(\"accent\", changelogUrl);\n\tconst changelogLine = theme.fg(\"muted\", \"Changelog: \") + changelogLink;\n\tconst note = release.note?.trim();\n\n\thost.chatContainer.addChild(new Spacer(1));\n\thost.chatContainer.addChild(new DynamicBorder((text) => theme.fg(\"warning\", text)));\n\thost.chatContainer.addChild(\n\t\tnew Text(`${theme.bold(theme.fg(\"warning\", \"Update Available\"))}\\n${updateInstruction}`, 1, 0),\n\t);\n\tif (note) {\n\t\thost.chatContainer.addChild(new Spacer(1));\n\t\thost.chatContainer.addChild(\n\t\t\tnew Markdown(note, 1, 0, host.getMarkdownThemeWithSettings(), {\n\t\t\t\tcolor: (text) => theme.fg(\"muted\", text),\n\t\t\t}),\n\t\t);\n\t\thost.chatContainer.addChild(new Spacer(1));\n\t}\n\thost.chatContainer.addChild(new Text(changelogLine, 1, 0));\n\thost.chatContainer.addChild(new DynamicBorder((text) => theme.fg(\"warning\", text)));\n\thost.ui.requestRender();\n}\n\nexport function showPackageUpdateNotification(host: StartupChecksHost, packages: string[]): void {\n\tconst action = theme.fg(\"accent\", `${APP_NAME} update`);\n\tconst updateInstruction = theme.fg(\"muted\", \"Package updates are available. Run \") + action;\n\tconst packageLines = packages.map((pkg) => `- ${pkg}`).join(\"\\n\");\n\n\thost.chatContainer.addChild(new Spacer(1));\n\thost.chatContainer.addChild(new DynamicBorder((text) => theme.fg(\"warning\", text)));\n\thost.chatContainer.addChild(\n\t\tnew Text(\n\t\t\t`${theme.bold(theme.fg(\"warning\", \"Package Updates Available\"))}\\n${updateInstruction}\\n${theme.fg(\"muted\", \"Packages:\")}\\n${packageLines}`,\n\t\t\t1,\n\t\t\t0,\n\t\t),\n\t);\n\thost.chatContainer.addChild(new DynamicBorder((text) => theme.fg(\"warning\", text)));\n\thost.ui.requestRender();\n}\n"]}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Startup notices and update/telemetry checks extracted from interactive-mode.
|
|
3
|
+
*
|
|
4
|
+
* These render the "What's New" changelog notice and the untrusted-project
|
|
5
|
+
* warning, probe for package/tmux configuration issues, surface update
|
|
6
|
+
* notifications, and report anonymous install telemetry. They read
|
|
7
|
+
* session/settings state and render into the chat container through a narrow
|
|
8
|
+
* `StartupChecksHost` seam (`startupNoticesShown` is threaded via get/set);
|
|
9
|
+
* interactive-mode keeps thin delegating wrappers.
|
|
10
|
+
*/
|
|
11
|
+
import { spawn } from "node:child_process";
|
|
12
|
+
import { getCapabilities, hyperlink, Markdown, Spacer, Text } from "@caupulican/pi-tui";
|
|
13
|
+
import { APP_NAME, getAgentDir, VERSION } from "../../config.js";
|
|
14
|
+
import { DefaultPackageManager } from "../../core/package-manager.js";
|
|
15
|
+
import { isInstallTelemetryEnabled } from "../../core/telemetry.js";
|
|
16
|
+
import { hasProjectTrustInputs } from "../../core/trust-manager.js";
|
|
17
|
+
import { getChangelogPath, getNewEntries, parseChangelog } from "../../utils/changelog.js";
|
|
18
|
+
import { getPiUserAgent } from "../../utils/pi-user-agent.js";
|
|
19
|
+
import { DynamicBorder } from "./components/dynamic-border.js";
|
|
20
|
+
import { theme } from "./theme/theme.js";
|
|
21
|
+
export async function checkForPackageUpdates(host) {
|
|
22
|
+
if (process.env.PI_OFFLINE) {
|
|
23
|
+
return [];
|
|
24
|
+
}
|
|
25
|
+
try {
|
|
26
|
+
const packageManager = new DefaultPackageManager({
|
|
27
|
+
cwd: host.sessionManager.getCwd(),
|
|
28
|
+
agentDir: getAgentDir(),
|
|
29
|
+
settingsManager: host.settingsManager,
|
|
30
|
+
});
|
|
31
|
+
const updates = await packageManager.checkForAvailableUpdates();
|
|
32
|
+
return updates.map((update) => update.displayName);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
return [];
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export async function checkTmuxKeyboardSetup() {
|
|
39
|
+
if (!process.env.TMUX)
|
|
40
|
+
return undefined;
|
|
41
|
+
const runTmuxShow = (option) => {
|
|
42
|
+
return new Promise((resolve) => {
|
|
43
|
+
const proc = spawn("tmux", ["show", "-gv", option], {
|
|
44
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
45
|
+
});
|
|
46
|
+
let stdout = "";
|
|
47
|
+
const timer = setTimeout(() => {
|
|
48
|
+
proc.kill();
|
|
49
|
+
resolve(undefined);
|
|
50
|
+
}, 2000);
|
|
51
|
+
proc.stdout?.on("data", (data) => {
|
|
52
|
+
stdout += data.toString();
|
|
53
|
+
});
|
|
54
|
+
proc.on("error", () => {
|
|
55
|
+
clearTimeout(timer);
|
|
56
|
+
resolve(undefined);
|
|
57
|
+
});
|
|
58
|
+
proc.on("close", (code) => {
|
|
59
|
+
clearTimeout(timer);
|
|
60
|
+
resolve(code === 0 ? stdout.trim() : undefined);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
63
|
+
};
|
|
64
|
+
const [extendedKeys, extendedKeysFormat] = await Promise.all([
|
|
65
|
+
runTmuxShow("extended-keys"),
|
|
66
|
+
runTmuxShow("extended-keys-format"),
|
|
67
|
+
]);
|
|
68
|
+
// If we couldn't query tmux (timeout, sandbox, etc.), don't warn
|
|
69
|
+
if (extendedKeys === undefined)
|
|
70
|
+
return undefined;
|
|
71
|
+
if (extendedKeys !== "on" && extendedKeys !== "always") {
|
|
72
|
+
return "tmux extended-keys is off. Modified Enter keys may not work. Add `set -g extended-keys on` to ~/.tmux.conf and restart tmux.";
|
|
73
|
+
}
|
|
74
|
+
if (extendedKeysFormat === "xterm") {
|
|
75
|
+
return "tmux extended-keys-format is xterm. Pi works best with csi-u. Add `set -g extended-keys-format csi-u` to ~/.tmux.conf and restart tmux.";
|
|
76
|
+
}
|
|
77
|
+
return undefined;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Get changelog entries to display on startup.
|
|
81
|
+
* Only shows new entries since last seen version, skips for resumed sessions.
|
|
82
|
+
*/
|
|
83
|
+
export function getChangelogForDisplay(host) {
|
|
84
|
+
// Skip changelog for resumed/continued sessions (already have messages)
|
|
85
|
+
if (host.session.state.messages.length > 0) {
|
|
86
|
+
return undefined;
|
|
87
|
+
}
|
|
88
|
+
const lastVersion = host.settingsManager.getLastChangelogVersion();
|
|
89
|
+
const changelogPath = getChangelogPath();
|
|
90
|
+
const entries = parseChangelog(changelogPath);
|
|
91
|
+
if (!lastVersion) {
|
|
92
|
+
// Fresh install - record the version, send telemetry, don't show changelog
|
|
93
|
+
host.settingsManager.setLastChangelogVersion(VERSION);
|
|
94
|
+
reportInstallTelemetry(host, VERSION);
|
|
95
|
+
return undefined;
|
|
96
|
+
}
|
|
97
|
+
const newEntries = getNewEntries(entries, lastVersion);
|
|
98
|
+
if (newEntries.length > 0) {
|
|
99
|
+
host.settingsManager.setLastChangelogVersion(VERSION);
|
|
100
|
+
reportInstallTelemetry(host, VERSION);
|
|
101
|
+
return newEntries.map((e) => e.content).join("\n\n");
|
|
102
|
+
}
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
function reportInstallTelemetry(host, version) {
|
|
106
|
+
if (process.env.PI_OFFLINE) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
if (!isInstallTelemetryEnabled(host.settingsManager)) {
|
|
110
|
+
return;
|
|
111
|
+
}
|
|
112
|
+
void fetch(`https://pi.dev/api/report-install?version=${encodeURIComponent(version)}`, {
|
|
113
|
+
headers: {
|
|
114
|
+
"User-Agent": getPiUserAgent(version),
|
|
115
|
+
},
|
|
116
|
+
signal: AbortSignal.timeout(5000),
|
|
117
|
+
})
|
|
118
|
+
.then(() => undefined)
|
|
119
|
+
.catch(() => undefined);
|
|
120
|
+
}
|
|
121
|
+
export function showStartupNoticesIfNeeded(host) {
|
|
122
|
+
if (host.startupNoticesShown) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
host.startupNoticesShown = true;
|
|
126
|
+
if (!host.changelogMarkdown) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
if (host.chatContainer.children.length > 0) {
|
|
130
|
+
host.chatContainer.addChild(new Spacer(1));
|
|
131
|
+
}
|
|
132
|
+
host.chatContainer.addChild(new DynamicBorder());
|
|
133
|
+
if (host.settingsManager.getCollapseChangelog()) {
|
|
134
|
+
const versionMatch = host.changelogMarkdown.match(/##\s+\[?(\d+\.\d+\.\d+)\]?/);
|
|
135
|
+
const latestVersion = versionMatch ? versionMatch[1] : host.version;
|
|
136
|
+
const condensedText = `Updated to v${latestVersion}. Use ${theme.bold("/changelog")} to view full changelog.`;
|
|
137
|
+
host.chatContainer.addChild(new Text(condensedText, 1, 0));
|
|
138
|
+
}
|
|
139
|
+
else {
|
|
140
|
+
host.chatContainer.addChild(new Text(theme.bold(theme.fg("accent", "What's New")), 1, 0));
|
|
141
|
+
host.chatContainer.addChild(new Spacer(1));
|
|
142
|
+
host.chatContainer.addChild(new Markdown(host.changelogMarkdown.trim(), 1, 0, host.getMarkdownThemeWithSettings()));
|
|
143
|
+
host.chatContainer.addChild(new Spacer(1));
|
|
144
|
+
}
|
|
145
|
+
host.chatContainer.addChild(new DynamicBorder());
|
|
146
|
+
}
|
|
147
|
+
export function renderProjectTrustWarningIfNeeded(host) {
|
|
148
|
+
if (host.settingsManager.isProjectTrusted() || !hasProjectTrustInputs(host.sessionManager.getCwd())) {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
if (host.chatContainer.children.length > 0) {
|
|
152
|
+
host.chatContainer.addChild(new Spacer(1));
|
|
153
|
+
}
|
|
154
|
+
host.chatContainer.addChild(new Text(theme.fg("warning", "This project is not trusted. Project instructions (AGENTS.md/CLAUDE.md/GEMINI.md), .pi resources, and project packages are ignored. Use /trust to save a trust decision, then restart pi."), 1, 0));
|
|
155
|
+
}
|
|
156
|
+
export function showNewVersionNotification(host, release) {
|
|
157
|
+
const action = theme.fg("accent", `${APP_NAME} update`);
|
|
158
|
+
const updateInstruction = theme.fg("muted", `New version ${release.version} is available. Run `) + action;
|
|
159
|
+
const changelogUrl = "https://pi.dev/changelog";
|
|
160
|
+
const changelogLink = getCapabilities().hyperlinks
|
|
161
|
+
? hyperlink(theme.fg("accent", "open changelog"), changelogUrl)
|
|
162
|
+
: theme.fg("accent", changelogUrl);
|
|
163
|
+
const changelogLine = theme.fg("muted", "Changelog: ") + changelogLink;
|
|
164
|
+
const note = release.note?.trim();
|
|
165
|
+
host.chatContainer.addChild(new Spacer(1));
|
|
166
|
+
host.chatContainer.addChild(new DynamicBorder((text) => theme.fg("warning", text)));
|
|
167
|
+
host.chatContainer.addChild(new Text(`${theme.bold(theme.fg("warning", "Update Available"))}\n${updateInstruction}`, 1, 0));
|
|
168
|
+
if (note) {
|
|
169
|
+
host.chatContainer.addChild(new Spacer(1));
|
|
170
|
+
host.chatContainer.addChild(new Markdown(note, 1, 0, host.getMarkdownThemeWithSettings(), {
|
|
171
|
+
color: (text) => theme.fg("muted", text),
|
|
172
|
+
}));
|
|
173
|
+
host.chatContainer.addChild(new Spacer(1));
|
|
174
|
+
}
|
|
175
|
+
host.chatContainer.addChild(new Text(changelogLine, 1, 0));
|
|
176
|
+
host.chatContainer.addChild(new DynamicBorder((text) => theme.fg("warning", text)));
|
|
177
|
+
host.ui.requestRender();
|
|
178
|
+
}
|
|
179
|
+
export function showPackageUpdateNotification(host, packages) {
|
|
180
|
+
const action = theme.fg("accent", `${APP_NAME} update`);
|
|
181
|
+
const updateInstruction = theme.fg("muted", "Package updates are available. Run ") + action;
|
|
182
|
+
const packageLines = packages.map((pkg) => `- ${pkg}`).join("\n");
|
|
183
|
+
host.chatContainer.addChild(new Spacer(1));
|
|
184
|
+
host.chatContainer.addChild(new DynamicBorder((text) => theme.fg("warning", text)));
|
|
185
|
+
host.chatContainer.addChild(new Text(`${theme.bold(theme.fg("warning", "Package Updates Available"))}\n${updateInstruction}\n${theme.fg("muted", "Packages:")}\n${packageLines}`, 1, 0));
|
|
186
|
+
host.chatContainer.addChild(new DynamicBorder((text) => theme.fg("warning", text)));
|
|
187
|
+
host.ui.requestRender();
|
|
188
|
+
}
|
|
189
|
+
//# sourceMappingURL=startup-checks.js.map
|