@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
|
@@ -20,10 +20,12 @@
|
|
|
20
20
|
// many things other than "your session is gone"
|
|
21
21
|
// - treat generic -32000/ConnectionClosed errors as session expiry
|
|
22
22
|
// - treat AbortError/cancellation as a session failure
|
|
23
|
-
import { ProtocolError, SdkHttpError } from "@modelcontextprotocol/client";
|
|
23
|
+
import { ProtocolError, SdkHttpError, UnauthorizedError } from "@modelcontextprotocol/client";
|
|
24
24
|
import { logger } from "./logger.ts";
|
|
25
25
|
import { throwIfAborted } from "./abort.ts";
|
|
26
26
|
import { isServerDisabled, type McpConfig } from "./types.ts";
|
|
27
|
+
import { supportsOAuth } from "./mcp-auth-flow.ts";
|
|
28
|
+
import { invalidateAuthEntryCache } from "./mcp-auth.ts";
|
|
27
29
|
import type { McpServerManager, ServerConnection } from "./server-manager.ts";
|
|
28
30
|
|
|
29
31
|
/**
|
|
@@ -106,6 +108,11 @@ export async function withSessionRecovery<T>(
|
|
|
106
108
|
try {
|
|
107
109
|
return await fn(connection);
|
|
108
110
|
} catch (err) {
|
|
111
|
+
const definition = deps.config.mcpServers[serverName];
|
|
112
|
+
if (definition && supportsOAuth(definition)
|
|
113
|
+
&& (err instanceof UnauthorizedError || (err instanceof SdkHttpError && err.status === 401))) {
|
|
114
|
+
invalidateAuthEntryCache(serverName);
|
|
115
|
+
}
|
|
109
116
|
if (!isTerminatedSession(err, hadSessionId)) {
|
|
110
117
|
throw err;
|
|
111
118
|
}
|
|
@@ -114,7 +121,6 @@ export async function withSessionRecovery<T>(
|
|
|
114
121
|
// connection's definition, in case config changed since connect. If the
|
|
115
122
|
// server was removed from config in the meantime there is nothing to
|
|
116
123
|
// reconnect to, so surface the original error.
|
|
117
|
-
const definition = deps.config.mcpServers[serverName];
|
|
118
124
|
if (!definition) {
|
|
119
125
|
throw err;
|
|
120
126
|
}
|
|
@@ -24,19 +24,59 @@ export function isToolCallApprovalRequired(
|
|
|
24
24
|
config: McpConfig,
|
|
25
25
|
serverName: string,
|
|
26
26
|
toolMeta: Pick<ToolMetadata, "originalName">,
|
|
27
|
+
toolMetadata?: ReadonlyMap<string, readonly ToolMetadata[]>,
|
|
27
28
|
): boolean {
|
|
28
29
|
const definition = config.mcpServers[serverName];
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
: config.settings?.approveTools;
|
|
30
|
+
const serverApproval = definition?.approveTools;
|
|
31
|
+
const approval = serverApproval !== undefined ? serverApproval : config.settings?.approveTools;
|
|
32
32
|
|
|
33
33
|
if (approval === true) return true;
|
|
34
34
|
if (!Array.isArray(approval) || approval.length === 0) return false;
|
|
35
35
|
|
|
36
36
|
const prefix = resolveToolPrefix(definition, config.settings?.toolPrefix);
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
approval
|
|
37
|
+
const currentCandidates = getToolNameCandidates(toolMeta.originalName, serverName, prefix, false);
|
|
38
|
+
if (serverApproval !== undefined) {
|
|
39
|
+
if (matchesToolPattern(currentCandidates, approval)) return true;
|
|
40
|
+
if (!toolMetadata) return matchesToolPattern(getToolNameCandidates(toolMeta.originalName, serverName, prefix), approval);
|
|
41
|
+
const legacyCandidates = getToolNameCandidates(toolMeta.originalName, serverName, prefix);
|
|
42
|
+
const legacyEmittedName = [...currentCandidates].find(candidate => candidate !== toolMeta.originalName)?.replace(/-/g, "_");
|
|
43
|
+
if (legacyEmittedName) legacyCandidates.add(legacyEmittedName);
|
|
44
|
+
for (const candidate of currentCandidates) legacyCandidates.delete(candidate);
|
|
45
|
+
const otherCurrentCandidates = new Set<string>();
|
|
46
|
+
for (const tool of toolMetadata.get(serverName) ?? []) {
|
|
47
|
+
for (const candidate of getToolNameCandidates(tool.originalName, serverName, prefix, false)) {
|
|
48
|
+
otherCurrentCandidates.add(candidate);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
for (const candidate of currentCandidates) otherCurrentCandidates.delete(candidate);
|
|
52
|
+
return approval.some(pattern =>
|
|
53
|
+
matchesToolPattern(legacyCandidates, [pattern])
|
|
54
|
+
&& !matchesToolPattern(otherCurrentCandidates, [pattern]),
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
if (matchesToolPattern(currentCandidates, approval)) return true;
|
|
60
|
+
if (!toolMetadata) return false;
|
|
61
|
+
|
|
62
|
+
const legacyCandidates = getToolNameCandidates(toolMeta.originalName, serverName, prefix);
|
|
63
|
+
const legacyEmittedName = [...currentCandidates].find(candidate => candidate !== toolMeta.originalName)?.replace(/-/g, "_");
|
|
64
|
+
if (legacyEmittedName) legacyCandidates.add(legacyEmittedName);
|
|
65
|
+
for (const candidate of currentCandidates) legacyCandidates.delete(candidate);
|
|
66
|
+
const otherCurrentCandidates = new Set<string>();
|
|
67
|
+
for (const [name, metadata] of toolMetadata) {
|
|
68
|
+
const otherPrefix = resolveToolPrefix(config.mcpServers[name], config.settings?.toolPrefix);
|
|
69
|
+
for (const tool of metadata) {
|
|
70
|
+
for (const candidate of getToolNameCandidates(tool.originalName, name, otherPrefix, false)) {
|
|
71
|
+
otherCurrentCandidates.add(candidate);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
for (const candidate of currentCandidates) otherCurrentCandidates.delete(candidate);
|
|
76
|
+
|
|
77
|
+
return approval.some(pattern =>
|
|
78
|
+
matchesToolPattern(legacyCandidates, [pattern])
|
|
79
|
+
&& !matchesToolPattern(otherCurrentCandidates, [pattern]),
|
|
40
80
|
);
|
|
41
81
|
}
|
|
42
82
|
|
|
@@ -94,6 +134,7 @@ export async function ensureToolCallApproved(
|
|
|
94
134
|
args: Record<string, unknown> | undefined,
|
|
95
135
|
signal?: AbortSignal,
|
|
96
136
|
origin: McpToolApprovalOrigin = toolMeta.resourceUri ? "resource" : "proxy",
|
|
137
|
+
approvalMetadata?: ReadonlyMap<string, readonly ToolMetadata[]>,
|
|
97
138
|
): Promise<ToolCallApprovalResult> {
|
|
98
139
|
const cacheKey = `${serverName}\u0000${toolMeta.originalName}`;
|
|
99
140
|
const approvedToolCalls = state.approvedToolCalls ??= new Map<string, true>();
|
|
@@ -109,7 +150,7 @@ export async function ensureToolCallApproved(
|
|
|
109
150
|
}
|
|
110
151
|
if (brokerDecision === "deny") return { ok: false, reason: "denied" };
|
|
111
152
|
|
|
112
|
-
if (!isToolCallApprovalRequired(state.config, serverName, toolMeta)) {
|
|
153
|
+
if (!isToolCallApprovalRequired(state.config, serverName, toolMeta, approvalMetadata ?? state.toolMetadata)) {
|
|
113
154
|
return { ok: true };
|
|
114
155
|
}
|
|
115
156
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { getToolUiResourceUri } from "./ui-app-bridge-helpers.ts";
|
|
2
2
|
import type { McpExtensionState } from "./state.ts";
|
|
3
3
|
import type { ToolMetadata, McpTool, McpResource, ServerEntry, ToolPrefix } from "./types.ts";
|
|
4
|
-
import { formatToolName, isToolAllowed, resolveToolPrefix } from "./types.ts";
|
|
4
|
+
import { createToolSelectorCandidateIndex, formatToolName, getToolNameCandidates, isToolAllowed, resolveToolPrefix } from "./types.ts";
|
|
5
5
|
import { resourceNameToToolName } from "./resource-tools.ts";
|
|
6
6
|
import { extractToolUiStreamMode } from "./utils.ts";
|
|
7
7
|
import { extractUiToolVisibility, isUiToolVisibleToModel } from "./ui-tool-visibility.ts";
|
|
@@ -11,19 +11,77 @@ export function buildToolMetadata(
|
|
|
11
11
|
resources: McpResource[],
|
|
12
12
|
definition: ServerEntry,
|
|
13
13
|
serverName: string,
|
|
14
|
-
prefix: ToolPrefix
|
|
14
|
+
prefix: ToolPrefix,
|
|
15
|
+
configuredServers?: Record<string, ServerEntry>,
|
|
16
|
+
knownMetadata?: Map<string, ToolMetadata[]>,
|
|
17
|
+
includeMissingConfiguredCandidates = false,
|
|
15
18
|
): { metadata: ToolMetadata[]; failedTools: string[] } {
|
|
16
19
|
const metadata: ToolMetadata[] = [];
|
|
17
20
|
const failedTools: string[] = [];
|
|
18
21
|
const seenNames = new Set<string>();
|
|
19
22
|
const effectivePrefix = resolveToolPrefix(definition, prefix);
|
|
23
|
+
const hasToolFilters =
|
|
24
|
+
(Array.isArray(definition.includeTools) && definition.includeTools.length > 0) ||
|
|
25
|
+
(Array.isArray(definition.excludeTools) && definition.excludeTools.length > 0);
|
|
26
|
+
const selectorCandidateIndex = hasToolFilters && configuredServers ? (() => {
|
|
27
|
+
const candidates = new Set<string>();
|
|
28
|
+
const additionalCandidatesByToolName = new Map<string, Set<string>>();
|
|
29
|
+
const evaluatedToolNames = new Set<string>();
|
|
30
|
+
const addCandidates = (
|
|
31
|
+
target: Set<string>,
|
|
32
|
+
originalName: string,
|
|
33
|
+
candidateServerName: string,
|
|
34
|
+
candidatePrefix: ToolPrefix,
|
|
35
|
+
) => {
|
|
36
|
+
for (const candidate of getToolNameCandidates(originalName, candidateServerName, candidatePrefix, false)) target.add(candidate);
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
for (const tool of tools) {
|
|
40
|
+
if (!tool?.name) continue;
|
|
41
|
+
evaluatedToolNames.add(tool.name);
|
|
42
|
+
addCandidates(candidates, tool.name, serverName, effectivePrefix);
|
|
43
|
+
}
|
|
44
|
+
if (definition.exposeResources !== false) {
|
|
45
|
+
for (const resource of resources) {
|
|
46
|
+
const baseName = `read_${resourceNameToToolName(resource.name)}`;
|
|
47
|
+
evaluatedToolNames.add(baseName);
|
|
48
|
+
if (resource?.name && resource?.uri) addCandidates(candidates, baseName, serverName, effectivePrefix);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
for (const [otherServerName, otherDefinition] of Object.entries(configuredServers)) {
|
|
52
|
+
if (otherServerName === serverName) continue;
|
|
53
|
+
const otherPrefix = resolveToolPrefix(otherDefinition, prefix);
|
|
54
|
+
const knownTools = knownMetadata?.get(otherServerName);
|
|
55
|
+
if (knownTools) {
|
|
56
|
+
for (const tool of knownTools) {
|
|
57
|
+
candidates.add(tool.name);
|
|
58
|
+
addCandidates(candidates, tool.originalName, otherServerName, otherPrefix);
|
|
59
|
+
}
|
|
60
|
+
} else if (!knownMetadata || includeMissingConfiguredCandidates) {
|
|
61
|
+
for (const toolName of evaluatedToolNames) {
|
|
62
|
+
let additionalCandidates = additionalCandidatesByToolName.get(toolName);
|
|
63
|
+
if (!additionalCandidates) {
|
|
64
|
+
additionalCandidates = new Set<string>();
|
|
65
|
+
additionalCandidatesByToolName.set(toolName, additionalCandidates);
|
|
66
|
+
}
|
|
67
|
+
addCandidates(additionalCandidates, toolName, otherServerName, otherPrefix);
|
|
68
|
+
if (includeMissingConfiguredCandidates) {
|
|
69
|
+
for (const candidate of getToolNameCandidates(toolName, otherServerName, otherPrefix, false)) {
|
|
70
|
+
additionalCandidates.add(candidate.replace(/-/g, "_"));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return createToolSelectorCandidateIndex(candidates, additionalCandidatesByToolName);
|
|
77
|
+
})() : undefined;
|
|
20
78
|
|
|
21
79
|
for (const tool of tools) {
|
|
22
80
|
if (!tool?.name) {
|
|
23
81
|
failedTools.push("(unnamed)");
|
|
24
82
|
continue;
|
|
25
83
|
}
|
|
26
|
-
if (!isToolAllowed(tool.name, serverName, effectivePrefix, definition.includeTools, definition.excludeTools)) {
|
|
84
|
+
if (!isToolAllowed(tool.name, serverName, effectivePrefix, definition.includeTools, definition.excludeTools, selectorCandidateIndex)) {
|
|
27
85
|
continue;
|
|
28
86
|
}
|
|
29
87
|
|
|
@@ -59,7 +117,7 @@ export function buildToolMetadata(
|
|
|
59
117
|
if (definition.exposeResources !== false) {
|
|
60
118
|
for (const resource of resources) {
|
|
61
119
|
const baseName = `read_${resourceNameToToolName(resource.name)}`;
|
|
62
|
-
if (!isToolAllowed(baseName, serverName, effectivePrefix, definition.includeTools, definition.excludeTools)) {
|
|
120
|
+
if (!isToolAllowed(baseName, serverName, effectivePrefix, definition.includeTools, definition.excludeTools, selectorCandidateIndex)) {
|
|
63
121
|
continue;
|
|
64
122
|
}
|
|
65
123
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AgentToolResult, ToolRenderResultOptions } from "@earendil-works/pi-coding-agent";
|
|
2
|
-
import { type Component, Text } from "@earendil-works/pi-tui";
|
|
2
|
+
import { type Component, Text, truncateToWidth, visibleWidth } from "@earendil-works/pi-tui";
|
|
3
3
|
|
|
4
4
|
type McpToolResultDetails = Record<string, unknown> & { error?: unknown };
|
|
5
5
|
type McpToolContentBlock = AgentToolResult<McpToolResultDetails>["content"][number];
|
|
@@ -23,8 +23,27 @@ export interface McpProxyToolCallInput {
|
|
|
23
23
|
action?: string;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
interface McpToolRenderState {
|
|
27
|
+
compactTitle?: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
26
30
|
interface McpToolRenderContext {
|
|
27
31
|
isError: boolean;
|
|
32
|
+
isPartial?: boolean;
|
|
33
|
+
expanded?: boolean;
|
|
34
|
+
state?: McpToolRenderState;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export type McpToolResultRendering = "compact" | "boxed";
|
|
38
|
+
|
|
39
|
+
export interface McpToolRenderOptions {
|
|
40
|
+
resultRendering: McpToolResultRendering;
|
|
41
|
+
collapsedResultLines: 1 | 2 | 3;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface McpToolRenderSettings {
|
|
45
|
+
toolResultRendering?: unknown;
|
|
46
|
+
collapsedResultLines?: unknown;
|
|
28
47
|
}
|
|
29
48
|
|
|
30
49
|
export interface McpToolResultDisplay {
|
|
@@ -33,10 +52,62 @@ export interface McpToolResultDisplay {
|
|
|
33
52
|
}
|
|
34
53
|
|
|
35
54
|
const DEFAULT_MAX_CALL_INPUT_CHARS = 1500;
|
|
36
|
-
const
|
|
55
|
+
const DEFAULT_BOXED_COLLAPSED_LINES = 3;
|
|
56
|
+
const DEFAULT_COMPACT_COLLAPSED_LINES = 1;
|
|
37
57
|
const DEFAULT_MAX_COLLAPSED_CHARS = 8000;
|
|
38
58
|
const COLLAPSED_RENDER_CHAR_SLACK = 8;
|
|
39
59
|
|
|
60
|
+
class EmptyComponent implements Component {
|
|
61
|
+
render(): string[] {
|
|
62
|
+
return [];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
invalidate(): void {}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
class CompactMcpToolResult implements Component {
|
|
69
|
+
private rendered: { width: number; lines: string[] } | null = null;
|
|
70
|
+
|
|
71
|
+
constructor(
|
|
72
|
+
private readonly title: string,
|
|
73
|
+
private readonly display: McpToolResultDisplay,
|
|
74
|
+
private readonly theme: RenderTheme,
|
|
75
|
+
) {}
|
|
76
|
+
|
|
77
|
+
render(width: number): string[] {
|
|
78
|
+
const safeWidth = Math.max(1, Math.floor(width));
|
|
79
|
+
if (this.rendered?.width === safeWidth) return this.rendered.lines;
|
|
80
|
+
|
|
81
|
+
const resultLines = this.display.lines.filter((line, index, lines) => {
|
|
82
|
+
return !(this.display.truncated && index === lines.length - 1 && line === "…");
|
|
83
|
+
});
|
|
84
|
+
const lines = resultLines.length > 0 ? resultLines : [""];
|
|
85
|
+
const bodies = lines.map((line, index) => {
|
|
86
|
+
const prefix = index === 0 && this.title ? `${this.theme.fg("toolTitle", this.title)} → ` : "";
|
|
87
|
+
return `${prefix}${this.theme.fg("toolOutput", line)}`;
|
|
88
|
+
});
|
|
89
|
+
const hiddenText = this.display.truncated || bodies.some((body) => visibleWidth(body) > safeWidth);
|
|
90
|
+
const rendered = bodies.map((body, index) => {
|
|
91
|
+
const suffix = hiddenText && index === bodies.length - 1 ? " … (Ctrl+O to expand)" : "";
|
|
92
|
+
if (!suffix) return truncateToWidth(body, safeWidth, "…");
|
|
93
|
+
if (safeWidth >= suffix.length + 20) {
|
|
94
|
+
return `${truncateToWidth(body, safeWidth - suffix.length, "…")}${this.theme.fg("muted", suffix)}`;
|
|
95
|
+
}
|
|
96
|
+
const shortSuffix = " (Ctrl+O)";
|
|
97
|
+
if (safeWidth >= shortSuffix.length + 5) {
|
|
98
|
+
return `${truncateToWidth(body, safeWidth - shortSuffix.length, "…")}${this.theme.fg("muted", shortSuffix)}`;
|
|
99
|
+
}
|
|
100
|
+
return truncateToWidth(this.theme.fg("muted", shortSuffix.trim()), safeWidth, "…");
|
|
101
|
+
});
|
|
102
|
+
this.rendered = { width: safeWidth, lines: rendered };
|
|
103
|
+
return rendered;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
invalidate(): void {
|
|
107
|
+
this.rendered = null;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
40
111
|
class CollapsibleText implements Component {
|
|
41
112
|
private readonly fullText: Text;
|
|
42
113
|
private readonly footerText: Text;
|
|
@@ -47,8 +118,8 @@ class CollapsibleText implements Component {
|
|
|
47
118
|
private readonly text: string,
|
|
48
119
|
private readonly expanded: boolean,
|
|
49
120
|
private readonly maxCollapsedLines: number,
|
|
50
|
-
|
|
51
|
-
|
|
121
|
+
ellipsis: string,
|
|
122
|
+
expandHint: string,
|
|
52
123
|
private readonly preTruncated = false,
|
|
53
124
|
) {
|
|
54
125
|
this.fullText = new Text(text, 0, 0);
|
|
@@ -168,13 +239,52 @@ function renderToolCallLines(lines: string[], theme?: RenderTheme) {
|
|
|
168
239
|
return new Text([styledTitle, ...styledRest].join("\n"), 0, 0);
|
|
169
240
|
}
|
|
170
241
|
|
|
171
|
-
export function
|
|
172
|
-
|
|
242
|
+
export function resolveMcpToolRenderOptions(settings?: McpToolRenderSettings): McpToolRenderOptions {
|
|
243
|
+
const resultRendering = settings?.toolResultRendering === "boxed" ? "boxed" : "compact";
|
|
244
|
+
const collapsedLines = settings?.collapsedResultLines;
|
|
245
|
+
const defaultLines = resultRendering === "boxed" ? DEFAULT_BOXED_COLLAPSED_LINES : DEFAULT_COMPACT_COLLAPSED_LINES;
|
|
246
|
+
return {
|
|
247
|
+
resultRendering,
|
|
248
|
+
collapsedResultLines: collapsedLines === 1 || collapsedLines === 2 || collapsedLines === 3 ? collapsedLines : defaultLines,
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function shouldUseCompactFinalRender(options: McpToolRenderOptions, context?: McpToolRenderContext): boolean {
|
|
253
|
+
return options.resultRendering === "compact"
|
|
254
|
+
&& context !== undefined
|
|
255
|
+
&& context.isPartial === false
|
|
256
|
+
&& context.expanded !== true
|
|
257
|
+
&& context.isError !== true;
|
|
173
258
|
}
|
|
174
259
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
260
|
+
function renderToolCall(
|
|
261
|
+
lines: string[],
|
|
262
|
+
theme: RenderTheme | undefined,
|
|
263
|
+
context: McpToolRenderContext | undefined,
|
|
264
|
+
options: McpToolRenderOptions,
|
|
265
|
+
) {
|
|
266
|
+
if (context?.state) context.state.compactTitle = lines[0] ?? "mcp";
|
|
267
|
+
if (shouldUseCompactFinalRender(options, context)) return new EmptyComponent();
|
|
268
|
+
return renderToolCallLines(lines, theme);
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
export function renderMcpProxyToolCall(
|
|
272
|
+
args: McpProxyToolCallInput,
|
|
273
|
+
theme?: RenderTheme,
|
|
274
|
+
context?: McpToolRenderContext,
|
|
275
|
+
) {
|
|
276
|
+
return renderToolCall(formatMcpProxyToolCallLines(args), theme, context, resolveMcpToolRenderOptions());
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
export function createMcpProxyToolCallRenderer(options: McpToolRenderOptions) {
|
|
280
|
+
return (args: McpProxyToolCallInput, theme?: RenderTheme, context?: McpToolRenderContext) => {
|
|
281
|
+
return renderToolCall(formatMcpProxyToolCallLines(args), theme, context, options);
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
export function createMcpDirectToolCallRenderer(displayName: string, options = resolveMcpToolRenderOptions()) {
|
|
286
|
+
return (args: Record<string, unknown>, theme?: RenderTheme, context?: McpToolRenderContext) => {
|
|
287
|
+
return renderToolCall(formatMcpDirectToolCallLines(displayName, args), theme, context, options);
|
|
178
288
|
};
|
|
179
289
|
}
|
|
180
290
|
|
|
@@ -254,7 +364,7 @@ export function formatMcpToolResultIdentity(details: McpToolResultDetails | unde
|
|
|
254
364
|
export function formatMcpToolResultLines(
|
|
255
365
|
result: Pick<AgentToolResult<McpToolResultDetails>, "content">,
|
|
256
366
|
expanded: boolean,
|
|
257
|
-
maxCollapsedLines =
|
|
367
|
+
maxCollapsedLines = DEFAULT_BOXED_COLLAPSED_LINES,
|
|
258
368
|
maxCollapsedChars = DEFAULT_MAX_COLLAPSED_CHARS,
|
|
259
369
|
): McpToolResultDisplay {
|
|
260
370
|
if (!expanded) {
|
|
@@ -271,6 +381,7 @@ export function renderMcpToolResult(
|
|
|
271
381
|
options: ToolRenderResultOptions,
|
|
272
382
|
theme?: RenderTheme,
|
|
273
383
|
context?: McpToolRenderContext,
|
|
384
|
+
renderOptions = resolveMcpToolRenderOptions(),
|
|
274
385
|
) {
|
|
275
386
|
const activeTheme = theme ?? plainTheme;
|
|
276
387
|
if (options.isPartial) {
|
|
@@ -279,7 +390,13 @@ export function renderMcpToolResult(
|
|
|
279
390
|
|
|
280
391
|
const hasErrorDetails = Boolean(result.details.error);
|
|
281
392
|
const expanded = options.expanded || context?.isError === true || hasErrorDetails;
|
|
282
|
-
|
|
393
|
+
if (!expanded && renderOptions.resultRendering === "compact") {
|
|
394
|
+
const display = formatMcpToolResultLines(result, false, renderOptions.collapsedResultLines);
|
|
395
|
+
const title = context?.state?.compactTitle ?? formatMcpToolResultIdentity(result.details) ?? "";
|
|
396
|
+
return new CompactMcpToolResult(title, display, activeTheme);
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
const display = formatMcpToolResultLines(result, expanded, renderOptions.collapsedResultLines);
|
|
283
400
|
const identity = formatMcpToolResultIdentity(result.details);
|
|
284
401
|
const output = [
|
|
285
402
|
...(identity ? [activeTheme.fg("muted", identity)] : []),
|
|
@@ -289,9 +406,18 @@ export function renderMcpToolResult(
|
|
|
289
406
|
return new CollapsibleText(
|
|
290
407
|
output,
|
|
291
408
|
expanded,
|
|
292
|
-
|
|
409
|
+
renderOptions.collapsedResultLines + (identity ? 1 : 0),
|
|
293
410
|
activeTheme.fg("muted", "…"),
|
|
294
411
|
activeTheme.fg("muted", "(Ctrl+O to expand)"),
|
|
295
412
|
display.truncated,
|
|
296
413
|
);
|
|
297
414
|
}
|
|
415
|
+
|
|
416
|
+
export function createMcpToolResultRenderer(renderOptions: McpToolRenderOptions) {
|
|
417
|
+
return (
|
|
418
|
+
result: AgentToolResult<McpToolResultDetails>,
|
|
419
|
+
options: ToolRenderResultOptions,
|
|
420
|
+
theme?: RenderTheme,
|
|
421
|
+
context?: McpToolRenderContext,
|
|
422
|
+
) => renderMcpToolResult(result, options, theme, context, renderOptions);
|
|
423
|
+
}
|