@herbertgao/pi-extensions 2026.8.4 → 2026.8.6
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 +11 -3
- package/node_modules/@herbertgao/pi-cc-extensions/README.md +11 -3
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +24 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +91 -1
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/compact-thinking.ts +7 -3
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/context.ts +74 -5
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/index.ts +7 -6
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +21 -12
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/default-mode.ts +4 -5
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/markdown-enhance.ts +53 -14
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/grouping.ts +22 -12
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/result.ts +2 -4
- package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
- package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +18 -0
- package/node_modules/@herbertgao/pi-subagents/package.json +8 -4
- package/node_modules/@herbertgao/pi-subagents/src/agent-color.ts +72 -67
- package/node_modules/@herbertgao/pi-subagents/src/agent-file-toggle.ts +255 -0
- package/node_modules/@herbertgao/pi-subagents/src/agent-manager.ts +191 -3
- package/node_modules/@herbertgao/pi-subagents/src/agent-runner.ts +20 -4
- package/node_modules/@herbertgao/pi-subagents/src/index.ts +289 -113
- package/node_modules/@herbertgao/pi-subagents/src/output-file.ts +24 -1
- package/node_modules/@herbertgao/pi-subagents/src/ui/agent-widget.ts +24 -2
- package/node_modules/@herbertgao/pi-subagents/src/ui/fleet-list.ts +15 -6
- package/node_modules/@herbertgao/pi-subagents/src/ui/schedule-menu.ts +9 -8
- package/node_modules/@herbertgao/pi-subagents/src/ui/select-item.ts +48 -0
- package/node_modules/@herbertgao/pi-subagents/src/worktree.ts +9 -5
- package/node_modules/@juicesharp/rpiv-ask-user-question/README.md +2 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/ask-user-question.ts +20 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/hosts.md +6 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/keyboard.md +7 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +2 -2
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/build-questionnaire.ts +7 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/key-router.ts +16 -5
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/questionnaire-session.ts +4 -2
- package/node_modules/@narumitw/pi-btw/README.md +32 -24
- package/node_modules/@narumitw/pi-btw/package.json +6 -6
- package/node_modules/@narumitw/pi-btw/src/btw.ts +4 -2
- package/node_modules/@narumitw/pi-btw/src/menu.ts +34 -13
- package/node_modules/@narumitw/pi-btw/src/settings.ts +22 -2
- package/node_modules/pi-lens/CHANGELOG.md +2535 -954
- package/node_modules/pi-lens/README.md +13 -0
- package/node_modules/pi-lens/dist/clients/actionable-warnings.js +73 -18
- package/node_modules/pi-lens/dist/clients/advisory-provenance.js +314 -0
- package/node_modules/pi-lens/dist/clients/agent-behavior-client.js +21 -4
- package/node_modules/pi-lens/dist/clients/agent-nudge.js +14 -7
- package/node_modules/pi-lens/dist/clients/ast-grep-client.js +68 -16
- package/node_modules/pi-lens/dist/clients/ast-grep-types.js +0 -1
- package/node_modules/pi-lens/dist/clients/ast-grep-yaml-synth.js +37 -10
- package/node_modules/pi-lens/dist/clients/atomic-write-staging.js +63 -0
- package/node_modules/pi-lens/dist/clients/atomic-write.js +114 -14
- package/node_modules/pi-lens/dist/clients/bash-file-access.js +193 -23
- package/node_modules/pi-lens/dist/clients/biome-client.js +136 -24
- package/node_modules/pi-lens/dist/clients/bootstrap.js +11 -2
- package/node_modules/pi-lens/dist/clients/bounded-cache.js +34 -0
- package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.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 +19 -4
- package/node_modules/pi-lens/dist/clients/cache/rule-cache.js +47 -5
- package/node_modules/pi-lens/dist/clients/cache-manager.js +97 -9
- package/node_modules/pi-lens/dist/clients/cache-observability.js +301 -14
- package/node_modules/pi-lens/dist/clients/call-graph.js +449 -117
- package/node_modules/pi-lens/dist/clients/cascade-format.js +57 -2
- package/node_modules/pi-lens/dist/clients/child-unref.js +85 -0
- package/node_modules/pi-lens/dist/clients/codebase-model.js +52 -23
- package/node_modules/pi-lens/dist/clients/collateral-test-role.js +40 -0
- package/node_modules/pi-lens/dist/clients/complexity-client.js +2 -1
- package/node_modules/pi-lens/dist/clients/console-guard-install.js +26 -0
- package/node_modules/pi-lens/dist/clients/cooperative-budget.js +42 -0
- package/node_modules/pi-lens/dist/clients/dead-code-client.js +137 -31
- package/node_modules/pi-lens/dist/clients/debug-handles.js +206 -0
- package/node_modules/pi-lens/dist/clients/debug-heap.js +167 -0
- package/node_modules/pi-lens/dist/clients/degradation-ledger.js +153 -0
- package/node_modules/pi-lens/dist/clients/dependency-checker.js +361 -77
- package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +65 -13
- package/node_modules/pi-lens/dist/clients/diagnostics-publish.js +18 -4
- package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +176 -29
- package/node_modules/pi-lens/dist/clients/dispatch/facts/function-facts.js +23 -7
- package/node_modules/pi-lens/dist/clients/dispatch/facts/import-facts.js +8 -18
- package/node_modules/pi-lens/dist/clients/dispatch/facts/tree-sitter-facts.js +8 -5
- package/node_modules/pi-lens/dist/clients/dispatch/indent-detect.js +35 -0
- package/node_modules/pi-lens/dist/clients/dispatch/inline-suppressions.js +17 -8
- package/node_modules/pi-lens/dist/clients/dispatch/integration.js +1172 -683
- package/node_modules/pi-lens/dist/clients/dispatch/lazy.js +14 -0
- package/node_modules/pi-lens/dist/clients/dispatch/plan.js +11 -1
- package/node_modules/pi-lens/dist/clients/dispatch/rule-id-normalize.js +50 -0
- package/node_modules/pi-lens/dist/clients/dispatch/rule-policy.js +135 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +23 -5
- package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +5 -9
- package/node_modules/pi-lens/dist/clients/dispatch/runners/detekt.js +3 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/hadolint.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-lint.js +154 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/htmlhint.js +3 -2
- package/node_modules/pi-lens/dist/clients/dispatch/runners/index.js +5 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +47 -6
- package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +4 -9
- package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +9 -5
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ruff.js +4 -8
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shellcheck.js +2 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/shfmt.js +2 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/spotbugs.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +2 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/terragrunt.js +163 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/tflint.js +37 -5
- package/node_modules/pi-lens/dist/clients/dispatch/runners/tree-sitter.js +3 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +13 -7
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +226 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +69 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/lazy-installer.js +3 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +473 -42
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +22 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +97 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/yaml-rule-parser.js +5 -4
- package/node_modules/pi-lens/dist/clients/disposition-publish.js +18 -4
- package/node_modules/pi-lens/dist/clients/durable-store.js +97 -0
- package/node_modules/pi-lens/dist/clients/eval-timestamp.js +17 -0
- package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +94 -3
- package/node_modules/pi-lens/dist/clients/extension-log.js +432 -0
- package/node_modules/pi-lens/dist/clients/extension-mode.js +73 -0
- package/node_modules/pi-lens/dist/clients/file-kinds.js +57 -0
- package/node_modules/pi-lens/dist/clients/file-role.js +18 -3
- package/node_modules/pi-lens/dist/clients/file-utils.js +56 -34
- package/node_modules/pi-lens/dist/clients/fix-worklog.js +5 -1
- package/node_modules/pi-lens/dist/clients/format-events-publish.js +51 -7
- package/node_modules/pi-lens/dist/clients/format-service.js +24 -8
- package/node_modules/pi-lens/dist/clients/formatters-lazy.js +8 -0
- package/node_modules/pi-lens/dist/clients/formatters.js +358 -61
- package/node_modules/pi-lens/dist/clients/generated-artifacts.js +148 -15
- package/node_modules/pi-lens/dist/clients/git-guard.js +678 -11
- package/node_modules/pi-lens/dist/clients/git-tracked-ignore.js +4 -0
- package/node_modules/pi-lens/dist/clients/go-client.js +23 -40
- package/node_modules/pi-lens/dist/clients/govulncheck-client.js +124 -7
- package/node_modules/pi-lens/dist/clients/grammar-source.js +12 -4
- package/node_modules/pi-lens/dist/clients/gzip-stage-write.js +21 -3
- package/node_modules/pi-lens/dist/clients/host-ports.js +31 -0
- package/node_modules/pi-lens/dist/clients/installer/index.js +395 -100
- package/node_modules/pi-lens/dist/clients/instance-reaper.js +142 -172
- package/node_modules/pi-lens/dist/clients/jscpd-client.js +27 -55
- package/node_modules/pi-lens/dist/clients/knip-client.js +58 -42
- package/node_modules/pi-lens/dist/clients/language-policy.js +14 -2
- package/node_modules/pi-lens/dist/clients/language-profile.js +13 -7
- package/node_modules/pi-lens/dist/clients/latency-logger.js +72 -1
- package/node_modules/pi-lens/dist/clients/lens-config.js +12 -1
- package/node_modules/pi-lens/dist/clients/lens-engine.js +86 -17
- package/node_modules/pi-lens/dist/clients/lens-events.js +63 -9
- package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +16 -0
- package/node_modules/pi-lens/dist/clients/lens-map.js +94 -19
- package/node_modules/pi-lens/dist/clients/live-bus-emitter.js +73 -0
- package/node_modules/pi-lens/dist/clients/log-cleanup.js +2 -1
- package/node_modules/pi-lens/dist/clients/lsp/aggregation.js +30 -4
- package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +59 -14
- package/node_modules/pi-lens/dist/clients/lsp/client.js +662 -56
- package/node_modules/pi-lens/dist/clients/lsp/config.js +13 -2
- package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +115 -0
- package/node_modules/pi-lens/dist/clients/lsp/edits.js +1012 -121
- package/node_modules/pi-lens/dist/clients/lsp/index.js +2025 -800
- package/node_modules/pi-lens/dist/clients/lsp/launch.js +32 -26
- package/node_modules/pi-lens/dist/clients/lsp/path-utils.js +1 -1
- package/node_modules/pi-lens/dist/clients/lsp/ruby-drive-dirs.js +83 -0
- package/node_modules/pi-lens/dist/clients/lsp/server.js +437 -86
- package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +96 -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 +18 -3
- package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +28 -4
- package/node_modules/pi-lens/dist/clients/lsp-lazy.js +8 -0
- package/node_modules/pi-lens/dist/clients/lsp-mutation.js +248 -0
- package/node_modules/pi-lens/dist/clients/mcp/analyze.js +127 -32
- package/node_modules/pi-lens/dist/clients/mcp/ipc.js +157 -24
- package/node_modules/pi-lens/dist/clients/mcp/session.js +235 -14
- package/node_modules/pi-lens/dist/clients/memory-sampler.js +115 -0
- package/node_modules/pi-lens/dist/clients/metrics-client.js +2 -1
- package/node_modules/pi-lens/dist/clients/metrics-history.js +2 -1
- package/node_modules/pi-lens/dist/clients/model-provider.js +53 -0
- package/node_modules/pi-lens/dist/clients/module-report-lsp.js +5 -0
- package/node_modules/pi-lens/dist/clients/module-report.js +168 -3
- package/node_modules/pi-lens/dist/clients/ndjson-logger.js +319 -118
- package/node_modules/pi-lens/dist/clients/opengrep-client.js +1 -1
- package/node_modules/pi-lens/dist/clients/partial-edit-apply.js +120 -5
- package/node_modules/pi-lens/dist/clients/path-utils.js +110 -9
- package/node_modules/pi-lens/dist/clients/pipeline.js +76 -15
- package/node_modules/pi-lens/dist/clients/print-mode.js +21 -0
- package/node_modules/pi-lens/dist/clients/project-changes.js +40 -0
- package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +3 -2
- package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +1 -1
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/call-graph-impact.js +8 -0
- 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/scanner.js +21 -1
- package/node_modules/pi-lens/dist/clients/project-lens-config.js +86 -9
- package/node_modules/pi-lens/dist/clients/project-report.js +27 -13
- package/node_modules/pi-lens/dist/clients/project-snapshot.js +175 -20
- package/node_modules/pi-lens/dist/clients/project-trust.js +181 -0
- package/node_modules/pi-lens/dist/clients/quiet-window.js +18 -4
- package/node_modules/pi-lens/dist/clients/read-bridge.js +147 -0
- package/node_modules/pi-lens/dist/clients/read-guard-logger.js +159 -1
- package/node_modules/pi-lens/dist/clients/read-guard-tool-lines.js +150 -29
- package/node_modules/pi-lens/dist/clients/read-guard.js +185 -4
- package/node_modules/pi-lens/dist/clients/resource-sampler.js +70 -84
- package/node_modules/pi-lens/dist/clients/review-graph/builder.js +1122 -221
- package/node_modules/pi-lens/dist/clients/review-graph/git-identity.js +2 -1
- package/node_modules/pi-lens/dist/clients/review-graph/import-resolvers.js +21 -10
- package/node_modules/pi-lens/dist/clients/review-graph/query.js +24 -0
- package/node_modules/pi-lens/dist/clients/review-graph/symbol-id.js +46 -0
- package/node_modules/pi-lens/dist/clients/review-graph/tsconfig-paths.js +57 -6
- package/node_modules/pi-lens/dist/clients/review-graph/workspace-modules.js +51 -3
- package/node_modules/pi-lens/dist/clients/review-graph-logger.js +30 -1
- package/node_modules/pi-lens/dist/clients/ruff-client.js +27 -44
- package/node_modules/pi-lens/dist/clients/run-duration.js +55 -0
- package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +257 -77
- package/node_modules/pi-lens/dist/clients/runtime-context.js +129 -12
- package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +242 -26
- package/node_modules/pi-lens/dist/clients/runtime-session.js +428 -117
- package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +71 -48
- package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +342 -33
- package/node_modules/pi-lens/dist/clients/runtime-turn.js +619 -93
- package/node_modules/pi-lens/dist/clients/rust-client.js +23 -38
- package/node_modules/pi-lens/dist/clients/safe-spawn.js +777 -62
- package/node_modules/pi-lens/dist/clients/security-scan-client.js +90 -6
- package/node_modules/pi-lens/dist/clients/session-state-store.js +3 -2
- package/node_modules/pi-lens/dist/clients/sg-runner.js +424 -196
- package/node_modules/pi-lens/dist/clients/slow-fs.js +2 -1
- package/node_modules/pi-lens/dist/clients/smells-rollup.js +231 -0
- package/node_modules/pi-lens/dist/clients/source-filter.js +184 -20
- package/node_modules/pi-lens/dist/clients/source-walker.js +66 -10
- package/node_modules/pi-lens/dist/clients/startup-scan.js +15 -16
- package/node_modules/pi-lens/dist/clients/startup-timing.js +7 -1
- package/node_modules/pi-lens/dist/clients/test-runner-client.js +469 -32
- package/node_modules/pi-lens/dist/clients/tool-event.js +35 -0
- package/node_modules/pi-lens/dist/clients/tool-policy.js +390 -39
- package/node_modules/pi-lens/dist/clients/tool-render.js +155 -0
- package/node_modules/pi-lens/dist/clients/tool-set-policy.js +76 -0
- package/node_modules/pi-lens/dist/clients/tree-sitter-cache.js +6 -1
- package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +419 -50
- package/node_modules/pi-lens/dist/clients/tree-sitter-logger.js +21 -0
- package/node_modules/pi-lens/dist/clients/tree-sitter-query-loader.js +7 -1
- package/node_modules/pi-lens/dist/clients/tree-sitter-shared.js +7 -2
- package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +44 -7
- package/node_modules/pi-lens/dist/clients/user-notify.js +51 -0
- package/node_modules/pi-lens/dist/clients/vanished-instance-marker.js +57 -0
- package/node_modules/pi-lens/dist/clients/warm-attach.js +50 -13
- package/node_modules/pi-lens/dist/clients/widget-state.js +300 -43
- package/node_modules/pi-lens/dist/clients/word-index.js +680 -81
- package/node_modules/pi-lens/dist/clients/workspace-topology.js +89 -6
- package/node_modules/pi-lens/dist/index.js +51785 -36118
- package/node_modules/pi-lens/dist/mcp/analyze-cli.js +182 -29
- package/node_modules/pi-lens/dist/mcp/server.js +219 -46
- 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/ast-grep-search.js +93 -27
- package/node_modules/pi-lens/dist/tools/lens-diagnostic-mark.js +5 -2
- package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +203 -38
- package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +210 -42
- package/node_modules/pi-lens/dist/tools/lsp-navigation.js +46 -3
- package/node_modules/pi-lens/dist/tools/module-report.js +9 -0
- package/node_modules/pi-lens/dist/tools/symbol-search.js +1 -1
- package/node_modules/pi-lens/docs/agent-guide.md +40 -15
- package/node_modules/pi-lens/docs/agent-tools.md +21 -10
- package/node_modules/pi-lens/docs/analysisall.md +192 -0
- package/node_modules/pi-lens/docs/api-ports-inventory.md +165 -0
- package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +14 -3
- package/node_modules/pi-lens/docs/durable-store-audit-1202.md +32 -0
- package/node_modules/pi-lens/docs/environment-variables.md +44 -0
- package/node_modules/pi-lens/docs/fable.md +27 -0
- package/node_modules/pi-lens/docs/features.md +45 -3
- package/node_modules/pi-lens/docs/globalconfig.md +56 -1
- package/node_modules/pi-lens/docs/language-coverage.md +4 -3
- package/node_modules/pi-lens/docs/lsp-capability-matrix.md +2 -2
- package/node_modules/pi-lens/docs/mcp.md +37 -4
- package/node_modules/pi-lens/docs/servercapabilities.md +3 -3
- package/node_modules/pi-lens/docs/settings.md +18 -1
- package/node_modules/pi-lens/docs/tools.md +4 -1
- package/node_modules/pi-lens/docs/usage.md +41 -5
- package/node_modules/pi-lens/docs/word-index.md +35 -0
- package/node_modules/pi-lens/package.json +10 -10
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-bare-except-test.yml +49 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-bare-host-path-in-win32-branch-test.yml +87 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-chained-type-assertions-test.yml +8 -0
- 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-nested-links-test.yml +11 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-raw-json-store-write-test.yml +17 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-js-test.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-test.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-js-test.yml +8 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-test.yml +8 -0
- 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-win32-isabsolute-for-qualification-test.yml +16 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-except.yml +3 -15
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-host-path-in-win32-branch.yml +25 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-chained-type-assertions.yml +21 -0
- 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-nested-links.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-raw-json-store-write.yml +30 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply-js.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get-js.yml +13 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get.yml +16 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-laundering.yml +27 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-win32-isabsolute-for-qualification.yml +23 -0
- package/node_modules/pi-lens/rules/tree-sitter-queries/tsx/no-nested-links.yml +4 -6
- package/node_modules/pi-lens/rules/tree-sitter-queries/typescript/duplicate-function-arg.yml +2 -2
- package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +134 -2
- package/node_modules/pi-lens/skills/pi-lens-ast-grep/SKILL.md +10 -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 +8 -114
- package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/reference.md +129 -0
- package/node_modules/pi-lens/skills/pi-lens-write-tree-sitter-rule/SKILL.md +3 -1
- package/node_modules/pi-mcp-adapter/CHANGELOG.md +38 -0
- package/node_modules/pi-mcp-adapter/README.md +38 -4
- package/node_modules/pi-mcp-adapter/agent-dir.ts +12 -4
- package/node_modules/pi-mcp-adapter/agent-plugin-loader.ts +1 -1
- package/node_modules/pi-mcp-adapter/cli.js +25 -4
- package/node_modules/pi-mcp-adapter/commands.ts +15 -7
- package/node_modules/pi-mcp-adapter/config.ts +4 -4
- package/node_modules/pi-mcp-adapter/direct-tools.ts +58 -8
- package/node_modules/pi-mcp-adapter/host-html-template.ts +0 -8
- package/node_modules/pi-mcp-adapter/index.ts +8 -3
- package/node_modules/pi-mcp-adapter/init.ts +29 -5
- package/node_modules/pi-mcp-adapter/lifecycle.ts +0 -4
- package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +1 -2
- package/node_modules/pi-mcp-adapter/mcp-auth.ts +60 -2
- package/node_modules/pi-mcp-adapter/mcp-panel.ts +45 -9
- package/node_modules/pi-mcp-adapter/mcp-script-worker.mjs +22 -20
- package/node_modules/pi-mcp-adapter/mcp-setup-panel.ts +2 -1
- package/node_modules/pi-mcp-adapter/metadata-cache.ts +37 -4
- package/node_modules/pi-mcp-adapter/npx-resolver.ts +81 -26
- package/node_modules/pi-mcp-adapter/package.json +4 -3
- package/node_modules/pi-mcp-adapter/proxy-modes.ts +108 -26
- package/node_modules/pi-mcp-adapter/request-headers-command.ts +336 -0
- package/node_modules/pi-mcp-adapter/search-ranking.ts +86 -7
- package/node_modules/pi-mcp-adapter/server-manager.ts +41 -7
- package/node_modules/pi-mcp-adapter/session-recovery.ts +8 -2
- package/node_modules/pi-mcp-adapter/tool-approval.ts +48 -7
- package/node_modules/pi-mcp-adapter/tool-metadata.ts +62 -4
- package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +138 -12
- package/node_modules/pi-mcp-adapter/types.ts +176 -27
- package/node_modules/pi-mcp-adapter/ui-server.ts +20 -1
- package/node_modules/pi-web-access/CHANGELOG.md +14 -0
- package/node_modules/pi-web-access/README.md +18 -12
- package/node_modules/pi-web-access/auth-fetch.ts +148 -0
- package/node_modules/pi-web-access/chrome-cookies.ts +110 -23
- 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 +106 -34
- 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 +18 -4
- package/node_modules/pi-web-access/index.ts +120 -48
- package/node_modules/pi-web-access/package.json +2 -2
- package/node_modules/pi-web-access/summary-review.ts +11 -5
- package/node_modules/pi-web-access/youtube-extract.ts +2 -2
- package/package.json +12 -13
- package/node_modules/pi-lens/dist/clients/ast-grep-parser.js +0 -86
- package/node_modules/pi-lens/dist/clients/lsp/interactive-install.js +0 -367
- package/node_modules/pi-lens/dist/clients/lsp/lsp-index.js +0 -10
- package/node_modules/pi-lens/dist/clients/lsp/server-strategies.js +0 -5
- package/node_modules/pi-lens/dist/clients/project-metadata.js +0 -690
- package/node_modules/pi-lens/dist/clients/source-groups.js +0 -96
- package/node_modules/pi-lens/dist/clients/startup-marker.js +0 -6
- package/node_modules/pi-lens/dist/clients/types.js +0 -11
|
@@ -4,6 +4,7 @@ import { Type } from "typebox";
|
|
|
4
4
|
import { StringEnum, complete, type Api, type ImageContent, type Model, 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";
|
|
9
10
|
import { clearCloneCache } from "./github-extract.ts";
|
|
@@ -50,6 +51,7 @@ import { isSearch1APIAvailable } from "./search1api.ts";
|
|
|
50
51
|
import { isSearchinfinityAvailable } from "./searchinfinity.ts";
|
|
51
52
|
import { isQueritAvailable } from "./querit.ts";
|
|
52
53
|
import { isTavilyAvailable } from "./tavily.ts";
|
|
54
|
+
import { isFirecrawlAvailable } from "./firecrawl.ts";
|
|
53
55
|
import { isJinaSearchAvailable } from "./jina-search.ts";
|
|
54
56
|
import { isSerpdiveAvailable } from "./serpdive.ts";
|
|
55
57
|
import { isKagiAvailable } from "./kagi.ts";
|
|
@@ -154,6 +156,7 @@ interface ProviderAvailability {
|
|
|
154
156
|
searchinfinity: boolean;
|
|
155
157
|
querit: boolean;
|
|
156
158
|
tavily: boolean;
|
|
159
|
+
firecrawl: boolean;
|
|
157
160
|
jina: boolean;
|
|
158
161
|
serpdive: boolean;
|
|
159
162
|
searxng: boolean;
|
|
@@ -384,6 +387,7 @@ async function getProviderAvailability(ctx: ExtensionContext): Promise<ProviderA
|
|
|
384
387
|
searchinfinity: isSearchinfinityAvailable(),
|
|
385
388
|
querit: isQueritAvailable(),
|
|
386
389
|
tavily: isTavilyAvailable(),
|
|
390
|
+
firecrawl: isFirecrawlAvailable(),
|
|
387
391
|
jina: isJinaSearchAvailable(),
|
|
388
392
|
serpdive: isSerpdiveAvailable(),
|
|
389
393
|
kagi: isKagiAvailable(),
|
|
@@ -441,6 +445,7 @@ function firstAvailableProvider(available: ProviderAvailability, preferOpenAI: b
|
|
|
441
445
|
if (available.searchinfinity) return "searchinfinity";
|
|
442
446
|
if (available.querit) return "querit";
|
|
443
447
|
if (available.tavily) return "tavily";
|
|
448
|
+
if (available.firecrawl) return "firecrawl";
|
|
444
449
|
if (available.jina) return "jina";
|
|
445
450
|
if (available.serpdive) return "serpdive";
|
|
446
451
|
if (available.kagi) return "kagi";
|
|
@@ -496,6 +501,9 @@ function resolveProvider(
|
|
|
496
501
|
if (provider === "tavily" && !available.tavily) {
|
|
497
502
|
return firstAvailableProvider(available, preferOpenAI, "tavily");
|
|
498
503
|
}
|
|
504
|
+
if (provider === "firecrawl" && !available.firecrawl) {
|
|
505
|
+
return firstAvailableProvider(available, preferOpenAI, "firecrawl");
|
|
506
|
+
}
|
|
499
507
|
if (provider === "jina" && !available.jina) {
|
|
500
508
|
return firstAvailableProvider(available, preferOpenAI, "jina");
|
|
501
509
|
}
|
|
@@ -566,8 +574,8 @@ interface PendingCurate {
|
|
|
566
574
|
const DEFAULT_MAX_INLINE_CONTENT_CHARS = 30_000;
|
|
567
575
|
const MAX_INLINE_CONTENT_CHARS = 200_000;
|
|
568
576
|
|
|
569
|
-
function getMaxInlineContentChars(): number {
|
|
570
|
-
const value =
|
|
577
|
+
function getMaxInlineContentChars(config = loadConfig()): number {
|
|
578
|
+
const value = config.maxInlineContentChars;
|
|
571
579
|
if (typeof value !== "number" || !Number.isFinite(value) || !Number.isInteger(value) || value <= 0) {
|
|
572
580
|
return DEFAULT_MAX_INLINE_CONTENT_CHARS;
|
|
573
581
|
}
|
|
@@ -578,6 +586,12 @@ function stripThumbnails(results: ExtractedContent[]): ExtractedContent[] {
|
|
|
578
586
|
return results.map(({ thumbnail, frames, ...rest }) => rest);
|
|
579
587
|
}
|
|
580
588
|
|
|
589
|
+
function storeFetchResult(pi: { appendEntry(type: string, data: unknown): void }, responseId: string, data: StoredSearchData & { type: "fetch"; urls: ExtractedContent[] }, authProfile?: AuthFetchProfile): boolean {
|
|
590
|
+
if (authProfile?.cache === "off") return false;
|
|
591
|
+
pi.appendEntry("web-search-results", storeFetchedContentResult(responseId, data));
|
|
592
|
+
return true;
|
|
593
|
+
}
|
|
594
|
+
|
|
581
595
|
function initialContentSlice(content: string, maxChars: number): {
|
|
582
596
|
text: string;
|
|
583
597
|
endOffset: number;
|
|
@@ -608,6 +622,17 @@ function normalizeFindQueries(value: string | string[]): string[] {
|
|
|
608
622
|
return queries;
|
|
609
623
|
}
|
|
610
624
|
|
|
625
|
+
function formatInputValue(value: unknown): string {
|
|
626
|
+
if (typeof value === "string") return JSON.stringify(value);
|
|
627
|
+
if (typeof value === "number") return Number.isNaN(value) ? "NaN" : String(value);
|
|
628
|
+
try {
|
|
629
|
+
const serialized = JSON.stringify(value);
|
|
630
|
+
return serialized === undefined ? String(value) : serialized;
|
|
631
|
+
} catch {
|
|
632
|
+
return String(value);
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
|
|
611
636
|
function formatSearchSummary(results: SearchResult[], answer: string): string {
|
|
612
637
|
if (results.length === 0) {
|
|
613
638
|
return answer ? `${answer}\n\n---\n\n**Sources:**\nNo sources returned.` : "No results found.";
|
|
@@ -1636,13 +1661,13 @@ export default function (pi: ExtensionAPI) {
|
|
|
1636
1661
|
name: toolNames.webSearch,
|
|
1637
1662
|
label: "Web Search",
|
|
1638
1663
|
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 SerpBase. Pass a provider array to search only those providers simultaneously, or use provider "all" to search every eligible provider except DuckDuckGo, AnySearch, xAI, Bright Data, and SerpBase. 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. DuckDuckGo, AnySearch, xAI, Bright Data, and SerpBase 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, Jina, SERPdive, Kagi, Bocha, Ollama, Perplexity, Gemini API, or Gemini Web. When SearXNG is configured, it is preferred first for local/private search.`,
|
|
1664
|
+
`Search the web using OpenAI, Brave, Parallel, TinyFish, Search1API, Searchinfinity, Querit, Tavily, Firecrawl, Jina, SERPdive, Kagi, Bocha, Ollama, SearXNG, DuckDuckGo, Exa, Perplexity, Gemini, AnySearch, xAI, Bright Data, or SerpBase. Pass a provider array to search only those providers simultaneously, or use provider "all" to search every eligible provider except DuckDuckGo, AnySearch, xAI, Bright Data, and SerpBase. 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. DuckDuckGo, AnySearch, xAI, Bright Data, and SerpBase 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
1665
|
promptSnippet:
|
|
1641
1666
|
"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
1667
|
parameters: Type.Object({
|
|
1643
1668
|
query: Type.Optional(Type.String({ description: "Single search query. For research tasks, prefer 'queries' with multiple varied angles instead." })),
|
|
1644
1669
|
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.
|
|
1670
|
+
numResults: Type.Optional(Type.Integer({ minimum: 1, maximum: 20, description: "Results per query (default: 5, max: 20)" })),
|
|
1646
1671
|
includeContent: Type.Optional(Type.Boolean({ description: "Fetch full page content (async)" })),
|
|
1647
1672
|
recencyFilter: Type.Optional(
|
|
1648
1673
|
StringEnum(["day", "week", "month", "year"], { description: "Filter by recency" }),
|
|
@@ -2212,7 +2237,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
2212
2237
|
parameters: Type.Object({
|
|
2213
2238
|
claim: Type.String({ description: "The assertion to check against web sources." }),
|
|
2214
2239
|
queries: Type.Optional(Type.Array(Type.String(), { description: "Search queries (default: the claim)." })),
|
|
2215
|
-
numResults: Type.Optional(Type.
|
|
2240
|
+
numResults: Type.Optional(Type.Integer({ minimum: 1, maximum: 20, description: "Results per query (default: 5, max: 20)." })),
|
|
2216
2241
|
fetchContent: Type.Optional(Type.Boolean({ description: "Fetch up to 5 result pages for exact passage extraction." })),
|
|
2217
2242
|
recencyFilter: Type.Optional(StringEnum(["day", "week", "month", "year"], { description: "Filter by recency." })),
|
|
2218
2243
|
domainFilter: Type.Optional(Type.Array(Type.String(), { description: "Limit to domains; prefix with - to exclude." })),
|
|
@@ -2330,6 +2355,9 @@ export default function (pi: ExtensionAPI) {
|
|
|
2330
2355
|
model: Type.Optional(Type.String({
|
|
2331
2356
|
description: "Override the Gemini model for video/YouTube analysis (e.g. 'gemini-3.6-flash'). Defaults to config or gemini-3.6-flash.",
|
|
2332
2357
|
})),
|
|
2358
|
+
auth: Type.Optional(Type.Union([Type.String(), Type.Boolean()], {
|
|
2359
|
+
description: "Opt into an authFetch profile for local browser-cookie fetching. Use a profile name, or true only when exactly one profile exists.",
|
|
2360
|
+
})),
|
|
2333
2361
|
}),
|
|
2334
2362
|
|
|
2335
2363
|
async execute(_toolCallId, params, signal, onUpdate, ctx): Promise<AgentToolResult<Record<string, unknown>>> {
|
|
@@ -2354,6 +2382,18 @@ export default function (pi: ExtensionAPI) {
|
|
|
2354
2382
|
if (mode === "answer" && options.model) {
|
|
2355
2383
|
return { content: [{ type: "text", text: "Error: use answerModel, not model, with mode answer." }], details: { error: "model is incompatible with mode answer" } };
|
|
2356
2384
|
}
|
|
2385
|
+
if (mode === "answer" && options.auth !== undefined) {
|
|
2386
|
+
return { content: [{ type: "text", text: "Error: auth cannot be combined with mode answer." }], details: { error: "auth cannot be combined with mode answer" } };
|
|
2387
|
+
}
|
|
2388
|
+
let authFetchProfile: AuthFetchProfile | undefined;
|
|
2389
|
+
if (options.auth !== undefined) {
|
|
2390
|
+
try {
|
|
2391
|
+
authFetchProfile = resolveAuthFetchProfile(options.auth);
|
|
2392
|
+
} catch (err) {
|
|
2393
|
+
const error = err instanceof Error ? err.message : String(err);
|
|
2394
|
+
return { content: [{ type: "text", text: `Error: ${error}` }], details: { error } };
|
|
2395
|
+
}
|
|
2396
|
+
}
|
|
2357
2397
|
if (urlList.length === 0) {
|
|
2358
2398
|
return {
|
|
2359
2399
|
content: [{ type: "text", text: "Error: No URL provided." }],
|
|
@@ -2366,13 +2406,13 @@ export default function (pi: ExtensionAPI) {
|
|
|
2366
2406
|
details: { phase: "fetch", progress: 0 },
|
|
2367
2407
|
});
|
|
2368
2408
|
|
|
2369
|
-
const { answerModel: _answerModel, ...extractionOptions } = options;
|
|
2409
|
+
const { answerModel: _answerModel, auth: _auth, ...extractionOptions } = options;
|
|
2370
2410
|
const fetchOptions = mode === "answer"
|
|
2371
2411
|
? (() => {
|
|
2372
2412
|
const { prompt: _prompt, ...rest } = extractionOptions;
|
|
2373
|
-
return rest;
|
|
2413
|
+
return { ...rest, ...(authFetchProfile ? { authFetchProfile } : {}) };
|
|
2374
2414
|
})()
|
|
2375
|
-
: extractionOptions;
|
|
2415
|
+
: { ...extractionOptions, ...(authFetchProfile ? { authFetchProfile } : {}) };
|
|
2376
2416
|
const fetchResults = await fetchAllContent(urlList, signal, fetchOptions);
|
|
2377
2417
|
const presentedResults = mode === "answer"
|
|
2378
2418
|
? await Promise.all(fetchResults.map(async result => {
|
|
@@ -2396,7 +2436,6 @@ export default function (pi: ExtensionAPI) {
|
|
|
2396
2436
|
const successful = presentedResults.filter((r) => !r.error).length;
|
|
2397
2437
|
const totalChars = presentedResults.reduce((sum, r) => sum + r.content.length, 0);
|
|
2398
2438
|
|
|
2399
|
-
// ALWAYS store results (even for single URL)
|
|
2400
2439
|
const responseId = generateId();
|
|
2401
2440
|
const data = {
|
|
2402
2441
|
id: responseId,
|
|
@@ -2404,7 +2443,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
2404
2443
|
timestamp: Date.now(),
|
|
2405
2444
|
urls: stripThumbnails(fetchResults),
|
|
2406
2445
|
} satisfies StoredSearchData & { type: "fetch"; urls: ExtractedContent[] };
|
|
2407
|
-
pi
|
|
2446
|
+
const storedContent = storeFetchResult(pi, responseId, data, authFetchProfile);
|
|
2408
2447
|
|
|
2409
2448
|
// Single URL: return content directly (possibly truncated) with responseId
|
|
2410
2449
|
if (urlList.length === 1) {
|
|
@@ -2412,7 +2451,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
2412
2451
|
if (result.error) {
|
|
2413
2452
|
return {
|
|
2414
2453
|
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 },
|
|
2454
|
+
details: { urls: urlList, urlCount: 1, successful: 0, error: result.error, ...(storedContent ? { responseId } : {}), prompt: params.prompt, timestamp: params.timestamp, frames: params.frames },
|
|
2416
2455
|
};
|
|
2417
2456
|
}
|
|
2418
2457
|
|
|
@@ -2423,9 +2462,11 @@ export default function (pi: ExtensionAPI) {
|
|
|
2423
2462
|
|
|
2424
2463
|
if (truncated) {
|
|
2425
2464
|
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
|
-
|
|
2465
|
+
output += storedContent
|
|
2466
|
+
? getSearchContentEnabled
|
|
2467
|
+
? `Use ${toolNames.getSearchContent}({ responseId: "${responseId}", urlIndex: 0, offset: ${slice.endOffset} }) for the next slice.`
|
|
2468
|
+
: "Content retrieval is not registered."
|
|
2469
|
+
: "Authenticated fetch cache is off; repeat the fetch to read more.";
|
|
2429
2470
|
}
|
|
2430
2471
|
|
|
2431
2472
|
const content: Array<TextContent | ImageContent> = [];
|
|
@@ -2448,7 +2489,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
2448
2489
|
successful: 1,
|
|
2449
2490
|
totalChars: fullLength,
|
|
2450
2491
|
title: result.title,
|
|
2451
|
-
responseId,
|
|
2492
|
+
...(storedContent ? { responseId } : {}),
|
|
2452
2493
|
truncated,
|
|
2453
2494
|
hasImage: imageCount > 0,
|
|
2454
2495
|
imageCount,
|
|
@@ -2476,19 +2517,21 @@ export default function (pi: ExtensionAPI) {
|
|
|
2476
2517
|
output += `- ${title || url} (${content.length} chars)\n`;
|
|
2477
2518
|
}
|
|
2478
2519
|
}
|
|
2479
|
-
output +=
|
|
2480
|
-
?
|
|
2481
|
-
|
|
2520
|
+
output += storedContent
|
|
2521
|
+
? getSearchContentEnabled
|
|
2522
|
+
? `\n---\nUse ${toolNames.getSearchContent}({ responseId: "${responseId}", urlIndex: 0 }) to retrieve bounded content slices.`
|
|
2523
|
+
: "\n---\nContent retrieval is not registered."
|
|
2524
|
+
: "\n---\nAuthenticated fetch cache is off; repeat the fetch to read content.";
|
|
2482
2525
|
|
|
2483
2526
|
return {
|
|
2484
2527
|
content: [{ type: "text", text: output }],
|
|
2485
|
-
details: { urls: urlList, urlCount: urlList.length, successful, totalChars, responseId },
|
|
2528
|
+
details: { urls: urlList, urlCount: urlList.length, successful, totalChars, ...(storedContent ? { responseId } : {}) },
|
|
2486
2529
|
};
|
|
2487
2530
|
},
|
|
2488
2531
|
|
|
2489
2532
|
renderCall(args, theme) {
|
|
2490
2533
|
const { urlList, options } = normalizeFetchContentParams(args);
|
|
2491
|
-
const { prompt, timestamp, frames, model, mode, answerModel } = options;
|
|
2534
|
+
const { prompt, timestamp, frames, model, mode, answerModel, auth } = options;
|
|
2492
2535
|
if (urlList.length === 0) {
|
|
2493
2536
|
return new Text(theme.fg("toolTitle", theme.bold("fetch ")) + theme.fg("error", "(no URL)"), 0, 0);
|
|
2494
2537
|
}
|
|
@@ -2525,6 +2568,9 @@ export default function (pi: ExtensionAPI) {
|
|
|
2525
2568
|
if (answerModel) {
|
|
2526
2569
|
lines.push(theme.fg("dim", " answer model: ") + theme.fg("warning", answerModel));
|
|
2527
2570
|
}
|
|
2571
|
+
if (auth !== undefined) {
|
|
2572
|
+
lines.push(theme.fg("dim", " auth: ") + theme.fg("warning", auth === true ? "true" : auth));
|
|
2573
|
+
}
|
|
2528
2574
|
return new Text(lines.join("\n"), 0, 0);
|
|
2529
2575
|
},
|
|
2530
2576
|
|
|
@@ -2616,7 +2662,9 @@ export default function (pi: ExtensionAPI) {
|
|
|
2616
2662
|
},
|
|
2617
2663
|
});
|
|
2618
2664
|
|
|
2619
|
-
if (getSearchContentEnabled)
|
|
2665
|
+
if (getSearchContentEnabled) {
|
|
2666
|
+
const maxInlineContentChars = getMaxInlineContentChars(initConfig);
|
|
2667
|
+
pi.registerTool({
|
|
2620
2668
|
name: toolNames.getSearchContent,
|
|
2621
2669
|
label: "Get Search Content",
|
|
2622
2670
|
description: `Retrieve bounded content slices or find matching passages in a previous ${storedContentSources} call.`,
|
|
@@ -2625,11 +2673,11 @@ export default function (pi: ExtensionAPI) {
|
|
|
2625
2673
|
parameters: Type.Object({
|
|
2626
2674
|
responseId: Type.String({ description: `The responseId from ${storedContentSources}` }),
|
|
2627
2675
|
query: Type.Optional(Type.String({ description: searchQueryDescription })),
|
|
2628
|
-
queryIndex: Type.Optional(Type.
|
|
2676
|
+
queryIndex: Type.Optional(Type.Integer({ minimum: 0, description: "Get content for query at index" })),
|
|
2629
2677
|
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.
|
|
2678
|
+
urlIndex: Type.Optional(Type.Integer({ minimum: 0, description: "Get content for URL at index" })),
|
|
2679
|
+
offset: Type.Optional(Type.Integer({ minimum: 0, description: "Character offset for fetched URL content slices (default 0). Cannot be combined with findText." })),
|
|
2680
|
+
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
2681
|
findText: Type.Optional(Type.Union([
|
|
2634
2682
|
Type.String({ minLength: 1, maxLength: 500 }),
|
|
2635
2683
|
Type.Array(Type.String({ minLength: 1, maxLength: 500 }), { minItems: 1, maxItems: 10 }),
|
|
@@ -2639,15 +2687,23 @@ export default function (pi: ExtensionAPI) {
|
|
|
2639
2687
|
|
|
2640
2688
|
async execute(_toolCallId, params): Promise<AgentToolResult<Record<string, unknown>>> {
|
|
2641
2689
|
if (params.findText !== undefined && (params.offset !== undefined || params.limit !== undefined)) {
|
|
2642
|
-
|
|
2690
|
+
const offset = formatInputValue(params.offset);
|
|
2691
|
+
const limit = formatInputValue(params.limit);
|
|
2692
|
+
return {
|
|
2693
|
+
content: [{ type: "text", text: `findText cannot be combined with offset or limit. Received offset=${offset}, limit=${limit}; omit offset and limit when using findText.` }],
|
|
2694
|
+
details: { error: "Incompatible find options" },
|
|
2695
|
+
};
|
|
2643
2696
|
}
|
|
2644
2697
|
if (params.findMode !== undefined && params.findText === undefined) {
|
|
2645
|
-
return {
|
|
2698
|
+
return {
|
|
2699
|
+
content: [{ type: "text", text: `findMode ${formatInputValue(params.findMode)} requires findText; provide findText or omit findMode.` }],
|
|
2700
|
+
details: { error: "findMode requires findText" },
|
|
2701
|
+
};
|
|
2646
2702
|
}
|
|
2647
2703
|
const data = getResult(params.responseId);
|
|
2648
2704
|
if (!data) {
|
|
2649
2705
|
return {
|
|
2650
|
-
content: [{ type: "text", text: `Error: No stored results for
|
|
2706
|
+
content: [{ type: "text", text: `Error: No stored results for responseId ${formatInputValue(params.responseId)}. Use a responseId returned by ${storedContentSources}.` }],
|
|
2651
2707
|
details: { error: "Not found", responseId: params.responseId },
|
|
2652
2708
|
};
|
|
2653
2709
|
}
|
|
@@ -2656,22 +2712,30 @@ export default function (pi: ExtensionAPI) {
|
|
|
2656
2712
|
const artifact = getResearchArtifact(params.responseId);
|
|
2657
2713
|
if (!artifact) {
|
|
2658
2714
|
return {
|
|
2659
|
-
content: [{ type: "text", text: `Error: artifact ${params.responseId} not found
|
|
2715
|
+
content: [{ type: "text", text: `Error: stored research artifact for responseId ${formatInputValue(params.responseId)} was not found. Use a responseId returned by ${storedContentSources}.` }],
|
|
2660
2716
|
details: { error: "Artifact not found", responseId: params.responseId },
|
|
2661
2717
|
};
|
|
2662
2718
|
}
|
|
2663
2719
|
const serialized = JSON.stringify(artifact, null, 2);
|
|
2664
|
-
const maxInlineContentChars = getMaxInlineContentChars();
|
|
2665
2720
|
const offset = params.offset ?? 0;
|
|
2666
2721
|
const limit = params.limit ?? maxInlineContentChars;
|
|
2667
2722
|
if (!Number.isInteger(offset) || offset < 0) {
|
|
2668
|
-
return {
|
|
2723
|
+
return {
|
|
2724
|
+
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.` }],
|
|
2725
|
+
details: { error: "Invalid offset", offset },
|
|
2726
|
+
};
|
|
2669
2727
|
}
|
|
2670
2728
|
if (!Number.isInteger(limit) || limit <= 0 || limit > maxInlineContentChars) {
|
|
2671
|
-
return {
|
|
2729
|
+
return {
|
|
2730
|
+
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.` }],
|
|
2731
|
+
details: { error: "Invalid limit", limit, maxLimit: maxInlineContentChars },
|
|
2732
|
+
};
|
|
2672
2733
|
}
|
|
2673
2734
|
if (offset > serialized.length) {
|
|
2674
|
-
return {
|
|
2735
|
+
return {
|
|
2736
|
+
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.` }],
|
|
2737
|
+
details: { error: "Offset out of range", offset, contentLength: serialized.length },
|
|
2738
|
+
};
|
|
2675
2739
|
}
|
|
2676
2740
|
const endOffset = Math.min(offset + limit, serialized.length);
|
|
2677
2741
|
const artifactSlice = serialized.slice(offset, endOffset);
|
|
@@ -2690,29 +2754,30 @@ export default function (pi: ExtensionAPI) {
|
|
|
2690
2754
|
if (!queryData) {
|
|
2691
2755
|
const available = data.queries.map((q) => `"${q.query}"`).join(", ");
|
|
2692
2756
|
return {
|
|
2693
|
-
content: [{ type: "text", text: `Query
|
|
2757
|
+
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
2758
|
details: { error: "Query not found" },
|
|
2695
2759
|
};
|
|
2696
2760
|
}
|
|
2697
2761
|
} else if (params.queryIndex !== undefined) {
|
|
2698
2762
|
queryData = data.queries[params.queryIndex];
|
|
2699
2763
|
if (!queryData) {
|
|
2764
|
+
const available = data.queries.map((q, i) => `${i}: "${q.query}"`).join(", ");
|
|
2700
2765
|
return {
|
|
2701
|
-
content: [{ type: "text", text: `
|
|
2766
|
+
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
2767
|
details: { error: "Index out of range" },
|
|
2703
2768
|
};
|
|
2704
2769
|
}
|
|
2705
2770
|
} else {
|
|
2706
2771
|
const available = data.queries.map((q, i) => `${i}: "${q.query}"`).join(", ");
|
|
2707
2772
|
return {
|
|
2708
|
-
content: [{ type: "text", text: `Specify query or queryIndex. Available: ${available}
|
|
2773
|
+
content: [{ type: "text", text: `Specify query or queryIndex for responseId ${formatInputValue(params.responseId)}. Available queries: ${available || "none"}.` }],
|
|
2709
2774
|
details: { error: "No query specified" },
|
|
2710
2775
|
};
|
|
2711
2776
|
}
|
|
2712
2777
|
|
|
2713
2778
|
if (queryData.error) {
|
|
2714
2779
|
return {
|
|
2715
|
-
content: [{ type: "text", text: `Error
|
|
2780
|
+
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
2781
|
details: { error: queryData.error, query: queryData.query },
|
|
2717
2782
|
};
|
|
2718
2783
|
}
|
|
@@ -2728,7 +2793,10 @@ export default function (pi: ExtensionAPI) {
|
|
|
2728
2793
|
};
|
|
2729
2794
|
} catch (err) {
|
|
2730
2795
|
const error = err instanceof Error ? err.message : String(err);
|
|
2731
|
-
return {
|
|
2796
|
+
return {
|
|
2797
|
+
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.` }],
|
|
2798
|
+
details: { error, query: queryData.query },
|
|
2799
|
+
};
|
|
2732
2800
|
}
|
|
2733
2801
|
}
|
|
2734
2802
|
|
|
@@ -2748,7 +2816,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
2748
2816
|
if (!urlData) {
|
|
2749
2817
|
const available = data.urls.map((u) => u.url).join("\n ");
|
|
2750
2818
|
return {
|
|
2751
|
-
content: [{ type: "text", text: `URL not found. Available:\n ${available}
|
|
2819
|
+
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
2820
|
details: { error: "URL not found" },
|
|
2753
2821
|
};
|
|
2754
2822
|
}
|
|
@@ -2756,22 +2824,23 @@ export default function (pi: ExtensionAPI) {
|
|
|
2756
2824
|
selectedUrlIndex = params.urlIndex;
|
|
2757
2825
|
urlData = data.urls[selectedUrlIndex];
|
|
2758
2826
|
if (!urlData) {
|
|
2827
|
+
const available = data.urls.map((u, i) => `${i}: ${u.url}`).join("\n ");
|
|
2759
2828
|
return {
|
|
2760
|
-
content: [{ type: "text", text: `
|
|
2829
|
+
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
2830
|
details: { error: "Index out of range" },
|
|
2762
2831
|
};
|
|
2763
2832
|
}
|
|
2764
2833
|
} else {
|
|
2765
2834
|
const available = data.urls.map((u, i) => `${i}: ${u.url}`).join("\n ");
|
|
2766
2835
|
return {
|
|
2767
|
-
content: [{ type: "text", text: `Specify url or urlIndex. Available:\n ${available}` }],
|
|
2836
|
+
content: [{ type: "text", text: `Specify url or urlIndex for responseId ${formatInputValue(params.responseId)}. Available URLs:\n ${available || " none"}` }],
|
|
2768
2837
|
details: { error: "No URL specified" },
|
|
2769
2838
|
};
|
|
2770
2839
|
}
|
|
2771
2840
|
|
|
2772
2841
|
if (urlData.error) {
|
|
2773
2842
|
return {
|
|
2774
|
-
content: [{ type: "text", text: `Error
|
|
2843
|
+
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
2844
|
details: { error: urlData.error, url: urlData.url },
|
|
2776
2845
|
};
|
|
2777
2846
|
}
|
|
@@ -2786,28 +2855,30 @@ export default function (pi: ExtensionAPI) {
|
|
|
2786
2855
|
};
|
|
2787
2856
|
} catch (err) {
|
|
2788
2857
|
const error = err instanceof Error ? err.message : String(err);
|
|
2789
|
-
return {
|
|
2858
|
+
return {
|
|
2859
|
+
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.` }],
|
|
2860
|
+
details: { error, url: urlData.url },
|
|
2861
|
+
};
|
|
2790
2862
|
}
|
|
2791
2863
|
}
|
|
2792
2864
|
|
|
2793
|
-
const maxInlineContentChars = getMaxInlineContentChars();
|
|
2794
2865
|
const offset = params.offset ?? 0;
|
|
2795
2866
|
const limit = params.limit ?? maxInlineContentChars;
|
|
2796
2867
|
if (!Number.isInteger(offset) || offset < 0) {
|
|
2797
2868
|
return {
|
|
2798
|
-
content: [{ type: "text", text:
|
|
2869
|
+
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
2870
|
details: { error: "Invalid offset", offset },
|
|
2800
2871
|
};
|
|
2801
2872
|
}
|
|
2802
2873
|
if (!Number.isInteger(limit) || limit <= 0 || limit > maxInlineContentChars) {
|
|
2803
2874
|
return {
|
|
2804
|
-
content: [{ type: "text", text: `limit must be an integer from 1 to ${maxInlineContentChars}
|
|
2875
|
+
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
2876
|
details: { error: "Invalid limit", limit, maxLimit: maxInlineContentChars },
|
|
2806
2877
|
};
|
|
2807
2878
|
}
|
|
2808
2879
|
if (offset > urlData.content.length) {
|
|
2809
2880
|
return {
|
|
2810
|
-
content: [{ type: "text", text: `
|
|
2881
|
+
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
2882
|
details: { error: "Offset out of range", offset, contentLength: urlData.content.length },
|
|
2812
2883
|
};
|
|
2813
2884
|
}
|
|
@@ -2839,7 +2910,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
2839
2910
|
}
|
|
2840
2911
|
|
|
2841
2912
|
return {
|
|
2842
|
-
content: [{ type: "text", text:
|
|
2913
|
+
content: [{ type: "text", text: `Invalid stored data for responseId ${formatInputValue(params.responseId)}: received type ${formatInputValue(data.type)}. Use a responseId returned by ${storedContentSources}.` }],
|
|
2843
2914
|
details: { error: "Invalid data" },
|
|
2844
2915
|
};
|
|
2845
2916
|
},
|
|
@@ -2916,6 +2987,7 @@ export default function (pi: ExtensionAPI) {
|
|
|
2916
2987
|
return new Text(statusLine + "\n" + theme.fg("dim", preview), 0, 0);
|
|
2917
2988
|
},
|
|
2918
2989
|
});
|
|
2990
|
+
}
|
|
2919
2991
|
|
|
2920
2992
|
if (isCommandEnabled(initConfig, "websearch")) pi.registerCommand("websearch", {
|
|
2921
2993
|
description: "Open web search curator",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-web-access",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Web search, URL fetching, GitHub repo cloning, PDF extraction, YouTube video understanding, and local video analysis for Pi coding agent. Supports OpenAI, Brave, Parallel, TinyFish, Search1API, Searchinfinity, Querit, Tavily, Jina, SERPdive, Kagi, Ollama, AnySearch, Bright Data SERP, SerpBase, SearXNG,
|
|
3
|
+
"version": "0.23.0",
|
|
4
|
+
"description": "Web search, URL fetching, GitHub repo cloning, PDF extraction, YouTube video understanding, and local video analysis for Pi coding agent. Supports OpenAI, Brave, Parallel, TinyFish, Search1API, Searchinfinity, Querit, Tavily, Firecrawl, Jina, SERPdive, Kagi, Ollama, AnySearch, Bright Data SERP, SerpBase, SearXNG, Exa, Perplexity, and Gemini.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"test": "node --test",
|
|
@@ -4,6 +4,8 @@ import { findModelWithProviderRouting, loadEnabledModelPatterns, modelMatchesEna
|
|
|
4
4
|
import type { QueryResultData } from "./storage.ts";
|
|
5
5
|
|
|
6
6
|
type ProviderHeaders = Record<string, string | null>;
|
|
7
|
+
type CompleteFunction = typeof complete;
|
|
8
|
+
type SummaryModelRegistry = SummaryGenerationContext["modelRegistry"] & { complete?: CompleteFunction };
|
|
7
9
|
|
|
8
10
|
const PREFERRED_SUMMARY_MODELS = [
|
|
9
11
|
{ provider: "anthropic", id: "claude-haiku-4-5" },
|
|
@@ -198,14 +200,14 @@ function parseModelSelector(value: string): { provider: string; id: string } {
|
|
|
198
200
|
async function resolveSummaryModelCandidates(
|
|
199
201
|
ctx: SummaryGenerationContext,
|
|
200
202
|
modelOverride?: string,
|
|
201
|
-
): Promise<{ candidates: Array<{ model: Model<Api>; apiKey
|
|
203
|
+
): Promise<{ candidates: Array<{ model: Model<Api>; apiKey?: string; headers?: ProviderHeaders }>; errors: string[] }> {
|
|
202
204
|
const enabledModelPatterns = loadEnabledModelPatterns(ctx);
|
|
203
205
|
const specs: Array<{ provider: string; id: string }> = [];
|
|
204
206
|
const normalizedOverride = typeof modelOverride === "string" ? modelOverride.trim() : "";
|
|
205
207
|
if (normalizedOverride.length > 0) specs.push(parseModelSelector(normalizedOverride));
|
|
206
208
|
specs.push(...PREFERRED_SUMMARY_MODELS);
|
|
207
209
|
|
|
208
|
-
const candidates: Array<{ model: Model<Api>; apiKey
|
|
210
|
+
const candidates: Array<{ model: Model<Api>; apiKey?: string; headers?: ProviderHeaders }> = [];
|
|
209
211
|
const errors: string[] = [];
|
|
210
212
|
const seen = new Set<string>();
|
|
211
213
|
for (const spec of specs) {
|
|
@@ -223,7 +225,7 @@ async function resolveSummaryModelCandidates(
|
|
|
223
225
|
continue;
|
|
224
226
|
}
|
|
225
227
|
const auth = await ctx.modelRegistry.getApiKeyAndHeaders(model);
|
|
226
|
-
if (!auth.ok
|
|
228
|
+
if (!auth.ok) {
|
|
227
229
|
errors.push(`No API key available for summary model ${value}`);
|
|
228
230
|
continue;
|
|
229
231
|
}
|
|
@@ -275,13 +277,17 @@ export async function generateSummaryDraft(
|
|
|
275
277
|
signal?: AbortSignal,
|
|
276
278
|
modelOverride?: string,
|
|
277
279
|
feedback?: string,
|
|
278
|
-
completeFn
|
|
280
|
+
completeFn?: CompleteFunction,
|
|
279
281
|
deadlineMs = SUMMARY_GENERATION_DEADLINE_MS,
|
|
280
282
|
): Promise<{ summary: string; meta: SummaryMeta }> {
|
|
281
283
|
if (!ctx || !ctx.modelRegistry) {
|
|
282
284
|
throw new Error("Summary generation context unavailable");
|
|
283
285
|
}
|
|
284
286
|
|
|
287
|
+
const registry = ctx.modelRegistry as SummaryModelRegistry;
|
|
288
|
+
const usesRegistryComplete = !completeFn && typeof registry.complete === "function";
|
|
289
|
+
completeFn ??= usesRegistryComplete ? registry.complete!.bind(registry) as CompleteFunction : complete;
|
|
290
|
+
|
|
285
291
|
const generationStartedAt = Date.now();
|
|
286
292
|
const deadlineController = new AbortController();
|
|
287
293
|
const deadlineMarker = Symbol("summary-generation-deadline");
|
|
@@ -349,7 +355,7 @@ export async function generateSummaryDraft(
|
|
|
349
355
|
const response = await raceSummaryOperation(Promise.resolve(completeFn(
|
|
350
356
|
model,
|
|
351
357
|
{ messages: [userMessage] },
|
|
352
|
-
{ apiKey, headers, signal: completionSignal },
|
|
358
|
+
usesRegistryComplete ? { signal: completionSignal } : { apiKey, headers, signal: completionSignal },
|
|
353
359
|
)));
|
|
354
360
|
if (response.stopReason === "aborted") {
|
|
355
361
|
throw new Error("Aborted");
|
|
@@ -132,7 +132,7 @@ export async function extractYouTube(
|
|
|
132
132
|
|
|
133
133
|
const error = attemptErrors.length > 0
|
|
134
134
|
? ["Could not extract YouTube video content.", "", ...attemptErrors.map(message => `- ${message}`)].join("\n")
|
|
135
|
-
: "Could not extract YouTube video content. Sign into Google in
|
|
135
|
+
: "Could not extract YouTube video content. Sign into Google in a supported Chromium browser for automatic access, or set GEMINI_API_KEY.";
|
|
136
136
|
activityMonitor.logError(activityId, error);
|
|
137
137
|
return { url, title: "", content: "", error };
|
|
138
138
|
}
|
|
@@ -311,7 +311,7 @@ async function tryPerplexity(
|
|
|
311
311
|
|
|
312
312
|
const content =
|
|
313
313
|
`# Video Summary (via Perplexity)\n\n${answer}\n\n` +
|
|
314
|
-
`*Full video understanding requires Gemini access. Set GEMINI_API_KEY or sign into Google in
|
|
314
|
+
`*Full video understanding requires Gemini access. Set GEMINI_API_KEY or sign into Google in a supported Chromium browser.*`;
|
|
315
315
|
|
|
316
316
|
return {
|
|
317
317
|
url,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@herbertgao/pi-extensions",
|
|
3
|
-
"version": "2026.8.
|
|
3
|
+
"version": "2026.8.6",
|
|
4
4
|
"description": "Aggregate installer for HerbertGao-maintained Pi extensions.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"extensions",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"@earendil-works/pi-tui": "^0.84.1",
|
|
43
43
|
"@effect/platform-node": "4.0.0-beta.103",
|
|
44
44
|
"@effect/platform-node-shared": "4.0.0-beta.103",
|
|
45
|
-
"@herbertgao/pi-cc-extensions": "0.8.
|
|
45
|
+
"@herbertgao/pi-cc-extensions": "0.8.55",
|
|
46
46
|
"@herbertgao/pi-copy-response": "0.2.6",
|
|
47
47
|
"@herbertgao/pi-handoff": "1.1.2",
|
|
48
48
|
"@herbertgao/pi-inline-skills": "1.0.5",
|
|
@@ -51,18 +51,18 @@
|
|
|
51
51
|
"@herbertgao/pi-recap": "0.4.4",
|
|
52
52
|
"@herbertgao/pi-rename": "0.4.2",
|
|
53
53
|
"@herbertgao/pi-stash": "0.1.1",
|
|
54
|
-
"@herbertgao/pi-subagents": "0.15.
|
|
54
|
+
"@herbertgao/pi-subagents": "0.15.5",
|
|
55
55
|
"@herbertgao/pi-titlebar-spinner": "0.1.3",
|
|
56
|
-
"@juicesharp/rpiv-ask-user-question": "2.
|
|
57
|
-
"@juicesharp/rpiv-config": "^2.
|
|
56
|
+
"@juicesharp/rpiv-ask-user-question": "2.6.0",
|
|
57
|
+
"@juicesharp/rpiv-config": "^2.6.0",
|
|
58
58
|
"@modelcontextprotocol/client": "2.0.0",
|
|
59
59
|
"@modelcontextprotocol/core": "2.0.0",
|
|
60
60
|
"@modelcontextprotocol/ext-apps": "^1.2.2",
|
|
61
61
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
62
62
|
"@mozilla/readability": "^0.6.0",
|
|
63
63
|
"@napi-rs/keyring": "^1.3.0",
|
|
64
|
-
"@narumitw/pi-btw": "0.
|
|
65
|
-
"@narumitw/pi-tui-kit": "^0.
|
|
64
|
+
"@narumitw/pi-btw": "0.52.0",
|
|
65
|
+
"@narumitw/pi-tui-kit": "^0.54.0",
|
|
66
66
|
"@noble/ed25519": "^3.1.0",
|
|
67
67
|
"@pi-plugins/fast-mode": "0.1.9",
|
|
68
68
|
"@shikijs/cli": "^4.0.2",
|
|
@@ -77,14 +77,14 @@
|
|
|
77
77
|
"jiti": "^2.7.0",
|
|
78
78
|
"js-yaml": "^5.2.2",
|
|
79
79
|
"linkedom": "^0.16.0",
|
|
80
|
-
"minimatch": "^10.2.
|
|
80
|
+
"minimatch": "^10.2.6",
|
|
81
81
|
"nanoid": "^5.0.0",
|
|
82
82
|
"open": "^10.2.0",
|
|
83
83
|
"p-limit": "^6.1.0",
|
|
84
84
|
"pi-footer": "0.5.1",
|
|
85
|
-
"pi-lens": "
|
|
86
|
-
"pi-mcp-adapter": "2.
|
|
87
|
-
"pi-web-access": "0.
|
|
85
|
+
"pi-lens": "4.0.1",
|
|
86
|
+
"pi-mcp-adapter": "2.26.0",
|
|
87
|
+
"pi-web-access": "0.23.0",
|
|
88
88
|
"pidusage": "^4.0.1",
|
|
89
89
|
"promise.try": "^2.0.1",
|
|
90
90
|
"qrcode-terminal": "^0.12.0",
|
|
@@ -161,8 +161,7 @@
|
|
|
161
161
|
"skills": [
|
|
162
162
|
"./node_modules/@dietrichgebert/ponytail/skills",
|
|
163
163
|
"./node_modules/pi-mcp-adapter/skills",
|
|
164
|
-
"./node_modules/pi-lens/skills"
|
|
165
|
-
"./node_modules/remote-pi/skills"
|
|
164
|
+
"./node_modules/pi-lens/skills"
|
|
166
165
|
]
|
|
167
166
|
}
|
|
168
167
|
}
|