apex-code 0.5.0 → 0.5.2
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 +263 -5
- package/README.md +624 -0
- package/dist/bun/cli.d.ts +3 -1
- package/dist/bun/cli.d.ts.map +1 -1
- package/dist/bun/cli.js +3 -9
- package/dist/bun/cli.js.map +1 -1
- package/dist/bun/runtime-setup.d.ts +2 -0
- package/dist/bun/runtime-setup.d.ts.map +1 -0
- package/dist/bun/runtime-setup.js +9 -0
- package/dist/bun/runtime-setup.js.map +1 -0
- package/dist/bun/sandbox-env-setup.d.ts +2 -0
- package/dist/bun/sandbox-env-setup.d.ts.map +1 -0
- package/dist/bun/sandbox-env-setup.js +4 -0
- package/dist/bun/sandbox-env-setup.js.map +1 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +16 -5
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/config-selector.d.ts.map +1 -1
- package/dist/cli/config-selector.js +2 -1
- package/dist/cli/config-selector.js.map +1 -1
- package/dist/cli/file-processor.d.ts +1 -1
- package/dist/cli/file-processor.d.ts.map +1 -1
- package/dist/cli/file-processor.js.map +1 -1
- 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/setup.d.ts +2 -0
- package/dist/cli/setup.d.ts.map +1 -0
- package/dist/cli/setup.js +13 -0
- package/dist/cli/setup.js.map +1 -0
- package/dist/config.d.ts +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -0
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +16 -8
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session.d.ts +85 -15
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +685 -266
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-storage.d.ts +4 -0
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +55 -0
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/bug-report.d.ts +176 -0
- package/dist/core/bug-report.d.ts.map +1 -0
- package/dist/core/bug-report.js +291 -0
- package/dist/core/bug-report.js.map +1 -0
- package/dist/core/cache-stats.d.ts.map +1 -1
- package/dist/core/cache-stats.js +12 -1
- package/dist/core/cache-stats.js.map +1 -1
- package/dist/core/cache-warmer.d.ts +103 -0
- package/dist/core/cache-warmer.d.ts.map +1 -0
- package/dist/core/cache-warmer.js +356 -0
- package/dist/core/cache-warmer.js.map +1 -0
- package/dist/core/compaction/branch-summarization.d.ts +1 -1
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js +4 -3
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts +5 -3
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +163 -66
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/context/pipeline.d.ts +8 -8
- package/dist/core/context/pipeline.d.ts.map +1 -1
- package/dist/core/context/pipeline.js +21 -12
- package/dist/core/context/pipeline.js.map +1 -1
- package/dist/core/crash-log.d.ts +27 -0
- package/dist/core/crash-log.d.ts.map +1 -0
- package/dist/core/crash-log.js +139 -0
- package/dist/core/crash-log.js.map +1 -0
- package/dist/core/export-html/template.js +6 -1
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/jiti-loader.d.ts +2 -0
- package/dist/core/extensions/jiti-loader.d.ts.map +1 -0
- package/dist/core/extensions/jiti-loader.js +4 -0
- package/dist/core/extensions/jiti-loader.js.map +1 -0
- package/dist/core/extensions/jiti-static-loader.d.ts +2 -0
- package/dist/core/extensions/jiti-static-loader.d.ts.map +1 -0
- package/dist/core/extensions/jiti-static-loader.js +4 -0
- package/dist/core/extensions/jiti-static-loader.js.map +1 -0
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +40 -59
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +24 -8
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +195 -72
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +142 -55
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/extensions/virtual-modules.d.ts +3 -0
- package/dist/core/extensions/virtual-modules.d.ts.map +1 -0
- package/dist/core/extensions/virtual-modules.js +41 -0
- package/dist/core/extensions/virtual-modules.js.map +1 -0
- package/dist/core/extensions/wrapper.d.ts.map +1 -1
- package/dist/core/extensions/wrapper.js +1 -20
- package/dist/core/extensions/wrapper.js.map +1 -1
- package/dist/core/http-dispatcher.d.ts.map +1 -1
- package/dist/core/http-dispatcher.js +2 -0
- package/dist/core/http-dispatcher.js.map +1 -1
- package/dist/core/index.d.ts +2 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js.map +1 -1
- package/dist/core/keybindings.d.ts +6 -1
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +5 -1
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/messages.d.ts +1 -1
- package/dist/core/messages.d.ts.map +1 -1
- package/dist/core/messages.js +1 -0
- package/dist/core/messages.js.map +1 -1
- package/dist/core/model-config.d.ts +168 -20
- package/dist/core/model-config.d.ts.map +1 -1
- package/dist/core/model-config.js +44 -18
- package/dist/core/model-config.js.map +1 -1
- package/dist/core/model-registry.d.ts +5 -1
- package/dist/core/model-registry.d.ts.map +1 -1
- package/dist/core/model-registry.js +8 -0
- package/dist/core/model-registry.js.map +1 -1
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +4 -3
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/model-runtime.d.ts +1 -0
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +12 -6
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/permissions/store.d.ts.map +1 -1
- package/dist/core/permissions/store.js +11 -8
- package/dist/core/permissions/store.js.map +1 -1
- package/dist/core/prompt-templates.d.ts +6 -1
- package/dist/core/prompt-templates.d.ts.map +1 -1
- package/dist/core/prompt-templates.js +61 -35
- package/dist/core/prompt-templates.js.map +1 -1
- package/dist/core/provider-composer.d.ts +4 -2
- package/dist/core/provider-composer.d.ts.map +1 -1
- package/dist/core/provider-composer.js +29 -2
- package/dist/core/provider-composer.js.map +1 -1
- package/dist/core/radius.d.ts +3 -0
- package/dist/core/radius.d.ts.map +1 -1
- package/dist/core/radius.js +6 -0
- package/dist/core/radius.js.map +1 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +6 -2
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +63 -42
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-export.d.ts +6 -2
- package/dist/core/session-export.d.ts.map +1 -1
- package/dist/core/session-export.js +14 -13
- package/dist/core/session-export.js.map +1 -1
- package/dist/core/session-manager.d.ts +66 -15
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +295 -115
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +27 -4
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +55 -7
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/skills.d.ts +1 -1
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +5 -4
- package/dist/core/skills.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +1 -0
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/system-prompt.d.ts +49 -6
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +140 -79
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/bash.d.ts +7 -8
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +20 -115
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/edit.d.ts +1 -12
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +6 -204
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +4 -55
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +4 -60
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/ls.d.ts.map +1 -1
- package/dist/core/tools/ls.js +4 -49
- package/dist/core/tools/ls.js.map +1 -1
- package/dist/core/tools/read.d.ts +4 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +10 -125
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/renderers/bash.d.ts +18 -0
- package/dist/core/tools/renderers/bash.d.ts.map +1 -0
- package/dist/core/tools/renderers/bash.js +126 -0
- package/dist/core/tools/renderers/bash.js.map +1 -0
- package/dist/core/tools/renderers/edit.d.ts +23 -0
- package/dist/core/tools/renderers/edit.d.ts.map +1 -0
- package/dist/core/tools/renderers/edit.js +207 -0
- package/dist/core/tools/renderers/edit.js.map +1 -0
- package/dist/core/tools/renderers/find.d.ts +10 -0
- package/dist/core/tools/renderers/find.d.ts.map +1 -0
- package/dist/core/tools/renderers/find.js +64 -0
- package/dist/core/tools/renderers/find.js.map +1 -0
- package/dist/core/tools/renderers/grep.d.ts +10 -0
- package/dist/core/tools/renderers/grep.d.ts.map +1 -0
- package/dist/core/tools/renderers/grep.js +69 -0
- package/dist/core/tools/renderers/grep.js.map +1 -0
- package/dist/core/tools/renderers/index.d.ts +34 -0
- package/dist/core/tools/renderers/index.d.ts.map +1 -0
- package/dist/core/tools/renderers/index.js +47 -0
- package/dist/core/tools/renderers/index.js.map +1 -0
- package/dist/core/tools/renderers/ls.d.ts +10 -0
- package/dist/core/tools/renderers/ls.d.ts.map +1 -0
- package/dist/core/tools/renderers/ls.js +58 -0
- package/dist/core/tools/renderers/ls.js.map +1 -0
- package/dist/core/tools/renderers/read.d.ts +11 -0
- package/dist/core/tools/renderers/read.d.ts.map +1 -0
- package/dist/core/tools/renderers/read.js +132 -0
- package/dist/core/tools/renderers/read.js.map +1 -0
- package/dist/core/tools/renderers/write.d.ts +10 -0
- package/dist/core/tools/renderers/write.d.ts.map +1 -0
- package/dist/core/tools/renderers/write.js +152 -0
- package/dist/core/tools/renderers/write.js.map +1 -0
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +6 -146
- package/dist/core/tools/write.js.map +1 -1
- package/dist/core/usage-totals.d.ts +1 -1
- package/dist/core/usage-totals.d.ts.map +1 -1
- package/dist/core/usage-totals.js +5 -1
- package/dist/core/usage-totals.js.map +1 -1
- package/dist/extensions/llama/client.d.ts +2 -0
- package/dist/extensions/llama/client.d.ts.map +1 -1
- package/dist/extensions/llama/client.js +7 -3
- package/dist/extensions/llama/client.js.map +1 -1
- package/dist/extensions/llama/provider.d.ts.map +1 -1
- package/dist/extensions/llama/provider.js +20 -5
- package/dist/extensions/llama/provider.js.map +1 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +21 -13
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/bug-report.d.ts +16 -0
- package/dist/modes/interactive/bug-report.d.ts.map +1 -0
- package/dist/modes/interactive/bug-report.js +167 -0
- package/dist/modes/interactive/bug-report.js.map +1 -0
- package/dist/modes/interactive/chat-viewport.d.ts +20 -0
- package/dist/modes/interactive/chat-viewport.d.ts.map +1 -0
- package/dist/modes/interactive/chat-viewport.js +28 -0
- package/dist/modes/interactive/chat-viewport.js.map +1 -0
- package/dist/modes/interactive/components/assistant-message.d.ts +7 -0
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +63 -17
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.js +12 -5
- package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.js +12 -5
- package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/custom-editor.d.ts +12 -0
- package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-editor.js +38 -0
- package/dist/modes/interactive/components/custom-editor.js.map +1 -1
- package/dist/modes/interactive/components/error-summary.d.ts +11 -0
- package/dist/modes/interactive/components/error-summary.d.ts.map +1 -0
- package/dist/modes/interactive/components/error-summary.js +31 -0
- package/dist/modes/interactive/components/error-summary.js.map +1 -0
- package/dist/modes/interactive/components/extension-editor.d.ts +4 -1
- package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-editor.js +6 -1
- package/dist/modes/interactive/components/extension-editor.js.map +1 -1
- package/dist/modes/interactive/components/extension-input.d.ts +2 -0
- package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-input.js +6 -0
- package/dist/modes/interactive/components/extension-input.js.map +1 -1
- package/dist/modes/interactive/components/extension-selector.d.ts +2 -0
- package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-selector.js +4 -0
- package/dist/modes/interactive/components/extension-selector.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +4 -1
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts +1 -1
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/index.js.map +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +3 -3
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/scoped-models-selector.js +13 -15
- package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
- package/dist/modes/interactive/components/session-selector.d.ts +5 -5
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js +74 -48
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +5 -1
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +35 -10
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.js +11 -4
- package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
- package/dist/modes/interactive/components/status-indicator.d.ts +3 -1
- package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -1
- package/dist/modes/interactive/components/status-indicator.js +10 -3
- package/dist/modes/interactive/components/status-indicator.js.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.js +6 -6
- package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts +27 -5
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +64 -42
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/tree-selector.js +9 -0
- package/dist/modes/interactive/components/tree-selector.js.map +1 -1
- package/dist/modes/interactive/components/trust-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/trust-selector.js +2 -2
- package/dist/modes/interactive/components/trust-selector.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +43 -29
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +431 -166
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/dark.json +2 -1
- package/dist/modes/interactive/theme/light.json +2 -1
- package/dist/modes/interactive/theme/theme-controller.d.ts +1 -0
- package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme-controller.js +5 -0
- package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
- package/dist/modes/interactive/theme/theme-json.d.ts +84 -0
- package/dist/modes/interactive/theme/theme-json.d.ts.map +1 -0
- package/dist/modes/interactive/theme/theme-json.js +130 -0
- package/dist/modes/interactive/theme/theme-json.js.map +1 -0
- package/dist/modes/interactive/theme/theme-schema.json +6 -2
- package/dist/modes/interactive/theme/theme.d.ts +14 -5
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +18 -119
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/interactive/tui-renderer.d.ts +21 -0
- package/dist/modes/interactive/tui-renderer.d.ts.map +1 -0
- package/dist/modes/interactive/tui-renderer.js +66 -0
- package/dist/modes/interactive/tui-renderer.js.map +1 -0
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +2 -2
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/package-manager-cli.d.ts.map +1 -1
- package/dist/package-manager-cli.js +31 -72
- package/dist/package-manager-cli.js.map +1 -1
- package/dist/testing/replay/recorded-provider.d.ts +2 -2
- package/dist/testing/replay/recorded-provider.d.ts.map +1 -1
- package/dist/testing/replay/recorded-provider.js +2 -5
- package/dist/testing/replay/recorded-provider.js.map +1 -1
- package/dist/testing/replay/runner.d.ts.map +1 -1
- package/dist/testing/replay/runner.js +0 -1
- package/dist/testing/replay/runner.js.map +1 -1
- package/dist/utils/clipboard-command.d.ts +7 -0
- package/dist/utils/clipboard-command.d.ts.map +1 -0
- package/dist/utils/clipboard-command.js +45 -0
- package/dist/utils/clipboard-command.js.map +1 -0
- package/dist/utils/clipboard-image.d.ts.map +1 -1
- package/dist/utils/clipboard-image.js +53 -81
- package/dist/utils/clipboard-image.js.map +1 -1
- package/dist/utils/clipboard.d.ts.map +1 -1
- package/dist/utils/clipboard.js +111 -121
- package/dist/utils/clipboard.js.map +1 -1
- package/dist/utils/exif-orientation.d.ts.map +1 -1
- package/dist/utils/exif-orientation.js +2 -3
- package/dist/utils/exif-orientation.js.map +1 -1
- package/dist/utils/mime.d.ts.map +1 -1
- package/dist/utils/mime.js +1 -1
- package/dist/utils/mime.js.map +1 -1
- package/dist/utils/syntax-highlight.d.ts.map +1 -1
- package/dist/utils/syntax-highlight.js +21 -21
- package/dist/utils/syntax-highlight.js.map +1 -1
- package/dist/utils/tool-result-images.d.ts +3 -1
- package/dist/utils/tool-result-images.d.ts.map +1 -1
- package/dist/utils/tool-result-images.js +4 -1
- package/dist/utils/tool-result-images.js.map +1 -1
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +11 -2
- package/dist/utils/tools-manager.js.map +1 -1
- package/dist/utils/wsl.d.ts +3 -0
- package/dist/utils/wsl.d.ts.map +1 -0
- package/dist/utils/wsl.js +15 -0
- package/dist/utils/wsl.js.map +1 -0
- package/dist/utils/zip.d.ts +7 -0
- package/dist/utils/zip.d.ts.map +1 -0
- package/dist/utils/zip.js +60 -0
- package/dist/utils/zip.js.map +1 -0
- package/docs/cli-integration.md +107 -0
- package/docs/cli.md +269 -0
- package/docs/compaction.md +73 -24
- package/docs/configuration.md +45 -0
- package/docs/containerization.md +22 -21
- package/docs/custom-provider.md +21 -12
- package/docs/development.md +19 -0
- package/docs/docs.json +139 -95
- package/docs/extensions.md +243 -371
- package/docs/how-pi-works.md +49 -0
- package/docs/images/interactive-mode.png +0 -0
- package/docs/index.md +3 -3
- package/docs/json.md +7 -3
- package/docs/keybindings.md +57 -54
- package/docs/llama-cpp.md +2 -2
- package/docs/message-types.md +261 -0
- package/docs/models.md +103 -49
- package/docs/packages.md +49 -47
- package/docs/prompt-templates.md +29 -56
- package/docs/providers.md +91 -139
- package/docs/quickstart.md +42 -14
- package/docs/rpc-commands.md +854 -0
- package/docs/rpc-extension-ui.md +200 -0
- package/docs/rpc.md +121 -223
- package/docs/sdk.md +99 -124
- package/docs/security.md +7 -7
- package/docs/session-format.md +85 -82
- package/docs/sessions.md +41 -57
- package/docs/settings.md +94 -87
- package/docs/shell-aliases.md +68 -3
- package/docs/skills.md +62 -49
- package/docs/slash-commands.md +60 -0
- package/docs/terminal-setup.md +86 -55
- package/docs/termux.md +65 -75
- package/docs/themes.md +64 -86
- package/docs/tmux.md +29 -7
- package/docs/tui.md +67 -122
- package/docs/usage.md +31 -42
- package/docs/windows.md +41 -13
- package/examples/README.md +16 -2
- package/examples/extensions/README.md +0 -1
- package/examples/extensions/custom-provider-anthropic/index.ts +18 -12
- 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/index.ts +2 -2
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/dynamic-resources/dynamic.json +2 -0
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/prompt-customizer.ts +19 -67
- 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/plugins/pi-example-plugin/README.md +38 -0
- package/examples/plugins/pi-example-plugin/package.json +10 -0
- package/examples/plugins/pi-example-plugin/src/contract.ts +13 -0
- package/examples/plugins/pi-example-plugin/src/session.ts +24 -0
- package/examples/plugins/pi-example-plugin/src/tui.ts +31 -0
- package/examples/rpc-client.ts +35 -0
- package/examples/rpc-extension-ui.ts +25 -5
- package/examples/sdk/README.md +1 -1
- package/npm-shrinkwrap.json +861 -513
- package/package.json +27 -18
- package/dist/bun/register-bedrock.d.ts +0 -2
- package/dist/bun/register-bedrock.d.ts.map +0 -1
- package/dist/bun/register-bedrock.js +0 -4
- package/dist/bun/register-bedrock.js.map +0 -1
- package/dist/cli/experimental/auth.d.ts +0 -16
- package/dist/cli/experimental/auth.d.ts.map +0 -1
- package/dist/cli/experimental/auth.js +0 -13
- package/dist/cli/experimental/auth.js.map +0 -1
- package/dist/cli/experimental/cli.d.ts +0 -6
- package/dist/cli/experimental/cli.d.ts.map +0 -1
- package/dist/cli/experimental/cli.js +0 -5
- package/dist/cli/experimental/cli.js.map +0 -1
- package/dist/cli/experimental/command-options.d.ts +0 -17
- package/dist/cli/experimental/command-options.d.ts.map +0 -1
- package/dist/cli/experimental/command-options.js +0 -35
- package/dist/cli/experimental/command-options.js.map +0 -1
- package/dist/cli/experimental/command.d.ts +0 -63
- package/dist/cli/experimental/command.d.ts.map +0 -1
- package/dist/cli/experimental/command.js +0 -130
- package/dist/cli/experimental/command.js.map +0 -1
- package/dist/cli/experimental/commands/client.d.ts +0 -13
- package/dist/cli/experimental/commands/client.d.ts.map +0 -1
- package/dist/cli/experimental/commands/client.js +0 -25
- package/dist/cli/experimental/commands/client.js.map +0 -1
- package/dist/cli/experimental/commands/pi.d.ts +0 -15
- package/dist/cli/experimental/commands/pi.d.ts.map +0 -1
- package/dist/cli/experimental/commands/pi.js +0 -28
- package/dist/cli/experimental/commands/pi.js.map +0 -1
- package/dist/cli/experimental/commands/server.d.ts +0 -13
- package/dist/cli/experimental/commands/server.d.ts.map +0 -1
- package/dist/cli/experimental/commands/server.js +0 -25
- package/dist/cli/experimental/commands/server.js.map +0 -1
- package/dist/cli/experimental/transport-address.d.ts +0 -10
- package/dist/cli/experimental/transport-address.d.ts.map +0 -1
- package/dist/cli/experimental/transport-address.js +0 -38
- package/dist/cli/experimental/transport-address.js.map +0 -1
- package/dist/client/index.d.ts +0 -3
- package/dist/client/index.d.ts.map +0 -1
- package/dist/client/index.js +0 -3
- package/dist/client/index.js.map +0 -1
- package/dist/client/remote-session.d.ts +0 -53
- package/dist/client/remote-session.d.ts.map +0 -1
- package/dist/client/remote-session.js +0 -340
- package/dist/client/remote-session.js.map +0 -1
- package/dist/client/transcript.d.ts +0 -12
- package/dist/client/transcript.d.ts.map +0 -1
- package/dist/client/transcript.js +0 -98
- package/dist/client/transcript.js.map +0 -1
- package/dist/utils/clipboard-native.d.ts +0 -11
- package/dist/utils/clipboard-native.d.ts.map +0 -1
- package/dist/utils/clipboard-native.js +0 -20
- package/dist/utils/clipboard-native.js.map +0 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { uuidv7 } from "@earendil-works/pi-ai";
|
|
1
|
+
import { getCurrentSystemMessage, uuidv7, } from "@earendil-works/pi-ai";
|
|
2
2
|
import { randomUUID } from "crypto";
|
|
3
3
|
import { appendFileSync, closeSync, createReadStream, existsSync, mkdirSync, openSync, readdirSync, readSync, renameSync, rmSync, statSync, writeFileSync, } from "fs";
|
|
4
4
|
import { readdir, stat } from "fs/promises";
|
|
5
|
-
import { join, resolve } from "path";
|
|
5
|
+
import { basename, join, resolve } from "path";
|
|
6
6
|
import { createInterface } from "readline";
|
|
7
7
|
import { StringDecoder } from "string_decoder";
|
|
8
8
|
import { APP_NAME, getAgentDir as getDefaultAgentDir, getSessionsDir } from "../config.js";
|
|
@@ -184,6 +184,8 @@ export function sessionEntryToContextMessages(entry) {
|
|
|
184
184
|
const message = entry.message;
|
|
185
185
|
// Session files are parsed without validation; old versions, forks, or
|
|
186
186
|
// hand-edited files can contain messages with null/missing content.
|
|
187
|
+
if (message.role === "system" && message.content == null)
|
|
188
|
+
return [{ ...message, content: "" }];
|
|
187
189
|
if ((message.role === "user" || message.role === "assistant" || message.role === "toolResult") &&
|
|
188
190
|
message.content == null) {
|
|
189
191
|
return [{ ...message, content: [] }];
|
|
@@ -199,7 +201,8 @@ export function sessionEntryToContextMessages(entry) {
|
|
|
199
201
|
return [createBranchSummaryMessage(entry.summary, entry.fromId, entry.timestamp)];
|
|
200
202
|
}
|
|
201
203
|
if (entry.type === "compaction") {
|
|
202
|
-
|
|
204
|
+
const summary = createCompactionSummaryMessage(entry.summary, entry.tokensBefore, entry.timestamp);
|
|
205
|
+
return entry.systemMessage ? [entry.systemMessage, summary] : [summary];
|
|
203
206
|
}
|
|
204
207
|
return [];
|
|
205
208
|
}
|
|
@@ -233,7 +236,7 @@ export function buildContextEntries(entries, leafId, byId) {
|
|
|
233
236
|
if (entry.id === compaction.firstKeptEntryId) {
|
|
234
237
|
foundFirstKept = true;
|
|
235
238
|
}
|
|
236
|
-
if (foundFirstKept) {
|
|
239
|
+
if (foundFirstKept && !(entry.type === "message" && entry.message.role === "system")) {
|
|
237
240
|
contextEntries.push(entry);
|
|
238
241
|
}
|
|
239
242
|
}
|
|
@@ -245,10 +248,55 @@ export function buildContextEntries(entries, leafId, byId) {
|
|
|
245
248
|
* If leafId is provided, walks from that entry to root.
|
|
246
249
|
* Handles compaction and branch summaries along the path.
|
|
247
250
|
*/
|
|
248
|
-
|
|
251
|
+
function projectContextEntry(entry, edit) {
|
|
252
|
+
const messages = sessionEntryToContextMessages(entry);
|
|
253
|
+
if (!edit)
|
|
254
|
+
return messages;
|
|
255
|
+
const replacement = edit.replacement;
|
|
256
|
+
if (replacement === null)
|
|
257
|
+
return [];
|
|
258
|
+
return messages.map((message) => {
|
|
259
|
+
if (message.role !== "user" &&
|
|
260
|
+
message.role !== "assistant" &&
|
|
261
|
+
message.role !== "toolResult" &&
|
|
262
|
+
message.role !== "custom") {
|
|
263
|
+
return message;
|
|
264
|
+
}
|
|
265
|
+
const content = (message.role === "assistant" || message.role === "toolResult") && typeof replacement.content === "string"
|
|
266
|
+
? [{ type: "text", text: replacement.content }]
|
|
267
|
+
: replacement.content;
|
|
268
|
+
return { ...message, content };
|
|
269
|
+
});
|
|
270
|
+
}
|
|
271
|
+
/** Build provenance-preserving, compaction-aware model context. */
|
|
272
|
+
export function buildSessionProjection(entries, leafId, byId) {
|
|
249
273
|
const path = buildSessionPath(entries, leafId, byId);
|
|
250
274
|
const { thinkingLevel, model } = getSessionContextSettings(path);
|
|
251
|
-
const
|
|
275
|
+
const contextEntries = buildContextEntries(entries, leafId, byId);
|
|
276
|
+
const edits = new Map();
|
|
277
|
+
for (const entry of contextEntries) {
|
|
278
|
+
if (entry.type === "context_edit")
|
|
279
|
+
edits.set(entry.targetId, entry);
|
|
280
|
+
}
|
|
281
|
+
const projectedEntries = contextEntries.map((sourceEntry, index) => ({
|
|
282
|
+
sourceEntry,
|
|
283
|
+
// buildContextEntries() may retain an older compaction entry because its
|
|
284
|
+
// raw ID lies inside the newest retained range. Only the newest compaction
|
|
285
|
+
// at index zero contributes a checkpoint and summary.
|
|
286
|
+
messages: sourceEntry.type === "compaction" && index > 0
|
|
287
|
+
? []
|
|
288
|
+
: projectContextEntry(sourceEntry, edits.get(sourceEntry.id)),
|
|
289
|
+
}));
|
|
290
|
+
return {
|
|
291
|
+
entries: projectedEntries,
|
|
292
|
+
messages: projectedEntries.flatMap((entry) => entry.messages),
|
|
293
|
+
thinkingLevel,
|
|
294
|
+
model,
|
|
295
|
+
};
|
|
296
|
+
}
|
|
297
|
+
/** Build the finalized model context from the canonical session projection. */
|
|
298
|
+
export function buildSessionContext(entries, leafId, byId) {
|
|
299
|
+
const { messages, thinkingLevel, model } = buildSessionProjection(entries, leafId, byId);
|
|
252
300
|
return { messages, thinkingLevel, model };
|
|
253
301
|
}
|
|
254
302
|
/**
|
|
@@ -413,14 +461,16 @@ export function findMostRecentSession(sessionDir, cwd) {
|
|
|
413
461
|
const resolvedCwd = cwd ? resolvePath(cwd) : undefined;
|
|
414
462
|
try {
|
|
415
463
|
const files = readdirSync(resolvedSessionDir)
|
|
416
|
-
.filter((
|
|
417
|
-
.map((
|
|
418
|
-
.map((path) => ({ path,
|
|
419
|
-
.
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
464
|
+
.filter((file) => file.endsWith(".jsonl"))
|
|
465
|
+
.map((file) => join(resolvedSessionDir, file))
|
|
466
|
+
.map((path) => ({ path, mtime: statSync(path).mtimeMs }))
|
|
467
|
+
.sort((a, b) => b.mtime - a.mtime);
|
|
468
|
+
for (const { path } of files) {
|
|
469
|
+
const header = readSessionHeaderForDiscovery(path);
|
|
470
|
+
if (header && (!resolvedCwd || sessionCwdMatches(getSessionHeaderCwd(header), resolvedCwd)))
|
|
471
|
+
return path;
|
|
472
|
+
}
|
|
473
|
+
return null;
|
|
424
474
|
}
|
|
425
475
|
catch {
|
|
426
476
|
// Directory access and stat races make recent-session discovery unavailable.
|
|
@@ -453,9 +503,9 @@ function getMessageActivityTime(entry) {
|
|
|
453
503
|
const t = new Date(entry.timestamp).getTime();
|
|
454
504
|
return Number.isNaN(t) ? undefined : t;
|
|
455
505
|
}
|
|
456
|
-
async function buildSessionInfo(filePath) {
|
|
506
|
+
async function buildSessionInfo(filePath, signal, fileStats) {
|
|
457
507
|
try {
|
|
458
|
-
const stats = await stat(filePath);
|
|
508
|
+
const stats = fileStats ?? (await stat(filePath));
|
|
459
509
|
let header = null;
|
|
460
510
|
let messageCount = 0;
|
|
461
511
|
let firstMessage = "";
|
|
@@ -463,7 +513,7 @@ async function buildSessionInfo(filePath) {
|
|
|
463
513
|
let name;
|
|
464
514
|
let lastActivityTime;
|
|
465
515
|
const rl = createInterface({
|
|
466
|
-
input: createReadStream(filePath, { encoding: "utf8" }),
|
|
516
|
+
input: createReadStream(filePath, { encoding: "utf8", signal }),
|
|
467
517
|
crlfDelay: Infinity,
|
|
468
518
|
});
|
|
469
519
|
for await (const line of rl) {
|
|
@@ -524,67 +574,63 @@ async function buildSessionInfo(filePath) {
|
|
|
524
574
|
};
|
|
525
575
|
}
|
|
526
576
|
catch {
|
|
577
|
+
signal?.throwIfAborted();
|
|
527
578
|
return null;
|
|
528
579
|
}
|
|
529
580
|
}
|
|
530
581
|
const MAX_CONCURRENT_SESSION_INFO_LOADS = 10;
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
582
|
+
const MAX_CONCURRENT_SESSION_DISCOVERY_LOADS = 64;
|
|
583
|
+
const CURRENT_SESSION_LIST_PUBLISH_INTERVAL = 10;
|
|
584
|
+
const ALL_SESSION_LIST_PUBLISH_INTERVAL = 100;
|
|
585
|
+
async function mapWithConcurrency(items, limit, map, signal) {
|
|
586
|
+
const results = new Array(items.length);
|
|
534
587
|
let nextIndex = 0;
|
|
535
|
-
const
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
let task;
|
|
541
|
-
task = buildSessionInfo(file)
|
|
542
|
-
.then((info) => {
|
|
543
|
-
results[index] = info;
|
|
544
|
-
})
|
|
545
|
-
.catch(() => {
|
|
546
|
-
results[index] = null;
|
|
547
|
-
})
|
|
548
|
-
.finally(() => {
|
|
549
|
-
inFlight.delete(task);
|
|
550
|
-
onLoaded();
|
|
551
|
-
});
|
|
552
|
-
inFlight.add(task);
|
|
553
|
-
};
|
|
554
|
-
while (nextIndex < files.length || inFlight.size > 0) {
|
|
555
|
-
while (nextIndex < files.length && inFlight.size < MAX_CONCURRENT_SESSION_INFO_LOADS) {
|
|
556
|
-
startNext();
|
|
588
|
+
const worker = async () => {
|
|
589
|
+
while (nextIndex < items.length) {
|
|
590
|
+
signal?.throwIfAborted();
|
|
591
|
+
const index = nextIndex++;
|
|
592
|
+
results[index] = await map(items[index], index);
|
|
557
593
|
}
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
}
|
|
561
|
-
}
|
|
594
|
+
};
|
|
595
|
+
await Promise.all(Array.from({ length: Math.min(limit, items.length) }, () => worker()));
|
|
562
596
|
return results;
|
|
563
597
|
}
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
598
|
+
function sortSessionInfos(sessions) {
|
|
599
|
+
return sessions.sort((a, b) => b.modified.getTime() - a.modified.getTime());
|
|
600
|
+
}
|
|
601
|
+
function buildSessionInfosWithConcurrency(files, onLoaded, signal) {
|
|
602
|
+
return mapWithConcurrency(files, MAX_CONCURRENT_SESSION_INFO_LOADS, async (file, index) => {
|
|
603
|
+
const info = await buildSessionInfo(file.path, signal, file.stats);
|
|
604
|
+
onLoaded(info, index);
|
|
605
|
+
return info;
|
|
606
|
+
}, signal);
|
|
607
|
+
}
|
|
608
|
+
async function listSessionsFromDir(dir, onProgress, signal) {
|
|
609
|
+
signal?.throwIfAborted();
|
|
610
|
+
if (!existsSync(dir))
|
|
611
|
+
return [];
|
|
569
612
|
try {
|
|
570
613
|
const dirEntries = await readdir(dir);
|
|
571
|
-
const files = dirEntries
|
|
572
|
-
|
|
614
|
+
const files = dirEntries
|
|
615
|
+
.filter((file) => file.endsWith(".jsonl"))
|
|
616
|
+
.sort((a, b) => b.localeCompare(a))
|
|
617
|
+
.map((file) => ({ path: join(dir, file) }));
|
|
618
|
+
const total = files.length;
|
|
619
|
+
const partialSessions = [];
|
|
573
620
|
let loaded = 0;
|
|
574
|
-
const results = await buildSessionInfosWithConcurrency(files, () => {
|
|
621
|
+
const results = await buildSessionInfosWithConcurrency(files, (info) => {
|
|
575
622
|
loaded++;
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
}
|
|
623
|
+
if (info)
|
|
624
|
+
partialSessions.push(info);
|
|
625
|
+
const publishPartial = loaded === 1 || loaded % CURRENT_SESSION_LIST_PUBLISH_INTERVAL === 0 || loaded === files.length;
|
|
626
|
+
onProgress?.(loaded, total, publishPartial ? sortSessionInfos([...partialSessions]) : undefined);
|
|
627
|
+
}, signal);
|
|
628
|
+
return results.filter((info) => info !== null);
|
|
583
629
|
}
|
|
584
630
|
catch {
|
|
585
|
-
|
|
631
|
+
signal?.throwIfAborted();
|
|
632
|
+
return [];
|
|
586
633
|
}
|
|
587
|
-
return sessions;
|
|
588
634
|
}
|
|
589
635
|
/**
|
|
590
636
|
* Manages conversation sessions as append-only trees stored in JSONL files.
|
|
@@ -625,6 +671,9 @@ export class SessionManager {
|
|
|
625
671
|
if (sessionFile) {
|
|
626
672
|
this._setSessionFile(sessionFile, preloadedFileEntries);
|
|
627
673
|
}
|
|
674
|
+
else if (preloadedFileEntries?.length) {
|
|
675
|
+
this._loadEntries(preloadedFileEntries, newSessionOptions);
|
|
676
|
+
}
|
|
628
677
|
else {
|
|
629
678
|
this.newSession(newSessionOptions);
|
|
630
679
|
}
|
|
@@ -636,11 +685,10 @@ export class SessionManager {
|
|
|
636
685
|
_setSessionFile(sessionFile, preloadedFileEntries) {
|
|
637
686
|
this.sessionFile = resolvePath(sessionFile);
|
|
638
687
|
if (existsSync(this.sessionFile)) {
|
|
639
|
-
|
|
640
|
-
this.entriesVersion++;
|
|
688
|
+
const entries = preloadedFileEntries ?? loadEntriesFromFile(this.sessionFile);
|
|
641
689
|
// If file was empty, initialize it with a valid session header. If it was
|
|
642
690
|
// non-empty but did not parse as a pi session, fail without modifying it.
|
|
643
|
-
if (
|
|
691
|
+
if (entries.length === 0) {
|
|
644
692
|
const explicitPath = this.sessionFile;
|
|
645
693
|
if (statSync(explicitPath).size > 0) {
|
|
646
694
|
throw new Error(`Session file is not a valid ${APP_NAME} session: ${explicitPath}`);
|
|
@@ -651,12 +699,7 @@ export class SessionManager {
|
|
|
651
699
|
this.flushed = true;
|
|
652
700
|
return;
|
|
653
701
|
}
|
|
654
|
-
|
|
655
|
-
this.sessionId = header?.id ?? createSessionId();
|
|
656
|
-
if (migrateToCurrentVersion(this.fileEntries)) {
|
|
657
|
-
this._rewriteFile();
|
|
658
|
-
}
|
|
659
|
-
this._buildIndex();
|
|
702
|
+
this._loadEntries(entries);
|
|
660
703
|
this.flushed = true;
|
|
661
704
|
}
|
|
662
705
|
else {
|
|
@@ -693,6 +736,22 @@ export class SessionManager {
|
|
|
693
736
|
}
|
|
694
737
|
return this.sessionFile;
|
|
695
738
|
}
|
|
739
|
+
_loadEntries(entries, options) {
|
|
740
|
+
const header = entries.find((e) => e.type === "session");
|
|
741
|
+
if (header) {
|
|
742
|
+
this.fileEntries = entries;
|
|
743
|
+
this.sessionId = header.id;
|
|
744
|
+
if (migrateToCurrentVersion(this.fileEntries)) {
|
|
745
|
+
this._rewriteFile();
|
|
746
|
+
}
|
|
747
|
+
}
|
|
748
|
+
else {
|
|
749
|
+
this.newSession(options);
|
|
750
|
+
this.fileEntries = this.fileEntries.concat(entries);
|
|
751
|
+
}
|
|
752
|
+
this.entriesVersion++;
|
|
753
|
+
this._buildIndex();
|
|
754
|
+
}
|
|
696
755
|
_buildIndex() {
|
|
697
756
|
this.byId.clear();
|
|
698
757
|
this.labelsById.clear();
|
|
@@ -833,19 +892,39 @@ export class SessionManager {
|
|
|
833
892
|
this._appendEntry(entry);
|
|
834
893
|
return entry.id;
|
|
835
894
|
}
|
|
895
|
+
/** Append model-attributed usage that does not participate in LLM context. Returns the appended entry. */
|
|
896
|
+
appendUsage(kind, provider, model, usage, note) {
|
|
897
|
+
const entry = {
|
|
898
|
+
type: "usage",
|
|
899
|
+
id: generateId(this.byId),
|
|
900
|
+
parentId: this.leafId,
|
|
901
|
+
timestamp: new Date().toISOString(),
|
|
902
|
+
kind,
|
|
903
|
+
provider,
|
|
904
|
+
model,
|
|
905
|
+
usage,
|
|
906
|
+
...(note ? { note } : {}),
|
|
907
|
+
};
|
|
908
|
+
this._appendEntry(entry);
|
|
909
|
+
return entry;
|
|
910
|
+
}
|
|
836
911
|
/** Append a compaction summary as child of current leaf, then advance leaf. Returns entry id. */
|
|
837
912
|
appendCompaction(summary, firstKeptEntryId, tokensBefore, details, fromHook, usage) {
|
|
913
|
+
const timestamp = new Date().toISOString();
|
|
914
|
+
const systemMessage = getCurrentSystemMessage(this.buildSessionProjection().messages);
|
|
915
|
+
const id = generateId(this.byId);
|
|
838
916
|
const entry = {
|
|
839
917
|
type: "compaction",
|
|
840
|
-
id
|
|
918
|
+
id,
|
|
841
919
|
parentId: this.leafId,
|
|
842
|
-
timestamp
|
|
920
|
+
timestamp,
|
|
843
921
|
summary,
|
|
844
|
-
firstKeptEntryId,
|
|
922
|
+
firstKeptEntryId: firstKeptEntryId ?? id,
|
|
845
923
|
tokensBefore,
|
|
846
924
|
details,
|
|
847
925
|
usage,
|
|
848
926
|
fromHook,
|
|
927
|
+
...(systemMessage ? { systemMessage: { ...systemMessage, timestamp: new Date(timestamp).getTime() } } : {}),
|
|
849
928
|
};
|
|
850
929
|
this._appendEntry(entry);
|
|
851
930
|
return entry.id;
|
|
@@ -943,6 +1022,44 @@ export class SessionManager {
|
|
|
943
1022
|
this._appendEntry(entry);
|
|
944
1023
|
return entry.id;
|
|
945
1024
|
}
|
|
1025
|
+
/** Append a branch-local edit to an earlier model-visible entry. */
|
|
1026
|
+
appendContextEdit(targetId, replacement) {
|
|
1027
|
+
if (replacement !== null &&
|
|
1028
|
+
(typeof replacement !== "object" ||
|
|
1029
|
+
!("content" in replacement) ||
|
|
1030
|
+
(typeof replacement.content !== "string" && !Array.isArray(replacement.content)))) {
|
|
1031
|
+
throw new Error("Context edit replacement must be null or contain string/array content");
|
|
1032
|
+
}
|
|
1033
|
+
const target = this.byId.get(targetId);
|
|
1034
|
+
if (!target)
|
|
1035
|
+
throw new Error(`Entry ${targetId} not found`);
|
|
1036
|
+
if (!this.getBranch().some((entry) => entry.id === targetId)) {
|
|
1037
|
+
throw new Error(`Entry ${targetId} is not on the active branch`);
|
|
1038
|
+
}
|
|
1039
|
+
const editable = target.type === "custom_message" ||
|
|
1040
|
+
(target.type === "message" &&
|
|
1041
|
+
(target.message.role === "user" ||
|
|
1042
|
+
target.message.role === "assistant" ||
|
|
1043
|
+
target.message.role === "toolResult"));
|
|
1044
|
+
if (!editable)
|
|
1045
|
+
throw new Error(`Entry ${targetId} does not contribute editable model content`);
|
|
1046
|
+
const targetRole = target.type === "message" ? target.message.role : "custom";
|
|
1047
|
+
const normalizedReplacement = replacement !== null &&
|
|
1048
|
+
(targetRole === "assistant" || targetRole === "toolResult") &&
|
|
1049
|
+
typeof replacement.content === "string"
|
|
1050
|
+
? { content: [{ type: "text", text: replacement.content }] }
|
|
1051
|
+
: replacement;
|
|
1052
|
+
const entry = {
|
|
1053
|
+
type: "context_edit",
|
|
1054
|
+
id: generateId(this.byId),
|
|
1055
|
+
parentId: this.leafId,
|
|
1056
|
+
timestamp: new Date().toISOString(),
|
|
1057
|
+
targetId,
|
|
1058
|
+
replacement: normalizedReplacement,
|
|
1059
|
+
};
|
|
1060
|
+
this._appendEntry(entry);
|
|
1061
|
+
return entry.id;
|
|
1062
|
+
}
|
|
946
1063
|
// =========================================================================
|
|
947
1064
|
// Tree Traversal
|
|
948
1065
|
// =========================================================================
|
|
@@ -1032,8 +1149,12 @@ export class SessionManager {
|
|
|
1032
1149
|
* Build the session context (what gets sent to the LLM).
|
|
1033
1150
|
* Uses tree traversal from current leaf.
|
|
1034
1151
|
*/
|
|
1152
|
+
buildSessionProjection() {
|
|
1153
|
+
return buildSessionProjection(this.getEntries(), this.leafId, this.byId);
|
|
1154
|
+
}
|
|
1035
1155
|
buildSessionContext() {
|
|
1036
|
-
|
|
1156
|
+
const { messages, thinkingLevel, model } = this.buildSessionProjection();
|
|
1157
|
+
return { messages, thinkingLevel, model };
|
|
1037
1158
|
}
|
|
1038
1159
|
/**
|
|
1039
1160
|
* Get session header.
|
|
@@ -1167,11 +1288,27 @@ export class SessionManager {
|
|
|
1167
1288
|
// Because labels are real tree entries, later entries can be children of labels;
|
|
1168
1289
|
// removing labels requires re-chaining the retained path to avoid orphaned subtrees.
|
|
1169
1290
|
const pathWithoutLabels = [];
|
|
1291
|
+
const replacementByLabelId = new Map();
|
|
1292
|
+
const pendingLabelIds = [];
|
|
1170
1293
|
let pathParentId = null;
|
|
1171
1294
|
for (const entry of path) {
|
|
1172
|
-
if (entry.type === "label")
|
|
1295
|
+
if (entry.type === "label") {
|
|
1296
|
+
pendingLabelIds.push(entry.id);
|
|
1173
1297
|
continue;
|
|
1174
|
-
|
|
1298
|
+
}
|
|
1299
|
+
for (const labelId of pendingLabelIds) {
|
|
1300
|
+
replacementByLabelId.set(labelId, entry.id);
|
|
1301
|
+
}
|
|
1302
|
+
pendingLabelIds.length = 0;
|
|
1303
|
+
pathWithoutLabels.push(entry.type === "compaction"
|
|
1304
|
+
? {
|
|
1305
|
+
...entry,
|
|
1306
|
+
parentId: pathParentId,
|
|
1307
|
+
firstKeptEntryId: entry.firstKeptEntryId === entry.id
|
|
1308
|
+
? entry.id
|
|
1309
|
+
: (replacementByLabelId.get(entry.firstKeptEntryId) ?? entry.firstKeptEntryId),
|
|
1310
|
+
}
|
|
1311
|
+
: { ...entry, parentId: pathParentId });
|
|
1175
1312
|
pathParentId = entry.id;
|
|
1176
1313
|
}
|
|
1177
1314
|
const newSessionId = createSessionId();
|
|
@@ -1305,9 +1442,9 @@ export class SessionManager {
|
|
|
1305
1442
|
}
|
|
1306
1443
|
return new SessionManager(cwd, dir, undefined, true);
|
|
1307
1444
|
}
|
|
1308
|
-
/** Create an in-memory session (no file persistence) */
|
|
1309
|
-
static inMemory(cwd = process.cwd(), options) {
|
|
1310
|
-
return new SessionManager(cwd, "", undefined, false, options);
|
|
1445
|
+
/** Create an in-memory session (no file persistence), optionally from entries held outside the filesystem. */
|
|
1446
|
+
static inMemory(cwd = process.cwd(), options, entries) {
|
|
1447
|
+
return new SessionManager(cwd, "", undefined, false, options, entries);
|
|
1311
1448
|
}
|
|
1312
1449
|
/**
|
|
1313
1450
|
* Fork a session from another project directory into the current project.
|
|
@@ -1357,67 +1494,110 @@ export class SessionManager {
|
|
|
1357
1494
|
}
|
|
1358
1495
|
return new SessionManager(resolvedTargetCwd, dir, newSessionFile, true);
|
|
1359
1496
|
}
|
|
1497
|
+
/**
|
|
1498
|
+
* Find an exact session ID without loading transcript bodies.
|
|
1499
|
+
* @param cwd Working directory (used to compute default session directory)
|
|
1500
|
+
* @param id Exact session ID
|
|
1501
|
+
* @param sessionDir Optional session directory. If omitted, uses default (~/.pi/agent/sessions/<encoded-cwd>/).
|
|
1502
|
+
*/
|
|
1503
|
+
static findById(cwd, id, sessionDir) {
|
|
1504
|
+
const dir = sessionDir ? normalizePath(sessionDir) : getDefaultSessionDir(cwd);
|
|
1505
|
+
const filterCwd = sessionDir !== undefined && dir !== getDefaultSessionDirPath(cwd);
|
|
1506
|
+
const resolvedCwd = resolvePath(cwd);
|
|
1507
|
+
try {
|
|
1508
|
+
for (const file of readdirSync(dir)) {
|
|
1509
|
+
if (!file.endsWith(".jsonl"))
|
|
1510
|
+
continue;
|
|
1511
|
+
const path = join(dir, file);
|
|
1512
|
+
const header = readSessionHeaderForDiscovery(path);
|
|
1513
|
+
if (header?.id !== id)
|
|
1514
|
+
continue;
|
|
1515
|
+
if (filterCwd && !sessionCwdMatches(getSessionHeaderCwd(header), resolvedCwd))
|
|
1516
|
+
continue;
|
|
1517
|
+
return path;
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
catch {
|
|
1521
|
+
// Exact session discovery is best-effort, matching list().
|
|
1522
|
+
}
|
|
1523
|
+
return undefined;
|
|
1524
|
+
}
|
|
1360
1525
|
/**
|
|
1361
1526
|
* List all sessions for a directory.
|
|
1362
1527
|
* @param cwd Working directory (used to compute default session directory)
|
|
1363
1528
|
* @param sessionDir Optional session directory. If omitted, uses default (~/.apex-code/agent/sessions/<encoded-cwd>/).
|
|
1364
1529
|
* @param onProgress Optional callback for progress updates (loaded, total)
|
|
1365
1530
|
*/
|
|
1366
|
-
static async list(cwd, sessionDir, onProgress) {
|
|
1531
|
+
static async list(cwd, sessionDir, onProgress, signal) {
|
|
1367
1532
|
const dir = sessionDir ? normalizePath(sessionDir) : getDefaultSessionDir(cwd);
|
|
1368
1533
|
const filterCwd = sessionDir !== undefined && dir !== getDefaultSessionDirPath(cwd);
|
|
1369
1534
|
const resolvedCwd = resolvePath(cwd);
|
|
1370
|
-
const
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1535
|
+
const includeSession = (session) => !filterCwd || sessionCwdMatches(session.cwd, resolvedCwd);
|
|
1536
|
+
const progress = onProgress
|
|
1537
|
+
? (loaded, total, partialSessions) => onProgress(loaded, total, partialSessions?.filter(includeSession))
|
|
1538
|
+
: undefined;
|
|
1539
|
+
const sessions = (await listSessionsFromDir(dir, progress, signal)).filter(includeSession);
|
|
1540
|
+
return sortSessionInfos(sessions);
|
|
1541
|
+
}
|
|
1542
|
+
static async listAll(sessionDirOrOnProgress, onProgressOrSignal, signal) {
|
|
1375
1543
|
const customSessionDir = typeof sessionDirOrOnProgress === "string" ? normalizePath(sessionDirOrOnProgress) : undefined;
|
|
1376
|
-
const progress = typeof sessionDirOrOnProgress === "function"
|
|
1544
|
+
const progress = typeof sessionDirOrOnProgress === "function"
|
|
1545
|
+
? sessionDirOrOnProgress
|
|
1546
|
+
: typeof onProgressOrSignal === "function"
|
|
1547
|
+
? onProgressOrSignal
|
|
1548
|
+
: undefined;
|
|
1549
|
+
const abortSignal = typeof sessionDirOrOnProgress === "string" || typeof onProgressOrSignal === "function"
|
|
1550
|
+
? signal
|
|
1551
|
+
: (onProgressOrSignal ?? signal);
|
|
1552
|
+
abortSignal?.throwIfAborted();
|
|
1377
1553
|
if (customSessionDir) {
|
|
1378
|
-
|
|
1379
|
-
sessions.sort((a, b) => b.modified.getTime() - a.modified.getTime());
|
|
1380
|
-
return sessions;
|
|
1554
|
+
return sortSessionInfos(await listSessionsFromDir(customSessionDir, progress, abortSignal));
|
|
1381
1555
|
}
|
|
1382
1556
|
const sessionsDir = getSessionsDir();
|
|
1383
1557
|
try {
|
|
1384
|
-
if (!existsSync(sessionsDir))
|
|
1558
|
+
if (!existsSync(sessionsDir))
|
|
1385
1559
|
return [];
|
|
1386
|
-
}
|
|
1387
1560
|
const entries = await readdir(sessionsDir, { withFileTypes: true });
|
|
1388
1561
|
const dirs = entries
|
|
1389
1562
|
.filter((entry) => entry.isDirectory() || entry.isSymbolicLink())
|
|
1390
1563
|
.map((entry) => join(sessionsDir, entry.name));
|
|
1391
|
-
|
|
1392
|
-
let totalFiles = 0;
|
|
1393
|
-
const dirFiles = [];
|
|
1394
|
-
for (const dir of dirs) {
|
|
1564
|
+
const dirFiles = await mapWithConcurrency(dirs, MAX_CONCURRENT_SESSION_DISCOVERY_LOADS, async (dir) => {
|
|
1395
1565
|
try {
|
|
1396
|
-
|
|
1397
|
-
dirFiles.push(files.map((f) => join(dir, f)));
|
|
1398
|
-
totalFiles += files.length;
|
|
1566
|
+
return (await readdir(dir)).filter((file) => file.endsWith(".jsonl")).map((file) => join(dir, file));
|
|
1399
1567
|
}
|
|
1400
1568
|
catch {
|
|
1401
|
-
|
|
1569
|
+
return [];
|
|
1402
1570
|
}
|
|
1403
|
-
}
|
|
1404
|
-
// Process all files with progress tracking
|
|
1405
|
-
let loaded = 0;
|
|
1406
|
-
const sessions = [];
|
|
1571
|
+
}, abortSignal);
|
|
1407
1572
|
const allFiles = dirFiles.flat();
|
|
1408
|
-
const
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
});
|
|
1412
|
-
for (const info of results) {
|
|
1413
|
-
if (info) {
|
|
1414
|
-
sessions.push(info);
|
|
1573
|
+
const candidates = await mapWithConcurrency(allFiles, MAX_CONCURRENT_SESSION_DISCOVERY_LOADS, async (path) => {
|
|
1574
|
+
try {
|
|
1575
|
+
return { path, stats: await stat(path) };
|
|
1415
1576
|
}
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1577
|
+
catch {
|
|
1578
|
+
return { path };
|
|
1579
|
+
}
|
|
1580
|
+
}, abortSignal);
|
|
1581
|
+
candidates.sort((a, b) => (b.stats?.mtimeMs ?? Number.NEGATIVE_INFINITY) - (a.stats?.mtimeMs ?? Number.NEGATIVE_INFINITY) ||
|
|
1582
|
+
basename(b.path).localeCompare(basename(a.path)));
|
|
1583
|
+
const totalFiles = candidates.length;
|
|
1584
|
+
let loaded = 0;
|
|
1585
|
+
let firstCandidateLoaded = false;
|
|
1586
|
+
const partialSessions = [];
|
|
1587
|
+
const results = await buildSessionInfosWithConcurrency(candidates, (info, index) => {
|
|
1588
|
+
loaded++;
|
|
1589
|
+
if (index === 0)
|
|
1590
|
+
firstCandidateLoaded = true;
|
|
1591
|
+
if (info)
|
|
1592
|
+
partialSessions.push(info);
|
|
1593
|
+
const publishPartial = firstCandidateLoaded &&
|
|
1594
|
+
(index === 0 || loaded % ALL_SESSION_LIST_PUBLISH_INTERVAL === 0 || loaded === totalFiles);
|
|
1595
|
+
progress?.(loaded, totalFiles, publishPartial ? sortSessionInfos([...partialSessions]) : undefined);
|
|
1596
|
+
}, abortSignal);
|
|
1597
|
+
return sortSessionInfos(results.filter((info) => info !== null));
|
|
1419
1598
|
}
|
|
1420
1599
|
catch {
|
|
1600
|
+
abortSignal?.throwIfAborted();
|
|
1421
1601
|
return [];
|
|
1422
1602
|
}
|
|
1423
1603
|
}
|