@herbertgao/pi-extensions 2026.8.6 → 2026.8.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (343) hide show
  1. package/README.md +5 -5
  2. package/node_modules/@herbertgao/pi-cc-extensions/README.en.md +1 -1
  3. package/node_modules/@herbertgao/pi-cc-extensions/README.md +1 -1
  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 +272 -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 +1 -1
  9. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/hover.ts +14 -0
  10. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/interaction.ts +55 -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 +1 -0
  35. package/node_modules/@juicesharp/rpiv-ask-user-question/ask-user-question.ts +26 -10
  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 +2 -1
  39. package/node_modules/@juicesharp/rpiv-ask-user-question/docs/localization.md +3 -1
  40. package/node_modules/@juicesharp/rpiv-ask-user-question/locales/en.json +2 -2
  41. package/node_modules/@juicesharp/rpiv-ask-user-question/locales/zh.json +2 -2
  42. package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +3 -2
  43. package/node_modules/@juicesharp/rpiv-ask-user-question/state/build-questionnaire.ts +10 -0
  44. package/node_modules/@juicesharp/rpiv-ask-user-question/state/key-router.ts +3 -1
  45. package/node_modules/@juicesharp/rpiv-ask-user-question/state/questionnaire-session.ts +30 -7
  46. package/node_modules/@juicesharp/rpiv-ask-user-question/state/state.ts +14 -6
  47. package/node_modules/@juicesharp/rpiv-ask-user-question/view/dialog-builder.ts +30 -4
  48. package/node_modules/@juicesharp/rpiv-ask-user-question/view/tab-content-strategy.ts +26 -5
  49. package/node_modules/@narumitw/pi-btw/README.md +120 -111
  50. package/node_modules/@narumitw/pi-btw/dist/index.ts +2898 -0
  51. package/node_modules/@narumitw/pi-btw/dist/index.ts.map +7 -0
  52. package/node_modules/@narumitw/pi-btw/package.json +10 -6
  53. package/node_modules/@narumitw/pi-btw/src/btw.ts +36 -40
  54. package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +55 -10
  55. package/node_modules/@narumitw/pi-btw/src/main-tree-picker.ts +390 -0
  56. package/node_modules/@narumitw/pi-btw/src/menu.ts +45 -2
  57. package/node_modules/@narumitw/pi-btw/src/transcript-pager.ts +136 -45
  58. package/node_modules/pi-lens/CHANGELOG.md +909 -0
  59. package/node_modules/pi-lens/README.md +11 -3
  60. package/node_modules/pi-lens/config/ruff/core.toml +42 -0
  61. package/node_modules/pi-lens/dist/clients/actionable-warnings.js +130 -27
  62. package/node_modules/pi-lens/dist/clients/advisory-provenance.js +126 -13
  63. package/node_modules/pi-lens/dist/clients/agent-nudge.js +67 -11
  64. package/node_modules/pi-lens/dist/clients/ast-grep-client.js +9 -3
  65. package/node_modules/pi-lens/dist/clients/atomic-write.js +9 -3
  66. package/node_modules/pi-lens/dist/clients/bash-file-access.js +285 -8
  67. package/node_modules/pi-lens/dist/clients/biome-client.js +61 -30
  68. package/node_modules/pi-lens/dist/clients/blocker-freshness.js +428 -0
  69. package/node_modules/pi-lens/dist/clients/blocker-past-eof.js +119 -0
  70. package/node_modules/pi-lens/dist/clients/bootstrap.js +12 -1
  71. package/node_modules/pi-lens/dist/clients/bounded-pid-file-lock.js +12 -3
  72. package/node_modules/pi-lens/dist/clients/bounded-telemetry.js +192 -0
  73. package/node_modules/pi-lens/dist/clients/cascade-budget.js +196 -0
  74. package/node_modules/pi-lens/dist/clients/cascade-format.js +20 -1
  75. package/node_modules/pi-lens/dist/clients/cascade-types.js +9 -1
  76. package/node_modules/pi-lens/dist/clients/child-unref.js +54 -6
  77. package/node_modules/pi-lens/dist/clients/code-quality-warnings.js +76 -24
  78. package/node_modules/pi-lens/dist/clients/dead-code-client.js +123 -31
  79. package/node_modules/pi-lens/dist/clients/deadline-utils.js +8 -1
  80. package/node_modules/pi-lens/dist/clients/debug-handles.js +5 -0
  81. package/node_modules/pi-lens/dist/clients/degradation-ledger.js +62 -13
  82. package/node_modules/pi-lens/dist/clients/dependency-checker.js +25 -3
  83. package/node_modules/pi-lens/dist/clients/diagnostic-dispositions.js +147 -33
  84. package/node_modules/pi-lens/dist/clients/diagnostic-line-freshness.js +298 -0
  85. package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +52 -2
  86. package/node_modules/pi-lens/dist/clients/dispatch/integration.js +256 -88
  87. package/node_modules/pi-lens/dist/clients/dispatch/lazy.js +7 -4
  88. package/node_modules/pi-lens/dist/clients/dispatch/plan.js +5 -0
  89. package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +234 -18
  90. package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +187 -19
  91. package/node_modules/pi-lens/dist/clients/dispatch/runners/cpp-check.js +6 -3
  92. package/node_modules/pi-lens/dist/clients/dispatch/runners/credo.js +11 -9
  93. package/node_modules/pi-lens/dist/clients/dispatch/runners/cue-vet.js +398 -0
  94. package/node_modules/pi-lens/dist/clients/dispatch/runners/elixir-check.js +11 -3
  95. package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +12 -7
  96. package/node_modules/pi-lens/dist/clients/dispatch/runners/go-vet.js +18 -0
  97. package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-render.js +895 -0
  98. package/node_modules/pi-lens/dist/clients/dispatch/runners/index.js +4 -0
  99. package/node_modules/pi-lens/dist/clients/dispatch/runners/javac.js +16 -3
  100. package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +60 -53
  101. package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +16 -0
  102. package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +23 -0
  103. package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +331 -55
  104. package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +38 -5
  105. package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +97 -19
  106. package/node_modules/pi-lens/dist/clients/dispatch/runners/spellcheck.js +14 -0
  107. package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +20 -0
  108. package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +22 -0
  109. package/node_modules/pi-lens/dist/clients/dispatch/runners/swiftlint.js +10 -0
  110. package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +18 -6
  111. package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +73 -12
  112. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +275 -13
  113. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +21 -6
  114. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/lazy-installer.js +260 -27
  115. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +734 -64
  116. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +86 -11
  117. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/tool-failure.js +72 -0
  118. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +9 -0
  119. package/node_modules/pi-lens/dist/clients/dispatch/runners/vale.js +9 -0
  120. package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +18 -1
  121. package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +4 -2
  122. package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +28 -5
  123. package/node_modules/pi-lens/dist/clients/extension-log.js +22 -1
  124. package/node_modules/pi-lens/dist/clients/file-kinds.js +8 -2
  125. package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +294 -0
  126. package/node_modules/pi-lens/dist/clients/finding-identity.js +88 -0
  127. package/node_modules/pi-lens/dist/clients/formatters-lazy.js +3 -2
  128. package/node_modules/pi-lens/dist/clients/formatters.js +500 -115
  129. package/node_modules/pi-lens/dist/clients/generation-guard.js +216 -0
  130. package/node_modules/pi-lens/dist/clients/git-guard.js +31 -0
  131. package/node_modules/pi-lens/dist/clients/gitleaks-client.js +181 -8
  132. package/node_modules/pi-lens/dist/clients/govulncheck-client.js +109 -9
  133. package/node_modules/pi-lens/dist/clients/grammar-source.js +333 -10
  134. package/node_modules/pi-lens/dist/clients/host-ports.js +8 -0
  135. package/node_modules/pi-lens/dist/clients/installer/index.js +1114 -100
  136. package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh-session.js +58 -0
  137. package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh.js +715 -0
  138. package/node_modules/pi-lens/dist/clients/instance-reaper.js +643 -97
  139. package/node_modules/pi-lens/dist/clients/instance-registry.js +87 -17
  140. package/node_modules/pi-lens/dist/clients/jscpd-client.js +82 -6
  141. package/node_modules/pi-lens/dist/clients/knip-client.js +310 -10
  142. package/node_modules/pi-lens/dist/clients/language-policy.js +8 -2
  143. package/node_modules/pi-lens/dist/clients/language-profile.js +2 -0
  144. package/node_modules/pi-lens/dist/clients/latency-logger.js +440 -11
  145. package/node_modules/pi-lens/dist/clients/lazy-import.js +21 -0
  146. package/node_modules/pi-lens/dist/clients/ledger-bounds.js +21 -0
  147. package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +8 -0
  148. package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +102 -7
  149. package/node_modules/pi-lens/dist/clients/lsp/client.js +1516 -159
  150. package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +83 -1
  151. package/node_modules/pi-lens/dist/clients/lsp/document-drift.js +389 -0
  152. package/node_modules/pi-lens/dist/clients/lsp/index.js +2274 -147
  153. package/node_modules/pi-lens/dist/clients/lsp/inferred-project.js +215 -0
  154. package/node_modules/pi-lens/dist/clients/lsp/jvm-runtime.js +146 -14
  155. package/node_modules/pi-lens/dist/clients/lsp/language.js +48 -4
  156. package/node_modules/pi-lens/dist/clients/lsp/server.js +277 -16
  157. package/node_modules/pi-lens/dist/clients/lsp/spawn-history.js +22 -0
  158. package/node_modules/pi-lens/dist/clients/lsp/sync-kind.js +43 -0
  159. package/node_modules/pi-lens/dist/clients/lsp/tsserver-sync.js +79 -3
  160. package/node_modules/pi-lens/dist/clients/lsp/wait-policy/strategies.js +43 -0
  161. package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +422 -28
  162. package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-session.js +30 -0
  163. package/node_modules/pi-lens/dist/clients/lsp/workspace-sweep-hold.js +175 -0
  164. package/node_modules/pi-lens/dist/clients/lsp-lazy.js +3 -2
  165. package/node_modules/pi-lens/dist/clients/mcp/session.js +10 -2
  166. package/node_modules/pi-lens/dist/clients/module-report.js +8 -0
  167. package/node_modules/pi-lens/dist/clients/opengrep-client.js +15 -1
  168. package/node_modules/pi-lens/dist/clients/package-manager.js +170 -14
  169. package/node_modules/pi-lens/dist/clients/path-attribution-telemetry.js +27 -0
  170. package/node_modules/pi-lens/dist/clients/path-utils.js +160 -0
  171. package/node_modules/pi-lens/dist/clients/pipeline.js +154 -33
  172. package/node_modules/pi-lens/dist/clients/post-autofix-notice.js +37 -0
  173. package/node_modules/pi-lens/dist/clients/project-diagnostics/cache.js +17 -3
  174. package/node_modules/pi-lens/dist/clients/project-diagnostics/extractors.js +89 -22
  175. package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +84 -14
  176. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/gitleaks.js +15 -3
  177. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/trivy.js +50 -2
  178. package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +5 -0
  179. package/node_modules/pi-lens/dist/clients/project-lens-config.js +3 -0
  180. package/node_modules/pi-lens/dist/clients/project-snapshot.js +299 -0
  181. package/node_modules/pi-lens/dist/clients/quiet-window-config.js +47 -0
  182. package/node_modules/pi-lens/dist/clients/quiet-window.js +11 -25
  183. package/node_modules/pi-lens/dist/clients/read-guard-logger.js +1 -1
  184. package/node_modules/pi-lens/dist/clients/read-guard.js +184 -10
  185. package/node_modules/pi-lens/dist/clients/resource-sampler.js +49 -17
  186. package/node_modules/pi-lens/dist/clients/reverse-deps.js +50 -11
  187. package/node_modules/pi-lens/dist/clients/review-graph/query.js +52 -4
  188. package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +96 -7
  189. package/node_modules/pi-lens/dist/clients/runtime-context.js +8 -1
  190. package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +308 -45
  191. package/node_modules/pi-lens/dist/clients/runtime-session.js +332 -9
  192. package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +217 -22
  193. package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +212 -79
  194. package/node_modules/pi-lens/dist/clients/runtime-turn.js +575 -67
  195. package/node_modules/pi-lens/dist/clients/safe-spawn.js +220 -7
  196. package/node_modules/pi-lens/dist/clients/scratch-tree-policy.js +161 -0
  197. package/node_modules/pi-lens/dist/clients/search-read-registration.js +34 -6
  198. package/node_modules/pi-lens/dist/clients/security-scan-client.js +157 -24
  199. package/node_modules/pi-lens/dist/clients/sg-runner.js +116 -22
  200. package/node_modules/pi-lens/dist/clients/single-flight.js +158 -0
  201. package/node_modules/pi-lens/dist/clients/stale-marker.js +17 -0
  202. package/node_modules/pi-lens/dist/clients/startup-timing.js +19 -1
  203. package/node_modules/pi-lens/dist/clients/test-runner-client.js +151 -16
  204. package/node_modules/pi-lens/dist/clients/tool-event.js +56 -5
  205. package/node_modules/pi-lens/dist/clients/tool-policy.js +125 -20
  206. package/node_modules/pi-lens/dist/clients/tree-sitter-cache.js +75 -1
  207. package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +769 -64
  208. package/node_modules/pi-lens/dist/clients/tree-sitter-shared.js +11 -0
  209. package/node_modules/pi-lens/dist/clients/tree-sitter-symbol-extractor.js +90 -0
  210. package/node_modules/pi-lens/dist/clients/trivy-client.js +19 -1
  211. package/node_modules/pi-lens/dist/clients/widget-state.js +336 -36
  212. package/node_modules/pi-lens/dist/clients/zizmor-config.js +214 -14
  213. package/node_modules/pi-lens/dist/index.js +67738 -55739
  214. package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +466 -54
  215. package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +132 -43
  216. package/node_modules/pi-lens/dist/tools/lsp-navigation.js +46 -7
  217. package/node_modules/pi-lens/docs/agent-guide.md +6 -1
  218. package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +515 -506
  219. package/node_modules/pi-lens/docs/dispositions.md +21 -0
  220. package/node_modules/pi-lens/docs/features.md +19 -5
  221. package/node_modules/pi-lens/docs/globalconfig.md +3 -0
  222. package/node_modules/pi-lens/docs/language-coverage.md +71 -5
  223. package/node_modules/pi-lens/docs/mcp.md +2 -2
  224. package/node_modules/pi-lens/docs/servercapabilities.md +4 -1
  225. package/node_modules/pi-lens/docs/settings.md +19 -1
  226. package/node_modules/pi-lens/docs/usage.md +1 -0
  227. package/node_modules/pi-lens/package.json +10 -6
  228. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/no-reflect-get-js-snapshot.yml +23 -0
  229. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/no-reflect-get-snapshot.yml +23 -0
  230. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/__snapshots__/ts-void-zero-snapshot.yml +23 -0
  231. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-bare-object-param-test.yml +16 -0
  232. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-chained-type-assertions-test.yml +15 -1
  233. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-compile-call-test.yml +29 -1
  234. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-dupe-class-members-test.yml +33 -0
  235. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-inner-html-js-test.yml +7 -1
  236. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-inner-html-test.yml +7 -1
  237. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-known-value-widening-test.yml +9 -0
  238. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-non-null-assertion-test.yml +216 -0
  239. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-js-test.yml +2 -0
  240. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-apply-test.yml +2 -0
  241. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-js-test.yml +2 -1
  242. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-reflect-get-test.yml +2 -1
  243. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-return-value-in-generator-test.yml +12 -0
  244. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-runtime-typeof-test.yml +33 -0
  245. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-server-bind-wildcard-test.yml +9 -0
  246. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-shape-in-symbol-names-test.yml +13 -0
  247. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-sql-in-code-js-test.yml +5 -1
  248. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-sql-in-code-test.yml +5 -1
  249. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-parameters-test.yml +12 -0
  250. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unknown-returns-test.yml +16 -0
  251. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unsafe-dictionary-any-test.yml +10 -0
  252. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-unsafe-dictionary-unknown-test.yml +8 -0
  253. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/redundant-unsafe-function-test.yml +35 -0
  254. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/require-safety-comment-for-as-unknown-as-test.yml +177 -0
  255. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/ts-void-zero-test.yml +1 -0
  256. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-await-expression-member-js.yml +13 -2
  257. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-await-expression-member.yml +13 -2
  258. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-host-path-in-win32-branch.yml +2 -0
  259. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-bare-object-param.yml +60 -0
  260. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-chained-type-assertions.yml +57 -12
  261. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-compile-call.yml +63 -5
  262. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-dupe-class-members.yml +52 -8
  263. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-inner-html-js.yml +27 -2
  264. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-inner-html.yml +27 -2
  265. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-known-value-widening.yml +71 -0
  266. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-non-null-assertion.yml +316 -0
  267. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-raw-json-store-write.yml +7 -0
  268. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply-js.yml +22 -2
  269. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-apply.yml +23 -2
  270. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get-js.yml +33 -5
  271. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-reflect-get.yml +34 -8
  272. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-return-value-in-generator.yml +22 -5
  273. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-runtime-typeof.yml +121 -0
  274. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-server-bind-wildcard.yml +23 -7
  275. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-shape-in-symbol-names.yml +68 -0
  276. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-sql-in-code-js.yml +41 -2
  277. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-sql-in-code.yml +41 -2
  278. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-laundering.yml +6 -1
  279. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-parameters.yml +67 -0
  280. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unknown-returns.yml +106 -0
  281. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unsafe-dictionary-any.yml +50 -0
  282. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-unsafe-dictionary-unknown.yml +56 -0
  283. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-win32-isabsolute-for-qualification.yml +2 -0
  284. package/node_modules/pi-lens/rules/ast-grep-rules/rules/redundant-unsafe-function.yml +32 -0
  285. package/node_modules/pi-lens/rules/ast-grep-rules/rules/require-safety-comment-for-as-unknown-as.yml +184 -0
  286. package/node_modules/pi-lens/rules/ast-grep-rules/rules/ts-void-zero.yml +5 -0
  287. package/node_modules/pi-lens/rules/ast-grep-rules/self-scan-baseline.json +5 -0
  288. package/node_modules/pi-lens/scripts/analyze-pi-lens-logs.mjs +53 -1
  289. package/node_modules/pi-lens/scripts/download-grammars.js +25 -0
  290. package/node_modules/pi-lens/scripts/grammars.lock.json +9 -0
  291. package/node_modules/pi-lens/skills/pi-lens-ast-grep/SKILL.md +2 -0
  292. package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/SKILL.md +80 -3
  293. package/node_modules/pi-lens/skills/pi-lens-write-ast-grep-rule/reference.md +41 -0
  294. package/node_modules/pi-lens/vendor/grammars/tree-sitter-cue.wasm +0 -0
  295. package/node_modules/pi-mcp-adapter/CHANGELOG.md +36 -0
  296. package/node_modules/pi-mcp-adapter/README.md +47 -5
  297. package/node_modules/pi-mcp-adapter/cli.js +163 -1
  298. package/node_modules/pi-mcp-adapter/commands.ts +128 -22
  299. package/node_modules/pi-mcp-adapter/config.ts +25 -7
  300. package/node_modules/pi-mcp-adapter/direct-tools.ts +5 -4
  301. package/node_modules/pi-mcp-adapter/index.ts +219 -32
  302. package/node_modules/pi-mcp-adapter/init.ts +36 -4
  303. package/node_modules/pi-mcp-adapter/lifecycle.ts +315 -24
  304. package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +39 -6
  305. package/node_modules/pi-mcp-adapter/mcp-bearer-store.ts +387 -0
  306. package/node_modules/pi-mcp-adapter/mcp-callback-server.ts +27 -3
  307. package/node_modules/pi-mcp-adapter/mcp-code.ts +4 -0
  308. package/node_modules/pi-mcp-adapter/mcp-panel.ts +42 -13
  309. package/node_modules/pi-mcp-adapter/metadata-cache.ts +32 -21
  310. package/node_modules/pi-mcp-adapter/package-mcp-loader.ts +168 -0
  311. package/node_modules/pi-mcp-adapter/package.json +3 -1
  312. package/node_modules/pi-mcp-adapter/proxy-modes.ts +5 -4
  313. package/node_modules/pi-mcp-adapter/request-headers-command.ts +31 -37
  314. package/node_modules/pi-mcp-adapter/search-ranking.ts +92 -22
  315. package/node_modules/pi-mcp-adapter/server-manager.ts +140 -2
  316. package/node_modules/pi-mcp-adapter/session-recovery.ts +7 -0
  317. package/node_modules/pi-mcp-adapter/tool-approval.ts +15 -2
  318. package/node_modules/pi-mcp-adapter/tool-result-renderer.ts +44 -4
  319. package/node_modules/pi-mcp-adapter/types.ts +2 -0
  320. package/node_modules/pi-mcp-adapter/ui-server.ts +18 -16
  321. package/node_modules/pi-mcp-adapter/utils.ts +70 -0
  322. package/node_modules/pi-web-access/CHANGELOG.md +23 -0
  323. package/node_modules/pi-web-access/README.md +27 -9
  324. package/node_modules/pi-web-access/anysearch.ts +4 -2
  325. package/node_modules/pi-web-access/brave.ts +16 -4
  326. package/node_modules/pi-web-access/curator-page.ts +6 -3
  327. package/node_modules/pi-web-access/curator-server.ts +4 -1
  328. package/node_modules/pi-web-access/exa.ts +18 -7
  329. package/node_modules/pi-web-access/extract.ts +28 -3
  330. package/node_modules/pi-web-access/gemini-search.ts +16 -4
  331. package/node_modules/pi-web-access/index.ts +41 -57
  332. package/node_modules/pi-web-access/package.json +1 -1
  333. package/node_modules/pi-web-access/page-query.ts +4 -2
  334. package/node_modules/pi-web-access/parallel-mcp.ts +249 -0
  335. package/node_modules/pi-web-access/parallel.ts +2 -2
  336. package/node_modules/pi-web-access/query-rewrite.ts +51 -0
  337. package/node_modules/pi-web-access/serper.ts +211 -0
  338. package/node_modules/pi-web-access/summary-model-scope.ts +12 -4
  339. package/node_modules/pi-web-access/summary-review.ts +44 -22
  340. package/node_modules/pi-web-access/tavily.ts +16 -4
  341. package/node_modules/pi-web-access/utils.ts +87 -0
  342. package/node_modules/pi-web-access/valyu.ts +199 -0
  343. package/package.json +13 -13
