@herbertgao/pi-extensions 2026.8.14 → 2026.9.0

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 (270) hide show
  1. package/README.md +19 -13
  2. package/THIRD_PARTY_NOTICES.md +26 -1
  3. package/node_modules/@czottmann/pi-automode/CHANGELOG.md +8 -1
  4. package/node_modules/@czottmann/pi-automode/README.md +4 -0
  5. package/node_modules/@czottmann/pi-automode/extensions/auto-mode/classifier.ts +71 -9
  6. package/node_modules/@czottmann/pi-automode/package.json +1 -1
  7. package/node_modules/@herbertgao/pi-bark/LICENSE +21 -0
  8. package/node_modules/@herbertgao/pi-bark/README.md +44 -0
  9. package/node_modules/@herbertgao/pi-bark/assets/pi-icon.png +0 -0
  10. package/node_modules/@herbertgao/pi-bark/package.json +53 -0
  11. package/node_modules/@herbertgao/pi-bark/src/index.ts +178 -0
  12. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/config.ts +20 -0
  13. package/node_modules/@herbertgao/pi-cc-extensions/extensions/config/panel.ts +46 -3
  14. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/interaction.ts +55 -17
  15. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/packets.ts +6 -0
  16. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/mouse/scroll.ts +5 -0
  17. package/node_modules/@herbertgao/pi-cc-extensions/extensions/renderer/tool/result.ts +34 -30
  18. package/node_modules/@herbertgao/pi-cc-extensions/package.json +3 -3
  19. package/node_modules/@juicesharp/rpiv-ask-user-question/package.json +2 -2
  20. package/node_modules/@narumitw/pi-btw/README.md +129 -88
  21. package/node_modules/@narumitw/pi-btw/dist/index.ts +283 -59
  22. package/node_modules/@narumitw/pi-btw/dist/index.ts.map +3 -3
  23. package/node_modules/@narumitw/pi-btw/package.json +5 -8
  24. package/node_modules/@narumitw/pi-btw/src/btw.ts +31 -26
  25. package/node_modules/@narumitw/pi-btw/src/fullscreen-ui.ts +264 -24
  26. package/node_modules/@narumitw/pi-btw/src/menu.ts +34 -2
  27. package/node_modules/@narumitw/pi-btw/src/settings.ts +16 -0
  28. package/node_modules/@narumitw/pi-btw/src/text.ts +18 -0
  29. package/node_modules/@narumitw/pi-btw/src/transcript-pager.ts +5 -16
  30. package/node_modules/@narumitw/pi-caffeinate/LICENSE +21 -0
  31. package/node_modules/@narumitw/pi-caffeinate/README.md +224 -0
  32. package/node_modules/@narumitw/pi-caffeinate/dist/index.ts +1112 -0
  33. package/node_modules/@narumitw/pi-caffeinate/dist/index.ts.map +7 -0
  34. package/node_modules/@narumitw/pi-caffeinate/package.json +53 -0
  35. package/node_modules/@narumitw/pi-caffeinate/src/caffeinate.ts +811 -0
  36. package/node_modules/@narumitw/pi-caffeinate/src/dbus-inhibit.ts +153 -0
  37. package/node_modules/@narumitw/pi-caffeinate/src/index.ts +1 -0
  38. package/node_modules/@narumitw/pi-caffeinate/src/inhibitor-process.ts +43 -0
  39. package/node_modules/@narumitw/pi-caffeinate/src/inhibitors.ts +167 -0
  40. package/node_modules/@narumitw/pi-caffeinate/src/settings.ts +202 -0
  41. package/node_modules/@tifan/pi-handoff/README.md +39 -13
  42. package/node_modules/@tifan/pi-handoff/package.json +2 -2
  43. package/node_modules/@tifan/pi-handoff/src/index.ts +166 -5
  44. package/node_modules/@tifan/pi-recap/README.md +1 -1
  45. package/node_modules/@tifan/pi-recap/package.json +2 -2
  46. package/node_modules/@tifan/pi-recap/src/index.ts +15 -0
  47. package/node_modules/@tifan/pi-rename/README.md +42 -21
  48. package/node_modules/@tifan/pi-rename/package.json +1 -1
  49. package/node_modules/@tifan/pi-rename/src/index.ts +62 -11
  50. package/node_modules/@tifan/pi-rename/src/language.ts +18 -0
  51. package/node_modules/@tifan/pi-rename/src/models.ts +69 -13
  52. package/node_modules/@tifan/pi-rename/src/naming.ts +36 -7
  53. package/node_modules/@tifan/pi-rename/src/sanitize.ts +22 -14
  54. package/node_modules/pi-lens/CHANGELOG.md +320 -0
  55. package/node_modules/pi-lens/config/dependency-cruiser-eager-allowlist.json +79 -0
  56. package/node_modules/pi-lens/dist/clients/actionable-warnings-logger.js +16 -1
  57. package/node_modules/pi-lens/dist/clients/ast-grep-client.js +13 -6
  58. package/node_modules/pi-lens/dist/clients/availability-probe-flight.js +12 -0
  59. package/node_modules/pi-lens/dist/clients/biome-client.js +7 -0
  60. package/node_modules/pi-lens/dist/clients/blocker-freshness.js +20 -0
  61. package/node_modules/pi-lens/dist/clients/bounded-telemetry.js +56 -19
  62. package/node_modules/pi-lens/dist/clients/build-identity.js +95 -0
  63. package/node_modules/pi-lens/dist/clients/bus-publish.js +3 -0
  64. package/node_modules/pi-lens/dist/clients/cache/rule-cache.js +2 -1
  65. package/node_modules/pi-lens/dist/clients/cache-observability.js +2 -1
  66. package/node_modules/pi-lens/dist/clients/cascade-logger.js +15 -1
  67. package/node_modules/pi-lens/dist/clients/dead-code-client.js +14 -11
  68. package/node_modules/pi-lens/dist/clients/degradation-ledger.js +56 -4
  69. package/node_modules/pi-lens/dist/clients/demoted-finding-render.js +14 -0
  70. package/node_modules/pi-lens/dist/clients/dependency-checker.js +20 -3
  71. package/node_modules/pi-lens/dist/clients/deps/minimatch.js +1 -1
  72. package/node_modules/pi-lens/dist/clients/dispatch/collect-later-tier.js +39 -0
  73. package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +150 -9
  74. package/node_modules/pi-lens/dist/clients/dispatch/fact-store.js +231 -9
  75. package/node_modules/pi-lens/dist/clients/dispatch/integration.js +205 -100
  76. package/node_modules/pi-lens/dist/clients/dispatch/pending-runner-findings.js +87 -0
  77. package/node_modules/pi-lens/dist/clients/dispatch/plan.js +21 -5
  78. package/node_modules/pi-lens/dist/clients/dispatch/runners/ast-grep-napi.js +174 -55
  79. package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +5 -1
  80. package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-lint.js +16 -3
  81. package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-render.js +54 -9
  82. package/node_modules/pi-lens/dist/clients/dispatch/runners/index.js +1 -3
  83. package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +37 -1
  84. package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +4 -1
  85. package/node_modules/pi-lens/dist/clients/dispatch/runners/oxlint.js +11 -4
  86. package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +4 -0
  87. package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +8 -3
  88. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +76 -25
  89. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/spawn-outcome.js +4 -0
  90. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/tool-failure.js +19 -7
  91. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/toolchain-availability.js +7 -13
  92. package/node_modules/pi-lens/dist/clients/dispatch/runners/yaml-rule-parser.js +51 -17
  93. package/node_modules/pi-lens/dist/clients/event-loop-monitor.js +66 -1
  94. package/node_modules/pi-lens/dist/clients/file-utils.js +157 -7
  95. package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +5 -0
  96. package/node_modules/pi-lens/dist/clients/formatters.js +28 -3
  97. package/node_modules/pi-lens/dist/clients/git-guard.js +197 -47
  98. package/node_modules/pi-lens/dist/clients/git-tracked-ignore.js +32 -1
  99. package/node_modules/pi-lens/dist/clients/govulncheck-client.js +5 -1
  100. package/node_modules/pi-lens/dist/clients/gzip-stage-write.js +7 -0
  101. package/node_modules/pi-lens/dist/clients/installer/index.js +131 -34
  102. package/node_modules/pi-lens/dist/clients/installer/managed-tool-refresh.js +3 -1
  103. package/node_modules/pi-lens/dist/clients/instance-reaper.js +4 -13
  104. package/node_modules/pi-lens/dist/clients/instance-registry-lock.js +145 -0
  105. package/node_modules/pi-lens/dist/clients/instance-registry.js +432 -122
  106. package/node_modules/pi-lens/dist/clients/jscpd-client.js +6 -1
  107. package/node_modules/pi-lens/dist/clients/language-profile.js +4 -2
  108. package/node_modules/pi-lens/dist/clients/latency-logger.js +19 -1
  109. package/node_modules/pi-lens/dist/clients/lens-flag-registry.js +8 -0
  110. package/node_modules/pi-lens/dist/clients/lens-map.js +3 -1
  111. package/node_modules/pi-lens/dist/clients/lsp/cascade-tier.js +4 -0
  112. package/node_modules/pi-lens/dist/clients/lsp/client.js +516 -31
  113. package/node_modules/pi-lens/dist/clients/lsp/config.js +25 -2
  114. package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +9 -4
  115. package/node_modules/pi-lens/dist/clients/lsp/index.js +509 -182
  116. package/node_modules/pi-lens/dist/clients/lsp/jvm-runtime.js +5 -0
  117. package/node_modules/pi-lens/dist/clients/lsp/launch.js +36 -8
  118. package/node_modules/pi-lens/dist/clients/lsp/pending-aux-coverage.js +116 -4
  119. package/node_modules/pi-lens/dist/clients/lsp/server.js +142 -13
  120. package/node_modules/pi-lens/dist/clients/lsp/session-roots.js +99 -0
  121. package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +16 -6
  122. package/node_modules/pi-lens/dist/clients/lsp/workspace-sweep-hold.js +32 -23
  123. package/node_modules/pi-lens/dist/clients/lsp-mutation.js +16 -2
  124. package/node_modules/pi-lens/dist/clients/mcp/analyze.js +12 -6
  125. package/node_modules/pi-lens/dist/clients/mcp/session.js +14 -1
  126. package/node_modules/pi-lens/dist/clients/memory-sampler.js +23 -1
  127. package/node_modules/pi-lens/dist/clients/message-end-attribution.js +30 -0
  128. package/node_modules/pi-lens/dist/clients/metrics-history.js +21 -4
  129. package/node_modules/pi-lens/dist/clients/opaque-mutation-scan.js +232 -18
  130. package/node_modules/pi-lens/dist/clients/package-manager.js +6 -18
  131. package/node_modules/pi-lens/dist/clients/path-keyed-map.js +14 -1
  132. package/node_modules/pi-lens/dist/clients/path-utils.js +32 -0
  133. package/node_modules/pi-lens/dist/clients/pipeline.js +0 -8
  134. package/node_modules/pi-lens/dist/clients/process-singletons.js +210 -0
  135. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/madge.js +2 -1
  136. package/node_modules/pi-lens/dist/clients/project-diagnostics/scanner.js +10 -4
  137. package/node_modules/pi-lens/dist/clients/project-snapshot.js +33 -11
  138. package/node_modules/pi-lens/dist/clients/read-guard-logger.js +24 -2
  139. package/node_modules/pi-lens/dist/clients/read-guard.js +74 -7
  140. package/node_modules/pi-lens/dist/clients/recent-touches.js +17 -5
  141. package/node_modules/pi-lens/dist/clients/review-graph/builder.js +639 -62
  142. package/node_modules/pi-lens/dist/clients/review-graph/tsconfig-paths.js +5 -1
  143. package/node_modules/pi-lens/dist/clients/review-graph-logger.js +21 -1
  144. package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +68 -0
  145. package/node_modules/pi-lens/dist/clients/runtime-session.js +30 -12
  146. package/node_modules/pi-lens/dist/clients/runtime-tool-call.js +15 -0
  147. package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +106 -7
  148. package/node_modules/pi-lens/dist/clients/runtime-turn.js +242 -27
  149. package/node_modules/pi-lens/dist/clients/safe-spawn.js +158 -18
  150. package/node_modules/pi-lens/dist/clients/security-scan-client.js +48 -17
  151. package/node_modules/pi-lens/dist/clients/session-lifecycle.js +238 -42
  152. package/node_modules/pi-lens/dist/clients/sg-runner.js +27 -15
  153. package/node_modules/pi-lens/dist/clients/shared-checkout-guard.js +338 -0
  154. package/node_modules/pi-lens/dist/clients/spawn-output-cap.js +37 -0
  155. package/node_modules/pi-lens/dist/clients/spawn-timeout-cooldown.js +15 -1
  156. package/node_modules/pi-lens/dist/clients/startup-scan.js +6 -7
  157. package/node_modules/pi-lens/dist/clients/startup-timing.js +69 -4
  158. package/node_modules/pi-lens/dist/clients/string-utils.js +20 -0
  159. package/node_modules/pi-lens/dist/clients/test-runner-client.js +419 -88
  160. package/node_modules/pi-lens/dist/clients/tool-policy.js +1 -1
  161. package/node_modules/pi-lens/dist/clients/tree-sitter-client.js +11 -5
  162. package/node_modules/pi-lens/dist/clients/tree-sitter-logger.js +17 -1
  163. package/node_modules/pi-lens/dist/clients/warm-attach.js +8 -10
  164. package/node_modules/pi-lens/dist/clients/word-index-logger.js +13 -1
  165. package/node_modules/pi-lens/dist/clients/word-index-store.js +448 -0
  166. package/node_modules/pi-lens/dist/clients/word-index.js +582 -104
  167. package/node_modules/pi-lens/dist/clients/workspace-topology.js +17 -0
  168. package/node_modules/pi-lens/dist/clients/zizmor-config.js +26 -6
  169. package/node_modules/pi-lens/dist/index.js +11243 -6651
  170. package/node_modules/pi-lens/dist/mcp/build-staleness.js +8 -7
  171. package/node_modules/pi-lens/dist/mcp/cli.js +3 -1
  172. package/node_modules/pi-lens/dist/mcp/server.js +6 -1
  173. package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +4 -0
  174. package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +14 -5
  175. package/node_modules/pi-lens/dist/tools/lsp-navigation.js +3 -1
  176. package/node_modules/pi-lens/docs/agent-guide.md +4 -2
  177. package/node_modules/pi-lens/docs/ast-grep_rules_catalog.md +41 -10
  178. package/node_modules/pi-lens/docs/astplayground.md +26 -17
  179. package/node_modules/pi-lens/package.json +5 -1
  180. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/c-no-malloc-free-test.yml +20 -0
  181. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/cpp-no-malloc-free-test.yml +25 -0
  182. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/cpp-no-printf-test.yml +19 -0
  183. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/go-no-fmt-println-test.yml +19 -0
  184. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/go-no-panic-in-lib-test.yml +17 -0
  185. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/go-no-underscore-func-name-test.yml +18 -0
  186. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/go-prefer-errors-is-test.yml +15 -0
  187. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/go-prefer-string-builder-test.yml +21 -0
  188. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/hyphenated-svg-attribute-test.yml +11 -0
  189. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/kotlin-no-lateinit-test.yml +17 -0
  190. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/kotlin-no-nullable-boolean-test.yml +15 -0
  191. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/kotlin-no-println-test.yml +19 -0
  192. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/kotlin-no-unnecessary-let-test.yml +7 -0
  193. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/kotlin-no-unsafe-cast-test.yml +7 -0
  194. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/kotlin-no-var-test.yml +7 -0
  195. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/kotlin-prefer-data-class-test.yml +25 -0
  196. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/kotlin-prefer-is-empty-test.yml +11 -0
  197. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-important-test.yml +21 -0
  198. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-raw-types-test.yml +30 -0
  199. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-string-concat-in-loop-test.yml +100 -0
  200. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/no-system-out-println-test.yml +7 -0
  201. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/prefer-string-is-empty-test.yml +7 -0
  202. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/python-optional-type-test.yml +9 -0
  203. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/reducible-list-comprehension-test.yml +11 -0
  204. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/ruby-symbol-to-proc-candidate-test.yml +10 -0
  205. package/node_modules/pi-lens/rules/ast-grep-rules/rule-tests/rust-no-chars-enumerate-test.yml +7 -0
  206. package/node_modules/pi-lens/rules/ast-grep-rules/rules/c-no-malloc-free.yml +39 -0
  207. package/node_modules/pi-lens/rules/ast-grep-rules/rules/cpp-no-malloc-free.yml +45 -0
  208. package/node_modules/pi-lens/rules/ast-grep-rules/rules/cpp-no-printf.yml +41 -0
  209. package/node_modules/pi-lens/rules/ast-grep-rules/rules/go-no-fmt-println.yml +43 -0
  210. package/node_modules/pi-lens/rules/ast-grep-rules/rules/go-no-panic-in-lib.yml +41 -0
  211. package/node_modules/pi-lens/rules/ast-grep-rules/rules/go-no-underscore-func-name.yml +35 -0
  212. package/node_modules/pi-lens/rules/ast-grep-rules/rules/go-prefer-errors-is.yml +40 -0
  213. package/node_modules/pi-lens/rules/ast-grep-rules/rules/go-prefer-string-builder.yml +43 -0
  214. package/node_modules/pi-lens/rules/ast-grep-rules/rules/hyphenated-svg-attribute.yml +32 -0
  215. package/node_modules/pi-lens/rules/ast-grep-rules/rules/kotlin-no-lateinit.yml +37 -0
  216. package/node_modules/pi-lens/rules/ast-grep-rules/rules/kotlin-no-nullable-boolean.yml +33 -0
  217. package/node_modules/pi-lens/rules/ast-grep-rules/rules/kotlin-no-println.yml +42 -0
  218. package/node_modules/pi-lens/rules/ast-grep-rules/rules/kotlin-no-unnecessary-let.yml +28 -0
  219. package/node_modules/pi-lens/rules/ast-grep-rules/rules/kotlin-no-unsafe-cast.yml +28 -0
  220. package/node_modules/pi-lens/rules/ast-grep-rules/rules/kotlin-no-var.yml +35 -0
  221. package/node_modules/pi-lens/rules/ast-grep-rules/rules/kotlin-prefer-data-class.yml +66 -0
  222. package/node_modules/pi-lens/rules/ast-grep-rules/rules/kotlin-prefer-is-empty.yml +35 -0
  223. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-important.yml +21 -0
  224. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-raw-types.yml +33 -0
  225. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-string-concat-in-loop.yml +90 -0
  226. package/node_modules/pi-lens/rules/ast-grep-rules/rules/no-system-out-println.yml +16 -0
  227. package/node_modules/pi-lens/rules/ast-grep-rules/rules/prefer-string-is-empty.yml +11 -0
  228. package/node_modules/pi-lens/rules/ast-grep-rules/rules/python-optional-type.yml +22 -0
  229. package/node_modules/pi-lens/rules/ast-grep-rules/rules/reducible-list-comprehension.yml +29 -0
  230. package/node_modules/pi-lens/rules/ast-grep-rules/rules/ruby-symbol-to-proc-candidate.yml +25 -0
  231. package/node_modules/pi-lens/rules/ast-grep-rules/rules/rust-no-chars-enumerate.yml +19 -0
  232. package/node_modules/pi-mcp-adapter/CHANGELOG.md +42 -0
  233. package/node_modules/pi-mcp-adapter/README.md +15 -15
  234. package/node_modules/pi-mcp-adapter/commands.ts +59 -22
  235. package/node_modules/pi-mcp-adapter/config.ts +18 -4
  236. package/node_modules/pi-mcp-adapter/direct-tools.ts +26 -6
  237. package/node_modules/pi-mcp-adapter/dist/config.d.ts +4 -0
  238. package/node_modules/pi-mcp-adapter/dist/config.js +13 -4
  239. package/node_modules/pi-mcp-adapter/dist/config.js.map +1 -1
  240. package/node_modules/pi-mcp-adapter/dist/types.d.ts +12 -4
  241. package/node_modules/pi-mcp-adapter/dist/types.js.map +1 -1
  242. package/node_modules/pi-mcp-adapter/error-signal.ts +15 -4
  243. package/node_modules/pi-mcp-adapter/errors.ts +141 -0
  244. package/node_modules/pi-mcp-adapter/host-html-template.ts +58 -5
  245. package/node_modules/pi-mcp-adapter/index.ts +2 -3
  246. package/node_modules/pi-mcp-adapter/init.ts +5 -0
  247. package/node_modules/pi-mcp-adapter/mcp-auth-flow.ts +105 -32
  248. package/node_modules/pi-mcp-adapter/mcp-panel.ts +30 -9
  249. package/node_modules/pi-mcp-adapter/mcp-setup-panel.ts +66 -28
  250. package/node_modules/pi-mcp-adapter/mcp-status.ts +2 -0
  251. package/node_modules/pi-mcp-adapter/package.json +2 -1
  252. package/node_modules/pi-mcp-adapter/proxy-modes.ts +88 -25
  253. package/node_modules/pi-mcp-adapter/sandbox-proxy-template.ts +217 -0
  254. package/node_modules/pi-mcp-adapter/server-manager.ts +343 -6
  255. package/node_modules/pi-mcp-adapter/skills/mcp-scripting/SKILL.md +1 -0
  256. package/node_modules/pi-mcp-adapter/types.ts +19 -4
  257. package/node_modules/pi-mcp-adapter/ui-resource-handler.ts +18 -2
  258. package/node_modules/pi-mcp-adapter/ui-server.ts +179 -54
  259. package/node_modules/pi-mcp-adapter/ui-session.ts +28 -8
  260. package/node_modules/pi-web-access/CHANGELOG.md +20 -0
  261. package/node_modules/pi-web-access/README.md +15 -2
  262. package/node_modules/pi-web-access/extract.ts +57 -12
  263. package/node_modules/pi-web-access/github-extract.ts +47 -3
  264. package/node_modules/pi-web-access/index.ts +1 -1
  265. package/node_modules/pi-web-access/package.json +1 -1
  266. package/node_modules/pi-web-access/page-query.ts +61 -8
  267. package/package.json +21 -17
  268. package/node_modules/@tifan/pi-titlebar-spinner/README.md +0 -24
  269. package/node_modules/@tifan/pi-titlebar-spinner/package.json +0 -39
  270. package/node_modules/@tifan/pi-titlebar-spinner/src/index.ts +0 -49
