@imdigitalashish/zpi 0.1.1
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 +2801 -0
- package/README.md +95 -0
- package/dist/cli/args.d.ts +47 -0
- package/dist/cli/args.d.ts.map +1 -0
- package/dist/cli/args.js +293 -0
- package/dist/cli/args.js.map +1 -0
- package/dist/cli/config-selector.d.ts +14 -0
- package/dist/cli/config-selector.d.ts.map +1 -0
- package/dist/cli/config-selector.js +31 -0
- package/dist/cli/config-selector.js.map +1 -0
- package/dist/cli/file-processor.d.ts +15 -0
- package/dist/cli/file-processor.d.ts.map +1 -0
- package/dist/cli/file-processor.js +79 -0
- package/dist/cli/file-processor.js.map +1 -0
- package/dist/cli/list-models.d.ts +9 -0
- package/dist/cli/list-models.d.ts.map +1 -0
- package/dist/cli/list-models.js +92 -0
- package/dist/cli/list-models.js.map +1 -0
- package/dist/cli/session-picker.d.ts +9 -0
- package/dist/cli/session-picker.d.ts.map +1 -0
- package/dist/cli/session-picker.js +34 -0
- package/dist/cli/session-picker.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +11 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +68 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +203 -0
- package/dist/config.js.map +1 -0
- package/dist/core/agent-session.d.ts +571 -0
- package/dist/core/agent-session.d.ts.map +1 -0
- package/dist/core/agent-session.js +2353 -0
- package/dist/core/agent-session.js.map +1 -0
- package/dist/core/auth-storage.d.ts +129 -0
- package/dist/core/auth-storage.d.ts.map +1 -0
- package/dist/core/auth-storage.js +394 -0
- package/dist/core/auth-storage.js.map +1 -0
- package/dist/core/bash-executor.d.ts +47 -0
- package/dist/core/bash-executor.d.ts.map +1 -0
- package/dist/core/bash-executor.js +212 -0
- package/dist/core/bash-executor.js.map +1 -0
- package/dist/core/compaction/branch-summarization.d.ts +86 -0
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -0
- package/dist/core/compaction/branch-summarization.js +242 -0
- package/dist/core/compaction/branch-summarization.js.map +1 -0
- package/dist/core/compaction/compaction.d.ts +121 -0
- package/dist/core/compaction/compaction.d.ts.map +1 -0
- package/dist/core/compaction/compaction.js +607 -0
- package/dist/core/compaction/compaction.js.map +1 -0
- package/dist/core/compaction/index.d.ts +7 -0
- package/dist/core/compaction/index.d.ts.map +1 -0
- package/dist/core/compaction/index.js +7 -0
- package/dist/core/compaction/index.js.map +1 -0
- package/dist/core/compaction/utils.d.ts +35 -0
- package/dist/core/compaction/utils.d.ts.map +1 -0
- package/dist/core/compaction/utils.js +138 -0
- package/dist/core/compaction/utils.js.map +1 -0
- package/dist/core/defaults.d.ts +3 -0
- package/dist/core/defaults.d.ts.map +1 -0
- package/dist/core/defaults.js +2 -0
- package/dist/core/defaults.js.map +1 -0
- package/dist/core/diagnostics.d.ts +15 -0
- package/dist/core/diagnostics.d.ts.map +1 -0
- package/dist/core/diagnostics.js +2 -0
- package/dist/core/diagnostics.js.map +1 -0
- package/dist/core/event-bus.d.ts +9 -0
- package/dist/core/event-bus.d.ts.map +1 -0
- package/dist/core/event-bus.js +25 -0
- package/dist/core/event-bus.js.map +1 -0
- package/dist/core/exec.d.ts +29 -0
- package/dist/core/exec.d.ts.map +1 -0
- package/dist/core/exec.js +71 -0
- package/dist/core/exec.js.map +1 -0
- package/dist/core/export-html/ansi-to-html.d.ts +22 -0
- package/dist/core/export-html/ansi-to-html.d.ts.map +1 -0
- package/dist/core/export-html/ansi-to-html.js +249 -0
- package/dist/core/export-html/ansi-to-html.js.map +1 -0
- package/dist/core/export-html/index.d.ts +34 -0
- package/dist/core/export-html/index.d.ts.map +1 -0
- package/dist/core/export-html/index.js +222 -0
- package/dist/core/export-html/index.js.map +1 -0
- package/dist/core/export-html/template.css +971 -0
- package/dist/core/export-html/template.html +54 -0
- package/dist/core/export-html/template.js +1586 -0
- package/dist/core/export-html/tool-renderer.d.ts +35 -0
- package/dist/core/export-html/tool-renderer.d.ts.map +1 -0
- package/dist/core/export-html/tool-renderer.js +57 -0
- package/dist/core/export-html/tool-renderer.js.map +1 -0
- package/dist/core/export-html/vendor/highlight.min.js +1213 -0
- package/dist/core/export-html/vendor/marked.min.js +6 -0
- package/dist/core/extensions/index.d.ts +11 -0
- package/dist/core/extensions/index.d.ts.map +1 -0
- package/dist/core/extensions/index.js +9 -0
- package/dist/core/extensions/index.js.map +1 -0
- package/dist/core/extensions/loader.d.ts +25 -0
- package/dist/core/extensions/loader.d.ts.map +1 -0
- package/dist/core/extensions/loader.js +402 -0
- package/dist/core/extensions/loader.js.map +1 -0
- package/dist/core/extensions/runner.d.ts +146 -0
- package/dist/core/extensions/runner.d.ts.map +1 -0
- package/dist/core/extensions/runner.js +626 -0
- package/dist/core/extensions/runner.js.map +1 -0
- package/dist/core/extensions/types.d.ts +984 -0
- package/dist/core/extensions/types.d.ts.map +1 -0
- package/dist/core/extensions/types.js +35 -0
- package/dist/core/extensions/types.js.map +1 -0
- package/dist/core/extensions/wrapper.d.ts +27 -0
- package/dist/core/extensions/wrapper.d.ts.map +1 -0
- package/dist/core/extensions/wrapper.js +102 -0
- package/dist/core/extensions/wrapper.js.map +1 -0
- package/dist/core/footer-data-provider.d.ts +32 -0
- package/dist/core/footer-data-provider.d.ts.map +1 -0
- package/dist/core/footer-data-provider.js +134 -0
- package/dist/core/footer-data-provider.js.map +1 -0
- package/dist/core/index.d.ts +9 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +9 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/keybindings.d.ts +55 -0
- package/dist/core/keybindings.d.ts.map +1 -0
- package/dist/core/keybindings.js +153 -0
- package/dist/core/keybindings.js.map +1 -0
- package/dist/core/memory.d.ts +64 -0
- package/dist/core/memory.d.ts.map +1 -0
- package/dist/core/memory.js +247 -0
- package/dist/core/memory.js.map +1 -0
- package/dist/core/messages.d.ts +77 -0
- package/dist/core/messages.d.ts.map +1 -0
- package/dist/core/messages.js +149 -0
- package/dist/core/messages.js.map +1 -0
- package/dist/core/model-registry.d.ts +102 -0
- package/dist/core/model-registry.d.ts.map +1 -0
- package/dist/core/model-registry.js +515 -0
- package/dist/core/model-registry.js.map +1 -0
- package/dist/core/model-resolver.d.ts +104 -0
- package/dist/core/model-resolver.d.ts.map +1 -0
- package/dist/core/model-resolver.js +403 -0
- package/dist/core/model-resolver.js.map +1 -0
- package/dist/core/package-manager.d.ts +151 -0
- package/dist/core/package-manager.d.ts.map +1 -0
- package/dist/core/package-manager.js +1426 -0
- package/dist/core/package-manager.js.map +1 -0
- package/dist/core/prompt-templates.d.ts +50 -0
- package/dist/core/prompt-templates.d.ts.map +1 -0
- package/dist/core/prompt-templates.js +251 -0
- package/dist/core/prompt-templates.js.map +1 -0
- package/dist/core/resolve-config-value.d.ts +17 -0
- package/dist/core/resolve-config-value.d.ts.map +1 -0
- package/dist/core/resolve-config-value.js +59 -0
- package/dist/core/resolve-config-value.js.map +1 -0
- package/dist/core/resource-loader.d.ts +184 -0
- package/dist/core/resource-loader.d.ts.map +1 -0
- package/dist/core/resource-loader.js +673 -0
- package/dist/core/resource-loader.js.map +1 -0
- package/dist/core/sdk.d.ts +90 -0
- package/dist/core/sdk.d.ts.map +1 -0
- package/dist/core/sdk.js +238 -0
- package/dist/core/sdk.js.map +1 -0
- package/dist/core/session-manager.d.ts +323 -0
- package/dist/core/session-manager.d.ts.map +1 -0
- package/dist/core/session-manager.js +1091 -0
- package/dist/core/session-manager.js.map +1 -0
- package/dist/core/settings-manager.d.ts +230 -0
- package/dist/core/settings-manager.d.ts.map +1 -0
- package/dist/core/settings-manager.js +656 -0
- package/dist/core/settings-manager.js.map +1 -0
- package/dist/core/skills.d.ts +58 -0
- package/dist/core/skills.d.ts.map +1 -0
- package/dist/core/skills.js +364 -0
- package/dist/core/skills.js.map +1 -0
- package/dist/core/slash-commands.d.ts +15 -0
- package/dist/core/slash-commands.d.ts.map +1 -0
- package/dist/core/slash-commands.js +23 -0
- package/dist/core/slash-commands.js.map +1 -0
- package/dist/core/system-prompt.d.ts +26 -0
- package/dist/core/system-prompt.d.ts.map +1 -0
- package/dist/core/system-prompt.js +150 -0
- package/dist/core/system-prompt.js.map +1 -0
- package/dist/core/timings.d.ts +7 -0
- package/dist/core/timings.d.ts.map +1 -0
- package/dist/core/timings.js +25 -0
- package/dist/core/timings.js.map +1 -0
- package/dist/core/tools/bash.d.ts +55 -0
- package/dist/core/tools/bash.d.ts.map +1 -0
- package/dist/core/tools/bash.js +242 -0
- package/dist/core/tools/bash.js.map +1 -0
- package/dist/core/tools/edit-diff.d.ts +63 -0
- package/dist/core/tools/edit-diff.d.ts.map +1 -0
- package/dist/core/tools/edit-diff.js +243 -0
- package/dist/core/tools/edit-diff.js.map +1 -0
- package/dist/core/tools/edit.d.ts +39 -0
- package/dist/core/tools/edit.d.ts.map +1 -0
- package/dist/core/tools/edit.js +146 -0
- package/dist/core/tools/edit.js.map +1 -0
- package/dist/core/tools/find.d.ts +39 -0
- package/dist/core/tools/find.d.ts.map +1 -0
- package/dist/core/tools/find.js +206 -0
- package/dist/core/tools/find.js.map +1 -0
- package/dist/core/tools/grep.d.ts +45 -0
- package/dist/core/tools/grep.d.ts.map +1 -0
- package/dist/core/tools/grep.js +239 -0
- package/dist/core/tools/grep.js.map +1 -0
- package/dist/core/tools/index.d.ts +102 -0
- package/dist/core/tools/index.d.ts.map +1 -0
- package/dist/core/tools/index.js +71 -0
- package/dist/core/tools/index.js.map +1 -0
- package/dist/core/tools/ls.d.ts +40 -0
- package/dist/core/tools/ls.d.ts.map +1 -0
- package/dist/core/tools/ls.js +118 -0
- package/dist/core/tools/ls.js.map +1 -0
- package/dist/core/tools/memory.d.ts +45 -0
- package/dist/core/tools/memory.d.ts.map +1 -0
- package/dist/core/tools/memory.js +346 -0
- package/dist/core/tools/memory.js.map +1 -0
- package/dist/core/tools/path-utils.d.ts +8 -0
- package/dist/core/tools/path-utils.d.ts.map +1 -0
- package/dist/core/tools/path-utils.js +81 -0
- package/dist/core/tools/path-utils.js.map +1 -0
- package/dist/core/tools/read.d.ts +39 -0
- package/dist/core/tools/read.d.ts.map +1 -0
- package/dist/core/tools/read.js +166 -0
- package/dist/core/tools/read.js.map +1 -0
- package/dist/core/tools/truncate.d.ts +70 -0
- package/dist/core/tools/truncate.d.ts.map +1 -0
- package/dist/core/tools/truncate.js +205 -0
- package/dist/core/tools/truncate.js.map +1 -0
- package/dist/core/tools/write.d.ts +29 -0
- package/dist/core/tools/write.d.ts.map +1 -0
- package/dist/core/tools/write.js +78 -0
- package/dist/core/tools/write.js.map +1 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +43 -0
- package/dist/index.js.map +1 -0
- package/dist/main.d.ts +8 -0
- package/dist/main.d.ts.map +1 -0
- package/dist/main.js +651 -0
- package/dist/main.js.map +1 -0
- package/dist/migrations.d.ts +33 -0
- package/dist/migrations.d.ts.map +1 -0
- package/dist/migrations.js +261 -0
- package/dist/migrations.js.map +1 -0
- package/dist/modes/index.d.ts +9 -0
- package/dist/modes/index.d.ts.map +1 -0
- package/dist/modes/index.js +8 -0
- package/dist/modes/index.js.map +1 -0
- package/dist/modes/interactive/components/armin.d.ts +34 -0
- package/dist/modes/interactive/components/armin.d.ts.map +1 -0
- package/dist/modes/interactive/components/armin.js +333 -0
- package/dist/modes/interactive/components/armin.js.map +1 -0
- package/dist/modes/interactive/components/assistant-message.d.ts +16 -0
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/assistant-message.js +96 -0
- package/dist/modes/interactive/components/assistant-message.js.map +1 -0
- package/dist/modes/interactive/components/bash-execution.d.ts +35 -0
- package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -0
- package/dist/modes/interactive/components/bash-execution.js +162 -0
- package/dist/modes/interactive/components/bash-execution.js.map +1 -0
- package/dist/modes/interactive/components/bordered-loader.d.ts +16 -0
- package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -0
- package/dist/modes/interactive/components/bordered-loader.js +51 -0
- package/dist/modes/interactive/components/bordered-loader.js.map +1 -0
- package/dist/modes/interactive/components/branch-summary-message.d.ts +16 -0
- package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/branch-summary-message.js +44 -0
- package/dist/modes/interactive/components/branch-summary-message.js.map +1 -0
- package/dist/modes/interactive/components/compaction-summary-message.d.ts +16 -0
- package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/compaction-summary-message.js +45 -0
- package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -0
- package/dist/modes/interactive/components/config-selector.d.ts +71 -0
- package/dist/modes/interactive/components/config-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/config-selector.js +479 -0
- package/dist/modes/interactive/components/config-selector.js.map +1 -0
- package/dist/modes/interactive/components/countdown-timer.d.ts +14 -0
- package/dist/modes/interactive/components/countdown-timer.d.ts.map +1 -0
- package/dist/modes/interactive/components/countdown-timer.js +33 -0
- package/dist/modes/interactive/components/countdown-timer.js.map +1 -0
- package/dist/modes/interactive/components/custom-editor.d.ts +21 -0
- package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -0
- package/dist/modes/interactive/components/custom-editor.js +70 -0
- package/dist/modes/interactive/components/custom-editor.js.map +1 -0
- package/dist/modes/interactive/components/custom-message.d.ts +20 -0
- package/dist/modes/interactive/components/custom-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/custom-message.js +79 -0
- package/dist/modes/interactive/components/custom-message.js.map +1 -0
- package/dist/modes/interactive/components/daxnuts.d.ts +23 -0
- package/dist/modes/interactive/components/daxnuts.d.ts.map +1 -0
- package/dist/modes/interactive/components/daxnuts.js +140 -0
- package/dist/modes/interactive/components/daxnuts.js.map +1 -0
- package/dist/modes/interactive/components/diff.d.ts +12 -0
- package/dist/modes/interactive/components/diff.d.ts.map +1 -0
- package/dist/modes/interactive/components/diff.js +133 -0
- package/dist/modes/interactive/components/diff.js.map +1 -0
- package/dist/modes/interactive/components/dynamic-border.d.ts +15 -0
- package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -0
- package/dist/modes/interactive/components/dynamic-border.js +21 -0
- package/dist/modes/interactive/components/dynamic-border.js.map +1 -0
- package/dist/modes/interactive/components/extension-editor.d.ts +17 -0
- package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -0
- package/dist/modes/interactive/components/extension-editor.js +102 -0
- package/dist/modes/interactive/components/extension-editor.js.map +1 -0
- package/dist/modes/interactive/components/extension-input.d.ts +23 -0
- package/dist/modes/interactive/components/extension-input.d.ts.map +1 -0
- package/dist/modes/interactive/components/extension-input.js +61 -0
- package/dist/modes/interactive/components/extension-input.js.map +1 -0
- package/dist/modes/interactive/components/extension-selector.d.ts +24 -0
- package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/extension-selector.js +78 -0
- package/dist/modes/interactive/components/extension-selector.js.map +1 -0
- package/dist/modes/interactive/components/footer.d.ts +26 -0
- package/dist/modes/interactive/components/footer.d.ts.map +1 -0
- package/dist/modes/interactive/components/footer.js +213 -0
- package/dist/modes/interactive/components/footer.js.map +1 -0
- package/dist/modes/interactive/components/index.d.ts +32 -0
- package/dist/modes/interactive/components/index.d.ts.map +1 -0
- package/dist/modes/interactive/components/index.js +33 -0
- package/dist/modes/interactive/components/index.js.map +1 -0
- package/dist/modes/interactive/components/keybinding-hints.d.ts +41 -0
- package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -0
- package/dist/modes/interactive/components/keybinding-hints.js +61 -0
- package/dist/modes/interactive/components/keybinding-hints.js.map +1 -0
- package/dist/modes/interactive/components/login-dialog.d.ts +42 -0
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -0
- package/dist/modes/interactive/components/login-dialog.js +145 -0
- package/dist/modes/interactive/components/login-dialog.js.map +1 -0
- package/dist/modes/interactive/components/model-selector.d.ts +47 -0
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/model-selector.js +271 -0
- package/dist/modes/interactive/components/model-selector.js.map +1 -0
- package/dist/modes/interactive/components/oauth-selector.d.ts +19 -0
- package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/oauth-selector.js +97 -0
- package/dist/modes/interactive/components/oauth-selector.js.map +1 -0
- package/dist/modes/interactive/components/scoped-models-selector.d.ts +49 -0
- package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/scoped-models-selector.js +275 -0
- package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -0
- package/dist/modes/interactive/components/session-selector-search.d.ts +23 -0
- package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -0
- package/dist/modes/interactive/components/session-selector-search.js +155 -0
- package/dist/modes/interactive/components/session-selector-search.js.map +1 -0
- package/dist/modes/interactive/components/session-selector.d.ts +95 -0
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/session-selector.js +851 -0
- package/dist/modes/interactive/components/session-selector.js.map +1 -0
- package/dist/modes/interactive/components/settings-selector.d.ts +58 -0
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/settings-selector.js +299 -0
- package/dist/modes/interactive/components/settings-selector.js.map +1 -0
- package/dist/modes/interactive/components/show-images-selector.d.ts +10 -0
- package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/show-images-selector.js +35 -0
- package/dist/modes/interactive/components/show-images-selector.js.map +1 -0
- package/dist/modes/interactive/components/skill-invocation-message.d.ts +17 -0
- package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/skill-invocation-message.js +47 -0
- package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -0
- package/dist/modes/interactive/components/theme-selector.d.ts +11 -0
- package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/theme-selector.js +46 -0
- package/dist/modes/interactive/components/theme-selector.js.map +1 -0
- package/dist/modes/interactive/components/thinking-selector.d.ts +11 -0
- package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/thinking-selector.js +47 -0
- package/dist/modes/interactive/components/thinking-selector.js.map +1 -0
- package/dist/modes/interactive/components/tool-execution.d.ts +70 -0
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -0
- package/dist/modes/interactive/components/tool-execution.js +636 -0
- package/dist/modes/interactive/components/tool-execution.js.map +1 -0
- package/dist/modes/interactive/components/tree-selector.d.ts +68 -0
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/tree-selector.js +934 -0
- package/dist/modes/interactive/components/tree-selector.js.map +1 -0
- package/dist/modes/interactive/components/user-message-selector.d.ts +30 -0
- package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/user-message-selector.js +113 -0
- package/dist/modes/interactive/components/user-message-selector.js.map +1 -0
- package/dist/modes/interactive/components/user-message.d.ts +8 -0
- package/dist/modes/interactive/components/user-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/user-message.js +16 -0
- package/dist/modes/interactive/components/user-message.js.map +1 -0
- package/dist/modes/interactive/components/visual-truncate.d.ts +24 -0
- package/dist/modes/interactive/components/visual-truncate.d.ts.map +1 -0
- package/dist/modes/interactive/components/visual-truncate.js +33 -0
- package/dist/modes/interactive/components/visual-truncate.js.map +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts +316 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -0
- package/dist/modes/interactive/interactive-mode.js +3848 -0
- package/dist/modes/interactive/interactive-mode.js.map +1 -0
- package/dist/modes/interactive/theme/dark.json +85 -0
- package/dist/modes/interactive/theme/light.json +84 -0
- package/dist/modes/interactive/theme/theme-schema.json +335 -0
- package/dist/modes/interactive/theme/theme.d.ts +78 -0
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -0
- package/dist/modes/interactive/theme/theme.js +944 -0
- package/dist/modes/interactive/theme/theme.js.map +1 -0
- package/dist/modes/print-mode.d.ts +28 -0
- package/dist/modes/print-mode.d.ts.map +1 -0
- package/dist/modes/print-mode.js +101 -0
- package/dist/modes/print-mode.js.map +1 -0
- package/dist/modes/rpc/rpc-client.d.ts +217 -0
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -0
- package/dist/modes/rpc/rpc-client.js +405 -0
- package/dist/modes/rpc/rpc-client.js.map +1 -0
- package/dist/modes/rpc/rpc-mode.d.ts +20 -0
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -0
- package/dist/modes/rpc/rpc-mode.js +511 -0
- package/dist/modes/rpc/rpc-mode.js.map +1 -0
- package/dist/modes/rpc/rpc-types.d.ts +409 -0
- package/dist/modes/rpc/rpc-types.d.ts.map +1 -0
- package/dist/modes/rpc/rpc-types.js +8 -0
- package/dist/modes/rpc/rpc-types.js.map +1 -0
- package/dist/utils/changelog.d.ts +21 -0
- package/dist/utils/changelog.d.ts.map +1 -0
- package/dist/utils/changelog.js +87 -0
- package/dist/utils/changelog.js.map +1 -0
- package/dist/utils/clipboard-image.d.ts +11 -0
- package/dist/utils/clipboard-image.d.ts.map +1 -0
- package/dist/utils/clipboard-image.js +162 -0
- package/dist/utils/clipboard-image.js.map +1 -0
- package/dist/utils/clipboard-native.d.ts +7 -0
- package/dist/utils/clipboard-native.d.ts.map +1 -0
- package/dist/utils/clipboard-native.js +14 -0
- package/dist/utils/clipboard-native.js.map +1 -0
- package/dist/utils/clipboard.d.ts +2 -0
- package/dist/utils/clipboard.d.ts.map +1 -0
- package/dist/utils/clipboard.js +67 -0
- package/dist/utils/clipboard.js.map +1 -0
- package/dist/utils/frontmatter.d.ts +8 -0
- package/dist/utils/frontmatter.d.ts.map +1 -0
- package/dist/utils/frontmatter.js +26 -0
- package/dist/utils/frontmatter.js.map +1 -0
- package/dist/utils/git.d.ts +26 -0
- package/dist/utils/git.d.ts.map +1 -0
- package/dist/utils/git.js +163 -0
- package/dist/utils/git.js.map +1 -0
- package/dist/utils/image-convert.d.ts +9 -0
- package/dist/utils/image-convert.d.ts.map +1 -0
- package/dist/utils/image-convert.js +35 -0
- package/dist/utils/image-convert.js.map +1 -0
- package/dist/utils/image-resize.d.ts +36 -0
- package/dist/utils/image-resize.d.ts.map +1 -0
- package/dist/utils/image-resize.js +181 -0
- package/dist/utils/image-resize.js.map +1 -0
- package/dist/utils/mime.d.ts +2 -0
- package/dist/utils/mime.d.ts.map +1 -0
- package/dist/utils/mime.js +26 -0
- package/dist/utils/mime.js.map +1 -0
- package/dist/utils/photon.d.ts +21 -0
- package/dist/utils/photon.d.ts.map +1 -0
- package/dist/utils/photon.js +121 -0
- package/dist/utils/photon.js.map +1 -0
- package/dist/utils/shell.d.ts +26 -0
- package/dist/utils/shell.d.ts.map +1 -0
- package/dist/utils/shell.js +186 -0
- package/dist/utils/shell.js.map +1 -0
- package/dist/utils/sleep.d.ts +5 -0
- package/dist/utils/sleep.d.ts.map +1 -0
- package/dist/utils/sleep.js +17 -0
- package/dist/utils/sleep.js.map +1 -0
- package/dist/utils/tools-manager.d.ts +3 -0
- package/dist/utils/tools-manager.d.ts.map +1 -0
- package/dist/utils/tools-manager.js +207 -0
- package/dist/utils/tools-manager.js.map +1 -0
- package/docs/compaction.md +390 -0
- package/docs/custom-provider.md +548 -0
- package/docs/development.md +69 -0
- package/docs/extensions.md +1935 -0
- package/docs/images/doom-extension.png +0 -0
- package/docs/images/exy.png +0 -0
- package/docs/images/interactive-mode.png +0 -0
- package/docs/images/tree-view.png +0 -0
- package/docs/json.md +79 -0
- package/docs/keybindings.md +174 -0
- package/docs/models.md +293 -0
- package/docs/packages.md +209 -0
- package/docs/prompt-templates.md +67 -0
- package/docs/providers.md +186 -0
- package/docs/rpc.md +1317 -0
- package/docs/sdk.md +968 -0
- package/docs/session.md +412 -0
- package/docs/settings.md +223 -0
- package/docs/shell-aliases.md +13 -0
- package/docs/skills.md +231 -0
- package/docs/terminal-setup.md +70 -0
- package/docs/termux.md +127 -0
- package/docs/themes.md +295 -0
- package/docs/tree.md +219 -0
- package/docs/tui.md +887 -0
- package/docs/windows.md +17 -0
- package/examples/README.md +25 -0
- package/examples/extensions/README.md +203 -0
- package/examples/extensions/antigravity-image-gen.ts +413 -0
- package/examples/extensions/auto-commit-on-exit.ts +49 -0
- package/examples/extensions/bash-spawn-hook.ts +30 -0
- package/examples/extensions/bookmark.ts +50 -0
- package/examples/extensions/claude-rules.ts +86 -0
- package/examples/extensions/commands.ts +72 -0
- package/examples/extensions/confirm-destructive.ts +59 -0
- package/examples/extensions/custom-compaction.ts +114 -0
- package/examples/extensions/custom-footer.ts +64 -0
- package/examples/extensions/custom-header.ts +73 -0
- package/examples/extensions/custom-provider-anthropic/index.ts +604 -0
- package/examples/extensions/custom-provider-anthropic/package-lock.json +24 -0
- package/examples/extensions/custom-provider-anthropic/package.json +19 -0
- package/examples/extensions/custom-provider-gitlab-duo/index.ts +349 -0
- package/examples/extensions/custom-provider-gitlab-duo/package.json +16 -0
- package/examples/extensions/custom-provider-gitlab-duo/test.ts +82 -0
- package/examples/extensions/custom-provider-qwen-cli/index.ts +345 -0
- package/examples/extensions/custom-provider-qwen-cli/package.json +16 -0
- package/examples/extensions/dirty-repo-guard.ts +56 -0
- package/examples/extensions/doom-overlay/README.md +46 -0
- package/examples/extensions/doom-overlay/doom/build/doom.js +21 -0
- package/examples/extensions/doom-overlay/doom/build/doom.wasm +0 -0
- package/examples/extensions/doom-overlay/doom/build.sh +152 -0
- package/examples/extensions/doom-overlay/doom/doomgeneric_pi.c +72 -0
- package/examples/extensions/doom-overlay/doom-component.ts +132 -0
- package/examples/extensions/doom-overlay/doom-engine.ts +173 -0
- package/examples/extensions/doom-overlay/doom-keys.ts +104 -0
- package/examples/extensions/doom-overlay/index.ts +74 -0
- package/examples/extensions/doom-overlay/wad-finder.ts +51 -0
- package/examples/extensions/dynamic-resources/SKILL.md +8 -0
- package/examples/extensions/dynamic-resources/dynamic.json +79 -0
- package/examples/extensions/dynamic-resources/dynamic.md +5 -0
- package/examples/extensions/dynamic-resources/index.ts +15 -0
- package/examples/extensions/event-bus.ts +43 -0
- package/examples/extensions/file-trigger.ts +41 -0
- package/examples/extensions/git-checkpoint.ts +53 -0
- package/examples/extensions/handoff.ts +150 -0
- package/examples/extensions/hello.ts +25 -0
- package/examples/extensions/inline-bash.ts +94 -0
- package/examples/extensions/input-transform.ts +43 -0
- package/examples/extensions/interactive-shell.ts +196 -0
- package/examples/extensions/mac-system-theme.ts +47 -0
- package/examples/extensions/message-renderer.ts +59 -0
- package/examples/extensions/minimal-mode.ts +426 -0
- package/examples/extensions/modal-editor.ts +85 -0
- package/examples/extensions/model-status.ts +31 -0
- package/examples/extensions/notify.ts +55 -0
- package/examples/extensions/overlay-qa-tests.ts +881 -0
- package/examples/extensions/overlay-test.ts +150 -0
- package/examples/extensions/permission-gate.ts +34 -0
- package/examples/extensions/pirate.ts +47 -0
- package/examples/extensions/plan-mode/README.md +65 -0
- package/examples/extensions/plan-mode/index.ts +340 -0
- package/examples/extensions/plan-mode/utils.ts +168 -0
- package/examples/extensions/preset.ts +398 -0
- package/examples/extensions/protected-paths.ts +30 -0
- package/examples/extensions/qna.ts +119 -0
- package/examples/extensions/question.ts +264 -0
- package/examples/extensions/questionnaire.ts +427 -0
- package/examples/extensions/rainbow-editor.ts +88 -0
- package/examples/extensions/reload-runtime.ts +37 -0
- package/examples/extensions/rpc-demo.ts +124 -0
- package/examples/extensions/sandbox/index.ts +318 -0
- package/examples/extensions/sandbox/package-lock.json +92 -0
- package/examples/extensions/sandbox/package.json +19 -0
- package/examples/extensions/send-user-message.ts +97 -0
- package/examples/extensions/session-name.ts +27 -0
- package/examples/extensions/shutdown-command.ts +63 -0
- package/examples/extensions/snake.ts +343 -0
- package/examples/extensions/space-invaders.ts +560 -0
- package/examples/extensions/ssh.ts +220 -0
- package/examples/extensions/status-line.ts +40 -0
- package/examples/extensions/subagent/README.md +172 -0
- package/examples/extensions/subagent/agents/planner.md +37 -0
- package/examples/extensions/subagent/agents/reviewer.md +35 -0
- package/examples/extensions/subagent/agents/scout.md +50 -0
- package/examples/extensions/subagent/agents/worker.md +24 -0
- package/examples/extensions/subagent/agents.ts +127 -0
- package/examples/extensions/subagent/index.ts +964 -0
- package/examples/extensions/subagent/prompts/implement-and-review.md +10 -0
- package/examples/extensions/subagent/prompts/implement.md +10 -0
- package/examples/extensions/subagent/prompts/scout-and-plan.md +9 -0
- package/examples/extensions/summarize.ts +195 -0
- package/examples/extensions/system-prompt-header.ts +17 -0
- package/examples/extensions/timed-confirm.ts +70 -0
- package/examples/extensions/titlebar-spinner.ts +58 -0
- package/examples/extensions/todo.ts +299 -0
- package/examples/extensions/tool-override.ts +143 -0
- package/examples/extensions/tools.ts +146 -0
- package/examples/extensions/trigger-compact.ts +40 -0
- package/examples/extensions/truncated-tool.ts +192 -0
- package/examples/extensions/widget-placement.ts +17 -0
- package/examples/extensions/with-deps/index.ts +36 -0
- package/examples/extensions/with-deps/package-lock.json +31 -0
- package/examples/extensions/with-deps/package.json +22 -0
- package/examples/rpc-extension-ui.ts +632 -0
- package/examples/sdk/01-minimal.ts +22 -0
- package/examples/sdk/02-custom-model.ts +49 -0
- package/examples/sdk/03-custom-prompt.ts +55 -0
- package/examples/sdk/04-skills.ts +46 -0
- package/examples/sdk/05-tools.ts +56 -0
- package/examples/sdk/06-extensions.ts +88 -0
- package/examples/sdk/07-context-files.ts +40 -0
- package/examples/sdk/08-prompt-templates.ts +47 -0
- package/examples/sdk/09-api-keys-and-oauth.ts +48 -0
- package/examples/sdk/10-settings.ts +51 -0
- package/examples/sdk/11-sessions.ts +48 -0
- package/examples/sdk/12-full-control.ts +82 -0
- package/examples/sdk/README.md +144 -0
- package/package.json +96 -0
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { existsSync, readFileSync, statSync, watch } from "fs";
|
|
2
|
+
import { dirname, join, resolve } from "path";
|
|
3
|
+
/**
|
|
4
|
+
* Find the git HEAD path by walking up from cwd.
|
|
5
|
+
* Handles both regular git repos (.git is a directory) and worktrees (.git is a file).
|
|
6
|
+
*/
|
|
7
|
+
function findGitHeadPath() {
|
|
8
|
+
let dir = process.cwd();
|
|
9
|
+
while (true) {
|
|
10
|
+
const gitPath = join(dir, ".git");
|
|
11
|
+
if (existsSync(gitPath)) {
|
|
12
|
+
try {
|
|
13
|
+
const stat = statSync(gitPath);
|
|
14
|
+
if (stat.isFile()) {
|
|
15
|
+
const content = readFileSync(gitPath, "utf8").trim();
|
|
16
|
+
if (content.startsWith("gitdir: ")) {
|
|
17
|
+
const gitDir = content.slice(8);
|
|
18
|
+
const headPath = resolve(dir, gitDir, "HEAD");
|
|
19
|
+
if (existsSync(headPath))
|
|
20
|
+
return headPath;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
else if (stat.isDirectory()) {
|
|
24
|
+
const headPath = join(gitPath, "HEAD");
|
|
25
|
+
if (existsSync(headPath))
|
|
26
|
+
return headPath;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
const parent = dirname(dir);
|
|
34
|
+
if (parent === dir)
|
|
35
|
+
return null;
|
|
36
|
+
dir = parent;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Provides git branch and extension statuses - data not otherwise accessible to extensions.
|
|
41
|
+
* Token stats, model info available via ctx.sessionManager and ctx.model.
|
|
42
|
+
*/
|
|
43
|
+
export class FooterDataProvider {
|
|
44
|
+
extensionStatuses = new Map();
|
|
45
|
+
cachedBranch = undefined;
|
|
46
|
+
gitWatcher = null;
|
|
47
|
+
branchChangeCallbacks = new Set();
|
|
48
|
+
availableProviderCount = 0;
|
|
49
|
+
constructor() {
|
|
50
|
+
this.setupGitWatcher();
|
|
51
|
+
}
|
|
52
|
+
/** Current git branch, null if not in repo, "detached" if detached HEAD */
|
|
53
|
+
getGitBranch() {
|
|
54
|
+
if (this.cachedBranch !== undefined)
|
|
55
|
+
return this.cachedBranch;
|
|
56
|
+
try {
|
|
57
|
+
const gitHeadPath = findGitHeadPath();
|
|
58
|
+
if (!gitHeadPath) {
|
|
59
|
+
this.cachedBranch = null;
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
const content = readFileSync(gitHeadPath, "utf8").trim();
|
|
63
|
+
this.cachedBranch = content.startsWith("ref: refs/heads/") ? content.slice(16) : "detached";
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
this.cachedBranch = null;
|
|
67
|
+
}
|
|
68
|
+
return this.cachedBranch;
|
|
69
|
+
}
|
|
70
|
+
/** Extension status texts set via ctx.ui.setStatus() */
|
|
71
|
+
getExtensionStatuses() {
|
|
72
|
+
return this.extensionStatuses;
|
|
73
|
+
}
|
|
74
|
+
/** Subscribe to git branch changes. Returns unsubscribe function. */
|
|
75
|
+
onBranchChange(callback) {
|
|
76
|
+
this.branchChangeCallbacks.add(callback);
|
|
77
|
+
return () => this.branchChangeCallbacks.delete(callback);
|
|
78
|
+
}
|
|
79
|
+
/** Internal: set extension status */
|
|
80
|
+
setExtensionStatus(key, text) {
|
|
81
|
+
if (text === undefined) {
|
|
82
|
+
this.extensionStatuses.delete(key);
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
this.extensionStatuses.set(key, text);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
/** Internal: clear extension statuses */
|
|
89
|
+
clearExtensionStatuses() {
|
|
90
|
+
this.extensionStatuses.clear();
|
|
91
|
+
}
|
|
92
|
+
/** Number of unique providers with available models (for footer display) */
|
|
93
|
+
getAvailableProviderCount() {
|
|
94
|
+
return this.availableProviderCount;
|
|
95
|
+
}
|
|
96
|
+
/** Internal: update available provider count */
|
|
97
|
+
setAvailableProviderCount(count) {
|
|
98
|
+
this.availableProviderCount = count;
|
|
99
|
+
}
|
|
100
|
+
/** Internal: cleanup */
|
|
101
|
+
dispose() {
|
|
102
|
+
if (this.gitWatcher) {
|
|
103
|
+
this.gitWatcher.close();
|
|
104
|
+
this.gitWatcher = null;
|
|
105
|
+
}
|
|
106
|
+
this.branchChangeCallbacks.clear();
|
|
107
|
+
}
|
|
108
|
+
setupGitWatcher() {
|
|
109
|
+
if (this.gitWatcher) {
|
|
110
|
+
this.gitWatcher.close();
|
|
111
|
+
this.gitWatcher = null;
|
|
112
|
+
}
|
|
113
|
+
const gitHeadPath = findGitHeadPath();
|
|
114
|
+
if (!gitHeadPath)
|
|
115
|
+
return;
|
|
116
|
+
// Watch the directory containing HEAD, not HEAD itself.
|
|
117
|
+
// Git uses atomic writes (write temp, rename over HEAD), which changes the inode.
|
|
118
|
+
// fs.watch on a file stops working after the inode changes.
|
|
119
|
+
const gitDir = dirname(gitHeadPath);
|
|
120
|
+
try {
|
|
121
|
+
this.gitWatcher = watch(gitDir, (_eventType, filename) => {
|
|
122
|
+
if (filename === "HEAD") {
|
|
123
|
+
this.cachedBranch = undefined;
|
|
124
|
+
for (const cb of this.branchChangeCallbacks)
|
|
125
|
+
cb();
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
catch {
|
|
130
|
+
// Silently fail if we can't watch
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=footer-data-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"footer-data-provider.js","sourceRoot":"","sources":["../../src/core/footer-data-provider.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, type FSWatcher, readFileSync, statSync, watch } from \"fs\";\r\nimport { dirname, join, resolve } from \"path\";\r\n\r\n/**\r\n * Find the git HEAD path by walking up from cwd.\r\n * Handles both regular git repos (.git is a directory) and worktrees (.git is a file).\r\n */\r\nfunction findGitHeadPath(): string | null {\r\n\tlet dir = process.cwd();\r\n\twhile (true) {\r\n\t\tconst gitPath = join(dir, \".git\");\r\n\t\tif (existsSync(gitPath)) {\r\n\t\t\ttry {\r\n\t\t\t\tconst stat = statSync(gitPath);\r\n\t\t\t\tif (stat.isFile()) {\r\n\t\t\t\t\tconst content = readFileSync(gitPath, \"utf8\").trim();\r\n\t\t\t\t\tif (content.startsWith(\"gitdir: \")) {\r\n\t\t\t\t\t\tconst gitDir = content.slice(8);\r\n\t\t\t\t\t\tconst headPath = resolve(dir, gitDir, \"HEAD\");\r\n\t\t\t\t\t\tif (existsSync(headPath)) return headPath;\r\n\t\t\t\t\t}\r\n\t\t\t\t} else if (stat.isDirectory()) {\r\n\t\t\t\t\tconst headPath = join(gitPath, \"HEAD\");\r\n\t\t\t\t\tif (existsSync(headPath)) return headPath;\r\n\t\t\t\t}\r\n\t\t\t} catch {\r\n\t\t\t\treturn null;\r\n\t\t\t}\r\n\t\t}\r\n\t\tconst parent = dirname(dir);\r\n\t\tif (parent === dir) return null;\r\n\t\tdir = parent;\r\n\t}\r\n}\r\n\r\n/**\r\n * Provides git branch and extension statuses - data not otherwise accessible to extensions.\r\n * Token stats, model info available via ctx.sessionManager and ctx.model.\r\n */\r\nexport class FooterDataProvider {\r\n\tprivate extensionStatuses = new Map<string, string>();\r\n\tprivate cachedBranch: string | null | undefined = undefined;\r\n\tprivate gitWatcher: FSWatcher | null = null;\r\n\tprivate branchChangeCallbacks = new Set<() => void>();\r\n\tprivate availableProviderCount = 0;\r\n\r\n\tconstructor() {\r\n\t\tthis.setupGitWatcher();\r\n\t}\r\n\r\n\t/** Current git branch, null if not in repo, \"detached\" if detached HEAD */\r\n\tgetGitBranch(): string | null {\r\n\t\tif (this.cachedBranch !== undefined) return this.cachedBranch;\r\n\r\n\t\ttry {\r\n\t\t\tconst gitHeadPath = findGitHeadPath();\r\n\t\t\tif (!gitHeadPath) {\r\n\t\t\t\tthis.cachedBranch = null;\r\n\t\t\t\treturn null;\r\n\t\t\t}\r\n\t\t\tconst content = readFileSync(gitHeadPath, \"utf8\").trim();\r\n\t\t\tthis.cachedBranch = content.startsWith(\"ref: refs/heads/\") ? content.slice(16) : \"detached\";\r\n\t\t} catch {\r\n\t\t\tthis.cachedBranch = null;\r\n\t\t}\r\n\t\treturn this.cachedBranch;\r\n\t}\r\n\r\n\t/** Extension status texts set via ctx.ui.setStatus() */\r\n\tgetExtensionStatuses(): ReadonlyMap<string, string> {\r\n\t\treturn this.extensionStatuses;\r\n\t}\r\n\r\n\t/** Subscribe to git branch changes. Returns unsubscribe function. */\r\n\tonBranchChange(callback: () => void): () => void {\r\n\t\tthis.branchChangeCallbacks.add(callback);\r\n\t\treturn () => this.branchChangeCallbacks.delete(callback);\r\n\t}\r\n\r\n\t/** Internal: set extension status */\r\n\tsetExtensionStatus(key: string, text: string | undefined): void {\r\n\t\tif (text === undefined) {\r\n\t\t\tthis.extensionStatuses.delete(key);\r\n\t\t} else {\r\n\t\t\tthis.extensionStatuses.set(key, text);\r\n\t\t}\r\n\t}\r\n\r\n\t/** Internal: clear extension statuses */\r\n\tclearExtensionStatuses(): void {\r\n\t\tthis.extensionStatuses.clear();\r\n\t}\r\n\r\n\t/** Number of unique providers with available models (for footer display) */\r\n\tgetAvailableProviderCount(): number {\r\n\t\treturn this.availableProviderCount;\r\n\t}\r\n\r\n\t/** Internal: update available provider count */\r\n\tsetAvailableProviderCount(count: number): void {\r\n\t\tthis.availableProviderCount = count;\r\n\t}\r\n\r\n\t/** Internal: cleanup */\r\n\tdispose(): void {\r\n\t\tif (this.gitWatcher) {\r\n\t\t\tthis.gitWatcher.close();\r\n\t\t\tthis.gitWatcher = null;\r\n\t\t}\r\n\t\tthis.branchChangeCallbacks.clear();\r\n\t}\r\n\r\n\tprivate setupGitWatcher(): void {\r\n\t\tif (this.gitWatcher) {\r\n\t\t\tthis.gitWatcher.close();\r\n\t\t\tthis.gitWatcher = null;\r\n\t\t}\r\n\r\n\t\tconst gitHeadPath = findGitHeadPath();\r\n\t\tif (!gitHeadPath) return;\r\n\r\n\t\t// Watch the directory containing HEAD, not HEAD itself.\r\n\t\t// Git uses atomic writes (write temp, rename over HEAD), which changes the inode.\r\n\t\t// fs.watch on a file stops working after the inode changes.\r\n\t\tconst gitDir = dirname(gitHeadPath);\r\n\r\n\t\ttry {\r\n\t\t\tthis.gitWatcher = watch(gitDir, (_eventType, filename) => {\r\n\t\t\t\tif (filename === \"HEAD\") {\r\n\t\t\t\t\tthis.cachedBranch = undefined;\r\n\t\t\t\t\tfor (const cb of this.branchChangeCallbacks) cb();\r\n\t\t\t\t}\r\n\t\t\t});\r\n\t\t} catch {\r\n\t\t\t// Silently fail if we can't watch\r\n\t\t}\r\n\t}\r\n}\r\n\r\n/** Read-only view for extensions - excludes setExtensionStatus, setAvailableProviderCount and dispose */\r\nexport type ReadonlyFooterDataProvider = Pick<\r\n\tFooterDataProvider,\r\n\t\"getGitBranch\" | \"getExtensionStatuses\" | \"getAvailableProviderCount\" | \"onBranchChange\"\r\n>;\r\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core modules shared between all run modes.
|
|
3
|
+
*/
|
|
4
|
+
export { AgentSession, type AgentSessionConfig, type AgentSessionEvent, type AgentSessionEventListener, type ModelCycleResult, type PromptOptions, type SessionStats, } from "./agent-session.js";
|
|
5
|
+
export { type BashExecutorOptions, type BashResult, executeBash, executeBashWithOperations } from "./bash-executor.js";
|
|
6
|
+
export type { CompactionResult } from "./compaction/index.js";
|
|
7
|
+
export { createEventBus, type EventBus, type EventBusController } from "./event-bus.js";
|
|
8
|
+
export { type AgentEndEvent, type AgentStartEvent, type AgentToolResult, type AgentToolUpdateCallback, type BeforeAgentStartEvent, type ContextEvent, discoverAndLoadExtensions, type ExecOptions, type ExecResult, type Extension, type ExtensionAPI, type ExtensionCommandContext, type ExtensionContext, type ExtensionError, type ExtensionEvent, type ExtensionFactory, type ExtensionFlag, type ExtensionHandler, ExtensionRunner, type ExtensionShortcut, type ExtensionUIContext, type LoadExtensionsResult, type MessageRenderer, type RegisteredCommand, type SessionBeforeCompactEvent, type SessionBeforeForkEvent, type SessionBeforeSwitchEvent, type SessionBeforeTreeEvent, type SessionCompactEvent, type SessionForkEvent, type SessionShutdownEvent, type SessionStartEvent, type SessionSwitchEvent, type SessionTreeEvent, type ToolCallEvent, type ToolDefinition, type ToolRenderResultOptions, type ToolResultEvent, type TurnEndEvent, type TurnStartEvent, wrapToolsWithExtensions, } from "./extensions/index.js";
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACN,YAAY,EACZ,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACtB,KAAK,yBAAyB,EAC9B,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,KAAK,YAAY,GACjB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,KAAK,mBAAmB,EAAE,KAAK,UAAU,EAAE,WAAW,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AACvH,YAAY,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,KAAK,QAAQ,EAAE,KAAK,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAGxF,OAAO,EACN,KAAK,aAAa,EAClB,KAAK,eAAe,EACpB,KAAK,eAAe,EACpB,KAAK,uBAAuB,EAC5B,KAAK,qBAAqB,EAC1B,KAAK,YAAY,EACjB,yBAAyB,EACzB,KAAK,WAAW,EAChB,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,YAAY,EACjB,KAAK,uBAAuB,EAC5B,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,KAAK,cAAc,EACnB,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,KAAK,gBAAgB,EACrB,eAAe,EACf,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EACzB,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,yBAAyB,EAC9B,KAAK,sBAAsB,EAC3B,KAAK,wBAAwB,EAC7B,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACxB,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EACzB,KAAK,iBAAiB,EACtB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,uBAAuB,EAC5B,KAAK,eAAe,EACpB,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,uBAAuB,GACvB,MAAM,uBAAuB,CAAC","sourcesContent":["/**\r\n * Core modules shared between all run modes.\r\n */\r\n\r\nexport {\r\n\tAgentSession,\r\n\ttype AgentSessionConfig,\r\n\ttype AgentSessionEvent,\r\n\ttype AgentSessionEventListener,\r\n\ttype ModelCycleResult,\r\n\ttype PromptOptions,\r\n\ttype SessionStats,\r\n} from \"./agent-session.js\";\r\nexport { type BashExecutorOptions, type BashResult, executeBash, executeBashWithOperations } from \"./bash-executor.js\";\r\nexport type { CompactionResult } from \"./compaction/index.js\";\r\nexport { createEventBus, type EventBus, type EventBusController } from \"./event-bus.js\";\r\n\r\n// Extensions system\r\nexport {\r\n\ttype AgentEndEvent,\r\n\ttype AgentStartEvent,\r\n\ttype AgentToolResult,\r\n\ttype AgentToolUpdateCallback,\r\n\ttype BeforeAgentStartEvent,\r\n\ttype ContextEvent,\r\n\tdiscoverAndLoadExtensions,\r\n\ttype ExecOptions,\r\n\ttype ExecResult,\r\n\ttype Extension,\r\n\ttype ExtensionAPI,\r\n\ttype ExtensionCommandContext,\r\n\ttype ExtensionContext,\r\n\ttype ExtensionError,\r\n\ttype ExtensionEvent,\r\n\ttype ExtensionFactory,\r\n\ttype ExtensionFlag,\r\n\ttype ExtensionHandler,\r\n\tExtensionRunner,\r\n\ttype ExtensionShortcut,\r\n\ttype ExtensionUIContext,\r\n\ttype LoadExtensionsResult,\r\n\ttype MessageRenderer,\r\n\ttype RegisteredCommand,\r\n\ttype SessionBeforeCompactEvent,\r\n\ttype SessionBeforeForkEvent,\r\n\ttype SessionBeforeSwitchEvent,\r\n\ttype SessionBeforeTreeEvent,\r\n\ttype SessionCompactEvent,\r\n\ttype SessionForkEvent,\r\n\ttype SessionShutdownEvent,\r\n\ttype SessionStartEvent,\r\n\ttype SessionSwitchEvent,\r\n\ttype SessionTreeEvent,\r\n\ttype ToolCallEvent,\r\n\ttype ToolDefinition,\r\n\ttype ToolRenderResultOptions,\r\n\ttype ToolResultEvent,\r\n\ttype TurnEndEvent,\r\n\ttype TurnStartEvent,\r\n\twrapToolsWithExtensions,\r\n} from \"./extensions/index.js\";\r\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Core modules shared between all run modes.
|
|
3
|
+
*/
|
|
4
|
+
export { AgentSession, } from "./agent-session.js";
|
|
5
|
+
export { executeBash, executeBashWithOperations } from "./bash-executor.js";
|
|
6
|
+
export { createEventBus } from "./event-bus.js";
|
|
7
|
+
// Extensions system
|
|
8
|
+
export { discoverAndLoadExtensions, ExtensionRunner, wrapToolsWithExtensions, } from "./extensions/index.js";
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACN,YAAY,GAOZ,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAA6C,WAAW,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAEvH,OAAO,EAAE,cAAc,EAA0C,MAAM,gBAAgB,CAAC;AAExF,oBAAoB;AACpB,OAAO,EAON,yBAAyB,EAYzB,eAAe,EAsBf,uBAAuB,GACvB,MAAM,uBAAuB,CAAC","sourcesContent":["/**\r\n * Core modules shared between all run modes.\r\n */\r\n\r\nexport {\r\n\tAgentSession,\r\n\ttype AgentSessionConfig,\r\n\ttype AgentSessionEvent,\r\n\ttype AgentSessionEventListener,\r\n\ttype ModelCycleResult,\r\n\ttype PromptOptions,\r\n\ttype SessionStats,\r\n} from \"./agent-session.js\";\r\nexport { type BashExecutorOptions, type BashResult, executeBash, executeBashWithOperations } from \"./bash-executor.js\";\r\nexport type { CompactionResult } from \"./compaction/index.js\";\r\nexport { createEventBus, type EventBus, type EventBusController } from \"./event-bus.js\";\r\n\r\n// Extensions system\r\nexport {\r\n\ttype AgentEndEvent,\r\n\ttype AgentStartEvent,\r\n\ttype AgentToolResult,\r\n\ttype AgentToolUpdateCallback,\r\n\ttype BeforeAgentStartEvent,\r\n\ttype ContextEvent,\r\n\tdiscoverAndLoadExtensions,\r\n\ttype ExecOptions,\r\n\ttype ExecResult,\r\n\ttype Extension,\r\n\ttype ExtensionAPI,\r\n\ttype ExtensionCommandContext,\r\n\ttype ExtensionContext,\r\n\ttype ExtensionError,\r\n\ttype ExtensionEvent,\r\n\ttype ExtensionFactory,\r\n\ttype ExtensionFlag,\r\n\ttype ExtensionHandler,\r\n\tExtensionRunner,\r\n\ttype ExtensionShortcut,\r\n\ttype ExtensionUIContext,\r\n\ttype LoadExtensionsResult,\r\n\ttype MessageRenderer,\r\n\ttype RegisteredCommand,\r\n\ttype SessionBeforeCompactEvent,\r\n\ttype SessionBeforeForkEvent,\r\n\ttype SessionBeforeSwitchEvent,\r\n\ttype SessionBeforeTreeEvent,\r\n\ttype SessionCompactEvent,\r\n\ttype SessionForkEvent,\r\n\ttype SessionShutdownEvent,\r\n\ttype SessionStartEvent,\r\n\ttype SessionSwitchEvent,\r\n\ttype SessionTreeEvent,\r\n\ttype ToolCallEvent,\r\n\ttype ToolDefinition,\r\n\ttype ToolRenderResultOptions,\r\n\ttype ToolResultEvent,\r\n\ttype TurnEndEvent,\r\n\ttype TurnStartEvent,\r\n\twrapToolsWithExtensions,\r\n} from \"./extensions/index.js\";\r\n"]}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { type EditorAction, type KeyId } from "@mariozechner/pi-tui";
|
|
2
|
+
/**
|
|
3
|
+
* Application-level actions (coding agent specific).
|
|
4
|
+
*/
|
|
5
|
+
export type AppAction = "interrupt" | "clear" | "exit" | "suspend" | "cycleThinkingLevel" | "cycleModelForward" | "cycleModelBackward" | "selectModel" | "expandTools" | "toggleThinking" | "toggleSessionNamedFilter" | "externalEditor" | "followUp" | "dequeue" | "pasteImage" | "newSession" | "tree" | "fork" | "resume";
|
|
6
|
+
/**
|
|
7
|
+
* All configurable actions.
|
|
8
|
+
*/
|
|
9
|
+
export type KeyAction = AppAction | EditorAction;
|
|
10
|
+
/**
|
|
11
|
+
* Full keybindings configuration (app + editor actions).
|
|
12
|
+
*/
|
|
13
|
+
export type KeybindingsConfig = {
|
|
14
|
+
[K in KeyAction]?: KeyId | KeyId[];
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Default application keybindings.
|
|
18
|
+
*/
|
|
19
|
+
export declare const DEFAULT_APP_KEYBINDINGS: Record<AppAction, KeyId | KeyId[]>;
|
|
20
|
+
/**
|
|
21
|
+
* All default keybindings (app + editor).
|
|
22
|
+
*/
|
|
23
|
+
export declare const DEFAULT_KEYBINDINGS: Required<KeybindingsConfig>;
|
|
24
|
+
/**
|
|
25
|
+
* Manages all keybindings (app + editor).
|
|
26
|
+
*/
|
|
27
|
+
export declare class KeybindingsManager {
|
|
28
|
+
private config;
|
|
29
|
+
private appActionToKeys;
|
|
30
|
+
private constructor();
|
|
31
|
+
/**
|
|
32
|
+
* Create from config file and set up editor keybindings.
|
|
33
|
+
*/
|
|
34
|
+
static create(agentDir?: string): KeybindingsManager;
|
|
35
|
+
/**
|
|
36
|
+
* Create in-memory.
|
|
37
|
+
*/
|
|
38
|
+
static inMemory(config?: KeybindingsConfig): KeybindingsManager;
|
|
39
|
+
private static loadFromFile;
|
|
40
|
+
private buildMaps;
|
|
41
|
+
/**
|
|
42
|
+
* Check if input matches an app action.
|
|
43
|
+
*/
|
|
44
|
+
matches(data: string, action: AppAction): boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Get keys bound to an app action.
|
|
47
|
+
*/
|
|
48
|
+
getKeys(action: AppAction): KeyId[];
|
|
49
|
+
/**
|
|
50
|
+
* Get the full effective config.
|
|
51
|
+
*/
|
|
52
|
+
getEffectiveConfig(): Required<KeybindingsConfig>;
|
|
53
|
+
}
|
|
54
|
+
export type { EditorAction, KeyId };
|
|
55
|
+
//# sourceMappingURL=keybindings.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keybindings.d.ts","sourceRoot":"","sources":["../../src/core/keybindings.ts"],"names":[],"mappings":"AAAA,OAAO,EAEN,KAAK,YAAY,EAGjB,KAAK,KAAK,EAGV,MAAM,sBAAsB,CAAC;AAK9B;;GAEG;AACH,MAAM,MAAM,SAAS,GAClB,WAAW,GACX,OAAO,GACP,MAAM,GACN,SAAS,GACT,oBAAoB,GACpB,mBAAmB,GACnB,oBAAoB,GACpB,aAAa,GACb,aAAa,GACb,gBAAgB,GAChB,0BAA0B,GAC1B,gBAAgB,GAChB,UAAU,GACV,SAAS,GACT,YAAY,GACZ,YAAY,GACZ,MAAM,GACN,MAAM,GACN,QAAQ,CAAC;AAEZ;;GAEG;AACH,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,YAAY,CAAC;AAEjD;;GAEG;AACH,MAAM,MAAM,iBAAiB,GAAG;KAC9B,CAAC,IAAI,SAAS,CAAC,CAAC,EAAE,KAAK,GAAG,KAAK,EAAE;CAClC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,uBAAuB,EAAE,MAAM,CAAC,SAAS,EAAE,KAAK,GAAG,KAAK,EAAE,CAoBtE,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,mBAAmB,EAAE,QAAQ,CAAC,iBAAiB,CAG3D,CAAC;AA6BF;;GAEG;AACH,qBAAa,kBAAkB;IAC9B,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,eAAe,CAA0B;IAEjD,OAAO,eAIN;IAED;;OAEG;IACH,MAAM,CAAC,MAAM,CAAC,QAAQ,GAAE,MAAsB,GAAG,kBAAkB,CAgBlE;IAED;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAE,iBAAsB,GAAG,kBAAkB,CAElE;IAED,OAAO,CAAC,MAAM,CAAC,YAAY;IAS3B,OAAO,CAAC,SAAS;IAiBjB;;OAEG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,GAAG,OAAO,CAOhD;IAED;;OAEG;IACH,OAAO,CAAC,MAAM,EAAE,SAAS,GAAG,KAAK,EAAE,CAElC;IAED;;OAEG;IACH,kBAAkB,IAAI,QAAQ,CAAC,iBAAiB,CAAC,CAQhD;CACD;AAGD,YAAY,EAAE,YAAY,EAAE,KAAK,EAAE,CAAC","sourcesContent":["import {\r\n\tDEFAULT_EDITOR_KEYBINDINGS,\r\n\ttype EditorAction,\r\n\ttype EditorKeybindingsConfig,\r\n\tEditorKeybindingsManager,\r\n\ttype KeyId,\r\n\tmatchesKey,\r\n\tsetEditorKeybindings,\r\n} from \"@mariozechner/pi-tui\";\r\nimport { existsSync, readFileSync } from \"fs\";\r\nimport { join } from \"path\";\r\nimport { getAgentDir } from \"../config.js\";\r\n\r\n/**\r\n * Application-level actions (coding agent specific).\r\n */\r\nexport type AppAction =\r\n\t| \"interrupt\"\r\n\t| \"clear\"\r\n\t| \"exit\"\r\n\t| \"suspend\"\r\n\t| \"cycleThinkingLevel\"\r\n\t| \"cycleModelForward\"\r\n\t| \"cycleModelBackward\"\r\n\t| \"selectModel\"\r\n\t| \"expandTools\"\r\n\t| \"toggleThinking\"\r\n\t| \"toggleSessionNamedFilter\"\r\n\t| \"externalEditor\"\r\n\t| \"followUp\"\r\n\t| \"dequeue\"\r\n\t| \"pasteImage\"\r\n\t| \"newSession\"\r\n\t| \"tree\"\r\n\t| \"fork\"\r\n\t| \"resume\";\r\n\r\n/**\r\n * All configurable actions.\r\n */\r\nexport type KeyAction = AppAction | EditorAction;\r\n\r\n/**\r\n * Full keybindings configuration (app + editor actions).\r\n */\r\nexport type KeybindingsConfig = {\r\n\t[K in KeyAction]?: KeyId | KeyId[];\r\n};\r\n\r\n/**\r\n * Default application keybindings.\r\n */\r\nexport const DEFAULT_APP_KEYBINDINGS: Record<AppAction, KeyId | KeyId[]> = {\r\n\tinterrupt: \"escape\",\r\n\tclear: \"ctrl+c\",\r\n\texit: \"ctrl+d\",\r\n\tsuspend: \"ctrl+z\",\r\n\tcycleThinkingLevel: \"shift+tab\",\r\n\tcycleModelForward: \"ctrl+p\",\r\n\tcycleModelBackward: \"shift+ctrl+p\",\r\n\tselectModel: \"ctrl+l\",\r\n\texpandTools: \"ctrl+o\",\r\n\ttoggleThinking: \"ctrl+t\",\r\n\ttoggleSessionNamedFilter: \"ctrl+n\",\r\n\texternalEditor: \"ctrl+g\",\r\n\tfollowUp: \"alt+enter\",\r\n\tdequeue: \"alt+up\",\r\n\tpasteImage: \"ctrl+v\",\r\n\tnewSession: [],\r\n\ttree: [],\r\n\tfork: [],\r\n\tresume: [],\r\n};\r\n\r\n/**\r\n * All default keybindings (app + editor).\r\n */\r\nexport const DEFAULT_KEYBINDINGS: Required<KeybindingsConfig> = {\r\n\t...DEFAULT_EDITOR_KEYBINDINGS,\r\n\t...DEFAULT_APP_KEYBINDINGS,\r\n};\r\n\r\n// App actions list for type checking\r\nconst APP_ACTIONS: AppAction[] = [\r\n\t\"interrupt\",\r\n\t\"clear\",\r\n\t\"exit\",\r\n\t\"suspend\",\r\n\t\"cycleThinkingLevel\",\r\n\t\"cycleModelForward\",\r\n\t\"cycleModelBackward\",\r\n\t\"selectModel\",\r\n\t\"expandTools\",\r\n\t\"toggleThinking\",\r\n\t\"toggleSessionNamedFilter\",\r\n\t\"externalEditor\",\r\n\t\"followUp\",\r\n\t\"dequeue\",\r\n\t\"pasteImage\",\r\n\t\"newSession\",\r\n\t\"tree\",\r\n\t\"fork\",\r\n\t\"resume\",\r\n];\r\n\r\nfunction isAppAction(action: string): action is AppAction {\r\n\treturn APP_ACTIONS.includes(action as AppAction);\r\n}\r\n\r\n/**\r\n * Manages all keybindings (app + editor).\r\n */\r\nexport class KeybindingsManager {\r\n\tprivate config: KeybindingsConfig;\r\n\tprivate appActionToKeys: Map<AppAction, KeyId[]>;\r\n\r\n\tprivate constructor(config: KeybindingsConfig) {\r\n\t\tthis.config = config;\r\n\t\tthis.appActionToKeys = new Map();\r\n\t\tthis.buildMaps();\r\n\t}\r\n\r\n\t/**\r\n\t * Create from config file and set up editor keybindings.\r\n\t */\r\n\tstatic create(agentDir: string = getAgentDir()): KeybindingsManager {\r\n\t\tconst configPath = join(agentDir, \"keybindings.json\");\r\n\t\tconst config = KeybindingsManager.loadFromFile(configPath);\r\n\t\tconst manager = new KeybindingsManager(config);\r\n\r\n\t\t// Set up editor keybindings globally\r\n\t\t// Include both editor actions and expandTools (shared between app and editor)\r\n\t\tconst editorConfig: EditorKeybindingsConfig = {};\r\n\t\tfor (const [action, keys] of Object.entries(config)) {\r\n\t\t\tif (!isAppAction(action) || action === \"expandTools\") {\r\n\t\t\t\teditorConfig[action as EditorAction] = keys;\r\n\t\t\t}\r\n\t\t}\r\n\t\tsetEditorKeybindings(new EditorKeybindingsManager(editorConfig));\r\n\r\n\t\treturn manager;\r\n\t}\r\n\r\n\t/**\r\n\t * Create in-memory.\r\n\t */\r\n\tstatic inMemory(config: KeybindingsConfig = {}): KeybindingsManager {\r\n\t\treturn new KeybindingsManager(config);\r\n\t}\r\n\r\n\tprivate static loadFromFile(path: string): KeybindingsConfig {\r\n\t\tif (!existsSync(path)) return {};\r\n\t\ttry {\r\n\t\t\treturn JSON.parse(readFileSync(path, \"utf-8\"));\r\n\t\t} catch {\r\n\t\t\treturn {};\r\n\t\t}\r\n\t}\r\n\r\n\tprivate buildMaps(): void {\r\n\t\tthis.appActionToKeys.clear();\r\n\r\n\t\t// Set defaults for app actions\r\n\t\tfor (const [action, keys] of Object.entries(DEFAULT_APP_KEYBINDINGS)) {\r\n\t\t\tconst keyArray = Array.isArray(keys) ? keys : [keys];\r\n\t\t\tthis.appActionToKeys.set(action as AppAction, [...keyArray]);\r\n\t\t}\r\n\r\n\t\t// Override with user config (app actions only)\r\n\t\tfor (const [action, keys] of Object.entries(this.config)) {\r\n\t\t\tif (keys === undefined || !isAppAction(action)) continue;\r\n\t\t\tconst keyArray = Array.isArray(keys) ? keys : [keys];\r\n\t\t\tthis.appActionToKeys.set(action, keyArray);\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Check if input matches an app action.\r\n\t */\r\n\tmatches(data: string, action: AppAction): boolean {\r\n\t\tconst keys = this.appActionToKeys.get(action);\r\n\t\tif (!keys) return false;\r\n\t\tfor (const key of keys) {\r\n\t\t\tif (matchesKey(data, key)) return true;\r\n\t\t}\r\n\t\treturn false;\r\n\t}\r\n\r\n\t/**\r\n\t * Get keys bound to an app action.\r\n\t */\r\n\tgetKeys(action: AppAction): KeyId[] {\r\n\t\treturn this.appActionToKeys.get(action) ?? [];\r\n\t}\r\n\r\n\t/**\r\n\t * Get the full effective config.\r\n\t */\r\n\tgetEffectiveConfig(): Required<KeybindingsConfig> {\r\n\t\tconst result = { ...DEFAULT_KEYBINDINGS };\r\n\t\tfor (const [action, keys] of Object.entries(this.config)) {\r\n\t\t\tif (keys !== undefined) {\r\n\t\t\t\t(result as KeybindingsConfig)[action as KeyAction] = keys;\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn result;\r\n\t}\r\n}\r\n\r\n// Re-export for convenience\r\nexport type { EditorAction, KeyId };\r\n"]}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import { DEFAULT_EDITOR_KEYBINDINGS, EditorKeybindingsManager, matchesKey, setEditorKeybindings, } from "@mariozechner/pi-tui";
|
|
2
|
+
import { existsSync, readFileSync } from "fs";
|
|
3
|
+
import { join } from "path";
|
|
4
|
+
import { getAgentDir } from "../config.js";
|
|
5
|
+
/**
|
|
6
|
+
* Default application keybindings.
|
|
7
|
+
*/
|
|
8
|
+
export const DEFAULT_APP_KEYBINDINGS = {
|
|
9
|
+
interrupt: "escape",
|
|
10
|
+
clear: "ctrl+c",
|
|
11
|
+
exit: "ctrl+d",
|
|
12
|
+
suspend: "ctrl+z",
|
|
13
|
+
cycleThinkingLevel: "shift+tab",
|
|
14
|
+
cycleModelForward: "ctrl+p",
|
|
15
|
+
cycleModelBackward: "shift+ctrl+p",
|
|
16
|
+
selectModel: "ctrl+l",
|
|
17
|
+
expandTools: "ctrl+o",
|
|
18
|
+
toggleThinking: "ctrl+t",
|
|
19
|
+
toggleSessionNamedFilter: "ctrl+n",
|
|
20
|
+
externalEditor: "ctrl+g",
|
|
21
|
+
followUp: "alt+enter",
|
|
22
|
+
dequeue: "alt+up",
|
|
23
|
+
pasteImage: "ctrl+v",
|
|
24
|
+
newSession: [],
|
|
25
|
+
tree: [],
|
|
26
|
+
fork: [],
|
|
27
|
+
resume: [],
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* All default keybindings (app + editor).
|
|
31
|
+
*/
|
|
32
|
+
export const DEFAULT_KEYBINDINGS = {
|
|
33
|
+
...DEFAULT_EDITOR_KEYBINDINGS,
|
|
34
|
+
...DEFAULT_APP_KEYBINDINGS,
|
|
35
|
+
};
|
|
36
|
+
// App actions list for type checking
|
|
37
|
+
const APP_ACTIONS = [
|
|
38
|
+
"interrupt",
|
|
39
|
+
"clear",
|
|
40
|
+
"exit",
|
|
41
|
+
"suspend",
|
|
42
|
+
"cycleThinkingLevel",
|
|
43
|
+
"cycleModelForward",
|
|
44
|
+
"cycleModelBackward",
|
|
45
|
+
"selectModel",
|
|
46
|
+
"expandTools",
|
|
47
|
+
"toggleThinking",
|
|
48
|
+
"toggleSessionNamedFilter",
|
|
49
|
+
"externalEditor",
|
|
50
|
+
"followUp",
|
|
51
|
+
"dequeue",
|
|
52
|
+
"pasteImage",
|
|
53
|
+
"newSession",
|
|
54
|
+
"tree",
|
|
55
|
+
"fork",
|
|
56
|
+
"resume",
|
|
57
|
+
];
|
|
58
|
+
function isAppAction(action) {
|
|
59
|
+
return APP_ACTIONS.includes(action);
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Manages all keybindings (app + editor).
|
|
63
|
+
*/
|
|
64
|
+
export class KeybindingsManager {
|
|
65
|
+
config;
|
|
66
|
+
appActionToKeys;
|
|
67
|
+
constructor(config) {
|
|
68
|
+
this.config = config;
|
|
69
|
+
this.appActionToKeys = new Map();
|
|
70
|
+
this.buildMaps();
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Create from config file and set up editor keybindings.
|
|
74
|
+
*/
|
|
75
|
+
static create(agentDir = getAgentDir()) {
|
|
76
|
+
const configPath = join(agentDir, "keybindings.json");
|
|
77
|
+
const config = KeybindingsManager.loadFromFile(configPath);
|
|
78
|
+
const manager = new KeybindingsManager(config);
|
|
79
|
+
// Set up editor keybindings globally
|
|
80
|
+
// Include both editor actions and expandTools (shared between app and editor)
|
|
81
|
+
const editorConfig = {};
|
|
82
|
+
for (const [action, keys] of Object.entries(config)) {
|
|
83
|
+
if (!isAppAction(action) || action === "expandTools") {
|
|
84
|
+
editorConfig[action] = keys;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
setEditorKeybindings(new EditorKeybindingsManager(editorConfig));
|
|
88
|
+
return manager;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Create in-memory.
|
|
92
|
+
*/
|
|
93
|
+
static inMemory(config = {}) {
|
|
94
|
+
return new KeybindingsManager(config);
|
|
95
|
+
}
|
|
96
|
+
static loadFromFile(path) {
|
|
97
|
+
if (!existsSync(path))
|
|
98
|
+
return {};
|
|
99
|
+
try {
|
|
100
|
+
return JSON.parse(readFileSync(path, "utf-8"));
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
return {};
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
buildMaps() {
|
|
107
|
+
this.appActionToKeys.clear();
|
|
108
|
+
// Set defaults for app actions
|
|
109
|
+
for (const [action, keys] of Object.entries(DEFAULT_APP_KEYBINDINGS)) {
|
|
110
|
+
const keyArray = Array.isArray(keys) ? keys : [keys];
|
|
111
|
+
this.appActionToKeys.set(action, [...keyArray]);
|
|
112
|
+
}
|
|
113
|
+
// Override with user config (app actions only)
|
|
114
|
+
for (const [action, keys] of Object.entries(this.config)) {
|
|
115
|
+
if (keys === undefined || !isAppAction(action))
|
|
116
|
+
continue;
|
|
117
|
+
const keyArray = Array.isArray(keys) ? keys : [keys];
|
|
118
|
+
this.appActionToKeys.set(action, keyArray);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Check if input matches an app action.
|
|
123
|
+
*/
|
|
124
|
+
matches(data, action) {
|
|
125
|
+
const keys = this.appActionToKeys.get(action);
|
|
126
|
+
if (!keys)
|
|
127
|
+
return false;
|
|
128
|
+
for (const key of keys) {
|
|
129
|
+
if (matchesKey(data, key))
|
|
130
|
+
return true;
|
|
131
|
+
}
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Get keys bound to an app action.
|
|
136
|
+
*/
|
|
137
|
+
getKeys(action) {
|
|
138
|
+
return this.appActionToKeys.get(action) ?? [];
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Get the full effective config.
|
|
142
|
+
*/
|
|
143
|
+
getEffectiveConfig() {
|
|
144
|
+
const result = { ...DEFAULT_KEYBINDINGS };
|
|
145
|
+
for (const [action, keys] of Object.entries(this.config)) {
|
|
146
|
+
if (keys !== undefined) {
|
|
147
|
+
result[action] = keys;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return result;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
//# sourceMappingURL=keybindings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keybindings.js","sourceRoot":"","sources":["../../src/core/keybindings.ts"],"names":[],"mappings":"AAAA,OAAO,EACN,0BAA0B,EAG1B,wBAAwB,EAExB,UAAU,EACV,oBAAoB,GACpB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAC9C,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAsC3C;;GAEG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAuC;IAC1E,SAAS,EAAE,QAAQ;IACnB,KAAK,EAAE,QAAQ;IACf,IAAI,EAAE,QAAQ;IACd,OAAO,EAAE,QAAQ;IACjB,kBAAkB,EAAE,WAAW;IAC/B,iBAAiB,EAAE,QAAQ;IAC3B,kBAAkB,EAAE,cAAc;IAClC,WAAW,EAAE,QAAQ;IACrB,WAAW,EAAE,QAAQ;IACrB,cAAc,EAAE,QAAQ;IACxB,wBAAwB,EAAE,QAAQ;IAClC,cAAc,EAAE,QAAQ;IACxB,QAAQ,EAAE,WAAW;IACrB,OAAO,EAAE,QAAQ;IACjB,UAAU,EAAE,QAAQ;IACpB,UAAU,EAAE,EAAE;IACd,IAAI,EAAE,EAAE;IACR,IAAI,EAAE,EAAE;IACR,MAAM,EAAE,EAAE;CACV,CAAC;AAEF;;GAEG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAgC;IAC/D,GAAG,0BAA0B;IAC7B,GAAG,uBAAuB;CAC1B,CAAC;AAEF,qCAAqC;AACrC,MAAM,WAAW,GAAgB;IAChC,WAAW;IACX,OAAO;IACP,MAAM;IACN,SAAS;IACT,oBAAoB;IACpB,mBAAmB;IACnB,oBAAoB;IACpB,aAAa;IACb,aAAa;IACb,gBAAgB;IAChB,0BAA0B;IAC1B,gBAAgB;IAChB,UAAU;IACV,SAAS;IACT,YAAY;IACZ,YAAY;IACZ,MAAM;IACN,MAAM;IACN,QAAQ;CACR,CAAC;AAEF,SAAS,WAAW,CAAC,MAAc,EAAuB;IACzD,OAAO,WAAW,CAAC,QAAQ,CAAC,MAAmB,CAAC,CAAC;AAAA,CACjD;AAED;;GAEG;AACH,MAAM,OAAO,kBAAkB;IACtB,MAAM,CAAoB;IAC1B,eAAe,CAA0B;IAEjD,YAAoB,MAAyB,EAAE;QAC9C,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,eAAe,GAAG,IAAI,GAAG,EAAE,CAAC;QACjC,IAAI,CAAC,SAAS,EAAE,CAAC;IAAA,CACjB;IAED;;OAEG;IACH,MAAM,CAAC,MAAM,CAAC,QAAQ,GAAW,WAAW,EAAE,EAAsB;QACnE,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,EAAE,kBAAkB,CAAC,CAAC;QACtD,MAAM,MAAM,GAAG,kBAAkB,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC;QAC3D,MAAM,OAAO,GAAG,IAAI,kBAAkB,CAAC,MAAM,CAAC,CAAC;QAE/C,qCAAqC;QACrC,8EAA8E;QAC9E,MAAM,YAAY,GAA4B,EAAE,CAAC;QACjD,KAAK,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACrD,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,MAAM,KAAK,aAAa,EAAE,CAAC;gBACtD,YAAY,CAAC,MAAsB,CAAC,GAAG,IAAI,CAAC;YAC7C,CAAC;QACF,CAAC;QACD,oBAAoB,CAAC,IAAI,wBAAwB,CAAC,YAAY,CAAC,CAAC,CAAC;QAEjE,OAAO,OAAO,CAAC;IAAA,CACf;IAED;;OAEG;IACH,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAsB,EAAE,EAAsB;QACnE,OAAO,IAAI,kBAAkB,CAAC,MAAM,CAAC,CAAC;IAAA,CACtC;IAEO,MAAM,CAAC,YAAY,CAAC,IAAY,EAAqB;QAC5D,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,OAAO,EAAE,CAAC;QACjC,IAAI,CAAC;YACJ,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;QAChD,CAAC;QAAC,MAAM,CAAC;YACR,OAAO,EAAE,CAAC;QACX,CAAC;IAAA,CACD;IAEO,SAAS,GAAS;QACzB,IAAI,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC;QAE7B,+BAA+B;QAC/B,KAAK,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,uBAAuB,CAAC,EAAE,CAAC;YACtE,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YACrD,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,MAAmB,EAAE,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC;QAC9D,CAAC;QAED,+CAA+C;QAC/C,KAAK,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YAC1D,IAAI,IAAI,KAAK,SAAS,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC;gBAAE,SAAS;YACzD,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YACrD,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;QAC5C,CAAC;IAAA,CACD;IAED;;OAEG;IACH,OAAO,CAAC,IAAY,EAAE,MAAiB,EAAW;QACjD,MAAM,IAAI,GAAG,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC9C,IAAI,CAAC,IAAI;YAAE,OAAO,KAAK,CAAC;QACxB,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACxB,IAAI,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC;gBAAE,OAAO,IAAI,CAAC;QACxC,CAAC;QACD,OAAO,KAAK,CAAC;IAAA,CACb;IAED;;OAEG;IACH,OAAO,CAAC,MAAiB,EAAW;QACnC,OAAO,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IAAA,CAC9C;IAED;;OAEG;IACH,kBAAkB,GAAgC;QACjD,MAAM,MAAM,GAAG,EAAE,GAAG,mBAAmB,EAAE,CAAC;QAC1C,KAAK,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YAC1D,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;gBACvB,MAA4B,CAAC,MAAmB,CAAC,GAAG,IAAI,CAAC;YAC3D,CAAC;QACF,CAAC;QACD,OAAO,MAAM,CAAC;IAAA,CACd;CACD","sourcesContent":["import {\r\n\tDEFAULT_EDITOR_KEYBINDINGS,\r\n\ttype EditorAction,\r\n\ttype EditorKeybindingsConfig,\r\n\tEditorKeybindingsManager,\r\n\ttype KeyId,\r\n\tmatchesKey,\r\n\tsetEditorKeybindings,\r\n} from \"@mariozechner/pi-tui\";\r\nimport { existsSync, readFileSync } from \"fs\";\r\nimport { join } from \"path\";\r\nimport { getAgentDir } from \"../config.js\";\r\n\r\n/**\r\n * Application-level actions (coding agent specific).\r\n */\r\nexport type AppAction =\r\n\t| \"interrupt\"\r\n\t| \"clear\"\r\n\t| \"exit\"\r\n\t| \"suspend\"\r\n\t| \"cycleThinkingLevel\"\r\n\t| \"cycleModelForward\"\r\n\t| \"cycleModelBackward\"\r\n\t| \"selectModel\"\r\n\t| \"expandTools\"\r\n\t| \"toggleThinking\"\r\n\t| \"toggleSessionNamedFilter\"\r\n\t| \"externalEditor\"\r\n\t| \"followUp\"\r\n\t| \"dequeue\"\r\n\t| \"pasteImage\"\r\n\t| \"newSession\"\r\n\t| \"tree\"\r\n\t| \"fork\"\r\n\t| \"resume\";\r\n\r\n/**\r\n * All configurable actions.\r\n */\r\nexport type KeyAction = AppAction | EditorAction;\r\n\r\n/**\r\n * Full keybindings configuration (app + editor actions).\r\n */\r\nexport type KeybindingsConfig = {\r\n\t[K in KeyAction]?: KeyId | KeyId[];\r\n};\r\n\r\n/**\r\n * Default application keybindings.\r\n */\r\nexport const DEFAULT_APP_KEYBINDINGS: Record<AppAction, KeyId | KeyId[]> = {\r\n\tinterrupt: \"escape\",\r\n\tclear: \"ctrl+c\",\r\n\texit: \"ctrl+d\",\r\n\tsuspend: \"ctrl+z\",\r\n\tcycleThinkingLevel: \"shift+tab\",\r\n\tcycleModelForward: \"ctrl+p\",\r\n\tcycleModelBackward: \"shift+ctrl+p\",\r\n\tselectModel: \"ctrl+l\",\r\n\texpandTools: \"ctrl+o\",\r\n\ttoggleThinking: \"ctrl+t\",\r\n\ttoggleSessionNamedFilter: \"ctrl+n\",\r\n\texternalEditor: \"ctrl+g\",\r\n\tfollowUp: \"alt+enter\",\r\n\tdequeue: \"alt+up\",\r\n\tpasteImage: \"ctrl+v\",\r\n\tnewSession: [],\r\n\ttree: [],\r\n\tfork: [],\r\n\tresume: [],\r\n};\r\n\r\n/**\r\n * All default keybindings (app + editor).\r\n */\r\nexport const DEFAULT_KEYBINDINGS: Required<KeybindingsConfig> = {\r\n\t...DEFAULT_EDITOR_KEYBINDINGS,\r\n\t...DEFAULT_APP_KEYBINDINGS,\r\n};\r\n\r\n// App actions list for type checking\r\nconst APP_ACTIONS: AppAction[] = [\r\n\t\"interrupt\",\r\n\t\"clear\",\r\n\t\"exit\",\r\n\t\"suspend\",\r\n\t\"cycleThinkingLevel\",\r\n\t\"cycleModelForward\",\r\n\t\"cycleModelBackward\",\r\n\t\"selectModel\",\r\n\t\"expandTools\",\r\n\t\"toggleThinking\",\r\n\t\"toggleSessionNamedFilter\",\r\n\t\"externalEditor\",\r\n\t\"followUp\",\r\n\t\"dequeue\",\r\n\t\"pasteImage\",\r\n\t\"newSession\",\r\n\t\"tree\",\r\n\t\"fork\",\r\n\t\"resume\",\r\n];\r\n\r\nfunction isAppAction(action: string): action is AppAction {\r\n\treturn APP_ACTIONS.includes(action as AppAction);\r\n}\r\n\r\n/**\r\n * Manages all keybindings (app + editor).\r\n */\r\nexport class KeybindingsManager {\r\n\tprivate config: KeybindingsConfig;\r\n\tprivate appActionToKeys: Map<AppAction, KeyId[]>;\r\n\r\n\tprivate constructor(config: KeybindingsConfig) {\r\n\t\tthis.config = config;\r\n\t\tthis.appActionToKeys = new Map();\r\n\t\tthis.buildMaps();\r\n\t}\r\n\r\n\t/**\r\n\t * Create from config file and set up editor keybindings.\r\n\t */\r\n\tstatic create(agentDir: string = getAgentDir()): KeybindingsManager {\r\n\t\tconst configPath = join(agentDir, \"keybindings.json\");\r\n\t\tconst config = KeybindingsManager.loadFromFile(configPath);\r\n\t\tconst manager = new KeybindingsManager(config);\r\n\r\n\t\t// Set up editor keybindings globally\r\n\t\t// Include both editor actions and expandTools (shared between app and editor)\r\n\t\tconst editorConfig: EditorKeybindingsConfig = {};\r\n\t\tfor (const [action, keys] of Object.entries(config)) {\r\n\t\t\tif (!isAppAction(action) || action === \"expandTools\") {\r\n\t\t\t\teditorConfig[action as EditorAction] = keys;\r\n\t\t\t}\r\n\t\t}\r\n\t\tsetEditorKeybindings(new EditorKeybindingsManager(editorConfig));\r\n\r\n\t\treturn manager;\r\n\t}\r\n\r\n\t/**\r\n\t * Create in-memory.\r\n\t */\r\n\tstatic inMemory(config: KeybindingsConfig = {}): KeybindingsManager {\r\n\t\treturn new KeybindingsManager(config);\r\n\t}\r\n\r\n\tprivate static loadFromFile(path: string): KeybindingsConfig {\r\n\t\tif (!existsSync(path)) return {};\r\n\t\ttry {\r\n\t\t\treturn JSON.parse(readFileSync(path, \"utf-8\"));\r\n\t\t} catch {\r\n\t\t\treturn {};\r\n\t\t}\r\n\t}\r\n\r\n\tprivate buildMaps(): void {\r\n\t\tthis.appActionToKeys.clear();\r\n\r\n\t\t// Set defaults for app actions\r\n\t\tfor (const [action, keys] of Object.entries(DEFAULT_APP_KEYBINDINGS)) {\r\n\t\t\tconst keyArray = Array.isArray(keys) ? keys : [keys];\r\n\t\t\tthis.appActionToKeys.set(action as AppAction, [...keyArray]);\r\n\t\t}\r\n\r\n\t\t// Override with user config (app actions only)\r\n\t\tfor (const [action, keys] of Object.entries(this.config)) {\r\n\t\t\tif (keys === undefined || !isAppAction(action)) continue;\r\n\t\t\tconst keyArray = Array.isArray(keys) ? keys : [keys];\r\n\t\t\tthis.appActionToKeys.set(action, keyArray);\r\n\t\t}\r\n\t}\r\n\r\n\t/**\r\n\t * Check if input matches an app action.\r\n\t */\r\n\tmatches(data: string, action: AppAction): boolean {\r\n\t\tconst keys = this.appActionToKeys.get(action);\r\n\t\tif (!keys) return false;\r\n\t\tfor (const key of keys) {\r\n\t\t\tif (matchesKey(data, key)) return true;\r\n\t\t}\r\n\t\treturn false;\r\n\t}\r\n\r\n\t/**\r\n\t * Get keys bound to an app action.\r\n\t */\r\n\tgetKeys(action: AppAction): KeyId[] {\r\n\t\treturn this.appActionToKeys.get(action) ?? [];\r\n\t}\r\n\r\n\t/**\r\n\t * Get the full effective config.\r\n\t */\r\n\tgetEffectiveConfig(): Required<KeybindingsConfig> {\r\n\t\tconst result = { ...DEFAULT_KEYBINDINGS };\r\n\t\tfor (const [action, keys] of Object.entries(this.config)) {\r\n\t\t\tif (keys !== undefined) {\r\n\t\t\t\t(result as KeybindingsConfig)[action as KeyAction] = keys;\r\n\t\t\t}\r\n\t\t}\r\n\t\treturn result;\r\n\t}\r\n}\r\n\r\n// Re-export for convenience\r\nexport type { EditorAction, KeyId };\r\n"]}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Persistent memory system — procedural, episodic, and semantic memories
|
|
3
|
+
* stored per-project in .pi/memory/ as JSON files.
|
|
4
|
+
*/
|
|
5
|
+
export interface ProceduralMemory {
|
|
6
|
+
id: string;
|
|
7
|
+
name: string;
|
|
8
|
+
trigger: string;
|
|
9
|
+
steps: string[];
|
|
10
|
+
tags: string[];
|
|
11
|
+
created: string;
|
|
12
|
+
updated: string;
|
|
13
|
+
sourceSession: string;
|
|
14
|
+
}
|
|
15
|
+
export interface EpisodicMemory {
|
|
16
|
+
id: string;
|
|
17
|
+
summary: string;
|
|
18
|
+
details: string[];
|
|
19
|
+
reflection?: {
|
|
20
|
+
mistakes: string[];
|
|
21
|
+
lessons: string[];
|
|
22
|
+
};
|
|
23
|
+
tags: string[];
|
|
24
|
+
date: string;
|
|
25
|
+
sourceSession: string;
|
|
26
|
+
}
|
|
27
|
+
export interface SemanticMemory {
|
|
28
|
+
id: string;
|
|
29
|
+
category: "preference" | "architecture" | "convention" | "fact";
|
|
30
|
+
text: string;
|
|
31
|
+
tags: string[];
|
|
32
|
+
created: string;
|
|
33
|
+
sourceSession: string;
|
|
34
|
+
}
|
|
35
|
+
export interface MemoryStore<T> {
|
|
36
|
+
memories: T[];
|
|
37
|
+
}
|
|
38
|
+
export type MemoryType = "procedural" | "episodic" | "semantic";
|
|
39
|
+
export declare function getMemoryDir(cwd: string): string;
|
|
40
|
+
export declare function loadStore<T>(cwd: string, filename: string): MemoryStore<T>;
|
|
41
|
+
export declare function saveStore<T>(cwd: string, filename: string, store: MemoryStore<T>): void;
|
|
42
|
+
export declare function generateId(prefix: string, store: MemoryStore<{
|
|
43
|
+
id: string;
|
|
44
|
+
}>): string;
|
|
45
|
+
export declare function nowISO(): string;
|
|
46
|
+
export declare function getSessionId(): string;
|
|
47
|
+
export declare function getStoreFile(type: MemoryType): string;
|
|
48
|
+
export declare function searchMemories<T extends {
|
|
49
|
+
tags: string[];
|
|
50
|
+
}>(memories: T[], query: string, getText: (m: T) => string): T[];
|
|
51
|
+
export declare function compactEpisodicMemories(memories: EpisodicMemory[]): EpisodicMemory[];
|
|
52
|
+
export declare function formatProceduralForDisplay(m: ProceduralMemory): string;
|
|
53
|
+
export declare function formatEpisodicForDisplay(m: EpisodicMemory): string;
|
|
54
|
+
export declare function formatSemanticForDisplay(m: SemanticMemory): string;
|
|
55
|
+
export declare function buildMemoryPromptSection(cwd: string): string;
|
|
56
|
+
export declare function formatTimestamp(ts: number): string;
|
|
57
|
+
export interface MemoryCounts {
|
|
58
|
+
semantic: number;
|
|
59
|
+
procedural: number;
|
|
60
|
+
episodic: number;
|
|
61
|
+
total: number;
|
|
62
|
+
}
|
|
63
|
+
export declare function getMemoryCounts(cwd: string): MemoryCounts;
|
|
64
|
+
//# sourceMappingURL=memory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../src/core/memory.ts"],"names":[],"mappings":"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","sourcesContent":["/**\r\n * Persistent memory system — procedural, episodic, and semantic memories\r\n * stored per-project in .pi/memory/ as JSON files.\r\n */\r\n\r\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from \"node:fs\";\r\nimport { join } from \"node:path\";\r\n\r\n// ---------------------------------------------------------------------------\r\n// Types\r\n// ---------------------------------------------------------------------------\r\n\r\nexport interface ProceduralMemory {\r\n\tid: string;\r\n\tname: string;\r\n\ttrigger: string;\r\n\tsteps: string[];\r\n\ttags: string[];\r\n\tcreated: string;\r\n\tupdated: string;\r\n\tsourceSession: string;\r\n}\r\n\r\nexport interface EpisodicMemory {\r\n\tid: string;\r\n\tsummary: string;\r\n\tdetails: string[];\r\n\treflection?: {\r\n\t\tmistakes: string[];\r\n\t\tlessons: string[];\r\n\t};\r\n\ttags: string[];\r\n\tdate: string;\r\n\tsourceSession: string;\r\n}\r\n\r\nexport interface SemanticMemory {\r\n\tid: string;\r\n\tcategory: \"preference\" | \"architecture\" | \"convention\" | \"fact\";\r\n\ttext: string;\r\n\ttags: string[];\r\n\tcreated: string;\r\n\tsourceSession: string;\r\n}\r\n\r\nexport interface MemoryStore<T> {\r\n\tmemories: T[];\r\n}\r\n\r\nexport type MemoryType = \"procedural\" | \"episodic\" | \"semantic\";\r\n\r\n// ---------------------------------------------------------------------------\r\n// Storage\r\n// ---------------------------------------------------------------------------\r\n\r\nexport function getMemoryDir(cwd: string): string {\r\n\treturn join(cwd, \".pi\", \"memory\");\r\n}\r\n\r\nfunction ensureMemoryDir(cwd: string): string {\r\n\tconst dir = getMemoryDir(cwd);\r\n\tif (!existsSync(dir)) {\r\n\t\tmkdirSync(dir, { recursive: true });\r\n\t}\r\n\treturn dir;\r\n}\r\n\r\nexport function loadStore<T>(cwd: string, filename: string): MemoryStore<T> {\r\n\tconst filepath = join(getMemoryDir(cwd), filename);\r\n\tif (!existsSync(filepath)) {\r\n\t\treturn { memories: [] };\r\n\t}\r\n\ttry {\r\n\t\tconst raw = readFileSync(filepath, \"utf-8\");\r\n\t\treturn JSON.parse(raw) as MemoryStore<T>;\r\n\t} catch {\r\n\t\treturn { memories: [] };\r\n\t}\r\n}\r\n\r\nexport function saveStore<T>(cwd: string, filename: string, store: MemoryStore<T>): void {\r\n\tconst dir = ensureMemoryDir(cwd);\r\n\tconst filepath = join(dir, filename);\r\n\twriteFileSync(filepath, JSON.stringify(store, null, 2), \"utf-8\");\r\n}\r\n\r\nexport function generateId(prefix: string, store: MemoryStore<{ id: string }>): string {\r\n\tlet max = 0;\r\n\tfor (const m of store.memories) {\r\n\t\tconst num = parseInt(m.id.replace(`${prefix}_`, \"\"), 10);\r\n\t\tif (!Number.isNaN(num) && num > max) max = num;\r\n\t}\r\n\treturn `${prefix}_${String(max + 1).padStart(3, \"0\")}`;\r\n}\r\n\r\nexport function nowISO(): string {\r\n\treturn new Date().toISOString();\r\n}\r\n\r\nexport function getSessionId(): string {\r\n\treturn `session_${Date.now()}`;\r\n}\r\n\r\nconst STORE_FILES: Record<MemoryType, string> = {\r\n\tprocedural: \"procedural.json\",\r\n\tepisodic: \"episodic.json\",\r\n\tsemantic: \"semantic.json\",\r\n};\r\n\r\nexport function getStoreFile(type: MemoryType): string {\r\n\treturn STORE_FILES[type];\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Search\r\n// ---------------------------------------------------------------------------\r\n\r\nexport function searchMemories<T extends { tags: string[] }>(\r\n\tmemories: T[],\r\n\tquery: string,\r\n\tgetText: (m: T) => string,\r\n): T[] {\r\n\tconst lower = query.toLowerCase();\r\n\tconst queryWords = lower.split(/\\s+/).filter(Boolean);\r\n\treturn memories.filter((m) => {\r\n\t\tconst text = getText(m).toLowerCase();\r\n\t\tconst tagText = m.tags.join(\" \").toLowerCase();\r\n\t\tconst combined = `${text} ${tagText}`;\r\n\t\treturn queryWords.every((w) => combined.includes(w));\r\n\t});\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Compaction\r\n// ---------------------------------------------------------------------------\r\n\r\nexport function compactEpisodicMemories(memories: EpisodicMemory[]): EpisodicMemory[] {\r\n\tif (memories.length <= 1) return memories;\r\n\r\n\tconst tagGroups = new Map<string, EpisodicMemory[]>();\r\n\tfor (const m of memories) {\r\n\t\tlet placed = false;\r\n\t\tfor (const [key, group] of tagGroups) {\r\n\t\t\tconst groupTags = new Set(key.split(\",\"));\r\n\t\t\tif (m.tags.some((t) => groupTags.has(t))) {\r\n\t\t\t\tgroup.push(m);\r\n\t\t\t\tconst mergedTags = new Set([...groupTags, ...m.tags]);\r\n\t\t\t\ttagGroups.delete(key);\r\n\t\t\t\ttagGroups.set([...mergedTags].join(\",\"), group);\r\n\t\t\t\tplaced = true;\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t}\r\n\t\tif (!placed) {\r\n\t\t\ttagGroups.set(m.tags.join(\",\") || m.id, [m]);\r\n\t\t}\r\n\t}\r\n\r\n\tconst compacted: EpisodicMemory[] = [];\r\n\tfor (const [, group] of tagGroups) {\r\n\t\tif (group.length <= 1) {\r\n\t\t\tcompacted.push(...group);\r\n\t\t\tcontinue;\r\n\t\t}\r\n\t\tconst allDetails = group.flatMap((m) => m.details);\r\n\t\tconst allTags = [...new Set(group.flatMap((m) => m.tags))];\r\n\t\tconst allMistakes = group.flatMap((m) => m.reflection?.mistakes ?? []);\r\n\t\tconst allLessons = group.flatMap((m) => m.reflection?.lessons ?? []);\r\n\t\tconst summaries = group.map((m) => m.summary);\r\n\r\n\t\tcompacted.push({\r\n\t\t\tid: group[0].id,\r\n\t\t\tsummary: `Consolidated: ${summaries.join(\"; \")}`,\r\n\t\t\tdetails: [...new Set(allDetails)],\r\n\t\t\treflection:\r\n\t\t\t\tallMistakes.length > 0 || allLessons.length > 0\r\n\t\t\t\t\t? { mistakes: [...new Set(allMistakes)], lessons: [...new Set(allLessons)] }\r\n\t\t\t\t\t: undefined,\r\n\t\t\ttags: allTags,\r\n\t\t\tdate: group[group.length - 1].date,\r\n\t\t\tsourceSession: group[group.length - 1].sourceSession,\r\n\t\t});\r\n\t}\r\n\treturn compacted;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Display formatters\r\n// ---------------------------------------------------------------------------\r\n\r\nexport function formatProceduralForDisplay(m: ProceduralMemory): string {\r\n\tconst steps = m.steps.map((s, i) => ` ${i + 1}. ${s}`).join(\"\\n\");\r\n\treturn `[${m.id}] ${m.name}\\n Trigger: ${m.trigger}\\n Tags: ${m.tags.join(\", \")}\\n Steps:\\n${steps}\\n Updated: ${m.updated}`;\r\n}\r\n\r\nexport function formatEpisodicForDisplay(m: EpisodicMemory): string {\r\n\tlet text = `[${m.id}] ${m.summary}\\n Date: ${m.date}\\n Tags: ${m.tags.join(\", \")}`;\r\n\tif (m.details.length > 0) {\r\n\t\ttext += `\\n Details:\\n${m.details.map((d) => ` - ${d}`).join(\"\\n\")}`;\r\n\t}\r\n\tif (m.reflection) {\r\n\t\tif (m.reflection.mistakes.length > 0) {\r\n\t\t\ttext += `\\n Mistakes:\\n${m.reflection.mistakes.map((x) => ` - ${x}`).join(\"\\n\")}`;\r\n\t\t}\r\n\t\tif (m.reflection.lessons.length > 0) {\r\n\t\t\ttext += `\\n Lessons:\\n${m.reflection.lessons.map((x) => ` - ${x}`).join(\"\\n\")}`;\r\n\t\t}\r\n\t}\r\n\treturn text;\r\n}\r\n\r\nexport function formatSemanticForDisplay(m: SemanticMemory): string {\r\n\treturn `[${m.id}] (${m.category}) ${m.text}\\n Tags: ${m.tags.join(\", \")}\\n Created: ${m.created}`;\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// System prompt section\r\n// ---------------------------------------------------------------------------\r\n\r\nexport function buildMemoryPromptSection(cwd: string): string {\r\n\tconst semantic = loadStore<SemanticMemory>(cwd, \"semantic.json\");\r\n\tconst procedural = loadStore<ProceduralMemory>(cwd, \"procedural.json\");\r\n\tconst episodic = loadStore<EpisodicMemory>(cwd, \"episodic.json\");\r\n\r\n\tif (semantic.memories.length === 0 && procedural.memories.length === 0 && episodic.memories.length === 0) {\r\n\t\treturn `\\n\\n<memory_system>\r\nYou have a persistent memory system that stores knowledge across sessions.\r\nCurrently no memories are stored. Use the memory_write tool to save:\r\n1. Procedural memories when the user guides you through a multi-step workflow.\r\n2. Semantic memories when the user states a preference, rule, correction, or fact.\r\n3. Episodic memories when a significant task completes.\r\n</memory_system>`;\r\n\t}\r\n\r\n\tconst parts: string[] = [];\r\n\r\n\tparts.push(`\\n\\n<memory_system>\r\nYou have a persistent memory system that stores knowledge across sessions.\r\nYou MUST use these memories to improve your responses. Do not ask the user\r\nto repeat things they have already taught you.\r\n\r\nAUTOMATIC MEMORY CAPTURE RULES:\r\n1. When the user guides you through a multi-step workflow (correcting steps,\r\n adding steps, reordering), save it as a PROCEDURAL memory using the\r\n memory_write tool. Extract the general workflow, not the specific instance.\r\n2. When the user states a preference or rule (\"always do X\", \"never do Y\",\r\n \"I prefer X\"), save it as a SEMANTIC memory immediately.\r\n3. When the user corrects you or you make a mistake, save the lesson as a\r\n SEMANTIC memory with category \"convention\".\r\n4. When a significant task completes, save a summary as an EPISODIC memory.\r\n5. If you detect a conflict with an existing memory, ask the user: \"You\r\n previously told me [old]. You are now saying [new]. Should I update this?\"\r\n Only update after confirmation.\r\n\r\nTIMESTAMP AWARENESS:\r\nEach user message includes a timestamp. Use these to detect time gaps.\r\nIf the user returns after a significant gap (>10 minutes), acknowledge it\r\nnaturally if relevant. Do not force it if the gap is not relevant.`);\r\n\r\n\tif (semantic.memories.length > 0) {\r\n\t\tparts.push(\"\\n<semantic_memories>\");\r\n\t\tfor (const m of semantic.memories) {\r\n\t\t\tparts.push(` <memory id=\"${m.id}\" category=\"${m.category}\">${escapeXml(m.text)}</memory>`);\r\n\t\t}\r\n\t\tparts.push(\"</semantic_memories>\");\r\n\t}\r\n\r\n\tif (procedural.memories.length > 0) {\r\n\t\tparts.push(\"\\n<procedural_memories>\");\r\n\t\tfor (const m of procedural.memories) {\r\n\t\t\tconst steps = m.steps.map((s, i) => `${i + 1}. ${s}`).join(\"; \");\r\n\t\t\tparts.push(\r\n\t\t\t\t` <procedure id=\"${m.id}\" name=\"${escapeXml(m.name)}\" trigger=\"${escapeXml(m.trigger)}\">${escapeXml(steps)}</procedure>`,\r\n\t\t\t);\r\n\t\t}\r\n\t\tparts.push(\"</procedural_memories>\");\r\n\t}\r\n\r\n\tif (episodic.memories.length > 0) {\r\n\t\tconst recent = episodic.memories.slice(-10);\r\n\t\tparts.push(\"\\n<recent_episodic_memories>\");\r\n\t\tfor (const m of recent) {\r\n\t\t\tconst details = m.details.join(\"; \");\r\n\t\t\tlet text = details;\r\n\t\t\tif (m.reflection?.lessons.length) {\r\n\t\t\t\ttext += ` | Lessons: ${m.reflection.lessons.join(\"; \")}`;\r\n\t\t\t}\r\n\t\t\tparts.push(\r\n\t\t\t\t` <episode id=\"${m.id}\" date=\"${m.date}\" summary=\"${escapeXml(m.summary)}\">${escapeXml(text)}</episode>`,\r\n\t\t\t);\r\n\t\t}\r\n\t\tparts.push(\"</recent_episodic_memories>\");\r\n\t}\r\n\r\n\tparts.push(\"\\n</memory_system>\");\r\n\r\n\treturn parts.join(\"\\n\");\r\n}\r\n\r\nfunction escapeXml(str: string): string {\r\n\treturn str\r\n\t\t.replace(/&/g, \"&\")\r\n\t\t.replace(/</g, \"<\")\r\n\t\t.replace(/>/g, \">\")\r\n\t\t.replace(/\"/g, \""\")\r\n\t\t.replace(/'/g, \"'\");\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Timestamp formatting\r\n// ---------------------------------------------------------------------------\r\n\r\nexport function formatTimestamp(ts: number): string {\r\n\tconst d = new Date(ts);\r\n\treturn d.toLocaleString(\"en-US\", {\r\n\t\tyear: \"numeric\",\r\n\t\tmonth: \"short\",\r\n\t\tday: \"numeric\",\r\n\t\thour: \"2-digit\",\r\n\t\tminute: \"2-digit\",\r\n\t\tsecond: \"2-digit\",\r\n\t\thour12: false,\r\n\t});\r\n}\r\n\r\n// ---------------------------------------------------------------------------\r\n// Memory counts (for status display)\r\n// ---------------------------------------------------------------------------\r\n\r\nexport interface MemoryCounts {\r\n\tsemantic: number;\r\n\tprocedural: number;\r\n\tepisodic: number;\r\n\ttotal: number;\r\n}\r\n\r\nexport function getMemoryCounts(cwd: string): MemoryCounts {\r\n\tconst semantic = loadStore<SemanticMemory>(cwd, \"semantic.json\").memories.length;\r\n\tconst procedural = loadStore<ProceduralMemory>(cwd, \"procedural.json\").memories.length;\r\n\tconst episodic = loadStore<EpisodicMemory>(cwd, \"episodic.json\").memories.length;\r\n\treturn { semantic, procedural, episodic, total: semantic + procedural + episodic };\r\n}\r\n"]}
|