@@ -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;
@@ -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
- 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
- }
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 打开全量预览;回到底部按钮 scrollToBottom。
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
- if (!isTool && !isGroup && !isAssistant) return false;
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
- // 整卡二次点击:内部工具仍归所属 group,保持整体展开/收起语义。
314
- card.setExpanded(false);
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);
@@ -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;
@@ -1377,7 +1377,8 @@ function displayConfigCacheKey(config: ToolDisplayConfig): string {
1377
1377
  config.diffViewMode,
1378
1378
  config.diffIndicatorMode,
1379
1379
  String(config.diffSplitMinWidth),
1380
- String(config.diffCollapsedLines),
1380
+ String(config.editDiffCollapsedLines),
1381
+ String(config.writeDiffCollapsedLines),
1381
1382
  config.diffWordWrap ? "1" : "0",
1382
1383
  String(config.expandedPreviewMaxLines),
1383
1384
  ].join(":");
@@ -2232,10 +2233,22 @@ function resolveDiffDisplayLimit(
2232
2233
  : DEFAULT_TOOL_DISPLAY_CONFIG.expandedPreviewMaxLines;
2233
2234
  const collapsedLimit = Number.isFinite(maxCollapsedLines)
2234
2235
  ? maxCollapsedLines
2235
- : DEFAULT_TOOL_DISPLAY_CONFIG.diffCollapsedLines;
2236
+ : DEFAULT_TOOL_DISPLAY_CONFIG.editDiffCollapsedLines;
2236
2237
  return expanded ? Math.max(0, expandedLimit) : Math.max(1, collapsedLimit);
2237
2238
  }
