apex-code 0.0.1-alpha.7 → 0.0.1-alpha.9
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 +229 -0
- package/README.md +5 -0
- package/dist/cli/args.d.ts +4 -1
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +44 -9
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/concurrent-session.d.ts +3 -0
- package/dist/cli/concurrent-session.d.ts.map +1 -0
- package/dist/cli/concurrent-session.js +13 -0
- package/dist/cli/concurrent-session.js.map +1 -0
- package/dist/cli/file-processor.d.ts.map +1 -1
- package/dist/cli/file-processor.js +2 -1
- package/dist/cli/file-processor.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +1 -2
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts +3 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +21 -13
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session-services.d.ts.map +1 -1
- package/dist/core/agent-session-services.js +20 -0
- package/dist/core/agent-session-services.js.map +1 -1
- package/dist/core/agent-session.d.ts +41 -9
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +172 -101
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-storage.d.ts +4 -1
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +12 -9
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js +10 -9
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js +3 -0
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts +4 -3
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +41 -32
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/defaults.d.ts +1 -0
- package/dist/core/defaults.d.ts.map +1 -1
- package/dist/core/defaults.js +9 -0
- package/dist/core/defaults.js.map +1 -1
- package/dist/core/durable-state/sqlite.d.ts.map +1 -1
- package/dist/core/durable-state/sqlite.js +26 -2
- package/dist/core/durable-state/sqlite.js.map +1 -1
- package/dist/core/experimental.d.ts +4 -0
- package/dist/core/experimental.d.ts.map +1 -1
- package/dist/core/experimental.js +4 -0
- package/dist/core/experimental.js.map +1 -1
- package/dist/core/extensions/index.d.ts +2 -2
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/loader.d.ts.map +1 -1
- package/dist/core/extensions/loader.js +115 -48
- package/dist/core/extensions/loader.js.map +1 -1
- package/dist/core/extensions/types.d.ts +42 -9
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js +3 -0
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/footer-data-provider.d.ts +1 -1
- package/dist/core/footer-data-provider.d.ts.map +1 -1
- package/dist/core/footer-data-provider.js +1 -1
- package/dist/core/footer-data-provider.js.map +1 -1
- package/dist/core/http-dispatcher.d.ts +1 -2
- package/dist/core/http-dispatcher.d.ts.map +1 -1
- package/dist/core/http-dispatcher.js +2 -17
- package/dist/core/http-dispatcher.js.map +1 -1
- package/dist/core/http-idle-timeout.d.ts +12 -0
- package/dist/core/http-idle-timeout.d.ts.map +1 -0
- package/dist/core/http-idle-timeout.js +27 -0
- package/dist/core/http-idle-timeout.js.map +1 -0
- package/dist/core/keybindings.d.ts +38 -13
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +26 -5
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/lsp/client.d.ts +2 -0
- package/dist/core/lsp/client.d.ts.map +1 -1
- package/dist/core/lsp/client.js +27 -2
- package/dist/core/lsp/client.js.map +1 -1
- package/dist/core/model-config.d.ts +10 -0
- package/dist/core/model-config.d.ts.map +1 -1
- package/dist/core/model-config.js +4 -1
- package/dist/core/model-config.js.map +1 -1
- package/dist/core/model-resolver.d.ts +1 -0
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +14 -8
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/models-store.d.ts.map +1 -1
- package/dist/core/models-store.js +2 -1
- package/dist/core/models-store.js.map +1 -1
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +22 -14
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/pi-manifest.d.ts.map +1 -1
- package/dist/core/pi-manifest.js +2 -1
- package/dist/core/pi-manifest.js.map +1 -1
- package/dist/core/remote-catalog-provider.d.ts.map +1 -1
- package/dist/core/remote-catalog-provider.js +2 -1
- package/dist/core/remote-catalog-provider.js.map +1 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +3 -2
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/sandbox/child-entry.d.ts.map +1 -1
- package/dist/core/sandbox/child-entry.js +8 -1
- package/dist/core/sandbox/child-entry.js.map +1 -1
- package/dist/core/sandbox/cli-launch.d.ts +3 -0
- package/dist/core/sandbox/cli-launch.d.ts.map +1 -1
- package/dist/core/sandbox/cli-launch.js +25 -4
- package/dist/core/sandbox/cli-launch.js.map +1 -1
- package/dist/core/sandbox/cli-supervisor.d.ts.map +1 -1
- package/dist/core/sandbox/cli-supervisor.js +53 -13
- package/dist/core/sandbox/cli-supervisor.js.map +1 -1
- package/dist/core/sandbox/linux-backend.d.ts.map +1 -1
- package/dist/core/sandbox/linux-backend.js +15 -0
- package/dist/core/sandbox/linux-backend.js.map +1 -1
- package/dist/core/sandbox/macos-backend.d.ts.map +1 -1
- package/dist/core/sandbox/macos-backend.js +24 -1
- package/dist/core/sandbox/macos-backend.js.map +1 -1
- package/dist/core/sandbox/rpc/credential-client.d.ts +20 -0
- package/dist/core/sandbox/rpc/credential-client.d.ts.map +1 -0
- package/dist/core/sandbox/rpc/credential-client.js +170 -0
- package/dist/core/sandbox/rpc/credential-client.js.map +1 -0
- package/dist/core/sandbox/rpc/credential-proxy.d.ts +44 -0
- package/dist/core/sandbox/rpc/credential-proxy.d.ts.map +1 -0
- package/dist/core/sandbox/rpc/credential-proxy.js +381 -0
- package/dist/core/sandbox/rpc/credential-proxy.js.map +1 -0
- package/dist/core/sandbox/supervisor.d.ts +11 -0
- package/dist/core/sandbox/supervisor.d.ts.map +1 -1
- package/dist/core/sandbox/supervisor.js.map +1 -1
- package/dist/core/sandbox/terminal-size.d.ts +40 -0
- package/dist/core/sandbox/terminal-size.d.ts.map +1 -0
- package/dist/core/sandbox/terminal-size.js +105 -0
- package/dist/core/sandbox/terminal-size.js.map +1 -0
- package/dist/core/sdk.d.ts +8 -5
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +26 -7
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-export.d.ts +4 -0
- package/dist/core/session-export.d.ts.map +1 -0
- package/dist/core/session-export.js +32 -0
- package/dist/core/session-export.js.map +1 -0
- package/dist/core/session-lease.d.ts +31 -0
- package/dist/core/session-lease.d.ts.map +1 -0
- package/dist/core/session-lease.js +138 -0
- package/dist/core/session-lease.js.map +1 -0
- package/dist/core/session-manager.d.ts +5 -0
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +5 -4
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-diagnostics.d.ts +9 -0
- package/dist/core/settings-diagnostics.d.ts.map +1 -0
- package/dist/core/settings-diagnostics.js +21 -0
- package/dist/core/settings-diagnostics.js.map +1 -0
- package/dist/core/settings-manager.d.ts +35 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +93 -12
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +51 -33
- package/dist/core/skills.js.map +1 -1
- package/dist/core/slash-commands.d.ts.map +1 -1
- package/dist/core/slash-commands.js +4 -1
- package/dist/core/slash-commands.js.map +1 -1
- package/dist/core/system-prompt.d.ts +2 -2
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +53 -62
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/bash.d.ts +14 -1
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +38 -20
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/delegate.d.ts.map +1 -1
- package/dist/core/tools/delegate.js +24 -0
- package/dist/core/tools/delegate.js.map +1 -1
- package/dist/core/tools/edit-diff.d.ts +0 -5
- package/dist/core/tools/edit-diff.d.ts.map +1 -1
- package/dist/core/tools/edit-diff.js +2 -5
- package/dist/core/tools/edit-diff.js.map +1 -1
- package/dist/core/tools/edit.d.ts.map +1 -1
- package/dist/core/tools/edit.js +22 -4
- package/dist/core/tools/edit.js.map +1 -1
- package/dist/core/tools/find.d.ts.map +1 -1
- package/dist/core/tools/find.js +1 -1
- package/dist/core/tools/find.js.map +1 -1
- package/dist/core/tools/grep.d.ts +2 -0
- package/dist/core/tools/grep.d.ts.map +1 -1
- package/dist/core/tools/grep.js +35 -10
- package/dist/core/tools/grep.js.map +1 -1
- package/dist/core/tools/index.d.ts +4 -1
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +9 -0
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/tools/ls.d.ts +2 -0
- package/dist/core/tools/ls.d.ts.map +1 -1
- package/dist/core/tools/ls.js +5 -1
- package/dist/core/tools/ls.js.map +1 -1
- package/dist/core/tools/powershell.d.ts +16 -0
- package/dist/core/tools/powershell.d.ts.map +1 -0
- package/dist/core/tools/powershell.js +39 -0
- package/dist/core/tools/powershell.js.map +1 -0
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +2 -0
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/tools/web-search-exa.d.ts +33 -0
- package/dist/core/tools/web-search-exa.d.ts.map +1 -0
- package/dist/core/tools/web-search-exa.js +128 -0
- package/dist/core/tools/web-search-exa.js.map +1 -0
- package/dist/core/tools/write.d.ts.map +1 -1
- package/dist/core/tools/write.js +2 -0
- package/dist/core/tools/write.js.map +1 -1
- package/dist/core/trust-manager.d.ts.map +1 -1
- package/dist/core/trust-manager.js +2 -1
- package/dist/core/trust-manager.js.map +1 -1
- package/dist/core/web-search-provider.d.ts +64 -0
- package/dist/core/web-search-provider.d.ts.map +1 -0
- package/dist/core/web-search-provider.js +149 -0
- package/dist/core/web-search-provider.js.map +1 -0
- package/dist/extensions/llama/index.d.ts.map +1 -1
- package/dist/extensions/llama/index.js +2 -0
- package/dist/extensions/llama/index.js.map +1 -1
- package/dist/extensions/llama/provider.d.ts.map +1 -1
- package/dist/extensions/llama/provider.js +6 -2
- package/dist/extensions/llama/provider.js.map +1 -1
- package/dist/index.d.ts +6 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts +5 -0
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +38 -16
- package/dist/main.js.map +1 -1
- package/dist/migrations.d.ts.map +1 -1
- package/dist/migrations.js +4 -3
- package/dist/migrations.js.map +1 -1
- package/dist/modes/interactive/components/custom-editor.d.ts +23 -0
- package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-editor.js +105 -2
- package/dist/modes/interactive/components/custom-editor.js.map +1 -1
- package/dist/modes/interactive/components/dynamic-border.d.ts +7 -1
- package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
- package/dist/modes/interactive/components/dynamic-border.js +11 -2
- package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
- package/dist/modes/interactive/components/extension-selector.d.ts +4 -0
- package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/extension-selector.js +24 -6
- package/dist/modes/interactive/components/extension-selector.js.map +1 -1
- package/dist/modes/interactive/components/first-time-setup.d.ts.map +1 -1
- package/dist/modes/interactive/components/first-time-setup.js +6 -3
- package/dist/modes/interactive/components/first-time-setup.js.map +1 -1
- package/dist/modes/interactive/components/first-use-hints.d.ts +8 -0
- package/dist/modes/interactive/components/first-use-hints.d.ts.map +1 -0
- package/dist/modes/interactive/components/first-use-hints.js +22 -0
- package/dist/modes/interactive/components/first-use-hints.js.map +1 -0
- package/dist/modes/interactive/components/footer.d.ts +12 -0
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +128 -9
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/index.d.ts +1 -0
- package/dist/modes/interactive/components/index.d.ts.map +1 -1
- package/dist/modes/interactive/components/index.js +1 -0
- package/dist/modes/interactive/components/index.js.map +1 -1
- package/dist/modes/interactive/components/model-selector.d.ts +12 -3
- package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/model-selector.js +71 -14
- package/dist/modes/interactive/components/model-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts +10 -3
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +128 -56
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/settings-submenu.d.ts +72 -0
- package/dist/modes/interactive/components/settings-submenu.d.ts.map +1 -0
- package/dist/modes/interactive/components/settings-submenu.js +165 -0
- package/dist/modes/interactive/components/settings-submenu.js.map +1 -0
- package/dist/modes/interactive/components/splash-header.d.ts +29 -4
- package/dist/modes/interactive/components/splash-header.d.ts.map +1 -1
- package/dist/modes/interactive/components/splash-header.js +58 -23
- package/dist/modes/interactive/components/splash-header.js.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.d.ts +15 -3
- package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/thinking-selector.js +74 -17
- package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts +14 -0
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +113 -35
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/components/tool-panel.d.ts +30 -0
- package/dist/modes/interactive/components/tool-panel.d.ts.map +1 -0
- package/dist/modes/interactive/components/tool-panel.js +130 -0
- package/dist/modes/interactive/components/tool-panel.js.map +1 -0
- package/dist/modes/interactive/external-editor.d.ts.map +1 -1
- package/dist/modes/interactive/external-editor.js +2 -1
- package/dist/modes/interactive/external-editor.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +55 -9
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +446 -87
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/model-catalog-refresh.d.ts +7 -0
- package/dist/modes/interactive/model-catalog-refresh.d.ts.map +1 -0
- package/dist/modes/interactive/model-catalog-refresh.js +34 -0
- package/dist/modes/interactive/model-catalog-refresh.js.map +1 -0
- package/dist/modes/interactive/theme/apex.json +62 -63
- package/dist/modes/interactive/theme/dark.json +2 -0
- package/dist/modes/interactive/theme/light.json +2 -0
- package/dist/modes/interactive/theme/theme-controller.d.ts +10 -2
- package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme-controller.js +25 -11
- package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
- package/dist/modes/interactive/theme/theme-schema.json +9 -1
- package/dist/modes/interactive/theme/theme.d.ts +14 -3
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +60 -10
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/json-event.d.ts +18 -12
- package/dist/modes/json-event.d.ts.map +1 -1
- package/dist/modes/json-event.js +22 -5
- package/dist/modes/json-event.js.map +1 -1
- package/dist/package-manager-cli.d.ts +1 -0
- package/dist/package-manager-cli.d.ts.map +1 -1
- package/dist/package-manager-cli.js +197 -5
- package/dist/package-manager-cli.js.map +1 -1
- package/dist/server/create-harness.d.ts.map +1 -1
- package/dist/server/create-harness.js +2 -0
- package/dist/server/create-harness.js.map +1 -1
- package/dist/themes/apex-logo.d.ts +36 -16
- package/dist/themes/apex-logo.d.ts.map +1 -1
- package/dist/themes/apex-logo.js +32 -28
- package/dist/themes/apex-logo.js.map +1 -1
- package/dist/utils/frontmatter.d.ts.map +1 -1
- package/dist/utils/frontmatter.js +2 -1
- package/dist/utils/frontmatter.js.map +1 -1
- package/dist/utils/management-http.d.ts +5 -3
- package/dist/utils/management-http.d.ts.map +1 -1
- package/dist/utils/management-http.js +14 -10
- package/dist/utils/management-http.js.map +1 -1
- package/dist/utils/shell.d.ts +3 -0
- package/dist/utils/shell.d.ts.map +1 -1
- package/dist/utils/shell.js +17 -5
- package/dist/utils/shell.js.map +1 -1
- package/dist/utils/syntax-highlight.d.ts +1 -0
- package/dist/utils/syntax-highlight.d.ts.map +1 -1
- package/dist/utils/syntax-highlight.js +60 -1
- package/dist/utils/syntax-highlight.js.map +1 -1
- package/dist/utils/text.d.ts +8 -0
- package/dist/utils/text.d.ts.map +1 -0
- package/dist/utils/text.js +9 -0
- package/dist/utils/text.js.map +1 -0
- package/dist/utils/tools-manager.d.ts +10 -1
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +15 -20
- package/dist/utils/tools-manager.js.map +1 -1
- package/docs/compaction.md +18 -3
- package/docs/custom-provider.md +6 -3
- package/docs/environment-variables.md +1 -0
- package/docs/extensions.md +21 -7
- package/docs/json.md +12 -5
- package/docs/keybindings.md +15 -9
- package/docs/llama-cpp.md +2 -0
- package/docs/models.md +8 -2
- package/docs/packages.md +2 -2
- package/docs/rpc.md +24 -7
- package/docs/sdk.md +16 -2
- package/docs/settings.md +73 -2
- package/docs/skills.md +4 -3
- package/docs/terminal-setup.md +34 -9
- package/docs/themes.md +24 -3
- package/docs/tui.md +2 -2
- package/docs/usage.md +9 -4
- package/docs/windows.md +24 -2
- package/examples/extensions/border-status-editor.ts +1 -1
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/git-checkpoint.ts +2 -2
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/notify.ts +3 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/subagent/README.md +3 -1
- package/examples/extensions/subagent/agents.ts +40 -9
- package/examples/extensions/subagent/index.ts +27 -4
- package/examples/extensions/titlebar-spinner.ts +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/examples/rpc-extension-ui.ts +1 -1
- package/examples/sdk/06-extensions.ts +1 -1
- package/examples/sdk/README.md +1 -1
- package/npm-shrinkwrap.json +280 -445
- package/package.json +9 -11
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type Component } from "@earendil-works/pi-tui";
|
|
2
|
+
export type ToolLifecycle = "queued" | "running" | "done" | "error";
|
|
3
|
+
export type ToolSymbolPreset = "unicode" | "ascii";
|
|
4
|
+
export declare function formatToolDuration(durationMs: number): string;
|
|
5
|
+
export interface ToolStatusLineOptions {
|
|
6
|
+
lifecycle: ToolLifecycle;
|
|
7
|
+
symbolPreset: ToolSymbolPreset;
|
|
8
|
+
durationMs?: number;
|
|
9
|
+
}
|
|
10
|
+
/** Prime-style flat shell for renderer-based tool calls. */
|
|
11
|
+
export declare class ToolPanelComponent implements Component {
|
|
12
|
+
private readonly child;
|
|
13
|
+
private readonly options;
|
|
14
|
+
constructor(child: Component, options: ToolStatusLineOptions);
|
|
15
|
+
render(width: number): string[];
|
|
16
|
+
invalidate(): void;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Prefixes an existing public tool renderer with Apex-owned lifecycle text.
|
|
20
|
+
* The wrapped renderer receives the remaining width, so its own wrapping and
|
|
21
|
+
* cursor-free layout stay intact without a pi-tui hook.
|
|
22
|
+
*/
|
|
23
|
+
export declare class ToolStatusLineComponent implements Component {
|
|
24
|
+
private readonly child;
|
|
25
|
+
private readonly options;
|
|
26
|
+
constructor(child: Component, options: ToolStatusLineOptions);
|
|
27
|
+
render(width: number): string[];
|
|
28
|
+
invalidate(): void;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=tool-panel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-panel.d.ts","sourceRoot":"","sources":["../../../../src/modes/interactive/components/tool-panel.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAiC,MAAM,wBAAwB,CAAC;AAGvF,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC;AACpE,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,OAAO,CAAC;AAoCnD,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,MAAM,GAAG,MAAM,CAI7D;AAED,MAAM,WAAW,qBAAqB;IACrC,SAAS,EAAE,aAAa,CAAC;IACzB,YAAY,EAAE,gBAAgB,CAAC;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;CACpB;AAQD,4DAA4D;AAC5D,qBAAa,kBAAmB,YAAW,SAAS;IACnD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAY;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAwB;IAEhD,YAAY,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,qBAAqB,EAG3D;IAED,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAqC9B;IAED,UAAU,IAAI,IAAI,CAEjB;CACD;AAED;;;;GAIG;AACH,qBAAa,uBAAwB,YAAW,SAAS;IACxD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAY;IAClC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAwB;IAEhD,YAAY,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,qBAAqB,EAG3D;IAED,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAmB9B;IAED,UAAU,IAAI,IAAI,CAEjB;CACD","sourcesContent":["import { type Component, truncateToWidth, visibleWidth } from \"@earendil-works/pi-tui\";\nimport { paintBackground, theme } from \"../theme/theme.ts\";\n\nexport type ToolLifecycle = \"queued\" | \"running\" | \"done\" | \"error\";\nexport type ToolSymbolPreset = \"unicode\" | \"ascii\";\n\nconst LIFECYCLE_SYMBOLS: Record<ToolSymbolPreset, Record<ToolLifecycle, string>> = {\n\tunicode: { queued: \"○\", running: \"◌\", done: \"✓\", error: \"✗\" },\n\tascii: { queued: \"[ ]\", running: \"[~]\", done: \"[x]\", error: \"[!]\" },\n};\n\n/**\n * Running takes the brand accent rather than `warning`. Work in progress is\n * not a caution; amber is reserved for states the user may need to act on.\n */\nfunction lifecycleColor(lifecycle: ToolLifecycle): \"dim\" | \"accent\" | \"success\" | \"error\" {\n\tswitch (lifecycle) {\n\t\tcase \"queued\":\n\t\t\treturn \"dim\";\n\t\tcase \"running\":\n\t\t\treturn \"accent\";\n\t\tcase \"done\":\n\t\t\treturn \"success\";\n\t\tcase \"error\":\n\t\t\treturn \"error\";\n\t}\n}\n\n/**\n * The status spine drawn down the left edge of a tool panel.\n *\n * It is a redundant channel over the lifecycle word in the header, so it is\n * free to lean on colour. The glyph still distinguishes work that has not\n * started from work that has, which is the distinction a glance most needs.\n */\nconst SPINE_GLYPHS: Record<ToolSymbolPreset, Record<ToolLifecycle, string>> = {\n\tunicode: { queued: \"┆\", running: \"▌\", done: \"▌\", error: \"▌\" },\n\tascii: { queued: \":\", running: \"|\", done: \"|\", error: \"|\" },\n};\n\nexport function formatToolDuration(durationMs: number): string {\n\tif (durationMs < 1000) return `${Math.max(0, Math.round(durationMs))}ms`;\n\tif (durationMs < 10_000) return `${(durationMs / 1000).toFixed(1)}s`;\n\treturn `${Math.round(durationMs / 1000)}s`;\n}\n\nexport interface ToolStatusLineOptions {\n\tlifecycle: ToolLifecycle;\n\tsymbolPreset: ToolSymbolPreset;\n\tdurationMs?: number;\n}\n\nfunction lifecycleBackground(lifecycle: ToolLifecycle): \"toolPendingBg\" | \"toolSuccessBg\" | \"toolErrorBg\" {\n\tif (lifecycle === \"done\") return \"toolSuccessBg\";\n\tif (lifecycle === \"error\") return \"toolErrorBg\";\n\treturn \"toolPendingBg\";\n}\n\n/** Prime-style flat shell for renderer-based tool calls. */\nexport class ToolPanelComponent implements Component {\n\tprivate readonly child: Component;\n\tprivate readonly options: ToolStatusLineOptions;\n\n\tconstructor(child: Component, options: ToolStatusLineOptions) {\n\t\tthis.child = child;\n\t\tthis.options = options;\n\t}\n\n\trender(width: number): string[] {\n\t\tif (width <= 0) return [];\n\t\tconst padding = Math.min(2, Math.floor((width - 1) / 2));\n\t\tconst innerWidth = Math.max(1, width - padding * 2);\n\t\tconst childLines = this.child.render(innerWidth);\n\t\tif (childLines.length === 0) return [];\n\n\t\tconst { lifecycle, symbolPreset, durationMs } = this.options;\n\t\tconst duration = durationMs === undefined ? \"\" : ` ${formatToolDuration(durationMs)}`;\n\t\tconst state = theme.fg(\n\t\t\tlifecycleColor(lifecycle),\n\t\t\t`${LIFECYCLE_SYMBOLS[symbolPreset][lifecycle]} ${lifecycle}${duration}`,\n\t\t);\n\t\tconst separator = theme.fg(\"dim\", symbolPreset === \"ascii\" ? \" - \" : \" · \");\n\t\tconst stateWidth = visibleWidth(separator) + visibleWidth(state);\n\t\tconst label = childLines[0].replace(/\\s+$/, \"\");\n\t\tconst header =\n\t\t\tstateWidth < innerWidth\n\t\t\t\t? `${truncateToWidth(label, innerWidth - stateWidth, \"\")}${separator}${state}`\n\t\t\t\t: truncateToWidth(state, innerWidth, \"\");\n\t\tconst panelLines = [header];\n\t\tif (childLines.length > 1) panelLines.push(\"\", ...childLines.slice(1));\n\n\t\tconst background = lifecycleBackground(lifecycle);\n\t\t// The spine occupies the first column of the existing left padding, so it\n\t\t// marks state without costing the panel a column of content. Below two\n\t\t// columns of padding there is no room for it and it is dropped.\n\t\tconst showSpine = padding >= 1;\n\t\tconst spine = showSpine\n\t\t\t? paintBackground(theme.fg(lifecycleColor(lifecycle), SPINE_GLYPHS[symbolPreset][lifecycle]), background)\n\t\t\t: \"\";\n\t\tconst leftPadding = \" \".repeat(Math.max(0, padding - (showSpine ? 1 : 0)));\n\t\treturn panelLines.map((line) => {\n\t\t\tconst clipped = truncateToWidth(line, innerWidth, \"\");\n\t\t\tconst rightPadding = \" \".repeat(Math.max(0, innerWidth - visibleWidth(clipped)));\n\t\t\treturn spine + paintBackground(`${leftPadding}${clipped}${rightPadding}${\" \".repeat(padding)}`, background);\n\t\t});\n\t}\n\n\tinvalidate(): void {\n\t\tthis.child.invalidate?.();\n\t}\n}\n\n/**\n * Prefixes an existing public tool renderer with Apex-owned lifecycle text.\n * The wrapped renderer receives the remaining width, so its own wrapping and\n * cursor-free layout stay intact without a pi-tui hook.\n */\nexport class ToolStatusLineComponent implements Component {\n\tprivate readonly child: Component;\n\tprivate readonly options: ToolStatusLineOptions;\n\n\tconstructor(child: Component, options: ToolStatusLineOptions) {\n\t\tthis.child = child;\n\t\tthis.options = options;\n\t}\n\n\trender(width: number): string[] {\n\t\tif (width <= 0) return [];\n\t\tconst { lifecycle, symbolPreset, durationMs } = this.options;\n\t\tconst duration = durationMs === undefined ? \"\" : ` ${formatToolDuration(durationMs)}`;\n\t\tconst separator = symbolPreset === \"ascii\" ? \" | \" : \" · \";\n\t\tconst plainPrefix = `${LIFECYCLE_SYMBOLS[symbolPreset][lifecycle]} ${lifecycle}${duration}${separator}`;\n\t\tconst prefix = theme.fg(lifecycleColor(lifecycle), plainPrefix);\n\t\tconst prefixWidth = visibleWidth(prefix);\n\n\t\tif (prefixWidth >= width) {\n\t\t\treturn [truncateToWidth(prefix, width, \"\")];\n\t\t}\n\n\t\tconst childWidth = Math.max(1, width - prefixWidth);\n\t\tconst childLines = this.child.render(childWidth);\n\t\tif (childLines.length === 0) return [];\n\n\t\tconst continuation = \" \".repeat(prefixWidth);\n\t\treturn childLines.map((line, index) => (index === 0 ? prefix : continuation) + line);\n\t}\n\n\tinvalidate(): void {\n\t\tthis.child.invalidate?.();\n\t}\n}\n"]}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
2
|
+
import { paintBackground, theme } from "../theme/theme.js";
|
|
3
|
+
const LIFECYCLE_SYMBOLS = {
|
|
4
|
+
unicode: { queued: "○", running: "◌", done: "✓", error: "✗" },
|
|
5
|
+
ascii: { queued: "[ ]", running: "[~]", done: "[x]", error: "[!]" },
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Running takes the brand accent rather than `warning`. Work in progress is
|
|
9
|
+
* not a caution; amber is reserved for states the user may need to act on.
|
|
10
|
+
*/
|
|
11
|
+
function lifecycleColor(lifecycle) {
|
|
12
|
+
switch (lifecycle) {
|
|
13
|
+
case "queued":
|
|
14
|
+
return "dim";
|
|
15
|
+
case "running":
|
|
16
|
+
return "accent";
|
|
17
|
+
case "done":
|
|
18
|
+
return "success";
|
|
19
|
+
case "error":
|
|
20
|
+
return "error";
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* The status spine drawn down the left edge of a tool panel.
|
|
25
|
+
*
|
|
26
|
+
* It is a redundant channel over the lifecycle word in the header, so it is
|
|
27
|
+
* free to lean on colour. The glyph still distinguishes work that has not
|
|
28
|
+
* started from work that has, which is the distinction a glance most needs.
|
|
29
|
+
*/
|
|
30
|
+
const SPINE_GLYPHS = {
|
|
31
|
+
unicode: { queued: "┆", running: "▌", done: "▌", error: "▌" },
|
|
32
|
+
ascii: { queued: ":", running: "|", done: "|", error: "|" },
|
|
33
|
+
};
|
|
34
|
+
export function formatToolDuration(durationMs) {
|
|
35
|
+
if (durationMs < 1000)
|
|
36
|
+
return `${Math.max(0, Math.round(durationMs))}ms`;
|
|
37
|
+
if (durationMs < 10_000)
|
|
38
|
+
return `${(durationMs / 1000).toFixed(1)}s`;
|
|
39
|
+
return `${Math.round(durationMs / 1000)}s`;
|
|
40
|
+
}
|
|
41
|
+
function lifecycleBackground(lifecycle) {
|
|
42
|
+
if (lifecycle === "done")
|
|
43
|
+
return "toolSuccessBg";
|
|
44
|
+
if (lifecycle === "error")
|
|
45
|
+
return "toolErrorBg";
|
|
46
|
+
return "toolPendingBg";
|
|
47
|
+
}
|
|
48
|
+
/** Prime-style flat shell for renderer-based tool calls. */
|
|
49
|
+
export class ToolPanelComponent {
|
|
50
|
+
child;
|
|
51
|
+
options;
|
|
52
|
+
constructor(child, options) {
|
|
53
|
+
this.child = child;
|
|
54
|
+
this.options = options;
|
|
55
|
+
}
|
|
56
|
+
render(width) {
|
|
57
|
+
if (width <= 0)
|
|
58
|
+
return [];
|
|
59
|
+
const padding = Math.min(2, Math.floor((width - 1) / 2));
|
|
60
|
+
const innerWidth = Math.max(1, width - padding * 2);
|
|
61
|
+
const childLines = this.child.render(innerWidth);
|
|
62
|
+
if (childLines.length === 0)
|
|
63
|
+
return [];
|
|
64
|
+
const { lifecycle, symbolPreset, durationMs } = this.options;
|
|
65
|
+
const duration = durationMs === undefined ? "" : ` ${formatToolDuration(durationMs)}`;
|
|
66
|
+
const state = theme.fg(lifecycleColor(lifecycle), `${LIFECYCLE_SYMBOLS[symbolPreset][lifecycle]} ${lifecycle}${duration}`);
|
|
67
|
+
const separator = theme.fg("dim", symbolPreset === "ascii" ? " - " : " · ");
|
|
68
|
+
const stateWidth = visibleWidth(separator) + visibleWidth(state);
|
|
69
|
+
const label = childLines[0].replace(/\s+$/, "");
|
|
70
|
+
const header = stateWidth < innerWidth
|
|
71
|
+
? `${truncateToWidth(label, innerWidth - stateWidth, "")}${separator}${state}`
|
|
72
|
+
: truncateToWidth(state, innerWidth, "");
|
|
73
|
+
const panelLines = [header];
|
|
74
|
+
if (childLines.length > 1)
|
|
75
|
+
panelLines.push("", ...childLines.slice(1));
|
|
76
|
+
const background = lifecycleBackground(lifecycle);
|
|
77
|
+
// The spine occupies the first column of the existing left padding, so it
|
|
78
|
+
// marks state without costing the panel a column of content. Below two
|
|
79
|
+
// columns of padding there is no room for it and it is dropped.
|
|
80
|
+
const showSpine = padding >= 1;
|
|
81
|
+
const spine = showSpine
|
|
82
|
+
? paintBackground(theme.fg(lifecycleColor(lifecycle), SPINE_GLYPHS[symbolPreset][lifecycle]), background)
|
|
83
|
+
: "";
|
|
84
|
+
const leftPadding = " ".repeat(Math.max(0, padding - (showSpine ? 1 : 0)));
|
|
85
|
+
return panelLines.map((line) => {
|
|
86
|
+
const clipped = truncateToWidth(line, innerWidth, "");
|
|
87
|
+
const rightPadding = " ".repeat(Math.max(0, innerWidth - visibleWidth(clipped)));
|
|
88
|
+
return spine + paintBackground(`${leftPadding}${clipped}${rightPadding}${" ".repeat(padding)}`, background);
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
invalidate() {
|
|
92
|
+
this.child.invalidate?.();
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Prefixes an existing public tool renderer with Apex-owned lifecycle text.
|
|
97
|
+
* The wrapped renderer receives the remaining width, so its own wrapping and
|
|
98
|
+
* cursor-free layout stay intact without a pi-tui hook.
|
|
99
|
+
*/
|
|
100
|
+
export class ToolStatusLineComponent {
|
|
101
|
+
child;
|
|
102
|
+
options;
|
|
103
|
+
constructor(child, options) {
|
|
104
|
+
this.child = child;
|
|
105
|
+
this.options = options;
|
|
106
|
+
}
|
|
107
|
+
render(width) {
|
|
108
|
+
if (width <= 0)
|
|
109
|
+
return [];
|
|
110
|
+
const { lifecycle, symbolPreset, durationMs } = this.options;
|
|
111
|
+
const duration = durationMs === undefined ? "" : ` ${formatToolDuration(durationMs)}`;
|
|
112
|
+
const separator = symbolPreset === "ascii" ? " | " : " · ";
|
|
113
|
+
const plainPrefix = `${LIFECYCLE_SYMBOLS[symbolPreset][lifecycle]} ${lifecycle}${duration}${separator}`;
|
|
114
|
+
const prefix = theme.fg(lifecycleColor(lifecycle), plainPrefix);
|
|
115
|
+
const prefixWidth = visibleWidth(prefix);
|
|
116
|
+
if (prefixWidth >= width) {
|
|
117
|
+
return [truncateToWidth(prefix, width, "")];
|
|
118
|
+
}
|
|
119
|
+
const childWidth = Math.max(1, width - prefixWidth);
|
|
120
|
+
const childLines = this.child.render(childWidth);
|
|
121
|
+
if (childLines.length === 0)
|
|
122
|
+
return [];
|
|
123
|
+
const continuation = " ".repeat(prefixWidth);
|
|
124
|
+
return childLines.map((line, index) => (index === 0 ? prefix : continuation) + line);
|
|
125
|
+
}
|
|
126
|
+
invalidate() {
|
|
127
|
+
this.child.invalidate?.();
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=tool-panel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-panel.js","sourceRoot":"","sources":["../../../../src/modes/interactive/components/tool-panel.ts"],"names":[],"mappings":"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","sourcesContent":["import { type Component, truncateToWidth, visibleWidth } from \"@earendil-works/pi-tui\";\nimport { paintBackground, theme } from \"../theme/theme.ts\";\n\nexport type ToolLifecycle = \"queued\" | \"running\" | \"done\" | \"error\";\nexport type ToolSymbolPreset = \"unicode\" | \"ascii\";\n\nconst LIFECYCLE_SYMBOLS: Record<ToolSymbolPreset, Record<ToolLifecycle, string>> = {\n\tunicode: { queued: \"○\", running: \"◌\", done: \"✓\", error: \"✗\" },\n\tascii: { queued: \"[ ]\", running: \"[~]\", done: \"[x]\", error: \"[!]\" },\n};\n\n/**\n * Running takes the brand accent rather than `warning`. Work in progress is\n * not a caution; amber is reserved for states the user may need to act on.\n */\nfunction lifecycleColor(lifecycle: ToolLifecycle): \"dim\" | \"accent\" | \"success\" | \"error\" {\n\tswitch (lifecycle) {\n\t\tcase \"queued\":\n\t\t\treturn \"dim\";\n\t\tcase \"running\":\n\t\t\treturn \"accent\";\n\t\tcase \"done\":\n\t\t\treturn \"success\";\n\t\tcase \"error\":\n\t\t\treturn \"error\";\n\t}\n}\n\n/**\n * The status spine drawn down the left edge of a tool panel.\n *\n * It is a redundant channel over the lifecycle word in the header, so it is\n * free to lean on colour. The glyph still distinguishes work that has not\n * started from work that has, which is the distinction a glance most needs.\n */\nconst SPINE_GLYPHS: Record<ToolSymbolPreset, Record<ToolLifecycle, string>> = {\n\tunicode: { queued: \"┆\", running: \"▌\", done: \"▌\", error: \"▌\" },\n\tascii: { queued: \":\", running: \"|\", done: \"|\", error: \"|\" },\n};\n\nexport function formatToolDuration(durationMs: number): string {\n\tif (durationMs < 1000) return `${Math.max(0, Math.round(durationMs))}ms`;\n\tif (durationMs < 10_000) return `${(durationMs / 1000).toFixed(1)}s`;\n\treturn `${Math.round(durationMs / 1000)}s`;\n}\n\nexport interface ToolStatusLineOptions {\n\tlifecycle: ToolLifecycle;\n\tsymbolPreset: ToolSymbolPreset;\n\tdurationMs?: number;\n}\n\nfunction lifecycleBackground(lifecycle: ToolLifecycle): \"toolPendingBg\" | \"toolSuccessBg\" | \"toolErrorBg\" {\n\tif (lifecycle === \"done\") return \"toolSuccessBg\";\n\tif (lifecycle === \"error\") return \"toolErrorBg\";\n\treturn \"toolPendingBg\";\n}\n\n/** Prime-style flat shell for renderer-based tool calls. */\nexport class ToolPanelComponent implements Component {\n\tprivate readonly child: Component;\n\tprivate readonly options: ToolStatusLineOptions;\n\n\tconstructor(child: Component, options: ToolStatusLineOptions) {\n\t\tthis.child = child;\n\t\tthis.options = options;\n\t}\n\n\trender(width: number): string[] {\n\t\tif (width <= 0) return [];\n\t\tconst padding = Math.min(2, Math.floor((width - 1) / 2));\n\t\tconst innerWidth = Math.max(1, width - padding * 2);\n\t\tconst childLines = this.child.render(innerWidth);\n\t\tif (childLines.length === 0) return [];\n\n\t\tconst { lifecycle, symbolPreset, durationMs } = this.options;\n\t\tconst duration = durationMs === undefined ? \"\" : ` ${formatToolDuration(durationMs)}`;\n\t\tconst state = theme.fg(\n\t\t\tlifecycleColor(lifecycle),\n\t\t\t`${LIFECYCLE_SYMBOLS[symbolPreset][lifecycle]} ${lifecycle}${duration}`,\n\t\t);\n\t\tconst separator = theme.fg(\"dim\", symbolPreset === \"ascii\" ? \" - \" : \" · \");\n\t\tconst stateWidth = visibleWidth(separator) + visibleWidth(state);\n\t\tconst label = childLines[0].replace(/\\s+$/, \"\");\n\t\tconst header =\n\t\t\tstateWidth < innerWidth\n\t\t\t\t? `${truncateToWidth(label, innerWidth - stateWidth, \"\")}${separator}${state}`\n\t\t\t\t: truncateToWidth(state, innerWidth, \"\");\n\t\tconst panelLines = [header];\n\t\tif (childLines.length > 1) panelLines.push(\"\", ...childLines.slice(1));\n\n\t\tconst background = lifecycleBackground(lifecycle);\n\t\t// The spine occupies the first column of the existing left padding, so it\n\t\t// marks state without costing the panel a column of content. Below two\n\t\t// columns of padding there is no room for it and it is dropped.\n\t\tconst showSpine = padding >= 1;\n\t\tconst spine = showSpine\n\t\t\t? paintBackground(theme.fg(lifecycleColor(lifecycle), SPINE_GLYPHS[symbolPreset][lifecycle]), background)\n\t\t\t: \"\";\n\t\tconst leftPadding = \" \".repeat(Math.max(0, padding - (showSpine ? 1 : 0)));\n\t\treturn panelLines.map((line) => {\n\t\t\tconst clipped = truncateToWidth(line, innerWidth, \"\");\n\t\t\tconst rightPadding = \" \".repeat(Math.max(0, innerWidth - visibleWidth(clipped)));\n\t\t\treturn spine + paintBackground(`${leftPadding}${clipped}${rightPadding}${\" \".repeat(padding)}`, background);\n\t\t});\n\t}\n\n\tinvalidate(): void {\n\t\tthis.child.invalidate?.();\n\t}\n}\n\n/**\n * Prefixes an existing public tool renderer with Apex-owned lifecycle text.\n * The wrapped renderer receives the remaining width, so its own wrapping and\n * cursor-free layout stay intact without a pi-tui hook.\n */\nexport class ToolStatusLineComponent implements Component {\n\tprivate readonly child: Component;\n\tprivate readonly options: ToolStatusLineOptions;\n\n\tconstructor(child: Component, options: ToolStatusLineOptions) {\n\t\tthis.child = child;\n\t\tthis.options = options;\n\t}\n\n\trender(width: number): string[] {\n\t\tif (width <= 0) return [];\n\t\tconst { lifecycle, symbolPreset, durationMs } = this.options;\n\t\tconst duration = durationMs === undefined ? \"\" : ` ${formatToolDuration(durationMs)}`;\n\t\tconst separator = symbolPreset === \"ascii\" ? \" | \" : \" · \";\n\t\tconst plainPrefix = `${LIFECYCLE_SYMBOLS[symbolPreset][lifecycle]} ${lifecycle}${duration}${separator}`;\n\t\tconst prefix = theme.fg(lifecycleColor(lifecycle), plainPrefix);\n\t\tconst prefixWidth = visibleWidth(prefix);\n\n\t\tif (prefixWidth >= width) {\n\t\t\treturn [truncateToWidth(prefix, width, \"\")];\n\t\t}\n\n\t\tconst childWidth = Math.max(1, width - prefixWidth);\n\t\tconst childLines = this.child.render(childWidth);\n\t\tif (childLines.length === 0) return [];\n\n\t\tconst continuation = \" \".repeat(prefixWidth);\n\t\treturn childLines.map((line, index) => (index === 0 ? prefix : continuation) + line);\n\t}\n\n\tinvalidate(): void {\n\t\tthis.child.invalidate?.();\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"external-editor.d.ts","sourceRoot":"","sources":["../../../src/modes/interactive/external-editor.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"external-editor.d.ts","sourceRoot":"","sources":["../../../src/modes/interactive/external-editor.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,qBAAqB;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,oBAAoB,GAAG;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,MAAM,EAAE,QAAQ,CAAA;CAAE,CAAC;AAiDlG,wBAAsB,oBAAoB,CAAC,OAAO,EAAE,qBAAqB,GAAG,OAAO,CAAC,oBAAoB,CAAC,CA+BxG","sourcesContent":["import { spawn } from \"node:child_process\";\nimport { mkdtempSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { stripBom } from \"../../utils/text.ts\";\n\nexport interface ExternalEditorOptions {\n\tcommand: string;\n\tcontent: string;\n}\n\nexport type ExternalEditorResult = { status: \"complete\"; content: string } | { status: \"failed\" };\n\nfunction parseCommand(command: string): string[] | undefined {\n\tconst args: string[] = [];\n\tlet current = \"\";\n\tlet quote: '\"' | \"'\" | undefined;\n\tlet escaped = false;\n\tlet started = false;\n\n\tfor (const character of command) {\n\t\tif (escaped) {\n\t\t\tcurrent += character;\n\t\t\tescaped = false;\n\t\t\tstarted = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (character === \"\\\\\" && quote !== \"'\") {\n\t\t\tescaped = true;\n\t\t\tstarted = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (quote) {\n\t\t\tif (character === quote) quote = undefined;\n\t\t\telse current += character;\n\t\t\tstarted = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (character === '\"' || character === \"'\") {\n\t\t\tquote = character;\n\t\t\tstarted = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (/\\s/.test(character)) {\n\t\t\tif (started) {\n\t\t\t\targs.push(current);\n\t\t\t\tcurrent = \"\";\n\t\t\t\tstarted = false;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tcurrent += character;\n\t\tstarted = true;\n\t}\n\tif (escaped || quote || (!started && args.length === 0)) return undefined;\n\tif (started) args.push(current);\n\tif (!args[0]) return undefined;\n\treturn args;\n}\n\nexport async function editInExternalEditor(options: ExternalEditorOptions): Promise<ExternalEditorResult> {\n\tconst command = parseCommand(options.command);\n\tif (!command) return { status: \"failed\" };\n\n\tconst directory = mkdtempSync(join(tmpdir(), \"apex-code-editor-\"));\n\tconst filePath = join(directory, \"prompt.md\");\n\ttry {\n\t\twriteFileSync(filePath, options.content, \"utf-8\");\n\t\tconst [editor, ...editorArgs] = command;\n\t\tprocess.stdout.write(\n\t\t\t`Launching external editor: ${options.command}\\nApex Code will resume when the editor exits.\\n`,\n\t\t);\n\n\t\t// Do not use spawnSync here. On Windows, synchronous child_process calls can keep\n\t\t// Node/libuv's console input read active after the parent pauses stdin, racing\n\t\t// vim/nvim for the console input buffer until Ctrl+C cancels the pending read.\n\t\tconst exitCode = await new Promise<number | null>((resolve) => {\n\t\t\tconst child = spawn(editor, [...editorArgs, filePath], { stdio: \"inherit\", shell: false });\n\t\t\tchild.on(\"error\", () => resolve(null));\n\t\t\tchild.on(\"close\", (code) => resolve(code));\n\t\t});\n\n\t\tif (exitCode !== 0) return { status: \"failed\" };\n\t\treturn { status: \"complete\", content: stripBom(readFileSync(filePath, \"utf-8\")).replace(/\\n$/, \"\") };\n\t} finally {\n\t\ttry {\n\t\t\trmSync(directory, { recursive: true, force: true });\n\t\t} catch {\n\t\t\t// Cleanup is best effort.\n\t\t}\n\t}\n}\n"]}
|
|
@@ -2,6 +2,7 @@ import { spawn } from "node:child_process";
|
|
|
2
2
|
import { mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
4
|
import { join } from "node:path";
|
|
5
|
+
import { stripBom } from "../../utils/text.js";
|
|
5
6
|
function parseCommand(command) {
|
|
6
7
|
const args = [];
|
|
7
8
|
let current = "";
|
|
@@ -72,7 +73,7 @@ export async function editInExternalEditor(options) {
|
|
|
72
73
|
});
|
|
73
74
|
if (exitCode !== 0)
|
|
74
75
|
return { status: "failed" };
|
|
75
|
-
return { status: "complete", content: readFileSync(filePath, "utf-8").replace(/\n$/, "") };
|
|
76
|
+
return { status: "complete", content: stripBom(readFileSync(filePath, "utf-8")).replace(/\n$/, "") };
|
|
76
77
|
}
|
|
77
78
|
finally {
|
|
78
79
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"external-editor.js","sourceRoot":"","sources":["../../../src/modes/interactive/external-editor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC3E,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"external-editor.js","sourceRoot":"","sources":["../../../src/modes/interactive/external-editor.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn } from \"node:child_process\";\nimport { mkdtempSync, readFileSync, rmSync, writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { stripBom } from \"../../utils/text.ts\";\n\nexport interface ExternalEditorOptions {\n\tcommand: string;\n\tcontent: string;\n}\n\nexport type ExternalEditorResult = { status: \"complete\"; content: string } | { status: \"failed\" };\n\nfunction parseCommand(command: string): string[] | undefined {\n\tconst args: string[] = [];\n\tlet current = \"\";\n\tlet quote: '\"' | \"'\" | undefined;\n\tlet escaped = false;\n\tlet started = false;\n\n\tfor (const character of command) {\n\t\tif (escaped) {\n\t\t\tcurrent += character;\n\t\t\tescaped = false;\n\t\t\tstarted = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (character === \"\\\\\" && quote !== \"'\") {\n\t\t\tescaped = true;\n\t\t\tstarted = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (quote) {\n\t\t\tif (character === quote) quote = undefined;\n\t\t\telse current += character;\n\t\t\tstarted = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (character === '\"' || character === \"'\") {\n\t\t\tquote = character;\n\t\t\tstarted = true;\n\t\t\tcontinue;\n\t\t}\n\t\tif (/\\s/.test(character)) {\n\t\t\tif (started) {\n\t\t\t\targs.push(current);\n\t\t\t\tcurrent = \"\";\n\t\t\t\tstarted = false;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tcurrent += character;\n\t\tstarted = true;\n\t}\n\tif (escaped || quote || (!started && args.length === 0)) return undefined;\n\tif (started) args.push(current);\n\tif (!args[0]) return undefined;\n\treturn args;\n}\n\nexport async function editInExternalEditor(options: ExternalEditorOptions): Promise<ExternalEditorResult> {\n\tconst command = parseCommand(options.command);\n\tif (!command) return { status: \"failed\" };\n\n\tconst directory = mkdtempSync(join(tmpdir(), \"apex-code-editor-\"));\n\tconst filePath = join(directory, \"prompt.md\");\n\ttry {\n\t\twriteFileSync(filePath, options.content, \"utf-8\");\n\t\tconst [editor, ...editorArgs] = command;\n\t\tprocess.stdout.write(\n\t\t\t`Launching external editor: ${options.command}\\nApex Code will resume when the editor exits.\\n`,\n\t\t);\n\n\t\t// Do not use spawnSync here. On Windows, synchronous child_process calls can keep\n\t\t// Node/libuv's console input read active after the parent pauses stdin, racing\n\t\t// vim/nvim for the console input buffer until Ctrl+C cancels the pending read.\n\t\tconst exitCode = await new Promise<number | null>((resolve) => {\n\t\t\tconst child = spawn(editor, [...editorArgs, filePath], { stdio: \"inherit\", shell: false });\n\t\t\tchild.on(\"error\", () => resolve(null));\n\t\t\tchild.on(\"close\", (code) => resolve(code));\n\t\t});\n\n\t\tif (exitCode !== 0) return { status: \"failed\" };\n\t\treturn { status: \"complete\", content: stripBom(readFileSync(filePath, \"utf-8\")).replace(/\\n$/, \"\") };\n\t} finally {\n\t\ttry {\n\t\t\trmSync(directory, { recursive: true, force: true });\n\t\t} catch {\n\t\t\t// Cleanup is best effort.\n\t\t}\n\t}\n}\n"]}
|
|
@@ -6,8 +6,9 @@ import type { ImageContent } from "@earendil-works/pi-ai/compat";
|
|
|
6
6
|
import type { Terminal } from "@earendil-works/pi-tui";
|
|
7
7
|
import { type TUI, TuiAltScreen, TuiMainScreen } from "@earendil-works/pi-tui";
|
|
8
8
|
import { type AgentSessionRuntime } from "../../core/agent-session-runtime.ts";
|
|
9
|
+
import type { AgentSessionRuntimeDiagnostic } from "../../core/agent-session-services.ts";
|
|
9
10
|
import { SessionManager } from "../../core/session-manager.ts";
|
|
10
|
-
import type { TuiMode } from "../../core/settings-manager.ts";
|
|
11
|
+
import type { FullscreenExitOutput, TuiMode } from "../../core/settings-manager.ts";
|
|
11
12
|
import { type LatestApexCodeRelease } from "../../utils/version-check.ts";
|
|
12
13
|
export declare function formatResumeCommand(sessionManager: SessionManager): string | undefined;
|
|
13
14
|
/**
|
|
@@ -16,6 +17,8 @@ export declare function formatResumeCommand(sessionManager: SessionManager): str
|
|
|
16
17
|
export interface InteractiveModeOptions {
|
|
17
18
|
/** Providers that were migrated to auth.json (shows warning) */
|
|
18
19
|
migratedProviders?: string[];
|
|
20
|
+
/** Diagnostics collected before the interactive TUI was initialized. */
|
|
21
|
+
startupDiagnostics?: AgentSessionRuntimeDiagnostic[];
|
|
19
22
|
/** Warning message if session model couldn't be restored */
|
|
20
23
|
modelFallbackMessage?: string;
|
|
21
24
|
/** Cwd to trust after reload if it gained a .pi directory during this implicitly trusted session. */
|
|
@@ -30,6 +33,8 @@ export interface InteractiveModeOptions {
|
|
|
30
33
|
verbose?: boolean;
|
|
31
34
|
/** TUI layout mode. */
|
|
32
35
|
tuiMode?: TuiMode;
|
|
36
|
+
/** Initial interactive theme setting for this invocation. */
|
|
37
|
+
initialThemeSetting?: string;
|
|
33
38
|
}
|
|
34
39
|
interface InteractiveTuiOptions {
|
|
35
40
|
tuiMode: TuiMode;
|
|
@@ -68,6 +73,14 @@ export declare class InteractiveMode {
|
|
|
68
73
|
private footer;
|
|
69
74
|
private footerContainer;
|
|
70
75
|
private footerDataProvider;
|
|
76
|
+
/**
|
|
77
|
+
* Whether the startup screen is showing its counted inventory line.
|
|
78
|
+
*
|
|
79
|
+
* Warnings are only allowed to collapse into that count when the count is
|
|
80
|
+
* actually on screen. Under a quiet startup there is no splash header, so
|
|
81
|
+
* collapsing them would hide conflicts entirely rather than summarise them.
|
|
82
|
+
*/
|
|
83
|
+
private startupInventoryVisible;
|
|
71
84
|
private keybindings;
|
|
72
85
|
private version;
|
|
73
86
|
private isInitialized;
|
|
@@ -88,6 +101,7 @@ export declare class InteractiveMode {
|
|
|
88
101
|
private anthropicSubscriptionWarningShown;
|
|
89
102
|
private lastStatusSpacer;
|
|
90
103
|
private lastStatusText;
|
|
104
|
+
private managedToolStatusStarted;
|
|
91
105
|
private streamingComponent;
|
|
92
106
|
private streamingMessage;
|
|
93
107
|
private pendingTools;
|
|
@@ -99,6 +113,7 @@ export declare class InteractiveMode {
|
|
|
99
113
|
private unsubscribe?;
|
|
100
114
|
private signalCleanupHandlers;
|
|
101
115
|
private isBashMode;
|
|
116
|
+
private firstUseHints;
|
|
102
117
|
private bashComponent;
|
|
103
118
|
private pendingBashComponents;
|
|
104
119
|
private autoCompactionEscapeHandler?;
|
|
@@ -125,6 +140,7 @@ export declare class InteractiveMode {
|
|
|
125
140
|
private get agent();
|
|
126
141
|
private get sessionManager();
|
|
127
142
|
private get settingsManager();
|
|
143
|
+
private offerFirstUseHint;
|
|
128
144
|
constructor(runtimeHost: AgentSessionRuntime, options?: InteractiveModeOptions);
|
|
129
145
|
private getAutocompleteSourceTag;
|
|
130
146
|
private prefixAutocompleteDescription;
|
|
@@ -176,12 +192,37 @@ export declare class InteractiveMode {
|
|
|
176
192
|
private formatPathWithSource;
|
|
177
193
|
private formatDiagnostics;
|
|
178
194
|
private showLoadedResources;
|
|
195
|
+
/**
|
|
196
|
+
* Every startup diagnostic, grouped by the resource kind that produced it.
|
|
197
|
+
*
|
|
198
|
+
* One list feeds both the counted line in the header and the detailed
|
|
199
|
+
* listing, so the two can never disagree about how many issues exist.
|
|
200
|
+
*/
|
|
201
|
+
private collectDiagnosticGroups;
|
|
202
|
+
/**
|
|
203
|
+
* The counted line in the ruled band under the mark.
|
|
204
|
+
*
|
|
205
|
+
* The startup screen used to print all 152 skill names across fifteen rows.
|
|
206
|
+
* A count answers the only question that screen can usefully answer, which
|
|
207
|
+
* is what got loaded; the names live behind /resources now.
|
|
208
|
+
*/
|
|
209
|
+
/**
|
|
210
|
+
* The sigil row under the hint: how to reach commands, bash, and files.
|
|
211
|
+
*
|
|
212
|
+
* These are the only three characters that change what the composer does, so
|
|
213
|
+
* they take the accent and everything around them stays quiet.
|
|
214
|
+
*/
|
|
215
|
+
/** Live keybindings under the autocomplete dropdown. */
|
|
216
|
+
private buildAutocompleteFooter;
|
|
217
|
+
private buildStartupShortcuts;
|
|
218
|
+
private buildStartupInventory;
|
|
179
219
|
private bindCurrentSessionExtensions;
|
|
180
220
|
private applyFullscreenScrollbarSetting;
|
|
181
221
|
private applyRuntimeSettings;
|
|
182
222
|
private rebindCurrentSession;
|
|
183
223
|
private handleFatalRuntimeError;
|
|
184
224
|
private renderCurrentSessionState;
|
|
225
|
+
private clearPendingTools;
|
|
185
226
|
/**
|
|
186
227
|
* Get a registered tool definition by name (for custom rendering).
|
|
187
228
|
*/
|
|
@@ -236,6 +277,7 @@ export declare class InteractiveMode {
|
|
|
236
277
|
* Hide the extension selector.
|
|
237
278
|
*/
|
|
238
279
|
private hideExtensionSelector;
|
|
280
|
+
private showConfigurationIndex;
|
|
239
281
|
private showExtensionConfirm;
|
|
240
282
|
private promptForMissingSessionCwd;
|
|
241
283
|
/**
|
|
@@ -271,11 +313,14 @@ export declare class InteractiveMode {
|
|
|
271
313
|
private setupKeyHandlers;
|
|
272
314
|
private handleRightClickPaste;
|
|
273
315
|
private handleClipboardPaste;
|
|
316
|
+
private handleStartupSubmit;
|
|
274
317
|
private setupEditorSubmitHandler;
|
|
275
318
|
private subscribeToAgent;
|
|
276
319
|
private handleEvent;
|
|
277
320
|
/** Extract text content from a user message */
|
|
278
321
|
private getUserMessageText;
|
|
322
|
+
/** Show a managed-tool status update in the chat. */
|
|
323
|
+
private showManagedToolStatus;
|
|
279
324
|
/**
|
|
280
325
|
* Show a status message in the chat.
|
|
281
326
|
*
|
|
@@ -293,6 +338,11 @@ export declare class InteractiveMode {
|
|
|
293
338
|
* @param options.populateHistory Add user messages to editor history
|
|
294
339
|
*/
|
|
295
340
|
private renderSessionEntries;
|
|
341
|
+
/**
|
|
342
|
+
* Render billing usage for a compaction or branch summary. The notice is derived
|
|
343
|
+
* from persisted summary usage and is not stored as a separate session entry.
|
|
344
|
+
*/
|
|
345
|
+
private addCompactionCostNotice;
|
|
296
346
|
/**
|
|
297
347
|
* Show a transcript notice when a completed assistant message paid for a
|
|
298
348
|
* significant cache miss. Only states observable facts: the miss itself,
|
|
@@ -367,16 +417,12 @@ export declare class InteractiveMode {
|
|
|
367
417
|
* @param create Factory that receives a `done` callback and returns the component and focus target
|
|
368
418
|
*/
|
|
369
419
|
private showSelector;
|
|
370
|
-
/**
|
|
371
|
-
* Resyncs the footer from the store. Called on every session swap, not just at
|
|
372
|
-
* startup: `applyRuntimeSettings` also repoints the cwd, and cwd selects which
|
|
373
|
-
* project-scope permission file applies, so the mode genuinely can differ
|
|
374
|
-
* between two sessions in one process. A footer left showing the old value
|
|
375
|
-
* would under-report bypassPermissions, which is the one direction that matters.
|
|
376
|
-
*/
|
|
377
420
|
private refreshFooterPermissionMode;
|
|
378
421
|
private applyPermissionMode;
|
|
379
422
|
private showSettingsSelector;
|
|
423
|
+
private handleThinkingCommand;
|
|
424
|
+
private selectThinkingLevel;
|
|
425
|
+
private showThinkingSelector;
|
|
380
426
|
private handleModelCommand;
|
|
381
427
|
private findExactModelMatch;
|
|
382
428
|
/** Update the footer's available provider count from the current snapshot without refreshing catalogs. */
|
|
@@ -433,7 +479,7 @@ export declare class InteractiveMode {
|
|
|
433
479
|
private checkDaxnutsEasterEgg;
|
|
434
480
|
private handleBashCommand;
|
|
435
481
|
private handleCompactCommand;
|
|
436
|
-
stop(): void;
|
|
482
|
+
stop(fullscreenExitOutput?: FullscreenExitOutput): void;
|
|
437
483
|
}
|
|
438
484
|
export {};
|
|
439
485
|
//# sourceMappingURL=interactive-mode.d.ts.map
|