@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
@@ -31,12 +31,45 @@ import { getBrowserCookiesForHosts, getLastBrowserCookieDiagnostic } from "./chr
31
31
  import { sanitizeInlineDataUris } from "./data-uri-sanitize.ts";
32
32
 
33
33
  const DEFAULT_TIMEOUT_MS = 30000;
34
+ const MAX_CONFIGURED_TIMEOUT_MS = 2_147_483_647;
34
35
  const CONCURRENT_LIMIT = 3;
36
+ const WEB_SEARCH_CONFIG_PATH = getWebSearchConfigPath();
37
+
38
+ function loadFetchTimeoutMs(): number {
39
+ if (!existsSync(WEB_SEARCH_CONFIG_PATH)) return DEFAULT_TIMEOUT_MS;
40
+
41
+ let raw: unknown;
42
+ try {
43
+ raw = JSON.parse(readFileSync(WEB_SEARCH_CONFIG_PATH, "utf-8"));
44
+ } catch (err) {
45
+ const message = err instanceof Error ? err.message : String(err);
46
+ throw new Error(`Failed to parse ${WEB_SEARCH_CONFIG_PATH}: ${message}`);
47
+ }
48
+ if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
49
+ throw new Error(`Invalid config in ${WEB_SEARCH_CONFIG_PATH}: expected a JSON object`);
50
+ }
51
+
52
+ const fetchConfig = (raw as Record<string, unknown>).fetch;
53
+ if (fetchConfig === undefined) return DEFAULT_TIMEOUT_MS;
54
+ if (!fetchConfig || typeof fetchConfig !== "object" || Array.isArray(fetchConfig)) {
55
+ throw new Error(`fetch in ${WEB_SEARCH_CONFIG_PATH} must be an object`);
56
+ }
57
+
58
+ const value = (fetchConfig as Record<string, unknown>).timeout;
59
+ if (value === undefined) return DEFAULT_TIMEOUT_MS;
60
+ if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
61
+ throw new Error(`Invalid fetch.timeout in ${WEB_SEARCH_CONFIG_PATH}: expected a positive finite number of seconds, got ${JSON.stringify(value)}`);
62
+ }
63
+ const timeoutMs = Math.ceil(value * 1000);
64
+ if (!Number.isSafeInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > MAX_CONFIGURED_TIMEOUT_MS) {
65
+ throw new Error(`Invalid fetch.timeout in ${WEB_SEARCH_CONFIG_PATH}: converted timeout must be a finite safe integer from 1 through ${MAX_CONFIGURED_TIMEOUT_MS} milliseconds`);
66
+ }
67
+ return Math.max(1, timeoutMs);
68
+ }
35
69
 
36
70
  const NON_RECOVERABLE_ERRORS = ["Unsupported content type", "Response too large", "PDF extraction is disabled", "Image fetching is disabled"];
37
71
  const MIN_USEFUL_CONTENT = 500;
38
72
  const SUPPORTED_IMAGE_TYPES = new Set(["image/png", "image/jpeg", "image/webp", "image/gif"]);
39
- const WEB_SEARCH_CONFIG_PATH = getWebSearchConfigPath();
40
73
  const FETCH_PROVIDERS = ["http", "firecrawl", "jina", "tinyfish", "search1api", "querit", "kagi", "ollama", "parallel", "parallel-mcp", "brightdata", "gemini"] as const;
41
74
  type FetchProvider = typeof FETCH_PROVIDERS[number];
42
75
  type FetchRouting = { providers: FetchProvider[]; allowRemoteHostedProviders: boolean };
