@astralyn/pi 1.0.5 → 1.2.0
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 +79 -0
- package/dist/bundle/chunks/anthropic-messages-NVP5OPIM.js +6 -0
- package/dist/bundle/chunks/anthropic.js +1 -1
- package/dist/bundle/chunks/{azure-openai-responses-LDW4FGAQ.js → azure-openai-responses-IBTOZ5MH.js} +1 -1
- package/dist/bundle/chunks/bedrock-converse-stream.js +2 -2
- package/dist/bundle/chunks/chunk-4XZYHGVN.js +11 -0
- package/dist/bundle/chunks/{chunk-GIG5IHES.js → chunk-5KJH3GGH.js} +1 -1
- package/dist/bundle/chunks/chunk-6VYRLG5F.js +2 -0
- package/dist/bundle/chunks/{chunk-UCXU7KLO.js → chunk-7HJ6CHUB.js} +1 -1
- package/dist/bundle/chunks/chunk-7UBIBLPN.js +2 -0
- package/dist/bundle/chunks/{chunk-IE3Z7ESB.js → chunk-A5HU4TE6.js} +418 -362
- package/dist/bundle/chunks/{chunk-HDHRZ7GT.js → chunk-B2UOWO4A.js} +1 -1
- package/dist/bundle/chunks/chunk-J75WV3FL.js +2 -0
- package/dist/bundle/chunks/{chunk-A6ALEEY5.js → chunk-LHSPN2IO.js} +1 -1
- package/dist/bundle/chunks/chunk-Q74S7ILH.js +2 -0
- package/dist/bundle/chunks/chunk-QDDSFJ35.js +2 -0
- package/dist/bundle/chunks/{chunk-IFELM7MW.js → chunk-UQECUCUH.js} +1 -1
- package/dist/bundle/chunks/cloudflare-workers-ai-system-one-HGOVFZDC.js +2 -0
- package/dist/bundle/chunks/codemode-worker.js +18 -10
- package/dist/bundle/chunks/github-copilot.js +1 -1
- package/dist/bundle/chunks/{google-generative-ai-S5A5IBU4.js → google-generative-ai-M44TSMAN.js} +1 -1
- package/dist/bundle/chunks/{google-vertex-UBRQFDB4.js → google-vertex-3C4OWLFX.js} +1 -1
- package/dist/bundle/chunks/image-resize-worker.js +1 -1
- package/dist/bundle/chunks/{llama-cpp-classify-R7DQLTQN.js → llama-cpp-classify-H3IZDR5O.js} +2 -2
- package/dist/bundle/chunks/mistral-conversations-I5PL4VCZ.js +5 -0
- package/dist/bundle/chunks/openai-chatgpt.js +1 -1
- package/dist/bundle/chunks/openai-codex-responses-O5EUDL54.js +10 -0
- package/dist/bundle/chunks/openai-codex.js +1 -1
- package/dist/bundle/chunks/{openai-completions-H4VMO7AU.js → openai-completions-X3SSG5BQ.js} +1 -1
- package/dist/bundle/chunks/openai-decisions-TVCDIPZX.js +5 -0
- package/dist/bundle/chunks/{openai-responses-G4PGNM2H.js → openai-responses-NYPNKVDV.js} +1 -1
- package/dist/bundle/chunks/{openrouter-images-YP3YVB54.js → openrouter-images-TDLJV5N4.js} +1 -1
- package/dist/bundle/chunks/{pi-messages-HZZ7GEEW.js → pi-messages-ZXNERWJG.js} +1 -1
- package/dist/bundle/chunks/typesafe-system-one-LWPJYTJP.js +2 -0
- package/dist/bundle/chunks/{virtual-modules-46MSJGKO.js → virtual-modules-OZTPKGU7.js} +1 -1
- package/dist/bundle/cli.js +1 -1
- package/dist/bundle/index.js +1 -1
- package/dist/bundle/rpc-entry.js +1 -1
- package/dist/cli/args.d.ts +1 -1
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +13 -1
- package/dist/cli/args.js.map +1 -1
- package/dist/core/agent-session.d.ts +26 -7
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +190 -183
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/auth-storage.d.ts.map +1 -1
- package/dist/core/auth-storage.js +20 -13
- package/dist/core/auth-storage.js.map +1 -1
- package/dist/core/bash-executor.d.ts.map +1 -1
- package/dist/core/bash-executor.js +40 -45
- package/dist/core/bash-executor.js.map +1 -1
- package/dist/core/bug-report.d.ts +9 -1
- package/dist/core/bug-report.d.ts.map +1 -1
- package/dist/core/compaction/utils.d.ts +6 -0
- package/dist/core/compaction/utils.d.ts.map +1 -1
- package/dist/core/compaction/utils.js +7 -8
- package/dist/core/compaction/utils.js.map +1 -1
- package/dist/core/context-snapshot.d.ts +4 -1
- package/dist/core/context-snapshot.d.ts.map +1 -1
- package/dist/core/context-snapshot.js +45 -0
- package/dist/core/context-snapshot.js.map +1 -1
- package/dist/core/export-html/tool-renderer.d.ts.map +1 -1
- package/dist/core/export-html/tool-renderer.js +2 -0
- package/dist/core/export-html/tool-renderer.js.map +1 -1
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/runner.d.ts +4 -2
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +2 -3
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +42 -7
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/key-id-schema.d.ts +6 -0
- package/dist/core/key-id-schema.d.ts.map +1 -0
- package/dist/core/key-id-schema.js +16 -0
- package/dist/core/key-id-schema.js.map +1 -0
- package/dist/core/keybinding-registry.d.ts +4 -3
- package/dist/core/keybinding-registry.d.ts.map +1 -1
- package/dist/core/keybinding-registry.js +4 -3
- package/dist/core/keybinding-registry.js.map +1 -1
- package/dist/core/keybindings-schema.d.ts +4 -0
- package/dist/core/keybindings-schema.d.ts.map +1 -0
- package/dist/core/keybindings-schema.js +16 -0
- package/dist/core/keybindings-schema.js.map +1 -0
- package/dist/core/keybindings.d.ts +258 -81
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +27 -24
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/model-config.d.ts +713 -180
- package/dist/core/model-config.d.ts.map +1 -1
- package/dist/core/model-config.js +18 -179
- package/dist/core/model-config.js.map +1 -1
- package/dist/core/model-runtime.d.ts.map +1 -1
- package/dist/core/model-runtime.js +13 -7
- package/dist/core/model-runtime.js.map +1 -1
- package/dist/core/nested-tool-calls.d.ts +1 -0
- package/dist/core/nested-tool-calls.d.ts.map +1 -1
- package/dist/core/nested-tool-calls.js +1 -0
- package/dist/core/nested-tool-calls.js.map +1 -1
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +3 -3
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/project-trust.d.ts.map +1 -1
- package/dist/core/project-trust.js +2 -1
- package/dist/core/project-trust.js.map +1 -1
- package/dist/core/remote-catalog-provider.d.ts +12 -1
- package/dist/core/remote-catalog-provider.d.ts.map +1 -1
- package/dist/core/remote-catalog-provider.js +82 -24
- package/dist/core/remote-catalog-provider.js.map +1 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +7 -2
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/sdk.d.ts +4 -0
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +17 -5
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/settings-defaults.d.ts +65 -0
- package/dist/core/settings-defaults.d.ts.map +1 -0
- package/dist/core/settings-defaults.js +66 -0
- package/dist/core/settings-defaults.js.map +1 -0
- package/dist/core/settings-manager.d.ts +15 -147
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +85 -57
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/settings-schema.d.ts +231 -0
- package/dist/core/settings-schema.d.ts.map +1 -0
- package/dist/core/settings-schema.js +294 -0
- package/dist/core/settings-schema.js.map +1 -0
- package/dist/core/tasks/session.d.ts +9 -0
- package/dist/core/tasks/session.d.ts.map +1 -1
- package/dist/core/tasks/session.js +21 -0
- package/dist/core/tasks/session.js.map +1 -1
- package/dist/core/tools/render-utils.d.ts +18 -0
- package/dist/core/tools/render-utils.d.ts.map +1 -1
- package/dist/core/tools/render-utils.js +46 -0
- package/dist/core/tools/render-utils.js.map +1 -1
- package/dist/core/tools/renderers/bash.d.ts.map +1 -1
- package/dist/core/tools/renderers/bash.js +21 -45
- package/dist/core/tools/renderers/bash.js.map +1 -1
- package/dist/core/tools/renderers/edit.js +1 -1
- package/dist/core/tools/renderers/edit.js.map +1 -1
- package/dist/extensions/btw/keybindings.d.ts +2 -2
- package/dist/extensions/btw/keybindings.d.ts.map +1 -1
- package/dist/extensions/btw/keybindings.js.map +1 -1
- package/dist/extensions/codemode/execute.d.ts.map +1 -1
- package/dist/extensions/codemode/execute.js +115 -40
- package/dist/extensions/codemode/execute.js.map +1 -1
- package/dist/extensions/codemode/index.d.ts.map +1 -1
- package/dist/extensions/codemode/index.js +3 -7
- package/dist/extensions/codemode/index.js.map +1 -1
- package/dist/extensions/codemode/renderer.d.ts +2 -2
- package/dist/extensions/codemode/renderer.d.ts.map +1 -1
- package/dist/extensions/codemode/renderer.js +9 -3
- package/dist/extensions/codemode/renderer.js.map +1 -1
- package/dist/extensions/codemode/tool.d.ts +6 -12
- package/dist/extensions/codemode/tool.d.ts.map +1 -1
- package/dist/extensions/codemode/tool.js +46 -34
- package/dist/extensions/codemode/tool.js.map +1 -1
- package/dist/extensions/index.js +2 -2
- package/dist/extensions/index.js.map +1 -1
- package/dist/extensions/list-keybindings.d.ts +2 -2
- package/dist/extensions/list-keybindings.d.ts.map +1 -1
- package/dist/extensions/list-keybindings.js.map +1 -1
- package/dist/extensions/llama/provider.d.ts.map +1 -1
- package/dist/extensions/llama/provider.js +34 -11
- package/dist/extensions/llama/provider.js.map +1 -1
- package/dist/extensions/mcp/cli.js +22 -31
- package/dist/extensions/mcp/cli.js.map +1 -1
- package/dist/extensions/mcp/index.d.ts.map +1 -1
- package/dist/extensions/mcp/index.js +187 -95
- package/dist/extensions/mcp/index.js.map +1 -1
- package/dist/extensions/mcp/oauth.d.ts +5 -3
- package/dist/extensions/mcp/oauth.d.ts.map +1 -1
- package/dist/extensions/mcp/oauth.js +36 -10
- package/dist/extensions/mcp/oauth.js.map +1 -1
- package/dist/extensions/mcp/resources.d.ts +0 -6
- package/dist/extensions/mcp/resources.d.ts.map +1 -1
- package/dist/extensions/mcp/resources.js +1 -1
- package/dist/extensions/mcp/resources.js.map +1 -1
- package/dist/extensions/mcp/runtime.d.ts +3 -6
- package/dist/extensions/mcp/runtime.d.ts.map +1 -1
- package/dist/extensions/mcp/runtime.js +4 -39
- package/dist/extensions/mcp/runtime.js.map +1 -1
- package/dist/extensions/mcp/tools.d.ts +2 -3
- package/dist/extensions/mcp/tools.d.ts.map +1 -1
- package/dist/extensions/mcp/tools.js +62 -6
- package/dist/extensions/mcp/tools.js.map +1 -1
- package/dist/extensions/mcp/ui.d.ts +3 -3
- package/dist/extensions/mcp/ui.d.ts.map +1 -1
- package/dist/extensions/mcp/ui.js +10 -2
- package/dist/extensions/mcp/ui.js.map +1 -1
- package/dist/extensions/provider/keybindings.d.ts +2 -2
- package/dist/extensions/provider/keybindings.d.ts.map +1 -1
- package/dist/extensions/provider/keybindings.js.map +1 -1
- package/dist/extensions/search/code-search.d.ts +27 -0
- package/dist/extensions/search/code-search.d.ts.map +1 -0
- package/dist/extensions/search/code-search.js +120 -0
- package/dist/extensions/search/code-search.js.map +1 -0
- package/dist/extensions/search/command.d.ts +5 -0
- package/dist/extensions/search/command.d.ts.map +1 -0
- package/dist/extensions/search/command.js +69 -0
- package/dist/extensions/search/command.js.map +1 -0
- package/dist/extensions/search/credential.d.ts +25 -0
- package/dist/extensions/search/credential.d.ts.map +1 -0
- package/dist/extensions/search/credential.js +117 -0
- package/dist/extensions/search/credential.js.map +1 -0
- package/dist/extensions/search/devin.d.ts +34 -0
- package/dist/extensions/search/devin.d.ts.map +1 -0
- package/dist/extensions/search/devin.js +210 -0
- package/dist/extensions/search/devin.js.map +1 -0
- package/dist/extensions/search/index.d.ts +5 -0
- package/dist/extensions/search/index.d.ts.map +1 -0
- package/dist/extensions/search/index.js +113 -0
- package/dist/extensions/search/index.js.map +1 -0
- package/dist/extensions/search/panel.d.ts +53 -0
- package/dist/extensions/search/panel.d.ts.map +1 -0
- package/dist/extensions/search/panel.js +157 -0
- package/dist/extensions/search/panel.js.map +1 -0
- package/dist/extensions/search/prompt.d.ts +14 -0
- package/dist/extensions/search/prompt.d.ts.map +1 -0
- package/dist/extensions/search/prompt.js +221 -0
- package/dist/extensions/search/prompt.js.map +1 -0
- package/dist/extensions/search/render.d.ts +28 -0
- package/dist/extensions/search/render.d.ts.map +1 -0
- package/dist/extensions/search/render.js +86 -0
- package/dist/extensions/search/render.js.map +1 -0
- package/dist/extensions/search/workspace.d.ts +39 -0
- package/dist/extensions/search/workspace.d.ts.map +1 -0
- package/dist/extensions/search/workspace.js +363 -0
- package/dist/extensions/search/workspace.js.map +1 -0
- package/dist/extensions/tool-search/index.d.ts.map +1 -1
- package/dist/extensions/tool-search/index.js +1 -6
- package/dist/extensions/tool-search/index.js.map +1 -1
- package/dist/extensions/tool-search/tool.d.ts +0 -2
- package/dist/extensions/tool-search/tool.d.ts.map +1 -1
- package/dist/extensions/tool-search/tool.js +2 -4
- package/dist/extensions/tool-search/tool.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/main.js +3 -3
- package/dist/main.js.map +1 -1
- package/dist/modes/interactive/components/bash-execution.d.ts +5 -1
- package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/bash-execution.js +14 -14
- package/dist/modes/interactive/components/bash-execution.js.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.d.ts +2 -1
- package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/branch-summary-message.js +5 -2
- package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.d.ts +2 -1
- package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/compaction-summary-message.js +5 -2
- package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
- package/dist/modes/interactive/components/custom-entry.d.ts +3 -1
- package/dist/modes/interactive/components/custom-entry.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-entry.js +7 -2
- package/dist/modes/interactive/components/custom-entry.js.map +1 -1
- package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/custom-message.js +1 -0
- package/dist/modes/interactive/components/custom-message.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +4 -3
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.d.ts +2 -1
- package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/skill-invocation-message.js +5 -2
- package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
- package/dist/modes/interactive/components/status-indicator.d.ts +1 -1
- package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -1
- package/dist/modes/interactive/components/status-indicator.js +2 -2
- package/dist/modes/interactive/components/status-indicator.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts +2 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +63 -64
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/program-status-reporter.d.ts +34 -0
- package/dist/modes/interactive/program-status-reporter.d.ts.map +1 -0
- package/dist/modes/interactive/program-status-reporter.js +107 -0
- package/dist/modes/interactive/program-status-reporter.js.map +1 -0
- package/dist/modes/interactive/tasks/host-hooks.d.ts +14 -0
- package/dist/modes/interactive/tasks/host-hooks.d.ts.map +1 -0
- package/dist/modes/interactive/tasks/host-hooks.js +31 -0
- package/dist/modes/interactive/tasks/host-hooks.js.map +1 -0
- package/dist/modes/interactive/theme/dark.json +1 -1
- package/dist/modes/interactive/theme/light.json +1 -1
- package/dist/modes/interactive/theme/theme-schema.d.ts +28 -0
- package/dist/modes/interactive/theme/theme-schema.d.ts.map +1 -0
- package/dist/modes/interactive/theme/theme-schema.js +105 -0
- package/dist/modes/interactive/theme/theme-schema.js.map +1 -0
- package/dist/modes/interactive/theme/theme-tokens.d.ts +257 -0
- package/dist/modes/interactive/theme/theme-tokens.d.ts.map +1 -0
- package/dist/modes/interactive/theme/theme-tokens.js +94 -0
- package/dist/modes/interactive/theme/theme-tokens.js.map +1 -0
- package/dist/modes/interactive/theme/theme.d.ts +13 -16
- package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
- package/dist/modes/interactive/theme/theme.js +23 -31
- package/dist/modes/interactive/theme/theme.js.map +1 -1
- package/dist/modes/interactive/tool-view/tool-execution.d.ts +5 -0
- package/dist/modes/interactive/tool-view/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/tool-view/tool-execution.js +7 -0
- package/dist/modes/interactive/tool-view/tool-execution.js.map +1 -1
- package/dist/modes/print-mode.d.ts.map +1 -1
- package/dist/modes/print-mode.js +4 -0
- package/dist/modes/print-mode.js.map +1 -1
- package/dist/package-manager-cli.d.ts.map +1 -1
- package/dist/package-manager-cli.js +24 -0
- package/dist/package-manager-cli.js.map +1 -1
- package/dist/utils/ansi.d.ts +8 -0
- package/dist/utils/ansi.d.ts.map +1 -1
- package/dist/utils/ansi.js +30 -11
- package/dist/utils/ansi.js.map +1 -1
- package/dist/utils/clipboard.d.ts.map +1 -1
- package/dist/utils/clipboard.js +18 -12
- package/dist/utils/clipboard.js.map +1 -1
- package/dist/utils/image-resize-core.d.ts +12 -0
- package/dist/utils/image-resize-core.d.ts.map +1 -1
- package/dist/utils/image-resize-core.js +5 -0
- package/dist/utils/image-resize-core.js.map +1 -1
- package/dist/utils/image-resize-worker.js +3 -2
- package/dist/utils/image-resize-worker.js.map +1 -1
- package/dist/utils/image-resize.d.ts.map +1 -1
- package/dist/utils/image-resize.js +9 -10
- package/dist/utils/image-resize.js.map +1 -1
- package/docs/bundled/README.md +1 -1
- package/docs/bundled/extensions/provider.md +1 -1
- package/docs/bundled/extensions/question.md +1 -1
- package/docs/bundled/extensions/search.md +51 -0
- package/docs/bundled/extensions/statusline.md +15 -41
- package/docs/codemode.md +24 -4
- package/docs/compaction.md +2 -2
- package/docs/docs.json +0 -4
- package/docs/environment-variables.md +3 -1
- package/docs/extensions.md +15 -5
- package/docs/json.md +2 -2
- package/docs/keybindings.md +1 -0
- package/docs/llama-cpp.md +8 -1
- package/docs/mcp.md +1 -1
- package/docs/models.md +5 -1
- package/docs/providers.md +33 -0
- package/docs/rpc.md +6 -3
- package/docs/session-format.md +1 -0
- package/docs/settings.md +5 -5
- package/docs/terminal-setup.md +14 -0
- package/docs/themes.md +4 -2
- package/docs/tui.md +1 -1
- package/docs/usage.md +7 -3
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/dynamic-resources/dynamic.json +1 -1
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/overlay-test.ts +2 -2
- package/examples/extensions/plan-mode/index.ts +6 -2
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +54 -102
- package/package.json +10 -20
- package/schemas/keybindings.schema.json +453 -0
- package/schemas/models.schema.json +1157 -0
- package/schemas/settings.schema.json +782 -0
- package/schemas/theme.schema.json +365 -0
- package/dist/bundle/chunks/anthropic-messages-YIOJIMVL.js +0 -6
- package/dist/bundle/chunks/chunk-57XI7YJH.js +0 -2
- package/dist/bundle/chunks/chunk-JI4WGISU.js +0 -2
- package/dist/bundle/chunks/chunk-TCQ4HHQD.js +0 -2
- package/dist/bundle/chunks/chunk-TXJO4AJ7.js +0 -11
- package/dist/bundle/chunks/cloudflare-workers-ai-system-one-OWU5SM6J.js +0 -2
- package/dist/bundle/chunks/mistral-conversations-A2N5FSOV.js +0 -5
- package/dist/bundle/chunks/openai-codex-responses-Q6JHCWLE.js +0 -10
- package/dist/bundle/chunks/typesafe-system-one-KYKKNU3E.js +0 -2
- package/dist/extensions/web-search/auth.d.ts +0 -12
- package/dist/extensions/web-search/auth.d.ts.map +0 -1
- package/dist/extensions/web-search/auth.js +0 -90
- package/dist/extensions/web-search/auth.js.map +0 -1
- package/dist/extensions/web-search/constants.d.ts +0 -13
- package/dist/extensions/web-search/constants.d.ts.map +0 -1
- package/dist/extensions/web-search/constants.js +0 -26
- package/dist/extensions/web-search/constants.js.map +0 -1
- package/dist/extensions/web-search/execute.d.ts +0 -9
- package/dist/extensions/web-search/execute.d.ts.map +0 -1
- package/dist/extensions/web-search/execute.js +0 -96
- package/dist/extensions/web-search/execute.js.map +0 -1
- package/dist/extensions/web-search/format.d.ts +0 -21
- package/dist/extensions/web-search/format.d.ts.map +0 -1
- package/dist/extensions/web-search/format.js +0 -117
- package/dist/extensions/web-search/format.js.map +0 -1
- package/dist/extensions/web-search/index.d.ts +0 -6
- package/dist/extensions/web-search/index.d.ts.map +0 -1
- package/dist/extensions/web-search/index.js +0 -50
- package/dist/extensions/web-search/index.js.map +0 -1
- package/dist/extensions/web-search/providers/deepseek.d.ts +0 -13
- package/dist/extensions/web-search/providers/deepseek.d.ts.map +0 -1
- package/dist/extensions/web-search/providers/deepseek.js +0 -110
- package/dist/extensions/web-search/providers/deepseek.js.map +0 -1
- package/dist/extensions/web-search/providers/http.d.ts +0 -4
- package/dist/extensions/web-search/providers/http.d.ts.map +0 -1
- package/dist/extensions/web-search/providers/http.js +0 -42
- package/dist/extensions/web-search/providers/http.js.map +0 -1
- package/dist/extensions/web-search/providers/minimax.d.ts +0 -12
- package/dist/extensions/web-search/providers/minimax.d.ts.map +0 -1
- package/dist/extensions/web-search/providers/minimax.js +0 -61
- package/dist/extensions/web-search/providers/minimax.js.map +0 -1
- package/dist/extensions/web-search/render.d.ts +0 -15
- package/dist/extensions/web-search/render.d.ts.map +0 -1
- package/dist/extensions/web-search/render.js +0 -142
- package/dist/extensions/web-search/render.js.map +0 -1
- package/dist/extensions/web-search/results.d.ts +0 -35
- package/dist/extensions/web-search/results.d.ts.map +0 -1
- package/dist/extensions/web-search/results.js +0 -167
- package/dist/extensions/web-search/results.js.map +0 -1
- package/dist/extensions/web-search/schema.d.ts +0 -10
- package/dist/extensions/web-search/schema.d.ts.map +0 -1
- package/dist/extensions/web-search/schema.js +0 -36
- package/dist/extensions/web-search/schema.js.map +0 -1
- package/dist/extensions/web-search/types.d.ts +0 -51
- package/dist/extensions/web-search/types.d.ts.map +0 -1
- package/dist/extensions/web-search/types.js +0 -5
- package/dist/extensions/web-search/types.js.map +0 -1
- package/dist/modes/interactive/theme/theme-json.d.ts +0 -85
- package/dist/modes/interactive/theme/theme-json.d.ts.map +0 -1
- package/dist/modes/interactive/theme/theme-json.js +0 -132
- package/dist/modes/interactive/theme/theme-json.js.map +0 -1
- package/dist/modes/interactive/theme/theme-schema.json +0 -361
- package/docs/bundled/extensions/web-search.md +0 -46
- package/examples/plugins/pi-example-plugin/README.md +0 -38
- package/examples/plugins/pi-example-plugin/package.json +0 -10
- package/examples/plugins/pi-example-plugin/src/contract.ts +0 -13
- package/examples/plugins/pi-example-plugin/src/session.ts +0 -24
- package/examples/plugins/pi-example-plugin/src/tui.ts +0 -31
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The two Devin (Windsurf) endpoints the search tools call. Both authenticate with the API key
|
|
3
|
+
* inside the request body; neither needs a JWT exchange, a rate-limit preflight, or host details.
|
|
4
|
+
*
|
|
5
|
+
* - `GetDevstralStream` is one turn of the SWE-grep planner: a Connect-streaming protobuf request
|
|
6
|
+
* carrying a chat transcript and tool schemas, answered by one text completion.
|
|
7
|
+
* - `GetWebSearchResults` is a Connect-unary JSON request answered by `{ results: [...] }`.
|
|
8
|
+
*
|
|
9
|
+
* There is no published schema. The field numbers and the client identity below are the minimum
|
|
10
|
+
* the backend accepts; dropping any of them makes it answer `invalid_argument`.
|
|
11
|
+
*/
|
|
12
|
+
import { gunzipSync, gzipSync } from "node:zlib";
|
|
13
|
+
const SERVICE = "https://server.self-serve.windsurf.com/exa.api_server_pb.ApiServerService";
|
|
14
|
+
const APP = "windsurf";
|
|
15
|
+
const APP_VERSION = "1.48.2";
|
|
16
|
+
const LANGUAGE_SERVER_VERSION = "1.9544.35";
|
|
17
|
+
const WEB_CLIENT_VERSION = "1.9600.41";
|
|
18
|
+
const TIMEOUT_MS = 30_000;
|
|
19
|
+
export class DevinError extends Error {
|
|
20
|
+
constructor() {
|
|
21
|
+
super(...arguments);
|
|
22
|
+
this.name = "DevinError";
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
/** The credential is missing, revoked, or malformed; only signing in again fixes it. */
|
|
26
|
+
export class DevinAuthError extends DevinError {
|
|
27
|
+
constructor() {
|
|
28
|
+
super(...arguments);
|
|
29
|
+
this.name = "DevinAuthError";
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
function errorFor(code, message = "") {
|
|
33
|
+
if (code === 401 || code === 403 || code === "unauthenticated" || code === "permission_denied") {
|
|
34
|
+
return new DevinAuthError("Devin rejected the credential.");
|
|
35
|
+
}
|
|
36
|
+
if (code === 429 || code === "resource_exhausted") {
|
|
37
|
+
return new DevinError("Devin rate-limited the request. Wait a moment and retry.");
|
|
38
|
+
}
|
|
39
|
+
return new DevinError(`Devin request failed (${code}${message ? `: ${message}` : ""}).`);
|
|
40
|
+
}
|
|
41
|
+
async function post(url, init, signal) {
|
|
42
|
+
const timeout = AbortSignal.timeout(TIMEOUT_MS);
|
|
43
|
+
let response;
|
|
44
|
+
try {
|
|
45
|
+
response = await fetch(url, {
|
|
46
|
+
...init,
|
|
47
|
+
method: "POST",
|
|
48
|
+
redirect: "error",
|
|
49
|
+
signal: signal ? AbortSignal.any([signal, timeout]) : timeout,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
catch (e) {
|
|
53
|
+
if (signal?.aborted)
|
|
54
|
+
throw e;
|
|
55
|
+
throw new DevinError(timeout.aborted ? "Devin did not answer in time." : `Could not reach Devin: ${String(e)}`);
|
|
56
|
+
}
|
|
57
|
+
if (!response.ok) {
|
|
58
|
+
const body = (await response.json().catch(() => undefined));
|
|
59
|
+
throw errorFor(body?.code ?? response.status, body?.message);
|
|
60
|
+
}
|
|
61
|
+
return response;
|
|
62
|
+
}
|
|
63
|
+
// --- Protobuf, just enough for these messages ---
|
|
64
|
+
function varint(value) {
|
|
65
|
+
const bytes = [];
|
|
66
|
+
while (value > 0x7f) {
|
|
67
|
+
bytes.push((value & 0x7f) | 0x80);
|
|
68
|
+
value >>>= 7;
|
|
69
|
+
}
|
|
70
|
+
bytes.push(value);
|
|
71
|
+
return bytes;
|
|
72
|
+
}
|
|
73
|
+
function field(no, value) {
|
|
74
|
+
if (typeof value === "number")
|
|
75
|
+
return Buffer.from([...varint(no << 3), ...varint(value)]);
|
|
76
|
+
const data = typeof value === "string" ? Buffer.from(value, "utf-8") : value;
|
|
77
|
+
return Buffer.concat([Buffer.from([...varint((no << 3) | 2), ...varint(data.length)]), data]);
|
|
78
|
+
}
|
|
79
|
+
/** The length-delimited values of field `no` at the top level of `data`. */
|
|
80
|
+
function readField(data, no) {
|
|
81
|
+
const out = [];
|
|
82
|
+
let i = 0;
|
|
83
|
+
const readVarint = () => {
|
|
84
|
+
let value = 0;
|
|
85
|
+
for (let shift = 0; i < data.length; shift += 7) {
|
|
86
|
+
const b = data[i++];
|
|
87
|
+
value += (b & 0x7f) * 2 ** shift;
|
|
88
|
+
if (!(b & 0x80))
|
|
89
|
+
break;
|
|
90
|
+
}
|
|
91
|
+
return value;
|
|
92
|
+
};
|
|
93
|
+
while (i < data.length) {
|
|
94
|
+
const tag = readVarint();
|
|
95
|
+
const wire = tag & 7;
|
|
96
|
+
if (wire === 0)
|
|
97
|
+
readVarint();
|
|
98
|
+
else if (wire === 1)
|
|
99
|
+
i += 8;
|
|
100
|
+
else if (wire === 5)
|
|
101
|
+
i += 4;
|
|
102
|
+
else if (wire === 2) {
|
|
103
|
+
const length = readVarint();
|
|
104
|
+
if (tag >>> 3 === no)
|
|
105
|
+
out.push(data.subarray(i, i + length));
|
|
106
|
+
i += length;
|
|
107
|
+
}
|
|
108
|
+
else
|
|
109
|
+
break;
|
|
110
|
+
}
|
|
111
|
+
return out;
|
|
112
|
+
}
|
|
113
|
+
const ROLE = { user: 1, assistant: 2, tool: 4, system: 5 };
|
|
114
|
+
export function encodeChatRequest(apiKey, messages, tools) {
|
|
115
|
+
const metadata = Buffer.concat([
|
|
116
|
+
field(1, APP),
|
|
117
|
+
field(2, APP_VERSION),
|
|
118
|
+
field(3, apiKey),
|
|
119
|
+
field(7, LANGUAGE_SERVER_VERSION),
|
|
120
|
+
]);
|
|
121
|
+
const parts = [field(1, metadata)];
|
|
122
|
+
for (const m of messages) {
|
|
123
|
+
const msg = [field(2, ROLE[m.role]), field(3, m.content)];
|
|
124
|
+
if (m.call) {
|
|
125
|
+
msg.push(field(6, Buffer.concat([field(1, m.call.id), field(2, m.call.name), field(3, m.call.arguments)])));
|
|
126
|
+
}
|
|
127
|
+
if (m.callId)
|
|
128
|
+
msg.push(field(7, m.callId));
|
|
129
|
+
parts.push(field(2, Buffer.concat(msg)));
|
|
130
|
+
}
|
|
131
|
+
parts.push(field(3, tools));
|
|
132
|
+
return Buffer.concat(parts);
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Connect streaming envelopes: a flags byte (bit 0 gzip, bit 1 end-of-stream) and a length. Data
|
|
136
|
+
* frames carry text chunks in field 2; the end frame is JSON that names an error, if any.
|
|
137
|
+
*/
|
|
138
|
+
export function decodeChatResponse(body) {
|
|
139
|
+
let text = "";
|
|
140
|
+
let i = 0;
|
|
141
|
+
while (i + 5 <= body.length) {
|
|
142
|
+
const flags = body[i];
|
|
143
|
+
const length = body.readUInt32BE(i + 1);
|
|
144
|
+
let payload = body.subarray(i + 5, i + 5 + length);
|
|
145
|
+
i += 5 + length;
|
|
146
|
+
if (flags & 1)
|
|
147
|
+
payload = gunzipSync(payload);
|
|
148
|
+
if (flags & 2) {
|
|
149
|
+
const end = JSON.parse(payload.toString("utf-8") || "{}");
|
|
150
|
+
if (end.error)
|
|
151
|
+
throw errorFor(end.error.code ?? "unknown", end.error.message);
|
|
152
|
+
continue;
|
|
153
|
+
}
|
|
154
|
+
for (const chunk of readField(payload, 2))
|
|
155
|
+
text += chunk.toString("utf-8");
|
|
156
|
+
}
|
|
157
|
+
return text;
|
|
158
|
+
}
|
|
159
|
+
export async function chat(apiKey, messages, tools, signal) {
|
|
160
|
+
const message = gzipSync(encodeChatRequest(apiKey, messages, tools));
|
|
161
|
+
const envelope = Buffer.alloc(5);
|
|
162
|
+
envelope[0] = 1;
|
|
163
|
+
envelope.writeUInt32BE(message.length, 1);
|
|
164
|
+
const response = await post(`${SERVICE}/GetDevstralStream`, {
|
|
165
|
+
headers: {
|
|
166
|
+
"Content-Type": "application/connect+proto",
|
|
167
|
+
"Connect-Protocol-Version": "1",
|
|
168
|
+
"Connect-Content-Encoding": "gzip",
|
|
169
|
+
"Connect-Accept-Encoding": "gzip",
|
|
170
|
+
"Connect-Timeout-Ms": String(TIMEOUT_MS),
|
|
171
|
+
},
|
|
172
|
+
body: new Uint8Array(Buffer.concat([envelope, message])),
|
|
173
|
+
}, signal);
|
|
174
|
+
return decodeChatResponse(Buffer.from(await response.arrayBuffer()));
|
|
175
|
+
}
|
|
176
|
+
export async function webSearch(apiKey, query, limit, signal) {
|
|
177
|
+
const response = await post(`${SERVICE}/GetWebSearchResults`, {
|
|
178
|
+
headers: { "Content-Type": "application/json", "Connect-Protocol-Version": "1" },
|
|
179
|
+
body: JSON.stringify({
|
|
180
|
+
metadata: { apiKey, ideName: APP, ideVersion: WEB_CLIENT_VERSION, extensionVersion: WEB_CLIENT_VERSION },
|
|
181
|
+
query,
|
|
182
|
+
limit,
|
|
183
|
+
}),
|
|
184
|
+
}, signal);
|
|
185
|
+
const results = (await response.json().catch(() => undefined))?.results;
|
|
186
|
+
if (!Array.isArray(results))
|
|
187
|
+
throw new DevinError("Devin returned a malformed web search response.");
|
|
188
|
+
return results.flatMap((row) => {
|
|
189
|
+
const { url, title, summary } = (row ?? {});
|
|
190
|
+
if (typeof url !== "string" || !isWebUrl(url))
|
|
191
|
+
return [];
|
|
192
|
+
return [
|
|
193
|
+
{
|
|
194
|
+
url,
|
|
195
|
+
...(typeof title === "string" && title.trim() ? { title: title.trim() } : {}),
|
|
196
|
+
...(typeof summary === "string" && summary.trim() ? { summary: summary.trim() } : {}),
|
|
197
|
+
},
|
|
198
|
+
];
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
function isWebUrl(value) {
|
|
202
|
+
try {
|
|
203
|
+
const url = new URL(value);
|
|
204
|
+
return (url.protocol === "https:" || url.protocol === "http:") && !url.username && !url.password;
|
|
205
|
+
}
|
|
206
|
+
catch {
|
|
207
|
+
return false;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
//# sourceMappingURL=devin.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"devin.js","sourceRoot":"","sources":["../../../src/extensions/search/devin.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The two Devin (Windsurf) endpoints the search tools call. Both authenticate with the API key\n * inside the request body; neither needs a JWT exchange, a rate-limit preflight, or host details.\n *\n * - `GetDevstralStream` is one turn of the SWE-grep planner: a Connect-streaming protobuf request\n * carrying a chat transcript and tool schemas, answered by one text completion.\n * - `GetWebSearchResults` is a Connect-unary JSON request answered by `{ results: [...] }`.\n *\n * There is no published schema. The field numbers and the client identity below are the minimum\n * the backend accepts; dropping any of them makes it answer `invalid_argument`.\n */\nimport { gunzipSync, gzipSync } from \"node:zlib\";\n\nconst SERVICE = \"https://server.self-serve.windsurf.com/exa.api_server_pb.ApiServerService\";\nconst APP = \"windsurf\";\nconst APP_VERSION = \"1.48.2\";\nconst LANGUAGE_SERVER_VERSION = \"1.9544.35\";\nconst WEB_CLIENT_VERSION = \"1.9600.41\";\nconst TIMEOUT_MS = 30_000;\n\nexport class DevinError extends Error {\n\toverride name = \"DevinError\";\n}\n\n/** The credential is missing, revoked, or malformed; only signing in again fixes it. */\nexport class DevinAuthError extends DevinError {\n\toverride name = \"DevinAuthError\";\n}\n\nfunction errorFor(code: string | number, message = \"\"): DevinError {\n\tif (code === 401 || code === 403 || code === \"unauthenticated\" || code === \"permission_denied\") {\n\t\treturn new DevinAuthError(\"Devin rejected the credential.\");\n\t}\n\tif (code === 429 || code === \"resource_exhausted\") {\n\t\treturn new DevinError(\"Devin rate-limited the request. Wait a moment and retry.\");\n\t}\n\treturn new DevinError(`Devin request failed (${code}${message ? `: ${message}` : \"\"}).`);\n}\n\nasync function post(url: string, init: RequestInit, signal?: AbortSignal): Promise<Response> {\n\tconst timeout = AbortSignal.timeout(TIMEOUT_MS);\n\tlet response: Response;\n\ttry {\n\t\tresponse = await fetch(url, {\n\t\t\t...init,\n\t\t\tmethod: \"POST\",\n\t\t\tredirect: \"error\",\n\t\t\tsignal: signal ? AbortSignal.any([signal, timeout]) : timeout,\n\t\t});\n\t} catch (e) {\n\t\tif (signal?.aborted) throw e;\n\t\tthrow new DevinError(timeout.aborted ? \"Devin did not answer in time.\" : `Could not reach Devin: ${String(e)}`);\n\t}\n\tif (!response.ok) {\n\t\tconst body = (await response.json().catch(() => undefined)) as { code?: string; message?: string } | undefined;\n\t\tthrow errorFor(body?.code ?? response.status, body?.message);\n\t}\n\treturn response;\n}\n\n// --- Protobuf, just enough for these messages ---\n\nfunction varint(value: number): number[] {\n\tconst bytes: number[] = [];\n\twhile (value > 0x7f) {\n\t\tbytes.push((value & 0x7f) | 0x80);\n\t\tvalue >>>= 7;\n\t}\n\tbytes.push(value);\n\treturn bytes;\n}\n\nfunction field(no: number, value: string | number | Buffer): Buffer {\n\tif (typeof value === \"number\") return Buffer.from([...varint(no << 3), ...varint(value)]);\n\tconst data = typeof value === \"string\" ? Buffer.from(value, \"utf-8\") : value;\n\treturn Buffer.concat([Buffer.from([...varint((no << 3) | 2), ...varint(data.length)]), data]);\n}\n\n/** The length-delimited values of field `no` at the top level of `data`. */\nfunction readField(data: Buffer, no: number): Buffer[] {\n\tconst out: Buffer[] = [];\n\tlet i = 0;\n\tconst readVarint = (): number => {\n\t\tlet value = 0;\n\t\tfor (let shift = 0; i < data.length; shift += 7) {\n\t\t\tconst b = data[i++]!;\n\t\t\tvalue += (b & 0x7f) * 2 ** shift;\n\t\t\tif (!(b & 0x80)) break;\n\t\t}\n\t\treturn value;\n\t};\n\twhile (i < data.length) {\n\t\tconst tag = readVarint();\n\t\tconst wire = tag & 7;\n\t\tif (wire === 0) readVarint();\n\t\telse if (wire === 1) i += 8;\n\t\telse if (wire === 5) i += 4;\n\t\telse if (wire === 2) {\n\t\t\tconst length = readVarint();\n\t\t\tif (tag >>> 3 === no) out.push(data.subarray(i, i + length));\n\t\t\ti += length;\n\t\t} else break;\n\t}\n\treturn out;\n}\n\n// --- Planner turn ---\n\nexport interface ChatMessage {\n\trole: \"system\" | \"user\" | \"assistant\" | \"tool\";\n\tcontent: string;\n\t/** On an assistant message: the tool call it made. */\n\tcall?: { id: string; name: string; arguments: string };\n\t/** On a tool message: the id of the call it answers. */\n\tcallId?: string;\n}\n\nconst ROLE = { user: 1, assistant: 2, tool: 4, system: 5 } as const;\n\nexport function encodeChatRequest(apiKey: string, messages: ChatMessage[], tools: string): Buffer {\n\tconst metadata = Buffer.concat([\n\t\tfield(1, APP),\n\t\tfield(2, APP_VERSION),\n\t\tfield(3, apiKey),\n\t\tfield(7, LANGUAGE_SERVER_VERSION),\n\t]);\n\tconst parts = [field(1, metadata)];\n\tfor (const m of messages) {\n\t\tconst msg = [field(2, ROLE[m.role]), field(3, m.content)];\n\t\tif (m.call) {\n\t\t\tmsg.push(field(6, Buffer.concat([field(1, m.call.id), field(2, m.call.name), field(3, m.call.arguments)])));\n\t\t}\n\t\tif (m.callId) msg.push(field(7, m.callId));\n\t\tparts.push(field(2, Buffer.concat(msg)));\n\t}\n\tparts.push(field(3, tools));\n\treturn Buffer.concat(parts);\n}\n\n/**\n * Connect streaming envelopes: a flags byte (bit 0 gzip, bit 1 end-of-stream) and a length. Data\n * frames carry text chunks in field 2; the end frame is JSON that names an error, if any.\n */\nexport function decodeChatResponse(body: Buffer): string {\n\tlet text = \"\";\n\tlet i = 0;\n\twhile (i + 5 <= body.length) {\n\t\tconst flags = body[i]!;\n\t\tconst length = body.readUInt32BE(i + 1);\n\t\tlet payload = body.subarray(i + 5, i + 5 + length);\n\t\ti += 5 + length;\n\t\tif (flags & 1) payload = gunzipSync(payload);\n\t\tif (flags & 2) {\n\t\t\tconst end = JSON.parse(payload.toString(\"utf-8\") || \"{}\") as { error?: { code?: string; message?: string } };\n\t\t\tif (end.error) throw errorFor(end.error.code ?? \"unknown\", end.error.message);\n\t\t\tcontinue;\n\t\t}\n\t\tfor (const chunk of readField(payload, 2)) text += chunk.toString(\"utf-8\");\n\t}\n\treturn text;\n}\n\nexport async function chat(\n\tapiKey: string,\n\tmessages: ChatMessage[],\n\ttools: string,\n\tsignal?: AbortSignal,\n): Promise<string> {\n\tconst message = gzipSync(encodeChatRequest(apiKey, messages, tools));\n\tconst envelope = Buffer.alloc(5);\n\tenvelope[0] = 1;\n\tenvelope.writeUInt32BE(message.length, 1);\n\tconst response = await post(\n\t\t`${SERVICE}/GetDevstralStream`,\n\t\t{\n\t\t\theaders: {\n\t\t\t\t\"Content-Type\": \"application/connect+proto\",\n\t\t\t\t\"Connect-Protocol-Version\": \"1\",\n\t\t\t\t\"Connect-Content-Encoding\": \"gzip\",\n\t\t\t\t\"Connect-Accept-Encoding\": \"gzip\",\n\t\t\t\t\"Connect-Timeout-Ms\": String(TIMEOUT_MS),\n\t\t\t},\n\t\t\tbody: new Uint8Array(Buffer.concat([envelope, message])),\n\t\t},\n\t\tsignal,\n\t);\n\treturn decodeChatResponse(Buffer.from(await response.arrayBuffer()));\n}\n\n// --- Web search ---\n\nexport interface WebResult {\n\turl: string;\n\ttitle?: string;\n\t/** Query-relevant excerpts of the page, joined by `...`; up to about 4,000 characters. */\n\tsummary?: string;\n}\n\nexport async function webSearch(\n\tapiKey: string,\n\tquery: string,\n\tlimit: number,\n\tsignal?: AbortSignal,\n): Promise<WebResult[]> {\n\tconst response = await post(\n\t\t`${SERVICE}/GetWebSearchResults`,\n\t\t{\n\t\t\theaders: { \"Content-Type\": \"application/json\", \"Connect-Protocol-Version\": \"1\" },\n\t\t\tbody: JSON.stringify({\n\t\t\t\tmetadata: { apiKey, ideName: APP, ideVersion: WEB_CLIENT_VERSION, extensionVersion: WEB_CLIENT_VERSION },\n\t\t\t\tquery,\n\t\t\t\tlimit,\n\t\t\t}),\n\t\t},\n\t\tsignal,\n\t);\n\tconst results = ((await response.json().catch(() => undefined)) as { results?: unknown } | undefined)?.results;\n\tif (!Array.isArray(results)) throw new DevinError(\"Devin returned a malformed web search response.\");\n\treturn results.flatMap((row): WebResult[] => {\n\t\tconst { url, title, summary } = (row ?? {}) as Record<string, unknown>;\n\t\tif (typeof url !== \"string\" || !isWebUrl(url)) return [];\n\t\treturn [\n\t\t\t{\n\t\t\t\turl,\n\t\t\t\t...(typeof title === \"string\" && title.trim() ? { title: title.trim() } : {}),\n\t\t\t\t...(typeof summary === \"string\" && summary.trim() ? { summary: summary.trim() } : {}),\n\t\t\t},\n\t\t];\n\t});\n}\n\nfunction isWebUrl(value: string): boolean {\n\ttry {\n\t\tconst url = new URL(value);\n\t\treturn (url.protocol === \"https:\" || url.protocol === \"http:\") && !url.username && !url.password;\n\t} catch {\n\t\treturn false;\n\t}\n}\n"]}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ExtensionAPI } from "../../core/extensions/types.ts";
|
|
2
|
+
import { type WebResult } from "./devin.ts";
|
|
3
|
+
export declare function formatWebResults(query: string, results: WebResult[]): string;
|
|
4
|
+
export default function search(pi: ExtensionAPI): void;
|
|
5
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/extensions/search/index.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAKnE,OAAO,EAAkB,KAAK,SAAS,EAAa,MAAM,YAAY,CAAC;AA8CvE,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,SAAS,EAAE,GAAG,MAAM,CAW5E;AAED,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CA8DrD"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Devin Search: `code_search` and `web_search`, both authenticated by one Devin sign-in.
|
|
3
|
+
*
|
|
4
|
+
* Both tools stay registered so `/tools` and old transcripts know them; a session without a
|
|
5
|
+
* credential starts with them inactive, and signing in or out through `/search` toggles them.
|
|
6
|
+
*/
|
|
7
|
+
import { resolve } from "node:path";
|
|
8
|
+
import { Type } from "typebox";
|
|
9
|
+
import { truncateHead } from "../../core/tools/truncate.js";
|
|
10
|
+
import { codeSearch, formatLocations } from "./code-search.js";
|
|
11
|
+
import { registerSearchCommand, syncTools } from "./command.js";
|
|
12
|
+
import { getCredential } from "./credential.js";
|
|
13
|
+
import { DevinAuthError, webSearch } from "./devin.js";
|
|
14
|
+
import { renderCodeSearchCall, renderCodeSearchResult, renderWebSearchCall, renderWebSearchResult, } from "./render.js";
|
|
15
|
+
import { isInside } from "./workspace.js";
|
|
16
|
+
const WEB_EXCERPT_MAX_CHARS = 1500;
|
|
17
|
+
const CodeSearchParams = Type.Object({
|
|
18
|
+
query: Type.String({
|
|
19
|
+
description: "Natural-language description of the behavior, flow, error, or concept to locate, in concise English. Keep identifiers, API names, and error text verbatim. Not for a bare symbol, filename, or literal.",
|
|
20
|
+
}),
|
|
21
|
+
path: Type.Optional(Type.String({
|
|
22
|
+
description: "Subdirectory to search, relative to or inside the working directory. Defaults to the working directory.",
|
|
23
|
+
})),
|
|
24
|
+
});
|
|
25
|
+
const WebSearchParams = Type.Object({
|
|
26
|
+
query: Type.String({
|
|
27
|
+
description: "Web search query. Be specific: product names, versions, exact error text. English matches best.",
|
|
28
|
+
}),
|
|
29
|
+
max_results: Type.Optional(Type.Integer({ minimum: 1, maximum: 10, description: "Results to return (default 5)." })),
|
|
30
|
+
});
|
|
31
|
+
const SIGN_IN_HINT = "Ask the user to run /search to sign in to Devin.";
|
|
32
|
+
/** Run a Devin call with the current credential; credential failures tell the model what fixes them. */
|
|
33
|
+
async function withDevin(run) {
|
|
34
|
+
const credential = getCredential();
|
|
35
|
+
if (!credential)
|
|
36
|
+
throw new Error(`Devin Search is not signed in. ${SIGN_IN_HINT}`);
|
|
37
|
+
try {
|
|
38
|
+
return await run(credential.apiKey);
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
throw error instanceof DevinAuthError ? new Error(`${error.message} ${SIGN_IN_HINT}`) : error;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
export function formatWebResults(query, results) {
|
|
45
|
+
if (!results.length)
|
|
46
|
+
return `No web results for "${query}".`;
|
|
47
|
+
const blocks = results.map((r, i) => {
|
|
48
|
+
const lines = [`${i + 1}. ${r.title ?? r.url}`, ` ${r.url}`];
|
|
49
|
+
if (r.summary) {
|
|
50
|
+
const excerpt = r.summary.replace(/\n\s*\n+/g, "\n").trim();
|
|
51
|
+
lines.push(excerpt.length > WEB_EXCERPT_MAX_CHARS ? `${excerpt.slice(0, WEB_EXCERPT_MAX_CHARS)}…` : excerpt);
|
|
52
|
+
}
|
|
53
|
+
return lines.join("\n");
|
|
54
|
+
});
|
|
55
|
+
return truncateHead(`Web results for "${query}":\n\n${blocks.join("\n\n")}`).content;
|
|
56
|
+
}
|
|
57
|
+
export default function search(pi) {
|
|
58
|
+
pi.registerTool({
|
|
59
|
+
name: "code_search",
|
|
60
|
+
label: "Code Search",
|
|
61
|
+
description: "Find where behavior lives in the local repository from a description of it. " +
|
|
62
|
+
"Returns candidate files with line ranges.",
|
|
63
|
+
promptSnippet: "Find code by describing its behavior",
|
|
64
|
+
promptGuidelines: [
|
|
65
|
+
"Use `code_search` when you cannot name the file or symbol you need; use `read`, `grep`, or `find` when you can.",
|
|
66
|
+
"Read the returned ranges before editing; the locations are candidates, not answers.",
|
|
67
|
+
],
|
|
68
|
+
parameters: CodeSearchParams,
|
|
69
|
+
renderCall: renderCodeSearchCall,
|
|
70
|
+
renderResult: renderCodeSearchResult,
|
|
71
|
+
async execute(_toolCallId, params, signal, onUpdate, ctx) {
|
|
72
|
+
const root = resolve(ctx.cwd, params.path ?? ".");
|
|
73
|
+
if (!isInside(ctx.cwd, root))
|
|
74
|
+
throw new Error(`path must be inside the working directory (${ctx.cwd}).`);
|
|
75
|
+
const locations = await withDevin((apiKey) => codeSearch({
|
|
76
|
+
apiKey,
|
|
77
|
+
query: params.query.trim(),
|
|
78
|
+
root,
|
|
79
|
+
cwd: ctx.cwd,
|
|
80
|
+
signal,
|
|
81
|
+
onProgress: (text) => onUpdate?.({ content: [{ type: "text", text }], details: { locations: [] } }),
|
|
82
|
+
}));
|
|
83
|
+
return { content: [{ type: "text", text: formatLocations(locations) }], details: { locations } };
|
|
84
|
+
},
|
|
85
|
+
});
|
|
86
|
+
// Pi's system prompt carries no date, so models otherwise search with their training year.
|
|
87
|
+
const currentMonth = new Date().toLocaleDateString("en-US", { month: "long", year: "numeric" });
|
|
88
|
+
pi.registerTool({
|
|
89
|
+
name: "web_search",
|
|
90
|
+
label: "Web Search",
|
|
91
|
+
description: "Search the live web for current information. Returns titles, URLs, and the page excerpts that match the query.",
|
|
92
|
+
promptSnippet: "Search the live web for current information",
|
|
93
|
+
promptGuidelines: [
|
|
94
|
+
"Use `web_search` for information beyond your knowledge cutoff.",
|
|
95
|
+
`It is ${currentMonth}; put this year in \`web_search\` queries for recent releases, versions, or events, not the year your training data suggests.`,
|
|
96
|
+
"When an answer relies on `web_search` results, cite each result you used as a markdown link: [Title](URL).",
|
|
97
|
+
],
|
|
98
|
+
parameters: WebSearchParams,
|
|
99
|
+
renderCall: renderWebSearchCall,
|
|
100
|
+
renderResult: renderWebSearchResult,
|
|
101
|
+
async execute(_toolCallId, params, signal) {
|
|
102
|
+
const query = params.query.trim();
|
|
103
|
+
const results = await withDevin((apiKey) => webSearch(apiKey, query, params.max_results ?? 5, signal));
|
|
104
|
+
return {
|
|
105
|
+
content: [{ type: "text", text: formatWebResults(query, results) }],
|
|
106
|
+
details: { results: results.map(({ url, title }) => ({ url, title })) },
|
|
107
|
+
};
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
registerSearchCommand(pi);
|
|
111
|
+
pi.on("session_start", async () => syncTools(pi));
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/extensions/search/index.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Devin Search: `code_search` and `web_search`, both authenticated by one Devin sign-in.\n *\n * Both tools stay registered so `/tools` and old transcripts know them; a session without a\n * credential starts with them inactive, and signing in or out through `/search` toggles them.\n */\nimport { resolve } from \"node:path\";\nimport { type Static, Type } from \"typebox\";\nimport type { ExtensionAPI } from \"../../core/extensions/types.ts\";\nimport { truncateHead } from \"../../core/tools/truncate.ts\";\nimport { codeSearch, formatLocations } from \"./code-search.ts\";\nimport { registerSearchCommand, syncTools } from \"./command.ts\";\nimport { getCredential } from \"./credential.ts\";\nimport { DevinAuthError, type WebResult, webSearch } from \"./devin.ts\";\nimport {\n\ttype CodeSearchDetails,\n\trenderCodeSearchCall,\n\trenderCodeSearchResult,\n\trenderWebSearchCall,\n\trenderWebSearchResult,\n\ttype WebSearchDetails,\n} from \"./render.ts\";\nimport { isInside } from \"./workspace.ts\";\n\nconst WEB_EXCERPT_MAX_CHARS = 1500;\n\nconst CodeSearchParams = Type.Object({\n\tquery: Type.String({\n\t\tdescription:\n\t\t\t\"Natural-language description of the behavior, flow, error, or concept to locate, in concise English. Keep identifiers, API names, and error text verbatim. Not for a bare symbol, filename, or literal.\",\n\t}),\n\tpath: Type.Optional(\n\t\tType.String({\n\t\t\tdescription:\n\t\t\t\t\"Subdirectory to search, relative to or inside the working directory. Defaults to the working directory.\",\n\t\t}),\n\t),\n});\n\nconst WebSearchParams = Type.Object({\n\tquery: Type.String({\n\t\tdescription: \"Web search query. Be specific: product names, versions, exact error text. English matches best.\",\n\t}),\n\tmax_results: Type.Optional(Type.Integer({ minimum: 1, maximum: 10, description: \"Results to return (default 5).\" })),\n});\n\nconst SIGN_IN_HINT = \"Ask the user to run /search to sign in to Devin.\";\n\n/** Run a Devin call with the current credential; credential failures tell the model what fixes them. */\nasync function withDevin<T>(run: (apiKey: string) => Promise<T>): Promise<T> {\n\tconst credential = getCredential();\n\tif (!credential) throw new Error(`Devin Search is not signed in. ${SIGN_IN_HINT}`);\n\ttry {\n\t\treturn await run(credential.apiKey);\n\t} catch (error) {\n\t\tthrow error instanceof DevinAuthError ? new Error(`${error.message} ${SIGN_IN_HINT}`) : error;\n\t}\n}\n\nexport function formatWebResults(query: string, results: WebResult[]): string {\n\tif (!results.length) return `No web results for \"${query}\".`;\n\tconst blocks = results.map((r, i) => {\n\t\tconst lines = [`${i + 1}. ${r.title ?? r.url}`, ` ${r.url}`];\n\t\tif (r.summary) {\n\t\t\tconst excerpt = r.summary.replace(/\\n\\s*\\n+/g, \"\\n\").trim();\n\t\t\tlines.push(excerpt.length > WEB_EXCERPT_MAX_CHARS ? `${excerpt.slice(0, WEB_EXCERPT_MAX_CHARS)}…` : excerpt);\n\t\t}\n\t\treturn lines.join(\"\\n\");\n\t});\n\treturn truncateHead(`Web results for \"${query}\":\\n\\n${blocks.join(\"\\n\\n\")}`).content;\n}\n\nexport default function search(pi: ExtensionAPI): void {\n\tpi.registerTool<typeof CodeSearchParams, CodeSearchDetails>({\n\t\tname: \"code_search\",\n\t\tlabel: \"Code Search\",\n\t\tdescription:\n\t\t\t\"Find where behavior lives in the local repository from a description of it. \" +\n\t\t\t\"Returns candidate files with line ranges.\",\n\t\tpromptSnippet: \"Find code by describing its behavior\",\n\t\tpromptGuidelines: [\n\t\t\t\"Use `code_search` when you cannot name the file or symbol you need; use `read`, `grep`, or `find` when you can.\",\n\t\t\t\"Read the returned ranges before editing; the locations are candidates, not answers.\",\n\t\t],\n\t\tparameters: CodeSearchParams,\n\t\trenderCall: renderCodeSearchCall,\n\t\trenderResult: renderCodeSearchResult,\n\n\t\tasync execute(_toolCallId, params: Static<typeof CodeSearchParams>, signal, onUpdate, ctx) {\n\t\t\tconst root = resolve(ctx.cwd, params.path ?? \".\");\n\t\t\tif (!isInside(ctx.cwd, root)) throw new Error(`path must be inside the working directory (${ctx.cwd}).`);\n\t\t\tconst locations = await withDevin((apiKey) =>\n\t\t\t\tcodeSearch({\n\t\t\t\t\tapiKey,\n\t\t\t\t\tquery: params.query.trim(),\n\t\t\t\t\troot,\n\t\t\t\t\tcwd: ctx.cwd,\n\t\t\t\t\tsignal,\n\t\t\t\t\tonProgress: (text) => onUpdate?.({ content: [{ type: \"text\", text }], details: { locations: [] } }),\n\t\t\t\t}),\n\t\t\t);\n\t\t\treturn { content: [{ type: \"text\", text: formatLocations(locations) }], details: { locations } };\n\t\t},\n\t});\n\n\t// Pi's system prompt carries no date, so models otherwise search with their training year.\n\tconst currentMonth = new Date().toLocaleDateString(\"en-US\", { month: \"long\", year: \"numeric\" });\n\tpi.registerTool<typeof WebSearchParams, WebSearchDetails>({\n\t\tname: \"web_search\",\n\t\tlabel: \"Web Search\",\n\t\tdescription:\n\t\t\t\"Search the live web for current information. Returns titles, URLs, and the page excerpts that match the query.\",\n\t\tpromptSnippet: \"Search the live web for current information\",\n\t\tpromptGuidelines: [\n\t\t\t\"Use `web_search` for information beyond your knowledge cutoff.\",\n\t\t\t`It is ${currentMonth}; put this year in \\`web_search\\` queries for recent releases, versions, or events, not the year your training data suggests.`,\n\t\t\t\"When an answer relies on `web_search` results, cite each result you used as a markdown link: [Title](URL).\",\n\t\t],\n\t\tparameters: WebSearchParams,\n\t\trenderCall: renderWebSearchCall,\n\t\trenderResult: renderWebSearchResult,\n\n\t\tasync execute(_toolCallId, params: Static<typeof WebSearchParams>, signal) {\n\t\t\tconst query = params.query.trim();\n\t\t\tconst results = await withDevin((apiKey) => webSearch(apiKey, query, params.max_results ?? 5, signal));\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: formatWebResults(query, results) }],\n\t\t\t\tdetails: { results: results.map(({ url, title }) => ({ url, title })) },\n\t\t\t};\n\t\t},\n\t});\n\n\tregisterSearchCommand(pi);\n\tpi.on(\"session_start\", async () => syncTools(pi));\n}\n"]}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `/search` panel: one framed view whose screens replace each other in place — the account
|
|
3
|
+
* menu, browser sign-in, token paste, sign-out confirmation, and a working state between them.
|
|
4
|
+
*/
|
|
5
|
+
import { type Component, type Focusable, type TUI } from "@earendil-works/pi-tui";
|
|
6
|
+
import type { KeybindingsManager } from "../../core/keybindings.ts";
|
|
7
|
+
import { type Theme } from "../../modes/interactive/theme/theme.ts";
|
|
8
|
+
export interface AccountState {
|
|
9
|
+
/** Where the credential comes from, or undefined when signed out. */
|
|
10
|
+
source?: "saved" | "env";
|
|
11
|
+
/** Where a saved credential lives, or the environment variable that supplies one. */
|
|
12
|
+
location: string;
|
|
13
|
+
}
|
|
14
|
+
export interface PanelActions {
|
|
15
|
+
state(): AccountState;
|
|
16
|
+
/** A sign-in URL and a function that turns the pasted code or token into a verified, saved sign-in. */
|
|
17
|
+
startSignIn(): {
|
|
18
|
+
url: string;
|
|
19
|
+
complete(input: string): Promise<void>;
|
|
20
|
+
};
|
|
21
|
+
/** Verify and save a pasted token. */
|
|
22
|
+
saveToken(input: string): Promise<void>;
|
|
23
|
+
signOut(): void;
|
|
24
|
+
}
|
|
25
|
+
export declare class SearchPanel implements Component, Focusable {
|
|
26
|
+
private content;
|
|
27
|
+
private inputHandler;
|
|
28
|
+
private input;
|
|
29
|
+
private notice;
|
|
30
|
+
private _focused;
|
|
31
|
+
private readonly tui;
|
|
32
|
+
private readonly theme;
|
|
33
|
+
private readonly keybindings;
|
|
34
|
+
private readonly actions;
|
|
35
|
+
private readonly close;
|
|
36
|
+
constructor(tui: TUI, theme: Theme, keybindings: KeybindingsManager, actions: PanelActions, close: () => void);
|
|
37
|
+
get focused(): boolean;
|
|
38
|
+
set focused(value: boolean);
|
|
39
|
+
private show;
|
|
40
|
+
private muted;
|
|
41
|
+
private showMenu;
|
|
42
|
+
/** A screen with one text field; Enter submits a non-empty value, Esc returns to the menu. */
|
|
43
|
+
private showInputScreen;
|
|
44
|
+
private showBrowserSignIn;
|
|
45
|
+
private showPaste;
|
|
46
|
+
private showSignOut;
|
|
47
|
+
/** Show a working state while `task` runs, then return to the menu with its outcome. */
|
|
48
|
+
private run;
|
|
49
|
+
handleInput(data: string): void;
|
|
50
|
+
render(width: number): string[];
|
|
51
|
+
invalidate(): void;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=panel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"panel.d.ts","sourceRoot":"","sources":["../../../src/extensions/search/panel.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EACN,KAAK,SAAS,EAEd,KAAK,SAAS,EAMd,KAAK,GAAG,EAGR,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAIpE,OAAO,EAAsB,KAAK,KAAK,EAAE,MAAM,wCAAwC,CAAC;AAExF,MAAM,WAAW,YAAY;IAC5B,qEAAqE;IACrE,MAAM,CAAC,EAAE,OAAO,GAAG,KAAK,CAAC;IACzB,qFAAqF;IACrF,QAAQ,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IAC5B,KAAK,IAAI,YAAY,CAAC;IACtB,uGAAuG;IACvG,WAAW,IAAI;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE,CAAC;IACvE,sCAAsC;IACtC,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,OAAO,IAAI,IAAI,CAAC;CAChB;AAID,qBAAa,WAAY,YAAW,SAAS,EAAE,SAAS;IACvD,OAAO,CAAC,OAAO,CAAmB;IAClC,OAAO,CAAC,YAAY,CAAuC;IAC3D,OAAO,CAAC,KAAK,CAAoB;IACjC,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAM;IAC1B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAQ;IAC9B,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAqB;IACjD,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IACvC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAa;gBAEvB,GAAG,EAAE,GAAG,EAAE,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,IAAI;IAS7G,IAAI,OAAO,IAAI,OAAO,CAErB;IAED,IAAI,OAAO,CAAC,KAAK,EAAE,OAAO,EAGzB;IAED,OAAO,CAAC,IAAI;IAuBZ,OAAO,CAAC,KAAK;IAIb,OAAO,CAAC,QAAQ;IAsChB,8FAA8F;IAC9F,OAAO,CAAC,eAAe;IA0BvB,OAAO,CAAC,iBAAiB;IAgBzB,OAAO,CAAC,SAAS;IAIjB,OAAO,CAAC,WAAW;IAuBnB,wFAAwF;YAC1E,GAAG;IAejB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAK/B,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE;IAM/B,UAAU,IAAI,IAAI;CAGlB"}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `/search` panel: one framed view whose screens replace each other in place — the account
|
|
3
|
+
* menu, browser sign-in, token paste, sign-out confirmation, and a working state between them.
|
|
4
|
+
*/
|
|
5
|
+
import { Container, Input, SelectList, Spacer, Text, truncateToWidth, visibleWidth, } from "@earendil-works/pi-tui";
|
|
6
|
+
import { AuthUrlComponent } from "../../modes/interactive/components/auth-url.js";
|
|
7
|
+
import { DynamicBorder } from "../../modes/interactive/components/dynamic-border.js";
|
|
8
|
+
import { keyHint } from "../../modes/interactive/components/keybinding-hints.js";
|
|
9
|
+
import { getSelectListTheme } from "../../modes/interactive/theme/theme.js";
|
|
10
|
+
export class SearchPanel {
|
|
11
|
+
constructor(tui, theme, keybindings, actions, close) {
|
|
12
|
+
this.content = new Container();
|
|
13
|
+
this._focused = false;
|
|
14
|
+
this.tui = tui;
|
|
15
|
+
this.theme = theme;
|
|
16
|
+
this.keybindings = keybindings;
|
|
17
|
+
this.actions = actions;
|
|
18
|
+
this.close = close;
|
|
19
|
+
this.showMenu();
|
|
20
|
+
}
|
|
21
|
+
get focused() {
|
|
22
|
+
return this._focused;
|
|
23
|
+
}
|
|
24
|
+
set focused(value) {
|
|
25
|
+
this._focused = value;
|
|
26
|
+
if (this.input)
|
|
27
|
+
this.input.focused = value;
|
|
28
|
+
}
|
|
29
|
+
show(title, body, hints, handler, input) {
|
|
30
|
+
const accent = (text) => this.theme.fg("accent", text);
|
|
31
|
+
const frame = new Container();
|
|
32
|
+
frame.addChild(new DynamicBorder(accent));
|
|
33
|
+
frame.addChild(new Text(accent(this.theme.bold(title)), 1, 0));
|
|
34
|
+
for (const child of body)
|
|
35
|
+
frame.addChild(child);
|
|
36
|
+
frame.addChild(new Spacer(1));
|
|
37
|
+
frame.addChild(new Text(hints.join(this.theme.fg("dim", " • ")), 1, 0));
|
|
38
|
+
frame.addChild(new DynamicBorder(accent));
|
|
39
|
+
if (this.input)
|
|
40
|
+
this.input.focused = false;
|
|
41
|
+
this.content = frame;
|
|
42
|
+
this.inputHandler = handler;
|
|
43
|
+
this.input = input;
|
|
44
|
+
if (input)
|
|
45
|
+
input.focused = this._focused;
|
|
46
|
+
this.tui.requestRender();
|
|
47
|
+
}
|
|
48
|
+
muted(text) {
|
|
49
|
+
return new Text(this.theme.fg("muted", text), 1, 0);
|
|
50
|
+
}
|
|
51
|
+
showMenu() {
|
|
52
|
+
const { source, location } = this.actions.state();
|
|
53
|
+
const status = source
|
|
54
|
+
? `${this.theme.fg("success", "●")} Signed in${source === "env" ? " from the environment" : ""} ${this.theme.fg("dim", `· ${location}`)}`
|
|
55
|
+
: `${this.theme.fg("dim", "○")} Not signed in ${this.theme.fg("dim", "· code_search and web_search are off")}`;
|
|
56
|
+
const body = [new Text(status, 1, 0)];
|
|
57
|
+
if (this.notice) {
|
|
58
|
+
body.push(new Text(this.theme.fg(this.notice.kind, this.notice.text), 1, 0));
|
|
59
|
+
this.notice = undefined;
|
|
60
|
+
}
|
|
61
|
+
body.push(new Spacer(1));
|
|
62
|
+
const items = [
|
|
63
|
+
{
|
|
64
|
+
value: "browser",
|
|
65
|
+
label: source ? "Switch account" : "Sign in with browser",
|
|
66
|
+
description: "Authorize on devin.ai, then paste the code",
|
|
67
|
+
},
|
|
68
|
+
{ value: "paste", label: "Paste a token", description: "Use an existing Devin session token" },
|
|
69
|
+
];
|
|
70
|
+
if (source === "saved")
|
|
71
|
+
items.push({ value: "signout", label: "Sign out", description: "Forget the saved token" });
|
|
72
|
+
const list = new SelectList(items, items.length, getSelectListTheme());
|
|
73
|
+
list.onSelect = (item) => {
|
|
74
|
+
if (item.value === "browser")
|
|
75
|
+
this.showBrowserSignIn();
|
|
76
|
+
else if (item.value === "paste")
|
|
77
|
+
this.showPaste();
|
|
78
|
+
else
|
|
79
|
+
this.showSignOut();
|
|
80
|
+
};
|
|
81
|
+
list.onCancel = () => this.close();
|
|
82
|
+
body.push(list);
|
|
83
|
+
this.show("Devin Search", body, [keyHint("tui.select.confirm", "select"), keyHint("tui.select.cancel", "close")], (data) => list.handleInput(data));
|
|
84
|
+
}
|
|
85
|
+
/** A screen with one text field; Enter submits a non-empty value, Esc returns to the menu. */
|
|
86
|
+
showInputScreen(title, intro, label, submit, extraKey) {
|
|
87
|
+
const input = new Input();
|
|
88
|
+
this.show(title, [...intro, new Spacer(1), this.muted(label), input], [keyHint("tui.select.confirm", "submit"), keyHint("tui.select.cancel", "back")], (data) => {
|
|
89
|
+
if (this.keybindings.matches(data, "tui.select.confirm")) {
|
|
90
|
+
const value = input.getValue().trim();
|
|
91
|
+
if (value)
|
|
92
|
+
void this.run(() => submit(value));
|
|
93
|
+
}
|
|
94
|
+
else if (this.keybindings.matches(data, "tui.select.cancel")) {
|
|
95
|
+
this.showMenu();
|
|
96
|
+
}
|
|
97
|
+
else if (!extraKey?.(data)) {
|
|
98
|
+
input.handleInput(data);
|
|
99
|
+
}
|
|
100
|
+
}, input);
|
|
101
|
+
}
|
|
102
|
+
showBrowserSignIn() {
|
|
103
|
+
const attempt = this.actions.startSignIn();
|
|
104
|
+
const link = new AuthUrlComponent(this.tui, attempt.url);
|
|
105
|
+
this.showInputScreen("Sign in to Devin", [new Spacer(1), this.muted("Approve access in your browser. If it did not open, visit:"), link], "Paste the code Devin shows:", (value) => attempt.complete(value), (data) => {
|
|
106
|
+
if (!this.keybindings.matches(data, "app.message.copy"))
|
|
107
|
+
return false;
|
|
108
|
+
void link.copy();
|
|
109
|
+
return true;
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
showPaste() {
|
|
113
|
+
this.showInputScreen("Paste a token", [], "Devin session token:", (value) => this.actions.saveToken(value));
|
|
114
|
+
}
|
|
115
|
+
showSignOut() {
|
|
116
|
+
const { location } = this.actions.state();
|
|
117
|
+
const items = [
|
|
118
|
+
{ value: "signout", label: "Sign out", description: `Remove the token from ${location}` },
|
|
119
|
+
{ value: "back", label: "Cancel" },
|
|
120
|
+
];
|
|
121
|
+
const list = new SelectList(items, items.length, getSelectListTheme());
|
|
122
|
+
list.onSelect = (item) => {
|
|
123
|
+
if (item.value === "signout") {
|
|
124
|
+
this.actions.signOut();
|
|
125
|
+
this.notice = { kind: "success", text: "Signed out." };
|
|
126
|
+
}
|
|
127
|
+
this.showMenu();
|
|
128
|
+
};
|
|
129
|
+
list.onCancel = () => this.showMenu();
|
|
130
|
+
this.show("Sign out of Devin?", [new Spacer(1), list], [keyHint("tui.select.confirm", "select"), keyHint("tui.select.cancel", "back")], (data) => list.handleInput(data));
|
|
131
|
+
}
|
|
132
|
+
/** Show a working state while `task` runs, then return to the menu with its outcome. */
|
|
133
|
+
async run(task) {
|
|
134
|
+
this.show("Devin Search", [new Spacer(1), this.muted("Verifying with Devin…")], [this.theme.fg("dim", "please wait")]);
|
|
135
|
+
try {
|
|
136
|
+
await task();
|
|
137
|
+
this.notice = { kind: "success", text: "Signed in — code_search and web_search are on." };
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
this.notice = { kind: "error", text: error instanceof Error ? error.message : String(error) };
|
|
141
|
+
}
|
|
142
|
+
this.showMenu();
|
|
143
|
+
}
|
|
144
|
+
handleInput(data) {
|
|
145
|
+
this.inputHandler?.(data);
|
|
146
|
+
this.tui.requestRender();
|
|
147
|
+
}
|
|
148
|
+
render(width) {
|
|
149
|
+
return this.content
|
|
150
|
+
.render(width)
|
|
151
|
+
.map((line) => (visibleWidth(line) > width ? truncateToWidth(line, width, "") : line));
|
|
152
|
+
}
|
|
153
|
+
invalidate() {
|
|
154
|
+
this.content.invalidate();
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=panel.js.map
|