synabun 2.0.0 → 2.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (507) hide show
  1. package/CHANGELOG.md +97 -0
  2. package/NOTICE +5 -0
  3. package/README.md +2 -1
  4. package/THIRD-PARTY-LICENSES.md +59 -0
  5. package/benchmarks/fixtures/browser/README.md +1 -1
  6. package/benchmarks/fixtures/desktop/README.md +1 -1
  7. package/docs/whatsapp.md +153 -18
  8. package/hooks/claude-code/pre-compact.mjs +11 -0
  9. package/hooks/claude-code/prompt-submit.mjs +60 -184
  10. package/hooks/claude-code/session-start.mjs +73 -16
  11. package/hooks/claude-code/shared.mjs +26 -3
  12. package/hooks/claude-code/stop.mjs +5 -5
  13. package/lib/child-path.js +303 -0
  14. package/lib/claude-hooks.js +2 -1
  15. package/lib/data-home-migration.js +2 -0
  16. package/lib/desktop-app.js +265 -0
  17. package/lib/external-tools.js +7 -3
  18. package/lib/log-redact.js +102 -0
  19. package/lib/packaged-runtime.js +138 -11
  20. package/lib/start-launcher.js +88 -1
  21. package/mcp-server/dist/http.d.ts +3 -1
  22. package/mcp-server/dist/http.d.ts.map +1 -1
  23. package/mcp-server/dist/http.js +15 -4
  24. package/mcp-server/dist/http.js.map +1 -1
  25. package/mcp-server/dist/index.d.ts.map +1 -1
  26. package/mcp-server/dist/index.js +9 -6
  27. package/mcp-server/dist/index.js.map +1 -1
  28. package/mcp-server/dist/services/budget-judgments.d.ts +108 -0
  29. package/mcp-server/dist/services/budget-judgments.d.ts.map +1 -0
  30. package/mcp-server/dist/services/budget-judgments.js +153 -0
  31. package/mcp-server/dist/services/budget-judgments.js.map +1 -0
  32. package/mcp-server/dist/services/codex-config-heal.d.ts +5 -1
  33. package/mcp-server/dist/services/codex-config-heal.d.ts.map +1 -1
  34. package/mcp-server/dist/services/codex-config-heal.js +41 -4
  35. package/mcp-server/dist/services/codex-config-heal.js.map +1 -1
  36. package/mcp-server/dist/services/identity.d.ts +11 -0
  37. package/mcp-server/dist/services/identity.d.ts.map +1 -1
  38. package/mcp-server/dist/services/identity.js +24 -0
  39. package/mcp-server/dist/services/identity.js.map +1 -1
  40. package/mcp-server/dist/services/neural-interface.d.ts +13 -0
  41. package/mcp-server/dist/services/neural-interface.d.ts.map +1 -1
  42. package/mcp-server/dist/services/neural-interface.js +34 -2
  43. package/mcp-server/dist/services/neural-interface.js.map +1 -1
  44. package/mcp-server/dist/services/typesafe-config.d.ts +1 -1
  45. package/mcp-server/dist/services/typesafe-config.d.ts.map +1 -1
  46. package/mcp-server/dist/services/typesafe-config.js +4 -1
  47. package/mcp-server/dist/services/typesafe-config.js.map +1 -1
  48. package/mcp-server/dist/tools/agents.d.ts +10 -7
  49. package/mcp-server/dist/tools/agents.d.ts.map +1 -1
  50. package/mcp-server/dist/tools/agents.js +34 -13
  51. package/mcp-server/dist/tools/agents.js.map +1 -1
  52. package/mcp-server/dist/tools/whatsapp-send-file.d.ts +17 -0
  53. package/mcp-server/dist/tools/whatsapp-send-file.d.ts.map +1 -0
  54. package/mcp-server/dist/tools/whatsapp-send-file.js +44 -0
  55. package/mcp-server/dist/tools/whatsapp-send-file.js.map +1 -0
  56. package/mcp-server/dist/tui.js +2 -1
  57. package/mcp-server/dist/tui.js.map +1 -1
  58. package/mcp-server/dist/version.d.ts +5 -0
  59. package/mcp-server/dist/version.d.ts.map +1 -0
  60. package/mcp-server/dist/version.js +21 -0
  61. package/mcp-server/dist/version.js.map +1 -0
  62. package/mcp-server/package-lock.json +2 -2
  63. package/mcp-server/package.json +1 -3
  64. package/mcp-server/run.mjs +15 -9
  65. package/mcp-server/src/http.ts +18 -3
  66. package/mcp-server/src/index.ts +9 -6
  67. package/mcp-server/src/services/budget-judgments.ts +183 -0
  68. package/mcp-server/src/services/codex-config-heal.ts +35 -4
  69. package/mcp-server/src/services/identity.ts +27 -0
  70. package/mcp-server/src/services/neural-interface.ts +34 -2
  71. package/mcp-server/src/services/typesafe-config.ts +4 -1
  72. package/mcp-server/src/tools/agents.ts +33 -14
  73. package/mcp-server/src/tools/whatsapp-send-file.ts +51 -0
  74. package/mcp-server/src/tui.ts +2 -1
  75. package/mcp-server/src/version.ts +22 -0
  76. package/neural-interface/i18n/en.json +2126 -209
  77. package/neural-interface/i18n/pt-BR.json +2123 -207
  78. package/neural-interface/lib/account-usage.js +163 -0
  79. package/neural-interface/lib/assistant-api.js +316 -57
  80. package/neural-interface/lib/assistant-brains/claude.js +19 -2
  81. package/neural-interface/lib/assistant-brains/codex.js +3 -0
  82. package/neural-interface/lib/assistant-brains/opencode.js +17 -4
  83. package/neural-interface/lib/assistant-budget-planner.js +390 -0
  84. package/neural-interface/lib/assistant-budget-split.js +408 -0
  85. package/neural-interface/lib/assistant-budget.js +94 -95
  86. package/neural-interface/lib/assistant-catalog.js +179 -27
  87. package/neural-interface/lib/assistant-config.js +91 -14
  88. package/neural-interface/lib/assistant-dispatch.js +494 -138
  89. package/neural-interface/lib/assistant-hidden-models.js +393 -66
  90. package/neural-interface/lib/assistant-jev.js +26 -3
  91. package/neural-interface/lib/assistant-memory.js +24 -10
  92. package/neural-interface/lib/assistant-persona.js +73 -12
  93. package/neural-interface/lib/assistant-plan-permissions.js +8 -1
  94. package/neural-interface/lib/assistant-pricing.js +21 -6
  95. package/neural-interface/lib/assistant-route-accounts.js +14 -0
  96. package/neural-interface/lib/assistant-route-gate.js +19 -3
  97. package/neural-interface/lib/assistant-router.js +373 -42
  98. package/neural-interface/lib/assistant-runtime.js +488 -59
  99. package/neural-interface/lib/assistant-task-prompt.js +13 -3
  100. package/neural-interface/lib/assistant-test-density.js +142 -0
  101. package/neural-interface/lib/assistant-user-context-budgets.js +123 -0
  102. package/neural-interface/lib/assistant-user-context.js +908 -0
  103. package/neural-interface/lib/assistant-user-knowledge.js +328 -0
  104. package/neural-interface/lib/assistant-user-learn.js +404 -0
  105. package/neural-interface/lib/assistant-user-threads.js +226 -0
  106. package/neural-interface/lib/assistant-user-writer.js +183 -0
  107. package/neural-interface/lib/augmented-path.js +317 -53
  108. package/neural-interface/lib/browser-background-tab.js +134 -0
  109. package/neural-interface/lib/browser-screenshot.js +678 -61
  110. package/neural-interface/lib/claude-accounts.js +342 -31
  111. package/neural-interface/lib/claude-agent-bridge.js +123 -9
  112. package/neural-interface/lib/claude-executable.js +6 -1
  113. package/neural-interface/lib/claude-model-catalog.js +33 -5
  114. package/neural-interface/lib/claude-panel-auth.js +221 -0
  115. package/neural-interface/lib/claude-profile-api-key.js +62 -0
  116. package/neural-interface/lib/claude-temporary.js +46 -7
  117. package/neural-interface/lib/cli-install-api.js +137 -0
  118. package/neural-interface/lib/cli-install.js +797 -0
  119. package/neural-interface/lib/cli-path.js +130 -0
  120. package/neural-interface/lib/cli-resolver.js +744 -0
  121. package/neural-interface/lib/cli-update-planner.js +143 -7
  122. package/neural-interface/lib/cloudflared/install.js +533 -0
  123. package/neural-interface/lib/cloudflared/manager.js +545 -0
  124. package/neural-interface/lib/cloudflared/pins.js +115 -0
  125. package/neural-interface/lib/cloudflared/pins.json +63 -0
  126. package/neural-interface/lib/cloudflared/tunnel.js +265 -0
  127. package/neural-interface/lib/codex-account-auth.js +178 -0
  128. package/neural-interface/lib/codex-accounts.js +489 -0
  129. package/neural-interface/lib/codex-capabilities.js +2 -1
  130. package/neural-interface/lib/codex-compat-rpc.js +8 -2
  131. package/neural-interface/lib/codex-mcp-approvals.js +5 -1
  132. package/neural-interface/lib/codex-panel-auth.js +62 -0
  133. package/neural-interface/lib/codex-session-settings.js +1 -1
  134. package/neural-interface/lib/codex-settings-schema.js +120 -0
  135. package/neural-interface/lib/desktop/config.js +3 -0
  136. package/neural-interface/lib/editor-completion-endpoint.js +264 -0
  137. package/neural-interface/lib/editor-completion-opencode.js +436 -0
  138. package/neural-interface/lib/editor-completion.js +714 -0
  139. package/neural-interface/lib/editor-config.js +149 -0
  140. package/neural-interface/lib/editor-files-api.js +268 -0
  141. package/neural-interface/lib/editor-git-api.js +134 -0
  142. package/neural-interface/lib/file-explorer-api.js +1039 -0
  143. package/neural-interface/lib/file-explorer-system.js +355 -0
  144. package/neural-interface/lib/file-explorer-trash.ps1 +85 -0
  145. package/neural-interface/lib/file-explorer-watch.js +239 -0
  146. package/neural-interface/lib/git-bash/bzip2.js +339 -0
  147. package/neural-interface/lib/git-bash/claude-settings.js +73 -0
  148. package/neural-interface/lib/git-bash/extract-worker.js +34 -0
  149. package/neural-interface/lib/git-bash/install.js +529 -0
  150. package/neural-interface/lib/git-bash/licenses/COPYING +360 -0
  151. package/neural-interface/lib/git-bash/licenses/LGPL-2.1 +511 -0
  152. package/neural-interface/lib/git-bash/manager.js +268 -0
  153. package/neural-interface/lib/git-bash/pins.js +206 -0
  154. package/neural-interface/lib/git-bash/pins.json +34 -0
  155. package/neural-interface/lib/git-bash/resolver.js +194 -0
  156. package/neural-interface/lib/git-diff-api.js +103 -0
  157. package/neural-interface/lib/git-read.js +234 -0
  158. package/neural-interface/lib/greeting/api.js +89 -0
  159. package/neural-interface/lib/greeting/budgets.js +90 -0
  160. package/neural-interface/lib/greeting/engine.js +461 -0
  161. package/neural-interface/lib/greeting/facts.js +320 -0
  162. package/neural-interface/lib/greeting/sources.js +252 -0
  163. package/neural-interface/lib/greeting/writer.js +139 -0
  164. package/neural-interface/lib/http-guards.js +189 -13
  165. package/neural-interface/lib/install-details.js +145 -0
  166. package/neural-interface/lib/machine-names.js +88 -0
  167. package/neural-interface/lib/mcp-installer.js +14 -2
  168. package/neural-interface/lib/memory-api.js +31 -7
  169. package/neural-interface/lib/native-loop-providers.js +26 -8
  170. package/neural-interface/lib/native-loop-runtime.js +9 -4
  171. package/neural-interface/lib/os-path.js +319 -0
  172. package/neural-interface/lib/plugin-installer.js +4 -2
  173. package/neural-interface/lib/project-storage.js +5 -7
  174. package/neural-interface/lib/provider-panel-api-key-auth.js +92 -0
  175. package/neural-interface/lib/provider-panel-terminal-auth.js +95 -0
  176. package/neural-interface/lib/pty-host/core.js +2 -1
  177. package/neural-interface/lib/pty-host/manager.js +27 -2
  178. package/neural-interface/lib/remote-policy.js +20 -11
  179. package/neural-interface/lib/request-gate.js +589 -0
  180. package/neural-interface/lib/session-title-generator.js +4 -3
  181. package/neural-interface/lib/system-about.js +340 -0
  182. package/neural-interface/lib/system-activity.js +66 -0
  183. package/neural-interface/lib/terminal-env.js +11 -3
  184. package/neural-interface/lib/terminal-path.js +55 -0
  185. package/neural-interface/lib/ui-blob-api.js +108 -0
  186. package/neural-interface/lib/ui-blob-store.js +68 -0
  187. package/neural-interface/lib/virtual-socket.js +12 -1
  188. package/neural-interface/lib/whatsapp/baileys-adapter.js +165 -45
  189. package/neural-interface/lib/whatsapp/bridge.js +78 -34
  190. package/neural-interface/lib/whatsapp/commands.js +13 -14
  191. package/neural-interface/lib/whatsapp/config.js +134 -20
  192. package/neural-interface/lib/whatsapp/fake-baileys.js +99 -14
  193. package/neural-interface/lib/whatsapp/host-core.js +168 -35
  194. package/neural-interface/lib/whatsapp/inbound.js +5 -3
  195. package/neural-interface/lib/whatsapp/local-file.js +524 -0
  196. package/neural-interface/lib/whatsapp/manager.js +92 -32
  197. package/neural-interface/lib/whatsapp/paths.js +11 -1
  198. package/neural-interface/lib/whatsapp/protocol.js +65 -5
  199. package/neural-interface/lib/whatsapp/redact.js +63 -0
  200. package/neural-interface/lib/whatsapp/service.js +343 -91
  201. package/neural-interface/lib/whatsapp/transcription.js +463 -0
  202. package/neural-interface/package-lock.json +701 -2
  203. package/neural-interface/package.json +13 -2
  204. package/neural-interface/public/index.html +2 -0
  205. package/neural-interface/public/index2d.html +2 -0
  206. package/neural-interface/public/install-app.html +9 -6
  207. package/neural-interface/public/offline.html +19 -3
  208. package/neural-interface/public/onboarding.html +107 -2
  209. package/neural-interface/public/shared/account-i18n.js +7 -0
  210. package/neural-interface/public/shared/account-menu.js +539 -0
  211. package/neural-interface/public/shared/account-usage.js +19 -0
  212. package/neural-interface/public/shared/account-view.js +335 -0
  213. package/neural-interface/public/shared/agent-runtime-options.js +50 -14
  214. package/neural-interface/public/shared/assistant/asst-accounts.js +182 -184
  215. package/neural-interface/public/shared/assistant/asst-api.js +32 -2
  216. package/neural-interface/public/shared/assistant/asst-automation.js +286 -0
  217. package/neural-interface/public/shared/assistant/asst-brain-picker.js +430 -81
  218. package/neural-interface/public/shared/assistant/asst-budget.js +259 -303
  219. package/neural-interface/public/shared/assistant/asst-composer.js +11 -1
  220. package/neural-interface/public/shared/assistant/asst-mascot.js +140 -61
  221. package/neural-interface/public/shared/assistant/asst-menu.js +27 -11
  222. package/neural-interface/public/shared/assistant/asst-panel.js +198 -42
  223. package/neural-interface/public/shared/assistant/asst-render.js +197 -23
  224. package/neural-interface/public/shared/assistant/asst-route-models.js +108 -0
  225. package/neural-interface/public/shared/assistant/asst-route.js +95 -343
  226. package/neural-interface/public/shared/assistant/asst-routes-editor.js +534 -0
  227. package/neural-interface/public/shared/assistant/asst-sanitize.js +8 -1
  228. package/neural-interface/public/shared/assistant/asst-sidepanel.js +31 -9
  229. package/neural-interface/public/shared/assistant/asst-slash.js +1 -1
  230. package/neural-interface/public/shared/assistant/asst-state.js +186 -2
  231. package/neural-interface/public/shared/assistant/asst-styles.js +247 -11
  232. package/neural-interface/public/shared/blob-store.js +111 -22
  233. package/neural-interface/public/shared/cdx/cdx-commands.js +4 -1
  234. package/neural-interface/public/shared/cdx/cdx-features.js +22 -14
  235. package/neural-interface/public/shared/cdx/cdx-icons.js +2 -0
  236. package/neural-interface/public/shared/cdx/cdx-panel.js +80 -118
  237. package/neural-interface/public/shared/cdx/cdx-render.js +25 -89
  238. package/neural-interface/public/shared/cdx/cdx-settings.js +231 -0
  239. package/neural-interface/public/shared/cdx/cdx-styles.js +164 -107
  240. package/neural-interface/public/shared/cdx/cdx-tabs.js +348 -668
  241. package/neural-interface/public/shared/cdx/cdx-ws.js +2 -0
  242. package/neural-interface/public/shared/claude-account-view.js +3 -0
  243. package/neural-interface/public/shared/cli-install-view.js +392 -0
  244. package/neural-interface/public/shared/cli-status.js +282 -22
  245. package/neural-interface/public/shared/constants.js +6 -1
  246. package/neural-interface/public/shared/cp/cp-events.js +2 -1
  247. package/neural-interface/public/shared/cp/cp-rehydrate.js +2 -1
  248. package/neural-interface/public/shared/cp/cp-styles.js +61 -0
  249. package/neural-interface/public/shared/desktop-bridge.js +39 -0
  250. package/neural-interface/public/shared/desktop-titlebar-page.js +59 -0
  251. package/neural-interface/public/shared/desktop-titlebar-view.js +122 -0
  252. package/neural-interface/public/shared/desktop-titlebar.js +153 -0
  253. package/neural-interface/public/shared/desktop-update-view.js +462 -0
  254. package/neural-interface/public/shared/editor/editor-ai-logic.js +409 -0
  255. package/neural-interface/public/shared/editor/editor-ai.js +619 -0
  256. package/neural-interface/public/shared/editor/editor-commands.js +212 -0
  257. package/neural-interface/public/shared/editor/editor-compare.js +103 -0
  258. package/neural-interface/public/shared/editor/editor-completion-list.js +172 -0
  259. package/neural-interface/public/shared/editor/editor-doc.js +257 -0
  260. package/neural-interface/public/shared/editor/editor-git-logic.js +131 -0
  261. package/neural-interface/public/shared/editor/editor-git.js +95 -0
  262. package/neural-interface/public/shared/editor/editor-languages.js +156 -0
  263. package/neural-interface/public/shared/editor/editor-lint.js +229 -0
  264. package/neural-interface/public/shared/editor/editor-loader.js +51 -0
  265. package/neural-interface/public/shared/editor/editor-markdown.js +90 -0
  266. package/neural-interface/public/shared/editor/editor-menu.js +233 -0
  267. package/neural-interface/public/shared/editor/editor-minimap.js +371 -0
  268. package/neural-interface/public/shared/editor/editor-palette-logic.js +192 -0
  269. package/neural-interface/public/shared/editor/editor-palette.js +125 -0
  270. package/neural-interface/public/shared/editor/editor-panel-logic.js +288 -0
  271. package/neural-interface/public/shared/editor/editor-panel.js +2099 -0
  272. package/neural-interface/public/shared/editor/editor-prefs.js +224 -0
  273. package/neural-interface/public/shared/editor/editor-safety.js +500 -0
  274. package/neural-interface/public/shared/editor/editor-search.js +352 -0
  275. package/neural-interface/public/shared/editor/editor-statusbar.js +144 -0
  276. package/neural-interface/public/shared/editor/editor-tabs-logic.js +331 -0
  277. package/neural-interface/public/shared/editor/editor-tabs.js +233 -0
  278. package/neural-interface/public/shared/editor/editor-theme.js +244 -0
  279. package/neural-interface/public/shared/editor/editor-view.js +332 -0
  280. package/neural-interface/public/shared/explorer/fx-api.js +216 -0
  281. package/neural-interface/public/shared/explorer/fx-links.js +204 -0
  282. package/neural-interface/public/shared/explorer/fx-logic.js +537 -0
  283. package/neural-interface/public/shared/explorer/fx-main.js +865 -0
  284. package/neural-interface/public/shared/explorer/fx-names.js +87 -0
  285. package/neural-interface/public/shared/explorer/fx-ops.js +370 -0
  286. package/neural-interface/public/shared/explorer/fx-popups.js +490 -0
  287. package/neural-interface/public/shared/explorer/fx-tree.js +790 -0
  288. package/neural-interface/public/shared/file-links.js +339 -0
  289. package/neural-interface/public/shared/git-bash-view.js +145 -0
  290. package/neural-interface/public/shared/greeting/greeting-card.js +178 -0
  291. package/neural-interface/public/shared/greeting/greeting-view.js +148 -0
  292. package/neural-interface/public/shared/html-shell.js +161 -165
  293. package/neural-interface/public/shared/i18n.js +19 -1
  294. package/neural-interface/public/shared/install-details-view.js +86 -0
  295. package/neural-interface/public/shared/ocp-v2/ocp-v2-childpanel.js +4 -0
  296. package/neural-interface/public/shared/ocp-v2/ocp-v2-greeting.js +47 -0
  297. package/neural-interface/public/shared/ocp-v2/ocp-v2-panel.js +131 -17
  298. package/neural-interface/public/shared/ocp-v2/ocp-v2-render.js +7 -1
  299. package/neural-interface/public/shared/ocp-v2/ocp-v2-send.js +22 -0
  300. package/neural-interface/public/shared/ocp-v2/ocp-v2-styles.js +158 -0
  301. package/neural-interface/public/shared/ocp-v2/ocp-v2-ws.js +3 -2
  302. package/neural-interface/public/shared/pwa-install-page.js +32 -2
  303. package/neural-interface/public/shared/pwa-install.css +3 -3
  304. package/neural-interface/public/shared/pwa-install.js +100 -1
  305. package/neural-interface/public/shared/settings/settings-about-pane.js +271 -0
  306. package/neural-interface/public/shared/settings/settings-about.js +254 -0
  307. package/neural-interface/public/shared/settings/settings-code-editor-pane.js +412 -0
  308. package/neural-interface/public/shared/settings/settings-code-editor.js +328 -0
  309. package/neural-interface/public/shared/settings/settings-greeting.js +133 -0
  310. package/neural-interface/public/shared/settings/settings-ia.js +33 -4
  311. package/neural-interface/public/shared/settings/settings-user-context.js +154 -0
  312. package/neural-interface/public/shared/showcase-privacy.js +489 -0
  313. package/neural-interface/public/shared/start-bridge.js +238 -19
  314. package/neural-interface/public/shared/storage.js +30 -3
  315. package/neural-interface/public/shared/styles.css +1710 -770
  316. package/neural-interface/public/shared/synabun-mascot.js +68 -58
  317. package/neural-interface/public/shared/tunnel-view.js +167 -0
  318. package/neural-interface/public/shared/ui-claude-panel.js +369 -229
  319. package/neural-interface/public/shared/ui-cli-banner.js +355 -0
  320. package/neural-interface/public/shared/ui-detail.js +15 -0
  321. package/neural-interface/public/shared/ui-explorer.js +22 -0
  322. package/neural-interface/public/shared/ui-file-explorer.js +481 -2496
  323. package/neural-interface/public/shared/ui-file-links.js +103 -0
  324. package/neural-interface/public/shared/ui-git-bash.js +124 -0
  325. package/neural-interface/public/shared/ui-help.js +26 -0
  326. package/neural-interface/public/shared/ui-invite.js +126 -116
  327. package/neural-interface/public/shared/ui-judgments.js +10 -1
  328. package/neural-interface/public/shared/ui-keybinds.js +4 -0
  329. package/neural-interface/public/shared/ui-loading.js +187 -19
  330. package/neural-interface/public/shared/ui-menubar.js +25 -33
  331. package/neural-interface/public/shared/ui-native-loop-router-state.js +11 -0
  332. package/neural-interface/public/shared/ui-native-loop-router.js +15 -2
  333. package/neural-interface/public/shared/ui-navbar.js +48 -22
  334. package/neural-interface/public/shared/ui-provider-auth.js +104 -0
  335. package/neural-interface/public/shared/ui-provider-terminal-auth.js +223 -0
  336. package/neural-interface/public/shared/ui-sessions.js +9 -3
  337. package/neural-interface/public/shared/ui-settings.js +509 -490
  338. package/neural-interface/public/shared/ui-sidepanel-runtime.js +2 -1
  339. package/neural-interface/public/shared/ui-sidepanel-sessions.js +3 -1
  340. package/neural-interface/public/shared/ui-sync.js +22 -0
  341. package/neural-interface/public/shared/ui-terminal.js +40 -5
  342. package/neural-interface/public/shared/ui-tool-updates.js +5 -0
  343. package/neural-interface/public/shared/ui-tunnel.js +130 -0
  344. package/neural-interface/public/shared/ui-tutorial-steps.js +6 -2
  345. package/neural-interface/public/shared/ui-update.js +594 -5
  346. package/neural-interface/public/shared/ui-whatsapp.js +21 -6
  347. package/neural-interface/public/shared/ui-whiteboard.js +12 -0
  348. package/neural-interface/public/shared/ui-worker-end.js +245 -0
  349. package/neural-interface/public/shared/ui-workspaces.js +41 -27
  350. package/neural-interface/public/shared/whatsapp/wa-view.js +51 -8
  351. package/neural-interface/public/shared/worker-end.js +253 -0
  352. package/neural-interface/public/sw.js +2 -2
  353. package/neural-interface/public/variant/2d/main.js +10 -1
  354. package/neural-interface/public/variant/3d/main.js +10 -1
  355. package/neural-interface/public/vendor/codemirror/chunks/apl-CSDKT72Z.js +1 -0
  356. package/neural-interface/public/vendor/codemirror/chunks/asciiarmor-JYYPU5BM.js +1 -0
  357. package/neural-interface/public/vendor/codemirror/chunks/asn1-NRWCZDA6.js +1 -0
  358. package/neural-interface/public/vendor/codemirror/chunks/asterisk-5OU6D4ZQ.js +1 -0
  359. package/neural-interface/public/vendor/codemirror/chunks/brainfuck-ID4N4SYC.js +1 -0
  360. package/neural-interface/public/vendor/codemirror/chunks/chunk-4RZWGCS2.js +1 -0
  361. package/neural-interface/public/vendor/codemirror/chunks/chunk-ACTJM3JR.js +11 -0
  362. package/neural-interface/public/vendor/codemirror/chunks/chunk-S6BMAXLK.js +1 -0
  363. package/neural-interface/public/vendor/codemirror/chunks/chunk-TO2RDOHQ.js +3 -0
  364. package/neural-interface/public/vendor/codemirror/chunks/chunk-US2GMZZQ.js +13 -0
  365. package/neural-interface/public/vendor/codemirror/chunks/chunk-WYYO5ZAJ.js +1 -0
  366. package/neural-interface/public/vendor/codemirror/chunks/chunk-XALZTDJC.js +1 -0
  367. package/neural-interface/public/vendor/codemirror/chunks/chunk-YRNUTRDV.js +1 -0
  368. package/neural-interface/public/vendor/codemirror/chunks/chunk-Z3QOKH62.js +1 -0
  369. package/neural-interface/public/vendor/codemirror/chunks/clike-OWQBSOGL.js +1 -0
  370. package/neural-interface/public/vendor/codemirror/chunks/clojure-KV75UQWC.js +1 -0
  371. package/neural-interface/public/vendor/codemirror/chunks/cmake-GTEP5Y3C.js +1 -0
  372. package/neural-interface/public/vendor/codemirror/chunks/cobol-WCZ7QEGJ.js +1 -0
  373. package/neural-interface/public/vendor/codemirror/chunks/coffeescript-TGLBOT6B.js +1 -0
  374. package/neural-interface/public/vendor/codemirror/chunks/commonlisp-WVVI432V.js +1 -0
  375. package/neural-interface/public/vendor/codemirror/chunks/crystal-S6R6HLKQ.js +1 -0
  376. package/neural-interface/public/vendor/codemirror/chunks/css-PDA2RINP.js +1 -0
  377. package/neural-interface/public/vendor/codemirror/chunks/cypher-HL5QPL4C.js +1 -0
  378. package/neural-interface/public/vendor/codemirror/chunks/d-HHJH2HAJ.js +1 -0
  379. package/neural-interface/public/vendor/codemirror/chunks/diff-MN3A35BY.js +1 -0
  380. package/neural-interface/public/vendor/codemirror/chunks/dist-25SQLBVS.js +3 -0
  381. package/neural-interface/public/vendor/codemirror/chunks/dist-27ZGGJJS.js +1 -0
  382. package/neural-interface/public/vendor/codemirror/chunks/dist-4E52OJIF.js +1 -0
  383. package/neural-interface/public/vendor/codemirror/chunks/dist-6FT73XDC.js +2 -0
  384. package/neural-interface/public/vendor/codemirror/chunks/dist-BE6YGRMW.js +1 -0
  385. package/neural-interface/public/vendor/codemirror/chunks/dist-CJSGKW2O.js +1 -0
  386. package/neural-interface/public/vendor/codemirror/chunks/dist-CRPH2WLI.js +1 -0
  387. package/neural-interface/public/vendor/codemirror/chunks/dist-CTG7JEQN.js +1 -0
  388. package/neural-interface/public/vendor/codemirror/chunks/dist-I3FEVELX.js +1 -0
  389. package/neural-interface/public/vendor/codemirror/chunks/dist-IM5BBSWZ.js +1 -0
  390. package/neural-interface/public/vendor/codemirror/chunks/dist-KERUKTIF.js +1 -0
  391. package/neural-interface/public/vendor/codemirror/chunks/dist-LXTMWZAM.js +1 -0
  392. package/neural-interface/public/vendor/codemirror/chunks/dist-MABASSET.js +1 -0
  393. package/neural-interface/public/vendor/codemirror/chunks/dist-MJVBUZLL.js +3 -0
  394. package/neural-interface/public/vendor/codemirror/chunks/dist-MNB3WZVU.js +1 -0
  395. package/neural-interface/public/vendor/codemirror/chunks/dist-QYWXOE3U.js +7 -0
  396. package/neural-interface/public/vendor/codemirror/chunks/dist-TEBOFWLZ.js +1 -0
  397. package/neural-interface/public/vendor/codemirror/chunks/dist-UNXFROM3.js +1 -0
  398. package/neural-interface/public/vendor/codemirror/chunks/dist-XL2SLQO6.js +1 -0
  399. package/neural-interface/public/vendor/codemirror/chunks/dist-XO42Y3AP.js +6 -0
  400. package/neural-interface/public/vendor/codemirror/chunks/dist-Y2WWDWJK.js +1 -0
  401. package/neural-interface/public/vendor/codemirror/chunks/dist-YFEZKWMU.js +1 -0
  402. package/neural-interface/public/vendor/codemirror/chunks/dist-ZY7SWQO6.js +1 -0
  403. package/neural-interface/public/vendor/codemirror/chunks/dockerfile-3Y4R4NCH.js +1 -0
  404. package/neural-interface/public/vendor/codemirror/chunks/dtd-5343GJ4P.js +1 -0
  405. package/neural-interface/public/vendor/codemirror/chunks/dylan-FI2CXSW2.js +1 -0
  406. package/neural-interface/public/vendor/codemirror/chunks/ebnf-GNQ77YWA.js +1 -0
  407. package/neural-interface/public/vendor/codemirror/chunks/ecl-MRPUAE2L.js +1 -0
  408. package/neural-interface/public/vendor/codemirror/chunks/eiffel-DZROES27.js +1 -0
  409. package/neural-interface/public/vendor/codemirror/chunks/elm-4KICRFKQ.js +1 -0
  410. package/neural-interface/public/vendor/codemirror/chunks/erlang-3IHYC263.js +1 -0
  411. package/neural-interface/public/vendor/codemirror/chunks/factor-C6D3E5UK.js +1 -0
  412. package/neural-interface/public/vendor/codemirror/chunks/fcl-VYTWUJMI.js +1 -0
  413. package/neural-interface/public/vendor/codemirror/chunks/forth-ZBO2EH5M.js +1 -0
  414. package/neural-interface/public/vendor/codemirror/chunks/fortran-5NDCRWIK.js +1 -0
  415. package/neural-interface/public/vendor/codemirror/chunks/gas-SKRMOXFP.js +1 -0
  416. package/neural-interface/public/vendor/codemirror/chunks/gherkin-L45YXZLW.js +1 -0
  417. package/neural-interface/public/vendor/codemirror/chunks/groovy-GLPTLN44.js +1 -0
  418. package/neural-interface/public/vendor/codemirror/chunks/haskell-E7NF7P4Y.js +1 -0
  419. package/neural-interface/public/vendor/codemirror/chunks/haxe-K2NVDOB6.js +1 -0
  420. package/neural-interface/public/vendor/codemirror/chunks/http-Q6DRQIJB.js +1 -0
  421. package/neural-interface/public/vendor/codemirror/chunks/idl-MZYNJVLN.js +1 -0
  422. package/neural-interface/public/vendor/codemirror/chunks/javascript-6YRYK2HR.js +1 -0
  423. package/neural-interface/public/vendor/codemirror/chunks/julia-HXEL2T5G.js +1 -0
  424. package/neural-interface/public/vendor/codemirror/chunks/livescript-MV7CI2JZ.js +1 -0
  425. package/neural-interface/public/vendor/codemirror/chunks/lua-E36NHOOD.js +1 -0
  426. package/neural-interface/public/vendor/codemirror/chunks/mathematica-3XOZZCMC.js +1 -0
  427. package/neural-interface/public/vendor/codemirror/chunks/mbox-ODYGFKS7.js +1 -0
  428. package/neural-interface/public/vendor/codemirror/chunks/mirc-WB43AWF5.js +1 -0
  429. package/neural-interface/public/vendor/codemirror/chunks/mllike-ZT6ET7ZH.js +1 -0
  430. package/neural-interface/public/vendor/codemirror/chunks/modelica-LLMZPFGA.js +1 -0
  431. package/neural-interface/public/vendor/codemirror/chunks/mscgen-2OPNNYFH.js +1 -0
  432. package/neural-interface/public/vendor/codemirror/chunks/mumps-6P3HWJH6.js +1 -0
  433. package/neural-interface/public/vendor/codemirror/chunks/nginx-TCGKQTRW.js +1 -0
  434. package/neural-interface/public/vendor/codemirror/chunks/nsis-ATIGIXTJ.js +1 -0
  435. package/neural-interface/public/vendor/codemirror/chunks/ntriples-5PLBI5OV.js +1 -0
  436. package/neural-interface/public/vendor/codemirror/chunks/octave-QF2S3NL6.js +1 -0
  437. package/neural-interface/public/vendor/codemirror/chunks/oz-JFIVFFH2.js +1 -0
  438. package/neural-interface/public/vendor/codemirror/chunks/pascal-JG6SW76V.js +1 -0
  439. package/neural-interface/public/vendor/codemirror/chunks/perl-4B3IWVVO.js +1 -0
  440. package/neural-interface/public/vendor/codemirror/chunks/pig-ABEBH4MI.js +1 -0
  441. package/neural-interface/public/vendor/codemirror/chunks/powershell-H32XE7TL.js +1 -0
  442. package/neural-interface/public/vendor/codemirror/chunks/properties-NN644MMA.js +1 -0
  443. package/neural-interface/public/vendor/codemirror/chunks/protobuf-YKWQK2J3.js +1 -0
  444. package/neural-interface/public/vendor/codemirror/chunks/pug-RIYXEKFW.js +1 -0
  445. package/neural-interface/public/vendor/codemirror/chunks/puppet-JZQ5WPEV.js +1 -0
  446. package/neural-interface/public/vendor/codemirror/chunks/python-EBCGGHAC.js +1 -0
  447. package/neural-interface/public/vendor/codemirror/chunks/q-5UMH2YQY.js +1 -0
  448. package/neural-interface/public/vendor/codemirror/chunks/r-7XMGG453.js +1 -0
  449. package/neural-interface/public/vendor/codemirror/chunks/rpm-IEV7TSLR.js +1 -0
  450. package/neural-interface/public/vendor/codemirror/chunks/ruby-T4SPFPNM.js +1 -0
  451. package/neural-interface/public/vendor/codemirror/chunks/sas-GEDX67ET.js +1 -0
  452. package/neural-interface/public/vendor/codemirror/chunks/scheme-FTLOWKPC.js +1 -0
  453. package/neural-interface/public/vendor/codemirror/chunks/shell-HUFRKFSJ.js +1 -0
  454. package/neural-interface/public/vendor/codemirror/chunks/sieve-P5QUDVYO.js +1 -0
  455. package/neural-interface/public/vendor/codemirror/chunks/smalltalk-2SORJNQI.js +1 -0
  456. package/neural-interface/public/vendor/codemirror/chunks/solr-M22TGAR5.js +1 -0
  457. package/neural-interface/public/vendor/codemirror/chunks/sparql-4M3KL752.js +1 -0
  458. package/neural-interface/public/vendor/codemirror/chunks/spreadsheet-3K23LA4N.js +1 -0
  459. package/neural-interface/public/vendor/codemirror/chunks/sql-VHRFMUBI.js +1 -0
  460. package/neural-interface/public/vendor/codemirror/chunks/stex-QZDAQUY2.js +1 -0
  461. package/neural-interface/public/vendor/codemirror/chunks/stylus-7ZDKAKBD.js +1 -0
  462. package/neural-interface/public/vendor/codemirror/chunks/swift-WCLCLGMR.js +1 -0
  463. package/neural-interface/public/vendor/codemirror/chunks/tcl-JLMU6WOK.js +1 -0
  464. package/neural-interface/public/vendor/codemirror/chunks/textile-4CHDKZ4T.js +1 -0
  465. package/neural-interface/public/vendor/codemirror/chunks/tiddlywiki-DKMCZZQ4.js +1 -0
  466. package/neural-interface/public/vendor/codemirror/chunks/tiki-F4JIG36Q.js +1 -0
  467. package/neural-interface/public/vendor/codemirror/chunks/toml-BHMHTIM2.js +1 -0
  468. package/neural-interface/public/vendor/codemirror/chunks/troff-YQ2KV5NT.js +1 -0
  469. package/neural-interface/public/vendor/codemirror/chunks/ttcn-ZHRCVFJY.js +1 -0
  470. package/neural-interface/public/vendor/codemirror/chunks/ttcn-cfg-KJOVTY4X.js +1 -0
  471. package/neural-interface/public/vendor/codemirror/chunks/turtle-535P5N6I.js +1 -0
  472. package/neural-interface/public/vendor/codemirror/chunks/vb-76UMQHOT.js +1 -0
  473. package/neural-interface/public/vendor/codemirror/chunks/vbscript-CGNDTK6Z.js +1 -0
  474. package/neural-interface/public/vendor/codemirror/chunks/velocity-VSJDO5T5.js +1 -0
  475. package/neural-interface/public/vendor/codemirror/chunks/verilog-4T6ETXIP.js +1 -0
  476. package/neural-interface/public/vendor/codemirror/chunks/vhdl-T7FNAXUN.js +1 -0
  477. package/neural-interface/public/vendor/codemirror/chunks/webidl-P6MJSJ6J.js +1 -0
  478. package/neural-interface/public/vendor/codemirror/chunks/xquery-UOVILRGN.js +1 -0
  479. package/neural-interface/public/vendor/codemirror/chunks/yacas-CV2APROL.js +1 -0
  480. package/neural-interface/public/vendor/codemirror/chunks/z80-3KFNVM4M.js +1 -0
  481. package/neural-interface/public/vendor/codemirror/codemirror-6.43.14-75f05e67.min.js +2 -0
  482. package/neural-interface/public/vendor/codemirror/manifest.json +60 -0
  483. package/neural-interface/scripts/build-vendor.mjs +78 -2
  484. package/neural-interface/scripts/vendor-codemirror-entry.js +121 -0
  485. package/neural-interface/server.js +2085 -1629
  486. package/neural-interface/templates/rulesets/README.md +1 -1
  487. package/package.json +5 -8
  488. package/setup.js +53 -15
  489. package/benchmarks/browser-live-results.json +0 -79
  490. package/benchmarks/browser-v2-results.json +0 -258
  491. package/neural-interface/lib/codex-capabilities.d.ts +0 -41
  492. package/neural-interface/public/category-logos/claude.svg +0 -1
  493. package/neural-interface/public/category-logos/gemini-color.svg +0 -1
  494. package/neural-interface/public/category-logos/openai.svg +0 -1
  495. package/neural-interface/public/category-logos/synabun.png +0 -0
  496. package/neural-interface/public/claude.svg +0 -1
  497. package/neural-interface/public/gallery.svg +0 -6
  498. package/neural-interface/public/leonardoai.svg +0 -1
  499. package/neural-interface/public/mcp.svg +0 -4
  500. package/neural-interface/public/opencode-logo-dark-square.svg +0 -1
  501. package/neural-interface/public/pin-svgrepo-com.svg +0 -25
  502. package/neural-interface/public/sessionicon.svg +0 -8
  503. package/neural-interface/public/toolbar-album.svg +0 -8
  504. package/neural-interface/public/toolbar-question.svg +0 -6
  505. package/neural-interface/public/toolbar-sessions.svg +0 -6
  506. package/neural-interface/scripts/codex-protocol-fixture.mjs +0 -83
  507. package/skills/synabun/synabunicon.png +0 -0
