@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,151 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { basename, extname, isAbsolute, resolve } from "node:path";
|
|
3
|
+
import { processImage } from "../../../../utils/image-process.js";
|
|
4
|
+
export const IMAGE_ATTACHMENT_REFERENCE_REGEX = /^\s*(?:\[?Image #([1-9]\d*)(?:,[^\]\n]*)?\]?|(?:attachment|image):\/\/([1-9]\d*))\s*$/i;
|
|
5
|
+
const MAX_IMAGE_BYTES = 10 * 1024 * 1024;
|
|
6
|
+
const MAX_TOTAL_BYTES = 25 * 1024 * 1024;
|
|
7
|
+
const EXTENSION_MIME_TYPES = {
|
|
8
|
+
".gif": "image/gif",
|
|
9
|
+
".jpeg": "image/jpeg",
|
|
10
|
+
".jpg": "image/jpeg",
|
|
11
|
+
".json": "application/json",
|
|
12
|
+
".pdf": "application/pdf",
|
|
13
|
+
".png": "image/png",
|
|
14
|
+
".txt": "text/plain",
|
|
15
|
+
".webp": "image/webp",
|
|
16
|
+
};
|
|
17
|
+
export function parseImageAttachmentReference(input) {
|
|
18
|
+
const match = IMAGE_ATTACHMENT_REFERENCE_REGEX.exec(input);
|
|
19
|
+
const rawIndex = match?.[1] ?? match?.[2];
|
|
20
|
+
return rawIndex ? { index: Number(rawIndex) } : null;
|
|
21
|
+
}
|
|
22
|
+
function detectMimeType(bytes) {
|
|
23
|
+
if (startsWith(bytes, [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a]))
|
|
24
|
+
return "image/png";
|
|
25
|
+
if (startsWith(bytes, [0xff, 0xd8, 0xff]))
|
|
26
|
+
return "image/jpeg";
|
|
27
|
+
if (startsWithAscii(bytes, 0, "GIF8"))
|
|
28
|
+
return "image/gif";
|
|
29
|
+
if (startsWithAscii(bytes, 0, "RIFF") && startsWithAscii(bytes, 8, "WEBP"))
|
|
30
|
+
return "image/webp";
|
|
31
|
+
if (startsWithAscii(bytes, 0, "%PDF-"))
|
|
32
|
+
return "application/pdf";
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
function startsWith(bytes, signature) {
|
|
36
|
+
return signature.every((byte, index) => bytes[index] === byte);
|
|
37
|
+
}
|
|
38
|
+
function startsWithAscii(bytes, offset, text) {
|
|
39
|
+
return text.split("").every((character, index) => bytes[offset + index] === character.charCodeAt(0));
|
|
40
|
+
}
|
|
41
|
+
function mimeTypeFromName(name) {
|
|
42
|
+
return EXTENSION_MIME_TYPES[extname(name).toLowerCase()];
|
|
43
|
+
}
|
|
44
|
+
function parseBase64(input) {
|
|
45
|
+
const match = /^data:([^;,]+)(?:;[^,]*)?,(.*)$/is.exec(input);
|
|
46
|
+
return match ? { data: match[2], mimeType: match[1].toLowerCase() } : { data: input, mimeType: undefined };
|
|
47
|
+
}
|
|
48
|
+
function decodeBase64(input) {
|
|
49
|
+
const data = Buffer.from(input, "base64");
|
|
50
|
+
if (data.length === 0 && input.trim().length > 0) {
|
|
51
|
+
throw new Error("Error: Could not decode base64 input.");
|
|
52
|
+
}
|
|
53
|
+
return data;
|
|
54
|
+
}
|
|
55
|
+
function lastUserImages(ctx) {
|
|
56
|
+
const branch = ctx.sessionManager.getBranch();
|
|
57
|
+
for (let index = branch.length - 1; index >= 0; index--) {
|
|
58
|
+
const entry = branch[index];
|
|
59
|
+
if (entry.type !== "message" || entry.message.role !== "user")
|
|
60
|
+
continue;
|
|
61
|
+
return Array.isArray(entry.message.content)
|
|
62
|
+
? entry.message.content.filter((block) => block.type === "image")
|
|
63
|
+
: [];
|
|
64
|
+
}
|
|
65
|
+
return [];
|
|
66
|
+
}
|
|
67
|
+
function availableAttachmentError(input, images) {
|
|
68
|
+
if (images.length === 0) {
|
|
69
|
+
return new Error(`Error: No image attachments are available in this turn. "${input}" must be a readable file path or attachment URI.`);
|
|
70
|
+
}
|
|
71
|
+
const available = images.map((_, index) => `Image #${index + 1} -> attachment://${index + 1}`).join(", ");
|
|
72
|
+
return new Error(`Error: Could not resolve image attachment '${input}'. Available image attachments: ${available}.`);
|
|
73
|
+
}
|
|
74
|
+
async function finalizeInput(ctx, input) {
|
|
75
|
+
if (input.bytes.byteLength > MAX_IMAGE_BYTES) {
|
|
76
|
+
throw new Error("Error: Input exceeds the 10MiB per-image limit.");
|
|
77
|
+
}
|
|
78
|
+
const mimeType = detectMimeType(input.bytes) ?? input.mimeType;
|
|
79
|
+
if (!mimeType)
|
|
80
|
+
throw new Error(`Error: Could not determine MIME type for ${input.label}.`);
|
|
81
|
+
if (!mimeType.startsWith("image/") || !ctx.getImageSettings().autoResize) {
|
|
82
|
+
return {
|
|
83
|
+
data: Buffer.from(input.bytes).toString("base64"),
|
|
84
|
+
inputBytes: input.bytes.byteLength,
|
|
85
|
+
label: input.label,
|
|
86
|
+
mimeType,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
const processed = await processImage(input.bytes, mimeType, { autoResizeImages: true });
|
|
90
|
+
if (!processed.ok)
|
|
91
|
+
throw new Error(`Error: Could not process image ${input.label}: ${processed.message}`);
|
|
92
|
+
return {
|
|
93
|
+
data: processed.data,
|
|
94
|
+
inputBytes: input.bytes.byteLength,
|
|
95
|
+
label: input.label,
|
|
96
|
+
mimeType: processed.mimeType,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
async function loadPathInput(ctx, input) {
|
|
100
|
+
if (/^https?:\/\//i.test(input)) {
|
|
101
|
+
throw new Error("Error: Remote URLs are not supported; download first, use local path.");
|
|
102
|
+
}
|
|
103
|
+
const reference = parseImageAttachmentReference(input);
|
|
104
|
+
if (reference) {
|
|
105
|
+
const images = lastUserImages(ctx);
|
|
106
|
+
const image = images[reference.index - 1];
|
|
107
|
+
if (!image)
|
|
108
|
+
throw availableAttachmentError(input, images);
|
|
109
|
+
return finalizeInput(ctx, {
|
|
110
|
+
bytes: decodeBase64(image.data),
|
|
111
|
+
label: `Image #${reference.index}`,
|
|
112
|
+
mimeType: image.mimeType.toLowerCase(),
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
const path = isAbsolute(input) ? input : resolve(ctx.cwd, input);
|
|
116
|
+
try {
|
|
117
|
+
return await finalizeInput(ctx, {
|
|
118
|
+
bytes: await readFile(path),
|
|
119
|
+
label: basename(path),
|
|
120
|
+
mimeType: mimeTypeFromName(path),
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
if (isErrno(error, "ENOENT"))
|
|
125
|
+
throw new Error(`Error: File not found: ${input}`);
|
|
126
|
+
throw error;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
function isErrno(error, code) {
|
|
130
|
+
return error instanceof Error && "code" in error && error.code === code;
|
|
131
|
+
}
|
|
132
|
+
export async function loadLookAtInputs(ctx, paths, base64Inputs) {
|
|
133
|
+
if (ctx.getImageSettings().blockImages)
|
|
134
|
+
throw new Error("Error: Image inputs are blocked by settings.");
|
|
135
|
+
const loaded = await Promise.all([
|
|
136
|
+
...paths.map((path) => loadPathInput(ctx, path)),
|
|
137
|
+
...base64Inputs.map(async (input) => {
|
|
138
|
+
const base64 = parseBase64(input);
|
|
139
|
+
return finalizeInput(ctx, {
|
|
140
|
+
bytes: decodeBase64(base64.data),
|
|
141
|
+
label: "base64 input",
|
|
142
|
+
mimeType: base64.mimeType,
|
|
143
|
+
});
|
|
144
|
+
}),
|
|
145
|
+
]);
|
|
146
|
+
const totalBytes = loaded.reduce((total, input) => total + input.inputBytes, 0);
|
|
147
|
+
if (totalBytes > MAX_TOTAL_BYTES)
|
|
148
|
+
throw new Error("Error: Inputs exceed the 25MiB aggregate limit.");
|
|
149
|
+
return loaded.map(({ inputBytes: _, ...input }) => input);
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=image-input.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"image-input.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/look-at/image-input.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport { basename, extname, isAbsolute, resolve } from \"node:path\";\nimport type { ImageContent } from \"@earendil-works/pi-ai\";\nimport { processImage } from \"../../../../utils/image-process.ts\";\nimport type { ReadonlySessionManager } from \"../../../session-manager.ts\";\n\nexport const IMAGE_ATTACHMENT_REFERENCE_REGEX =\n\t/^\\s*(?:\\[?Image #([1-9]\\d*)(?:,[^\\]\\n]*)?\\]?|(?:attachment|image):\\/\\/([1-9]\\d*))\\s*$/i;\n\nconst MAX_IMAGE_BYTES = 10 * 1024 * 1024;\nconst MAX_TOTAL_BYTES = 25 * 1024 * 1024;\n\nconst EXTENSION_MIME_TYPES: Readonly<Record<string, string>> = {\n\t\".gif\": \"image/gif\",\n\t\".jpeg\": \"image/jpeg\",\n\t\".jpg\": \"image/jpeg\",\n\t\".json\": \"application/json\",\n\t\".pdf\": \"application/pdf\",\n\t\".png\": \"image/png\",\n\t\".txt\": \"text/plain\",\n\t\".webp\": \"image/webp\",\n};\n\nexport interface LookAtImageInputContext {\n\tcwd: string;\n\tsessionManager: Pick<ReadonlySessionManager, \"getBranch\">;\n\tgetImageSettings(): { autoResize: boolean; blockImages: boolean };\n}\n\nexport interface LoadedLookAtInput {\n\tdata: string;\n\tlabel: string;\n\tmimeType: string;\n}\n\nexport interface AttachmentReference {\n\tindex: number;\n}\n\nexport function parseImageAttachmentReference(input: string): AttachmentReference | null {\n\tconst match = IMAGE_ATTACHMENT_REFERENCE_REGEX.exec(input);\n\tconst rawIndex = match?.[1] ?? match?.[2];\n\treturn rawIndex ? { index: Number(rawIndex) } : null;\n}\n\nfunction detectMimeType(bytes: Uint8Array): string | undefined {\n\tif (startsWith(bytes, [0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0a])) return \"image/png\";\n\tif (startsWith(bytes, [0xff, 0xd8, 0xff])) return \"image/jpeg\";\n\tif (startsWithAscii(bytes, 0, \"GIF8\")) return \"image/gif\";\n\tif (startsWithAscii(bytes, 0, \"RIFF\") && startsWithAscii(bytes, 8, \"WEBP\")) return \"image/webp\";\n\tif (startsWithAscii(bytes, 0, \"%PDF-\")) return \"application/pdf\";\n\treturn undefined;\n}\n\nfunction startsWith(bytes: Uint8Array, signature: readonly number[]): boolean {\n\treturn signature.every((byte, index) => bytes[index] === byte);\n}\n\nfunction startsWithAscii(bytes: Uint8Array, offset: number, text: string): boolean {\n\treturn text.split(\"\").every((character, index) => bytes[offset + index] === character.charCodeAt(0));\n}\n\nfunction mimeTypeFromName(name: string): string | undefined {\n\treturn EXTENSION_MIME_TYPES[extname(name).toLowerCase()];\n}\n\nfunction parseBase64(input: string): { data: string; mimeType: string | undefined } {\n\tconst match = /^data:([^;,]+)(?:;[^,]*)?,(.*)$/is.exec(input);\n\treturn match ? { data: match[2], mimeType: match[1].toLowerCase() } : { data: input, mimeType: undefined };\n}\n\nfunction decodeBase64(input: string): Uint8Array {\n\tconst data = Buffer.from(input, \"base64\");\n\tif (data.length === 0 && input.trim().length > 0) {\n\t\tthrow new Error(\"Error: Could not decode base64 input.\");\n\t}\n\treturn data;\n}\n\nfunction lastUserImages(ctx: LookAtImageInputContext): readonly ImageContent[] {\n\tconst branch = ctx.sessionManager.getBranch();\n\tfor (let index = branch.length - 1; index >= 0; index--) {\n\t\tconst entry = branch[index];\n\t\tif (entry.type !== \"message\" || entry.message.role !== \"user\") continue;\n\t\treturn Array.isArray(entry.message.content)\n\t\t\t? entry.message.content.filter((block): block is ImageContent => block.type === \"image\")\n\t\t\t: [];\n\t}\n\treturn [];\n}\n\nfunction availableAttachmentError(input: string, images: readonly ImageContent[]): Error {\n\tif (images.length === 0) {\n\t\treturn new Error(\n\t\t\t`Error: No image attachments are available in this turn. \"${input}\" must be a readable file path or attachment URI.`,\n\t\t);\n\t}\n\tconst available = images.map((_, index) => `Image #${index + 1} -> attachment://${index + 1}`).join(\", \");\n\treturn new Error(`Error: Could not resolve image attachment '${input}'. Available image attachments: ${available}.`);\n}\n\ninterface LoadedInput extends LoadedLookAtInput {\n\tinputBytes: number;\n}\n\nasync function finalizeInput(\n\tctx: LookAtImageInputContext,\n\tinput: { bytes: Uint8Array; label: string; mimeType: string | undefined },\n): Promise<LoadedInput> {\n\tif (input.bytes.byteLength > MAX_IMAGE_BYTES) {\n\t\tthrow new Error(\"Error: Input exceeds the 10MiB per-image limit.\");\n\t}\n\tconst mimeType = detectMimeType(input.bytes) ?? input.mimeType;\n\tif (!mimeType) throw new Error(`Error: Could not determine MIME type for ${input.label}.`);\n\tif (!mimeType.startsWith(\"image/\") || !ctx.getImageSettings().autoResize) {\n\t\treturn {\n\t\t\tdata: Buffer.from(input.bytes).toString(\"base64\"),\n\t\t\tinputBytes: input.bytes.byteLength,\n\t\t\tlabel: input.label,\n\t\t\tmimeType,\n\t\t};\n\t}\n\tconst processed = await processImage(input.bytes, mimeType, { autoResizeImages: true });\n\tif (!processed.ok) throw new Error(`Error: Could not process image ${input.label}: ${processed.message}`);\n\treturn {\n\t\tdata: processed.data,\n\t\tinputBytes: input.bytes.byteLength,\n\t\tlabel: input.label,\n\t\tmimeType: processed.mimeType,\n\t};\n}\n\nasync function loadPathInput(ctx: LookAtImageInputContext, input: string): Promise<LoadedInput> {\n\tif (/^https?:\\/\\//i.test(input)) {\n\t\tthrow new Error(\"Error: Remote URLs are not supported; download first, use local path.\");\n\t}\n\tconst reference = parseImageAttachmentReference(input);\n\tif (reference) {\n\t\tconst images = lastUserImages(ctx);\n\t\tconst image = images[reference.index - 1];\n\t\tif (!image) throw availableAttachmentError(input, images);\n\t\treturn finalizeInput(ctx, {\n\t\t\tbytes: decodeBase64(image.data),\n\t\t\tlabel: `Image #${reference.index}`,\n\t\t\tmimeType: image.mimeType.toLowerCase(),\n\t\t});\n\t}\n\tconst path = isAbsolute(input) ? input : resolve(ctx.cwd, input);\n\ttry {\n\t\treturn await finalizeInput(ctx, {\n\t\t\tbytes: await readFile(path),\n\t\t\tlabel: basename(path),\n\t\t\tmimeType: mimeTypeFromName(path),\n\t\t});\n\t} catch (error) {\n\t\tif (isErrno(error, \"ENOENT\")) throw new Error(`Error: File not found: ${input}`);\n\t\tthrow error;\n\t}\n}\n\nfunction isErrno(error: unknown, code: string): boolean {\n\treturn error instanceof Error && \"code\" in error && error.code === code;\n}\n\nexport async function loadLookAtInputs(\n\tctx: LookAtImageInputContext,\n\tpaths: readonly string[],\n\tbase64Inputs: readonly string[],\n): Promise<LoadedLookAtInput[]> {\n\tif (ctx.getImageSettings().blockImages) throw new Error(\"Error: Image inputs are blocked by settings.\");\n\tconst loaded = await Promise.all([\n\t\t...paths.map((path) => loadPathInput(ctx, path)),\n\t\t...base64Inputs.map(async (input) => {\n\t\t\tconst base64 = parseBase64(input);\n\t\t\treturn finalizeInput(ctx, {\n\t\t\t\tbytes: decodeBase64(base64.data),\n\t\t\t\tlabel: \"base64 input\",\n\t\t\t\tmimeType: base64.mimeType,\n\t\t\t});\n\t\t}),\n\t]);\n\tconst totalBytes = loaded.reduce((total, input) => total + input.inputBytes, 0);\n\tif (totalBytes > MAX_TOTAL_BYTES) throw new Error(\"Error: Inputs exceed the 25MiB aggregate limit.\");\n\treturn loaded.map(({ inputBytes: _, ...input }) => input);\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/look-at/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAoB,MAAM,gBAAgB,CAAC;AAWrE,MAAM,CAAC,OAAO,UAAU,eAAe,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAoD9D"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { LOOK_AT_PARAMETERS, normalizeLookAtArgs, prepareLookAtArguments, validateLookAtArgs } from "./arguments.js";
|
|
2
|
+
import { registerLookAtCommand } from "./commands.js";
|
|
3
|
+
import { resolveVisionModel } from "./model-selector.js";
|
|
4
|
+
import { LOOK_AT_DESCRIPTION, LOOK_AT_PROMPT_SNIPPET } from "./prompts.js";
|
|
5
|
+
import { renderLookAtCall, renderLookAtResult } from "./render.js";
|
|
6
|
+
import { runLookAt } from "./runner.js";
|
|
7
|
+
import { createLookAtStore, loadLookAtChain, loadLookAtEnabled } from "./settings.js";
|
|
8
|
+
const TOOL_NAME = "look_at";
|
|
9
|
+
export default function lookAtExtension(pi) {
|
|
10
|
+
const store = createLookAtStore();
|
|
11
|
+
pi.registerTool({
|
|
12
|
+
name: TOOL_NAME,
|
|
13
|
+
label: "Look At",
|
|
14
|
+
description: LOOK_AT_DESCRIPTION,
|
|
15
|
+
promptSnippet: LOOK_AT_PROMPT_SNIPPET,
|
|
16
|
+
parameters: LOOK_AT_PARAMETERS,
|
|
17
|
+
prepareArguments: prepareLookAtArguments,
|
|
18
|
+
async execute(_toolCallId, params, signal, _onUpdate, ctx) {
|
|
19
|
+
const normalized = normalizeLookAtArgs(params);
|
|
20
|
+
const validationError = validateLookAtArgs(normalized);
|
|
21
|
+
if (validationError)
|
|
22
|
+
throw new Error(validationError);
|
|
23
|
+
const result = await runLookAt(normalized, signal, ctx, store);
|
|
24
|
+
return {
|
|
25
|
+
content: [{ type: "text", text: result.text }],
|
|
26
|
+
details: { model: result.model, sources: result.sources, mimeTypes: result.mimeTypes },
|
|
27
|
+
};
|
|
28
|
+
},
|
|
29
|
+
renderCall: renderLookAtCall,
|
|
30
|
+
renderResult: renderLookAtResult,
|
|
31
|
+
});
|
|
32
|
+
function syncToolActivation(ctx) {
|
|
33
|
+
const active = pi.getActiveTools();
|
|
34
|
+
const shouldBeActive = loadLookAtEnabled(ctx, store) &&
|
|
35
|
+
ctx.model !== undefined &&
|
|
36
|
+
!ctx.model.input.includes("image") &&
|
|
37
|
+
resolveVisionModel(loadLookAtChain(ctx, store), ctx.modelRegistry.getAvailable()) !== undefined;
|
|
38
|
+
const isActive = active.includes(TOOL_NAME);
|
|
39
|
+
if (shouldBeActive && !isActive) {
|
|
40
|
+
pi.setActiveTools([...active, TOOL_NAME]);
|
|
41
|
+
}
|
|
42
|
+
else if (!shouldBeActive && isActive) {
|
|
43
|
+
pi.setActiveTools(active.filter((name) => name !== TOOL_NAME));
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
pi.on("session_start", async (_event, ctx) => {
|
|
47
|
+
syncToolActivation(ctx);
|
|
48
|
+
});
|
|
49
|
+
pi.on("model_select", async (_event, ctx) => {
|
|
50
|
+
syncToolActivation(ctx);
|
|
51
|
+
});
|
|
52
|
+
registerLookAtCommand(pi, {
|
|
53
|
+
store,
|
|
54
|
+
loadChain: (ctx) => loadLookAtChain(ctx, store),
|
|
55
|
+
resync: (ctx) => syncToolActivation(ctx),
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/look-at/index.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ExtensionAPI, ExtensionContext } from \"../../types.ts\";\nimport { LOOK_AT_PARAMETERS, normalizeLookAtArgs, prepareLookAtArguments, validateLookAtArgs } from \"./arguments.ts\";\nimport { registerLookAtCommand } from \"./commands.ts\";\nimport { resolveVisionModel } from \"./model-selector.ts\";\nimport { LOOK_AT_DESCRIPTION, LOOK_AT_PROMPT_SNIPPET } from \"./prompts.ts\";\nimport { type LookAtToolDetails, renderLookAtCall, renderLookAtResult } from \"./render.ts\";\nimport { runLookAt } from \"./runner.ts\";\nimport { createLookAtStore, loadLookAtChain, loadLookAtEnabled } from \"./settings.ts\";\n\nconst TOOL_NAME = \"look_at\";\n\nexport default function lookAtExtension(pi: ExtensionAPI): void {\n\tconst store = createLookAtStore();\n\n\tpi.registerTool<typeof LOOK_AT_PARAMETERS, LookAtToolDetails>({\n\t\tname: TOOL_NAME,\n\t\tlabel: \"Look At\",\n\t\tdescription: LOOK_AT_DESCRIPTION,\n\t\tpromptSnippet: LOOK_AT_PROMPT_SNIPPET,\n\t\tparameters: LOOK_AT_PARAMETERS,\n\t\tprepareArguments: prepareLookAtArguments,\n\t\tasync execute(_toolCallId, params, signal, _onUpdate, ctx) {\n\t\t\tconst normalized = normalizeLookAtArgs(params);\n\t\t\tconst validationError = validateLookAtArgs(normalized);\n\t\t\tif (validationError) throw new Error(validationError);\n\n\t\t\tconst result = await runLookAt(normalized, signal, ctx, store);\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: result.text }],\n\t\t\t\tdetails: { model: result.model, sources: result.sources, mimeTypes: result.mimeTypes },\n\t\t\t};\n\t\t},\n\t\trenderCall: renderLookAtCall,\n\t\trenderResult: renderLookAtResult,\n\t});\n\n\tfunction syncToolActivation(ctx: ExtensionContext): void {\n\t\tconst active = pi.getActiveTools();\n\t\tconst shouldBeActive =\n\t\t\tloadLookAtEnabled(ctx, store) &&\n\t\t\tctx.model !== undefined &&\n\t\t\t!ctx.model.input.includes(\"image\") &&\n\t\t\tresolveVisionModel(loadLookAtChain(ctx, store), ctx.modelRegistry.getAvailable()) !== undefined;\n\t\tconst isActive = active.includes(TOOL_NAME);\n\t\tif (shouldBeActive && !isActive) {\n\t\t\tpi.setActiveTools([...active, TOOL_NAME]);\n\t\t} else if (!shouldBeActive && isActive) {\n\t\t\tpi.setActiveTools(active.filter((name) => name !== TOOL_NAME));\n\t\t}\n\t}\n\n\tpi.on(\"session_start\", async (_event, ctx) => {\n\t\tsyncToolActivation(ctx);\n\t});\n\tpi.on(\"model_select\", async (_event, ctx) => {\n\t\tsyncToolActivation(ctx);\n\t});\n\n\tregisterLookAtCommand(pi, {\n\t\tstore,\n\t\tloadChain: (ctx) => loadLookAtChain(ctx, store),\n\t\tresync: (ctx) => syncToolActivation(ctx),\n\t});\n}\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ThinkingLevel } from "@earendil-works/pi-agent-core";
|
|
2
|
+
import type { Api, Model } from "@earendil-works/pi-ai";
|
|
3
|
+
export declare const DEFAULT_LOOK_AT_CHAIN: readonly ["gpt-5.6-terra:off", "gemini-3.1-pro-preview:low", "gemini-3.5-flash", "kimi-k3"];
|
|
4
|
+
export interface ResolvedVisionModel {
|
|
5
|
+
model: Model<Api>;
|
|
6
|
+
thinkingLevel?: ThinkingLevel;
|
|
7
|
+
}
|
|
8
|
+
export declare function resolveVisionModel(chain: readonly string[], available: readonly Model<Api>[]): ResolvedVisionModel | undefined;
|
|
9
|
+
//# sourceMappingURL=model-selector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-selector.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/look-at/model-selector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAIxD,eAAO,MAAM,qBAAqB,YACjC,mBAAmB,EACnB,4BAA4B,EAC5B,kBAAkB,EAClB,SAAS,CACA,CAAC;AAIX,MAAM,WAAW,mBAAmB;IACnC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IAClB,aAAa,CAAC,EAAE,aAAa,CAAC;CAC9B;AAgED,wBAAgB,kBAAkB,CACjC,KAAK,EAAE,SAAS,MAAM,EAAE,EACxB,SAAS,EAAE,SAAS,KAAK,CAAC,GAAG,CAAC,EAAE,GAC9B,mBAAmB,GAAG,SAAS,CAcjC"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { isValidThinkingLevel } from "../../../../cli/args.js";
|
|
2
|
+
import { findExactModelReferenceMatch, parseModelPattern } from "../../../model-resolver.js";
|
|
3
|
+
export const DEFAULT_LOOK_AT_CHAIN = [
|
|
4
|
+
"gpt-5.6-terra:off",
|
|
5
|
+
"gemini-3.1-pro-preview:low",
|
|
6
|
+
"gemini-3.5-flash",
|
|
7
|
+
"kimi-k3",
|
|
8
|
+
];
|
|
9
|
+
const AMBIGUOUS_ID_PROVIDER_PREFERENCE = ["openai", "google", "moonshotai"];
|
|
10
|
+
// pi-ai ThinkingLevel has no "off"; an off/absent suffix must reach callers as undefined.
|
|
11
|
+
function normalizeThinkingLevel(level) {
|
|
12
|
+
return level === undefined || level === "off" ? undefined : level;
|
|
13
|
+
}
|
|
14
|
+
function splitThinkingSuffix(entry) {
|
|
15
|
+
const lastColon = entry.lastIndexOf(":");
|
|
16
|
+
if (lastColon === -1) {
|
|
17
|
+
return { reference: entry, thinkingLevel: undefined };
|
|
18
|
+
}
|
|
19
|
+
const suffix = entry.slice(lastColon + 1);
|
|
20
|
+
if (isValidThinkingLevel(suffix)) {
|
|
21
|
+
return { reference: entry.slice(0, lastColon), thinkingLevel: suffix };
|
|
22
|
+
}
|
|
23
|
+
return { reference: entry, thinkingLevel: undefined };
|
|
24
|
+
}
|
|
25
|
+
function pickProviderForAmbiguousId(candidates) {
|
|
26
|
+
if (candidates.length === 0) {
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
for (const provider of AMBIGUOUS_ID_PROVIDER_PREFERENCE) {
|
|
30
|
+
const match = candidates.find((model) => model.provider === provider);
|
|
31
|
+
if (match) {
|
|
32
|
+
return match;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return [...candidates].sort((a, b) => a.provider.localeCompare(b.provider))[0];
|
|
36
|
+
}
|
|
37
|
+
function resolveEntry(entry, visionCandidates) {
|
|
38
|
+
const fullExact = findExactModelReferenceMatch(entry, visionCandidates);
|
|
39
|
+
if (fullExact) {
|
|
40
|
+
return { model: fullExact, thinkingLevel: undefined };
|
|
41
|
+
}
|
|
42
|
+
const { reference, thinkingLevel } = splitThinkingSuffix(entry);
|
|
43
|
+
const normalized = normalizeThinkingLevel(thinkingLevel);
|
|
44
|
+
const referenceExact = findExactModelReferenceMatch(reference, visionCandidates);
|
|
45
|
+
if (referenceExact) {
|
|
46
|
+
return { model: referenceExact, thinkingLevel: normalized };
|
|
47
|
+
}
|
|
48
|
+
if (!reference.includes("/")) {
|
|
49
|
+
const wanted = reference.trim().toLowerCase();
|
|
50
|
+
const sameIdCandidates = visionCandidates.filter((model) => model.id.toLowerCase() === wanted);
|
|
51
|
+
if (sameIdCandidates.length > 1) {
|
|
52
|
+
const preferred = pickProviderForAmbiguousId(sameIdCandidates);
|
|
53
|
+
if (preferred) {
|
|
54
|
+
return { model: preferred, thinkingLevel: normalized };
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
const parsed = parseModelPattern(reference, visionCandidates);
|
|
59
|
+
if (parsed.model) {
|
|
60
|
+
return { model: parsed.model, thinkingLevel: normalizeThinkingLevel(normalized ?? parsed.thinkingLevel) };
|
|
61
|
+
}
|
|
62
|
+
return undefined;
|
|
63
|
+
}
|
|
64
|
+
export function resolveVisionModel(chain, available) {
|
|
65
|
+
const visionCandidates = available.filter((model) => model.input.includes("image"));
|
|
66
|
+
if (visionCandidates.length === 0) {
|
|
67
|
+
return undefined;
|
|
68
|
+
}
|
|
69
|
+
for (const entry of chain) {
|
|
70
|
+
const resolved = resolveEntry(entry, visionCandidates);
|
|
71
|
+
if (resolved) {
|
|
72
|
+
return resolved;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return { model: visionCandidates[0], thinkingLevel: undefined };
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=model-selector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-selector.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/look-at/model-selector.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ThinkingLevel } from \"@earendil-works/pi-agent-core\";\nimport type { Api, Model } from \"@earendil-works/pi-ai\";\nimport { isValidThinkingLevel } from \"../../../../cli/args.ts\";\nimport { findExactModelReferenceMatch, parseModelPattern } from \"../../../model-resolver.ts\";\n\nexport const DEFAULT_LOOK_AT_CHAIN = [\n\t\"gpt-5.6-terra:off\",\n\t\"gemini-3.1-pro-preview:low\",\n\t\"gemini-3.5-flash\",\n\t\"kimi-k3\",\n] as const;\n\nconst AMBIGUOUS_ID_PROVIDER_PREFERENCE: readonly string[] = [\"openai\", \"google\", \"moonshotai\"];\n\nexport interface ResolvedVisionModel {\n\tmodel: Model<Api>;\n\tthinkingLevel?: ThinkingLevel;\n}\n\n// pi-ai ThinkingLevel has no \"off\"; an off/absent suffix must reach callers as undefined.\nfunction normalizeThinkingLevel(level: ThinkingLevel | undefined): ThinkingLevel | undefined {\n\treturn level === undefined || level === \"off\" ? undefined : level;\n}\n\nfunction splitThinkingSuffix(entry: string): { reference: string; thinkingLevel: ThinkingLevel | undefined } {\n\tconst lastColon = entry.lastIndexOf(\":\");\n\tif (lastColon === -1) {\n\t\treturn { reference: entry, thinkingLevel: undefined };\n\t}\n\tconst suffix = entry.slice(lastColon + 1);\n\tif (isValidThinkingLevel(suffix)) {\n\t\treturn { reference: entry.slice(0, lastColon), thinkingLevel: suffix };\n\t}\n\treturn { reference: entry, thinkingLevel: undefined };\n}\n\nfunction pickProviderForAmbiguousId(candidates: Model<Api>[]): Model<Api> | undefined {\n\tif (candidates.length === 0) {\n\t\treturn undefined;\n\t}\n\tfor (const provider of AMBIGUOUS_ID_PROVIDER_PREFERENCE) {\n\t\tconst match = candidates.find((model) => model.provider === provider);\n\t\tif (match) {\n\t\t\treturn match;\n\t\t}\n\t}\n\treturn [...candidates].sort((a, b) => a.provider.localeCompare(b.provider))[0];\n}\n\nfunction resolveEntry(entry: string, visionCandidates: Model<Api>[]): ResolvedVisionModel | undefined {\n\tconst fullExact = findExactModelReferenceMatch(entry, visionCandidates);\n\tif (fullExact) {\n\t\treturn { model: fullExact, thinkingLevel: undefined };\n\t}\n\n\tconst { reference, thinkingLevel } = splitThinkingSuffix(entry);\n\tconst normalized = normalizeThinkingLevel(thinkingLevel);\n\n\tconst referenceExact = findExactModelReferenceMatch(reference, visionCandidates);\n\tif (referenceExact) {\n\t\treturn { model: referenceExact, thinkingLevel: normalized };\n\t}\n\n\tif (!reference.includes(\"/\")) {\n\t\tconst wanted = reference.trim().toLowerCase();\n\t\tconst sameIdCandidates = visionCandidates.filter((model) => model.id.toLowerCase() === wanted);\n\t\tif (sameIdCandidates.length > 1) {\n\t\t\tconst preferred = pickProviderForAmbiguousId(sameIdCandidates);\n\t\t\tif (preferred) {\n\t\t\t\treturn { model: preferred, thinkingLevel: normalized };\n\t\t\t}\n\t\t}\n\t}\n\n\tconst parsed = parseModelPattern(reference, visionCandidates);\n\tif (parsed.model) {\n\t\treturn { model: parsed.model, thinkingLevel: normalizeThinkingLevel(normalized ?? parsed.thinkingLevel) };\n\t}\n\treturn undefined;\n}\n\nexport function resolveVisionModel(\n\tchain: readonly string[],\n\tavailable: readonly Model<Api>[],\n): ResolvedVisionModel | undefined {\n\tconst visionCandidates = available.filter((model) => model.input.includes(\"image\"));\n\tif (visionCandidates.length === 0) {\n\t\treturn undefined;\n\t}\n\n\tfor (const entry of chain) {\n\t\tconst resolved = resolveEntry(entry, visionCandidates);\n\t\tif (resolved) {\n\t\t\treturn resolved;\n\t\t}\n\t}\n\n\treturn { model: visionCandidates[0], thinkingLevel: undefined };\n}\n"]}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const LOOK_AT_SYSTEM_PROMPT = "You analyze attached media for a downstream agent that cannot inspect the attachments directly.\n\nExtract only the information requested by the goal. Match the language of the goal.\n\nEvidence rules:\n- Be evidence-first. Clearly separate direct observations from inferences, and label inferences as such.\n- Transcribe every visible piece of text verbatim, preserving casing, punctuation, and reading order. Mark unreadable text explicitly rather than guessing.\n- Never fabricate details in occluded, blurry, cropped, or otherwise uncertain regions. State that the detail is unavailable or uncertain.\n- For multiple attachments, report findings for each source label, then compare and contrast them when the goal calls for comparison.\n- Be thorough about the goal and concise about unrelated detail.\n\nReturn only the response body. Do not add a preamble, meta commentary, or postscript.";
|
|
2
|
+
export declare function buildLookAtUserMessage(goal: string, sourceLabels: readonly string[]): string;
|
|
3
|
+
export declare const LOOK_AT_DESCRIPTION = "Extract basic information from media files such as PDFs, images, and diagrams when a quick summary is sufficient. Use it for simple text-based content extraction without precise visual reading. Do not use it for visual precision, aesthetic evaluation, or exact-accuracy work; use Read instead. Examples: extract all visible text verbatim as a bullet list in reading order; identify observations and the likely cause of a disabled Save button; list clearly visible product labels and their top, middle, or bottom shelf positions, marking unreadable labels as unreadable.";
|
|
4
|
+
export declare const LOOK_AT_PROMPT_SNIPPET = "Extract a quick summary or basic information from attached media; use Read instead when visual precision or exact accuracy matters.";
|
|
5
|
+
//# sourceMappingURL=prompts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/look-at/prompts.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,qBAAqB,m4BAWoD,CAAC;AAEvF,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,MAAM,EAAE,YAAY,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAG5F;AAED,eAAO,MAAM,mBAAmB,8jBAA8jB,CAAC;AAE/lB,eAAO,MAAM,sBAAsB,wIACmG,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export const LOOK_AT_SYSTEM_PROMPT = `You analyze attached media for a downstream agent that cannot inspect the attachments directly.
|
|
2
|
+
|
|
3
|
+
Extract only the information requested by the goal. Match the language of the goal.
|
|
4
|
+
|
|
5
|
+
Evidence rules:
|
|
6
|
+
- Be evidence-first. Clearly separate direct observations from inferences, and label inferences as such.
|
|
7
|
+
- Transcribe every visible piece of text verbatim, preserving casing, punctuation, and reading order. Mark unreadable text explicitly rather than guessing.
|
|
8
|
+
- Never fabricate details in occluded, blurry, cropped, or otherwise uncertain regions. State that the detail is unavailable or uncertain.
|
|
9
|
+
- For multiple attachments, report findings for each source label, then compare and contrast them when the goal calls for comparison.
|
|
10
|
+
- Be thorough about the goal and concise about unrelated detail.
|
|
11
|
+
|
|
12
|
+
Return only the response body. Do not add a preamble, meta commentary, or postscript.`;
|
|
13
|
+
export function buildLookAtUserMessage(goal, sourceLabels) {
|
|
14
|
+
const sources = sourceLabels.map((label) => `- ${label}`).join("\n");
|
|
15
|
+
return `Goal:\n${goal}\n\nAttached sources:\n${sources}`;
|
|
16
|
+
}
|
|
17
|
+
export const LOOK_AT_DESCRIPTION = `Extract basic information from media files such as PDFs, images, and diagrams when a quick summary is sufficient. Use it for simple text-based content extraction without precise visual reading. Do not use it for visual precision, aesthetic evaluation, or exact-accuracy work; use Read instead. Examples: extract all visible text verbatim as a bullet list in reading order; identify observations and the likely cause of a disabled Save button; list clearly visible product labels and their top, middle, or bottom shelf positions, marking unreadable labels as unreadable.`;
|
|
18
|
+
export const LOOK_AT_PROMPT_SNIPPET = "Extract a quick summary or basic information from attached media; use Read instead when visual precision or exact accuracy matters.";
|
|
19
|
+
//# sourceMappingURL=prompts.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/look-at/prompts.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,qBAAqB,GAAG;;;;;;;;;;;sFAWiD,CAAC;AAEvF,MAAM,UAAU,sBAAsB,CAAC,IAAY,EAAE,YAA+B;IACnF,MAAM,OAAO,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrE,OAAO,UAAU,IAAI,0BAA0B,OAAO,EAAE,CAAC;AAC1D,CAAC;AAED,MAAM,CAAC,MAAM,mBAAmB,GAAG,2jBAA2jB,CAAC;AAE/lB,MAAM,CAAC,MAAM,sBAAsB,GAClC,qIAAqI,CAAC","sourcesContent":["export const LOOK_AT_SYSTEM_PROMPT = `You analyze attached media for a downstream agent that cannot inspect the attachments directly.\n\nExtract only the information requested by the goal. Match the language of the goal.\n\nEvidence rules:\n- Be evidence-first. Clearly separate direct observations from inferences, and label inferences as such.\n- Transcribe every visible piece of text verbatim, preserving casing, punctuation, and reading order. Mark unreadable text explicitly rather than guessing.\n- Never fabricate details in occluded, blurry, cropped, or otherwise uncertain regions. State that the detail is unavailable or uncertain.\n- For multiple attachments, report findings for each source label, then compare and contrast them when the goal calls for comparison.\n- Be thorough about the goal and concise about unrelated detail.\n\nReturn only the response body. Do not add a preamble, meta commentary, or postscript.`;\n\nexport function buildLookAtUserMessage(goal: string, sourceLabels: readonly string[]): string {\n\tconst sources = sourceLabels.map((label) => `- ${label}`).join(\"\\n\");\n\treturn `Goal:\\n${goal}\\n\\nAttached sources:\\n${sources}`;\n}\n\nexport const LOOK_AT_DESCRIPTION = `Extract basic information from media files such as PDFs, images, and diagrams when a quick summary is sufficient. Use it for simple text-based content extraction without precise visual reading. Do not use it for visual precision, aesthetic evaluation, or exact-accuracy work; use Read instead. Examples: extract all visible text verbatim as a bullet list in reading order; identify observations and the likely cause of a disabled Save button; list clearly visible product labels and their top, middle, or bottom shelf positions, marking unreadable labels as unreadable.`;\n\nexport const LOOK_AT_PROMPT_SNIPPET =\n\t\"Extract a quick summary or basic information from attached media; use Read instead when visual precision or exact accuracy matters.\";\n"]}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Text } from "@earendil-works/pi-tui";
|
|
2
|
+
import type { Theme } from "../../../../modes/interactive/theme/theme.ts";
|
|
3
|
+
import type { ToolRenderContext, ToolRenderResultOptions } from "../../types.ts";
|
|
4
|
+
export interface LookAtToolDetails {
|
|
5
|
+
model: string;
|
|
6
|
+
sources: string[];
|
|
7
|
+
mimeTypes: string[];
|
|
8
|
+
}
|
|
9
|
+
export interface LookAtRenderArgs {
|
|
10
|
+
file_path?: string;
|
|
11
|
+
file_paths?: readonly string[];
|
|
12
|
+
image_data?: string;
|
|
13
|
+
image_data_list?: readonly string[];
|
|
14
|
+
goal?: string;
|
|
15
|
+
}
|
|
16
|
+
interface LookAtRenderResult {
|
|
17
|
+
content: ReadonlyArray<{
|
|
18
|
+
type: string;
|
|
19
|
+
text?: string;
|
|
20
|
+
}>;
|
|
21
|
+
details?: LookAtToolDetails;
|
|
22
|
+
}
|
|
23
|
+
export declare function renderLookAtCall(args: LookAtRenderArgs, theme: Theme, _context: ToolRenderContext<unknown, LookAtRenderArgs>): Text;
|
|
24
|
+
export declare function renderLookAtResult(result: LookAtRenderResult, options: ToolRenderResultOptions, theme: Theme, _context: ToolRenderContext<unknown, LookAtRenderArgs>): Text;
|
|
25
|
+
export {};
|
|
26
|
+
//# sourceMappingURL=render.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/look-at/render.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAmB,MAAM,wBAAwB,CAAC;AAC/D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,8CAA8C,CAAC;AAC1E,OAAO,KAAK,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AASjF,MAAM,WAAW,iBAAiB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,gBAAgB;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,IAAI,CAAC,EAAE,MAAM,CAAC;CACd;AAED,UAAU,kBAAkB;IAC3B,OAAO,EAAE,aAAa,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACxD,OAAO,CAAC,EAAE,iBAAiB,CAAC;CAC5B;AAED,wBAAgB,gBAAgB,CAC/B,IAAI,EAAE,gBAAgB,EACtB,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,iBAAiB,CAAC,OAAO,EAAE,gBAAgB,CAAC,GACpD,IAAI,CAcN;AAED,wBAAgB,kBAAkB,CACjC,MAAM,EAAE,kBAAkB,EAC1B,OAAO,EAAE,uBAAuB,EAChC,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,iBAAiB,CAAC,OAAO,EAAE,gBAAgB,CAAC,GACpD,IAAI,CAmBN"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { basename } from "node:path";
|
|
2
|
+
import { Text, truncateToWidth } from "@earendil-works/pi-tui";
|
|
3
|
+
const GOAL_PREVIEW_WIDTH = 110;
|
|
4
|
+
const RESULT_PREVIEW_LINES = 4;
|
|
5
|
+
const RESULT_PREVIEW_WIDTH = 120;
|
|
6
|
+
const IMAGE_ATTACHMENT_REFERENCE = /^\s*(?:\[?Image #([1-9]\d*)(?:,[^\]\n]*)?\]?|(?:attachment|image):\/\/([1-9]\d*))\s*$/i;
|
|
7
|
+
export function renderLookAtCall(args, theme, _context) {
|
|
8
|
+
const sources = sourceLabels(args);
|
|
9
|
+
const sourceSummary = sources.length > 0 ? sources.join(", ") : "no sources";
|
|
10
|
+
const goal = oneLine(args.goal) || "pending";
|
|
11
|
+
const title = theme.fg("toolTitle", theme.bold("look_at "));
|
|
12
|
+
return new Text([
|
|
13
|
+
title + theme.fg("accent", sourceSummary),
|
|
14
|
+
theme.fg("muted", "goal: ") + theme.fg("toolOutput", shorten(goal, GOAL_PREVIEW_WIDTH)),
|
|
15
|
+
].join("\n"), 0, 0);
|
|
16
|
+
}
|
|
17
|
+
export function renderLookAtResult(result, options, theme, _context) {
|
|
18
|
+
const model = typeof result.details?.model === "string" ? result.details.model.trim() : "";
|
|
19
|
+
const text = textContent(result);
|
|
20
|
+
const rows = [];
|
|
21
|
+
if (model) {
|
|
22
|
+
rows.push(theme.fg("accent", `[vision ${model}]`));
|
|
23
|
+
}
|
|
24
|
+
if (!text) {
|
|
25
|
+
rows.push(theme.fg(options.isPartial ? "warning" : "dim", options.isPartial ? "Analyzing media..." : "empty response"));
|
|
26
|
+
}
|
|
27
|
+
else if (options.expanded) {
|
|
28
|
+
rows.push(...text.split("\n").map((line) => theme.fg("toolOutput", line)));
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
rows.push(...previewLines(text, theme));
|
|
32
|
+
}
|
|
33
|
+
return new Text(rows.join("\n"), 0, 0);
|
|
34
|
+
}
|
|
35
|
+
function sourceLabels(args) {
|
|
36
|
+
const paths = [...stringValues(args.file_paths), ...stringValue(args.file_path)];
|
|
37
|
+
const base64Inputs = [...stringValues(args.image_data_list), ...stringValue(args.image_data)];
|
|
38
|
+
return [...paths.map(pathLabel), ...base64Inputs.map(() => "base64 input")];
|
|
39
|
+
}
|
|
40
|
+
function stringValues(value) {
|
|
41
|
+
return value?.filter((item) => item.trim().length > 0) ?? [];
|
|
42
|
+
}
|
|
43
|
+
function stringValue(value) {
|
|
44
|
+
return value?.trim() ? [value] : [];
|
|
45
|
+
}
|
|
46
|
+
function pathLabel(path) {
|
|
47
|
+
const match = IMAGE_ATTACHMENT_REFERENCE.exec(path);
|
|
48
|
+
const imageIndex = match?.[1] ?? match?.[2];
|
|
49
|
+
return imageIndex ? `Image #${imageIndex}` : basename(path);
|
|
50
|
+
}
|
|
51
|
+
function textContent(result) {
|
|
52
|
+
return result.content.find((block) => block.type === "text")?.text ?? "";
|
|
53
|
+
}
|
|
54
|
+
function previewLines(text, theme) {
|
|
55
|
+
const lines = text
|
|
56
|
+
.split("\n")
|
|
57
|
+
.map((line) => line.trim())
|
|
58
|
+
.filter((line) => line.length > 0)
|
|
59
|
+
.slice(0, RESULT_PREVIEW_LINES);
|
|
60
|
+
if (lines.length === 0)
|
|
61
|
+
return [theme.fg("dim", "empty response")];
|
|
62
|
+
return lines.map((line) => theme.fg("toolOutput", ` ${truncateToWidth(line, RESULT_PREVIEW_WIDTH)}`));
|
|
63
|
+
}
|
|
64
|
+
function oneLine(value) {
|
|
65
|
+
return value?.replace(/\s+/g, " ").trim() ?? "";
|
|
66
|
+
}
|
|
67
|
+
function shorten(value, max) {
|
|
68
|
+
return value.length <= max ? value : `${value.slice(0, max - 1)}…`;
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/look-at/render.ts"],"names":[],"mappings":"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","sourcesContent":["import { basename } from \"node:path\";\nimport { Text, truncateToWidth } from \"@earendil-works/pi-tui\";\nimport type { Theme } from \"../../../../modes/interactive/theme/theme.ts\";\nimport type { ToolRenderContext, ToolRenderResultOptions } from \"../../types.ts\";\n\nconst GOAL_PREVIEW_WIDTH = 110;\nconst RESULT_PREVIEW_LINES = 4;\nconst RESULT_PREVIEW_WIDTH = 120;\n\nconst IMAGE_ATTACHMENT_REFERENCE =\n\t/^\\s*(?:\\[?Image #([1-9]\\d*)(?:,[^\\]\\n]*)?\\]?|(?:attachment|image):\\/\\/([1-9]\\d*))\\s*$/i;\n\nexport interface LookAtToolDetails {\n\tmodel: string;\n\tsources: string[];\n\tmimeTypes: string[];\n}\n\nexport interface LookAtRenderArgs {\n\tfile_path?: string;\n\tfile_paths?: readonly string[];\n\timage_data?: string;\n\timage_data_list?: readonly string[];\n\tgoal?: string;\n}\n\ninterface LookAtRenderResult {\n\tcontent: ReadonlyArray<{ type: string; text?: string }>;\n\tdetails?: LookAtToolDetails;\n}\n\nexport function renderLookAtCall(\n\targs: LookAtRenderArgs,\n\ttheme: Theme,\n\t_context: ToolRenderContext<unknown, LookAtRenderArgs>,\n): Text {\n\tconst sources = sourceLabels(args);\n\tconst sourceSummary = sources.length > 0 ? sources.join(\", \") : \"no sources\";\n\tconst goal = oneLine(args.goal) || \"pending\";\n\tconst title = theme.fg(\"toolTitle\", theme.bold(\"look_at \"));\n\n\treturn new Text(\n\t\t[\n\t\t\ttitle + theme.fg(\"accent\", sourceSummary),\n\t\t\ttheme.fg(\"muted\", \"goal: \") + theme.fg(\"toolOutput\", shorten(goal, GOAL_PREVIEW_WIDTH)),\n\t\t].join(\"\\n\"),\n\t\t0,\n\t\t0,\n\t);\n}\n\nexport function renderLookAtResult(\n\tresult: LookAtRenderResult,\n\toptions: ToolRenderResultOptions,\n\ttheme: Theme,\n\t_context: ToolRenderContext<unknown, LookAtRenderArgs>,\n): Text {\n\tconst model = typeof result.details?.model === \"string\" ? result.details.model.trim() : \"\";\n\tconst text = textContent(result);\n\tconst rows: string[] = [];\n\n\tif (model) {\n\t\trows.push(theme.fg(\"accent\", `[vision ${model}]`));\n\t}\n\tif (!text) {\n\t\trows.push(\n\t\t\ttheme.fg(options.isPartial ? \"warning\" : \"dim\", options.isPartial ? \"Analyzing media...\" : \"empty response\"),\n\t\t);\n\t} else if (options.expanded) {\n\t\trows.push(...text.split(\"\\n\").map((line) => theme.fg(\"toolOutput\", line)));\n\t} else {\n\t\trows.push(...previewLines(text, theme));\n\t}\n\n\treturn new Text(rows.join(\"\\n\"), 0, 0);\n}\n\nfunction sourceLabels(args: LookAtRenderArgs): string[] {\n\tconst paths = [...stringValues(args.file_paths), ...stringValue(args.file_path)];\n\tconst base64Inputs = [...stringValues(args.image_data_list), ...stringValue(args.image_data)];\n\treturn [...paths.map(pathLabel), ...base64Inputs.map(() => \"base64 input\")];\n}\n\nfunction stringValues(value: readonly string[] | undefined): readonly string[] {\n\treturn value?.filter((item) => item.trim().length > 0) ?? [];\n}\n\nfunction stringValue(value: string | undefined): readonly string[] {\n\treturn value?.trim() ? [value] : [];\n}\n\nfunction pathLabel(path: string): string {\n\tconst match = IMAGE_ATTACHMENT_REFERENCE.exec(path);\n\tconst imageIndex = match?.[1] ?? match?.[2];\n\treturn imageIndex ? `Image #${imageIndex}` : basename(path);\n}\n\nfunction textContent(result: LookAtRenderResult): string {\n\treturn result.content.find((block) => block.type === \"text\")?.text ?? \"\";\n}\n\nfunction previewLines(text: string, theme: Theme): string[] {\n\tconst lines = text\n\t\t.split(\"\\n\")\n\t\t.map((line) => line.trim())\n\t\t.filter((line) => line.length > 0)\n\t\t.slice(0, RESULT_PREVIEW_LINES);\n\tif (lines.length === 0) return [theme.fg(\"dim\", \"empty response\")];\n\treturn lines.map((line) => theme.fg(\"toolOutput\", ` ${truncateToWidth(line, RESULT_PREVIEW_WIDTH)}`));\n}\n\nfunction oneLine(value: string | undefined): string {\n\treturn value?.replace(/\\s+/g, \" \").trim() ?? \"\";\n}\n\nfunction shorten(value: string, max: number): string {\n\treturn value.length <= max ? value : `${value.slice(0, max - 1)}…`;\n}\n"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Api, AssistantMessageEventStream, Context, Model, ModelsSimpleStreamOptions } from "@earendil-works/pi-ai";
|
|
2
|
+
import type { ExtensionContext } from "../../types.ts";
|
|
3
|
+
import type { NormalizedLookAtArgs } from "./arguments.ts";
|
|
4
|
+
import { type LookAtStore } from "./settings.ts";
|
|
5
|
+
export type LookAtStreamRunner = (model: Model<Api>, context: Context, options: ModelsSimpleStreamOptions) => AssistantMessageEventStream;
|
|
6
|
+
export interface LookAtRunnerDependencies {
|
|
7
|
+
streamRunner?: LookAtStreamRunner;
|
|
8
|
+
}
|
|
9
|
+
export interface LookAtRunResult {
|
|
10
|
+
model: string;
|
|
11
|
+
sources: string[];
|
|
12
|
+
mimeTypes: string[];
|
|
13
|
+
text: string;
|
|
14
|
+
}
|
|
15
|
+
export declare function runLookAt(args: NormalizedLookAtArgs, signal: AbortSignal | undefined, ctx: ExtensionContext, store: LookAtStore, dependencies?: LookAtRunnerDependencies): Promise<LookAtRunResult>;
|
|
16
|
+
//# sourceMappingURL=runner.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runner.d.ts","sourceRoot":"","sources":["../../../../../src/core/extensions/builtin/look-at/runner.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACX,GAAG,EAEH,2BAA2B,EAC3B,OAAO,EAEP,KAAK,EACL,yBAAyB,EAGzB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AACvD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAI3D,OAAO,EAAE,KAAK,WAAW,EAAmB,MAAM,eAAe,CAAC;AAIlE,MAAM,MAAM,kBAAkB,GAAG,CAChC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EACjB,OAAO,EAAE,OAAO,EAChB,OAAO,EAAE,yBAAyB,KAC9B,2BAA2B,CAAC;AAEjC,MAAM,WAAW,wBAAwB;IACxC,YAAY,CAAC,EAAE,kBAAkB,CAAC;CAClC;AAED,MAAM,WAAW,eAAe;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;CACb;AAED,wBAAsB,SAAS,CAC9B,IAAI,EAAE,oBAAoB,EAC1B,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,GAAG,EAAE,gBAAgB,EACrB,KAAK,EAAE,WAAW,EAClB,YAAY,GAAE,wBAA6B,GACzC,OAAO,CAAC,eAAe,CAAC,CA6D1B"}
|