synabun 2.0.0 → 2.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (507) hide show
  1. package/CHANGELOG.md +97 -0
  2. package/NOTICE +5 -0
  3. package/README.md +2 -1
  4. package/THIRD-PARTY-LICENSES.md +59 -0
  5. package/benchmarks/fixtures/browser/README.md +1 -1
  6. package/benchmarks/fixtures/desktop/README.md +1 -1
  7. package/docs/whatsapp.md +153 -18
  8. package/hooks/claude-code/pre-compact.mjs +11 -0
  9. package/hooks/claude-code/prompt-submit.mjs +60 -184
  10. package/hooks/claude-code/session-start.mjs +73 -16
  11. package/hooks/claude-code/shared.mjs +26 -3
  12. package/hooks/claude-code/stop.mjs +5 -5
  13. package/lib/child-path.js +303 -0
  14. package/lib/claude-hooks.js +2 -1
  15. package/lib/data-home-migration.js +2 -0
  16. package/lib/desktop-app.js +265 -0
  17. package/lib/external-tools.js +7 -3
  18. package/lib/log-redact.js +102 -0
  19. package/lib/packaged-runtime.js +138 -11
  20. package/lib/start-launcher.js +88 -1
  21. package/mcp-server/dist/http.d.ts +3 -1
  22. package/mcp-server/dist/http.d.ts.map +1 -1
  23. package/mcp-server/dist/http.js +15 -4
  24. package/mcp-server/dist/http.js.map +1 -1
  25. package/mcp-server/dist/index.d.ts.map +1 -1
  26. package/mcp-server/dist/index.js +9 -6
  27. package/mcp-server/dist/index.js.map +1 -1
  28. package/mcp-server/dist/services/budget-judgments.d.ts +108 -0
  29. package/mcp-server/dist/services/budget-judgments.d.ts.map +1 -0
  30. package/mcp-server/dist/services/budget-judgments.js +153 -0
  31. package/mcp-server/dist/services/budget-judgments.js.map +1 -0
  32. package/mcp-server/dist/services/codex-config-heal.d.ts +5 -1
  33. package/mcp-server/dist/services/codex-config-heal.d.ts.map +1 -1
  34. package/mcp-server/dist/services/codex-config-heal.js +41 -4
  35. package/mcp-server/dist/services/codex-config-heal.js.map +1 -1
  36. package/mcp-server/dist/services/identity.d.ts +11 -0
  37. package/mcp-server/dist/services/identity.d.ts.map +1 -1
  38. package/mcp-server/dist/services/identity.js +24 -0
  39. package/mcp-server/dist/services/identity.js.map +1 -1
  40. package/mcp-server/dist/services/neural-interface.d.ts +13 -0
  41. package/mcp-server/dist/services/neural-interface.d.ts.map +1 -1
  42. package/mcp-server/dist/services/neural-interface.js +34 -2
  43. package/mcp-server/dist/services/neural-interface.js.map +1 -1
  44. package/mcp-server/dist/services/typesafe-config.d.ts +1 -1
  45. package/mcp-server/dist/services/typesafe-config.d.ts.map +1 -1
  46. package/mcp-server/dist/services/typesafe-config.js +4 -1
  47. package/mcp-server/dist/services/typesafe-config.js.map +1 -1
  48. package/mcp-server/dist/tools/agents.d.ts +10 -7
  49. package/mcp-server/dist/tools/agents.d.ts.map +1 -1
  50. package/mcp-server/dist/tools/agents.js +34 -13
  51. package/mcp-server/dist/tools/agents.js.map +1 -1
  52. package/mcp-server/dist/tools/whatsapp-send-file.d.ts +17 -0
  53. package/mcp-server/dist/tools/whatsapp-send-file.d.ts.map +1 -0
  54. package/mcp-server/dist/tools/whatsapp-send-file.js +44 -0
  55. package/mcp-server/dist/tools/whatsapp-send-file.js.map +1 -0
  56. package/mcp-server/dist/tui.js +2 -1
  57. package/mcp-server/dist/tui.js.map +1 -1
  58. package/mcp-server/dist/version.d.ts +5 -0
  59. package/mcp-server/dist/version.d.ts.map +1 -0
  60. package/mcp-server/dist/version.js +21 -0
  61. package/mcp-server/dist/version.js.map +1 -0
  62. package/mcp-server/package-lock.json +2 -2
  63. package/mcp-server/package.json +1 -3
  64. package/mcp-server/run.mjs +15 -9
  65. package/mcp-server/src/http.ts +18 -3
  66. package/mcp-server/src/index.ts +9 -6
  67. package/mcp-server/src/services/budget-judgments.ts +183 -0
  68. package/mcp-server/src/services/codex-config-heal.ts +35 -4
  69. package/mcp-server/src/services/identity.ts +27 -0
  70. package/mcp-server/src/services/neural-interface.ts +34 -2
  71. package/mcp-server/src/services/typesafe-config.ts +4 -1
  72. package/mcp-server/src/tools/agents.ts +33 -14
  73. package/mcp-server/src/tools/whatsapp-send-file.ts +51 -0
  74. package/mcp-server/src/tui.ts +2 -1
  75. package/mcp-server/src/version.ts +22 -0
  76. package/neural-interface/i18n/en.json +2126 -209
  77. package/neural-interface/i18n/pt-BR.json +2123 -207
  78. package/neural-interface/lib/account-usage.js +163 -0
  79. package/neural-interface/lib/assistant-api.js +316 -57
  80. package/neural-interface/lib/assistant-brains/claude.js +19 -2
  81. package/neural-interface/lib/assistant-brains/codex.js +3 -0
  82. package/neural-interface/lib/assistant-brains/opencode.js +17 -4
  83. package/neural-interface/lib/assistant-budget-planner.js +390 -0
  84. package/neural-interface/lib/assistant-budget-split.js +408 -0
  85. package/neural-interface/lib/assistant-budget.js +94 -95
  86. package/neural-interface/lib/assistant-catalog.js +179 -27
  87. package/neural-interface/lib/assistant-config.js +91 -14
  88. package/neural-interface/lib/assistant-dispatch.js +494 -138
  89. package/neural-interface/lib/assistant-hidden-models.js +393 -66
  90. package/neural-interface/lib/assistant-jev.js +26 -3
  91. package/neural-interface/lib/assistant-memory.js +24 -10
  92. package/neural-interface/lib/assistant-persona.js +73 -12
  93. package/neural-interface/lib/assistant-plan-permissions.js +8 -1
  94. package/neural-interface/lib/assistant-pricing.js +21 -6
  95. package/neural-interface/lib/assistant-route-accounts.js +14 -0
  96. package/neural-interface/lib/assistant-route-gate.js +19 -3
  97. package/neural-interface/lib/assistant-router.js +373 -42
  98. package/neural-interface/lib/assistant-runtime.js +488 -59
  99. package/neural-interface/lib/assistant-task-prompt.js +13 -3
  100. package/neural-interface/lib/assistant-test-density.js +142 -0
  101. package/neural-interface/lib/assistant-user-context-budgets.js +123 -0
  102. package/neural-interface/lib/assistant-user-context.js +908 -0
  103. package/neural-interface/lib/assistant-user-knowledge.js +328 -0
  104. package/neural-interface/lib/assistant-user-learn.js +404 -0
  105. package/neural-interface/lib/assistant-user-threads.js +226 -0
  106. package/neural-interface/lib/assistant-user-writer.js +183 -0
  107. package/neural-interface/lib/augmented-path.js +317 -53
  108. package/neural-interface/lib/browser-background-tab.js +134 -0
  109. package/neural-interface/lib/browser-screenshot.js +678 -61
  110. package/neural-interface/lib/claude-accounts.js +342 -31
  111. package/neural-interface/lib/claude-agent-bridge.js +123 -9
  112. package/neural-interface/lib/claude-executable.js +6 -1
  113. package/neural-interface/lib/claude-model-catalog.js +33 -5
  114. package/neural-interface/lib/claude-panel-auth.js +221 -0
  115. package/neural-interface/lib/claude-profile-api-key.js +62 -0
  116. package/neural-interface/lib/claude-temporary.js +46 -7
  117. package/neural-interface/lib/cli-install-api.js +137 -0
  118. package/neural-interface/lib/cli-install.js +797 -0
  119. package/neural-interface/lib/cli-path.js +130 -0
  120. package/neural-interface/lib/cli-resolver.js +744 -0
  121. package/neural-interface/lib/cli-update-planner.js +143 -7
  122. package/neural-interface/lib/cloudflared/install.js +533 -0
  123. package/neural-interface/lib/cloudflared/manager.js +545 -0
  124. package/neural-interface/lib/cloudflared/pins.js +115 -0
  125. package/neural-interface/lib/cloudflared/pins.json +63 -0
  126. package/neural-interface/lib/cloudflared/tunnel.js +265 -0
  127. package/neural-interface/lib/codex-account-auth.js +178 -0
  128. package/neural-interface/lib/codex-accounts.js +489 -0
  129. package/neural-interface/lib/codex-capabilities.js +2 -1
  130. package/neural-interface/lib/codex-compat-rpc.js +8 -2
  131. package/neural-interface/lib/codex-mcp-approvals.js +5 -1
  132. package/neural-interface/lib/codex-panel-auth.js +62 -0
  133. package/neural-interface/lib/codex-session-settings.js +1 -1
  134. package/neural-interface/lib/codex-settings-schema.js +120 -0
  135. package/neural-interface/lib/desktop/config.js +3 -0
  136. package/neural-interface/lib/editor-completion-endpoint.js +264 -0
  137. package/neural-interface/lib/editor-completion-opencode.js +436 -0
  138. package/neural-interface/lib/editor-completion.js +714 -0
  139. package/neural-interface/lib/editor-config.js +149 -0
  140. package/neural-interface/lib/editor-files-api.js +268 -0
  141. package/neural-interface/lib/editor-git-api.js +134 -0
  142. package/neural-interface/lib/file-explorer-api.js +1039 -0
  143. package/neural-interface/lib/file-explorer-system.js +355 -0
  144. package/neural-interface/lib/file-explorer-trash.ps1 +85 -0
  145. package/neural-interface/lib/file-explorer-watch.js +239 -0
  146. package/neural-interface/lib/git-bash/bzip2.js +339 -0
  147. package/neural-interface/lib/git-bash/claude-settings.js +73 -0
  148. package/neural-interface/lib/git-bash/extract-worker.js +34 -0
  149. package/neural-interface/lib/git-bash/install.js +529 -0
  150. package/neural-interface/lib/git-bash/licenses/COPYING +360 -0
  151. package/neural-interface/lib/git-bash/licenses/LGPL-2.1 +511 -0
  152. package/neural-interface/lib/git-bash/manager.js +268 -0
  153. package/neural-interface/lib/git-bash/pins.js +206 -0
  154. package/neural-interface/lib/git-bash/pins.json +34 -0
  155. package/neural-interface/lib/git-bash/resolver.js +194 -0
  156. package/neural-interface/lib/git-diff-api.js +103 -0
  157. package/neural-interface/lib/git-read.js +234 -0
  158. package/neural-interface/lib/greeting/api.js +89 -0
  159. package/neural-interface/lib/greeting/budgets.js +90 -0
  160. package/neural-interface/lib/greeting/engine.js +461 -0
  161. package/neural-interface/lib/greeting/facts.js +320 -0
  162. package/neural-interface/lib/greeting/sources.js +252 -0
  163. package/neural-interface/lib/greeting/writer.js +139 -0
  164. package/neural-interface/lib/http-guards.js +189 -13
  165. package/neural-interface/lib/install-details.js +145 -0
  166. package/neural-interface/lib/machine-names.js +88 -0
  167. package/neural-interface/lib/mcp-installer.js +14 -2
  168. package/neural-interface/lib/memory-api.js +31 -7
  169. package/neural-interface/lib/native-loop-providers.js +26 -8
  170. package/neural-interface/lib/native-loop-runtime.js +9 -4
  171. package/neural-interface/lib/os-path.js +319 -0
  172. package/neural-interface/lib/plugin-installer.js +4 -2
  173. package/neural-interface/lib/project-storage.js +5 -7
  174. package/neural-interface/lib/provider-panel-api-key-auth.js +92 -0
  175. package/neural-interface/lib/provider-panel-terminal-auth.js +95 -0
  176. package/neural-interface/lib/pty-host/core.js +2 -1
  177. package/neural-interface/lib/pty-host/manager.js +27 -2
  178. package/neural-interface/lib/remote-policy.js +20 -11
  179. package/neural-interface/lib/request-gate.js +589 -0
  180. package/neural-interface/lib/session-title-generator.js +4 -3
  181. package/neural-interface/lib/system-about.js +340 -0
  182. package/neural-interface/lib/system-activity.js +66 -0
  183. package/neural-interface/lib/terminal-env.js +11 -3
  184. package/neural-interface/lib/terminal-path.js +55 -0
  185. package/neural-interface/lib/ui-blob-api.js +108 -0
  186. package/neural-interface/lib/ui-blob-store.js +68 -0
  187. package/neural-interface/lib/virtual-socket.js +12 -1
  188. package/neural-interface/lib/whatsapp/baileys-adapter.js +165 -45
  189. package/neural-interface/lib/whatsapp/bridge.js +78 -34
  190. package/neural-interface/lib/whatsapp/commands.js +13 -14
  191. package/neural-interface/lib/whatsapp/config.js +134 -20
  192. package/neural-interface/lib/whatsapp/fake-baileys.js +99 -14
  193. package/neural-interface/lib/whatsapp/host-core.js +168 -35
  194. package/neural-interface/lib/whatsapp/inbound.js +5 -3
  195. package/neural-interface/lib/whatsapp/local-file.js +524 -0
  196. package/neural-interface/lib/whatsapp/manager.js +92 -32
  197. package/neural-interface/lib/whatsapp/paths.js +11 -1
  198. package/neural-interface/lib/whatsapp/protocol.js +65 -5
  199. package/neural-interface/lib/whatsapp/redact.js +63 -0
  200. package/neural-interface/lib/whatsapp/service.js +343 -91
  201. package/neural-interface/lib/whatsapp/transcription.js +463 -0
  202. package/neural-interface/package-lock.json +701 -2
  203. package/neural-interface/package.json +13 -2
  204. package/neural-interface/public/index.html +2 -0
  205. package/neural-interface/public/index2d.html +2 -0
  206. package/neural-interface/public/install-app.html +9 -6
  207. package/neural-interface/public/offline.html +19 -3
  208. package/neural-interface/public/onboarding.html +107 -2
  209. package/neural-interface/public/shared/account-i18n.js +7 -0
  210. package/neural-interface/public/shared/account-menu.js +539 -0
  211. package/neural-interface/public/shared/account-usage.js +19 -0
  212. package/neural-interface/public/shared/account-view.js +335 -0
  213. package/neural-interface/public/shared/agent-runtime-options.js +50 -14
  214. package/neural-interface/public/shared/assistant/asst-accounts.js +182 -184
  215. package/neural-interface/public/shared/assistant/asst-api.js +32 -2
  216. package/neural-interface/public/shared/assistant/asst-automation.js +286 -0
  217. package/neural-interface/public/shared/assistant/asst-brain-picker.js +430 -81
  218. package/neural-interface/public/shared/assistant/asst-budget.js +259 -303
  219. package/neural-interface/public/shared/assistant/asst-composer.js +11 -1
  220. package/neural-interface/public/shared/assistant/asst-mascot.js +140 -61
  221. package/neural-interface/public/shared/assistant/asst-menu.js +27 -11
  222. package/neural-interface/public/shared/assistant/asst-panel.js +198 -42
  223. package/neural-interface/public/shared/assistant/asst-render.js +197 -23
  224. package/neural-interface/public/shared/assistant/asst-route-models.js +108 -0
  225. package/neural-interface/public/shared/assistant/asst-route.js +95 -343
  226. package/neural-interface/public/shared/assistant/asst-routes-editor.js +534 -0
  227. package/neural-interface/public/shared/assistant/asst-sanitize.js +8 -1
  228. package/neural-interface/public/shared/assistant/asst-sidepanel.js +31 -9
  229. package/neural-interface/public/shared/assistant/asst-slash.js +1 -1
  230. package/neural-interface/public/shared/assistant/asst-state.js +186 -2
  231. package/neural-interface/public/shared/assistant/asst-styles.js +247 -11
  232. package/neural-interface/public/shared/blob-store.js +111 -22
  233. package/neural-interface/public/shared/cdx/cdx-commands.js +4 -1
  234. package/neural-interface/public/shared/cdx/cdx-features.js +22 -14
  235. package/neural-interface/public/shared/cdx/cdx-icons.js +2 -0
  236. package/neural-interface/public/shared/cdx/cdx-panel.js +80 -118
  237. package/neural-interface/public/shared/cdx/cdx-render.js +25 -89
  238. package/neural-interface/public/shared/cdx/cdx-settings.js +231 -0
  239. package/neural-interface/public/shared/cdx/cdx-styles.js +164 -107
  240. package/neural-interface/public/shared/cdx/cdx-tabs.js +348 -668
  241. package/neural-interface/public/shared/cdx/cdx-ws.js +2 -0
  242. package/neural-interface/public/shared/claude-account-view.js +3 -0
  243. package/neural-interface/public/shared/cli-install-view.js +392 -0
  244. package/neural-interface/public/shared/cli-status.js +282 -22
  245. package/neural-interface/public/shared/constants.js +6 -1
  246. package/neural-interface/public/shared/cp/cp-events.js +2 -1
  247. package/neural-interface/public/shared/cp/cp-rehydrate.js +2 -1
  248. package/neural-interface/public/shared/cp/cp-styles.js +61 -0
  249. package/neural-interface/public/shared/desktop-bridge.js +39 -0
  250. package/neural-interface/public/shared/desktop-titlebar-page.js +59 -0
  251. package/neural-interface/public/shared/desktop-titlebar-view.js +122 -0
  252. package/neural-interface/public/shared/desktop-titlebar.js +153 -0
  253. package/neural-interface/public/shared/desktop-update-view.js +462 -0
  254. package/neural-interface/public/shared/editor/editor-ai-logic.js +409 -0
  255. package/neural-interface/public/shared/editor/editor-ai.js +619 -0
  256. package/neural-interface/public/shared/editor/editor-commands.js +212 -0
  257. package/neural-interface/public/shared/editor/editor-compare.js +103 -0
  258. package/neural-interface/public/shared/editor/editor-completion-list.js +172 -0
  259. package/neural-interface/public/shared/editor/editor-doc.js +257 -0
  260. package/neural-interface/public/shared/editor/editor-git-logic.js +131 -0
  261. package/neural-interface/public/shared/editor/editor-git.js +95 -0
  262. package/neural-interface/public/shared/editor/editor-languages.js +156 -0
  263. package/neural-interface/public/shared/editor/editor-lint.js +229 -0
  264. package/neural-interface/public/shared/editor/editor-loader.js +51 -0
  265. package/neural-interface/public/shared/editor/editor-markdown.js +90 -0
  266. package/neural-interface/public/shared/editor/editor-menu.js +233 -0
  267. package/neural-interface/public/shared/editor/editor-minimap.js +371 -0
  268. package/neural-interface/public/shared/editor/editor-palette-logic.js +192 -0
  269. package/neural-interface/public/shared/editor/editor-palette.js +125 -0
  270. package/neural-interface/public/shared/editor/editor-panel-logic.js +288 -0
  271. package/neural-interface/public/shared/editor/editor-panel.js +2099 -0
  272. package/neural-interface/public/shared/editor/editor-prefs.js +224 -0
  273. package/neural-interface/public/shared/editor/editor-safety.js +500 -0
  274. package/neural-interface/public/shared/editor/editor-search.js +352 -0
  275. package/neural-interface/public/shared/editor/editor-statusbar.js +144 -0
  276. package/neural-interface/public/shared/editor/editor-tabs-logic.js +331 -0
  277. package/neural-interface/public/shared/editor/editor-tabs.js +233 -0
  278. package/neural-interface/public/shared/editor/editor-theme.js +244 -0
  279. package/neural-interface/public/shared/editor/editor-view.js +332 -0
  280. package/neural-interface/public/shared/explorer/fx-api.js +216 -0
  281. package/neural-interface/public/shared/explorer/fx-links.js +204 -0
  282. package/neural-interface/public/shared/explorer/fx-logic.js +537 -0
  283. package/neural-interface/public/shared/explorer/fx-main.js +865 -0
  284. package/neural-interface/public/shared/explorer/fx-names.js +87 -0
  285. package/neural-interface/public/shared/explorer/fx-ops.js +370 -0
  286. package/neural-interface/public/shared/explorer/fx-popups.js +490 -0
  287. package/neural-interface/public/shared/explorer/fx-tree.js +790 -0
  288. package/neural-interface/public/shared/file-links.js +339 -0
  289. package/neural-interface/public/shared/git-bash-view.js +145 -0
  290. package/neural-interface/public/shared/greeting/greeting-card.js +178 -0
  291. package/neural-interface/public/shared/greeting/greeting-view.js +148 -0
  292. package/neural-interface/public/shared/html-shell.js +161 -165
  293. package/neural-interface/public/shared/i18n.js +19 -1
  294. package/neural-interface/public/shared/install-details-view.js +86 -0
  295. package/neural-interface/public/shared/ocp-v2/ocp-v2-childpanel.js +4 -0
  296. package/neural-interface/public/shared/ocp-v2/ocp-v2-greeting.js +47 -0
  297. package/neural-interface/public/shared/ocp-v2/ocp-v2-panel.js +131 -17
  298. package/neural-interface/public/shared/ocp-v2/ocp-v2-render.js +7 -1
  299. package/neural-interface/public/shared/ocp-v2/ocp-v2-send.js +22 -0
  300. package/neural-interface/public/shared/ocp-v2/ocp-v2-styles.js +158 -0
  301. package/neural-interface/public/shared/ocp-v2/ocp-v2-ws.js +3 -2
  302. package/neural-interface/public/shared/pwa-install-page.js +32 -2
  303. package/neural-interface/public/shared/pwa-install.css +3 -3
  304. package/neural-interface/public/shared/pwa-install.js +100 -1
  305. package/neural-interface/public/shared/settings/settings-about-pane.js +271 -0
  306. package/neural-interface/public/shared/settings/settings-about.js +254 -0
  307. package/neural-interface/public/shared/settings/settings-code-editor-pane.js +412 -0
  308. package/neural-interface/public/shared/settings/settings-code-editor.js +328 -0
  309. package/neural-interface/public/shared/settings/settings-greeting.js +133 -0
  310. package/neural-interface/public/shared/settings/settings-ia.js +33 -4
  311. package/neural-interface/public/shared/settings/settings-user-context.js +154 -0
  312. package/neural-interface/public/shared/showcase-privacy.js +489 -0
  313. package/neural-interface/public/shared/start-bridge.js +238 -19
  314. package/neural-interface/public/shared/storage.js +30 -3
  315. package/neural-interface/public/shared/styles.css +1710 -770
  316. package/neural-interface/public/shared/synabun-mascot.js +68 -58
  317. package/neural-interface/public/shared/tunnel-view.js +167 -0
  318. package/neural-interface/public/shared/ui-claude-panel.js +369 -229
  319. package/neural-interface/public/shared/ui-cli-banner.js +355 -0
  320. package/neural-interface/public/shared/ui-detail.js +15 -0
  321. package/neural-interface/public/shared/ui-explorer.js +22 -0
  322. package/neural-interface/public/shared/ui-file-explorer.js +481 -2496
  323. package/neural-interface/public/shared/ui-file-links.js +103 -0
  324. package/neural-interface/public/shared/ui-git-bash.js +124 -0
  325. package/neural-interface/public/shared/ui-help.js +26 -0
  326. package/neural-interface/public/shared/ui-invite.js +126 -116
  327. package/neural-interface/public/shared/ui-judgments.js +10 -1
  328. package/neural-interface/public/shared/ui-keybinds.js +4 -0
  329. package/neural-interface/public/shared/ui-loading.js +187 -19
  330. package/neural-interface/public/shared/ui-menubar.js +25 -33
  331. package/neural-interface/public/shared/ui-native-loop-router-state.js +11 -0
  332. package/neural-interface/public/shared/ui-native-loop-router.js +15 -2
  333. package/neural-interface/public/shared/ui-navbar.js +48 -22
  334. package/neural-interface/public/shared/ui-provider-auth.js +104 -0
  335. package/neural-interface/public/shared/ui-provider-terminal-auth.js +223 -0
  336. package/neural-interface/public/shared/ui-sessions.js +9 -3
  337. package/neural-interface/public/shared/ui-settings.js +509 -490
  338. package/neural-interface/public/shared/ui-sidepanel-runtime.js +2 -1
  339. package/neural-interface/public/shared/ui-sidepanel-sessions.js +3 -1
  340. package/neural-interface/public/shared/ui-sync.js +22 -0
  341. package/neural-interface/public/shared/ui-terminal.js +40 -5
  342. package/neural-interface/public/shared/ui-tool-updates.js +5 -0
  343. package/neural-interface/public/shared/ui-tunnel.js +130 -0
  344. package/neural-interface/public/shared/ui-tutorial-steps.js +6 -2
  345. package/neural-interface/public/shared/ui-update.js +594 -5
  346. package/neural-interface/public/shared/ui-whatsapp.js +21 -6
  347. package/neural-interface/public/shared/ui-whiteboard.js +12 -0
  348. package/neural-interface/public/shared/ui-worker-end.js +245 -0
  349. package/neural-interface/public/shared/ui-workspaces.js +41 -27
  350. package/neural-interface/public/shared/whatsapp/wa-view.js +51 -8
  351. package/neural-interface/public/shared/worker-end.js +253 -0
  352. package/neural-interface/public/sw.js +2 -2
  353. package/neural-interface/public/variant/2d/main.js +10 -1
  354. package/neural-interface/public/variant/3d/main.js +10 -1
  355. package/neural-interface/public/vendor/codemirror/chunks/apl-CSDKT72Z.js +1 -0
  356. package/neural-interface/public/vendor/codemirror/chunks/asciiarmor-JYYPU5BM.js +1 -0
  357. package/neural-interface/public/vendor/codemirror/chunks/asn1-NRWCZDA6.js +1 -0
  358. package/neural-interface/public/vendor/codemirror/chunks/asterisk-5OU6D4ZQ.js +1 -0
  359. package/neural-interface/public/vendor/codemirror/chunks/brainfuck-ID4N4SYC.js +1 -0
  360. package/neural-interface/public/vendor/codemirror/chunks/chunk-4RZWGCS2.js +1 -0
  361. package/neural-interface/public/vendor/codemirror/chunks/chunk-ACTJM3JR.js +11 -0
  362. package/neural-interface/public/vendor/codemirror/chunks/chunk-S6BMAXLK.js +1 -0
  363. package/neural-interface/public/vendor/codemirror/chunks/chunk-TO2RDOHQ.js +3 -0
  364. package/neural-interface/public/vendor/codemirror/chunks/chunk-US2GMZZQ.js +13 -0
  365. package/neural-interface/public/vendor/codemirror/chunks/chunk-WYYO5ZAJ.js +1 -0
  366. package/neural-interface/public/vendor/codemirror/chunks/chunk-XALZTDJC.js +1 -0
  367. package/neural-interface/public/vendor/codemirror/chunks/chunk-YRNUTRDV.js +1 -0
  368. package/neural-interface/public/vendor/codemirror/chunks/chunk-Z3QOKH62.js +1 -0
  369. package/neural-interface/public/vendor/codemirror/chunks/clike-OWQBSOGL.js +1 -0
  370. package/neural-interface/public/vendor/codemirror/chunks/clojure-KV75UQWC.js +1 -0
  371. package/neural-interface/public/vendor/codemirror/chunks/cmake-GTEP5Y3C.js +1 -0
  372. package/neural-interface/public/vendor/codemirror/chunks/cobol-WCZ7QEGJ.js +1 -0
  373. package/neural-interface/public/vendor/codemirror/chunks/coffeescript-TGLBOT6B.js +1 -0
  374. package/neural-interface/public/vendor/codemirror/chunks/commonlisp-WVVI432V.js +1 -0
  375. package/neural-interface/public/vendor/codemirror/chunks/crystal-S6R6HLKQ.js +1 -0
  376. package/neural-interface/public/vendor/codemirror/chunks/css-PDA2RINP.js +1 -0
  377. package/neural-interface/public/vendor/codemirror/chunks/cypher-HL5QPL4C.js +1 -0
  378. package/neural-interface/public/vendor/codemirror/chunks/d-HHJH2HAJ.js +1 -0
  379. package/neural-interface/public/vendor/codemirror/chunks/diff-MN3A35BY.js +1 -0
  380. package/neural-interface/public/vendor/codemirror/chunks/dist-25SQLBVS.js +3 -0
  381. package/neural-interface/public/vendor/codemirror/chunks/dist-27ZGGJJS.js +1 -0
  382. package/neural-interface/public/vendor/codemirror/chunks/dist-4E52OJIF.js +1 -0
  383. package/neural-interface/public/vendor/codemirror/chunks/dist-6FT73XDC.js +2 -0
  384. package/neural-interface/public/vendor/codemirror/chunks/dist-BE6YGRMW.js +1 -0
  385. package/neural-interface/public/vendor/codemirror/chunks/dist-CJSGKW2O.js +1 -0
  386. package/neural-interface/public/vendor/codemirror/chunks/dist-CRPH2WLI.js +1 -0
  387. package/neural-interface/public/vendor/codemirror/chunks/dist-CTG7JEQN.js +1 -0
  388. package/neural-interface/public/vendor/codemirror/chunks/dist-I3FEVELX.js +1 -0
  389. package/neural-interface/public/vendor/codemirror/chunks/dist-IM5BBSWZ.js +1 -0
  390. package/neural-interface/public/vendor/codemirror/chunks/dist-KERUKTIF.js +1 -0
  391. package/neural-interface/public/vendor/codemirror/chunks/dist-LXTMWZAM.js +1 -0
  392. package/neural-interface/public/vendor/codemirror/chunks/dist-MABASSET.js +1 -0
  393. package/neural-interface/public/vendor/codemirror/chunks/dist-MJVBUZLL.js +3 -0
  394. package/neural-interface/public/vendor/codemirror/chunks/dist-MNB3WZVU.js +1 -0
  395. package/neural-interface/public/vendor/codemirror/chunks/dist-QYWXOE3U.js +7 -0
  396. package/neural-interface/public/vendor/codemirror/chunks/dist-TEBOFWLZ.js +1 -0
  397. package/neural-interface/public/vendor/codemirror/chunks/dist-UNXFROM3.js +1 -0
  398. package/neural-interface/public/vendor/codemirror/chunks/dist-XL2SLQO6.js +1 -0
  399. package/neural-interface/public/vendor/codemirror/chunks/dist-XO42Y3AP.js +6 -0
  400. package/neural-interface/public/vendor/codemirror/chunks/dist-Y2WWDWJK.js +1 -0
  401. package/neural-interface/public/vendor/codemirror/chunks/dist-YFEZKWMU.js +1 -0
  402. package/neural-interface/public/vendor/codemirror/chunks/dist-ZY7SWQO6.js +1 -0
  403. package/neural-interface/public/vendor/codemirror/chunks/dockerfile-3Y4R4NCH.js +1 -0
  404. package/neural-interface/public/vendor/codemirror/chunks/dtd-5343GJ4P.js +1 -0
  405. package/neural-interface/public/vendor/codemirror/chunks/dylan-FI2CXSW2.js +1 -0
  406. package/neural-interface/public/vendor/codemirror/chunks/ebnf-GNQ77YWA.js +1 -0
  407. package/neural-interface/public/vendor/codemirror/chunks/ecl-MRPUAE2L.js +1 -0
  408. package/neural-interface/public/vendor/codemirror/chunks/eiffel-DZROES27.js +1 -0
  409. package/neural-interface/public/vendor/codemirror/chunks/elm-4KICRFKQ.js +1 -0
  410. package/neural-interface/public/vendor/codemirror/chunks/erlang-3IHYC263.js +1 -0
  411. package/neural-interface/public/vendor/codemirror/chunks/factor-C6D3E5UK.js +1 -0
  412. package/neural-interface/public/vendor/codemirror/chunks/fcl-VYTWUJMI.js +1 -0
  413. package/neural-interface/public/vendor/codemirror/chunks/forth-ZBO2EH5M.js +1 -0
  414. package/neural-interface/public/vendor/codemirror/chunks/fortran-5NDCRWIK.js +1 -0
  415. package/neural-interface/public/vendor/codemirror/chunks/gas-SKRMOXFP.js +1 -0
  416. package/neural-interface/public/vendor/codemirror/chunks/gherkin-L45YXZLW.js +1 -0
  417. package/neural-interface/public/vendor/codemirror/chunks/groovy-GLPTLN44.js +1 -0
  418. package/neural-interface/public/vendor/codemirror/chunks/haskell-E7NF7P4Y.js +1 -0
  419. package/neural-interface/public/vendor/codemirror/chunks/haxe-K2NVDOB6.js +1 -0
  420. package/neural-interface/public/vendor/codemirror/chunks/http-Q6DRQIJB.js +1 -0
  421. package/neural-interface/public/vendor/codemirror/chunks/idl-MZYNJVLN.js +1 -0
  422. package/neural-interface/public/vendor/codemirror/chunks/javascript-6YRYK2HR.js +1 -0
  423. package/neural-interface/public/vendor/codemirror/chunks/julia-HXEL2T5G.js +1 -0
  424. package/neural-interface/public/vendor/codemirror/chunks/livescript-MV7CI2JZ.js +1 -0
  425. package/neural-interface/public/vendor/codemirror/chunks/lua-E36NHOOD.js +1 -0
  426. package/neural-interface/public/vendor/codemirror/chunks/mathematica-3XOZZCMC.js +1 -0
  427. package/neural-interface/public/vendor/codemirror/chunks/mbox-ODYGFKS7.js +1 -0
  428. package/neural-interface/public/vendor/codemirror/chunks/mirc-WB43AWF5.js +1 -0
  429. package/neural-interface/public/vendor/codemirror/chunks/mllike-ZT6ET7ZH.js +1 -0
  430. package/neural-interface/public/vendor/codemirror/chunks/modelica-LLMZPFGA.js +1 -0
  431. package/neural-interface/public/vendor/codemirror/chunks/mscgen-2OPNNYFH.js +1 -0
  432. package/neural-interface/public/vendor/codemirror/chunks/mumps-6P3HWJH6.js +1 -0
  433. package/neural-interface/public/vendor/codemirror/chunks/nginx-TCGKQTRW.js +1 -0
  434. package/neural-interface/public/vendor/codemirror/chunks/nsis-ATIGIXTJ.js +1 -0
  435. package/neural-interface/public/vendor/codemirror/chunks/ntriples-5PLBI5OV.js +1 -0
  436. package/neural-interface/public/vendor/codemirror/chunks/octave-QF2S3NL6.js +1 -0
  437. package/neural-interface/public/vendor/codemirror/chunks/oz-JFIVFFH2.js +1 -0
  438. package/neural-interface/public/vendor/codemirror/chunks/pascal-JG6SW76V.js +1 -0
  439. package/neural-interface/public/vendor/codemirror/chunks/perl-4B3IWVVO.js +1 -0
  440. package/neural-interface/public/vendor/codemirror/chunks/pig-ABEBH4MI.js +1 -0
  441. package/neural-interface/public/vendor/codemirror/chunks/powershell-H32XE7TL.js +1 -0
  442. package/neural-interface/public/vendor/codemirror/chunks/properties-NN644MMA.js +1 -0
  443. package/neural-interface/public/vendor/codemirror/chunks/protobuf-YKWQK2J3.js +1 -0
  444. package/neural-interface/public/vendor/codemirror/chunks/pug-RIYXEKFW.js +1 -0
  445. package/neural-interface/public/vendor/codemirror/chunks/puppet-JZQ5WPEV.js +1 -0
  446. package/neural-interface/public/vendor/codemirror/chunks/python-EBCGGHAC.js +1 -0
  447. package/neural-interface/public/vendor/codemirror/chunks/q-5UMH2YQY.js +1 -0
  448. package/neural-interface/public/vendor/codemirror/chunks/r-7XMGG453.js +1 -0
  449. package/neural-interface/public/vendor/codemirror/chunks/rpm-IEV7TSLR.js +1 -0
  450. package/neural-interface/public/vendor/codemirror/chunks/ruby-T4SPFPNM.js +1 -0
  451. package/neural-interface/public/vendor/codemirror/chunks/sas-GEDX67ET.js +1 -0
  452. package/neural-interface/public/vendor/codemirror/chunks/scheme-FTLOWKPC.js +1 -0
  453. package/neural-interface/public/vendor/codemirror/chunks/shell-HUFRKFSJ.js +1 -0
  454. package/neural-interface/public/vendor/codemirror/chunks/sieve-P5QUDVYO.js +1 -0
  455. package/neural-interface/public/vendor/codemirror/chunks/smalltalk-2SORJNQI.js +1 -0
  456. package/neural-interface/public/vendor/codemirror/chunks/solr-M22TGAR5.js +1 -0
  457. package/neural-interface/public/vendor/codemirror/chunks/sparql-4M3KL752.js +1 -0
  458. package/neural-interface/public/vendor/codemirror/chunks/spreadsheet-3K23LA4N.js +1 -0
  459. package/neural-interface/public/vendor/codemirror/chunks/sql-VHRFMUBI.js +1 -0
  460. package/neural-interface/public/vendor/codemirror/chunks/stex-QZDAQUY2.js +1 -0
  461. package/neural-interface/public/vendor/codemirror/chunks/stylus-7ZDKAKBD.js +1 -0
  462. package/neural-interface/public/vendor/codemirror/chunks/swift-WCLCLGMR.js +1 -0
  463. package/neural-interface/public/vendor/codemirror/chunks/tcl-JLMU6WOK.js +1 -0
  464. package/neural-interface/public/vendor/codemirror/chunks/textile-4CHDKZ4T.js +1 -0
  465. package/neural-interface/public/vendor/codemirror/chunks/tiddlywiki-DKMCZZQ4.js +1 -0
  466. package/neural-interface/public/vendor/codemirror/chunks/tiki-F4JIG36Q.js +1 -0
  467. package/neural-interface/public/vendor/codemirror/chunks/toml-BHMHTIM2.js +1 -0
  468. package/neural-interface/public/vendor/codemirror/chunks/troff-YQ2KV5NT.js +1 -0
  469. package/neural-interface/public/vendor/codemirror/chunks/ttcn-ZHRCVFJY.js +1 -0
  470. package/neural-interface/public/vendor/codemirror/chunks/ttcn-cfg-KJOVTY4X.js +1 -0
  471. package/neural-interface/public/vendor/codemirror/chunks/turtle-535P5N6I.js +1 -0
  472. package/neural-interface/public/vendor/codemirror/chunks/vb-76UMQHOT.js +1 -0
  473. package/neural-interface/public/vendor/codemirror/chunks/vbscript-CGNDTK6Z.js +1 -0
  474. package/neural-interface/public/vendor/codemirror/chunks/velocity-VSJDO5T5.js +1 -0
  475. package/neural-interface/public/vendor/codemirror/chunks/verilog-4T6ETXIP.js +1 -0
  476. package/neural-interface/public/vendor/codemirror/chunks/vhdl-T7FNAXUN.js +1 -0
  477. package/neural-interface/public/vendor/codemirror/chunks/webidl-P6MJSJ6J.js +1 -0
  478. package/neural-interface/public/vendor/codemirror/chunks/xquery-UOVILRGN.js +1 -0
  479. package/neural-interface/public/vendor/codemirror/chunks/yacas-CV2APROL.js +1 -0
  480. package/neural-interface/public/vendor/codemirror/chunks/z80-3KFNVM4M.js +1 -0
  481. package/neural-interface/public/vendor/codemirror/codemirror-6.43.14-75f05e67.min.js +2 -0
  482. package/neural-interface/public/vendor/codemirror/manifest.json +60 -0
  483. package/neural-interface/scripts/build-vendor.mjs +78 -2
  484. package/neural-interface/scripts/vendor-codemirror-entry.js +121 -0
  485. package/neural-interface/server.js +2085 -1629
  486. package/neural-interface/templates/rulesets/README.md +1 -1
  487. package/package.json +5 -8
  488. package/setup.js +53 -15
  489. package/benchmarks/browser-live-results.json +0 -79
  490. package/benchmarks/browser-v2-results.json +0 -258
  491. package/neural-interface/lib/codex-capabilities.d.ts +0 -41
  492. package/neural-interface/public/category-logos/claude.svg +0 -1
  493. package/neural-interface/public/category-logos/gemini-color.svg +0 -1
  494. package/neural-interface/public/category-logos/openai.svg +0 -1
  495. package/neural-interface/public/category-logos/synabun.png +0 -0
  496. package/neural-interface/public/claude.svg +0 -1
  497. package/neural-interface/public/gallery.svg +0 -6
  498. package/neural-interface/public/leonardoai.svg +0 -1
  499. package/neural-interface/public/mcp.svg +0 -4
  500. package/neural-interface/public/opencode-logo-dark-square.svg +0 -1
  501. package/neural-interface/public/pin-svgrepo-com.svg +0 -25
  502. package/neural-interface/public/sessionicon.svg +0 -8
  503. package/neural-interface/public/toolbar-album.svg +0 -8
  504. package/neural-interface/public/toolbar-question.svg +0 -6
  505. package/neural-interface/public/toolbar-sessions.svg +0 -6
  506. package/neural-interface/scripts/codex-protocol-fixture.mjs +0 -83
  507. package/skills/synabun/synabunicon.png +0 -0
