@code-yeongyu/senpi 2026.7.20 → 2026.7.22
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 +41 -0
- package/README.md +1 -0
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +1 -0
- package/dist/cli/args.js.map +1 -1
- package/dist/core/agent-session.d.ts +32 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +409 -68
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-storage.js +1 -1
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts +2 -2
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +67 -16
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/compaction/stream-watchdog.d.ts +31 -0
- package/dist/core/compaction/stream-watchdog.d.ts.map +1 -0
- package/dist/core/compaction/stream-watchdog.js +78 -0
- package/dist/core/compaction/stream-watchdog.js.map +1 -0
- package/dist/core/extensions/builtin/btw/index.d.ts +3 -0
- package/dist/core/extensions/builtin/btw/index.d.ts.map +1 -0
- package/dist/core/extensions/builtin/btw/index.js +120 -0
- package/dist/core/extensions/builtin/btw/index.js.map +1 -0
- package/dist/core/extensions/builtin/btw/panel.d.ts +21 -0
- package/dist/core/extensions/builtin/btw/panel.d.ts.map +1 -0
- package/dist/core/extensions/builtin/btw/panel.js +61 -0
- package/dist/core/extensions/builtin/btw/panel.js.map +1 -0
- package/dist/core/extensions/builtin/btw/side-query.d.ts +31 -0
- package/dist/core/extensions/builtin/btw/side-query.d.ts.map +1 -0
- package/dist/core/extensions/builtin/btw/side-query.js +68 -0
- package/dist/core/extensions/builtin/btw/side-query.js.map +1 -0
- package/dist/core/extensions/builtin/compaction/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/index.js +47 -11
- package/dist/core/extensions/builtin/compaction/index.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/openai-remote.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/openai-remote.js +3 -1
- package/dist/core/extensions/builtin/compaction/openai-remote.js.map +1 -1
- package/dist/core/extensions/builtin/compaction/speculative.d.ts +17 -0
- package/dist/core/extensions/builtin/compaction/speculative.d.ts.map +1 -1
- package/dist/core/extensions/builtin/compaction/speculative.js +93 -26
- package/dist/core/extensions/builtin/compaction/speculative.js.map +1 -1
- package/dist/core/extensions/builtin/config-reload/index.d.ts +39 -0
- package/dist/core/extensions/builtin/config-reload/index.d.ts.map +1 -0
- package/dist/core/extensions/builtin/config-reload/index.js +659 -0
- package/dist/core/extensions/builtin/config-reload/index.js.map +1 -0
- package/dist/core/extensions/builtin/config-reload/log.d.ts +55 -0
- package/dist/core/extensions/builtin/config-reload/log.d.ts.map +1 -0
- package/dist/core/extensions/builtin/config-reload/log.js +128 -0
- package/dist/core/extensions/builtin/config-reload/log.js.map +1 -0
- package/dist/core/extensions/builtin/config-reload/protocol.d.ts +71 -0
- package/dist/core/extensions/builtin/config-reload/protocol.d.ts.map +1 -0
- package/dist/core/extensions/builtin/config-reload/protocol.js +83 -0
- package/dist/core/extensions/builtin/config-reload/protocol.js.map +1 -0
- package/dist/core/extensions/builtin/config-reload/watch-engine.d.ts +43 -0
- package/dist/core/extensions/builtin/config-reload/watch-engine.d.ts.map +1 -0
- package/dist/core/extensions/builtin/config-reload/watch-engine.js +298 -0
- package/dist/core/extensions/builtin/config-reload/watch-engine.js.map +1 -0
- package/dist/core/extensions/builtin/goal/command-registration.d.ts +2 -2
- package/dist/core/extensions/builtin/goal/command-registration.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/command-registration.js +3 -4
- package/dist/core/extensions/builtin/goal/command-registration.js.map +1 -1
- package/dist/core/extensions/builtin/goal/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/index.js +11 -27
- package/dist/core/extensions/builtin/goal/index.js.map +1 -1
- package/dist/core/extensions/builtin/goal/tool-registration.d.ts +2 -2
- package/dist/core/extensions/builtin/goal/tool-registration.d.ts.map +1 -1
- package/dist/core/extensions/builtin/goal/tool-registration.js +2 -3
- package/dist/core/extensions/builtin/goal/tool-registration.js.map +1 -1
- package/dist/core/extensions/builtin/goal/turn-usage.d.ts +20 -0
- package/dist/core/extensions/builtin/goal/turn-usage.d.ts.map +1 -0
- package/dist/core/extensions/builtin/goal/turn-usage.js +61 -0
- package/dist/core/extensions/builtin/goal/turn-usage.js.map +1 -0
- package/dist/core/extensions/builtin/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/index.js +9 -0
- package/dist/core/extensions/builtin/index.js.map +1 -1
- package/dist/core/extensions/builtin/look-at/arguments.d.ts +27 -0
- package/dist/core/extensions/builtin/look-at/arguments.d.ts.map +1 -0
- package/dist/core/extensions/builtin/look-at/arguments.js +109 -0
- package/dist/core/extensions/builtin/look-at/arguments.js.map +1 -0
- package/dist/core/extensions/builtin/look-at/commands.d.ts +9 -0
- package/dist/core/extensions/builtin/look-at/commands.d.ts.map +1 -0
- package/dist/core/extensions/builtin/look-at/commands.js +102 -0
- package/dist/core/extensions/builtin/look-at/commands.js.map +1 -0
- package/dist/core/extensions/builtin/look-at/image-input.d.ts +21 -0
- package/dist/core/extensions/builtin/look-at/image-input.d.ts.map +1 -0
- package/dist/core/extensions/builtin/look-at/image-input.js +151 -0
- package/dist/core/extensions/builtin/look-at/image-input.js.map +1 -0
- package/dist/core/extensions/builtin/look-at/index.d.ts +3 -0
- package/dist/core/extensions/builtin/look-at/index.d.ts.map +1 -0
- package/dist/core/extensions/builtin/look-at/index.js +58 -0
- package/dist/core/extensions/builtin/look-at/index.js.map +1 -0
- package/dist/core/extensions/builtin/look-at/model-selector.d.ts +9 -0
- package/dist/core/extensions/builtin/look-at/model-selector.d.ts.map +1 -0
- package/dist/core/extensions/builtin/look-at/model-selector.js +77 -0
- package/dist/core/extensions/builtin/look-at/model-selector.js.map +1 -0
- package/dist/core/extensions/builtin/look-at/prompts.d.ts +5 -0
- package/dist/core/extensions/builtin/look-at/prompts.d.ts.map +1 -0
- package/dist/core/extensions/builtin/look-at/prompts.js +19 -0
- package/dist/core/extensions/builtin/look-at/prompts.js.map +1 -0
- package/dist/core/extensions/builtin/look-at/render.d.ts +26 -0
- package/dist/core/extensions/builtin/look-at/render.d.ts.map +1 -0
- package/dist/core/extensions/builtin/look-at/render.js +70 -0
- package/dist/core/extensions/builtin/look-at/render.js.map +1 -0
- package/dist/core/extensions/builtin/look-at/runner.d.ts +16 -0
- package/dist/core/extensions/builtin/look-at/runner.d.ts.map +1 -0
- package/dist/core/extensions/builtin/look-at/runner.js +108 -0
- package/dist/core/extensions/builtin/look-at/runner.js.map +1 -0
- package/dist/core/extensions/builtin/look-at/settings.d.ts +13 -0
- package/dist/core/extensions/builtin/look-at/settings.d.ts.map +1 -0
- package/dist/core/extensions/builtin/look-at/settings.js +20 -0
- package/dist/core/extensions/builtin/look-at/settings.js.map +1 -0
- package/dist/core/extensions/builtin/mcp/commands.d.ts.map +1 -1
- package/dist/core/extensions/builtin/mcp/commands.js +2 -0
- package/dist/core/extensions/builtin/mcp/commands.js.map +1 -1
- package/dist/core/extensions/builtin/mcp/config-schema.d.ts +6 -0
- package/dist/core/extensions/builtin/mcp/config-schema.d.ts.map +1 -1
- package/dist/core/extensions/builtin/mcp/config-schema.js +1 -0
- package/dist/core/extensions/builtin/mcp/config-schema.js.map +1 -1
- package/dist/core/extensions/builtin/mcp/config.d.ts.map +1 -1
- package/dist/core/extensions/builtin/mcp/config.js +9 -1
- package/dist/core/extensions/builtin/mcp/config.js.map +1 -1
- package/dist/core/extensions/builtin/mcp/service.d.ts.map +1 -1
- package/dist/core/extensions/builtin/mcp/service.js +22 -6
- package/dist/core/extensions/builtin/mcp/service.js.map +1 -1
- package/dist/core/extensions/builtin/mcp/startup-race.d.ts +10 -0
- package/dist/core/extensions/builtin/mcp/startup-race.d.ts.map +1 -1
- package/dist/core/extensions/builtin/mcp/startup-race.js +18 -1
- package/dist/core/extensions/builtin/mcp/startup-race.js.map +1 -1
- package/dist/core/extensions/builtin/model-fallback/index.d.ts +4 -0
- package/dist/core/extensions/builtin/model-fallback/index.d.ts.map +1 -0
- package/dist/core/extensions/builtin/model-fallback/index.js +55 -0
- package/dist/core/extensions/builtin/model-fallback/index.js.map +1 -0
- package/dist/core/extensions/builtin/model-fallback/settings.d.ts +6 -0
- package/dist/core/extensions/builtin/model-fallback/settings.d.ts.map +1 -0
- package/dist/core/extensions/builtin/model-fallback/settings.js +11 -0
- package/dist/core/extensions/builtin/model-fallback/settings.js.map +1 -0
- package/dist/core/extensions/builtin/model-fallback/ui.d.ts +12 -0
- package/dist/core/extensions/builtin/model-fallback/ui.d.ts.map +1 -0
- package/dist/core/extensions/builtin/model-fallback/ui.js +72 -0
- package/dist/core/extensions/builtin/model-fallback/ui.js.map +1 -0
- package/dist/core/extensions/builtin/nested-agents-md/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/nested-agents-md/index.js +4 -1
- package/dist/core/extensions/builtin/nested-agents-md/index.js.map +1 -1
- package/dist/core/extensions/builtin/rules/index.d.ts.map +1 -1
- package/dist/core/extensions/builtin/rules/index.js +4 -1
- package/dist/core/extensions/builtin/rules/index.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/output-format.d.ts +28 -0
- package/dist/core/extensions/builtin/terminal/output-format.d.ts.map +1 -0
- package/dist/core/extensions/builtin/terminal/output-format.js +74 -0
- package/dist/core/extensions/builtin/terminal/output-format.js.map +1 -0
- package/dist/core/extensions/builtin/terminal/runtime-session.d.ts +3 -0
- package/dist/core/extensions/builtin/terminal/runtime-session.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/runtime-session.js +22 -2
- package/dist/core/extensions/builtin/terminal/runtime-session.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/shared.d.ts +7 -0
- package/dist/core/extensions/builtin/terminal/shared.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/shared.js +14 -0
- package/dist/core/extensions/builtin/terminal/shared.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/tools/bash-output.d.ts +5 -1
- package/dist/core/extensions/builtin/terminal/tools/bash-output.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/tools/bash-output.js +88 -6
- package/dist/core/extensions/builtin/terminal/tools/bash-output.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/tools/bash.d.ts +12 -1
- package/dist/core/extensions/builtin/terminal/tools/bash.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/tools/bash.js +82 -8
- package/dist/core/extensions/builtin/terminal/tools/bash.js.map +1 -1
- package/dist/core/extensions/builtin/terminal/tools/render.d.ts +16 -0
- package/dist/core/extensions/builtin/terminal/tools/render.d.ts.map +1 -0
- package/dist/core/extensions/builtin/terminal/tools/render.js +30 -0
- package/dist/core/extensions/builtin/terminal/tools/render.js.map +1 -0
- package/dist/core/extensions/builtin/terminal/tools/spawn.d.ts +2 -0
- package/dist/core/extensions/builtin/terminal/tools/spawn.d.ts.map +1 -1
- package/dist/core/extensions/builtin/terminal/tools/spawn.js +1 -1
- package/dist/core/extensions/builtin/terminal/tools/spawn.js.map +1 -1
- package/dist/core/extensions/builtin/todotools/tools/todo.d.ts.map +1 -1
- package/dist/core/extensions/builtin/todotools/tools/todo.js +22 -6
- package/dist/core/extensions/builtin/todotools/tools/todo.js.map +1 -1
- package/dist/core/extensions/builtin/webfetch/webfetch/fetcher.d.ts +1 -0
- package/dist/core/extensions/builtin/webfetch/webfetch/fetcher.d.ts.map +1 -1
- package/dist/core/extensions/builtin/webfetch/webfetch/fetcher.js +13 -4
- package/dist/core/extensions/builtin/webfetch/webfetch/fetcher.js.map +1 -1
- package/dist/core/extensions/builtin/webfetch/webfetch/renderers.d.ts.map +1 -1
- package/dist/core/extensions/builtin/webfetch/webfetch/renderers.js +17 -2
- package/dist/core/extensions/builtin/webfetch/webfetch/renderers.js.map +1 -1
- package/dist/core/extensions/builtin/webfetch/webfetch/tool.d.ts +8 -1
- package/dist/core/extensions/builtin/webfetch/webfetch/tool.d.ts.map +1 -1
- package/dist/core/extensions/builtin/webfetch/webfetch/tool.js +45 -3
- package/dist/core/extensions/builtin/webfetch/webfetch/tool.js.map +1 -1
- package/dist/core/extensions/builtin/websearch/websearch/renderers.d.ts.map +1 -1
- package/dist/core/extensions/builtin/websearch/websearch/renderers.js +13 -4
- package/dist/core/extensions/builtin/websearch/websearch/renderers.js.map +1 -1
- package/dist/core/extensions/builtin/websearch/websearch/search.d.ts +3 -2
- package/dist/core/extensions/builtin/websearch/websearch/search.d.ts.map +1 -1
- package/dist/core/extensions/builtin/websearch/websearch/search.js +2 -1
- package/dist/core/extensions/builtin/websearch/websearch/search.js.map +1 -1
- package/dist/core/extensions/builtin/websearch/websearch/tool.d.ts.map +1 -1
- package/dist/core/extensions/builtin/websearch/websearch/tool.js +17 -1
- package/dist/core/extensions/builtin/websearch/websearch/tool.js.map +1 -1
- package/dist/core/extensions/builtin/websearch/websearch/types.d.ts +2 -0
- package/dist/core/extensions/builtin/websearch/websearch/types.d.ts.map +1 -1
- package/dist/core/extensions/builtin/websearch/websearch/types.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +6 -0
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +71 -3
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +96 -10
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/model-config-schema.d.ts +1942 -0
- package/dist/core/model-config-schema.d.ts.map +1 -0
- package/dist/core/model-config-schema.js +197 -0
- package/dist/core/model-config-schema.js.map +1 -0
- package/dist/core/model-config.d.ts +2 -578
- package/dist/core/model-config.d.ts.map +1 -1
- package/dist/core/model-config.js +1 -194
- package/dist/core/model-config.js.map +1 -1
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +1 -0
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +9 -3
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/provider-composer.d.ts +1 -0
- package/dist/core/provider-composer.d.ts.map +1 -1
- package/dist/core/provider-composer.js +3 -2
- package/dist/core/provider-composer.js.map +1 -1
- package/dist/core/provider-display-names.d.ts.map +1 -1
- package/dist/core/provider-display-names.js +1 -0
- package/dist/core/provider-display-names.js.map +1 -1
- package/dist/core/retry-fallback/chains.d.ts +29 -0
- package/dist/core/retry-fallback/chains.d.ts.map +1 -0
- package/dist/core/retry-fallback/chains.js +109 -0
- package/dist/core/retry-fallback/chains.js.map +1 -0
- package/dist/core/retry-fallback/controller.d.ts +77 -0
- package/dist/core/retry-fallback/controller.d.ts.map +1 -0
- package/dist/core/retry-fallback/controller.js +157 -0
- package/dist/core/retry-fallback/controller.js.map +1 -0
- package/dist/core/retry-fallback/cooldown.d.ts +21 -0
- package/dist/core/retry-fallback/cooldown.d.ts.map +1 -0
- package/dist/core/retry-fallback/cooldown.js +49 -0
- package/dist/core/retry-fallback/cooldown.js.map +1 -0
- package/dist/core/retry-fallback/log.d.ts +10 -0
- package/dist/core/retry-fallback/log.d.ts.map +1 -0
- package/dist/core/retry-fallback/log.js +128 -0
- package/dist/core/retry-fallback/log.js.map +1 -0
- package/dist/core/retry-fallback/validate.d.ts +8 -0
- package/dist/core/retry-fallback/validate.d.ts.map +1 -0
- package/dist/core/retry-fallback/validate.js +63 -0
- package/dist/core/retry-fallback/validate.js.map +1 -0
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +1 -0
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-manager.d.ts +39 -3
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +125 -16
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/settings-manager.d.ts +33 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +153 -6
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts +2 -1
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +30 -20
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/todo-strike.d.ts +8 -0
- package/dist/modes/interactive/components/todo-strike.d.ts.map +1 -0
- package/dist/modes/interactive/components/todo-strike.js +35 -0
- package/dist/modes/interactive/components/todo-strike.js.map +1 -0
- package/dist/modes/interactive/components/tool-execution-renderer.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution-renderer.js +8 -1
- package/dist/modes/interactive/components/tool-execution-renderer.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution.d.ts +4 -0
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +51 -2
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +6 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +124 -4
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/tool-progress.d.ts +8 -0
- package/dist/modes/interactive/tool-progress.d.ts.map +1 -0
- package/dist/modes/interactive/tool-progress.js +26 -0
- package/dist/modes/interactive/tool-progress.js.map +1 -0
- package/dist/modes/interactive/tool-result-reveal.d.ts +18 -0
- package/dist/modes/interactive/tool-result-reveal.d.ts.map +1 -0
- package/dist/modes/interactive/tool-result-reveal.js +155 -0
- package/dist/modes/interactive/tool-result-reveal.js.map +1 -0
- package/dist/utils/fs-watch.d.ts +2 -2
- package/dist/utils/fs-watch.d.ts.map +1 -1
- package/dist/utils/fs-watch.js +2 -2
- package/dist/utils/fs-watch.js.map +1 -1
- package/docs/extensions.md +79 -1
- package/docs/mcp.md +10 -1
- package/docs/models.md +102 -1
- package/docs/providers.md +3 -1
- package/docs/settings.md +35 -0
- package/node_modules/@code-yeongyu/senpi-codemode/CHANGELOG.md +24 -0
- package/node_modules/@code-yeongyu/senpi-codemode/package.json +3 -3
- package/node_modules/@code-yeongyu/senpi-codemode/src/tool/cell-handler.ts +13 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js +76 -8
- package/node_modules/@earendil-works/pi-agent-core/dist/agent-loop.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/agent.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/agent.js +26 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/agent.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/agent-harness.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/agent-harness.js +24 -2
- package/node_modules/@earendil-works/pi-agent-core/dist/harness/agent-harness.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/types.d.ts +5 -0
- package/node_modules/@earendil-works/pi-agent-core/dist/types.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/dist/types.js.map +1 -1
- package/node_modules/@earendil-works/pi-agent-core/package.json +2 -2
- package/node_modules/@earendil-works/pi-ai/README.md +2 -0
- package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js +68 -25
- package/node_modules/@earendil-works/pi-ai/dist/api/anthropic-messages.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/lazy.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/lazy.js +33 -6
- package/node_modules/@earendil-works/pi-ai/dist/api/lazy.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses-shared.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses-shared.js +6 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/openai-responses-shared.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/transform-messages.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api/transform-messages.js +62 -52
- package/node_modules/@earendil-works/pi-ai/dist/api/transform-messages.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/api-registry.d.ts +19 -0
- package/node_modules/@earendil-works/pi-ai/dist/api-registry.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/api-registry.js +50 -0
- package/node_modules/@earendil-works/pi-ai/dist/api-registry.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/compat.d.ts +2 -17
- package/node_modules/@earendil-works/pi-ai/dist/compat.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/compat.js +3 -52
- package/node_modules/@earendil-works/pi-ai/dist/compat.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/env-api-keys.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/env-api-keys.js +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/env-api-keys.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.d.ts +45 -0
- package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js +45 -0
- package/node_modules/@earendil-works/pi-ai/dist/image-models.generated.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/index.d.ts +5 -0
- package/node_modules/@earendil-works/pi-ai/dist/index.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/index.js +5 -0
- package/node_modules/@earendil-works/pi-ai/dist/index.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/model.d.ts +27 -0
- package/node_modules/@earendil-works/pi-ai/dist/model.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/model.js +2 -0
- package/node_modules/@earendil-works/pi-ai/dist/model.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts +1178 -1072
- package/node_modules/@earendil-works/pi-ai/dist/models.generated.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/models.generated.js +2 -0
- package/node_modules/@earendil-works/pi-ai/dist/models.generated.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/alibaba-token-plan.d.ts +3 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/alibaba-token-plan.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/alibaba-token-plan.js +15 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/alibaba-token-plan.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/alibaba-token-plan.models.d.ts +64 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/alibaba-token-plan.models.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/alibaba-token-plan.models.js +5 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/alibaba-token-plan.models.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/all.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/all.js +2 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/all.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/alibaba-token-plan.json +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/google.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/kimi-coding.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/opencode.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/openrouter.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/data/vercel-ai-gateway.json +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/faux.d.ts +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/faux.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/faux.js +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/faux.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/google.models.d.ts +8 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/google.models.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/google.models.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding.models.d.ts +0 -4
- package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding.models.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/kimi-coding.models.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/opencode.models.d.ts +12 -4
- package/node_modules/@earendil-works/pi-ai/dist/providers/opencode.models.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/opencode.models.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/openrouter.models.d.ts +20 -4
- package/node_modules/@earendil-works/pi-ai/dist/providers/openrouter.models.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/openrouter.models.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/vercel-ai-gateway.models.d.ts +16 -0
- package/node_modules/@earendil-works/pi-ai/dist/providers/vercel-ai-gateway.models.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/providers/vercel-ai-gateway.models.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/index.d.ts +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/index.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/index.js +8 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/index.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/invoke-stream-helpers.d.ts +20 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/invoke-stream-helpers.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/invoke-stream-helpers.js +79 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/invoke-stream-helpers.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/invoke-tag-scanner.d.ts +2 -18
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/invoke-tag-scanner.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/invoke-tag-scanner.js +4 -218
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/invoke-tag-scanner.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/invoke-tag-syntax.d.ts +38 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/invoke-tag-syntax.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/invoke-tag-syntax.js +210 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/invoke-tag-syntax.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/recovery-stream.d.ts +9 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/recovery-stream.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/recovery-stream.js +231 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/recovery-stream.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/recovery-wrapper-state.d.ts +38 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/recovery-wrapper-state.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/recovery-wrapper-state.js +84 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/recovery-wrapper-state.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/stream-boundary.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/stream-boundary.js +20 -57
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/stream-boundary.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/stream.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/stream.js +16 -99
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/anthropic-xml/stream.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/index.d.ts +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/index.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/index.js +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/index.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/recovery-stream.d.ts +5 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/recovery-stream.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/recovery-stream.js +6 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/protocols/antml/recovery-stream.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-code-mask.d.ts +19 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-code-mask.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-code-mask.js +185 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-code-mask.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-content-lifecycle.d.ts +11 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-content-lifecycle.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-content-lifecycle.js +24 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-content-lifecycle.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-diagnostics.d.ts +4 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-diagnostics.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-diagnostics.js +13 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-diagnostics.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-event-stream.d.ts +15 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-event-stream.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-event-stream.js +37 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-event-stream.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-message-snapshot.d.ts +4 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-message-snapshot.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-message-snapshot.js +61 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-message-snapshot.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-native-projection.d.ts +29 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-native-projection.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-native-projection.js +148 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-native-projection.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-stream-failure.d.ts +5 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-stream-failure.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-stream-failure.js +36 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-stream-failure.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-stream-terminal.d.ts +15 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-stream-terminal.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-stream-terminal.js +88 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-stream-terminal.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-stream-wrapper.d.ts +3 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-stream-wrapper.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-stream-wrapper.js +233 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-stream-wrapper.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-text-projection.d.ts +23 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-text-projection.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-text-projection.js +77 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/recovery-text-projection.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/stream-message-metadata.d.ts +5 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/stream-message-metadata.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/stream-message-metadata.js +63 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/stream-message-metadata.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/stream-thinking-projection.d.ts +13 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/stream-thinking-projection.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/stream-thinking-projection.js +52 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/stream-thinking-projection.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/stream-wrapper-shared.d.ts +41 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/stream-wrapper-shared.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/stream-wrapper-shared.js +209 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/stream-wrapper-shared.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/stream-wrapper.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/stream-wrapper.js +70 -346
- package/node_modules/@earendil-works/pi-ai/dist/tool-call-middleware/stream-wrapper.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/types.d.ts +18 -23
- package/node_modules/@earendil-works/pi-ai/dist/types.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/types.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/retry.d.ts.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js +5 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/retry.js.map +1 -1
- package/node_modules/@earendil-works/pi-ai/dist/utils/stop-details.d.ts +4 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/stop-details.d.ts.map +1 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/stop-details.js +6 -0
- package/node_modules/@earendil-works/pi-ai/dist/utils/stop-details.js.map +1 -0
- package/node_modules/@earendil-works/pi-ai/package.json +1 -1
- package/node_modules/@earendil-works/pi-pty/package.json +1 -1
- package/node_modules/@earendil-works/pi-tui/package.json +1 -1
- package/package.json +6 -6
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface ToolProgressDetails {
|
|
2
|
+
readonly activity?: string;
|
|
3
|
+
readonly startedAt: number;
|
|
4
|
+
readonly maxWaitMs?: number;
|
|
5
|
+
}
|
|
6
|
+
export declare function readToolProgress(details: unknown): ToolProgressDetails | undefined;
|
|
7
|
+
export declare function formatToolProgressLine(progress: ToolProgressDetails, now: number, spinnerFrame?: number): string;
|
|
8
|
+
//# sourceMappingURL=tool-progress.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-progress.d.ts","sourceRoot":"","sources":["../../../src/modes/interactive/tool-progress.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,mBAAmB,GAAG,SAAS,CAYlF;AAED,wBAAgB,sBAAsB,CAAC,QAAQ,EAAE,mBAAmB,EAAE,GAAG,EAAE,MAAM,EAAE,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAOhH"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { formatWorkingElapsedSeconds } from "./working-status.js";
|
|
2
|
+
export function readToolProgress(details) {
|
|
3
|
+
if (typeof details !== "object" || details === null || !("progress" in details))
|
|
4
|
+
return undefined;
|
|
5
|
+
const progress = details.progress;
|
|
6
|
+
if (typeof progress !== "object" || progress === null || !("startedAt" in progress))
|
|
7
|
+
return undefined;
|
|
8
|
+
if (typeof progress.startedAt !== "number" || !Number.isFinite(progress.startedAt))
|
|
9
|
+
return undefined;
|
|
10
|
+
if ("activity" in progress && typeof progress.activity !== "string")
|
|
11
|
+
return undefined;
|
|
12
|
+
if ("maxWaitMs" in progress && (typeof progress.maxWaitMs !== "number" || !Number.isFinite(progress.maxWaitMs))) {
|
|
13
|
+
return undefined;
|
|
14
|
+
}
|
|
15
|
+
const activity = "activity" in progress && typeof progress.activity === "string" ? progress.activity : undefined;
|
|
16
|
+
const maxWaitMs = "maxWaitMs" in progress && typeof progress.maxWaitMs === "number" ? progress.maxWaitMs : undefined;
|
|
17
|
+
return { activity, startedAt: progress.startedAt, maxWaitMs };
|
|
18
|
+
}
|
|
19
|
+
export function formatToolProgressLine(progress, now, spinnerFrame) {
|
|
20
|
+
const activity = progress.activity || "working";
|
|
21
|
+
const elapsed = formatWorkingElapsedSeconds((now - progress.startedAt) / 1_000);
|
|
22
|
+
const maxWait = progress.maxWaitMs === undefined ? "" : ` / max ${Math.max(0, Math.floor(progress.maxWaitMs / 1_000))}s`;
|
|
23
|
+
const spinner = spinnerFrame === undefined ? "⏵" : ["⏵", "⏷", "⏴", "⏶"][spinnerFrame % 4];
|
|
24
|
+
return `${spinner} ${activity} · ${elapsed}${maxWait}`;
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=tool-progress.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-progress.js","sourceRoot":"","sources":["../../../src/modes/interactive/tool-progress.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AAQlE,MAAM,UAAU,gBAAgB,CAAC,OAAgB;IAChD,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,IAAI,CAAC,CAAC,UAAU,IAAI,OAAO,CAAC;QAAE,OAAO,SAAS,CAAC;IAClG,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;IAClC,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,KAAK,IAAI,IAAI,CAAC,CAAC,WAAW,IAAI,QAAQ,CAAC;QAAE,OAAO,SAAS,CAAC;IACtG,IAAI,OAAO,QAAQ,CAAC,SAAS,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC;QAAE,OAAO,SAAS,CAAC;IACrG,IAAI,UAAU,IAAI,QAAQ,IAAI,OAAO,QAAQ,CAAC,QAAQ,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IACtF,IAAI,WAAW,IAAI,QAAQ,IAAI,CAAC,OAAO,QAAQ,CAAC,SAAS,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC;QACjH,OAAO,SAAS,CAAC;IAClB,CAAC;IACD,MAAM,QAAQ,GAAG,UAAU,IAAI,QAAQ,IAAI,OAAO,QAAQ,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;IACjH,MAAM,SAAS,GAAG,WAAW,IAAI,QAAQ,IAAI,OAAO,QAAQ,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;IACrH,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAC,SAAS,EAAE,SAAS,EAAE,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,QAA6B,EAAE,GAAW,EAAE,YAAqB;IACvG,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,IAAI,SAAS,CAAC;IAChD,MAAM,OAAO,GAAG,2BAA2B,CAAC,CAAC,GAAG,GAAG,QAAQ,CAAC,SAAS,CAAC,GAAG,KAAK,CAAC,CAAC;IAChF,MAAM,OAAO,GACZ,QAAQ,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC;IAC1G,MAAM,OAAO,GAAG,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC;IAC1F,OAAO,GAAG,OAAO,IAAI,QAAQ,MAAM,OAAO,GAAG,OAAO,EAAE,CAAC;AACxD,CAAC","sourcesContent":["import { formatWorkingElapsedSeconds } from \"./working-status.ts\";\n\nexport interface ToolProgressDetails {\n\treadonly activity?: string;\n\treadonly startedAt: number;\n\treadonly maxWaitMs?: number;\n}\n\nexport function readToolProgress(details: unknown): ToolProgressDetails | undefined {\n\tif (typeof details !== \"object\" || details === null || !(\"progress\" in details)) return undefined;\n\tconst progress = details.progress;\n\tif (typeof progress !== \"object\" || progress === null || !(\"startedAt\" in progress)) return undefined;\n\tif (typeof progress.startedAt !== \"number\" || !Number.isFinite(progress.startedAt)) return undefined;\n\tif (\"activity\" in progress && typeof progress.activity !== \"string\") return undefined;\n\tif (\"maxWaitMs\" in progress && (typeof progress.maxWaitMs !== \"number\" || !Number.isFinite(progress.maxWaitMs))) {\n\t\treturn undefined;\n\t}\n\tconst activity = \"activity\" in progress && typeof progress.activity === \"string\" ? progress.activity : undefined;\n\tconst maxWaitMs = \"maxWaitMs\" in progress && typeof progress.maxWaitMs === \"number\" ? progress.maxWaitMs : undefined;\n\treturn { activity, startedAt: progress.startedAt, maxWaitMs };\n}\n\nexport function formatToolProgressLine(progress: ToolProgressDetails, now: number, spinnerFrame?: number): string {\n\tconst activity = progress.activity || \"working\";\n\tconst elapsed = formatWorkingElapsedSeconds((now - progress.startedAt) / 1_000);\n\tconst maxWait =\n\t\tprogress.maxWaitMs === undefined ? \"\" : ` / max ${Math.max(0, Math.floor(progress.maxWaitMs / 1_000))}s`;\n\tconst spinner = spinnerFrame === undefined ? \"⏵\" : [\"⏵\", \"⏷\", \"⏴\", \"⏶\"][spinnerFrame % 4];\n\treturn `${spinner} ${activity} · ${elapsed}${maxWait}`;\n}\n"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ToolExecutionComponent } from "./components/tool-execution.ts";
|
|
2
|
+
import type { ToolExecutionResult } from "./components/tool-execution-types.ts";
|
|
3
|
+
type ToolResultRevealComponent = Pick<ToolExecutionComponent, "updateResult">;
|
|
4
|
+
export type ToolResultRevealControllerOptions = {
|
|
5
|
+
readonly getSmoothStreaming: () => boolean;
|
|
6
|
+
readonly getSmoothStreamingFps: () => number;
|
|
7
|
+
readonly requestRender: () => void;
|
|
8
|
+
};
|
|
9
|
+
export declare class ToolResultRevealController {
|
|
10
|
+
#private;
|
|
11
|
+
constructor(options: ToolResultRevealControllerOptions);
|
|
12
|
+
update(id: string, component: ToolResultRevealComponent, partialResult: ToolExecutionResult): boolean;
|
|
13
|
+
finish(id: string): void;
|
|
14
|
+
refresh(): void;
|
|
15
|
+
stop(): void;
|
|
16
|
+
}
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=tool-result-reveal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-result-reveal.d.ts","sourceRoot":"","sources":["../../../src/modes/interactive/tool-result-reveal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AAC7E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAGhF,KAAK,yBAAyB,GAAG,IAAI,CAAC,sBAAsB,EAAE,cAAc,CAAC,CAAC;AAW9E,MAAM,MAAM,iCAAiC,GAAG;IAC/C,QAAQ,CAAC,kBAAkB,EAAE,MAAM,OAAO,CAAC;IAC3C,QAAQ,CAAC,qBAAqB,EAAE,MAAM,MAAM,CAAC;IAC7C,QAAQ,CAAC,aAAa,EAAE,MAAM,IAAI,CAAC;CACnC,CAAC;AAiBF,qBAAa,0BAA0B;;IAQtC,YAAY,OAAO,EAAE,iCAAiC,EAIrD;IAED,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,yBAAyB,EAAE,aAAa,EAAE,mBAAmB,GAAG,OAAO,CA+BpG;IAED,MAAM,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAMvB;IAED,OAAO,IAAI,IAAI,CAUd;IAED,IAAI,IAAI,IAAI,CAGX;CA0ED"}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { BlockUnitCounter, DEFAULT_SMOOTH_FPS, MAX_SMOOTH_FPS, MIN_SMOOTH_FPS, nextStep } from "./streaming-reveal.js";
|
|
2
|
+
function firstText(result) {
|
|
3
|
+
const block = result.content[0];
|
|
4
|
+
return block?.type === "text" ? block.text : undefined;
|
|
5
|
+
}
|
|
6
|
+
function displayResult(state, revealed = state.revealed) {
|
|
7
|
+
const first = state.target.content[0];
|
|
8
|
+
if (first?.type !== "text")
|
|
9
|
+
throw new Error("Expected a text tool result");
|
|
10
|
+
return {
|
|
11
|
+
content: [{ ...first, text: state.unitCounter.slice(0, state.text, revealed) }, ...state.target.content.slice(1)],
|
|
12
|
+
details: state.target.details,
|
|
13
|
+
isError: false,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export class ToolResultRevealController {
|
|
17
|
+
#getSmoothStreaming;
|
|
18
|
+
#getSmoothStreamingFps;
|
|
19
|
+
#requestRender;
|
|
20
|
+
#states = new Map();
|
|
21
|
+
#timer;
|
|
22
|
+
#timerFps;
|
|
23
|
+
constructor(options) {
|
|
24
|
+
this.#getSmoothStreaming = options.getSmoothStreaming;
|
|
25
|
+
this.#getSmoothStreamingFps = options.getSmoothStreamingFps;
|
|
26
|
+
this.#requestRender = options.requestRender;
|
|
27
|
+
}
|
|
28
|
+
update(id, component, partialResult) {
|
|
29
|
+
const text = firstText(partialResult);
|
|
30
|
+
if (!this.#getSmoothStreaming() || text === undefined) {
|
|
31
|
+
this.#discard(id);
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
const existing = this.#states.get(id);
|
|
35
|
+
if (existing === undefined || existing.component !== component || !text.startsWith(existing.text)) {
|
|
36
|
+
const state = {
|
|
37
|
+
component,
|
|
38
|
+
target: partialResult,
|
|
39
|
+
text,
|
|
40
|
+
revealed: 0,
|
|
41
|
+
lastTickAt: performance.now(),
|
|
42
|
+
unitCounter: new BlockUnitCounter(),
|
|
43
|
+
};
|
|
44
|
+
state.revealed = state.unitCounter.count(0, text);
|
|
45
|
+
component.updateResult(displayResult(state), true);
|
|
46
|
+
this.#states.set(id, state);
|
|
47
|
+
this.#syncTimer();
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
const wasCaughtUp = existing.revealed >= existing.unitCounter.count(0, existing.text);
|
|
51
|
+
existing.target = partialResult;
|
|
52
|
+
existing.text = text;
|
|
53
|
+
const total = existing.unitCounter.count(0, text);
|
|
54
|
+
if (wasCaughtUp && existing.revealed < total)
|
|
55
|
+
existing.lastTickAt = performance.now();
|
|
56
|
+
this.#syncTimer();
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
finish(id) {
|
|
60
|
+
const state = this.#states.get(id);
|
|
61
|
+
if (state === undefined)
|
|
62
|
+
return;
|
|
63
|
+
state.component.updateResult(displayResult(state, state.unitCounter.count(0, state.text)), true);
|
|
64
|
+
this.#states.delete(id);
|
|
65
|
+
this.#syncTimer();
|
|
66
|
+
}
|
|
67
|
+
refresh() {
|
|
68
|
+
if (!this.#getSmoothStreaming()) {
|
|
69
|
+
this.#flushAll();
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
if (!this.#hasBacklog()) {
|
|
73
|
+
this.#stopTimer();
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
this.#startTimer(true);
|
|
77
|
+
}
|
|
78
|
+
stop() {
|
|
79
|
+
this.#stopTimer();
|
|
80
|
+
this.#states.clear();
|
|
81
|
+
}
|
|
82
|
+
#discard(id) {
|
|
83
|
+
if (!this.#states.delete(id))
|
|
84
|
+
return;
|
|
85
|
+
this.#syncTimer();
|
|
86
|
+
}
|
|
87
|
+
#flushAll() {
|
|
88
|
+
for (const state of this.#states.values()) {
|
|
89
|
+
state.component.updateResult(displayResult(state, state.unitCounter.count(0, state.text)), true);
|
|
90
|
+
}
|
|
91
|
+
this.#states.clear();
|
|
92
|
+
this.#stopTimer();
|
|
93
|
+
}
|
|
94
|
+
#hasBacklog() {
|
|
95
|
+
for (const state of this.#states.values()) {
|
|
96
|
+
if (state.revealed < state.unitCounter.count(0, state.text))
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
#syncTimer() {
|
|
102
|
+
if (!this.#hasBacklog()) {
|
|
103
|
+
this.#stopTimer();
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
this.#startTimer(false);
|
|
107
|
+
}
|
|
108
|
+
#startTimer(restart) {
|
|
109
|
+
const configuredFps = this.#getSmoothStreamingFps();
|
|
110
|
+
const fps = Number.isFinite(configuredFps)
|
|
111
|
+
? Math.min(MAX_SMOOTH_FPS, Math.max(MIN_SMOOTH_FPS, configuredFps))
|
|
112
|
+
: DEFAULT_SMOOTH_FPS;
|
|
113
|
+
if (!restart && this.#timer !== undefined && this.#timerFps === fps)
|
|
114
|
+
return;
|
|
115
|
+
this.#stopTimer();
|
|
116
|
+
const now = performance.now();
|
|
117
|
+
for (const state of this.#states.values()) {
|
|
118
|
+
if (state.revealed < state.unitCounter.count(0, state.text))
|
|
119
|
+
state.lastTickAt = now;
|
|
120
|
+
}
|
|
121
|
+
const timer = setInterval(() => this.#tick(), 1000 / fps);
|
|
122
|
+
timer.unref();
|
|
123
|
+
this.#timer = timer;
|
|
124
|
+
this.#timerFps = fps;
|
|
125
|
+
}
|
|
126
|
+
#stopTimer() {
|
|
127
|
+
if (this.#timer !== undefined)
|
|
128
|
+
clearInterval(this.#timer);
|
|
129
|
+
this.#timer = undefined;
|
|
130
|
+
this.#timerFps = undefined;
|
|
131
|
+
}
|
|
132
|
+
#tick() {
|
|
133
|
+
if (!this.#getSmoothStreaming()) {
|
|
134
|
+
this.#flushAll();
|
|
135
|
+
this.#requestRender();
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
const now = performance.now();
|
|
139
|
+
let rendered = false;
|
|
140
|
+
for (const state of this.#states.values()) {
|
|
141
|
+
const total = state.unitCounter.count(0, state.text);
|
|
142
|
+
const backlog = total - state.revealed;
|
|
143
|
+
if (backlog <= 0)
|
|
144
|
+
continue;
|
|
145
|
+
state.revealed = Math.min(total, state.revealed + nextStep(backlog, now - state.lastTickAt));
|
|
146
|
+
state.lastTickAt = now;
|
|
147
|
+
state.component.updateResult(displayResult(state), true);
|
|
148
|
+
rendered = true;
|
|
149
|
+
}
|
|
150
|
+
if (rendered)
|
|
151
|
+
this.#requestRender();
|
|
152
|
+
this.#syncTimer();
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
//# sourceMappingURL=tool-result-reveal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tool-result-reveal.js","sourceRoot":"","sources":["../../../src/modes/interactive/tool-result-reveal.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ToolExecutionComponent } from \"./components/tool-execution.ts\";\nimport type { ToolExecutionResult } from \"./components/tool-execution-types.ts\";\nimport { BlockUnitCounter, DEFAULT_SMOOTH_FPS, MAX_SMOOTH_FPS, MIN_SMOOTH_FPS, nextStep } from \"./streaming-reveal.ts\";\n\ntype ToolResultRevealComponent = Pick<ToolExecutionComponent, \"updateResult\">;\n\ntype ToolResultRevealState = {\n\tcomponent: ToolResultRevealComponent;\n\ttarget: ToolExecutionResult;\n\ttext: string;\n\trevealed: number;\n\tlastTickAt: number;\n\tunitCounter: BlockUnitCounter;\n};\n\nexport type ToolResultRevealControllerOptions = {\n\treadonly getSmoothStreaming: () => boolean;\n\treadonly getSmoothStreamingFps: () => number;\n\treadonly requestRender: () => void;\n};\n\nfunction firstText(result: ToolExecutionResult): string | undefined {\n\tconst block = result.content[0];\n\treturn block?.type === \"text\" ? block.text : undefined;\n}\n\nfunction displayResult(state: ToolResultRevealState, revealed = state.revealed): ToolExecutionResult {\n\tconst first = state.target.content[0];\n\tif (first?.type !== \"text\") throw new Error(\"Expected a text tool result\");\n\treturn {\n\t\tcontent: [{ ...first, text: state.unitCounter.slice(0, state.text, revealed) }, ...state.target.content.slice(1)],\n\t\tdetails: state.target.details,\n\t\tisError: false,\n\t};\n}\n\nexport class ToolResultRevealController {\n\treadonly #getSmoothStreaming: () => boolean;\n\treadonly #getSmoothStreamingFps: () => number;\n\treadonly #requestRender: () => void;\n\treadonly #states = new Map<string, ToolResultRevealState>();\n\t#timer: NodeJS.Timeout | undefined;\n\t#timerFps: number | undefined;\n\n\tconstructor(options: ToolResultRevealControllerOptions) {\n\t\tthis.#getSmoothStreaming = options.getSmoothStreaming;\n\t\tthis.#getSmoothStreamingFps = options.getSmoothStreamingFps;\n\t\tthis.#requestRender = options.requestRender;\n\t}\n\n\tupdate(id: string, component: ToolResultRevealComponent, partialResult: ToolExecutionResult): boolean {\n\t\tconst text = firstText(partialResult);\n\t\tif (!this.#getSmoothStreaming() || text === undefined) {\n\t\t\tthis.#discard(id);\n\t\t\treturn false;\n\t\t}\n\n\t\tconst existing = this.#states.get(id);\n\t\tif (existing === undefined || existing.component !== component || !text.startsWith(existing.text)) {\n\t\t\tconst state: ToolResultRevealState = {\n\t\t\t\tcomponent,\n\t\t\t\ttarget: partialResult,\n\t\t\t\ttext,\n\t\t\t\trevealed: 0,\n\t\t\t\tlastTickAt: performance.now(),\n\t\t\t\tunitCounter: new BlockUnitCounter(),\n\t\t\t};\n\t\t\tstate.revealed = state.unitCounter.count(0, text);\n\t\t\tcomponent.updateResult(displayResult(state), true);\n\t\t\tthis.#states.set(id, state);\n\t\t\tthis.#syncTimer();\n\t\t\treturn true;\n\t\t}\n\n\t\tconst wasCaughtUp = existing.revealed >= existing.unitCounter.count(0, existing.text);\n\t\texisting.target = partialResult;\n\t\texisting.text = text;\n\t\tconst total = existing.unitCounter.count(0, text);\n\t\tif (wasCaughtUp && existing.revealed < total) existing.lastTickAt = performance.now();\n\t\tthis.#syncTimer();\n\t\treturn true;\n\t}\n\n\tfinish(id: string): void {\n\t\tconst state = this.#states.get(id);\n\t\tif (state === undefined) return;\n\t\tstate.component.updateResult(displayResult(state, state.unitCounter.count(0, state.text)), true);\n\t\tthis.#states.delete(id);\n\t\tthis.#syncTimer();\n\t}\n\n\trefresh(): void {\n\t\tif (!this.#getSmoothStreaming()) {\n\t\t\tthis.#flushAll();\n\t\t\treturn;\n\t\t}\n\t\tif (!this.#hasBacklog()) {\n\t\t\tthis.#stopTimer();\n\t\t\treturn;\n\t\t}\n\t\tthis.#startTimer(true);\n\t}\n\n\tstop(): void {\n\t\tthis.#stopTimer();\n\t\tthis.#states.clear();\n\t}\n\n\t#discard(id: string): void {\n\t\tif (!this.#states.delete(id)) return;\n\t\tthis.#syncTimer();\n\t}\n\n\t#flushAll(): void {\n\t\tfor (const state of this.#states.values()) {\n\t\t\tstate.component.updateResult(displayResult(state, state.unitCounter.count(0, state.text)), true);\n\t\t}\n\t\tthis.#states.clear();\n\t\tthis.#stopTimer();\n\t}\n\n\t#hasBacklog(): boolean {\n\t\tfor (const state of this.#states.values()) {\n\t\t\tif (state.revealed < state.unitCounter.count(0, state.text)) return true;\n\t\t}\n\t\treturn false;\n\t}\n\n\t#syncTimer(): void {\n\t\tif (!this.#hasBacklog()) {\n\t\t\tthis.#stopTimer();\n\t\t\treturn;\n\t\t}\n\t\tthis.#startTimer(false);\n\t}\n\n\t#startTimer(restart: boolean): void {\n\t\tconst configuredFps = this.#getSmoothStreamingFps();\n\t\tconst fps = Number.isFinite(configuredFps)\n\t\t\t? Math.min(MAX_SMOOTH_FPS, Math.max(MIN_SMOOTH_FPS, configuredFps))\n\t\t\t: DEFAULT_SMOOTH_FPS;\n\t\tif (!restart && this.#timer !== undefined && this.#timerFps === fps) return;\n\t\tthis.#stopTimer();\n\t\tconst now = performance.now();\n\t\tfor (const state of this.#states.values()) {\n\t\t\tif (state.revealed < state.unitCounter.count(0, state.text)) state.lastTickAt = now;\n\t\t}\n\t\tconst timer = setInterval(() => this.#tick(), 1000 / fps);\n\t\ttimer.unref();\n\t\tthis.#timer = timer;\n\t\tthis.#timerFps = fps;\n\t}\n\n\t#stopTimer(): void {\n\t\tif (this.#timer !== undefined) clearInterval(this.#timer);\n\t\tthis.#timer = undefined;\n\t\tthis.#timerFps = undefined;\n\t}\n\n\t#tick(): void {\n\t\tif (!this.#getSmoothStreaming()) {\n\t\t\tthis.#flushAll();\n\t\t\tthis.#requestRender();\n\t\t\treturn;\n\t\t}\n\n\t\tconst now = performance.now();\n\t\tlet rendered = false;\n\t\tfor (const state of this.#states.values()) {\n\t\t\tconst total = state.unitCounter.count(0, state.text);\n\t\t\tconst backlog = total - state.revealed;\n\t\t\tif (backlog <= 0) continue;\n\t\t\tstate.revealed = Math.min(total, state.revealed + nextStep(backlog, now - state.lastTickAt));\n\t\t\tstate.lastTickAt = now;\n\t\t\tstate.component.updateResult(displayResult(state), true);\n\t\t\trendered = true;\n\t\t}\n\t\tif (rendered) this.#requestRender();\n\t\tthis.#syncTimer();\n\t}\n}\n"]}
|
package/dist/utils/fs-watch.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { type FSWatcher, type WatchListener } from "node:fs";
|
|
1
|
+
import { type FSWatcher, type WatchListener, type WatchOptions } from "node:fs";
|
|
2
2
|
export declare const FS_WATCH_RETRY_DELAY_MS = 5000;
|
|
3
3
|
export declare function closeWatcher(watcher: FSWatcher | null | undefined): void;
|
|
4
|
-
export declare function watchWithErrorHandler(path: string, listener: WatchListener<string>, onError: () => void): FSWatcher | null;
|
|
4
|
+
export declare function watchWithErrorHandler(path: string, listener: WatchListener<string>, onError: () => void, options?: WatchOptions): FSWatcher | null;
|
|
5
5
|
//# sourceMappingURL=fs-watch.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fs-watch.d.ts","sourceRoot":"","sources":["../../src/utils/fs-watch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,aAAa,EAAS,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"fs-watch.d.ts","sourceRoot":"","sources":["../../src/utils/fs-watch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,KAAK,aAAa,EAAE,KAAK,YAAY,EAAS,MAAM,SAAS,CAAC;AAEvF,eAAO,MAAM,uBAAuB,OAAO,CAAC;AAE5C,wBAAgB,YAAY,CAAC,OAAO,EAAE,SAAS,GAAG,IAAI,GAAG,SAAS,GAAG,IAAI,CAUxE;AAED,wBAAgB,qBAAqB,CACpC,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,aAAa,CAAC,MAAM,CAAC,EAC/B,OAAO,EAAE,MAAM,IAAI,EACnB,OAAO,CAAC,EAAE,YAAY,GACpB,SAAS,GAAG,IAAI,CASlB"}
|
package/dist/utils/fs-watch.js
CHANGED
|
@@ -11,9 +11,9 @@ export function closeWatcher(watcher) {
|
|
|
11
11
|
// Ignore watcher close errors
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
|
-
export function watchWithErrorHandler(path, listener, onError) {
|
|
14
|
+
export function watchWithErrorHandler(path, listener, onError, options) {
|
|
15
15
|
try {
|
|
16
|
-
const watcher = watch(path, listener);
|
|
16
|
+
const watcher = watch(path, { ...options, encoding: "utf8" }, listener);
|
|
17
17
|
watcher.on("error", onError);
|
|
18
18
|
return watcher;
|
|
19
19
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fs-watch.js","sourceRoot":"","sources":["../../src/utils/fs-watch.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"fs-watch.js","sourceRoot":"","sources":["../../src/utils/fs-watch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyD,KAAK,EAAE,MAAM,SAAS,CAAC;AAEvF,MAAM,CAAC,MAAM,uBAAuB,GAAG,IAAI,CAAC;AAE5C,MAAM,UAAU,YAAY,CAAC,OAAqC;IACjE,IAAI,CAAC,OAAO,EAAE,CAAC;QACd,OAAO;IACR,CAAC;IAED,IAAI,CAAC;QACJ,OAAO,CAAC,KAAK,EAAE,CAAC;IACjB,CAAC;IAAC,MAAM,CAAC;QACR,8BAA8B;IAC/B,CAAC;AACF,CAAC;AAED,MAAM,UAAU,qBAAqB,CACpC,IAAY,EACZ,QAA+B,EAC/B,OAAmB,EACnB,OAAsB;IAEtB,IAAI,CAAC;QACJ,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,EAAE,GAAG,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,QAAQ,CAAC,CAAC;QACxE,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAC7B,OAAO,OAAO,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,EAAE,CAAC;QACV,OAAO,IAAI,CAAC;IACb,CAAC;AACF,CAAC","sourcesContent":["import { type FSWatcher, type WatchListener, type WatchOptions, watch } from \"node:fs\";\n\nexport const FS_WATCH_RETRY_DELAY_MS = 5000;\n\nexport function closeWatcher(watcher: FSWatcher | null | undefined): void {\n\tif (!watcher) {\n\t\treturn;\n\t}\n\n\ttry {\n\t\twatcher.close();\n\t} catch {\n\t\t// Ignore watcher close errors\n\t}\n}\n\nexport function watchWithErrorHandler(\n\tpath: string,\n\tlistener: WatchListener<string>,\n\tonError: () => void,\n\toptions?: WatchOptions,\n): FSWatcher | null {\n\ttry {\n\t\tconst watcher = watch(path, { ...options, encoding: \"utf8\" }, listener);\n\t\twatcher.on(\"error\", onError);\n\t\treturn watcher;\n\t} catch {\n\t\tonError();\n\t\treturn null;\n\t}\n}\n"]}
|
package/docs/extensions.md
CHANGED
|
@@ -12,6 +12,7 @@ Extensions are TypeScript modules that extend pi's behavior. They can subscribe
|
|
|
12
12
|
- **User interaction** - Prompt users via `ctx.ui` (select, confirm, input, notify)
|
|
13
13
|
- **Custom UI components** - Full TUI components with keyboard input via `ctx.ui.custom()` for complex interactions
|
|
14
14
|
- **Custom commands** - Register commands like `/mycommand` via `pi.registerCommand()`
|
|
15
|
+
- **Model fallback** - The bundled [`/fallback`](#bundled-fallback-command) command manages global per-model retry chains. Use `/fallback <target> <fallback1> [fallback2 ...]` for scripts, or `/fallback` in the TUI to view and edit chains. `--no-model-fallback` and `SENPI_NO_FALLBACK=1` disable it for one run.
|
|
15
16
|
- **Session persistence** - Store state that survives restarts via `pi.appendEntry()`
|
|
16
17
|
- **Custom rendering** - Control how tool calls/results and messages appear in TUI
|
|
17
18
|
|
|
@@ -31,6 +32,7 @@ See [examples/extensions/](../examples/extensions/) for working implementations.
|
|
|
31
32
|
## Table of Contents
|
|
32
33
|
|
|
33
34
|
- [Quick Start](#quick-start)
|
|
35
|
+
- [Bundled /fallback Command](#bundled-fallback-command)
|
|
34
36
|
- [Extension Locations](#extension-locations)
|
|
35
37
|
- [Available Imports](#available-imports)
|
|
36
38
|
- [Writing an Extension](#writing-an-extension)
|
|
@@ -45,6 +47,7 @@ See [examples/extensions/](../examples/extensions/) for working implementations.
|
|
|
45
47
|
- [ExtensionContext](#extensioncontext)
|
|
46
48
|
- [ExtensionCommandContext](#extensioncommandcontext)
|
|
47
49
|
- [ExtensionAPI Methods](#extensionapi-methods)
|
|
50
|
+
- [Config reload](#config-reload)
|
|
48
51
|
- [State Management](#state-management)
|
|
49
52
|
- [Custom Tools](#custom-tools)
|
|
50
53
|
- [Dynamic Tool Loading](#dynamic-tool-loading)
|
|
@@ -106,6 +109,32 @@ Test with `--extension` (or `-e`) flag:
|
|
|
106
109
|
pi -e ./my-extension.ts
|
|
107
110
|
```
|
|
108
111
|
|
|
112
|
+
## Bundled /fallback Command
|
|
113
|
+
|
|
114
|
+
The bundled `model-fallback` extension registers `/fallback` to manage global per-model retry fallback chains. The command writes through the active session settings manager, so a saved chain is available to the current session's next retry without restarting Senpi. See [Settings](settings.md#model-fallback-chains) for selector syntax and runtime behavior.
|
|
115
|
+
|
|
116
|
+
Use the quick-set form in scripts or any non-TUI mode:
|
|
117
|
+
|
|
118
|
+
```text
|
|
119
|
+
/fallback anthropic/claude-fable-5 ccapi/kimi-k3:max
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
The first argument is the exact primary model selector; each later argument is an ordered fallback selector. Quick-set validates selectors before saving. At least one fallback is required:
|
|
123
|
+
|
|
124
|
+
```text
|
|
125
|
+
/fallback <target> <fallback1> [fallback2 ...]
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Run `/fallback` without arguments in the TUI for a menu that can:
|
|
129
|
+
|
|
130
|
+
- show configured chains and live fallback state;
|
|
131
|
+
- add or edit a chain by choosing the target, each fallback, and either an explicit or inherited thinking level;
|
|
132
|
+
- remove a chain;
|
|
133
|
+
- toggle `retry.modelFallback`; and
|
|
134
|
+
- choose `retry.fallbackRevertPolicy` (`cooldown-expiry` or `never`).
|
|
135
|
+
|
|
136
|
+
Use quick-set in non-TUI modes; the no-argument menu requires interactive UI. Pass `--no-model-fallback` or set `SENPI_NO_FALLBACK=1` to disable fallback for that process without modifying saved settings.
|
|
137
|
+
|
|
109
138
|
## Extension Locations
|
|
110
139
|
|
|
111
140
|
> **Security:** Extensions run with your full system permissions and can execute arbitrary code. Only install from sources you trust.
|
|
@@ -1717,6 +1746,55 @@ pi.events.on("my:event", (data) => { ... });
|
|
|
1717
1746
|
pi.events.emit("my:event", { ... });
|
|
1718
1747
|
```
|
|
1719
1748
|
|
|
1749
|
+
## Config reload
|
|
1750
|
+
|
|
1751
|
+
Senpi's default-on `config-reload` builtin watches configured global surfaces and trusted project-local `.senpi` surfaces. A real content change requests the normal full session reload when the agent is idle; busy or compacting sessions defer it until a safe idle edge. Parseable built-in files (`settings.json`, `models.json`, and `keybindings.json`) are validated before reload, so a rejected edit keeps the running configuration active.
|
|
1752
|
+
|
|
1753
|
+
Configure it in `settings.json` with optional fields; omitted fields use the defaults shown here. Invalid `configReload` fields are ignored individually, so a malformed block falls back to these defaults rather than disabling watching:
|
|
1754
|
+
|
|
1755
|
+
```json
|
|
1756
|
+
{
|
|
1757
|
+
"configReload": {
|
|
1758
|
+
"enabled": true,
|
|
1759
|
+
"debounceMs": 200,
|
|
1760
|
+
"watch": {
|
|
1761
|
+
"settings": true,
|
|
1762
|
+
"models": true,
|
|
1763
|
+
"keybindings": true,
|
|
1764
|
+
"prompts": true,
|
|
1765
|
+
"skills": true,
|
|
1766
|
+
"extensions": true
|
|
1767
|
+
}
|
|
1768
|
+
}
|
|
1769
|
+
}
|
|
1770
|
+
```
|
|
1771
|
+
|
|
1772
|
+
`skills` covers skill paths declared in settings as well as trusted project skills. Themes, credentials, sessions, and reload logs are not watched. Project config surfaces require project trust.
|
|
1773
|
+
|
|
1774
|
+
### `config-watch:*` event protocol
|
|
1775
|
+
|
|
1776
|
+
Extensions can register additional reloadable surfaces on the shared in-process `pi.events` bus. The channels are `config-watch:register`, `config-watch:unregister`, `config-watch:ready`, `config-watch:changed`, `config-watch:reloaded`, and `config-watch:rejected`. Registrations with the same `id` are last-wins. The registration wire shape is:
|
|
1777
|
+
|
|
1778
|
+
```typescript
|
|
1779
|
+
{
|
|
1780
|
+
id: string;
|
|
1781
|
+
displayName: string;
|
|
1782
|
+
targets: Array<{
|
|
1783
|
+
path: string;
|
|
1784
|
+
kind: "file" | "dir";
|
|
1785
|
+
filterGlobs?: string[]; // simple name/suffix patterns, for example ["omo.json", "omo.jsonc"]
|
|
1786
|
+
}>;
|
|
1787
|
+
validate?: (changedPaths: readonly string[]) =>
|
|
1788
|
+
| { ok: true }
|
|
1789
|
+
| { ok: false; errors: string[] }
|
|
1790
|
+
| Promise<{ ok: true } | { ok: false; errors: string[] }>;
|
|
1791
|
+
}
|
|
1792
|
+
```
|
|
1793
|
+
|
|
1794
|
+
`config-watch:changed` emits `{ registrationId, paths, deferred }`; `config-watch:reloaded` emits `{ registrationId, paths }`; and `config-watch:rejected` emits `{ registrationId, paths, errors }`. `config-watch:ready` emits `{ enabled }`. Treat all event payloads as untrusted at the receiver boundary.
|
|
1795
|
+
|
|
1796
|
+
In TUI mode the builtin requests the host reload action and shows notifications. RPC hosts without a reload action intentionally run in degraded mode: watchers remain active and `config-watch:changed` still emits, but no reload is requested. Print mode starts no watchers so a short-lived process can exit normally.
|
|
1797
|
+
|
|
1720
1798
|
### pi.registerProvider(name, config)
|
|
1721
1799
|
|
|
1722
1800
|
Register or override a model provider dynamically. Useful for proxies, custom endpoints, or team-wide model configurations.
|
|
@@ -2898,7 +2976,7 @@ const highlighted = highlightCode(code, lang, theme);
|
|
|
2898
2976
|
| Interactive | `"tui"` | `true` | Full TUI with terminal rendering |
|
|
2899
2977
|
| RPC (`--mode rpc`) | `"rpc"` | `true` | Dialogs and notifications via JSON protocol; `custom()` returns `undefined`. See [rpc.md](rpc.md) |
|
|
2900
2978
|
| JSON (`--mode json`) | `"json"` | `false` | Event stream to stdout; UI methods are no-ops |
|
|
2901
|
-
| Print (`-p`) | `"print"` | `false` | Extensions run but can't prompt |
|
|
2979
|
+
| Print (`-p`) | `"print"` | `false` | Extensions run but can't prompt; `config-reload` deliberately starts no filesystem watchers |
|
|
2902
2980
|
|
|
2903
2981
|
Use `ctx.mode === "tui"` before TUI-specific features (`custom()`, component factories, terminal input). Use `ctx.hasUI` before dialog and notification methods that work in both TUI and RPC modes.
|
|
2904
2982
|
|
package/docs/mcp.md
CHANGED
|
@@ -87,6 +87,15 @@ Per-request timeout. Default `30000`.
|
|
|
87
87
|
### `connectTimeoutMs`
|
|
88
88
|
Connect + initialize handshake timeout. Default `15000`.
|
|
89
89
|
|
|
90
|
+
### `startupTimeoutMs`
|
|
91
|
+
Bounded startup window (ms) that a server's first connect + catalog fetch is
|
|
92
|
+
raced against during session attach. A server that does not settle inside the
|
|
93
|
+
window keeps connecting in the background and surfaces its tools when ready, so
|
|
94
|
+
a slow or wedged server never blocks the first turn. Default `250`. Set higher
|
|
95
|
+
to wait for tools before the first turn, `0` to never wait. The
|
|
96
|
+
`SENPI_MCP_STARTUP_TIMEOUT_MS` environment variable overrides this for every
|
|
97
|
+
server.
|
|
98
|
+
|
|
90
99
|
### `includeTools`
|
|
91
100
|
Glob allowlist (`*` wildcards) over server-side tool names. Default: all.
|
|
92
101
|
|
|
@@ -199,7 +208,7 @@ Extension-declared servers use bare names (no prefix).
|
|
|
199
208
|
| `degraded` | transient failure; auto-reconnect with backoff is running | wait, or `/mcp reconnect <name>` |
|
|
200
209
|
| tools missing | server filtered/disabled, or hidden behind search | check `includeTools`/`excludeTools`, ask the model to `tool_search` |
|
|
201
210
|
| child exits at spawn (EOF) | bad `command`/`args`/`env` | `/mcp logs <name>` shows the captured stderr |
|
|
202
|
-
| slow first call | lazy server cold boot | use `lifecycle:"eager"`
|
|
211
|
+
| slow first call | lazy server cold boot (tools attach in the background) | raise `startupTimeoutMs`, or use `lifecycle:"eager"` / `"keep-alive"` |
|
|
203
212
|
|
|
204
213
|
## Security notes
|
|
205
214
|
|
package/docs/models.md
CHANGED
|
@@ -209,6 +209,7 @@ If your command is slow, expensive, rate-limited, or should keep using a previou
|
|
|
209
209
|
| `contextWindow` | No | `128000` | Context window size in tokens |
|
|
210
210
|
| `maxTokens` | No | `16384` | Maximum output tokens |
|
|
211
211
|
| `cost` | No | all zeros | Per-million-token rates with optional request-wide input pricing tiers |
|
|
212
|
+
| `recoverTextToolCalls` | No | Claude ID default | Enables or disables recovery of leaked Claude XML tool calls from streamed assistant text. This is a top-level model field, not a `compat` field. |
|
|
212
213
|
| `compat` | No | provider `compat` | Provider compatibility overrides. Merged with provider-level `compat` when both are set. |
|
|
213
214
|
|
|
214
215
|
A cost tier supplies a complete alternate rate set and applies to the full request when total input usage (`input + cacheRead + cacheWrite`) exceeds `inputTokensAbove`. When multiple tiers match, the highest threshold wins.
|
|
@@ -237,6 +238,106 @@ Current behavior:
|
|
|
237
238
|
- `/model`, `--list-models`, and the interactive footer display entries by model `id`.
|
|
238
239
|
- The configured `name` is used for model matching and secondary model detail text. It does not replace the footer/status-bar model id.
|
|
239
240
|
|
|
241
|
+
## Claude text tool-call recovery
|
|
242
|
+
|
|
243
|
+
Some Claude-family models or compatible gateways may accidentally emit a
|
|
244
|
+
supported tool call as XML assistant text instead of a native provider tool
|
|
245
|
+
call. Senpi can recover these calls while the response is streaming, execute a
|
|
246
|
+
complete validated call through the normal agent loop, and persist it as native
|
|
247
|
+
tool-call history for the next request.
|
|
248
|
+
|
|
249
|
+
The setting is the top-level boolean `recoverTextToolCalls`. Non-boolean values
|
|
250
|
+
in `models.json` are rejected.
|
|
251
|
+
|
|
252
|
+
### Recovery activation precedence
|
|
253
|
+
|
|
254
|
+
| Priority | Condition | Result |
|
|
255
|
+
|----------|-----------|--------|
|
|
256
|
+
| 1 | The model has a configured text tool-call protocol | Disabled |
|
|
257
|
+
| 2 | `recoverTextToolCalls` is explicitly `true` or `false` | Configured boolean |
|
|
258
|
+
| 3 | The original selected model id matches the Claude boundary rule | Claude ID default |
|
|
259
|
+
|
|
260
|
+
The default boundary rule is
|
|
261
|
+
`/(^|[^a-z0-9])claude([^a-z0-9]|$)/i`. It is evaluated against the
|
|
262
|
+
original selected model id, before a provider alias or request hook rewrites
|
|
263
|
+
the wire model id. Recovery is provider/API independent and is skipped when
|
|
264
|
+
the request has no tools.
|
|
265
|
+
|
|
266
|
+
Explicitly disable recovery for a Claude model:
|
|
267
|
+
|
|
268
|
+
```json
|
|
269
|
+
{
|
|
270
|
+
"providers": {
|
|
271
|
+
"anthropic": {
|
|
272
|
+
"modelOverrides": {
|
|
273
|
+
"anthropic/claude-sonnet-4": {
|
|
274
|
+
"recoverTextToolCalls": false
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
Explicitly enable recovery for a non-Claude custom alias:
|
|
283
|
+
|
|
284
|
+
```json
|
|
285
|
+
{
|
|
286
|
+
"providers": {
|
|
287
|
+
"custom-proxy": {
|
|
288
|
+
"baseUrl": "https://proxy.example.com/v1",
|
|
289
|
+
"apiKey": "$CUSTOM_PROXY_KEY",
|
|
290
|
+
"api": "openai-completions",
|
|
291
|
+
"models": [
|
|
292
|
+
{
|
|
293
|
+
"id": "model-without-claude-name",
|
|
294
|
+
"recoverTextToolCalls": true
|
|
295
|
+
}
|
|
296
|
+
]
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
Text tool-call protocols retain exclusive ownership of text parsing. If
|
|
303
|
+
`toolCallFormat` resolves for a model, recovery stays disabled even when
|
|
304
|
+
`recoverTextToolCalls` is explicitly `true`.
|
|
305
|
+
|
|
306
|
+
### Recovery scan boundaries
|
|
307
|
+
|
|
308
|
+
| Content | Scanned | Behavior |
|
|
309
|
+
|---------|---------|----------|
|
|
310
|
+
| Ordinary assistant text | Yes | Supported leaked invokes may become native tool calls |
|
|
311
|
+
| Inline and fenced code | No | Preserved byte-for-byte as text |
|
|
312
|
+
| Thinking and redacted thinking | No | Preserved with signatures and metadata |
|
|
313
|
+
| Provider-native and native tool-call blocks | No | Passed through without XML inspection |
|
|
314
|
+
| Historical persisted messages | No | Replayed as stored; legacy XML text is not rewritten |
|
|
315
|
+
|
|
316
|
+
The recognized syntax is limited to bare `invoke`/`parameter`/`function_calls`
|
|
317
|
+
tags and their exact lowercase `antml:` variants. Unknown tools, ambiguous tool
|
|
318
|
+
names, unrelated tags, and arbitrary namespace prefixes remain text.
|
|
319
|
+
|
|
320
|
+
### Recovery outcomes
|
|
321
|
+
|
|
322
|
+
| Condition | Outcome |
|
|
323
|
+
|-----------|---------|
|
|
324
|
+
| Complete valid call | Execute once |
|
|
325
|
+
| Incomplete or invalid call | Do not execute |
|
|
326
|
+
| Caller abort | Interrupted; do not execute |
|
|
327
|
+
| Late native ID collision | Fail closed; do not execute |
|
|
328
|
+
|
|
329
|
+
An incomplete call is persisted as an incomplete native tool call and produces
|
|
330
|
+
a safe error result asking the model to re-issue complete arguments. A caller
|
|
331
|
+
abort always remains interrupted, even if a complete leaked call was already
|
|
332
|
+
recognized. Native/recovered ID collisions discovered after an event was
|
|
333
|
+
emitted terminate with an error instead of renaming provider IDs.
|
|
334
|
+
|
|
335
|
+
Recovered calls are persisted and replayed in each provider's native format.
|
|
336
|
+
Senpi does not migrate or rewrite older stored assistant text. The next
|
|
337
|
+
prompt-cache suffix may change after recovery because new messages contain
|
|
338
|
+
native tool-call history instead of leaked XML; that cache-key change is
|
|
339
|
+
expected.
|
|
340
|
+
|
|
240
341
|
### Thinking Level Map
|
|
241
342
|
|
|
242
343
|
Use `thinkingLevelMap` on a model to describe model-specific thinking controls. Keys are senpi thinking levels: `off`, `minimal`, `low`, `medium`, `high`, `xhigh`, `max`. Maps may contain holes; for example, a model can expose `high` and `max` without exposing `xhigh`.
|
|
@@ -340,7 +441,7 @@ Use `modelOverrides` to customize built-in models and matching extension-registe
|
|
|
340
441
|
}
|
|
341
442
|
```
|
|
342
443
|
|
|
343
|
-
`modelOverrides` supports these fields per model: `name`, `reasoning`, `thinkingLevelMap`, `input`, `cost` (partial), `contextWindow`, `maxTokens`, `headers`, `compat`.
|
|
444
|
+
`modelOverrides` supports these fields per model: `name`, `reasoning`, `thinkingLevelMap`, `input`, `cost` (partial), `contextWindow`, `maxTokens`, `headers`, `recoverTextToolCalls`, `compat`.
|
|
344
445
|
|
|
345
446
|
Direct OpenAI GPT-5.6 Sol, Terra, and Luna default to a `272000` context window so requests remain within OpenAI's short-context pricing tier. To opt into OpenAI's 1.05M context window, increase it for each model you use:
|
|
346
447
|
|
package/docs/providers.md
CHANGED
|
@@ -91,6 +91,7 @@ pi
|
|
|
91
91
|
| Xiaomi MiMo Token Plan (China) | `XIAOMI_TOKEN_PLAN_CN_API_KEY` | `xiaomi-token-plan-cn` |
|
|
92
92
|
| Xiaomi MiMo Token Plan (Amsterdam) | `XIAOMI_TOKEN_PLAN_AMS_API_KEY` | `xiaomi-token-plan-ams` |
|
|
93
93
|
| Xiaomi MiMo Token Plan (Singapore) | `XIAOMI_TOKEN_PLAN_SGP_API_KEY` | `xiaomi-token-plan-sgp` |
|
|
94
|
+
| Alibaba Token Plan (ap-southeast-1) | `ALIBABA_TOKEN_PLAN_API_KEY` | `alibaba-token-plan` |
|
|
94
95
|
|
|
95
96
|
Reference for environment variables and `auth.json` keys: [`const envMap`](https://github.com/earendil-works/pi-mono/blob/main/packages/ai/src/env-api-keys.ts) in [`packages/ai/src/env-api-keys.ts`](https://github.com/earendil-works/pi-mono/blob/main/packages/ai/src/env-api-keys.ts).
|
|
96
97
|
|
|
@@ -112,7 +113,8 @@ Store credentials in `~/.pi/agent/auth.json`:
|
|
|
112
113
|
"xiaomi": { "type": "api_key", "key": "..." },
|
|
113
114
|
"xiaomi-token-plan-cn": { "type": "api_key", "key": "..." },
|
|
114
115
|
"xiaomi-token-plan-ams": { "type": "api_key", "key": "..." },
|
|
115
|
-
"xiaomi-token-plan-sgp": { "type": "api_key", "key": "..." }
|
|
116
|
+
"xiaomi-token-plan-sgp": { "type": "api_key", "key": "..." },
|
|
117
|
+
"alibaba-token-plan": { "type": "api_key", "key": "..." }
|
|
116
118
|
}
|
|
117
119
|
```
|
|
118
120
|
|
package/docs/settings.md
CHANGED
|
@@ -206,6 +206,9 @@ Set `PI_SKIP_VERSION_CHECK=1` to disable the senpi version update check. Use `--
|
|
|
206
206
|
| `retry.enabled` | boolean | `true` | Enable automatic agent-level retry on transient errors |
|
|
207
207
|
| `retry.maxRetries` | number | `3` | Maximum agent-level retry attempts |
|
|
208
208
|
| `retry.baseDelayMs` | number | `2000` | Base delay for agent-level exponential backoff (2s, 4s, 8s) |
|
|
209
|
+
| `retry.modelFallback` | boolean | `true` | Let eligible retry failures advance through configured per-model fallback chains |
|
|
210
|
+
| `retry.fallbackChains` | `Record<string, string[]>` | `{}` | Ordered exact model-selector to fallback-selector chains |
|
|
211
|
+
| `retry.fallbackRevertPolicy` | `"cooldown-expiry"` \| `"never"` | `"cooldown-expiry"` | Automatic primary-model restoration policy |
|
|
209
212
|
| `retry.provider.timeoutMs` | number | `300000` | Provider/SDK request timeout and stream idle timeout in milliseconds |
|
|
210
213
|
| `retry.provider.maxRetries` | number | `0` | Provider/SDK retry attempts |
|
|
211
214
|
| `retry.provider.maxRetryDelayMs` | number | `60000` | Max server-requested delay before failing (60s) |
|
|
@@ -229,6 +232,38 @@ Keep `retry.provider.maxRetries` at `0` unless provider-level retries are explic
|
|
|
229
232
|
}
|
|
230
233
|
```
|
|
231
234
|
|
|
235
|
+
#### Model fallback chains
|
|
236
|
+
|
|
237
|
+
`retry.fallbackChains` maps one exact primary-model selector to an ordered list of fallback selectors. A selector is `provider/model` with an optional `:thinking-level` suffix. For example, this switches Fable 5 to Kimi K3 at `max` thinking when an eligible failure occurs:
|
|
238
|
+
|
|
239
|
+
```json
|
|
240
|
+
{
|
|
241
|
+
"retry": {
|
|
242
|
+
"modelFallback": true,
|
|
243
|
+
"fallbackChains": {
|
|
244
|
+
"anthropic/claude-fable-5": ["ccapi/kimi-k3:max"]
|
|
245
|
+
},
|
|
246
|
+
"fallbackRevertPolicy": "cooldown-expiry"
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
A chain is only for the exact primary model it names: selector lookup first considers an exact thinking-level selector, then the same `provider/model` without its thinking suffix. Wildcard selectors, role keys such as `default`, and other catch-all chains are not supported.
|
|
252
|
+
|
|
253
|
+
A fallback entry with `:thinking-level` requests that level on the target model; a bare entry inherits the current thinking level. Either value is clamped to the target model's supported levels. When an unpinned fallback later returns to the primary, it restores the original thinking level unless you changed it while using the fallback.
|
|
254
|
+
|
|
255
|
+
`/fallback` writes these settings to the global settings file. Project settings are still merged when read; because `fallbackChains` is a nested map, a project `retry.fallbackChains` replaces the global map rather than merging individual chain keys.
|
|
256
|
+
|
|
257
|
+
#### Fallback behavior and diagnostics
|
|
258
|
+
|
|
259
|
+
With `retry.enabled` and `retry.modelFallback` enabled, Senpi can switch from a transient or eligible hard provider failure to the next configured candidate. The switch continues the current turn without changing the existing conversation prefix, preserving prompt-cache inputs; fallback lifecycle events are never added to model context. Returning to a primary model happens only at a turn boundary, never while a response is streaming.
|
|
260
|
+
|
|
261
|
+
Anthropic streaming refusals are identified from typed `stopDetails`. A configured candidate receives an immediate **pinned** fallback switch with a user-visible fallback notice: Senpi does not retry the refusing model and a pinned fallback never auto-reverts. Set `retry.fallbackRevertPolicy` to `"cooldown-expiry"` (the default) to return an unpinned fallback to its primary after the primary's cooldown expires, or `"never"` to keep the fallback until you change models.
|
|
262
|
+
|
|
263
|
+
Fallback decisions are process-local. A `senpi-task` or subagent child process reads its own settings and maintains its own in-memory suppression state; it does not affect its parent process. Disable fallback for one run without changing settings with `--no-model-fallback` or `SENPI_NO_FALLBACK=1`.
|
|
264
|
+
|
|
265
|
+
For diagnostics, Senpi writes sanitized NDJSON records for candidate skips, cooldowns, switches, reverts, manual clears, and validation warnings to `<agentDir>/logs/fallback.log`. The file is mode `0600` and rotates at 5 MB (`fallback.log.1`).
|
|
266
|
+
|
|
232
267
|
### Message Delivery
|
|
233
268
|
|
|
234
269
|
| Setting | Type | Default | Description |
|