pi-ui-extend 0.1.1

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 (420) hide show
  1. package/README.md +307 -0
  2. package/bin/pix.mjs +219 -0
  3. package/dist/app/app.d.ts +96 -0
  4. package/dist/app/app.js +871 -0
  5. package/dist/app/blink-controller.d.ts +23 -0
  6. package/dist/app/blink-controller.js +82 -0
  7. package/dist/app/cli.d.ts +8 -0
  8. package/dist/app/cli.js +83 -0
  9. package/dist/app/clipboard.d.ts +1 -0
  10. package/dist/app/clipboard.js +24 -0
  11. package/dist/app/command-controller.d.ts +18 -0
  12. package/dist/app/command-controller.js +58 -0
  13. package/dist/app/command-host.d.ts +44 -0
  14. package/dist/app/command-host.js +1 -0
  15. package/dist/app/command-model-actions.d.ts +12 -0
  16. package/dist/app/command-model-actions.js +176 -0
  17. package/dist/app/command-navigation-actions.d.ts +19 -0
  18. package/dist/app/command-navigation-actions.js +267 -0
  19. package/dist/app/command-registry.d.ts +32 -0
  20. package/dist/app/command-registry.js +225 -0
  21. package/dist/app/command-runtime.d.ts +5 -0
  22. package/dist/app/command-runtime.js +32 -0
  23. package/dist/app/command-session-actions.d.ts +20 -0
  24. package/dist/app/command-session-actions.js +295 -0
  25. package/dist/app/constants.d.ts +52 -0
  26. package/dist/app/constants.js +103 -0
  27. package/dist/app/conversation-entry-renderer.d.ts +21 -0
  28. package/dist/app/conversation-entry-renderer.js +81 -0
  29. package/dist/app/conversation-shell-renderer.d.ts +5 -0
  30. package/dist/app/conversation-shell-renderer.js +43 -0
  31. package/dist/app/conversation-tool-renderer.d.ts +16 -0
  32. package/dist/app/conversation-tool-renderer.js +216 -0
  33. package/dist/app/conversation-viewport.d.ts +55 -0
  34. package/dist/app/conversation-viewport.js +252 -0
  35. package/dist/app/dcp-stats.d.ts +2 -0
  36. package/dist/app/dcp-stats.js +116 -0
  37. package/dist/app/editor-layout-renderer.d.ts +31 -0
  38. package/dist/app/editor-layout-renderer.js +211 -0
  39. package/dist/app/editor-panels.d.ts +4 -0
  40. package/dist/app/editor-panels.js +130 -0
  41. package/dist/app/extension-actions-controller.d.ts +22 -0
  42. package/dist/app/extension-actions-controller.js +60 -0
  43. package/dist/app/extension-event-bus.d.ts +3 -0
  44. package/dist/app/extension-event-bus.js +23 -0
  45. package/dist/app/extension-ui-controller.d.ts +57 -0
  46. package/dist/app/extension-ui-controller.js +532 -0
  47. package/dist/app/file-link-opener.d.ts +2 -0
  48. package/dist/app/file-link-opener.js +66 -0
  49. package/dist/app/file-links.d.ts +10 -0
  50. package/dist/app/file-links.js +117 -0
  51. package/dist/app/guards.d.ts +3 -0
  52. package/dist/app/guards.js +9 -0
  53. package/dist/app/icons.d.ts +37 -0
  54. package/dist/app/icons.js +97 -0
  55. package/dist/app/id.d.ts +1 -0
  56. package/dist/app/id.js +4 -0
  57. package/dist/app/image-click-targets.d.ts +5 -0
  58. package/dist/app/image-click-targets.js +32 -0
  59. package/dist/app/image-opener.d.ts +2 -0
  60. package/dist/app/image-opener.js +64 -0
  61. package/dist/app/input-action-controller.d.ts +47 -0
  62. package/dist/app/input-action-controller.js +209 -0
  63. package/dist/app/input-controller.d.ts +60 -0
  64. package/dist/app/input-controller.js +425 -0
  65. package/dist/app/input-paste-handler.d.ts +27 -0
  66. package/dist/app/input-paste-handler.js +146 -0
  67. package/dist/app/menu-items-controller.d.ts +32 -0
  68. package/dist/app/menu-items-controller.js +182 -0
  69. package/dist/app/message-content.d.ts +8 -0
  70. package/dist/app/message-content.js +115 -0
  71. package/dist/app/model-ref.d.ts +13 -0
  72. package/dist/app/model-ref.js +50 -0
  73. package/dist/app/model-usage-controller.d.ts +35 -0
  74. package/dist/app/model-usage-controller.js +99 -0
  75. package/dist/app/model-usage-status.d.ts +125 -0
  76. package/dist/app/model-usage-status.js +749 -0
  77. package/dist/app/mouse-controller.d.ts +182 -0
  78. package/dist/app/mouse-controller.js +968 -0
  79. package/dist/app/native-modifiers.d.ts +3 -0
  80. package/dist/app/native-modifiers.js +60 -0
  81. package/dist/app/nerd-font-controller.d.ts +11 -0
  82. package/dist/app/nerd-font-controller.js +90 -0
  83. package/dist/app/popup-action-controller.d.ts +44 -0
  84. package/dist/app/popup-action-controller.js +278 -0
  85. package/dist/app/popup-menu-controller.d.ts +183 -0
  86. package/dist/app/popup-menu-controller.js +1070 -0
  87. package/dist/app/prompt-enhancer-controller.d.ts +40 -0
  88. package/dist/app/prompt-enhancer-controller.js +215 -0
  89. package/dist/app/queued-message-controller.d.ts +62 -0
  90. package/dist/app/queued-message-controller.js +377 -0
  91. package/dist/app/render-controller.d.ts +41 -0
  92. package/dist/app/render-controller.js +378 -0
  93. package/dist/app/render-text.d.ts +19 -0
  94. package/dist/app/render-text.js +67 -0
  95. package/dist/app/request-history.d.ts +23 -0
  96. package/dist/app/request-history.js +131 -0
  97. package/dist/app/runtime.d.ts +39 -0
  98. package/dist/app/runtime.js +195 -0
  99. package/dist/app/screen-selection.d.ts +6 -0
  100. package/dist/app/screen-selection.js +9 -0
  101. package/dist/app/screen-styler.d.ts +34 -0
  102. package/dist/app/screen-styler.js +168 -0
  103. package/dist/app/scroll-controller.d.ts +51 -0
  104. package/dist/app/scroll-controller.js +207 -0
  105. package/dist/app/session-event-controller.d.ts +69 -0
  106. package/dist/app/session-event-controller.js +338 -0
  107. package/dist/app/session-history.d.ts +23 -0
  108. package/dist/app/session-history.js +164 -0
  109. package/dist/app/session-lifecycle-controller.d.ts +55 -0
  110. package/dist/app/session-lifecycle-controller.js +116 -0
  111. package/dist/app/session-search.d.ts +24 -0
  112. package/dist/app/session-search.js +215 -0
  113. package/dist/app/shell-command.d.ts +27 -0
  114. package/dist/app/shell-command.js +176 -0
  115. package/dist/app/shell-controller.d.ts +28 -0
  116. package/dist/app/shell-controller.js +124 -0
  117. package/dist/app/slash-commands.d.ts +6 -0
  118. package/dist/app/slash-commands.js +75 -0
  119. package/dist/app/startup-checks.d.ts +8 -0
  120. package/dist/app/startup-checks.js +59 -0
  121. package/dist/app/startup-info.d.ts +3 -0
  122. package/dist/app/startup-info.js +176 -0
  123. package/dist/app/status-controller.d.ts +35 -0
  124. package/dist/app/status-controller.js +105 -0
  125. package/dist/app/status-line-renderer.d.ts +68 -0
  126. package/dist/app/status-line-renderer.js +453 -0
  127. package/dist/app/subagents-files.d.ts +10 -0
  128. package/dist/app/subagents-files.js +193 -0
  129. package/dist/app/subagents-model.d.ts +23 -0
  130. package/dist/app/subagents-model.js +224 -0
  131. package/dist/app/subagents-widget-controller.d.ts +43 -0
  132. package/dist/app/subagents-widget-controller.js +311 -0
  133. package/dist/app/tab-line-renderer.d.ts +26 -0
  134. package/dist/app/tab-line-renderer.js +222 -0
  135. package/dist/app/tabs-controller.d.ts +100 -0
  136. package/dist/app/tabs-controller.js +885 -0
  137. package/dist/app/terminal-controller.d.ts +40 -0
  138. package/dist/app/terminal-controller.js +135 -0
  139. package/dist/app/terminal-edit-shortcuts.d.ts +23 -0
  140. package/dist/app/terminal-edit-shortcuts.js +138 -0
  141. package/dist/app/terminal-output-buffer.d.ts +20 -0
  142. package/dist/app/terminal-output-buffer.js +52 -0
  143. package/dist/app/toast-controller.d.ts +13 -0
  144. package/dist/app/toast-controller.js +40 -0
  145. package/dist/app/toast-renderer.d.ts +9 -0
  146. package/dist/app/toast-renderer.js +79 -0
  147. package/dist/app/todo-model.d.ts +22 -0
  148. package/dist/app/todo-model.js +179 -0
  149. package/dist/app/todo-widget-controller.d.ts +21 -0
  150. package/dist/app/todo-widget-controller.js +59 -0
  151. package/dist/app/tool-block-renderer.d.ts +26 -0
  152. package/dist/app/tool-block-renderer.js +439 -0
  153. package/dist/app/types.d.ts +550 -0
  154. package/dist/app/types.js +1 -0
  155. package/dist/app/update.d.ts +36 -0
  156. package/dist/app/update.js +315 -0
  157. package/dist/app/voice-controller.d.ts +52 -0
  158. package/dist/app/voice-controller.js +600 -0
  159. package/dist/app/workspace-actions-controller.d.ts +40 -0
  160. package/dist/app/workspace-actions-controller.js +215 -0
  161. package/dist/app/workspace-undo.d.ts +44 -0
  162. package/dist/app/workspace-undo.js +215 -0
  163. package/dist/config.d.ts +62 -0
  164. package/dist/config.js +527 -0
  165. package/dist/context-progress-bar.d.ts +17 -0
  166. package/dist/context-progress-bar.js +48 -0
  167. package/dist/default-pix-config.d.ts +1 -0
  168. package/dist/default-pix-config.js +375 -0
  169. package/dist/fuzzy.d.ts +23 -0
  170. package/dist/fuzzy.js +165 -0
  171. package/dist/input-editor-files.d.ts +15 -0
  172. package/dist/input-editor-files.js +62 -0
  173. package/dist/input-editor.d.ts +186 -0
  174. package/dist/input-editor.js +835 -0
  175. package/dist/main.d.ts +1 -0
  176. package/dist/main.js +12 -0
  177. package/dist/markdown-format.d.ts +22 -0
  178. package/dist/markdown-format.js +542 -0
  179. package/dist/sdk.d.ts +3 -0
  180. package/dist/sdk.js +1 -0
  181. package/dist/syntax-highlight.d.ts +22 -0
  182. package/dist/syntax-highlight.js +528 -0
  183. package/dist/terminal-width.d.ts +6 -0
  184. package/dist/terminal-width.js +245 -0
  185. package/dist/theme.d.ts +56 -0
  186. package/dist/theme.js +118 -0
  187. package/dist/tool-renderers/apply-patch.d.ts +2 -0
  188. package/dist/tool-renderers/apply-patch.js +36 -0
  189. package/dist/tool-renderers/ast.d.ts +2 -0
  190. package/dist/tool-renderers/ast.js +5 -0
  191. package/dist/tool-renderers/compress.d.ts +2 -0
  192. package/dist/tool-renderers/compress.js +126 -0
  193. package/dist/tool-renderers/index.d.ts +3 -0
  194. package/dist/tool-renderers/index.js +44 -0
  195. package/dist/tool-renderers/question.d.ts +2 -0
  196. package/dist/tool-renderers/question.js +88 -0
  197. package/dist/tool-renderers/read.d.ts +2 -0
  198. package/dist/tool-renderers/read.js +36 -0
  199. package/dist/tool-renderers/repo.d.ts +2 -0
  200. package/dist/tool-renderers/repo.js +13 -0
  201. package/dist/tool-renderers/shell.d.ts +3 -0
  202. package/dist/tool-renderers/shell.js +27 -0
  203. package/dist/tool-renderers/skill.d.ts +2 -0
  204. package/dist/tool-renderers/skill.js +132 -0
  205. package/dist/tool-renderers/subagents.d.ts +2 -0
  206. package/dist/tool-renderers/subagents.js +51 -0
  207. package/dist/tool-renderers/todo.d.ts +2 -0
  208. package/dist/tool-renderers/todo.js +9 -0
  209. package/dist/tool-renderers/types.d.ts +42 -0
  210. package/dist/tool-renderers/types.js +1 -0
  211. package/dist/tool-renderers/utils.d.ts +31 -0
  212. package/dist/tool-renderers/utils.js +230 -0
  213. package/dist/tool-renderers/web.d.ts +3 -0
  214. package/dist/tool-renderers/web.js +9 -0
  215. package/dist/tool-renderers/write.d.ts +2 -0
  216. package/dist/tool-renderers/write.js +42 -0
  217. package/dist/ui.d.ts +56 -0
  218. package/dist/ui.js +94 -0
  219. package/docs/release.md +81 -0
  220. package/extensions/question/contract.ts +100 -0
  221. package/extensions/question/index.ts +34 -0
  222. package/extensions/question/render.ts +28 -0
  223. package/extensions/question/result.ts +86 -0
  224. package/extensions/question/tool-description.ts +11 -0
  225. package/extensions/question/tui.ts +629 -0
  226. package/extensions/question/types.ts +123 -0
  227. package/extensions/session-title/config.ts +169 -0
  228. package/extensions/session-title/index.ts +459 -0
  229. package/extensions/terminal-bell/index.ts +315 -0
  230. package/external/pi-tools-suite/README.md +242 -0
  231. package/external/pi-tools-suite/index.ts +1 -0
  232. package/external/pi-tools-suite/licenses/ollama-pi-web-search.MIT +21 -0
  233. package/external/pi-tools-suite/licenses/opencode-mystatus-MIT.txt +21 -0
  234. package/external/pi-tools-suite/package.json +53 -0
  235. package/external/pi-tools-suite/src/antigravity-auth/auth-store.ts +194 -0
  236. package/external/pi-tools-suite/src/antigravity-auth/commands.ts +80 -0
  237. package/external/pi-tools-suite/src/antigravity-auth/constants.ts +26 -0
  238. package/external/pi-tools-suite/src/antigravity-auth/headers.ts +20 -0
  239. package/external/pi-tools-suite/src/antigravity-auth/index.ts +104 -0
  240. package/external/pi-tools-suite/src/antigravity-auth/models.ts +86 -0
  241. package/external/pi-tools-suite/src/antigravity-auth/oauth.ts +305 -0
  242. package/external/pi-tools-suite/src/antigravity-auth/payload.ts +423 -0
  243. package/external/pi-tools-suite/src/antigravity-auth/status.ts +78 -0
  244. package/external/pi-tools-suite/src/antigravity-auth/stream.ts +302 -0
  245. package/external/pi-tools-suite/src/antigravity-auth/types.ts +113 -0
  246. package/external/pi-tools-suite/src/ast-grep/index.ts +6 -0
  247. package/external/pi-tools-suite/src/ast-grep/render.ts +70 -0
  248. package/external/pi-tools-suite/src/ast-grep/schema.ts +109 -0
  249. package/external/pi-tools-suite/src/ast-grep/tool.ts +345 -0
  250. package/external/pi-tools-suite/src/ast-grep/types.ts +55 -0
  251. package/external/pi-tools-suite/src/ast-grep/utils.ts +65 -0
  252. package/external/pi-tools-suite/src/async-subagents/async-subagents.sample.jsonc +222 -0
  253. package/external/pi-tools-suite/src/async-subagents/commands.ts +518 -0
  254. package/external/pi-tools-suite/src/async-subagents/constants.ts +11 -0
  255. package/external/pi-tools-suite/src/async-subagents/core/agent-strategy.ts +74 -0
  256. package/external/pi-tools-suite/src/async-subagents/core/attachment-bridge.ts +133 -0
  257. package/external/pi-tools-suite/src/async-subagents/core/cleanup.ts +66 -0
  258. package/external/pi-tools-suite/src/async-subagents/core/concurrency.ts +90 -0
  259. package/external/pi-tools-suite/src/async-subagents/core/config.ts +819 -0
  260. package/external/pi-tools-suite/src/async-subagents/core/log-limits.ts +166 -0
  261. package/external/pi-tools-suite/src/async-subagents/core/model-fallback.ts +133 -0
  262. package/external/pi-tools-suite/src/async-subagents/core/paths.ts +47 -0
  263. package/external/pi-tools-suite/src/async-subagents/core/pi-invocation.ts +35 -0
  264. package/external/pi-tools-suite/src/async-subagents/core/presets.ts +67 -0
  265. package/external/pi-tools-suite/src/async-subagents/core/process.ts +15 -0
  266. package/external/pi-tools-suite/src/async-subagents/core/prompt.ts +66 -0
  267. package/external/pi-tools-suite/src/async-subagents/core/registry.ts +224 -0
  268. package/external/pi-tools-suite/src/async-subagents/core/retry.ts +191 -0
  269. package/external/pi-tools-suite/src/async-subagents/core/routing.ts +259 -0
  270. package/external/pi-tools-suite/src/async-subagents/core/sessions.ts +138 -0
  271. package/external/pi-tools-suite/src/async-subagents/core/spawn.ts +688 -0
  272. package/external/pi-tools-suite/src/async-subagents/core/state.ts +281 -0
  273. package/external/pi-tools-suite/src/async-subagents/core/stop.ts +131 -0
  274. package/external/pi-tools-suite/src/async-subagents/core/structured-result.ts +237 -0
  275. package/external/pi-tools-suite/src/async-subagents/core/tool-guard.ts +34 -0
  276. package/external/pi-tools-suite/src/async-subagents/core/types.ts +150 -0
  277. package/external/pi-tools-suite/src/async-subagents/core/ultrawork-auto.ts +184 -0
  278. package/external/pi-tools-suite/src/async-subagents/core/utils.ts +11 -0
  279. package/external/pi-tools-suite/src/async-subagents/format.ts +41 -0
  280. package/external/pi-tools-suite/src/async-subagents/index.ts +422 -0
  281. package/external/pi-tools-suite/src/async-subagents/lib.ts +88 -0
  282. package/external/pi-tools-suite/src/async-subagents/live.ts +10 -0
  283. package/external/pi-tools-suite/src/async-subagents/polling.ts +83 -0
  284. package/external/pi-tools-suite/src/async-subagents/render.ts +230 -0
  285. package/external/pi-tools-suite/src/async-subagents/subagent-overlay.ts +77 -0
  286. package/external/pi-tools-suite/src/async-subagents/tasks.ts +120 -0
  287. package/external/pi-tools-suite/src/async-subagents/tools/cleanup.ts +99 -0
  288. package/external/pi-tools-suite/src/async-subagents/tools/result.ts +179 -0
  289. package/external/pi-tools-suite/src/async-subagents/tools/spawn.ts +372 -0
  290. package/external/pi-tools-suite/src/async-subagents/tools/status.ts +60 -0
  291. package/external/pi-tools-suite/src/async-subagents/tools/stop.ts +79 -0
  292. package/external/pi-tools-suite/src/async-subagents/tools/subagents.ts +152 -0
  293. package/external/pi-tools-suite/src/async-subagents/tools/wait.ts +67 -0
  294. package/external/pi-tools-suite/src/async-subagents/types.ts +45 -0
  295. package/external/pi-tools-suite/src/async-subagents/ui.ts +5 -0
  296. package/external/pi-tools-suite/src/compress/commands.ts +440 -0
  297. package/external/pi-tools-suite/src/compress/compress-tool.ts +368 -0
  298. package/external/pi-tools-suite/src/compress/compression-blocks.ts +524 -0
  299. package/external/pi-tools-suite/src/compress/config.ts +310 -0
  300. package/external/pi-tools-suite/src/compress/dcp-tui-filter.ts +498 -0
  301. package/external/pi-tools-suite/src/compress/index.ts +397 -0
  302. package/external/pi-tools-suite/src/compress/prompts.ts +269 -0
  303. package/external/pi-tools-suite/src/compress/pruner-candidates.ts +176 -0
  304. package/external/pi-tools-suite/src/compress/pruner-compression-blocks.ts +260 -0
  305. package/external/pi-tools-suite/src/compress/pruner-message-ids.ts +147 -0
  306. package/external/pi-tools-suite/src/compress/pruner-metadata.ts +268 -0
  307. package/external/pi-tools-suite/src/compress/pruner-nudge.ts +315 -0
  308. package/external/pi-tools-suite/src/compress/pruner-tools.ts +263 -0
  309. package/external/pi-tools-suite/src/compress/pruner-types.ts +25 -0
  310. package/external/pi-tools-suite/src/compress/pruner.ts +92 -0
  311. package/external/pi-tools-suite/src/compress/state.ts +486 -0
  312. package/external/pi-tools-suite/src/compress/ui.ts +308 -0
  313. package/external/pi-tools-suite/src/config.ts +176 -0
  314. package/external/pi-tools-suite/src/context-usage.ts +31 -0
  315. package/external/pi-tools-suite/src/default-pi-tools-suite-config.ts +355 -0
  316. package/external/pi-tools-suite/src/index.ts +46 -0
  317. package/external/pi-tools-suite/src/lib/lsp.ts +62 -0
  318. package/external/pi-tools-suite/src/lib/project.ts +42 -0
  319. package/external/pi-tools-suite/src/lib/tool-args.ts +137 -0
  320. package/external/pi-tools-suite/src/lsp/_shared/config.ts +156 -0
  321. package/external/pi-tools-suite/src/lsp/_shared/glob.ts +60 -0
  322. package/external/pi-tools-suite/src/lsp/_shared/output.ts +102 -0
  323. package/external/pi-tools-suite/src/lsp/_shared/paths.ts +138 -0
  324. package/external/pi-tools-suite/src/lsp/_shared/runner.ts +64 -0
  325. package/external/pi-tools-suite/src/lsp/_shared/template.ts +23 -0
  326. package/external/pi-tools-suite/src/lsp/_shared/trust.ts +116 -0
  327. package/external/pi-tools-suite/src/lsp/_shared/types.ts +98 -0
  328. package/external/pi-tools-suite/src/lsp/async.ts +29 -0
  329. package/external/pi-tools-suite/src/lsp/child-process.ts +81 -0
  330. package/external/pi-tools-suite/src/lsp/client.ts +340 -0
  331. package/external/pi-tools-suite/src/lsp/constants.ts +9 -0
  332. package/external/pi-tools-suite/src/lsp/diagnostics-store.ts +64 -0
  333. package/external/pi-tools-suite/src/lsp/documents.ts +24 -0
  334. package/external/pi-tools-suite/src/lsp/index.ts +31 -0
  335. package/external/pi-tools-suite/src/lsp/lsp-utils.ts +37 -0
  336. package/external/pi-tools-suite/src/lsp/manager.ts +190 -0
  337. package/external/pi-tools-suite/src/lsp/mutation-events.ts +78 -0
  338. package/external/pi-tools-suite/src/lsp/renderer.ts +1 -0
  339. package/external/pi-tools-suite/src/lsp/tool-result.ts +6 -0
  340. package/external/pi-tools-suite/src/lsp/tsserver.ts +107 -0
  341. package/external/pi-tools-suite/src/lsp/types.ts +15 -0
  342. package/external/pi-tools-suite/src/model-tools/apply-patch.ts +590 -0
  343. package/external/pi-tools-suite/src/model-tools/index.ts +430 -0
  344. package/external/pi-tools-suite/src/model-tools/path-utils.ts +6 -0
  345. package/external/pi-tools-suite/src/model-tools/tool-args.ts +11 -0
  346. package/external/pi-tools-suite/src/prompt-commands/index.ts +349 -0
  347. package/external/pi-tools-suite/src/repo-discovery/index.ts +384 -0
  348. package/external/pi-tools-suite/src/repo-discovery/project.ts +7 -0
  349. package/external/pi-tools-suite/src/startup-section.ts +13 -0
  350. package/external/pi-tools-suite/src/terminal-bell/index.ts +309 -0
  351. package/external/pi-tools-suite/src/todo/index.ts +201 -0
  352. package/external/pi-tools-suite/src/todo/state/auto-clear.ts +13 -0
  353. package/external/pi-tools-suite/src/todo/state/invariants.ts +21 -0
  354. package/external/pi-tools-suite/src/todo/state/persistence.ts +94 -0
  355. package/external/pi-tools-suite/src/todo/state/replay.ts +38 -0
  356. package/external/pi-tools-suite/src/todo/state/selectors.ts +49 -0
  357. package/external/pi-tools-suite/src/todo/state/state-reducer.ts +362 -0
  358. package/external/pi-tools-suite/src/todo/state/state.ts +18 -0
  359. package/external/pi-tools-suite/src/todo/state/store.ts +52 -0
  360. package/external/pi-tools-suite/src/todo/state/task-graph.ts +57 -0
  361. package/external/pi-tools-suite/src/todo/todo.ts +487 -0
  362. package/external/pi-tools-suite/src/todo/tool/response-envelope.ts +143 -0
  363. package/external/pi-tools-suite/src/todo/tool/types.ts +188 -0
  364. package/external/pi-tools-suite/src/todo/view/format.ts +18 -0
  365. package/external/pi-tools-suite/src/todo/view/labels.ts +13 -0
  366. package/external/pi-tools-suite/src/tool-descriptions.ts +369 -0
  367. package/external/pi-tools-suite/src/usage/index.ts +152 -0
  368. package/external/pi-tools-suite/src/usage/lib/copilot.ts +535 -0
  369. package/external/pi-tools-suite/src/usage/lib/google.ts +478 -0
  370. package/external/pi-tools-suite/src/usage/lib/openai.ts +268 -0
  371. package/external/pi-tools-suite/src/usage/lib/types.ts +114 -0
  372. package/external/pi-tools-suite/src/usage/lib/utils.ts +134 -0
  373. package/external/pi-tools-suite/src/usage/lib/zhipu.ts +228 -0
  374. package/external/pi-tools-suite/src/web-search/index.ts +397 -0
  375. package/package.json +89 -0
  376. package/skills/context7/SKILL.md +69 -0
  377. package/skills/context7/scripts/context7.sh +73 -0
  378. package/skills/handoff/SKILL.md +15 -0
  379. package/skills/pdf/LICENSE.txt +30 -0
  380. package/skills/pdf/SKILL.md +314 -0
  381. package/skills/pdf/forms.md +294 -0
  382. package/skills/pdf/reference.md +612 -0
  383. package/skills/pdf/scripts/check_bounding_boxes.py +65 -0
  384. package/skills/pdf/scripts/check_fillable_fields.py +11 -0
  385. package/skills/pdf/scripts/convert_pdf_to_images.py +33 -0
  386. package/skills/pdf/scripts/create_validation_image.py +37 -0
  387. package/skills/pdf/scripts/extract_form_field_info.py +122 -0
  388. package/skills/pdf/scripts/extract_form_structure.py +115 -0
  389. package/skills/pdf/scripts/fill_fillable_fields.py +98 -0
  390. package/skills/pdf/scripts/fill_pdf_form_with_annotations.py +107 -0
  391. package/skills/playwright-cli/SKILL.md +388 -0
  392. package/skills/playwright-cli/references/element-attributes.md +23 -0
  393. package/skills/playwright-cli/references/playwright-tests.md +39 -0
  394. package/skills/playwright-cli/references/request-mocking.md +87 -0
  395. package/skills/playwright-cli/references/running-code.md +241 -0
  396. package/skills/playwright-cli/references/session-management.md +225 -0
  397. package/skills/playwright-cli/references/spec-driven-testing.md +305 -0
  398. package/skills/playwright-cli/references/storage-state.md +275 -0
  399. package/skills/playwright-cli/references/test-generation.md +134 -0
  400. package/skills/playwright-cli/references/tracing.md +139 -0
  401. package/skills/playwright-cli/references/video-recording.md +143 -0
  402. package/skills/simplify/SKILL.md +51 -0
  403. package/skills/skill-creator/LICENSE.txt +202 -0
  404. package/skills/skill-creator/SKILL.md +485 -0
  405. package/skills/skill-creator/agents/analyzer.md +274 -0
  406. package/skills/skill-creator/agents/comparator.md +202 -0
  407. package/skills/skill-creator/agents/grader.md +223 -0
  408. package/skills/skill-creator/assets/eval_review.html +146 -0
  409. package/skills/skill-creator/eval-viewer/generate_review.py +471 -0
  410. package/skills/skill-creator/eval-viewer/viewer.html +1325 -0
  411. package/skills/skill-creator/references/schemas.md +430 -0
  412. package/skills/skill-creator/scripts/__init__.py +0 -0
  413. package/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
  414. package/skills/skill-creator/scripts/generate_report.py +326 -0
  415. package/skills/skill-creator/scripts/improve_description.py +247 -0
  416. package/skills/skill-creator/scripts/package_skill.py +136 -0
  417. package/skills/skill-creator/scripts/quick_validate.py +103 -0
  418. package/skills/skill-creator/scripts/run_eval.py +310 -0
  419. package/skills/skill-creator/scripts/run_loop.py +328 -0
  420. package/skills/skill-creator/scripts/utils.py +47 -0
