@herbertgao/pi-extensions 2026.8.11 → 2026.8.13
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/README.md +23 -10
- package/{node_modules/@herbertgao/pi-mermaid-open/LICENSE → THIRD_PARTY_NOTICES.md} +19 -1
- package/node_modules/@czottmann/pi-automode/CHANGELOG.md +15 -0
- package/node_modules/@czottmann/pi-automode/README.md +5 -3
- package/node_modules/@czottmann/pi-automode/docs/adr/ADR-001-permission-precedence-and-trust-boundaries.md +2 -0
- package/node_modules/@czottmann/pi-automode/docs/adr/ADR-002-global-config-in-extension-data-directory.md +60 -0
- package/node_modules/@czottmann/pi-automode/docs/adr/INDEX.md +1 -0
- package/node_modules/@czottmann/pi-automode/docs/automode-classifier-flow.md +4 -4
- package/node_modules/@czottmann/pi-automode/docs/configuration.md +20 -4
- package/node_modules/@czottmann/pi-automode/docs/observability-logging.md +1 -1
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/bash.ts +692 -0
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/config.ts +181 -3
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/constants.ts +4 -1
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/extension.ts +143 -36
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/hard-deny.ts +103 -148
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/paths.ts +32 -6
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode/permissions.ts +344 -22
- package/node_modules/@czottmann/pi-automode/extensions/auto-mode.ts +1 -0
- package/node_modules/@czottmann/pi-automode/package.json +4 -1
- package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +2 -1
- package/node_modules/@herbertgao/pi-cc-extensions/README.md +2 -1
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +4 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +21 -1
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/agent-summary/core.ts +1 -1
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/context.ts +19 -19
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +4 -2
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/default-mode.ts +2 -1
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/grouping.ts +10 -2
- package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
- package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +10 -0
- package/node_modules/@herbertgao/pi-subagents/README.md +21 -15
- package/node_modules/@herbertgao/pi-subagents/package.json +3 -3
- package/node_modules/@herbertgao/pi-subagents/src/agent-file-toggle.ts +11 -8
- package/node_modules/@herbertgao/pi-subagents/src/agent-manager.ts +184 -106
- package/node_modules/@herbertgao/pi-subagents/src/cross-extension-rpc.ts +31 -11
- package/node_modules/@herbertgao/pi-subagents/src/custom-agents.ts +9 -1
- package/node_modules/@herbertgao/pi-subagents/src/index.ts +156 -31
- package/node_modules/@herbertgao/pi-subagents/src/invocation-config.ts +17 -0
- package/node_modules/@herbertgao/pi-subagents/src/model-resolver.ts +14 -0
- package/node_modules/@herbertgao/pi-subagents/src/schedule.ts +8 -0
- package/node_modules/@herbertgao/pi-subagents/src/settings.ts +32 -1
- package/node_modules/@herbertgao/pi-subagents/src/types.ts +17 -2
- package/node_modules/@herbertgao/pi-subagents/src/ui/agent-widget.ts +23 -2
- package/node_modules/@herbertgao/pi-subagents/src/ui/conversation-viewer.ts +259 -24
- package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +2 -2
- package/node_modules/@luxusai/pi-hindsight/CHANGELOG.md +376 -0
- package/node_modules/@luxusai/pi-hindsight/README.md +92 -0
- package/node_modules/@luxusai/pi-hindsight/docs/adr/001-memory-lifecycle-and-scope.md +56 -0
- package/node_modules/@luxusai/pi-hindsight/docs/adr/002-explicit-routing-strategy-seam.md +169 -0
- package/node_modules/@luxusai/pi-hindsight/docs/adr/003-tui-memory-mode-vocabulary.md +107 -0
- package/node_modules/@luxusai/pi-hindsight/docs/adr/004-lifeos-dual-bank-design.md +89 -0
- package/node_modules/@luxusai/pi-hindsight/docs/adr/005-domain-banks-and-agent-first-surface.md +189 -0
- package/node_modules/@luxusai/pi-hindsight/docs/assets/logos/pi-hindsight-logo-dark.webp +0 -0
- package/node_modules/@luxusai/pi-hindsight/docs/assets/logos/pi-hindsight-logo-dark@2x.webp +0 -0
- package/node_modules/@luxusai/pi-hindsight/docs/coding-memory-evaluation.md +54 -0
- package/node_modules/@luxusai/pi-hindsight/docs/compatibility.md +75 -0
- package/node_modules/@luxusai/pi-hindsight/docs/hindsight-core-functions.md +300 -0
- package/node_modules/@luxusai/pi-hindsight/docs/mission-and-mental-model-quality.md +158 -0
- package/node_modules/@luxusai/pi-hindsight/docs/next-opt-out-design.md +164 -0
- package/node_modules/@luxusai/pi-hindsight/docs/risky-memory-modes.md +139 -0
- package/node_modules/@luxusai/pi-hindsight/docs/starter-mental-model-suggestions.md +74 -0
- package/node_modules/@luxusai/pi-hindsight/docs/surface-reference.md +261 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-operations.ts +151 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-selection.ts +18 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-settings-presenter.ts +46 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/bank-templates.ts +383 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/banking.ts +240 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/knowledge-page-seed.ts +176 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/banks/retain-strategies.ts +178 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/client/client-retry.ts +41 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/client/client.ts +386 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/client/fetch-compat.ts +39 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/client/timeout.ts +34 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config-defaults.ts +140 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config-editing-model.ts +61 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config-editing-registry.ts +925 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config-field-paths.ts +247 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config-normalize.ts +547 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config-writer.ts +480 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/config/config.ts +182 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/config/setup-gate.ts +86 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-execute.ts +1010 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-parse.ts +175 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-plan.ts +425 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-presentation.ts +210 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/imports/import-sessions.ts +817 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/index.ts +25 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/git-seed.ts +319 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle-recall.ts +196 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle-retain.ts +189 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle-runtime.ts +65 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/memory-lifecycle.ts +260 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/mental-models.ts +244 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/observation-scopes.ts +59 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/recall-cleanup.ts +82 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/recall-visibility.ts +45 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/recall.ts +331 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain-cursor.ts +354 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain-job-builder.ts +66 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain-receipts.ts +132 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/lifecycle/retain.ts +228 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-bank-template-operations.ts +74 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-config-operations.ts +16 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-control-operations.ts +648 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-diagnostics-operations.ts +105 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-identity.ts +68 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-operation-service.ts +71 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-operation-types.ts +13 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-recall-operations.ts +162 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-retain-operations.ts +131 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-scope.ts +104 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/memory-session-operations.ts +37 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/operation-catalog.ts +893 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/reflect-presenter.ts +35 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/scope-migrate.ts +177 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/operations/tools.ts +7 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/queue/flush-presenter.ts +21 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/queue/jsonl-queue-store.ts +112 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue-delivery.ts +111 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue-lock.ts +214 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue-operations.ts +70 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/queue/queue.ts +392 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/bank-template-presentation.ts +45 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/commands.ts +9 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/guided-setup.ts +860 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/prefill-input.ts +105 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-flow.ts +189 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-server-probe.ts +299 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-actions.ts +201 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-facts.ts +47 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-render.ts +239 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui-types.ts +50 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/setup-tui.ts +259 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/tui/tool-presenters.ts +77 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/types.ts +534 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/diagnostics.ts +319 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/messages.ts +325 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/sanitize.ts +42 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/session-memory-meta.ts +244 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/session-operations.ts +56 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/session.ts +50 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/status-fields.ts +167 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/status-health.ts +207 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/utils/status.ts +120 -0
- package/node_modules/@luxusai/pi-hindsight/extensions/version.ts +8 -0
- package/node_modules/@luxusai/pi-hindsight/package.json +118 -0
- package/node_modules/@luxusai/pi-hindsight/skills/hindsight-memory-doctor/SKILL.md +75 -0
- package/node_modules/@narumitw/pi-btw/dist/index.ts +143 -46
- package/node_modules/@narumitw/pi-btw/dist/index.ts.map +3 -3
- package/node_modules/@narumitw/pi-btw/package.json +6 -6
- package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +136 -22
- package/node_modules/{@herbertgao → @tifan}/pi-copy-response/README.md +2 -4
- package/node_modules/{@herbertgao → @tifan}/pi-copy-response/package.json +5 -15
- package/node_modules/{@herbertgao → @tifan}/pi-handoff/README.md +4 -6
- package/node_modules/@tifan/pi-handoff/package.json +43 -0
- package/node_modules/{@herbertgao → @tifan}/pi-handoff/src/index.ts +1 -1
- package/node_modules/{@herbertgao → @tifan}/pi-inline-skills/README.md +2 -4
- package/node_modules/{@herbertgao → @tifan}/pi-inline-skills/package.json +5 -15
- package/node_modules/{@herbertgao → @tifan}/pi-mermaid-open/README.md +5 -7
- package/node_modules/{@herbertgao → @tifan}/pi-mermaid-open/package.json +5 -19
- package/node_modules/{@herbertgao → @tifan}/pi-preferred-thinking/README.md +4 -6
- package/node_modules/{@herbertgao → @tifan}/pi-preferred-thinking/package.json +6 -16
- package/node_modules/{@herbertgao → @tifan}/pi-preferred-thinking/src/index.ts +1 -6
- package/node_modules/{@herbertgao → @tifan}/pi-recap/README.md +4 -6
- package/node_modules/@tifan/pi-recap/package.json +42 -0
- package/node_modules/{@herbertgao → @tifan}/pi-recap/src/models.ts +1 -6
- package/node_modules/{@herbertgao → @tifan}/pi-rename/README.md +13 -8
- package/node_modules/@tifan/pi-rename/package.json +47 -0
- package/node_modules/@tifan/pi-rename/src/herdr-label.ts +4 -0
- package/node_modules/{@herbertgao → @tifan}/pi-rename/src/index.ts +4 -16
- package/node_modules/{@herbertgao → @tifan}/pi-rename/src/models.ts +1 -6
- package/node_modules/{@herbertgao → @tifan}/pi-titlebar-spinner/README.md +2 -4
- package/node_modules/{@herbertgao → @tifan}/pi-titlebar-spinner/package.json +5 -15
- package/node_modules/pi-lens/CHANGELOG.md +96 -1
- package/node_modules/pi-lens/dist/clients/actionable-warnings-logger.js +2 -1
- package/node_modules/pi-lens/dist/clients/actionable-warnings.js +14 -5
- package/node_modules/pi-lens/dist/clients/advisory-provenance.js +48 -18
- package/node_modules/pi-lens/dist/clients/ast-grep-client.js +1 -3
- package/node_modules/pi-lens/dist/clients/atomic-write-staging.js +16 -4
- package/node_modules/pi-lens/dist/clients/bash-file-access.js +3 -1
- package/node_modules/pi-lens/dist/clients/biome-client.js +1 -3
- package/node_modules/pi-lens/dist/clients/blocker-freshness.js +21 -8
- package/node_modules/pi-lens/dist/clients/bounded-cache.js +24 -8
- package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +4 -3
- package/node_modules/pi-lens/dist/clients/cache-manager.js +6 -7
- package/node_modules/pi-lens/dist/clients/cache-observability.js +461 -66
- package/node_modules/pi-lens/dist/clients/call-graph.js +238 -63
- package/node_modules/pi-lens/dist/clients/codebase-model.js +13 -5
- package/node_modules/pi-lens/dist/clients/complexity-client.js +1 -3
- package/node_modules/pi-lens/dist/clients/dead-code-client.js +19 -8
- package/node_modules/pi-lens/dist/clients/dead-code-logger.js +1 -2
- package/node_modules/pi-lens/dist/clients/deadline-utils.js +3 -1
- package/node_modules/pi-lens/dist/clients/debug-heap.js +8 -1
- package/node_modules/pi-lens/dist/clients/degradation-ledger.js +1 -1
- package/node_modules/pi-lens/dist/clients/dependency-checker.js +11 -7
- package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +39 -2
- package/node_modules/pi-lens/dist/clients/diagnostic-line-freshness.js +5 -1
- package/node_modules/pi-lens/dist/clients/dispatch/auxiliary-lsp.js +2 -3
- package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +13 -1
- package/node_modules/pi-lens/dist/clients/dispatch/facts/function-facts.js +3 -1
- package/node_modules/pi-lens/dist/clients/dispatch/facts/import-facts.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/facts/tree-sitter-facts.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/integration.js +9 -4
- package/node_modules/pi-lens/dist/clients/dispatch/rules/error-swallowing.js +3 -1
- package/node_modules/pi-lens/dist/clients/dispatch/rules/pass-through-wrappers.js +6 -2
- package/node_modules/pi-lens/dist/clients/dispatch/rules/unsafe-boundary.js +31 -7
- package/node_modules/pi-lens/dist/clients/dispatch/runners/actionlint.js +5 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +10 -14
- package/node_modules/pi-lens/dist/clients/dispatch/runners/cpp-check.js +5 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/dotnet-build.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/elixir-check.js +3 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +25 -6
- package/node_modules/pi-lens/dist/clients/dispatch/runners/fish-indent.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/gleam-check.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/golangci-lint.js +3 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/hadolint.js +13 -8
- package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-lint.js +4 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/htmlhint.js +25 -10
- package/node_modules/pi-lens/dist/clients/dispatch/runners/javac.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ktlint.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +28 -4
- package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +6 -8
- package/node_modules/pi-lens/dist/clients/dispatch/runners/oxlint.js +212 -11
- package/node_modules/pi-lens/dist/clients/dispatch/runners/php-lint.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/phpstan.js +8 -4
- package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +10 -6
- package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +23 -14
- package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shellcheck.js +7 -9
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shfmt.js +5 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +7 -7
- package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +6 -8
- package/node_modules/pi-lens/dist/clients/dispatch/runners/terragrunt.js +13 -8
- package/node_modules/pi-lens/dist/clients/dispatch/runners/tflint.js +13 -8
- package/node_modules/pi-lens/dist/clients/dispatch/runners/tree-sitter.js +17 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +7 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +24 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/tool-failure.js +35 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/yaml-rule-parser.js +1 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +6 -8
- package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +1 -1
- package/node_modules/pi-lens/dist/clients/dispatch/suppress-writer.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/types.js +6 -1
- package/node_modules/pi-lens/dist/clients/dispatch/utils/lsp-diagnostics.js +6 -2
- package/node_modules/pi-lens/dist/clients/extension-log.js +5 -3
- package/node_modules/pi-lens/dist/clients/feature-hints.js +8 -1
- package/node_modules/pi-lens/dist/clients/file-kinds.js +34 -129
- package/node_modules/pi-lens/dist/clients/file-utils.js +17 -1
- package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +57 -2
- package/node_modules/pi-lens/dist/clients/formatters.js +144 -27
- package/node_modules/pi-lens/dist/clients/freshness.js +38 -0
- package/node_modules/pi-lens/dist/clients/git-guard.js +43 -13
- package/node_modules/pi-lens/dist/clients/go-client.js +1 -3
- package/node_modules/pi-lens/dist/clients/grammar-source.js +1 -1
- package/node_modules/pi-lens/dist/clients/gzip-stage-write.js +30 -4
- package/node_modules/pi-lens/dist/clients/host-edit-normalize.js +1 -3
- package/node_modules/pi-lens/dist/clients/install-diagnostics.js +4 -2
- package/node_modules/pi-lens/dist/clients/installer/index.js +86 -77
- package/node_modules/pi-lens/dist/clients/instance-reaper.js +5 -2
- package/node_modules/pi-lens/dist/clients/instance-registry.js +4 -2
- package/node_modules/pi-lens/dist/clients/jscpd-client.js +6 -1
- package/node_modules/pi-lens/dist/clients/knip-client.js +29 -15
- package/node_modules/pi-lens/dist/clients/language-profile.js +4 -1
- package/node_modules/pi-lens/dist/clients/latency-logger.js +13 -2
- package/node_modules/pi-lens/dist/clients/lens-config.js +1 -1
- package/node_modules/pi-lens/dist/clients/lens-map.js +8 -3
- package/node_modules/pi-lens/dist/clients/live-bus-emitter.js +1 -1
- package/node_modules/pi-lens/dist/clients/lsp/config.js +4 -6
- package/node_modules/pi-lens/dist/clients/lsp/edits.js +119 -32
- package/node_modules/pi-lens/dist/clients/lsp/index.js +94 -35
- package/node_modules/pi-lens/dist/clients/lsp/inferred-project.js +2 -1
- package/node_modules/pi-lens/dist/clients/lsp/jvm-runtime.js +4 -1
- package/node_modules/pi-lens/dist/clients/lsp/launch.js +11 -3
- package/node_modules/pi-lens/dist/clients/lsp/pending-aux-coverage.js +152 -0
- package/node_modules/pi-lens/dist/clients/lsp/server.js +19 -7
- package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +10 -2
- package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +9 -4
- package/node_modules/pi-lens/dist/clients/lsp-document-symbols.js +1 -3
- package/node_modules/pi-lens/dist/clients/lsp-mutation.js +10 -20
- package/node_modules/pi-lens/dist/clients/mcp/host-shim.js +1 -1
- package/node_modules/pi-lens/dist/clients/memory-sampler.js +73 -7
- package/node_modules/pi-lens/dist/clients/metrics-client.js +1 -3
- package/node_modules/pi-lens/dist/clients/middle-man-analysis.js +8 -3
- package/node_modules/pi-lens/dist/clients/module-report-lsp.js +7 -1
- package/node_modules/pi-lens/dist/clients/module-report.js +14 -17
- package/node_modules/pi-lens/dist/clients/ndjson-logger.js +3 -5
- package/node_modules/pi-lens/dist/clients/opaque-mutation-scan.js +220 -0
- package/node_modules/pi-lens/dist/clients/package-manager.js +6 -1
- package/node_modules/pi-lens/dist/clients/pipeline.js +57 -9
- package/node_modules/pi-lens/dist/clients/project-conventions.js +2 -8
- package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +10 -7
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/call-graph-impact.js +2 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/gitleaks.js +3 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +13 -9
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/trivy.js +3 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +5 -2
- package/node_modules/pi-lens/dist/clients/project-lens-config.js +12 -5
- package/node_modules/pi-lens/dist/clients/project-snapshot-fingerprint.js +48 -0
- package/node_modules/pi-lens/dist/clients/project-snapshot-persist-worker.js +15 -1
- package/node_modules/pi-lens/dist/clients/project-snapshot.js +472 -66
- package/node_modules/pi-lens/dist/clients/read-expansion.js +12 -2
- package/node_modules/pi-lens/dist/clients/read-guard-logger.js +5 -4
- package/node_modules/pi-lens/dist/clients/read-guard-tool-lines.js +5 -2
- package/node_modules/pi-lens/dist/clients/read-guard.js +1 -1
- package/node_modules/pi-lens/dist/clients/resource-sampler.js +1 -1
- package/node_modules/pi-lens/dist/clients/reverse-deps.js +6 -5
- package/node_modules/pi-lens/dist/clients/review-graph/builder.js +42 -17
- package/node_modules/pi-lens/dist/clients/review-graph/git-identity.js +8 -2
- package/node_modules/pi-lens/dist/clients/review-graph/import-resolvers.js +10 -1
- package/node_modules/pi-lens/dist/clients/review-graph/query.js +2 -1
- package/node_modules/pi-lens/dist/clients/review-graph/tsconfig-paths.js +4 -2
- package/node_modules/pi-lens/dist/clients/review-graph/workspace-modules.js +2 -2
- package/node_modules/pi-lens/dist/clients/ruff-client.js +6 -5
- package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +63 -31
- package/node_modules/pi-lens/dist/clients/runtime-context.js +12 -4
- package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +83 -4
- package/node_modules/pi-lens/dist/clients/runtime-session.js +14 -0
- package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +59 -3
- package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +148 -34
- package/node_modules/pi-lens/dist/clients/runtime-turn.js +147 -6
- package/node_modules/pi-lens/dist/clients/rust-client.js +1 -3
- package/node_modules/pi-lens/dist/clients/safe-spawn.js +150 -11
- package/node_modules/pi-lens/dist/clients/security-scan-client.js +1 -3
- package/node_modules/pi-lens/dist/clients/session-summary.js +3 -1
- package/node_modules/pi-lens/dist/clients/sg-runner.js +1 -3
- package/node_modules/pi-lens/dist/clients/source-filter.js +10 -6
- package/node_modules/pi-lens/dist/clients/source-walker.js +1 -1
- package/node_modules/pi-lens/dist/clients/spawn-timeout-cooldown.js +96 -0
- package/node_modules/pi-lens/dist/clients/startup-scan.js +4 -1
- package/node_modules/pi-lens/dist/clients/tool-definition.js +7 -0
- package/node_modules/pi-lens/dist/clients/tool-policy.js +26 -11
- package/node_modules/pi-lens/dist/clients/tool-render.js +2 -1
- package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +10 -4
- package/node_modules/pi-lens/dist/clients/tree-sitter-logger.js +2 -2
- package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +12 -5
- package/node_modules/pi-lens/dist/clients/warm-attach.js +12 -5
- package/node_modules/pi-lens/dist/clients/widget-state.js +27 -11
- package/node_modules/pi-lens/dist/clients/word-index.js +3 -1
- package/node_modules/pi-lens/dist/clients/workspace-topology.js +8 -2
- package/node_modules/pi-lens/dist/clients/zizmor-config.js +9 -1
- package/node_modules/pi-lens/dist/i18n.js +13 -5
- package/node_modules/pi-lens/dist/index.js +10797 -8627
- package/node_modules/pi-lens/dist/mcp/server.js +3 -1
- package/node_modules/pi-lens/dist/tools/ast-grep-replace.js +68 -12
- package/node_modules/pi-lens/dist/tools/lens-diagnostic-mark.js +21 -7
- package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +164 -35
- package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +24 -7
- package/node_modules/pi-lens/dist/tools/lsp-navigation.js +3 -1
- package/node_modules/pi-lens/dist/tools/module-report.js +1 -1
- package/node_modules/pi-lens/dist/tools/project-report.js +1 -1
- package/node_modules/pi-lens/dist/tools/symbol-search.js +5 -2
- package/node_modules/pi-lens/docs/durable-store-audit-1202.md +1 -1
- package/node_modules/pi-lens/docs/servercapabilities.md +1 -1
- package/node_modules/pi-lens/package.json +160 -156
- package/node_modules/pi-lens/rules/typos/_typos.toml +2 -2
- package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +31 -13
- package/node_modules/pi-lens/scripts/download-grammars.js +9 -3
- package/node_modules/pi-lens/scripts/rpc-load-check.mjs +30 -9
- package/node_modules/pi-mcp-adapter/CHANGELOG.md +47 -0
- package/node_modules/pi-mcp-adapter/README.md +42 -13
- package/node_modules/pi-mcp-adapter/commands.ts +4 -2
- package/node_modules/pi-mcp-adapter/config.ts +45 -5
- package/node_modules/pi-mcp-adapter/direct-tools.ts +103 -92
- package/node_modules/pi-mcp-adapter/dist/agent-dir.d.ts +10 -0
- package/node_modules/pi-mcp-adapter/dist/agent-dir.js +63 -0
- package/node_modules/pi-mcp-adapter/dist/agent-dir.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/agent-plugin-loader.d.ts +8 -0
- package/node_modules/pi-mcp-adapter/dist/agent-plugin-loader.js +356 -0
- package/node_modules/pi-mcp-adapter/dist/agent-plugin-loader.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/config.d.ts +123 -0
- package/node_modules/pi-mcp-adapter/dist/config.js +1087 -0
- package/node_modules/pi-mcp-adapter/dist/config.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/metadata-cache.d.ts +19 -0
- package/node_modules/pi-mcp-adapter/dist/metadata-cache.js +319 -0
- package/node_modules/pi-mcp-adapter/dist/metadata-cache.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/package-mcp-loader.d.ts +2 -0
- package/node_modules/pi-mcp-adapter/dist/package-mcp-loader.js +156 -0
- package/node_modules/pi-mcp-adapter/dist/package-mcp-loader.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/resource-tools.d.ts +1 -0
- package/node_modules/pi-mcp-adapter/dist/resource-tools.js +15 -0
- package/node_modules/pi-mcp-adapter/dist/resource-tools.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/types.d.ts +564 -0
- package/node_modules/pi-mcp-adapter/dist/types.js +287 -0
- package/node_modules/pi-mcp-adapter/dist/types.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/ui-app-bridge-helpers.d.ts +6 -0
- package/node_modules/pi-mcp-adapter/dist/ui-app-bridge-helpers.js +37 -0
- package/node_modules/pi-mcp-adapter/dist/ui-app-bridge-helpers.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/ui-stream-types.d.ts +104 -0
- package/node_modules/pi-mcp-adapter/dist/ui-stream-types.js +59 -0
- package/node_modules/pi-mcp-adapter/dist/ui-stream-types.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/ui-tool-visibility.d.ts +4 -0
- package/node_modules/pi-mcp-adapter/dist/ui-tool-visibility.js +27 -0
- package/node_modules/pi-mcp-adapter/dist/ui-tool-visibility.js.map +1 -0
- package/node_modules/pi-mcp-adapter/dist/utils.d.ts +32 -0
- package/node_modules/pi-mcp-adapter/dist/utils.js +338 -0
- package/node_modules/pi-mcp-adapter/dist/utils.js.map +1 -0
- package/node_modules/pi-mcp-adapter/failure-backoff.ts +23 -0
- package/node_modules/pi-mcp-adapter/index.ts +204 -82
- package/node_modules/pi-mcp-adapter/init.ts +41 -30
- package/node_modules/pi-mcp-adapter/lifecycle.ts +16 -8
- package/node_modules/pi-mcp-adapter/mcp-code.ts +2 -0
- package/node_modules/pi-mcp-adapter/mcp-oauth-provider.ts +66 -16
- package/node_modules/pi-mcp-adapter/mcp-output-guard.ts +95 -7
- package/node_modules/pi-mcp-adapter/mcp-probe.ts +18 -4
- package/node_modules/pi-mcp-adapter/mcp-references.ts +368 -0
- package/node_modules/pi-mcp-adapter/mcp-status.ts +8 -19
- package/node_modules/pi-mcp-adapter/metadata-cache.ts +20 -12
- package/node_modules/pi-mcp-adapter/namespace-tools.ts +276 -0
- package/node_modules/pi-mcp-adapter/package.json +24 -6
- package/node_modules/pi-mcp-adapter/proxy-modes.ts +66 -10
- package/node_modules/pi-mcp-adapter/search-ranking.ts +2 -0
- package/node_modules/pi-mcp-adapter/server-manager.ts +63 -12
- package/node_modules/pi-mcp-adapter/state.ts +1 -3
- package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +16 -2
- package/node_modules/pi-mcp-adapter/types.ts +48 -1
- package/node_modules/pi-mcp-adapter/ui-server.ts +3 -19
- package/node_modules/pi-mcp-adapter/ui-session.ts +2 -1
- package/node_modules/pi-mcp-adapter/utils.ts +21 -19
- package/node_modules/pi-web-access/CHANGELOG.md +26 -0
- package/node_modules/pi-web-access/README.md +71 -14
- package/node_modules/pi-web-access/chrome-cookies.ts +115 -35
- package/node_modules/pi-web-access/credential-source.ts +6 -2
- package/node_modules/pi-web-access/curator-page.ts +5 -3
- package/node_modules/pi-web-access/curator-server.ts +2 -1
- package/node_modules/pi-web-access/extract.ts +89 -9
- package/node_modules/pi-web-access/fetch-params.ts +13 -0
- package/node_modules/pi-web-access/gemini-adc.ts +298 -0
- package/node_modules/pi-web-access/gemini-api.ts +59 -15
- package/node_modules/pi-web-access/gemini-search.ts +58 -18
- package/node_modules/pi-web-access/gemini-url-context.ts +3 -2
- package/node_modules/pi-web-access/gemini-web-config.ts +57 -7
- package/node_modules/pi-web-access/gemini-web.ts +9 -3
- package/node_modules/pi-web-access/github-api.ts +5 -4
- package/node_modules/pi-web-access/github-issue-pr.ts +700 -0
- package/node_modules/pi-web-access/index.ts +403 -297
- package/node_modules/pi-web-access/kimi-search.ts +234 -0
- package/node_modules/pi-web-access/openai-search.ts +118 -21
- package/node_modules/pi-web-access/package.json +3 -2
- package/node_modules/pi-web-access/ssrf-protection.ts +4 -1
- package/node_modules/pi-web-access/utils.ts +307 -1
- package/node_modules/pi-web-access/youtube-extract.ts +2 -2
- package/package.json +46 -37
- package/node_modules/@herbertgao/pi-copy-response/CHANGELOG.md +0 -49
- package/node_modules/@herbertgao/pi-copy-response/LICENSE +0 -22
- package/node_modules/@herbertgao/pi-handoff/CHANGELOG.md +0 -83
- package/node_modules/@herbertgao/pi-handoff/LICENSE +0 -22
- package/node_modules/@herbertgao/pi-handoff/package.json +0 -60
- package/node_modules/@herbertgao/pi-inline-skills/CHANGELOG.md +0 -57
- package/node_modules/@herbertgao/pi-inline-skills/LICENSE +0 -22
- package/node_modules/@herbertgao/pi-mermaid-open/CHANGELOG.md +0 -39
- package/node_modules/@herbertgao/pi-preferred-thinking/CHANGELOG.md +0 -63
- package/node_modules/@herbertgao/pi-preferred-thinking/LICENSE +0 -22
- package/node_modules/@herbertgao/pi-recap/CHANGELOG.md +0 -101
- package/node_modules/@herbertgao/pi-recap/LICENSE +0 -22
- package/node_modules/@herbertgao/pi-recap/package.json +0 -55
- package/node_modules/@herbertgao/pi-rename/CHANGELOG.md +0 -49
- package/node_modules/@herbertgao/pi-rename/LICENSE +0 -22
- package/node_modules/@herbertgao/pi-rename/package.json +0 -63
- package/node_modules/@herbertgao/pi-titlebar-spinner/CHANGELOG.md +0 -25
- package/node_modules/@herbertgao/pi-titlebar-spinner/LICENSE +0 -22
- /package/node_modules/{@herbertgao → @tifan}/pi-copy-response/src/index.ts +0 -0
- /package/node_modules/{@herbertgao → @tifan}/pi-handoff/src/complete-text.ts +0 -0
- /package/node_modules/{@herbertgao → @tifan}/pi-handoff/src/session-query.ts +0 -0
- /package/node_modules/{@herbertgao → @tifan}/pi-inline-skills/src/index.ts +0 -0
- /package/node_modules/{@herbertgao → @tifan}/pi-mermaid-open/herdr-plugin/herdr-plugin.toml +0 -0
- /package/node_modules/{@herbertgao → @tifan}/pi-mermaid-open/herdr-plugin/viewer.mjs +0 -0
- /package/node_modules/{@herbertgao → @tifan}/pi-mermaid-open/src/index.ts +0 -0
- /package/node_modules/{@herbertgao → @tifan}/pi-recap/src/index.ts +0 -0
- /package/node_modules/{@herbertgao → @tifan}/pi-recap/src/model-picker.ts +0 -0
- /package/node_modules/{@herbertgao → @tifan}/pi-recap/src/sanitize.ts +0 -0
- /package/node_modules/{@herbertgao → @tifan}/pi-recap/src/tui.ts +0 -0
- /package/node_modules/{@herbertgao → @tifan}/pi-rename/src/model-picker.ts +0 -0
- /package/node_modules/{@herbertgao → @tifan}/pi-rename/src/naming.ts +0 -0
- /package/node_modules/{@herbertgao → @tifan}/pi-rename/src/sanitize.ts +0 -0
- /package/node_modules/{@herbertgao → @tifan}/pi-titlebar-spinner/src/index.ts +0 -0
|
@@ -11,7 +11,7 @@ import { rewriteSearchQuery } from "./query-rewrite.ts";
|
|
|
11
11
|
import { clearCloneCache } from "./github-extract.ts";
|
|
12
12
|
import { getConfiguredSearchRouting, normalizeSearchProviderSelection, RESOLVED_SEARCH_PROVIDERS, SEARCH_PROVIDERS, search, type AttributedSearchResponse, type SearchProvider, type SearchProviderSelection, type ResolvedSearchProvider } from "./gemini-search.ts";
|
|
13
13
|
import type { SearchResult } from "./perplexity.ts";
|
|
14
|
-
import { formatSeconds, getWebSearchConfigDir, getWebSearchConfigPath, resolveCuratorNetworkConfig } from "./utils.ts";
|
|
14
|
+
import { formatSeconds, getWebSearchConfigDir, getWebSearchConfigPath, installGlobalProxyFetch, resolveCuratorNetworkConfig, runWithProxy } from "./utils.ts";
|
|
15
15
|
import {
|
|
16
16
|
clearResults,
|
|
17
17
|
deleteResult,
|
|
@@ -42,10 +42,10 @@ import { join } from "node:path";
|
|
|
42
42
|
import { isPerplexityAvailable } from "./perplexity.ts";
|
|
43
43
|
import { isExaAvailable } from "./exa.ts";
|
|
44
44
|
import { isGeminiApiAvailable } from "./gemini-api.ts";
|
|
45
|
-
import { getActiveGoogleEmail, getGeminiWebAvailabilityDiagnostic, isGeminiWebAvailable } from "./gemini-web.ts";
|
|
45
|
+
import { getActiveGoogleEmail, getGeminiWebAvailabilityDiagnostic, getGeminiWebAvailabilityDiagnosticDetails, isGeminiWebAvailable } from "./gemini-web.ts";
|
|
46
46
|
import { isBrowserCookieAccessAllowed } from "./gemini-web-config.ts";
|
|
47
47
|
import { isBraveAvailable } from "./brave.ts";
|
|
48
|
-
import { isOpenAISearchAvailable } from "./openai-search.ts";
|
|
48
|
+
import { isCurrentModelHostedSearchEligible, isOpenAISearchAvailable } from "./openai-search.ts";
|
|
49
49
|
import { isParallelAvailable } from "./parallel.ts";
|
|
50
50
|
import { isParallelMcpAvailable } from "./parallel-mcp.ts";
|
|
51
51
|
import { isTinyFishAvailable } from "./tinyfish.ts";
|
|
@@ -63,6 +63,7 @@ import { isSearXNGAvailable } from "./searxng.ts";
|
|
|
63
63
|
import { isDuckDuckGoAvailable } from "./duckduckgo.ts";
|
|
64
64
|
import { isAnySearchAvailable } from "./anysearch.ts";
|
|
65
65
|
import { isXaiSearchAvailable } from "./xai-search.ts";
|
|
66
|
+
import { isKimiSearchAvailable } from "./kimi-search.ts";
|
|
66
67
|
import { isBrightDataAvailable } from "./brightdata.ts";
|
|
67
68
|
import { isSerpBaseAvailable } from "./serpbase.ts";
|
|
68
69
|
import { isSerperAvailable } from "./serper.ts";
|
|
@@ -92,6 +93,18 @@ async function fetchAllContent(
|
|
|
92
93
|
return extractModule.fetchAllContent(urls, signal, options);
|
|
93
94
|
}
|
|
94
95
|
|
|
96
|
+
function withRegisteredFetchOptions(
|
|
97
|
+
options: ExtractOptions | undefined,
|
|
98
|
+
toolNames: ExtractOptions["toolNames"],
|
|
99
|
+
proxy?: string,
|
|
100
|
+
): ExtractOptions {
|
|
101
|
+
return {
|
|
102
|
+
...(options ?? {}),
|
|
103
|
+
toolNames,
|
|
104
|
+
...(proxy !== undefined ? { proxy } : {}),
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
95
108
|
function isAbortError(err: unknown): boolean {
|
|
96
109
|
return (err instanceof Error ? err.message : String(err)).toLowerCase().includes("abort");
|
|
97
110
|
}
|
|
@@ -171,6 +184,7 @@ export interface ProviderAvailability {
|
|
|
171
184
|
perplexity: boolean;
|
|
172
185
|
exa: boolean;
|
|
173
186
|
gemini: boolean;
|
|
187
|
+
kimi: boolean;
|
|
174
188
|
kagi: boolean;
|
|
175
189
|
bocha: boolean;
|
|
176
190
|
ollama: boolean;
|
|
@@ -383,7 +397,7 @@ function shouldAutoOpenCuratorBrowser(config: WebSearchConfig): boolean {
|
|
|
383
397
|
}
|
|
384
398
|
|
|
385
399
|
async function getProviderAvailability(ctx: ExtensionContext): Promise<ProviderAvailability> {
|
|
386
|
-
const geminiWebAvail = await
|
|
400
|
+
const geminiWebAvail = await getOptionalGeminiWebAvailability();
|
|
387
401
|
const geminiApiAvail = isGeminiApiAvailable();
|
|
388
402
|
const providers = {
|
|
389
403
|
openai: await isOpenAISearchAvailable(ctx),
|
|
@@ -406,6 +420,7 @@ async function getProviderAvailability(ctx: ExtensionContext): Promise<ProviderA
|
|
|
406
420
|
perplexity: isPerplexityAvailable(),
|
|
407
421
|
exa: isExaAvailable(),
|
|
408
422
|
gemini: geminiApiAvail || !!geminiWebAvail,
|
|
423
|
+
kimi: await isKimiSearchAvailable(ctx),
|
|
409
424
|
anysearch: isAnySearchAvailable(),
|
|
410
425
|
xai: await isXaiSearchAvailable(ctx),
|
|
411
426
|
brightdata: isBrightDataAvailable(),
|
|
@@ -414,12 +429,20 @@ async function getProviderAvailability(ctx: ExtensionContext): Promise<ProviderA
|
|
|
414
429
|
valyu: isValyuAvailable(),
|
|
415
430
|
};
|
|
416
431
|
return {
|
|
417
|
-
// Parallel MCP, DuckDuckGo, AnySearch, xAI, Bright Data, SerpBase,
|
|
418
|
-
all: Object.entries(providers).some(([provider, available]) => provider !== "parallel-mcp" && provider !== "duckduckgo" && provider !== "anysearch" && provider !== "
|
|
432
|
+
// Parallel MCP, DuckDuckGo, Kimi, AnySearch, Valyu, xAI, Bright Data, SerpBase, and Serper are explicit-only, so they never make `all` eligible.
|
|
433
|
+
all: Object.entries(providers).some(([provider, available]) => provider !== "parallel-mcp" && provider !== "duckduckgo" && provider !== "kimi" && provider !== "anysearch" && provider !== "valyu" && provider !== "xai" && provider !== "brightdata" && provider !== "serpbase" && provider !== "serper" && provider !== "gemini" && available) || geminiApiAvail,
|
|
419
434
|
...providers,
|
|
420
435
|
};
|
|
421
436
|
}
|
|
422
437
|
|
|
438
|
+
async function getOptionalGeminiWebAvailability() {
|
|
439
|
+
try {
|
|
440
|
+
return await isGeminiWebAvailable();
|
|
441
|
+
} catch {
|
|
442
|
+
return null;
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
423
446
|
function shouldUseOpenAICodexDefault(ctx?: Pick<ExtensionContext, "model">): boolean {
|
|
424
447
|
return ctx?.model?.provider === "openai-codex";
|
|
425
448
|
}
|
|
@@ -453,7 +476,7 @@ export function resolveCuratorDefaultProvider(
|
|
|
453
476
|
ctx?: Pick<ExtensionContext, "model">,
|
|
454
477
|
options?: Pick<PendingCurate, "numResults" | "recencyFilter">,
|
|
455
478
|
): CuratorProvider {
|
|
456
|
-
return resolveProvider(provider, available, options, shouldUseOpenAICodexDefault(ctx));
|
|
479
|
+
return resolveProvider(provider, available, options, shouldUseOpenAICodexDefault(ctx), ctx);
|
|
457
480
|
}
|
|
458
481
|
|
|
459
482
|
function firstAvailableProvider(available: ProviderAvailability, preferOpenAI: boolean, fallback: ResolvedSearchProvider): ResolvedSearchProvider {
|
|
@@ -484,6 +507,7 @@ function resolveProvider(
|
|
|
484
507
|
available: ProviderAvailability,
|
|
485
508
|
options?: Pick<PendingCurate, "numResults" | "recencyFilter">,
|
|
486
509
|
preferOpenAICodexDefault = false,
|
|
510
|
+
ctx?: Pick<ExtensionContext, "model">,
|
|
487
511
|
): CuratorProvider {
|
|
488
512
|
if (Array.isArray(provider)) return "all";
|
|
489
513
|
const preferOpenAI = shouldPreferOpenAI(options, preferOpenAICodexDefault);
|
|
@@ -492,9 +516,10 @@ function resolveProvider(
|
|
|
492
516
|
const routing = getConfiguredSearchRouting();
|
|
493
517
|
if (routing) {
|
|
494
518
|
for (const candidate of routing.providers) {
|
|
519
|
+
if (candidate === "openai" && routing.useCurrentModel === true && !isCurrentModelHostedSearchEligible(ctx)) continue;
|
|
495
520
|
if (available[candidate]) return candidate;
|
|
496
521
|
}
|
|
497
|
-
return routing.providers[0];
|
|
522
|
+
return routing.providers.find(candidate => candidate !== "openai" || routing.useCurrentModel !== true || isCurrentModelHostedSearchEligible(ctx)) ?? routing.providers[0];
|
|
498
523
|
}
|
|
499
524
|
return firstAvailableProvider(available, preferOpenAI, "exa");
|
|
500
525
|
}
|
|
@@ -584,6 +609,7 @@ interface PendingCurate {
|
|
|
584
609
|
summaryModels: Array<{ value: string; label: string }>;
|
|
585
610
|
defaultSummaryModel: string | null;
|
|
586
611
|
timeoutSeconds: number;
|
|
612
|
+
proxy?: string;
|
|
587
613
|
curatorUrl?: string;
|
|
588
614
|
onUpdate: ((update: { content: Array<{ type: string; text: string }>; details?: Record<string, unknown> }) => void) | undefined;
|
|
589
615
|
signal: AbortSignal | undefined;
|
|
@@ -646,6 +672,40 @@ function normalizeFindQueries(value: string | string[]): string[] {
|
|
|
646
672
|
return queries;
|
|
647
673
|
}
|
|
648
674
|
|
|
675
|
+
interface GetSearchContentParams {
|
|
676
|
+
responseId: string;
|
|
677
|
+
query?: string;
|
|
678
|
+
queryIndex?: number;
|
|
679
|
+
url?: string;
|
|
680
|
+
urlIndex?: number;
|
|
681
|
+
offset?: number;
|
|
682
|
+
limit?: number;
|
|
683
|
+
findText?: string | string[];
|
|
684
|
+
findMode?: FindMode;
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
type RawGetSearchContentParams = Omit<GetSearchContentParams, "findMode"> & { findMode?: unknown };
|
|
688
|
+
|
|
689
|
+
function normalizeFindMode(value: unknown): FindMode | undefined {
|
|
690
|
+
if (value === undefined) return undefined;
|
|
691
|
+
if (value === "exact" || value === "case-insensitive" || value === "fuzzy") return value;
|
|
692
|
+
throw new Error('findMode must be "exact", "case-insensitive", or "fuzzy"');
|
|
693
|
+
}
|
|
694
|
+
|
|
695
|
+
function normalizeGetSearchContentParams(params: RawGetSearchContentParams): GetSearchContentParams {
|
|
696
|
+
const normalized: GetSearchContentParams = { ...params, findMode: normalizeFindMode(params.findMode) };
|
|
697
|
+
|
|
698
|
+
if (normalized.query?.trim() === "") delete normalized.query;
|
|
699
|
+
if (normalized.url?.trim() === "") delete normalized.url;
|
|
700
|
+
|
|
701
|
+
if (normalized.findText !== undefined) {
|
|
702
|
+
delete normalized.offset;
|
|
703
|
+
delete normalized.limit;
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
return normalized;
|
|
707
|
+
}
|
|
708
|
+
|
|
649
709
|
function formatInputValue(value: unknown): string {
|
|
650
710
|
if (typeof value === "string") return JSON.stringify(value);
|
|
651
711
|
if (typeof value === "number") return Number.isNaN(value) ? "NaN" : String(value);
|
|
@@ -978,11 +1038,18 @@ function handleSessionChange(ctx: ExtensionContext): void {
|
|
|
978
1038
|
|
|
979
1039
|
export default function (pi: ExtensionAPI) {
|
|
980
1040
|
const initConfig = loadConfigForExtensionInit();
|
|
1041
|
+
installGlobalProxyFetch();
|
|
981
1042
|
const toolNames = resolveToolNames(initConfig);
|
|
982
1043
|
const webSearchEnabled = isToolEnabled(initConfig, "webSearch");
|
|
983
1044
|
const sourceCheckEnabled = isToolEnabled(initConfig, "sourceCheck");
|
|
984
1045
|
const fetchContentEnabled = isToolEnabled(initConfig, "fetchContent");
|
|
985
1046
|
const getSearchContentEnabled = isToolEnabled(initConfig, "getSearchContent");
|
|
1047
|
+
// Names as registered this session, so fetch failure guidance never points
|
|
1048
|
+
// at tools that are disabled or were renamed after init.
|
|
1049
|
+
const registeredToolNames = {
|
|
1050
|
+
...(webSearchEnabled ? { webSearch: toolNames.webSearch } : {}),
|
|
1051
|
+
...(fetchContentEnabled ? { fetchContent: toolNames.fetchContent } : {}),
|
|
1052
|
+
};
|
|
986
1053
|
const storedContentSources = joinToolNames([
|
|
987
1054
|
...(webSearchEnabled ? [toolNames.webSearch] : []),
|
|
988
1055
|
...(sourceCheckEnabled ? [toolNames.sourceCheck] : []),
|
|
@@ -997,12 +1064,12 @@ export default function (pi: ExtensionAPI) {
|
|
|
997
1064
|
const curateKey = initConfig.shortcuts?.curate || DEFAULT_SHORTCUTS.curate;
|
|
998
1065
|
const activityKey = initConfig.shortcuts?.activity || DEFAULT_SHORTCUTS.activity;
|
|
999
1066
|
|
|
1000
|
-
function startBackgroundFetch(urls: string[]): string | null {
|
|
1067
|
+
function startBackgroundFetch(urls: string[], proxy?: string): string | null {
|
|
1001
1068
|
if (urls.length === 0) return null;
|
|
1002
1069
|
const fetchId = generateId();
|
|
1003
1070
|
const controller = new AbortController();
|
|
1004
1071
|
pendingFetches.set(fetchId, controller);
|
|
1005
|
-
fetchAllContent(urls, controller.signal)
|
|
1072
|
+
runWithProxy(proxy, () => fetchAllContent(urls, controller.signal, withRegisteredFetchOptions(undefined, registeredToolNames, proxy)))
|
|
1006
1073
|
.then((fetched) => {
|
|
1007
1074
|
if (!sessionActive || !pendingFetches.has(fetchId)) return;
|
|
1008
1075
|
const data = {
|
|
@@ -1067,6 +1134,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
1067
1134
|
workflow?: SummaryWorkflow;
|
|
1068
1135
|
approvedSummary?: string;
|
|
1069
1136
|
summaryMeta?: SummaryMeta;
|
|
1137
|
+
proxy?: string;
|
|
1070
1138
|
}
|
|
1071
1139
|
|
|
1072
1140
|
function normalizeSummaryMeta(meta: SummaryMeta | undefined, summaryText: string): SummaryMeta {
|
|
@@ -1319,7 +1387,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
1319
1387
|
output += `---\nFull content for ${opts.inlineContent.length} sources available [${fetchId}].`;
|
|
1320
1388
|
}
|
|
1321
1389
|
} else if (opts.includeContent) {
|
|
1322
|
-
fetchId = startBackgroundFetch(opts.urls);
|
|
1390
|
+
fetchId = startBackgroundFetch(opts.urls, opts.proxy);
|
|
1323
1391
|
if (fetchId && !hasApprovedSummary) {
|
|
1324
1392
|
output += `---\nContent fetching in background [${fetchId}]. Will notify when ready.`;
|
|
1325
1393
|
}
|
|
@@ -1434,25 +1502,27 @@ export default function (pi: ExtensionAPI) {
|
|
|
1434
1502
|
},
|
|
1435
1503
|
{
|
|
1436
1504
|
async onSummarize(selectedQueryIndices, summarizeSignal, model, feedback) {
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1505
|
+
return runWithProxy(pc.proxy, async () => {
|
|
1506
|
+
if (pendingCurates.get(callId) !== pc) throw new Error("Curator session is no longer active.");
|
|
1507
|
+
pc.onUpdate?.({
|
|
1508
|
+
content: [{ type: "text", text: "Generating summary draft..." }],
|
|
1509
|
+
details: { phase: "generating-summary", progress: 0.9, curatorUrl: pc.curatorUrl, timeoutSeconds: pc.timeoutSeconds, shortcut: curateKey },
|
|
1510
|
+
});
|
|
1511
|
+
const draft = await generateSummaryForSelectedIndices(
|
|
1512
|
+
selectedQueryIndices,
|
|
1513
|
+
pc.searchResults,
|
|
1514
|
+
pc.summaryContext,
|
|
1515
|
+
summarizeSignal,
|
|
1516
|
+
model,
|
|
1517
|
+
feedback,
|
|
1518
|
+
);
|
|
1519
|
+
if (pendingCurates.get(callId) !== pc) throw new Error("Curator session is no longer active.");
|
|
1520
|
+
pc.onUpdate?.({
|
|
1521
|
+
content: [{ type: "text", text: "Summary draft ready — waiting for approval..." }],
|
|
1522
|
+
details: { phase: "waiting-for-approval", progress: 1, curatorUrl: pc.curatorUrl, timeoutSeconds: pc.timeoutSeconds, shortcut: curateKey },
|
|
1523
|
+
});
|
|
1524
|
+
return draft;
|
|
1454
1525
|
});
|
|
1455
|
-
return draft;
|
|
1456
1526
|
},
|
|
1457
1527
|
onSubmit(payload) {
|
|
1458
1528
|
if (pendingCurates.get(callId) !== pc) return;
|
|
@@ -1469,6 +1539,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
1469
1539
|
inlineContent: filteredInline.length > 0 ? filteredInline : undefined,
|
|
1470
1540
|
curated: true,
|
|
1471
1541
|
curatedFrom: pc.searchResults.size,
|
|
1542
|
+
proxy: pc.proxy,
|
|
1472
1543
|
};
|
|
1473
1544
|
if (!payload.rawResults) {
|
|
1474
1545
|
const resolvedSummary = resolveSummaryForSubmit(payload, pc.searchResults);
|
|
@@ -1497,6 +1568,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
1497
1568
|
workflow: pc.workflow,
|
|
1498
1569
|
approvedSummary: resolvedSummary.approvedSummary,
|
|
1499
1570
|
summaryMeta: resolvedSummary.summaryMeta,
|
|
1571
|
+
proxy: pc.proxy,
|
|
1500
1572
|
}));
|
|
1501
1573
|
} else {
|
|
1502
1574
|
const conn = activeCurators.get(callId)?.getConnectionState();
|
|
@@ -1525,20 +1597,22 @@ export default function (pi: ExtensionAPI) {
|
|
|
1525
1597
|
}
|
|
1526
1598
|
},
|
|
1527
1599
|
async onAddSearch(query, provider) {
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1600
|
+
return runWithProxy(pc.proxy, async () => {
|
|
1601
|
+
if (pendingCurates.get(callId) !== pc) throw new Error("Curator session is no longer active.");
|
|
1602
|
+
const requestedProvider = resolveCuratorSearchProvider(provider, pc.searchProvider);
|
|
1603
|
+
const response = await search(query, {
|
|
1604
|
+
provider: requestedProvider,
|
|
1605
|
+
numResults: pc.numResults,
|
|
1606
|
+
recencyFilter: pc.recencyFilter,
|
|
1607
|
+
domainFilter: pc.domainFilter,
|
|
1608
|
+
includeContent: pc.includeContent,
|
|
1609
|
+
signal: addSearchSignal,
|
|
1610
|
+
extensionContext: ctx,
|
|
1611
|
+
});
|
|
1612
|
+
if (pendingCurates.get(callId) !== pc) throw new Error("Curator session is no longer active.");
|
|
1613
|
+
if (response.inlineContent) pc.allInlineContent.push(...response.inlineContent);
|
|
1614
|
+
return toCuratorSearchEntries(response);
|
|
1538
1615
|
});
|
|
1539
|
-
if (pendingCurates.get(callId) !== pc) throw new Error("Curator session is no longer active.");
|
|
1540
|
-
if (response.inlineContent) pc.allInlineContent.push(...response.inlineContent);
|
|
1541
|
-
return toCuratorSearchEntries(response);
|
|
1542
1616
|
},
|
|
1543
1617
|
onAddSearchResults(entries) {
|
|
1544
1618
|
if (pendingCurates.get(callId) !== pc) return;
|
|
@@ -1547,8 +1621,10 @@ export default function (pi: ExtensionAPI) {
|
|
|
1547
1621
|
}
|
|
1548
1622
|
},
|
|
1549
1623
|
async onRewriteQuery(query, rewriteSignal) {
|
|
1550
|
-
|
|
1551
|
-
|
|
1624
|
+
return runWithProxy(pc.proxy, async () => {
|
|
1625
|
+
if (pendingCurates.get(callId) !== pc) throw new Error("Curator session is no longer active.");
|
|
1626
|
+
return rewriteSearchQuery(query, pc.summaryContext, rewriteSignal);
|
|
1627
|
+
});
|
|
1552
1628
|
},
|
|
1553
1629
|
},
|
|
1554
1630
|
);
|
|
@@ -1674,7 +1750,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
1674
1750
|
name: toolNames.webSearch,
|
|
1675
1751
|
label: "Web Search",
|
|
1676
1752
|
description:
|
|
1677
|
-
`Search the web using OpenAI, Brave, Parallel, Parallel MCP, TinyFish, Search1API, Searchinfinity, Querit, Tavily, Firecrawl, Jina, SERPdive, Kagi, Bocha, Ollama, SearXNG, DuckDuckGo, Exa, Perplexity, Gemini, AnySearch, Valyu, xAI, Bright Data, SerpBase, or Serper. Pass a provider array to search only those providers simultaneously, or use provider "all" to search every eligible provider except Parallel MCP, DuckDuckGo, AnySearch, Valyu, xAI, Bright Data, SerpBase, and Serper. Returns an AI-synthesized answer with source citations. OpenAI search uses a Codex subscription or OpenAI API key; xAI search uses a SuperGrok/X Premium subscription or xAI API key. Parallel MCP, DuckDuckGo, AnySearch, Valyu, xAI, Bright Data, SerpBase, and Serper are available only when explicitly selected. For comprehensive research, prefer queries (plural) with 2-4 varied angles over a single query — each query gets its own synthesized answer, so varying phrasing and scope gives much broader coverage. When includeContent is true, full page content is fetched in the background. Searches auto-open the interactive browser curator and stream results live; set workflow to "none" to skip curation or "auto-summary" for a model-generated summary without the browser curator. The configured provider is used when provider is omitted or set to auto; omit provider unless explicitly overriding it. Without a configured provider, SearXNG is preferred first for local/private search. When the active Pi model is openai-codex, Codex-backed OpenAI search is preferred next. Otherwise Exa is preferred before OpenAI, then Brave, Parallel, TinyFish, Search1API, Searchinfinity, Querit, Tavily, Firecrawl, Jina, SERPdive, Kagi, Bocha, Ollama, Perplexity, Gemini API, or Gemini Web.`,
|
|
1753
|
+
`Search the web using OpenAI, Brave, Parallel, Parallel MCP, TinyFish, Search1API, Searchinfinity, Querit, Tavily, Firecrawl, Jina, SERPdive, Kagi, Bocha, Ollama, SearXNG, DuckDuckGo, Exa, Perplexity, Gemini, Kimi, AnySearch, Valyu, xAI, Bright Data, SerpBase, or Serper. Pass a provider array to search only those providers simultaneously, or use provider "all" to search every eligible provider except Parallel MCP, DuckDuckGo, Kimi, AnySearch, Valyu, xAI, Bright Data, SerpBase, and Serper. Returns an AI-synthesized answer with source citations. OpenAI search uses a Codex subscription or OpenAI API key; Kimi search uses a Kimi Code Plan authenticated through /login kimi-coding; xAI search uses a SuperGrok/X Premium subscription or xAI API key. Parallel MCP, DuckDuckGo, Kimi, AnySearch, Valyu, xAI, Bright Data, SerpBase, and Serper are available only when explicitly selected. For comprehensive research, prefer queries (plural) with 2-4 varied angles over a single query — each query gets its own synthesized answer, so varying phrasing and scope gives much broader coverage. When includeContent is true, full page content is fetched in the background. Searches auto-open the interactive browser curator and stream results live; set workflow to "none" to skip curation or "auto-summary" for a model-generated summary without the browser curator. The configured provider is used when provider is omitted or set to auto; omit provider unless explicitly overriding it. Without a configured provider, SearXNG is preferred first for local/private search. When the active Pi model is openai-codex, Codex-backed OpenAI search is preferred next. Otherwise Exa is preferred before OpenAI, then Brave, Parallel, TinyFish, Search1API, Searchinfinity, Querit, Tavily, Firecrawl, Jina, SERPdive, Kagi, Bocha, Ollama, Perplexity, Gemini API, or Gemini Web.`,
|
|
1678
1754
|
promptSnippet:
|
|
1679
1755
|
"Use for web research questions. Prefer {queries:[...]} with 2-4 varied angles over a single query for broader coverage. Omit provider unless explicitly overriding the configured default.",
|
|
1680
1756
|
parameters: Type.Object({
|
|
@@ -1686,39 +1762,43 @@ export default function (pi: ExtensionAPI) {
|
|
|
1686
1762
|
StringEnum(["day", "week", "month", "year"], { description: "Filter by recency" }),
|
|
1687
1763
|
),
|
|
1688
1764
|
domainFilter: Type.Optional(Type.Array(Type.String(), { description: "Limit to domains (prefix with - to exclude)" })),
|
|
1689
|
-
provider: Type.Optional(searchProviderSchema("Search provider or non-empty list of providers to search simultaneously; use all to search every eligible provider except Parallel MCP, DuckDuckGo, AnySearch, xAI, Bright Data, SerpBase,
|
|
1765
|
+
provider: Type.Optional(searchProviderSchema("Search provider or non-empty list of providers to search simultaneously; use all to search every eligible provider except Parallel MCP, DuckDuckGo, Kimi, AnySearch, Valyu, xAI, Bright Data, SerpBase, and Serper, omit this field to use the configured provider, or use auto when none is configured")),
|
|
1690
1766
|
workflow: Type.Optional(
|
|
1691
1767
|
StringEnum(["none", "summary-review", "auto-summary"], {
|
|
1692
1768
|
description: "Search workflow mode: none = no curator, summary-review = open curator with auto summary draft (default), auto-summary = generate summary without opening curator",
|
|
1693
1769
|
}),
|
|
1694
1770
|
),
|
|
1771
|
+
proxy: Type.Optional(Type.String({
|
|
1772
|
+
description: "http(s) proxy URL (e.g. http://host:port) used for every outbound request in this call (search APIs and content fetches). Node fetch ignores HTTP(S)_PROXY env vars, so set this (or `proxy` in web-search.json) when direct access is blocked; empty string forces direct access.",
|
|
1773
|
+
})),
|
|
1695
1774
|
}),
|
|
1696
1775
|
|
|
1697
1776
|
async execute(callId, params, signal, onUpdate, ctx) {
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1777
|
+
return runWithProxy(typeof params.proxy === "string" ? params.proxy : undefined, async () => {
|
|
1778
|
+
const rawQueryList: unknown[] = Array.isArray(params.queries)
|
|
1779
|
+
? params.queries
|
|
1780
|
+
: (params.query !== undefined ? [params.query] : []);
|
|
1781
|
+
const queryList = normalizeQueryList(rawQueryList);
|
|
1782
|
+
const configWorkflow = loadConfigForExtensionInit().workflow;
|
|
1783
|
+
const workflow = resolveWorkflow(params.workflow ?? configWorkflow, ctx?.hasUI !== false);
|
|
1784
|
+
const shouldCurate = workflow === "summary-review";
|
|
1785
|
+
const recencyFilter = normalizeRecencyFilter(params.recencyFilter);
|
|
1786
|
+
|
|
1787
|
+
if (queryList.length === 0) {
|
|
1788
|
+
return {
|
|
1789
|
+
content: [{ type: "text", text: "Error: No query provided. Use 'query' or 'queries' parameter." }],
|
|
1790
|
+
details: { error: "No query provided" },
|
|
1791
|
+
};
|
|
1792
|
+
}
|
|
1713
1793
|
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1794
|
+
if (shouldCurate && !ctx) {
|
|
1795
|
+
return {
|
|
1796
|
+
content: [{ type: "text", text: "Error: Curation requires an active extension context." }],
|
|
1797
|
+
details: { error: "Missing extension context" },
|
|
1798
|
+
};
|
|
1799
|
+
}
|
|
1720
1800
|
|
|
1721
|
-
|
|
1801
|
+
if (shouldCurate) {
|
|
1722
1802
|
closeCurator(callId);
|
|
1723
1803
|
|
|
1724
1804
|
let resolvePromise: (value: AgentToolResult<Record<string, unknown>>) => void = () => {};
|
|
@@ -1773,6 +1853,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
1773
1853
|
summaryModels: summaryModelChoices.summaryModels,
|
|
1774
1854
|
defaultSummaryModel: summaryModelChoices.defaultSummaryModel,
|
|
1775
1855
|
timeoutSeconds: curatorTimeoutSeconds,
|
|
1856
|
+
proxy: typeof params.proxy === "string" ? params.proxy : undefined,
|
|
1776
1857
|
onUpdate: onUpdate as PendingCurate["onUpdate"],
|
|
1777
1858
|
signal,
|
|
1778
1859
|
abortSearches: () => {
|
|
@@ -1983,6 +2064,8 @@ export default function (pi: ExtensionAPI) {
|
|
|
1983
2064
|
workflow: workflow === "auto-summary" ? "auto-summary" : undefined,
|
|
1984
2065
|
approvedSummary,
|
|
1985
2066
|
summaryMeta,
|
|
2067
|
+
proxy: typeof params.proxy === "string" ? params.proxy : undefined,
|
|
2068
|
+
});
|
|
1986
2069
|
});
|
|
1987
2070
|
},
|
|
1988
2071
|
|
|
@@ -2254,85 +2337,90 @@ export default function (pi: ExtensionAPI) {
|
|
|
2254
2337
|
fetchContent: Type.Optional(Type.Boolean({ description: "Fetch up to 5 result pages for exact passage extraction." })),
|
|
2255
2338
|
recencyFilter: Type.Optional(StringEnum(["day", "week", "month", "year"], { description: "Filter by recency." })),
|
|
2256
2339
|
domainFilter: Type.Optional(Type.Array(Type.String(), { description: "Limit to domains; prefix with - to exclude." })),
|
|
2257
|
-
provider: Type.Optional(searchProviderSchema("Search provider or non-empty list of providers to search simultaneously; all searches every eligible provider except DuckDuckGo, AnySearch, xAI, Bright Data, SerpBase,
|
|
2340
|
+
provider: Type.Optional(searchProviderSchema("Search provider or non-empty list of providers to search simultaneously; all searches every eligible provider except Parallel MCP, DuckDuckGo, Kimi, AnySearch, Valyu, xAI, Bright Data, SerpBase, and Serper")),
|
|
2341
|
+
proxy: Type.Optional(Type.String({
|
|
2342
|
+
description: "http(s) proxy URL (e.g. http://host:port) used for every outbound request in this call (search APIs and result-page fetches). Empty string forces direct access.",
|
|
2343
|
+
})),
|
|
2258
2344
|
}),
|
|
2259
2345
|
async execute(_callId, params, signal, _onUpdate, ctx) {
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2346
|
+
return runWithProxy(typeof params.proxy === "string" ? params.proxy : undefined, async () => {
|
|
2347
|
+
const claim = typeof params.claim === "string" ? params.claim.trim() : "";
|
|
2348
|
+
if (!claim) {
|
|
2349
|
+
return { content: [{ type: "text", text: "Error: 'claim' is required." }], details: { error: "Missing claim" } };
|
|
2350
|
+
}
|
|
2264
2351
|
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
if (signal?.aborted) break;
|
|
2283
|
-
try {
|
|
2284
|
-
const response = await search(query, {
|
|
2285
|
-
provider: resolveRequestedProvider(params.provider),
|
|
2286
|
-
numResults,
|
|
2287
|
-
recencyFilter,
|
|
2288
|
-
domainFilter,
|
|
2289
|
-
signal,
|
|
2290
|
-
extensionContext: ctx,
|
|
2291
|
-
});
|
|
2352
|
+
const requestedQueries = Array.isArray(params.queries)
|
|
2353
|
+
? params.queries.filter((query): query is string => typeof query === "string").map((query) => query.trim()).filter(Boolean)
|
|
2354
|
+
: [];
|
|
2355
|
+
const queries = (requestedQueries.length > 0 ? requestedQueries : [claim]).slice(0, 8);
|
|
2356
|
+
const numResults = typeof params.numResults === "number" && Number.isFinite(params.numResults)
|
|
2357
|
+
? Math.min(20, Math.max(1, Math.floor(params.numResults)))
|
|
2358
|
+
: 5;
|
|
2359
|
+
const domainFilter = Array.isArray(params.domainFilter)
|
|
2360
|
+
? params.domainFilter.filter((domain): domain is string => typeof domain === "string")
|
|
2361
|
+
: undefined;
|
|
2362
|
+
const recencyFilter = normalizeRecencyFilter(params.recencyFilter);
|
|
2363
|
+
const resultsByUrl = new Map<string, SearchResult>();
|
|
2364
|
+
const summaries: string[] = [];
|
|
2365
|
+
const errors: Array<{ query: string; error: string }> = [];
|
|
2366
|
+
let provider: string | undefined;
|
|
2367
|
+
|
|
2368
|
+
for (const query of queries) {
|
|
2292
2369
|
if (signal?.aborted) break;
|
|
2293
|
-
|
|
2294
|
-
|
|
2295
|
-
|
|
2296
|
-
|
|
2370
|
+
try {
|
|
2371
|
+
const response = await search(query, {
|
|
2372
|
+
provider: resolveRequestedProvider(params.provider),
|
|
2373
|
+
numResults,
|
|
2374
|
+
recencyFilter,
|
|
2375
|
+
domainFilter,
|
|
2376
|
+
signal,
|
|
2377
|
+
extensionContext: ctx,
|
|
2378
|
+
});
|
|
2379
|
+
if (signal?.aborted) break;
|
|
2380
|
+
provider ??= response.provider;
|
|
2381
|
+
if (response.answer) summaries.push(`${query}: ${response.answer}`);
|
|
2382
|
+
for (const result of response.results) {
|
|
2383
|
+
if (!resultsByUrl.has(result.url)) resultsByUrl.set(result.url, result);
|
|
2384
|
+
}
|
|
2385
|
+
} catch (err) {
|
|
2386
|
+
if (signal?.aborted || isAbortError(err)) break;
|
|
2387
|
+
errors.push({ query, error: err instanceof Error ? err.message : String(err) });
|
|
2297
2388
|
}
|
|
2298
|
-
} catch (err) {
|
|
2299
|
-
if (signal?.aborted || isAbortError(err)) break;
|
|
2300
|
-
errors.push({ query, error: err instanceof Error ? err.message : String(err) });
|
|
2301
2389
|
}
|
|
2302
|
-
}
|
|
2303
2390
|
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
2315
|
-
|
|
2316
|
-
|
|
2317
|
-
|
|
2318
|
-
|
|
2319
|
-
|
|
2320
|
-
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2326
|
-
|
|
2327
|
-
|
|
2328
|
-
|
|
2329
|
-
|
|
2330
|
-
|
|
2391
|
+
const results = [...resultsByUrl.values()].slice(0, 20).map((result, index) => ({ ...result, rank: index + 1 }));
|
|
2392
|
+
let fetched: ExtractedContent[] = [];
|
|
2393
|
+
if (params.fetchContent && results.length > 0) {
|
|
2394
|
+
const urls = results.slice(0, 5).map((result) => result.url);
|
|
2395
|
+
try {
|
|
2396
|
+
fetched = await fetchAllContent(urls, signal, withRegisteredFetchOptions(undefined, registeredToolNames, typeof params.proxy === "string" ? params.proxy : undefined));
|
|
2397
|
+
} catch (err) {
|
|
2398
|
+
if (signal?.aborted || isAbortError(err)) throw err;
|
|
2399
|
+
fetched = urls.map((url) => ({ url, title: "", content: "", error: err instanceof Error ? err.message : String(err) }));
|
|
2400
|
+
}
|
|
2401
|
+
}
|
|
2402
|
+
const artifact = withClaimAssessment(buildResearchArtifact({
|
|
2403
|
+
query: claim,
|
|
2404
|
+
provider,
|
|
2405
|
+
summary: summaries.length > 0 ? summaries.join("\n\n") : undefined,
|
|
2406
|
+
results,
|
|
2407
|
+
fetched,
|
|
2408
|
+
recency: recencyFilter,
|
|
2409
|
+
domainFilter,
|
|
2410
|
+
}), [claim]);
|
|
2411
|
+
if (errors.length > 0) artifact.errors = errors;
|
|
2412
|
+
storeResearchArtifact(artifact);
|
|
2413
|
+
pi.appendEntry("web-search-results", {
|
|
2414
|
+
id: artifact.id,
|
|
2415
|
+
type: "research",
|
|
2416
|
+
timestamp: artifact.timestamp,
|
|
2417
|
+
artifact,
|
|
2418
|
+
});
|
|
2419
|
+
return {
|
|
2420
|
+
content: [{ type: "text", text: formatSourceCheckResult(artifact, getSearchContentEnabled ? toolNames.getSearchContent : null) }],
|
|
2421
|
+
details: { responseId: artifact.id, artifact, sourceCount: artifact.sources.length, passageCount: artifact.passages.length },
|
|
2422
|
+
};
|
|
2331
2423
|
});
|
|
2332
|
-
return {
|
|
2333
|
-
content: [{ type: "text", text: formatSourceCheckResult(artifact, getSearchContentEnabled ? toolNames.getSearchContent : null) }],
|
|
2334
|
-
details: { responseId: artifact.id, artifact, sourceCount: artifact.sources.length, passageCount: artifact.passages.length },
|
|
2335
|
-
};
|
|
2336
2424
|
},
|
|
2337
2425
|
});
|
|
2338
2426
|
|
|
@@ -2371,6 +2459,9 @@ export default function (pi: ExtensionAPI) {
|
|
|
2371
2459
|
auth: Type.Optional(Type.Union([Type.String(), Type.Boolean()], {
|
|
2372
2460
|
description: "Opt into an authFetch profile for local browser-cookie fetching. Use a profile name, or true only when exactly one profile exists.",
|
|
2373
2461
|
})),
|
|
2462
|
+
proxy: Type.Optional(Type.String({
|
|
2463
|
+
description: "http(s) proxy URL (e.g. http://host:port) used for this fetch. Needed when the target is unreachable directly; localhost and NO_PROXY hosts always bypass the proxy. Empty string forces direct access.",
|
|
2464
|
+
})),
|
|
2374
2465
|
}),
|
|
2375
2466
|
|
|
2376
2467
|
async execute(_toolCallId, params, signal, onUpdate, ctx): Promise<AgentToolResult<Record<string, unknown>>> {
|
|
@@ -2382,164 +2473,164 @@ export default function (pi: ExtensionAPI) {
|
|
|
2382
2473
|
return { content: [{ type: "text", text: `Error: ${error}` }], details: { error } };
|
|
2383
2474
|
}
|
|
2384
2475
|
const { urlList, options } = normalized;
|
|
2385
|
-
|
|
2386
|
-
|
|
2387
|
-
|
|
2388
|
-
|
|
2389
|
-
if (mode === "raw" && (options.forceClone === true || options.timestamp || options.frames || options.prompt || options.model || options.answerModel)) {
|
|
2390
|
-
return { content: [{ type: "text", text: "Error: mode raw cannot be combined with forceClone, prompt, timestamp, frames, model, or answerModel." }], details: { error: "Incompatible raw mode options" } };
|
|
2391
|
-
}
|
|
2392
|
-
if (mode !== "answer" && options.answerModel) {
|
|
2393
|
-
return { content: [{ type: "text", text: "Error: answerModel requires mode answer." }], details: { error: "answerModel requires mode answer" } };
|
|
2394
|
-
}
|
|
2395
|
-
if (mode === "answer" && options.model) {
|
|
2396
|
-
return { content: [{ type: "text", text: "Error: use answerModel, not model, with mode answer." }], details: { error: "model is incompatible with mode answer" } };
|
|
2397
|
-
}
|
|
2398
|
-
if (mode === "answer" && options.auth !== undefined) {
|
|
2399
|
-
return { content: [{ type: "text", text: "Error: auth cannot be combined with mode answer." }], details: { error: "auth cannot be combined with mode answer" } };
|
|
2400
|
-
}
|
|
2401
|
-
let authFetchProfile: AuthFetchProfile | undefined;
|
|
2402
|
-
if (options.auth !== undefined) {
|
|
2403
|
-
try {
|
|
2404
|
-
authFetchProfile = resolveAuthFetchProfile(options.auth);
|
|
2405
|
-
} catch (err) {
|
|
2406
|
-
const error = err instanceof Error ? err.message : String(err);
|
|
2407
|
-
return { content: [{ type: "text", text: `Error: ${error}` }], details: { error } };
|
|
2476
|
+
return runWithProxy(options.proxy, async () => {
|
|
2477
|
+
const mode = options.mode ?? "readable";
|
|
2478
|
+
if (mode === "answer" && !options.prompt) {
|
|
2479
|
+
return { content: [{ type: "text", text: "Error: mode answer requires prompt." }], details: { error: "mode answer requires prompt" } };
|
|
2408
2480
|
}
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
details: { error: "
|
|
2414
|
-
}
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
const fetchOptions = mode === "answer"
|
|
2424
|
-
? (() => {
|
|
2425
|
-
const { prompt: _prompt, ...rest } = extractionOptions;
|
|
2426
|
-
return { ...rest, ...(authFetchProfile ? { authFetchProfile } : {}) };
|
|
2427
|
-
})()
|
|
2428
|
-
: { ...extractionOptions, ...(authFetchProfile ? { authFetchProfile } : {}) };
|
|
2429
|
-
const fetchResults = await fetchAllContent(urlList, signal, fetchOptions);
|
|
2430
|
-
const presentedResults = mode === "answer"
|
|
2431
|
-
? await Promise.all(fetchResults.map(async result => {
|
|
2432
|
-
if (result.error) return result;
|
|
2433
|
-
if (result.thumbnail || result.mimeType?.startsWith("image/")) {
|
|
2434
|
-
return { ...result, error: "Page answer requires textual fetched content" };
|
|
2435
|
-
}
|
|
2481
|
+
if (mode === "raw" && (options.forceClone === true || options.timestamp || options.frames || options.prompt || options.model || options.answerModel)) {
|
|
2482
|
+
return { content: [{ type: "text", text: "Error: mode raw cannot be combined with forceClone, prompt, timestamp, frames, model, or answerModel." }], details: { error: "Incompatible raw mode options" } };
|
|
2483
|
+
}
|
|
2484
|
+
if (mode !== "answer" && options.answerModel) {
|
|
2485
|
+
return { content: [{ type: "text", text: "Error: answerModel requires mode answer." }], details: { error: "answerModel requires mode answer" } };
|
|
2486
|
+
}
|
|
2487
|
+
if (mode === "answer" && options.model) {
|
|
2488
|
+
return { content: [{ type: "text", text: "Error: use answerModel, not model, with mode answer." }], details: { error: "model is incompatible with mode answer" } };
|
|
2489
|
+
}
|
|
2490
|
+
if (mode === "answer" && options.auth !== undefined) {
|
|
2491
|
+
return { content: [{ type: "text", text: "Error: auth cannot be combined with mode answer." }], details: { error: "auth cannot be combined with mode answer" } };
|
|
2492
|
+
}
|
|
2493
|
+
let authFetchProfile: AuthFetchProfile | undefined;
|
|
2494
|
+
if (options.auth !== undefined) {
|
|
2436
2495
|
try {
|
|
2437
|
-
|
|
2438
|
-
question: options.prompt!,
|
|
2439
|
-
pageText: result.content,
|
|
2440
|
-
sourceUrl: result.url,
|
|
2441
|
-
...(options.answerModel ? { model: options.answerModel } : {}),
|
|
2442
|
-
}, ctx, signal);
|
|
2443
|
-
return { ...result, content: answer.text };
|
|
2496
|
+
authFetchProfile = resolveAuthFetchProfile(options.auth);
|
|
2444
2497
|
} catch (err) {
|
|
2445
|
-
|
|
2498
|
+
const error = err instanceof Error ? err.message : String(err);
|
|
2499
|
+
return { content: [{ type: "text", text: `Error: ${error}` }], details: { error } };
|
|
2446
2500
|
}
|
|
2447
|
-
}
|
|
2448
|
-
|
|
2449
|
-
const successful = presentedResults.filter((r) => !r.error).length;
|
|
2450
|
-
const totalChars = presentedResults.reduce((sum, r) => sum + r.content.length, 0);
|
|
2451
|
-
|
|
2452
|
-
const responseId = generateId();
|
|
2453
|
-
const data = {
|
|
2454
|
-
id: responseId,
|
|
2455
|
-
type: "fetch",
|
|
2456
|
-
timestamp: Date.now(),
|
|
2457
|
-
urls: stripThumbnails(fetchResults),
|
|
2458
|
-
} satisfies StoredSearchData & { type: "fetch"; urls: ExtractedContent[] };
|
|
2459
|
-
const storedContent = storeFetchResult(pi, responseId, data, authFetchProfile);
|
|
2460
|
-
|
|
2461
|
-
// Single URL: return content directly (possibly truncated) with responseId
|
|
2462
|
-
if (urlList.length === 1) {
|
|
2463
|
-
const result = presentedResults[0];
|
|
2464
|
-
if (result.error) {
|
|
2501
|
+
}
|
|
2502
|
+
if (urlList.length === 0) {
|
|
2465
2503
|
return {
|
|
2466
|
-
content: [{ type: "text", text:
|
|
2467
|
-
details: {
|
|
2504
|
+
content: [{ type: "text", text: "Error: No URL provided." }],
|
|
2505
|
+
details: { error: "No URL provided" },
|
|
2468
2506
|
};
|
|
2469
2507
|
}
|
|
2470
2508
|
|
|
2471
|
-
|
|
2472
|
-
|
|
2473
|
-
|
|
2474
|
-
|
|
2509
|
+
onUpdate?.({
|
|
2510
|
+
content: [{ type: "text", text: `Fetching ${urlList.length} URL(s)...` }],
|
|
2511
|
+
details: { phase: "fetch", progress: 0 },
|
|
2512
|
+
});
|
|
2513
|
+
|
|
2514
|
+
const { answerModel: _answerModel, auth: _auth, ...extractionOptions } = options;
|
|
2515
|
+
const fetchOptions = mode === "answer"
|
|
2516
|
+
? (() => {
|
|
2517
|
+
const { prompt: _prompt, ...rest } = extractionOptions;
|
|
2518
|
+
return { ...rest, ...(authFetchProfile ? { authFetchProfile } : {}) };
|
|
2519
|
+
})()
|
|
2520
|
+
: { ...extractionOptions, ...(authFetchProfile ? { authFetchProfile } : {}) };
|
|
2521
|
+
const fetchResults = await fetchAllContent(urlList, signal, withRegisteredFetchOptions(fetchOptions, registeredToolNames, options.proxy));
|
|
2522
|
+
const presentedResults = mode === "answer"
|
|
2523
|
+
? await Promise.all(fetchResults.map(async result => {
|
|
2524
|
+
if (result.error) return result;
|
|
2525
|
+
if (result.thumbnail || result.mimeType?.startsWith("image/")) {
|
|
2526
|
+
return { ...result, error: "Page answer requires textual fetched content" };
|
|
2527
|
+
}
|
|
2528
|
+
try {
|
|
2529
|
+
const answer = await answerFromPage({
|
|
2530
|
+
question: options.prompt!,
|
|
2531
|
+
pageText: result.content,
|
|
2532
|
+
sourceUrl: result.url,
|
|
2533
|
+
...(options.answerModel ? { model: options.answerModel } : {}),
|
|
2534
|
+
}, ctx, signal);
|
|
2535
|
+
return { ...result, content: answer.text };
|
|
2536
|
+
} catch (err) {
|
|
2537
|
+
return { ...result, error: `Page answer failed: ${err instanceof Error ? err.message : String(err)}` };
|
|
2538
|
+
}
|
|
2539
|
+
}))
|
|
2540
|
+
: fetchResults;
|
|
2541
|
+
const successful = presentedResults.filter((r) => !r.error).length;
|
|
2542
|
+
const totalChars = presentedResults.reduce((sum, r) => sum + r.content.length, 0);
|
|
2543
|
+
|
|
2544
|
+
const responseId = generateId();
|
|
2545
|
+
const data = {
|
|
2546
|
+
id: responseId,
|
|
2547
|
+
type: "fetch",
|
|
2548
|
+
timestamp: Date.now(),
|
|
2549
|
+
urls: stripThumbnails(fetchResults),
|
|
2550
|
+
} satisfies StoredSearchData & { type: "fetch"; urls: ExtractedContent[] };
|
|
2551
|
+
const storedContent = storeFetchResult(pi, responseId, data, authFetchProfile);
|
|
2552
|
+
|
|
2553
|
+
if (urlList.length === 1) {
|
|
2554
|
+
const result = presentedResults[0];
|
|
2555
|
+
if (result.error) {
|
|
2556
|
+
return {
|
|
2557
|
+
content: [{ type: "text", text: `Error: ${result.error}` }],
|
|
2558
|
+
details: { urls: urlList, urlCount: 1, successful: 0, error: result.error, ...(storedContent ? { responseId } : {}), prompt: params.prompt, timestamp: params.timestamp, frames: params.frames },
|
|
2559
|
+
};
|
|
2560
|
+
}
|
|
2561
|
+
|
|
2562
|
+
const fullLength = result.content.length;
|
|
2563
|
+
const slice = initialContentSlice(result.content, getMaxInlineContentChars());
|
|
2564
|
+
const truncated = slice.endOffset < fullLength;
|
|
2565
|
+
let output = slice.text;
|
|
2566
|
+
|
|
2567
|
+
if (truncated) {
|
|
2568
|
+
output += `\n\n---\nShowing ${slice.endOffset} of ${fullLength} chars, ${slice.shownBytes} of ${slice.totalBytes} bytes, and ${slice.shownLines} of ${slice.totalLines} lines. `;
|
|
2569
|
+
output += storedContent
|
|
2570
|
+
? getSearchContentEnabled
|
|
2571
|
+
? `Use ${toolNames.getSearchContent}({ responseId: "${responseId}", urlIndex: 0, offset: ${slice.endOffset} }) for the next slice.`
|
|
2572
|
+
: "Content retrieval is not registered."
|
|
2573
|
+
: "Authenticated fetch cache is off; repeat the fetch to read more.";
|
|
2574
|
+
}
|
|
2575
|
+
|
|
2576
|
+
const content: Array<TextContent | ImageContent> = [];
|
|
2577
|
+
if (result.frames?.length) {
|
|
2578
|
+
for (const frame of result.frames) {
|
|
2579
|
+
content.push({ type: "image", data: frame.data, mimeType: frame.mimeType });
|
|
2580
|
+
content.push({ type: "text", text: `Frame at ${frame.timestamp}` });
|
|
2581
|
+
}
|
|
2582
|
+
} else if (result.thumbnail) {
|
|
2583
|
+
content.push({ type: "image", data: result.thumbnail.data, mimeType: result.thumbnail.mimeType });
|
|
2584
|
+
}
|
|
2585
|
+
content.push({ type: "text", text: output });
|
|
2475
2586
|
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
:
|
|
2482
|
-
|
|
2587
|
+
const imageCount = (result.frames?.length ?? 0) + (result.thumbnail ? 1 : 0);
|
|
2588
|
+
return {
|
|
2589
|
+
content,
|
|
2590
|
+
details: {
|
|
2591
|
+
urls: urlList,
|
|
2592
|
+
urlCount: 1,
|
|
2593
|
+
successful: 1,
|
|
2594
|
+
totalChars: fullLength,
|
|
2595
|
+
title: result.title,
|
|
2596
|
+
...(storedContent ? { responseId } : {}),
|
|
2597
|
+
truncated,
|
|
2598
|
+
hasImage: imageCount > 0,
|
|
2599
|
+
imageCount,
|
|
2600
|
+
prompt: params.prompt,
|
|
2601
|
+
timestamp: params.timestamp,
|
|
2602
|
+
frames: params.frames,
|
|
2603
|
+
duration: result.duration,
|
|
2604
|
+
mode,
|
|
2605
|
+
mimeType: result.mimeType,
|
|
2606
|
+
status: result.status,
|
|
2607
|
+
totalBytes: slice.totalBytes,
|
|
2608
|
+
totalLines: slice.totalLines,
|
|
2609
|
+
shownBytes: slice.shownBytes,
|
|
2610
|
+
shownLines: slice.shownLines,
|
|
2611
|
+
},
|
|
2612
|
+
};
|
|
2483
2613
|
}
|
|
2484
2614
|
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2615
|
+
let output = "## Fetched URLs\n\n";
|
|
2616
|
+
for (const { url, title, content, error } of presentedResults) {
|
|
2617
|
+
if (error) {
|
|
2618
|
+
output += `- ${url}: Error - ${error}\n`;
|
|
2619
|
+
} else {
|
|
2620
|
+
output += `- ${title || url} (${content.length} chars)\n`;
|
|
2490
2621
|
}
|
|
2491
|
-
} else if (result.thumbnail) {
|
|
2492
|
-
content.push({ type: "image", data: result.thumbnail.data, mimeType: result.thumbnail.mimeType });
|
|
2493
2622
|
}
|
|
2494
|
-
|
|
2623
|
+
output += storedContent
|
|
2624
|
+
? getSearchContentEnabled
|
|
2625
|
+
? `\n---\nUse ${toolNames.getSearchContent}({ responseId: "${responseId}", urlIndex: 0 }) to retrieve bounded content slices.`
|
|
2626
|
+
: "\n---\nContent retrieval is not registered."
|
|
2627
|
+
: "\n---\nAuthenticated fetch cache is off; repeat the fetch to read content.";
|
|
2495
2628
|
|
|
2496
|
-
const imageCount = (result.frames?.length ?? 0) + (result.thumbnail ? 1 : 0);
|
|
2497
2629
|
return {
|
|
2498
|
-
content,
|
|
2499
|
-
details: {
|
|
2500
|
-
urls: urlList,
|
|
2501
|
-
urlCount: 1,
|
|
2502
|
-
successful: 1,
|
|
2503
|
-
totalChars: fullLength,
|
|
2504
|
-
title: result.title,
|
|
2505
|
-
...(storedContent ? { responseId } : {}),
|
|
2506
|
-
truncated,
|
|
2507
|
-
hasImage: imageCount > 0,
|
|
2508
|
-
imageCount,
|
|
2509
|
-
prompt: params.prompt,
|
|
2510
|
-
timestamp: params.timestamp,
|
|
2511
|
-
frames: params.frames,
|
|
2512
|
-
duration: result.duration,
|
|
2513
|
-
mode,
|
|
2514
|
-
mimeType: result.mimeType,
|
|
2515
|
-
status: result.status,
|
|
2516
|
-
totalBytes: slice.totalBytes,
|
|
2517
|
-
totalLines: slice.totalLines,
|
|
2518
|
-
shownBytes: slice.shownBytes,
|
|
2519
|
-
shownLines: slice.shownLines,
|
|
2520
|
-
},
|
|
2630
|
+
content: [{ type: "text", text: output }],
|
|
2631
|
+
details: { urls: urlList, urlCount: urlList.length, successful, totalChars, ...(storedContent ? { responseId } : {}) },
|
|
2521
2632
|
};
|
|
2522
|
-
}
|
|
2523
|
-
|
|
2524
|
-
// Multi-URL: existing behavior (summary + responseId)
|
|
2525
|
-
let output = "## Fetched URLs\n\n";
|
|
2526
|
-
for (const { url, title, content, error } of presentedResults) {
|
|
2527
|
-
if (error) {
|
|
2528
|
-
output += `- ${url}: Error - ${error}\n`;
|
|
2529
|
-
} else {
|
|
2530
|
-
output += `- ${title || url} (${content.length} chars)\n`;
|
|
2531
|
-
}
|
|
2532
|
-
}
|
|
2533
|
-
output += storedContent
|
|
2534
|
-
? getSearchContentEnabled
|
|
2535
|
-
? `\n---\nUse ${toolNames.getSearchContent}({ responseId: "${responseId}", urlIndex: 0 }) to retrieve bounded content slices.`
|
|
2536
|
-
: "\n---\nContent retrieval is not registered."
|
|
2537
|
-
: "\n---\nAuthenticated fetch cache is off; repeat the fetch to read content.";
|
|
2538
|
-
|
|
2539
|
-
return {
|
|
2540
|
-
content: [{ type: "text", text: output }],
|
|
2541
|
-
details: { urls: urlList, urlCount: urlList.length, successful, totalChars, ...(storedContent ? { responseId } : {}) },
|
|
2542
|
-
};
|
|
2633
|
+
});
|
|
2543
2634
|
},
|
|
2544
2635
|
|
|
2545
2636
|
renderCall(args, theme) {
|
|
@@ -2689,24 +2780,17 @@ export default function (pi: ExtensionAPI) {
|
|
|
2689
2780
|
queryIndex: Type.Optional(Type.Integer({ minimum: 0, description: "Get content for query at index" })),
|
|
2690
2781
|
url: Type.Optional(Type.String({ description: "Get content for this URL" })),
|
|
2691
2782
|
urlIndex: Type.Optional(Type.Integer({ minimum: 0, description: "Get content for URL at index" })),
|
|
2692
|
-
offset: Type.Optional(Type.Integer({ minimum: 0, description: "Character offset for fetched URL content slices (default 0).
|
|
2693
|
-
limit: Type.Optional(Type.Integer({ minimum: 1, maximum: maxInlineContentChars, description: "Maximum characters to return for fetched URL content slices (default and max are set by maxInlineContentChars).
|
|
2783
|
+
offset: Type.Optional(Type.Integer({ minimum: 0, description: "Character offset for fetched URL content slices (default 0). Ignored when findText is supplied." })),
|
|
2784
|
+
limit: Type.Optional(Type.Integer({ minimum: 1, maximum: maxInlineContentChars, description: "Maximum characters to return for fetched URL content slices (default and max are set by maxInlineContentChars). Ignored when findText is supplied." })),
|
|
2694
2785
|
findText: Type.Optional(Type.Union([
|
|
2695
2786
|
Type.String({ minLength: 1, maxLength: 500 }),
|
|
2696
2787
|
Type.Array(Type.String({ minLength: 1, maxLength: 500 }), { minItems: 1, maxItems: 10 }),
|
|
2697
|
-
], { description: "Text or texts to find in the selected stored content.
|
|
2788
|
+
], { description: "Text or texts to find in the selected stored content. When supplied, offset and limit are ignored." })),
|
|
2698
2789
|
findMode: Type.Optional(StringEnum(["exact", "case-insensitive", "fuzzy"], { description: "Matching mode for findText (default: case-insensitive). Requires findText." })),
|
|
2699
2790
|
}),
|
|
2700
2791
|
|
|
2701
|
-
async execute(_toolCallId,
|
|
2702
|
-
|
|
2703
|
-
const offset = formatInputValue(params.offset);
|
|
2704
|
-
const limit = formatInputValue(params.limit);
|
|
2705
|
-
return {
|
|
2706
|
-
content: [{ type: "text", text: `findText cannot be combined with offset or limit. Received offset=${offset}, limit=${limit}; omit offset and limit when using findText.` }],
|
|
2707
|
-
details: { error: "Incompatible find options" },
|
|
2708
|
-
};
|
|
2709
|
-
}
|
|
2792
|
+
async execute(_toolCallId, rawParams): Promise<AgentToolResult<Record<string, unknown>>> {
|
|
2793
|
+
const params = normalizeGetSearchContentParams(rawParams);
|
|
2710
2794
|
if (params.findMode !== undefined && params.findText === undefined) {
|
|
2711
2795
|
return {
|
|
2712
2796
|
content: [{ type: "text", text: `findMode ${formatInputValue(params.findMode)} requires findText; provide findText or omit findMode.` }],
|
|
@@ -2730,6 +2814,22 @@ export default function (pi: ExtensionAPI) {
|
|
|
2730
2814
|
};
|
|
2731
2815
|
}
|
|
2732
2816
|
const serialized = JSON.stringify(artifact, null, 2);
|
|
2817
|
+
if (params.findText !== undefined) {
|
|
2818
|
+
try {
|
|
2819
|
+
const found = findContent(serialized, normalizeFindQueries(params.findText), params.findMode ?? "case-insensitive");
|
|
2820
|
+
const { text, ...findDetails } = found;
|
|
2821
|
+
return {
|
|
2822
|
+
content: [{ type: "text", text }],
|
|
2823
|
+
details: { responseId: artifact.id, type: "research", contentLength: serialized.length, findMode: params.findMode ?? "case-insensitive", ...findDetails },
|
|
2824
|
+
};
|
|
2825
|
+
} catch (err) {
|
|
2826
|
+
const error = err instanceof Error ? err.message : String(err);
|
|
2827
|
+
return {
|
|
2828
|
+
content: [{ type: "text", text: `Unable to find ${formatInputValue(params.findText)} in research artifact for responseId ${formatInputValue(params.responseId)}: ${error}. Check findText and use a supported findMode.` }],
|
|
2829
|
+
details: { error, responseId: params.responseId, type: "research" },
|
|
2830
|
+
};
|
|
2831
|
+
}
|
|
2832
|
+
}
|
|
2733
2833
|
const offset = params.offset ?? 0;
|
|
2734
2834
|
const limit = params.limit ?? maxInlineContentChars;
|
|
2735
2835
|
if (!Number.isInteger(offset) || offset < 0) {
|
|
@@ -2798,7 +2898,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
2798
2898
|
const fullResults = formatFullResults(queryData);
|
|
2799
2899
|
if (params.findText !== undefined) {
|
|
2800
2900
|
try {
|
|
2801
|
-
const found = findContent(fullResults, normalizeFindQueries(params.findText),
|
|
2901
|
+
const found = findContent(fullResults, normalizeFindQueries(params.findText), params.findMode ?? "case-insensitive");
|
|
2802
2902
|
const { text, ...findDetails } = found;
|
|
2803
2903
|
return {
|
|
2804
2904
|
content: [{ type: "text", text }],
|
|
@@ -2860,7 +2960,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
2860
2960
|
|
|
2861
2961
|
if (params.findText !== undefined) {
|
|
2862
2962
|
try {
|
|
2863
|
-
const found = findContent(urlData.content, normalizeFindQueries(params.findText),
|
|
2963
|
+
const found = findContent(urlData.content, normalizeFindQueries(params.findText), params.findMode ?? "case-insensitive");
|
|
2864
2964
|
const { text, ...findDetails } = found;
|
|
2865
2965
|
return {
|
|
2866
2966
|
content: [{ type: "text", text: `# ${urlData.title || urlData.url}\n\n${text}` }],
|
|
@@ -3321,14 +3421,16 @@ export default function (pi: ExtensionAPI) {
|
|
|
3321
3421
|
const cookies = await isGeminiWebAvailable();
|
|
3322
3422
|
if (!cookies) {
|
|
3323
3423
|
const diagnostic = getGeminiWebAvailabilityDiagnostic();
|
|
3424
|
+
const diagnosticDetails = getGeminiWebAvailabilityDiagnosticDetails();
|
|
3425
|
+
const attempted = formatCookieAttempts(diagnosticDetails?.attempts ?? []);
|
|
3324
3426
|
const text = diagnostic
|
|
3325
|
-
? `Gemini Web is unavailable: ${diagnostic}`
|
|
3427
|
+
? `Gemini Web is unavailable: ${diagnostic}${attempted ? ` Attempted browser profiles: ${attempted}.` : ""}`
|
|
3326
3428
|
: "Gemini Web is unavailable. Sign into gemini.google.com in a supported Chromium-based browser.";
|
|
3327
3429
|
pi.sendMessage({
|
|
3328
3430
|
customType: "google-account",
|
|
3329
3431
|
content: [{ type: "text", text }],
|
|
3330
3432
|
display: true,
|
|
3331
|
-
details: { available: false, cookieAccessAllowed: true, diagnostic },
|
|
3433
|
+
details: { available: false, cookieAccessAllowed: true, diagnostic, cookieDiagnostic: diagnosticDetails },
|
|
3332
3434
|
}, { triggerTurn: true, deliverAs: "followUp" });
|
|
3333
3435
|
return;
|
|
3334
3436
|
}
|
|
@@ -3347,6 +3449,10 @@ export default function (pi: ExtensionAPI) {
|
|
|
3347
3449
|
},
|
|
3348
3450
|
});
|
|
3349
3451
|
|
|
3452
|
+
function formatCookieAttempts(attempts: { browser: string; profile: string; status: string }[]): string {
|
|
3453
|
+
return attempts.map(({ browser, profile, status }) => `${browser}/${profile} (${status})`).join(", ");
|
|
3454
|
+
}
|
|
3455
|
+
|
|
3350
3456
|
if (isCommandEnabled(initConfig, "search")) pi.registerCommand("search", {
|
|
3351
3457
|
description: "Browse stored web search results",
|
|
3352
3458
|
handler: async (_args, ctx) => {
|