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
@@ -73,6 +73,74 @@ export function blobDelete(ns, id) {
73
73
  d.prepare('DELETE FROM ui_blobs WHERE ns = ? AND id = ?').run(ns, id);
74
74
  }
75
75
 
76
+ // ── Which of a page's requests for one entry is the newer ──
77
+ // A page numbers what it asks for (public/shared/blob-store.js: `rev`, counted up, and `writer`, the page's own
78
+ // id). The requests it sends while it is being left (a keepalive fetch, a beacon) reach the server in any order:
79
+ // a delete may arrive before the write it was meant to follow, an older write after a newer one. So what the
80
+ // store last did for a page is remembered here, entry by entry, a deletion too, and a request of that page with
81
+ // a number that is not higher is not applied.
82
+ //
83
+ // Remembered per namespace, entry and page. A request of another page, and one without a number, is applied as
84
+ // it arrives, as it always was, and takes nothing away from what is remembered: a page that deleted an entry
85
+ // with its request 2 does not get its request 1 applied because somebody else wrote in between. And remembered
86
+ // only once the store has done what was asked (`stale()` asks, `applied()` records): a write that failed has used
87
+ // up no number, and is applied when the page sends it again.
88
+ //
89
+ // Kept in memory for a quarter of an hour, far longer than a request of a page that is gone can still be on its
90
+ // way, and for at most BLOB_ORDER_MAX marks (those applied longest ago go first); a restart forgets all of it.
91
+ export const BLOB_ORDER_TTL_MS = 15 * 60_000;
92
+ const BLOB_ORDER_MAX = 5000;
93
+ const WRITER_RE = /^[A-Za-z0-9_-]{1,64}$/;
94
+
95
+ /** The revision a request carries in its query (`?rev=<n>&writer=<id>`), or null when it carries none that counts. */
96
+ export function blobRevision(query) {
97
+ const rev = Number(typeof query?.rev === 'string' ? query.rev : NaN);
98
+ const writer = query?.writer;
99
+ if (!Number.isSafeInteger(rev) || rev < 1 || typeof writer !== 'string' || !WRITER_RE.test(writer)) return null;
100
+ return { writer, rev };
101
+ }
102
+
103
+ /**
104
+ * The memory of what the store last did for each page, entry by entry.
105
+ * @param {{ now?: () => number, ttlMs?: number, max?: number }} [o]
106
+ * @returns {{
107
+ * stale: (ns: string, id: string, revision: { writer: string, rev: number } | null) => boolean,
108
+ * applied: (ns: string, id: string, revision: { writer: string, rev: number } | null) => void,
109
+ * size: () => number,
110
+ * }}
111
+ * `stale`: is this request older than (or the same as) what was last applied for its page and entry? It only
112
+ * asks: nothing is remembered of a request until `applied` is told that the store has done it. Both take a
113
+ * request without a revision (null): never stale, never remembered.
114
+ */
115
+ export function createBlobOrder({ now = Date.now, ttlMs = BLOB_ORDER_TTL_MS, max = BLOB_ORDER_MAX } = {}) {
116
+ const marks = new Map(); // namespace, entry and page → { rev, at }, the one applied longest ago first
117
+ // Three parts that cannot run into one another: the first two are written with their lengths.
118
+ const keyOf = (ns, id, writer) => `${String(ns).length}:${ns}${String(id).length}:${id}${writer}`;
119
+ return {
120
+ stale(ns, id, revision) {
121
+ if (!revision) return false;
122
+ const mark = marks.get(keyOf(ns, id, revision.writer));
123
+ return !!mark && now() - mark.at < ttlMs && revision.rev <= mark.rev;
124
+ },
125
+ applied(ns, id, revision) {
126
+ if (!revision) return;
127
+ const at = now();
128
+ const key = keyOf(ns, id, revision.writer);
129
+ const mark = marks.get(key);
130
+ const rev = mark && at - mark.at < ttlMs ? Math.max(mark.rev, revision.rev) : revision.rev;
131
+ marks.delete(key);
132
+ marks.set(key, { rev, at });
133
+ // What has expired goes (it lies at the old end), then whatever is over the bound.
134
+ for (const [oldest, value] of marks) {
135
+ if (at - value.at < ttlMs) break;
136
+ marks.delete(oldest);
137
+ }
138
+ while (marks.size > max) marks.delete(marks.keys().next().value);
139
+ },
140
+ size: () => marks.size,
141
+ };
142
+ }
143
+
76
144
  export function blobClearNamespace(ns) {
77
145
  const d = getBlobDb();
78
146
  const result = d.prepare('DELETE FROM ui_blobs WHERE ns = ?').run(ns);
@@ -15,7 +15,17 @@ export const OPEN = 1;
15
15
  export const CLOSING = 2;
16
16
  export const CLOSED = 3;
17
17
 
18
- export function createVirtualSocket({ onSend = () => {}, name = 'virtual' } = {}) {
18
+ // A brain's credential (assistant-runtime.js mintBrainCredential), kept beside the socket object
19
+ // that server code built: a client's WebSocket never has one, and nothing a client sends can set
20
+ // it. The Codex skin handler reads it here (brainCredentialOf), never from a message.
21
+ const credentials = new WeakMap();
22
+
23
+ /** The credential the server attached to this in-process socket, or null (always null for a client's socket). */
24
+ export function brainCredentialOf(socket) {
25
+ return (socket && credentials.get(socket)) || null;
26
+ }
27
+
28
+ export function createVirtualSocket({ onSend = () => {}, name = 'virtual', credential = null } = {}) {
19
29
  const emitter = new EventEmitter();
20
30
  emitter.setMaxListeners(50);
21
31
  const socket = {
@@ -56,5 +66,6 @@ export function createVirtualSocket({ onSend = () => {}, name = 'virtual' } = {}
56
66
  emit: (...args) => emitter.emit(...args),
57
67
  listenerCount: (type) => emitter.listenerCount(type),
58
68
  };
69
+ if (typeof credential === 'string' && credential) credentials.set(socket, credential);
59
70
  return socket;
60
71
  }
@@ -7,7 +7,7 @@
7
7
  import { existsSync, readFileSync } from 'node:fs';
8
8
  import { join } from 'node:path';
9
9
  import { pathToFileURL } from 'node:url';
10
- import { CONN, ERR, LIMITS } from './protocol.js';
10
+ import { CONN, CONN_WARNINGS, ERR, LIMITS, VOICE_MARKER } from './protocol.js';
11
11
  import { parseJid, sameAccount } from './identity.js';
12
12
  import { redactWa } from './redact.js';
13
13
 
@@ -18,7 +18,7 @@ export const RUNTIME_EXPORTS = Object.freeze([
18
18
  ]);
19
19
 
20
20
  const QUOTED_MAX = 1000;
21
- const DOWNLOAD_TIMEOUT_MS = 30_000;
21
+ export const DOWNLOAD_TIMEOUT_MS = 30_000;
22
22
  const VERSION_RECHECK_MS = 6 * 3600_000;
23
23
 
24
24
  function adapterError(code, message, cause) {
@@ -235,68 +235,103 @@ export function disconnectCode(err) {
235
235
  return null;
236
236
  }
237
237
 
238
+ // Baileys 7.0.0-rc14 (the pinned connector) closes with 500 for more than a
239
+ // bad session: 500 is DisconnectReason.badSession, but it is also the code
240
+ // getErrorCodeFromStreamError (Utils/generics.js) gives any <stream:error>
241
+ // without a code of its own ("Stream Errored (<first child tag>)", the child
242
+ // node in `data`), the code getCodeFromWSError gives a WebSocket error it
243
+ // cannot place ("WebSocket Error (…)"), and the default of a <failure> without
244
+ // a reason ("Connection Failure"). Baileys itself never names a bad session:
245
+ // only WhatsApp's own stream-error child tag can, and only that wipes the
246
+ // saved credentials. Every other 500 is transport noise and is retried.
247
+ const STREAM_ERROR = /^Stream Errored \(/;
248
+ const INVALID_SESSION_TAG = /\b(?:bad[-_ ]?session|not[-_ ]?authori[sz]ed|invalid[-_ ]?session)\b/i;
249
+
250
+ /** WhatsApp said the saved session is invalid: a stream error whose reason tag names it (`<not-authorized/>`). */
251
+ export function invalidSessionSignal(err) {
252
+ const message = typeof err?.message === 'string' ? err.message : '';
253
+ if (!STREAM_ERROR.test(message)) return false;
254
+ const tag = typeof err?.data?.tag === 'string' ? err.data.tag : '';
255
+ return INVALID_SESSION_TAG.test(`${message} ${tag}`);
256
+ }
257
+
258
+ /** Which kind of generic 500 this is (the reason a log line and lastDisconnect carry). */
259
+ function transportReason(err) {
260
+ const message = typeof err?.message === 'string' ? err.message : '';
261
+ if (STREAM_ERROR.test(message)) return 'stream_error';
262
+ if (/^WebSocket Error \(/.test(message)) return 'websocket_error';
263
+ if (/^Connection Failure\b/.test(message)) return 'connection_failure';
264
+ return 'status_500';
265
+ }
266
+
238
267
  /**
239
268
  * Map a lastDisconnect error to what the host does next, by DisconnectReason
240
269
  * NAME (408 is both connectionLost and timedOut; the enum's reverse map says
241
- * timedOut).
242
- * @returns {{action:'reconnect_now'|'refresh_version'|'backoff'|'stop', state:string, wipe:boolean, reason:string, code:number|null}}
270
+ * timedOut). A saved session never gives up on its own: only 401 (logged out)
271
+ * and an explicitly invalid session stop it, and both wipe the credentials.
272
+ * 440 and 403 retry from the longest delay (`delay: 'long'`) and carry a
273
+ * `warning` the service shows (CONN_WARNINGS). While linking (no saved
274
+ * session) anything but 515, 405, 401 and 403 means the QR or code ran out.
275
+ * @returns {{action:'reconnect_now'|'refresh_version'|'backoff'|'stop', state:string, wipe:boolean, reason:string, code:number|null,
276
+ * delay?:'long', warning?:'replaced'|'forbidden'}}
243
277
  */
244
278
  export function classifyDisconnect(err, { linking = false, DisconnectReason = {} } = {}) {
245
279
  const code = disconnectCode(err);
246
280
  const name = code !== null && typeof DisconnectReason[code] === 'string' ? DisconnectReason[code] : null;
247
- const out = (action, state, wipe, reason) => ({ action, state, wipe, reason, code });
281
+ const out = (action, state, wipe, reason, extra = null) => ({ action, state, wipe, reason, code, ...(extra || {}) });
282
+ // 500: an explicit bad session, or noise (a generic stream / WebSocket / failure error).
283
+ const reason = name === 'badSession' ? (invalidSessionSignal(err) ? 'badSession' : transportReason(err)) : name;
248
284
  if (code === 405) return out('refresh_version', linking ? CONN.CONNECTING : CONN.RECONNECTING, false, 'outdated_version');
249
- switch (name) {
250
- case 'restartRequired':
251
- return out('reconnect_now', CONN.CONNECTING, false, name);
252
- case 'loggedOut':
253
- return out('stop', CONN.LOGGED_OUT, true, name);
254
- case 'connectionReplaced':
255
- return out('stop', CONN.REPLACED, false, name);
256
- case 'forbidden':
257
- return out('stop', CONN.FORBIDDEN, false, name);
258
- case 'badSession':
259
- case 'multideviceMismatch':
260
- return out('stop', CONN.ERROR, false, name);
261
- default:
262
- // timedOut / connectionLost / connectionClosed / unavailableService /
263
- // anything unknown. While linking that means the QR or code ran out:
264
- // stop instead of looping through fresh QR codes.
265
- if (linking) return out('stop', CONN.LINK_EXPIRED, true, name || 'link_failed');
266
- return out('backoff', CONN.RECONNECTING, false, name || (code === null ? 'closed' : `status_${code}`));
285
+ if (name === 'restartRequired') return out('reconnect_now', CONN.CONNECTING, false, name);
286
+ if (name === 'loggedOut') return out('stop', CONN.LOGGED_OUT, true, name);
287
+ if (linking) {
288
+ if (name === 'forbidden') return out('stop', CONN.FORBIDDEN, false, name);
289
+ // A timeout or a closed stream means the QR / code ran out: stop instead of looping through fresh QR codes.
290
+ return out('stop', CONN.LINK_EXPIRED, true, reason || 'link_failed');
291
+ }
292
+ if (reason === 'badSession') return out('stop', CONN.LOGGED_OUT, true, reason);
293
+ const warning = CONN_WARNINGS[code];
294
+ if (warning) {
295
+ // Two copies of one session would kick each other every few seconds, and a refused account is not hammered.
296
+ return out('backoff', CONN.RECONNECTING, false, name || `status_${code}`, { delay: 'long', warning });
267
297
  }
298
+ // timedOut / connectionLost / connectionClosed / unavailableService / multideviceMismatch /
299
+ // a generic 500 / anything unknown: keep the credentials and try again.
300
+ return out('backoff', CONN.RECONNECTING, false, reason || (code === null ? 'closed' : `status_${code}`));
268
301
  }
269
302
 
270
303
  /**
271
- * Reconnect delays 2/5/15/30/60/120/300 s ±20%; the ladder resets after 10
272
- * minutes connected; more than 10 reconnects inside 10 minutes gives up.
304
+ * Reconnect delays 2/4/8/16/32/64/128/256/300 s, each ±20% and never above
305
+ * 300 s; the ladder starts over after 10 minutes connected (noteStable). It
306
+ * never gives up. `next({ long: true })` (440, 403) goes to the top at once and
307
+ * stays there until that stable connection: after a session another copy took
308
+ * or an account WhatsApp refused, any drop waits the long delay (a refused
309
+ * account may fail in other ways too, and two copies must not trade quick
310
+ * retries), the same 10 minutes that end the warning Settings shows.
273
311
  */
274
312
  export function createReconnectPolicy({
275
- now = () => Date.now(),
276
313
  rng = Math.random,
277
- scheduleSec = [2, 5, 15, 30, 60, 120, 300],
314
+ scheduleSec = [2, 4, 8, 16, 32, 64, 128, 256, 300],
278
315
  jitter = 0.2,
279
- limit = 10,
280
- windowMs = 10 * 60_000,
316
+ maxMs = 300_000,
281
317
  } = {}) {
282
318
  let idx = 0;
283
- let attempts = [];
319
+ let attempts = 0;
284
320
  return {
285
- /** @returns {{delayMs:number} | {giveUp:true}} */
286
- next() {
287
- const t = now();
288
- attempts = attempts.filter((a) => t - a < windowMs);
289
- if (attempts.length >= limit) return { giveUp: true };
290
- attempts.push(t);
321
+ /** @returns {{delayMs:number}} */
322
+ next({ long = false } = {}) {
323
+ if (long) idx = Math.max(idx, scheduleSec.length - 1);
291
324
  const base = scheduleSec[Math.min(idx, scheduleSec.length - 1)] * 1000;
292
325
  idx += 1;
326
+ attempts += 1;
293
327
  const factor = 1 + (rng() * 2 - 1) * jitter;
294
- return { delayMs: Math.max(0, Math.round(base * factor)) };
328
+ return { delayMs: Math.min(maxMs, Math.max(0, Math.round(base * factor))) };
295
329
  },
296
330
  /** Connected long enough: start the ladder over. */
297
331
  noteStable() { idx = 0; },
298
- reset() { idx = 0; attempts = []; },
299
- get attempts() { return attempts.length; },
332
+ reset() { idx = 0; attempts = 0; },
333
+ /** Retries scheduled since the last reset (an explicit connect). */
334
+ get attempts() { return attempts; },
300
335
  };
301
336
  }
302
337
 
@@ -323,8 +358,8 @@ const DROP_TYPES = Object.freeze({
323
358
  stickerPackMessage: 'sticker',
324
359
  });
325
360
 
361
+ // audioMessage (voice notes and audio files) is kind 'audio': transcribed on this computer (transcription.js).
326
362
  const UNSUPPORTED = Object.freeze({
327
- audioMessage: 'audio',
328
363
  videoMessage: 'video',
329
364
  ptvMessage: 'video',
330
365
  documentMessage: 'document',
@@ -347,7 +382,7 @@ function captionOf(inner) {
347
382
 
348
383
  /**
349
384
  * Classify the content of one message without downloading anything.
350
- * @returns {{drop:string} | {type:string, kind:'text'|'image'|'unsupported', inner:object|null,
385
+ * @returns {{drop:string} | {type:string, kind:'text'|'image'|'audio'|'unsupported', inner:object|null,
351
386
  * contextInfo:object|null, text:string, unsupportedType:string|null}}
352
387
  */
353
388
  export function describeContent(msg, mod) {
@@ -370,6 +405,9 @@ export function describeContent(msg, mod) {
370
405
  if (type === 'imageMessage') {
371
406
  return { type, kind: 'image', inner, contextInfo, text: captionOf(inner), unsupportedType: null };
372
407
  }
408
+ if (type === 'audioMessage') {
409
+ return { type, kind: 'audio', inner, contextInfo, text: captionOf(inner), unsupportedType: null };
410
+ }
373
411
  return { type, kind: 'unsupported', inner, contextInfo, text: captionOf(inner), unsupportedType: UNSUPPORTED[type] || 'other' };
374
412
  }
375
413
 
@@ -401,13 +439,65 @@ function withTimeout(promise, ms, label) {
401
439
 
402
440
  const MSG_ID_RE = /^[A-Za-z0-9._:+/=-]{1,128}$/;
403
441
 
442
+ /** A size or duration a message declares about itself (a number, a protobuf Long, a string), or null when it says none. */
443
+ function declared(value) {
444
+ if (value === null || value === undefined || value === '') return null;
445
+ let n = NaN;
446
+ if (typeof value === 'number') n = value;
447
+ else if (typeof value === 'bigint' || typeof value === 'string') n = Number(value);
448
+ else if (typeof value?.toNumber === 'function') { try { n = value.toNumber(); } catch { n = NaN; } }
449
+ return Number.isFinite(n) && n >= 0 ? n : null;
450
+ }
451
+
452
+ /**
453
+ * A voice note or audio file (kind 'audio'), only for a message host-core already accepted:
454
+ * → { transcript, recorded } or { unsupported: { type: 'audio', reason } }. `recorded`: a voice note
455
+ * the sender recorded in WhatsApp (ptt), not an audio file attached to the chat. Nothing is downloaded while
456
+ * transcription is off or cannot run here, or when the message says it is over a limit.
457
+ * transcriber transcription.js createTranscriber() (enabled, available(), transcribe())
458
+ * stale sent so long ago that the bridge will skip it anyway: not worth transcribing
459
+ */
460
+ async function readAudio(msg, { mod, sock, logger, inner, transcriber, stale }) {
461
+ const refuse = (reason) => ({ unsupported: { type: 'audio', reason } });
462
+ if (!transcriber || !transcriber.enabled) return refuse('transcription_disabled');
463
+ let ready = false;
464
+ try { ready = transcriber.available() === true; } catch { ready = false; }
465
+ if (!ready) return refuse('transcription_unavailable');
466
+ if ((declared(inner?.fileLength) ?? 0) > LIMITS.MAX_AUDIO_BYTES) return refuse('too_large');
467
+ if ((declared(inner?.seconds) ?? 0) > LIMITS.MAX_AUDIO_SECONDS) return refuse('too_long');
468
+ if (stale) return refuse('stale');
469
+ let bytes;
470
+ try {
471
+ const buf = await withTimeout(
472
+ mod.downloadMediaMessage(msg, 'buffer', {}, { logger, reuploadRequest: sock?.updateMediaMessage }),
473
+ DOWNLOAD_TIMEOUT_MS,
474
+ 'audio download',
475
+ );
476
+ bytes = Buffer.isBuffer(buf) ? buf : Buffer.from(buf || []);
477
+ } catch {
478
+ return refuse('transcription_failed');
479
+ }
480
+ if (bytes.length > LIMITS.MAX_AUDIO_BYTES) return refuse('too_large');
481
+ if (!bytes.length) return refuse('transcription_failed');
482
+ let result = null;
483
+ try { result = await transcriber.transcribe(bytes); } catch { result = null; }
484
+ if (result?.ok && typeof result.text === 'string' && result.text.trim()) return { transcript: result.text.trim(), recorded: inner?.ptt === true };
485
+ // Turned off while the note waited its turn: said as such, not as a failure.
486
+ return refuse(['too_long', 'too_large', 'transcription_disabled'].includes(result?.reason) ? result.reason : 'transcription_failed');
487
+ }
488
+
404
489
  /**
405
490
  * Turn an accepted message into the parts of an InboundMessage (never a JID).
406
- * @returns {Promise<{text:string, images:Array, unsupported:null|{type:string, reason?:string}, forwarded:boolean, quoted:null|{id:string,text:string,fromBot:boolean}}>}
491
+ * A transcribed voice note: `text` is VOICE_MARKER + the transcript, then "\n" + the caption when
492
+ * there is one (the transcript first when the text is cut), and `voice: true`; `audioFile: true` when
493
+ * it is an audio file rather than a note recorded in WhatsApp (its words may be anyone's: the bridge
494
+ * treats it like a picture).
495
+ * @returns {Promise<{text:string, images:Array, unsupported:null|{type:string, reason?:string}, forwarded:boolean,
496
+ * quoted:null|{id:string,text:string,fromBot:boolean}, voice:boolean, audioFile:boolean}>}
407
497
  */
408
- export async function extractInbound(msg, { mod, sock, logger, sentIds, described, text }) {
498
+ export async function extractInbound(msg, { mod, sock, logger, sentIds, described, text, transcriber = null, audioStale = false }) {
409
499
  const d = described;
410
- const body = String(text ?? d.text ?? '').slice(0, LIMITS.MAX_INBOUND_TEXT);
500
+ let body = String(text ?? d.text ?? '').slice(0, LIMITS.MAX_INBOUND_TEXT);
411
501
  const ctx = d.contextInfo;
412
502
  const forwarded = !!(ctx && (ctx.isForwarded || Number(ctx.forwardingScore) > 0));
413
503
  let quoted = null;
@@ -420,7 +510,21 @@ export async function extractInbound(msg, { mod, sock, logger, sentIds, describe
420
510
  }
421
511
  const images = [];
422
512
  let unsupported = null;
513
+ let voice = false;
514
+ let audioFile = false;
423
515
  if (d.kind === 'unsupported') unsupported = { type: d.unsupportedType };
516
+ if (d.kind === 'audio') {
517
+ const audio = await readAudio(msg, { mod, sock, logger, inner: d.inner, transcriber, stale: audioStale });
518
+ if (audio.transcript) {
519
+ const caption = String(text ?? d.text ?? '');
520
+ body = `${VOICE_MARKER} ${audio.transcript}${caption.trim() ? `\n${caption}` : ''}`.slice(0, LIMITS.MAX_INBOUND_TEXT);
521
+ voice = true;
522
+ audioFile = !audio.recorded;
523
+ } else {
524
+ // The same unsupported-audio shape as before, with why; a caption still gets through.
525
+ unsupported = audio.unsupported;
526
+ }
527
+ }
424
528
  if (d.kind === 'image') {
425
529
  const mime = String(d.inner?.mimetype || '').split(';')[0].trim().toLowerCase();
426
530
  const declared = Number(d.inner?.fileLength ?? 0);
@@ -443,7 +547,23 @@ export async function extractInbound(msg, { mod, sock, logger, sentIds, describe
443
547
  }
444
548
  }
445
549
  }
446
- return { text: body, images, unsupported, forwarded, quoted };
550
+ return { text: body, images, unsupported, forwarded, quoted, voice, audioFile };
551
+ }
552
+
553
+ /**
554
+ * The sendMessage content for a file prepared by local-file.js (prepareLocalFile): a document
555
+ * (mimetype + fileName, the caption when there is one), a photo or a video (the caption), or audio
556
+ * (never a caption, never a voice note). `jpegThumbnail: null` keeps Baileys from building a preview,
557
+ * which for a video means running FFmpeg through a shell: SynaBun never decodes the file it sends.
558
+ */
559
+ export function fileMessage(file) {
560
+ const caption = typeof file?.caption === 'string' && file.caption ? { caption: file.caption } : {};
561
+ switch (file?.type) {
562
+ case 'image': return { image: file.data, mimetype: file.mimetype, jpegThumbnail: null, ...caption };
563
+ case 'video': return { video: file.data, mimetype: file.mimetype, jpegThumbnail: null, ...caption };
564
+ case 'audio': return { audio: file.data, mimetype: file.mimetype, ptt: false };
565
+ default: return { document: file.data, mimetype: file.mimetype, fileName: file.fileName || 'file', ...caption };
566
+ }
447
567
  }
448
568
 
449
569
  /** The minimal message Baileys needs to quote an owner message in a reply. */