@f5-sales-demo/xcsh 19.51.2
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 +7073 -0
- package/README.md +14 -0
- package/examples/README.md +21 -0
- package/examples/custom-tools/README.md +109 -0
- package/examples/custom-tools/hello/index.ts +20 -0
- package/examples/custom-tools/todo/index.ts +206 -0
- package/examples/extensions/README.md +143 -0
- package/examples/extensions/api-demo.ts +89 -0
- package/examples/extensions/chalk-logger.ts +25 -0
- package/examples/extensions/hello.ts +32 -0
- package/examples/extensions/pirate.ts +43 -0
- package/examples/extensions/plan-mode.ts +551 -0
- package/examples/extensions/reload-runtime.ts +37 -0
- package/examples/extensions/todo.ts +296 -0
- package/examples/extensions/tools.ts +145 -0
- package/examples/extensions/with-deps/index.ts +36 -0
- package/examples/extensions/with-deps/package-lock.json +31 -0
- package/examples/extensions/with-deps/package.json +16 -0
- package/examples/hooks/README.md +56 -0
- package/examples/hooks/auto-commit-on-exit.ts +48 -0
- package/examples/hooks/confirm-destructive.ts +58 -0
- package/examples/hooks/custom-compaction.ts +115 -0
- package/examples/hooks/dirty-repo-guard.ts +51 -0
- package/examples/hooks/file-trigger.ts +40 -0
- package/examples/hooks/git-checkpoint.ts +52 -0
- package/examples/hooks/handoff.ts +149 -0
- package/examples/hooks/permission-gate.ts +33 -0
- package/examples/hooks/protected-paths.ts +29 -0
- package/examples/hooks/qna.ts +118 -0
- package/examples/hooks/status-line.ts +39 -0
- package/examples/sdk/01-minimal.ts +21 -0
- package/examples/sdk/02-custom-model.ts +49 -0
- package/examples/sdk/03-custom-prompt.ts +43 -0
- package/examples/sdk/04-skills.ts +43 -0
- package/examples/sdk/06-extensions.ts +80 -0
- package/examples/sdk/06-hooks.ts +61 -0
- package/examples/sdk/07-context-files.ts +35 -0
- package/examples/sdk/08-prompt-templates.ts +41 -0
- package/examples/sdk/08-slash-commands.ts +46 -0
- package/examples/sdk/09-api-keys-and-oauth.ts +54 -0
- package/examples/sdk/11-sessions.ts +47 -0
- package/examples/sdk/README.md +172 -0
- package/package.json +539 -0
- package/scripts/build-info/resolvers.ts +51 -0
- package/scripts/capture-ax-fixture.ts +84 -0
- package/scripts/capture-login-fixture.ts +30 -0
- package/scripts/check-workflow-field-coverage.ts +101 -0
- package/scripts/extension-uat-harness.ts +340 -0
- package/scripts/format-prompts.ts +68 -0
- package/scripts/generate-api-spec-index.ts +580 -0
- package/scripts/generate-branding-index.ts +81 -0
- package/scripts/generate-build-info.ts +106 -0
- package/scripts/generate-console-catalog.ts +88 -0
- package/scripts/generate-console-field-metadata.ts +74 -0
- package/scripts/generate-docs-index.ts +40 -0
- package/scripts/generate-template.ts +32 -0
- package/scripts/generate-terraform-index.ts +81 -0
- package/scripts/mermaid-gallery.ts +132 -0
- package/scripts/uat-matrix-modalities.ts +451 -0
- package/scripts/uat-matrix-report.ts +175 -0
- package/scripts/uat-matrix.ts +353 -0
- package/src/async/index.ts +2 -0
- package/src/async/job-manager.ts +416 -0
- package/src/async/support.ts +5 -0
- package/src/autoresearch/apply-contract-to-state.ts +1 -0
- package/src/autoresearch/command-resume.md +17 -0
- package/src/autoresearch/contract.ts +205 -0
- package/src/autoresearch/dashboard.ts +374 -0
- package/src/autoresearch/git.ts +191 -0
- package/src/autoresearch/helpers.ts +328 -0
- package/src/autoresearch/index.ts +402 -0
- package/src/autoresearch/prompt.md +236 -0
- package/src/autoresearch/resume-message.md +16 -0
- package/src/autoresearch/state.ts +303 -0
- package/src/autoresearch/tools/init-experiment.ts +400 -0
- package/src/autoresearch/tools/log-experiment.ts +793 -0
- package/src/autoresearch/tools/run-experiment.ts +679 -0
- package/src/autoresearch/types.ts +114 -0
- package/src/browser/acquire.ts +249 -0
- package/src/browser/actions.ts +126 -0
- package/src/browser/auth.ts +176 -0
- package/src/browser/ax.ts +134 -0
- package/src/browser/cdp-core.ts +45 -0
- package/src/browser/cdp-page-actions.ts +51 -0
- package/src/browser/chrome-locate.ts +66 -0
- package/src/browser/dom-context.ts +89 -0
- package/src/browser/dt-context.ts +100 -0
- package/src/browser/extension-bridge.ts +182 -0
- package/src/browser/extension-page-actions.ts +397 -0
- package/src/browser/extension-provider.ts +373 -0
- package/src/browser/index.ts +17 -0
- package/src/browser/input-commit.ts +74 -0
- package/src/browser/native-messaging.ts +20 -0
- package/src/browser/page-actions.ts +18 -0
- package/src/browser/provider.ts +155 -0
- package/src/browser/resolver.ts +126 -0
- package/src/browser/selector.ts +40 -0
- package/src/bun-imports.d.ts +22 -0
- package/src/capability/context-file.ts +43 -0
- package/src/capability/extension-module.ts +34 -0
- package/src/capability/extension.ts +47 -0
- package/src/capability/fs.ts +107 -0
- package/src/capability/hook.ts +40 -0
- package/src/capability/index.ts +438 -0
- package/src/capability/instruction.ts +37 -0
- package/src/capability/mcp.ts +74 -0
- package/src/capability/prompt.ts +35 -0
- package/src/capability/rule.ts +224 -0
- package/src/capability/settings.ts +34 -0
- package/src/capability/skill.ts +50 -0
- package/src/capability/slash-command.ts +40 -0
- package/src/capability/ssh.ts +41 -0
- package/src/capability/system-prompt.ts +34 -0
- package/src/capability/tool.ts +38 -0
- package/src/capability/types.ts +168 -0
- package/src/cli/agents-cli.ts +138 -0
- package/src/cli/args.ts +286 -0
- package/src/cli/chrome-cli.ts +88 -0
- package/src/cli/classify-install-target.ts +50 -0
- package/src/cli/commands/init-xdg.ts +27 -0
- package/src/cli/config-cli.ts +418 -0
- package/src/cli/file-processor.ts +121 -0
- package/src/cli/grep-cli.ts +160 -0
- package/src/cli/grievances-cli.ts +78 -0
- package/src/cli/initial-message.ts +58 -0
- package/src/cli/jupyter-cli.ts +106 -0
- package/src/cli/list-models.ts +128 -0
- package/src/cli/plugin-cli.ts +964 -0
- package/src/cli/read-cli.ts +68 -0
- package/src/cli/session-picker.ts +52 -0
- package/src/cli/setup-cli.ts +479 -0
- package/src/cli/shell-cli.ts +174 -0
- package/src/cli/ssh-cli.ts +179 -0
- package/src/cli/stats-cli.ts +182 -0
- package/src/cli/update-cli.ts +446 -0
- package/src/cli/web-search-cli.ts +203 -0
- package/src/cli.ts +123 -0
- package/src/commands/agents.ts +57 -0
- package/src/commands/chrome-host.ts +71 -0
- package/src/commands/chrome.ts +28 -0
- package/src/commands/commit.ts +36 -0
- package/src/commands/config.ts +51 -0
- package/src/commands/grep.ts +48 -0
- package/src/commands/grievances.ts +20 -0
- package/src/commands/jupyter.ts +32 -0
- package/src/commands/launch.ts +144 -0
- package/src/commands/plugin.ts +78 -0
- package/src/commands/read.ts +33 -0
- package/src/commands/setup.ts +42 -0
- package/src/commands/shell.ts +29 -0
- package/src/commands/ssh.ts +60 -0
- package/src/commands/stats.ts +29 -0
- package/src/commands/update.ts +21 -0
- package/src/commands/web-search.ts +46 -0
- package/src/commit/agentic/agent.ts +314 -0
- package/src/commit/agentic/fallback.ts +96 -0
- package/src/commit/agentic/index.ts +354 -0
- package/src/commit/agentic/prompts/analyze-file.md +22 -0
- package/src/commit/agentic/prompts/session-user.md +25 -0
- package/src/commit/agentic/prompts/split-confirm.md +1 -0
- package/src/commit/agentic/prompts/system.md +38 -0
- package/src/commit/agentic/state.ts +60 -0
- package/src/commit/agentic/tools/analyze-file.ts +127 -0
- package/src/commit/agentic/tools/git-file-diff.ts +191 -0
- package/src/commit/agentic/tools/git-hunk.ts +50 -0
- package/src/commit/agentic/tools/git-overview.ts +81 -0
- package/src/commit/agentic/tools/index.ts +54 -0
- package/src/commit/agentic/tools/propose-changelog.ts +139 -0
- package/src/commit/agentic/tools/propose-commit.ts +122 -0
- package/src/commit/agentic/tools/recent-commits.ts +81 -0
- package/src/commit/agentic/tools/schemas.ts +31 -0
- package/src/commit/agentic/tools/split-commit.ts +251 -0
- package/src/commit/agentic/topo-sort.ts +44 -0
- package/src/commit/agentic/trivial.ts +51 -0
- package/src/commit/agentic/validation.ts +183 -0
- package/src/commit/analysis/conventional.ts +122 -0
- package/src/commit/analysis/index.ts +4 -0
- package/src/commit/analysis/scope.ts +242 -0
- package/src/commit/analysis/summary.ts +105 -0
- package/src/commit/analysis/validation.ts +66 -0
- package/src/commit/changelog/detect.ts +40 -0
- package/src/commit/changelog/generate.ts +101 -0
- package/src/commit/changelog/index.ts +234 -0
- package/src/commit/changelog/parse.ts +44 -0
- package/src/commit/cli.ts +85 -0
- package/src/commit/git/diff.ts +148 -0
- package/src/commit/index.ts +5 -0
- package/src/commit/map-reduce/index.ts +69 -0
- package/src/commit/map-reduce/map-phase.ts +193 -0
- package/src/commit/map-reduce/reduce-phase.ts +108 -0
- package/src/commit/map-reduce/utils.ts +9 -0
- package/src/commit/message.ts +11 -0
- package/src/commit/model-selection.ts +66 -0
- package/src/commit/pipeline.ts +242 -0
- package/src/commit/prompts/analysis-system.md +148 -0
- package/src/commit/prompts/analysis-user.md +38 -0
- package/src/commit/prompts/changelog-system.md +50 -0
- package/src/commit/prompts/changelog-user.md +18 -0
- package/src/commit/prompts/file-observer-system.md +24 -0
- package/src/commit/prompts/file-observer-user.md +8 -0
- package/src/commit/prompts/reduce-system.md +50 -0
- package/src/commit/prompts/reduce-user.md +17 -0
- package/src/commit/prompts/summary-retry.md +3 -0
- package/src/commit/prompts/summary-system.md +38 -0
- package/src/commit/prompts/summary-user.md +13 -0
- package/src/commit/prompts/types-description.md +2 -0
- package/src/commit/types.ts +118 -0
- package/src/commit/utils/exclusions.ts +42 -0
- package/src/commit/utils.ts +44 -0
- package/src/config/auto-config.ts +698 -0
- package/src/config/context-schema.json +115 -0
- package/src/config/file-lock.ts +121 -0
- package/src/config/keybindings.ts +493 -0
- package/src/config/mcp-schema.json +230 -0
- package/src/config/model-equivalence.ts +675 -0
- package/src/config/model-registry.ts +2265 -0
- package/src/config/model-resolver.ts +1289 -0
- package/src/config/prompt-templates.ts +271 -0
- package/src/config/resolve-config-value.ts +110 -0
- package/src/config/settings-schema.ts +2155 -0
- package/src/config/settings.ts +730 -0
- package/src/config.ts +418 -0
- package/src/cursor.ts +323 -0
- package/src/dap/client.ts +674 -0
- package/src/dap/config.ts +150 -0
- package/src/dap/defaults.json +211 -0
- package/src/dap/index.ts +4 -0
- package/src/dap/session.ts +1255 -0
- package/src/dap/types.ts +600 -0
- package/src/debug/index.ts +440 -0
- package/src/debug/log-formatting.ts +58 -0
- package/src/debug/log-viewer.ts +908 -0
- package/src/debug/profiler.ts +158 -0
- package/src/debug/report-bundle.ts +365 -0
- package/src/debug/system-info.ts +107 -0
- package/src/discovery/agents-md.ts +67 -0
- package/src/discovery/agents.ts +219 -0
- package/src/discovery/builtin.ts +851 -0
- package/src/discovery/claude-plugins.ts +297 -0
- package/src/discovery/claude.ts +543 -0
- package/src/discovery/cline.ts +83 -0
- package/src/discovery/codex.ts +535 -0
- package/src/discovery/cursor.ts +220 -0
- package/src/discovery/gemini.ts +396 -0
- package/src/discovery/github.ts +118 -0
- package/src/discovery/helpers.ts +934 -0
- package/src/discovery/index.ts +79 -0
- package/src/discovery/language.ts +46 -0
- package/src/discovery/mcp-json.ts +171 -0
- package/src/discovery/opencode.ts +393 -0
- package/src/discovery/plugin-dir-roots.ts +28 -0
- package/src/discovery/ssh.ts +153 -0
- package/src/discovery/substitute-plugin-root.ts +29 -0
- package/src/discovery/vscode.ts +105 -0
- package/src/discovery/windsurf.ts +147 -0
- package/src/edit/diff.ts +818 -0
- package/src/edit/index.ts +481 -0
- package/src/edit/line-hash.ts +67 -0
- package/src/edit/modes/chunk.ts +762 -0
- package/src/edit/modes/hashline.ts +1366 -0
- package/src/edit/modes/patch.ts +1791 -0
- package/src/edit/modes/replace.ts +1115 -0
- package/src/edit/normalize.ts +375 -0
- package/src/edit/renderer.ts +627 -0
- package/src/exa/factory.ts +61 -0
- package/src/exa/index.ts +27 -0
- package/src/exa/mcp-client.ts +293 -0
- package/src/exa/render.ts +232 -0
- package/src/exa/researcher.ts +47 -0
- package/src/exa/search.ts +86 -0
- package/src/exa/types.ts +166 -0
- package/src/exa/websets.ts +247 -0
- package/src/exec/bash-executor.ts +332 -0
- package/src/exec/exec.ts +53 -0
- package/src/exec/idle-timeout-watchdog.ts +126 -0
- package/src/exec/non-interactive-env.ts +48 -0
- package/src/export/custom-share.ts +65 -0
- package/src/export/html/index.ts +161 -0
- package/src/export/html/template.css +1001 -0
- package/src/export/html/template.generated.ts +2 -0
- package/src/export/html/template.html +46 -0
- package/src/export/html/template.js +1950 -0
- package/src/export/html/template.macro.ts +24 -0
- package/src/export/html/vendor/highlight.min.js +1213 -0
- package/src/export/html/vendor/marked.min.js +6 -0
- package/src/export/ttsr.ts +434 -0
- package/src/extensibility/custom-commands/bundled/ci-green/index.ts +25 -0
- package/src/extensibility/custom-commands/bundled/review/index.ts +456 -0
- package/src/extensibility/custom-commands/index.ts +2 -0
- package/src/extensibility/custom-commands/loader.ts +236 -0
- package/src/extensibility/custom-commands/types.ts +111 -0
- package/src/extensibility/custom-tools/index.ts +7 -0
- package/src/extensibility/custom-tools/loader.ts +238 -0
- package/src/extensibility/custom-tools/types.ts +251 -0
- package/src/extensibility/custom-tools/wrapper.ts +47 -0
- package/src/extensibility/extensions/index.ts +15 -0
- package/src/extensibility/extensions/loader.ts +572 -0
- package/src/extensibility/extensions/runner.ts +848 -0
- package/src/extensibility/extensions/types.ts +1394 -0
- package/src/extensibility/extensions/wrapper.ts +191 -0
- package/src/extensibility/hooks/index.ts +5 -0
- package/src/extensibility/hooks/loader.ts +255 -0
- package/src/extensibility/hooks/runner.ts +425 -0
- package/src/extensibility/hooks/tool-wrapper.ts +108 -0
- package/src/extensibility/hooks/types.ts +826 -0
- package/src/extensibility/plugins/doctor.ts +66 -0
- package/src/extensibility/plugins/git-url.ts +281 -0
- package/src/extensibility/plugins/index.ts +9 -0
- package/src/extensibility/plugins/installer.ts +192 -0
- package/src/extensibility/plugins/loader.ts +267 -0
- package/src/extensibility/plugins/manager.ts +731 -0
- package/src/extensibility/plugins/marketplace/cache.ts +136 -0
- package/src/extensibility/plugins/marketplace/fetcher.ts +318 -0
- package/src/extensibility/plugins/marketplace/index.ts +6 -0
- package/src/extensibility/plugins/marketplace/manager.ts +781 -0
- package/src/extensibility/plugins/marketplace/prerequisites.ts +255 -0
- package/src/extensibility/plugins/marketplace/registry.ts +196 -0
- package/src/extensibility/plugins/marketplace/source-resolver.ts +147 -0
- package/src/extensibility/plugins/marketplace/types.ts +201 -0
- package/src/extensibility/plugins/parser.ts +105 -0
- package/src/extensibility/plugins/types.ts +194 -0
- package/src/extensibility/skills.ts +269 -0
- package/src/extensibility/slash-commands.ts +246 -0
- package/src/extensibility/tool-proxy.ts +25 -0
- package/src/extensibility/utils.ts +38 -0
- package/src/index.ts +61 -0
- package/src/internal-urls/agent-protocol.ts +136 -0
- package/src/internal-urls/api-catalog-resolve.ts +495 -0
- package/src/internal-urls/api-catalog-types.ts +94 -0
- package/src/internal-urls/api-spec-resolve.ts +1036 -0
- package/src/internal-urls/api-spec-types.ts +239 -0
- package/src/internal-urls/artifact-protocol.ts +97 -0
- package/src/internal-urls/branding-index.generated.ts +88 -0
- package/src/internal-urls/build-info-runtime.ts +302 -0
- package/src/internal-urls/build-info.generated.ts +33 -0
- package/src/internal-urls/computer-profile.ts +692 -0
- package/src/internal-urls/console-catalog-types.ts +21 -0
- package/src/internal-urls/console-catalog.generated.ts +532 -0
- package/src/internal-urls/console-field-metadata-types.ts +59 -0
- package/src/internal-urls/console-field-metadata.generated.ts +4841 -0
- package/src/internal-urls/console-resolve.ts +178 -0
- package/src/internal-urls/docs-index.generated.ts +698 -0
- package/src/internal-urls/extension-api.md +147 -0
- package/src/internal-urls/index.ts +46 -0
- package/src/internal-urls/jobs-protocol.ts +119 -0
- package/src/internal-urls/json-query.ts +126 -0
- package/src/internal-urls/local-protocol.ts +206 -0
- package/src/internal-urls/mcp-protocol.ts +156 -0
- package/src/internal-urls/memory-protocol.ts +133 -0
- package/src/internal-urls/parse.ts +72 -0
- package/src/internal-urls/profile-collectors.ts +106 -0
- package/src/internal-urls/router.ts +55 -0
- package/src/internal-urls/rule-protocol.ts +55 -0
- package/src/internal-urls/skill-protocol.ts +111 -0
- package/src/internal-urls/terraform-index.generated.ts +1852 -0
- package/src/internal-urls/terraform-resolve.ts +184 -0
- package/src/internal-urls/terraform-types.ts +45 -0
- package/src/internal-urls/types.ts +52 -0
- package/src/internal-urls/user-profile.ts +363 -0
- package/src/internal-urls/xcsh-protocol.ts +644 -0
- package/src/ipy/cancellation.ts +28 -0
- package/src/ipy/executor.ts +1155 -0
- package/src/ipy/gateway-coordinator.ts +424 -0
- package/src/ipy/kernel.ts +1091 -0
- package/src/ipy/modules.ts +144 -0
- package/src/ipy/prelude.py +849 -0
- package/src/ipy/prelude.ts +3 -0
- package/src/ipy/runtime.ts +221 -0
- package/src/locales/ar.json +512 -0
- package/src/locales/de.json +512 -0
- package/src/locales/en.json +549 -0
- package/src/locales/es.json +512 -0
- package/src/locales/fr.json +512 -0
- package/src/locales/hi.json +512 -0
- package/src/locales/index.ts +29 -0
- package/src/locales/it.json +512 -0
- package/src/locales/ja.json +512 -0
- package/src/locales/ko.json +512 -0
- package/src/locales/pt-br.json +512 -0
- package/src/locales/th.json +512 -0
- package/src/locales/zh-cn.json +512 -0
- package/src/locales/zh-tw.json +512 -0
- package/src/lsp/client.ts +941 -0
- package/src/lsp/clients/biome-client.ts +202 -0
- package/src/lsp/clients/index.ts +50 -0
- package/src/lsp/clients/lsp-linter-client.ts +93 -0
- package/src/lsp/clients/swiftlint-client.ts +120 -0
- package/src/lsp/config.ts +418 -0
- package/src/lsp/defaults.json +999 -0
- package/src/lsp/edits.ts +109 -0
- package/src/lsp/index.ts +1746 -0
- package/src/lsp/lspmux.ts +233 -0
- package/src/lsp/render.ts +692 -0
- package/src/lsp/startup-events.ts +13 -0
- package/src/lsp/types.ts +444 -0
- package/src/lsp/utils.ts +691 -0
- package/src/main.ts +944 -0
- package/src/mcp/client.ts +482 -0
- package/src/mcp/config-writer.ts +225 -0
- package/src/mcp/config.ts +365 -0
- package/src/mcp/discoverable-tool-metadata.ts +202 -0
- package/src/mcp/index.ts +29 -0
- package/src/mcp/json-rpc.ts +84 -0
- package/src/mcp/loader.ts +124 -0
- package/src/mcp/manager.ts +1152 -0
- package/src/mcp/oauth-discovery.ts +349 -0
- package/src/mcp/oauth-flow.ts +387 -0
- package/src/mcp/render.ts +157 -0
- package/src/mcp/smithery-auth.ts +104 -0
- package/src/mcp/smithery-connect.ts +145 -0
- package/src/mcp/smithery-registry.ts +477 -0
- package/src/mcp/tool-bridge.ts +417 -0
- package/src/mcp/tool-cache.ts +117 -0
- package/src/mcp/transports/http.ts +475 -0
- package/src/mcp/transports/index.ts +6 -0
- package/src/mcp/transports/stdio.ts +325 -0
- package/src/mcp/types.ts +423 -0
- package/src/memories/index.ts +1115 -0
- package/src/memories/storage.ts +577 -0
- package/src/modes/acp/acp-agent.ts +1361 -0
- package/src/modes/acp/acp-event-mapper.ts +538 -0
- package/src/modes/acp/acp-mode.ts +15 -0
- package/src/modes/acp/index.ts +2 -0
- package/src/modes/components/agent-dashboard.ts +1124 -0
- package/src/modes/components/assistant-message.ts +213 -0
- package/src/modes/components/bash-execution.ts +345 -0
- package/src/modes/components/bordered-loader.ts +41 -0
- package/src/modes/components/branch-summary-message.ts +45 -0
- package/src/modes/components/btw-panel.ts +103 -0
- package/src/modes/components/compaction-summary-message.ts +51 -0
- package/src/modes/components/context-add-wizard.ts +534 -0
- package/src/modes/components/countdown-timer.ts +75 -0
- package/src/modes/components/custom-editor.ts +238 -0
- package/src/modes/components/custom-message.ts +91 -0
- package/src/modes/components/diff.ts +210 -0
- package/src/modes/components/dynamic-border.ts +25 -0
- package/src/modes/components/extensions/extension-dashboard.ts +326 -0
- package/src/modes/components/extensions/extension-list.ts +492 -0
- package/src/modes/components/extensions/index.ts +9 -0
- package/src/modes/components/extensions/inspector-panel.ts +317 -0
- package/src/modes/components/extensions/state-manager.ts +587 -0
- package/src/modes/components/extensions/types.ts +191 -0
- package/src/modes/components/footer.ts +262 -0
- package/src/modes/components/gutter-block.ts +315 -0
- package/src/modes/components/history-search.ts +158 -0
- package/src/modes/components/hook-editor.ts +151 -0
- package/src/modes/components/hook-input.ts +81 -0
- package/src/modes/components/hook-message.ts +100 -0
- package/src/modes/components/hook-selector.ts +192 -0
- package/src/modes/components/index.ts +36 -0
- package/src/modes/components/keybinding-hints.ts +65 -0
- package/src/modes/components/login-dialog.ts +164 -0
- package/src/modes/components/mcp-add-wizard.ts +1314 -0
- package/src/modes/components/model-selector.ts +946 -0
- package/src/modes/components/oauth-selector.ts +211 -0
- package/src/modes/components/plugin-selector.ts +95 -0
- package/src/modes/components/plugin-settings.ts +477 -0
- package/src/modes/components/plugins/index.ts +5 -0
- package/src/modes/components/plugins/plugin-dashboard.ts +523 -0
- package/src/modes/components/plugins/plugin-inspector-pane.ts +84 -0
- package/src/modes/components/plugins/plugin-list-pane.ts +109 -0
- package/src/modes/components/plugins/state-manager.ts +229 -0
- package/src/modes/components/plugins/types.ts +51 -0
- package/src/modes/components/plugins/utils.ts +6 -0
- package/src/modes/components/python-execution.ts +244 -0
- package/src/modes/components/queue-mode-selector.ts +56 -0
- package/src/modes/components/read-tool-group.ts +137 -0
- package/src/modes/components/session-observer-overlay.ts +483 -0
- package/src/modes/components/session-selector.ts +343 -0
- package/src/modes/components/settings-defs.ts +568 -0
- package/src/modes/components/settings-selector.ts +641 -0
- package/src/modes/components/show-images-selector.ts +45 -0
- package/src/modes/components/skill-message.ts +90 -0
- package/src/modes/components/status-line/context-gradient.ts +64 -0
- package/src/modes/components/status-line/git-utils.ts +42 -0
- package/src/modes/components/status-line/hex-ansi.ts +29 -0
- package/src/modes/components/status-line/index.ts +4 -0
- package/src/modes/components/status-line/presets.ts +174 -0
- package/src/modes/components/status-line/segments.ts +494 -0
- package/src/modes/components/status-line/separators.ts +55 -0
- package/src/modes/components/status-line/token-rate.ts +66 -0
- package/src/modes/components/status-line/types.ts +96 -0
- package/src/modes/components/status-line-segment-editor.ts +361 -0
- package/src/modes/components/status-line.ts +729 -0
- package/src/modes/components/theme-selector.ts +63 -0
- package/src/modes/components/thinking-selector.ts +52 -0
- package/src/modes/components/todo-reminder.ts +54 -0
- package/src/modes/components/tool-execution.ts +781 -0
- package/src/modes/components/tree-selector.ts +908 -0
- package/src/modes/components/ttsr-notification.ts +80 -0
- package/src/modes/components/user-message-selector.ts +141 -0
- package/src/modes/components/user-message.ts +100 -0
- package/src/modes/components/visual-truncate.ts +63 -0
- package/src/modes/components/welcome-checks.ts +313 -0
- package/src/modes/components/welcome.ts +270 -0
- package/src/modes/controllers/btw-controller.ts +193 -0
- package/src/modes/controllers/chord-routing.ts +37 -0
- package/src/modes/controllers/command-controller.ts +1293 -0
- package/src/modes/controllers/context-command-controller.ts +61 -0
- package/src/modes/controllers/event-controller.ts +743 -0
- package/src/modes/controllers/extension-ui-controller.ts +983 -0
- package/src/modes/controllers/input-controller.ts +877 -0
- package/src/modes/controllers/mcp-command-controller.ts +1940 -0
- package/src/modes/controllers/selector-controller.ts +1292 -0
- package/src/modes/controllers/ssh-command-controller.ts +421 -0
- package/src/modes/index.ts +34 -0
- package/src/modes/interactive-mode.ts +1781 -0
- package/src/modes/oauth-manual-input.ts +42 -0
- package/src/modes/print-mode.ts +196 -0
- package/src/modes/prompt-action-autocomplete.ts +231 -0
- package/src/modes/rpc/host-tools.ts +186 -0
- package/src/modes/rpc/rpc-client.ts +762 -0
- package/src/modes/rpc/rpc-mode.ts +877 -0
- package/src/modes/rpc/rpc-types.ts +322 -0
- package/src/modes/session-observer-registry.ts +146 -0
- package/src/modes/shared.ts +30 -0
- package/src/modes/theme/defaults/index.ts +7 -0
- package/src/modes/theme/defaults/xcsh-dark.json +113 -0
- package/src/modes/theme/defaults/xcsh-light.json +115 -0
- package/src/modes/theme/mermaid-cache.ts +151 -0
- package/src/modes/theme/mermaid-palette.ts +39 -0
- package/src/modes/theme/theme-schema.json +553 -0
- package/src/modes/theme/theme.ts +2563 -0
- package/src/modes/types.ts +273 -0
- package/src/modes/utils/hotkeys-markdown.ts +60 -0
- package/src/modes/utils/keybinding-matchers.ts +30 -0
- package/src/modes/utils/read-group-outcome-aggregator.ts +55 -0
- package/src/modes/utils/sanitize-error-message.ts +60 -0
- package/src/modes/utils/tools-markdown.ts +28 -0
- package/src/modes/utils/ui-helpers.ts +734 -0
- package/src/plan-mode/approved-plan.ts +55 -0
- package/src/plan-mode/state.ts +6 -0
- package/src/priority.json +37 -0
- package/src/prompts/agents/designer.md +67 -0
- package/src/prompts/agents/explore.md +61 -0
- package/src/prompts/agents/frontmatter.md +10 -0
- package/src/prompts/agents/init.md +36 -0
- package/src/prompts/agents/librarian.md +121 -0
- package/src/prompts/agents/plan.md +49 -0
- package/src/prompts/agents/reviewer.md +127 -0
- package/src/prompts/agents/task.md +16 -0
- package/src/prompts/ci-green-request.md +35 -0
- package/src/prompts/compaction/branch-summary-context.md +5 -0
- package/src/prompts/compaction/branch-summary-preamble.md +2 -0
- package/src/prompts/compaction/branch-summary.md +30 -0
- package/src/prompts/compaction/compaction-short-summary.md +9 -0
- package/src/prompts/compaction/compaction-summary-context.md +5 -0
- package/src/prompts/compaction/compaction-summary.md +38 -0
- package/src/prompts/compaction/compaction-turn-prefix.md +17 -0
- package/src/prompts/compaction/compaction-update-summary.md +45 -0
- package/src/prompts/memories/consolidation.md +30 -0
- package/src/prompts/memories/read-path.md +11 -0
- package/src/prompts/memories/stage_one_input.md +6 -0
- package/src/prompts/memories/stage_one_system.md +21 -0
- package/src/prompts/review-request.md +70 -0
- package/src/prompts/system/agent-creation-architect.md +65 -0
- package/src/prompts/system/agent-creation-user.md +6 -0
- package/src/prompts/system/auto-handoff-threshold-focus.md +1 -0
- package/src/prompts/system/btw-user.md +8 -0
- package/src/prompts/system/commit-message-system.md +2 -0
- package/src/prompts/system/custom-system-prompt.md +82 -0
- package/src/prompts/system/eager-todo.md +13 -0
- package/src/prompts/system/file-operations.md +10 -0
- package/src/prompts/system/handoff-document.md +48 -0
- package/src/prompts/system/plan-mode-active.md +114 -0
- package/src/prompts/system/plan-mode-approved.md +23 -0
- package/src/prompts/system/plan-mode-reference.md +14 -0
- package/src/prompts/system/plan-mode-subagent.md +34 -0
- package/src/prompts/system/plan-mode-tool-decision-reminder.md +9 -0
- package/src/prompts/system/subagent-submit-reminder.md +7 -0
- package/src/prompts/system/subagent-system-prompt.md +36 -0
- package/src/prompts/system/subagent-user-prompt.md +12 -0
- package/src/prompts/system/summarization-system.md +3 -0
- package/src/prompts/system/system-prompt.md +698 -0
- package/src/prompts/system/title-system.md +2 -0
- package/src/prompts/system/ttsr-interrupt.md +7 -0
- package/src/prompts/system/web-search.md +28 -0
- package/src/prompts/tools/ask.md +28 -0
- package/src/prompts/tools/ast-edit.md +48 -0
- package/src/prompts/tools/ast-grep.md +54 -0
- package/src/prompts/tools/async-result.md +5 -0
- package/src/prompts/tools/bash.md +67 -0
- package/src/prompts/tools/browser.md +26 -0
- package/src/prompts/tools/calculator.md +10 -0
- package/src/prompts/tools/cancel-job.md +5 -0
- package/src/prompts/tools/catalog-workflow-runner.md +13 -0
- package/src/prompts/tools/checkpoint.md +16 -0
- package/src/prompts/tools/chunk-edit.md +279 -0
- package/src/prompts/tools/debug.md +43 -0
- package/src/prompts/tools/display-image.md +23 -0
- package/src/prompts/tools/exit-plan-mode.md +41 -0
- package/src/prompts/tools/find.md +26 -0
- package/src/prompts/tools/gemini-image.md +7 -0
- package/src/prompts/tools/grep.md +29 -0
- package/src/prompts/tools/hashline.md +131 -0
- package/src/prompts/tools/inspect-image-system.md +20 -0
- package/src/prompts/tools/inspect-image.md +32 -0
- package/src/prompts/tools/lsp.md +33 -0
- package/src/prompts/tools/patch.md +77 -0
- package/src/prompts/tools/poll.md +5 -0
- package/src/prompts/tools/python.md +60 -0
- package/src/prompts/tools/read-chunk.md +35 -0
- package/src/prompts/tools/read.md +63 -0
- package/src/prompts/tools/render-mermaid.md +9 -0
- package/src/prompts/tools/replace.md +36 -0
- package/src/prompts/tools/resolve.md +8 -0
- package/src/prompts/tools/rewind.md +13 -0
- package/src/prompts/tools/search-tool-bm25.md +34 -0
- package/src/prompts/tools/ssh.md +44 -0
- package/src/prompts/tools/task-summary.md +28 -0
- package/src/prompts/tools/task.md +131 -0
- package/src/prompts/tools/todo-write.md +89 -0
- package/src/prompts/tools/vim.md +98 -0
- package/src/prompts/tools/web-search.md +10 -0
- package/src/prompts/tools/write.md +14 -0
- package/src/prompts/tools/xcsh-api.md +283 -0
- package/src/resource-management/index.ts +42 -0
- package/src/sdk.ts +2123 -0
- package/src/secrets/index.ts +146 -0
- package/src/secrets/obfuscator.ts +290 -0
- package/src/secrets/regex.ts +21 -0
- package/src/services/context-env.ts +102 -0
- package/src/services/xcsh-api-client.ts +230 -0
- package/src/services/xcsh-context-command.ts +803 -0
- package/src/services/xcsh-context-display.ts +49 -0
- package/src/services/xcsh-context-indicators.ts +17 -0
- package/src/services/xcsh-context-segment.ts +39 -0
- package/src/services/xcsh-context.ts +1410 -0
- package/src/services/xcsh-env.ts +107 -0
- package/src/services/xcsh-knowledge.ts +177 -0
- package/src/services/xcsh-table.ts +164 -0
- package/src/session/agent-session.ts +6690 -0
- package/src/session/agent-storage.ts +451 -0
- package/src/session/artifacts.ts +132 -0
- package/src/session/auth-storage.ts +17 -0
- package/src/session/blob-store.ts +135 -0
- package/src/session/compaction/branch-summarization.ts +322 -0
- package/src/session/compaction/compaction.ts +1388 -0
- package/src/session/compaction/index.ts +7 -0
- package/src/session/compaction/pruning.ts +91 -0
- package/src/session/compaction/utils.ts +184 -0
- package/src/session/history-storage.ts +253 -0
- package/src/session/messages.ts +597 -0
- package/src/session/session-dump-format.ts +203 -0
- package/src/session/session-manager.ts +2816 -0
- package/src/session/session-storage.ts +370 -0
- package/src/session/streaming-output.ts +770 -0
- package/src/session/tool-choice-queue.ts +213 -0
- package/src/slash-commands/builtin-registry.ts +1614 -0
- package/src/slash-commands/export-command.ts +178 -0
- package/src/slash-commands/marketplace-install-parser.ts +99 -0
- package/src/slash-commands/resource-commands.ts +250 -0
- package/src/ssh/config-writer.ts +183 -0
- package/src/ssh/connection-manager.ts +445 -0
- package/src/ssh/ssh-executor.ts +131 -0
- package/src/ssh/sshfs-mount.ts +137 -0
- package/src/ssh/utils.ts +8 -0
- package/src/stt/downloader.ts +71 -0
- package/src/stt/index.ts +3 -0
- package/src/stt/recorder.ts +351 -0
- package/src/stt/setup.ts +52 -0
- package/src/stt/stt-controller.ts +160 -0
- package/src/stt/transcribe.py +70 -0
- package/src/stt/transcriber.ts +91 -0
- package/src/system-prompt.ts +688 -0
- package/src/task/agents.ts +166 -0
- package/src/task/commands.ts +131 -0
- package/src/task/discovery.ts +126 -0
- package/src/task/executor.ts +1324 -0
- package/src/task/index.ts +1197 -0
- package/src/task/isolation-backend.ts +72 -0
- package/src/task/name-generator.ts +1577 -0
- package/src/task/output-manager.ts +107 -0
- package/src/task/parallel.ts +116 -0
- package/src/task/render.ts +1035 -0
- package/src/task/subprocess-tool-registry.ts +88 -0
- package/src/task/template.ts +33 -0
- package/src/task/types.ts +230 -0
- package/src/task/worktree.ts +580 -0
- package/src/task/xcsh-command.ts +26 -0
- package/src/thinking.ts +87 -0
- package/src/tools/action-renderer.ts +198 -0
- package/src/tools/archive-reader.ts +315 -0
- package/src/tools/ask.ts +791 -0
- package/src/tools/ast-edit.ts +492 -0
- package/src/tools/ast-grep.ts +453 -0
- package/src/tools/auto-generated-guard.ts +305 -0
- package/src/tools/bash-interactive.ts +383 -0
- package/src/tools/bash-interceptor.ts +67 -0
- package/src/tools/bash-normalize.ts +107 -0
- package/src/tools/bash-skill-urls.ts +246 -0
- package/src/tools/bash.ts +878 -0
- package/src/tools/browser-renderer.ts +129 -0
- package/src/tools/browser.ts +1366 -0
- package/src/tools/calculator.ts +543 -0
- package/src/tools/cancel-job.ts +100 -0
- package/src/tools/catalog-workflow-runner.ts +718 -0
- package/src/tools/checkpoint.ts +133 -0
- package/src/tools/context.ts +39 -0
- package/src/tools/debug.ts +1004 -0
- package/src/tools/display-image-renderer.ts +96 -0
- package/src/tools/display-image.ts +109 -0
- package/src/tools/exit-plan-mode.ts +101 -0
- package/src/tools/fetch.ts +1462 -0
- package/src/tools/find.ts +437 -0
- package/src/tools/fs-cache-invalidation.ts +33 -0
- package/src/tools/gemini-image.ts +1004 -0
- package/src/tools/grep.ts +705 -0
- package/src/tools/index.ts +442 -0
- package/src/tools/inspect-image-renderer.ts +101 -0
- package/src/tools/inspect-image.ts +176 -0
- package/src/tools/json-tree.ts +266 -0
- package/src/tools/jtd-to-json-schema.ts +199 -0
- package/src/tools/jtd-to-typescript.ts +136 -0
- package/src/tools/jtd-utils.ts +102 -0
- package/src/tools/list-limit.ts +40 -0
- package/src/tools/mermaid-renderer.ts +127 -0
- package/src/tools/notebook.ts +288 -0
- package/src/tools/output-meta.ts +588 -0
- package/src/tools/path-utils.ts +560 -0
- package/src/tools/plan-mode-guard.ts +41 -0
- package/src/tools/poll-tool.ts +177 -0
- package/src/tools/puppeteer/00_stealth_tampering.txt +63 -0
- package/src/tools/puppeteer/01_stealth_activity.txt +20 -0
- package/src/tools/puppeteer/02_stealth_hairline.txt +11 -0
- package/src/tools/puppeteer/03_stealth_botd.txt +384 -0
- package/src/tools/puppeteer/04_stealth_iframe.txt +81 -0
- package/src/tools/puppeteer/05_stealth_webgl.txt +75 -0
- package/src/tools/puppeteer/06_stealth_screen.txt +72 -0
- package/src/tools/puppeteer/07_stealth_fonts.txt +97 -0
- package/src/tools/puppeteer/08_stealth_audio.txt +51 -0
- package/src/tools/puppeteer/09_stealth_locale.txt +46 -0
- package/src/tools/puppeteer/10_stealth_plugins.txt +206 -0
- package/src/tools/puppeteer/11_stealth_hardware.txt +8 -0
- package/src/tools/puppeteer/12_stealth_codecs.txt +40 -0
- package/src/tools/puppeteer/13_stealth_worker.txt +74 -0
- package/src/tools/python.ts +1184 -0
- package/src/tools/read.ts +1591 -0
- package/src/tools/render-mermaid.ts +93 -0
- package/src/tools/render-utils.ts +677 -0
- package/src/tools/renderers.ts +82 -0
- package/src/tools/report-tool-issue.ts +80 -0
- package/src/tools/resolve.ts +196 -0
- package/src/tools/review.ts +238 -0
- package/src/tools/search-tool-bm25.ts +288 -0
- package/src/tools/sqlite-reader.ts +623 -0
- package/src/tools/ssh.ts +322 -0
- package/src/tools/submit-result.ts +229 -0
- package/src/tools/todo-render.ts +33 -0
- package/src/tools/todo-write.ts +440 -0
- package/src/tools/tool-errors.ts +62 -0
- package/src/tools/tool-result.ts +93 -0
- package/src/tools/tool-timeouts.ts +30 -0
- package/src/tools/vim.ts +981 -0
- package/src/tools/write.ts +671 -0
- package/src/tools/xcsh-api-renderer.ts +402 -0
- package/src/tools/xcsh-api.ts +887 -0
- package/src/tui/code-cell.ts +101 -0
- package/src/tui/file-list.ts +47 -0
- package/src/tui/index.ts +11 -0
- package/src/tui/output-block.ts +175 -0
- package/src/tui/status-line.ts +39 -0
- package/src/tui/tree-list.ts +84 -0
- package/src/tui/types.ts +15 -0
- package/src/tui/utils.ts +103 -0
- package/src/utils/changelog.ts +98 -0
- package/src/utils/clipboard.ts +80 -0
- package/src/utils/command-args.ts +76 -0
- package/src/utils/commit-message-generator.ts +137 -0
- package/src/utils/edit-mode.ts +50 -0
- package/src/utils/event-bus.ts +33 -0
- package/src/utils/external-editor.ts +65 -0
- package/src/utils/file-display-mode.ts +37 -0
- package/src/utils/file-mentions.ts +376 -0
- package/src/utils/fuzzy.ts +108 -0
- package/src/utils/git.ts +1495 -0
- package/src/utils/gitstatus.ts +140 -0
- package/src/utils/image-convert.ts +27 -0
- package/src/utils/image-loading.ts +98 -0
- package/src/utils/image-passthrough.ts +118 -0
- package/src/utils/image-resize.ts +272 -0
- package/src/utils/image-viewer.ts +17 -0
- package/src/utils/lang-from-path.ts +239 -0
- package/src/utils/markit.ts +81 -0
- package/src/utils/open.ts +20 -0
- package/src/utils/session-color.ts +55 -0
- package/src/utils/shell-snapshot.ts +188 -0
- package/src/utils/title-generator.ts +193 -0
- package/src/utils/tool-choice.ts +28 -0
- package/src/utils/tools-manager.ts +356 -0
- package/src/vim/buffer.ts +309 -0
- package/src/vim/commands.ts +382 -0
- package/src/vim/engine.ts +2426 -0
- package/src/vim/parser.ts +151 -0
- package/src/vim/render.ts +252 -0
- package/src/vim/types.ts +197 -0
- package/src/web/kagi.ts +174 -0
- package/src/web/parallel.ts +346 -0
- package/src/web/scrapers/artifacthub.ts +207 -0
- package/src/web/scrapers/arxiv.ts +83 -0
- package/src/web/scrapers/aur.ts +162 -0
- package/src/web/scrapers/biorxiv.ts +133 -0
- package/src/web/scrapers/bluesky.ts +262 -0
- package/src/web/scrapers/brew.ts +172 -0
- package/src/web/scrapers/cheatsh.ts +68 -0
- package/src/web/scrapers/chocolatey.ts +196 -0
- package/src/web/scrapers/choosealicense.ts +95 -0
- package/src/web/scrapers/cisa-kev.ts +87 -0
- package/src/web/scrapers/clojars.ts +154 -0
- package/src/web/scrapers/coingecko.ts +177 -0
- package/src/web/scrapers/crates-io.ts +110 -0
- package/src/web/scrapers/crossref.ts +136 -0
- package/src/web/scrapers/devto.ts +147 -0
- package/src/web/scrapers/discogs.ts +306 -0
- package/src/web/scrapers/discourse.ts +197 -0
- package/src/web/scrapers/dockerhub.ts +138 -0
- package/src/web/scrapers/docs-rs.ts +653 -0
- package/src/web/scrapers/fdroid.ts +134 -0
- package/src/web/scrapers/firefox-addons.ts +191 -0
- package/src/web/scrapers/flathub.ts +223 -0
- package/src/web/scrapers/github-gist.ts +58 -0
- package/src/web/scrapers/github.ts +452 -0
- package/src/web/scrapers/gitlab.ts +401 -0
- package/src/web/scrapers/go-pkg.ts +266 -0
- package/src/web/scrapers/hackage.ts +140 -0
- package/src/web/scrapers/hackernews.ts +189 -0
- package/src/web/scrapers/hex.ts +105 -0
- package/src/web/scrapers/huggingface.ts +321 -0
- package/src/web/scrapers/iacr.ts +89 -0
- package/src/web/scrapers/index.ts +252 -0
- package/src/web/scrapers/jetbrains-marketplace.ts +159 -0
- package/src/web/scrapers/lemmy.ts +203 -0
- package/src/web/scrapers/lobsters.ts +175 -0
- package/src/web/scrapers/mastodon.ts +292 -0
- package/src/web/scrapers/maven.ts +138 -0
- package/src/web/scrapers/mdn.ts +169 -0
- package/src/web/scrapers/metacpan.ts +222 -0
- package/src/web/scrapers/musicbrainz.ts +250 -0
- package/src/web/scrapers/npm.ts +98 -0
- package/src/web/scrapers/nuget.ts +183 -0
- package/src/web/scrapers/nvd.ts +222 -0
- package/src/web/scrapers/ollama.ts +239 -0
- package/src/web/scrapers/open-vsx.ts +106 -0
- package/src/web/scrapers/opencorporates.ts +292 -0
- package/src/web/scrapers/openlibrary.ts +336 -0
- package/src/web/scrapers/orcid.ts +286 -0
- package/src/web/scrapers/osv.ts +176 -0
- package/src/web/scrapers/packagist.ts +160 -0
- package/src/web/scrapers/pub-dev.ts +143 -0
- package/src/web/scrapers/pubmed.ts +211 -0
- package/src/web/scrapers/pypi.ts +112 -0
- package/src/web/scrapers/rawg.ts +110 -0
- package/src/web/scrapers/readthedocs.ts +120 -0
- package/src/web/scrapers/reddit.ts +95 -0
- package/src/web/scrapers/repology.ts +251 -0
- package/src/web/scrapers/rfc.ts +201 -0
- package/src/web/scrapers/rubygems.ts +103 -0
- package/src/web/scrapers/searchcode.ts +190 -0
- package/src/web/scrapers/sec-edgar.ts +261 -0
- package/src/web/scrapers/semantic-scholar.ts +171 -0
- package/src/web/scrapers/snapcraft.ts +187 -0
- package/src/web/scrapers/sourcegraph.ts +336 -0
- package/src/web/scrapers/spdx.ts +108 -0
- package/src/web/scrapers/spotify.ts +198 -0
- package/src/web/scrapers/stackoverflow.ts +120 -0
- package/src/web/scrapers/terraform.ts +277 -0
- package/src/web/scrapers/tldr.ts +47 -0
- package/src/web/scrapers/twitter.ts +93 -0
- package/src/web/scrapers/types.ts +267 -0
- package/src/web/scrapers/utils.ts +109 -0
- package/src/web/scrapers/vimeo.ts +133 -0
- package/src/web/scrapers/vscode-marketplace.ts +187 -0
- package/src/web/scrapers/w3c.ts +156 -0
- package/src/web/scrapers/wikidata.ts +344 -0
- package/src/web/scrapers/wikipedia.ts +84 -0
- package/src/web/scrapers/youtube.ts +313 -0
- package/src/web/search/errors.ts +120 -0
- package/src/web/search/index.ts +346 -0
- package/src/web/search/params.ts +129 -0
- package/src/web/search/provider.ts +97 -0
- package/src/web/search/providers/anthropic.ts +339 -0
- package/src/web/search/providers/base.ts +35 -0
- package/src/web/search/providers/brave.ts +150 -0
- package/src/web/search/providers/codex.ts +402 -0
- package/src/web/search/providers/exa.ts +264 -0
- package/src/web/search/providers/firecrawl.ts +115 -0
- package/src/web/search/providers/gemini.ts +566 -0
- package/src/web/search/providers/jina.ts +99 -0
- package/src/web/search/providers/kagi.ts +70 -0
- package/src/web/search/providers/kimi.ts +157 -0
- package/src/web/search/providers/parallel.ts +63 -0
- package/src/web/search/providers/perplexity.ts +546 -0
- package/src/web/search/providers/synthetic.ts +113 -0
- package/src/web/search/providers/tavily.ts +162 -0
- package/src/web/search/providers/utils.ts +36 -0
- package/src/web/search/providers/zai.ts +311 -0
- package/src/web/search/render.ts +348 -0
- package/src/web/search/types.ts +438 -0
- package/src/web/search/utils.ts +17 -0
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* High-performance git status via gitstatusd daemon.
|
|
3
|
+
*
|
|
4
|
+
* gitstatusd is a C binary that provides git status 10x faster than
|
|
5
|
+
* `git status --porcelain` by caching dirty file state in memory.
|
|
6
|
+
* Protocol: named pipes with \x1f field separators and \x1e record terminators.
|
|
7
|
+
*/
|
|
8
|
+
import * as fs from "node:fs";
|
|
9
|
+
import * as os from "node:os";
|
|
10
|
+
import * as path from "node:path";
|
|
11
|
+
import { logger } from "@f5xc-salesdemos/pi-utils";
|
|
12
|
+
|
|
13
|
+
export interface GitStatusResult {
|
|
14
|
+
workdir: string;
|
|
15
|
+
commit: string;
|
|
16
|
+
localBranch: string;
|
|
17
|
+
remoteBranch: string;
|
|
18
|
+
remoteName: string;
|
|
19
|
+
remoteUrl: string;
|
|
20
|
+
action: string;
|
|
21
|
+
indexSize: number;
|
|
22
|
+
staged: number;
|
|
23
|
+
unstaged: number;
|
|
24
|
+
conflicted: number;
|
|
25
|
+
untracked: number;
|
|
26
|
+
ahead: number;
|
|
27
|
+
behind: number;
|
|
28
|
+
stashes: number;
|
|
29
|
+
tag: string;
|
|
30
|
+
commitSummary: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const FIELD_SEP = "\x1f";
|
|
34
|
+
const RECORD_SEP = "\x1e";
|
|
35
|
+
|
|
36
|
+
let daemon: { proc: ReturnType<typeof Bun.spawn>; requestId: number } | null = null;
|
|
37
|
+
let startAttempted = false;
|
|
38
|
+
|
|
39
|
+
function findGitstatusd(): string | null {
|
|
40
|
+
const cacheDir = path.join(os.homedir(), ".cache", "gitstatus");
|
|
41
|
+
const arch = process.arch === "arm64" ? "aarch64" : "x86_64";
|
|
42
|
+
const platform = process.platform === "darwin" ? "darwin" : "linux";
|
|
43
|
+
const binary = path.join(cacheDir, `gitstatusd-${platform}-${arch}`);
|
|
44
|
+
if (fs.existsSync(binary)) return binary;
|
|
45
|
+
|
|
46
|
+
// Fallback: search PATH
|
|
47
|
+
const result = Bun.spawnSync(["which", "gitstatusd"], { stdout: "pipe" });
|
|
48
|
+
if (result.exitCode === 0) return result.stdout.toString().trim();
|
|
49
|
+
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function startDaemon(): boolean {
|
|
54
|
+
if (daemon) return true;
|
|
55
|
+
if (startAttempted) return false;
|
|
56
|
+
startAttempted = true;
|
|
57
|
+
|
|
58
|
+
const binary = findGitstatusd();
|
|
59
|
+
if (!binary) {
|
|
60
|
+
logger.debug("gitstatusd not found, falling back to git CLI");
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
try {
|
|
65
|
+
const proc = Bun.spawn(
|
|
66
|
+
[binary, "-G", "v1.5.4", "-s", "-1", "-u", "-1", "-d", "-1", "-c", "-1", "-m", "-1", "-v", "FATAL", "-t", "4"],
|
|
67
|
+
{ stdin: "pipe", stdout: "pipe", stderr: "ignore" },
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
daemon = { proc, requestId: 0 };
|
|
71
|
+
|
|
72
|
+
proc.exited.then(() => {
|
|
73
|
+
daemon = null;
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
return true;
|
|
77
|
+
} catch (err) {
|
|
78
|
+
logger.debug("Failed to start gitstatusd", { error: err instanceof Error ? err.message : String(err) });
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export async function queryGitStatus(directory: string, timeoutMs = 3000): Promise<GitStatusResult | null> {
|
|
84
|
+
if (!startDaemon()) return null;
|
|
85
|
+
if (!daemon) return null;
|
|
86
|
+
|
|
87
|
+
const reqId = String(++daemon.requestId);
|
|
88
|
+
const request = `${reqId}${FIELD_SEP}${directory}${RECORD_SEP}`;
|
|
89
|
+
|
|
90
|
+
try {
|
|
91
|
+
const stdin = daemon.proc.stdin as { write(data: string): void; flush(): void };
|
|
92
|
+
stdin.write(request);
|
|
93
|
+
stdin.flush();
|
|
94
|
+
|
|
95
|
+
const reader = (daemon.proc.stdout as ReadableStream<Uint8Array>).getReader();
|
|
96
|
+
const timeoutPromise = new Promise<null>(resolve => setTimeout(() => resolve(null), timeoutMs));
|
|
97
|
+
const readPromise = reader.read().then(({ value }) => (value ? new TextDecoder().decode(value) : null));
|
|
98
|
+
|
|
99
|
+
const response = await Promise.race([readPromise, timeoutPromise]);
|
|
100
|
+
reader.releaseLock();
|
|
101
|
+
|
|
102
|
+
if (!response) return null;
|
|
103
|
+
|
|
104
|
+
const raw = response.replace(RECORD_SEP, "");
|
|
105
|
+
const fields = raw.split(FIELD_SEP);
|
|
106
|
+
|
|
107
|
+
if (fields.length < 20 || fields[0] !== reqId || fields[1] !== "1") {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return {
|
|
112
|
+
workdir: fields[2] || "",
|
|
113
|
+
commit: fields[3] || "",
|
|
114
|
+
localBranch: fields[4] || "",
|
|
115
|
+
remoteBranch: fields[5] || "",
|
|
116
|
+
remoteName: fields[6] || "",
|
|
117
|
+
remoteUrl: fields[7] || "",
|
|
118
|
+
action: fields[8] || "",
|
|
119
|
+
indexSize: parseInt(fields[9] || "0", 10),
|
|
120
|
+
staged: parseInt(fields[10] || "0", 10),
|
|
121
|
+
unstaged: parseInt(fields[11] || "0", 10),
|
|
122
|
+
conflicted: parseInt(fields[12] || "0", 10),
|
|
123
|
+
untracked: parseInt(fields[13] || "0", 10),
|
|
124
|
+
ahead: parseInt(fields[14] || "0", 10),
|
|
125
|
+
behind: parseInt(fields[15] || "0", 10),
|
|
126
|
+
stashes: parseInt(fields[16] || "0", 10),
|
|
127
|
+
tag: fields[17] || "",
|
|
128
|
+
commitSummary: fields[27] || "",
|
|
129
|
+
};
|
|
130
|
+
} catch {
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export function stopDaemon(): void {
|
|
136
|
+
if (daemon) {
|
|
137
|
+
daemon.proc.kill();
|
|
138
|
+
daemon = null;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { ImageFormat, PhotonImage } from "@f5xc-salesdemos/pi-natives";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Convert image to PNG format for terminal display.
|
|
5
|
+
* Kitty graphics protocol requires PNG format (f=100).
|
|
6
|
+
*/
|
|
7
|
+
export async function convertToPng(
|
|
8
|
+
base64Data: string,
|
|
9
|
+
mimeType: string,
|
|
10
|
+
): Promise<{ data: string; mimeType: string } | null> {
|
|
11
|
+
// Already PNG, no conversion needed
|
|
12
|
+
if (mimeType === "image/png") {
|
|
13
|
+
return { data: base64Data, mimeType };
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
const image = await PhotonImage.parse(new Uint8Array(Buffer.from(base64Data, "base64")));
|
|
18
|
+
const pngBuffer = await image.encode(ImageFormat.PNG, 100);
|
|
19
|
+
return {
|
|
20
|
+
data: Buffer.from(pngBuffer).toBase64(),
|
|
21
|
+
mimeType: "image/png",
|
|
22
|
+
};
|
|
23
|
+
} catch {
|
|
24
|
+
// Conversion failed
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import * as fs from "node:fs/promises";
|
|
2
|
+
import type { ImageContent } from "@f5xc-salesdemos/pi-ai";
|
|
3
|
+
import { formatBytes, readImageMetadata, SUPPORTED_IMAGE_MIME_TYPES } from "@f5xc-salesdemos/pi-utils";
|
|
4
|
+
import { resolveReadPath } from "../tools/path-utils";
|
|
5
|
+
import { convertToPng } from "./image-convert";
|
|
6
|
+
import { formatDimensionNote, resizeImage } from "./image-resize";
|
|
7
|
+
|
|
8
|
+
export const MAX_IMAGE_INPUT_BYTES = 20 * 1024 * 1024;
|
|
9
|
+
export const SUPPORTED_INPUT_IMAGE_MIME_TYPES = SUPPORTED_IMAGE_MIME_TYPES;
|
|
10
|
+
|
|
11
|
+
export interface LoadImageInputOptions {
|
|
12
|
+
path: string;
|
|
13
|
+
cwd: string;
|
|
14
|
+
autoResize: boolean;
|
|
15
|
+
maxBytes?: number;
|
|
16
|
+
resolvedPath?: string;
|
|
17
|
+
detectedMimeType?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface LoadedImageInput {
|
|
21
|
+
resolvedPath: string;
|
|
22
|
+
mimeType: string;
|
|
23
|
+
data: string;
|
|
24
|
+
textNote: string;
|
|
25
|
+
dimensionNote?: string;
|
|
26
|
+
bytes: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export class ImageInputTooLargeError extends Error {
|
|
30
|
+
readonly bytes: number;
|
|
31
|
+
readonly maxBytes: number;
|
|
32
|
+
|
|
33
|
+
constructor(bytes: number, maxBytes: number) {
|
|
34
|
+
super(`Image file too large: ${formatBytes(bytes)} exceeds ${formatBytes(maxBytes)} limit.`);
|
|
35
|
+
this.name = "ImageInputTooLargeError";
|
|
36
|
+
this.bytes = bytes;
|
|
37
|
+
this.maxBytes = maxBytes;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export async function ensureSupportedImageInput(image: ImageContent): Promise<ImageContent | null> {
|
|
42
|
+
if (SUPPORTED_INPUT_IMAGE_MIME_TYPES.has(image.mimeType)) {
|
|
43
|
+
return image;
|
|
44
|
+
}
|
|
45
|
+
const converted = await convertToPng(image.data, image.mimeType);
|
|
46
|
+
return converted ? { type: "image", data: converted.data, mimeType: converted.mimeType } : null;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export async function loadImageInput(options: LoadImageInputOptions): Promise<LoadedImageInput | null> {
|
|
50
|
+
const maxBytes = options.maxBytes ?? MAX_IMAGE_INPUT_BYTES;
|
|
51
|
+
const resolvedPath = options.resolvedPath ?? resolveReadPath(options.path, options.cwd);
|
|
52
|
+
const metadata = options.detectedMimeType
|
|
53
|
+
? { mimeType: options.detectedMimeType }
|
|
54
|
+
: await readImageMetadata(resolvedPath);
|
|
55
|
+
const mimeType = metadata?.mimeType;
|
|
56
|
+
if (!mimeType) return null;
|
|
57
|
+
|
|
58
|
+
const stat = await Bun.file(resolvedPath).stat();
|
|
59
|
+
if (stat.size > maxBytes) {
|
|
60
|
+
throw new ImageInputTooLargeError(stat.size, maxBytes);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const inputBuffer = await fs.readFile(resolvedPath);
|
|
64
|
+
if (inputBuffer.byteLength > maxBytes) {
|
|
65
|
+
throw new ImageInputTooLargeError(inputBuffer.byteLength, maxBytes);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
let outputData = Buffer.from(inputBuffer).toBase64();
|
|
69
|
+
let outputMimeType = mimeType;
|
|
70
|
+
let outputBytes = inputBuffer.byteLength;
|
|
71
|
+
let dimensionNote: string | undefined;
|
|
72
|
+
|
|
73
|
+
if (options.autoResize) {
|
|
74
|
+
try {
|
|
75
|
+
const resized = await resizeImage({ type: "image", data: outputData, mimeType });
|
|
76
|
+
outputData = resized.data;
|
|
77
|
+
outputMimeType = resized.mimeType;
|
|
78
|
+
outputBytes = resized.buffer.byteLength;
|
|
79
|
+
dimensionNote = formatDimensionNote(resized);
|
|
80
|
+
} catch {
|
|
81
|
+
// keep original image when resize fails
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
let textNote = `Read image file [${outputMimeType}]`;
|
|
86
|
+
if (dimensionNote) {
|
|
87
|
+
textNote += `\n${dimensionNote}`;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return {
|
|
91
|
+
resolvedPath,
|
|
92
|
+
mimeType: outputMimeType,
|
|
93
|
+
data: outputData,
|
|
94
|
+
textNote,
|
|
95
|
+
dimensionNote,
|
|
96
|
+
bytes: outputBytes,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { TERMINAL } from "@f5xc-salesdemos/pi-tui/terminal-capabilities";
|
|
2
|
+
|
|
3
|
+
// -- Start sequence detection regexes --
|
|
4
|
+
|
|
5
|
+
const SIXEL_START_REGEX = /\x1bP(?:[0-9;]*)q/u;
|
|
6
|
+
// Match all iTerm2 image sequences: File=, MultipartFile=, FilePart=, FileEnd
|
|
7
|
+
const ITERM2_START_REGEX = /\x1b\]1337;(?:File=|MultipartFile=|FilePart=|FileEnd)/u;
|
|
8
|
+
const KITTY_START_REGEX = /\x1b_G/u;
|
|
9
|
+
|
|
10
|
+
// -- Full sequence matching regexes (for placeholder/restore) --
|
|
11
|
+
|
|
12
|
+
const SIXEL_SEQUENCE_REGEX = /\x1bP(?:[0-9;]*)q[\s\S]*?(?:\x1b\\|\x07)/gu;
|
|
13
|
+
// Match all iTerm2 image OSC sequences through their terminator (BEL or ST).
|
|
14
|
+
// Covers File= (inline), MultipartFile= (multipart start), FilePart= (chunks), FileEnd.
|
|
15
|
+
const ITERM2_SEQUENCE_REGEX = /\x1b\]1337;(?:File=|MultipartFile=|FilePart=|FileEnd)[\s\S]*?(?:\x07|\x1b\\)/gu;
|
|
16
|
+
const KITTY_SEQUENCE_REGEX = /\x1b_G[^\x1b]*\x1b\\/gu;
|
|
17
|
+
|
|
18
|
+
const SIXEL_END_SEQUENCE = "\x1b\\";
|
|
19
|
+
const SIXEL_END_BELL = "\x07";
|
|
20
|
+
|
|
21
|
+
const PLACEHOLDER_PREFIX = "__OMP_IMAGE_SEQUENCE_";
|
|
22
|
+
|
|
23
|
+
export function isImagePassthroughEnabled(): boolean {
|
|
24
|
+
return TERMINAL.imageProtocol !== null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function containsImageSequence(text: string): boolean {
|
|
28
|
+
return SIXEL_START_REGEX.test(text) || ITERM2_START_REGEX.test(text) || KITTY_START_REGEX.test(text);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function isImageLine(line: string): boolean {
|
|
32
|
+
return containsImageSequence(line);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function getImageLineMask(lines: string[]): boolean[] {
|
|
36
|
+
let inSixelSequence = false;
|
|
37
|
+
return lines.map(line => {
|
|
38
|
+
const hasSixelStart = SIXEL_START_REGEX.test(line);
|
|
39
|
+
const hasIterm2 = ITERM2_START_REGEX.test(line);
|
|
40
|
+
const hasKitty = KITTY_START_REGEX.test(line);
|
|
41
|
+
|
|
42
|
+
if (hasSixelStart) {
|
|
43
|
+
inSixelSequence = true;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const isImage = inSixelSequence || hasIterm2 || hasKitty;
|
|
47
|
+
|
|
48
|
+
if (inSixelSequence && (line.includes(SIXEL_END_SEQUENCE) || line.includes(SIXEL_END_BELL))) {
|
|
49
|
+
inSixelSequence = false;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
return isImage;
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Extracts base64 image data from iTerm2 multipart sequences in raw output.
|
|
58
|
+
* Returns the reassembled base64 string and detected mime type, or null
|
|
59
|
+
* if no multipart image is found.
|
|
60
|
+
*/
|
|
61
|
+
export function extractITerm2ImageData(text: string): { base64: string; mimeType: string } | null {
|
|
62
|
+
if (!ITERM2_START_REGEX.test(text)) return null;
|
|
63
|
+
|
|
64
|
+
// Check for single-part File= first
|
|
65
|
+
const singleMatch = text.match(/\x1b\]1337;File=([^:]*):([A-Za-z0-9+/=\s]+)(?:\x07|\x1b\\)/u);
|
|
66
|
+
if (singleMatch) {
|
|
67
|
+
const base64 = singleMatch[2].replace(/\s/g, "");
|
|
68
|
+
const mimeType = detectMimeFromBase64(base64);
|
|
69
|
+
return { base64, mimeType };
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Reassemble multipart: collect all FilePart payloads in order
|
|
73
|
+
const partRegex = /\x1b\]1337;FilePart=([A-Za-z0-9+/=\s]+)(?:\x07|\x1b\\)/gu;
|
|
74
|
+
const parts: string[] = [];
|
|
75
|
+
for (;;) {
|
|
76
|
+
const match = partRegex.exec(text);
|
|
77
|
+
if (!match) break;
|
|
78
|
+
parts.push(match[1].replace(/\s/g, ""));
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (parts.length === 0) return null;
|
|
82
|
+
|
|
83
|
+
const base64 = parts.join("");
|
|
84
|
+
const mimeType = detectMimeFromBase64(base64);
|
|
85
|
+
return { base64, mimeType };
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function detectMimeFromBase64(base64: string): string {
|
|
89
|
+
const header = base64.slice(0, 12);
|
|
90
|
+
if (header.startsWith("iVBOR")) return "image/png";
|
|
91
|
+
if (header.startsWith("/9j/")) return "image/jpeg";
|
|
92
|
+
if (header.startsWith("R0lGO")) return "image/gif";
|
|
93
|
+
if (header.startsWith("UklGR")) return "image/webp";
|
|
94
|
+
return "image/png";
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export function sanitizeWithImagePassthrough(text: string, sanitize: (text: string) => string): string {
|
|
98
|
+
if (!isImagePassthroughEnabled() || !containsImageSequence(text)) {
|
|
99
|
+
return sanitize(text);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const preservedSequences: string[] = [];
|
|
103
|
+
|
|
104
|
+
let tokenized = text;
|
|
105
|
+
for (const regex of [SIXEL_SEQUENCE_REGEX, ITERM2_SEQUENCE_REGEX, KITTY_SEQUENCE_REGEX]) {
|
|
106
|
+
tokenized = tokenized.replace(regex, match => {
|
|
107
|
+
const token = `${PLACEHOLDER_PREFIX}${preservedSequences.length}__`;
|
|
108
|
+
preservedSequences.push(match);
|
|
109
|
+
return token;
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
const sanitized = sanitize(tokenized);
|
|
114
|
+
return sanitized.replace(/__OMP_IMAGE_SEQUENCE_(\d+)__/gu, (_, indexText: string) => {
|
|
115
|
+
const index = Number.parseInt(indexText, 10);
|
|
116
|
+
return preservedSequences[index] ?? "";
|
|
117
|
+
});
|
|
118
|
+
}
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
import type { ImageContent } from "@f5xc-salesdemos/pi-ai";
|
|
2
|
+
import { ImageFormat, PhotonImage, SamplingFilter } from "@f5xc-salesdemos/pi-natives";
|
|
3
|
+
|
|
4
|
+
export interface ImageResizeOptions {
|
|
5
|
+
maxWidth?: number; // Default: 1568
|
|
6
|
+
maxHeight?: number; // Default: 1568
|
|
7
|
+
maxBytes?: number; // Default: 500KB
|
|
8
|
+
jpegQuality?: number; // Default: 75
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface ResizedImage {
|
|
12
|
+
buffer: Uint8Array;
|
|
13
|
+
mimeType: string;
|
|
14
|
+
originalWidth: number;
|
|
15
|
+
originalHeight: number;
|
|
16
|
+
width: number;
|
|
17
|
+
height: number;
|
|
18
|
+
wasResized: boolean;
|
|
19
|
+
get data(): string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// 500KB target — aggressive compression; Anthropic's 5MB per-image cap is rarely the
|
|
23
|
+
// binding constraint once images are downsized to 1568px (Anthropic's internal threshold).
|
|
24
|
+
const DEFAULT_MAX_BYTES = 500 * 1024;
|
|
25
|
+
|
|
26
|
+
const DEFAULT_OPTIONS: Required<ImageResizeOptions> = {
|
|
27
|
+
// 1568px — Anthropic downscales anything larger; OpenAI tiles at 768px;
|
|
28
|
+
// sending bigger pixels wastes bandwidth the model never sees.
|
|
29
|
+
maxWidth: 1568,
|
|
30
|
+
maxHeight: 1568,
|
|
31
|
+
maxBytes: DEFAULT_MAX_BYTES,
|
|
32
|
+
jpegQuality: 75,
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
/** Pick the smallest of N encoded buffers. */
|
|
36
|
+
function pickSmallest(...candidates: Array<{ buffer: Uint8Array; mimeType: string }>): {
|
|
37
|
+
buffer: Uint8Array;
|
|
38
|
+
mimeType: string;
|
|
39
|
+
} {
|
|
40
|
+
return candidates.reduce((best, c) => (c.buffer.length < best.buffer.length ? c : best));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Polyfill for Buffer.toBase64, technically since it derives from Uint8Array it should exist but Bun reasons... */
|
|
44
|
+
Buffer.prototype.toBase64 = function (this: Buffer) {
|
|
45
|
+
return new Uint8Array(this.buffer, this.byteOffset, this.byteLength).toBase64();
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Resize and recompress an image to fit within the specified max dimensions and file size.
|
|
50
|
+
*
|
|
51
|
+
* Defaults target Anthropic's internal 1568px downscale threshold and produce small
|
|
52
|
+
* lossy JPEG output suitable for tool-call payloads (~100–500KB typical).
|
|
53
|
+
*
|
|
54
|
+
* Strategy:
|
|
55
|
+
* 1. Fast path — if input already fits dimensions AND is at <=25% of byte budget,
|
|
56
|
+
* return as-is. Avoids re-encoding tiny icons/diagrams.
|
|
57
|
+
* 2. Resize to maxWidth/maxHeight, encode both PNG and JPEG at default quality,
|
|
58
|
+
* pick whichever is smaller. PNG wins for line art / few-color UI; JPEG wins
|
|
59
|
+
* for photographic content.
|
|
60
|
+
* 3. If still too large, JPEG-only quality ladder (PNG quality is a no-op).
|
|
61
|
+
* 4. If still too large, progressively reduce dimensions and retry the JPEG ladder.
|
|
62
|
+
* 5. Last resort: ship the smallest variant produced.
|
|
63
|
+
*
|
|
64
|
+
* On any decode failure, returns the original bytes unchanged with wasResized=false.
|
|
65
|
+
*/
|
|
66
|
+
export async function resizeImage(img: ImageContent, options?: ImageResizeOptions): Promise<ResizedImage> {
|
|
67
|
+
const opts = { ...DEFAULT_OPTIONS, ...options };
|
|
68
|
+
const inputBuffer = Buffer.from(img.data, "base64");
|
|
69
|
+
|
|
70
|
+
try {
|
|
71
|
+
const image = await PhotonImage.parse(inputBuffer);
|
|
72
|
+
|
|
73
|
+
const originalWidth = image.width;
|
|
74
|
+
const originalHeight = image.height;
|
|
75
|
+
const format = img.mimeType?.split("/")[1] ?? "png";
|
|
76
|
+
|
|
77
|
+
// Check if already within all limits (dimensions AND size)
|
|
78
|
+
const originalSize = inputBuffer.length;
|
|
79
|
+
// Fast path: skip if already within dimensions AND well under budget.
|
|
80
|
+
// Threshold is 1/4 of budget — if already that compact, don't re-encode.
|
|
81
|
+
// Avoids wasted work on tiny icons/diagrams while ensuring larger PNGs
|
|
82
|
+
// still get JPEG-compressed.
|
|
83
|
+
const comfortableSize = opts.maxBytes / 4;
|
|
84
|
+
if (originalWidth <= opts.maxWidth && originalHeight <= opts.maxHeight && originalSize <= comfortableSize) {
|
|
85
|
+
return {
|
|
86
|
+
buffer: inputBuffer,
|
|
87
|
+
mimeType: img.mimeType ?? `image/${format}`,
|
|
88
|
+
originalWidth,
|
|
89
|
+
originalHeight,
|
|
90
|
+
width: originalWidth,
|
|
91
|
+
height: originalHeight,
|
|
92
|
+
wasResized: false,
|
|
93
|
+
get data() {
|
|
94
|
+
return img.data;
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Calculate initial dimensions respecting max limits
|
|
100
|
+
let targetWidth = originalWidth;
|
|
101
|
+
let targetHeight = originalHeight;
|
|
102
|
+
|
|
103
|
+
if (targetWidth > opts.maxWidth) {
|
|
104
|
+
targetHeight = Math.round((targetHeight * opts.maxWidth) / targetWidth);
|
|
105
|
+
targetWidth = opts.maxWidth;
|
|
106
|
+
}
|
|
107
|
+
if (targetHeight > opts.maxHeight) {
|
|
108
|
+
targetWidth = Math.round((targetWidth * opts.maxHeight) / targetHeight);
|
|
109
|
+
targetHeight = opts.maxHeight;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// First-attempt encoder: try PNG, JPEG, and lossy WebP — return whichever is smallest.
|
|
113
|
+
// PNG wins for line art / few-color UI; JPEG and WebP win for photographic content;
|
|
114
|
+
// WebP usually beats JPEG by 25–35% at the same perceptual quality.
|
|
115
|
+
async function encodeSmallest(
|
|
116
|
+
width: number,
|
|
117
|
+
height: number,
|
|
118
|
+
quality: number,
|
|
119
|
+
): Promise<{ buffer: Uint8Array; mimeType: string }> {
|
|
120
|
+
const resized = await image.resize(width, height, SamplingFilter.Lanczos3);
|
|
121
|
+
|
|
122
|
+
const [pngBuffer, jpegBuffer, webpBuffer] = await Promise.all([
|
|
123
|
+
resized.encode(ImageFormat.PNG, quality),
|
|
124
|
+
resized.encode(ImageFormat.JPEG, quality),
|
|
125
|
+
resized.encode(ImageFormat.WEBP, quality),
|
|
126
|
+
]);
|
|
127
|
+
|
|
128
|
+
return pickSmallest(
|
|
129
|
+
{ buffer: pngBuffer, mimeType: "image/png" },
|
|
130
|
+
{ buffer: jpegBuffer, mimeType: "image/jpeg" },
|
|
131
|
+
{ buffer: webpBuffer, mimeType: "image/webp" },
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Lossy-only encoder — used in quality/dimension fallback ladders where PNG can't shrink
|
|
136
|
+
// further (PNG quality is a no-op). Picks the smaller of JPEG vs lossy WebP at the
|
|
137
|
+
// requested quality.
|
|
138
|
+
async function encodeLossy(
|
|
139
|
+
width: number,
|
|
140
|
+
height: number,
|
|
141
|
+
quality: number,
|
|
142
|
+
): Promise<{ buffer: Uint8Array; mimeType: string }> {
|
|
143
|
+
const resized = await image.resize(width, height, SamplingFilter.Lanczos3);
|
|
144
|
+
const [jpegBuffer, webpBuffer] = await Promise.all([
|
|
145
|
+
resized.encode(ImageFormat.JPEG, quality),
|
|
146
|
+
resized.encode(ImageFormat.WEBP, quality),
|
|
147
|
+
]);
|
|
148
|
+
return pickSmallest(
|
|
149
|
+
{ buffer: jpegBuffer, mimeType: "image/jpeg" },
|
|
150
|
+
{ buffer: webpBuffer, mimeType: "image/webp" },
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Quality ladder — more aggressive steps for tighter budgets
|
|
155
|
+
const qualitySteps = [70, 60, 50, 40];
|
|
156
|
+
const scaleSteps = [1.0, 0.75, 0.5, 0.35, 0.25];
|
|
157
|
+
|
|
158
|
+
let best: { buffer: Uint8Array; mimeType: string };
|
|
159
|
+
let finalWidth = targetWidth;
|
|
160
|
+
let finalHeight = targetHeight;
|
|
161
|
+
|
|
162
|
+
// First attempt: resize to target, try both PNG and JPEG, pick smaller
|
|
163
|
+
best = await encodeSmallest(targetWidth, targetHeight, opts.jpegQuality);
|
|
164
|
+
|
|
165
|
+
if (best.buffer.length <= opts.maxBytes) {
|
|
166
|
+
return {
|
|
167
|
+
buffer: best.buffer,
|
|
168
|
+
mimeType: best.mimeType,
|
|
169
|
+
originalWidth,
|
|
170
|
+
originalHeight,
|
|
171
|
+
width: finalWidth,
|
|
172
|
+
height: finalHeight,
|
|
173
|
+
wasResized: true,
|
|
174
|
+
get data() {
|
|
175
|
+
return Buffer.from(best.buffer).toBase64();
|
|
176
|
+
},
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Still too large — lossy ladder (JPEG vs WebP, smallest wins) with decreasing quality
|
|
181
|
+
for (const quality of qualitySteps) {
|
|
182
|
+
best = await encodeLossy(targetWidth, targetHeight, quality);
|
|
183
|
+
|
|
184
|
+
if (best.buffer.length <= opts.maxBytes) {
|
|
185
|
+
return {
|
|
186
|
+
buffer: best.buffer,
|
|
187
|
+
mimeType: best.mimeType,
|
|
188
|
+
originalWidth,
|
|
189
|
+
originalHeight,
|
|
190
|
+
width: finalWidth,
|
|
191
|
+
height: finalHeight,
|
|
192
|
+
wasResized: true,
|
|
193
|
+
get data() {
|
|
194
|
+
return Buffer.from(best.buffer).toBase64();
|
|
195
|
+
},
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Still too large — reduce dimensions progressively with the lossy ladder
|
|
201
|
+
for (const scale of scaleSteps) {
|
|
202
|
+
finalWidth = Math.round(targetWidth * scale);
|
|
203
|
+
finalHeight = Math.round(targetHeight * scale);
|
|
204
|
+
|
|
205
|
+
if (finalWidth < 100 || finalHeight < 100) {
|
|
206
|
+
break;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
for (const quality of qualitySteps) {
|
|
210
|
+
best = await encodeLossy(finalWidth, finalHeight, quality);
|
|
211
|
+
|
|
212
|
+
if (best.buffer.length <= opts.maxBytes) {
|
|
213
|
+
return {
|
|
214
|
+
buffer: best.buffer,
|
|
215
|
+
mimeType: best.mimeType,
|
|
216
|
+
originalWidth,
|
|
217
|
+
originalHeight,
|
|
218
|
+
width: finalWidth,
|
|
219
|
+
height: finalHeight,
|
|
220
|
+
wasResized: true,
|
|
221
|
+
get data() {
|
|
222
|
+
return Buffer.from(best.buffer).toBase64();
|
|
223
|
+
},
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// Last resort: return smallest version we produced
|
|
230
|
+
return {
|
|
231
|
+
buffer: best.buffer,
|
|
232
|
+
mimeType: best.mimeType,
|
|
233
|
+
originalWidth,
|
|
234
|
+
originalHeight,
|
|
235
|
+
width: finalWidth,
|
|
236
|
+
height: finalHeight,
|
|
237
|
+
wasResized: true,
|
|
238
|
+
get data() {
|
|
239
|
+
return Buffer.from(best.buffer).toBase64();
|
|
240
|
+
},
|
|
241
|
+
};
|
|
242
|
+
} catch {
|
|
243
|
+
// Failed to load image
|
|
244
|
+
return {
|
|
245
|
+
buffer: inputBuffer,
|
|
246
|
+
mimeType: img.mimeType,
|
|
247
|
+
originalWidth: 0,
|
|
248
|
+
originalHeight: 0,
|
|
249
|
+
width: 0,
|
|
250
|
+
height: 0,
|
|
251
|
+
wasResized: false,
|
|
252
|
+
get data() {
|
|
253
|
+
return img.data;
|
|
254
|
+
},
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/**
|
|
260
|
+
* Format a dimension note for resized images.
|
|
261
|
+
* This helps the model understand the coordinate mapping.
|
|
262
|
+
*/
|
|
263
|
+
export function formatDimensionNote(result: ResizedImage): string | undefined {
|
|
264
|
+
if (!result.wasResized) {
|
|
265
|
+
return undefined;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
const scale = result.originalWidth / result.width;
|
|
269
|
+
return `[Image: original ${result.originalWidth}x${result.originalHeight}, displayed at ${result.width}x${
|
|
270
|
+
result.height
|
|
271
|
+
}. Multiply coordinates by ${scale.toFixed(2)} to map to original image.]`;
|
|
272
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Opens an image in the system's default image viewer.
|
|
3
|
+
* Returns true if the viewer was launched successfully.
|
|
4
|
+
*/
|
|
5
|
+
export async function openImageExternal(path: string): Promise<boolean> {
|
|
6
|
+
const command = process.platform === "darwin" ? "open" : "xdg-open";
|
|
7
|
+
try {
|
|
8
|
+
const proc = Bun.spawn([command, path], {
|
|
9
|
+
stdout: "ignore",
|
|
10
|
+
stderr: "ignore",
|
|
11
|
+
});
|
|
12
|
+
await proc.exited;
|
|
13
|
+
return proc.exitCode === 0;
|
|
14
|
+
} catch {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
}
|