@vaclav-synacek/pi-coding-agent-termux 0.45.7
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 +1961 -0
- package/README.md +1392 -0
- package/dist/cli/args.d.ts +42 -0
- package/dist/cli/args.d.ts.map +1 -0
- package/dist/cli/args.js +248 -0
- package/dist/cli/args.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 +32 -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 +10 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +61 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +141 -0
- package/dist/config.js.map +1 -0
- package/dist/core/agent-session.d.ts +523 -0
- package/dist/core/agent-session.d.ts.map +1 -0
- package/dist/core/agent-session.js +1795 -0
- package/dist/core/agent-session.js.map +1 -0
- package/dist/core/auth-storage.d.ts +112 -0
- package/dist/core/auth-storage.d.ts.map +1 -0
- package/dist/core/auth-storage.js +297 -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 +211 -0
- package/dist/core/bash-executor.js.map +1 -0
- package/dist/core/compaction/branch-summarization.d.ts +84 -0
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -0
- package/dist/core/compaction/branch-summarization.js +235 -0
- package/dist/core/compaction/branch-summarization.js.map +1 -0
- package/dist/core/compaction/compaction.d.ts +110 -0
- package/dist/core/compaction/compaction.d.ts.map +1 -0
- package/dist/core/compaction/compaction.js +559 -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/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/index.d.ts +17 -0
- package/dist/core/export-html/index.d.ts.map +1 -0
- package/dist/core/export-html/index.js +193 -0
- package/dist/core/export-html/index.js.map +1 -0
- package/dist/core/export-html/template.css +910 -0
- package/dist/core/export-html/template.html +54 -0
- package/dist/core/export-html/template.js +1329 -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 +10 -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 +383 -0
- package/dist/core/extensions/loader.js.map +1 -0
- package/dist/core/extensions/runner.d.ts +89 -0
- package/dist/core/extensions/runner.d.ts.map +1 -0
- package/dist/core/extensions/runner.js +406 -0
- package/dist/core/extensions/runner.js.map +1 -0
- package/dist/core/extensions/types.d.ts +654 -0
- package/dist/core/extensions/types.d.ts.map +1 -0
- package/dist/core/extensions/types.js +32 -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 +25 -0
- package/dist/core/footer-data-provider.d.ts.map +1 -0
- package/dist/core/footer-data-provider.js +121 -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 +59 -0
- package/dist/core/keybindings.d.ts.map +1 -0
- package/dist/core/keybindings.js +151 -0
- package/dist/core/keybindings.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 +123 -0
- package/dist/core/messages.js.map +1 -0
- package/dist/core/model-registry.d.ts +57 -0
- package/dist/core/model-registry.d.ts.map +1 -0
- package/dist/core/model-registry.js +314 -0
- package/dist/core/model-registry.js.map +1 -0
- package/dist/core/model-resolver.d.ts +76 -0
- package/dist/core/model-resolver.d.ts.map +1 -0
- package/dist/core/model-resolver.js +308 -0
- package/dist/core/model-resolver.js.map +1 -0
- package/dist/core/prompt-templates.d.ts +40 -0
- package/dist/core/prompt-templates.d.ts.map +1 -0
- package/dist/core/prompt-templates.js +197 -0
- package/dist/core/prompt-templates.js.map +1 -0
- package/dist/core/sdk.d.ts +181 -0
- package/dist/core/sdk.d.ts.map +1 -0
- package/dist/core/sdk.js +466 -0
- package/dist/core/sdk.js.map +1 -0
- package/dist/core/session-manager.d.ts +313 -0
- package/dist/core/session-manager.d.ts.map +1 -0
- package/dist/core/session-manager.js +996 -0
- package/dist/core/session-manager.js.map +1 -0
- package/dist/core/settings-manager.d.ts +138 -0
- package/dist/core/settings-manager.d.ts.map +1 -0
- package/dist/core/settings-manager.js +327 -0
- package/dist/core/settings-manager.js.map +1 -0
- package/dist/core/skills.d.ts +50 -0
- package/dist/core/skills.d.ts.map +1 -0
- package/dist/core/skills.js +338 -0
- package/dist/core/skills.js.map +1 -0
- package/dist/core/system-prompt.d.ts +48 -0
- package/dist/core/system-prompt.d.ts.map +1 -0
- package/dist/core/system-prompt.js +224 -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 +42 -0
- package/dist/core/tools/bash.d.ts.map +1 -0
- package/dist/core/tools/bash.js +223 -0
- package/dist/core/tools/bash.js.map +1 -0
- package/dist/core/tools/edit-diff.d.ts +33 -0
- package/dist/core/tools/edit-diff.d.ts.map +1 -0
- package/dist/core/tools/edit-diff.js +171 -0
- package/dist/core/tools/edit-diff.js.map +1 -0
- package/dist/core/tools/edit.d.ts +37 -0
- package/dist/core/tools/edit.d.ts.map +1 -0
- package/dist/core/tools/edit.js +143 -0
- package/dist/core/tools/edit.js.map +1 -0
- package/dist/core/tools/find.d.ts +37 -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 +43 -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 +70 -0
- package/dist/core/tools/index.d.ts.map +1 -0
- package/dist/core/tools/index.js +56 -0
- package/dist/core/tools/index.js.map +1 -0
- package/dist/core/tools/ls.d.ts +38 -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/path-utils.d.ts +8 -0
- package/dist/core/tools/path-utils.d.ts.map +1 -0
- package/dist/core/tools/path-utils.js +53 -0
- package/dist/core/tools/path-utils.js.map +1 -0
- package/dist/core/tools/read.d.ts +37 -0
- package/dist/core/tools/read.d.ts.map +1 -0
- package/dist/core/tools/read.js +165 -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 +27 -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 +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +35 -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 +354 -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 +15 -0
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/assistant-message.js +89 -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 +161 -0
- package/dist/modes/interactive/components/bash-execution.js.map +1 -0
- package/dist/modes/interactive/components/bordered-loader.d.ts +12 -0
- package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -0
- package/dist/modes/interactive/components/bordered-loader.js +30 -0
- package/dist/modes/interactive/components/bordered-loader.js.map +1 -0
- package/dist/modes/interactive/components/branch-summary-message.d.ts +15 -0
- package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/branch-summary-message.js +39 -0
- package/dist/modes/interactive/components/branch-summary-message.js.map +1 -0
- package/dist/modes/interactive/components/compaction-summary-message.d.ts +15 -0
- package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/compaction-summary-message.js +40 -0
- package/dist/modes/interactive/components/compaction-summary-message.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 +69 -0
- package/dist/modes/interactive/components/custom-editor.js.map +1 -0
- package/dist/modes/interactive/components/custom-message.d.ts +19 -0
- package/dist/modes/interactive/components/custom-message.d.ts.map +1 -0
- package/dist/modes/interactive/components/custom-message.js +84 -0
- package/dist/modes/interactive/components/custom-message.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 +15 -0
- package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -0
- package/dist/modes/interactive/components/extension-editor.js +96 -0
- package/dist/modes/interactive/components/extension-editor.js.map +1 -0
- package/dist/modes/interactive/components/extension-input.d.ts +20 -0
- package/dist/modes/interactive/components/extension-input.d.ts.map +1 -0
- package/dist/modes/interactive/components/extension-input.js +51 -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 +73 -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 +207 -0
- package/dist/modes/interactive/components/footer.js.map +1 -0
- package/dist/modes/interactive/components/index.d.ts +29 -0
- package/dist/modes/interactive/components/index.d.ts.map +1 -0
- package/dist/modes/interactive/components/index.js +30 -0
- package/dist/modes/interactive/components/index.js.map +1 -0
- package/dist/modes/interactive/components/login-dialog.d.ts +39 -0
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -0
- package/dist/modes/interactive/components/login-dialog.js +135 -0
- package/dist/modes/interactive/components/login-dialog.js.map +1 -0
- package/dist/modes/interactive/components/model-selector.d.ts +35 -0
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/model-selector.js +211 -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 +98 -0
- package/dist/modes/interactive/components/oauth-selector.js.map +1 -0
- package/dist/modes/interactive/components/scoped-models-selector.d.ts +46 -0
- package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/scoped-models-selector.js +258 -0
- package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -0
- package/dist/modes/interactive/components/session-selector.d.ts +44 -0
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/session-selector.js +311 -0
- package/dist/modes/interactive/components/session-selector.js.map +1 -0
- package/dist/modes/interactive/components/settings-selector.d.ts +43 -0
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/settings-selector.js +219 -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/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 +606 -0
- package/dist/modes/interactive/components/tool-execution.js.map +1 -0
- package/dist/modes/interactive/components/tree-selector.d.ts +52 -0
- package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -0
- package/dist/modes/interactive/components/tree-selector.js +745 -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 +261 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -0
- package/dist/modes/interactive/interactive-mode.js +3194 -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 +308 -0
- package/dist/modes/interactive/theme/theme.d.ts +71 -0
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -0
- package/dist/modes/interactive/theme/theme.js +893 -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 +140 -0
- package/dist/modes/print-mode.js.map +1 -0
- package/dist/modes/rpc/rpc-client.d.ts +209 -0
- package/dist/modes/rpc/rpc-client.d.ts.map +1 -0
- package/dist/modes/rpc/rpc-client.js +392 -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 +486 -0
- package/dist/modes/rpc/rpc-mode.js.map +1 -0
- package/dist/modes/rpc/rpc-types.d.ts +372 -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 +129 -0
- package/dist/utils/clipboard-image.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 +73 -0
- package/dist/utils/clipboard.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 +31 -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 +188 -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/shell.d.ts +26 -0
- package/dist/utils/shell.d.ts.map +1 -0
- package/dist/utils/shell.js +151 -0
- package/dist/utils/shell.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 +187 -0
- package/dist/utils/tools-manager.js.map +1 -0
- package/dist/utils/vips.d.ts +11 -0
- package/dist/utils/vips.d.ts.map +1 -0
- package/dist/utils/vips.js +35 -0
- package/dist/utils/vips.js.map +1 -0
- package/docs/compaction.md +388 -0
- package/docs/extensions.md +1524 -0
- package/docs/rpc.md +1046 -0
- package/docs/sdk.md +1024 -0
- package/docs/session.md +255 -0
- package/docs/skills.md +317 -0
- package/docs/theme.md +617 -0
- package/docs/tree.md +201 -0
- package/docs/tui.md +797 -0
- package/examples/README.md +24 -0
- package/examples/extensions/README.md +168 -0
- package/examples/extensions/auto-commit-on-exit.ts +49 -0
- package/examples/extensions/chalk-logger.ts +26 -0
- package/examples/extensions/claude-rules.ts +86 -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 +72 -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/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/interactive-shell.ts +196 -0
- package/examples/extensions/mac-system-theme.ts +47 -0
- package/examples/extensions/modal-editor.ts +85 -0
- package/examples/extensions/model-status.ts +31 -0
- package/examples/extensions/notify.ts +25 -0
- package/examples/extensions/overlay-qa-tests.ts +881 -0
- package/examples/extensions/overlay-test.ts +145 -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 +277 -0
- package/examples/extensions/questionnaire.ts +427 -0
- package/examples/extensions/rainbow-editor.ts +95 -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/shutdown-command.ts +63 -0
- package/examples/extensions/snake.ts +343 -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 +156 -0
- package/examples/extensions/subagent/index.ts +963 -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/timed-confirm.ts +70 -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/truncated-tool.ts +192 -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/sdk/01-minimal.ts +22 -0
- package/examples/sdk/02-custom-model.ts +49 -0
- package/examples/sdk/03-custom-prompt.ts +44 -0
- package/examples/sdk/04-skills.ts +47 -0
- package/examples/sdk/05-tools.ts +56 -0
- package/examples/sdk/06-extensions.ts +79 -0
- package/examples/sdk/07-context-files.ts +36 -0
- package/examples/sdk/08-prompt-templates.ts +42 -0
- package/examples/sdk/09-api-keys-and-oauth.ts +55 -0
- package/examples/sdk/10-settings.ts +38 -0
- package/examples/sdk/11-sessions.ts +48 -0
- package/examples/sdk/12-full-control.ts +72 -0
- package/examples/sdk/README.md +150 -0
- package/package.json +88 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/compaction/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iBAAiB,CAAC;AAChC,cAAc,YAAY,CAAC","sourcesContent":["/**\n * Compaction and summarization utilities.\n */\n\nexport * from \"./branch-summarization.js\";\nexport * from \"./compaction.js\";\nexport * from \"./utils.js\";\n"]}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared utilities for compaction and branch summarization.
|
|
3
|
+
*/
|
|
4
|
+
import type { AgentMessage } from "@mariozechner/pi-agent-core";
|
|
5
|
+
import type { Message } from "@mariozechner/pi-ai";
|
|
6
|
+
export interface FileOperations {
|
|
7
|
+
read: Set<string>;
|
|
8
|
+
written: Set<string>;
|
|
9
|
+
edited: Set<string>;
|
|
10
|
+
}
|
|
11
|
+
export declare function createFileOps(): FileOperations;
|
|
12
|
+
/**
|
|
13
|
+
* Extract file operations from tool calls in an assistant message.
|
|
14
|
+
*/
|
|
15
|
+
export declare function extractFileOpsFromMessage(message: AgentMessage, fileOps: FileOperations): void;
|
|
16
|
+
/**
|
|
17
|
+
* Compute final file lists from file operations.
|
|
18
|
+
* Returns readFiles (files only read, not modified) and modifiedFiles.
|
|
19
|
+
*/
|
|
20
|
+
export declare function computeFileLists(fileOps: FileOperations): {
|
|
21
|
+
readFiles: string[];
|
|
22
|
+
modifiedFiles: string[];
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Format file operations as XML tags for summary.
|
|
26
|
+
*/
|
|
27
|
+
export declare function formatFileOperations(readFiles: string[], modifiedFiles: string[]): string;
|
|
28
|
+
/**
|
|
29
|
+
* Serialize LLM messages to text for summarization.
|
|
30
|
+
* This prevents the model from treating it as a conversation to continue.
|
|
31
|
+
* Call convertToLlm() first to handle custom message types.
|
|
32
|
+
*/
|
|
33
|
+
export declare function serializeConversation(messages: Message[]): string;
|
|
34
|
+
export declare const SUMMARIZATION_SYSTEM_PROMPT = "You are a context summarization assistant. Your task is to read a conversation between a user and an AI coding assistant, then produce a structured summary following the exact format specified.\n\nDo NOT continue the conversation. Do NOT respond to any questions in the conversation. ONLY output the structured summary.";
|
|
35
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/core/compaction/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAMnD,MAAM,WAAW,cAAc;IAC9B,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAClB,OAAO,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IACrB,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CACpB;AAED,wBAAgB,aAAa,IAAI,cAAc,CAM9C;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,cAAc,GAAG,IAAI,CA2B9F;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,cAAc,GAAG;IAAE,SAAS,EAAE,MAAM,EAAE,CAAC;IAAC,aAAa,EAAE,MAAM,EAAE,CAAA;CAAE,CAK1G;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,aAAa,EAAE,MAAM,EAAE,GAAG,MAAM,CAUzF;AAMD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,MAAM,CAqDjE;AAMD,eAAO,MAAM,2BAA2B,oUAEmF,CAAC","sourcesContent":["/**\n * Shared utilities for compaction and branch summarization.\n */\n\nimport type { AgentMessage } from \"@mariozechner/pi-agent-core\";\nimport type { Message } from \"@mariozechner/pi-ai\";\n\n// ============================================================================\n// File Operation Tracking\n// ============================================================================\n\nexport interface FileOperations {\n\tread: Set<string>;\n\twritten: Set<string>;\n\tedited: Set<string>;\n}\n\nexport function createFileOps(): FileOperations {\n\treturn {\n\t\tread: new Set(),\n\t\twritten: new Set(),\n\t\tedited: new Set(),\n\t};\n}\n\n/**\n * Extract file operations from tool calls in an assistant message.\n */\nexport function extractFileOpsFromMessage(message: AgentMessage, fileOps: FileOperations): void {\n\tif (message.role !== \"assistant\") return;\n\tif (!(\"content\" in message) || !Array.isArray(message.content)) return;\n\n\tfor (const block of message.content) {\n\t\tif (typeof block !== \"object\" || block === null) continue;\n\t\tif (!(\"type\" in block) || block.type !== \"toolCall\") continue;\n\t\tif (!(\"arguments\" in block) || !(\"name\" in block)) continue;\n\n\t\tconst args = block.arguments as Record<string, unknown> | undefined;\n\t\tif (!args) continue;\n\n\t\tconst path = typeof args.path === \"string\" ? args.path : undefined;\n\t\tif (!path) continue;\n\n\t\tswitch (block.name) {\n\t\t\tcase \"read\":\n\t\t\t\tfileOps.read.add(path);\n\t\t\t\tbreak;\n\t\t\tcase \"write\":\n\t\t\t\tfileOps.written.add(path);\n\t\t\t\tbreak;\n\t\t\tcase \"edit\":\n\t\t\t\tfileOps.edited.add(path);\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n\n/**\n * Compute final file lists from file operations.\n * Returns readFiles (files only read, not modified) and modifiedFiles.\n */\nexport function computeFileLists(fileOps: FileOperations): { readFiles: string[]; modifiedFiles: string[] } {\n\tconst modified = new Set([...fileOps.edited, ...fileOps.written]);\n\tconst readOnly = [...fileOps.read].filter((f) => !modified.has(f)).sort();\n\tconst modifiedFiles = [...modified].sort();\n\treturn { readFiles: readOnly, modifiedFiles };\n}\n\n/**\n * Format file operations as XML tags for summary.\n */\nexport function formatFileOperations(readFiles: string[], modifiedFiles: string[]): string {\n\tconst sections: string[] = [];\n\tif (readFiles.length > 0) {\n\t\tsections.push(`<read-files>\\n${readFiles.join(\"\\n\")}\\n</read-files>`);\n\t}\n\tif (modifiedFiles.length > 0) {\n\t\tsections.push(`<modified-files>\\n${modifiedFiles.join(\"\\n\")}\\n</modified-files>`);\n\t}\n\tif (sections.length === 0) return \"\";\n\treturn `\\n\\n${sections.join(\"\\n\\n\")}`;\n}\n\n// ============================================================================\n// Message Serialization\n// ============================================================================\n\n/**\n * Serialize LLM messages to text for summarization.\n * This prevents the model from treating it as a conversation to continue.\n * Call convertToLlm() first to handle custom message types.\n */\nexport function serializeConversation(messages: Message[]): string {\n\tconst parts: string[] = [];\n\n\tfor (const msg of messages) {\n\t\tif (msg.role === \"user\") {\n\t\t\tconst content =\n\t\t\t\ttypeof msg.content === \"string\"\n\t\t\t\t\t? msg.content\n\t\t\t\t\t: msg.content\n\t\t\t\t\t\t\t.filter((c): c is { type: \"text\"; text: string } => c.type === \"text\")\n\t\t\t\t\t\t\t.map((c) => c.text)\n\t\t\t\t\t\t\t.join(\"\");\n\t\t\tif (content) parts.push(`[User]: ${content}`);\n\t\t} else if (msg.role === \"assistant\") {\n\t\t\tconst textParts: string[] = [];\n\t\t\tconst thinkingParts: string[] = [];\n\t\t\tconst toolCalls: string[] = [];\n\n\t\t\tfor (const block of msg.content) {\n\t\t\t\tif (block.type === \"text\") {\n\t\t\t\t\ttextParts.push(block.text);\n\t\t\t\t} else if (block.type === \"thinking\") {\n\t\t\t\t\tthinkingParts.push(block.thinking);\n\t\t\t\t} else if (block.type === \"toolCall\") {\n\t\t\t\t\tconst args = block.arguments as Record<string, unknown>;\n\t\t\t\t\tconst argsStr = Object.entries(args)\n\t\t\t\t\t\t.map(([k, v]) => `${k}=${JSON.stringify(v)}`)\n\t\t\t\t\t\t.join(\", \");\n\t\t\t\t\ttoolCalls.push(`${block.name}(${argsStr})`);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (thinkingParts.length > 0) {\n\t\t\t\tparts.push(`[Assistant thinking]: ${thinkingParts.join(\"\\n\")}`);\n\t\t\t}\n\t\t\tif (textParts.length > 0) {\n\t\t\t\tparts.push(`[Assistant]: ${textParts.join(\"\\n\")}`);\n\t\t\t}\n\t\t\tif (toolCalls.length > 0) {\n\t\t\t\tparts.push(`[Assistant tool calls]: ${toolCalls.join(\"; \")}`);\n\t\t\t}\n\t\t} else if (msg.role === \"toolResult\") {\n\t\t\tconst content = msg.content\n\t\t\t\t.filter((c): c is { type: \"text\"; text: string } => c.type === \"text\")\n\t\t\t\t.map((c) => c.text)\n\t\t\t\t.join(\"\");\n\t\t\tif (content) {\n\t\t\t\tparts.push(`[Tool result]: ${content}`);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn parts.join(\"\\n\\n\");\n}\n\n// ============================================================================\n// Summarization System Prompt\n// ============================================================================\n\nexport const SUMMARIZATION_SYSTEM_PROMPT = `You are a context summarization assistant. Your task is to read a conversation between a user and an AI coding assistant, then produce a structured summary following the exact format specified.\n\nDo NOT continue the conversation. Do NOT respond to any questions in the conversation. ONLY output the structured summary.`;\n"]}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared utilities for compaction and branch summarization.
|
|
3
|
+
*/
|
|
4
|
+
export function createFileOps() {
|
|
5
|
+
return {
|
|
6
|
+
read: new Set(),
|
|
7
|
+
written: new Set(),
|
|
8
|
+
edited: new Set(),
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Extract file operations from tool calls in an assistant message.
|
|
13
|
+
*/
|
|
14
|
+
export function extractFileOpsFromMessage(message, fileOps) {
|
|
15
|
+
if (message.role !== "assistant")
|
|
16
|
+
return;
|
|
17
|
+
if (!("content" in message) || !Array.isArray(message.content))
|
|
18
|
+
return;
|
|
19
|
+
for (const block of message.content) {
|
|
20
|
+
if (typeof block !== "object" || block === null)
|
|
21
|
+
continue;
|
|
22
|
+
if (!("type" in block) || block.type !== "toolCall")
|
|
23
|
+
continue;
|
|
24
|
+
if (!("arguments" in block) || !("name" in block))
|
|
25
|
+
continue;
|
|
26
|
+
const args = block.arguments;
|
|
27
|
+
if (!args)
|
|
28
|
+
continue;
|
|
29
|
+
const path = typeof args.path === "string" ? args.path : undefined;
|
|
30
|
+
if (!path)
|
|
31
|
+
continue;
|
|
32
|
+
switch (block.name) {
|
|
33
|
+
case "read":
|
|
34
|
+
fileOps.read.add(path);
|
|
35
|
+
break;
|
|
36
|
+
case "write":
|
|
37
|
+
fileOps.written.add(path);
|
|
38
|
+
break;
|
|
39
|
+
case "edit":
|
|
40
|
+
fileOps.edited.add(path);
|
|
41
|
+
break;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Compute final file lists from file operations.
|
|
47
|
+
* Returns readFiles (files only read, not modified) and modifiedFiles.
|
|
48
|
+
*/
|
|
49
|
+
export function computeFileLists(fileOps) {
|
|
50
|
+
const modified = new Set([...fileOps.edited, ...fileOps.written]);
|
|
51
|
+
const readOnly = [...fileOps.read].filter((f) => !modified.has(f)).sort();
|
|
52
|
+
const modifiedFiles = [...modified].sort();
|
|
53
|
+
return { readFiles: readOnly, modifiedFiles };
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Format file operations as XML tags for summary.
|
|
57
|
+
*/
|
|
58
|
+
export function formatFileOperations(readFiles, modifiedFiles) {
|
|
59
|
+
const sections = [];
|
|
60
|
+
if (readFiles.length > 0) {
|
|
61
|
+
sections.push(`<read-files>\n${readFiles.join("\n")}\n</read-files>`);
|
|
62
|
+
}
|
|
63
|
+
if (modifiedFiles.length > 0) {
|
|
64
|
+
sections.push(`<modified-files>\n${modifiedFiles.join("\n")}\n</modified-files>`);
|
|
65
|
+
}
|
|
66
|
+
if (sections.length === 0)
|
|
67
|
+
return "";
|
|
68
|
+
return `\n\n${sections.join("\n\n")}`;
|
|
69
|
+
}
|
|
70
|
+
// ============================================================================
|
|
71
|
+
// Message Serialization
|
|
72
|
+
// ============================================================================
|
|
73
|
+
/**
|
|
74
|
+
* Serialize LLM messages to text for summarization.
|
|
75
|
+
* This prevents the model from treating it as a conversation to continue.
|
|
76
|
+
* Call convertToLlm() first to handle custom message types.
|
|
77
|
+
*/
|
|
78
|
+
export function serializeConversation(messages) {
|
|
79
|
+
const parts = [];
|
|
80
|
+
for (const msg of messages) {
|
|
81
|
+
if (msg.role === "user") {
|
|
82
|
+
const content = typeof msg.content === "string"
|
|
83
|
+
? msg.content
|
|
84
|
+
: msg.content
|
|
85
|
+
.filter((c) => c.type === "text")
|
|
86
|
+
.map((c) => c.text)
|
|
87
|
+
.join("");
|
|
88
|
+
if (content)
|
|
89
|
+
parts.push(`[User]: ${content}`);
|
|
90
|
+
}
|
|
91
|
+
else if (msg.role === "assistant") {
|
|
92
|
+
const textParts = [];
|
|
93
|
+
const thinkingParts = [];
|
|
94
|
+
const toolCalls = [];
|
|
95
|
+
for (const block of msg.content) {
|
|
96
|
+
if (block.type === "text") {
|
|
97
|
+
textParts.push(block.text);
|
|
98
|
+
}
|
|
99
|
+
else if (block.type === "thinking") {
|
|
100
|
+
thinkingParts.push(block.thinking);
|
|
101
|
+
}
|
|
102
|
+
else if (block.type === "toolCall") {
|
|
103
|
+
const args = block.arguments;
|
|
104
|
+
const argsStr = Object.entries(args)
|
|
105
|
+
.map(([k, v]) => `${k}=${JSON.stringify(v)}`)
|
|
106
|
+
.join(", ");
|
|
107
|
+
toolCalls.push(`${block.name}(${argsStr})`);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
if (thinkingParts.length > 0) {
|
|
111
|
+
parts.push(`[Assistant thinking]: ${thinkingParts.join("\n")}`);
|
|
112
|
+
}
|
|
113
|
+
if (textParts.length > 0) {
|
|
114
|
+
parts.push(`[Assistant]: ${textParts.join("\n")}`);
|
|
115
|
+
}
|
|
116
|
+
if (toolCalls.length > 0) {
|
|
117
|
+
parts.push(`[Assistant tool calls]: ${toolCalls.join("; ")}`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
else if (msg.role === "toolResult") {
|
|
121
|
+
const content = msg.content
|
|
122
|
+
.filter((c) => c.type === "text")
|
|
123
|
+
.map((c) => c.text)
|
|
124
|
+
.join("");
|
|
125
|
+
if (content) {
|
|
126
|
+
parts.push(`[Tool result]: ${content}`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return parts.join("\n\n");
|
|
131
|
+
}
|
|
132
|
+
// ============================================================================
|
|
133
|
+
// Summarization System Prompt
|
|
134
|
+
// ============================================================================
|
|
135
|
+
export const SUMMARIZATION_SYSTEM_PROMPT = `You are a context summarization assistant. Your task is to read a conversation between a user and an AI coding assistant, then produce a structured summary following the exact format specified.
|
|
136
|
+
|
|
137
|
+
Do NOT continue the conversation. Do NOT respond to any questions in the conversation. ONLY output the structured summary.`;
|
|
138
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/core/compaction/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAeH,MAAM,UAAU,aAAa,GAAmB;IAC/C,OAAO;QACN,IAAI,EAAE,IAAI,GAAG,EAAE;QACf,OAAO,EAAE,IAAI,GAAG,EAAE;QAClB,MAAM,EAAE,IAAI,GAAG,EAAE;KACjB,CAAC;AAAA,CACF;AAED;;GAEG;AACH,MAAM,UAAU,yBAAyB,CAAC,OAAqB,EAAE,OAAuB,EAAQ;IAC/F,IAAI,OAAO,CAAC,IAAI,KAAK,WAAW;QAAE,OAAO;IACzC,IAAI,CAAC,CAAC,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC;QAAE,OAAO;IAEvE,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QACrC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;YAAE,SAAS;QAC1D,IAAI,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU;YAAE,SAAS;QAC9D,IAAI,CAAC,CAAC,WAAW,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,IAAI,KAAK,CAAC;YAAE,SAAS;QAE5D,MAAM,IAAI,GAAG,KAAK,CAAC,SAAgD,CAAC;QACpE,IAAI,CAAC,IAAI;YAAE,SAAS;QAEpB,MAAM,IAAI,GAAG,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;QACnE,IAAI,CAAC,IAAI;YAAE,SAAS;QAEpB,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;YACpB,KAAK,MAAM;gBACV,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBACvB,MAAM;YACP,KAAK,OAAO;gBACX,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBAC1B,MAAM;YACP,KAAK,MAAM;gBACV,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBACzB,MAAM;QACR,CAAC;IACF,CAAC;AAAA,CACD;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAuB,EAAoD;IAC3G,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC;IAClE,MAAM,QAAQ,GAAG,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC1E,MAAM,aAAa,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC;IAC3C,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,aAAa,EAAE,CAAC;AAAA,CAC9C;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,SAAmB,EAAE,aAAuB,EAAU;IAC1F,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC1B,QAAQ,CAAC,IAAI,CAAC,iBAAiB,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;IACvE,CAAC;IACD,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9B,QAAQ,CAAC,IAAI,CAAC,qBAAqB,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;IACnF,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACrC,OAAO,OAAO,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;AAAA,CACtC;AAED,+EAA+E;AAC/E,wBAAwB;AACxB,+EAA+E;AAE/E;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,QAAmB,EAAU;IAClE,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC5B,IAAI,GAAG,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACzB,MAAM,OAAO,GACZ,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ;gBAC9B,CAAC,CAAC,GAAG,CAAC,OAAO;gBACb,CAAC,CAAC,GAAG,CAAC,OAAO;qBACV,MAAM,CAAC,CAAC,CAAC,EAAuC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC;qBACrE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;qBAClB,IAAI,CAAC,EAAE,CAAC,CAAC;YACd,IAAI,OAAO;gBAAE,KAAK,CAAC,IAAI,CAAC,WAAW,OAAO,EAAE,CAAC,CAAC;QAC/C,CAAC;aAAM,IAAI,GAAG,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;YACrC,MAAM,SAAS,GAAa,EAAE,CAAC;YAC/B,MAAM,aAAa,GAAa,EAAE,CAAC;YACnC,MAAM,SAAS,GAAa,EAAE,CAAC;YAE/B,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;gBACjC,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;oBAC3B,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAC5B,CAAC;qBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;oBACtC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;gBACpC,CAAC;qBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;oBACtC,MAAM,IAAI,GAAG,KAAK,CAAC,SAAoC,CAAC;oBACxD,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC;yBAClC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC;yBAC5C,IAAI,CAAC,IAAI,CAAC,CAAC;oBACb,SAAS,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,IAAI,IAAI,OAAO,GAAG,CAAC,CAAC;gBAC7C,CAAC;YACF,CAAC;YAED,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC9B,KAAK,CAAC,IAAI,CAAC,yBAAyB,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACjE,CAAC;YACD,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC1B,KAAK,CAAC,IAAI,CAAC,gBAAgB,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACpD,CAAC;YACD,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC1B,KAAK,CAAC,IAAI,CAAC,2BAA2B,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC/D,CAAC;QACF,CAAC;aAAM,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YACtC,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO;iBACzB,MAAM,CAAC,CAAC,CAAC,EAAuC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC;iBACrE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;iBAClB,IAAI,CAAC,EAAE,CAAC,CAAC;YACX,IAAI,OAAO,EAAE,CAAC;gBACb,KAAK,CAAC,IAAI,CAAC,kBAAkB,OAAO,EAAE,CAAC,CAAC;YACzC,CAAC;QACF,CAAC;IACF,CAAC;IAED,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;AAAA,CAC1B;AAED,+EAA+E;AAC/E,8BAA8B;AAC9B,+EAA+E;AAE/E,MAAM,CAAC,MAAM,2BAA2B,GAAG;;2HAEgF,CAAC","sourcesContent":["/**\n * Shared utilities for compaction and branch summarization.\n */\n\nimport type { AgentMessage } from \"@mariozechner/pi-agent-core\";\nimport type { Message } from \"@mariozechner/pi-ai\";\n\n// ============================================================================\n// File Operation Tracking\n// ============================================================================\n\nexport interface FileOperations {\n\tread: Set<string>;\n\twritten: Set<string>;\n\tedited: Set<string>;\n}\n\nexport function createFileOps(): FileOperations {\n\treturn {\n\t\tread: new Set(),\n\t\twritten: new Set(),\n\t\tedited: new Set(),\n\t};\n}\n\n/**\n * Extract file operations from tool calls in an assistant message.\n */\nexport function extractFileOpsFromMessage(message: AgentMessage, fileOps: FileOperations): void {\n\tif (message.role !== \"assistant\") return;\n\tif (!(\"content\" in message) || !Array.isArray(message.content)) return;\n\n\tfor (const block of message.content) {\n\t\tif (typeof block !== \"object\" || block === null) continue;\n\t\tif (!(\"type\" in block) || block.type !== \"toolCall\") continue;\n\t\tif (!(\"arguments\" in block) || !(\"name\" in block)) continue;\n\n\t\tconst args = block.arguments as Record<string, unknown> | undefined;\n\t\tif (!args) continue;\n\n\t\tconst path = typeof args.path === \"string\" ? args.path : undefined;\n\t\tif (!path) continue;\n\n\t\tswitch (block.name) {\n\t\t\tcase \"read\":\n\t\t\t\tfileOps.read.add(path);\n\t\t\t\tbreak;\n\t\t\tcase \"write\":\n\t\t\t\tfileOps.written.add(path);\n\t\t\t\tbreak;\n\t\t\tcase \"edit\":\n\t\t\t\tfileOps.edited.add(path);\n\t\t\t\tbreak;\n\t\t}\n\t}\n}\n\n/**\n * Compute final file lists from file operations.\n * Returns readFiles (files only read, not modified) and modifiedFiles.\n */\nexport function computeFileLists(fileOps: FileOperations): { readFiles: string[]; modifiedFiles: string[] } {\n\tconst modified = new Set([...fileOps.edited, ...fileOps.written]);\n\tconst readOnly = [...fileOps.read].filter((f) => !modified.has(f)).sort();\n\tconst modifiedFiles = [...modified].sort();\n\treturn { readFiles: readOnly, modifiedFiles };\n}\n\n/**\n * Format file operations as XML tags for summary.\n */\nexport function formatFileOperations(readFiles: string[], modifiedFiles: string[]): string {\n\tconst sections: string[] = [];\n\tif (readFiles.length > 0) {\n\t\tsections.push(`<read-files>\\n${readFiles.join(\"\\n\")}\\n</read-files>`);\n\t}\n\tif (modifiedFiles.length > 0) {\n\t\tsections.push(`<modified-files>\\n${modifiedFiles.join(\"\\n\")}\\n</modified-files>`);\n\t}\n\tif (sections.length === 0) return \"\";\n\treturn `\\n\\n${sections.join(\"\\n\\n\")}`;\n}\n\n// ============================================================================\n// Message Serialization\n// ============================================================================\n\n/**\n * Serialize LLM messages to text for summarization.\n * This prevents the model from treating it as a conversation to continue.\n * Call convertToLlm() first to handle custom message types.\n */\nexport function serializeConversation(messages: Message[]): string {\n\tconst parts: string[] = [];\n\n\tfor (const msg of messages) {\n\t\tif (msg.role === \"user\") {\n\t\t\tconst content =\n\t\t\t\ttypeof msg.content === \"string\"\n\t\t\t\t\t? msg.content\n\t\t\t\t\t: msg.content\n\t\t\t\t\t\t\t.filter((c): c is { type: \"text\"; text: string } => c.type === \"text\")\n\t\t\t\t\t\t\t.map((c) => c.text)\n\t\t\t\t\t\t\t.join(\"\");\n\t\t\tif (content) parts.push(`[User]: ${content}`);\n\t\t} else if (msg.role === \"assistant\") {\n\t\t\tconst textParts: string[] = [];\n\t\t\tconst thinkingParts: string[] = [];\n\t\t\tconst toolCalls: string[] = [];\n\n\t\t\tfor (const block of msg.content) {\n\t\t\t\tif (block.type === \"text\") {\n\t\t\t\t\ttextParts.push(block.text);\n\t\t\t\t} else if (block.type === \"thinking\") {\n\t\t\t\t\tthinkingParts.push(block.thinking);\n\t\t\t\t} else if (block.type === \"toolCall\") {\n\t\t\t\t\tconst args = block.arguments as Record<string, unknown>;\n\t\t\t\t\tconst argsStr = Object.entries(args)\n\t\t\t\t\t\t.map(([k, v]) => `${k}=${JSON.stringify(v)}`)\n\t\t\t\t\t\t.join(\", \");\n\t\t\t\t\ttoolCalls.push(`${block.name}(${argsStr})`);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (thinkingParts.length > 0) {\n\t\t\t\tparts.push(`[Assistant thinking]: ${thinkingParts.join(\"\\n\")}`);\n\t\t\t}\n\t\t\tif (textParts.length > 0) {\n\t\t\t\tparts.push(`[Assistant]: ${textParts.join(\"\\n\")}`);\n\t\t\t}\n\t\t\tif (toolCalls.length > 0) {\n\t\t\t\tparts.push(`[Assistant tool calls]: ${toolCalls.join(\"; \")}`);\n\t\t\t}\n\t\t} else if (msg.role === \"toolResult\") {\n\t\t\tconst content = msg.content\n\t\t\t\t.filter((c): c is { type: \"text\"; text: string } => c.type === \"text\")\n\t\t\t\t.map((c) => c.text)\n\t\t\t\t.join(\"\");\n\t\t\tif (content) {\n\t\t\t\tparts.push(`[Tool result]: ${content}`);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn parts.join(\"\\n\\n\");\n}\n\n// ============================================================================\n// Summarization System Prompt\n// ============================================================================\n\nexport const SUMMARIZATION_SYSTEM_PROMPT = `You are a context summarization assistant. Your task is to read a conversation between a user and an AI coding assistant, then produce a structured summary following the exact format specified.\n\nDo NOT continue the conversation. Do NOT respond to any questions in the conversation. ONLY output the structured summary.`;\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface EventBus {
|
|
2
|
+
emit(channel: string, data: unknown): void;
|
|
3
|
+
on(channel: string, handler: (data: unknown) => void): () => void;
|
|
4
|
+
}
|
|
5
|
+
export interface EventBusController extends EventBus {
|
|
6
|
+
clear(): void;
|
|
7
|
+
}
|
|
8
|
+
export declare function createEventBus(): EventBusController;
|
|
9
|
+
//# sourceMappingURL=event-bus.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-bus.d.ts","sourceRoot":"","sources":["../../src/core/event-bus.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,QAAQ;IACxB,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI,CAAC;IAC3C,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;CAClE;AAED,MAAM,WAAW,kBAAmB,SAAQ,QAAQ;IACnD,KAAK,IAAI,IAAI,CAAC;CACd;AAED,wBAAgB,cAAc,IAAI,kBAAkB,CAqBnD","sourcesContent":["import { EventEmitter } from \"node:events\";\n\nexport interface EventBus {\n\temit(channel: string, data: unknown): void;\n\ton(channel: string, handler: (data: unknown) => void): () => void;\n}\n\nexport interface EventBusController extends EventBus {\n\tclear(): void;\n}\n\nexport function createEventBus(): EventBusController {\n\tconst emitter = new EventEmitter();\n\treturn {\n\t\temit: (channel, data) => {\n\t\t\temitter.emit(channel, data);\n\t\t},\n\t\ton: (channel, handler) => {\n\t\t\tconst safeHandler = async (data: unknown) => {\n\t\t\t\ttry {\n\t\t\t\t\tawait handler(data);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconsole.error(`Event handler error (${channel}):`, err);\n\t\t\t\t}\n\t\t\t};\n\t\t\temitter.on(channel, safeHandler);\n\t\t\treturn () => emitter.off(channel, safeHandler);\n\t\t},\n\t\tclear: () => {\n\t\t\temitter.removeAllListeners();\n\t\t},\n\t};\n}\n"]}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { EventEmitter } from "node:events";
|
|
2
|
+
export function createEventBus() {
|
|
3
|
+
const emitter = new EventEmitter();
|
|
4
|
+
return {
|
|
5
|
+
emit: (channel, data) => {
|
|
6
|
+
emitter.emit(channel, data);
|
|
7
|
+
},
|
|
8
|
+
on: (channel, handler) => {
|
|
9
|
+
const safeHandler = async (data) => {
|
|
10
|
+
try {
|
|
11
|
+
await handler(data);
|
|
12
|
+
}
|
|
13
|
+
catch (err) {
|
|
14
|
+
console.error(`Event handler error (${channel}):`, err);
|
|
15
|
+
}
|
|
16
|
+
};
|
|
17
|
+
emitter.on(channel, safeHandler);
|
|
18
|
+
return () => emitter.off(channel, safeHandler);
|
|
19
|
+
},
|
|
20
|
+
clear: () => {
|
|
21
|
+
emitter.removeAllListeners();
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=event-bus.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-bus.js","sourceRoot":"","sources":["../../src/core/event-bus.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAW3C,MAAM,UAAU,cAAc,GAAuB;IACpD,MAAM,OAAO,GAAG,IAAI,YAAY,EAAE,CAAC;IACnC,OAAO;QACN,IAAI,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC;YACxB,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAAA,CAC5B;QACD,EAAE,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC;YACzB,MAAM,WAAW,GAAG,KAAK,EAAE,IAAa,EAAE,EAAE,CAAC;gBAC5C,IAAI,CAAC;oBACJ,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;gBACrB,CAAC;gBAAC,OAAO,GAAG,EAAE,CAAC;oBACd,OAAO,CAAC,KAAK,CAAC,wBAAwB,OAAO,IAAI,EAAE,GAAG,CAAC,CAAC;gBACzD,CAAC;YAAA,CACD,CAAC;YACF,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;YACjC,OAAO,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;QAAA,CAC/C;QACD,KAAK,EAAE,GAAG,EAAE,CAAC;YACZ,OAAO,CAAC,kBAAkB,EAAE,CAAC;QAAA,CAC7B;KACD,CAAC;AAAA,CACF","sourcesContent":["import { EventEmitter } from \"node:events\";\n\nexport interface EventBus {\n\temit(channel: string, data: unknown): void;\n\ton(channel: string, handler: (data: unknown) => void): () => void;\n}\n\nexport interface EventBusController extends EventBus {\n\tclear(): void;\n}\n\nexport function createEventBus(): EventBusController {\n\tconst emitter = new EventEmitter();\n\treturn {\n\t\temit: (channel, data) => {\n\t\t\temitter.emit(channel, data);\n\t\t},\n\t\ton: (channel, handler) => {\n\t\t\tconst safeHandler = async (data: unknown) => {\n\t\t\t\ttry {\n\t\t\t\t\tawait handler(data);\n\t\t\t\t} catch (err) {\n\t\t\t\t\tconsole.error(`Event handler error (${channel}):`, err);\n\t\t\t\t}\n\t\t\t};\n\t\t\temitter.on(channel, safeHandler);\n\t\t\treturn () => emitter.off(channel, safeHandler);\n\t\t},\n\t\tclear: () => {\n\t\t\temitter.removeAllListeners();\n\t\t},\n\t};\n}\n"]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared command execution utilities for extensions and custom tools.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Options for executing shell commands.
|
|
6
|
+
*/
|
|
7
|
+
export interface ExecOptions {
|
|
8
|
+
/** AbortSignal to cancel the command */
|
|
9
|
+
signal?: AbortSignal;
|
|
10
|
+
/** Timeout in milliseconds */
|
|
11
|
+
timeout?: number;
|
|
12
|
+
/** Working directory */
|
|
13
|
+
cwd?: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Result of executing a shell command.
|
|
17
|
+
*/
|
|
18
|
+
export interface ExecResult {
|
|
19
|
+
stdout: string;
|
|
20
|
+
stderr: string;
|
|
21
|
+
code: number;
|
|
22
|
+
killed: boolean;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Execute a shell command and return stdout/stderr/code.
|
|
26
|
+
* Supports timeout and abort signal.
|
|
27
|
+
*/
|
|
28
|
+
export declare function execCommand(command: string, args: string[], cwd: string, options?: ExecOptions): Promise<ExecResult>;
|
|
29
|
+
//# sourceMappingURL=exec.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exec.d.ts","sourceRoot":"","sources":["../../src/core/exec.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH;;GAEG;AACH,MAAM,WAAW,WAAW;IAC3B,wCAAwC;IACxC,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,8BAA8B;IAC9B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wBAAwB;IACxB,GAAG,CAAC,EAAE,MAAM,CAAC;CACb;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAChC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,WAAW,GACnB,OAAO,CAAC,UAAU,CAAC,CAkErB","sourcesContent":["/**\n * Shared command execution utilities for extensions and custom tools.\n */\n\nimport { spawn } from \"node:child_process\";\n\n/**\n * Options for executing shell commands.\n */\nexport interface ExecOptions {\n\t/** AbortSignal to cancel the command */\n\tsignal?: AbortSignal;\n\t/** Timeout in milliseconds */\n\ttimeout?: number;\n\t/** Working directory */\n\tcwd?: string;\n}\n\n/**\n * Result of executing a shell command.\n */\nexport interface ExecResult {\n\tstdout: string;\n\tstderr: string;\n\tcode: number;\n\tkilled: boolean;\n}\n\n/**\n * Execute a shell command and return stdout/stderr/code.\n * Supports timeout and abort signal.\n */\nexport async function execCommand(\n\tcommand: string,\n\targs: string[],\n\tcwd: string,\n\toptions?: ExecOptions,\n): Promise<ExecResult> {\n\treturn new Promise((resolve) => {\n\t\tconst proc = spawn(command, args, {\n\t\t\tcwd,\n\t\t\tshell: false,\n\t\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t\t});\n\n\t\tlet stdout = \"\";\n\t\tlet stderr = \"\";\n\t\tlet killed = false;\n\t\tlet timeoutId: NodeJS.Timeout | undefined;\n\n\t\tconst killProcess = () => {\n\t\t\tif (!killed) {\n\t\t\t\tkilled = true;\n\t\t\t\tproc.kill(\"SIGTERM\");\n\t\t\t\t// Force kill after 5 seconds if SIGTERM doesn't work\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tif (!proc.killed) {\n\t\t\t\t\t\tproc.kill(\"SIGKILL\");\n\t\t\t\t\t}\n\t\t\t\t}, 5000);\n\t\t\t}\n\t\t};\n\n\t\t// Handle abort signal\n\t\tif (options?.signal) {\n\t\t\tif (options.signal.aborted) {\n\t\t\t\tkillProcess();\n\t\t\t} else {\n\t\t\t\toptions.signal.addEventListener(\"abort\", killProcess, { once: true });\n\t\t\t}\n\t\t}\n\n\t\t// Handle timeout\n\t\tif (options?.timeout && options.timeout > 0) {\n\t\t\ttimeoutId = setTimeout(() => {\n\t\t\t\tkillProcess();\n\t\t\t}, options.timeout);\n\t\t}\n\n\t\tproc.stdout?.on(\"data\", (data) => {\n\t\t\tstdout += data.toString();\n\t\t});\n\n\t\tproc.stderr?.on(\"data\", (data) => {\n\t\t\tstderr += data.toString();\n\t\t});\n\n\t\tproc.on(\"close\", (code) => {\n\t\t\tif (timeoutId) clearTimeout(timeoutId);\n\t\t\tif (options?.signal) {\n\t\t\t\toptions.signal.removeEventListener(\"abort\", killProcess);\n\t\t\t}\n\t\t\tresolve({ stdout, stderr, code: code ?? 0, killed });\n\t\t});\n\n\t\tproc.on(\"error\", (_err) => {\n\t\t\tif (timeoutId) clearTimeout(timeoutId);\n\t\t\tif (options?.signal) {\n\t\t\t\toptions.signal.removeEventListener(\"abort\", killProcess);\n\t\t\t}\n\t\t\tresolve({ stdout, stderr, code: 1, killed });\n\t\t});\n\t});\n}\n"]}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared command execution utilities for extensions and custom tools.
|
|
3
|
+
*/
|
|
4
|
+
import { spawn } from "node:child_process";
|
|
5
|
+
/**
|
|
6
|
+
* Execute a shell command and return stdout/stderr/code.
|
|
7
|
+
* Supports timeout and abort signal.
|
|
8
|
+
*/
|
|
9
|
+
export async function execCommand(command, args, cwd, options) {
|
|
10
|
+
return new Promise((resolve) => {
|
|
11
|
+
const proc = spawn(command, args, {
|
|
12
|
+
cwd,
|
|
13
|
+
shell: false,
|
|
14
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
15
|
+
});
|
|
16
|
+
let stdout = "";
|
|
17
|
+
let stderr = "";
|
|
18
|
+
let killed = false;
|
|
19
|
+
let timeoutId;
|
|
20
|
+
const killProcess = () => {
|
|
21
|
+
if (!killed) {
|
|
22
|
+
killed = true;
|
|
23
|
+
proc.kill("SIGTERM");
|
|
24
|
+
// Force kill after 5 seconds if SIGTERM doesn't work
|
|
25
|
+
setTimeout(() => {
|
|
26
|
+
if (!proc.killed) {
|
|
27
|
+
proc.kill("SIGKILL");
|
|
28
|
+
}
|
|
29
|
+
}, 5000);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
// Handle abort signal
|
|
33
|
+
if (options?.signal) {
|
|
34
|
+
if (options.signal.aborted) {
|
|
35
|
+
killProcess();
|
|
36
|
+
}
|
|
37
|
+
else {
|
|
38
|
+
options.signal.addEventListener("abort", killProcess, { once: true });
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// Handle timeout
|
|
42
|
+
if (options?.timeout && options.timeout > 0) {
|
|
43
|
+
timeoutId = setTimeout(() => {
|
|
44
|
+
killProcess();
|
|
45
|
+
}, options.timeout);
|
|
46
|
+
}
|
|
47
|
+
proc.stdout?.on("data", (data) => {
|
|
48
|
+
stdout += data.toString();
|
|
49
|
+
});
|
|
50
|
+
proc.stderr?.on("data", (data) => {
|
|
51
|
+
stderr += data.toString();
|
|
52
|
+
});
|
|
53
|
+
proc.on("close", (code) => {
|
|
54
|
+
if (timeoutId)
|
|
55
|
+
clearTimeout(timeoutId);
|
|
56
|
+
if (options?.signal) {
|
|
57
|
+
options.signal.removeEventListener("abort", killProcess);
|
|
58
|
+
}
|
|
59
|
+
resolve({ stdout, stderr, code: code ?? 0, killed });
|
|
60
|
+
});
|
|
61
|
+
proc.on("error", (_err) => {
|
|
62
|
+
if (timeoutId)
|
|
63
|
+
clearTimeout(timeoutId);
|
|
64
|
+
if (options?.signal) {
|
|
65
|
+
options.signal.removeEventListener("abort", killProcess);
|
|
66
|
+
}
|
|
67
|
+
resolve({ stdout, stderr, code: 1, killed });
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=exec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"exec.js","sourceRoot":"","sources":["../../src/core/exec.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Shared command execution utilities for extensions and custom tools.\n */\n\nimport { spawn } from \"node:child_process\";\n\n/**\n * Options for executing shell commands.\n */\nexport interface ExecOptions {\n\t/** AbortSignal to cancel the command */\n\tsignal?: AbortSignal;\n\t/** Timeout in milliseconds */\n\ttimeout?: number;\n\t/** Working directory */\n\tcwd?: string;\n}\n\n/**\n * Result of executing a shell command.\n */\nexport interface ExecResult {\n\tstdout: string;\n\tstderr: string;\n\tcode: number;\n\tkilled: boolean;\n}\n\n/**\n * Execute a shell command and return stdout/stderr/code.\n * Supports timeout and abort signal.\n */\nexport async function execCommand(\n\tcommand: string,\n\targs: string[],\n\tcwd: string,\n\toptions?: ExecOptions,\n): Promise<ExecResult> {\n\treturn new Promise((resolve) => {\n\t\tconst proc = spawn(command, args, {\n\t\t\tcwd,\n\t\t\tshell: false,\n\t\t\tstdio: [\"ignore\", \"pipe\", \"pipe\"],\n\t\t});\n\n\t\tlet stdout = \"\";\n\t\tlet stderr = \"\";\n\t\tlet killed = false;\n\t\tlet timeoutId: NodeJS.Timeout | undefined;\n\n\t\tconst killProcess = () => {\n\t\t\tif (!killed) {\n\t\t\t\tkilled = true;\n\t\t\t\tproc.kill(\"SIGTERM\");\n\t\t\t\t// Force kill after 5 seconds if SIGTERM doesn't work\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\tif (!proc.killed) {\n\t\t\t\t\t\tproc.kill(\"SIGKILL\");\n\t\t\t\t\t}\n\t\t\t\t}, 5000);\n\t\t\t}\n\t\t};\n\n\t\t// Handle abort signal\n\t\tif (options?.signal) {\n\t\t\tif (options.signal.aborted) {\n\t\t\t\tkillProcess();\n\t\t\t} else {\n\t\t\t\toptions.signal.addEventListener(\"abort\", killProcess, { once: true });\n\t\t\t}\n\t\t}\n\n\t\t// Handle timeout\n\t\tif (options?.timeout && options.timeout > 0) {\n\t\t\ttimeoutId = setTimeout(() => {\n\t\t\t\tkillProcess();\n\t\t\t}, options.timeout);\n\t\t}\n\n\t\tproc.stdout?.on(\"data\", (data) => {\n\t\t\tstdout += data.toString();\n\t\t});\n\n\t\tproc.stderr?.on(\"data\", (data) => {\n\t\t\tstderr += data.toString();\n\t\t});\n\n\t\tproc.on(\"close\", (code) => {\n\t\t\tif (timeoutId) clearTimeout(timeoutId);\n\t\t\tif (options?.signal) {\n\t\t\t\toptions.signal.removeEventListener(\"abort\", killProcess);\n\t\t\t}\n\t\t\tresolve({ stdout, stderr, code: code ?? 0, killed });\n\t\t});\n\n\t\tproc.on(\"error\", (_err) => {\n\t\t\tif (timeoutId) clearTimeout(timeoutId);\n\t\t\tif (options?.signal) {\n\t\t\t\toptions.signal.removeEventListener(\"abort\", killProcess);\n\t\t\t}\n\t\t\tresolve({ stdout, stderr, code: 1, killed });\n\t\t});\n\t});\n}\n"]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { AgentState } from "@mariozechner/pi-agent-core";
|
|
2
|
+
import { SessionManager } from "../session-manager.js";
|
|
3
|
+
export interface ExportOptions {
|
|
4
|
+
outputPath?: string;
|
|
5
|
+
themeName?: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Export session to HTML using SessionManager and AgentState.
|
|
9
|
+
* Used by TUI's /export command.
|
|
10
|
+
*/
|
|
11
|
+
export declare function exportSessionToHtml(sm: SessionManager, state?: AgentState, options?: ExportOptions | string): Promise<string>;
|
|
12
|
+
/**
|
|
13
|
+
* Export session file to HTML (standalone, without AgentState).
|
|
14
|
+
* Used by CLI for exporting arbitrary session files.
|
|
15
|
+
*/
|
|
16
|
+
export declare function exportFromFile(inputPath: string, options?: ExportOptions | string): Promise<string>;
|
|
17
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/export-html/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAa,MAAM,6BAA6B,CAAC;AAMzE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,MAAM,WAAW,aAAa;IAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACnB;AAuKD;;;GAGG;AACH,wBAAsB,mBAAmB,CACxC,EAAE,EAAE,cAAc,EAClB,KAAK,CAAC,EAAE,UAAU,EAClB,OAAO,CAAC,EAAE,aAAa,GAAG,MAAM,GAC9B,OAAO,CAAC,MAAM,CAAC,CA8BjB;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA4BzG","sourcesContent":["import type { AgentState, AgentTool } from \"@mariozechner/pi-agent-core\";\nimport { buildCodexPiBridge, getCodexInstructions } from \"@mariozechner/pi-ai\";\nimport { existsSync, readFileSync, writeFileSync } from \"fs\";\nimport { basename, join } from \"path\";\nimport { APP_NAME, getExportTemplateDir } from \"../../config.js\";\nimport { getResolvedThemeColors, getThemeExportColors } from \"../../modes/interactive/theme/theme.js\";\nimport { SessionManager } from \"../session-manager.js\";\n\nexport interface ExportOptions {\n\toutputPath?: string;\n\tthemeName?: string;\n}\n\n/** Info about Codex injection to show inline with model_change entries */\ninterface CodexInjectionInfo {\n\t/** Codex instructions text */\n\tinstructions: string;\n\t/** Bridge text (tool list) */\n\tbridge: string;\n}\n\n/**\n * Build Codex injection info for display inline with model_change entries.\n */\nasync function buildCodexInjectionInfo(tools?: AgentTool[]): Promise<CodexInjectionInfo | undefined> {\n\t// Try to get cached instructions for default model family\n\tlet instructions: string | null = null;\n\ttry {\n\t\tinstructions = getCodexInstructions();\n\t} catch {\n\t\t// Cache miss - that's fine\n\t}\n\n\tconst bridgeText = buildCodexPiBridge(tools);\n\n\tconst instructionsText =\n\t\tinstructions || \"(Codex instructions not cached. Run a Codex request to populate the local cache.)\";\n\n\treturn {\n\t\tinstructions: instructionsText,\n\t\tbridge: bridgeText,\n\t};\n}\n\n/** Parse a color string to RGB values. Supports hex (#RRGGBB) and rgb(r,g,b) formats. */\nfunction parseColor(color: string): { r: number; g: number; b: number } | undefined {\n\tconst hexMatch = color.match(/^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/);\n\tif (hexMatch) {\n\t\treturn {\n\t\t\tr: Number.parseInt(hexMatch[1], 16),\n\t\t\tg: Number.parseInt(hexMatch[2], 16),\n\t\t\tb: Number.parseInt(hexMatch[3], 16),\n\t\t};\n\t}\n\tconst rgbMatch = color.match(/^rgb\\s*\\(\\s*(\\d+)\\s*,\\s*(\\d+)\\s*,\\s*(\\d+)\\s*\\)$/);\n\tif (rgbMatch) {\n\t\treturn {\n\t\t\tr: Number.parseInt(rgbMatch[1], 10),\n\t\t\tg: Number.parseInt(rgbMatch[2], 10),\n\t\t\tb: Number.parseInt(rgbMatch[3], 10),\n\t\t};\n\t}\n\treturn undefined;\n}\n\n/** Calculate relative luminance of a color (0-1, higher = lighter). */\nfunction getLuminance(r: number, g: number, b: number): number {\n\tconst toLinear = (c: number) => {\n\t\tconst s = c / 255;\n\t\treturn s <= 0.03928 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;\n\t};\n\treturn 0.2126 * toLinear(r) + 0.7152 * toLinear(g) + 0.0722 * toLinear(b);\n}\n\n/** Adjust color brightness. Factor > 1 lightens, < 1 darkens. */\nfunction adjustBrightness(color: string, factor: number): string {\n\tconst parsed = parseColor(color);\n\tif (!parsed) return color;\n\tconst adjust = (c: number) => Math.min(255, Math.max(0, Math.round(c * factor)));\n\treturn `rgb(${adjust(parsed.r)}, ${adjust(parsed.g)}, ${adjust(parsed.b)})`;\n}\n\n/** Derive export background colors from a base color (e.g., userMessageBg). */\nfunction deriveExportColors(baseColor: string): { pageBg: string; cardBg: string; infoBg: string } {\n\tconst parsed = parseColor(baseColor);\n\tif (!parsed) {\n\t\treturn {\n\t\t\tpageBg: \"rgb(24, 24, 30)\",\n\t\t\tcardBg: \"rgb(30, 30, 36)\",\n\t\t\tinfoBg: \"rgb(60, 55, 40)\",\n\t\t};\n\t}\n\n\tconst luminance = getLuminance(parsed.r, parsed.g, parsed.b);\n\tconst isLight = luminance > 0.5;\n\n\tif (isLight) {\n\t\treturn {\n\t\t\tpageBg: adjustBrightness(baseColor, 0.96),\n\t\t\tcardBg: baseColor,\n\t\t\tinfoBg: `rgb(${Math.min(255, parsed.r + 10)}, ${Math.min(255, parsed.g + 5)}, ${Math.max(0, parsed.b - 20)})`,\n\t\t};\n\t}\n\treturn {\n\t\tpageBg: adjustBrightness(baseColor, 0.7),\n\t\tcardBg: adjustBrightness(baseColor, 0.85),\n\t\tinfoBg: `rgb(${Math.min(255, parsed.r + 20)}, ${Math.min(255, parsed.g + 15)}, ${parsed.b})`,\n\t};\n}\n\n/**\n * Generate CSS custom property declarations from theme colors.\n */\nfunction generateThemeVars(themeName?: string): string {\n\tconst colors = getResolvedThemeColors(themeName);\n\tconst lines: string[] = [];\n\tfor (const [key, value] of Object.entries(colors)) {\n\t\tlines.push(`--${key}: ${value};`);\n\t}\n\n\t// Use explicit theme export colors if available, otherwise derive from userMessageBg\n\tconst themeExport = getThemeExportColors(themeName);\n\tconst userMessageBg = colors.userMessageBg || \"#343541\";\n\tconst derivedColors = deriveExportColors(userMessageBg);\n\n\tlines.push(`--exportPageBg: ${themeExport.pageBg ?? derivedColors.pageBg};`);\n\tlines.push(`--exportCardBg: ${themeExport.cardBg ?? derivedColors.cardBg};`);\n\tlines.push(`--exportInfoBg: ${themeExport.infoBg ?? derivedColors.infoBg};`);\n\n\treturn lines.join(\"\\n \");\n}\n\ninterface SessionData {\n\theader: ReturnType<SessionManager[\"getHeader\"]>;\n\tentries: ReturnType<SessionManager[\"getEntries\"]>;\n\tleafId: string | null;\n\tsystemPrompt?: string;\n\t/** Info for rendering Codex injection inline with model_change entries */\n\tcodexInjectionInfo?: CodexInjectionInfo;\n\ttools?: { name: string; description: string }[];\n}\n\n/**\n * Core HTML generation logic shared by both export functions.\n */\nfunction generateHtml(sessionData: SessionData, themeName?: string): string {\n\tconst templateDir = getExportTemplateDir();\n\tconst template = readFileSync(join(templateDir, \"template.html\"), \"utf-8\");\n\tconst templateCss = readFileSync(join(templateDir, \"template.css\"), \"utf-8\");\n\tconst templateJs = readFileSync(join(templateDir, \"template.js\"), \"utf-8\");\n\tconst markedJs = readFileSync(join(templateDir, \"vendor\", \"marked.min.js\"), \"utf-8\");\n\tconst hljsJs = readFileSync(join(templateDir, \"vendor\", \"highlight.min.js\"), \"utf-8\");\n\n\tconst themeVars = generateThemeVars(themeName);\n\tconst colors = getResolvedThemeColors(themeName);\n\tconst exportColors = deriveExportColors(colors.userMessageBg || \"#343541\");\n\tconst bodyBg = exportColors.pageBg;\n\tconst containerBg = exportColors.cardBg;\n\tconst infoBg = exportColors.infoBg;\n\n\t// Base64 encode session data to avoid escaping issues\n\tconst sessionDataBase64 = Buffer.from(JSON.stringify(sessionData)).toString(\"base64\");\n\n\t// Build the CSS with theme variables injected\n\tconst css = templateCss\n\t\t.replace(\"{{THEME_VARS}}\", themeVars)\n\t\t.replace(\"{{BODY_BG}}\", bodyBg)\n\t\t.replace(\"{{CONTAINER_BG}}\", containerBg)\n\t\t.replace(\"{{INFO_BG}}\", infoBg);\n\n\treturn template\n\t\t.replace(\"{{CSS}}\", css)\n\t\t.replace(\"{{JS}}\", templateJs)\n\t\t.replace(\"{{SESSION_DATA}}\", sessionDataBase64)\n\t\t.replace(\"{{MARKED_JS}}\", markedJs)\n\t\t.replace(\"{{HIGHLIGHT_JS}}\", hljsJs);\n}\n\n/**\n * Export session to HTML using SessionManager and AgentState.\n * Used by TUI's /export command.\n */\nexport async function exportSessionToHtml(\n\tsm: SessionManager,\n\tstate?: AgentState,\n\toptions?: ExportOptions | string,\n): Promise<string> {\n\tconst opts: ExportOptions = typeof options === \"string\" ? { outputPath: options } : options || {};\n\n\tconst sessionFile = sm.getSessionFile();\n\tif (!sessionFile) {\n\t\tthrow new Error(\"Cannot export in-memory session to HTML\");\n\t}\n\tif (!existsSync(sessionFile)) {\n\t\tthrow new Error(\"Nothing to export yet - start a conversation first\");\n\t}\n\n\tconst sessionData: SessionData = {\n\t\theader: sm.getHeader(),\n\t\tentries: sm.getEntries(),\n\t\tleafId: sm.getLeafId(),\n\t\tsystemPrompt: state?.systemPrompt,\n\t\tcodexInjectionInfo: await buildCodexInjectionInfo(state?.tools),\n\t\ttools: state?.tools?.map((t) => ({ name: t.name, description: t.description })),\n\t};\n\n\tconst html = generateHtml(sessionData, opts.themeName);\n\n\tlet outputPath = opts.outputPath;\n\tif (!outputPath) {\n\t\tconst sessionBasename = basename(sessionFile, \".jsonl\");\n\t\toutputPath = `${APP_NAME}-session-${sessionBasename}.html`;\n\t}\n\n\twriteFileSync(outputPath, html, \"utf8\");\n\treturn outputPath;\n}\n\n/**\n * Export session file to HTML (standalone, without AgentState).\n * Used by CLI for exporting arbitrary session files.\n */\nexport async function exportFromFile(inputPath: string, options?: ExportOptions | string): Promise<string> {\n\tconst opts: ExportOptions = typeof options === \"string\" ? { outputPath: options } : options || {};\n\n\tif (!existsSync(inputPath)) {\n\t\tthrow new Error(`File not found: ${inputPath}`);\n\t}\n\n\tconst sm = SessionManager.open(inputPath);\n\n\tconst sessionData: SessionData = {\n\t\theader: sm.getHeader(),\n\t\tentries: sm.getEntries(),\n\t\tleafId: sm.getLeafId(),\n\t\tsystemPrompt: undefined,\n\t\tcodexInjectionInfo: await buildCodexInjectionInfo(undefined),\n\t\ttools: undefined,\n\t};\n\n\tconst html = generateHtml(sessionData, opts.themeName);\n\n\tlet outputPath = opts.outputPath;\n\tif (!outputPath) {\n\t\tconst inputBasename = basename(inputPath, \".jsonl\");\n\t\toutputPath = `${APP_NAME}-session-${inputBasename}.html`;\n\t}\n\n\twriteFileSync(outputPath, html, \"utf8\");\n\treturn outputPath;\n}\n"]}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { buildCodexPiBridge, getCodexInstructions } from "@mariozechner/pi-ai";
|
|
2
|
+
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
3
|
+
import { basename, join } from "path";
|
|
4
|
+
import { APP_NAME, getExportTemplateDir } from "../../config.js";
|
|
5
|
+
import { getResolvedThemeColors, getThemeExportColors } from "../../modes/interactive/theme/theme.js";
|
|
6
|
+
import { SessionManager } from "../session-manager.js";
|
|
7
|
+
/**
|
|
8
|
+
* Build Codex injection info for display inline with model_change entries.
|
|
9
|
+
*/
|
|
10
|
+
async function buildCodexInjectionInfo(tools) {
|
|
11
|
+
// Try to get cached instructions for default model family
|
|
12
|
+
let instructions = null;
|
|
13
|
+
try {
|
|
14
|
+
instructions = getCodexInstructions();
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
// Cache miss - that's fine
|
|
18
|
+
}
|
|
19
|
+
const bridgeText = buildCodexPiBridge(tools);
|
|
20
|
+
const instructionsText = instructions || "(Codex instructions not cached. Run a Codex request to populate the local cache.)";
|
|
21
|
+
return {
|
|
22
|
+
instructions: instructionsText,
|
|
23
|
+
bridge: bridgeText,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
/** Parse a color string to RGB values. Supports hex (#RRGGBB) and rgb(r,g,b) formats. */
|
|
27
|
+
function parseColor(color) {
|
|
28
|
+
const hexMatch = color.match(/^#([0-9a-fA-F]{2})([0-9a-fA-F]{2})([0-9a-fA-F]{2})$/);
|
|
29
|
+
if (hexMatch) {
|
|
30
|
+
return {
|
|
31
|
+
r: Number.parseInt(hexMatch[1], 16),
|
|
32
|
+
g: Number.parseInt(hexMatch[2], 16),
|
|
33
|
+
b: Number.parseInt(hexMatch[3], 16),
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
const rgbMatch = color.match(/^rgb\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)$/);
|
|
37
|
+
if (rgbMatch) {
|
|
38
|
+
return {
|
|
39
|
+
r: Number.parseInt(rgbMatch[1], 10),
|
|
40
|
+
g: Number.parseInt(rgbMatch[2], 10),
|
|
41
|
+
b: Number.parseInt(rgbMatch[3], 10),
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
return undefined;
|
|
45
|
+
}
|
|
46
|
+
/** Calculate relative luminance of a color (0-1, higher = lighter). */
|
|
47
|
+
function getLuminance(r, g, b) {
|
|
48
|
+
const toLinear = (c) => {
|
|
49
|
+
const s = c / 255;
|
|
50
|
+
return s <= 0.03928 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;
|
|
51
|
+
};
|
|
52
|
+
return 0.2126 * toLinear(r) + 0.7152 * toLinear(g) + 0.0722 * toLinear(b);
|
|
53
|
+
}
|
|
54
|
+
/** Adjust color brightness. Factor > 1 lightens, < 1 darkens. */
|
|
55
|
+
function adjustBrightness(color, factor) {
|
|
56
|
+
const parsed = parseColor(color);
|
|
57
|
+
if (!parsed)
|
|
58
|
+
return color;
|
|
59
|
+
const adjust = (c) => Math.min(255, Math.max(0, Math.round(c * factor)));
|
|
60
|
+
return `rgb(${adjust(parsed.r)}, ${adjust(parsed.g)}, ${adjust(parsed.b)})`;
|
|
61
|
+
}
|
|
62
|
+
/** Derive export background colors from a base color (e.g., userMessageBg). */
|
|
63
|
+
function deriveExportColors(baseColor) {
|
|
64
|
+
const parsed = parseColor(baseColor);
|
|
65
|
+
if (!parsed) {
|
|
66
|
+
return {
|
|
67
|
+
pageBg: "rgb(24, 24, 30)",
|
|
68
|
+
cardBg: "rgb(30, 30, 36)",
|
|
69
|
+
infoBg: "rgb(60, 55, 40)",
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
const luminance = getLuminance(parsed.r, parsed.g, parsed.b);
|
|
73
|
+
const isLight = luminance > 0.5;
|
|
74
|
+
if (isLight) {
|
|
75
|
+
return {
|
|
76
|
+
pageBg: adjustBrightness(baseColor, 0.96),
|
|
77
|
+
cardBg: baseColor,
|
|
78
|
+
infoBg: `rgb(${Math.min(255, parsed.r + 10)}, ${Math.min(255, parsed.g + 5)}, ${Math.max(0, parsed.b - 20)})`,
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
pageBg: adjustBrightness(baseColor, 0.7),
|
|
83
|
+
cardBg: adjustBrightness(baseColor, 0.85),
|
|
84
|
+
infoBg: `rgb(${Math.min(255, parsed.r + 20)}, ${Math.min(255, parsed.g + 15)}, ${parsed.b})`,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Generate CSS custom property declarations from theme colors.
|
|
89
|
+
*/
|
|
90
|
+
function generateThemeVars(themeName) {
|
|
91
|
+
const colors = getResolvedThemeColors(themeName);
|
|
92
|
+
const lines = [];
|
|
93
|
+
for (const [key, value] of Object.entries(colors)) {
|
|
94
|
+
lines.push(`--${key}: ${value};`);
|
|
95
|
+
}
|
|
96
|
+
// Use explicit theme export colors if available, otherwise derive from userMessageBg
|
|
97
|
+
const themeExport = getThemeExportColors(themeName);
|
|
98
|
+
const userMessageBg = colors.userMessageBg || "#343541";
|
|
99
|
+
const derivedColors = deriveExportColors(userMessageBg);
|
|
100
|
+
lines.push(`--exportPageBg: ${themeExport.pageBg ?? derivedColors.pageBg};`);
|
|
101
|
+
lines.push(`--exportCardBg: ${themeExport.cardBg ?? derivedColors.cardBg};`);
|
|
102
|
+
lines.push(`--exportInfoBg: ${themeExport.infoBg ?? derivedColors.infoBg};`);
|
|
103
|
+
return lines.join("\n ");
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Core HTML generation logic shared by both export functions.
|
|
107
|
+
*/
|
|
108
|
+
function generateHtml(sessionData, themeName) {
|
|
109
|
+
const templateDir = getExportTemplateDir();
|
|
110
|
+
const template = readFileSync(join(templateDir, "template.html"), "utf-8");
|
|
111
|
+
const templateCss = readFileSync(join(templateDir, "template.css"), "utf-8");
|
|
112
|
+
const templateJs = readFileSync(join(templateDir, "template.js"), "utf-8");
|
|
113
|
+
const markedJs = readFileSync(join(templateDir, "vendor", "marked.min.js"), "utf-8");
|
|
114
|
+
const hljsJs = readFileSync(join(templateDir, "vendor", "highlight.min.js"), "utf-8");
|
|
115
|
+
const themeVars = generateThemeVars(themeName);
|
|
116
|
+
const colors = getResolvedThemeColors(themeName);
|
|
117
|
+
const exportColors = deriveExportColors(colors.userMessageBg || "#343541");
|
|
118
|
+
const bodyBg = exportColors.pageBg;
|
|
119
|
+
const containerBg = exportColors.cardBg;
|
|
120
|
+
const infoBg = exportColors.infoBg;
|
|
121
|
+
// Base64 encode session data to avoid escaping issues
|
|
122
|
+
const sessionDataBase64 = Buffer.from(JSON.stringify(sessionData)).toString("base64");
|
|
123
|
+
// Build the CSS with theme variables injected
|
|
124
|
+
const css = templateCss
|
|
125
|
+
.replace("{{THEME_VARS}}", themeVars)
|
|
126
|
+
.replace("{{BODY_BG}}", bodyBg)
|
|
127
|
+
.replace("{{CONTAINER_BG}}", containerBg)
|
|
128
|
+
.replace("{{INFO_BG}}", infoBg);
|
|
129
|
+
return template
|
|
130
|
+
.replace("{{CSS}}", css)
|
|
131
|
+
.replace("{{JS}}", templateJs)
|
|
132
|
+
.replace("{{SESSION_DATA}}", sessionDataBase64)
|
|
133
|
+
.replace("{{MARKED_JS}}", markedJs)
|
|
134
|
+
.replace("{{HIGHLIGHT_JS}}", hljsJs);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Export session to HTML using SessionManager and AgentState.
|
|
138
|
+
* Used by TUI's /export command.
|
|
139
|
+
*/
|
|
140
|
+
export async function exportSessionToHtml(sm, state, options) {
|
|
141
|
+
const opts = typeof options === "string" ? { outputPath: options } : options || {};
|
|
142
|
+
const sessionFile = sm.getSessionFile();
|
|
143
|
+
if (!sessionFile) {
|
|
144
|
+
throw new Error("Cannot export in-memory session to HTML");
|
|
145
|
+
}
|
|
146
|
+
if (!existsSync(sessionFile)) {
|
|
147
|
+
throw new Error("Nothing to export yet - start a conversation first");
|
|
148
|
+
}
|
|
149
|
+
const sessionData = {
|
|
150
|
+
header: sm.getHeader(),
|
|
151
|
+
entries: sm.getEntries(),
|
|
152
|
+
leafId: sm.getLeafId(),
|
|
153
|
+
systemPrompt: state?.systemPrompt,
|
|
154
|
+
codexInjectionInfo: await buildCodexInjectionInfo(state?.tools),
|
|
155
|
+
tools: state?.tools?.map((t) => ({ name: t.name, description: t.description })),
|
|
156
|
+
};
|
|
157
|
+
const html = generateHtml(sessionData, opts.themeName);
|
|
158
|
+
let outputPath = opts.outputPath;
|
|
159
|
+
if (!outputPath) {
|
|
160
|
+
const sessionBasename = basename(sessionFile, ".jsonl");
|
|
161
|
+
outputPath = `${APP_NAME}-session-${sessionBasename}.html`;
|
|
162
|
+
}
|
|
163
|
+
writeFileSync(outputPath, html, "utf8");
|
|
164
|
+
return outputPath;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Export session file to HTML (standalone, without AgentState).
|
|
168
|
+
* Used by CLI for exporting arbitrary session files.
|
|
169
|
+
*/
|
|
170
|
+
export async function exportFromFile(inputPath, options) {
|
|
171
|
+
const opts = typeof options === "string" ? { outputPath: options } : options || {};
|
|
172
|
+
if (!existsSync(inputPath)) {
|
|
173
|
+
throw new Error(`File not found: ${inputPath}`);
|
|
174
|
+
}
|
|
175
|
+
const sm = SessionManager.open(inputPath);
|
|
176
|
+
const sessionData = {
|
|
177
|
+
header: sm.getHeader(),
|
|
178
|
+
entries: sm.getEntries(),
|
|
179
|
+
leafId: sm.getLeafId(),
|
|
180
|
+
systemPrompt: undefined,
|
|
181
|
+
codexInjectionInfo: await buildCodexInjectionInfo(undefined),
|
|
182
|
+
tools: undefined,
|
|
183
|
+
};
|
|
184
|
+
const html = generateHtml(sessionData, opts.themeName);
|
|
185
|
+
let outputPath = opts.outputPath;
|
|
186
|
+
if (!outputPath) {
|
|
187
|
+
const inputBasename = basename(inputPath, ".jsonl");
|
|
188
|
+
outputPath = `${APP_NAME}-session-${inputBasename}.html`;
|
|
189
|
+
}
|
|
190
|
+
writeFileSync(outputPath, html, "utf8");
|
|
191
|
+
return outputPath;
|
|
192
|
+
}
|
|
193
|
+
//# sourceMappingURL=index.js.map
|