@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
package/README.md CHANGED
@@ -11,18 +11,20 @@ pi install npm:@herbertgao/pi-extensions
11
11
  The package bundles 11 active `@herbertgao/*` child packages, including `@herbertgao/pi-cc-extensions`, plus the following upstream packages under their original names:
12
12
 
13
13
  - `@dietrichgebert/ponytail@4.9.0`
14
- - `@juicesharp/rpiv-ask-user-question@2.6.0`
15
- - `@narumitw/pi-btw@0.52.0`
16
- - `@pi-plugins/fast-mode@0.1.9`
17
- - `pi-mcp-adapter@2.26.0`
14
+ - `@juicesharp/rpiv-ask-user-question@2.7.0`
15
+ - `@narumitw/pi-btw@0.55.1`
16
+ - `@pi-plugins/fast-mode@0.1.10`
17
+ - `pi-mcp-adapter@2.27.0`
18
18
  - `pi-footer@0.5.1`
19
- - `pi-lens@4.0.1`
20
- - `pi-web-access@0.23.0`
19
+ - `pi-lens@4.1.1`
20
+ - `pi-web-access@0.24.1`
21
21
  - `remote-pi@0.7.0`
22
22
  - `@czottmann/pi-automode@1.11.0`
23
23
 
24
24
  Pi loads their extensions and skills through `node_modules/` paths inside one package root. The upstream companions are pinned and bundled, not forked or renamed.
25
25
 
26
+ `pi-lens@4.1.1` improves diagnostics, cache, and LSP observability; prevents session-switch crashes; restores oxlint warnings; speeds large ignored-tree scans; and retries failed log writes once.
27
+
26
28
  If `pi-footer` was installed separately before upgrading to an aggregate release that includes it, remove the standalone source shown by `pi list` so only the bundled copy loads. For the pinned standalone install used while preparing this integration:
27
29
 
