@herbertgao/pi-extensions 2026.8.6 → 2026.8.8

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.
Files changed (385) hide show
  1. package/README.md +8 -6
  2. package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +2 -2
  3. package/node_modules/@herbertgao/pi-cc-extensions/README.md +2 -2
  4. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +19 -7
  5. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +30 -9
  6. package/node_modules/@herbertgao/pi-cc-extensions/extensions/feature/compact-thinking.ts +320 -22
  7. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/compact-mode.ts +94 -77
  8. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/message-display.ts +79 -17
  9. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/hover.ts +27 -0
  10. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/interaction.ts +66 -17
  11. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/layout.ts +41 -2
  12. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/diff-renderer.ts +75 -6
  13. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/diff/types.ts +7 -3
  14. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/grouping.ts +64 -1
  15. package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
  16. package/node_modules/@herbertgao/pi-subagents/CHANGELOG.md +6 -0
  17. package/node_modules/@herbertgao/pi-subagents/README.md +30 -22
  18. package/node_modules/@herbertgao/pi-subagents/examples/agent-tool-description.md +5 -5
  19. package/node_modules/@herbertgao/pi-subagents/package.json +7 -7
  20. package/node_modules/@herbertgao/pi-subagents/src/agent-file-toggle.ts +7 -1
  21. package/node_modules/@herbertgao/pi-subagents/src/agent-manager.ts +48 -19
  22. package/node_modules/@herbertgao/pi-subagents/src/agent-runner.ts +17 -13
  23. package/node_modules/@herbertgao/pi-subagents/src/custom-agents.ts +26 -2
  24. package/node_modules/@herbertgao/pi-subagents/src/index.ts +219 -40
  25. package/node_modules/@herbertgao/pi-subagents/src/invocation-config.ts +101 -3
  26. package/node_modules/@herbertgao/pi-subagents/src/nested-tools.ts +18 -4
  27. package/node_modules/@herbertgao/pi-subagents/src/settings.ts +99 -0
  28. package/node_modules/@herbertgao/pi-subagents/src/types.ts +22 -3
  29. package/node_modules/@herbertgao/pi-subagents/src/ui/agent-widget.ts +51 -3
  30. package/node_modules/@herbertgao/pi-subagents/src/ui/conversation-viewer.ts +20 -2
  31. package/node_modules/@herbertgao/pi-subagents/src/ui/fleet-list.ts +21 -6
  32. package/node_modules/@herbertgao/pi-subagents/src/usage.ts +129 -1
  33. package/node_modules/@herbertgao/pi-subagents/src/worktree.ts +20 -0
  34. package/node_modules/@juicesharp/rpiv-ask-user-question/README.md +5 -4
  35. package/node_modules/@juicesharp/rpiv-ask-user-question/ask-user-question.ts +174 -100
  36. package/node_modules/@juicesharp/rpiv-ask-user-question/config.ts +25 -0
  37. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/configuration.md +13 -4
  38. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/hosts.md +5 -1
  39. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/keyboard.md +10 -2
  40. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/localization.md +10 -6
  41. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/tool-schema.md +11 -5
  42. package/node_modules/@juicesharp/rpiv-ask-user-question/locales/en.json +5 -2
  43. package/node_modules/@juicesharp/rpiv-ask-user-question/locales/zh.json +2 -2
  44. package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +3 -2
  45. package/node_modules/@juicesharp/rpiv-ask-user-question/state/build-questionnaire.ts +10 -0
  46. package/node_modules/@juicesharp/rpiv-ask-user-question/state/key-router.ts +140 -97
  47. package/node_modules/@juicesharp/rpiv-ask-user-question/state/questionnaire-session.ts +63 -28
  48. package/node_modules/@juicesharp/rpiv-ask-user-question/state/selectors/projections.ts +22 -15
  49. package/node_modules/@juicesharp/rpiv-ask-user-question/state/state-reducer.ts +11 -1
  50. package/node_modules/@juicesharp/rpiv-ask-user-question/state/state.ts +14 -6
  51. package/node_modules/@juicesharp/rpiv-ask-user-question/tool/response-envelope.ts +11 -0
  52. package/node_modules/@juicesharp/rpiv-ask-user-question/tool/types.ts +11 -0
  53. package/node_modules/@juicesharp/rpiv-ask-user-question/view/components/multi-select-view.ts +31 -17
  54. package/node_modules/@juicesharp/rpiv-ask-user-question/view/components/preview/preview-block-renderer.ts +15 -6
  55. package/node_modules/@juicesharp/rpiv-ask-user-question/view/components/wrapping-select.ts +15 -6
  56. package/node_modules/@juicesharp/rpiv-ask-user-question/view/dialog-builder.ts +86 -38
  57. package/node_modules/@juicesharp/rpiv-ask-user-question/view/tab-content-strategy.ts +76 -9
  58. package/node_modules/@narumitw/pi-btw/README.md +120 -111
  59. package/node_modules/@narumitw/pi-btw/dist/index.ts +2898 -0
  60. package/node_modules/@narumitw/pi-btw/dist/index.ts.map +7 -0
  61. package/node_modules/@narumitw/pi-btw/package.json +10 -6
  62. package/node_modules/@narumitw/pi-btw/src/btw.ts +36 -40
  63. package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +55 -10
  64. package/node_modules/@narumitw/pi-btw/src/main-tree-picker.ts +390 -0
  65. package/node_modules/@narumitw/pi-btw/src/menu.ts +45 -2
  66. package/node_modules/@narumitw/pi-btw/src/transcript-pager.ts +136 -45
  67. package/node_modules/@pi-plugins/fast-mode/dist/index.mjs +44 -1856
  68. package/node_modules/@pi-plugins/fast-mode/dist/index.mjs.map +1 -1
  69. package/node_modules/@pi-plugins/fast-mode/package.json +4 -6
  70. package/node_modules/pi-lens/CHANGELOG.md +999 -0
  71. package/node_modules/pi-lens/README.md +117 -3
  72. package/node_modules/pi-lens/config/ruff/core.toml +42 -0
  73. package/node_modules/pi-lens/dist/clients/actionable-warnings.js +130 -27
  74. package/node_modules/pi-lens/dist/clients/advisory-provenance.js +126 -13
  75. package/node_modules/pi-lens/dist/clients/agent-nudge.js +67 -11
  76. package/node_modules/pi-lens/dist/clients/ast-grep-client.js +9 -3
  77. package/node_modules/pi-lens/dist/clients/atomic-write.js +9 -3
  78. package/node_modules/pi-lens/dist/clients/bash-file-access.js +381 -13
  79. package/node_modules/pi-lens/dist/clients/biome-client.js +61 -30
  80. package/node_modules/pi-lens/dist/clients/blocker-freshness.js +428 -0
  81. package/node_modules/pi-lens/dist/clients/blocker-past-eof.js +129 -0
  82. package/node_modules/pi-lens/dist/clients/bootstrap.js +12 -1
  83. package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +12 -3
  84. package/node_modules/pi-lens/dist/clients/bounded-telemetry.js +206 -0
  85. package/node_modules/pi-lens/dist/clients/cache-observability.js +353 -76
  86. package/node_modules/pi-lens/dist/clients/cascade-budget.js +196 -0
  87. package/node_modules/pi-lens/dist/clients/cascade-format.js +20 -1
  88. package/node_modules/pi-lens/dist/clients/cascade-types.js +9 -1
  89. package/node_modules/pi-lens/dist/clients/child-unref.js +54 -6
  90. package/node_modules/pi-lens/dist/clients/code-quality-warnings.js +76 -24
  91. package/node_modules/pi-lens/dist/clients/dead-code-client.js +123 -31
  92. package/node_modules/pi-lens/dist/clients/deadline-utils.js +8 -1
  93. package/node_modules/pi-lens/dist/clients/debug-handles.js +5 -0
  94. package/node_modules/pi-lens/dist/clients/degradation-ledger.js +84 -14
  95. package/node_modules/pi-lens/dist/clients/demoted-finding-render.js +155 -0
  96. package/node_modules/pi-lens/dist/clients/dependency-checker.js +25 -3
  97. package/node_modules/pi-lens/dist/clients/deps/pi-tui.js +8 -2
  98. package/node_modules/pi-lens/dist/clients/deps/typebox.js +8 -3
  99. package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +147 -33
  100. package/node_modules/pi-lens/dist/clients/diagnostic-line-freshness.js +298 -0
  101. package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +52 -2
  102. package/node_modules/pi-lens/dist/clients/dispatch/integration.js +256 -88
  103. package/node_modules/pi-lens/dist/clients/dispatch/lazy.js +7 -4
  104. package/node_modules/pi-lens/dist/clients/dispatch/plan.js +5 -0
  105. package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +234 -18
  106. package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +187 -19
  107. package/node_modules/pi-lens/dist/clients/dispatch/runners/cpp-check.js +6 -3
  108. package/node_modules/pi-lens/dist/clients/dispatch/runners/credo.js +11 -9
  109. package/node_modules/pi-lens/dist/clients/dispatch/runners/cue-vet.js +398 -0
  110. package/node_modules/pi-lens/dist/clients/dispatch/runners/detekt.js +9 -6
  111. package/node_modules/pi-lens/dist/clients/dispatch/runners/elixir-check.js +11 -3
  112. package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +12 -7
  113. package/node_modules/pi-lens/dist/clients/dispatch/runners/go-vet.js +18 -0
  114. package/node_modules/pi-lens/dist/clients/dispatch/runners/hadolint.js +9 -7
  115. package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-render.js +895 -0
  116. package/node_modules/pi-lens/dist/clients/dispatch/runners/htmlhint.js +8 -6
  117. package/node_modules/pi-lens/dist/clients/dispatch/runners/index.js +4 -0
  118. package/node_modules/pi-lens/dist/clients/dispatch/runners/javac.js +16 -3
  119. package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +60 -53
  120. package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +16 -2
  121. package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +25 -2
  122. package/node_modules/pi-lens/dist/clients/dispatch/runners/oxlint.js +20 -5
  123. package/node_modules/pi-lens/dist/clients/dispatch/runners/phpstan.js +44 -11
  124. package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +331 -55
  125. package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +38 -5
  126. package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +97 -19
  127. package/node_modules/pi-lens/dist/clients/dispatch/runners/spellcheck.js +17 -8
  128. package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +32 -4
  129. package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +47 -3
  130. package/node_modules/pi-lens/dist/clients/dispatch/runners/swiftlint.js +14 -4
  131. package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +127 -28
  132. package/node_modules/pi-lens/dist/clients/dispatch/runners/tflint.js +12 -7
  133. package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +73 -12
  134. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +275 -13
  135. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +21 -6
  136. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/lazy-installer.js +260 -27
  137. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +734 -64
  138. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +86 -11
  139. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/tool-failure.js +188 -0
  140. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +9 -0
  141. package/node_modules/pi-lens/dist/clients/dispatch/runners/vale.js +21 -10
  142. package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +18 -2
  143. package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +4 -2
  144. package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +28 -5
  145. package/node_modules/pi-lens/dist/clients/extension-log.js +22 -1
  146. package/node_modules/pi-lens/dist/clients/file-kinds.js +8 -2
  147. package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +316 -0
  148. package/node_modules/pi-lens/dist/clients/finding-identity.js +88 -0
  149. package/node_modules/pi-lens/dist/clients/formatters-lazy.js +3 -2
  150. package/node_modules/pi-lens/dist/clients/formatters.js +500 -115
  151. package/node_modules/pi-lens/dist/clients/generation-guard.js +216 -0
  152. package/node_modules/pi-lens/dist/clients/git-guard.js +31 -0
  153. package/node_modules/pi-lens/dist/clients/gitleaks-client.js +181 -8
  154. package/node_modules/pi-lens/dist/clients/govulncheck-client.js +109 -9
  155. package/node_modules/pi-lens/dist/clients/grammar-source.js +333 -10
  156. package/node_modules/pi-lens/dist/clients/host-ports.js +8 -0
  157. package/node_modules/pi-lens/dist/clients/installer/index.js +1114 -100
  158. package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh-session.js +58 -0
  159. package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh.js +715 -0
  160. package/node_modules/pi-lens/dist/clients/instance-reaper.js +643 -97
  161. package/node_modules/pi-lens/dist/clients/instance-registry.js +87 -17
  162. package/node_modules/pi-lens/dist/clients/jscpd-client.js +87 -8
  163. package/node_modules/pi-lens/dist/clients/knip-client.js +310 -10
  164. package/node_modules/pi-lens/dist/clients/language-policy.js +8 -2
  165. package/node_modules/pi-lens/dist/clients/language-profile.js +9 -2
  166. package/node_modules/pi-lens/dist/clients/latency-logger.js +440 -11
  167. package/node_modules/pi-lens/dist/clients/lazy-import.js +21 -0
  168. package/node_modules/pi-lens/dist/clients/ledger-bounds.js +21 -0
  169. package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +8 -0
  170. package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +128 -8
  171. package/node_modules/pi-lens/dist/clients/lsp/client.js +1660 -164
  172. package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +83 -1
  173. package/node_modules/pi-lens/dist/clients/lsp/document-drift.js +389 -0
  174. package/node_modules/pi-lens/dist/clients/lsp/index.js +2423 -151
  175. package/node_modules/pi-lens/dist/clients/lsp/inferred-project.js +215 -0
  176. package/node_modules/pi-lens/dist/clients/lsp/jvm-runtime.js +146 -14
  177. package/node_modules/pi-lens/dist/clients/lsp/language.js +48 -4
  178. package/node_modules/pi-lens/dist/clients/lsp/server.js +277 -16
  179. package/node_modules/pi-lens/dist/clients/lsp/spawn-history.js +22 -0
  180. package/node_modules/pi-lens/dist/clients/lsp/sync-kind.js +43 -0
  181. package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +79 -3
  182. package/node_modules/pi-lens/dist/clients/lsp/wait-policy/strategies.js +43 -0
  183. package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +422 -28
  184. package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-session.js +30 -0
  185. package/node_modules/pi-lens/dist/clients/lsp/workspace-sweep-hold.js +175 -0
  186. package/node_modules/pi-lens/dist/clients/lsp-lazy.js +3 -2
  187. package/node_modules/pi-lens/dist/clients/mcp/session.js +10 -2
  188. package/node_modules/pi-lens/dist/clients/module-report.js +22 -1
  189. package/node_modules/pi-lens/dist/clients/ndjson-logger.js +114 -23
  190. package/node_modules/pi-lens/dist/clients/opengrep-client.js +15 -1
  191. package/node_modules/pi-lens/dist/clients/package-manager.js +170 -14
  192. package/node_modules/pi-lens/dist/clients/path-attribution-telemetry.js +27 -0
  193. package/node_modules/pi-lens/dist/clients/path-utils.js +160 -0
  194. package/node_modules/pi-lens/dist/clients/pipeline.js +154 -33
  195. package/node_modules/pi-lens/dist/clients/post-autofix-notice.js +37 -0
  196. package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +17 -3
  197. package/node_modules/pi-lens/dist/clients/project-diagnostics/extractors.js +89 -22
  198. package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +84 -14
  199. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/gitleaks.js +15 -3
  200. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/trivy.js +50 -2
  201. package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +23 -9
  202. package/node_modules/pi-lens/dist/clients/project-lens-config.js +3 -0
  203. package/node_modules/pi-lens/dist/clients/project-report.js +62 -27
  204. package/node_modules/pi-lens/dist/clients/project-snapshot.js +299 -0
  205. package/node_modules/pi-lens/dist/clients/quiet-window-config.js +47 -0
  206. package/node_modules/pi-lens/dist/clients/quiet-window.js +11 -25
  207. package/node_modules/pi-lens/dist/clients/read-guard-logger.js +8 -3
  208. package/node_modules/pi-lens/dist/clients/read-guard.js +253 -10
  209. package/node_modules/pi-lens/dist/clients/resource-sampler.js +49 -17
  210. package/node_modules/pi-lens/dist/clients/reverse-deps.js +50 -11
  211. package/node_modules/pi-lens/dist/clients/review-graph/builder.js +194 -31
  212. package/node_modules/pi-lens/dist/clients/review-graph/query.js +52 -4
  213. package/node_modules/pi-lens/dist/clients/review-graph/revision-drift.js +21 -0
  214. package/node_modules/pi-lens/dist/clients/review-graph/workspace-modules.js +6 -3
  215. package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +96 -7
  216. package/node_modules/pi-lens/dist/clients/runtime-context.js +8 -1
  217. package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +352 -45
  218. package/node_modules/pi-lens/dist/clients/runtime-session.js +373 -9
  219. package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +217 -22
  220. package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +212 -79
  221. package/node_modules/pi-lens/dist/clients/runtime-turn.js +620 -67
  222. package/node_modules/pi-lens/dist/clients/safe-spawn.js +220 -7
  223. package/node_modules/pi-lens/dist/clients/scratch-tree-policy.js +161 -0
  224. package/node_modules/pi-lens/dist/clients/search-read-registration.js +34 -6
  225. package/node_modules/pi-lens/dist/clients/security-scan-client.js +157 -24
  226. package/node_modules/pi-lens/dist/clients/session-event-guard.js +184 -0
  227. package/node_modules/pi-lens/dist/clients/sg-runner.js +116 -22
  228. package/node_modules/pi-lens/dist/clients/single-flight.js +158 -0
  229. package/node_modules/pi-lens/dist/clients/source-filter.js +6 -2
  230. package/node_modules/pi-lens/dist/clients/stale-marker.js +17 -0
  231. package/node_modules/pi-lens/dist/clients/startup-scan.js +5 -2
  232. package/node_modules/pi-lens/dist/clients/startup-timing.js +19 -1
  233. package/node_modules/pi-lens/dist/clients/test-runner-client.js +151 -16
  234. package/node_modules/pi-lens/dist/clients/tool-event.js +56 -5
  235. package/node_modules/pi-lens/dist/clients/tool-policy.js +125 -20
  236. package/node_modules/pi-lens/dist/clients/tree-sitter-cache.js +75 -1
  237. package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +769 -64
  238. package/node_modules/pi-lens/dist/clients/tree-sitter-logger.js +1 -0
  239. package/node_modules/pi-lens/dist/clients/tree-sitter-shared.js +11 -0
  240. package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +90 -0
  241. package/node_modules/pi-lens/dist/clients/trivy-client.js +19 -1
  242. package/node_modules/pi-lens/dist/clients/widget-state.js +336 -36
  243. package/node_modules/pi-lens/dist/clients/zizmor-config.js +214 -14
  244. package/node_modules/pi-lens/dist/index.js +61407 -48577
  245. package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +476 -57
  246. package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +132 -43
  247. package/node_modules/pi-lens/dist/tools/lsp-navigation.js +46 -7
  248. package/node_modules/pi-lens/docs/agent-guide.md +6 -1
  249. package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +515 -506
  250. package/node_modules/pi-lens/docs/dispositions.md +21 -0
  251. package/node_modules/pi-lens/docs/features.md +19 -5
  252. package/node_modules/pi-lens/docs/globalconfig.md +3 -0
  253. package/node_modules/pi-lens/docs/language-coverage.md +71 -5
  254. package/node_modules/pi-lens/docs/mcp.md +2 -2
  255. package/node_modules/pi-lens/docs/servercapabilities.md +4 -1
  256. package/node_modules/pi-lens/docs/settings.md +19 -1
  257. package/node_modules/pi-lens/docs/usage.md +1 -0
  258. package/node_modules/pi-lens/package.json +27 -10
  259. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/no-reflect-get-js-snapshot.yml +23 -0
  260. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/no-reflect-get-snapshot.yml +23 -0
  261. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/ts-void-zero-snapshot.yml +23 -0
  262. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-bare-object-param-test.yml +16 -0
  263. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-chained-type-assertions-test.yml +15 -1
  264. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-compile-call-test.yml +29 -1
  265. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-dupe-class-members-test.yml +33 -0
  266. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-inner-html-js-test.yml +7 -1
  267. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-inner-html-test.yml +7 -1
  268. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-known-value-widening-test.yml +9 -0
  269. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-non-null-assertion-test.yml +216 -0
  270. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-js-test.yml +2 -0
  271. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-test.yml +2 -0
  272. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-js-test.yml +2 -1
  273. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-test.yml +2 -1
  274. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-return-value-in-generator-test.yml +12 -0
  275. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-runtime-typeof-test.yml +33 -0
  276. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-server-bind-wildcard-test.yml +9 -0
  277. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-shape-in-symbol-names-test.yml +13 -0
  278. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-sql-in-code-js-test.yml +5 -1
  279. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-sql-in-code-test.yml +5 -1
  280. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-parameters-test.yml +12 -0
  281. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-returns-test.yml +16 -0
  282. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unsafe-dictionary-any-test.yml +10 -0
  283. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unsafe-dictionary-unknown-test.yml +8 -0
  284. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/redundant-unsafe-function-test.yml +35 -0
  285. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/require-safety-comment-for-as-unknown-as-test.yml +177 -0
  286. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/ts-void-zero-test.yml +1 -0
  287. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-await-expression-member-js.yml +13 -2
  288. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-await-expression-member.yml +13 -2
  289. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-host-path-in-win32-branch.yml +2 -0
  290. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-object-param.yml +60 -0
  291. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-chained-type-assertions.yml +57 -12
  292. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-compile-call.yml +63 -5
  293. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-dupe-class-members.yml +52 -8
  294. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-inner-html-js.yml +27 -2
  295. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-inner-html.yml +27 -2
  296. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-known-value-widening.yml +71 -0
  297. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-non-null-assertion.yml +316 -0
  298. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-raw-json-store-write.yml +7 -0
  299. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply-js.yml +22 -2
  300. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply.yml +23 -2
  301. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get-js.yml +33 -5
  302. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get.yml +34 -8
  303. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-return-value-in-generator.yml +22 -5
  304. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-runtime-typeof.yml +121 -0
  305. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-server-bind-wildcard.yml +23 -7
  306. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-shape-in-symbol-names.yml +68 -0
  307. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-sql-in-code-js.yml +41 -2
  308. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-sql-in-code.yml +41 -2
  309. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-laundering.yml +6 -1
  310. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-parameters.yml +67 -0
  311. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-returns.yml +106 -0
  312. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unsafe-dictionary-any.yml +50 -0
  313. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unsafe-dictionary-unknown.yml +56 -0
  314. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-win32-isabsolute-for-qualification.yml +2 -0
  315. package/node_modules/pi-lens/rules/ast-grep-rules/rules/redundant-unsafe-function.yml +32 -0
  316. package/node_modules/pi-lens/rules/ast-grep-rules/rules/require-safety-comment-for-as-unknown-as.yml +184 -0
  317. package/node_modules/pi-lens/rules/ast-grep-rules/rules/ts-void-zero.yml +5 -0
  318. package/node_modules/pi-lens/rules/ast-grep-rules/self-scan-baseline.json +5 -0
  319. package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +53 -1
  320. package/node_modules/pi-lens/scripts/download-grammars.js +25 -0
  321. package/node_modules/pi-lens/scripts/grammars.lock.json +9 -0
  322. package/node_modules/pi-lens/scripts/install-selftest.mjs +99 -11
  323. package/node_modules/pi-lens/scripts/lib/host-provided-deps.mjs +75 -0
  324. package/node_modules/pi-lens/scripts/lib/warm-loader-cache.mjs +285 -0
  325. package/node_modules/pi-lens/scripts/warm-loader-cache.mjs +233 -0
  326. package/node_modules/pi-lens/skills/pi-lens-ast-grep/SKILL.md +2 -0
  327. package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/SKILL.md +80 -3
  328. package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/reference.md +41 -0
  329. package/node_modules/pi-lens/vendor/grammars/tree-sitter-cue.wasm +0 -0
  330. package/node_modules/pi-mcp-adapter/CHANGELOG.md +36 -0
  331. package/node_modules/pi-mcp-adapter/README.md +47 -5
  332. package/node_modules/pi-mcp-adapter/cli.js +163 -1
  333. package/node_modules/pi-mcp-adapter/commands.ts +128 -22
  334. package/node_modules/pi-mcp-adapter/config.ts +25 -7
  335. package/node_modules/pi-mcp-adapter/direct-tools.ts +5 -4
  336. package/node_modules/pi-mcp-adapter/index.ts +219 -32
  337. package/node_modules/pi-mcp-adapter/init.ts +36 -4
  338. package/node_modules/pi-mcp-adapter/lifecycle.ts +315 -24
  339. package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +39 -6
  340. package/node_modules/pi-mcp-adapter/mcp-bearer-store.ts +387 -0
  341. package/node_modules/pi-mcp-adapter/mcp-callback-server.ts +27 -3
  342. package/node_modules/pi-mcp-adapter/mcp-code.ts +4 -0
  343. package/node_modules/pi-mcp-adapter/mcp-panel.ts +42 -13
  344. package/node_modules/pi-mcp-adapter/metadata-cache.ts +32 -21
  345. package/node_modules/pi-mcp-adapter/package-mcp-loader.ts +168 -0
  346. package/node_modules/pi-mcp-adapter/package.json +3 -1
  347. package/node_modules/pi-mcp-adapter/proxy-modes.ts +5 -4
  348. package/node_modules/pi-mcp-adapter/request-headers-command.ts +31 -37
  349. package/node_modules/pi-mcp-adapter/search-ranking.ts +92 -22
  350. package/node_modules/pi-mcp-adapter/server-manager.ts +140 -2
  351. package/node_modules/pi-mcp-adapter/session-recovery.ts +7 -0
  352. package/node_modules/pi-mcp-adapter/tool-approval.ts +15 -2
  353. package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +44 -4
  354. package/node_modules/pi-mcp-adapter/types.ts +2 -0
  355. package/node_modules/pi-mcp-adapter/ui-server.ts +18 -16
  356. package/node_modules/pi-mcp-adapter/utils.ts +70 -0
  357. package/node_modules/pi-web-access/CHANGELOG.md +37 -0
  358. package/node_modules/pi-web-access/README.md +32 -13
  359. package/node_modules/pi-web-access/anysearch.ts +4 -2
  360. package/node_modules/pi-web-access/brave.ts +16 -4
  361. package/node_modules/pi-web-access/chrome-cookies.ts +86 -15
  362. package/node_modules/pi-web-access/curator-page.ts +6 -3
  363. package/node_modules/pi-web-access/curator-server.ts +4 -1
  364. package/node_modules/pi-web-access/data-uri-sanitize.ts +406 -0
  365. package/node_modules/pi-web-access/exa.ts +18 -7
  366. package/node_modules/pi-web-access/extract.ts +40 -5
  367. package/node_modules/pi-web-access/firecrawl.ts +18 -2
  368. package/node_modules/pi-web-access/gemini-search.ts +16 -4
  369. package/node_modules/pi-web-access/github-extract.ts +65 -36
  370. package/node_modules/pi-web-access/index.ts +60 -61
  371. package/node_modules/pi-web-access/openai-search.ts +17 -6
  372. package/node_modules/pi-web-access/package.json +1 -1
  373. package/node_modules/pi-web-access/page-query.ts +4 -2
  374. package/node_modules/pi-web-access/parallel-mcp.ts +249 -0
  375. package/node_modules/pi-web-access/parallel.ts +2 -2
  376. package/node_modules/pi-web-access/pdf-extract.ts +18 -5
  377. package/node_modules/pi-web-access/query-rewrite.ts +51 -0
  378. package/node_modules/pi-web-access/serper.ts +211 -0
  379. package/node_modules/pi-web-access/ssrf-protection.ts +12 -2
  380. package/node_modules/pi-web-access/summary-model-scope.ts +12 -4
  381. package/node_modules/pi-web-access/summary-review.ts +44 -22
  382. package/node_modules/pi-web-access/tavily.ts +16 -4
  383. package/node_modules/pi-web-access/utils.ts +87 -0
  384. package/node_modules/pi-web-access/valyu.ts +199 -0
  385. package/package.json +14 -14