@@ -0,0 +1,600 @@
1
+ import { spawn, spawnSync } from "node:child_process";
2
+ import { createWriteStream } from "node:fs";
3
+ import { access, mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
4
+ import http from "node:http";
5
+ import https from "node:https";
6
+ import { createRequire } from "node:module";
7
+ import { join } from "node:path";
8
+ import { fileURLToPath } from "node:url";
9
+ import { savePixDictationLanguage } from "../config.js";
10
+ import { APP_ICONS } from "./icons.js";
11
+ const SAMPLE_RATE = 16_000;
12
+ const require = createRequire(import.meta.url);
13
+ const projectRoot = fileURLToPath(new URL("../..", import.meta.url));
14
+ const modelsRoot = join(projectRoot, "models", "vosk");
15
+ const VOSK_PACKAGE_SPEC = "vosk@0.3.39";
16
+ const VOICE_SPINNER_FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
17
+ let voskInstallPromise;
18
+ export class AppVoiceController {
19
+ host;
20
+ modelDefinitions;
21
+ languages;
22
+ language;
23
+ state = "idle";
24
+ modelCache = new Map();
25
+ audioProcess;
26
+ recognizer;
27
+ progressMessage;
28
+ progressFrame = 0;
29
+ progressTimer;
30
+ lastSystemProgressMessage;
31
+ partialTranscript;
32
+ startGeneration = 0;
33
+ constructor(host, dictationConfig) {
34
+ this.host = host;
35
+ this.modelDefinitions = dictationConfig.languages;
36
+ this.languages = Object.keys(this.modelDefinitions);
37
+ this.language = this.initialLanguage(dictationConfig.language);
38
+ }
39
+ statusWidgetText() {
40
+ const languageLabel = this.showLanguageSwitcher() ? ` ${this.language.toUpperCase()}` : "";
41
+ switch (this.state) {
42
+ case "installing":
43
+ return `${APP_ICONS.microphone}${languageLabel} ${APP_ICONS.timerSand}`;
44
+ case "downloading":
45
+ return `${APP_ICONS.down}${languageLabel}`;
46
+ case "loading":
47
+ return `${APP_ICONS.microphone}${languageLabel} ${APP_ICONS.timerSand}`;
48
+ case "listening":
49
+ return `${APP_ICONS.microphone}${languageLabel}`;
50
+ case "idle":
51
+ return `${APP_ICONS.microphone}${languageLabel}`;
52
+ }
53
+ }
54
+ showLanguageSwitcher() {
55
+ return this.languages.length > 1;
56
+ }
57
+ statusWidgetActive() {
58
+ return this.state === "listening";
59
+ }
60
+ progressOverlayText() {
61
+ if (!this.progressMessage)
62
+ return undefined;
63
+ const spinner = VOICE_SPINNER_FRAMES[this.progressFrame % VOICE_SPINNER_FRAMES.length] ?? APP_ICONS.timerSand;
64
+ return `${spinner} ${this.progressMessage}`;
65
+ }
66
+ async toggleRecording() {
67
+ if (this.state !== "idle") {
68
+ await this.stopRecording();
69
+ return;
70
+ }
71
+ await this.startRecording();
72
+ }
73
+ async toggleLanguage() {
74
+ if (!this.showLanguageSwitcher())
75
+ return;
76
+ const wasActive = this.state !== "idle";
77
+ if (wasActive)
78
+ await this.stopRecording();
79
+ this.language = this.nextLanguage();
80
+ this.saveLanguageSelection(this.language);
81
+ this.host.showToast(`Voice language: ${this.modelDefinition(this.language).label}`, "info");
82
+ this.host.render();
83
+ if (wasActive)
84
+ void this.startRecording();
85
+ }
86
+ async stopRecording() {
87
+ this.startGeneration += 1;
88
+ const audioProcess = this.audioProcess;
89
+ const recognizer = this.recognizer;
90
+ this.audioProcess = undefined;
91
+ this.recognizer = undefined;
92
+ if (audioProcess && !audioProcess.killed)
93
+ audioProcess.kill("SIGTERM");
94
+ if (recognizer) {
95
+ this.clearPartialTranscript();
96
+ this.emitTranscript(recognizer.finalResult());
97
+ recognizer.free?.();
98
+ }
99
+ if (this.state !== "idle") {
100
+ this.clearProgressMessage();
101
+ this.state = "idle";
102
+ this.host.render();
103
+ }
104
+ }
105
+ async dispose() {
106
+ await this.stopRecording();
107
+ for (const model of this.modelCache.values())
108
+ model.free?.();
109
+ this.modelCache.clear();
110
+ }
111
+ async startRecording() {
112
+ const language = this.language;
113
+ const generation = this.startGeneration + 1;
114
+ this.startGeneration = generation;
115
+ try {
116
+ const initialVosk = tryLoadVosk();
117
+ const vosk = initialVosk.ok
118
+ ? initialVosk.module
119
+ : await this.installAndLoadVosk(initialVosk.error, generation);
120
+ if (!this.isCurrentStart(generation))
121
+ return;
122
+ vosk.setLogLevel?.(-1);
123
+ this.state = "downloading";
124
+ this.host.render();
125
+ const modelPath = await ensureModel(language, this.modelDefinition(language));
126
+ if (!this.isCurrentStart(generation))
127
+ return;
128
+ this.state = "loading";
129
+ this.host.render();
130
+ const model = this.cachedModel(language, modelPath, vosk);
131
+ const recorder = selectRecorderCommand();
132
+ const recognizer = new vosk.Recognizer({ model, sampleRate: SAMPLE_RATE });
133
+ const audioProcess = spawn(recorder.command, recorder.args, { stdio: ["ignore", "pipe", "pipe"] });
134
+ this.recognizer = recognizer;
135
+ this.audioProcess = audioProcess;
136
+ this.state = "listening";
137
+ this.host.render();
138
+ this.host.showToast(`Voice input on (${this.modelDefinition(language).label}, ${recorder.description})`, "info");
139
+ this.bindAudioProcess(audioProcess, recognizer, generation);
140
+ }
141
+ catch (error) {
142
+ if (!this.isCurrentStart(generation))
143
+ return;
144
+ this.clearProgressMessage();
145
+ this.cleanupRecognizer();
146
+ this.state = "idle";
147
+ this.addProgressSystemMessage(`Unavailable: ${errorMessage(error)}`);
148
+ this.host.showToast(`Voice input unavailable: ${errorMessage(error)}`, "error");
149
+ this.host.render();
150
+ }
151
+ }
152
+ cachedModel(language, modelPath, vosk) {
153
+ const cached = this.modelCache.get(language);
154
+ if (cached)
155
+ return cached;
156
+ const model = new vosk.Model(modelPath);
157
+ this.modelCache.set(language, model);
158
+ return model;
159
+ }
160
+ nextLanguage() {
161
+ const currentIndex = this.languages.indexOf(this.language);
162
+ const nextIndex = currentIndex >= 0 ? (currentIndex + 1) % this.languages.length : 0;
163
+ return this.languages[nextIndex] ?? this.language;
164
+ }
165
+ initialLanguage(configuredLanguage) {
166
+ if (configuredLanguage && this.languages.includes(configuredLanguage))
167
+ return configuredLanguage;
168
+ return this.languages.includes("en") ? "en" : this.languages[0] ?? "en";
169
+ }
170
+ saveLanguageSelection(language) {
171
+ try {
172
+ savePixDictationLanguage(language);
173
+ }
174
+ catch (error) {
175
+ this.host.showToast(`Could not save voice language: ${errorMessage(error)}`, "warning");
176
+ }
177
+ }
178
+ modelDefinition(language) {
179
+ const definition = this.modelDefinitions[language];
180
+ if (!definition)
181
+ throw new Error(`dictation language is not configured: ${language}`);
182
+ return definition;
183
+ }
184
+ async installAndLoadVosk(initialError, generation) {
185
+ this.state = "installing";
186
+ this.setProgressMessage("Installing Vosk voice bindings...");
187
+ const vosk = await loadVoskWithAutoInstall(initialError, (message) => {
188
+ if (this.isCurrentStart(generation))
189
+ this.setProgressMessage(message);
190
+ });
191
+ if (this.isCurrentStart(generation))
192
+ this.addProgressSystemMessage("Vosk voice bindings are ready.");
193
+ if (this.isCurrentStart(generation))
194
+ this.clearProgressMessage();
195
+ return vosk;
196
+ }
197
+ bindAudioProcess(audioProcess, recognizer, generation) {
198
+ let stderr = "";
199
+ audioProcess.stdout.on("data", (chunk) => {
200
+ if (!this.isCurrentAudioProcess(audioProcess, recognizer, generation))
201
+ return;
202
+ try {
203
+ if (recognizer.acceptWaveform(chunk)) {
204
+ this.clearPartialTranscript();
205
+ this.emitTranscript(recognizer.result());
206
+ }
207
+ else {
208
+ this.emitPartialTranscript(recognizer.partialResult?.());
209
+ }
210
+ }
211
+ catch (error) {
212
+ this.host.showToast(`Voice recognition failed: ${errorMessage(error)}`, "error");
213
+ void this.stopRecording();
214
+ }
215
+ });
216
+ audioProcess.stderr.on("data", (chunk) => {
217
+ stderr = `${stderr}${chunk.toString("utf8")}`.slice(-600);
218
+ });
219
+ audioProcess.once("error", (error) => {
220
+ if (!this.isCurrentAudioProcess(audioProcess, recognizer, generation))
221
+ return;
222
+ this.clearPartialTranscript();
223
+ this.cleanupRecognizer();
224
+ this.audioProcess = undefined;
225
+ this.state = "idle";
226
+ this.host.showToast(`Voice recorder failed: ${errorMessage(error)}`, "error");
227
+ this.host.render();
228
+ });
229
+ audioProcess.once("close", (code, signal) => {
230
+ if (!this.isCurrentAudioProcess(audioProcess, recognizer, generation))
231
+ return;
232
+ this.clearPartialTranscript();
233
+ this.emitTranscript(recognizer.finalResult());
234
+ this.cleanupRecognizer();
235
+ this.audioProcess = undefined;
236
+ this.state = "idle";
237
+ if (code && code !== 0) {
238
+ const details = stderr.trim() || signal || `exit code ${code}`;
239
+ this.host.showToast(`Voice recorder stopped: ${details}`, "warning");
240
+ }
241
+ this.host.render();
242
+ });
243
+ }
244
+ cleanupRecognizer() {
245
+ this.recognizer?.free?.();
246
+ this.recognizer = undefined;
247
+ }
248
+ setProgressMessage(message) {
249
+ this.progressMessage = message;
250
+ this.addProgressSystemMessage(message);
251
+ if (!this.progressTimer) {
252
+ this.progressTimer = setInterval(() => {
253
+ this.progressFrame += 1;
254
+ this.host.render();
255
+ }, 120);
256
+ this.progressTimer.unref();
257
+ }
258
+ this.host.render();
259
+ }
260
+ clearProgressMessage() {
261
+ this.progressMessage = undefined;
262
+ this.lastSystemProgressMessage = undefined;
263
+ if (this.progressTimer) {
264
+ clearInterval(this.progressTimer);
265
+ this.progressTimer = undefined;
266
+ }
267
+ }
268
+ addProgressSystemMessage(message) {
269
+ const text = `Voice input: ${message}`;
270
+ if (text === this.lastSystemProgressMessage)
271
+ return;
272
+ this.lastSystemProgressMessage = text;
273
+ this.host.addSystemMessage(text);
274
+ }
275
+ emitTranscript(result) {
276
+ const text = transcriptText(result);
277
+ if (!text)
278
+ return;
279
+ this.host.insertTranscript(text);
280
+ }
281
+ emitPartialTranscript(result) {
282
+ const text = partialTranscriptText(result);
283
+ if (text === this.partialTranscript)
284
+ return;
285
+ this.partialTranscript = text;
286
+ this.host.setPartialTranscript(text);
287
+ }
288
+ clearPartialTranscript() {
289
+ if (!this.partialTranscript)
290
+ return;
291
+ this.partialTranscript = undefined;
292
+ this.host.setPartialTranscript(undefined);
293
+ }
294
+ isCurrentStart(generation) {
295
+ return this.startGeneration === generation;
296
+ }
297
+ isCurrentAudioProcess(audioProcess, recognizer, generation) {
298
+ return this.startGeneration === generation && this.audioProcess === audioProcess && this.recognizer === recognizer;
299
+ }
300
+ }
301
+ async function ensureModel(language, definition) {
302
+ const modelPath = join(modelsRoot, definition.dirName);
303
+ if (await looksLikeVoskModel(modelPath))
304
+ return modelPath;
305
+ await mkdir(modelsRoot, { recursive: true });
306
+ const zipPath = join(modelsRoot, `${definition.dirName}.zip`);
307
+ const tempPath = join(modelsRoot, `${definition.dirName}.tmp-${process.pid}-${Date.now()}`);
308
+ await rm(zipPath, { force: true });
309
+ await rm(tempPath, { recursive: true, force: true });
310
+ await downloadFile(definition.url, zipPath);
311
+ await mkdir(tempPath, { recursive: true });
312
+ await extractZip(zipPath, tempPath);
313
+ const extractedPath = join(tempPath, definition.dirName);
314
+ if (!(await looksLikeVoskModel(extractedPath))) {
315
+ await rm(tempPath, { recursive: true, force: true });
316
+ await rm(zipPath, { force: true });
317
+ throw new Error(`downloaded ${definition.label} (${language}) model did not contain a valid Vosk model`);
318
+ }
319
+ await rm(modelPath, { recursive: true, force: true });
320
+ await rename(extractedPath, modelPath);
321
+ await rm(tempPath, { recursive: true, force: true });
322
+ await rm(zipPath, { force: true });
323
+ return modelPath;
324
+ }
325
+ async function looksLikeVoskModel(modelPath) {
326
+ return (await pathExists(join(modelPath, "conf", "model.conf"))) && (await pathExists(join(modelPath, "am", "final.mdl")));
327
+ }
328
+ async function pathExists(path) {
329
+ try {
330
+ await access(path);
331
+ return true;
332
+ }
333
+ catch {
334
+ return false;
335
+ }
336
+ }
337
+ async function downloadFile(url, destination, redirects = 3) {
338
+ await new Promise((resolve, reject) => {
339
+ const client = url.startsWith("https:") ? https : http;
340
+ const request = client.get(url, (response) => {
341
+ const statusCode = response.statusCode ?? 0;
342
+ const location = response.headers.location;
343
+ if ([301, 302, 303, 307, 308].includes(statusCode) && location && redirects > 0) {
344
+ response.resume();
345
+ const redirectedUrl = new URL(location, url).toString();
346
+ downloadFile(redirectedUrl, destination, redirects - 1).then(resolve, reject);
347
+ return;
348
+ }
349
+ if (statusCode !== 200) {
350
+ response.resume();
351
+ reject(new Error(`download failed with HTTP ${statusCode}`));
352
+ return;
353
+ }
354
+ const file = createWriteStream(destination);
355
+ file.on("finish", () => {
356
+ file.close((error) => {
357
+ if (error)
358
+ reject(error);
359
+ else
360
+ resolve();
361
+ });
362
+ });
363
+ file.on("error", reject);
364
+ response.pipe(file);
365
+ });
366
+ request.on("error", reject);
367
+ });
368
+ }
369
+ async function extractZip(zipPath, destination) {
370
+ if (commandExists("unzip")) {
371
+ await runCommand("unzip", ["-q", zipPath, "-d", destination]);
372
+ return;
373
+ }
374
+ if (process.platform === "darwin" && commandExists("ditto")) {
375
+ await runCommand("ditto", ["-x", "-k", zipPath, destination]);
376
+ return;
377
+ }
378
+ throw new Error("cannot extract Vosk model: install `unzip` (or `ditto` on macOS)");
379
+ }
380
+ async function runCommand(command, args) {
381
+ await new Promise((resolve, reject) => {
382
+ const child = spawn(command, args, { stdio: ["ignore", "ignore", "pipe"] });
383
+ let stderr = "";
384
+ child.stderr.on("data", (chunk) => {
385
+ stderr = `${stderr}${chunk.toString("utf8")}`.slice(-600);
386
+ });
387
+ child.once("error", reject);
388
+ child.once("close", (code) => {
389
+ if (code === 0)
390
+ resolve();
391
+ else
392
+ reject(new Error(`${command} failed${stderr.trim() ? `: ${stderr.trim()}` : ""}`));
393
+ });
394
+ });
395
+ }
396
+ async function loadVoskWithAutoInstall(initialError, progress) {
397
+ const installOutput = await ensureVoskInstalled(progress, initialError);
398
+ const attempt = tryLoadVosk();
399
+ if (attempt.ok)
400
+ return attempt.module;
401
+ throw new Error(`automatic Vosk install/build finished, but bindings still cannot load: ${errorMessage(attempt.error)}${installDiagnosticSuffix(installOutput)}`);
402
+ }
403
+ async function ensureVoskInstalled(progress, initialError) {
404
+ if (voskInstallPromise) {
405
+ progress("Waiting for Vosk install already in progress...");
406
+ await voskInstallPromise;
407
+ return "";
408
+ }
409
+ voskInstallPromise = installVoskBindings(progress, initialError).finally(() => {
410
+ voskInstallPromise = undefined;
411
+ });
412
+ return await voskInstallPromise;
413
+ }
414
+ async function installVoskBindings(progress, initialError) {
415
+ progress(`Installing Vosk bindings (${VOSK_PACKAGE_SPEC})...`);
416
+ let installOutput = "";
417
+ try {
418
+ installOutput = await runNpmCommand(["install", "--no-save", "--package-lock=false", VOSK_PACKAGE_SPEC, "--ignore-scripts"], "Installing Vosk", progress);
419
+ await patchVoskNativeDependencies(progress);
420
+ progress("Building Vosk native dependencies...");
421
+ const rebuildOutput = await runNpmCommand(["rebuild", "ffi-napi", "ref-napi", "--foreground-scripts", "--ignore-scripts=false"], "Building Vosk", progress);
422
+ const installedAttempt = tryLoadVosk();
423
+ if (installedAttempt.ok)
424
+ return `${installOutput}\n${rebuildOutput}`;
425
+ if (isMissingModuleError(installedAttempt.error)) {
426
+ throw new Error(`npm install finished without a loadable Vosk package: ${errorMessage(installedAttempt.error)}${installDiagnosticSuffix(`${installOutput}\n${rebuildOutput}`)}`);
427
+ }
428
+ progress("Rebuilding Vosk package...");
429
+ const voskRebuildOutput = await runNpmCommand(["rebuild", "vosk", "--foreground-scripts", "--ignore-scripts=false"], "Building Vosk", progress);
430
+ return `${installOutput}\n${rebuildOutput}\n${voskRebuildOutput}`;
431
+ }
432
+ catch (error) {
433
+ throw new Error(`automatic Vosk install/build failed: ${errorMessage(error)} (initial load error: ${errorMessage(initialError)})`);
434
+ }
435
+ }
436
+ async function patchVoskNativeDependencies(progress) {
437
+ const headerPath = join(projectRoot, "node_modules", "get-uv-event-loop-napi-h", "include", "get-uv-event-loop-napi.h");
438
+ let source;
439
+ try {
440
+ source = await readFile(headerPath, "utf8");
441
+ }
442
+ catch {
443
+ return;
444
+ }
445
+ const oldLine = "napi_get_uv_event_loop__ = &napi_get_uv_event_loop;";
446
+ const newLine = "napi_get_uv_event_loop__ = (get_uv_event_loop_fn)&napi_get_uv_event_loop;";
447
+ if (source.includes(newLine))
448
+ return;
449
+ if (!source.includes(oldLine))
450
+ return;
451
+ await writeFile(headerPath, source.replace(oldLine, newLine));
452
+ progress("Patched Vosk native headers for Node 24...");
453
+ }
454
+ async function runNpmCommand(args, label, progress) {
455
+ return await new Promise((resolve, reject) => {
456
+ const child = spawn(npmCommand(), args, {
457
+ cwd: projectRoot,
458
+ env: { ...process.env, npm_config_ignore_scripts: "false" },
459
+ stdio: ["ignore", "pipe", "pipe"],
460
+ });
461
+ let output = "";
462
+ const observeOutput = (chunk) => {
463
+ const text = chunk.toString("utf8");
464
+ output = `${output}${text}`.slice(-1200);
465
+ const line = lastUsefulLine(text);
466
+ if (line)
467
+ progress(`${label}: ${line}`);
468
+ };
469
+ child.stdout.on("data", observeOutput);
470
+ child.stderr.on("data", observeOutput);
471
+ child.once("error", reject);
472
+ child.once("close", (code) => {
473
+ if (code === 0)
474
+ resolve(output);
475
+ else
476
+ reject(new Error(`${npmCommand()} ${args.join(" ")} failed${output.trim() ? `: ${output.trim()}` : ""}`));
477
+ });
478
+ });
479
+ }
480
+ function isMissingModuleError(error) {
481
+ return /Cannot find module ['"]vosk['"]/u.test(errorMessage(error));
482
+ }
483
+ function installDiagnosticSuffix(output) {
484
+ const summary = compactOutputSummary(output);
485
+ const nodeHint = nodeVersionCompatibilityHint(output);
486
+ return `${summary ? ` Last npm output: ${summary}` : ""}${nodeHint ? ` ${nodeHint}` : ""}`;
487
+ }
488
+ function compactOutputSummary(output) {
489
+ const lines = output.split(/\r?\n/u).map((line) => line.trim()).filter(Boolean);
490
+ const interesting = lines.filter((line) => /\b(error|ERR!|failed|not ok|incompatible|Cannot find|node-gyp|make:)\b/iu.test(line));
491
+ const selected = (interesting.length > 0 ? interesting : lines).slice(-8);
492
+ const summary = selected.join(" | ");
493
+ return summary.length > 900 ? `${summary.slice(0, 897)}...` : summary;
494
+ }
495
+ function nodeVersionCompatibilityHint(output) {
496
+ const nodeMajor = Number.parseInt(process.versions.node.split(".")[0] ?? "", 10);
497
+ if (nodeMajor >= 25 && /ffi-napi|node-gyp|napi_add_finalizer|get_uv_event_loop/iu.test(output)) {
498
+ return `Detected Node ${process.versions.node}; Vosk npm bindings depend on ffi-napi, which may not build on this Node version. Try running Pix with Node 22 or 24.`;
499
+ }
500
+ return undefined;
501
+ }
502
+ function lastUsefulLine(text) {
503
+ const lines = text.split(/\r?\n/u).map((line) => line.trim()).filter(Boolean);
504
+ const line = lines.at(-1);
505
+ if (!line)
506
+ return undefined;
507
+ return line.length > 96 ? `${line.slice(0, 93)}...` : line;
508
+ }
509
+ function npmCommand() {
510
+ return process.platform === "win32" ? "npm.cmd" : "npm";
511
+ }
512
+ function tryLoadVosk() {
513
+ try {
514
+ return { ok: true, module: loadVosk() };
515
+ }
516
+ catch (error) {
517
+ return { ok: false, error };
518
+ }
519
+ }
520
+ function loadVosk() {
521
+ let moduleValue;
522
+ try {
523
+ moduleValue = require("vosk");
524
+ }
525
+ catch (error) {
526
+ throw new Error(`local Vosk bindings are not ready: ${errorMessage(error)}`);
527
+ }
528
+ if (!isVoskModule(moduleValue))
529
+ throw new Error("installed `vosk` package does not expose Model and Recognizer");
530
+ return moduleValue;
531
+ }
532
+ function isVoskModule(value) {
533
+ if (!value || typeof value !== "object")
534
+ return false;
535
+ const record = value;
536
+ return typeof record.Model === "function" && typeof record.Recognizer === "function";
537
+ }
538
+ function selectRecorderCommand() {
539
+ const commands = [
540
+ {
541
+ command: "rec",
542
+ args: ["-q", "-r", String(SAMPLE_RATE), "-c", "1", "-b", "16", "-e", "signed-integer", "-t", "raw", "-"],
543
+ description: "rec",
544
+ },
545
+ {
546
+ command: "sox",
547
+ args: ["-q", "-d", "-r", String(SAMPLE_RATE), "-c", "1", "-b", "16", "-e", "signed-integer", "-t", "raw", "-"],
548
+ description: "sox default device",
549
+ },
550
+ ];
551
+ if (process.platform === "darwin") {
552
+ commands.push({
553
+ command: "ffmpeg",
554
+ args: ["-hide_banner", "-loglevel", "error", "-f", "avfoundation", "-i", ":0", "-ar", String(SAMPLE_RATE), "-ac", "1", "-f", "s16le", "-"],
555
+ description: "ffmpeg avfoundation",
556
+ });
557
+ }
558
+ if (process.platform === "linux") {
559
+ commands.push({
560
+ command: "ffmpeg",
561
+ args: ["-hide_banner", "-loglevel", "error", "-f", "alsa", "-i", "default", "-ar", String(SAMPLE_RATE), "-ac", "1", "-f", "s16le", "-"],
562
+ description: "ffmpeg alsa",
563
+ }, {
564
+ command: "arecord",
565
+ args: ["-q", "-r", String(SAMPLE_RATE), "-c", "1", "-f", "S16_LE", "-t", "raw"],
566
+ description: "arecord",
567
+ });
568
+ }
569
+ const command = commands.find((candidate) => commandExists(candidate.command));
570
+ if (!command)
571
+ throw new Error("audio recorder not found: install SoX (`rec`/`sox`), ffmpeg, or arecord");
572
+ return command;
573
+ }
574
+ function commandExists(command) {
575
+ if (process.platform === "win32")
576
+ return spawnSync("where", [command], { stdio: "ignore" }).status === 0;
577
+ return spawnSync("sh", ["-lc", `command -v ${command}`], { stdio: "ignore" }).status === 0;
578
+ }
579
+ function transcriptText(result) {
580
+ const parsed = typeof result === "string" ? parseResultString(result) : result;
581
+ const text = parsed && typeof parsed.text === "string" ? parsed.text.trim().replace(/\s+/gu, " ") : "";
582
+ return text || undefined;
583
+ }
584
+ function partialTranscriptText(result) {
585
+ const parsed = typeof result === "string" ? parseResultString(result) : result;
586
+ const text = parsed && typeof parsed.partial === "string" ? parsed.partial.trim().replace(/\s+/gu, " ") : "";
587
+ return text || undefined;
588
+ }
589
+ function parseResultString(result) {
590
+ try {
591
+ const parsed = JSON.parse(result);
592
+ return parsed && typeof parsed === "object" ? parsed : undefined;
593
+ }
594
+ catch {
595
+ return undefined;
596
+ }
597
+ }
598
+ function errorMessage(error) {
599
+ return error instanceof Error ? error.message : String(error);
600
+ }
@@ -0,0 +1,40 @@
1
+ import { type AgentSessionRuntime } from "@earendil-works/pi-coding-agent";
2
+ import type { Entry } from "./types.js";
3
+ import { type WorkspaceMutation, type WorkspaceMutationFromToolInput, type WorkspaceMutationPreparation } from "./workspace-undo.js";
4
+ export type AppWorkspaceActionsControllerHost = {
5
+ readonly entries: Entry[];
6
+ runtime(): AgentSessionRuntime | undefined;
7
+ findUserEntry(entryId: string): Extract<Entry, {
8
+ kind: "user";
9
+ }> | undefined;
10
+ touchEntry(entry: Entry): void;
11
+ resetSessionView(): void;
12
+ loadSessionHistory(): void;
13
+ addEntry(entry: Entry): void;
14
+ setInput(value: string): void;
15
+ getInput(): string;
16
+ setStatus(status: string): void;
17
+ setSessionStatus(session: AgentSessionRuntime["session"] | undefined): void;
18
+ showToast(message: string, kind: "success" | "error" | "warning" | "info"): void;
19
+ render(): void;
20
+ isRunning(): boolean;
21
+ };
22
+ export declare class AppWorkspaceActionsController {
23
+ private readonly host;
24
+ private readonly workspaceUndoIndex;
25
+ constructor(host: AppWorkspaceActionsControllerHost);
26
+ prepareWorkspaceMutation(toolName: string, args: unknown): WorkspaceMutationPreparation | undefined;
27
+ workspaceMutationFromToolExecution(input: Omit<WorkspaceMutationFromToolInput, "cwd">): WorkspaceMutation | undefined;
28
+ recordWorkspaceMutationForUserEntry(entryId: string, mutation: WorkspaceMutation): void;
29
+ scheduleUserSessionEntryMetadataSync(): void;
30
+ syncUserSessionEntryMetadata(): void;
31
+ copyUserMessage(entryId: string): void;
32
+ forkFromUserMessage(entryId: string): Promise<void>;
33
+ undoChangesFromUserMessage(entryId: string): Promise<void>;
34
+ private resolveUserSessionEntryId;
35
+ private getIdleRuntimeForAction;
36
+ private workspaceMutationsForSessionEntry;
37
+ private hasWorkspaceMutationsForSessionEntry;
38
+ private persistWorkspaceMutations;
39
+ private workspaceUndoIndexKey;
40
+ }