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
@@ -26,7 +26,7 @@ import {
26
26
  } from '../ui-assistant.js';
27
27
  import { mountAssistant } from './asst-panel.js';
28
28
  import { openModelsManager } from './asst-route.js';
29
- import { brainLabel, readStoredBrain } from './asst-state.js';
29
+ import { brainLabel, readStoredBrain, restoredSessionName } from './asst-state.js';
30
30
  import { closeMenu, isMenuOpen, openMenu } from './asst-menu.js';
31
31
  import { injectAssistantSidepanelStyles } from './asst-sidepanel-styles.js';
32
32
  import { createMascot, mascotCameoSvg } from '../synabun-mascot.js';
@@ -50,7 +50,7 @@ let _initialized = false;
50
50
  let _starting = false;
51
51
  let _startError = ''; // the last message the host showed while starting (the failed state repeats it)
52
52
  let _placeholderMascot = null; // the character while starting: the empty state's, same size; it flies to the empty state's spot
53
- let _pendingPath = '';
53
+ let _pendingPaths = []; // file paths sent while no session was open: attached, in order, when one is
54
54
  let _toastTimer = null;
55
55
  let _renaming = false;
56
56
  const _tabs = []; // { sessionId, viewport, toolbar, ctl, pill, label, userRenamed, status, brain }