@@ -331,70 +331,93 @@ function editWriteExpandedCard(theme: any): any {
331
331
  );
332
332
  }
333
333
 
334
- /** compact 展开卡:外卡片保持 userMessageBg 原色;内部 tool call card(addToolChild)
335
- * 背景更深一层且只覆盖内容区(左右内缩、上下限首尾文本行),形成嵌套层次。
336
- * 逐行重建背景同时修复嵌套 Box 的右侧截断。 */
337
- function expandedToolCard(theme: any): any {
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
- const innerWidth = Math.max(0, width - 2);
352
- const lines: string[] = [];
353
- lines.push(paddedBackgroundRow(theme, slot, "", width));
354
- // 展开不再显示摘要行:跳过第一个 child 的首行空白,避免白占一行
355
- let skipLeadingBlank = true;
356
- for (const child of children) {
357
- const childLines = child.render(innerWidth);
358
- if (!child.__ccToolCard) {
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
- lines.push(paddedBackgroundRow(theme, slot, "", width));
395
- return lines;
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
- round.anchor.contentContainer.addChild({
934
- render(width: number): string[] {
935
- const theme = themeOf();
936
- const box = expandedToolCard(theme);
937
- for (const child of assistantChildren) box.addChild(child);
938
- const ids = roundToolCallIds(round);
939
- for (const tool of trackedToolComponents) {
940
- if (!ids.has(tool.toolCallId) || EDIT_WRITE_TOOLS.has(String(tool.toolName ?? ""))) {
941
- continue;
942
- }
943
- box.addToolChild({
944
- render: (innerWidth: number) => patch.toolOriginalRender.call(tool, innerWidth),
945
- invalidate: () => tool.invalidate?.(),
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;
@@ -17,6 +17,9 @@ import { showMoreHintText } from "./show-more-hint.ts";
17
17
  */
18
18
 
19
19
  const MESSAGE_DISPLAY_PATCH = Symbol.for("pi.ccstyle.message-display-patch");
20
+ const MESSAGE_DISPLAY_ORIGINAL_BG = Symbol.for("pi.ccstyle.message-display-original-bg");
21
+ const MESSAGE_DISPLAY_ORIGINAL_PADDING = Symbol.for("pi.ccstyle.message-display-original-padding");
22
+ const MESSAGE_DISPLAY_ORIGINAL_SAVED = Symbol.for("pi.ccstyle.message-display-original-saved");
20
23
 
21
24
  // 与 renderer/index.ts renderCall 的成功勾一致:亮绿 ✓(truecolor ANSI)。
22
25
  const BRIGHT_GREEN = "\x1b[38;2;80;220;100m";
@@ -55,21 +58,54 @@ const BRANCH_KIND: DisplayKind = {
55
58
  body: (component) => String(component.message?.summary ?? ""),
56
59
  };
57
60
 
58
- function renderCcstyle(component: any, kind: DisplayKind): void {
61
+ function ensureHintHover(component: any): void {
62
+ if (typeof component.setHintHovered === "function") return;
63
+ component.setHintHovered = function (this: any, hovered: boolean) {
64
+ if (this.hintHovered === hovered) return;
65
+ this.hintHovered = hovered;
66
+ this.invalidate?.();
67
+ };
68
+ }
69
+
70
+ function rememberMessageDisplay(component: any): void {
71
+ if (component[MESSAGE_DISPLAY_ORIGINAL_SAVED]) return;
72
+ component[MESSAGE_DISPLAY_ORIGINAL_BG] = component.bgFn;
73
+ component[MESSAGE_DISPLAY_ORIGINAL_PADDING] = [component.paddingX, component.paddingY];
74
+ component[MESSAGE_DISPLAY_ORIGINAL_SAVED] = true;
75
+ }
76
+
77
+ function restoreMessageDisplay(component: any): void {
78
+ if (!component[MESSAGE_DISPLAY_ORIGINAL_SAVED]) return;
79
+ const [paddingX, paddingY] = component[MESSAGE_DISPLAY_ORIGINAL_PADDING];
80
+ component.paddingX = paddingX;
81
+ component.paddingY = paddingY;
82
+ component.setBgFn?.(component[MESSAGE_DISPLAY_ORIGINAL_BG]);
83
+ delete component[MESSAGE_DISPLAY_ORIGINAL_BG];
84
+ delete component[MESSAGE_DISPLAY_ORIGINAL_PADDING];
85
+ delete component[MESSAGE_DISPLAY_ORIGINAL_SAVED];
86
+ }
87
+
88
+ function renderCcstyle(component: any, kind: DisplayKind): boolean {
59
89
  const theme = displayTheme;
60
- if (!theme) return; // 主题未就绪时保留原生渲染
90
+ if (!theme) return false; // 主题未就绪时回退原生渲染
91
+ rememberMessageDisplay(component);
61
92
  if (component.bgFn) component.setBgFn?.(undefined); // 与工具调用一致,去掉灰底
62
- if (component.paddingY !== 0) {
63
- component._ccstyleOriginalPaddingY = component.paddingY;
64
- component.paddingY = 0; // 工具组件 paddingY=0;原生 Box 默认 1,会上下各留一个空行
65
- }
93
+ component.paddingY = 0; // 工具组件 paddingY=0;原生 Box 默认 1,会上下各留一个空行
66
94
  component.clear();
95
+ ensureHintHover(component);
67
96
  const icon = `${BRIGHT_GREEN}✓${ANSI_FG_RESET}`; // 已完成消息,等同工具成功态
68
97
  const title = theme.fg("toolTitle", kind.title(component));
69
98
  if (!component.expanded) {
70
- const hint = theme.fg("dim", ` • ${showMoreHintText()}`);
99
+ const hovered = component.hintHovered === true;
100
+ const hint = `${theme.fg("dim", " • ")}${theme.fg(hovered ? "text" : "dim", showMoreHintText())}`;
71
101
  component.addChild(new Text(`${icon} ${title}${hint}`, 0, 0));
72
- return;
102
+ return true;
103
+ }
104
+ // 展开卡与 tool 一致:userMessageBg + 上下左右 1 格
105
+ component.paddingX = 1;
106
+ component.paddingY = 1;
107
+ if (typeof theme.bg === "function" && typeof component.setBgFn === "function") {
108
+ component.setBgFn((text: string) => theme.bg("userMessageBg", text));
73
109
  }
74
110
  component.addChild(new Text(`${icon} ${title}`, 0, 0));
75
111
  component.addChild(new Spacer(1));
@@ -78,6 +114,7 @@ function renderCcstyle(component: any, kind: DisplayKind): void {
78
114
  color: (text: string) => theme.fg("customMessageText", text),
79
115
  }),
80
116
  );
117
+ return true;
81
118
  }
82
119
 
83
120
  type PatchEntry = {
@@ -91,28 +128,42 @@ export function installMessageDisplayRendering(): () => void {
91
128
  const host = globalThis as any;
92
129
  const previous = host[MESSAGE_DISPLAY_PATCH];
93
130
  if (previous) previous.dispose();
94
- const patch: { active: boolean; entries: PatchEntry[]; dispose: () => void } = {
131
+ const patch: {
132
+ active: boolean;
133
+ entries: PatchEntry[];
134
+ components: Set<WeakRef<any>>;
135
+ tracked: WeakSet<object>;
136
+ dispose: () => void;
137
+ } = {
95
138
  active: true,
96
139
  entries: [],
140
+ components: new Set(),
141
+ tracked: new WeakSet(),
97
142
  dispose: () => {},
98
143
  };
144
+ const track = (component: object): void => {
145
+ for (const ref of patch.components) {
146
+ if (!ref.deref()) patch.components.delete(ref);
147
+ }
148
+ if (patch.tracked.has(component)) return;
149
+ patch.tracked.add(component);
150
+ patch.components.add(new WeakRef(component));
151
+ };
99
152
  const installOne = (ComponentClass: any, kind: DisplayKind): void => {
100
153
  const prototype = ComponentClass.prototype;
101
154
  const original = prototype.updateDisplay;
102
155
  const installed = function (this: any) {
103
156
  if (patch.active && config.mode !== "off") {
104
157
  try {
105
- renderCcstyle(this, kind);
106
- return;
158
+ if (renderCcstyle(this, kind)) {
159
+ track(this);
160
+ return;
161
+ }
107
162
  } catch {
108
163
  // 渲染失败回退原生
109
164
  }
110
165
  }
111
- // 回退原生前恢复 paddingY,避免原生渲染丢失上下内边距
112
- if (this._ccstyleOriginalPaddingY !== undefined) {
113
- this.paddingY = this._ccstyleOriginalPaddingY;
114
- delete this._ccstyleOriginalPaddingY;
115
- }
166
+ restoreMessageDisplay(this);
116
167
  original.call(this);
117
168
  };
118
169
  prototype.updateDisplay = installed;
@@ -128,6 +179,17 @@ export function installMessageDisplayRendering(): () => void {
128
179
  entry.prototype.updateDisplay = entry.original;
129
180
  }
130
181
  }
182
+ for (const ref of patch.components) {
183
+ const component = ref.deref();
184
+ if (!component) continue;
185
+ try {
186
+ restoreMessageDisplay(component);
187
+ component.updateDisplay();
188
+ } catch {
189
+ // 单个陈旧组件不应阻断其余原型与组件恢复
190
+ }
191
+ }
192
+ patch.components.clear();
131
193
  if (host[MESSAGE_DISPLAY_PATCH] === patch) delete host[MESSAGE_DISPLAY_PATCH];
132
194
  };
133
195
  host[MESSAGE_DISPLAY_PATCH] = patch;
@@ -135,7 +197,7 @@ export function installMessageDisplayRendering(): () => void {
135
197
  }
136
198
 
137
199
  /** 三个消息组件共享的结构特征;CustomMessageComponent 用 rebuild 无 updateDisplay,不命中。 */
138
- function isMessageDisplayComponent(value: any): boolean {
200
+ export function isMessageDisplayComponent(value: any): boolean {
139
201
  return Boolean(
140
202
  value &&
141
203
  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,26 @@ 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
+
57
+ let hoveredMessageDisplay: any = null;
58
+
59
+ export function setHoveredMessageDisplay(component: any): boolean {
60
+ if (component === hoveredMessageDisplay) return false;
61
+ hoveredMessageDisplay?.setHintHovered?.(false);
62
+ hoveredMessageDisplay = component;
63
+ component?.setHintHovered?.(true);
64
+ return true;
65
+ }
66
+
46
67
  let hoveredToolIoView: ExpandedToolIoView | null = null;
47
68
  let hoveredToolIoSection: ToolIoSection | null = null;
48
69
 
@@ -98,6 +119,8 @@ export function cachedFullscreenComponentAtRow(
98
119
  export type FullscreenHoverTarget =
99
120
  | { kind: "button" }
100
121
  | { kind: "group"; component: ToolGroupComponent }
122
+ | { kind: "thinking"; component: ThinkingPreviewBlock }
123
+ | { kind: "message"; component: any }
101
124
  | { kind: "assistant"; component: any }
102
125
  | {
103
126
  kind: "tool";
@@ -119,6 +142,10 @@ export function applyFullscreenHover(tui: any, target: FullscreenHoverTarget | n
119
142
  }
120
143
  const nextGroup = target?.kind === "group" ? target.component : null;
121
144
  if (setHoveredToolGroup(nextGroup)) changed = true;
145
+ const nextThinking = target?.kind === "thinking" ? target.component : null;
146
+ if (setHoveredThinking(nextThinking)) changed = true;
147
+ const nextMessage = target?.kind === "message" ? target.component : null;
148
+ if (setHoveredMessageDisplay(nextMessage)) changed = true;
122
149
  const nextAssistant = target?.kind === "assistant" ? target.component : null;
123
150
  if (setHoveredCompactAssistant(nextAssistant)) changed = true;
124
151
  const nextView = target?.kind === "tool" ? target.view : null;
@@ -1,6 +1,8 @@
1
+ import { ThinkingPreviewBlock, thinkingRunKey } 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,8 @@ import {
55
57
  sharedToolHoverState,
56
58
  setHoveredToolCallId,
57
59
  setHoveredToolGroup,
60
+ setHoveredThinking,
61
+ setHoveredMessageDisplay,
58
62
  setHoveredToolIo,
59
63
  type FullscreenHoverTarget,
60
64
  } from "./hover.ts";
@@ -151,6 +155,42 @@ function updateToolSummaryHover(tui: any, packet: SgrMousePacket): void {
151
155
  tui.requestRender?.();
152
156
  }
153
157
 
158
+ const EXPAND_PANEL_DOUBLE_CLICK_MS = 400;
159
+ let lastExpandPanelClick: { id: unknown; at: number } | null = null;
160
+
161
+ function expandPanelIdentity(card: any): unknown {
162
+ return card instanceof ThinkingPreviewBlock
163
+ ? thinkingRunKey(card.messageTimestamp, card.runStartIndex)
164
+ : card;
165
+ }
166
+
167
+ function isExpandPanelDoubleClick(card: any): boolean {
168
+ const now = Date.now();
169
+ const id = expandPanelIdentity(card);
170
+ const prev = lastExpandPanelClick;
171
+ lastExpandPanelClick = { id, at: now };
172
+ return Boolean(prev && prev.id === id && now - prev.at <= EXPAND_PANEL_DOUBLE_CLICK_MS);
173
+ }
174
+
175
+ function clearExpandPanelDoubleClick(): void {
176
+ lastExpandPanelClick = null;
177
+ }
178
+
179
+ function collapseExpandedCard(tui: any, card: any): boolean {
180
+ if (!isExpandPanelDoubleClick(card)) return false;
181
+ card.setExpanded(false);
182
+ setHoveredToolCallId(null);
183
+ setHoveredToolGroup(null);
184
+ setHoveredThinking(null);
185
+ setHoveredMessageDisplay(null);
186
+ setHoveredToolIo(null, null);
187
+ setHoveredCompactAssistant(null);
188
+ card.invalidate?.();
189
+ tui.requestRender?.();
190
+ clearExpandPanelDoubleClick();
191
+ return true;
192
+ }
193
+
154
194
  function toggleToolAtMouseClick(tui: any, packet: SgrMousePacket): boolean {
155
195
  const region = interactionRegionAt(packet);
156
196
  if (!region) return false;
@@ -158,19 +198,12 @@ function toggleToolAtMouseClick(tui: any, packet: SgrMousePacket): boolean {
158
198
  if (region.kind === "show-more") return tryOpenToolIoShowMore(region);
159
199
  const component = region.component;
160
200
  if (!component) return false;
161
- const width = Math.max(1, Number(tui?.terminal?.columns) || 80);
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
- }
201
+ if (region.kind === "expanded-card") return collapseExpandedCard(tui, component);
171
202
  component.setExpanded(true);
203
+ clearExpandPanelDoubleClick();
172
204
  setHoveredToolCallId(null);
173
205
  setHoveredToolGroup(null);
206
+ setHoveredThinking(null);
174
207
  setHoveredToolIo(null, null);
175
208
  component.invalidate?.();
176
209
  tui.requestRender?.();
@@ -241,10 +274,10 @@ const FULLSCREEN_VIEWPORT_PATCH = Symbol("ccstyle.fullscreen-viewport-patch");
241
274
  const FULLSCREEN_WHEEL_SCROLL_ORIGINAL = Symbol("ccstyle.fullscreen-wheel-scroll-original");
242
275
 
243
276
  /**
244
- * 官方 fullscreen 工具卡点击:collapsed hint 点击展开
245
- * (有且仅保持一个展开:展开前收起其他工具卡),expanded 整卡二次点击收起,
246
- * 截断头 show-more 打开全量预览;回到底部按钮 scrollToBottom。
247
- * 滚动条列、含 OSC8 链接行、非工具区域放行官方。
277
+ * 官方 fullscreen 工具卡点击:collapsed hint 单击展开
278
+ * (有且仅保持一个展开:展开前收起其他工具卡),expanded 整卡双击收起,
279
+ * 截断头 show-more 单击打开全量预览;回到底部按钮 scrollToBottom。
280
+ * 滚动条列、含 OSC8 链接行、非工具区域、展开卡单击放行官方。
248
281
  */
249
282
  function handleFullscreenToolClick(tui: any, packet: SgrMousePacket): boolean {
250
283
  const layout = tui.currentLayout;
@@ -274,7 +307,9 @@ function handleFullscreenToolClick(tui: any, packet: SgrMousePacket): boolean {
274
307
  const isTool = isToolExecutionComponent(component);
275
308
  const isGroup = component instanceof ToolGroupComponent;
276
309
  const isAssistant = isCompactAssistantComponent(component);
277
- if (!isTool && !isGroup && !isAssistant) return false;
310
+ const isThinking = component instanceof ThinkingPreviewBlock;
311
+ const isMessage = isMessageDisplayComponent(component);
312
+ if (!isTool && !isGroup && !isAssistant && !isThinking && !isMessage) return false;
278
313
  if (!component.expanded) {
279
314
  // collapsed 仅按钮文本可展开,不能把同一行正文/留白变成点击区。
280
315
  const hint = collapsedHintHitbox(line);
@@ -284,11 +319,14 @@ function handleFullscreenToolClick(tui: any, packet: SgrMousePacket): boolean {
284
319
  collectFullscreenToolCards(hit.box.component, others);
285
320
  for (const other of others) {
286
321
  if (other !== component && other.expanded) {
322
+ // 展开 round 内 thinking 时不要把外层 compact 卡收起。
323
+ if (isThinking && isCompactAssistantComponent(other)) continue;
287
324
  other.setExpanded(false);
288
325
  other.invalidate?.();
289
326
  }
290
327
  }
291
328
  component.setExpanded(true);
329
+ clearExpandPanelDoubleClick();
292
330
  } else {
293
331
  // 普通工具截断头 show-more:打开全量预览(不收起)。
294
332
  const view = isTool ? component.resultRendererComponent : null;
@@ -310,12 +348,14 @@ function handleFullscreenToolClick(tui: any, packet: SgrMousePacket): boolean {
310
348
  }
311
349
  }
312
350
  }
313
- // 整卡二次点击:内部工具仍归所属 group,保持整体展开/收起语义。
314
- card.setExpanded(false);
351
+ // 双击收起:内部工具仍归所属 group。单击放行官方(选择/链接)。
352
+ return collapseExpandedCard(tui, card);
315
353
  }
316
354
  // 点击后清 hover 高亮。
317
355
  setHoveredToolCallId(null);
318
356
  setHoveredToolGroup(null);
357
+ setHoveredThinking(null);
358
+ setHoveredMessageDisplay(null);
319
359
  setHoveredToolIo(null, null);
320
360
  setHoveredCompactAssistant(null);
321
361
  card.invalidate?.();
@@ -361,6 +401,8 @@ function handleFullscreenToolHover(tui: any, packet: SgrMousePacket): void {
361
401
  );
362
402
  if (component instanceof ToolGroupComponent) {
363
403
  if (overHint) target = { kind: "group", component };
404
+ } else if (component instanceof ThinkingPreviewBlock) {
405
+ if (component.expanded || overHint) target = { kind: "thinking", component };
364
406
  } else if (isToolExecutionComponent(component)) {
365
407
  let view: ExpandedToolIoView | null = null;
366
408
  let section: ToolIoSection | null = null;
@@ -384,6 +426,8 @@ function handleFullscreenToolHover(tui: any, packet: SgrMousePacket): void {
384
426
  } else if (isCompactAssistantComponent(component)) {
385
427
  // compact 摘要行:折叠时仅提示文字高亮,展开卡整体高亮。
386
428
  if (component.expanded || overHint) target = { kind: "assistant", component };
429
+ } else if (isMessageDisplayComponent(component)) {
430
+ if (overHint) target = { kind: "message", component };
387
431
  }
388
432
  }
389
433
  }
@@ -779,8 +823,11 @@ export function teardownToolMouseInteraction(
779
823
  toolMouseInputUnsubscribe = null;
780
824
  setHoveredToolCallId(null);
781
825
  setHoveredToolGroup(null);
826
+ setHoveredThinking(null);
827
+ setHoveredMessageDisplay(null);
782
828
  setHoveredToolIo(null, null);
783
829
  setHoveredCompactAssistant(null);
830
+ clearExpandPanelDoubleClick();
784
831
  try {
785
832
  if (isLazyProxyTui(getToolMouseTui())) releaseFullscreenToolMouseMotion(getToolMouseTui());
786
833
  else getToolMouseTui()?.terminal?.write?.(TOOL_MOUSE_DISABLE);
@@ -804,6 +851,8 @@ export function teardownToolMouseInteraction(
804
851
  /** off 模式清理:清空 hover 与回到底部按钮状态(跨模块 rebind 统一经由此函数)。 */
805
852
  export function resetToolHoverState(): void {
806
853
  setHoveredToolCallId(null);
854
+ setHoveredThinking(null);
855
+ setHoveredMessageDisplay(null);
807
856
  setHoveredCompactAssistant(null);
808
857
  setScrollButtonVisible(false);
809
858
  setScrollButtonHovered(false);
@@ -1,5 +1,7 @@
1
1
  import { visibleWidth } from "@earendil-works/pi-tui";
2
+ import { ThinkingPreviewBlock } from "../../feature/compact-thinking.ts";
2
3
  import { isCompactAssistantComponent } from "../compact-mode.ts";
4
+ import { isMessageDisplayComponent } from "../message-display.ts";
3
5
  import { ToolGroupComponent } from "../tool/grouping.ts";
4
6
  import { isToolExecutionComponent, stripTerminalSequencesPreservingLayout } from "./packets.ts";
5
7
  import { getScrollButtonWidget } from "./scroll.ts";
@@ -76,6 +78,29 @@ export function isScrollbarColumnAt(layout: any, x: number): boolean {
76
78
  return hit;
77
79
  }
78
80
 
81
+ /** compact 展开卡用 childAtRow 映射 thinking;其余按 render 行数下钻。 */
82
+ function nestedChildAtRow(node: any, localRow: number, width: number): any {
83
+ if (typeof node?.childAtRow === "function") {
84
+ return node.childAtRow(localRow, width);
85
+ }
86
+ if (!Array.isArray(node?.children)) return null;
87
+ let offset = 0;
88
+ for (const child of node.children) {
89
+ let count = 0;
90
+ try {
91
+ const rendered = child.render?.(width);
92
+ if (Array.isArray(rendered)) count = rendered.length;
93
+ } catch {
94
+ count = 0;
95
+ }
96
+ if (localRow < offset + count) {
97
+ return nestedChildAtRow(child, localRow - offset, width);
98
+ }
99
+ offset += count;
100
+ }
101
+ return null;
102
+ }
103
+
79
104
  /**
80
105
  * 布局 leaf box 的组件通常是容器(documentContainer/dock 容器等),工具卡与
81
106
  * widget 在其 children 内。按局部行遍历组件树,定位实际命中的子组件。
@@ -94,7 +119,19 @@ export function componentAtLocalRow(
94
119
  return { component, row: localRow };
95
120
  }
96
121
  if (isCompactAssistantComponent(component)) {
97
- // compact 摘要行整体作为可展开卡片(折叠摘要 / 展开内容)。
122
+ // 折叠:整行摘要。展开:先命中内部 thinking hint,其余仍归外层卡片。
123
+ if (component.expanded === true) {
124
+ const inner = nestedChildAtRow(component, localRow, width);
125
+ if (inner instanceof ThinkingPreviewBlock) {
126
+ return { component: inner, row: localRow };
127
+ }
128
+ }
129
+ return { component, row: localRow };
130
+ }
131
+ if (component instanceof ThinkingPreviewBlock) {
132
+ return { component, row: localRow };
133
+ }
134
+ if (isMessageDisplayComponent(component)) {
98
135
  return { component, row: localRow };
99
136
  }
100
137
  if (component === getScrollButtonWidget()) {
@@ -134,7 +171,9 @@ export function collectFullscreenToolCards(
134
171
  if (
135
172
  isToolExecutionComponent(component) ||
136
173
  component instanceof ToolGroupComponent ||
137
- isCompactAssistantComponent(component)
174
+ isCompactAssistantComponent(component) ||
175
+ component instanceof ThinkingPreviewBlock ||
176
+ isMessageDisplayComponent(component)
138
177
  ) {
139
178
  out.push(component);
140
179
  return;