28
30
  ```bash
@@ -55,7 +55,7 @@ Run `/reload` after installation.
55
55
  "diffViewMode": "auto", // diff layout: auto / split / unified
56
56
  "diffIndicatorMode": "bars", // diff change indicators: bars / classic / none
57
57
  "diffSplitMinWidth": 120, // min terminal width before auto layout uses side-by-side columns
58
- "diffCollapsedLines": 24, // diff body lines shown when collapsed; beyond that shows the expand hint (Ctrl+O / click)
58
+ "editDiffCollapsedLines": 24, // diff body lines shown when collapsed; beyond that shows the expand hint (Ctrl+O / click)
59
59
  "diffWordWrap": true, // whether long diff lines wrap (otherwise truncated)
60
60
  "expandedPreviewMaxLines": 40, // max body lines for expanded output/diff
61
61
  "useSummaryTitlesAsThinkingTitle": true, // use the latest provider summary as the active thinking title
@@ -101,5 +101,5 @@ bun run typecheck
101
101
 
102
102
  ## Credits
103
103
 
104
- - Derived from [`minuque/pi-cc-extensions`](https://github.com/minuque/pi-cc-extensions) under the MIT license.
104
+ - Derived from [`minuque/pi-cc-extensions` v0.8.64](https://github.com/minuque/pi-cc-extensions/releases/tag/v0.8.64) (`4709081`) under the MIT license.
105
105
  - Rich diffs are adapted from [`MasuRii/pi-tool-display`](https://github.com/MasuRii/pi-tool-display) (MIT). See [`extensions/renderer/tool/diff/ATTRIBUTION.md`](./extensions/renderer/tool/diff/ATTRIBUTION.md).
@@ -55,7 +55,7 @@ pi install npm:@herbertgao/pi-cc-extensions
55
55
  "diffViewMode": "auto", // diff 布局:auto / split / unified
56
56
  "diffIndicatorMode": "bars", // diff 变更指示:bars / classic / none
57
57
  "diffSplitMinWidth": 120, // 自动布局下使用左右分栏的最小终端宽度
58
- "diffCollapsedLines": 24, // 折叠时展示的 diff 行数,超出显示展开提示(Ctrl+O / 点击)
58
+ "editDiffCollapsedLines": 24, // 折叠时展示的 diff 行数,超出显示展开提示(Ctrl+O / 点击)
59
59
  "diffWordWrap": true, // 长 diff 行是否换行(否则截断)
60
60
  "expandedPreviewMaxLines": 40, // 展开后输出/diff 正文的最大行数
61
61
  "useSummaryTitlesAsThinkingTitle": true, // 用最新 provider 摘要作为思考标题
@@ -101,5 +101,5 @@ bun run typecheck
101
101
 
102
102
  ## 致谢
103
103
 
104
- - 基于 MIT 许可的 [`minuque/pi-cc-extensions`](https://github.com/minuque/pi-cc-extensions) 衍生维护。
104
+ - 基于 MIT 许可的 [`minuque/pi-cc-extensions` v0.8.64](https://github.com/minuque/pi-cc-extensions/releases/tag/v0.8.64)(`4709081`)衍生维护。
105
105
  - Rich diff 改编自 [`MasuRii/pi-tool-display`](https://github.com/MasuRii/pi-tool-display)(MIT);详见 [`extensions/renderer/tool/diff/ATTRIBUTION.md`](./extensions/renderer/tool/diff/ATTRIBUTION.md)。
@@ -17,7 +17,8 @@ export type Config = {
17
17
  diffViewMode: DiffViewMode;
18
18
  diffIndicatorMode: DiffIndicatorMode;
19
19
  diffSplitMinWidth: number;
20
- diffCollapsedLines: number;
20
+ editDiffCollapsedLines: number;
21
+ writeDiffCollapsedLines: number;
21
22
  diffWordWrap: boolean;
22
23
  expandedPreviewMaxLines: number;
23
24
  useSummaryTitlesAsThinkingTitle: boolean;
@@ -40,6 +41,8 @@ export const DIFF_VIEW_MODES: DiffViewMode[] = ["auto", "split", "unified"];
40
41
  export const DIFF_INDICATOR_MODES: DiffIndicatorMode[] = ["bars", "classic", "none"];
41
42
  export const DIFF_SPLIT_MIN_WIDTH_VALUES = ["80", "100", "120", "140", "160", "180"];
42
43
  export const DIFF_COLLAPSED_LINES_VALUES = ["12", "24", "36", "48", "80", "120"];
44
+ /** Write collapsed presets. 0 = stats only (`+N -0` + expand hint). */
45
+ export const WRITE_DIFF_COLLAPSED_LINES_VALUES = ["0", "4", "8", "12", "24", "36"];
43
46
  /** Presets for expanded body height — keep low options first so cycling stays TUI-friendly. */
44
47
  export const EXPANDED_PREVIEW_MAX_LINES_VALUES = ["40", "60", "80", "120", "200", "500", "2000"];
45
48
  export const THINKING_PREVIEW_LINES_VALUES = ["0", "1", "3", "5", "10"];
@@ -65,7 +68,8 @@ export const DEFAULT_CONFIG: Config = {
65
68
  diffViewMode: DEFAULT_TOOL_DISPLAY_CONFIG.diffViewMode,
66
69
  diffIndicatorMode: DEFAULT_TOOL_DISPLAY_CONFIG.diffIndicatorMode,
67
70
  diffSplitMinWidth: DEFAULT_TOOL_DISPLAY_CONFIG.diffSplitMinWidth,
68
- diffCollapsedLines: DEFAULT_TOOL_DISPLAY_CONFIG.diffCollapsedLines,
71
+ editDiffCollapsedLines: DEFAULT_TOOL_DISPLAY_CONFIG.editDiffCollapsedLines,
72
+ writeDiffCollapsedLines: DEFAULT_TOOL_DISPLAY_CONFIG.writeDiffCollapsedLines,
69
73
  diffWordWrap: DEFAULT_TOOL_DISPLAY_CONFIG.diffWordWrap,
70
74
  expandedPreviewMaxLines: DEFAULT_TOOL_DISPLAY_CONFIG.expandedPreviewMaxLines,
71
75
  useSummaryTitlesAsThinkingTitle: true,
@@ -134,12 +138,18 @@ export function normalizeConfig(input: unknown): Config {
134
138
  40,
135
139
  300,
136
140
  ),
137
- diffCollapsedLines: pickPositiveInt(
138
- source.diffCollapsedLines,
139
- DEFAULT_CONFIG.diffCollapsedLines,
141
+ editDiffCollapsedLines: pickPositiveInt(
142
+ source.editDiffCollapsedLines ?? source.diffCollapsedLines,
143
+ DEFAULT_CONFIG.editDiffCollapsedLines,
140
144
  1,
141
145
  500,
142
146
  ),
147
+ writeDiffCollapsedLines: pickPositiveInt(
148
+ source.writeDiffCollapsedLines,
149
+ DEFAULT_CONFIG.writeDiffCollapsedLines,
150
+ 0,
151
+ 500,
152
+ ),
143
153
  diffWordWrap: source.diffWordWrap !== false,
144
154
  expandedPreviewMaxLines: pickPositiveInt(
145
155
  source.expandedPreviewMaxLines,
@@ -182,7 +192,8 @@ export function getToolDisplayConfig(source: Config = config): ToolDisplayConfig
182
192
  diffViewMode: source.diffViewMode,
183
193
  diffIndicatorMode: source.diffIndicatorMode,
184
194
  diffSplitMinWidth: source.diffSplitMinWidth,
185
- diffCollapsedLines: source.diffCollapsedLines,
195
+ editDiffCollapsedLines: source.editDiffCollapsedLines,
196
+ writeDiffCollapsedLines: source.writeDiffCollapsedLines,
186
197
  diffWordWrap: source.diffWordWrap,
187
198
  expandedPreviewMaxLines: source.expandedPreviewMaxLines,
188
199
  };
@@ -199,7 +210,8 @@ export function formatConfigStatus(source: Config = config): string {
199
210
  `diffView=${source.diffViewMode}`,
200
211
  `diffIndicator=${source.diffIndicatorMode}`,
201
212
  `diffSplitMin=${source.diffSplitMinWidth}`,
202
- `diffCollapsed=${source.diffCollapsedLines}`,
213
+ `editCollapsed=${source.editDiffCollapsedLines}`,
214
+ `writeCollapsed=${source.writeDiffCollapsedLines}`,
203
215
  `diffWordWrap=${source.diffWordWrap ? "on" : "off"}`,
204
216
  `expandedMax=${source.expandedPreviewMaxLines}`,
205
217
  `thinkingTitle=${source.useSummaryTitlesAsThinkingTitle ? "summary" : "default"}`,
@@ -27,6 +27,7 @@ import {
27
27
  SCROLL_STEP_LINES_VALUES,
28
28
  THINKING_ANIMATION_INTERVAL_VALUES,
29
29
  THINKING_PREVIEW_LINES_VALUES,
30
+ WRITE_DIFF_COLLAPSED_LINES_VALUES,
30
31
  type CompactStyleMode,
31
32
  } from "./config.ts";
32
33
 
@@ -38,7 +39,7 @@ export type CcstylePanelHooks = {
38
39
 
39
40
  function modeSettingDescription(mode: CompactStyleMode): string {
40
41
  if (mode === "compact") {
41
- return "(Experimental) One summary line per assistant round; expanded edit/write rows show rich diffs.";
42
+ return "(Experimental) One summary line per assistant round; edit/write stay single-line until expanded.";
42
43
  }
43
44
  if (mode === "off") {
44
45
  return "Pi native tool rendering. Diff options below still apply independently.";
@@ -285,15 +286,25 @@ export async function showCcstylePanel(
285
286
  buildNumberInputSubmenu(theme, diffSplitSetting, closeSubmenu),
286
287
  };
287
288
  const diffCollapsedSetting = {
288
- id: "diffCollapsedLines",
289
- label: "Collapsed lines",
289
+ id: "editDiffCollapsedLines",
290
+ label: "Edit collapsed lines",
290
291
  description:
291
- "How many diff body lines to show before the expand hint (Ctrl+O / click). Enter to type a custom value.",
292
- currentValue: String(config.diffCollapsedLines),
292
+ "How many edit/diff body lines to show before the expand hint (Ctrl+O / click). Write uses its own setting below.",
293
+ currentValue: String(config.editDiffCollapsedLines),
293
294
  values: [...DIFF_COLLAPSED_LINES_VALUES],
294
295
  submenu: (_current: string, closeSubmenu: (selected?: string) => void) =>
295
296
  buildNumberInputSubmenu(theme, diffCollapsedSetting, closeSubmenu),
296
297
  };
298
+ const writeDiffCollapsedSetting = {
299
+ id: "writeDiffCollapsedLines",
300
+ label: "Write collapsed lines",
301
+ description:
302
+ "Write-only collapsed body lines. 0 shows ↳ created + expand hint. Enter to type a custom value.",
303
+ currentValue: String(config.writeDiffCollapsedLines),
304
+ values: [...WRITE_DIFF_COLLAPSED_LINES_VALUES],
305
+ submenu: (_current: string, closeSubmenu: (selected?: string) => void) =>
306
+ buildNumberInputSubmenu(theme, writeDiffCollapsedSetting, closeSubmenu),
307
+ };
297
308
  const diffWordWrapSetting = {
298
309
  id: "diffWordWrap",
299
310
  label: "Diff word wrap",
@@ -446,14 +457,23 @@ export async function showCcstylePanel(
446
457
  );
447
458
  diffSplitSetting.currentValue = String(config.diffSplitMinWidth);
448
459
  break;
449
- case "diffCollapsedLines":
450
- config.diffCollapsedLines = pickPositiveInt(
460
+ case "editDiffCollapsedLines":
461
+ config.editDiffCollapsedLines = pickPositiveInt(
451
462
  value,
452
- DEFAULT_CONFIG.diffCollapsedLines,
463
+ DEFAULT_CONFIG.editDiffCollapsedLines,
453
464
  1,
454
465
  500,
455
466
  );
456
- diffCollapsedSetting.currentValue = String(config.diffCollapsedLines);
467
+ diffCollapsedSetting.currentValue = String(config.editDiffCollapsedLines);
468
+ break;
469
+ case "writeDiffCollapsedLines":
470
+ config.writeDiffCollapsedLines = pickPositiveInt(
471
+ value,
472
+ DEFAULT_CONFIG.writeDiffCollapsedLines,
473
+ 0,
474
+ 500,
475
+ );
476
+ writeDiffCollapsedSetting.currentValue = String(config.writeDiffCollapsedLines);
457
477
  break;
458
478
  case "diffWordWrap":
459
479
  config.diffWordWrap = value === "on";
@@ -519,6 +539,7 @@ export async function showCcstylePanel(
519
539
  diffIndicatorSetting,
520
540
  diffSplitSetting,
521
541
  diffCollapsedSetting,
542
+ writeDiffCollapsedSetting,
522
543
  diffWordWrapSetting,
523
544
  expandedMaxSetting,
524
545
  ],
@@ -11,8 +11,14 @@ import {
11
11
  type ExtensionAPI,
12
12
  type Theme,
13
13
  } from "@earendil-works/pi-coding-agent";
14
- import { getKeybindings } from "@earendil-works/pi-tui";
15
- import { Markdown, Spacer, Text, type Component } from "@earendil-works/pi-tui";
14
+ import {
15
+ getKeybindings,
16
+ truncateToWidth,
17
+ visibleWidth,
18
+ wrapTextWithAnsi,
19
+ } from "@earendil-works/pi-tui";
20
+ import { Box, Markdown, Spacer, Text, type Component } from "@earendil-works/pi-tui";
21
+ import { isToolTuiFullscreen } from "../renderer/show-more-hint.ts";
16
22
  import {
17
23
  animateCompactThinkingText,
18
24
  formatThoughtDuration,
@@ -159,30 +165,316 @@ function getThinkingToggleHint() {
159
165
  return keys.length > 0 ? `${keys.join("/")} to expand` : undefined;
160
166
  }
161
167
 
162
- class StrictThinkingPreview implements Component {
168
+ function thinkingExpandAction(): string | undefined {
169
+ return isToolTuiFullscreen() ? "click to show more" : getThinkingToggleHint();
170
+ }
171
+
172
+ // 只 wrap 尾部窗口;缓存未着色折行,着色放到取出时做,避免主题切换命中旧 ANSI。
173
+ type PreviewCacheEntry = { lines: string[]; hiddenBefore: number };
174
+ const previewCache = new Map<string, PreviewCacheEntry>();
175
+ export const THINKING_PREVIEW_CACHE_MAX = 2_048;
176
+ const PREVIEW_BUDGET_MIN_CHARS = 2_000;
177
+ const PREVIEW_BUDGET_SLACK_LINES = 2;
178
+
179
+ function getCachedPreview(key: string): PreviewCacheEntry | undefined {
180
+ const entry = previewCache.get(key);
181
+ if (!entry) return undefined;
182
+ previewCache.delete(key);
183
+ previewCache.set(key, entry);
184
+ return entry;
185
+ }
186
+
187
+ function cachePreview(key: string, entry: PreviewCacheEntry): void {
188
+ previewCache.delete(key);
189
+ while (previewCache.size >= THINKING_PREVIEW_CACHE_MAX) {
190
+ const oldest = previewCache.keys().next().value;
191
+ if (oldest === undefined) break;
192
+ previewCache.delete(oldest);
193
+ }
194
+ previewCache.set(key, entry);
195
+ }
196
+
197
+ export function clearThinkingPreviewCache(): void {
198
+ previewCache.clear();
199
+ expandedWrapCache.clear();
200
+ }
201
+
202
+ type ExpandedWrapEntry = { text: string; lines: string[] };
203
+ const expandedWrapCache = new Map<string, ExpandedWrapEntry>();
204
+ export const THINKING_EXPANDED_WRAP_CACHE_MAX = 64;
205
+
206
+ export function thinkingRunKey(messageTimestamp: number, runStartIndex: number): string {
207
+ return `${messageTimestamp}:${runStartIndex}`;
208
+ }
209
+
210
+ function expandedWrapKey(messageTimestamp: number, runStartIndex: number, width: number): string {
211
+ return `${thinkingRunKey(messageTimestamp, runStartIndex)}:${width}`;
212
+ }
213
+
214
+ function wrapExpandedThinking(
215
+ messageTimestamp: number,
216
+ runStartIndex: number,
217
+ text: string,
218
+ width: number,
219
+ ): string[] {
220
+ const key = expandedWrapKey(messageTimestamp, runStartIndex, width);
221
+ const hit = expandedWrapCache.get(key);
222
+ if (hit && hit.text === text) {
223
+ expandedWrapCache.delete(key);
224
+ expandedWrapCache.set(key, hit);
225
+ return hit.lines;
226
+ }
227
+ const lines = wrapTextWithAnsi(text.replace(/\t/g, " "), Math.max(1, width));
228
+ expandedWrapCache.delete(key);
229
+ while (expandedWrapCache.size >= THINKING_EXPANDED_WRAP_CACHE_MAX) {
230
+ const oldest = expandedWrapCache.keys().next().value;
231
+ if (oldest === undefined) break;
232
+ expandedWrapCache.delete(oldest);
233
+ }
234
+ expandedWrapCache.set(key, { text, lines });
235
+ return lines;
236
+ }
237
+
238
+ function evictExpandedWraps(messageTimestamp: number, runStartIndex: number): void {
239
+ const prefix = `${thinkingRunKey(messageTimestamp, runStartIndex)}:`;
240
+ for (const key of expandedWrapCache.keys()) {
241
+ if (key.startsWith(prefix)) expandedWrapCache.delete(key);
242
+ }
243
+ }
244
+
245
+ export function thinkingPreviewCacheSize(): number {
246
+ return previewCache.size;
247
+ }
248
+
249
+ export function thinkingExpandedWrapCacheSize(): number {
250
+ return expandedWrapCache.size;
251
+ }
252
+
253
+ /** 按可见宽度估算折行数,不走 Text 全量 wrap。无换行长段也能计到隐藏行。 */
254
+ function countWrappedLines(text: string, contentWidth: number): number {
255
+ if (!text) return 0;
256
+ const width = Math.max(1, contentWidth);
257
+ let lines = 0;
258
+ for (const raw of text.replace(/\t/g, " ").split(/\r\n|\r|\n/)) {
259
+ const w = visibleWidth(raw);
260
+ lines += w === 0 ? 1 : Math.ceil(w / width);
261
+ }
262
+ return lines;
263
+ }
264
+
265
+ function padPreviewLine(line: string, width: number, padding: number): string {
266
+ const left = padding > 0 ? " ".repeat(padding) : "";
267
+ const right = padding > 0 ? " ".repeat(padding) : "";
268
+ const withMargins = left + line + right;
269
+ return withMargins + " ".repeat(Math.max(0, width - visibleWidth(withMargins)));
270
+ }
271
+
272
+ function layoutThinkingPreview(
273
+ text: string,
274
+ width: number,
275
+ padding: number,
276
+ ): { visible: string[]; hiddenLines: number } {
277
+ if (!text || config.previewLines <= 0) return { visible: [], hiddenLines: 0 };
278
+ const contentWidth = Math.max(1, width - padding * 2);
279
+ const budget = Math.max(
280
+ width * (config.previewLines + PREVIEW_BUDGET_SLACK_LINES),
281
+ PREVIEW_BUDGET_MIN_CHARS,
282
+ );
283
+ let source = text;
284
+ let cut = 0;
285
+ if (source.length > budget) {
286
+ const start = source.length - budget;
287
+ const newline = source.indexOf("\n", start);
288
+ cut = newline === -1 ? start : newline + 1;
289
+ if (cut < source.length) source = source.slice(cut);
290
+ else cut = 0;
291
+ }
292
+ const cacheKey = `${width}:${padding}:${cut}:${source}`;
293
+ let entry = getCachedPreview(cacheKey);
294
+ if (!entry) {
295
+ entry = {
296
+ lines: wrapTextWithAnsi(source.replace(/\t/g, " "), contentWidth),
297
+ hiddenBefore: cut > 0 ? countWrappedLines(text.slice(0, cut), contentWidth) : 0,
298
+ };
299
+ cachePreview(cacheKey, entry);
300
+ }
301
+ const hiddenLines = entry.hiddenBefore + Math.max(0, entry.lines.length - config.previewLines);
302
+ const visible = hiddenLines > 0 ? entry.lines.slice(-config.previewLines) : entry.lines;
303
+ return { visible, hiddenLines };
304
+ }
305
+
306
+ function hiddenPreviewHint(
307
+ hiddenLines: number,
308
+ forceExpandHint = false,
309
+ ): { prefix: string; action: string; suffix: string } | undefined {
310
+ const action = thinkingExpandAction() ?? "";
311
+ if (hiddenLines > 0) {
312
+ const noun = hiddenLines === 1 ? "line" : "lines";
313
+ return {
314
+ prefix: ` • (${hiddenLines} more ${noun}${action ? ", " : ""}`,
315
+ action,
316
+ suffix: ")",
317
+ };
318
+ }
319
+ if (forceExpandHint && isToolTuiFullscreen()) {
320
+ return { prefix: " • ", action: "click to show more", suffix: "" };
321
+ }
322
+ return undefined;
323
+ }
324
+
325
+ const expandedThinking = new Set<string>();
326
+
327
+ /** 折叠预览 + 展开全文。fullscreen 点击 hint 展开、双击整块收起,对齐工具卡。 */
328
+ export class ThinkingPreviewBlock implements Component {
329
+ private heading: string;
163
330
  private text: string;
164
331
  private padding: number;
332
+ readonly messageTimestamp: number;
333
+ readonly runStartIndex: number;
165
334
  private style: (text: string) => string;
166
-
167
- constructor(text: string, padding: number, style: (text: string) => string) {
335
+ private theme: Theme | undefined;
336
+ private _expanded: boolean;
337
+ private hintHovered = false;
338
+ private collapsedMemo:
339
+ | {
340
+ width: number;
341
+ previewLines: number;
342
+ hintHovered: boolean;
343
+ expandAction: string | undefined;
344
+ lines: string[];
345
+ }
346
+ | undefined;
347
+
348
+ constructor(
349
+ heading: string,
350
+ text: string,
351
+ padding: number,
352
+ messageTimestamp: number,
353
+ style: (text: string) => string,
354
+ theme?: Theme,
355
+ runStartIndex = 0,
356
+ ) {
357
+ this.heading = heading;
168
358
  this.text = text;
169
359
  this.padding = padding;
360
+ this.messageTimestamp = messageTimestamp;
361
+ this.runStartIndex = runStartIndex;
170
362
  this.style = style;
363
+ this.theme = theme;
364
+ this._expanded = expandedThinking.has(thinkingRunKey(messageTimestamp, runStartIndex));
365
+ }
366
+
367
+ private paint(color: string, text: string): string {
368
+ return this.theme && typeof this.theme.fg === "function"
369
+ ? this.theme.fg(color as never, text)
370
+ : text;
371
+ }
372
+
373
+ get expanded(): boolean {
374
+ return this._expanded;
375
+ }
376
+
377
+ setExpanded(expanded: boolean): void {
378
+ if (this._expanded !== expanded) this.collapsedMemo = undefined;
379
+ this._expanded = expanded;
380
+ const key = thinkingRunKey(this.messageTimestamp, this.runStartIndex);
381
+ if (expanded) expandedThinking.add(key);
382
+ else {
383
+ expandedThinking.delete(key);
384
+ evictExpandedWraps(this.messageTimestamp, this.runStartIndex);
385
+ }
386
+ }
387
+
388
+ setHintHovered(hovered: boolean): void {
389
+ if (this.hintHovered !== hovered) this.collapsedMemo = undefined;
390
+ this.hintHovered = hovered;
391
+ }
392
+
393
+ private headingLines(width: number, hiddenLines: number, padding: number): string[] {
394
+ const hint = this._expanded
395
+ ? undefined
396
+ : hiddenPreviewHint(hiddenLines, Boolean(this.text) && config.previewLines <= 0);
397
+ if (!hint) return new Text(this.heading, padding, 0).render(width);
398
+ const rawHint = hint.prefix + hint.action + hint.suffix;
399
+ const contentWidth = Math.max(1, width - padding * 2);
400
+ const headingBudget = Math.max(0, contentWidth - visibleWidth(rawHint));
401
+ const clipped =
402
+ visibleWidth(this.heading) > headingBudget
403
+ ? truncateToWidth(this.heading, headingBudget, "")
404
+ : this.heading;
405
+ const action = this.paint(this.hintHovered ? "text" : "dim", hint.action);
406
+ return new Text(
407
+ clipped + this.paint("dim", hint.prefix) + action + this.paint("dim", hint.suffix),
408
+ padding,
409
+ 0,
410
+ ).render(width);
411
+ }
412
+
413
+ private bodyLines(width: number, padding: number): { lines: string[]; hiddenLines: number } {
414
+ if (!this.text || (config.previewLines <= 0 && !this._expanded)) {
415
+ return { lines: [], hiddenLines: 0 };
416
+ }
417
+ if (this._expanded) {
418
+ return {
419
+ lines: wrapExpandedThinking(this.messageTimestamp, this.runStartIndex, this.text, width),
420
+ hiddenLines: 0,
421
+ };
422
+ }
423
+ const preview = layoutThinkingPreview(this.text, width, padding);
424
+ return { lines: preview.visible, hiddenLines: preview.hiddenLines };
171
425
  }
172
426
 
173
427
  render(width: number) {
174
- const lines = new Text(this.style(this.text), this.padding, 0).render(width);
175
- if (lines.length <= config.previewLines) return lines;
428
+ if (this._expanded) {
429
+ const innerWidth = Math.max(1, width - 2);
430
+ const body = this.bodyLines(innerWidth, 0);
431
+ const heading = this.headingLines(innerWidth, 0, 0);
432
+ const inner = body.lines.length
433
+ ? [...heading, ...body.lines.map((line) => this.style(line))]
434
+ : heading;
435
+ const bgFn =
436
+ this.theme && typeof this.theme.bg === "function"
437
+ ? (text: string) => this.theme!.bg("userMessageBg" as never, text)
438
+ : undefined;
439
+ const box = new Box(1, 1, bgFn);
440
+ box.addChild({
441
+ render: () => inner,
442
+ invalidate() {},
443
+ });
444
+ return box.render(width);
445
+ }
176
446
 
177
- const hiddenLines = lines.length - config.previewLines;
178
- const noun = hiddenLines === 1 ? "line" : "lines";
179
- const toggleHint = getThinkingToggleHint();
180
- const hint = `... (${hiddenLines} more ${noun}${toggleHint ? `, ${toggleHint}` : ""})`;
181
- const hintLines = new Text(this.style(hint), this.padding, 0).render(width);
182
- return [...hintLines, ...lines.slice(-config.previewLines)];
447
+ const expandAction = thinkingExpandAction();
448
+ if (
449
+ this.collapsedMemo?.width === width &&
450
+ this.collapsedMemo.previewLines === config.previewLines &&
451
+ this.collapsedMemo.hintHovered === this.hintHovered &&
452
+ this.collapsedMemo.expandAction === expandAction
453
+ ) {
454
+ return this.collapsedMemo.lines;
455
+ }
456
+
457
+ const body = this.bodyLines(width, this.padding);
458
+ const heading = this.headingLines(width, body.hiddenLines, this.padding);
459
+ const lines = body.lines.length
460
+ ? [
461
+ ...heading,
462
+ ...body.lines.map((line) => padPreviewLine(this.style(line), width, this.padding)),
463
+ ]
464
+ : heading;
465
+ this.collapsedMemo = {
466
+ width,
467
+ previewLines: config.previewLines,
468
+ hintHovered: this.hintHovered,
469
+ expandAction,
470
+ lines,
471
+ };
472
+ return lines;
183
473
  }
184
474
 
185
- invalidate() {}
475
+ invalidate() {
476
+ this.collapsedMemo = undefined;
477
+ }
186
478
  }
187
479
 
188
480
  function parseSummaryPart(text: string): SummaryPart | undefined {
@@ -456,14 +748,18 @@ function compactThinking(pi: ExtensionAPI) {
456
748
  durationText ? `Thought for ${durationText}` : (latestSummary?.title ?? "Thought"),
457
749
  );
458
750
  }
459
- self.contentContainer.addChild(new Text(heading, self.outputPad, 0));
460
-
461
- const previewSource = latestSummary?.body ?? thinkingBlocks.join("\n\n");
462
- if (config.previewLines > 0 && previewSource.trim()) {
463
- self.contentContainer.addChild(
464
- new StrictThinkingPreview(previewSource.trim(), self.outputPad, thinkingStyle),
465
- );
466
- }
751
+ const previewSource = (latestSummary?.body ?? thinkingBlocks.join("\n\n")).trim();
752
+ self.contentContainer.addChild(
753
+ new ThinkingPreviewBlock(
754
+ heading,
755
+ previewSource,
756
+ self.outputPad,
757
+ message.timestamp,
758
+ thinkingStyle,
759
+ activeTheme,
760
+ runStartIndex,
761
+ ),
762
+ );
467
763
 
468
764
  const hasVisibleContentAfter = message.content
469
765
  .slice(i + 1)
@@ -728,6 +1024,8 @@ function compactThinking(pi: ExtensionAPI) {
728
1024
  latestComponentTimestamp = undefined;
729
1025
  completedDurations.clear();
730
1026
  streamingComponents.clear();
1027
+ expandedThinking.clear();
1028
+ clearThinkingPreviewCache();
731
1029
  if (ctx.mode === "tui") ctx.ui.setWidget(WIDGET_ID, undefined);
732
1030
 
733
1031
  if (patchInstalled) {