package/README.md CHANGED
@@ -8,33 +8,39 @@ Aggregate installer for HerbertGao-maintained Pi extensions and pinned upstream
8
8
  pi install npm:@herbertgao/pi-extensions
9
9
  ```
10
10
 
11
- Requires Node.js 24 or newer.
11
+ Requires Node.js 24 or newer and Pi 0.84.4 or newer.
12
12
 
13
- The package bundles 3 active `@herbertgao/*` child packages—`pi-cc-extensions`, `resume-from`, and `pi-subagents`—plus the following upstream packages under their original names:
13
+ The package bundles 4 active `@herbertgao/*` child packages—`pi-bark`, `pi-cc-extensions`, `resume-from`, and `pi-subagents`—plus the following upstream packages under their original names:
14
14
 
15
15
  - `@dietrichgebert/ponytail@4.9.0`
16
- - `@juicesharp/rpiv-ask-user-question@2.7.1`
16
+ - `@juicesharp/rpiv-ask-user-question@2.8.0`
17
17
  - `@luxusai/pi-hindsight@0.12.0`
18
- - `@narumitw/pi-btw@0.55.4`
18
+ - `@narumitw/pi-btw@0.57.0`
19
+ - `@narumitw/pi-caffeinate@0.49.7`
19
20
  - `@pi-plugins/fast-mode@0.1.10`
20
21
  - `@tifan/pi-copy-response@0.2.6`
21
- - `@tifan/pi-handoff@2.0.1`
22
+ - `@tifan/pi-handoff@2.2.0`
22
23
  - `@tifan/pi-inline-skills@1.0.5`
23
24
  - `@tifan/pi-mermaid-open@0.2.0`
24
25
  - `@tifan/pi-preferred-thinking@1.0.1`
25
- - `@tifan/pi-recap@0.4.5`
26
- - `@tifan/pi-rename@0.5.1`
27
- - `@tifan/pi-titlebar-spinner@0.1.3`
28
- - `pi-mcp-adapter@2.30.0`
26
+ - `@tifan/pi-recap@0.4.6`
27
+ - `@tifan/pi-rename@0.6.0`
28
+ - `pi-mcp-adapter@2.31.0`
29
29
  - `pi-footer@0.5.1`
30
- - `pi-lens@4.1.2`
31
- - `pi-web-access@0.26.0`
30
+ - `pi-lens@4.1.3`
31
+ - `pi-web-access@0.27.0`
32
32
  - `remote-pi@0.7.0`
33
- - `@czottmann/pi-automode@1.14.0`
33
+ - `@czottmann/pi-automode@1.15.0`
34
34
 
35
35
  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.
36
36
 
37
- `@herbertgao/resume-from@0.2.0` keeps Claude Code sessions associated with their original repository when the active transcript later moves into a nested cwd. `pi-lens@4.1.2` improves delayed LSP diagnostics, stale-result cleanup, process cleanup, and snapshot completeness. `pi-automode@1.14.0` bounds classifier streams and permits only validated temporary-directory subtrees. `pi-web-access@0.26.0` adds explicit XCrawl search plus safer query and extraction fallbacks. Preferred Thinking 1.0.1 preserves an explicit subagent `--thinking` choice.
37
+ ### Bark notifications
38
+
39
+ `@herbertgao/pi-bark` sends localized Bark pushes when a user-facing Pi run fully settles or `@juicesharp/rpiv-ask-user-question` needs an answer. Notifications include emoji-labeled machine/path metadata and support the bundled official Pi badge through Bark's `icon` parameter. Configure it in `$PI_CODING_AGENT_DIR/bark.json` (normally `~/.pi/agent/bark.json`); see the [package README](../pi-bark/README.md). Without a valid endpoint it stays inactive.
40
+
41
+ `@narumitw/pi-caffeinate@0.49.7` uses the host platform's sleep inhibitor during each Pi agent run. On macOS, `/caffeinate sleep` keeps the system awake while allowing the display to sleep; `/caffeinate display` also keeps the display awake. It releases the inhibitor when the run or session ends.
42
+
43
+ `@herbertgao/resume-from@0.2.0` keeps Claude Code sessions associated with their original repository when the active transcript later moves into a nested cwd. `pi-lens@4.1.3` expands language routing and bounds retained diagnostic facts across multi-root sessions. `pi-automode@1.15.0` preserves dynamic providers on legacy registries. `pi-web-access@0.27.0` adds configurable fetch deadlines and answer models plus isolated GitHub clone runtimes. Preferred Thinking 1.0.1 preserves an explicit subagent `--thinking` choice. Deprecated `@tifan/pi-titlebar-spinner` is no longer bundled; Rename remains the single owner of Herdr tab naming.
38
44
 
39
45
  `pi-stash` is no longer bundled: `/btw` already preserves the main editor draft while handling side questions outside the main conversation. Prior `@herbertgao/pi-stash` releases remain available but are no longer maintained here.
40
46
 
@@ -9,7 +9,6 @@ The aggregate package bundles the following packages from [tifandotme/pi-extensi
9
9
  - `@tifan/pi-preferred-thinking`
10
10
  - `@tifan/pi-recap`
11
11
  - `@tifan/pi-rename`
12
- - `@tifan/pi-titlebar-spinner`
13
12
 
14
13
  They are distributed under the following MIT license:
15
14
 
@@ -38,3 +37,29 @@ THE SOFTWARE.
38
37
  ## `@luxusai/pi-hindsight`
39
38
 
40
39
  The aggregate also bundles [`@luxusai/pi-hindsight`](https://github.com/luxus/pi-hindsight) version 0.12.0. Its published `package.json` declares the SPDX license identifier `MIT`. The reviewed upstream repository and npm tarball do not currently include a standalone license or copyright notice, so this aggregate does not invent one; it preserves the published package metadata and upstream attribution verbatim.
40
+
41
+ ## `@narumitw/pi-caffeinate`
42
+
43
+ The aggregate bundles [`@narumitw/pi-caffeinate`](https://github.com/narumiruna/pi-extensions/tree/main/packages/pi-caffeinate) version 0.49.7 under its original MIT license:
44
+
45
+ MIT License
46
+
47
+ Copyright (c) 2026 narumiruna
48
+
49
+ Permission is hereby granted, free of charge, to any person obtaining a copy
50
+ of this software and associated documentation files (the "Software"), to deal
51
+ in the Software without restriction, including without limitation the rights
52
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
53
+ copies of the Software, and to permit persons to whom the Software is
54
+ furnished to do so, subject to the following conditions:
55
+
56
+ The above copyright notice and this permission notice shall be included in all
57
+ copies or substantial portions of the Software.
58
+
59
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
60
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
61
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
62
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
63
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
64
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
65
+ SOFTWARE.
@@ -4,6 +4,12 @@ All notable changes to this project are documented in this file.
4
4
 
5
5
  ## [Unreleased]
6
6
 
7
+ ## [1.15.0] - 2026-08-28
8
+
9
+ ## Bug fixes
10
+
11
+ - **OMP 18 classifier compatibility** — Support OMP 18 model registries that lack `complete()` and `getProvider()`. Load the legacy completion API only for these registries. Keep current Pi on its runtime registry path so extension-registered providers remain available. Thanks, @NarryG! (#29)
12
+
7
13
  ## [1.14.0] - 2026-08-27
8
14
 
9
15
  ## Bug fixes
@@ -45,7 +51,8 @@ All notable changes to this project are documented in this file.
45
51
  - **Project config trust gate** — Ignore `.pi/automode.local.json` and `.pi/automode.json` until Pi trusts the project. Apply the trust gate during startup and config reloads. (#16)
46
52
  - **In-memory observability logs** — Write logs to an extension-owned directory (`~/.pi/agent/extensions/pi-automode/logs/`) instead of the launching project directory. Thanks, @HerbertGao! (#13)
47
53
 
48
- [Unreleased]: https://github.com/czottmann/pi-automode/compare/v1.14.0...HEAD
54
+ [Unreleased]: https://github.com/czottmann/pi-automode/compare/v1.15.0...HEAD
55
+ [1.15.0]: https://github.com/czottmann/pi-automode/compare/v1.14.0...v1.15.0
49
56
  [1.14.0]: https://github.com/czottmann/pi-automode/compare/v1.13.0...v1.14.0
50
57
  [1.13.0]: https://github.com/czottmann/pi-automode/compare/v1.12.0...v1.13.0
51
58
  [1.12.0]: https://github.com/czottmann/pi-automode/compare/v1.11.0...v1.12.0
@@ -8,6 +8,10 @@ It is not a sandbox. Extensions run in the Pi process. A malicious extension can
8
8
 
9
9
  Pi-automode does not guard user `!` or `!!` shell commands. It guards only agent tool calls. Use it to reduce unsafe autonomous tool use. Do not use it as an OS security boundary.
10
10
 
11
+ ## Compatibility
12
+
13
+ Pi-automode supports Pi and Oh My Pi (OMP) 18. It automatically uses OMP's legacy completion API. The integration needs no OMP-specific configuration.
14
+
11
15
  ## Install
12
16
 
13
17
  From npm:
@@ -84,10 +84,9 @@ async function resolveClassifier(
84
84
  };
85
85
  }
86
86
 
87
- const rawComplete: ClassifierCompletionFn = (callModel, context, options) =>
88
- ctx.modelRegistry.complete(callModel, context, options);
89
- const simpleComplete: ClassifierCompletionFn = (callModel, context, options) =>
90
- completeSimpleWithRegistry(ctx, callModel, context, options);
87
+ const { rawComplete, simpleComplete } = createRegistryCompletionFns(
88
+ ctx.modelRegistry,
89
+ );
91
90
  const completionPlan = createClassifierCompletionPlan(
92
91
  model,
93
92
  config.classifierReasoningLevel,
@@ -125,6 +124,70 @@ export type ClassifierCompletionFn = (
125
124
  },
126
125
  ) => Promise<AssistantMessage>;
127
126
 
127
+ type RegistryCompletionApi = {
128
+ complete?: ClassifierCompletionFn;
129
+ getProvider?: (provider: string) => {
130
+ streamSimple: (
131
+ model: Model<any>,
132
+ context: { systemPrompt: string; messages: UserMessage[] },
133
+ options: Parameters<ClassifierCompletionFn>[2],
134
+ ) => { result: () => Promise<AssistantMessage> };
135
+ } | undefined;
136
+ };
137
+ type ClassifierCompletionFallbacks = {
138
+ rawComplete: ClassifierCompletionFn;
139
+ simpleComplete: ClassifierCompletionFn;
140
+ };
141
+
142
+ type ClassifierCompletionFallbackLoader =
143
+ () => Promise<ClassifierCompletionFallbacks>;
144
+
145
+ // Static import would initialize deprecated compat registries on current Pi;
146
+ // OMP rewrites this literal dynamic import to its native pi-ai module.
147
+ async function loadCompatCompletionFns(): Promise<ClassifierCompletionFallbacks> {
148
+ const { complete, completeSimple } = await import(
149
+ "@earendil-works/pi-ai/compat"
150
+ );
151
+ return {
152
+ rawComplete: complete as ClassifierCompletionFn,
153
+ simpleComplete: completeSimple as ClassifierCompletionFn,
154
+ };
155
+ }
156
+
157
+ /**
158
+ * Prefer the current runtime registry so extension-registered providers remain
159
+ * visible. Older Pi-family runtimes (including OMP 18) expose neither
160
+ * `complete` nor `getProvider`; lazily load the compat API they already use.
161
+ */
162
+ export function createRegistryCompletionFns(
163
+ registry: RegistryCompletionApi,
164
+ fallbackLoader: ClassifierCompletionFallbackLoader =
165
+ loadCompatCompletionFns,
166
+ ): ClassifierCompletionFallbacks {
167
+ let fallbackPromise: Promise<ClassifierCompletionFallbacks> | undefined;
168
+ const rawComplete: ClassifierCompletionFn =
169
+ typeof registry.complete === "function"
170
+ ? (model, context, options) =>
171
+ registry.complete!.call(registry, model, context, options)
172
+ : async (model, context, options) =>
173
+ (await (fallbackPromise ??= fallbackLoader())).rawComplete(
174
+ model,
175
+ context,
176
+ options,
177
+ );
178
+ const simpleComplete: ClassifierCompletionFn =
179
+ typeof registry.getProvider === "function"
180
+ ? (model, context, options) =>
181
+ completeSimpleWithRegistry(registry, model, context, options)
182
+ : async (model, context, options) =>
183
+ (await (fallbackPromise ??= fallbackLoader())).simpleComplete(
184
+ model,
185
+ context,
186
+ options,
187
+ );
188
+ return { rawComplete, simpleComplete };
189
+ }
190
+
128
191
  export type RetryOptions = {
129
192
  maxAttempts?: number;
130
193
  maxTokens?: number;
@@ -206,17 +269,16 @@ async function completeClassifierAttempt(
206
269
 
207
270
  /**
208
271
  * Run normalized Pi AI completion through the provider in Pi's runtime registry.
209
- * This temporary bridge is only valid until Pi exposes
210
- * `ctx.modelRegistry.completeSimple(...)` natively. Replace this function with
211
- * that API when the project's minimum supported Pi version includes it.
272
+ * Callers use this only when the registry exposes `getProvider`; legacy
273
+ * registries take the compat completion path instead.
212
274
  */
213
275
  async function completeSimpleWithRegistry(
214
- ctx: ExtensionContext,
276
+ registry: RegistryCompletionApi,
215
277
  model: Model<any>,
216
278
  context: { systemPrompt: string; messages: UserMessage[] },
217
279
  options: Parameters<ClassifierCompletionFn>[2],
218
280
  ): Promise<AssistantMessage> {
219
- const provider = ctx.modelRegistry.getProvider(model.provider);
281
+ const provider = registry.getProvider?.(model.provider);
220
282
  if (!provider) throw new Error(`Unknown provider: ${model.provider}`);
221
283
  return provider.streamSimple(model, context, options).result();
222
284
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@czottmann/pi-automode",
3
- "version": "1.14.0",
3
+ "version": "1.15.0",
4
4
  "description": "Claude Code-style auto mode guardrail for pi.",
5
5
  "repository": {
6
6
  "url": "https://github.com/czottmann/pi-automode"
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Herbert Gao
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,44 @@
1
+ # @herbertgao/pi-bark
2
+
3
+ Bark notifications for user-facing Pi sessions. It sends a notification when Pi fully settles and when [`@juicesharp/rpiv-ask-user-question`](https://github.com/juicesharp/rpiv-mono) opens a questionnaire. Requests follow Bark's official [POST form API](https://github.com/Finb/Bark/blob/master/docs/en-us/tutorial.md#request-methods).
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ pi install npm:@herbertgao/pi-bark
9
+ ```
10
+
11
+ The extension is also included in `@herbertgao/pi-extensions`.
12
+
13
+ ## Configure
14
+
15
+ Create `$PI_CODING_AGENT_DIR/bark.json` (normally `~/.pi/agent/bark.json`):
16
+
17
+ ```json
18
+ {
19
+ "endpoint": "https://api.day.app/your-device-key",
20
+ "machine": "MacBook Pro M1 Max",
21
+ "locale": "zh-CN",
22
+ "events": {
23
+ "agentSettled": true,
24
+ "askUserQuestion": true
25
+ },
26
+ "params": {
27
+ "group": "pi",
28
+ "icon": "https://raw.githubusercontent.com/HerbertGao/pi-extensions/master/packages/pi-bark/assets/pi-icon.png"
29
+ },
30
+ "timeoutMs": 4000
31
+ }
32
+ ```
33
+
34
+ `endpoint` is required. `locale` accepts `auto` (default), `zh-CN`, `zh-TW`, or `en`; unsupported languages fall back to English. `params` accepts additional Bark POST parameters such as `group`, `sound`, `icon`, and `level`; dynamic `title` and `body` values always take precedence. Set `"enabled": false` to disable all notifications without removing the package.
35
+
36
+ The notification body uses `šŸ’»` for the configured machine name and `šŸ“` for Pi's full working directory. Questionnaire text is intentionally not sent because it may contain sensitive context. Only sessions with a user-facing UI notify, so nested `pi-subagents` sessions do not create duplicate pushes.
37
+
38
+ The bundled [`assets/pi-icon.png`](assets/pi-icon.png) is a 512Ɨ512 rasterization of Pi's official [square badge](https://pi.dev/favicon.svg) from the [Pi Press Kit](https://pi.dev/press-kit), suitable for Bark's iOS 15+ `icon` parameter.
39
+
40
+ Keep `bark.json` private because the endpoint normally contains the Bark device key. Restart Pi or run `/reload` after changing it.
41
+
42
+ ## License
43
+
44
+ [MIT](LICENSE)
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "@herbertgao/pi-bark",
3
+ "version": "0.1.0",
4
+ "description": "Send Bark notifications when Pi finishes or needs user input.",
5
+ "keywords": [
6
+ "bark",
7
+ "notifications",
8
+ "pi-extension",
9
+ "pi-package"
10
+ ],
11
+ "homepage": "https://github.com/HerbertGao/pi-extensions/tree/master/packages/pi-bark#readme",
12
+ "bugs": {
13
+ "url": "https://github.com/HerbertGao/pi-extensions/issues"
14
+ },
15
+ "license": "MIT",
16
+ "author": "Herbert Gao",
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/HerbertGao/pi-extensions.git",
20
+ "directory": "packages/pi-bark"
21
+ },
22
+ "files": [
23
+ "assets",
24
+ "src",
25
+ "README.md",
26
+ "LICENSE"
27
+ ],
28
+ "type": "module",
29
+ "publishConfig": {
30
+ "access": "public",
31
+ "provenance": true
32
+ },
33
+ "scripts": {
34
+ "test": "node --test tests/**/*.test.ts",
35
+ "typecheck": "tsc --noEmit"
36
+ },
37
+ "devDependencies": {
38
+ "@types/node": "^24",
39
+ "typescript": "^5.9.3"
40
+ },
41
+ "peerDependencies": {
42
+ "@earendil-works/pi-coding-agent": "^0.84.0"
43
+ },
44
+ "engines": {
45
+ "node": ">=22.19.0"
46
+ },
47
+ "pi": {
48
+ "extensions": [
49
+ "./src/index.ts"
50
+ ]
51
+ },
52
+ "x-origin": "original"
53
+ }
@@ -0,0 +1,178 @@
1
+ import type { ExtensionAPI } from "@earendil-works/pi-coding-agent"
2
+ import { readFileSync } from "node:fs"
3
+ import { homedir, hostname } from "node:os"
4
+ import { join } from "node:path"
5
+
6
+ const ASK_USER_PROMPT_EVENT = "rpiv:ask-user:prompt"
7
+ const DEFAULT_TIMEOUT_MS = 4_000
8
+
9
+ export type BarkLocale = "en" | "zh-CN" | "zh-TW"
10
+ type NotificationEvent = "agentSettled" | "askUserQuestion"
11
+
12
+ const COPY: Record<BarkLocale, Record<NotificationEvent, string>> = {
13
+ en: {
14
+ agentSettled: "āœ… Pi finished",
15
+ askUserQuestion: "🟔 Pi needs your input",
16
+ },
17
+ "zh-CN": {
18
+ agentSettled: "āœ… Pi č·‘å®Œäŗ†",
19
+ askUserQuestion: "🟔 Pi ē­‰ä½ å›žē­”",
20
+ },
21
+ "zh-TW": {
22
+ agentSettled: "āœ… Pi 已完成",
23
+ askUserQuestion: "🟔 Pi ē­‰ä½ å›žč¦†",
24
+ },
25
+ }
26
+
27
+ export interface BarkConfig {
28
+ endpoint: string
29
+ machine: string
30
+ locale: BarkLocale
31
+ events: {
32
+ agentSettled: boolean
33
+ askUserQuestion: boolean
34
+ }
35
+ params: Record<string, string | number | boolean>
36
+ timeoutMs: number
37
+ }
38
+
39
+ export function getConfigPath(): string {
40
+ return join(
41
+ process.env.PI_CODING_AGENT_DIR ?? join(homedir(), ".pi", "agent"),
42
+ "bark.json",
43
+ )
44
+ }
45
+
46
+ export function resolveLocale(input: unknown): BarkLocale {
47
+ const requested =
48
+ typeof input === "string" && input.toLowerCase() !== "auto"
49
+ ? input
50
+ : Intl.DateTimeFormat().resolvedOptions().locale
51
+ const locale = requested.toLowerCase()
52
+ if (locale.includes("hant") || /^zh-(tw|hk|mo)/.test(locale)) return "zh-TW"
53
+ if (locale.startsWith("zh")) return "zh-CN"
54
+ return "en"
55
+ }
56
+
57
+ export function notificationTitle(
58
+ locale: BarkLocale,
59
+ event: NotificationEvent,
60
+ ): string {
61
+ return COPY[locale][event]
62
+ }
63
+
64
+ export function normalizeConfig(input: unknown): BarkConfig | undefined {
65
+ if (!input || typeof input !== "object") return undefined
66
+ const source = input as Record<string, unknown>
67
+ if (source.enabled === false || typeof source.endpoint !== "string")
68
+ return undefined
69
+
70
+ try {
71
+ const protocol = new URL(source.endpoint).protocol
72
+ if (protocol !== "http:" && protocol !== "https:") return undefined
73
+ } catch {
74
+ return undefined
75
+ }
76
+
77
+ const eventSource =
78
+ source.events && typeof source.events === "object"
79
+ ? (source.events as Record<string, unknown>)
80
+ : {}
81
+ const params =
82
+ source.params && typeof source.params === "object"
83
+ ? Object.fromEntries(
84
+ Object.entries(source.params).filter((entry) =>
85
+ ["string", "number", "boolean"].includes(typeof entry[1]),
86
+ ),
87
+ )
88
+ : {}
89
+ const timeoutMs =
90
+ typeof source.timeoutMs === "number" &&
91
+ Number.isFinite(source.timeoutMs) &&
92
+ source.timeoutMs > 0
93
+ ? source.timeoutMs
94
+ : DEFAULT_TIMEOUT_MS
95
+
96
+ return {
97
+ endpoint: source.endpoint,
98
+ machine:
99
+ typeof source.machine === "string" && source.machine.trim()
100
+ ? source.machine.trim()
101
+ : hostname(),
102
+ locale: resolveLocale(source.locale),
103
+ events: {
104
+ agentSettled: eventSource.agentSettled !== false,
105
+ askUserQuestion: eventSource.askUserQuestion !== false,
106
+ },
107
+ params,
108
+ timeoutMs,
109
+ }
110
+ }
111
+
112
+ export function loadConfig(path = getConfigPath()): BarkConfig | undefined {
113
+ try {
114
+ return normalizeConfig(JSON.parse(readFileSync(path, "utf8")))
115
+ } catch {
116
+ return undefined
117
+ }
118
+ }
119
+
120
+ export function formatBody(config: BarkConfig, cwd: string): string {
121
+ return `šŸ’» ${config.machine}\nšŸ“ ${cwd}`
122
+ }
123
+
124
+ export async function sendBark(
125
+ config: BarkConfig,
126
+ title: string,
127
+ body: string,
128
+ fetcher: typeof fetch = fetch,
129
+ ): Promise<void> {
130
+ const form = new URLSearchParams()
131
+ for (const [key, value] of Object.entries(config.params))
132
+ form.set(key, String(value))
133
+ form.set("title", title)
134
+ form.set("body", body)
135
+
136
+ const response = await fetcher(config.endpoint, {
137
+ method: "POST",
138
+ body: form,
139
+ signal: AbortSignal.timeout(config.timeoutMs),
140
+ })
141
+ if (!response.ok) throw new Error(`Bark returned HTTP ${response.status}`)
142
+ }
143
+
144
+ export default function piBark(pi: ExtensionAPI): void {
145
+ let config: BarkConfig | undefined
146
+ let cwd = process.cwd()
147
+ let userFacingSession = false
148
+
149
+ const notify = async (title: string): Promise<void> => {
150
+ if (!config || !userFacingSession) return
151
+ try {
152
+ await sendBark(config, title, formatBody(config, cwd))
153
+ } catch {
154
+ // Notifications are best-effort and must never interrupt Pi.
155
+ }
156
+ }
157
+
158
+ const unsubscribeAskUser = pi.events.on(ASK_USER_PROMPT_EVENT, () => {
159
+ if (config?.events.askUserQuestion)
160
+ void notify(notificationTitle(config.locale, "askUserQuestion"))
161
+ })
162
+
163
+ pi.on("session_start", (_event, ctx) => {
164
+ config = loadConfig()
165
+ cwd = ctx.cwd
166
+ userFacingSession = ctx.hasUI
167
+ })
168
+
169
+ pi.on("agent_settled", (_event, ctx) => {
170
+ cwd = ctx.cwd
171
+ if (config?.events.agentSettled)
172
+ void notify(notificationTitle(config.locale, "agentSettled"))
173
+ })
174
+
175
+ pi.on("session_shutdown", () => {
176
+ unsubscribeAskUser()
177
+ })
178
+ }
@@ -21,6 +21,8 @@ export type Config = {
21
21
  writeDiffCollapsedLines: number;
22
22
  diffWordWrap: boolean;
23
23
  expandedPreviewMaxLines: number;
24
+ expandedInputMaxLines: number;
25
+ expandedOutputMaxLines: number;
24
26
  useSummaryTitlesAsThinkingTitle: boolean;
25
27
  previewLines: number;
26
28
  animationIntervalMs: number;
@@ -46,6 +48,8 @@ export const DIFF_COLLAPSED_LINES_VALUES = ["12", "24", "36", "48", "80", "120"]
46
48
  export const WRITE_DIFF_COLLAPSED_LINES_VALUES = ["0", "4", "8", "12", "24", "36"];
47
49
  /** Presets for expanded body height — keep low options first so cycling stays TUI-friendly. */
48
50
  export const EXPANDED_PREVIEW_MAX_LINES_VALUES = ["40", "60", "80", "120", "200", "500", "2000"];
51
+ export const EXPANDED_INPUT_MAX_LINES_VALUES = ["5", "10", "20", "40", "80"];
52
+ export const EXPANDED_OUTPUT_MAX_LINES_VALUES = ["10", "20", "40", "80", "120"];
49
53
  export const THINKING_PREVIEW_LINES_VALUES = ["0", "1", "3", "5", "10"];
50
54
  export const THINKING_ANIMATION_INTERVAL_VALUES = ["40", "60", "90", "120", "180"];
51
55
  /** fullscreen ę»šč½®ę­„čæ›č”Œę•°é¢„č®¾ć€‚ */
@@ -73,6 +77,8 @@ export const DEFAULT_CONFIG: Config = {
73
77
  writeDiffCollapsedLines: DEFAULT_TOOL_DISPLAY_CONFIG.writeDiffCollapsedLines,
74
78
  diffWordWrap: DEFAULT_TOOL_DISPLAY_CONFIG.diffWordWrap,
75
79
  expandedPreviewMaxLines: DEFAULT_TOOL_DISPLAY_CONFIG.expandedPreviewMaxLines,
80
+ expandedInputMaxLines: 5,
81
+ expandedOutputMaxLines: 10,
76
82
  useSummaryTitlesAsThinkingTitle: true,
77
83
  previewLines: 3,
78
84
  animationIntervalMs: 90,
@@ -159,6 +165,18 @@ export function normalizeConfig(input: unknown): Config {
159
165
  10,
160
166
  50_000,
161
167
  ),
168
+ expandedInputMaxLines: pickPositiveInt(
169
+ source.expandedInputMaxLines,
170
+ DEFAULT_CONFIG.expandedInputMaxLines,
171
+ 1,
172
+ 5_000,
173
+ ),
174
+ expandedOutputMaxLines: pickPositiveInt(
175
+ source.expandedOutputMaxLines,
176
+ DEFAULT_CONFIG.expandedOutputMaxLines,
177
+ 1,
178
+ 5_000,
179
+ ),
162
180
  useSummaryTitlesAsThinkingTitle: source.useSummaryTitlesAsThinkingTitle !== false,
163
181
  previewLines: pickPositiveInt(
164
182
  source.previewLines,
@@ -217,6 +235,8 @@ export function formatConfigStatus(source: Config = config): string {
217
235
  `writeCollapsed=${source.writeDiffCollapsedLines}`,
218
236
  `diffWordWrap=${source.diffWordWrap ? "on" : "off"}`,
219
237
  `expandedMax=${source.expandedPreviewMaxLines}`,
238
+ `expandedInput=${source.expandedInputMaxLines}`,
239
+ `expandedOutput=${source.expandedOutputMaxLines}`,
220
240
  `thinkingTitle=${source.useSummaryTitlesAsThinkingTitle ? "summary" : "default"}`,
221
241
  `thinkingPreview=${source.previewLines}`,
222
242
  `thinkingAnimation=${source.animationIntervalMs}ms`,