@@ -0,0 +1,216 @@
1
+ // ═══════════════════════════════════════════
2
+ // SynaBun Neural Interface — File Explorer: the server
3
+ // ═══════════════════════════════════════════
4
+ //
5
+ // Every request the explorer makes. The page reloads at any time and the
6
+ // server only on a restart, so it works against an older server with what that
7
+ // has: the listing and search of /api/project-files, git from /api/git/status,
8
+ // a new file or folder and a delete through the editor's routes. Whether the
9
+ // server has the explorer's own routes (lib/file-explorer-api.js) it is told
10
+ // by the answer of GET /api/projects, which the panel asks for anyway
11
+ // (`serverSays`): an older server lists nothing there, and nothing of
12
+ // /api/explorer is ever asked of it. What it cannot do answers
13
+ // `{ ok: false, code: 'unsupported' }` here, without a request.
14
+ // Nothing in this file throws: a call resolves to `{ ok: true, … }` or to
15
+ // `{ ok: false, code, … }` (`offline` when the server did not answer).
16
+
17
+ import { fromLegacyListing, fromLegacySearch, trimSlash } from './fx-logic.js';
18
+
19
+ const JSON_HEADERS = { 'Content-Type': 'application/json' };
20
+ const RECONNECT_MS = [1500, 3000, 6000, 12000, 30000];
21
+
22
+ /**
23
+ * @param {{ fetchImpl?: typeof fetch, EventSourceImpl?: typeof EventSource }} [o]
24
+ */
25
+ export function createExplorerApi({ fetchImpl = (...args) => fetch(...args), EventSourceImpl = globalThis.EventSource } = {}) {
26
+ let asked = null; // the one question about what the server has
27
+ let listed = null; // what GET /api/projects said this server has
28
+ let caps = { known: false, explorer: false, info: null };
29
+
30
+ async function request(url, init) {
31
+ let res;
32
+ try { res = await fetchImpl(url, init); } catch (error) { return { ok: false, code: error?.name === 'AbortError' ? 'aborted' : 'offline' }; }
33
+ let body = null;
34
+ try { body = await res.json(); } catch { body = null; }
35
+ if (res.ok && body && body.ok !== false) return { ok: true, ...body };
36
+ // The server's first gate answers an invited guest 403 "Admin only", without a code of its own.
37
+ const guest = res.status === 403 && body?.error === 'Admin only';
38
+ return { ...(body && typeof body === 'object' ? body : {}), ok: false, code: body?.code || (guest ? 'GUEST_FORBIDDEN' : res.status === 403 ? 'denied' : res.status === 404 ? 'gone' : 'failed'), status: res.status };
39
+ }
40
+ const post = (path, body) => request(`/api/explorer${path}`, { method: 'POST', headers: JSON_HEADERS, body: JSON.stringify(body) });
41
+ const unsupported = () => Promise.resolve({ ok: false, code: 'unsupported' });
42
+
43
+ /**
44
+ * What GET /api/projects listed as this server's capabilities (null when it did not answer). Called by the panel
45
+ * each time it reads the projects: a server that was restarted since is found out by the next read.
46
+ */
47
+ function serverSays(list) {
48
+ const has = Array.isArray(list) && list.includes('explorer');
49
+ if (listed !== null && has === caps.explorer && caps.known) return;
50
+ listed = Array.isArray(list) ? list : (list === null ? null : []);
51
+ asked = null;
52
+ caps = { known: false, explorer: false, info: null };
53
+ }
54
+
55
+ /** What the server can do: its own word on the explorer's routes, asked for once it says it has them. */
56
+ function capabilities() {
57
+ if (!asked) {
58
+ asked = (async () => {
59
+ if (listed === null) { asked = null; return caps; } // not told yet: the next call looks again
60
+ const has = listed.includes('explorer');
61
+ const info = has ? await request('/api/explorer/info') : null;
62
+ if (has && !info.ok && info.code === 'offline') { asked = null; return caps; }
63
+ caps = { known: true, explorer: !!(has && info?.ok), info: info?.ok ? info : null };
64
+ return caps;
65
+ })();
66
+ }
67
+ return asked;
68
+ }
69
+
70
+ /** What is known of the server right now (after `capabilities()` answered). */
71
+ const abilities = () => ({
72
+ known: caps.known,
73
+ ops: caps.explorer,
74
+ watch: caps.explorer,
75
+ trash: caps.explorer && !!caps.info?.trash,
76
+ reveal: caps.explorer && !!caps.info?.reveal,
77
+ preview: caps.explorer,
78
+ platform: caps.info?.platform || null,
79
+ });
80
+
81
+ async function list(path) {
82
+ await capabilities();
83
+ if (caps.explorer) return request(`/api/explorer/list?path=${encodeURIComponent(path)}`);
84
+ const old = await request(`/api/project-files?path=${encodeURIComponent(path)}`);
85
+ if (!old.ok) {
86
+ // The older route words its failures itself: a folder that is not there, a path that is not allowed.
87
+ return { ok: false, code: old.code === 'offline' ? 'offline' : old.status === 403 ? (old.code === 'GUEST_FORBIDDEN' ? old.code : 'outside') : old.status === 400 ? 'gone' : 'failed' };
88
+ }
89
+ return fromLegacyListing(old);
90
+ }
91
+
92
+ async function search(root, query, signal) {
93
+ await capabilities();
94
+ if (caps.explorer) return request(`/api/explorer/search?root=${encodeURIComponent(root)}&q=${encodeURIComponent(query)}`, { signal });
95
+ const old = await request(`/api/project-files?${new URLSearchParams({ path: root, search: query, recursive: '1' })}`, { signal });
96
+ return old.ok ? fromLegacySearch(old) : old;
97
+ }
98
+
99
+ async function git(root) {
100
+ await capabilities();
101
+ if (caps.explorer) return request(`/api/explorer/git?root=${encodeURIComponent(root)}`);
102
+ const old = await request(`/api/git/status?path=${encodeURIComponent(root)}`);
103
+ if (!old.ok) return old;
104
+ if (!old.isGit) return { ok: true, isGit: false };
105
+ const changes = {};
106
+ for (const change of old.changes || []) if (change?.path) changes[change.path] = change.status;
107
+ return { ok: true, isGit: true, branch: old.branch || '', changes, ignored: [], legacy: true };
108
+ }
109
+
110
+ async function create(parent, name, type) {
111
+ await capabilities();
112
+ if (caps.explorer) return post('/create', { parent, name, type });
113
+ // An older server: its own two routes. It would write over a file, or take a folder that is there for a new
114
+ // one, so the folder is read first and a name that is taken is refused here.
115
+ const there = await list(parent);
116
+ if (!there.ok) return there;
117
+ if (there.items.some((item) => item.name.toLowerCase() === name.toLowerCase())) return { ok: false, code: 'exists', name };
118
+ const path = `${trimSlash(parent)}/${name}`;
119
+ const made = type === 'dir'
120
+ ? await request('/api/file-mkdir', { method: 'POST', headers: JSON_HEADERS, body: JSON.stringify({ path }) })
121
+ : await request('/api/file-content', { method: 'POST', headers: JSON_HEADERS, body: JSON.stringify({ path, content: '', create: true, expectAbsent: true }) });
122
+ if (made.ok) return { ok: true, path, type };
123
+ return { ok: false, code: made.status === 409 ? 'exists' : made.status === 403 ? 'denied' : made.code === 'offline' ? 'offline' : 'failed', name };
124
+ }
125
+
126
+ async function remove(paths, { permanent = false } = {}) {
127
+ await capabilities();
128
+ if (caps.explorer) return post('/delete', { paths, permanent });
129
+ // An older server deletes for good, one entry at a time, and a folder only when it is empty.
130
+ if (!permanent) return { ok: false, code: 'no-trash' };
131
+ const deleted = [];
132
+ for (const path of paths) {
133
+ const done = await request(`/api/file-content?path=${encodeURIComponent(path)}`, { method: 'DELETE' });
134
+ if (done.ok || done.status === 404) { deleted.push(path); continue; }
135
+ const notEmpty = done.status === 400 && /not empty/i.test(String(done.error || ''));
136
+ return { ok: false, code: notEmpty ? 'not-empty' : done.status === 403 ? 'denied' : done.code === 'offline' ? 'offline' : 'failed', deleted, failed: path };
137
+ }
138
+ return { ok: true, deleted, trashed: false };
139
+ }
140
+
141
+ const guarded = (call) => async (...args) => { await capabilities(); return caps.explorer ? call(...args) : unsupported(); };
142
+
143
+ /**
144
+ * Follow a project on disk. `onChange({ dirs, git })` names the shown folders that changed; `onReady(again)` says
145
+ * the stream is up (`again`: after it was down, so anything may have changed meanwhile). A stream is not a watch
146
+ * that works: `onState({ live, scope })` says what the server really watches, at the start and when it changes
147
+ * (`live`: 'full', 'partial' when some folders could not be watched, 'none' when the project is not watched at
148
+ * all; `scope`: 'tree', or 'folders' where only the shown folders are watched). `onResync()`: the server lost
149
+ * its watch on the project; it tries for it again by itself, and nothing is sent back for the report (what is
150
+ * shown may be stale, the folders that are shown are the ones it was told). Null on a server that has no
151
+ * watch. The connection is tried again by itself, ever more slowly, until `close()`.
152
+ */
153
+ function watch(root, { onChange, onReady = () => {}, onDown = () => {}, onState = () => {}, onResync = () => {} }) {
154
+ if (!caps.explorer || typeof EventSourceImpl !== 'function') return null;
155
+ let source = null; let id = null; let dirs = []; let closed = false; let attempt = 0; let timer = 0; let pushTimer = 0; let wasUp = false;
156
+ const push = () => {
157
+ clearTimeout(pushTimer);
158
+ pushTimer = setTimeout(() => { if (id && !closed) post(`/watch/${id}`, { dirs }); }, 120);
159
+ };
160
+ const connect = () => {
161
+ if (closed) return;
162
+ source = new EventSourceImpl(`/api/explorer/watch?root=${encodeURIComponent(root)}`);
163
+ const say = (data) => onState({ live: ['partial', 'none'].includes(data?.live) ? data.live : 'full', scope: data?.scope === 'folders' ? 'folders' : 'tree' });
164
+ source.addEventListener('ready', (event) => {
165
+ let said = null;
166
+ try { said = JSON.parse(event.data); } catch { said = null; }
167
+ id = said?.id || null;
168
+ attempt = 0;
169
+ push();
170
+ say(said);
171
+ onReady(wasUp);
172
+ wasUp = true;
173
+ });
174
+ source.addEventListener('state', (event) => { try { say(JSON.parse(event.data)); } catch { /* skipped, as below */ } });
175
+ source.addEventListener('change', (event) => { try { onChange(JSON.parse(event.data)); } catch { /* a report that cannot be read is skipped */ } });
176
+ source.addEventListener('resync', () => onResync());
177
+ source.onerror = () => {
178
+ // The browser would try again every three seconds for as long as the page lives: tried here, more slowly.
179
+ try { source.close(); } catch { /* closed */ }
180
+ id = null;
181
+ if (closed) return;
182
+ onDown();
183
+ timer = setTimeout(connect, RECONNECT_MS[Math.min(attempt++, RECONNECT_MS.length - 1)]);
184
+ };
185
+ };
186
+ connect();
187
+ return {
188
+ setDirs(list) { dirs = [...list]; push(); },
189
+ close() { closed = true; clearTimeout(timer); clearTimeout(pushTimer); try { source?.close(); } catch { /* closed */ } },
190
+ };
191
+ }
192
+
193
+ return {
194
+ serverSays,
195
+ capabilities,
196
+ abilities,
197
+ list,
198
+ search,
199
+ git,
200
+ create,
201
+ remove,
202
+ rename: guarded((path, name) => post('/rename', { path, name })),
203
+ // `permanent`: what a replace clears may be removed for good when the Trash cannot take it (the user was asked).
204
+ // `replace`: the names that may be replaced (the ones the user was asked about), or false.
205
+ move: guarded((paths, into, { replace = false, permanent = false } = {}) => post('/move', { paths, into, replace, permanent })),
206
+ copy: guarded((paths, into, { replace = false, permanent = false } = {}) => post('/copy', { paths, into, replace, permanent })),
207
+ reveal: guarded((path) => post('/reveal', { path })),
208
+ upload: guarded((file, into, { name = file.name, rel = '', replace = false, permanent = false } = {}) => request(
209
+ `/api/explorer/upload?${new URLSearchParams({ into, name, ...(rel ? { rel } : {}), ...(replace ? { replace: '1' } : {}), ...(replace && permanent ? { permanent: '1' } : {}) })}`,
210
+ { method: 'POST', headers: { 'Content-Type': 'application/octet-stream' }, body: file },
211
+ )),
212
+ /** Where the bytes of an image are (null on a server that has no preview). */
213
+ rawUrl: (path) => (caps.explorer ? `/api/explorer/raw?path=${encodeURIComponent(path)}` : null),
214
+ watch,
215
+ };
216
+ }
@@ -0,0 +1,204 @@
1
+ // ═══════════════════════════════════════════
2
+ // SynaBun Neural Interface — File Explorer: the editor and the agents
3
+ // ═══════════════════════════════════════════
4
+ //
5
+ // The two neighbours the tree talks to.
6
+ //
7
+ // The code editor (shared/editor/) says which files are open, which have
8
+ // unsaved text and which one is showing (`getEditorTabs()`, and the
9
+ // `editor-tabs-changed` event when that changes), and re-points the tab of a
10
+ // file that was renamed or moved (`repointEditorTab()`): the tab stays, with its
11
+ // text, caret, scroll position and undo history. The controller hands those
12
+ // in; nothing of the editor is read from the page or changed here.
13
+ //
14
+ // The agents: a path is handed to a side panel through the function each panel
15
+ // already has for it. What goes where, and the words for it, are decided here.
16
+
17
+ import { isWithin, trimSlash } from './fx-logic.js';
18
+
19
+ const wait = (ms) => new Promise((done) => setTimeout(done, ms));
20
+ async function until(check, ms) {
21
+ const end = Date.now() + ms;
22
+ for (;;) {
23
+ if (check()) return true;
24
+ if (Date.now() > end) return false;
25
+ await wait(40);
26
+ }
27
+ }
28
+ const sameSet = (a, b) => a.size === b.size && [...a].every((entry) => b.has(entry));
29
+ const laterFrame = (work) => (typeof requestAnimationFrame === 'function' ? requestAnimationFrame(work) : setTimeout(work, 16));
30
+
31
+ /**
32
+ * @param {object} o
33
+ * @param {(path: string, at?: { pin?: boolean }) => void} o.openFile editor-panel.js openFileInEditor
34
+ * @param {() => any} o.save editor-panel.js saveEditorPanel (the showing tab)
35
+ * @param {() => { open: { path: string, dirty: boolean }[], active: string | null }} o.tabs editor-panel.js getEditorTabs
36
+ * @param {(from: string, to: string) => { moved: object[], kept: string[] }} o.repoint editor-panel.js repointEditorTab
37
+ * @param {(listener: (tabs: object) => void) => (() => void)} o.subscribe hears `editor-tabs-changed`; gives back how to stop
38
+ * @param {(state: { open: Set<string>, dirty: Set<string>, active: string | null }) => void} o.onChange
39
+ * @param {(work: () => void) => any} [o.later] runs `work` soon (a frame): several changes are one redraw
40
+ */
41
+ export function createEditorLink({ openFile, save, tabs, repoint, subscribe, onChange, later = laterFrame }) {
42
+ let state = { open: new Set(), dirty: new Set(), active: null };
43
+ let stopHearing = null;
44
+ let due = false;
45
+
46
+ const shape = (said) => {
47
+ const next = { open: new Set(), dirty: new Set(), active: null };
48
+ for (const tab of said?.open || []) {
49
+ const path = trimSlash(tab?.path || '');
50
+ if (!path) continue;
51
+ next.open.add(path);
52
+ if (tab.dirty) next.dirty.add(path);
53
+ }
54
+ if (said?.active) next.active = trimSlash(said.active);
55
+ return next;
56
+ };
57
+ /** What the editor has open right now. */
58
+ const read = () => { try { return shape(tabs()); } catch { return shape(null); } };
59
+
60
+ function refresh() {
61
+ due = false;
62
+ if (!stopHearing) return;
63
+ const next = read();
64
+ if (next.active === state.active && sameSet(next.open, state.open) && sameSet(next.dirty, state.dirty)) return;
65
+ state = next;
66
+ onChange(state);
67
+ }
68
+ // The editor says so while it works (a first letter typed, a tab closed): the tree is drawn after it, once.
69
+ const schedule = () => { if (!due) { due = true; later(refresh); } };
70
+
71
+ /** Start following what the editor has open. */
72
+ function start() {
73
+ if (stopHearing) return;
74
+ stopHearing = subscribe(schedule) || (() => {});
75
+ schedule();
76
+ }
77
+ function stop() {
78
+ stopHearing?.();
79
+ stopHearing = null;
80
+ }
81
+
82
+ /** The open files with unsaved text that are one of `paths`, or inside one of them. */
83
+ const unsavedIn = (paths) => [...read().dirty].filter((file) => paths.some((path) => isWithin(path, file)));
84
+
85
+ /** Save one open file: its tab is shown, saved, and checked. False when it still has unsaved text after that. */
86
+ async function saveFile(path) {
87
+ const file = trimSlash(path);
88
+ openFile(file);
89
+ if (!(await until(() => read().active === file, 4000))) return false;
90
+ try { await save(); } catch { return false; }
91
+ return until(() => { const now = read(); return now.active === file && !now.dirty.has(file); }, 6000);
92
+ }
93
+
94
+ /**
95
+ * Entries were renamed or moved: the tabs of the files among them, or inside them, follow, each as it is.
96
+ * @param {{ from: string, to: string }[]} moves
97
+ * @returns {string[]} the open files that could not follow (the path each would take is open with unsaved text)
98
+ */
99
+ function follow(moves) {
100
+ const kept = [];
101
+ for (const move of moves) {
102
+ try { kept.push(...(repoint(move.from, move.to)?.kept || [])); }
103
+ catch (error) { console.warn('[file-explorer] the editor could not follow', move.from, error); }
104
+ }
105
+ return kept;
106
+ }
107
+
108
+ return { start, stop, state: () => state, read, unsavedIn, saveFile, follow };
109
+ }
110
+
111
+ // ── The agents ──
112
+
113
+ export const SEND_TARGETS = Object.freeze(['claude', 'codex', 'opencode', 'assistant']);
114
+ const TARGET_NAMES = { claude: 'Claude Code', codex: 'Codex', opencode: 'OpenCode' };
115
+
116
+ /**
117
+ * @param {object} o
118
+ * @param {object} o.deps what each panel offers: `sendToFocusedSession(kind, data)`, `claude(path)`, `codex(path)`,
119
+ * `opencode(path)`, `assistant(path)`, and `lastActive()` (the panel used last)
120
+ * @param {(key: string, params?: object) => string} o.t
121
+ */
122
+ export function createSender({ deps, t }) {
123
+ const nameOf = (target) => (target === 'session' ? t('fileExplorer.send.session') : TARGET_NAMES[target] || t('fileExplorer.send.assistant'));
124
+ /** Where "Send to AI" goes when nothing else is said: the panel that was used last. */
125
+ const current = () => { let last = null; try { last = deps.lastActive(); } catch { last = null; } return SEND_TARGETS.includes(last) ? last : 'claude'; };
126
+
127
+ /**
128
+ * Hand paths to an agent, each as a file reference of that panel. Only what a panel took counts as sent: a
129
+ * panel answers `false` for a path it did not take (the Assistant when it is switched off); anything else it
130
+ * answers, or nothing, is a path that was taken.
131
+ * @param {string[]} paths @param {string | null} [target] one of SEND_TARGETS; without it, the session window
132
+ * that has the focus, else the panel used last
133
+ * @returns {Promise<{ ok: boolean, target: string, name: string, count: number }>} `count`: how many were taken;
134
+ * `ok`: at least one was, and nothing failed
135
+ */
136
+ async function send(paths, target = null) {
137
+ const list = paths.filter(Boolean);
138
+ let to = target;
139
+ let taken = 0;
140
+ try {
141
+ if (!to) {
142
+ // A detached session that has the focus takes it: all of it, or none.
143
+ if (list.length && deps.sendToFocusedSession('path', list[0])) {
144
+ for (const path of list.slice(1)) deps.sendToFocusedSession('path', path);
145
+ return { ok: true, target: 'session', name: nameOf('session'), count: list.length };
146
+ }
147
+ to = current();
148
+ }
149
+ for (const path of list) if ((await deps[to](path)) !== false) taken++;
150
+ return { ok: taken > 0, target: to, name: nameOf(to), count: taken };
151
+ } catch (error) {
152
+ console.warn('[file-explorer] could not send to', to, error);
153
+ return { ok: false, target: to || current(), name: nameOf(to || current()), count: taken };
154
+ }
155
+ }
156
+
157
+ // Rows dragged out of the tree onto a side panel: the panel takes them as it takes "Send to AI".
158
+ let dragged = null; let marked = null; let onSent = () => {};
159
+ const surfaceOf = (event) => event.target?.closest?.('[data-sidepanel-provider]') || null;
160
+ const mark = (surface) => {
161
+ if (marked === surface) return;
162
+ marked?.classList.remove('fe-drop-agent');
163
+ marked = surface;
164
+ marked?.classList.add('fe-drop-agent');
165
+ };
166
+ const over = (event) => {
167
+ const surface = surfaceOf(event);
168
+ mark(surface && SEND_TARGETS.includes(surface.dataset.sidepanelProvider) ? surface : null);
169
+ if (!marked) return;
170
+ event.preventDefault();
171
+ event.stopPropagation();
172
+ event.dataTransfer.dropEffect = 'copy';
173
+ };
174
+ const drop = (event) => {
175
+ const surface = surfaceOf(event);
176
+ const target = surface?.dataset.sidepanelProvider;
177
+ const paths = dragged;
178
+ mark(null);
179
+ if (!paths || !SEND_TARGETS.includes(target)) return;
180
+ event.preventDefault();
181
+ event.stopPropagation();
182
+ send(paths, target).then(onSent);
183
+ };
184
+
185
+ return {
186
+ targets: () => SEND_TARGETS.map((id) => ({ id, name: nameOf(id) })),
187
+ current,
188
+ nameOf,
189
+ send,
190
+ /** Rows are being dragged: side panels take them until `dragEnd()`. */
191
+ dragStart(paths, sent) {
192
+ dragged = [...paths];
193
+ onSent = sent || (() => {});
194
+ document.addEventListener('dragover', over, true);
195
+ document.addEventListener('drop', drop, true);
196
+ },
197
+ dragEnd() {
198
+ dragged = null;
199
+ mark(null);
200
+ document.removeEventListener('dragover', over, true);
201
+ document.removeEventListener('drop', drop, true);
202
+ },
203
+ };
204
+ }