@herbertgao/pi-extensions 2026.8.6 → 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 +1 -1
- package/node_modules/@herbertgao/pi-cc-extensions/README.md +1 -1
- 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/renderer/compact-mode.ts +94 -77
- 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 +6 -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 +17 -13
- 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 +21 -6
- package/node_modules/@herbertgao/pi-subagents/src/usage.ts +129 -1
- package/node_modules/@herbertgao/pi-subagents/src/worktree.ts +20 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/README.md +1 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/ask-user-question.ts +26 -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 +2 -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 +120 -111
- 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 +10 -6
- package/node_modules/@narumitw/pi-btw/src/btw.ts +36 -40
- 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 +45 -2
- package/node_modules/@narumitw/pi-btw/src/transcript-pager.ts +136 -45
- package/node_modules/pi-lens/CHANGELOG.md +909 -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 +126 -13
- package/node_modules/pi-lens/dist/clients/agent-nudge.js +67 -11
- 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 +61 -30
- 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/cascade-budget.js +196 -0
- package/node_modules/pi-lens/dist/clients/cascade-format.js +20 -1
- 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/dead-code-client.js +123 -31
- 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 +25 -3
- package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +147 -33
- package/node_modules/pi-lens/dist/clients/diagnostic-line-freshness.js +298 -0
- package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +52 -2
- package/node_modules/pi-lens/dist/clients/dispatch/integration.js +256 -88
- 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 +60 -53
- 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 +275 -13
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +21 -6
- 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 +734 -64
- 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 +9 -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/event-loop-monitor.js +28 -5
- package/node_modules/pi-lens/dist/clients/extension-log.js +22 -1
- 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/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 +31 -0
- package/node_modules/pi-lens/dist/clients/gitleaks-client.js +181 -8
- package/node_modules/pi-lens/dist/clients/govulncheck-client.js +109 -9
- package/node_modules/pi-lens/dist/clients/grammar-source.js +333 -10
- package/node_modules/pi-lens/dist/clients/host-ports.js +8 -0
- package/node_modules/pi-lens/dist/clients/installer/index.js +1114 -100
- 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 +82 -6
- package/node_modules/pi-lens/dist/clients/knip-client.js +310 -10
- 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 +440 -11
- 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-flag-registry.js +8 -0
- package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +102 -7
- package/node_modules/pi-lens/dist/clients/lsp/client.js +1516 -159
- package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +83 -1
- package/node_modules/pi-lens/dist/clients/lsp/document-drift.js +389 -0
- package/node_modules/pi-lens/dist/clients/lsp/index.js +2274 -147
- 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 +277 -16
- 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 +79 -3
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/strategies.js +43 -0
- 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/session.js +10 -2
- 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 +154 -33
- 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 +84 -14
- 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/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 +52 -4
- package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +96 -7
- package/node_modules/pi-lens/dist/clients/runtime-context.js +8 -1
- package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +308 -45
- package/node_modules/pi-lens/dist/clients/runtime-session.js +332 -9
- package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +217 -22
- package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +212 -79
- package/node_modules/pi-lens/dist/clients/runtime-turn.js +575 -67
- 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 +157 -24
- package/node_modules/pi-lens/dist/clients/sg-runner.js +116 -22
- package/node_modules/pi-lens/dist/clients/single-flight.js +158 -0
- package/node_modules/pi-lens/dist/clients/stale-marker.js +17 -0
- package/node_modules/pi-lens/dist/clients/startup-timing.js +19 -1
- package/node_modules/pi-lens/dist/clients/test-runner-client.js +151 -16
- package/node_modules/pi-lens/dist/clients/tool-event.js +56 -5
- package/node_modules/pi-lens/dist/clients/tool-policy.js +125 -20
- 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/widget-state.js +336 -36
- package/node_modules/pi-lens/dist/clients/zizmor-config.js +214 -14
- package/node_modules/pi-lens/dist/index.js +67738 -55739
- package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +466 -54
- package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +132 -43
- package/node_modules/pi-lens/dist/tools/lsp-navigation.js +46 -7
- package/node_modules/pi-lens/docs/agent-guide.md +6 -1
- package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +515 -506
- package/node_modules/pi-lens/docs/dispositions.md +21 -0
- package/node_modules/pi-lens/docs/features.md +19 -5
- package/node_modules/pi-lens/docs/globalconfig.md +3 -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 +19 -1
- package/node_modules/pi-lens/docs/usage.md +1 -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 +15 -1
- 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-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 +2 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-test.yml +2 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-js-test.yml +2 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-test.yml +2 -1
- 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-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 +57 -12
- 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-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 +22 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply.yml +23 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get-js.yml +33 -5
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get.yml +34 -8
- 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 +6 -1
- 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 +53 -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 +2 -0
- package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/SKILL.md +80 -3
- package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/reference.md +41 -0
- package/node_modules/pi-lens/vendor/grammars/tree-sitter-cue.wasm +0 -0
- package/node_modules/pi-mcp-adapter/CHANGELOG.md +36 -0
- package/node_modules/pi-mcp-adapter/README.md +47 -5
- package/node_modules/pi-mcp-adapter/cli.js +163 -1
- package/node_modules/pi-mcp-adapter/commands.ts +128 -22
- package/node_modules/pi-mcp-adapter/config.ts +25 -7
- package/node_modules/pi-mcp-adapter/direct-tools.ts +5 -4
- 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/metadata-cache.ts +32 -21
- package/node_modules/pi-mcp-adapter/package-mcp-loader.ts +168 -0
- package/node_modules/pi-mcp-adapter/package.json +3 -1
- package/node_modules/pi-mcp-adapter/proxy-modes.ts +5 -4
- package/node_modules/pi-mcp-adapter/request-headers-command.ts +31 -37
- package/node_modules/pi-mcp-adapter/search-ranking.ts +92 -22
- package/node_modules/pi-mcp-adapter/server-manager.ts +140 -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-result-renderer.ts +44 -4
- package/node_modules/pi-mcp-adapter/types.ts +2 -0
- 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 +23 -0
- package/node_modules/pi-web-access/README.md +27 -9
- package/node_modules/pi-web-access/anysearch.ts +4 -2
- package/node_modules/pi-web-access/brave.ts +16 -4
- package/node_modules/pi-web-access/curator-page.ts +6 -3
- package/node_modules/pi-web-access/curator-server.ts +4 -1
- package/node_modules/pi-web-access/exa.ts +18 -7
- package/node_modules/pi-web-access/extract.ts +28 -3
- package/node_modules/pi-web-access/gemini-search.ts +16 -4
- package/node_modules/pi-web-access/index.ts +41 -57
- package/node_modules/pi-web-access/package.json +1 -1
- 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 +44 -22
- 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/package.json +13 -13
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import { mkdirSync } from "node:fs";
|
|
2
|
+
import { isDeepStrictEqual } from "node:util";
|
|
2
3
|
import {
|
|
3
4
|
Client,
|
|
5
|
+
SdkError,
|
|
6
|
+
SdkErrorCode,
|
|
4
7
|
SdkHttpError,
|
|
5
8
|
SSEClientTransport,
|
|
6
9
|
StreamableHTTPClientTransport,
|
|
7
10
|
UnauthorizedError,
|
|
8
11
|
type GetPromptResult,
|
|
9
12
|
type ReadResourceResult,
|
|
13
|
+
type CacheableRequestOptions,
|
|
10
14
|
type RequestOptions,
|
|
11
15
|
type UrlElicitationRequiredError,
|
|
12
16
|
type VersionNegotiationOptions,
|
|
@@ -32,6 +36,7 @@ import { logger } from "./logger.ts";
|
|
|
32
36
|
import { McpOAuthProvider } from "./mcp-oauth-provider.ts";
|
|
33
37
|
import { extractOAuthConfig, supportsOAuth, type McpOAuthRuntime } from "./mcp-auth-flow.ts";
|
|
34
38
|
import { invalidateAuthEntryCache, type AuthStorageOptions } from "./mcp-auth.ts";
|
|
39
|
+
import { getBearerTokenForUrl } from "./mcp-bearer-store.ts";
|
|
35
40
|
import { registerSamplingHandler, type ServerSamplingConfig } from "./sampling-handler.ts";
|
|
36
41
|
import {
|
|
37
42
|
handleUrlElicitation,
|
|
@@ -123,6 +128,8 @@ export interface ServerConnection {
|
|
|
123
128
|
transport: Transport;
|
|
124
129
|
definition: ServerDefinition;
|
|
125
130
|
tools: McpTool[];
|
|
131
|
+
/** Monotonic guard against older refresh responses replacing newer notifications. */
|
|
132
|
+
toolsRevision?: number;
|
|
126
133
|
resources: McpResource[];
|
|
127
134
|
prompts: McpPrompt[];
|
|
128
135
|
/** True when prompts were advertised but prompts/list failed. */
|
|
@@ -139,6 +146,10 @@ export interface ServerConnection {
|
|
|
139
146
|
type UiStreamListener = (serverName: string, notification: ServerStreamResultPatchNotification["params"]) => void;
|
|
140
147
|
type MetadataListChangedListener = (serverName: string, reason: string) => void;
|
|
141
148
|
|
|
149
|
+
export type ToolRefreshResult = "updated" | "unchanged" | "superseded" | "refresh-timeout";
|
|
150
|
+
|
|
151
|
+
const KEEP_ALIVE_REFRESH_TIMEOUT_MS = 5_000;
|
|
152
|
+
|
|
142
153
|
export class McpServerManager {
|
|
143
154
|
private connections = new Map<string, ServerConnection>();
|
|
144
155
|
private connectPromises = new Map<string, Promise<ServerConnection>>();
|
|
@@ -146,6 +157,10 @@ export class McpServerManager {
|
|
|
146
157
|
private uiStreamListeners = new Map<string, UiStreamListener>();
|
|
147
158
|
private samplingConfig: ServerSamplingConfig | undefined;
|
|
148
159
|
private metadataListChangedListener: MetadataListChangedListener | undefined;
|
|
160
|
+
private pendingMetadataPublications = new Map<
|
|
161
|
+
string,
|
|
162
|
+
{ connection: ServerConnection; reason: string }
|
|
163
|
+
>();
|
|
149
164
|
private elicitationConfig: ServerElicitationConfig | undefined;
|
|
150
165
|
private authStorageOptions: AuthStorageOptions = {};
|
|
151
166
|
private oauthRuntime: McpOAuthRuntime | undefined;
|
|
@@ -170,6 +185,25 @@ export class McpServerManager {
|
|
|
170
185
|
this.metadataListChangedListener = listener;
|
|
171
186
|
}
|
|
172
187
|
|
|
188
|
+
publishMetadataChanged(
|
|
189
|
+
name: string,
|
|
190
|
+
expectedConnection: ServerConnection,
|
|
191
|
+
reason: string,
|
|
192
|
+
): boolean {
|
|
193
|
+
const current = this.connections.get(name);
|
|
194
|
+
if (current !== expectedConnection || current.status !== "connected") return false;
|
|
195
|
+
try {
|
|
196
|
+
this.metadataListChangedListener?.(name, reason);
|
|
197
|
+
this.pendingMetadataPublications.delete(name);
|
|
198
|
+
return true;
|
|
199
|
+
} catch (error) {
|
|
200
|
+
this.pendingMetadataPublications.set(name, { connection: expectedConnection, reason });
|
|
201
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
202
|
+
logger.debug(`MCP: metadata publication failed for ${name}; queued for retry: ${message}`);
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
173
207
|
setElicitationConfig(config: ServerElicitationConfig | undefined): void {
|
|
174
208
|
this.elicitationConfig = config;
|
|
175
209
|
}
|
|
@@ -303,6 +337,100 @@ export class McpServerManager {
|
|
|
303
337
|
return abortable(promise, ownedSignal);
|
|
304
338
|
}
|
|
305
339
|
|
|
340
|
+
/**
|
|
341
|
+
* Fetch the authoritative tool catalog for a connection that still appears
|
|
342
|
+
* connected. The SDK response cache is explicitly bypassed so this request
|
|
343
|
+
* also proves the remote Streamable HTTP session is usable. Results are
|
|
344
|
+
* identity-guarded: a late response from a replaced connection is ignored.
|
|
345
|
+
*/
|
|
346
|
+
async refreshTools(
|
|
347
|
+
name: string,
|
|
348
|
+
expectedConnection: ServerConnection,
|
|
349
|
+
signal?: AbortSignal,
|
|
350
|
+
): Promise<ToolRefreshResult> {
|
|
351
|
+
if (this.stopped) throw new Error("MCP server manager is closed");
|
|
352
|
+
const ownedSignal = combineAbortSignals(this.runtimeSignal, signal);
|
|
353
|
+
throwIfAborted(ownedSignal);
|
|
354
|
+
|
|
355
|
+
const current = this.connections.get(name);
|
|
356
|
+
if (current !== expectedConnection || current.status !== "connected") {
|
|
357
|
+
return "superseded";
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
const requestOptions = this.buildRequestOptions(expectedConnection.definition, signal);
|
|
361
|
+
const timeout = Math.min(requestOptions?.timeout ?? KEEP_ALIVE_REFRESH_TIMEOUT_MS, KEEP_ALIVE_REFRESH_TIMEOUT_MS);
|
|
362
|
+
const healthOptions = {
|
|
363
|
+
...requestOptions,
|
|
364
|
+
timeout,
|
|
365
|
+
};
|
|
366
|
+
if (!expectedConnection.client.getServerCapabilities?.()?.tools) {
|
|
367
|
+
await expectedConnection.client.ping(healthOptions);
|
|
368
|
+
throwIfAborted(ownedSignal);
|
|
369
|
+
if (this.connections.get(name) !== expectedConnection || expectedConnection.status !== "connected") {
|
|
370
|
+
return "superseded";
|
|
371
|
+
}
|
|
372
|
+
this.retryPendingMetadataPublication(name, expectedConnection);
|
|
373
|
+
return "unchanged";
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
const toolsRevision = expectedConnection.toolsRevision ?? 0;
|
|
377
|
+
const refreshSignal = combineAbortSignals(healthOptions.signal, AbortSignal.timeout(timeout));
|
|
378
|
+
let tools: McpTool[];
|
|
379
|
+
try {
|
|
380
|
+
tools = await this.fetchAllTools(expectedConnection.client, {
|
|
381
|
+
...healthOptions,
|
|
382
|
+
...(refreshSignal ? { signal: refreshSignal } : {}),
|
|
383
|
+
cacheMode: "refresh",
|
|
384
|
+
});
|
|
385
|
+
} catch (error) {
|
|
386
|
+
throwIfAborted(ownedSignal);
|
|
387
|
+
if (this.connections.get(name) !== expectedConnection || expectedConnection.status !== "connected") {
|
|
388
|
+
return "superseded";
|
|
389
|
+
}
|
|
390
|
+
if (error instanceof SdkError && error.code === SdkErrorCode.RequestTimeout) {
|
|
391
|
+
return "refresh-timeout";
|
|
392
|
+
}
|
|
393
|
+
throw error;
|
|
394
|
+
}
|
|
395
|
+
throwIfAborted(ownedSignal);
|
|
396
|
+
|
|
397
|
+
if (this.connections.get(name) !== expectedConnection || expectedConnection.status !== "connected") {
|
|
398
|
+
return "superseded";
|
|
399
|
+
}
|
|
400
|
+
if ((expectedConnection.toolsRevision ?? 0) !== toolsRevision) {
|
|
401
|
+
return "superseded";
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
if (isDeepStrictEqual(expectedConnection.tools, tools)) {
|
|
405
|
+
this.retryPendingMetadataPublication(name, expectedConnection);
|
|
406
|
+
return "unchanged";
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
const previousTools = expectedConnection.tools;
|
|
410
|
+
expectedConnection.tools = tools;
|
|
411
|
+
expectedConnection.toolsRevision = toolsRevision + 1;
|
|
412
|
+
try {
|
|
413
|
+
await this.metadataListChangedListener?.(name, "keep-alive-refresh");
|
|
414
|
+
this.pendingMetadataPublications.delete(name);
|
|
415
|
+
} catch (error) {
|
|
416
|
+
if (this.connections.get(name) === expectedConnection && expectedConnection.tools === tools) {
|
|
417
|
+
expectedConnection.tools = previousTools;
|
|
418
|
+
expectedConnection.toolsRevision = toolsRevision;
|
|
419
|
+
}
|
|
420
|
+
throw error;
|
|
421
|
+
}
|
|
422
|
+
return "updated";
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
private retryPendingMetadataPublication(name: string, connection: ServerConnection): void {
|
|
426
|
+
const pendingPublication = this.pendingMetadataPublications.get(name);
|
|
427
|
+
if (pendingPublication?.connection !== connection) return;
|
|
428
|
+
this.metadataListChangedListener?.(name, pendingPublication.reason);
|
|
429
|
+
if (this.pendingMetadataPublications.get(name) === pendingPublication) {
|
|
430
|
+
this.pendingMetadataPublications.delete(name);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
306
434
|
private async doReconnect(
|
|
307
435
|
name: string,
|
|
308
436
|
definition: ServerDefinition,
|
|
@@ -440,6 +568,7 @@ export class McpServerManager {
|
|
|
440
568
|
transport,
|
|
441
569
|
definition,
|
|
442
570
|
tools: [],
|
|
571
|
+
toolsRevision: 0,
|
|
443
572
|
resources: [],
|
|
444
573
|
prompts: [],
|
|
445
574
|
...(instructions !== undefined ? { instructions } : {}),
|
|
@@ -641,7 +770,9 @@ export class McpServerManager {
|
|
|
641
770
|
const connection = this.connections.get(serverName);
|
|
642
771
|
if (!connection || connection.client !== client || connection.status !== "connected") return;
|
|
643
772
|
connection.tools = tools;
|
|
773
|
+
connection.toolsRevision = (connection.toolsRevision ?? 0) + 1;
|
|
644
774
|
this.metadataListChangedListener?.(serverName, "tools-list-changed");
|
|
775
|
+
this.pendingMetadataPublications.delete(serverName);
|
|
645
776
|
}
|
|
646
777
|
|
|
647
778
|
private handlePromptsListChanged(
|
|
@@ -660,6 +791,7 @@ export class McpServerManager {
|
|
|
660
791
|
connection.prompts = prompts;
|
|
661
792
|
connection.promptDiscoveryFailed = false;
|
|
662
793
|
this.metadataListChangedListener?.(serverName, "prompts-list-changed");
|
|
794
|
+
this.pendingMetadataPublications.delete(serverName);
|
|
663
795
|
}
|
|
664
796
|
|
|
665
797
|
private handleResourcesListChanged(
|
|
@@ -677,6 +809,7 @@ export class McpServerManager {
|
|
|
677
809
|
if (!connection || connection.client !== client || connection.status !== "connected") return;
|
|
678
810
|
connection.resources = resources;
|
|
679
811
|
this.metadataListChangedListener?.(serverName, "resources-list-changed");
|
|
812
|
+
this.pendingMetadataPublications.delete(serverName);
|
|
680
813
|
}
|
|
681
814
|
|
|
682
815
|
async handleUrlElicitationRequired(
|
|
@@ -734,7 +867,10 @@ export class McpServerManager {
|
|
|
734
867
|
if (definition.auth === "bearer") {
|
|
735
868
|
const token = commandBearer
|
|
736
869
|
? resolveCommandSecret(commandBearer, `MCP server "${serverName}" HTTP bearer token`)
|
|
737
|
-
: resolveBearerToken(definition)
|
|
870
|
+
: resolveBearerToken(definition)
|
|
871
|
+
?? (definition.bearerToken === undefined && definition.bearerTokenEnv === undefined && definition.bearerTokenStore === true
|
|
872
|
+
? getBearerTokenForUrl(serverName, serverUrl)
|
|
873
|
+
: undefined);
|
|
738
874
|
if (token) headers["Authorization"] = `Bearer ${token}`;
|
|
739
875
|
}
|
|
740
876
|
|
|
@@ -851,7 +987,7 @@ export class McpServerManager {
|
|
|
851
987
|
}
|
|
852
988
|
}
|
|
853
989
|
|
|
854
|
-
private async fetchAllTools(client: Client, requestOptions?:
|
|
990
|
+
private async fetchAllTools(client: Client, requestOptions?: CacheableRequestOptions): Promise<McpTool[]> {
|
|
855
991
|
const allTools: McpTool[] = [];
|
|
856
992
|
let cursor: string | undefined;
|
|
857
993
|
|
|
@@ -979,6 +1115,7 @@ export class McpServerManager {
|
|
|
979
1115
|
async close(name: string): Promise<void> {
|
|
980
1116
|
this.closeGenerations.set(name, (this.closeGenerations.get(name) ?? 0) + 1);
|
|
981
1117
|
this.connectAttempts.get(name)?.abort(new Error(`MCP connection ${name} was closed`));
|
|
1118
|
+
this.pendingMetadataPublications.delete(name);
|
|
982
1119
|
|
|
983
1120
|
const connection = this.connections.get(name);
|
|
984
1121
|
if (!connection) {
|
|
@@ -1042,6 +1179,7 @@ export class McpServerManager {
|
|
|
1042
1179
|
.filter(error => this.containsCleanupFailure(error));
|
|
1043
1180
|
this.uiStreamListeners.clear();
|
|
1044
1181
|
this.acceptedUrlElicitations.clear();
|
|
1182
|
+
this.pendingMetadataPublications.clear();
|
|
1045
1183
|
this.samplingConfig = undefined;
|
|
1046
1184
|
this.elicitationConfig = undefined;
|
|
1047
1185
|
await this.traceWriter?.flush();
|
|
@@ -146,6 +146,13 @@ export async function withSessionRecovery<T>(
|
|
|
146
146
|
throw err;
|
|
147
147
|
}
|
|
148
148
|
|
|
149
|
+
try {
|
|
150
|
+
deps.manager.publishMetadataChanged(serverName, freshConnection, "session-reconnect");
|
|
151
|
+
} catch (publicationError) {
|
|
152
|
+
const message = publicationError instanceof Error ? publicationError.message : String(publicationError);
|
|
153
|
+
logger.debug(`MCP metadata publication after reconnect failed for "${serverName}": ${message}`);
|
|
154
|
+
}
|
|
155
|
+
throwIfAborted(deps.signal);
|
|
149
156
|
return fn(freshConnection);
|
|
150
157
|
}
|
|
151
158
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { randomUUID } from "node:crypto";
|
|
1
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
2
2
|
import { abortable } from "./abort.ts";
|
|
3
3
|
import { combineAbortSignals } from "./runtime-owner.ts";
|
|
4
4
|
import type { McpExtensionState } from "./state.ts";
|
|
@@ -20,6 +20,18 @@ export type ToolCallApprovalResult =
|
|
|
20
20
|
| { ok: true }
|
|
21
21
|
| { ok: false; reason: "denied" | "approval_required_headless" };
|
|
22
22
|
|
|
23
|
+
function stableStringify(value: unknown): string {
|
|
24
|
+
if (value === null || value === undefined || typeof value !== "object") {
|
|
25
|
+
const serialized = JSON.stringify(value);
|
|
26
|
+
return serialized === undefined ? "undefined" : serialized;
|
|
27
|
+
}
|
|
28
|
+
if (Array.isArray(value)) {
|
|
29
|
+
return `[${value.map(item => stableStringify(item)).join(",")}]`;
|
|
30
|
+
}
|
|
31
|
+
const object = value as Record<string, unknown>;
|
|
32
|
+
return `{${Object.keys(object).sort().map(key => `${JSON.stringify(key)}:${stableStringify(object[key])}`).join(",")}}`;
|
|
33
|
+
}
|
|
34
|
+
|
|
23
35
|
export function isToolCallApprovalRequired(
|
|
24
36
|
config: McpConfig,
|
|
25
37
|
serverName: string,
|
|
@@ -136,7 +148,8 @@ export async function ensureToolCallApproved(
|
|
|
136
148
|
origin: McpToolApprovalOrigin = toolMeta.resourceUri ? "resource" : "proxy",
|
|
137
149
|
approvalMetadata?: ReadonlyMap<string, readonly ToolMetadata[]>,
|
|
138
150
|
): Promise<ToolCallApprovalResult> {
|
|
139
|
-
const
|
|
151
|
+
const argsHash = createHash("sha256").update(stableStringify(args ?? {})).digest("hex");
|
|
152
|
+
const cacheKey = `${serverName}\u0000${toolMeta.originalName}\u0000${argsHash}`;
|
|
140
153
|
const approvedToolCalls = state.approvedToolCalls ??= new Map<string, true>();
|
|
141
154
|
if (approvedToolCalls.has(cacheKey)) {
|
|
142
155
|
return { ok: true };
|
|
@@ -25,6 +25,7 @@ export interface McpProxyToolCallInput {
|
|
|
25
25
|
|
|
26
26
|
interface McpToolRenderState {
|
|
27
27
|
compactTitle?: string;
|
|
28
|
+
compactInputPreview?: string;
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
interface McpToolRenderContext {
|
|
@@ -52,6 +53,7 @@ export interface McpToolResultDisplay {
|
|
|
52
53
|
}
|
|
53
54
|
|
|
54
55
|
const DEFAULT_MAX_CALL_INPUT_CHARS = 1500;
|
|
56
|
+
const DEFAULT_MAX_COMPACT_INPUT_CHARS = 240;
|
|
55
57
|
const DEFAULT_BOXED_COLLAPSED_LINES = 3;
|
|
56
58
|
const DEFAULT_COMPACT_COLLAPSED_LINES = 1;
|
|
57
59
|
const DEFAULT_MAX_COLLAPSED_CHARS = 8000;
|
|
@@ -70,6 +72,7 @@ class CompactMcpToolResult implements Component {
|
|
|
70
72
|
|
|
71
73
|
constructor(
|
|
72
74
|
private readonly title: string,
|
|
75
|
+
private readonly inputPreview: string,
|
|
73
76
|
private readonly display: McpToolResultDisplay,
|
|
74
77
|
private readonly theme: RenderTheme,
|
|
75
78
|
) {}
|
|
@@ -83,7 +86,7 @@ class CompactMcpToolResult implements Component {
|
|
|
83
86
|
});
|
|
84
87
|
const lines = resultLines.length > 0 ? resultLines : [""];
|
|
85
88
|
const bodies = lines.map((line, index) => {
|
|
86
|
-
const prefix = index === 0
|
|
89
|
+
const prefix = index === 0 ? this.renderPrefix(safeWidth) : "";
|
|
87
90
|
return `${prefix}${this.theme.fg("toolOutput", line)}`;
|
|
88
91
|
});
|
|
89
92
|
const hiddenText = this.display.truncated || bodies.some((body) => visibleWidth(body) > safeWidth);
|
|
@@ -106,6 +109,22 @@ class CompactMcpToolResult implements Component {
|
|
|
106
109
|
invalidate(): void {
|
|
107
110
|
this.rendered = null;
|
|
108
111
|
}
|
|
112
|
+
|
|
113
|
+
private renderPrefix(width: number): string {
|
|
114
|
+
if (!this.title) return "";
|
|
115
|
+
const arrow = " → ";
|
|
116
|
+
if (!this.inputPreview) return `${this.theme.fg("toolTitle", this.title)}${arrow}`;
|
|
117
|
+
|
|
118
|
+
const maxPrefixWidth = Math.max(12, Math.floor(width * 0.55));
|
|
119
|
+
const titleWidth = visibleWidth(this.title);
|
|
120
|
+
const inputWidth = Math.max(0, maxPrefixWidth - titleWidth - 1);
|
|
121
|
+
if (inputWidth <= 3) {
|
|
122
|
+
return `${this.theme.fg("toolTitle", truncateToWidth(this.title, maxPrefixWidth, "…"))}${arrow}`;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const input = truncateToWidth(this.inputPreview, inputWidth, "…");
|
|
126
|
+
return `${this.theme.fg("toolTitle", this.title)} ${this.theme.fg("muted", input)}${arrow}`;
|
|
127
|
+
}
|
|
109
128
|
}
|
|
110
129
|
|
|
111
130
|
class CollapsibleText implements Component {
|
|
@@ -239,6 +258,10 @@ function renderToolCallLines(lines: string[], theme?: RenderTheme) {
|
|
|
239
258
|
return new Text([styledTitle, ...styledRest].join("\n"), 0, 0);
|
|
240
259
|
}
|
|
241
260
|
|
|
261
|
+
function formatCompactInputPreview(lines: string[], maxChars = DEFAULT_MAX_COMPACT_INPUT_CHARS): string {
|
|
262
|
+
return truncateText(lines.slice(1).join(" ").replace(/\s+/g, " ").trim(), maxChars);
|
|
263
|
+
}
|
|
264
|
+
|
|
242
265
|
export function resolveMcpToolRenderOptions(settings?: McpToolRenderSettings): McpToolRenderOptions {
|
|
243
266
|
const resultRendering = settings?.toolResultRendering === "boxed" ? "boxed" : "compact";
|
|
244
267
|
const collapsedLines = settings?.collapsedResultLines;
|
|
@@ -263,7 +286,10 @@ function renderToolCall(
|
|
|
263
286
|
context: McpToolRenderContext | undefined,
|
|
264
287
|
options: McpToolRenderOptions,
|
|
265
288
|
) {
|
|
266
|
-
if (context?.state)
|
|
289
|
+
if (context?.state) {
|
|
290
|
+
context.state.compactTitle = lines[0] ?? "mcp";
|
|
291
|
+
context.state.compactInputPreview = formatCompactInputPreview(lines);
|
|
292
|
+
}
|
|
267
293
|
if (shouldUseCompactFinalRender(options, context)) return new EmptyComponent();
|
|
268
294
|
return renderToolCallLines(lines, theme);
|
|
269
295
|
}
|
|
@@ -307,6 +333,19 @@ function collectCollapsedResultLines(
|
|
|
307
333
|
let truncated = false;
|
|
308
334
|
|
|
309
335
|
const appendLine = (line: string) => {
|
|
336
|
+
if (lines.length === 0) {
|
|
337
|
+
const previewWidth = Math.min(line.length, remainingChars);
|
|
338
|
+
if (line.slice(0, previewWidth).trim() === "") {
|
|
339
|
+
if (line.length >= remainingChars) {
|
|
340
|
+
truncated = true;
|
|
341
|
+
remainingChars = 0;
|
|
342
|
+
return false;
|
|
343
|
+
}
|
|
344
|
+
remainingChars -= line.length + 1;
|
|
345
|
+
return true;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
310
349
|
if (lines.length >= maxLines || remainingChars <= 0) {
|
|
311
350
|
truncated = true;
|
|
312
351
|
return false;
|
|
@@ -342,7 +381,7 @@ function collectCollapsedResultLines(
|
|
|
342
381
|
if (truncated) break;
|
|
343
382
|
}
|
|
344
383
|
|
|
345
|
-
if (lines.length === 0) lines.push("");
|
|
384
|
+
if (lines.length === 0) lines.push(truncated ? "(leading blank output omitted)" : "");
|
|
346
385
|
if (truncated && lines.length >= maxLines) lines.push("…");
|
|
347
386
|
return { lines, truncated };
|
|
348
387
|
}
|
|
@@ -393,7 +432,8 @@ export function renderMcpToolResult(
|
|
|
393
432
|
if (!expanded && renderOptions.resultRendering === "compact") {
|
|
394
433
|
const display = formatMcpToolResultLines(result, false, renderOptions.collapsedResultLines);
|
|
395
434
|
const title = context?.state?.compactTitle ?? formatMcpToolResultIdentity(result.details) ?? "";
|
|
396
|
-
|
|
435
|
+
const inputPreview = context?.state?.compactInputPreview ?? "";
|
|
436
|
+
return new CompactMcpToolResult(title, inputPreview, display, activeTheme);
|
|
397
437
|
}
|
|
398
438
|
|
|
399
439
|
const display = formatMcpToolResultLines(result, expanded, renderOptions.collapsedResultLines);
|
|
@@ -392,6 +392,8 @@ export interface ServerEntry {
|
|
|
392
392
|
auth?: "oauth" | "bearer" | false;
|
|
393
393
|
bearerToken?: string;
|
|
394
394
|
bearerTokenEnv?: string;
|
|
395
|
+
/** Read a static bearer token from the adapter-owned OS credential store. */
|
|
396
|
+
bearerTokenStore?: true;
|
|
395
397
|
/**
|
|
396
398
|
* OAuth configuration (optional).
|
|
397
399
|
* If not provided, the SDK will attempt dynamic client registration.
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
import { ContentBlockSchema } from "@modelcontextprotocol/core";
|
|
11
11
|
import type { ConsentManager } from "./consent-manager.ts";
|
|
12
12
|
import { ServerError, wrapError } from "./errors.ts";
|
|
13
|
-
import { formatAuthRequiredMessage } from "./utils.ts";
|
|
13
|
+
import { formatAuthRequiredMessage, normalizeToolArguments } from "./utils.ts";
|
|
14
14
|
import { buildHostHtmlTemplate, buildCspMetaContent } from "./host-html-template.ts";
|
|
15
15
|
import { logger } from "./logger.ts";
|
|
16
16
|
import type { McpServerManager } from "./server-manager.ts";
|
|
@@ -113,6 +113,7 @@ export async function startUiServer(options: UiServerOptions): Promise<UiServerH
|
|
|
113
113
|
let currentDisplayMode: UiDisplayMode = options.hostContext?.displayMode ?? "inline";
|
|
114
114
|
let nextEventId = 1;
|
|
115
115
|
const eventLog: Array<{ id: number; name: string; payload: unknown }> = [];
|
|
116
|
+
let latestCheckpointEventId: number | undefined;
|
|
116
117
|
let streamSummary: UiStreamSummary | undefined;
|
|
117
118
|
|
|
118
119
|
// Track messages from UI for retrieval
|
|
@@ -185,9 +186,12 @@ export async function startUiServer(options: UiServerOptions): Promise<UiServerH
|
|
|
185
186
|
lastHeartbeatAt = Date.now();
|
|
186
187
|
};
|
|
187
188
|
|
|
188
|
-
const updateStreamSummary = (payload: unknown) => {
|
|
189
|
+
const updateStreamSummary = (eventId: number, payload: unknown) => {
|
|
189
190
|
const envelope = getVisualizationStreamEnvelope((payload as { structuredContent?: unknown } | null)?.structuredContent);
|
|
190
191
|
if (!envelope) return;
|
|
192
|
+
if (envelope.frameType === "checkpoint" || envelope.frameType === "final") {
|
|
193
|
+
latestCheckpointEventId = eventId;
|
|
194
|
+
}
|
|
191
195
|
if (!streamSummary) {
|
|
192
196
|
streamSummary = {
|
|
193
197
|
streamId: envelope.streamId,
|
|
@@ -210,15 +214,9 @@ export async function startUiServer(options: UiServerOptions): Promise<UiServerH
|
|
|
210
214
|
};
|
|
211
215
|
|
|
212
216
|
const getLatestCheckpointIndex = () => {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
const envelope = getVisualizationStreamEnvelope((entry.payload as { structuredContent?: unknown } | null)?.structuredContent);
|
|
217
|
-
if (envelope?.frameType === "checkpoint" || envelope?.frameType === "final") {
|
|
218
|
-
return index;
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
return -1;
|
|
217
|
+
const firstEventId = eventLog[0]?.id;
|
|
218
|
+
if (latestCheckpointEventId === undefined || firstEventId === undefined || latestCheckpointEventId < firstEventId) return -1;
|
|
219
|
+
return latestCheckpointEventId - firstEventId;
|
|
222
220
|
};
|
|
223
221
|
|
|
224
222
|
const pruneEventLog = () => {
|
|
@@ -238,7 +236,7 @@ export async function startUiServer(options: UiServerOptions): Promise<UiServerH
|
|
|
238
236
|
if (completed) return;
|
|
239
237
|
const eventId = nextEventId++;
|
|
240
238
|
eventLog.push({ id: eventId, name, payload });
|
|
241
|
-
updateStreamSummary(payload);
|
|
239
|
+
updateStreamSummary(eventId, payload);
|
|
242
240
|
pruneEventLog();
|
|
243
241
|
const chunk = serializeEvent(eventId, name, payload);
|
|
244
242
|
for (const client of sseClients) {
|
|
@@ -438,12 +436,16 @@ export async function startUiServer(options: UiServerOptions): Promise<UiServerH
|
|
|
438
436
|
return;
|
|
439
437
|
}
|
|
440
438
|
|
|
439
|
+
let normalizedArguments: Record<string, unknown>;
|
|
440
|
+
try {
|
|
441
|
+
normalizedArguments = normalizeToolArguments(callParams.arguments, `tool "${callParams.name}" arguments`);
|
|
442
|
+
} catch (error) {
|
|
443
|
+
sendJson(res, 400, { ok: false, error: error instanceof Error ? error.message : String(error) });
|
|
444
|
+
return;
|
|
445
|
+
}
|
|
441
446
|
const callArgs = {
|
|
442
447
|
name: callParams.name,
|
|
443
|
-
arguments:
|
|
444
|
-
callParams.arguments && typeof callParams.arguments === "object" && !Array.isArray(callParams.arguments)
|
|
445
|
-
? callParams.arguments
|
|
446
|
-
: {},
|
|
448
|
+
arguments: normalizedArguments,
|
|
447
449
|
};
|
|
448
450
|
const toolMeta = {
|
|
449
451
|
name: callParams.name,
|
|
@@ -282,6 +282,76 @@ export function normalizeDirectToolInputSchema(schema: unknown): Record<string,
|
|
|
282
282
|
return normalized;
|
|
283
283
|
}
|
|
284
284
|
|
|
285
|
+
export function normalizeToolArguments(
|
|
286
|
+
value: unknown,
|
|
287
|
+
context = "tool arguments",
|
|
288
|
+
): Record<string, unknown> {
|
|
289
|
+
if (value === undefined || value === null || value === "") return {};
|
|
290
|
+
|
|
291
|
+
if (typeof value === "string") {
|
|
292
|
+
const trimmed = value.trim();
|
|
293
|
+
if (trimmed === "") return {};
|
|
294
|
+
let parsed: unknown;
|
|
295
|
+
try {
|
|
296
|
+
parsed = JSON.parse(trimmed);
|
|
297
|
+
} catch (error) {
|
|
298
|
+
throw new Error(
|
|
299
|
+
`${context}: invalid args JSON (${error instanceof SyntaxError ? error.message : String(error)}); ` +
|
|
300
|
+
`pass args as a JSON object, or as a valid JSON string encoding one`,
|
|
301
|
+
{ cause: error },
|
|
302
|
+
);
|
|
303
|
+
}
|
|
304
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
305
|
+
throw new Error(
|
|
306
|
+
`${context}: expected a JSON object, got ${Array.isArray(parsed) ? "array" : typeof parsed}`,
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
return parsed as Record<string, unknown>;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
if (typeof value !== "object" || Array.isArray(value)) {
|
|
313
|
+
throw new Error(
|
|
314
|
+
`${context}: expected a JSON object, got ${Array.isArray(value) ? "array" : typeof value}`,
|
|
315
|
+
);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
assertJsonSerializable(value, context);
|
|
319
|
+
try {
|
|
320
|
+
return JSON.parse(JSON.stringify(value)) as Record<string, unknown>;
|
|
321
|
+
} catch (error) {
|
|
322
|
+
throw new Error(
|
|
323
|
+
`${context}: value is not JSON-serializable: ${error instanceof Error ? error.message : String(error)}`,
|
|
324
|
+
{ cause: error },
|
|
325
|
+
);
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
function assertJsonSerializable(value: unknown, context: string, path = ""): void {
|
|
330
|
+
if (value === null) return;
|
|
331
|
+
if (typeof value === "string" || typeof value === "boolean") return;
|
|
332
|
+
if (typeof value === "number") {
|
|
333
|
+
if (!Number.isFinite(value)) throw new Error(`${context}: value at ${path || "root"} is not a finite number`);
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
if (Array.isArray(value)) {
|
|
337
|
+
for (const [index, item] of value.entries()) assertJsonSerializable(item, context, `${path}[${index}]`);
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
if (typeof value === "object") {
|
|
341
|
+
if (Object.getPrototypeOf(value) !== Object.prototype && Object.getPrototypeOf(value) !== null) {
|
|
342
|
+
throw new Error(`${context}: value at ${path || "root"} is not a plain JSON object`);
|
|
343
|
+
}
|
|
344
|
+
if (Object.getOwnPropertySymbols(value).length > 0) {
|
|
345
|
+
throw new Error(`${context}: value at ${path || "root"} has symbol keys`);
|
|
346
|
+
}
|
|
347
|
+
for (const [key, item] of Object.entries(value)) {
|
|
348
|
+
assertJsonSerializable(item, context, path ? `${path}.${key}` : key);
|
|
349
|
+
}
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
throw new Error(`${context}: value at ${path || "root"} is not JSON-serializable`);
|
|
353
|
+
}
|
|
354
|
+
|
|
285
355
|
export function formatAuthRequiredMessage(
|
|
286
356
|
config: Pick<McpConfig, "settings">,
|
|
287
357
|
serverName: string,
|
|
@@ -4,6 +4,29 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
## [Unreleased]
|
|
6
6
|
|
|
7
|
+
## [0.24.0] - 2026-08-18
|
|
8
|
+
|
|
9
|
+
### Highlights
|
|
10
|
+
- Added more provider choices, including Parallel Search MCP, Valyu, and Serper.
|
|
11
|
+
- Made `fetch_content` recover useful article text from more Next.js and React Server Components pages.
|
|
12
|
+
- Updated summary and query rewrite model defaults to newer fast models.
|
|
13
|
+
- Made nested summary and rewrite model calls follow Pi's model registry routing.
|
|
14
|
+
- Added more control over summary thinking levels and provider API base URLs.
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
- Added `summaryModel` thinking-level suffix support. Thanks to [@pkos98](https://github.com/pkos98) for issue #264.
|
|
18
|
+
- Added explicit-only Parallel Search MCP support for keyless search and opt-in hosted fetch. Thanks to [@happytomatoe](https://github.com/happytomatoe) for #257.
|
|
19
|
+
- Added explicit-only Valyu and Serper search providers. Thanks to [@mikhel01](https://github.com/mikhel01) for issues #259 and #260.
|
|
20
|
+
- Added configurable API base URLs for Brave, keyed Exa, and Tavily requests, with credential stripping across redirect origins. Thanks to [@XWIlluDelu](https://github.com/XWIlluDelu) for #265.
|
|
21
|
+
|
|
22
|
+
### Changed
|
|
23
|
+
- Refreshed default summary and query rewrite model preferences. Thanks to [@hyein-cbio](https://github.com/hyein-cbio) for #266.
|
|
24
|
+
|
|
25
|
+
### Fixed
|
|
26
|
+
- Route nested model calls through Pi's model registry. Thanks to [@rany2](https://github.com/rany2) for #263.
|
|
27
|
+
- Recover useful Next.js RSC content when Readability only extracts a loading shell, and report full, partial, or failed background content fetches accurately (#272, #273).
|
|
28
|
+
- Keep valid AnySearch results when the API omits or nulls result content. Thanks to [@mikhel01](https://github.com/mikhel01) for #258.
|
|
29
|
+
|
|
7
30
|
## [0.23.0] - 2026-08-15
|
|
8
31
|
|
|
9
32
|
### Added
|