2238
2239
 
2240
+ /** Write collapsed body limit. Missing/NaN falls back to edit's limit. */
2241
+ function resolveWriteCollapsedLimit(config: ToolDisplayConfig): number {
2242
+ const value = config.writeDiffCollapsedLines;
2243
+ if (Number.isFinite(value)) {
2244
+ return Math.max(0, value);
2245
+ }
2246
+ const fallback = Number.isFinite(config.editDiffCollapsedLines)
2247
+ ? config.editDiffCollapsedLines
2248
+ : DEFAULT_TOOL_DISPLAY_CONFIG.writeDiffCollapsedLines;
2249
+ return Math.max(0, fallback);
2250
+ }
2251
+
2239
2252
  /**
2240
2253
  * How many source rows/entries to fully highlight+render before applyLineLimit.
2241
2254
  * Extra headroom covers word-wrap expansion so the display limit can still fill.
@@ -2602,7 +2615,7 @@ export function renderEditDiffResult(
2602
2615
  const headerRows = renderHeaderRows(parsed.stats, mode, safeWidth, theme);
2603
2616
  const displayLimit = resolveDiffDisplayLimit(
2604
2617
  options.expanded,
2605
- live.diffCollapsedLines,
2618
+ live.editDiffCollapsedLines,
2606
2619
  live.expandedPreviewMaxLines,
2607
2620
  );
2608
2621
  const processBudget = resolveDiffProcessBudget(displayLimit, wordWrap);
@@ -2636,7 +2649,7 @@ export function renderEditDiffResult(
2636
2649
  bodyRows,
2637
2650
  safeWidth,
2638
2651
  options.expanded,
2639
- live.diffCollapsedLines,
2652
+ live.editDiffCollapsedLines,
2640
2653
  live.expandedPreviewMaxLines,
2641
2654
  parsed.stats.hunks,
2642
2655
  theme,
@@ -2901,6 +2914,41 @@ function renderWriteOverwriteGuardRows(
2901
2914
  return renderSingleDiffRow(buildWriteOverwriteGuardText(guard, width), "warning", width, theme);
2902
2915
  }
2903
2916
 
2917
+ /** Folded write with a zero body limit: `↳ created • click to show more`. */
2918
+ function renderWriteCollapsedHintLine(
2919
+ wasOverwrite: boolean,
2920
+ width: number,
2921
+ theme: DiffTheme,
2922
+ hovered: boolean,
2923
+ headerLabel?: string,
2924
+ ): string[] {
2925
+ const safeWidth = normalizeDiffRenderWidth(width);
2926
+ if (safeWidth === 0) {
2927
+ return [""];
2928
+ }
2929
+ const actionLabel = headerLabel?.trim() || (wasOverwrite ? "overwritten" : "created");
2930
+ const clickLabel = showMoreHintText();
2931
+ const candidates = [`↳ ${actionLabel} • ${clickLabel}`, `↳ ${actionLabel}`, actionLabel, "…"];
2932
+ let text = candidates[candidates.length - 1] ?? "…";
2933
+ for (const candidate of candidates) {
2934
+ if (visibleWidth(candidate) <= safeWidth) {
2935
+ text = candidate;
2936
+ break;
2937
+ }
2938
+ }
2939
+ if (visibleWidth(text) > safeWidth) {
2940
+ text = truncateToWidth(text, safeWidth, "");
2941
+ }
2942
+ const clickIndex = text.lastIndexOf(clickLabel);
2943
+ const styled =
2944
+ hovered && clickIndex >= 0
2945
+ ? theme.fg("muted", text.slice(0, clickIndex)) +
2946
+ theme.fg("text", clickLabel) +
2947
+ theme.fg("muted", text.slice(clickIndex + clickLabel.length))
2948
+ : theme.fg("muted", text);
2949
+ return [clampDiffLineToWidth(styled, safeWidth)];
2950
+ }
2951
+
2904
2952
  export function renderWriteDiffResult(
2905
2953
  content: string | undefined,
2906
2954
  options: DiffRenderOptions,
@@ -2977,6 +3025,27 @@ export function renderWriteDiffResult(
2977
3025
  return cached;
2978
3026
  }
2979
3027
 
3028
+ const writeCollapsedLimit = resolveWriteCollapsedLimit(live);
3029
+ if (!options.expanded && writeCollapsedLimit === 0) {
3030
+ return cache.set(
3031
+ safeWidth,
3032
+ options.expanded,
3033
+ mode,
3034
+ configKey,
3035
+ hovered,
3036
+ clampDiffLinesToWidth(
3037
+ renderWriteCollapsedHintLine(
3038
+ options.fileExistedBeforeWrite === true,
3039
+ safeWidth,
3040
+ theme,
3041
+ hovered,
3042
+ options.headerLabel,
3043
+ ),
3044
+ safeWidth,
3045
+ ),
3046
+ );
3047
+ }
3048
+
2980
3049
  const header = renderWriteHeader(
2981
3050
  options.fileExistedBeforeWrite === true,
2982
3051
  safeWidth,
@@ -3027,7 +3096,7 @@ export function renderWriteDiffResult(
3027
3096
  const data = getDetailedData();
3028
3097
  const displayLimit = resolveDiffDisplayLimit(
3029
3098
  options.expanded,
3030
- live.diffCollapsedLines,
3099
+ writeCollapsedLimit,
3031
3100
  live.expandedPreviewMaxLines,
3032
3101
  );
3033
3102
  const processBudget = resolveDiffProcessBudget(displayLimit, wordWrap);
@@ -3065,7 +3134,7 @@ export function renderWriteDiffResult(
3065
3134
  bodyRows,
3066
3135
  safeWidth,
3067
3136
  options.expanded,
3068
- live.diffCollapsedLines,
3137
+ writeCollapsedLimit,
3069
3138
  live.expandedPreviewMaxLines,
3070
3139
  data.hunkCount,
3071
3140
  theme,
@@ -5,7 +5,9 @@ export interface ToolDisplayConfig {
5
5
  diffViewMode: DiffViewMode;
6
6
  diffIndicatorMode: DiffIndicatorMode;
7
7
  diffSplitMinWidth: number;
8
- diffCollapsedLines: number;
8
+ editDiffCollapsedLines: number;
9
+ /** Write-only collapsed body lines. 0 = `↳ created • click to show more`. */
10
+ writeDiffCollapsedLines: number;
9
11
  diffWordWrap: boolean;
10
12
  expandedPreviewMaxLines: number;
11
13
  }
@@ -14,8 +16,10 @@ export const DEFAULT_TOOL_DISPLAY_CONFIG: ToolDisplayConfig = {
14
16
  diffViewMode: "auto",
15
17
  diffIndicatorMode: "bars",
16
18
  diffSplitMinWidth: 120,
17
- /** Collapsed tool/diff body: ~half a typical terminal after chrome. */
18
- diffCollapsedLines: 24,
19
+ /** Collapsed edit/diff body: ~half a typical terminal after chrome. */
20
+ editDiffCollapsedLines: 24,
21
+ /** Write create/overwrite collapsed body; 0 shows only the expand hint. */
22
+ writeDiffCollapsedLines: 0,
19
23
  diffWordWrap: true,
20
24
  /**
21
25
  * Expanded tool/diff body cap. 40 ≈ one screen of content after title,