@sammorrowdrums/mcpi 0.70.9 → 0.85.0-bootstrap.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 +1621 -0
- package/LICENSE +21 -0
- package/README.md +196 -141
- package/dist/bun/cli.d.ts.map +1 -1
- package/dist/bun/cli.js +4 -0
- package/dist/bun/cli.js.map +1 -1
- package/dist/bun/register-bedrock.d.ts.map +1 -1
- package/dist/bun/register-bedrock.js +1 -1
- package/dist/bun/register-bedrock.js.map +1 -1
- package/dist/bun/restore-sandbox-env.d.ts +17 -0
- package/dist/bun/restore-sandbox-env.d.ts.map +1 -0
- package/dist/bun/restore-sandbox-env.js +36 -0
- package/dist/bun/restore-sandbox-env.js.map +1 -0
- package/dist/cli/args.d.ts +9 -2
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +116 -16
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/auth-check.d.ts +19 -0
- package/dist/cli/auth-check.d.ts.map +1 -0
- package/dist/cli/auth-check.js +50 -0
- package/dist/cli/auth-check.js.map +1 -0
- package/dist/cli/auth-command.d.ts +24 -0
- package/dist/cli/auth-command.d.ts.map +1 -0
- package/dist/cli/auth-command.js +103 -0
- package/dist/cli/auth-command.js.map +1 -0
- package/dist/cli/config-selector.d.ts +6 -4
- package/dist/cli/config-selector.d.ts.map +1 -1
- package/dist/cli/config-selector.js +4 -4
- package/dist/cli/config-selector.js.map +1 -1
- package/dist/cli/credential-print.d.ts +13 -0
- package/dist/cli/credential-print.d.ts.map +1 -0
- package/dist/cli/credential-print.js +76 -0
- package/dist/cli/credential-print.js.map +1 -0
- package/dist/cli/experimental/auth.d.ts +16 -0
- package/dist/cli/experimental/auth.d.ts.map +1 -0
- package/dist/cli/experimental/auth.js +13 -0
- package/dist/cli/experimental/auth.js.map +1 -0
- package/dist/cli/experimental/cli.d.ts +6 -0
- package/dist/cli/experimental/cli.d.ts.map +1 -0
- package/dist/cli/experimental/cli.js +5 -0
- package/dist/cli/experimental/cli.js.map +1 -0
- package/dist/cli/experimental/command-options.d.ts +17 -0
- package/dist/cli/experimental/command-options.d.ts.map +1 -0
- package/dist/cli/experimental/command-options.js +35 -0
- package/dist/cli/experimental/command-options.js.map +1 -0
- package/dist/cli/experimental/command.d.ts +63 -0
- package/dist/cli/experimental/command.d.ts.map +1 -0
- package/dist/cli/experimental/command.js +130 -0
- package/dist/cli/experimental/command.js.map +1 -0
- package/dist/cli/experimental/commands/client.d.ts +13 -0
- package/dist/cli/experimental/commands/client.d.ts.map +1 -0
- package/dist/cli/experimental/commands/client.js +25 -0
- package/dist/cli/experimental/commands/client.js.map +1 -0
- package/dist/cli/experimental/commands/mcpi.d.ts +15 -0
- package/dist/cli/experimental/commands/mcpi.d.ts.map +1 -0
- package/dist/cli/experimental/commands/mcpi.js +28 -0
- package/dist/cli/experimental/commands/mcpi.js.map +1 -0
- package/dist/cli/experimental/commands/server.d.ts +13 -0
- package/dist/cli/experimental/commands/server.d.ts.map +1 -0
- package/dist/cli/experimental/commands/server.js +25 -0
- package/dist/cli/experimental/commands/server.js.map +1 -0
- package/dist/cli/experimental/transport-address.d.ts +10 -0
- package/dist/cli/experimental/transport-address.d.ts.map +1 -0
- package/dist/cli/experimental/transport-address.js +38 -0
- package/dist/cli/experimental/transport-address.js.map +1 -0
- package/dist/cli/file-processor.d.ts.map +1 -1
- package/dist/cli/file-processor.js +13 -26
- package/dist/cli/file-processor.js.map +1 -1
- package/dist/cli/initial-message.d.ts +1 -1
- package/dist/cli/initial-message.d.ts.map +1 -1
- package/dist/cli/initial-message.js.map +1 -1
- package/dist/cli/list-models.d.ts +2 -2
- package/dist/cli/list-models.d.ts.map +1 -1
- package/dist/cli/list-models.js +4 -4
- package/dist/cli/list-models.js.map +1 -1
- package/dist/cli/project-trust.d.ts +10 -0
- package/dist/cli/project-trust.d.ts.map +1 -0
- package/dist/cli/project-trust.js +48 -0
- package/dist/cli/project-trust.js.map +1 -0
- package/dist/cli/session-picker.d.ts +3 -2
- package/dist/cli/session-picker.d.ts.map +1 -1
- package/dist/cli/session-picker.js +5 -4
- package/dist/cli/session-picker.js.map +1 -1
- package/dist/cli/startup-ui.d.ts +20 -0
- package/dist/cli/startup-ui.d.ts.map +1 -0
- package/dist/cli/startup-ui.js +184 -0
- package/dist/cli/startup-ui.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +6 -3
- package/dist/cli.js.map +1 -1
- package/dist/client/index.d.ts +3 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +3 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/remote-session.d.ts +53 -0
- package/dist/client/remote-session.d.ts.map +1 -0
- package/dist/client/remote-session.js +340 -0
- package/dist/client/remote-session.js.map +1 -0
- package/dist/client/transcript.d.ts +12 -0
- package/dist/client/transcript.d.ts.map +1 -0
- package/dist/client/transcript.js +98 -0
- package/dist/client/transcript.js.map +1 -0
- package/dist/config.d.ts +34 -12
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +312 -61
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts +11 -9
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +16 -7
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session-services.d.ts +13 -12
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +34 -14
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +110 -53
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +658 -488
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-guidance.d.ts.map +1 -1
- package/dist/core/auth-guidance.js.map +1 -1
- package/dist/core/auth-storage.d.ts +35 -104
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +272 -286
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/bash-executor.d.ts +1 -1
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js +11 -8
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/cache-stats.d.ts +49 -0
- package/dist/core/cache-stats.d.ts.map +1 -0
- package/dist/core/cache-stats.js +101 -0
- package/dist/core/cache-stats.js.map +1 -0
- package/dist/core/compaction/branch-summarization.d.ts +16 -6
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js +13 -10
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts +25 -9
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +163 -133
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/compaction/index.d.ts +3 -3
- package/dist/core/compaction/index.d.ts.map +1 -1
- package/dist/core/compaction/index.js.map +1 -1
- package/dist/core/compaction/utils.d.ts +3 -3
- package/dist/core/compaction/utils.d.ts.map +1 -1
- package/dist/core/compaction/utils.js +7 -18
- package/dist/core/compaction/utils.js.map +1 -1
- package/dist/core/defaults.d.ts +1 -1
- package/dist/core/defaults.d.ts.map +1 -1
- package/dist/core/defaults.js.map +1 -1
- package/dist/core/env-overlay.d.ts +21 -0
- package/dist/core/env-overlay.d.ts.map +1 -0
- package/dist/core/env-overlay.js +25 -0
- package/dist/core/env-overlay.js.map +1 -0
- package/dist/core/exec.d.ts +8 -1
- package/dist/core/exec.d.ts.map +1 -1
- package/dist/core/exec.js +7 -1
- package/dist/core/exec.js.map +1 -1
- package/dist/core/experimental.d.ts +6 -0
- package/dist/core/experimental.d.ts.map +1 -0
- package/dist/core/experimental.js +8 -0
- package/dist/core/experimental.js.map +1 -0
- package/dist/core/export-html/ansi-to-html.d.ts.map +1 -1
- package/dist/core/export-html/ansi-to-html.js +1 -1
- package/dist/core/export-html/ansi-to-html.js.map +1 -1
- package/dist/core/export-html/index.d.ts +2 -2
- package/dist/core/export-html/index.d.ts.map +1 -1
- package/dist/core/export-html/index.js +8 -6
- package/dist/core/export-html/index.js.map +1 -1
- package/dist/core/export-html/template.css +53 -4
- package/dist/core/export-html/template.js +129 -35
- package/dist/core/export-html/tool-renderer.d.ts +2 -8
- package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
- package/dist/core/export-html/tool-renderer.js +15 -2
- package/dist/core/export-html/tool-renderer.js.map +1 -1
- package/dist/core/export-html/vendor/marked.min.js +75 -3
- package/dist/core/extensions/index.d.ts +8 -8
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts +5 -7
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +160 -87
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +32 -13
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +192 -4
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +217 -69
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/extensions/wrapper.d.ts +3 -3
- package/dist/core/extensions/wrapper.d.ts.map +1 -1
- package/dist/core/extensions/wrapper.js +22 -3
- package/dist/core/extensions/wrapper.js.map +1 -1
- package/dist/core/footer-data-provider.d.ts +12 -0
- package/dist/core/footer-data-provider.d.ts.map +1 -1
- package/dist/core/footer-data-provider.js +30 -2
- package/dist/core/footer-data-provider.js.map +1 -1
- package/dist/core/http-dispatcher.d.ts +22 -0
- package/dist/core/http-dispatcher.d.ts.map +1 -0
- package/dist/core/http-dispatcher.js +96 -0
- package/dist/core/http-dispatcher.js.map +1 -0
- package/dist/core/index.d.ts +9 -8
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +1 -0
- package/dist/core/index.js.map +1 -1
- package/dist/core/keybindings.d.ts +79 -10
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +11 -10
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/messages.d.ts +2 -2
- package/dist/core/messages.d.ts.map +1 -1
- package/dist/core/messages.js.map +1 -1
- package/dist/core/model-config.d.ts +571 -0
- package/dist/core/model-config.d.ts.map +1 -0
- package/dist/core/model-config.js +254 -0
- package/dist/core/model-config.js.map +1 -0
- package/dist/core/model-registry.d.ts +23 -110
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +65 -616
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts +20 -7
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +139 -43
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/model-runtime.d.ts +100 -0
- package/dist/core/model-runtime.d.ts.map +1 -0
- package/dist/core/model-runtime.js +602 -0
- package/dist/core/model-runtime.js.map +1 -0
- package/dist/core/models-store.d.ts +22 -0
- package/dist/core/models-store.d.ts.map +1 -0
- package/dist/core/models-store.js +113 -0
- package/dist/core/models-store.js.map +1 -0
- package/dist/core/output-guard.d.ts +1 -0
- package/dist/core/output-guard.d.ts.map +1 -1
- package/dist/core/output-guard.js +52 -22
- package/dist/core/output-guard.js.map +1 -1
- package/dist/core/package-manager.d.ts +21 -4
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +428 -191
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/pi-manifest.d.ts +8 -0
- package/dist/core/pi-manifest.d.ts.map +1 -0
- package/dist/core/pi-manifest.js +25 -0
- package/dist/core/pi-manifest.js.map +1 -0
- package/dist/core/project-trust.d.ts +15 -0
- package/dist/core/project-trust.d.ts.map +1 -0
- package/dist/core/project-trust.js +59 -0
- package/dist/core/project-trust.js.map +1 -0
- package/dist/core/prompt-templates.d.ts +4 -2
- package/dist/core/prompt-templates.d.ts.map +1 -1
- package/dist/core/prompt-templates.js +36 -50
- package/dist/core/prompt-templates.js.map +1 -1
- package/dist/core/provider-attribution.d.ts +4 -0
- package/dist/core/provider-attribution.d.ts.map +1 -0
- package/dist/core/provider-attribution.js +72 -0
- package/dist/core/provider-attribution.js.map +1 -0
- package/dist/core/provider-composer.d.ts +58 -0
- package/dist/core/provider-composer.d.ts.map +1 -0
- package/dist/core/provider-composer.js +396 -0
- package/dist/core/provider-composer.js.map +1 -0
- package/dist/core/radius.d.ts +2 -0
- package/dist/core/radius.d.ts.map +1 -0
- package/dist/core/radius.js +2 -0
- package/dist/core/radius.js.map +1 -0
- package/dist/core/remote-catalog-provider.d.ts +17 -0
- package/dist/core/remote-catalog-provider.d.ts.map +1 -0
- package/dist/core/remote-catalog-provider.js +137 -0
- package/dist/core/remote-catalog-provider.js.map +1 -0
- package/dist/core/resolve-config-value.d.ts +13 -6
- package/dist/core/resolve-config-value.d.ts.map +1 -1
- package/dist/core/resolve-config-value.js +143 -22
- package/dist/core/resolve-config-value.js.map +1 -1
- package/dist/core/resource-loader.d.ts +40 -12
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +236 -87
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/runtime-credentials.d.ts +15 -0
- package/dist/core/runtime-credentials.d.ts.map +1 -0
- package/dist/core/runtime-credentials.js +39 -0
- package/dist/core/runtime-credentials.js.map +1 -0
- package/dist/core/sdk.d.ts +26 -25
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +56 -49
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts +42 -19
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +454 -223
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +77 -8
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +255 -67
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/skills.d.ts +2 -2
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +12 -34
- package/dist/core/skills.js.map +1 -1
- package/dist/core/slash-commands.d.ts +2 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +4 -3
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/source-info.d.ts +1 -1
- package/dist/core/source-info.d.ts.map +1 -1
- package/dist/core/source-info.js.map +1 -1
- package/dist/core/system-prompt.d.ts +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +15 -25
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/telemetry.d.ts +7 -1
- package/dist/core/telemetry.d.ts.map +1 -1
- package/dist/core/telemetry.js +7 -1
- package/dist/core/telemetry.js.map +1 -1
- package/dist/core/timings.d.ts +5 -3
- package/dist/core/timings.d.ts.map +1 -1
- package/dist/core/timings.js +26 -16
- package/dist/core/timings.js.map +1 -1
- package/dist/core/tools/bash.d.ts +11 -7
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +220 -188
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit-diff.d.ts +26 -5
- package/dist/core/tools/edit-diff.d.ts.map +1 -1
- package/dist/core/tools/edit-diff.js +110 -23
- package/dist/core/tools/edit-diff.js.map +1 -1
- package/dist/core/tools/edit.d.ts +11 -5
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +67 -100
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/file-mutation-queue.d.ts.map +1 -1
- package/dist/core/tools/file-mutation-queue.js +27 -12
- package/dist/core/tools/file-mutation-queue.js.map +1 -1
- package/dist/core/tools/find.d.ts +10 -3
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +41 -37
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/grep.d.ts +7 -3
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +12 -8
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/index.d.ts +18 -18
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/ls.d.ts +7 -3
- package/dist/core/tools/ls.d.ts.map +1 -1
- package/dist/core/tools/ls.js +17 -15
- package/dist/core/tools/ls.js.map +1 -1
- package/dist/core/tools/output-accumulator.d.ts +52 -0
- package/dist/core/tools/output-accumulator.d.ts.map +1 -0
- package/dist/core/tools/output-accumulator.js +184 -0
- package/dist/core/tools/output-accumulator.js.map +1 -0
- package/dist/core/tools/path-utils.d.ts +2 -0
- package/dist/core/tools/path-utils.d.ts.map +1 -1
- package/dist/core/tools/path-utils.js +39 -21
- package/dist/core/tools/path-utils.js.map +1 -1
- package/dist/core/tools/read.d.ts +7 -3
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +101 -51
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/render-utils.d.ts +5 -2
- package/dist/core/tools/render-utils.d.ts.map +1 -1
- package/dist/core/tools/render-utils.js +18 -2
- package/dist/core/tools/render-utils.js.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.d.ts +2 -2
- package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
- package/dist/core/tools/tool-definition-wrapper.js +3 -3
- package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
- package/dist/core/tools/truncate.d.ts.map +1 -1
- package/dist/core/tools/truncate.js +12 -2
- package/dist/core/tools/truncate.js.map +1 -1
- package/dist/core/tools/write.d.ts +6 -2
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +35 -45
- package/dist/core/tools/write.js.map +1 -1
- package/dist/core/trust-manager.d.ts +36 -0
- package/dist/core/trust-manager.d.ts.map +1 -0
- package/dist/core/trust-manager.js +202 -0
- package/dist/core/trust-manager.js.map +1 -0
- package/dist/core/usage-totals.d.ts +19 -0
- package/dist/core/usage-totals.d.ts.map +1 -0
- package/dist/core/usage-totals.js +52 -0
- package/dist/core/usage-totals.js.map +1 -0
- package/dist/extensions/index.d.ts +3 -0
- package/dist/extensions/index.d.ts.map +1 -0
- package/dist/extensions/index.js +3 -0
- package/dist/extensions/index.js.map +1 -0
- package/dist/extensions/llama/client.d.ts +61 -0
- package/dist/extensions/llama/client.d.ts.map +1 -0
- package/dist/extensions/llama/client.js +302 -0
- package/dist/extensions/llama/client.js.map +1 -0
- package/dist/extensions/llama/huggingface.d.ts +23 -0
- package/dist/extensions/llama/huggingface.d.ts.map +1 -0
- package/dist/extensions/llama/huggingface.js +141 -0
- package/dist/extensions/llama/huggingface.js.map +1 -0
- package/dist/extensions/llama/index.d.ts +3 -0
- package/dist/extensions/llama/index.d.ts.map +1 -0
- package/dist/extensions/llama/index.js +217 -0
- package/dist/extensions/llama/index.js.map +1 -0
- package/dist/extensions/llama/provider.d.ts +10 -0
- package/dist/extensions/llama/provider.d.ts.map +1 -0
- package/dist/extensions/llama/provider.js +121 -0
- package/dist/extensions/llama/provider.js.map +1 -0
- package/dist/extensions/llama/ui.d.ts +42 -0
- package/dist/extensions/llama/ui.d.ts.map +1 -0
- package/dist/extensions/llama/ui.js +416 -0
- package/dist/extensions/llama/ui.js.map +1 -0
- package/dist/index.d.ts +34 -27
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -5
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts +2 -2
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +311 -101
- package/dist/main.js.map +1 -1
- package/dist/migrations.d.ts +5 -5
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +10 -10
- package/dist/migrations.js.map +1 -1
- package/dist/modes/index.d.ts +6 -5
- package/dist/modes/index.d.ts.map +1 -1
- package/dist/modes/index.js.map +1 -1
- package/dist/modes/interactive/components/armin.d.ts +1 -1
- package/dist/modes/interactive/components/armin.d.ts.map +1 -1
- package/dist/modes/interactive/components/armin.js.map +1 -1
- package/dist/modes/interactive/components/assistant-message.d.ts +8 -3
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +55 -26
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/bash-execution.d.ts +2 -2
- package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/bash-execution.js +4 -4
- package/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/dist/modes/interactive/components/bordered-loader.d.ts +2 -2
- package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
- package/dist/modes/interactive/components/bordered-loader.js +1 -1
- package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.d.ts +2 -2
- package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.js +1 -1
- package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.d.ts +2 -2
- package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.js +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/config-selector.d.ts +37 -6
- package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/config-selector.js +318 -34
- package/dist/modes/interactive/components/config-selector.js.map +1 -1
- package/dist/modes/interactive/components/countdown-timer.d.ts +3 -3
- package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -1
- package/dist/modes/interactive/components/countdown-timer.js +2 -2
- package/dist/modes/interactive/components/countdown-timer.js.map +1 -1
- package/dist/modes/interactive/components/custom-editor.d.ts +2 -2
- package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-editor.js +9 -2
- package/dist/modes/interactive/components/custom-editor.js.map +1 -1
- package/dist/modes/interactive/components/custom-entry.d.ts +19 -0
- package/dist/modes/interactive/components/custom-entry.d.ts.map +1 -0
- package/dist/modes/interactive/components/custom-entry.js +52 -0
- package/dist/modes/interactive/components/custom-entry.js.map +1 -0
- package/dist/modes/interactive/components/custom-message.d.ts +6 -4
- package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-message.js +11 -3
- package/dist/modes/interactive/components/custom-message.js.map +1 -1
- package/dist/modes/interactive/components/daxnuts.d.ts +1 -1
- package/dist/modes/interactive/components/daxnuts.d.ts.map +1 -1
- package/dist/modes/interactive/components/daxnuts.js.map +1 -1
- package/dist/modes/interactive/components/diff.d.ts.map +1 -1
- package/dist/modes/interactive/components/diff.js.map +1 -1
- package/dist/modes/interactive/components/dynamic-border.d.ts +1 -1
- package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
- package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
- package/dist/modes/interactive/components/extension-editor.d.ts +5 -4
- package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-editor.js +19 -32
- package/dist/modes/interactive/components/extension-editor.js.map +1 -1
- package/dist/modes/interactive/components/extension-input.d.ts +1 -1
- package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-input.js +1 -1
- package/dist/modes/interactive/components/extension-input.js.map +1 -1
- package/dist/modes/interactive/components/extension-selector.d.ts +3 -1
- package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-selector.js +7 -2
- package/dist/modes/interactive/components/extension-selector.js.map +1 -1
- package/dist/modes/interactive/components/first-time-setup.d.ts +25 -0
- package/dist/modes/interactive/components/first-time-setup.d.ts.map +1 -0
- package/dist/modes/interactive/components/first-time-setup.js +103 -0
- package/dist/modes/interactive/components/first-time-setup.js.map +1 -0
- package/dist/modes/interactive/components/footer.d.ts +9 -4
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +52 -31
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts +33 -31
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/index.js +2 -0
- package/dist/modes/interactive/components/index.js.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.d.ts +6 -1
- package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
- package/dist/modes/interactive/components/keybinding-hints.js +20 -6
- package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
- package/dist/modes/interactive/components/login-dialog.d.ts +12 -6
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/dist/modes/interactive/components/login-dialog.js +46 -17
- package/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/dist/modes/interactive/components/markdown-transform.d.ts +3 -0
- package/dist/modes/interactive/components/markdown-transform.d.ts.map +1 -0
- package/dist/modes/interactive/components/markdown-transform.js +19 -0
- package/dist/modes/interactive/components/markdown-transform.js.map +1 -0
- package/dist/modes/interactive/components/mermaid.d.ts +11 -0
- package/dist/modes/interactive/components/mermaid.d.ts.map +1 -0
- package/dist/modes/interactive/components/mermaid.js +75 -0
- package/dist/modes/interactive/components/mermaid.js.map +1 -0
- package/dist/modes/interactive/components/model-selector.d.ts +13 -6
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +92 -44
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.d.ts +7 -4
- package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/oauth-selector.js +32 -28
- package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.d.ts +5 -1
- package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.js +52 -14
- package/dist/modes/interactive/components/scoped-models-selector.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 +1 -1
- package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts +4 -5
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js +18 -16
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +23 -2
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +322 -22
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/show-images-selector.d.ts +1 -1
- package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/show-images-selector.js +1 -1
- package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.d.ts +2 -2
- package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.js +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
- package/dist/modes/interactive/components/status-indicator.d.ts +28 -0
- package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -0
- package/dist/modes/interactive/components/status-indicator.js +60 -0
- package/dist/modes/interactive/components/status-indicator.js.map +1 -0
- package/dist/modes/interactive/components/theme-selector.d.ts +1 -1
- package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/theme-selector.js +1 -1
- package/dist/modes/interactive/components/theme-selector.js.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.d.ts +2 -2
- package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.js +3 -2
- package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts +2 -2
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +33 -2
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/tree-selector.d.ts +7 -2
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-selector.js +179 -26
- package/dist/modes/interactive/components/tree-selector.js.map +1 -1
- package/dist/modes/interactive/components/trust-selector.d.ts +23 -0
- package/dist/modes/interactive/components/trust-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/trust-selector.js +91 -0
- package/dist/modes/interactive/components/trust-selector.js.map +1 -0
- package/dist/modes/interactive/components/user-message-selector.d.ts +1 -1
- package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message-selector.js +1 -1
- package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
- package/dist/modes/interactive/components/user-message.d.ts +9 -3
- package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/user-message.js +26 -6
- package/dist/modes/interactive/components/user-message.js.map +1 -1
- package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -1
- package/dist/modes/interactive/components/visual-truncate.js +1 -1
- package/dist/modes/interactive/components/visual-truncate.js.map +1 -1
- package/dist/modes/interactive/external-editor.d.ts +12 -0
- package/dist/modes/interactive/external-editor.d.ts.map +1 -0
- package/dist/modes/interactive/external-editor.js +37 -0
- package/dist/modes/interactive/external-editor.js.map +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts +104 -26
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +1565 -692
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/model-catalog-refresh.d.ts +7 -0
- package/dist/modes/interactive/model-catalog-refresh.d.ts.map +1 -0
- package/dist/modes/interactive/model-catalog-refresh.js +34 -0
- package/dist/modes/interactive/model-catalog-refresh.js.map +1 -0
- package/dist/modes/interactive/model-search.d.ts +12 -0
- package/dist/modes/interactive/model-search.d.ts.map +1 -0
- package/dist/modes/interactive/model-search.js +15 -0
- package/dist/modes/interactive/model-search.js.map +1 -0
- package/dist/modes/interactive/theme/dark.json +10 -5
- package/dist/modes/interactive/theme/light.json +10 -5
- package/dist/modes/interactive/theme/theme-controller.d.ts +40 -0
- package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -0
- package/dist/modes/interactive/theme/theme-controller.js +125 -0
- package/dist/modes/interactive/theme/theme-controller.js.map +1 -0
- package/dist/modes/interactive/theme/theme-schema.json +22 -5
- package/dist/modes/interactive/theme/theme.d.ts +48 -7
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +194 -76
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/json-event.d.ts +31 -0
- package/dist/modes/json-event.d.ts.map +1 -0
- package/dist/modes/json-event.js +15 -0
- package/dist/modes/json-event.js.map +1 -0
- package/dist/modes/print-mode.d.ts +3 -3
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +16 -5
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-client.d.ts +33 -10
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-client.js +89 -11
- package/dist/modes/rpc/rpc-client.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts +2 -2
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +69 -9
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-types.d.ts +43 -5
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-types.js.map +1 -1
- package/dist/package-manager-cli.d.ts +6 -2
- package/dist/package-manager-cli.d.ts.map +1 -1
- package/dist/package-manager-cli.js +527 -25
- package/dist/package-manager-cli.js.map +1 -1
- package/dist/path-migration.d.ts +13 -0
- package/dist/path-migration.d.ts.map +1 -0
- package/dist/path-migration.js +52 -0
- package/dist/path-migration.js.map +1 -0
- package/dist/rpc-entry.d.ts +3 -0
- package/dist/rpc-entry.d.ts.map +1 -0
- package/dist/rpc-entry.js +11 -0
- package/dist/rpc-entry.js.map +1 -0
- package/dist/server/create-harness.d.ts +26 -0
- package/dist/server/create-harness.d.ts.map +1 -0
- package/dist/server/create-harness.js +106 -0
- package/dist/server/create-harness.js.map +1 -0
- package/dist/utils/abort.d.ts +5 -0
- package/dist/utils/abort.d.ts.map +1 -0
- package/dist/utils/abort.js +48 -0
- package/dist/utils/abort.js.map +1 -0
- package/dist/utils/ansi.d.ts +2 -0
- package/dist/utils/ansi.d.ts.map +1 -0
- package/dist/utils/ansi.js +52 -0
- package/dist/utils/ansi.js.map +1 -0
- package/dist/utils/changelog.d.ts +2 -1
- package/dist/utils/changelog.d.ts.map +1 -1
- package/dist/utils/changelog.js +85 -0
- package/dist/utils/changelog.js.map +1 -1
- package/dist/utils/child-process.d.ts +12 -5
- package/dist/utils/child-process.d.ts.map +1 -1
- package/dist/utils/child-process.js +33 -5
- package/dist/utils/child-process.js.map +1 -1
- package/dist/utils/clipboard-image.d.ts.map +1 -1
- package/dist/utils/clipboard-image.js +4 -4
- package/dist/utils/clipboard-image.js.map +1 -1
- package/dist/utils/clipboard-native.d.ts +4 -1
- package/dist/utils/clipboard-native.d.ts.map +1 -1
- package/dist/utils/clipboard-native.js +14 -8
- package/dist/utils/clipboard-native.js.map +1 -1
- package/dist/utils/clipboard.d.ts +2 -0
- package/dist/utils/clipboard.d.ts.map +1 -1
- package/dist/utils/clipboard.js +129 -46
- package/dist/utils/clipboard.js.map +1 -1
- package/dist/utils/deprecation.d.ts +4 -0
- package/dist/utils/deprecation.d.ts.map +1 -0
- package/dist/utils/deprecation.js +13 -0
- package/dist/utils/deprecation.js.map +1 -0
- package/dist/utils/exif-orientation.d.ts +1 -1
- package/dist/utils/exif-orientation.d.ts.map +1 -1
- package/dist/utils/exif-orientation.js.map +1 -1
- package/dist/utils/git.d.ts.map +1 -1
- package/dist/utils/git.js +54 -22
- package/dist/utils/git.js.map +1 -1
- package/dist/utils/html.d.ts +7 -0
- package/dist/utils/html.d.ts.map +1 -0
- package/dist/utils/html.js +40 -0
- package/dist/utils/html.js.map +1 -0
- package/dist/utils/image-convert.d.ts +1 -0
- package/dist/utils/image-convert.d.ts.map +1 -1
- package/dist/utils/image-convert.js +21 -15
- package/dist/utils/image-convert.js.map +1 -1
- package/dist/utils/image-process.d.ts +18 -0
- package/dist/utils/image-process.d.ts.map +1 -0
- package/dist/utils/image-process.js +83 -0
- package/dist/utils/image-process.js.map +1 -0
- package/dist/utils/image-resize-core.d.ts +30 -0
- package/dist/utils/image-resize-core.d.ts.map +1 -0
- package/dist/utils/image-resize-core.js +124 -0
- package/dist/utils/image-resize-core.js.map +1 -0
- package/dist/utils/image-resize-worker.d.ts +2 -0
- package/dist/utils/image-resize-worker.d.ts.map +1 -0
- package/dist/utils/image-resize-worker.js +31 -0
- package/dist/utils/image-resize-worker.js.map +1 -0
- package/dist/utils/image-resize.d.ts +7 -27
- package/dist/utils/image-resize.d.ts.map +1 -1
- package/dist/utils/image-resize.js +75 -115
- package/dist/utils/image-resize.js.map +1 -1
- package/dist/utils/json.d.ts +3 -0
- package/dist/utils/json.d.ts.map +1 -0
- package/dist/utils/json.js +7 -0
- package/dist/utils/json.js.map +1 -0
- package/dist/utils/management-http.d.ts +23 -0
- package/dist/utils/management-http.d.ts.map +1 -0
- package/dist/utils/management-http.js +50 -0
- package/dist/utils/management-http.js.map +1 -0
- package/dist/utils/mime.d.ts +1 -0
- package/dist/utils/mime.d.ts.map +1 -1
- package/dist/utils/mime.js +100 -16
- package/dist/utils/mime.js.map +1 -1
- package/dist/utils/open-browser.d.ts +9 -0
- package/dist/utils/open-browser.d.ts.map +1 -0
- package/dist/utils/open-browser.js +22 -0
- package/dist/utils/open-browser.js.map +1 -0
- package/dist/utils/paths.d.ts +28 -1
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js +97 -2
- package/dist/utils/paths.js.map +1 -1
- package/dist/utils/pi-user-agent.d.ts +2 -0
- package/dist/utils/pi-user-agent.d.ts.map +1 -0
- package/dist/utils/pi-user-agent.js +5 -0
- package/dist/utils/pi-user-agent.js.map +1 -0
- package/dist/utils/shell.d.ts +1 -0
- package/dist/utils/shell.d.ts.map +1 -1
- package/dist/utils/shell.js +18 -6
- package/dist/utils/shell.js.map +1 -1
- package/dist/utils/syntax-highlight.d.ts +12 -0
- package/dist/utils/syntax-highlight.d.ts.map +1 -0
- package/dist/utils/syntax-highlight.js +118 -0
- package/dist/utils/syntax-highlight.js.map +1 -0
- package/dist/utils/tool-result-images.d.ts +19 -0
- package/dist/utils/tool-result-images.d.ts.map +1 -0
- package/dist/utils/tool-result-images.js +45 -0
- package/dist/utils/tool-result-images.js.map +1 -0
- package/dist/utils/tools-manager.d.ts +10 -1
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +105 -36
- package/dist/utils/tools-manager.js.map +1 -1
- package/dist/utils/version-check.d.ts +19 -0
- package/dist/utils/version-check.d.ts.map +1 -0
- package/dist/utils/version-check.js +85 -0
- package/dist/utils/version-check.js.map +1 -0
- package/dist/utils/windows-self-update.d.ts +3 -0
- package/dist/utils/windows-self-update.d.ts.map +1 -0
- package/dist/utils/windows-self-update.js +77 -0
- package/dist/utils/windows-self-update.js.map +1 -0
- package/docs/compaction.md +39 -32
- package/docs/containerization.md +113 -0
- package/docs/custom-provider.md +212 -75
- package/docs/development.md +9 -9
- package/docs/docs.json +156 -0
- package/docs/environment-variables.md +186 -0
- package/docs/extensions.md +652 -140
- package/docs/index.md +81 -0
- package/docs/json.md +26 -15
- package/docs/keybindings.md +60 -21
- package/docs/llama-cpp.md +99 -0
- package/docs/models.md +168 -34
- package/docs/packages.md +46 -36
- package/docs/prompt-templates.md +13 -5
- package/docs/providers.md +147 -26
- package/docs/quickstart.md +167 -0
- package/docs/rpc.md +218 -36
- package/docs/sdk.md +190 -125
- package/docs/security.md +59 -0
- package/docs/{session.md → session-format.md} +48 -22
- package/docs/sessions.md +145 -0
- package/docs/settings.md +130 -25
- package/docs/shell-aliases.md +2 -2
- package/docs/skills.md +13 -14
- package/docs/terminal-setup.md +73 -16
- package/docs/termux.md +10 -10
- package/docs/themes.md +41 -16
- package/docs/tmux.md +6 -4
- package/docs/tui.md +85 -61
- package/docs/usage.md +302 -0
- package/docs/windows.md +2 -2
- package/examples/README.md +1 -1
- package/examples/extensions/README.md +12 -9
- package/examples/extensions/bash-spawn-hook.ts +2 -2
- package/examples/extensions/border-status-editor.ts +145 -0
- package/examples/extensions/built-in-tool-renderer.ts +2 -2
- package/examples/extensions/claude-rules.ts +1 -1
- package/examples/extensions/commands.ts +1 -1
- package/examples/extensions/custom-compaction.ts +6 -16
- package/examples/extensions/custom-footer.ts +1 -1
- package/examples/extensions/custom-header.ts +7 -7
- package/examples/extensions/custom-provider-anthropic/index.ts +15 -8
- package/examples/extensions/custom-provider-anthropic/package-lock.json +4 -4
- package/examples/extensions/custom-provider-anthropic/package.json +3 -3
- package/examples/extensions/custom-provider-gitlab-duo/index.ts +65 -9
- package/examples/extensions/custom-provider-gitlab-duo/package.json +2 -2
- package/examples/extensions/custom-provider-gitlab-duo/test.ts +2 -2
- package/examples/extensions/doom-overlay/README.md +1 -1
- package/examples/extensions/doom-overlay/doom-component.ts +4 -4
- package/examples/extensions/doom-overlay/doom-keys.ts +1 -1
- package/examples/extensions/doom-overlay/index.ts +5 -5
- package/examples/extensions/doom-overlay/wad-finder.ts +7 -3
- package/examples/extensions/dynamic-resources/dynamic.json +1 -1
- package/examples/extensions/entry-renderer.ts +41 -0
- package/examples/extensions/git-merge-and-resolve.ts +115 -0
- package/examples/extensions/github-issue-autocomplete.ts +2 -2
- package/examples/extensions/gondolin/index.ts +531 -0
- package/examples/extensions/gondolin/package-lock.json +185 -0
- package/examples/extensions/gondolin/package.json +19 -0
- package/examples/extensions/handoff.ts +50 -14
- package/examples/extensions/hidden-thinking-label.ts +1 -1
- package/examples/extensions/inline-bash.ts +2 -2
- package/examples/extensions/input-transform-streaming.ts +39 -0
- package/examples/extensions/input-transform.ts +2 -2
- package/examples/extensions/interactive-shell.ts +2 -2
- package/examples/extensions/kimi-deferred-tools.ts +61 -0
- package/examples/extensions/mac-system-theme.ts +2 -2
- package/examples/extensions/message-renderer.ts +3 -3
- package/examples/extensions/minimal-mode.ts +2 -2
- package/examples/extensions/modal-editor.ts +2 -2
- package/examples/extensions/model-status.ts +1 -1
- package/examples/extensions/notify.ts +3 -3
- package/examples/extensions/overlay-qa-tests.ts +242 -140
- package/examples/extensions/overlay-test.ts +9 -6
- package/examples/extensions/pirate.ts +1 -1
- package/examples/extensions/plan-mode/README.md +3 -2
- package/examples/extensions/plan-mode/index.ts +90 -40
- package/examples/extensions/preset.ts +16 -10
- package/examples/extensions/project-trust.ts +64 -0
- package/examples/extensions/prompt-customizer.ts +1 -1
- package/examples/extensions/provider-payload.ts +5 -5
- package/examples/extensions/qna.ts +4 -8
- package/examples/extensions/question.ts +41 -19
- package/examples/extensions/questionnaire.ts +50 -29
- package/examples/extensions/rainbow-editor.ts +1 -1
- package/examples/extensions/reload-runtime.ts +2 -2
- package/examples/extensions/rpc-demo.ts +1 -1
- package/examples/extensions/sandbox/index.ts +9 -9
- package/examples/extensions/sandbox/package-lock.json +7 -7
- package/examples/extensions/sandbox/package.json +3 -3
- package/examples/extensions/shutdown-command.ts +5 -5
- package/examples/extensions/snake.ts +2 -2
- package/examples/extensions/space-invaders.ts +2 -2
- package/examples/extensions/ssh.ts +2 -2
- package/examples/extensions/structured-output.ts +1 -1
- package/examples/extensions/subagent/README.md +18 -13
- package/examples/extensions/subagent/agents.ts +42 -11
- package/examples/extensions/subagent/index.ts +76 -30
- package/examples/extensions/summarize.ts +12 -19
- package/examples/extensions/tic-tac-toe.ts +2 -2
- package/examples/extensions/titlebar-spinner.ts +3 -3
- package/examples/extensions/todo.ts +2 -2
- package/examples/extensions/tool-override.ts +1 -1
- package/examples/extensions/tools.ts +7 -2
- package/examples/extensions/truncated-tool.ts +2 -2
- package/examples/extensions/with-deps/package-lock.json +4 -4
- package/examples/extensions/with-deps/package.json +4 -4
- package/examples/extensions/working-indicator.ts +4 -4
- package/examples/extensions/working-message-test.ts +1 -1
- package/examples/rpc-extension-ui.ts +11 -2
- package/examples/sdk/01-minimal.ts +15 -11
- package/examples/sdk/02-custom-model.ts +18 -18
- package/examples/sdk/03-custom-prompt.ts +25 -17
- package/examples/sdk/04-skills.ts +3 -3
- package/examples/sdk/05-tools.ts +8 -4
- package/examples/sdk/06-extensions.ts +13 -9
- package/examples/sdk/07-context-files.ts +2 -2
- package/examples/sdk/08-prompt-templates.ts +3 -3
- package/examples/sdk/09-api-keys-and-oauth.ts +19 -33
- package/examples/sdk/10-settings.ts +4 -4
- package/examples/sdk/11-sessions.ts +4 -0
- package/examples/sdk/12-full-control.ts +22 -21
- package/examples/sdk/README.md +23 -30
- package/npm-shrinkwrap.json +1818 -0
- package/package.json +117 -99
- package/dist/modes/interactive/assets/clankolas.png +0 -0
- package/dist/modes/interactive/components/auth-selector-status.d.ts +0 -20
- package/dist/modes/interactive/components/auth-selector-status.d.ts.map +0 -1
- package/dist/modes/interactive/components/auth-selector-status.js +0 -23
- package/dist/modes/interactive/components/auth-selector-status.js.map +0 -1
- package/dist/modes/interactive/components/earendil-announcement.d.ts +0 -5
- package/dist/modes/interactive/components/earendil-announcement.d.ts.map +0 -1
- package/dist/modes/interactive/components/earendil-announcement.js +0 -40
- package/dist/modes/interactive/components/earendil-announcement.js.map +0 -1
- package/docs/images/exy.png +0 -0
- package/docs/tree.md +0 -233
- package/examples/extensions/antigravity-image-gen.ts +0 -418
- package/examples/extensions/custom-provider-qwen-cli/index.ts +0 -345
- package/examples/extensions/custom-provider-qwen-cli/package.json +0 -16
|
@@ -1,14 +1,22 @@
|
|
|
1
|
+
import { uuidv7 } from "@sammorrowdrums/mcpi-ai";
|
|
1
2
|
import { randomUUID } from "crypto";
|
|
2
|
-
import { appendFileSync, closeSync, existsSync, mkdirSync, openSync, readdirSync,
|
|
3
|
-
import { readdir,
|
|
3
|
+
import { appendFileSync, closeSync, createReadStream, existsSync, mkdirSync, openSync, readdirSync, readSync, statSync, writeFileSync, } from "fs";
|
|
4
|
+
import { readdir, stat } from "fs/promises";
|
|
4
5
|
import { join, resolve } from "path";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
6
|
+
import { createInterface } from "readline";
|
|
7
|
+
import { StringDecoder } from "string_decoder";
|
|
8
|
+
import { APP_NAME, getSessionsDir } from "../config.js";
|
|
9
|
+
import { normalizePath, resolvePath } from "../utils/paths.js";
|
|
7
10
|
import { createBranchSummaryMessage, createCompactionSummaryMessage, createCustomMessage, } from "./messages.js";
|
|
8
11
|
export const CURRENT_SESSION_VERSION = 3;
|
|
9
12
|
function createSessionId() {
|
|
10
13
|
return uuidv7();
|
|
11
14
|
}
|
|
15
|
+
export function assertValidSessionId(id) {
|
|
16
|
+
if (!/^[A-Za-z0-9](?:[A-Za-z0-9._-]*[A-Za-z0-9])?$/.test(id)) {
|
|
17
|
+
throw new Error("Session id must be non-empty, contain only alphanumeric characters, '-', '_', and '.', and start and end with an alphanumeric character");
|
|
18
|
+
}
|
|
19
|
+
}
|
|
12
20
|
/** Generate a unique short ID (8 hex chars, collision-checked) */
|
|
13
21
|
function generateId(byId) {
|
|
14
22
|
for (let i = 0; i < 100; i++) {
|
|
@@ -104,46 +112,40 @@ export function getLatestCompactionEntry(entries) {
|
|
|
104
112
|
}
|
|
105
113
|
return null;
|
|
106
114
|
}
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
// Build uuid index if not available
|
|
114
|
-
if (!byId) {
|
|
115
|
-
byId = new Map();
|
|
116
|
-
for (const entry of entries) {
|
|
117
|
-
byId.set(entry.id, entry);
|
|
118
|
-
}
|
|
115
|
+
function buildEntryIndex(entries, byId) {
|
|
116
|
+
if (byId)
|
|
117
|
+
return byId;
|
|
118
|
+
const index = new Map();
|
|
119
|
+
for (const entry of entries) {
|
|
120
|
+
index.set(entry.id, entry);
|
|
119
121
|
}
|
|
120
|
-
|
|
122
|
+
return index;
|
|
123
|
+
}
|
|
124
|
+
function buildSessionPath(entries, leafId, byId) {
|
|
125
|
+
const index = buildEntryIndex(entries, byId);
|
|
121
126
|
let leaf;
|
|
122
127
|
if (leafId === null) {
|
|
123
|
-
|
|
124
|
-
return { messages: [], thinkingLevel: "off", model: null };
|
|
128
|
+
return [];
|
|
125
129
|
}
|
|
126
130
|
if (leafId) {
|
|
127
|
-
leaf =
|
|
131
|
+
leaf = index.get(leafId);
|
|
128
132
|
}
|
|
133
|
+
leaf ??= entries[entries.length - 1];
|
|
129
134
|
if (!leaf) {
|
|
130
|
-
|
|
131
|
-
leaf = entries[entries.length - 1];
|
|
132
|
-
}
|
|
133
|
-
if (!leaf) {
|
|
134
|
-
return { messages: [], thinkingLevel: "off", model: null };
|
|
135
|
+
return [];
|
|
135
136
|
}
|
|
136
|
-
// Walk from leaf to root, collecting path
|
|
137
137
|
const path = [];
|
|
138
138
|
let current = leaf;
|
|
139
139
|
while (current) {
|
|
140
|
-
path.
|
|
141
|
-
current = current.parentId ?
|
|
140
|
+
path.push(current);
|
|
141
|
+
current = current.parentId ? index.get(current.parentId) : undefined;
|
|
142
142
|
}
|
|
143
|
-
|
|
143
|
+
path.reverse();
|
|
144
|
+
return path;
|
|
145
|
+
}
|
|
146
|
+
function getSessionContextSettings(path) {
|
|
144
147
|
let thinkingLevel = "off";
|
|
145
148
|
let model = null;
|
|
146
|
-
let compaction = null;
|
|
147
149
|
for (const entry of path) {
|
|
148
150
|
if (entry.type === "thinking_level_change") {
|
|
149
151
|
thinkingLevel = entry.thinkingLevel;
|
|
@@ -154,86 +156,157 @@ export function buildSessionContext(entries, leafId, byId) {
|
|
|
154
156
|
else if (entry.type === "message" && entry.message.role === "assistant") {
|
|
155
157
|
model = { provider: entry.message.provider, modelId: entry.message.model };
|
|
156
158
|
}
|
|
157
|
-
else if (entry.type === "compaction") {
|
|
158
|
-
compaction = entry;
|
|
159
|
-
}
|
|
160
159
|
}
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
messages.push(createBranchSummaryMessage(entry.summary, entry.fromId, entry.timestamp));
|
|
176
|
-
}
|
|
177
|
-
};
|
|
178
|
-
if (compaction) {
|
|
179
|
-
// Emit summary first
|
|
180
|
-
messages.push(createCompactionSummaryMessage(compaction.summary, compaction.tokensBefore, compaction.timestamp));
|
|
181
|
-
// Find compaction index in path
|
|
182
|
-
const compactionIdx = path.findIndex((e) => e.type === "compaction" && e.id === compaction.id);
|
|
183
|
-
// Emit kept messages (before compaction, starting from firstKeptEntryId)
|
|
184
|
-
let foundFirstKept = false;
|
|
185
|
-
for (let i = 0; i < compactionIdx; i++) {
|
|
186
|
-
const entry = path[i];
|
|
187
|
-
if (entry.id === compaction.firstKeptEntryId) {
|
|
188
|
-
foundFirstKept = true;
|
|
189
|
-
}
|
|
190
|
-
if (foundFirstKept) {
|
|
191
|
-
appendMessage(entry);
|
|
192
|
-
}
|
|
160
|
+
return { thinkingLevel, model };
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Project one selected session entry into LLM/runtime messages.
|
|
164
|
+
* Plain custom entries are display/state entries and do not participate in context.
|
|
165
|
+
*/
|
|
166
|
+
export function sessionEntryToContextMessages(entry) {
|
|
167
|
+
if (entry.type === "message") {
|
|
168
|
+
const message = entry.message;
|
|
169
|
+
// Session files are parsed without validation; old versions, forks, or
|
|
170
|
+
// hand-edited files can contain messages with null/missing content.
|
|
171
|
+
if ((message.role === "user" || message.role === "assistant" || message.role === "toolResult") &&
|
|
172
|
+
message.content == null) {
|
|
173
|
+
return [{ ...message, content: [] }];
|
|
193
174
|
}
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
175
|
+
return [message];
|
|
176
|
+
}
|
|
177
|
+
if (entry.type === "custom_message") {
|
|
178
|
+
return [
|
|
179
|
+
createCustomMessage(entry.customType, entry.content ?? [], entry.display, entry.details, entry.timestamp),
|
|
180
|
+
];
|
|
181
|
+
}
|
|
182
|
+
if (entry.type === "branch_summary" && entry.summary) {
|
|
183
|
+
return [createBranchSummaryMessage(entry.summary, entry.fromId, entry.timestamp)];
|
|
184
|
+
}
|
|
185
|
+
if (entry.type === "compaction") {
|
|
186
|
+
return [createCompactionSummaryMessage(entry.summary, entry.tokensBefore, entry.timestamp)];
|
|
187
|
+
}
|
|
188
|
+
return [];
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Build the active, compaction-aware session entry list.
|
|
192
|
+
*
|
|
193
|
+
* This follows the current leaf path. If the path contains compaction entries,
|
|
194
|
+
* the latest compaction is represented by the compaction entry itself, followed
|
|
195
|
+
* by the kept entries starting at firstKeptEntryId and all entries after the
|
|
196
|
+
* compaction entry. Older summarized entries are omitted.
|
|
197
|
+
*/
|
|
198
|
+
export function buildContextEntries(entries, leafId, byId) {
|
|
199
|
+
const path = buildSessionPath(entries, leafId, byId);
|
|
200
|
+
let compaction = null;
|
|
201
|
+
for (const entry of path) {
|
|
202
|
+
if (entry.type === "compaction") {
|
|
203
|
+
compaction = entry;
|
|
198
204
|
}
|
|
199
205
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
206
|
+
if (!compaction) {
|
|
207
|
+
return path;
|
|
208
|
+
}
|
|
209
|
+
const compactionIdx = path.findIndex((entry) => entry.id === compaction.id);
|
|
210
|
+
if (compactionIdx < 0) {
|
|
211
|
+
return path;
|
|
212
|
+
}
|
|
213
|
+
const contextEntries = [compaction];
|
|
214
|
+
let foundFirstKept = false;
|
|
215
|
+
for (let i = 0; i < compactionIdx; i++) {
|
|
216
|
+
const entry = path[i];
|
|
217
|
+
if (entry.id === compaction.firstKeptEntryId) {
|
|
218
|
+
foundFirstKept = true;
|
|
219
|
+
}
|
|
220
|
+
if (foundFirstKept) {
|
|
221
|
+
contextEntries.push(entry);
|
|
204
222
|
}
|
|
205
223
|
}
|
|
224
|
+
contextEntries.push(...path.slice(compactionIdx + 1));
|
|
225
|
+
return contextEntries;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Build the session context from entries using tree traversal.
|
|
229
|
+
* If leafId is provided, walks from that entry to root.
|
|
230
|
+
* Handles compaction and branch summaries along the path.
|
|
231
|
+
*/
|
|
232
|
+
export function buildSessionContext(entries, leafId, byId) {
|
|
233
|
+
const path = buildSessionPath(entries, leafId, byId);
|
|
234
|
+
const { thinkingLevel, model } = getSessionContextSettings(path);
|
|
235
|
+
const messages = buildContextEntries(entries, leafId, byId).flatMap(sessionEntryToContextMessages);
|
|
206
236
|
return { messages, thinkingLevel, model };
|
|
207
237
|
}
|
|
208
238
|
/**
|
|
209
239
|
* Compute the default session directory for a cwd.
|
|
210
|
-
* Encodes cwd into a safe directory name under
|
|
240
|
+
* Encodes cwd into a safe directory name under the mcpi state sessions directory.
|
|
211
241
|
*/
|
|
212
|
-
|
|
213
|
-
const
|
|
214
|
-
const
|
|
242
|
+
function getDefaultSessionDirPath(cwd, agentDir) {
|
|
243
|
+
const resolvedCwd = resolvePath(cwd);
|
|
244
|
+
const resolvedSessionsDir = agentDir ? join(resolvePath(agentDir), "sessions") : getSessionsDir();
|
|
245
|
+
const safePath = `--${resolvedCwd.replace(/^[/\\]/, "").replace(/[/\\:]/g, "-")}--`;
|
|
246
|
+
return join(resolvedSessionsDir, safePath);
|
|
247
|
+
}
|
|
248
|
+
export function getDefaultSessionDir(cwd, agentDir) {
|
|
249
|
+
const sessionDir = getDefaultSessionDirPath(cwd, agentDir);
|
|
215
250
|
if (!existsSync(sessionDir)) {
|
|
216
251
|
mkdirSync(sessionDir, { recursive: true });
|
|
217
252
|
}
|
|
218
253
|
return sessionDir;
|
|
219
254
|
}
|
|
255
|
+
const SESSION_READ_BUFFER_SIZE = 1024 * 1024;
|
|
256
|
+
const SESSION_HEADER_READ_BUFFER_SIZE = 4096;
|
|
257
|
+
/** Bound synchronous header discovery while allowing large cwd and custom metadata fields. */
|
|
258
|
+
const MAX_SESSION_HEADER_SCAN_BYTES = 1024 * 1024;
|
|
259
|
+
class SessionHeaderScanLimitError extends Error {
|
|
260
|
+
constructor(filePath) {
|
|
261
|
+
super(`Session header exceeds ${MAX_SESSION_HEADER_SCAN_BYTES}-byte scan limit: ${filePath}`);
|
|
262
|
+
this.name = "SessionHeaderScanLimitError";
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
function parseSessionEntryLine(line) {
|
|
266
|
+
if (!line.trim())
|
|
267
|
+
return null;
|
|
268
|
+
try {
|
|
269
|
+
return JSON.parse(line);
|
|
270
|
+
}
|
|
271
|
+
catch {
|
|
272
|
+
// Skip malformed lines
|
|
273
|
+
return null;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
220
276
|
/** Exported for testing */
|
|
221
277
|
export function loadEntriesFromFile(filePath) {
|
|
222
|
-
|
|
278
|
+
const resolvedFilePath = normalizePath(filePath);
|
|
279
|
+
if (!existsSync(resolvedFilePath))
|
|
223
280
|
return [];
|
|
224
|
-
const content = readFileSync(filePath, "utf8");
|
|
225
281
|
const entries = [];
|
|
226
|
-
const
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
282
|
+
const fd = openSync(resolvedFilePath, "r");
|
|
283
|
+
try {
|
|
284
|
+
const decoder = new StringDecoder("utf8");
|
|
285
|
+
const buffer = Buffer.allocUnsafe(SESSION_READ_BUFFER_SIZE);
|
|
286
|
+
let pending = "";
|
|
287
|
+
while (true) {
|
|
288
|
+
const bytesRead = readSync(fd, buffer, 0, buffer.length, null);
|
|
289
|
+
if (bytesRead === 0)
|
|
290
|
+
break;
|
|
291
|
+
pending += decoder.write(buffer.subarray(0, bytesRead));
|
|
292
|
+
let lineStart = 0;
|
|
293
|
+
let newlineIndex = pending.indexOf("\n", lineStart);
|
|
294
|
+
while (newlineIndex !== -1) {
|
|
295
|
+
const entry = parseSessionEntryLine(pending.slice(lineStart, newlineIndex));
|
|
296
|
+
if (entry)
|
|
297
|
+
entries.push(entry);
|
|
298
|
+
lineStart = newlineIndex + 1;
|
|
299
|
+
newlineIndex = pending.indexOf("\n", lineStart);
|
|
300
|
+
}
|
|
301
|
+
pending = pending.slice(lineStart);
|
|
236
302
|
}
|
|
303
|
+
pending += decoder.end();
|
|
304
|
+
const finalEntry = parseSessionEntryLine(pending);
|
|
305
|
+
if (finalEntry)
|
|
306
|
+
entries.push(finalEntry);
|
|
307
|
+
}
|
|
308
|
+
finally {
|
|
309
|
+
closeSync(fd);
|
|
237
310
|
}
|
|
238
311
|
// Validate session header
|
|
239
312
|
if (entries.length === 0)
|
|
@@ -244,34 +317,97 @@ export function loadEntriesFromFile(filePath) {
|
|
|
244
317
|
}
|
|
245
318
|
return entries;
|
|
246
319
|
}
|
|
247
|
-
|
|
320
|
+
/**
|
|
321
|
+
* Inspect a physical line while searching for the first parsed session entry.
|
|
322
|
+
* Blank and malformed lines are skipped to match loadEntriesFromFile().
|
|
323
|
+
* Returns undefined to keep scanning, null for a parsed non-header entry, or the header.
|
|
324
|
+
*/
|
|
325
|
+
function parseSessionHeaderCandidate(line) {
|
|
326
|
+
if (!line.trim())
|
|
327
|
+
return undefined;
|
|
328
|
+
const entry = parseSessionEntryLine(line);
|
|
329
|
+
if (!entry)
|
|
330
|
+
return undefined;
|
|
331
|
+
if (entry.type !== "session" || typeof entry.id !== "string")
|
|
332
|
+
return null;
|
|
333
|
+
return entry;
|
|
334
|
+
}
|
|
335
|
+
function readSessionHeader(filePath) {
|
|
336
|
+
const fd = openSync(filePath, "r");
|
|
248
337
|
try {
|
|
249
|
-
const
|
|
250
|
-
const buffer = Buffer.
|
|
251
|
-
const
|
|
338
|
+
const decoder = new StringDecoder("utf8");
|
|
339
|
+
const buffer = Buffer.allocUnsafe(SESSION_HEADER_READ_BUFFER_SIZE);
|
|
340
|
+
const lineChunks = [];
|
|
341
|
+
let scannedBytes = 0;
|
|
342
|
+
while (scannedBytes < MAX_SESSION_HEADER_SCAN_BYTES) {
|
|
343
|
+
const readLength = Math.min(buffer.length, MAX_SESSION_HEADER_SCAN_BYTES - scannedBytes);
|
|
344
|
+
const bytesRead = readSync(fd, buffer, 0, readLength, null);
|
|
345
|
+
if (bytesRead === 0) {
|
|
346
|
+
lineChunks.push(decoder.end());
|
|
347
|
+
return parseSessionHeaderCandidate(lineChunks.join("")) ?? null;
|
|
348
|
+
}
|
|
349
|
+
scannedBytes += bytesRead;
|
|
350
|
+
const chunk = decoder.write(buffer.subarray(0, bytesRead));
|
|
351
|
+
let lineStart = 0;
|
|
352
|
+
let newlineIndex = chunk.indexOf("\n", lineStart);
|
|
353
|
+
while (newlineIndex !== -1) {
|
|
354
|
+
lineChunks.push(chunk.slice(lineStart, newlineIndex));
|
|
355
|
+
const header = parseSessionHeaderCandidate(lineChunks.join(""));
|
|
356
|
+
if (header !== undefined)
|
|
357
|
+
return header;
|
|
358
|
+
lineChunks.length = 0;
|
|
359
|
+
lineStart = newlineIndex + 1;
|
|
360
|
+
newlineIndex = chunk.indexOf("\n", lineStart);
|
|
361
|
+
}
|
|
362
|
+
lineChunks.push(chunk.slice(lineStart));
|
|
363
|
+
}
|
|
364
|
+
// Probe for EOF so a final header without a newline is allowed when it ends
|
|
365
|
+
// exactly at the scan limit. Any additional byte exceeds the bounded scan.
|
|
366
|
+
const probe = Buffer.allocUnsafe(1);
|
|
367
|
+
if (readSync(fd, probe, 0, probe.length, null) === 0) {
|
|
368
|
+
lineChunks.push(decoder.end());
|
|
369
|
+
return parseSessionHeaderCandidate(lineChunks.join("")) ?? null;
|
|
370
|
+
}
|
|
371
|
+
throw new SessionHeaderScanLimitError(filePath);
|
|
372
|
+
}
|
|
373
|
+
finally {
|
|
252
374
|
closeSync(fd);
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
return
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
function readSessionHeaderForDiscovery(filePath) {
|
|
378
|
+
try {
|
|
379
|
+
return readSessionHeader(filePath);
|
|
258
380
|
}
|
|
259
381
|
catch {
|
|
260
|
-
|
|
382
|
+
// Discovery is best-effort: unreadable or oversized files are not sessions,
|
|
383
|
+
// and one corrupt file must not prevent other sessions from being found.
|
|
384
|
+
return null;
|
|
261
385
|
}
|
|
262
386
|
}
|
|
387
|
+
function getSessionHeaderCwd(header) {
|
|
388
|
+
const cwd = header.cwd;
|
|
389
|
+
return typeof cwd === "string" ? cwd : undefined;
|
|
390
|
+
}
|
|
391
|
+
function sessionCwdMatches(cwd, resolvedCwd) {
|
|
392
|
+
return cwd !== undefined && cwd !== "" && resolvePath(cwd) === resolvedCwd;
|
|
393
|
+
}
|
|
263
394
|
/** Exported for testing */
|
|
264
|
-
export function findMostRecentSession(sessionDir) {
|
|
395
|
+
export function findMostRecentSession(sessionDir, cwd) {
|
|
396
|
+
const resolvedSessionDir = normalizePath(sessionDir);
|
|
397
|
+
const resolvedCwd = cwd ? resolvePath(cwd) : undefined;
|
|
265
398
|
try {
|
|
266
|
-
const files = readdirSync(
|
|
399
|
+
const files = readdirSync(resolvedSessionDir)
|
|
267
400
|
.filter((f) => f.endsWith(".jsonl"))
|
|
268
|
-
.map((f) => join(
|
|
269
|
-
.
|
|
270
|
-
.
|
|
401
|
+
.map((f) => join(resolvedSessionDir, f))
|
|
402
|
+
.map((path) => ({ path, header: readSessionHeaderForDiscovery(path) }))
|
|
403
|
+
.filter((file) => file.header !== null &&
|
|
404
|
+
(!resolvedCwd || sessionCwdMatches(getSessionHeaderCwd(file.header), resolvedCwd)))
|
|
405
|
+
.map(({ path }) => ({ path, mtime: statSync(path).mtime }))
|
|
271
406
|
.sort((a, b) => b.mtime.getTime() - a.mtime.getTime());
|
|
272
407
|
return files[0]?.path || null;
|
|
273
408
|
}
|
|
274
409
|
catch {
|
|
410
|
+
// Directory access and stat races make recent-session discovery unavailable.
|
|
275
411
|
return null;
|
|
276
412
|
}
|
|
277
413
|
}
|
|
@@ -288,73 +424,53 @@ function extractTextContent(message) {
|
|
|
288
424
|
.map((block) => block.text)
|
|
289
425
|
.join(" ");
|
|
290
426
|
}
|
|
291
|
-
function
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
continue;
|
|
301
|
-
const msgTimestamp = message.timestamp;
|
|
302
|
-
if (typeof msgTimestamp === "number") {
|
|
303
|
-
lastActivityTime = Math.max(lastActivityTime ?? 0, msgTimestamp);
|
|
304
|
-
continue;
|
|
305
|
-
}
|
|
306
|
-
const entryTimestamp = entry.timestamp;
|
|
307
|
-
if (typeof entryTimestamp === "string") {
|
|
308
|
-
const t = new Date(entryTimestamp).getTime();
|
|
309
|
-
if (!Number.isNaN(t)) {
|
|
310
|
-
lastActivityTime = Math.max(lastActivityTime ?? 0, t);
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
return lastActivityTime;
|
|
315
|
-
}
|
|
316
|
-
function getSessionModifiedDate(entries, header, statsMtime) {
|
|
317
|
-
const lastActivityTime = getLastActivityTime(entries);
|
|
318
|
-
if (typeof lastActivityTime === "number" && lastActivityTime > 0) {
|
|
319
|
-
return new Date(lastActivityTime);
|
|
427
|
+
function getMessageActivityTime(entry) {
|
|
428
|
+
const message = entry.message;
|
|
429
|
+
if (!isMessageWithContent(message))
|
|
430
|
+
return undefined;
|
|
431
|
+
if (message.role !== "user" && message.role !== "assistant")
|
|
432
|
+
return undefined;
|
|
433
|
+
const msgTimestamp = message.timestamp;
|
|
434
|
+
if (typeof msgTimestamp === "number") {
|
|
435
|
+
return msgTimestamp;
|
|
320
436
|
}
|
|
321
|
-
const
|
|
322
|
-
return
|
|
437
|
+
const t = new Date(entry.timestamp).getTime();
|
|
438
|
+
return Number.isNaN(t) ? undefined : t;
|
|
323
439
|
}
|
|
324
440
|
async function buildSessionInfo(filePath) {
|
|
325
441
|
try {
|
|
326
|
-
const content = await readFile(filePath, "utf8");
|
|
327
|
-
const entries = [];
|
|
328
|
-
const lines = content.trim().split("\n");
|
|
329
|
-
for (const line of lines) {
|
|
330
|
-
if (!line.trim())
|
|
331
|
-
continue;
|
|
332
|
-
try {
|
|
333
|
-
entries.push(JSON.parse(line));
|
|
334
|
-
}
|
|
335
|
-
catch {
|
|
336
|
-
// Skip malformed lines
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
if (entries.length === 0)
|
|
340
|
-
return null;
|
|
341
|
-
const header = entries[0];
|
|
342
|
-
if (header.type !== "session")
|
|
343
|
-
return null;
|
|
344
442
|
const stats = await stat(filePath);
|
|
443
|
+
let header = null;
|
|
345
444
|
let messageCount = 0;
|
|
346
445
|
let firstMessage = "";
|
|
347
446
|
const allMessages = [];
|
|
348
447
|
let name;
|
|
349
|
-
|
|
448
|
+
let lastActivityTime;
|
|
449
|
+
const rl = createInterface({
|
|
450
|
+
input: createReadStream(filePath, { encoding: "utf8" }),
|
|
451
|
+
crlfDelay: Infinity,
|
|
452
|
+
});
|
|
453
|
+
for await (const line of rl) {
|
|
454
|
+
const entry = parseSessionEntryLine(line);
|
|
455
|
+
if (!entry)
|
|
456
|
+
continue;
|
|
457
|
+
if (!header) {
|
|
458
|
+
if (entry.type !== "session")
|
|
459
|
+
return null;
|
|
460
|
+
header = entry;
|
|
461
|
+
continue;
|
|
462
|
+
}
|
|
350
463
|
// Extract session name (use latest, including explicit clears)
|
|
351
464
|
if (entry.type === "session_info") {
|
|
352
|
-
|
|
353
|
-
name = infoEntry.name?.trim() || undefined;
|
|
465
|
+
name = entry.name?.trim() || undefined;
|
|
354
466
|
}
|
|
355
467
|
if (entry.type !== "message")
|
|
356
468
|
continue;
|
|
357
469
|
messageCount++;
|
|
470
|
+
const activityTime = getMessageActivityTime(entry);
|
|
471
|
+
if (typeof activityTime === "number") {
|
|
472
|
+
lastActivityTime = Math.max(lastActivityTime ?? 0, activityTime);
|
|
473
|
+
}
|
|
358
474
|
const message = entry.message;
|
|
359
475
|
if (!isMessageWithContent(message))
|
|
360
476
|
continue;
|
|
@@ -368,9 +484,16 @@ async function buildSessionInfo(filePath) {
|
|
|
368
484
|
firstMessage = textContent;
|
|
369
485
|
}
|
|
370
486
|
}
|
|
487
|
+
if (!header)
|
|
488
|
+
return null;
|
|
371
489
|
const cwd = typeof header.cwd === "string" ? header.cwd : "";
|
|
372
490
|
const parentSessionPath = header.parentSession;
|
|
373
|
-
const
|
|
491
|
+
const headerTime = typeof header.timestamp === "string" ? new Date(header.timestamp).getTime() : NaN;
|
|
492
|
+
const modified = typeof lastActivityTime === "number" && lastActivityTime > 0
|
|
493
|
+
? new Date(lastActivityTime)
|
|
494
|
+
: !Number.isNaN(headerTime)
|
|
495
|
+
? new Date(headerTime)
|
|
496
|
+
: stats.mtime;
|
|
374
497
|
return {
|
|
375
498
|
path: filePath,
|
|
376
499
|
id: header.id,
|
|
@@ -388,6 +511,40 @@ async function buildSessionInfo(filePath) {
|
|
|
388
511
|
return null;
|
|
389
512
|
}
|
|
390
513
|
}
|
|
514
|
+
const MAX_CONCURRENT_SESSION_INFO_LOADS = 10;
|
|
515
|
+
async function buildSessionInfosWithConcurrency(files, onLoaded) {
|
|
516
|
+
const results = new Array(files.length).fill(null);
|
|
517
|
+
const inFlight = new Set();
|
|
518
|
+
let nextIndex = 0;
|
|
519
|
+
const startNext = () => {
|
|
520
|
+
const index = nextIndex++;
|
|
521
|
+
const file = files[index];
|
|
522
|
+
if (!file)
|
|
523
|
+
return;
|
|
524
|
+
let task;
|
|
525
|
+
task = buildSessionInfo(file)
|
|
526
|
+
.then((info) => {
|
|
527
|
+
results[index] = info;
|
|
528
|
+
})
|
|
529
|
+
.catch(() => {
|
|
530
|
+
results[index] = null;
|
|
531
|
+
})
|
|
532
|
+
.finally(() => {
|
|
533
|
+
inFlight.delete(task);
|
|
534
|
+
onLoaded();
|
|
535
|
+
});
|
|
536
|
+
inFlight.add(task);
|
|
537
|
+
};
|
|
538
|
+
while (nextIndex < files.length || inFlight.size > 0) {
|
|
539
|
+
while (nextIndex < files.length && inFlight.size < MAX_CONCURRENT_SESSION_INFO_LOADS) {
|
|
540
|
+
startNext();
|
|
541
|
+
}
|
|
542
|
+
if (inFlight.size > 0) {
|
|
543
|
+
await Promise.race(inFlight);
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
return results;
|
|
547
|
+
}
|
|
391
548
|
async function listSessionsFromDir(dir, onProgress, progressOffset = 0, progressTotal) {
|
|
392
549
|
const sessions = [];
|
|
393
550
|
if (!existsSync(dir)) {
|
|
@@ -398,12 +555,10 @@ async function listSessionsFromDir(dir, onProgress, progressOffset = 0, progress
|
|
|
398
555
|
const files = dirEntries.filter((f) => f.endsWith(".jsonl")).map((f) => join(dir, f));
|
|
399
556
|
const total = progressTotal ?? files.length;
|
|
400
557
|
let loaded = 0;
|
|
401
|
-
const results = await
|
|
402
|
-
const info = await buildSessionInfo(file);
|
|
558
|
+
const results = await buildSessionInfosWithConcurrency(files, () => {
|
|
403
559
|
loaded++;
|
|
404
560
|
onProgress?.(progressOffset + loaded, total);
|
|
405
|
-
|
|
406
|
-
}));
|
|
561
|
+
});
|
|
407
562
|
for (const info of results) {
|
|
408
563
|
if (info) {
|
|
409
564
|
sessions.push(info);
|
|
@@ -438,29 +593,35 @@ export class SessionManager {
|
|
|
438
593
|
labelsById = new Map();
|
|
439
594
|
labelTimestampsById = new Map();
|
|
440
595
|
leafId = null;
|
|
441
|
-
constructor(cwd, sessionDir, sessionFile, persist) {
|
|
442
|
-
this.cwd = cwd;
|
|
443
|
-
this.sessionDir = sessionDir;
|
|
596
|
+
constructor(cwd, sessionDir, sessionFile, persist, newSessionOptions, preloadedFileEntries) {
|
|
597
|
+
this.cwd = resolvePath(cwd);
|
|
598
|
+
this.sessionDir = normalizePath(sessionDir);
|
|
444
599
|
this.persist = persist;
|
|
445
|
-
if (persist && sessionDir && !existsSync(sessionDir)) {
|
|
446
|
-
mkdirSync(sessionDir, { recursive: true });
|
|
600
|
+
if (persist && this.sessionDir && !existsSync(this.sessionDir)) {
|
|
601
|
+
mkdirSync(this.sessionDir, { recursive: true });
|
|
447
602
|
}
|
|
448
603
|
if (sessionFile) {
|
|
449
|
-
this.
|
|
604
|
+
this._setSessionFile(sessionFile, preloadedFileEntries);
|
|
450
605
|
}
|
|
451
606
|
else {
|
|
452
|
-
this.newSession();
|
|
607
|
+
this.newSession(newSessionOptions);
|
|
453
608
|
}
|
|
454
609
|
}
|
|
455
610
|
/** Switch to a different session file (used for resume and branching) */
|
|
456
611
|
setSessionFile(sessionFile) {
|
|
457
|
-
this.
|
|
612
|
+
this._setSessionFile(sessionFile);
|
|
613
|
+
}
|
|
614
|
+
_setSessionFile(sessionFile, preloadedFileEntries) {
|
|
615
|
+
this.sessionFile = resolvePath(sessionFile);
|
|
458
616
|
if (existsSync(this.sessionFile)) {
|
|
459
|
-
this.fileEntries = loadEntriesFromFile(this.sessionFile);
|
|
460
|
-
// If file was empty
|
|
461
|
-
//
|
|
617
|
+
this.fileEntries = preloadedFileEntries ?? loadEntriesFromFile(this.sessionFile);
|
|
618
|
+
// If file was empty, initialize it with a valid session header. If it was
|
|
619
|
+
// non-empty but did not parse as an mcpi session, fail without modifying it.
|
|
462
620
|
if (this.fileEntries.length === 0) {
|
|
463
621
|
const explicitPath = this.sessionFile;
|
|
622
|
+
if (statSync(explicitPath).size > 0) {
|
|
623
|
+
throw new Error(`Session file is not a valid ${APP_NAME} session: ${explicitPath}`);
|
|
624
|
+
}
|
|
464
625
|
this.newSession();
|
|
465
626
|
this.sessionFile = explicitPath;
|
|
466
627
|
this._rewriteFile();
|
|
@@ -482,6 +643,9 @@ export class SessionManager {
|
|
|
482
643
|
}
|
|
483
644
|
}
|
|
484
645
|
newSession(options) {
|
|
646
|
+
if (options?.id !== undefined) {
|
|
647
|
+
assertValidSessionId(options.id);
|
|
648
|
+
}
|
|
485
649
|
this.sessionId = options?.id ?? createSessionId();
|
|
486
650
|
const timestamp = new Date().toISOString();
|
|
487
651
|
const header = {
|
|
@@ -495,6 +659,7 @@ export class SessionManager {
|
|
|
495
659
|
this.fileEntries = [header];
|
|
496
660
|
this.byId.clear();
|
|
497
661
|
this.labelsById.clear();
|
|
662
|
+
this.labelTimestampsById.clear();
|
|
498
663
|
this.leafId = null;
|
|
499
664
|
this.flushed = false;
|
|
500
665
|
if (this.persist) {
|
|
@@ -528,8 +693,15 @@ export class SessionManager {
|
|
|
528
693
|
_rewriteFile() {
|
|
529
694
|
if (!this.persist || !this.sessionFile)
|
|
530
695
|
return;
|
|
531
|
-
const
|
|
532
|
-
|
|
696
|
+
const fd = openSync(this.sessionFile, "w");
|
|
697
|
+
try {
|
|
698
|
+
for (const entry of this.fileEntries) {
|
|
699
|
+
writeFileSync(fd, `${JSON.stringify(entry)}\n`);
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
finally {
|
|
703
|
+
closeSync(fd);
|
|
704
|
+
}
|
|
533
705
|
}
|
|
534
706
|
isPersisted() {
|
|
535
707
|
return this.persist;
|
|
@@ -540,6 +712,9 @@ export class SessionManager {
|
|
|
540
712
|
getSessionDir() {
|
|
541
713
|
return this.sessionDir;
|
|
542
714
|
}
|
|
715
|
+
usesDefaultSessionDir() {
|
|
716
|
+
return this.sessionDir === getDefaultSessionDirPath(this.cwd);
|
|
717
|
+
}
|
|
543
718
|
getSessionId() {
|
|
544
719
|
return this.sessionId;
|
|
545
720
|
}
|
|
@@ -551,13 +726,24 @@ export class SessionManager {
|
|
|
551
726
|
return;
|
|
552
727
|
const hasAssistant = this.fileEntries.some((e) => e.type === "message" && e.message.role === "assistant");
|
|
553
728
|
if (!hasAssistant) {
|
|
554
|
-
|
|
555
|
-
|
|
729
|
+
if (this.flushed) {
|
|
730
|
+
appendFileSync(this.sessionFile, `${JSON.stringify(entry)}\n`);
|
|
731
|
+
}
|
|
732
|
+
else {
|
|
733
|
+
// Mark as not flushed so when assistant arrives, all entries get written
|
|
734
|
+
this.flushed = false;
|
|
735
|
+
}
|
|
556
736
|
return;
|
|
557
737
|
}
|
|
558
738
|
if (!this.flushed) {
|
|
559
|
-
|
|
560
|
-
|
|
739
|
+
const fd = openSync(this.sessionFile, "wx");
|
|
740
|
+
try {
|
|
741
|
+
for (const e of this.fileEntries) {
|
|
742
|
+
writeFileSync(fd, `${JSON.stringify(e)}\n`);
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
finally {
|
|
746
|
+
closeSync(fd);
|
|
561
747
|
}
|
|
562
748
|
this.flushed = true;
|
|
563
749
|
}
|
|
@@ -614,7 +800,7 @@ export class SessionManager {
|
|
|
614
800
|
return entry.id;
|
|
615
801
|
}
|
|
616
802
|
/** Append a compaction summary as child of current leaf, then advance leaf. Returns entry id. */
|
|
617
|
-
appendCompaction(summary, firstKeptEntryId, tokensBefore, details, fromHook) {
|
|
803
|
+
appendCompaction(summary, firstKeptEntryId, tokensBefore, details, fromHook, usage) {
|
|
618
804
|
const entry = {
|
|
619
805
|
type: "compaction",
|
|
620
806
|
id: generateId(this.byId),
|
|
@@ -624,6 +810,7 @@ export class SessionManager {
|
|
|
624
810
|
firstKeptEntryId,
|
|
625
811
|
tokensBefore,
|
|
626
812
|
details,
|
|
813
|
+
usage,
|
|
627
814
|
fromHook,
|
|
628
815
|
};
|
|
629
816
|
this._appendEntry(entry);
|
|
@@ -644,12 +831,13 @@ export class SessionManager {
|
|
|
644
831
|
}
|
|
645
832
|
/** Append a session info entry (e.g., display name). Returns entry id. */
|
|
646
833
|
appendSessionInfo(name) {
|
|
834
|
+
const sanitizedName = name.replace(/[\r\n]+/g, " ").trim();
|
|
647
835
|
const entry = {
|
|
648
836
|
type: "session_info",
|
|
649
837
|
id: generateId(this.byId),
|
|
650
838
|
parentId: this.leafId,
|
|
651
839
|
timestamp: new Date().toISOString(),
|
|
652
|
-
name:
|
|
840
|
+
name: sanitizedName,
|
|
653
841
|
};
|
|
654
842
|
this._appendEntry(entry);
|
|
655
843
|
return entry.id;
|
|
@@ -757,11 +945,19 @@ export class SessionManager {
|
|
|
757
945
|
const startId = fromId ?? this.leafId;
|
|
758
946
|
let current = startId ? this.byId.get(startId) : undefined;
|
|
759
947
|
while (current) {
|
|
760
|
-
path.
|
|
948
|
+
path.push(current);
|
|
761
949
|
current = current.parentId ? this.byId.get(current.parentId) : undefined;
|
|
762
950
|
}
|
|
951
|
+
path.reverse();
|
|
763
952
|
return path;
|
|
764
953
|
}
|
|
954
|
+
/**
|
|
955
|
+
* Build the active, compaction-aware entry list for context/rendering.
|
|
956
|
+
* Uses tree traversal from current leaf.
|
|
957
|
+
*/
|
|
958
|
+
buildContextEntries() {
|
|
959
|
+
return buildContextEntries(this.getEntries(), this.leafId, this.byId);
|
|
960
|
+
}
|
|
765
961
|
/**
|
|
766
962
|
* Build the session context (what gets sent to the LLM).
|
|
767
963
|
* Uses tree traversal from current leaf.
|
|
@@ -854,7 +1050,7 @@ export class SessionManager {
|
|
|
854
1050
|
* Same as branch(), but also appends a branch_summary entry that captures
|
|
855
1051
|
* context from the abandoned conversation path.
|
|
856
1052
|
*/
|
|
857
|
-
branchWithSummary(branchFromId, summary, details, fromHook) {
|
|
1053
|
+
branchWithSummary(branchFromId, summary, details, fromHook, usage) {
|
|
858
1054
|
if (branchFromId !== null && !this.byId.has(branchFromId)) {
|
|
859
1055
|
throw new Error(`Entry ${branchFromId} not found`);
|
|
860
1056
|
}
|
|
@@ -867,6 +1063,7 @@ export class SessionManager {
|
|
|
867
1063
|
fromId: branchFromId ?? "root",
|
|
868
1064
|
summary,
|
|
869
1065
|
details,
|
|
1066
|
+
usage,
|
|
870
1067
|
fromHook,
|
|
871
1068
|
};
|
|
872
1069
|
this._appendEntry(entry);
|
|
@@ -883,8 +1080,17 @@ export class SessionManager {
|
|
|
883
1080
|
if (path.length === 0) {
|
|
884
1081
|
throw new Error(`Entry ${leafId} not found`);
|
|
885
1082
|
}
|
|
886
|
-
// Filter out LabelEntry from path - we'll recreate them from the resolved map
|
|
887
|
-
|
|
1083
|
+
// Filter out LabelEntry from path - we'll recreate them from the resolved map.
|
|
1084
|
+
// Because labels are real tree entries, later entries can be children of labels;
|
|
1085
|
+
// removing labels requires re-chaining the retained path to avoid orphaned subtrees.
|
|
1086
|
+
const pathWithoutLabels = [];
|
|
1087
|
+
let pathParentId = null;
|
|
1088
|
+
for (const entry of path) {
|
|
1089
|
+
if (entry.type === "label")
|
|
1090
|
+
continue;
|
|
1091
|
+
pathWithoutLabels.push({ ...entry, parentId: pathParentId });
|
|
1092
|
+
pathParentId = entry.id;
|
|
1093
|
+
}
|
|
888
1094
|
const newSessionId = createSessionId();
|
|
889
1095
|
const timestamp = new Date().toISOString();
|
|
890
1096
|
const fileTimestamp = timestamp.replace(/[:.]/g, "-");
|
|
@@ -965,11 +1171,11 @@ export class SessionManager {
|
|
|
965
1171
|
/**
|
|
966
1172
|
* Create a new session.
|
|
967
1173
|
* @param cwd Working directory (stored in session header)
|
|
968
|
-
* @param sessionDir Optional session directory. If omitted, uses
|
|
1174
|
+
* @param sessionDir Optional session directory. If omitted, uses the mcpi state sessions directory.
|
|
969
1175
|
*/
|
|
970
|
-
static create(cwd, sessionDir) {
|
|
971
|
-
const dir = sessionDir
|
|
972
|
-
return new SessionManager(cwd, dir, undefined, true);
|
|
1176
|
+
static create(cwd, sessionDir, options) {
|
|
1177
|
+
const dir = sessionDir ? normalizePath(sessionDir) : getDefaultSessionDir(cwd);
|
|
1178
|
+
return new SessionManager(cwd, dir, undefined, true, options);
|
|
973
1179
|
}
|
|
974
1180
|
/**
|
|
975
1181
|
* Open a specific session file.
|
|
@@ -978,30 +1184,45 @@ export class SessionManager {
|
|
|
978
1184
|
* @param cwdOverride Optional cwd override instead of the session header cwd.
|
|
979
1185
|
*/
|
|
980
1186
|
static open(path, sessionDir, cwdOverride) {
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
1187
|
+
const resolvedPath = resolvePath(path);
|
|
1188
|
+
let header = null;
|
|
1189
|
+
let preloadedFileEntries;
|
|
1190
|
+
if (cwdOverride === undefined && existsSync(resolvedPath)) {
|
|
1191
|
+
try {
|
|
1192
|
+
header = readSessionHeader(resolvedPath);
|
|
1193
|
+
}
|
|
1194
|
+
catch (error) {
|
|
1195
|
+
if (!(error instanceof SessionHeaderScanLimitError))
|
|
1196
|
+
throw error;
|
|
1197
|
+
// The bounded scan is only a discovery optimization. A full load remains
|
|
1198
|
+
// authoritative for legacy files with very large headers or prefixes.
|
|
1199
|
+
preloadedFileEntries = loadEntriesFromFile(resolvedPath);
|
|
1200
|
+
const firstEntry = preloadedFileEntries[0];
|
|
1201
|
+
header = firstEntry?.type === "session" ? firstEntry : null;
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
1204
|
+
const cwd = cwdOverride ?? (header ? getSessionHeaderCwd(header) : undefined) ?? process.cwd();
|
|
985
1205
|
// If no sessionDir provided, derive from file's parent directory
|
|
986
|
-
const dir = sessionDir
|
|
987
|
-
return new SessionManager(cwd, dir,
|
|
1206
|
+
const dir = sessionDir ? normalizePath(sessionDir) : resolve(resolvedPath, "..");
|
|
1207
|
+
return new SessionManager(cwd, dir, resolvedPath, true, undefined, preloadedFileEntries);
|
|
988
1208
|
}
|
|
989
1209
|
/**
|
|
990
1210
|
* Continue the most recent session, or create new if none.
|
|
991
1211
|
* @param cwd Working directory
|
|
992
|
-
* @param sessionDir Optional session directory. If omitted, uses
|
|
1212
|
+
* @param sessionDir Optional session directory. If omitted, uses the mcpi state sessions directory.
|
|
993
1213
|
*/
|
|
994
1214
|
static continueRecent(cwd, sessionDir) {
|
|
995
|
-
const dir = sessionDir
|
|
996
|
-
const
|
|
1215
|
+
const dir = sessionDir ? normalizePath(sessionDir) : getDefaultSessionDir(cwd);
|
|
1216
|
+
const filterCwd = sessionDir !== undefined && dir !== getDefaultSessionDirPath(cwd);
|
|
1217
|
+
const mostRecent = findMostRecentSession(dir, filterCwd ? cwd : undefined);
|
|
997
1218
|
if (mostRecent) {
|
|
998
1219
|
return new SessionManager(cwd, dir, mostRecent, true);
|
|
999
1220
|
}
|
|
1000
1221
|
return new SessionManager(cwd, dir, undefined, true);
|
|
1001
1222
|
}
|
|
1002
1223
|
/** Create an in-memory session (no file persistence) */
|
|
1003
|
-
static inMemory(cwd = process.cwd()) {
|
|
1004
|
-
return new SessionManager(cwd, "", undefined, false);
|
|
1224
|
+
static inMemory(cwd = process.cwd(), options) {
|
|
1225
|
+
return new SessionManager(cwd, "", undefined, false, options);
|
|
1005
1226
|
}
|
|
1006
1227
|
/**
|
|
1007
1228
|
* Fork a session from another project directory into the current project.
|
|
@@ -1010,21 +1231,26 @@ export class SessionManager {
|
|
|
1010
1231
|
* @param targetCwd Target working directory (where the new session will be stored)
|
|
1011
1232
|
* @param sessionDir Optional session directory. If omitted, uses default for targetCwd.
|
|
1012
1233
|
*/
|
|
1013
|
-
static forkFrom(sourcePath, targetCwd, sessionDir) {
|
|
1014
|
-
const
|
|
1234
|
+
static forkFrom(sourcePath, targetCwd, sessionDir, options) {
|
|
1235
|
+
const resolvedSourcePath = resolvePath(sourcePath);
|
|
1236
|
+
const resolvedTargetCwd = resolvePath(targetCwd);
|
|
1237
|
+
const sourceEntries = loadEntriesFromFile(resolvedSourcePath);
|
|
1015
1238
|
if (sourceEntries.length === 0) {
|
|
1016
|
-
throw new Error(`Cannot fork: source session file is empty or invalid: ${
|
|
1239
|
+
throw new Error(`Cannot fork: source session file is empty or invalid: ${resolvedSourcePath}`);
|
|
1017
1240
|
}
|
|
1018
1241
|
const sourceHeader = sourceEntries.find((e) => e.type === "session");
|
|
1019
1242
|
if (!sourceHeader) {
|
|
1020
|
-
throw new Error(`Cannot fork: source session has no header: ${
|
|
1243
|
+
throw new Error(`Cannot fork: source session has no header: ${resolvedSourcePath}`);
|
|
1021
1244
|
}
|
|
1022
|
-
const dir = sessionDir
|
|
1245
|
+
const dir = sessionDir ? normalizePath(sessionDir) : getDefaultSessionDir(resolvedTargetCwd);
|
|
1023
1246
|
if (!existsSync(dir)) {
|
|
1024
1247
|
mkdirSync(dir, { recursive: true });
|
|
1025
1248
|
}
|
|
1026
1249
|
// Create new session file with new ID but forked content
|
|
1027
|
-
|
|
1250
|
+
if (options?.id !== undefined) {
|
|
1251
|
+
assertValidSessionId(options.id);
|
|
1252
|
+
}
|
|
1253
|
+
const newSessionId = options?.id ?? createSessionId();
|
|
1028
1254
|
const timestamp = new Date().toISOString();
|
|
1029
1255
|
const fileTimestamp = timestamp.replace(/[:.]/g, "-");
|
|
1030
1256
|
const newSessionFile = join(dir, `${fileTimestamp}_${newSessionId}.jsonl`);
|
|
@@ -1034,42 +1260,49 @@ export class SessionManager {
|
|
|
1034
1260
|
version: CURRENT_SESSION_VERSION,
|
|
1035
1261
|
id: newSessionId,
|
|
1036
1262
|
timestamp,
|
|
1037
|
-
cwd:
|
|
1038
|
-
parentSession:
|
|
1263
|
+
cwd: resolvedTargetCwd,
|
|
1264
|
+
parentSession: resolvedSourcePath,
|
|
1039
1265
|
};
|
|
1040
|
-
|
|
1266
|
+
writeFileSync(newSessionFile, `${JSON.stringify(newHeader)}\n`, { flag: "wx" });
|
|
1041
1267
|
// Copy all non-header entries from source
|
|
1042
1268
|
for (const entry of sourceEntries) {
|
|
1043
1269
|
if (entry.type !== "session") {
|
|
1044
1270
|
appendFileSync(newSessionFile, `${JSON.stringify(entry)}\n`);
|
|
1045
1271
|
}
|
|
1046
1272
|
}
|
|
1047
|
-
return new SessionManager(
|
|
1273
|
+
return new SessionManager(resolvedTargetCwd, dir, newSessionFile, true);
|
|
1048
1274
|
}
|
|
1049
1275
|
/**
|
|
1050
1276
|
* List all sessions for a directory.
|
|
1051
1277
|
* @param cwd Working directory (used to compute default session directory)
|
|
1052
|
-
* @param sessionDir Optional session directory. If omitted, uses
|
|
1278
|
+
* @param sessionDir Optional session directory. If omitted, uses the mcpi state sessions directory.
|
|
1053
1279
|
* @param onProgress Optional callback for progress updates (loaded, total)
|
|
1054
1280
|
*/
|
|
1055
1281
|
static async list(cwd, sessionDir, onProgress) {
|
|
1056
|
-
const dir = sessionDir
|
|
1057
|
-
const
|
|
1282
|
+
const dir = sessionDir ? normalizePath(sessionDir) : getDefaultSessionDir(cwd);
|
|
1283
|
+
const filterCwd = sessionDir !== undefined && dir !== getDefaultSessionDirPath(cwd);
|
|
1284
|
+
const resolvedCwd = resolvePath(cwd);
|
|
1285
|
+
const sessions = (await listSessionsFromDir(dir, onProgress)).filter((session) => !filterCwd || sessionCwdMatches(session.cwd, resolvedCwd));
|
|
1058
1286
|
sessions.sort((a, b) => b.modified.getTime() - a.modified.getTime());
|
|
1059
1287
|
return sessions;
|
|
1060
1288
|
}
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1289
|
+
static async listAll(sessionDirOrOnProgress, onProgress) {
|
|
1290
|
+
const customSessionDir = typeof sessionDirOrOnProgress === "string" ? normalizePath(sessionDirOrOnProgress) : undefined;
|
|
1291
|
+
const progress = typeof sessionDirOrOnProgress === "function" ? sessionDirOrOnProgress : onProgress;
|
|
1292
|
+
if (customSessionDir) {
|
|
1293
|
+
const sessions = await listSessionsFromDir(customSessionDir, progress);
|
|
1294
|
+
sessions.sort((a, b) => b.modified.getTime() - a.modified.getTime());
|
|
1295
|
+
return sessions;
|
|
1296
|
+
}
|
|
1066
1297
|
const sessionsDir = getSessionsDir();
|
|
1067
1298
|
try {
|
|
1068
1299
|
if (!existsSync(sessionsDir)) {
|
|
1069
1300
|
return [];
|
|
1070
1301
|
}
|
|
1071
1302
|
const entries = await readdir(sessionsDir, { withFileTypes: true });
|
|
1072
|
-
const dirs = entries
|
|
1303
|
+
const dirs = entries
|
|
1304
|
+
.filter((entry) => entry.isDirectory() || entry.isSymbolicLink())
|
|
1305
|
+
.map((entry) => join(sessionsDir, entry.name));
|
|
1073
1306
|
// Count total files first for accurate progress
|
|
1074
1307
|
let totalFiles = 0;
|
|
1075
1308
|
const dirFiles = [];
|
|
@@ -1087,12 +1320,10 @@ export class SessionManager {
|
|
|
1087
1320
|
let loaded = 0;
|
|
1088
1321
|
const sessions = [];
|
|
1089
1322
|
const allFiles = dirFiles.flat();
|
|
1090
|
-
const results = await
|
|
1091
|
-
const info = await buildSessionInfo(file);
|
|
1323
|
+
const results = await buildSessionInfosWithConcurrency(allFiles, () => {
|
|
1092
1324
|
loaded++;
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
}));
|
|
1325
|
+
progress?.(loaded, totalFiles);
|
|
1326
|
+
});
|
|
1096
1327
|
for (const info of results) {
|
|
1097
1328
|
if (info) {
|
|
1098
1329
|
sessions.push(info);
|