@@ -51,6 +84,10 @@ function isDefuddleConsoleError(args: Parameters<typeof console.error>): boolean
51
84
  async function extractWithDefuddle(text: string, url: string): Promise<{ title: string; content: string } | null> {
52
85
  const { Defuddle } = await import("defuddle/node");
53
86
  const { document } = parseHTML(text);
87
+ Object.defineProperty(document, "location", {
88
+ value: new URL(url),
89
+ configurable: true,
90
+ });
54
91
  let processingError: unknown;
55
92
  const originalConsoleError = console.error;
56
93
  console.error = (...args) => {
@@ -298,11 +335,16 @@ export interface ExtractOptions {
298
335
  lookup?: Lookup;
299
336
  }
300
337
 
338
+ /** Resolve the direct HTTP/Jina fetch budget, with a per-call override taking precedence. */
339
+ export function resolveFetchTimeoutMs(options?: Pick<ExtractOptions, "timeoutMs">): number {
340
+ return options?.timeoutMs ?? loadFetchTimeoutMs();
341
+ }
342
+
301
343
  const JINA_READER_BASE = "https://r.jina.ai/";
302
- const JINA_TIMEOUT_MS = 30000;
303
344
 
304
345
  async function extractWithJinaReader(
305
346
  url: string,
347
+ timeoutMs: number,
306
348
  signal?: AbortSignal,
307
349
  lookup?: Lookup,
308
350
  ): Promise<ExtractedContent | null> {
@@ -325,7 +367,7 @@ async function extractWithJinaReader(
325
367
  "X-No-Cache": "true",
326
368
  },
327
369
  signal: AbortSignal.any([
328
- AbortSignal.timeout(JINA_TIMEOUT_MS),
370
+ AbortSignal.timeout(timeoutMs),
329
371
  ...(signal ? [signal] : []),
330
372
  ]),
331
373
  });
@@ -480,18 +522,14 @@ export async function extractContent(
480
522
  }
481
523
  }
482
524
 