@@ -260,7 +260,7 @@ function showPanelToast(text) {
260
260
 
261
261
  // ── Tabs ─────────────────────────────────────────────────────────────────────
262
262
 
263
- function mountTab({ sessionId, meta = null, brain = null, label = '', userRenamed = false, prompt = '', show = true } = {}) {
263
+ function mountTab({ sessionId, meta = null, brain = null, label = '', userRenamed = false, prompt = '', show = true, restoring = false } = {}) {
264
264
  if (!sessionId) return null;
265
265
  ensurePanel();
266
266
  const existing = findTab(sessionId);
@@ -280,9 +280,13 @@ function mountTab({ sessionId, meta = null, brain = null, label = '', userRename
280
280
  toolbar.className = 'asp-tab-bar';
281
281
  toolbar.dataset.sessionId = sessionId;
282
282
  panelEl('.asp-bar-slot').appendChild(toolbar);
283
- const renamed = !!(userRenamed && label);
283
+ // A renamed session comes back under its name: the session record's (a rename made in either
284
+ // host, the one the Sessions menu lists), else the rename saved with this tab. A record whose
285
+ // name was given up says so: the label and the renamed flag saved with a tab are stale.
286
+ const name = restoredSessionName(meta, userRenamed ? label : '');
287
+ const renamed = !!name;
284
288
  // The record exists before mountAssistant: the host hooks fire during mount.
285
- const tab = { sessionId, viewport, toolbar, ctl: null, pill: null, label: renamed ? label : defaultLabel(), userRenamed: renamed, status: 'idle', brain: brain || meta?.brain || null };
289
+ const tab = { sessionId, viewport, toolbar, ctl: null, pill: null, label: renamed ? name : defaultLabel(), userRenamed: renamed, status: 'idle', brain: brain || meta?.brain || null };
286
290
  _tabs.push(tab);
287
291
  const host = {
288
292
  id: HOST_ID,
@@ -295,6 +299,16 @@ function mountTab({ sessionId, meta = null, brain = null, label = '', userRename
295
299
  renderPills();
296
300
  saveTabs();
297
301
  },
302
+ // A rename the panel could not save: the tab and its saved label go back to the record's name.
303
+ setName(text, renamed) {
304
+ const next = String(text || '').trim();
305
+ if (!next) return;
306
+ tab.label = next;
307
+ tab.userRenamed = !!renamed;
308
+ renderHeader();
309
+ renderPills();
310
+ saveTabs();
311
+ },
298
312
  setStatus(status) {
299
313
  tab.status = status || 'idle';
300
314
  if (tab.status === 'done' && isTabVisible(tab)) tab.status = 'idle';
@@ -311,7 +325,7 @@ function mountTab({ sessionId, meta = null, brain = null, label = '', userRename
311
325
  },
312
326
  };
313
327
  tab.ctl = mountAssistant(viewport, { sessionId, brain: tab.brain, host, session: meta });
314
- if (tab.userRenamed) tab.ctl.setTitle(tab.label);
328
+ if (tab.userRenamed) tab.ctl.setTitle(tab.label, { restored: true });
315
329
  if (show) {
316
330
  switchTo(_tabs.length - 1);
317
331
  if (!_visible) setVisible(true);
@@ -324,7 +338,8 @@ function mountTab({ sessionId, meta = null, brain = null, label = '', userRename
324
338
  renderPills();
325
339
  saveTabs();
326
340
  if (prompt) setTimeout(() => { if (findTab(sessionId)) tab.ctl?.send(prompt); }, 50);
327
- if (_pendingPath && tab === activeTab()) { const path = _pendingPath; _pendingPath = ''; tab.ctl.attachPath(path); }
341
+ // (Not while the saved tabs are coming back: the first of them is not the one that was showing.)
342
+ if (_pendingPaths.length && !restoring && tab === activeTab()) { const paths = _pendingPaths; _pendingPaths = []; for (const path of paths) tab.ctl.attachPath(path); }
328
343
  return tab;
329
344
  }
330
345
 
@@ -635,12 +650,14 @@ export async function initAssistantPanel() {
635
650
  if (!_visible) setVisible(true);
636
651
  tab.ctl?.attachImageDataUrl(dataUrl, 'whiteboard');
637
652
  });
638
- on('assistant:attach-path', ({ path } = {}) => {
653
+ on('assistant:attach-path', (request = {}) => {
654
+ const { path } = request;
639
655
  if (!path || assistantBlocked()) return;
640
656
  const tab = activeTab();
641
657
  if (!_visible) setVisible(true);
642
658
  if (tab?.ctl) tab.ctl.attachPath(path);
643
- else _pendingPath = String(path);
659
+ else _pendingPaths.push(String(path));
660
+ request.taken = true; // the sender says "sent" only of what was taken
644
661
  });
645
662
  // The server renamed a conversation (first prompt): refresh tooltips after the component applied it.
646
663
  on('sync:assistant:session-updated', (msg) => {
@@ -663,6 +680,7 @@ export async function initAssistantPanel() {
663
680
  label: entry.label || '',
664
681
  userRenamed: !!entry.userRenamed,
665
682
  show: false,
683
+ restoring: true,
666
684
  });
667
685
  }
668
686
  if (_tabs.length) {
@@ -670,6 +688,10 @@ export async function initAssistantPanel() {
670
688
  markActive();
671
689
  renderHeader();
672
690
  renderPills();
691
+ // Paths that were sent while the sessions were being asked about go to the one that is showing again.
692
+ const paths = _pendingPaths;
693
+ _pendingPaths = [];
694
+ for (const path of paths) activeTab()?.ctl?.attachPath(path);
673
695
  }
674
696
  saveTabs();
675
697
  }
@@ -15,7 +15,7 @@ export const SLASH_COMMANDS = [
15
15
  { name: 'project', usage: '/project <path>', descKey: 'assistant.slash.project', desc: 'Set the working project' },
16
16
  { name: 'routes', usage: '/routes [always|unsure|never]', descKey: 'assistant.slash.routes', desc: 'Set when to ask before routing (or open the model routes)' },
17
17
  { name: 'models', usage: '/models [list | archived | hide <id…> | show <id…>]', descKey: 'assistant.slash.models', desc: 'Switch models off or on for the Assistant (or open the Models list)' },
18
- { name: 'budget', usage: '/budget', descKey: 'assistant.slash.budget', desc: 'Set the money caps (per run, session, brain)' },
18
+ { name: 'budget', usage: '/budget', descKey: 'assistant.slash.budget', desc: 'Set the session budget and view provider shares' },
19
19
  { name: 'computer', usage: '/computer [on|off]', descKey: 'assistant.slash.computer', desc: 'Let the assistant use your Mac' },
20
20
  { name: 'stop', usage: '/stop [runId|all]', descKey: 'assistant.slash.stop', desc: 'Stop a run, everything, or the current turn' },
21
21
  { name: 'new', usage: '/new [provider]', descKey: 'assistant.slash.new', desc: 'Start a fresh session' },
@@ -181,7 +181,7 @@ export function resolveBrainDefaults(brain, catalog = {}) {
181
181
 
182
182
  if (ACCOUNT_PROVIDERS.has(b.provider)) {
183
183
  const accounts = catalog.accounts?.[b.provider] || [];
184
- if (!b.accountId || (accounts.length && !accounts.some(a => a?.id === b.accountId))) {
184
+ if (!b.accountId || (b.accountId !== 'auto' && accounts.length && !accounts.some(a => a?.id === b.accountId))) {
185
185
  b.accountId = accounts.find(a => a?.isDefault)?.id || accounts[0]?.id || 'default';
186
186
  }
187
187
  } else {
@@ -231,6 +231,56 @@ export function modelShortName(model) {
231
231
  return tail.replace(/:\d+$/, '');
232
232
  }
233
233
 
234
+ // ── Projects ────────────────────────────────────────────────────────────────
235
+
236
+ /** A folder path without trailing separators ("/a/b/" is "/a/b"); the root stays itself. */
237
+ function folderPath(path) {
238
+ const value = str(path);
239
+ return value.replace(/[\\/]+$/, '') || value;
240
+ }
241
+
242
+ /**
243
+ * What a working folder is called: its label among SynaBun's registered
244
+ * projects (GET /api/projects: [{ path, label }]), else the folder's own name;
245
+ * '' for none. The toolbar's Working project, the empty state's picker and the
246
+ * "Fix … in {project}" suggestion all read it, so they name it the same way.
247
+ */
248
+ export function projectLabel(path, projects = []) {
249
+ const want = folderPath(path);
250
+ if (!want) return '';
251
+ const row = (Array.isArray(projects) ? projects : []).find(p => p && folderPath(p.path) === want);
252
+ return str(row?.label) || want.split(/[\\/]/).filter(Boolean).pop() || want;
253
+ }
254
+
255
+ const fillParams = (text, params) => (params ? String(text).replace(/\{(\w+)\}/g, (_, k) => (params[k] != null ? params[k] : `{${k}}`)) : String(text));
256
+
257
+ /**
258
+ * The empty state's project picker: { chosen, key, label, title, aria }. With
259
+ * no project the brain works in the home directory and the picker asks
260
+ * "Choose a project"; with one it reads "Project Synabun", the path in its
261
+ * tooltip. `tr(key, fallback, params)` translates.
262
+ */
263
+ export function emptyProjectView(project, projects = [], tr = (_key, fallback, params) => fillParams(fallback, params)) {
264
+ const path = str(project);
265
+ const name = projectLabel(path, projects);
266
+ if (!name) {
267
+ return {
268
+ chosen: false,
269
+ key: '',
270
+ label: tr('assistant.empty.chooseProject', 'Choose a project'),
271
+ title: tr('assistant.brain.projectNoneTip', 'Working project: home directory'),
272
+ aria: tr('assistant.empty.projectAria', 'Choose a project (now: {project})', { project: tr('assistant.brain.projectNone', 'Home directory') }),
273
+ };
274
+ }
275
+ return {
276
+ chosen: true,
277
+ key: tr('assistant.empty.project', 'Project'),
278
+ label: name,
279
+ title: path,
280
+ aria: tr('assistant.empty.projectAria', 'Choose a project (now: {project})', { project: name === path ? name : `${name}, ${path}` }),
281
+ };
282
+ }
283
+
234
284
  /** Does switching from `a` to `b` require a fresh server session (switch_brain)? */
235
285
  export function brainRequiresSwitch(a, b) {
236
286
  const x = normalizeBrain(a);
@@ -453,6 +503,22 @@ export function normalizeRouteMode(value, fallback = null) {
453
503
  return ROUTE_MODE_ALIASES[key] || fallback;
454
504
  }
455
505
 
506
+ // Test density: how much testing SynaBun asks of dispatched workers (server: lib/assistant-test-density.js).
507
+ // `null` means "server default" in a tab's own state; a missing or unknown value reads as the default level.
508
+ export const TEST_DENSITIES = ['none', 'light', 'standard', 'thorough'];
509
+ export const DEFAULT_TEST_DENSITY = 'light';
510
+
511
+ /** A known level, else `fallback` (the default level; pass null to tell "not set" apart). */
512
+ export function normalizeTestDensity(value, fallback = DEFAULT_TEST_DENSITY) {
513
+ const key = str(value).toLowerCase();
514
+ return TEST_DENSITIES.includes(key) ? key : fallback;
515
+ }
516
+
517
+ /** Bars of the composer's gauge that are filled at a level: none 0 · light 1 · standard 2 · thorough 3. */
518
+ export function testDensityBars(level) {
519
+ return TEST_DENSITIES.indexOf(normalizeTestDensity(level));
520
+ }
521
+
456
522
  const COMPUTER_ON = new Set(['on', 'true', '1', 'yes', 'enable', 'enabled']);
457
523
  const COMPUTER_OFF = new Set(['off', 'false', '0', 'no', 'disable', 'disabled']);
458
524
 
@@ -529,6 +595,121 @@ export function tabStorageKey(sessionId) {
529
595
  return `${KEYS.ASSISTANT_TAB_PREFIX}${sessionId}`;
530
596
  }
531
597
 
598
+ /**
599
+ * The name the user gave a session, '' when they never renamed it. It lives on
600
+ * the server's session record (`title` + `userRenamed`, written by a rename in
601
+ * either host): the Sessions menu and a reopened tab read the same name, and a
602
+ * host's saved tab label is only its copy.
603
+ */
604
+ export function userSessionTitle(meta) {
605
+ if (!meta || typeof meta !== 'object' || meta.userRenamed !== true) return '';
606
+ return str(meta.title);
607
+ }
608
+
609
+ /** What a tab is called until the user renames it (the server's DEFAULT_SESSION_TITLE). */
610
+ export const DEFAULT_SESSION_TITLE = 'SynaBun';
611
+
612
+ /**
613
+ * The title to write to the session record for a tab's name, null when there is
614
+ * nothing to write. `recordName` is userSessionTitle() of the record,
615
+ * `recordTitle` its title, `keepsRenames` whether the server marks renames
616
+ * (features.rename; one not restarted yet does not, and holds a name once its
617
+ * title says it), `defaultTitle` the default tab name as this locale shows it.
618
+ * The default name is no name: it is only written to take a rename back.
619
+ */
620
+ export function renameToSave(name, { recordName = '', recordTitle = '', keepsRenames = false, defaultTitle = DEFAULT_SESSION_TITLE } = {}) {
621
+ const next = str(name);
622
+ if (!next) return null;
623
+ if (next === DEFAULT_SESSION_TITLE || next === str(defaultTitle)) return keepsRenames && str(recordName) ? DEFAULT_SESSION_TITLE : null;
624
+ return next === (keepsRenames ? str(recordName) : str(recordTitle)) ? null : next;
625
+ }
626
+
627
+ /**
628
+ * The name a host gives the tab it mounts for a session: the record's
629
+ * (userSessionTitle), else the label saved with the tab when the record says
630
+ * nothing about a name (a rename made before the record kept names). A record
631
+ * with `userRenamed: false` had its name given up: a saved label is stale.
632
+ */
633
+ export function restoredSessionName(meta, savedLabel = '') {
634
+ return userSessionTitle(meta) || (sessionNameGivenUp(meta) ? '' : str(savedLabel));
635
+ }
636
+
637
+ /** The record says its name was taken back ("SynaBun" again): no saved label or renamed flag stands for it. */
638
+ export function sessionNameGivenUp(meta) {
639
+ return !!meta && typeof meta === 'object' && meta.userRenamed === false;
640
+ }
641
+
642
+ /**
643
+ * Every rename on its way to a session record, one write at a time per session,
644
+ * so the name asked for last is the one the record ends with: after each answer
645
+ * the newest name is compared with what the record holds now, and what still
646
+ * differs (taking a rename back included) is written. One writer for the page,
647
+ * not one per tab: a write goes on after its tab closed, and a session list
648
+ * waits for `settled()`. `patch(sessionId, { title })` is the request.
649
+ *
650
+ * save(sessionId, name, opts): `recordName` / `recordTitle` / `keepsRenames` /
651
+ * `defaultTitle` are renameToSave()'s, as the caller knows the record (a write
652
+ * under way hears the record from its answer instead); `from` is the name the
653
+ * tab had before the first of them. `onSaved(session)` gets each answer,
654
+ * `onFailed({ name, back })` a write that did not get through: `name` was not
655
+ * saved, `back` is the name the record answers to (the last one it confirmed,
656
+ * else `from`). The latest call's callbacks are the ones used. The promise
657
+ * never rejects.
658
+ */
659
+ export function createRenameWriter({ patch } = {}) {
660
+ const jobs = new Map(); // sessionId → { name, back, record, keepsRenames, defaultTitle, onSaved, onFailed, done }
661
+
662
+ const toWrite = (job) => renameToSave(job.name, { recordName: job.record.name, recordTitle: job.record.title, keepsRenames: job.keepsRenames, defaultTitle: job.defaultTitle });
663
+
664
+ async function run(sessionId, job) {
665
+ // The title of the last write the server answered. It may keep a name cut or tidied, which
666
+ // never equals the tab's: the same title is not sent twice in a row.
667
+ let written = null;
668
+ for (;;) {
669
+ const name = job.name;
670
+ const title = toWrite(job);
671
+ if (!title || title === written) break;
672
+ let session = null;
673
+ try { session = (await patch(sessionId, { title }))?.session || null; } catch {
674
+ jobs.delete(sessionId);
675
+ try { job.onFailed?.({ name: job.name, back: job.back }); } catch { /* the caller's */ }
676
+ return;
677
+ }
678
+ written = title;
679
+ job.back = name;
680
+ job.record = session?.title
681
+ ? { name: userSessionTitle(session), title: str(session.title) }
682
+ : { name: job.keepsRenames && title !== DEFAULT_SESSION_TITLE ? title : '', title };
683
+ try { job.onSaved?.(session); } catch { /* the caller's */ }
684
+ }
685
+ jobs.delete(sessionId);
686
+ }
687
+
688
+ function save(sessionId, name, { from = '', recordName = '', recordTitle = '', keepsRenames = false, defaultTitle = DEFAULT_SESSION_TITLE, onSaved = null, onFailed = null } = {}) {
689
+ const next = str(name);
690
+ if (!sessionId || !next) return Promise.resolve();
691
+ const waiting = jobs.get(sessionId);
692
+ if (waiting) {
693
+ // A write is under way: this name is the one compared with its answer.
694
+ Object.assign(waiting, { name: next, keepsRenames, defaultTitle, onSaved, onFailed });
695
+ return waiting.done;
696
+ }
697
+ const job = { name: next, back: str(from), record: { name: str(recordName), title: str(recordTitle) }, keepsRenames, defaultTitle, onSaved, onFailed, done: null };
698
+ if (!toWrite(job)) return Promise.resolve();
699
+ jobs.set(sessionId, job);
700
+ job.done = run(sessionId, job);
701
+ return job.done;
702
+ }
703
+
704
+ return {
705
+ save,
706
+ /** A rename of this session is on its way. */
707
+ pending: (sessionId) => jobs.has(sessionId),
708
+ /** Resolves once every rename that was on its way has its answer, whatever tab asked for it. */
709
+ settled: () => Promise.all([...jobs.values()].map((job) => job.done)).then(() => {}),
710
+ };
711
+ }
712
+
532
713
  export function createTabState(sessionId, brain, extra = {}) {
533
714
  return {
534
715
  sessionId,
@@ -548,6 +729,7 @@ export function createTabState(sessionId, brain, extra = {}) {
548
729
  draft: '',
549
730
  routeMode: null, // explicit per-session route mode; null = server default
550
731
  computerUse: null, // explicit per-session computer use; null = server default
732
+ testDensity: null, // explicit per-session test density; null = server default
551
733
  usageView: null,
552
734
  limit: null, // the provider's usage limit notice (applyLimit); never persisted, the server re-sends it on attach
553
735
  ...extra,
@@ -568,12 +750,13 @@ export function serializeTabState(state) {
568
750
  costUsd: Number.isFinite(Number(state.costUsd)) ? Number(state.costUsd) : 0,
569
751
  routeMode: normalizeRouteMode(state.routeMode, null),
570
752
  computerUse: normalizeComputerMode(state.computerUse, null),
753
+ testDensity: normalizeTestDensity(state.testDensity, null),
571
754
  usageView: compactUsageView(state.usageView),
572
755
  updatedAt: Date.now(),
573
756
  };
574
757
  }
575
758
 
576
- /** Tolerant of older payloads: missing routeMode / computerUse read as null (server default). */
759
+ /** Tolerant of older payloads: missing routeMode / computerUse / testDensity read as null (server default). */
577
760
  export function deserializeTabState(raw) {
578
761
  let data = raw;
579
762
  if (typeof raw === 'string') {
@@ -590,6 +773,7 @@ export function deserializeTabState(raw) {
590
773
  costUsd: Number.isFinite(Number(data.costUsd)) ? Number(data.costUsd) : 0,
591
774
  routeMode: normalizeRouteMode(data.routeMode, null),
592
775
  computerUse: normalizeComputerMode(data.computerUse, null),
776
+ testDensity: normalizeTestDensity(data.testDensity, null),
593
777
  usageView: compactUsageView(data.usageView),
594
778
  };
595
779
  }