@herbertgao/pi-extensions 2026.8.5 → 2026.8.7
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 +5 -5
- package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +2 -2
- package/node_modules/@herbertgao/pi-cc-extensions/README.md +2 -2
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +19 -7
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +30 -9
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/compact-thinking.ts +272 -22
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/context.ts +74 -5
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +94 -77
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/markdown-enhance.ts +48 -6
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/message-display.ts +1 -1
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/hover.ts +14 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/interaction.ts +55 -17
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/layout.ts +41 -2
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-renderer.ts +75 -6
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/types.ts +7 -3
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/grouping.ts +64 -1
- package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
- package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +16 -0
- package/node_modules/@herbertgao/pi-subagents/README.md +30 -22
- package/node_modules/@herbertgao/pi-subagents/examples/agent-tool-description.md +5 -5
- package/node_modules/@herbertgao/pi-subagents/package.json +7 -7
- package/node_modules/@herbertgao/pi-subagents/src/agent-file-toggle.ts +7 -1
- package/node_modules/@herbertgao/pi-subagents/src/agent-manager.ts +48 -19
- package/node_modules/@herbertgao/pi-subagents/src/agent-runner.ts +22 -15
- package/node_modules/@herbertgao/pi-subagents/src/custom-agents.ts +26 -2
- package/node_modules/@herbertgao/pi-subagents/src/index.ts +219 -40
- package/node_modules/@herbertgao/pi-subagents/src/invocation-config.ts +101 -3
- package/node_modules/@herbertgao/pi-subagents/src/nested-tools.ts +18 -4
- package/node_modules/@herbertgao/pi-subagents/src/settings.ts +99 -0
- package/node_modules/@herbertgao/pi-subagents/src/types.ts +22 -3
- package/node_modules/@herbertgao/pi-subagents/src/ui/agent-widget.ts +51 -3
- package/node_modules/@herbertgao/pi-subagents/src/ui/conversation-viewer.ts +20 -2
- package/node_modules/@herbertgao/pi-subagents/src/ui/fleet-list.ts +34 -10
- package/node_modules/@herbertgao/pi-subagents/src/usage.ts +129 -1
- package/node_modules/@herbertgao/pi-subagents/src/worktree.ts +29 -5
- package/node_modules/@juicesharp/rpiv-ask-user-question/README.md +3 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/ask-user-question.ts +46 -10
- package/node_modules/@juicesharp/rpiv-ask-user-question/config.ts +25 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/configuration.md +13 -4
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/hosts.md +8 -1
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/localization.md +3 -1
- package/node_modules/@juicesharp/rpiv-ask-user-question/locales/en.json +2 -2
- package/node_modules/@juicesharp/rpiv-ask-user-question/locales/zh.json +2 -2
- package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +3 -2
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/build-questionnaire.ts +10 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/key-router.ts +3 -1
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/questionnaire-session.ts +30 -7
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/state.ts +14 -6
- package/node_modules/@juicesharp/rpiv-ask-user-question/view/dialog-builder.ts +30 -4
- package/node_modules/@juicesharp/rpiv-ask-user-question/view/tab-content-strategy.ts +26 -5
- package/node_modules/@narumitw/pi-btw/README.md +119 -103
- package/node_modules/@narumitw/pi-btw/dist/index.ts +2898 -0
- package/node_modules/@narumitw/pi-btw/dist/index.ts.map +7 -0
- package/node_modules/@narumitw/pi-btw/package.json +13 -9
- package/node_modules/@narumitw/pi-btw/src/btw.ts +40 -42
- package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +55 -10
- package/node_modules/@narumitw/pi-btw/src/main-tree-picker.ts +390 -0
- package/node_modules/@narumitw/pi-btw/src/menu.ts +78 -15
- package/node_modules/@narumitw/pi-btw/src/settings.ts +22 -2
- package/node_modules/@narumitw/pi-btw/src/transcript-pager.ts +136 -45
- package/node_modules/pi-lens/CHANGELOG.md +1004 -0
- package/node_modules/pi-lens/README.md +11 -3
- package/node_modules/pi-lens/config/ruff/core.toml +42 -0
- package/node_modules/pi-lens/dist/clients/actionable-warnings.js +130 -27
- package/node_modules/pi-lens/dist/clients/advisory-provenance.js +427 -0
- package/node_modules/pi-lens/dist/clients/agent-nudge.js +79 -16
- package/node_modules/pi-lens/dist/clients/ast-grep-client.js +9 -3
- package/node_modules/pi-lens/dist/clients/atomic-write.js +9 -3
- package/node_modules/pi-lens/dist/clients/bash-file-access.js +285 -8
- package/node_modules/pi-lens/dist/clients/biome-client.js +176 -37
- package/node_modules/pi-lens/dist/clients/blocker-freshness.js +428 -0
- package/node_modules/pi-lens/dist/clients/blocker-past-eof.js +119 -0
- package/node_modules/pi-lens/dist/clients/bootstrap.js +12 -1
- package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +12 -3
- package/node_modules/pi-lens/dist/clients/bounded-telemetry.js +192 -0
- package/node_modules/pi-lens/dist/clients/bus-events-logger.js +62 -6
- package/node_modules/pi-lens/dist/clients/bus-publish.js +11 -3
- package/node_modules/pi-lens/dist/clients/cascade-budget.js +196 -0
- package/node_modules/pi-lens/dist/clients/cascade-format.js +76 -2
- package/node_modules/pi-lens/dist/clients/cascade-types.js +9 -1
- package/node_modules/pi-lens/dist/clients/child-unref.js +54 -6
- package/node_modules/pi-lens/dist/clients/code-quality-warnings.js +76 -24
- package/node_modules/pi-lens/dist/clients/console-guard-install.js +16 -4
- package/node_modules/pi-lens/dist/clients/dead-code-client.js +249 -52
- package/node_modules/pi-lens/dist/clients/deadline-utils.js +8 -1
- package/node_modules/pi-lens/dist/clients/debug-handles.js +5 -0
- package/node_modules/pi-lens/dist/clients/degradation-ledger.js +62 -13
- package/node_modules/pi-lens/dist/clients/dependency-checker.js +43 -9
- package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +153 -37
- package/node_modules/pi-lens/dist/clients/diagnostic-line-freshness.js +298 -0
- package/node_modules/pi-lens/dist/clients/diagnostics-publish.js +10 -3
- package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +165 -11
- package/node_modules/pi-lens/dist/clients/dispatch/integration.js +325 -72
- package/node_modules/pi-lens/dist/clients/dispatch/lazy.js +7 -4
- package/node_modules/pi-lens/dist/clients/dispatch/plan.js +5 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +234 -18
- package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +187 -19
- package/node_modules/pi-lens/dist/clients/dispatch/runners/cpp-check.js +6 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/credo.js +11 -9
- package/node_modules/pi-lens/dist/clients/dispatch/runners/cue-vet.js +398 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/elixir-check.js +11 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +12 -7
- package/node_modules/pi-lens/dist/clients/dispatch/runners/go-vet.js +18 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-render.js +895 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/index.js +4 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/javac.js +16 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +81 -41
- package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +16 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +23 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +331 -55
- package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +38 -5
- package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +97 -19
- package/node_modules/pi-lens/dist/clients/dispatch/runners/spellcheck.js +14 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +20 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +22 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/swiftlint.js +10 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +18 -6
- package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +73 -12
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +488 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +84 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/lazy-installer.js +260 -27
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +943 -93
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +86 -11
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/tool-failure.js +72 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +106 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/vale.js +9 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +18 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +4 -2
- package/node_modules/pi-lens/dist/clients/disposition-publish.js +10 -3
- package/node_modules/pi-lens/dist/clients/eval-timestamp.js +17 -0
- package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +28 -5
- package/node_modules/pi-lens/dist/clients/extension-log.js +317 -3
- package/node_modules/pi-lens/dist/clients/file-kinds.js +8 -2
- package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +294 -0
- package/node_modules/pi-lens/dist/clients/finding-identity.js +88 -0
- package/node_modules/pi-lens/dist/clients/fix-worklog.js +5 -1
- package/node_modules/pi-lens/dist/clients/format-events-publish.js +39 -8
- package/node_modules/pi-lens/dist/clients/formatters-lazy.js +3 -2
- package/node_modules/pi-lens/dist/clients/formatters.js +500 -115
- package/node_modules/pi-lens/dist/clients/generation-guard.js +216 -0
- package/node_modules/pi-lens/dist/clients/git-guard.js +49 -21
- package/node_modules/pi-lens/dist/clients/gitleaks-client.js +181 -8
- package/node_modules/pi-lens/dist/clients/go-client.js +21 -39
- package/node_modules/pi-lens/dist/clients/govulncheck-client.js +219 -10
- package/node_modules/pi-lens/dist/clients/grammar-source.js +333 -10
- package/node_modules/pi-lens/dist/clients/host-ports.js +9 -1
- package/node_modules/pi-lens/dist/clients/installer/index.js +1119 -101
- package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh-session.js +58 -0
- package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh.js +715 -0
- package/node_modules/pi-lens/dist/clients/instance-reaper.js +643 -97
- package/node_modules/pi-lens/dist/clients/instance-registry.js +87 -17
- package/node_modules/pi-lens/dist/clients/jscpd-client.js +86 -15
- package/node_modules/pi-lens/dist/clients/knip-client.js +361 -24
- package/node_modules/pi-lens/dist/clients/language-policy.js +8 -2
- package/node_modules/pi-lens/dist/clients/language-profile.js +2 -0
- package/node_modules/pi-lens/dist/clients/latency-logger.js +487 -9
- package/node_modules/pi-lens/dist/clients/lazy-import.js +21 -0
- package/node_modules/pi-lens/dist/clients/ledger-bounds.js +21 -0
- package/node_modules/pi-lens/dist/clients/lens-events.js +56 -25
- package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +16 -0
- package/node_modules/pi-lens/dist/clients/live-bus-emitter.js +45 -2
- package/node_modules/pi-lens/dist/clients/lsp/aggregation.js +30 -4
- package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +160 -20
- package/node_modules/pi-lens/dist/clients/lsp/client.js +1666 -148
- package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +111 -0
- package/node_modules/pi-lens/dist/clients/lsp/document-drift.js +389 -0
- package/node_modules/pi-lens/dist/clients/lsp/index.js +2496 -171
- package/node_modules/pi-lens/dist/clients/lsp/inferred-project.js +215 -0
- package/node_modules/pi-lens/dist/clients/lsp/jvm-runtime.js +146 -14
- package/node_modules/pi-lens/dist/clients/lsp/language.js +48 -4
- package/node_modules/pi-lens/dist/clients/lsp/server.js +517 -69
- package/node_modules/pi-lens/dist/clients/lsp/spawn-history.js +22 -0
- package/node_modules/pi-lens/dist/clients/lsp/sync-kind.js +43 -0
- package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +172 -0
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/classification.js +21 -5
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/strategies.js +61 -3
- package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +422 -28
- package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-session.js +30 -0
- package/node_modules/pi-lens/dist/clients/lsp/workspace-sweep-hold.js +175 -0
- package/node_modules/pi-lens/dist/clients/lsp-lazy.js +3 -2
- package/node_modules/pi-lens/dist/clients/mcp/analyze.js +4 -0
- package/node_modules/pi-lens/dist/clients/mcp/session.js +39 -18
- package/node_modules/pi-lens/dist/clients/model-provider.js +53 -0
- package/node_modules/pi-lens/dist/clients/module-report.js +8 -0
- package/node_modules/pi-lens/dist/clients/opengrep-client.js +15 -1
- package/node_modules/pi-lens/dist/clients/package-manager.js +170 -14
- package/node_modules/pi-lens/dist/clients/path-attribution-telemetry.js +27 -0
- package/node_modules/pi-lens/dist/clients/path-utils.js +160 -0
- package/node_modules/pi-lens/dist/clients/pipeline.js +178 -30
- package/node_modules/pi-lens/dist/clients/post-autofix-notice.js +37 -0
- package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +17 -3
- package/node_modules/pi-lens/dist/clients/project-diagnostics/extractors.js +89 -22
- package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +85 -15
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/gitleaks.js +15 -3
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +23 -2
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/trivy.js +50 -2
- package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +5 -0
- package/node_modules/pi-lens/dist/clients/project-lens-config.js +3 -0
- package/node_modules/pi-lens/dist/clients/project-snapshot.js +299 -0
- package/node_modules/pi-lens/dist/clients/quiet-window-config.js +47 -0
- package/node_modules/pi-lens/dist/clients/quiet-window.js +11 -25
- package/node_modules/pi-lens/dist/clients/read-guard-logger.js +1 -1
- package/node_modules/pi-lens/dist/clients/read-guard.js +184 -10
- package/node_modules/pi-lens/dist/clients/resource-sampler.js +49 -17
- package/node_modules/pi-lens/dist/clients/reverse-deps.js +50 -11
- package/node_modules/pi-lens/dist/clients/review-graph/query.js +76 -4
- package/node_modules/pi-lens/dist/clients/run-duration.js +55 -0
- package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +248 -13
- package/node_modules/pi-lens/dist/clients/runtime-context.js +112 -12
- package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +472 -61
- package/node_modules/pi-lens/dist/clients/runtime-session.js +359 -13
- package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +217 -22
- package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +269 -22
- package/node_modules/pi-lens/dist/clients/runtime-turn.js +948 -87
- package/node_modules/pi-lens/dist/clients/rust-client.js +21 -37
- package/node_modules/pi-lens/dist/clients/safe-spawn.js +220 -7
- package/node_modules/pi-lens/dist/clients/scratch-tree-policy.js +161 -0
- package/node_modules/pi-lens/dist/clients/search-read-registration.js +34 -6
- package/node_modules/pi-lens/dist/clients/security-scan-client.js +224 -8
- package/node_modules/pi-lens/dist/clients/sg-runner.js +249 -37
- package/node_modules/pi-lens/dist/clients/single-flight.js +158 -0
- package/node_modules/pi-lens/dist/clients/smells-rollup.js +18 -11
- package/node_modules/pi-lens/dist/clients/stale-marker.js +17 -0
- package/node_modules/pi-lens/dist/clients/startup-timing.js +26 -2
- package/node_modules/pi-lens/dist/clients/test-runner-client.js +574 -32
- package/node_modules/pi-lens/dist/clients/tool-event.js +56 -5
- package/node_modules/pi-lens/dist/clients/tool-policy.js +127 -20
- package/node_modules/pi-lens/dist/clients/tool-set-policy.js +76 -0
- package/node_modules/pi-lens/dist/clients/tree-sitter-cache.js +75 -1
- package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +769 -64
- package/node_modules/pi-lens/dist/clients/tree-sitter-shared.js +11 -0
- package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +90 -0
- package/node_modules/pi-lens/dist/clients/trivy-client.js +19 -1
- package/node_modules/pi-lens/dist/clients/warm-attach.js +17 -0
- package/node_modules/pi-lens/dist/clients/widget-state.js +336 -36
- package/node_modules/pi-lens/dist/clients/word-index.js +305 -33
- package/node_modules/pi-lens/dist/clients/zizmor-config.js +214 -14
- package/node_modules/pi-lens/dist/index.js +64677 -49484
- package/node_modules/pi-lens/dist/mcp/server.js +8 -2
- package/node_modules/pi-lens/dist/tools/activate-tools.js +17 -5
- package/node_modules/pi-lens/dist/tools/ast-grep-replace.js +9 -4
- package/node_modules/pi-lens/dist/tools/lens-diagnostic-mark.js +5 -2
- package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +469 -56
- package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +190 -46
- package/node_modules/pi-lens/dist/tools/lsp-navigation.js +46 -7
- package/node_modules/pi-lens/dist/tools/symbol-search.js +1 -1
- package/node_modules/pi-lens/docs/agent-guide.md +44 -14
- package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +518 -501
- package/node_modules/pi-lens/docs/dispositions.md +21 -0
- package/node_modules/pi-lens/docs/features.md +33 -6
- package/node_modules/pi-lens/docs/globalconfig.md +14 -0
- package/node_modules/pi-lens/docs/language-coverage.md +71 -5
- package/node_modules/pi-lens/docs/mcp.md +2 -2
- package/node_modules/pi-lens/docs/servercapabilities.md +4 -1
- package/node_modules/pi-lens/docs/settings.md +25 -1
- package/node_modules/pi-lens/docs/usage.md +24 -5
- package/node_modules/pi-lens/docs/word-index.md +35 -0
- package/node_modules/pi-lens/package.json +10 -6
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/no-reflect-get-js-snapshot.yml +23 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/no-reflect-get-snapshot.yml +23 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/ts-void-zero-snapshot.yml +23 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-bare-object-param-test.yml +16 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-chained-type-assertions-test.yml +22 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-compile-call-test.yml +29 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-conditional-empty-object-spread-js-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-conditional-empty-object-spread-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-dupe-class-members-test.yml +33 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-inner-html-js-test.yml +7 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-inner-html-test.yml +7 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-known-value-widening-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-non-null-assertion-test.yml +216 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-js-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-js-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-return-value-in-generator-test.yml +12 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-runtime-typeof-test.yml +33 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-server-bind-wildcard-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-shape-in-symbol-names-test.yml +13 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-sql-in-code-js-test.yml +5 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-sql-in-code-test.yml +5 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-laundering-test.yml +11 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-parameters-test.yml +12 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-returns-test.yml +16 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unsafe-dictionary-any-test.yml +10 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unsafe-dictionary-unknown-test.yml +8 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/redundant-unsafe-function-test.yml +35 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/require-safety-comment-for-as-unknown-as-test.yml +177 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/ts-void-zero-test.yml +1 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-await-expression-member-js.yml +13 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-await-expression-member.yml +13 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-host-path-in-win32-branch.yml +2 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-object-param.yml +60 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-chained-type-assertions.yml +66 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-compile-call.yml +63 -5
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-conditional-empty-object-spread-js.yml +21 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-conditional-empty-object-spread.yml +29 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-dupe-class-members.yml +52 -8
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-inner-html-js.yml +27 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-inner-html.yml +27 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-known-value-widening.yml +71 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-non-null-assertion.yml +316 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-raw-json-store-write.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply-js.yml +29 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply.yml +30 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get-js.yml +41 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get.yml +42 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-return-value-in-generator.yml +22 -5
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-runtime-typeof.yml +121 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-server-bind-wildcard.yml +23 -7
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-shape-in-symbol-names.yml +68 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-sql-in-code-js.yml +41 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-sql-in-code.yml +41 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-laundering.yml +32 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-parameters.yml +67 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-returns.yml +106 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unsafe-dictionary-any.yml +50 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unsafe-dictionary-unknown.yml +56 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-win32-isabsolute-for-qualification.yml +2 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/redundant-unsafe-function.yml +32 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/require-safety-comment-for-as-unknown-as.yml +184 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/ts-void-zero.yml +5 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/self-scan-baseline.json +5 -0
- package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +132 -1
- package/node_modules/pi-lens/scripts/download-grammars.js +25 -0
- package/node_modules/pi-lens/scripts/grammars.lock.json +9 -0
- package/node_modules/pi-lens/skills/pi-lens-ast-grep/SKILL.md +12 -11
- package/node_modules/pi-lens/skills/pi-lens-lsp-navigation/SKILL.md +22 -22
- package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/SKILL.md +87 -116
- package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/reference.md +170 -0
- package/node_modules/pi-lens/skills/pi-lens-write-tree-sitter-rule/SKILL.md +3 -1
- package/node_modules/pi-lens/vendor/grammars/tree-sitter-cue.wasm +0 -0
- package/node_modules/pi-mcp-adapter/CHANGELOG.md +49 -0
- package/node_modules/pi-mcp-adapter/README.md +51 -6
- package/node_modules/pi-mcp-adapter/agent-dir.ts +12 -4
- package/node_modules/pi-mcp-adapter/cli.js +188 -5
- package/node_modules/pi-mcp-adapter/commands.ts +128 -22
- package/node_modules/pi-mcp-adapter/config.ts +28 -10
- package/node_modules/pi-mcp-adapter/direct-tools.ts +23 -19
- package/node_modules/pi-mcp-adapter/index.ts +219 -32
- package/node_modules/pi-mcp-adapter/init.ts +36 -4
- package/node_modules/pi-mcp-adapter/lifecycle.ts +315 -24
- package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +39 -6
- package/node_modules/pi-mcp-adapter/mcp-bearer-store.ts +387 -0
- package/node_modules/pi-mcp-adapter/mcp-callback-server.ts +27 -3
- package/node_modules/pi-mcp-adapter/mcp-code.ts +4 -0
- package/node_modules/pi-mcp-adapter/mcp-panel.ts +42 -13
- package/node_modules/pi-mcp-adapter/mcp-setup-panel.ts +2 -1
- package/node_modules/pi-mcp-adapter/metadata-cache.ts +46 -25
- package/node_modules/pi-mcp-adapter/package-mcp-loader.ts +168 -0
- package/node_modules/pi-mcp-adapter/package.json +4 -1
- package/node_modules/pi-mcp-adapter/proxy-modes.ts +5 -4
- package/node_modules/pi-mcp-adapter/request-headers-command.ts +330 -0
- package/node_modules/pi-mcp-adapter/search-ranking.ts +92 -22
- package/node_modules/pi-mcp-adapter/server-manager.ts +145 -2
- package/node_modules/pi-mcp-adapter/session-recovery.ts +7 -0
- package/node_modules/pi-mcp-adapter/tool-approval.ts +15 -2
- package/node_modules/pi-mcp-adapter/tool-metadata.ts +38 -18
- package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +44 -4
- package/node_modules/pi-mcp-adapter/types.ts +95 -10
- package/node_modules/pi-mcp-adapter/ui-server.ts +18 -16
- package/node_modules/pi-mcp-adapter/utils.ts +70 -0
- package/node_modules/pi-web-access/CHANGELOG.md +37 -0
- package/node_modules/pi-web-access/README.md +38 -14
- package/node_modules/pi-web-access/anysearch.ts +4 -2
- package/node_modules/pi-web-access/auth-fetch.ts +148 -0
- package/node_modules/pi-web-access/brave.ts +16 -4
- package/node_modules/pi-web-access/chrome-cookies.ts +110 -23
- package/node_modules/pi-web-access/curator-page.ts +8 -3
- package/node_modules/pi-web-access/curator-server.ts +5 -1
- package/node_modules/pi-web-access/exa.ts +18 -7
- package/node_modules/pi-web-access/extract.ts +134 -37
- package/node_modules/pi-web-access/fetch-params.ts +17 -3
- package/node_modules/pi-web-access/firecrawl.ts +172 -12
- package/node_modules/pi-web-access/gemini-search.ts +33 -7
- package/node_modules/pi-web-access/index.ts +160 -104
- package/node_modules/pi-web-access/package.json +2 -2
- package/node_modules/pi-web-access/page-query.ts +4 -2
- package/node_modules/pi-web-access/parallel-mcp.ts +249 -0
- package/node_modules/pi-web-access/parallel.ts +2 -2
- package/node_modules/pi-web-access/query-rewrite.ts +51 -0
- package/node_modules/pi-web-access/serper.ts +211 -0
- package/node_modules/pi-web-access/summary-model-scope.ts +12 -4
- package/node_modules/pi-web-access/summary-review.ts +51 -23
- package/node_modules/pi-web-access/tavily.ts +16 -4
- package/node_modules/pi-web-access/utils.ts +87 -0
- package/node_modules/pi-web-access/valyu.ts +199 -0
- package/node_modules/pi-web-access/youtube-extract.ts +2 -2
- package/package.json +13 -13
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import type { AgentToolResult, ExtensionAPI, ExtensionContext } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import { Box, Text, truncateToWidth, type KeyId } from "@earendil-works/pi-tui";
|
|
3
3
|
import { Type } from "typebox";
|
|
4
|
-
import { StringEnum,
|
|
4
|
+
import { StringEnum, type ImageContent, type TextContent } from "@earendil-works/pi-ai/compat";
|
|
5
5
|
import type { ExtractedContent, ExtractOptions } from "./extract.ts";
|
|
6
6
|
import { normalizeFetchContentParams } from "./fetch-params.ts";
|
|
7
|
+
import { resolveAuthFetchProfile, type AuthFetchProfile } from "./auth-fetch.ts";
|
|
7
8
|
import { findContent, type FindMode } from "./content-find.ts";
|
|
8
9
|
import { answerFromPage } from "./page-query.ts";
|
|
10
|
+
import { rewriteSearchQuery } from "./query-rewrite.ts";
|
|
9
11
|
import { clearCloneCache } from "./github-extract.ts";
|
|
10
12
|
import { getConfiguredSearchRouting, normalizeSearchProviderSelection, RESOLVED_SEARCH_PROVIDERS, SEARCH_PROVIDERS, search, type AttributedSearchResponse, type SearchProvider, type SearchProviderSelection, type ResolvedSearchProvider } from "./gemini-search.ts";
|
|
11
13
|
import type { SearchResult } from "./perplexity.ts";
|
|
@@ -45,11 +47,13 @@ import { isBrowserCookieAccessAllowed } from "./gemini-web-config.ts";
|
|
|
45
47
|
import { isBraveAvailable } from "./brave.ts";
|
|
46
48
|
import { isOpenAISearchAvailable } from "./openai-search.ts";
|
|
47
49
|
import { isParallelAvailable } from "./parallel.ts";
|
|
50
|
+
import { isParallelMcpAvailable } from "./parallel-mcp.ts";
|
|
48
51
|
import { isTinyFishAvailable } from "./tinyfish.ts";
|
|
49
52
|
import { isSearch1APIAvailable } from "./search1api.ts";
|
|
50
53
|
import { isSearchinfinityAvailable } from "./searchinfinity.ts";
|
|
51
54
|
import { isQueritAvailable } from "./querit.ts";
|
|
52
55
|
import { isTavilyAvailable } from "./tavily.ts";
|
|
56
|
+
import { isFirecrawlAvailable } from "./firecrawl.ts";
|
|
53
57
|
import { isJinaSearchAvailable } from "./jina-search.ts";
|
|
54
58
|
import { isSerpdiveAvailable } from "./serpdive.ts";
|
|
55
59
|
import { isKagiAvailable } from "./kagi.ts";
|
|
@@ -61,8 +65,10 @@ import { isAnySearchAvailable } from "./anysearch.ts";
|
|
|
61
65
|
import { isXaiSearchAvailable } from "./xai-search.ts";
|
|
62
66
|
import { isBrightDataAvailable } from "./brightdata.ts";
|
|
63
67
|
import { isSerpBaseAvailable } from "./serpbase.ts";
|
|
68
|
+
import { isSerperAvailable } from "./serper.ts";
|
|
69
|
+
import { isValyuAvailable } from "./valyu.ts";
|
|
64
70
|
import { buildSearchErrorPlan, type SearchErrorDetails, type SearchErrorPlan } from "./render-search-error.ts";
|
|
65
|
-
import { findModelWithProviderRouting, loadEnabledModelPatterns, modelMatchesEnabledPatterns } from "./summary-model-scope.ts";
|
|
71
|
+
import { findModelWithProviderRouting, loadEnabledModelPatterns, modelMatchesEnabledPatterns, splitThinkingSuffix } from "./summary-model-scope.ts";
|
|
66
72
|
import {
|
|
67
73
|
buildResearchArtifact,
|
|
68
74
|
withClaimAssessment,
|
|
@@ -115,7 +121,9 @@ interface WebSearchConfig {
|
|
|
115
121
|
kagiApiKey?: unknown;
|
|
116
122
|
ollamaApiKey?: unknown;
|
|
117
123
|
serpbaseApiKey?: unknown;
|
|
124
|
+
serperApiKey?: unknown;
|
|
118
125
|
tinyfishApiKey?: unknown;
|
|
126
|
+
valyuApiKey?: unknown;
|
|
119
127
|
xaiApiKey?: unknown;
|
|
120
128
|
provider?: unknown;
|
|
121
129
|
searchProvider?: unknown;
|
|
@@ -149,11 +157,13 @@ interface ProviderAvailability {
|
|
|
149
157
|
openai: boolean;
|
|
150
158
|
brave: boolean;
|
|
151
159
|
parallel: boolean;
|
|
160
|
+
"parallel-mcp": boolean;
|
|
152
161
|
tinyfish: boolean;
|
|
153
162
|
search1api: boolean;
|
|
154
163
|
searchinfinity: boolean;
|
|
155
164
|
querit: boolean;
|
|
156
165
|
tavily: boolean;
|
|
166
|
+
firecrawl: boolean;
|
|
157
167
|
jina: boolean;
|
|
158
168
|
serpdive: boolean;
|
|
159
169
|
searxng: boolean;
|
|
@@ -168,6 +178,8 @@ interface ProviderAvailability {
|
|
|
168
178
|
xai: boolean;
|
|
169
179
|
brightdata: boolean;
|
|
170
180
|
serpbase: boolean;
|
|
181
|
+
serper: boolean;
|
|
182
|
+
valyu: boolean;
|
|
171
183
|
}
|
|
172
184
|
|
|
173
185
|
type WebSearchWorkflow = "none" | "summary-review" | "auto-summary";
|
|
@@ -219,8 +231,6 @@ type ToolNames = {
|
|
|
219
231
|
getSearchContent: string;
|
|
220
232
|
};
|
|
221
233
|
|
|
222
|
-
type ProviderHeaders = Record<string, string | null>;
|
|
223
|
-
|
|
224
234
|
const DEFAULT_TOOL_NAMES: ToolNames = {
|
|
225
235
|
webSearch: "web_search",
|
|
226
236
|
sourceCheck: "source_check",
|
|
@@ -379,11 +389,13 @@ async function getProviderAvailability(ctx: ExtensionContext): Promise<ProviderA
|
|
|
379
389
|
openai: await isOpenAISearchAvailable(ctx),
|
|
380
390
|
brave: isBraveAvailable(),
|
|
381
391
|
parallel: isParallelAvailable(),
|
|
392
|
+
"parallel-mcp": isParallelMcpAvailable(),
|
|
382
393
|
tinyfish: isTinyFishAvailable(),
|
|
383
394
|
search1api: isSearch1APIAvailable(),
|
|
384
395
|
searchinfinity: isSearchinfinityAvailable(),
|
|
385
396
|
querit: isQueritAvailable(),
|
|
386
397
|
tavily: isTavilyAvailable(),
|
|
398
|
+
firecrawl: isFirecrawlAvailable(),
|
|
387
399
|
jina: isJinaSearchAvailable(),
|
|
388
400
|
serpdive: isSerpdiveAvailable(),
|
|
389
401
|
kagi: isKagiAvailable(),
|
|
@@ -398,10 +410,12 @@ async function getProviderAvailability(ctx: ExtensionContext): Promise<ProviderA
|
|
|
398
410
|
xai: await isXaiSearchAvailable(ctx),
|
|
399
411
|
brightdata: isBrightDataAvailable(),
|
|
400
412
|
serpbase: isSerpBaseAvailable(),
|
|
413
|
+
serper: isSerperAvailable(),
|
|
414
|
+
valyu: isValyuAvailable(),
|
|
401
415
|
};
|
|
402
416
|
return {
|
|
403
|
-
// DuckDuckGo, AnySearch, xAI, Bright Data, and
|
|
404
|
-
all: Object.entries(providers).some(([provider, available]) => provider !== "duckduckgo" && provider !== "anysearch" && provider !== "xai" && provider !== "brightdata" && provider !== "serpbase" && provider !== "gemini" && available) || geminiApiAvail,
|
|
417
|
+
// Parallel MCP, DuckDuckGo, AnySearch, xAI, Bright Data, SerpBase, Serper, and Valyu are explicit-only, so they never make `all` eligible.
|
|
418
|
+
all: Object.entries(providers).some(([provider, available]) => provider !== "parallel-mcp" && provider !== "duckduckgo" && provider !== "anysearch" && provider !== "xai" && provider !== "brightdata" && provider !== "serpbase" && provider !== "serper" && provider !== "valyu" && provider !== "gemini" && available) || geminiApiAvail,
|
|
405
419
|
...providers,
|
|
406
420
|
};
|
|
407
421
|
}
|
|
@@ -441,6 +455,7 @@ function firstAvailableProvider(available: ProviderAvailability, preferOpenAI: b
|
|
|
441
455
|
if (available.searchinfinity) return "searchinfinity";
|
|
442
456
|
if (available.querit) return "querit";
|
|
443
457
|
if (available.tavily) return "tavily";
|
|
458
|
+
if (available.firecrawl) return "firecrawl";
|
|
444
459
|
if (available.jina) return "jina";
|
|
445
460
|
if (available.serpdive) return "serpdive";
|
|
446
461
|
if (available.kagi) return "kagi";
|
|
@@ -496,6 +511,9 @@ function resolveProvider(
|
|
|
496
511
|
if (provider === "tavily" && !available.tavily) {
|
|
497
512
|
return firstAvailableProvider(available, preferOpenAI, "tavily");
|
|
498
513
|
}
|
|
514
|
+
if (provider === "firecrawl" && !available.firecrawl) {
|
|
515
|
+
return firstAvailableProvider(available, preferOpenAI, "firecrawl");
|
|
516
|
+
}
|
|
499
517
|
if (provider === "jina" && !available.jina) {
|
|
500
518
|
return firstAvailableProvider(available, preferOpenAI, "jina");
|
|
501
519
|
}
|
|
@@ -566,8 +584,8 @@ interface PendingCurate {
|
|
|
566
584
|
const DEFAULT_MAX_INLINE_CONTENT_CHARS = 30_000;
|
|
567
585
|
const MAX_INLINE_CONTENT_CHARS = 200_000;
|
|
568
586
|
|
|
569
|
-
function getMaxInlineContentChars(): number {
|
|
570
|
-
const value =
|
|
587
|
+
function getMaxInlineContentChars(config = loadConfig()): number {
|
|
588
|
+
const value = config.maxInlineContentChars;
|
|
571
589
|
if (typeof value !== "number" || !Number.isFinite(value) || !Number.isInteger(value) || value <= 0) {
|
|
572
590
|
return DEFAULT_MAX_INLINE_CONTENT_CHARS;
|
|
573
591
|
}
|
|
@@ -578,6 +596,12 @@ function stripThumbnails(results: ExtractedContent[]): ExtractedContent[] {
|
|
|
578
596
|
return results.map(({ thumbnail, frames, ...rest }) => rest);
|
|
579
597
|
}
|
|
580
598
|
|
|
599
|
+
function storeFetchResult(pi: { appendEntry(type: string, data: unknown): void }, responseId: string, data: StoredSearchData & { type: "fetch"; urls: ExtractedContent[] }, authProfile?: AuthFetchProfile): boolean {
|
|
600
|
+
if (authProfile?.cache === "off") return false;
|
|
601
|
+
pi.appendEntry("web-search-results", storeFetchedContentResult(responseId, data));
|
|
602
|
+
return true;
|
|
603
|
+
}
|
|
604
|
+
|
|
581
605
|
function initialContentSlice(content: string, maxChars: number): {
|
|
582
606
|
text: string;
|
|
583
607
|
endOffset: number;
|
|
@@ -608,6 +632,17 @@ function normalizeFindQueries(value: string | string[]): string[] {
|
|
|
608
632
|
return queries;
|
|
609
633
|
}
|
|
610
634
|
|
|
635
|
+
function formatInputValue(value: unknown): string {
|
|
636
|
+
if (typeof value === "string") return JSON.stringify(value);
|
|
637
|
+
if (typeof value === "number") return Number.isNaN(value) ? "NaN" : String(value);
|
|
638
|
+
try {
|
|
639
|
+
const serialized = JSON.stringify(value);
|
|
640
|
+
return serialized === undefined ? String(value) : serialized;
|
|
641
|
+
} catch {
|
|
642
|
+
return String(value);
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
|
|
611
646
|
function formatSearchSummary(results: SearchResult[], answer: string): string {
|
|
612
647
|
if (results.length === 0) {
|
|
613
648
|
return answer ? `${answer}\n\n---\n\n**Sources:**\nNo sources returned.` : "No results found.";
|
|
@@ -949,10 +984,15 @@ export default function (pi: ExtensionAPI) {
|
|
|
949
984
|
} satisfies StoredSearchData & { type: "fetch"; urls: ExtractedContent[] };
|
|
950
985
|
pi.appendEntry("web-search-results", storeFetchedContentResult(fetchId, data));
|
|
951
986
|
const ok = fetched.filter(f => !f.error).length;
|
|
987
|
+
const availability = ok === fetched.length
|
|
988
|
+
? "Full page content now available."
|
|
989
|
+
: ok > 0
|
|
990
|
+
? "Partial page content now available."
|
|
991
|
+
: "No page content was fetched. Stored fetch diagnostics are available.";
|
|
952
992
|
pi.sendMessage(
|
|
953
993
|
{
|
|
954
994
|
customType: "web-search-content-ready",
|
|
955
|
-
content: `Content fetched for ${ok}/${fetched.length} URLs [${fetchId}].
|
|
995
|
+
content: `Content fetched for ${ok}/${fetched.length} URLs [${fetchId}]. ${availability}`,
|
|
956
996
|
display: true,
|
|
957
997
|
},
|
|
958
998
|
{ triggerTurn: true },
|
|
@@ -1063,47 +1103,6 @@ export default function (pi: ExtensionAPI) {
|
|
|
1063
1103
|
};
|
|
1064
1104
|
}
|
|
1065
1105
|
|
|
1066
|
-
async function resolveFirstAvailableModel(
|
|
1067
|
-
ctx: SummaryGenerationContext,
|
|
1068
|
-
candidates: Array<{ provider: string; id: string }>,
|
|
1069
|
-
): Promise<{ model: Model<Api>; apiKey: string; headers?: ProviderHeaders }> {
|
|
1070
|
-
const enabledModelPatterns = loadEnabledModelPatterns(ctx);
|
|
1071
|
-
for (const { provider, id } of candidates) {
|
|
1072
|
-
const model = findModelWithProviderRouting(ctx.modelRegistry, provider, id);
|
|
1073
|
-
if (!model || !modelMatchesEnabledPatterns(model, enabledModelPatterns)) continue;
|
|
1074
|
-
const auth = await ctx.modelRegistry.getApiKeyAndHeaders(model);
|
|
1075
|
-
if (auth.ok && auth.apiKey) return { model, apiKey: auth.apiKey, headers: auth.headers };
|
|
1076
|
-
}
|
|
1077
|
-
throw new Error(`No enabled model available: ${candidates.map(c => `${c.provider}/${c.id}`).join(", ")}`);
|
|
1078
|
-
}
|
|
1079
|
-
|
|
1080
|
-
async function rewriteSearchQuery(query: string, ctx: SummaryGenerationContext, signal: AbortSignal): Promise<string> {
|
|
1081
|
-
const { model, apiKey, headers } = await resolveFirstAvailableModel(ctx, [
|
|
1082
|
-
{ provider: "anthropic", id: "claude-haiku-4-5" },
|
|
1083
|
-
{ provider: "google", id: "gemini-3.6-flash" },
|
|
1084
|
-
{ provider: "openai", id: "gpt-4.1-mini" },
|
|
1085
|
-
]);
|
|
1086
|
-
const response = await complete(
|
|
1087
|
-
model,
|
|
1088
|
-
{
|
|
1089
|
-
messages: [{
|
|
1090
|
-
role: "user",
|
|
1091
|
-
content: [{ type: "text", text: `Rewrite this web search query to get better, more specific results. Add relevant year qualifiers, precise technical terms, and specificity. Return ONLY the improved query text, nothing else.\n\nQuery: ${query}` }],
|
|
1092
|
-
timestamp: Date.now(),
|
|
1093
|
-
}],
|
|
1094
|
-
},
|
|
1095
|
-
{ apiKey, headers, signal },
|
|
1096
|
-
);
|
|
1097
|
-
if (response.stopReason === "aborted") throw new Error("Aborted");
|
|
1098
|
-
const contentParts = Array.isArray(response.content) ? response.content : [];
|
|
1099
|
-
const text = contentParts
|
|
1100
|
-
.map(part => part.type === "text" ? part.text : "")
|
|
1101
|
-
.join("")
|
|
1102
|
-
.trim();
|
|
1103
|
-
if (!text) throw new Error("Rewrite returned empty response");
|
|
1104
|
-
return text;
|
|
1105
|
-
}
|
|
1106
|
-
|
|
1107
1106
|
async function generateSummaryForSelectedIndices(
|
|
1108
1107
|
selectedQueryIndices: number[],
|
|
1109
1108
|
resultsByIndex: Map<number, QueryResultData>,
|
|
@@ -1186,20 +1185,30 @@ export default function (pi: ExtensionAPI) {
|
|
|
1186
1185
|
const configuredSummaryModel = typeof config.summaryModel === "string" ? config.summaryModel.trim() : "";
|
|
1187
1186
|
const preferredDefaults = [
|
|
1188
1187
|
{ provider: "anthropic", id: "claude-haiku-4-5" },
|
|
1189
|
-
{ provider: "openai-codex", id: "gpt-5.
|
|
1188
|
+
{ provider: "openai-codex", id: "gpt-5.6-luna" },
|
|
1189
|
+
{ provider: "openai-codex", id: "gpt-5.6-terra" },
|
|
1190
|
+
{ provider: "google", id: "gemini-3.6-flash" },
|
|
1191
|
+
{ provider: "openai", id: "gpt-5-mini" },
|
|
1192
|
+
{ provider: "deepseek", id: "deepseek-v4-flash" },
|
|
1190
1193
|
];
|
|
1191
1194
|
|
|
1192
1195
|
const resolveAvailableModelValue = (selector: string): string | null => {
|
|
1193
|
-
const
|
|
1194
|
-
|
|
1196
|
+
const parsed = splitThinkingSuffix(selector);
|
|
1197
|
+
const slashIndex = parsed.value.indexOf("/");
|
|
1198
|
+
if (slashIndex <= 0 || slashIndex >= parsed.value.length - 1) return null;
|
|
1195
1199
|
const model = findModelWithProviderRouting(
|
|
1196
1200
|
summaryContext.modelRegistry,
|
|
1197
|
-
|
|
1198
|
-
|
|
1201
|
+
parsed.value.slice(0, slashIndex),
|
|
1202
|
+
parsed.value.slice(slashIndex + 1),
|
|
1199
1203
|
);
|
|
1200
1204
|
if (!model) return null;
|
|
1201
1205
|
const value = `${model.provider}/${model.id}`;
|
|
1202
|
-
|
|
1206
|
+
if (!availableValues.has(value)) return null;
|
|
1207
|
+
if (selector !== value && !seen.has(selector)) {
|
|
1208
|
+
seen.add(selector);
|
|
1209
|
+
summaryModels.push({ value: selector, label: selector });
|
|
1210
|
+
}
|
|
1211
|
+
return selector;
|
|
1203
1212
|
};
|
|
1204
1213
|
|
|
1205
1214
|
let defaultSummaryModel: string | null = null;
|
|
@@ -1636,19 +1645,19 @@ export default function (pi: ExtensionAPI) {
|
|
|
1636
1645
|
name: toolNames.webSearch,
|
|
1637
1646
|
label: "Web Search",
|
|
1638
1647
|
description:
|
|
1639
|
-
`Search the web using OpenAI, Brave, Parallel, TinyFish, Search1API, Searchinfinity, Querit, Tavily, Jina, SERPdive, Kagi, Bocha, Ollama, SearXNG, DuckDuckGo, Exa, Perplexity, Gemini, AnySearch, xAI, Bright Data, or
|
|
1648
|
+
`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, auto-selects OpenAI when suitable and available, then Exa, Brave, Parallel, TinyFish, Search1API, Searchinfinity, Querit, Tavily, Firecrawl, Jina, SERPdive, Kagi, Bocha, Ollama, Perplexity, Gemini API, or Gemini Web. When SearXNG is configured, it is preferred first for local/private search.`,
|
|
1640
1649
|
promptSnippet:
|
|
1641
1650
|
"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.",
|
|
1642
1651
|
parameters: Type.Object({
|
|
1643
1652
|
query: Type.Optional(Type.String({ description: "Single search query. For research tasks, prefer 'queries' with multiple varied angles instead." })),
|
|
1644
1653
|
queries: Type.Optional(Type.Array(Type.String(), { description: "Multiple queries searched in sequence, each returning its own synthesized answer. Prefer this for research — vary phrasing, scope, and angle across 2-4 queries to maximize coverage. Good: ['React vs Vue performance benchmarks 2026', 'React vs Vue developer experience comparison', 'React ecosystem size vs Vue ecosystem']. Bad: ['React vs Vue', 'React vs Vue comparison', 'React vs Vue review'] (too similar, redundant results)." })),
|
|
1645
|
-
numResults: Type.Optional(Type.
|
|
1654
|
+
numResults: Type.Optional(Type.Integer({ minimum: 1, maximum: 20, description: "Results per query (default: 5, max: 20)" })),
|
|
1646
1655
|
includeContent: Type.Optional(Type.Boolean({ description: "Fetch full page content (async)" })),
|
|
1647
1656
|
recencyFilter: Type.Optional(
|
|
1648
1657
|
StringEnum(["day", "week", "month", "year"], { description: "Filter by recency" }),
|
|
1649
1658
|
),
|
|
1650
1659
|
domainFilter: Type.Optional(Type.Array(Type.String(), { description: "Limit to domains (prefix with - to exclude)" })),
|
|
1651
|
-
provider: Type.Optional(searchProviderSchema("Search provider or non-empty list of providers to search simultaneously; use all to search every eligible provider except DuckDuckGo, AnySearch, xAI, Bright Data, and
|
|
1660
|
+
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, Serper, and Valyu, omit this field to use the configured provider, or use auto when none is configured")),
|
|
1652
1661
|
workflow: Type.Optional(
|
|
1653
1662
|
StringEnum(["none", "summary-review", "auto-summary"], {
|
|
1654
1663
|
description: "Search workflow mode: none = no curator, summary-review = open curator with auto summary draft (default), auto-summary = generate summary without opening curator",
|
|
@@ -2212,11 +2221,11 @@ export default function (pi: ExtensionAPI) {
|
|
|
2212
2221
|
parameters: Type.Object({
|
|
2213
2222
|
claim: Type.String({ description: "The assertion to check against web sources." }),
|
|
2214
2223
|
queries: Type.Optional(Type.Array(Type.String(), { description: "Search queries (default: the claim)." })),
|
|
2215
|
-
numResults: Type.Optional(Type.
|
|
2224
|
+
numResults: Type.Optional(Type.Integer({ minimum: 1, maximum: 20, description: "Results per query (default: 5, max: 20)." })),
|
|
2216
2225
|
fetchContent: Type.Optional(Type.Boolean({ description: "Fetch up to 5 result pages for exact passage extraction." })),
|
|
2217
2226
|
recencyFilter: Type.Optional(StringEnum(["day", "week", "month", "year"], { description: "Filter by recency." })),
|
|
2218
2227
|
domainFilter: Type.Optional(Type.Array(Type.String(), { description: "Limit to domains; prefix with - to exclude." })),
|
|
2219
|
-
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, and
|
|
2228
|
+
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, Serper, and Valyu")),
|
|
2220
2229
|
}),
|
|
2221
2230
|
async execute(_callId, params, signal, _onUpdate, ctx) {
|
|
2222
2231
|
const claim = typeof params.claim === "string" ? params.claim.trim() : "";
|
|
@@ -2330,6 +2339,9 @@ export default function (pi: ExtensionAPI) {
|
|
|
2330
2339
|
model: Type.Optional(Type.String({
|
|
2331
2340
|
description: "Override the Gemini model for video/YouTube analysis (e.g. 'gemini-3.6-flash'). Defaults to config or gemini-3.6-flash.",
|
|
2332
2341
|
})),
|
|
2342
|
+
auth: Type.Optional(Type.Union([Type.String(), Type.Boolean()], {
|
|
2343
|
+
description: "Opt into an authFetch profile for local browser-cookie fetching. Use a profile name, or true only when exactly one profile exists.",
|
|
2344
|
+
})),
|
|
2333
2345
|
}),
|
|
2334
2346
|
|
|
2335
2347
|
async execute(_toolCallId, params, signal, onUpdate, ctx): Promise<AgentToolResult<Record<string, unknown>>> {
|
|
@@ -2354,6 +2366,18 @@ export default function (pi: ExtensionAPI) {
|
|
|
2354
2366
|
if (mode === "answer" && options.model) {
|
|
2355
2367
|
return { content: [{ type: "text", text: "Error: use answerModel, not model, with mode answer." }], details: { error: "model is incompatible with mode answer" } };
|
|
2356
2368
|
}
|
|
2369
|
+
if (mode === "answer" && options.auth !== undefined) {
|
|
2370
|
+
return { content: [{ type: "text", text: "Error: auth cannot be combined with mode answer." }], details: { error: "auth cannot be combined with mode answer" } };
|
|
2371
|
+
}
|
|
2372
|
+
let authFetchProfile: AuthFetchProfile | undefined;
|
|
2373
|
+
if (options.auth !== undefined) {
|
|
2374
|
+
try {
|
|
2375
|
+
authFetchProfile = resolveAuthFetchProfile(options.auth);
|
|
2376
|
+
} catch (err) {
|
|
2377
|
+
const error = err instanceof Error ? err.message : String(err);
|
|
2378
|
+
return { content: [{ type: "text", text: `Error: ${error}` }], details: { error } };
|
|
2379
|
+
}
|
|
2380
|
+
}
|
|
2357
2381
|
if (urlList.length === 0) {
|
|
2358
2382
|
return {
|
|
2359
2383
|
content: [{ type: "text", text: "Error: No URL provided." }],
|
|
@@ -2366,13 +2390,13 @@ export default function (pi: ExtensionAPI) {
|
|
|
2366
2390
|
details: { phase: "fetch", progress: 0 },
|
|
2367
2391
|
});
|
|
2368
2392
|
|
|
2369
|
-
const { answerModel: _answerModel, ...extractionOptions } = options;
|
|
2393
|
+
const { answerModel: _answerModel, auth: _auth, ...extractionOptions } = options;
|
|
2370
2394
|
const fetchOptions = mode === "answer"
|
|
2371
2395
|
? (() => {
|
|
2372
2396
|
const { prompt: _prompt, ...rest } = extractionOptions;
|
|
2373
|
-
return rest;
|
|
2397
|
+
return { ...rest, ...(authFetchProfile ? { authFetchProfile } : {}) };
|
|
2374
2398
|
})()
|
|
2375
|
-
: extractionOptions;
|
|
2399
|
+
: { ...extractionOptions, ...(authFetchProfile ? { authFetchProfile } : {}) };
|
|
2376
2400
|
const fetchResults = await fetchAllContent(urlList, signal, fetchOptions);
|
|
2377
2401
|
const presentedResults = mode === "answer"
|
|
2378
2402
|
? await Promise.all(fetchResults.map(async result => {
|
|
@@ -2396,7 +2420,6 @@ export default function (pi: ExtensionAPI) {
|
|
|
2396
2420
|
const successful = presentedResults.filter((r) => !r.error).length;
|
|
2397
2421
|
const totalChars = presentedResults.reduce((sum, r) => sum + r.content.length, 0);
|
|
2398
2422
|
|
|
2399
|
-
// ALWAYS store results (even for single URL)
|
|
2400
2423
|
const responseId = generateId();
|
|
2401
2424
|
const data = {
|
|
2402
2425
|
id: responseId,
|
|
@@ -2404,7 +2427,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
2404
2427
|
timestamp: Date.now(),
|
|
2405
2428
|
urls: stripThumbnails(fetchResults),
|
|
2406
2429
|
} satisfies StoredSearchData & { type: "fetch"; urls: ExtractedContent[] };
|
|
2407
|
-
pi
|
|
2430
|
+
const storedContent = storeFetchResult(pi, responseId, data, authFetchProfile);
|
|
2408
2431
|
|
|
2409
2432
|
// Single URL: return content directly (possibly truncated) with responseId
|
|
2410
2433
|
if (urlList.length === 1) {
|
|
@@ -2412,7 +2435,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
2412
2435
|
if (result.error) {
|
|
2413
2436
|
return {
|
|
2414
2437
|
content: [{ type: "text", text: `Error: ${result.error}` }],
|
|
2415
|
-
details: { urls: urlList, urlCount: 1, successful: 0, error: result.error, responseId, prompt: params.prompt, timestamp: params.timestamp, frames: params.frames },
|
|
2438
|
+
details: { urls: urlList, urlCount: 1, successful: 0, error: result.error, ...(storedContent ? { responseId } : {}), prompt: params.prompt, timestamp: params.timestamp, frames: params.frames },
|
|
2416
2439
|
};
|
|
2417
2440
|
}
|
|
2418
2441
|
|
|
@@ -2423,9 +2446,11 @@ export default function (pi: ExtensionAPI) {
|
|
|
2423
2446
|
|
|
2424
2447
|
if (truncated) {
|
|
2425
2448
|
output += `\n\n---\nShowing ${slice.endOffset} of ${fullLength} chars, ${slice.shownBytes} of ${slice.totalBytes} bytes, and ${slice.shownLines} of ${slice.totalLines} lines. `;
|
|
2426
|
-
output +=
|
|
2427
|
-
?
|
|
2428
|
-
|
|
2449
|
+
output += storedContent
|
|
2450
|
+
? getSearchContentEnabled
|
|
2451
|
+
? `Use ${toolNames.getSearchContent}({ responseId: "${responseId}", urlIndex: 0, offset: ${slice.endOffset} }) for the next slice.`
|
|
2452
|
+
: "Content retrieval is not registered."
|
|
2453
|
+
: "Authenticated fetch cache is off; repeat the fetch to read more.";
|
|
2429
2454
|
}
|
|
2430
2455
|
|
|
2431
2456
|
const content: Array<TextContent | ImageContent> = [];
|
|
@@ -2448,7 +2473,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
2448
2473
|
successful: 1,
|
|
2449
2474
|
totalChars: fullLength,
|
|
2450
2475
|
title: result.title,
|
|
2451
|
-
responseId,
|
|
2476
|
+
...(storedContent ? { responseId } : {}),
|
|
2452
2477
|
truncated,
|
|
2453
2478
|
hasImage: imageCount > 0,
|
|
2454
2479
|
imageCount,
|
|
@@ -2476,19 +2501,21 @@ export default function (pi: ExtensionAPI) {
|
|
|
2476
2501
|
output += `- ${title || url} (${content.length} chars)\n`;
|
|
2477
2502
|
}
|
|
2478
2503
|
}
|
|
2479
|
-
output +=
|
|
2480
|
-
?
|
|
2481
|
-
|
|
2504
|
+
output += storedContent
|
|
2505
|
+
? getSearchContentEnabled
|
|
2506
|
+
? `\n---\nUse ${toolNames.getSearchContent}({ responseId: "${responseId}", urlIndex: 0 }) to retrieve bounded content slices.`
|
|
2507
|
+
: "\n---\nContent retrieval is not registered."
|
|
2508
|
+
: "\n---\nAuthenticated fetch cache is off; repeat the fetch to read content.";
|
|
2482
2509
|
|
|
2483
2510
|
return {
|
|
2484
2511
|
content: [{ type: "text", text: output }],
|
|
2485
|
-
details: { urls: urlList, urlCount: urlList.length, successful, totalChars, responseId },
|
|
2512
|
+
details: { urls: urlList, urlCount: urlList.length, successful, totalChars, ...(storedContent ? { responseId } : {}) },
|
|
2486
2513
|
};
|
|
2487
2514
|
},
|
|
2488
2515
|
|
|
2489
2516
|
renderCall(args, theme) {
|
|
2490
2517
|
const { urlList, options } = normalizeFetchContentParams(args);
|
|
2491
|
-
const { prompt, timestamp, frames, model, mode, answerModel } = options;
|
|
2518
|
+
const { prompt, timestamp, frames, model, mode, answerModel, auth } = options;
|
|
2492
2519
|
if (urlList.length === 0) {
|
|
2493
2520
|
return new Text(theme.fg("toolTitle", theme.bold("fetch ")) + theme.fg("error", "(no URL)"), 0, 0);
|
|
2494
2521
|
}
|
|
@@ -2525,6 +2552,9 @@ export default function (pi: ExtensionAPI) {
|
|
|
2525
2552
|
if (answerModel) {
|
|
2526
2553
|
lines.push(theme.fg("dim", " answer model: ") + theme.fg("warning", answerModel));
|
|
2527
2554
|
}
|
|
2555
|
+
if (auth !== undefined) {
|
|
2556
|
+
lines.push(theme.fg("dim", " auth: ") + theme.fg("warning", auth === true ? "true" : auth));
|
|
2557
|
+
}
|
|
2528
2558
|
return new Text(lines.join("\n"), 0, 0);
|
|
2529
2559
|
},
|
|
2530
2560
|
|
|
@@ -2616,7 +2646,9 @@ export default function (pi: ExtensionAPI) {
|
|
|
2616
2646
|
},
|
|
2617
2647
|
});
|
|
2618
2648
|
|
|
2619
|
-
if (getSearchContentEnabled)
|
|
2649
|
+
if (getSearchContentEnabled) {
|
|
2650
|
+
const maxInlineContentChars = getMaxInlineContentChars(initConfig);
|
|
2651
|
+
pi.registerTool({
|
|
2620
2652
|
name: toolNames.getSearchContent,
|
|
2621
2653
|
label: "Get Search Content",
|
|
2622
2654
|
description: `Retrieve bounded content slices or find matching passages in a previous ${storedContentSources} call.`,
|
|
@@ -2625,11 +2657,11 @@ export default function (pi: ExtensionAPI) {
|
|
|
2625
2657
|
parameters: Type.Object({
|
|
2626
2658
|
responseId: Type.String({ description: `The responseId from ${storedContentSources}` }),
|
|
2627
2659
|
query: Type.Optional(Type.String({ description: searchQueryDescription })),
|
|
2628
|
-
queryIndex: Type.Optional(Type.
|
|
2660
|
+
queryIndex: Type.Optional(Type.Integer({ minimum: 0, description: "Get content for query at index" })),
|
|
2629
2661
|
url: Type.Optional(Type.String({ description: "Get content for this URL" })),
|
|
2630
|
-
urlIndex: Type.Optional(Type.
|
|
2631
|
-
offset: Type.Optional(Type.
|
|
2632
|
-
limit: Type.Optional(Type.
|
|
2662
|
+
urlIndex: Type.Optional(Type.Integer({ minimum: 0, description: "Get content for URL at index" })),
|
|
2663
|
+
offset: Type.Optional(Type.Integer({ minimum: 0, description: "Character offset for fetched URL content slices (default 0). Cannot be combined with findText." })),
|
|
2664
|
+
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). Cannot be combined with findText." })),
|
|
2633
2665
|
findText: Type.Optional(Type.Union([
|
|
2634
2666
|
Type.String({ minLength: 1, maxLength: 500 }),
|
|
2635
2667
|
Type.Array(Type.String({ minLength: 1, maxLength: 500 }), { minItems: 1, maxItems: 10 }),
|
|
@@ -2639,15 +2671,23 @@ export default function (pi: ExtensionAPI) {
|
|
|
2639
2671
|
|
|
2640
2672
|
async execute(_toolCallId, params): Promise<AgentToolResult<Record<string, unknown>>> {
|
|
2641
2673
|
if (params.findText !== undefined && (params.offset !== undefined || params.limit !== undefined)) {
|
|
2642
|
-
|
|
2674
|
+
const offset = formatInputValue(params.offset);
|
|
2675
|
+
const limit = formatInputValue(params.limit);
|
|
2676
|
+
return {
|
|
2677
|
+
content: [{ type: "text", text: `findText cannot be combined with offset or limit. Received offset=${offset}, limit=${limit}; omit offset and limit when using findText.` }],
|
|
2678
|
+
details: { error: "Incompatible find options" },
|
|
2679
|
+
};
|
|
2643
2680
|
}
|
|
2644
2681
|
if (params.findMode !== undefined && params.findText === undefined) {
|
|
2645
|
-
return {
|
|
2682
|
+
return {
|
|
2683
|
+
content: [{ type: "text", text: `findMode ${formatInputValue(params.findMode)} requires findText; provide findText or omit findMode.` }],
|
|
2684
|
+
details: { error: "findMode requires findText" },
|
|
2685
|
+
};
|
|
2646
2686
|
}
|
|
2647
2687
|
const data = getResult(params.responseId);
|
|
2648
2688
|
if (!data) {
|
|
2649
2689
|
return {
|
|
2650
|
-
content: [{ type: "text", text: `Error: No stored results for
|
|
2690
|
+
content: [{ type: "text", text: `Error: No stored results for responseId ${formatInputValue(params.responseId)}. Use a responseId returned by ${storedContentSources}.` }],
|
|
2651
2691
|
details: { error: "Not found", responseId: params.responseId },
|
|
2652
2692
|
};
|
|
2653
2693
|
}
|
|
@@ -2656,22 +2696,30 @@ export default function (pi: ExtensionAPI) {
|
|
|
2656
2696
|
const artifact = getResearchArtifact(params.responseId);
|
|
2657
2697
|
if (!artifact) {
|
|
2658
2698
|
return {
|
|
2659
|
-
content: [{ type: "text", text: `Error: artifact ${params.responseId} not found
|
|
2699
|
+
content: [{ type: "text", text: `Error: stored research artifact for responseId ${formatInputValue(params.responseId)} was not found. Use a responseId returned by ${storedContentSources}.` }],
|
|
2660
2700
|
details: { error: "Artifact not found", responseId: params.responseId },
|
|
2661
2701
|
};
|
|
2662
2702
|
}
|
|
2663
2703
|
const serialized = JSON.stringify(artifact, null, 2);
|
|
2664
|
-
const maxInlineContentChars = getMaxInlineContentChars();
|
|
2665
2704
|
const offset = params.offset ?? 0;
|
|
2666
2705
|
const limit = params.limit ?? maxInlineContentChars;
|
|
2667
2706
|
if (!Number.isInteger(offset) || offset < 0) {
|
|
2668
|
-
return {
|
|
2707
|
+
return {
|
|
2708
|
+
content: [{ type: "text", text: `Invalid offset: received ${formatInputValue(offset)} for responseId ${formatInputValue(params.responseId)}; offset must be a non-negative integer. Use 0 or a larger integer.` }],
|
|
2709
|
+
details: { error: "Invalid offset", offset },
|
|
2710
|
+
};
|
|
2669
2711
|
}
|
|
2670
2712
|
if (!Number.isInteger(limit) || limit <= 0 || limit > maxInlineContentChars) {
|
|
2671
|
-
return {
|
|
2713
|
+
return {
|
|
2714
|
+
content: [{ type: "text", text: `Invalid limit: received ${formatInputValue(limit)} for responseId ${formatInputValue(params.responseId)}; limit must be an integer from 1 to ${maxInlineContentChars}. Use a value in that range.` }],
|
|
2715
|
+
details: { error: "Invalid limit", limit, maxLimit: maxInlineContentChars },
|
|
2716
|
+
};
|
|
2672
2717
|
}
|
|
2673
2718
|
if (offset > serialized.length) {
|
|
2674
|
-
return {
|
|
2719
|
+
return {
|
|
2720
|
+
content: [{ type: "text", text: `Offset ${offset} is out of range for responseId ${formatInputValue(params.responseId)}. Received offset ${offset}; valid range is 0-${serialized.length}. Use an offset within that range.` }],
|
|
2721
|
+
details: { error: "Offset out of range", offset, contentLength: serialized.length },
|
|
2722
|
+
};
|
|
2675
2723
|
}
|
|
2676
2724
|
const endOffset = Math.min(offset + limit, serialized.length);
|
|
2677
2725
|
const artifactSlice = serialized.slice(offset, endOffset);
|
|
@@ -2690,29 +2738,30 @@ export default function (pi: ExtensionAPI) {
|
|
|
2690
2738
|
if (!queryData) {
|
|
2691
2739
|
const available = data.queries.map((q) => `"${q.query}"`).join(", ");
|
|
2692
2740
|
return {
|
|
2693
|
-
content: [{ type: "text", text: `Query
|
|
2741
|
+
content: [{ type: "text", text: `Query ${formatInputValue(params.query)} was not found for responseId ${formatInputValue(params.responseId)}. Received query=${formatInputValue(params.query)}. Available queries: ${available || "none"}. Use one of the available queries or queryIndex.` }],
|
|
2694
2742
|
details: { error: "Query not found" },
|
|
2695
2743
|
};
|
|
2696
2744
|
}
|
|
2697
2745
|
} else if (params.queryIndex !== undefined) {
|
|
2698
2746
|
queryData = data.queries[params.queryIndex];
|
|
2699
2747
|
if (!queryData) {
|
|
2748
|
+
const available = data.queries.map((q, i) => `${i}: "${q.query}"`).join(", ");
|
|
2700
2749
|
return {
|
|
2701
|
-
content: [{ type: "text", text: `
|
|
2750
|
+
content: [{ type: "text", text: `Query index ${formatInputValue(params.queryIndex)} is out of range for responseId ${formatInputValue(params.responseId)}. Received queryIndex=${formatInputValue(params.queryIndex)}; valid indexes are 0-${data.queries.length - 1}. Available queries: ${available || "none"}. Use one of the available indexes.` }],
|
|
2702
2751
|
details: { error: "Index out of range" },
|
|
2703
2752
|
};
|
|
2704
2753
|
}
|
|
2705
2754
|
} else {
|
|
2706
2755
|
const available = data.queries.map((q, i) => `${i}: "${q.query}"`).join(", ");
|
|
2707
2756
|
return {
|
|
2708
|
-
content: [{ type: "text", text: `Specify query or queryIndex. Available: ${available}
|
|
2757
|
+
content: [{ type: "text", text: `Specify query or queryIndex for responseId ${formatInputValue(params.responseId)}. Available queries: ${available || "none"}.` }],
|
|
2709
2758
|
details: { error: "No query specified" },
|
|
2710
2759
|
};
|
|
2711
2760
|
}
|
|
2712
2761
|
|
|
2713
2762
|
if (queryData.error) {
|
|
2714
2763
|
return {
|
|
2715
|
-
content: [{ type: "text", text: `Error
|
|
2764
|
+
content: [{ type: "text", text: `Error retrieving query ${formatInputValue(queryData.query)} from responseId ${formatInputValue(params.responseId)}: ${queryData.error}. Check the stored search result and retry with another query or queryIndex if needed.` }],
|
|
2716
2765
|
details: { error: queryData.error, query: queryData.query },
|
|
2717
2766
|
};
|
|
2718
2767
|
}
|
|
@@ -2728,7 +2777,10 @@ export default function (pi: ExtensionAPI) {
|
|
|
2728
2777
|
};
|
|
2729
2778
|
} catch (err) {
|
|
2730
2779
|
const error = err instanceof Error ? err.message : String(err);
|
|
2731
|
-
return {
|
|
2780
|
+
return {
|
|
2781
|
+
content: [{ type: "text", text: `Unable to find ${formatInputValue(params.findText)} in query ${formatInputValue(queryData.query)} for responseId ${formatInputValue(params.responseId)}: ${error}. Check findText and use a supported findMode.` }],
|
|
2782
|
+
details: { error, query: queryData.query },
|
|
2783
|
+
};
|
|
2732
2784
|
}
|
|
2733
2785
|
}
|
|
2734
2786
|
|
|
@@ -2748,7 +2800,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
2748
2800
|
if (!urlData) {
|
|
2749
2801
|
const available = data.urls.map((u) => u.url).join("\n ");
|
|
2750
2802
|
return {
|
|
2751
|
-
content: [{ type: "text", text: `URL not found. Available:\n ${available}
|
|
2803
|
+
content: [{ type: "text", text: `URL ${formatInputValue(params.url)} was not found for responseId ${formatInputValue(params.responseId)}. Received url=${formatInputValue(params.url)}. Available URLs:\n ${available || " none"}\nUse one of the available URLs or urlIndex.` }],
|
|
2752
2804
|
details: { error: "URL not found" },
|
|
2753
2805
|
};
|
|
2754
2806
|
}
|
|
@@ -2756,22 +2808,23 @@ export default function (pi: ExtensionAPI) {
|
|
|
2756
2808
|
selectedUrlIndex = params.urlIndex;
|
|
2757
2809
|
urlData = data.urls[selectedUrlIndex];
|
|
2758
2810
|
if (!urlData) {
|
|
2811
|
+
const available = data.urls.map((u, i) => `${i}: ${u.url}`).join("\n ");
|
|
2759
2812
|
return {
|
|
2760
|
-
content: [{ type: "text", text: `
|
|
2813
|
+
content: [{ type: "text", text: `URL index ${formatInputValue(params.urlIndex)} is out of range for responseId ${formatInputValue(params.responseId)}. Received urlIndex=${formatInputValue(params.urlIndex)}; valid indexes are 0-${data.urls.length - 1}. Available URLs:\n ${available || " none"}\nUse one of the available indexes.` }],
|
|
2761
2814
|
details: { error: "Index out of range" },
|
|
2762
2815
|
};
|
|
2763
2816
|
}
|
|
2764
2817
|
} else {
|
|
2765
2818
|
const available = data.urls.map((u, i) => `${i}: ${u.url}`).join("\n ");
|
|
2766
2819
|
return {
|
|
2767
|
-
content: [{ type: "text", text: `Specify url or urlIndex. Available:\n ${available}` }],
|
|
2820
|
+
content: [{ type: "text", text: `Specify url or urlIndex for responseId ${formatInputValue(params.responseId)}. Available URLs:\n ${available || " none"}` }],
|
|
2768
2821
|
details: { error: "No URL specified" },
|
|
2769
2822
|
};
|
|
2770
2823
|
}
|
|
2771
2824
|
|
|
2772
2825
|
if (urlData.error) {
|
|
2773
2826
|
return {
|
|
2774
|
-
content: [{ type: "text", text: `Error
|
|
2827
|
+
content: [{ type: "text", text: `Error retrieving URL ${formatInputValue(urlData.url)} from responseId ${formatInputValue(params.responseId)}: ${urlData.error}. Check the stored fetch result and retry with another URL or urlIndex if needed.` }],
|
|
2775
2828
|
details: { error: urlData.error, url: urlData.url },
|
|
2776
2829
|
};
|
|
2777
2830
|
}
|
|
@@ -2786,28 +2839,30 @@ export default function (pi: ExtensionAPI) {
|
|
|
2786
2839
|
};
|
|
2787
2840
|
} catch (err) {
|
|
2788
2841
|
const error = err instanceof Error ? err.message : String(err);
|
|
2789
|
-
return {
|
|
2842
|
+
return {
|
|
2843
|
+
content: [{ type: "text", text: `Unable to find ${formatInputValue(params.findText)} in URL ${formatInputValue(urlData.url)} for responseId ${formatInputValue(params.responseId)}: ${error}. Check findText and use a supported findMode.` }],
|
|
2844
|
+
details: { error, url: urlData.url },
|
|
2845
|
+
};
|
|
2790
2846
|
}
|
|
2791
2847
|
}
|
|
2792
2848
|
|
|
2793
|
-
const maxInlineContentChars = getMaxInlineContentChars();
|
|
2794
2849
|
const offset = params.offset ?? 0;
|
|
2795
2850
|
const limit = params.limit ?? maxInlineContentChars;
|
|
2796
2851
|
if (!Number.isInteger(offset) || offset < 0) {
|
|
2797
2852
|
return {
|
|
2798
|
-
content: [{ type: "text", text:
|
|
2853
|
+
content: [{ type: "text", text: `Invalid offset: received ${formatInputValue(offset)} for URL ${formatInputValue(urlData.url)}; offset must be a non-negative integer. Use 0 or a larger integer.` }],
|
|
2799
2854
|
details: { error: "Invalid offset", offset },
|
|
2800
2855
|
};
|
|
2801
2856
|
}
|
|
2802
2857
|
if (!Number.isInteger(limit) || limit <= 0 || limit > maxInlineContentChars) {
|
|
2803
2858
|
return {
|
|
2804
|
-
content: [{ type: "text", text: `limit must be an integer from 1 to ${maxInlineContentChars}
|
|
2859
|
+
content: [{ type: "text", text: `Invalid limit: received ${formatInputValue(limit)} for URL ${formatInputValue(urlData.url)}; limit must be an integer from 1 to ${maxInlineContentChars}. Use a value in that range.` }],
|
|
2805
2860
|
details: { error: "Invalid limit", limit, maxLimit: maxInlineContentChars },
|
|
2806
2861
|
};
|
|
2807
2862
|
}
|
|
2808
2863
|
if (offset > urlData.content.length) {
|
|
2809
2864
|
return {
|
|
2810
|
-
content: [{ type: "text", text: `
|
|
2865
|
+
content: [{ type: "text", text: `Offset ${offset} is out of range for URL ${formatInputValue(urlData.url)} in responseId ${formatInputValue(params.responseId)}. Received offset ${offset}; valid range is 0-${urlData.content.length}. Use an offset within that range.` }],
|
|
2811
2866
|
details: { error: "Offset out of range", offset, contentLength: urlData.content.length },
|
|
2812
2867
|
};
|
|
2813
2868
|
}
|
|
@@ -2839,7 +2894,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
2839
2894
|
}
|
|
2840
2895
|
|
|
2841
2896
|
return {
|
|
2842
|
-
content: [{ type: "text", text:
|
|
2897
|
+
content: [{ type: "text", text: `Invalid stored data for responseId ${formatInputValue(params.responseId)}: received type ${formatInputValue(data.type)}. Use a responseId returned by ${storedContentSources}.` }],
|
|
2843
2898
|
details: { error: "Invalid data" },
|
|
2844
2899
|
};
|
|
2845
2900
|
},
|
|
@@ -2916,6 +2971,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
2916
2971
|
return new Text(statusLine + "\n" + theme.fg("dim", preview), 0, 0);
|
|
2917
2972
|
},
|
|
2918
2973
|
});
|
|
2974
|
+
}
|
|
2919
2975
|
|
|
2920
2976
|
if (isCommandEnabled(initConfig, "websearch")) pi.registerCommand("websearch", {
|
|
2921
2977
|
description: "Open web search curator",
|