483
- if (options?.authFetchProfile) {
525
+ if (options?.authFetchProfile || options?.mode === "raw") {
484
526
  try {
485
- return await extractViaHttp(url, signal, options);
527
+ return await extractViaHttp(url, resolveFetchTimeoutMs(options), signal, options);
486
528
  } catch (err) {
487
529
  return { url, title: "", content: "", error: errorMessage(err) };
488
530
  }
489
531
  }
490
532
 
491
- if (options?.mode === "raw") {
492
- return extractViaHttp(url, signal, options);
493
- }
494
-
495
533
  if (options?.frames || options?.timestamp) {
496
534
  const disabled = imageGateError();
497
535
  if (disabled) return { url, title: "", content: "", error: disabled };
@@ -703,6 +741,13 @@ export async function extractContent(
703
741
 
704
742
  if (signal?.aborted) return abortedResult(url);
705
743
 
744
+ let fetchTimeoutMs: number;
745
+ try {
746
+ fetchTimeoutMs = resolveFetchTimeoutMs(options);
747
+ } catch (err) {
748
+ return { url, title: "", content: "", error: errorMessage(err) };
749
+ }
750
+
706
751
  let fetchRouting: FetchRouting;
707
752
  try {
708
753
  fetchRouting = loadFetchRouting();
@@ -731,7 +776,7 @@ export async function extractContent(
731
776
  ? { ...httpResult, error: message }
732
777
  : { url, title: "", content: "", error: message };
733
778
  const runHttpProvider = async (): Promise<ExtractedContent | null> => {
734
- const { declaredLinks: discoveredLinks = [], ...result } = await extractViaHttp(url, signal, options);
779
+ const { declaredLinks: discoveredLinks = [], ...result } = await extractViaHttp(url, fetchTimeoutMs, signal, options);
735
780
  httpResult = result;
736
781
  declaredLinks = discoveredLinks;
737
782
  if (signal?.aborted) return abortedResult(url);
@@ -786,7 +831,7 @@ export async function extractContent(
786
831
  }
787
832
 
788
833
  if (provider === "jina") {
789
- const jinaResult = await extractWithJinaReader(url, signal, options?.lookup);
834
+ const jinaResult = await extractWithJinaReader(url, fetchTimeoutMs, signal, options?.lookup);
790
835
  if (jinaResult) return withDeclaredLinks(jinaResult);
791
836
  continue;
792
837
  }
@@ -1066,10 +1111,10 @@ function responseSizeLimitError(maxBytes: number): Error {
1066
1111
 
1067
1112
  async function extractViaHttp(
1068
1113
  url: string,
1114
+ timeoutMs: number,
1069
1115
  signal?: AbortSignal,
1070
1116
  options?: ExtractOptions,
1071
1117
  ): Promise<HttpExtractedContent> {
1072
- const timeoutMs = options?.timeoutMs ?? DEFAULT_TIMEOUT_MS;
1073
1118
  const activityId = activityMonitor.logStart({ type: "fetch", url });
1074
1119
 
1075
1120
  const controller = new AbortController();
@@ -1,4 +1,4 @@
1
- import { closeSync, existsSync, lstatSync, mkdirSync, openSync, readFileSync, readSync, readdirSync, realpathSync, rmSync, statSync, unlinkSync } from "node:fs";
1
+ import { chmodSync, closeSync, existsSync, lstatSync, mkdirSync, mkdtempSync, openSync, readFileSync, readSync, readdirSync, realpathSync, rmSync, statSync, unlinkSync } from "node:fs";
2
2
  import { execFile, spawn, type ChildProcess } from "node:child_process";
3
3
  import { createHash } from "node:crypto";
4
4
  import { basename, dirname, extname, join, resolve as resolvePath, sep as pathSep } from "node:path";
@@ -59,6 +59,7 @@ interface GitHubCloneConfig {
59
59
  const cloneCache = new Map<string, CachedClone>();
60
60
 
61
61
  let cachedConfig: GitHubCloneConfig | null = null;
62
+ let cloneRuntime: { parentPath: string; rootPath: string } | null = null;
62
63
 
63
64
  function normalizeEnabled(value: unknown, fallback: boolean): boolean {
64
65
  return typeof value === "boolean" ? value : fallback;
@@ -189,10 +190,48 @@ function cacheKey(owner: string, repo: string, ref?: string): string {
189
190
  return ref ? `${owner}/${repo}@${ref}` : `${owner}/${repo}`;
190
191
  }
191
192
 
193
+ function removeCloneRuntime(parentPath: string, runtimePath: string): void {
194
+ const normalizedParentPath = resolvePath(parentPath);
195
+ const normalizedRuntimePath = resolvePath(runtimePath);
196
+ if (dirname(normalizedRuntimePath) !== normalizedParentPath || !basename(normalizedRuntimePath).startsWith("runtime-")) return;
197
+
198
+ try {
199
+ const entry = lstatSync(normalizedRuntimePath);
200
+ if (entry.isSymbolicLink()) unlinkSync(normalizedRuntimePath);
201
+ else rmSync(normalizedRuntimePath, { recursive: true, force: true });
202
+ } catch {
203
+ // The runtime directory may already have been removed externally.
204
+ }
205
+ }
206
+
207
+ function getCloneRuntimeRoot(config: GitHubCloneConfig): string | null {
208
+ if (cloneRuntime) return cloneRuntime.rootPath;
209
+
210
+ let parentPath: string | null = null;
211
+ let runtimePath: string | null = null;
212
+ try {
213
+ const configuredPath = resolvePath(config.clonePath);
214
+ mkdirSync(configuredPath, { recursive: true });
215
+ parentPath = realpathSync(configuredPath);
216
+ runtimePath = mkdtempSync(join(parentPath, "runtime-"));
217
+ chmodSync(runtimePath, 0o700);
218
+ const rootPath = realpathSync(runtimePath);
219
+ if (dirname(rootPath) !== parentPath) {
220
+ removeCloneRuntime(parentPath, runtimePath);
221
+ return null;
222
+ }
223
+ cloneRuntime = { parentPath, rootPath };
224
+ return rootPath;
225
+ } catch {
226
+ if (parentPath && runtimePath) removeCloneRuntime(parentPath, runtimePath);
227
+ return null;
228
+ }
229
+ }
230
+
192
231
  function cloneDestination(config: GitHubCloneConfig, owner: string, repo: string, ref?: string): CloneDestination | null {
193
232
  try {
194
- mkdirSync(resolvePath(config.clonePath), { recursive: true });
195
- const rootPath = realpathSync(resolvePath(config.clonePath));
233
+ const rootPath = getCloneRuntimeRoot(config);
234
+ if (!rootPath) return null;
196
235
  const digest = createHash("sha256").update(JSON.stringify([owner, repo, ref ?? null])).digest("hex");
197
236
  const localPath = resolvePath(rootPath, digest);
198
237
  if (dirname(localPath) !== rootPath) return null;
@@ -742,5 +781,10 @@ export function clearCloneCache(): void {
742
781
  removeCloneDestination(entry.destination);
743
782
  }
744
783
  cloneCache.clear();
784
+
785
+ if (cloneRuntime) {
786
+ removeCloneRuntime(cloneRuntime.parentPath, cloneRuntime.rootPath);
787
+ }
788
+ cloneRuntime = null;
745
789
  cachedConfig = null;
746
790
  }
@@ -2443,7 +2443,7 @@ export default function (pi: ExtensionAPI) {
2443
2443
  description: "Fetch mode: readable (default extraction), raw (exact textual HTTP body), or answer (answer prompt using only fetched content).",
2444
2444
  })),
2445
2445
  answerModel: Type.Optional(Type.String({
2446
- description: "Optional provider/model-id override for mode answer. Defaults to the current Pi model.",
2446
+ description: "Optional provider/model-id override for mode answer. Defaults to fetch.answerProvider + fetch.answerModel when configured, otherwise the current Pi model.",
2447
2447
  })),
2448
2448
  timestamp: Type.Optional(Type.String({
2449
2449
  description: "Extract video frame(s) at a timestamp or time range. Single: '1:23:45', '23:45', or '85' (seconds). Range: '23:41-25:00' extracts evenly-spaced frames across that span (default 6). Use frames with ranges to control density; single+frames uses a fixed 5s interval. YouTube requires yt-dlp + ffmpeg; local videos require ffmpeg. Use a range when you know the approximate area but not the exact moment — you'll get a contact sheet to visually identify the right frame.",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-web-access",
3
- "version": "0.26.0",
3
+ "version": "0.27.0",
4
4
  "description": "Web search, URL fetching, GitHub repo cloning, PDF extraction, YouTube video understanding, and local video analysis for Pi coding agent. Supports OpenAI, Brave, Parallel, TinyFish, Search1API, Searchinfinity, Querit, Tavily, Firecrawl, Jina, SERPdive, Kagi, Ollama, AnySearch, Bright Data SERP, SerpBase, SearXNG, Exa, Perplexity, Gemini, and Kimi.",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -1,6 +1,8 @@
1
1
  import { complete, type Api, type Message, type Model } from "@earendil-works/pi-ai/compat";
2
2
  import type { ExtensionContext } from "@earendil-works/pi-coding-agent";
3
- import { loadEnabledModelPatterns, modelMatchesEnabledPatterns } from "./summary-model-scope.ts";
3
+ import { existsSync, readFileSync } from "node:fs";
4
+ import { findModelWithProviderRouting, loadEnabledModelPatterns, modelMatchesEnabledPatterns } from "./summary-model-scope.ts";
5
+ import { getWebSearchConfigPath } from "./utils.ts";
4
6
 
5
7
  const OUTPUT_TOKENS = 2_000;
6
8
  const INPUT_CONTEXT_FRACTION = 0.6;
@@ -16,7 +18,48 @@ export interface PageAnswer {
16
18
  truncated: boolean;
17
19
  }
18
20
 
19
- function parseModelSelector(value: string): { provider: string; id: string } {
21
+ interface AnswerModelSelector {
22
+ provider: string;
23
+ id: string;
24
+ }
25
+
26
+ function loadConfiguredAnswerModel(): AnswerModelSelector | undefined {
27
+ const configPath = getWebSearchConfigPath();
28
+ if (!existsSync(configPath)) return undefined;
29
+
30
+ let raw: unknown;
31
+ try {
32
+ raw = JSON.parse(readFileSync(configPath, "utf8"));
33
+ } catch (err) {
34
+ const message = err instanceof Error ? err.message : String(err);
35
+ throw new Error(`Failed to parse ${configPath}: ${message}`);
36
+ }
37
+
38
+ const root = raw && typeof raw === "object" && !Array.isArray(raw)
39
+ ? raw as Record<string, unknown>
40
+ : undefined;
41
+ const fetchConfig = root?.fetch;
42
+ if (!fetchConfig || typeof fetchConfig !== "object" || Array.isArray(fetchConfig)) return undefined;
43
+ const values = fetchConfig as Record<string, unknown>;
44
+ const hasProvider = Object.hasOwn(values, "answerProvider");
45
+ const hasModel = Object.hasOwn(values, "answerModel");
46
+ if (!hasProvider && !hasModel) return undefined;
47
+
48
+ const provider = values.answerProvider;
49
+ const model = values.answerModel;
50
+ if (hasProvider && (typeof provider !== "string" || provider.trim().length === 0)) {
51
+ throw new Error(`fetch.answerProvider in ${configPath} must be a non-empty string`);
52
+ }
53
+ if (hasModel && (typeof model !== "string" || model.trim().length === 0)) {
54
+ throw new Error(`fetch.answerModel in ${configPath} must be a non-empty string`);
55
+ }
56
+ if (!hasProvider || !hasModel) {
57
+ throw new Error(`fetch.answerProvider and fetch.answerModel must be configured together in ${configPath}`);
58
+ }
59
+ return { provider: (provider as string).trim(), id: (model as string).trim() };
60
+ }
61
+
62
+ function parseModelSelector(value: string): AnswerModelSelector {
20
63
  const separator = value.indexOf("/");
21
64
  if (separator <= 0 || separator === value.length - 1) {
22
65
  throw new Error(`Invalid answerModel: ${value}. Use provider/model-id.`);
@@ -24,14 +67,20 @@ function parseModelSelector(value: string): { provider: string; id: string } {
24
67
  return { provider: value.slice(0, separator), id: value.slice(separator + 1) };
25
68
  }
26
69
 
27
- function resolveModel(ctx: ExtensionContext, override?: string): Model<Api> {
28
- const model = override
70
+ function resolveModel(ctx: ExtensionContext, override?: string, configured?: AnswerModelSelector): Model<Api> {
71
+ const selector = override ? parseModelSelector(override) : configured;
72
+ const model = selector
29
73
  ? (() => {
30
- const selector = parseModelSelector(override);
31
- return ctx.modelRegistry.find(selector.provider, selector.id);
74
+ return findModelWithProviderRouting(ctx.modelRegistry, selector.provider, selector.id);
32
75
  })()
33
76
  : ctx.model;
34
- if (!model) throw new Error(override ? `Answer model not found: ${override}` : "No current model available for page answering");
77
+ if (!model) {
78
+ if (override) throw new Error(`Answer model not found: ${override}`);
79
+ if (configured) {
80
+ throw new Error(`Answer model not found: ${configured.provider}/${configured.id} (from fetch.answerProvider/fetch.answerModel in ${getWebSearchConfigPath()})`);
81
+ }
82
+ throw new Error("No current model available for page answering");
83
+ }
35
84
  if (!model.input.includes("text")) throw new Error(`Answer model does not support text input: ${model.provider}/${model.id}`);
36
85
  if (!modelMatchesEnabledPatterns(model, loadEnabledModelPatterns(ctx))) {
37
86
  throw new Error(`Answer model is not enabled: ${model.provider}/${model.id}`);
@@ -53,7 +102,11 @@ export async function answerFromPage(
53
102
  ctx: ExtensionContext,
54
103
  signal?: AbortSignal,
55
104
  ): Promise<PageAnswer> {
56
- const model = resolveModel(ctx, input.model);
105
+ // Resolve an explicit per-call model first. In particular, do not read a
106
+ // malformed or partial config when the caller has supplied an override.
107
+ const model = input.model
108
+ ? resolveModel(ctx, input.model)
109
+ : resolveModel(ctx, undefined, loadConfiguredAnswerModel());
57
110
  const auth = await ctx.modelRegistry.getApiKeyAndHeaders(model);
58
111
  if (!auth.ok || !auth.apiKey) throw new Error(`No API key available for answer model ${model.provider}/${model.id}`);
59
112
  const registry = ctx.modelRegistry as typeof ctx.modelRegistry & { complete?: typeof complete };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@herbertgao/pi-extensions",
3
- "version": "2026.8.14",
3
+ "version": "2026.9.0",
4
4
  "description": "Aggregate installer for HerbertGao-maintained Pi extensions.",
5
5
  "keywords": [
6
6
  "extensions",
@@ -37,17 +37,18 @@
37
37
  "dependencies": {
38
38
  "@ast-grep/cli": "^0.45.0",
39
39
  "@ast-grep/napi": "^0.45.0",
40
- "@czottmann/pi-automode": "1.14.0",
40
+ "@czottmann/pi-automode": "1.15.0",
41
41
  "@dietrichgebert/ponytail": "4.9.0",
42
- "@earendil-works/pi-coding-agent": "^0.84.2",
43
- "@earendil-works/pi-tui": "^0.84.2",
42
+ "@earendil-works/pi-coding-agent": "^0.84.4",
43
+ "@earendil-works/pi-tui": "^0.84.4",
44
44
  "@effect/platform-node": "4.0.0-beta.103",
45
45
  "@effect/platform-node-shared": "4.0.0-beta.103",
46
- "@herbertgao/pi-cc-extensions": "0.8.60",
46
+ "@herbertgao/pi-bark": "0.1.0",
47
+ "@herbertgao/pi-cc-extensions": "0.9.0",
47
48
  "@herbertgao/pi-subagents": "0.17.1",
48
49
  "@herbertgao/resume-from": "0.2.0",
49
- "@juicesharp/rpiv-ask-user-question": "2.7.1",
50
- "@juicesharp/rpiv-config": "^2.7.1",
50
+ "@juicesharp/rpiv-ask-user-question": "2.9.0",
51
+ "@juicesharp/rpiv-config": "^2.9.0",
51
52
  "@luxusai/pi-hindsight": "0.12.0",
52
53
  "@modelcontextprotocol/client": "2.0.0",
53
54
  "@modelcontextprotocol/core": "2.0.0",
@@ -55,26 +56,27 @@
55
56
  "@modelcontextprotocol/sdk": "^1.29.0",
56
57
  "@mozilla/readability": "^0.6.0",
57
58
  "@napi-rs/keyring": "^1.3.0",
58
- "@narumitw/pi-btw": "0.55.4",
59
+ "@narumitw/pi-btw": "0.57.0",
60
+ "@narumitw/pi-caffeinate": "0.49.7",
59
61
  "@narumitw/pi-tui-kit": "^0.59.0",
60
62
  "@noble/ed25519": "^3.1.0",
61
63
  "@pi-plugins/fast-mode": "0.1.10",
62
64
  "@shikijs/cli": "^4.0.2",
63
65
  "@sinclair/typebox": "^0.34.49",
64
66
  "@tifan/pi-copy-response": "0.2.6",
65
- "@tifan/pi-handoff": "2.0.1",
67
+ "@tifan/pi-handoff": "2.2.1",
66
68
  "@tifan/pi-inline-skills": "1.0.5",
67
69
  "@tifan/pi-mermaid-open": "0.2.0",
68
70
  "@tifan/pi-preferred-thinking": "1.0.1",
69
- "@tifan/pi-recap": "0.4.5",
70
- "@tifan/pi-rename": "0.5.1",
71
- "@tifan/pi-titlebar-spinner": "0.1.3",
71
+ "@tifan/pi-recap": "0.4.6",
72
+ "@tifan/pi-rename": "0.6.0",
72
73
  "@vectorize-io/hindsight-client": "^0.9.0",
73
74
  "ajv": "^8.17.1",
74
75
  "ajv-formats": "^3.0.1",
75
76
  "chalk": "^6.0.0",
76
77
  "croner": "^10.0.1",
77
78
  "cross-spawn": "^7.0.6",
79
+ "dbus-native": "^0.15.2",
78
80
  "defuddle": "0.19.3",
79
81
  "effect": "4.0.0-beta.103",
80
82
  "gpt-tokenizer": "^3.4.0",
@@ -88,9 +90,9 @@
88
90
  "open": "^10.2.0",
89
91
  "p-limit": "^6.1.0",
90
92
  "pi-footer": "0.5.1",
91
- "pi-lens": "4.1.2",
92
- "pi-mcp-adapter": "2.30.0",
93
- "pi-web-access": "0.26.0",
93
+ "pi-lens": "4.1.3",
94
+ "pi-mcp-adapter": "2.32.1",
95
+ "pi-web-access": "0.27.0",
94
96
  "pidusage": "^4.0.1",
95
97
  "promise.try": "^2.0.1",
96
98
  "qrcode-terminal": "^0.12.0",
@@ -113,12 +115,14 @@
113
115
  "bundledDependencies": [
114
116
  "@czottmann/pi-automode",
115
117
  "@dietrichgebert/ponytail",
118
+ "@herbertgao/pi-bark",
116
119
  "@herbertgao/pi-cc-extensions",
117
120
  "@herbertgao/pi-subagents",
118
121
  "@herbertgao/resume-from",
119
122
  "@juicesharp/rpiv-ask-user-question",
120
123
  "@luxusai/pi-hindsight",
121
124
  "@narumitw/pi-btw",
125
+ "@narumitw/pi-caffeinate",
122
126
  "@pi-plugins/fast-mode",
123
127
  "@tifan/pi-copy-response",
124
128
  "@tifan/pi-handoff",
@@ -127,7 +131,6 @@
127
131
  "@tifan/pi-preferred-thinking",
128
132
  "@tifan/pi-recap",
129
133
  "@tifan/pi-rename",
130
- "@tifan/pi-titlebar-spinner",
131
134
  "pi-footer",
132
135
  "pi-lens",
133
136
  "pi-mcp-adapter",
@@ -151,10 +154,11 @@
151
154
  "./node_modules/@tifan/pi-recap/src/index.ts",
152
155
  "./node_modules/@tifan/pi-rename/src/index.ts",
153
156
  "./node_modules/@herbertgao/pi-subagents/src/index.ts",
154
- "./node_modules/@tifan/pi-titlebar-spinner/src/index.ts",
155
157
  "./node_modules/@juicesharp/rpiv-ask-user-question/index.ts",
158
+ "./node_modules/@herbertgao/pi-bark/src/index.ts",
156
159
  "./node_modules/@luxusai/pi-hindsight/extensions/index.ts",
157
160
  "./node_modules/@narumitw/pi-btw/dist/index.ts",
161
+ "./node_modules/@narumitw/pi-caffeinate/dist/index.ts",
158
162
  "./node_modules/@pi-plugins/fast-mode/dist/index.mjs",
159
163
  "./node_modules/pi-mcp-adapter/index.ts",
160
164
  "./node_modules/pi-lens/dist/index.js",
@@ -1,24 +0,0 @@
1
- # @tifan/pi-titlebar-spinner
2
-
3
- Show a braille spinner in the pi titlebar while the agent runs.
4
-
5
- The spinner starts on `agent_start` and stops when the agent settles or the session shuts down. When it stops, the extension restores the default `π - [session - ]cwd` title.
6
-
7
- [add image: titlebar spinner while agent runs]
8
-
9
- - The titlebar while the spinner is active.
10
- - The restored titlebar after the agent finishes.
11
-
12
- ## Install
13
-
14
- ```bash
15
- pi install npm:@tifan/pi-titlebar-spinner
16
- ```
17
-
18
- ## Release notes
19
-
20
- See [CHANGELOG.md](CHANGELOG.md)
21
-
22
- ## License
23
-
24
- [MIT](LICENSE)
@@ -1,39 +0,0 @@
1
- {
2
- "name": "@tifan/pi-titlebar-spinner",
3
- "version": "0.1.3",
4
- "description": "Show a spinner in the pi titlebar while the agent runs.",
5
- "keywords": [
6
- "pi",
7
- "pi-extension",
8
- "pi-package",
9
- "spinner",
10
- "titlebar"
11
- ],
12
- "homepage": "https://github.com/tifandotme/pi-extensions/tree/master/packages/pi-titlebar-spinner#readme",
13
- "bugs": "https://github.com/tifandotme/pi-extensions/issues",
14
- "license": "MIT",
15
- "author": "Tifan Dwi Avianto <hi@tifan.me>",
16
- "repository": {
17
- "type": "git",
18
- "url": "git+https://github.com/tifandotme/pi-extensions.git",
19
- "directory": "packages/pi-titlebar-spinner"
20
- },
21
- "files": [
22
- "src/**/*.ts",
23
- "README.md",
24
- "LICENSE"
25
- ],
26
- "type": "module",
27
- "publishConfig": {
28
- "access": "public",
29
- "provenance": true
30
- },
31
- "engines": {
32
- "node": ">=20"
33
- },
34
- "pi": {
35
- "extensions": [
36
- "./src/index.ts"
37
- ]
38
- }
39
- }
@@ -1,49 +0,0 @@
1
- import path from "node:path"
2
- import type {
3
- ExtensionAPI,
4
- ExtensionContext,
5
- } from "@earendil-works/pi-coding-agent"
6
-
7
- const FRAMES = ["⡿", "⣟", "⣯", "⣷", "⣾", "⣽", "⣻", "⢿"]
8
- const INTERVAL_MS = 70
9
-
10
- function baseTitle(pi: ExtensionAPI, cwdPath: string): string {
11
- const cwd = path.basename(cwdPath)
12
- const session = pi.getSessionName()
13
- return session ? `π - ${session} - ${cwd}` : `π - ${cwd}`
14
- }
15
-
16
- export default function (pi: ExtensionAPI): void {
17
- let timer: ReturnType<typeof setInterval> | undefined
18
- let frameIndex = 0
19
-
20
- function stop(ctx: ExtensionContext): void {
21
- if (timer) {
22
- clearInterval(timer)
23
- timer = undefined
24
- }
25
- frameIndex = 0
26
- ctx.ui.setTitle(baseTitle(pi, ctx.cwd))
27
- }
28
-
29
- function start(ctx: ExtensionContext): void {
30
- stop(ctx)
31
- timer = setInterval(() => {
32
- const frame = FRAMES[frameIndex % FRAMES.length]
33
- ctx.ui.setTitle(`${frame} ${baseTitle(pi, ctx.cwd)}`)
34
- frameIndex++
35
- }, INTERVAL_MS)
36
- }
37
-
38
- pi.on("agent_start", async (_event, ctx) => {
39
- start(ctx)
40
- })
41
-
42
- pi.on("agent_settled", async (_event, ctx) => {
43
- stop(ctx)
44
- })
45
-
46
- pi.on("session_shutdown", async (_event, ctx) => {
47
- stop(ctx)
48
- })
49
- }