@herbertgao/pi-extensions 2026.8.5 → 2026.8.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -5
- package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +2 -2
- package/node_modules/@herbertgao/pi-cc-extensions/README.md +2 -2
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +19 -7
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +30 -9
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/compact-thinking.ts +272 -22
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/context.ts +74 -5
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +94 -77
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/markdown-enhance.ts +48 -6
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/message-display.ts +1 -1
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/hover.ts +14 -0
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/interaction.ts +55 -17
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/layout.ts +41 -2
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-renderer.ts +75 -6
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/types.ts +7 -3
- package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/grouping.ts +64 -1
- package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
- package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +16 -0
- package/node_modules/@herbertgao/pi-subagents/README.md +30 -22
- package/node_modules/@herbertgao/pi-subagents/examples/agent-tool-description.md +5 -5
- package/node_modules/@herbertgao/pi-subagents/package.json +7 -7
- package/node_modules/@herbertgao/pi-subagents/src/agent-file-toggle.ts +7 -1
- package/node_modules/@herbertgao/pi-subagents/src/agent-manager.ts +48 -19
- package/node_modules/@herbertgao/pi-subagents/src/agent-runner.ts +22 -15
- package/node_modules/@herbertgao/pi-subagents/src/custom-agents.ts +26 -2
- package/node_modules/@herbertgao/pi-subagents/src/index.ts +219 -40
- package/node_modules/@herbertgao/pi-subagents/src/invocation-config.ts +101 -3
- package/node_modules/@herbertgao/pi-subagents/src/nested-tools.ts +18 -4
- package/node_modules/@herbertgao/pi-subagents/src/settings.ts +99 -0
- package/node_modules/@herbertgao/pi-subagents/src/types.ts +22 -3
- package/node_modules/@herbertgao/pi-subagents/src/ui/agent-widget.ts +51 -3
- package/node_modules/@herbertgao/pi-subagents/src/ui/conversation-viewer.ts +20 -2
- package/node_modules/@herbertgao/pi-subagents/src/ui/fleet-list.ts +34 -10
- package/node_modules/@herbertgao/pi-subagents/src/usage.ts +129 -1
- package/node_modules/@herbertgao/pi-subagents/src/worktree.ts +29 -5
- package/node_modules/@juicesharp/rpiv-ask-user-question/README.md +3 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/ask-user-question.ts +46 -10
- package/node_modules/@juicesharp/rpiv-ask-user-question/config.ts +25 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/configuration.md +13 -4
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/hosts.md +8 -1
- package/node_modules/@juicesharp/rpiv-ask-user-question/docs/localization.md +3 -1
- package/node_modules/@juicesharp/rpiv-ask-user-question/locales/en.json +2 -2
- package/node_modules/@juicesharp/rpiv-ask-user-question/locales/zh.json +2 -2
- package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +3 -2
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/build-questionnaire.ts +10 -0
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/key-router.ts +3 -1
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/questionnaire-session.ts +30 -7
- package/node_modules/@juicesharp/rpiv-ask-user-question/state/state.ts +14 -6
- package/node_modules/@juicesharp/rpiv-ask-user-question/view/dialog-builder.ts +30 -4
- package/node_modules/@juicesharp/rpiv-ask-user-question/view/tab-content-strategy.ts +26 -5
- package/node_modules/@narumitw/pi-btw/README.md +119 -103
- package/node_modules/@narumitw/pi-btw/dist/index.ts +2898 -0
- package/node_modules/@narumitw/pi-btw/dist/index.ts.map +7 -0
- package/node_modules/@narumitw/pi-btw/package.json +13 -9
- package/node_modules/@narumitw/pi-btw/src/btw.ts +40 -42
- package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +55 -10
- package/node_modules/@narumitw/pi-btw/src/main-tree-picker.ts +390 -0
- package/node_modules/@narumitw/pi-btw/src/menu.ts +78 -15
- package/node_modules/@narumitw/pi-btw/src/settings.ts +22 -2
- package/node_modules/@narumitw/pi-btw/src/transcript-pager.ts +136 -45
- package/node_modules/pi-lens/CHANGELOG.md +1004 -0
- package/node_modules/pi-lens/README.md +11 -3
- package/node_modules/pi-lens/config/ruff/core.toml +42 -0
- package/node_modules/pi-lens/dist/clients/actionable-warnings.js +130 -27
- package/node_modules/pi-lens/dist/clients/advisory-provenance.js +427 -0
- package/node_modules/pi-lens/dist/clients/agent-nudge.js +79 -16
- package/node_modules/pi-lens/dist/clients/ast-grep-client.js +9 -3
- package/node_modules/pi-lens/dist/clients/atomic-write.js +9 -3
- package/node_modules/pi-lens/dist/clients/bash-file-access.js +285 -8
- package/node_modules/pi-lens/dist/clients/biome-client.js +176 -37
- package/node_modules/pi-lens/dist/clients/blocker-freshness.js +428 -0
- package/node_modules/pi-lens/dist/clients/blocker-past-eof.js +119 -0
- package/node_modules/pi-lens/dist/clients/bootstrap.js +12 -1
- package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +12 -3
- package/node_modules/pi-lens/dist/clients/bounded-telemetry.js +192 -0
- package/node_modules/pi-lens/dist/clients/bus-events-logger.js +62 -6
- package/node_modules/pi-lens/dist/clients/bus-publish.js +11 -3
- package/node_modules/pi-lens/dist/clients/cascade-budget.js +196 -0
- package/node_modules/pi-lens/dist/clients/cascade-format.js +76 -2
- package/node_modules/pi-lens/dist/clients/cascade-types.js +9 -1
- package/node_modules/pi-lens/dist/clients/child-unref.js +54 -6
- package/node_modules/pi-lens/dist/clients/code-quality-warnings.js +76 -24
- package/node_modules/pi-lens/dist/clients/console-guard-install.js +16 -4
- package/node_modules/pi-lens/dist/clients/dead-code-client.js +249 -52
- package/node_modules/pi-lens/dist/clients/deadline-utils.js +8 -1
- package/node_modules/pi-lens/dist/clients/debug-handles.js +5 -0
- package/node_modules/pi-lens/dist/clients/degradation-ledger.js +62 -13
- package/node_modules/pi-lens/dist/clients/dependency-checker.js +43 -9
- package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +153 -37
- package/node_modules/pi-lens/dist/clients/diagnostic-line-freshness.js +298 -0
- package/node_modules/pi-lens/dist/clients/diagnostics-publish.js +10 -3
- package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +165 -11
- package/node_modules/pi-lens/dist/clients/dispatch/integration.js +325 -72
- package/node_modules/pi-lens/dist/clients/dispatch/lazy.js +7 -4
- package/node_modules/pi-lens/dist/clients/dispatch/plan.js +5 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +234 -18
- package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +187 -19
- package/node_modules/pi-lens/dist/clients/dispatch/runners/cpp-check.js +6 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/credo.js +11 -9
- package/node_modules/pi-lens/dist/clients/dispatch/runners/cue-vet.js +398 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/elixir-check.js +11 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +12 -7
- package/node_modules/pi-lens/dist/clients/dispatch/runners/go-vet.js +18 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-render.js +895 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/index.js +4 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/javac.js +16 -3
- package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +81 -41
- package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +16 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +23 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +331 -55
- package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +38 -5
- package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +97 -19
- package/node_modules/pi-lens/dist/clients/dispatch/runners/spellcheck.js +14 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +20 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +22 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/swiftlint.js +10 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +18 -6
- package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +73 -12
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +488 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +84 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/lazy-installer.js +260 -27
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +943 -93
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +86 -11
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/tool-failure.js +72 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +106 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/vale.js +9 -0
- package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +18 -1
- package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +4 -2
- package/node_modules/pi-lens/dist/clients/disposition-publish.js +10 -3
- package/node_modules/pi-lens/dist/clients/eval-timestamp.js +17 -0
- package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +28 -5
- package/node_modules/pi-lens/dist/clients/extension-log.js +317 -3
- package/node_modules/pi-lens/dist/clients/file-kinds.js +8 -2
- package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +294 -0
- package/node_modules/pi-lens/dist/clients/finding-identity.js +88 -0
- package/node_modules/pi-lens/dist/clients/fix-worklog.js +5 -1
- package/node_modules/pi-lens/dist/clients/format-events-publish.js +39 -8
- package/node_modules/pi-lens/dist/clients/formatters-lazy.js +3 -2
- package/node_modules/pi-lens/dist/clients/formatters.js +500 -115
- package/node_modules/pi-lens/dist/clients/generation-guard.js +216 -0
- package/node_modules/pi-lens/dist/clients/git-guard.js +49 -21
- package/node_modules/pi-lens/dist/clients/gitleaks-client.js +181 -8
- package/node_modules/pi-lens/dist/clients/go-client.js +21 -39
- package/node_modules/pi-lens/dist/clients/govulncheck-client.js +219 -10
- package/node_modules/pi-lens/dist/clients/grammar-source.js +333 -10
- package/node_modules/pi-lens/dist/clients/host-ports.js +9 -1
- package/node_modules/pi-lens/dist/clients/installer/index.js +1119 -101
- package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh-session.js +58 -0
- package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh.js +715 -0
- package/node_modules/pi-lens/dist/clients/instance-reaper.js +643 -97
- package/node_modules/pi-lens/dist/clients/instance-registry.js +87 -17
- package/node_modules/pi-lens/dist/clients/jscpd-client.js +86 -15
- package/node_modules/pi-lens/dist/clients/knip-client.js +361 -24
- package/node_modules/pi-lens/dist/clients/language-policy.js +8 -2
- package/node_modules/pi-lens/dist/clients/language-profile.js +2 -0
- package/node_modules/pi-lens/dist/clients/latency-logger.js +487 -9
- package/node_modules/pi-lens/dist/clients/lazy-import.js +21 -0
- package/node_modules/pi-lens/dist/clients/ledger-bounds.js +21 -0
- package/node_modules/pi-lens/dist/clients/lens-events.js +56 -25
- package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +16 -0
- package/node_modules/pi-lens/dist/clients/live-bus-emitter.js +45 -2
- package/node_modules/pi-lens/dist/clients/lsp/aggregation.js +30 -4
- package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +160 -20
- package/node_modules/pi-lens/dist/clients/lsp/client.js +1666 -148
- package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +111 -0
- package/node_modules/pi-lens/dist/clients/lsp/document-drift.js +389 -0
- package/node_modules/pi-lens/dist/clients/lsp/index.js +2496 -171
- package/node_modules/pi-lens/dist/clients/lsp/inferred-project.js +215 -0
- package/node_modules/pi-lens/dist/clients/lsp/jvm-runtime.js +146 -14
- package/node_modules/pi-lens/dist/clients/lsp/language.js +48 -4
- package/node_modules/pi-lens/dist/clients/lsp/server.js +517 -69
- package/node_modules/pi-lens/dist/clients/lsp/spawn-history.js +22 -0
- package/node_modules/pi-lens/dist/clients/lsp/sync-kind.js +43 -0
- package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +172 -0
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/classification.js +21 -5
- package/node_modules/pi-lens/dist/clients/lsp/wait-policy/strategies.js +61 -3
- package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +422 -28
- package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-session.js +30 -0
- package/node_modules/pi-lens/dist/clients/lsp/workspace-sweep-hold.js +175 -0
- package/node_modules/pi-lens/dist/clients/lsp-lazy.js +3 -2
- package/node_modules/pi-lens/dist/clients/mcp/analyze.js +4 -0
- package/node_modules/pi-lens/dist/clients/mcp/session.js +39 -18
- package/node_modules/pi-lens/dist/clients/model-provider.js +53 -0
- package/node_modules/pi-lens/dist/clients/module-report.js +8 -0
- package/node_modules/pi-lens/dist/clients/opengrep-client.js +15 -1
- package/node_modules/pi-lens/dist/clients/package-manager.js +170 -14
- package/node_modules/pi-lens/dist/clients/path-attribution-telemetry.js +27 -0
- package/node_modules/pi-lens/dist/clients/path-utils.js +160 -0
- package/node_modules/pi-lens/dist/clients/pipeline.js +178 -30
- package/node_modules/pi-lens/dist/clients/post-autofix-notice.js +37 -0
- package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +17 -3
- package/node_modules/pi-lens/dist/clients/project-diagnostics/extractors.js +89 -22
- package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +85 -15
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/gitleaks.js +15 -3
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/runner-findings.js +23 -2
- package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/trivy.js +50 -2
- package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +5 -0
- package/node_modules/pi-lens/dist/clients/project-lens-config.js +3 -0
- package/node_modules/pi-lens/dist/clients/project-snapshot.js +299 -0
- package/node_modules/pi-lens/dist/clients/quiet-window-config.js +47 -0
- package/node_modules/pi-lens/dist/clients/quiet-window.js +11 -25
- package/node_modules/pi-lens/dist/clients/read-guard-logger.js +1 -1
- package/node_modules/pi-lens/dist/clients/read-guard.js +184 -10
- package/node_modules/pi-lens/dist/clients/resource-sampler.js +49 -17
- package/node_modules/pi-lens/dist/clients/reverse-deps.js +50 -11
- package/node_modules/pi-lens/dist/clients/review-graph/query.js +76 -4
- package/node_modules/pi-lens/dist/clients/run-duration.js +55 -0
- package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +248 -13
- package/node_modules/pi-lens/dist/clients/runtime-context.js +112 -12
- package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +472 -61
- package/node_modules/pi-lens/dist/clients/runtime-session.js +359 -13
- package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +217 -22
- package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +269 -22
- package/node_modules/pi-lens/dist/clients/runtime-turn.js +948 -87
- package/node_modules/pi-lens/dist/clients/rust-client.js +21 -37
- package/node_modules/pi-lens/dist/clients/safe-spawn.js +220 -7
- package/node_modules/pi-lens/dist/clients/scratch-tree-policy.js +161 -0
- package/node_modules/pi-lens/dist/clients/search-read-registration.js +34 -6
- package/node_modules/pi-lens/dist/clients/security-scan-client.js +224 -8
- package/node_modules/pi-lens/dist/clients/sg-runner.js +249 -37
- package/node_modules/pi-lens/dist/clients/single-flight.js +158 -0
- package/node_modules/pi-lens/dist/clients/smells-rollup.js +18 -11
- package/node_modules/pi-lens/dist/clients/stale-marker.js +17 -0
- package/node_modules/pi-lens/dist/clients/startup-timing.js +26 -2
- package/node_modules/pi-lens/dist/clients/test-runner-client.js +574 -32
- package/node_modules/pi-lens/dist/clients/tool-event.js +56 -5
- package/node_modules/pi-lens/dist/clients/tool-policy.js +127 -20
- package/node_modules/pi-lens/dist/clients/tool-set-policy.js +76 -0
- package/node_modules/pi-lens/dist/clients/tree-sitter-cache.js +75 -1
- package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +769 -64
- package/node_modules/pi-lens/dist/clients/tree-sitter-shared.js +11 -0
- package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +90 -0
- package/node_modules/pi-lens/dist/clients/trivy-client.js +19 -1
- package/node_modules/pi-lens/dist/clients/warm-attach.js +17 -0
- package/node_modules/pi-lens/dist/clients/widget-state.js +336 -36
- package/node_modules/pi-lens/dist/clients/word-index.js +305 -33
- package/node_modules/pi-lens/dist/clients/zizmor-config.js +214 -14
- package/node_modules/pi-lens/dist/index.js +64677 -49484
- package/node_modules/pi-lens/dist/mcp/server.js +8 -2
- package/node_modules/pi-lens/dist/tools/activate-tools.js +17 -5
- package/node_modules/pi-lens/dist/tools/ast-grep-replace.js +9 -4
- package/node_modules/pi-lens/dist/tools/lens-diagnostic-mark.js +5 -2
- package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +469 -56
- package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +190 -46
- package/node_modules/pi-lens/dist/tools/lsp-navigation.js +46 -7
- package/node_modules/pi-lens/dist/tools/symbol-search.js +1 -1
- package/node_modules/pi-lens/docs/agent-guide.md +44 -14
- package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +518 -501
- package/node_modules/pi-lens/docs/dispositions.md +21 -0
- package/node_modules/pi-lens/docs/features.md +33 -6
- package/node_modules/pi-lens/docs/globalconfig.md +14 -0
- package/node_modules/pi-lens/docs/language-coverage.md +71 -5
- package/node_modules/pi-lens/docs/mcp.md +2 -2
- package/node_modules/pi-lens/docs/servercapabilities.md +4 -1
- package/node_modules/pi-lens/docs/settings.md +25 -1
- package/node_modules/pi-lens/docs/usage.md +24 -5
- package/node_modules/pi-lens/docs/word-index.md +35 -0
- package/node_modules/pi-lens/package.json +10 -6
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/no-reflect-get-js-snapshot.yml +23 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/no-reflect-get-snapshot.yml +23 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/ts-void-zero-snapshot.yml +23 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-bare-object-param-test.yml +16 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-chained-type-assertions-test.yml +22 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-compile-call-test.yml +29 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-conditional-empty-object-spread-js-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-conditional-empty-object-spread-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-dupe-class-members-test.yml +33 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-inner-html-js-test.yml +7 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-inner-html-test.yml +7 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-known-value-widening-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-non-null-assertion-test.yml +216 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-js-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-js-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-return-value-in-generator-test.yml +12 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-runtime-typeof-test.yml +33 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-server-bind-wildcard-test.yml +9 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-shape-in-symbol-names-test.yml +13 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-sql-in-code-js-test.yml +5 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-sql-in-code-test.yml +5 -1
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-laundering-test.yml +11 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-parameters-test.yml +12 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-returns-test.yml +16 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unsafe-dictionary-any-test.yml +10 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unsafe-dictionary-unknown-test.yml +8 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/redundant-unsafe-function-test.yml +35 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/require-safety-comment-for-as-unknown-as-test.yml +177 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/ts-void-zero-test.yml +1 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-await-expression-member-js.yml +13 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-await-expression-member.yml +13 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-host-path-in-win32-branch.yml +2 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-object-param.yml +60 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-chained-type-assertions.yml +66 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-compile-call.yml +63 -5
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-conditional-empty-object-spread-js.yml +21 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-conditional-empty-object-spread.yml +29 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-dupe-class-members.yml +52 -8
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-inner-html-js.yml +27 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-inner-html.yml +27 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-known-value-widening.yml +71 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-non-null-assertion.yml +316 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-raw-json-store-write.yml +7 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply-js.yml +29 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply.yml +30 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get-js.yml +41 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get.yml +42 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-return-value-in-generator.yml +22 -5
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-runtime-typeof.yml +121 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-server-bind-wildcard.yml +23 -7
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-shape-in-symbol-names.yml +68 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-sql-in-code-js.yml +41 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-sql-in-code.yml +41 -2
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-laundering.yml +32 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-parameters.yml +67 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-returns.yml +106 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unsafe-dictionary-any.yml +50 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unsafe-dictionary-unknown.yml +56 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-win32-isabsolute-for-qualification.yml +2 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/redundant-unsafe-function.yml +32 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/require-safety-comment-for-as-unknown-as.yml +184 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/rules/ts-void-zero.yml +5 -0
- package/node_modules/pi-lens/rules/ast-grep-rules/self-scan-baseline.json +5 -0
- package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +132 -1
- package/node_modules/pi-lens/scripts/download-grammars.js +25 -0
- package/node_modules/pi-lens/scripts/grammars.lock.json +9 -0
- package/node_modules/pi-lens/skills/pi-lens-ast-grep/SKILL.md +12 -11
- package/node_modules/pi-lens/skills/pi-lens-lsp-navigation/SKILL.md +22 -22
- package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/SKILL.md +87 -116
- package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/reference.md +170 -0
- package/node_modules/pi-lens/skills/pi-lens-write-tree-sitter-rule/SKILL.md +3 -1
- package/node_modules/pi-lens/vendor/grammars/tree-sitter-cue.wasm +0 -0
- package/node_modules/pi-mcp-adapter/CHANGELOG.md +49 -0
- package/node_modules/pi-mcp-adapter/README.md +51 -6
- package/node_modules/pi-mcp-adapter/agent-dir.ts +12 -4
- package/node_modules/pi-mcp-adapter/cli.js +188 -5
- package/node_modules/pi-mcp-adapter/commands.ts +128 -22
- package/node_modules/pi-mcp-adapter/config.ts +28 -10
- package/node_modules/pi-mcp-adapter/direct-tools.ts +23 -19
- package/node_modules/pi-mcp-adapter/index.ts +219 -32
- package/node_modules/pi-mcp-adapter/init.ts +36 -4
- package/node_modules/pi-mcp-adapter/lifecycle.ts +315 -24
- package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +39 -6
- package/node_modules/pi-mcp-adapter/mcp-bearer-store.ts +387 -0
- package/node_modules/pi-mcp-adapter/mcp-callback-server.ts +27 -3
- package/node_modules/pi-mcp-adapter/mcp-code.ts +4 -0
- package/node_modules/pi-mcp-adapter/mcp-panel.ts +42 -13
- package/node_modules/pi-mcp-adapter/mcp-setup-panel.ts +2 -1
- package/node_modules/pi-mcp-adapter/metadata-cache.ts +46 -25
- package/node_modules/pi-mcp-adapter/package-mcp-loader.ts +168 -0
- package/node_modules/pi-mcp-adapter/package.json +4 -1
- package/node_modules/pi-mcp-adapter/proxy-modes.ts +5 -4
- package/node_modules/pi-mcp-adapter/request-headers-command.ts +330 -0
- package/node_modules/pi-mcp-adapter/search-ranking.ts +92 -22
- package/node_modules/pi-mcp-adapter/server-manager.ts +145 -2
- package/node_modules/pi-mcp-adapter/session-recovery.ts +7 -0
- package/node_modules/pi-mcp-adapter/tool-approval.ts +15 -2
- package/node_modules/pi-mcp-adapter/tool-metadata.ts +38 -18
- package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +44 -4
- package/node_modules/pi-mcp-adapter/types.ts +95 -10
- package/node_modules/pi-mcp-adapter/ui-server.ts +18 -16
- package/node_modules/pi-mcp-adapter/utils.ts +70 -0
- package/node_modules/pi-web-access/CHANGELOG.md +37 -0
- package/node_modules/pi-web-access/README.md +38 -14
- package/node_modules/pi-web-access/anysearch.ts +4 -2
- package/node_modules/pi-web-access/auth-fetch.ts +148 -0
- package/node_modules/pi-web-access/brave.ts +16 -4
- package/node_modules/pi-web-access/chrome-cookies.ts +110 -23
- package/node_modules/pi-web-access/curator-page.ts +8 -3
- package/node_modules/pi-web-access/curator-server.ts +5 -1
- package/node_modules/pi-web-access/exa.ts +18 -7
- package/node_modules/pi-web-access/extract.ts +134 -37
- package/node_modules/pi-web-access/fetch-params.ts +17 -3
- package/node_modules/pi-web-access/firecrawl.ts +172 -12
- package/node_modules/pi-web-access/gemini-search.ts +33 -7
- package/node_modules/pi-web-access/index.ts +160 -104
- package/node_modules/pi-web-access/package.json +2 -2
- package/node_modules/pi-web-access/page-query.ts +4 -2
- package/node_modules/pi-web-access/parallel-mcp.ts +249 -0
- package/node_modules/pi-web-access/parallel.ts +2 -2
- package/node_modules/pi-web-access/query-rewrite.ts +51 -0
- package/node_modules/pi-web-access/serper.ts +211 -0
- package/node_modules/pi-web-access/summary-model-scope.ts +12 -4
- package/node_modules/pi-web-access/summary-review.ts +51 -23
- package/node_modules/pi-web-access/tavily.ts +16 -4
- package/node_modules/pi-web-access/utils.ts +87 -0
- package/node_modules/pi-web-access/valyu.ts +199 -0
- package/node_modules/pi-web-access/youtube-extract.ts +2 -2
- package/package.json +13 -13
|
@@ -12,7 +12,7 @@ export type ContextPart = {
|
|
|
12
12
|
color: "accent" | "success" | "warning" | "muted" | "dim";
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
-
type PreviewKey = "systemPrompt" | "tools" | "contextFiles" | "skills";
|
|
15
|
+
type PreviewKey = "systemPrompt" | "tools" | "toolResults" | "contextFiles" | "skills";
|
|
16
16
|
|
|
17
17
|
type ContextPreview = {
|
|
18
18
|
key: PreviewKey;
|
|
@@ -303,6 +303,48 @@ export function scaleParts(parts: ContextPart[], target: number): ContextPart[]
|
|
|
303
303
|
return scaled;
|
|
304
304
|
}
|
|
305
305
|
|
|
306
|
+
export function resolveUsedTokens(
|
|
307
|
+
usage: { tokens: number | null; percent: number | null } | undefined,
|
|
308
|
+
estimated: number,
|
|
309
|
+
contextWindow: number,
|
|
310
|
+
): number {
|
|
311
|
+
const reported = usage?.tokens;
|
|
312
|
+
const fromPercent =
|
|
313
|
+
usage?.percent !== null && usage?.percent !== undefined && contextWindow > 0
|
|
314
|
+
? Math.round((usage.percent / 100) * contextWindow)
|
|
315
|
+
: undefined;
|
|
316
|
+
let resolved = reported ?? fromPercent ?? estimated;
|
|
317
|
+
if (reported !== null && reported !== undefined && fromPercent !== undefined) {
|
|
318
|
+
const tolerance = Math.max(32, Math.round(contextWindow * 0.001));
|
|
319
|
+
if (Math.abs(reported - fromPercent) > tolerance) resolved = fromPercent;
|
|
320
|
+
}
|
|
321
|
+
if (estimated > 0 && resolved < estimated * 0.25) return estimated;
|
|
322
|
+
return resolved;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
export function capParts(parts: ContextPart[], target: number, fixedPrefix = 0): ContextPart[] {
|
|
326
|
+
const fixed = parts.slice(0, fixedPrefix);
|
|
327
|
+
const variable = parts.slice(fixedPrefix);
|
|
328
|
+
const fixedTokens = fixed.reduce((sum, part) => sum + part.tokens, 0);
|
|
329
|
+
const variableTarget = Math.max(0, target - fixedTokens);
|
|
330
|
+
const estimated = variable.reduce((sum, part) => sum + part.tokens, 0);
|
|
331
|
+
if (estimated <= variableTarget || estimated === 0) return parts;
|
|
332
|
+
if (variableTarget === 0) return [...fixed, ...variable.map((part) => ({ ...part, tokens: 0 }))];
|
|
333
|
+
let previous = 0;
|
|
334
|
+
let cumulative = 0;
|
|
335
|
+
const capped = variable.map((part, index) => {
|
|
336
|
+
cumulative += part.tokens;
|
|
337
|
+
const next =
|
|
338
|
+
index === variable.length - 1
|
|
339
|
+
? variableTarget
|
|
340
|
+
: Math.round((cumulative / estimated) * variableTarget);
|
|
341
|
+
const tokens = next - previous;
|
|
342
|
+
previous = next;
|
|
343
|
+
return { ...part, tokens };
|
|
344
|
+
});
|
|
345
|
+
return [...fixed, ...capped];
|
|
346
|
+
}
|
|
347
|
+
|
|
306
348
|
export function formatTokens(tokens: number): string {
|
|
307
349
|
if (tokens < 1_000) return String(tokens);
|
|
308
350
|
if (tokens < 100_000) return `${(tokens / 1_000).toFixed(1)}k`;
|
|
@@ -326,13 +368,14 @@ type ContextBreakdown = {
|
|
|
326
368
|
parts: ContextPart[];
|
|
327
369
|
options: SystemPromptOptions;
|
|
328
370
|
systemPrompt: string;
|
|
371
|
+
toolResults: string;
|
|
329
372
|
};
|
|
330
373
|
|
|
331
374
|
/**
|
|
332
375
|
* Single pass over prompt options + session entries. Returns options/systemPrompt
|
|
333
376
|
* so the /context UI does not re-fetch or re-stringify the same sources.
|
|
334
377
|
*/
|
|
335
|
-
function collectContextBreakdown(ctx: ExtensionCommandContext): ContextBreakdown {
|
|
378
|
+
export function collectContextBreakdown(ctx: ExtensionCommandContext): ContextBreakdown {
|
|
336
379
|
const options = (ctx.getSystemPromptOptions?.() ?? {}) as SystemPromptOptions;
|
|
337
380
|
const systemPrompt = typeof ctx.getSystemPrompt === "function" ? ctx.getSystemPrompt() : "";
|
|
338
381
|
|
|
@@ -361,12 +404,16 @@ function collectContextBreakdown(ctx: ExtensionCommandContext): ContextBreakdown
|
|
|
361
404
|
let assistant = 0;
|
|
362
405
|
let toolResults = 0;
|
|
363
406
|
let summaries = 0;
|
|
407
|
+
const toolResultPreview: string[] = [];
|
|
364
408
|
for (const entry of ctx.sessionManager.buildContextEntries()) {
|
|
365
409
|
if (entry.type === "message") {
|
|
366
410
|
const tokens = estimateTokens(entry.message);
|
|
367
411
|
if (entry.message.role === "user") user += tokens;
|
|
368
412
|
else if (entry.message.role === "assistant") assistant += tokens;
|
|
369
413
|
else toolResults += tokens;
|
|
414
|
+
if (entry.message.role === "toolResult") {
|
|
415
|
+
toolResultPreview.push(`## Tool result\n\n${JSON.stringify(entry.message, null, 2)}`);
|
|
416
|
+
}
|
|
370
417
|
} else if (entry.type === "compaction" || entry.type === "branch_summary") {
|
|
371
418
|
summaries += tokenEstimate(entry);
|
|
372
419
|
}
|
|
@@ -388,6 +435,7 @@ function collectContextBreakdown(ctx: ExtensionCommandContext): ContextBreakdown
|
|
|
388
435
|
parts: parts.filter((part) => part.tokens > 0),
|
|
389
436
|
options,
|
|
390
437
|
systemPrompt,
|
|
438
|
+
toolResults: toolResultPreview.join("\n\n") || "No tool results in the current context.",
|
|
391
439
|
};
|
|
392
440
|
}
|
|
393
441
|
|
|
@@ -398,10 +446,25 @@ export default function contextUsageExtension(pi: ExtensionAPI) {
|
|
|
398
446
|
const usage = ctx.getContextUsage();
|
|
399
447
|
const contextWindow = usage?.contextWindow ?? ctx.model?.contextWindow ?? 0;
|
|
400
448
|
const breakdown = collectContextBreakdown(ctx);
|
|
401
|
-
const
|
|
402
|
-
const
|
|
449
|
+
const estimated = breakdown.parts.reduce((sum, part) => sum + part.tokens, 0);
|
|
450
|
+
const fixedParts = breakdown.parts.filter(
|
|
451
|
+
(part) => part.label === "System prompt" || part.label === "Tools",
|
|
452
|
+
);
|
|
453
|
+
const variableParts = breakdown.parts.filter(
|
|
454
|
+
(part) => part.label !== "System prompt" && part.label !== "Tools",
|
|
455
|
+
);
|
|
456
|
+
const orderedParts = [...fixedParts, ...variableParts];
|
|
457
|
+
const fixedTokens = fixedParts.reduce((sum, part) => sum + part.tokens, 0);
|
|
458
|
+
const used = Math.max(resolveUsedTokens(usage, estimated, contextWindow), fixedTokens);
|
|
459
|
+
const parts = capParts(orderedParts, used, fixedParts.length);
|
|
460
|
+
const attributed = parts.reduce((sum, part) => sum + part.tokens, 0);
|
|
461
|
+
const other = Math.max(0, used - attributed);
|
|
403
462
|
const free = Math.max(0, contextWindow - used);
|
|
404
|
-
const allParts = [
|
|
463
|
+
const allParts = [
|
|
464
|
+
...parts,
|
|
465
|
+
{ label: "Other", tokens: other, color: "muted" as const },
|
|
466
|
+
{ label: "Free space", tokens: free, color: "dim" as const },
|
|
467
|
+
];
|
|
405
468
|
|
|
406
469
|
if (ctx.mode !== "tui") {
|
|
407
470
|
const lines = allParts.map((part) => `${part.label}: ${formatTokens(part.tokens)} tokens`);
|
|
@@ -456,6 +519,12 @@ export default function contextUsageExtension(pi: ExtensionAPI) {
|
|
|
456
519
|
title: "Tools",
|
|
457
520
|
content: toolContent.join("\n\n") || "No active tools.",
|
|
458
521
|
},
|
|
522
|
+
{
|
|
523
|
+
key: "toolResults",
|
|
524
|
+
label: "Tool results",
|
|
525
|
+
title: "Tool Results",
|
|
526
|
+
content: breakdown.toolResults,
|
|
527
|
+
},
|
|
459
528
|
{
|
|
460
529
|
key: "contextFiles",
|
|
461
530
|
label: "Context files",
|
|
@@ -331,70 +331,93 @@ function editWriteExpandedCard(theme: any): any {
|
|
|
331
331
|
);
|
|
332
332
|
}
|
|
333
333
|
|
|
334
|
-
/** compact
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
334
|
+
/** compact 展开卡:保留本地嵌套工具背景,并记录 thinking 的点击行区间。 */
|
|
335
|
+
function layoutExpandedToolCard(
|
|
336
|
+
theme: any,
|
|
337
|
+
children: any[],
|
|
338
|
+
width: number,
|
|
339
|
+
): { lines: string[]; hits: Array<{ child: any; start: number; end: number }> } {
|
|
338
340
|
const slot = "userMessageBg";
|
|
339
341
|
const toolBgAnsi = darkenBgAnsi(theme, slot);
|
|
342
|
+
const innerWidth = Math.max(0, width - 2);
|
|
343
|
+
const lines: string[] = [];
|
|
344
|
+
const hits: Array<{ child: any; start: number; end: number }> = [];
|
|
345
|
+
lines.push(paddedBackgroundRow(theme, slot, "", width));
|
|
346
|
+
let skipLeadingBlank = true;
|
|
347
|
+
for (const child of children) {
|
|
348
|
+
const childLines = child.render(innerWidth);
|
|
349
|
+
if (!child.__ccToolCard) {
|
|
350
|
+
let start = 0;
|
|
351
|
+
if (skipLeadingBlank) {
|
|
352
|
+
while (start < childLines.length && !hasVisibleText(childLines[start])) start++;
|
|
353
|
+
skipLeadingBlank = false;
|
|
354
|
+
}
|
|
355
|
+
const rangeStart = lines.length;
|
|
356
|
+
for (let i = start; i < childLines.length; i++) {
|
|
357
|
+
lines.push(paddedBackgroundRow(theme, slot, childLines[i], width));
|
|
358
|
+
}
|
|
359
|
+
if (lines.length > rangeStart) hits.push({ child, start: rangeStart, end: lines.length });
|
|
360
|
+
continue;
|
|
361
|
+
}
|
|
362
|
+
skipLeadingBlank = false;
|
|
363
|
+
let first = -1;
|
|
364
|
+
let last = -1;
|
|
365
|
+
for (let i = 0; i < childLines.length; i++) {
|
|
366
|
+
if (hasVisibleText(childLines[i])) {
|
|
367
|
+
if (first < 0) first = i;
|
|
368
|
+
last = i;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
if (first < 0) {
|
|
372
|
+
for (const line of childLines) {
|
|
373
|
+
lines.push(paddedBackgroundRow(theme, slot, line, width));
|
|
374
|
+
}
|
|
375
|
+
continue;
|
|
376
|
+
}
|
|
377
|
+
lines.push(paddedBackgroundRow(theme, slot, "", width));
|
|
378
|
+
lines.push(toolCardBgRow(theme, slot, toolBgAnsi, "", width));
|
|
379
|
+
for (let i = first; i <= last; i++) {
|
|
380
|
+
lines.push(toolCardBgRow(theme, slot, toolBgAnsi, childLines[i], width));
|
|
381
|
+
}
|
|
382
|
+
lines.push(toolCardBgRow(theme, slot, toolBgAnsi, "", width));
|
|
383
|
+
}
|
|
384
|
+
lines.push(paddedBackgroundRow(theme, slot, "", width));
|
|
385
|
+
return { lines, hits };
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
function compactRoundCard(
|
|
389
|
+
cardItems: Array<{ child?: any; tool?: any }>,
|
|
390
|
+
toolRender: (tool: any, width: number) => string[],
|
|
391
|
+
): any {
|
|
340
392
|
const children: any[] = [];
|
|
393
|
+
for (const item of cardItems) {
|
|
394
|
+
if (item.child) children.push(item.child);
|
|
395
|
+
else if (item.tool) {
|
|
396
|
+
const tool = item.tool;
|
|
397
|
+
children.push({
|
|
398
|
+
__ccToolCard: true,
|
|
399
|
+
render: (innerWidth: number) => toolRender(tool, innerWidth),
|
|
400
|
+
invalidate: () => tool.invalidate?.(),
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
}
|
|
341
404
|
return {
|
|
342
405
|
children,
|
|
343
|
-
addChild(child: any) {
|
|
344
|
-
children.push(child);
|
|
345
|
-
},
|
|
346
|
-
addToolChild(child: any) {
|
|
347
|
-
child.__ccToolCard = true;
|
|
348
|
-
children.push(child);
|
|
349
|
-
},
|
|
350
406
|
render(width: number): string[] {
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
if (
|
|
359
|
-
let start = 0;
|
|
360
|
-
if (skipLeadingBlank) {
|
|
361
|
-
while (start < childLines.length && !hasVisibleText(childLines[start])) start++;
|
|
362
|
-
skipLeadingBlank = false;
|
|
363
|
-
}
|
|
364
|
-
for (let i = start; i < childLines.length; i++) {
|
|
365
|
-
lines.push(paddedBackgroundRow(theme, slot, childLines[i], width));
|
|
366
|
-
}
|
|
367
|
-
continue;
|
|
368
|
-
}
|
|
369
|
-
// 工具卡:前导 1 空行 + 首尾文本行之间的内容区(深色);不保留尾随,
|
|
370
|
-
// 相邻工具卡之间正好 1 空行,底部由卡片 padding 收尾。
|
|
371
|
-
skipLeadingBlank = false;
|
|
372
|
-
let first = -1;
|
|
373
|
-
let last = -1;
|
|
374
|
-
for (let i = 0; i < childLines.length; i++) {
|
|
375
|
-
if (hasVisibleText(childLines[i])) {
|
|
376
|
-
if (first < 0) first = i;
|
|
377
|
-
last = i;
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
if (first < 0) {
|
|
381
|
-
for (const line of childLines) {
|
|
382
|
-
lines.push(paddedBackgroundRow(theme, slot, line, width));
|
|
383
|
-
}
|
|
384
|
-
continue;
|
|
385
|
-
}
|
|
386
|
-
lines.push(paddedBackgroundRow(theme, slot, "", width));
|
|
387
|
-
// 子卡片内部上下各 1 行深色 padding
|
|
388
|
-
lines.push(toolCardBgRow(theme, slot, toolBgAnsi, "", width));
|
|
389
|
-
for (let i = first; i <= last; i++) {
|
|
390
|
-
lines.push(toolCardBgRow(theme, slot, toolBgAnsi, childLines[i], width));
|
|
391
|
-
}
|
|
392
|
-
lines.push(toolCardBgRow(theme, slot, toolBgAnsi, "", width));
|
|
407
|
+
return ["", ...layoutExpandedToolCard(themeOf(), children, width).lines];
|
|
408
|
+
},
|
|
409
|
+
childAtRow(localRow: number, width: number) {
|
|
410
|
+
if (localRow < 1) return null;
|
|
411
|
+
const row = localRow - 1;
|
|
412
|
+
const { hits } = layoutExpandedToolCard(themeOf(), children, width);
|
|
413
|
+
for (const hit of hits) {
|
|
414
|
+
if (row >= hit.start && row < hit.end) return hit.child;
|
|
393
415
|
}
|
|
394
|
-
|
|
395
|
-
|
|
416
|
+
return null;
|
|
417
|
+
},
|
|
418
|
+
invalidate() {
|
|
419
|
+
for (const child of children) child.invalidate?.();
|
|
396
420
|
},
|
|
397
|
-
invalidate() {},
|
|
398
421
|
};
|
|
399
422
|
}
|
|
400
423
|
|
|
@@ -930,27 +953,21 @@ export function installCompactMode(deps: CompactModeInstallDeps): CompactModeHoo
|
|
|
930
953
|
tool.updateDisplay?.();
|
|
931
954
|
}
|
|
932
955
|
}
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
return ["", ...box.render(width)];
|
|
949
|
-
},
|
|
950
|
-
invalidate() {
|
|
951
|
-
for (const child of assistantChildren) child.invalidate?.();
|
|
952
|
-
},
|
|
953
|
-
});
|
|
956
|
+
const cardItems: Array<{ child?: any; tool?: any }> = assistantChildren.map((child) => ({
|
|
957
|
+
child,
|
|
958
|
+
}));
|
|
959
|
+
const roundIds = roundToolCallIds(round);
|
|
960
|
+
for (const tool of trackedToolComponents) {
|
|
961
|
+
if (!roundIds.has(tool.toolCallId) || EDIT_WRITE_TOOLS.has(String(tool.toolName ?? ""))) {
|
|
962
|
+
continue;
|
|
963
|
+
}
|
|
964
|
+
cardItems.push({ tool });
|
|
965
|
+
}
|
|
966
|
+
round.anchor.contentContainer.addChild(
|
|
967
|
+
compactRoundCard(cardItems, (tool, innerWidth) =>
|
|
968
|
+
patch.toolOriginalRender.call(tool, innerWidth),
|
|
969
|
+
),
|
|
970
|
+
);
|
|
954
971
|
// 展开卡内工具会显示 error,外层仍挂 abort/length,避免只藏在折叠工具里。
|
|
955
972
|
appendStopStatus(round.anchor, stopStatus);
|
|
956
973
|
return;
|
|
@@ -80,14 +80,20 @@ function renderAdmonition(lines: string[], i: number): { output: string[]; next:
|
|
|
80
80
|
// 裸 URL 转可点击超链接
|
|
81
81
|
// ============================================================================
|
|
82
82
|
|
|
83
|
-
const URL_RE = /(?<!<)(?<!\]\()https?:\/\/[^\s<>'"
|
|
84
|
-
const TRIM_URL_RE = /[.,;:!?】」』"'
|
|
83
|
+
const URL_RE = /(?<!<)(?<!\]\()https?:\/\/[^\s<>'"|,。;:!?、」』】()【】《》『』「」]+/g;
|
|
84
|
+
const TRIM_URL_RE = /[.,;:!?】」』"'》)}]+$/;
|
|
85
85
|
|
|
86
86
|
/** 去掉 URL 尾部标点;括号按平衡保留(如 Wikipedia 链接含括号)。 */
|
|
87
87
|
function trimUrl(url: string): string {
|
|
88
88
|
let t = url.replace(TRIM_URL_RE, "");
|
|
89
|
-
while (
|
|
90
|
-
t
|
|
89
|
+
while (true) {
|
|
90
|
+
if (t.endsWith(")") && (t.match(/\(/g)?.length ?? 0) < (t.match(/\)/g)?.length ?? 0)) {
|
|
91
|
+
t = t.slice(0, -1);
|
|
92
|
+
} else if (t.endsWith("]") && (t.match(/\[/g)?.length ?? 0) < (t.match(/\]/g)?.length ?? 0)) {
|
|
93
|
+
t = t.slice(0, -1);
|
|
94
|
+
} else {
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
91
97
|
}
|
|
92
98
|
return t;
|
|
93
99
|
}
|
|
@@ -246,6 +252,41 @@ function deCircled(markdown: string): string {
|
|
|
246
252
|
return output.join("\n");
|
|
247
253
|
}
|
|
248
254
|
|
|
255
|
+
// ============================================================================
|
|
256
|
+
// 跨行链接规整
|
|
257
|
+
// ============================================================================
|
|
258
|
+
|
|
259
|
+
const MULTILINE_LINK_RE = /\[([^\]\n]*(?:\n[^\]\n]*)+)\](?=\()/g;
|
|
260
|
+
|
|
261
|
+
/** 防止 Markdown 跨行链接把行尾填充空格纳入 OSC 8 点击区。 */
|
|
262
|
+
function normalizeMultilineLinks(markdown: string): string {
|
|
263
|
+
const out: string[] = [];
|
|
264
|
+
let prose: string[] = [];
|
|
265
|
+
let fence: MarkdownFence | undefined;
|
|
266
|
+
const flush = () => {
|
|
267
|
+
if (prose.length === 0) return;
|
|
268
|
+
out.push(
|
|
269
|
+
prose.join("\n").replace(MULTILINE_LINK_RE, (_match, label: string) => {
|
|
270
|
+
const normalized = label.replace(/[ \t]*\n[ \t]*/g, " ").trim();
|
|
271
|
+
return `[${normalized}]`;
|
|
272
|
+
}),
|
|
273
|
+
);
|
|
274
|
+
prose = [];
|
|
275
|
+
};
|
|
276
|
+
for (const line of markdown.split("\n")) {
|
|
277
|
+
const scanned = scanMarkdownFence(line, fence);
|
|
278
|
+
fence = scanned.fence;
|
|
279
|
+
if (scanned.protected) {
|
|
280
|
+
flush();
|
|
281
|
+
out.push(line);
|
|
282
|
+
} else {
|
|
283
|
+
prose.push(line);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
flush();
|
|
287
|
+
return out.join("\n");
|
|
288
|
+
}
|
|
289
|
+
|
|
249
290
|
// ============================================================================
|
|
250
291
|
// 注册
|
|
251
292
|
// ============================================================================
|
|
@@ -255,8 +296,9 @@ export default function (pi: ExtensionAPI): void {
|
|
|
255
296
|
// 所以三个转换合并为一次注册,内部按序链式执行。
|
|
256
297
|
pi.registerMarkdownTransformer((markdown, context) => {
|
|
257
298
|
const { messageType, isStreaming = false } = context ?? {};
|
|
258
|
-
|
|
259
|
-
|
|
299
|
+
if (messageType === "assistant-thinking") return markdown;
|
|
300
|
+
markdown = normalizeMultilineLinks(markdown);
|
|
301
|
+
if (isStreaming) return markdown;
|
|
260
302
|
// 0. 圈数字转半角括号(Nerd Font 补丁字形缺陷规避)
|
|
261
303
|
markdown = deCircled(markdown);
|
|
262
304
|
// 1. Mermaid 方言渲染
|
|
@@ -135,7 +135,7 @@ export function installMessageDisplayRendering(): () => void {
|
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
/** 三个消息组件共享的结构特征;CustomMessageComponent 用 rebuild 无 updateDisplay,不命中。 */
|
|
138
|
-
function isMessageDisplayComponent(value: any): boolean {
|
|
138
|
+
export function isMessageDisplayComponent(value: any): boolean {
|
|
139
139
|
return Boolean(
|
|
140
140
|
value &&
|
|
141
141
|
typeof value === "object" &&
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ThinkingPreviewBlock } from "../../feature/compact-thinking.ts";
|
|
1
2
|
import { setHoveredCompactAssistant } from "../compact-mode.ts";
|
|
2
3
|
import {
|
|
3
4
|
isExpandedToolIoView,
|
|
@@ -43,6 +44,16 @@ export function setHoveredToolGroup(group: ToolGroupComponent | null): boolean {
|
|
|
43
44
|
return true;
|
|
44
45
|
}
|
|
45
46
|
|
|
47
|
+
let hoveredThinking: ThinkingPreviewBlock | null = null;
|
|
48
|
+
|
|
49
|
+
export function setHoveredThinking(block: ThinkingPreviewBlock | null): boolean {
|
|
50
|
+
if (block === hoveredThinking) return false;
|
|
51
|
+
hoveredThinking?.setHintHovered(false);
|
|
52
|
+
hoveredThinking = block;
|
|
53
|
+
block?.setHintHovered(true);
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
|
|
46
57
|
let hoveredToolIoView: ExpandedToolIoView | null = null;
|
|
47
58
|
let hoveredToolIoSection: ToolIoSection | null = null;
|
|
48
59
|
|
|
@@ -98,6 +109,7 @@ export function cachedFullscreenComponentAtRow(
|
|
|
98
109
|
export type FullscreenHoverTarget =
|
|
99
110
|
| { kind: "button" }
|
|
100
111
|
| { kind: "group"; component: ToolGroupComponent }
|
|
112
|
+
| { kind: "thinking"; component: ThinkingPreviewBlock }
|
|
101
113
|
| { kind: "assistant"; component: any }
|
|
102
114
|
| {
|
|
103
115
|
kind: "tool";
|
|
@@ -119,6 +131,8 @@ export function applyFullscreenHover(tui: any, target: FullscreenHoverTarget | n
|
|
|
119
131
|
}
|
|
120
132
|
const nextGroup = target?.kind === "group" ? target.component : null;
|
|
121
133
|
if (setHoveredToolGroup(nextGroup)) changed = true;
|
|
134
|
+
const nextThinking = target?.kind === "thinking" ? target.component : null;
|
|
135
|
+
if (setHoveredThinking(nextThinking)) changed = true;
|
|
122
136
|
const nextAssistant = target?.kind === "assistant" ? target.component : null;
|
|
123
137
|
if (setHoveredCompactAssistant(nextAssistant)) changed = true;
|
|
124
138
|
const nextView = target?.kind === "tool" ? target.view : null;
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { ThinkingPreviewBlock } from "../../feature/compact-thinking.ts";
|
|
1
2
|
import { hasActiveTextPreview, showTextPreview } from "../../feature/context.ts";
|
|
2
3
|
import { ToolGroupComponent } from "../tool/grouping.ts";
|
|
3
4
|
import { isCompactAssistantComponent, setHoveredCompactAssistant } from "../compact-mode.ts";
|
|
5
|
+
import { isMessageDisplayComponent } from "../message-display.ts";
|
|
4
6
|
import { config } from "../../config/config.ts";
|
|
5
7
|
import { isLazyProxyTui } from "../../utils/fullscreen-detect.ts";
|
|
6
8
|
import { setToolTuiFullscreen } from "../show-more-hint.ts";
|
|
@@ -55,6 +57,7 @@ import {
|
|
|
55
57
|
sharedToolHoverState,
|
|
56
58
|
setHoveredToolCallId,
|
|
57
59
|
setHoveredToolGroup,
|
|
60
|
+
setHoveredThinking,
|
|
58
61
|
setHoveredToolIo,
|
|
59
62
|
type FullscreenHoverTarget,
|
|
60
63
|
} from "./hover.ts";
|
|
@@ -151,6 +154,34 @@ function updateToolSummaryHover(tui: any, packet: SgrMousePacket): void {
|
|
|
151
154
|
tui.requestRender?.();
|
|
152
155
|
}
|
|
153
156
|
|
|
157
|
+
const EXPAND_PANEL_DOUBLE_CLICK_MS = 400;
|
|
158
|
+
let lastExpandPanelClick: { card: any; at: number } | null = null;
|
|
159
|
+
|
|
160
|
+
function isExpandPanelDoubleClick(card: any): boolean {
|
|
161
|
+
const now = Date.now();
|
|
162
|
+
const prev = lastExpandPanelClick;
|
|
163
|
+
lastExpandPanelClick = { card, at: now };
|
|
164
|
+
return Boolean(prev && prev.card === card && now - prev.at <= EXPAND_PANEL_DOUBLE_CLICK_MS);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function clearExpandPanelDoubleClick(): void {
|
|
168
|
+
lastExpandPanelClick = null;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function collapseExpandedCard(tui: any, card: any): boolean {
|
|
172
|
+
if (!isExpandPanelDoubleClick(card)) return false;
|
|
173
|
+
card.setExpanded(false);
|
|
174
|
+
setHoveredToolCallId(null);
|
|
175
|
+
setHoveredToolGroup(null);
|
|
176
|
+
setHoveredThinking(null);
|
|
177
|
+
setHoveredToolIo(null, null);
|
|
178
|
+
setHoveredCompactAssistant(null);
|
|
179
|
+
card.invalidate?.();
|
|
180
|
+
tui.requestRender?.();
|
|
181
|
+
clearExpandPanelDoubleClick();
|
|
182
|
+
return true;
|
|
183
|
+
}
|
|
184
|
+
|
|
154
185
|
function toggleToolAtMouseClick(tui: any, packet: SgrMousePacket): boolean {
|
|
155
186
|
const region = interactionRegionAt(packet);
|
|
156
187
|
if (!region) return false;
|
|
@@ -158,19 +189,12 @@ function toggleToolAtMouseClick(tui: any, packet: SgrMousePacket): boolean {
|
|
|
158
189
|
if (region.kind === "show-more") return tryOpenToolIoShowMore(region);
|
|
159
190
|
const component = region.component;
|
|
160
191
|
if (!component) return false;
|
|
161
|
-
|
|
162
|
-
if (region.kind === "expanded-card") {
|
|
163
|
-
component.setExpanded(false);
|
|
164
|
-
setHoveredToolCallId(null);
|
|
165
|
-
setHoveredToolGroup(null);
|
|
166
|
-
setHoveredToolIo(null, null);
|
|
167
|
-
component.invalidate?.();
|
|
168
|
-
tui.requestRender?.();
|
|
169
|
-
return true;
|
|
170
|
-
}
|
|
192
|
+
if (region.kind === "expanded-card") return collapseExpandedCard(tui, component);
|
|
171
193
|
component.setExpanded(true);
|
|
194
|
+
clearExpandPanelDoubleClick();
|
|
172
195
|
setHoveredToolCallId(null);
|
|
173
196
|
setHoveredToolGroup(null);
|
|
197
|
+
setHoveredThinking(null);
|
|
174
198
|
setHoveredToolIo(null, null);
|
|
175
199
|
component.invalidate?.();
|
|
176
200
|
tui.requestRender?.();
|
|
@@ -241,10 +265,10 @@ const FULLSCREEN_VIEWPORT_PATCH = Symbol("ccstyle.fullscreen-viewport-patch");
|
|
|
241
265
|
const FULLSCREEN_WHEEL_SCROLL_ORIGINAL = Symbol("ccstyle.fullscreen-wheel-scroll-original");
|
|
242
266
|
|
|
243
267
|
/**
|
|
244
|
-
* 官方 fullscreen 工具卡点击:collapsed hint
|
|
245
|
-
* (有且仅保持一个展开:展开前收起其他工具卡),expanded
|
|
246
|
-
* 截断头 show-more
|
|
247
|
-
* 滚动条列、含 OSC8
|
|
268
|
+
* 官方 fullscreen 工具卡点击:collapsed hint 单击展开
|
|
269
|
+
* (有且仅保持一个展开:展开前收起其他工具卡),expanded 整卡双击收起,
|
|
270
|
+
* 截断头 show-more 单击打开全量预览;回到底部按钮 scrollToBottom。
|
|
271
|
+
* 滚动条列、含 OSC8 链接行、非工具区域、展开卡单击放行官方。
|
|
248
272
|
*/
|
|
249
273
|
function handleFullscreenToolClick(tui: any, packet: SgrMousePacket): boolean {
|
|
250
274
|
const layout = tui.currentLayout;
|
|
@@ -274,7 +298,9 @@ function handleFullscreenToolClick(tui: any, packet: SgrMousePacket): boolean {
|
|
|
274
298
|
const isTool = isToolExecutionComponent(component);
|
|
275
299
|
const isGroup = component instanceof ToolGroupComponent;
|
|
276
300
|
const isAssistant = isCompactAssistantComponent(component);
|
|
277
|
-
|
|
301
|
+
const isThinking = component instanceof ThinkingPreviewBlock;
|
|
302
|
+
const isMessage = isMessageDisplayComponent(component);
|
|
303
|
+
if (!isTool && !isGroup && !isAssistant && !isThinking && !isMessage) return false;
|
|
278
304
|
if (!component.expanded) {
|
|
279
305
|
// collapsed 仅按钮文本可展开,不能把同一行正文/留白变成点击区。
|
|
280
306
|
const hint = collapsedHintHitbox(line);
|
|
@@ -284,11 +310,14 @@ function handleFullscreenToolClick(tui: any, packet: SgrMousePacket): boolean {
|
|
|
284
310
|
collectFullscreenToolCards(hit.box.component, others);
|
|
285
311
|
for (const other of others) {
|
|
286
312
|
if (other !== component && other.expanded) {
|
|
313
|
+
// 展开 round 内 thinking 时不要把外层 compact 卡收起。
|
|
314
|
+
if (isThinking && isCompactAssistantComponent(other)) continue;
|
|
287
315
|
other.setExpanded(false);
|
|
288
316
|
other.invalidate?.();
|
|
289
317
|
}
|
|
290
318
|
}
|
|
291
319
|
component.setExpanded(true);
|
|
320
|
+
clearExpandPanelDoubleClick();
|
|
292
321
|
} else {
|
|
293
322
|
// 普通工具截断头 show-more:打开全量预览(不收起)。
|
|
294
323
|
const view = isTool ? component.resultRendererComponent : null;
|
|
@@ -310,12 +339,13 @@ function handleFullscreenToolClick(tui: any, packet: SgrMousePacket): boolean {
|
|
|
310
339
|
}
|
|
311
340
|
}
|
|
312
341
|
}
|
|
313
|
-
//
|
|
314
|
-
card
|
|
342
|
+
// 双击收起:内部工具仍归所属 group。单击放行官方(选择/链接)。
|
|
343
|
+
return collapseExpandedCard(tui, card);
|
|
315
344
|
}
|
|
316
345
|
// 点击后清 hover 高亮。
|
|
317
346
|
setHoveredToolCallId(null);
|
|
318
347
|
setHoveredToolGroup(null);
|
|
348
|
+
setHoveredThinking(null);
|
|
319
349
|
setHoveredToolIo(null, null);
|
|
320
350
|
setHoveredCompactAssistant(null);
|
|
321
351
|
card.invalidate?.();
|
|
@@ -361,6 +391,8 @@ function handleFullscreenToolHover(tui: any, packet: SgrMousePacket): void {
|
|
|
361
391
|
);
|
|
362
392
|
if (component instanceof ToolGroupComponent) {
|
|
363
393
|
if (overHint) target = { kind: "group", component };
|
|
394
|
+
} else if (component instanceof ThinkingPreviewBlock) {
|
|
395
|
+
if (component.expanded || overHint) target = { kind: "thinking", component };
|
|
364
396
|
} else if (isToolExecutionComponent(component)) {
|
|
365
397
|
let view: ExpandedToolIoView | null = null;
|
|
366
398
|
let section: ToolIoSection | null = null;
|
|
@@ -384,6 +416,9 @@ function handleFullscreenToolHover(tui: any, packet: SgrMousePacket): void {
|
|
|
384
416
|
} else if (isCompactAssistantComponent(component)) {
|
|
385
417
|
// compact 摘要行:折叠时仅提示文字高亮,展开卡整体高亮。
|
|
386
418
|
if (component.expanded || overHint) target = { kind: "assistant", component };
|
|
419
|
+
} else if (isMessageDisplayComponent(component)) {
|
|
420
|
+
// skill/compaction/branch:折叠只点 hint;展开后双击收起。
|
|
421
|
+
if (component.expanded || overHint) target = { kind: "assistant", component };
|
|
387
422
|
}
|
|
388
423
|
}
|
|
389
424
|
}
|
|
@@ -779,8 +814,10 @@ export function teardownToolMouseInteraction(
|
|
|
779
814
|
toolMouseInputUnsubscribe = null;
|
|
780
815
|
setHoveredToolCallId(null);
|
|
781
816
|
setHoveredToolGroup(null);
|
|
817
|
+
setHoveredThinking(null);
|
|
782
818
|
setHoveredToolIo(null, null);
|
|
783
819
|
setHoveredCompactAssistant(null);
|
|
820
|
+
clearExpandPanelDoubleClick();
|
|
784
821
|
try {
|
|
785
822
|
if (isLazyProxyTui(getToolMouseTui())) releaseFullscreenToolMouseMotion(getToolMouseTui());
|
|
786
823
|
else getToolMouseTui()?.terminal?.write?.(TOOL_MOUSE_DISABLE);
|
|
@@ -804,6 +841,7 @@ export function teardownToolMouseInteraction(
|
|
|
804
841
|
/** off 模式清理:清空 hover 与回到底部按钮状态(跨模块 rebind 统一经由此函数)。 */
|
|
805
842
|
export function resetToolHoverState(): void {
|
|
806
843
|
setHoveredToolCallId(null);
|
|
844
|
+
setHoveredThinking(null);
|
|
807
845
|
setHoveredCompactAssistant(null);
|
|
808
846
|
setScrollButtonVisible(false);
|
|
809
847
|
setScrollButtonHovered(false);
|