@@ -0,0 +1,92 @@
1
+ const API_KEY_ERRORS = {
2
+ invalid_key: { status: 400, message: "That doesn't look like an API key for this provider." },
3
+ oauth_token: { status: 400, message: "That's a Claude sign-in token. Use Sign in with Claude." },
4
+ key_rejected: { status: 401, message: 'The provider rejected that key.' },
5
+ account_unavailable: { status: 404, message: 'This account is no longer available. Select an account again.' },
6
+ account_busy: { status: 409, message: 'Finish sign-in or reconnect this account and try again.' },
7
+ verification_unreachable: { status: 503, message: "Couldn't reach {vendor} to check the key. Try again." },
8
+ verification_unavailable: { status: 503, message: "{vendor} couldn't check the key. Try again shortly." },
9
+ storage_failed: { status: 500, message: "Couldn't save the key for this account." },
10
+ };
11
+ // `provider` names the vendor in the two verification messages (Anthropic for Claude, OpenAI for Codex).
12
+ export function providerApiKeyError(code, provider = 'claude') {
13
+ const { status, message } = Object.hasOwn(API_KEY_ERRORS, code) ? API_KEY_ERRORS[code] : API_KEY_ERRORS.storage_failed;
14
+ return Object.assign(new Error(message.replace('{vendor}', provider === 'codex' ? 'OpenAI' : 'Anthropic')), { status, code });
15
+ }
16
+
17
+ // Return the normalized value: clipboard padding is not part of a credential.
18
+ export function validateProviderApiKey(provider, key) {
19
+ if (!['claude', 'codex'].includes(provider)) throw Object.assign(new Error('Unknown provider'), { status: 404 });
20
+ if (typeof key !== 'string' || key.length > 4096) throw providerApiKeyError('invalid_key');
21
+ key = key.trim();
22
+ // setup-token produces an OAuth token, not an Anthropic API key. Never send
23
+ // it to x-api-key or persist it under the API-key authentication method.
24
+ if (provider === 'claude' && key.startsWith('sk-ant-oat01-')) throw providerApiKeyError('oauth_token');
25
+ const pattern = provider === 'claude' ? /^sk-ant-[A-Za-z0-9_-]{16,}$/ : /^sk-(?!ant-)[A-Za-z0-9_-]{16,}$/;
26
+ if (!pattern.test(key)) throw providerApiKeyError('invalid_key');
27
+ return key;
28
+ }
29
+
30
+ // Defense in depth for native diagnostics/events. Never forward credential fields.
31
+ export function redactProviderSecrets(value) {
32
+ if (typeof value === 'string') return value.replace(/sk-[A-Za-z0-9_-]{16,}/g, '[redacted]');
33
+ if (Array.isArray(value)) return value.map(redactProviderSecrets);
34
+ if (value && typeof value === 'object') return Object.fromEntries(Object.entries(value)
35
+ .filter(([key]) => !/^(api_?key|access_?token|refresh_?token|id_?token|authorization)$/i.test(key))
36
+ .map(([key, item]) => [key, redactProviderSecrets(item)]));
37
+ return value;
38
+ }
39
+
40
+ export function registerProviderPanelApiKeyAuthRoutes(app, { guard, claude, codex }) {
41
+ app.post('/api/provider-panel-auth/:provider/:accountId/api-key', guard, async (req, res) => {
42
+ res.setHeader('Cache-Control', 'no-store');
43
+ const { provider, accountId } = req.params;
44
+ let key = req.body?.key;
45
+ // Express's parsed request body must not outlive this handler with a secret.
46
+ if (req.body) delete req.body.key;
47
+ try {
48
+ key = validateProviderApiKey(provider, key);
49
+ if (!/^[a-z0-9-]{1,64}$/.test(accountId)) throw providerApiKeyError('account_unavailable');
50
+ // Codex keys are kept by SynaBun per account too (lib/codex-accounts.js): an older
51
+ // page may still send the `target` of its live connection, which is not needed now.
52
+ if (provider === 'claude') await claude(accountId, key);
53
+ else await codex(accountId, key);
54
+ res.json({ ok: true });
55
+ } catch (error) {
56
+ // Never serialize provider exceptions; a native error may echo its input.
57
+ const fallback = { 400: 'invalid_key', 401: 'key_rejected', 404: 'account_unavailable', 409: 'account_busy', 503: 'verification_unavailable' }[error.status] || 'storage_failed';
58
+ const code = Object.hasOwn(API_KEY_ERRORS, error.code) ? error.code : fallback;
59
+ const safe = providerApiKeyError(code, provider);
60
+ res.status(safe.status).json({ code, error: safe.message });
61
+ } finally { key = null; }
62
+ });
63
+ }
64
+
65
+ // Install immediately after the global JSON parser: its SyntaxError may contain
66
+ // a fragment of the secret-bearing body. Never pass that error to Express logs.
67
+ export function providerApiKeyBodyError(error, req, res, next) {
68
+ if (req.method !== 'POST' || !/^\/api\/provider-panel-auth\/[^/]+\/[^/]+\/api-key(?:\?|$)/.test(req.originalUrl || req.url || '')) return next(error);
69
+ delete error.body;
70
+ req.body = undefined;
71
+ res.setHeader('Cache-Control', 'no-store');
72
+ return res.status(error.status === 413 ? 413 : 400).json({ code: 'invalid_key', error: API_KEY_ERRORS.invalid_key.message });
73
+ }
74
+
75
+ // Native stderr arrives in arbitrary chunks. Redact complete lines so a split
76
+ // credential cannot leave an unmasked suffix; omit unterminated/oversized lines.
77
+ export function providerDiagnosticSink(write, maxChars = 65536) {
78
+ let buffer = '', dropping = false;
79
+ return chunk => {
80
+ const parts = String(chunk).split(/\r?\n/);
81
+ for (let i = 0; i < parts.length; i++) {
82
+ if (!dropping) {
83
+ buffer += parts[i];
84
+ if (buffer.length > maxChars) { buffer = ''; dropping = true; }
85
+ }
86
+ if (i < parts.length - 1) {
87
+ if (!dropping && buffer.trim()) write(redactProviderSecrets(buffer.trim()));
88
+ buffer = ''; dropping = false;
89
+ }
90
+ }
91
+ };
92
+ }
@@ -0,0 +1,95 @@
1
+ import { randomBytes } from 'node:crypto';
2
+ import { isAbsolute } from 'node:path';
3
+ import { claudeAuthEnv } from './claude-panel-auth.js';
4
+ import { applyCodexLaunchEnv } from './codex-accounts.js';
5
+
6
+ // Only server-owned account records and resolved executables enter the PTY.
7
+ export function providerLoginSpec({ provider, accountId, claudeAccounts, codexAccount, claudeExecutable, codexExecutable, env }) {
8
+ if (!['claude', 'codex'].includes(provider) || typeof accountId !== 'string' || !/^[a-z0-9-]{1,64}$/.test(accountId)) {
9
+ throw Object.assign(new Error('Unknown provider account'), { status: 404 });
10
+ }
11
+ const account = provider === 'claude' ? claudeAccounts.profileFor(accountId) : codexAccount(accountId);
12
+ if (!account || account.id !== accountId) throw Object.assign(new Error('Unknown provider account'), { status: 404 });
13
+ const file = provider === 'claude' ? claudeExecutable()?.path : codexExecutable();
14
+ if (!file || !isAbsolute(file) || /\.(cmd|bat)$/i.test(file)) {
15
+ throw new Error(`Could not resolve the ${provider === 'claude' ? 'Claude' : 'Codex'} executable. Check its installation.`);
16
+ }
17
+ let baseEnv = { ...env };
18
+ if (provider === 'codex') {
19
+ // Every Codex account, Default too: `codex login` writes to that account's CODEX_HOME, with no
20
+ // inherited OpenAI/Codex credential around it (lib/codex-accounts.js CODEX_CREDENTIAL_ENV).
21
+ if (!account.home) throw new Error('This Codex account has no home folder.');
22
+ baseEnv = applyCodexLaunchEnv(baseEnv, { env: { CODEX_HOME: account.home } });
23
+ } else if (accountId !== 'default') {
24
+ if (!account.home) throw new Error('This Claude account has no isolated home.');
25
+ baseEnv = claudeAuthEnv(baseEnv, { CLAUDE_CONFIG_DIR: account.home });
26
+ }
27
+ const args = provider === 'claude' ? ['auth', 'login', '--claudeai'] : ['login'];
28
+ return { launch: /\.[cm]?js$/i.test(file) ? { shell: process.execPath, args: [file, ...args] } : { shell: file, args }, baseEnv };
29
+ }
30
+
31
+ // `onSettled(provider, id, status)` (optional): told once when a sign-in terminal ends ('exited' when the
32
+ // CLI exited 0, else 'error'), so the host can ask the provider what it now says about the account.
33
+ export function createProviderPanelTerminalAuth({ resolveSpec, createSession, whenSpawned, killSession, timeoutMs = 10 * 60_000, onSettled = null }) {
34
+ const operations = new Map();
35
+ const key = (provider, id) => `${provider}:${id}`;
36
+ const snapshot = op => ({ sessionId: op.sessionId, status: op.status, error: op.error || '' });
37
+ function read(provider, id) {
38
+ resolveSpec(provider, id); // Validate deleted accounts and unsupported providers on reads too.
39
+ const op = operations.get(key(provider, id));
40
+ return op ? snapshot(op) : { status: 'idle' };
41
+ }
42
+ async function start(provider, id) {
43
+ const spec = resolveSpec(provider, id);
44
+ const existing = operations.get(key(provider, id));
45
+ if (existing && ['starting', 'pending'].includes(existing.status)) { await existing.ready; return snapshot(existing); }
46
+ const op = { sessionId: randomBytes(16).toString('hex'), status: 'starting' };
47
+ operations.set(key(provider, id), op);
48
+ let timer;
49
+ const finish = (status, error = '') => {
50
+ if (!['starting', 'pending'].includes(op.status)) return;
51
+ clearTimeout(timer); op.status = status; op.error = error;
52
+ if (typeof onSettled === 'function') Promise.resolve().then(() => onSettled(provider, id, status)).catch(() => {});
53
+ };
54
+ op.ready = (async () => {
55
+ try {
56
+ createSession('shell', 120, 30, undefined, { ...spec, sessionId: op.sessionId,
57
+ onExit: ({ exitCode }) => finish(exitCode === 0 ? 'exited' : 'error', exitCode === 0 ? '' : 'Sign-in failed. Try again.'),
58
+ onClosed: () => finish('error', 'Sign-in terminal closed. Try again.'),
59
+ });
60
+ let spawnTimer;
61
+ try {
62
+ await Promise.race([whenSpawned(op.sessionId), new Promise((_, reject) => {
63
+ spawnTimer = setTimeout(() => reject(new Error('Terminal host did not respond')), 15000);
64
+ })]);
65
+ } finally { clearTimeout(spawnTimer); }
66
+ if (op.status === 'starting') {
67
+ op.status = 'pending';
68
+ timer = setTimeout(() => { finish('error', 'Sign-in timed out. Try again.'); killSession(op.sessionId); }, timeoutMs);
69
+ timer.unref?.();
70
+ }
71
+ } catch {
72
+ finish('error', 'Could not open the sign-in terminal. Try again.');
73
+ killSession(op.sessionId);
74
+ }
75
+ })();
76
+ await op.ready;
77
+ return snapshot(op);
78
+ }
79
+ return { start, read };
80
+ }
81
+
82
+ export function registerProviderPanelTerminalAuthRoutes(app, { guard, auth }) {
83
+ const route = '/api/provider-panel-auth/:provider/:id/terminal';
84
+ app.get(route, guard, (req, res) => {
85
+ res.setHeader('Cache-Control', 'no-store');
86
+ try { res.json({ terminal: auth.read(req.params.provider, req.params.id) }); }
87
+ catch (error) { res.status(error.status || 500).json({ error: error.message }); }
88
+ });
89
+ app.post(route, guard, async (req, res) => {
90
+ res.setHeader('Cache-Control', 'no-store');
91
+ if (Object.keys(req.body || {}).length) return res.status(400).json({ error: 'Only provider and account selection are accepted.' });
92
+ try { res.json({ terminal: await auth.start(req.params.provider, req.params.id) }); }
93
+ catch (error) { res.status(error.status || 500).json({ error: error.message }); }
94
+ });
95
+ }
@@ -18,6 +18,7 @@ import { createTerminalModel } from './snapshot.js';
18
18
  import { evaluateFlow } from './flow.js';
19
19
  import { EV, OP, HOST_DEFAULTS } from './protocol.js';
20
20
  import { createEventLoopMonitor } from '../event-loop-monitor.js';
21
+ import { withPathEnv } from '../augmented-path.js';
21
22
 
22
23
  const IS_WIN = process.platform === 'win32';
23
24
  const IS_LINUX = process.platform === 'linux';
@@ -74,7 +75,7 @@ export function createPtyHostCore({ send, config = {}, pty: injectedPty = null }
74
75
  }
75
76
  const cols = clampInt(spec.cols, 2, 1000) || 120;
76
77
  const rows = clampInt(spec.rows, 1, 500) || 30;
77
- const env = { ...(spec.env || {}) };
78
+ const env = withPathEnv(spec.env || {});
78
79
  for (const k of Object.keys(env)) if (k.startsWith('NODE_CHANNEL_') || k === 'NODE_UNIQUE_ID') delete env[k];
79
80
 
80
81
  let file = spec.file;
@@ -38,6 +38,7 @@ export function createPtyHostManager({
38
38
  } = {}) {
39
39
  const handlers = new Map(); // id → { onSpawned, onTap, onResized, onClients, onExit }
40
40
  const spawnWaiters = new Map(); // id → waiter
41
+ const preparing = new Map(); // id → operations queued while PATH is read
41
42
  const requests = new Map(); // reqId → { resolve, reject, timer }
42
43
  let reqSeq = 0;
43
44
  let child = null;
@@ -158,6 +159,7 @@ export function createPtyHostManager({
158
159
  heldSockets = [];
159
160
  queue = [];
160
161
  const lost = [...handlers.entries()];
162
+ preparing.clear();
161
163
  handlers.clear();
162
164
  for (const [id] of lost) settleSpawn(id, new Error('pty-host exited'));
163
165
  spawnWaiters.clear();
@@ -175,6 +177,13 @@ export function createPtyHostManager({
175
177
 
176
178
  // ── Main → host ──
177
179
  function sendOp(msg) {
180
+ if (preparing.has(msg.id) && msg.op !== OP.SPAWN) {
181
+ if (msg.op === OP.KILL) {
182
+ preparing.delete(msg.id);
183
+ dispatch({ t: EV.SPAWN_ERROR, id: msg.id, message: 'Terminal closed before it started' });
184
+ } else preparing.get(msg.id).push(msg);
185
+ return;
186
+ }
178
187
  if (mode === 'inproc') {
179
188
  if (!core || !ready) { queue.push(msg); return; }
180
189
  core.handleMessage(msg);
@@ -190,11 +199,23 @@ export function createPtyHostManager({
190
199
  for (const msg of q) sendOp(msg);
191
200
  }
192
201
 
193
- function spawn(spec, h = {}) {
202
+ function spawn(spec, h = {}, prepare = null) {
194
203
  handlers.set(spec.id, h);
195
204
  const w = makeWaiter();
196
205
  spawnWaiters.set(spec.id, w);
197
- sendOp({ op: OP.SPAWN, ...spec });
206
+ if (prepare) {
207
+ const pending = [];
208
+ preparing.set(spec.id, pending);
209
+ Promise.resolve().then(prepare).then(prepared => {
210
+ if (shuttingDown || !handlers.has(spec.id) || preparing.get(spec.id) !== pending) return;
211
+ preparing.delete(spec.id);
212
+ sendOp({ op: OP.SPAWN, ...spec, ...prepared });
213
+ for (const message of pending) sendOp(message);
214
+ }).catch(error => {
215
+ preparing.delete(spec.id);
216
+ dispatch({ t: EV.SPAWN_ERROR, id: spec.id, message: error.message });
217
+ });
218
+ } else sendOp({ op: OP.SPAWN, ...spec });
198
219
  return w.promise;
199
220
  }
200
221
 
@@ -315,6 +336,8 @@ export function createPtyHostManager({
315
336
 
316
337
  async function shutdown({ timeoutMs = 1500 } = {}) {
317
338
  shuttingDown = true;
339
+ for (const id of preparing.keys()) settleSpawn(id, new Error('Terminal host is shutting down'));
340
+ preparing.clear();
318
341
  if (restartTimer) { clearTimeout(restartTimer); restartTimer = null; }
319
342
  if (mode === 'inproc') {
320
343
  try { core?.shutdownAll(); } catch {}
@@ -332,6 +355,8 @@ export function createPtyHostManager({
332
355
 
333
356
  function killNow() {
334
357
  shuttingDown = true;
358
+ for (const id of preparing.keys()) settleSpawn(id, new Error('Terminal host is shutting down'));
359
+ preparing.clear();
335
360
  if (restartTimer) { clearTimeout(restartTimer); restartTimer = null; }
336
361
  try { child?.kill('SIGTERM'); } catch {}
337
362
  try { core?.shutdownAll(); } catch {}
@@ -10,7 +10,9 @@
10
10
  // refuse, user allow rules included; routing always asks (one
11
11
  // route card per task is the task's approval); workers get no
12
12
  // computer, no "user-authorized-full" and a registered cwd.
13
- // autonomous — the modes as configured, until autonomousUntil; then ask.
13
+ // autonomous — the modes as configured. On WhatsApp it stays until the owner
14
+ // lowers it in Settings; any other channel only until its
15
+ // autonomousUntil, then ask.
14
16
  // Ask and Autonomous hold only on a Claude brain: its in-process PreToolUse
15
17
  // hook sees every call with its arguments. A Codex or OpenCode brain runs
16
18
  // ordinary commands inside its own sandbox / permissions without asking, so a
@@ -25,7 +27,7 @@
25
27
  //
26
28
  // Computer use (the Assistant's own computer tools) is off unless the owner
27
29
  // turned on its switch at this computer (the policy's `computerUse`), and then
28
- // only as remoteComputerUse says: unasked while Autonomous is active, after
30
+ // only as remoteComputerUse says: unasked while Autonomous is on, after
29
31
  // one yes per turn at Ask, never at Read-only, while paused or on a Codex /
30
32
  // OpenCode brain. That function is the one place that decides; the runtime,
31
33
  // the brain's hook, the desktop gate, the persona and the panel all ask it.
@@ -81,16 +83,17 @@ export class RemotePolicyError extends Error {
81
83
 
82
84
  /**
83
85
  * The level that applies now: null without a policy. Paused reads as
84
- * read-only, an expired (or never armed) autonomous as ask, a turn whose
85
- * prompt carried untrusted content is capped at ask, and a session whose brain
86
- * cannot hold Ask/Autonomous (`provider`, else the policy's brainProvider:
87
- * Codex, OpenCode) is read-only.
86
+ * read-only, a turn whose prompt carried untrusted content is capped at ask,
87
+ * and a session whose brain cannot hold Ask/Autonomous (`provider`, else the
88
+ * policy's brainProvider: Codex, OpenCode) is read-only. Autonomous on
89
+ * WhatsApp has no time limit (it stays until the owner lowers it); on any
90
+ * other channel an expired (or never armed) autonomousUntil reads as ask.
88
91
  */
89
92
  export function effectiveLevel(policy, { untrusted = false, now = Date.now(), provider = null } = {}) {
90
93
  if (!policy) return null;
91
94
  let level = normalizeLevel(policy.level);
92
95
  if (policy.paused === true) level = 'read-only';
93
- if (level === 'autonomous') {
96
+ if (level === 'autonomous' && policy.channel !== 'whatsapp') {
94
97
  const until = toMs(policy.autonomousUntil);
95
98
  if (!(until > now)) level = 'ask';
96
99
  }
@@ -139,7 +142,8 @@ export const COMPUTER_REASONS = Object.freeze({
139
142
  * read_only the Read-only level (or a session nobody registered since a restart)
140
143
  * unsupported, setup computer use is not available, or not set up, on this machine (`desktop`)
141
144
  * ask ask the Ask level: one yes per turn turns it on for that turn
142
- * autonomous_expired Autonomous is configured but its window is closed (or was never armed)
145
+ * autonomous_expired Autonomous is configured but its autonomousUntil passed (or was never set): never
146
+ * on WhatsApp, where Autonomous has no time limit
143
147
  * untrusted Autonomous is active, but this turn carries content the owner did not write
144
148
  * allowed autonomous Autonomous is active: the computer tools run unasked
145
149
  * `desktop`: { supported, ready } of the desktop service (omitted: not checked).
@@ -288,17 +292,20 @@ function defaultDataHome(env = process.env) {
288
292
  if (osPlatform() === 'win32' && env.APPDATA) return resolve(env.APPDATA, 'synabun');
289
293
  return resolve(homedir(), '.synabun');
290
294
  }
291
- /** Every place the WhatsApp Link may keep its session and connector (lib/whatsapp/paths.js), the refused override too. */
295
+ /**
296
+ * Every place the WhatsApp Link may keep its session and connector (lib/whatsapp/paths.js), the refused
297
+ * override too, and the voice-note folder whose programs the WhatsApp host runs (transcriptionDir).
298
+ */
292
299
  function whatsappLocations(dataHome, env, platform) {
293
300
  const out = [];
294
301
  try {
295
302
  const wa = resolveWhatsAppPaths({ dataHome, env, platform });
296
- out.push(wa.waHome, wa.defaultWaHome, wa.runtimeDir, wa.stagingDir);
303
+ out.push(wa.waHome, wa.defaultWaHome, wa.runtimeDir, wa.stagingDir, wa.transcriptionDir);
297
304
  } catch {}
298
305
  const override = typeof env.SYNABUN_WHATSAPP_HOME === 'string' ? env.SYNABUN_WHATSAPP_HOME.trim() : '';
299
306
  if (override) out.push(resolve(override));
300
307
  if (env.LOCALAPPDATA) out.push(resolve(env.LOCALAPPDATA, 'synabun', 'whatsapp'));
301
- out.push(resolve(dataHome, 'whatsapp'), resolve(dataHome, 'runtime', 'whatsapp'));
308
+ out.push(resolve(dataHome, 'whatsapp'), resolve(dataHome, 'runtime', 'whatsapp'), resolve(dataHome, 'runtime', 'whatsapp-transcription'));
302
309
  return [...new Set(out.filter(Boolean))];
303
310
  }
304
311
  const slash = (value) => String(value || '').replace(/\\/g, '/').replace(/\/{2,}/g, '/').toLowerCase();
@@ -359,6 +366,8 @@ const DENIED_PATTERNS = [
359
366
  { re: /\/etc\/cron|\/var\/at\/tabs|\/usr\/lib\/cron|\/var\/spool\/cron/, why: 'crontab' },
360
367
  { re: /\/api\/whatsapp\b/, why: 'the WhatsApp link' },
361
368
  { re: /(?:^|[^a-z0-9_-])runtime\/whatsapp\b/, why: 'the WhatsApp link' },
369
+ // The voice-note folder by name, wherever it sits (a relative path, a moved home): the WhatsApp host runs the programs in it.
370
+ { re: /(?:^|[^a-z0-9_.-])whatsapp-transcription(?=$|[^a-z0-9_-])/, why: 'the WhatsApp link (voice-note programs)' },
362
371
  { re: /(?:^|[^a-z0-9_-])\.?synabun\/whatsapp\b/, why: 'the WhatsApp link' },
363
372
  // The session store by name, wherever it sits (a relative path, a moved home): state.db and its -wal/-shm/-journal.
364
373
  { re: /(?:^|[^a-z0-9_.-])state\.db(?:-(?:wal|shm|journal))?(?=$|[^a-z0-9_.-])/, why: 'the WhatsApp login (state.db)' },