synabun 2.0.0 → 2.0.5

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 (334) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/NOTICE +5 -0
  3. package/README.md +1 -1
  4. package/THIRD-PARTY-LICENSES.md +46 -0
  5. package/benchmarks/fixtures/browser/README.md +1 -1
  6. package/benchmarks/fixtures/desktop/README.md +1 -1
  7. package/docs/whatsapp.md +2 -2
  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 +20 -0
  12. package/hooks/claude-code/stop.mjs +5 -5
  13. package/lib/start-launcher.js +88 -1
  14. package/mcp-server/package-lock.json +2 -2
  15. package/mcp-server/package.json +1 -3
  16. package/neural-interface/i18n/en.json +1500 -153
  17. package/neural-interface/i18n/pt-BR.json +1498 -152
  18. package/neural-interface/lib/assistant-api.js +62 -6
  19. package/neural-interface/lib/assistant-brains/claude.js +4 -0
  20. package/neural-interface/lib/assistant-catalog.js +179 -27
  21. package/neural-interface/lib/assistant-config.js +31 -2
  22. package/neural-interface/lib/assistant-dispatch.js +62 -13
  23. package/neural-interface/lib/assistant-hidden-models.js +393 -66
  24. package/neural-interface/lib/assistant-memory.js +24 -10
  25. package/neural-interface/lib/assistant-persona.js +6 -2
  26. package/neural-interface/lib/assistant-pricing.js +21 -6
  27. package/neural-interface/lib/assistant-runtime.js +181 -12
  28. package/neural-interface/lib/assistant-task-prompt.js +13 -3
  29. package/neural-interface/lib/assistant-test-density.js +142 -0
  30. package/neural-interface/lib/assistant-user-context-budgets.js +123 -0
  31. package/neural-interface/lib/assistant-user-context.js +908 -0
  32. package/neural-interface/lib/assistant-user-knowledge.js +328 -0
  33. package/neural-interface/lib/assistant-user-learn.js +404 -0
  34. package/neural-interface/lib/assistant-user-threads.js +226 -0
  35. package/neural-interface/lib/assistant-user-writer.js +181 -0
  36. package/neural-interface/lib/browser-background-tab.js +134 -0
  37. package/neural-interface/lib/browser-screenshot.js +678 -61
  38. package/neural-interface/lib/claude-agent-bridge.js +33 -6
  39. package/neural-interface/lib/claude-model-catalog.js +30 -2
  40. package/neural-interface/lib/claude-temporary.js +46 -7
  41. package/neural-interface/lib/cloudflared/install.js +533 -0
  42. package/neural-interface/lib/cloudflared/manager.js +545 -0
  43. package/neural-interface/lib/cloudflared/pins.js +115 -0
  44. package/neural-interface/lib/cloudflared/pins.json +63 -0
  45. package/neural-interface/lib/cloudflared/tunnel.js +265 -0
  46. package/neural-interface/lib/editor-completion-endpoint.js +264 -0
  47. package/neural-interface/lib/editor-completion-opencode.js +436 -0
  48. package/neural-interface/lib/editor-completion.js +714 -0
  49. package/neural-interface/lib/editor-config.js +149 -0
  50. package/neural-interface/lib/editor-files-api.js +268 -0
  51. package/neural-interface/lib/editor-git-api.js +134 -0
  52. package/neural-interface/lib/file-explorer-api.js +1039 -0
  53. package/neural-interface/lib/file-explorer-system.js +355 -0
  54. package/neural-interface/lib/file-explorer-trash.ps1 +85 -0
  55. package/neural-interface/lib/file-explorer-watch.js +239 -0
  56. package/neural-interface/lib/git-diff-api.js +103 -0
  57. package/neural-interface/lib/git-read.js +202 -0
  58. package/neural-interface/lib/greeting/api.js +89 -0
  59. package/neural-interface/lib/greeting/budgets.js +90 -0
  60. package/neural-interface/lib/greeting/engine.js +461 -0
  61. package/neural-interface/lib/greeting/facts.js +320 -0
  62. package/neural-interface/lib/greeting/sources.js +252 -0
  63. package/neural-interface/lib/greeting/writer.js +139 -0
  64. package/neural-interface/lib/http-guards.js +189 -13
  65. package/neural-interface/lib/machine-names.js +88 -0
  66. package/neural-interface/lib/memory-api.js +31 -7
  67. package/neural-interface/lib/native-loop-providers.js +10 -5
  68. package/neural-interface/lib/plugin-installer.js +4 -2
  69. package/neural-interface/lib/project-storage.js +5 -7
  70. package/neural-interface/lib/request-gate.js +589 -0
  71. package/neural-interface/lib/ui-blob-api.js +108 -0
  72. package/neural-interface/lib/ui-blob-store.js +68 -0
  73. package/neural-interface/package-lock.json +701 -2
  74. package/neural-interface/package.json +13 -2
  75. package/neural-interface/public/install-app.html +9 -6
  76. package/neural-interface/public/offline.html +3 -2
  77. package/neural-interface/public/onboarding.html +12 -1
  78. package/neural-interface/public/shared/agent-runtime-options.js +22 -6
  79. package/neural-interface/public/shared/assistant/asst-automation.js +286 -0
  80. package/neural-interface/public/shared/assistant/asst-brain-picker.js +312 -62
  81. package/neural-interface/public/shared/assistant/asst-composer.js +11 -1
  82. package/neural-interface/public/shared/assistant/asst-mascot.js +18 -58
  83. package/neural-interface/public/shared/assistant/asst-menu.js +12 -8
  84. package/neural-interface/public/shared/assistant/asst-panel.js +150 -28
  85. package/neural-interface/public/shared/assistant/asst-render.js +162 -19
  86. package/neural-interface/public/shared/assistant/asst-route-models.js +108 -0
  87. package/neural-interface/public/shared/assistant/asst-route.js +23 -329
  88. package/neural-interface/public/shared/assistant/asst-routes-editor.js +495 -0
  89. package/neural-interface/public/shared/assistant/asst-sanitize.js +8 -1
  90. package/neural-interface/public/shared/assistant/asst-sidepanel.js +31 -9
  91. package/neural-interface/public/shared/assistant/asst-state.js +185 -1
  92. package/neural-interface/public/shared/assistant/asst-styles.js +158 -4
  93. package/neural-interface/public/shared/blob-store.js +111 -22
  94. package/neural-interface/public/shared/cdx/cdx-panel.js +32 -11
  95. package/neural-interface/public/shared/cdx/cdx-render.js +25 -89
  96. package/neural-interface/public/shared/cdx/cdx-styles.js +36 -0
  97. package/neural-interface/public/shared/cdx/cdx-tabs.js +87 -4
  98. package/neural-interface/public/shared/constants.js +6 -1
  99. package/neural-interface/public/shared/cp/cp-rehydrate.js +2 -1
  100. package/neural-interface/public/shared/cp/cp-styles.js +15 -0
  101. package/neural-interface/public/shared/editor/editor-ai-logic.js +409 -0
  102. package/neural-interface/public/shared/editor/editor-ai.js +619 -0
  103. package/neural-interface/public/shared/editor/editor-commands.js +212 -0
  104. package/neural-interface/public/shared/editor/editor-compare.js +103 -0
  105. package/neural-interface/public/shared/editor/editor-completion-list.js +172 -0
  106. package/neural-interface/public/shared/editor/editor-doc.js +257 -0
  107. package/neural-interface/public/shared/editor/editor-git-logic.js +131 -0
  108. package/neural-interface/public/shared/editor/editor-git.js +95 -0
  109. package/neural-interface/public/shared/editor/editor-languages.js +156 -0
  110. package/neural-interface/public/shared/editor/editor-lint.js +229 -0
  111. package/neural-interface/public/shared/editor/editor-loader.js +51 -0
  112. package/neural-interface/public/shared/editor/editor-markdown.js +90 -0
  113. package/neural-interface/public/shared/editor/editor-menu.js +233 -0
  114. package/neural-interface/public/shared/editor/editor-minimap.js +371 -0
  115. package/neural-interface/public/shared/editor/editor-palette-logic.js +192 -0
  116. package/neural-interface/public/shared/editor/editor-palette.js +125 -0
  117. package/neural-interface/public/shared/editor/editor-panel-logic.js +288 -0
  118. package/neural-interface/public/shared/editor/editor-panel.js +2099 -0
  119. package/neural-interface/public/shared/editor/editor-prefs.js +224 -0
  120. package/neural-interface/public/shared/editor/editor-safety.js +500 -0
  121. package/neural-interface/public/shared/editor/editor-search.js +352 -0
  122. package/neural-interface/public/shared/editor/editor-statusbar.js +144 -0
  123. package/neural-interface/public/shared/editor/editor-tabs-logic.js +331 -0
  124. package/neural-interface/public/shared/editor/editor-tabs.js +233 -0
  125. package/neural-interface/public/shared/editor/editor-theme.js +244 -0
  126. package/neural-interface/public/shared/editor/editor-view.js +332 -0
  127. package/neural-interface/public/shared/explorer/fx-api.js +216 -0
  128. package/neural-interface/public/shared/explorer/fx-links.js +204 -0
  129. package/neural-interface/public/shared/explorer/fx-logic.js +537 -0
  130. package/neural-interface/public/shared/explorer/fx-main.js +865 -0
  131. package/neural-interface/public/shared/explorer/fx-names.js +87 -0
  132. package/neural-interface/public/shared/explorer/fx-ops.js +370 -0
  133. package/neural-interface/public/shared/explorer/fx-popups.js +490 -0
  134. package/neural-interface/public/shared/explorer/fx-tree.js +790 -0
  135. package/neural-interface/public/shared/file-links.js +339 -0
  136. package/neural-interface/public/shared/greeting/greeting-card.js +178 -0
  137. package/neural-interface/public/shared/greeting/greeting-view.js +148 -0
  138. package/neural-interface/public/shared/html-shell.js +160 -165
  139. package/neural-interface/public/shared/ocp-v2/ocp-v2-childpanel.js +4 -0
  140. package/neural-interface/public/shared/ocp-v2/ocp-v2-greeting.js +47 -0
  141. package/neural-interface/public/shared/ocp-v2/ocp-v2-panel.js +99 -17
  142. package/neural-interface/public/shared/ocp-v2/ocp-v2-render.js +7 -1
  143. package/neural-interface/public/shared/ocp-v2/ocp-v2-send.js +5 -0
  144. package/neural-interface/public/shared/ocp-v2/ocp-v2-styles.js +40 -0
  145. package/neural-interface/public/shared/ocp-v2/ocp-v2-ws.js +3 -2
  146. package/neural-interface/public/shared/pwa-install-page.js +29 -1
  147. package/neural-interface/public/shared/pwa-install.css +3 -3
  148. package/neural-interface/public/shared/pwa-install.js +100 -1
  149. package/neural-interface/public/shared/settings/settings-code-editor-pane.js +412 -0
  150. package/neural-interface/public/shared/settings/settings-code-editor.js +328 -0
  151. package/neural-interface/public/shared/settings/settings-greeting.js +133 -0
  152. package/neural-interface/public/shared/settings/settings-ia.js +18 -4
  153. package/neural-interface/public/shared/settings/settings-user-context.js +154 -0
  154. package/neural-interface/public/shared/start-bridge.js +238 -19
  155. package/neural-interface/public/shared/styles.css +1414 -721
  156. package/neural-interface/public/shared/synabun-mascot.js +20 -56
  157. package/neural-interface/public/shared/tunnel-view.js +167 -0
  158. package/neural-interface/public/shared/ui-claude-panel.js +157 -16
  159. package/neural-interface/public/shared/ui-detail.js +15 -0
  160. package/neural-interface/public/shared/ui-explorer.js +22 -0
  161. package/neural-interface/public/shared/ui-file-explorer.js +481 -2496
  162. package/neural-interface/public/shared/ui-file-links.js +103 -0
  163. package/neural-interface/public/shared/ui-help.js +26 -0
  164. package/neural-interface/public/shared/ui-invite.js +126 -116
  165. package/neural-interface/public/shared/ui-keybinds.js +4 -0
  166. package/neural-interface/public/shared/ui-loading.js +159 -15
  167. package/neural-interface/public/shared/ui-menubar.js +12 -30
  168. package/neural-interface/public/shared/ui-native-loop-router-state.js +11 -0
  169. package/neural-interface/public/shared/ui-native-loop-router.js +15 -2
  170. package/neural-interface/public/shared/ui-navbar.js +45 -21
  171. package/neural-interface/public/shared/ui-settings.js +455 -488
  172. package/neural-interface/public/shared/ui-sidepanel-runtime.js +2 -1
  173. package/neural-interface/public/shared/ui-sync.js +16 -0
  174. package/neural-interface/public/shared/ui-terminal.js +23 -5
  175. package/neural-interface/public/shared/ui-tunnel.js +130 -0
  176. package/neural-interface/public/shared/ui-tutorial-steps.js +6 -2
  177. package/neural-interface/public/shared/ui-whiteboard.js +12 -0
  178. package/neural-interface/public/shared/ui-worker-end.js +245 -0
  179. package/neural-interface/public/shared/ui-workspaces.js +41 -27
  180. package/neural-interface/public/shared/worker-end.js +251 -0
  181. package/neural-interface/public/sw.js +2 -2
  182. package/neural-interface/public/vendor/codemirror/chunks/apl-CSDKT72Z.js +1 -0
  183. package/neural-interface/public/vendor/codemirror/chunks/asciiarmor-JYYPU5BM.js +1 -0
  184. package/neural-interface/public/vendor/codemirror/chunks/asn1-NRWCZDA6.js +1 -0
  185. package/neural-interface/public/vendor/codemirror/chunks/asterisk-5OU6D4ZQ.js +1 -0
  186. package/neural-interface/public/vendor/codemirror/chunks/brainfuck-ID4N4SYC.js +1 -0
  187. package/neural-interface/public/vendor/codemirror/chunks/chunk-4RZWGCS2.js +1 -0
  188. package/neural-interface/public/vendor/codemirror/chunks/chunk-ACTJM3JR.js +11 -0
  189. package/neural-interface/public/vendor/codemirror/chunks/chunk-S6BMAXLK.js +1 -0
  190. package/neural-interface/public/vendor/codemirror/chunks/chunk-TO2RDOHQ.js +3 -0
  191. package/neural-interface/public/vendor/codemirror/chunks/chunk-US2GMZZQ.js +13 -0
  192. package/neural-interface/public/vendor/codemirror/chunks/chunk-WYYO5ZAJ.js +1 -0
  193. package/neural-interface/public/vendor/codemirror/chunks/chunk-XALZTDJC.js +1 -0
  194. package/neural-interface/public/vendor/codemirror/chunks/chunk-YRNUTRDV.js +1 -0
  195. package/neural-interface/public/vendor/codemirror/chunks/chunk-Z3QOKH62.js +1 -0
  196. package/neural-interface/public/vendor/codemirror/chunks/clike-OWQBSOGL.js +1 -0
  197. package/neural-interface/public/vendor/codemirror/chunks/clojure-KV75UQWC.js +1 -0
  198. package/neural-interface/public/vendor/codemirror/chunks/cmake-GTEP5Y3C.js +1 -0
  199. package/neural-interface/public/vendor/codemirror/chunks/cobol-WCZ7QEGJ.js +1 -0
  200. package/neural-interface/public/vendor/codemirror/chunks/coffeescript-TGLBOT6B.js +1 -0
  201. package/neural-interface/public/vendor/codemirror/chunks/commonlisp-WVVI432V.js +1 -0
  202. package/neural-interface/public/vendor/codemirror/chunks/crystal-S6R6HLKQ.js +1 -0
  203. package/neural-interface/public/vendor/codemirror/chunks/css-PDA2RINP.js +1 -0
  204. package/neural-interface/public/vendor/codemirror/chunks/cypher-HL5QPL4C.js +1 -0
  205. package/neural-interface/public/vendor/codemirror/chunks/d-HHJH2HAJ.js +1 -0
  206. package/neural-interface/public/vendor/codemirror/chunks/diff-MN3A35BY.js +1 -0
  207. package/neural-interface/public/vendor/codemirror/chunks/dist-25SQLBVS.js +3 -0
  208. package/neural-interface/public/vendor/codemirror/chunks/dist-27ZGGJJS.js +1 -0
  209. package/neural-interface/public/vendor/codemirror/chunks/dist-4E52OJIF.js +1 -0
  210. package/neural-interface/public/vendor/codemirror/chunks/dist-6FT73XDC.js +2 -0
  211. package/neural-interface/public/vendor/codemirror/chunks/dist-BE6YGRMW.js +1 -0
  212. package/neural-interface/public/vendor/codemirror/chunks/dist-CJSGKW2O.js +1 -0
  213. package/neural-interface/public/vendor/codemirror/chunks/dist-CRPH2WLI.js +1 -0
  214. package/neural-interface/public/vendor/codemirror/chunks/dist-CTG7JEQN.js +1 -0
  215. package/neural-interface/public/vendor/codemirror/chunks/dist-I3FEVELX.js +1 -0
  216. package/neural-interface/public/vendor/codemirror/chunks/dist-IM5BBSWZ.js +1 -0
  217. package/neural-interface/public/vendor/codemirror/chunks/dist-KERUKTIF.js +1 -0
  218. package/neural-interface/public/vendor/codemirror/chunks/dist-LXTMWZAM.js +1 -0
  219. package/neural-interface/public/vendor/codemirror/chunks/dist-MABASSET.js +1 -0
  220. package/neural-interface/public/vendor/codemirror/chunks/dist-MJVBUZLL.js +3 -0
  221. package/neural-interface/public/vendor/codemirror/chunks/dist-MNB3WZVU.js +1 -0
  222. package/neural-interface/public/vendor/codemirror/chunks/dist-QYWXOE3U.js +7 -0
  223. package/neural-interface/public/vendor/codemirror/chunks/dist-TEBOFWLZ.js +1 -0
  224. package/neural-interface/public/vendor/codemirror/chunks/dist-UNXFROM3.js +1 -0
  225. package/neural-interface/public/vendor/codemirror/chunks/dist-XL2SLQO6.js +1 -0
  226. package/neural-interface/public/vendor/codemirror/chunks/dist-XO42Y3AP.js +6 -0
  227. package/neural-interface/public/vendor/codemirror/chunks/dist-Y2WWDWJK.js +1 -0
  228. package/neural-interface/public/vendor/codemirror/chunks/dist-YFEZKWMU.js +1 -0
  229. package/neural-interface/public/vendor/codemirror/chunks/dist-ZY7SWQO6.js +1 -0
  230. package/neural-interface/public/vendor/codemirror/chunks/dockerfile-3Y4R4NCH.js +1 -0
  231. package/neural-interface/public/vendor/codemirror/chunks/dtd-5343GJ4P.js +1 -0
  232. package/neural-interface/public/vendor/codemirror/chunks/dylan-FI2CXSW2.js +1 -0
  233. package/neural-interface/public/vendor/codemirror/chunks/ebnf-GNQ77YWA.js +1 -0
  234. package/neural-interface/public/vendor/codemirror/chunks/ecl-MRPUAE2L.js +1 -0
  235. package/neural-interface/public/vendor/codemirror/chunks/eiffel-DZROES27.js +1 -0
  236. package/neural-interface/public/vendor/codemirror/chunks/elm-4KICRFKQ.js +1 -0
  237. package/neural-interface/public/vendor/codemirror/chunks/erlang-3IHYC263.js +1 -0
  238. package/neural-interface/public/vendor/codemirror/chunks/factor-C6D3E5UK.js +1 -0
  239. package/neural-interface/public/vendor/codemirror/chunks/fcl-VYTWUJMI.js +1 -0
  240. package/neural-interface/public/vendor/codemirror/chunks/forth-ZBO2EH5M.js +1 -0
  241. package/neural-interface/public/vendor/codemirror/chunks/fortran-5NDCRWIK.js +1 -0
  242. package/neural-interface/public/vendor/codemirror/chunks/gas-SKRMOXFP.js +1 -0
  243. package/neural-interface/public/vendor/codemirror/chunks/gherkin-L45YXZLW.js +1 -0
  244. package/neural-interface/public/vendor/codemirror/chunks/groovy-GLPTLN44.js +1 -0
  245. package/neural-interface/public/vendor/codemirror/chunks/haskell-E7NF7P4Y.js +1 -0
  246. package/neural-interface/public/vendor/codemirror/chunks/haxe-K2NVDOB6.js +1 -0
  247. package/neural-interface/public/vendor/codemirror/chunks/http-Q6DRQIJB.js +1 -0
  248. package/neural-interface/public/vendor/codemirror/chunks/idl-MZYNJVLN.js +1 -0
  249. package/neural-interface/public/vendor/codemirror/chunks/javascript-6YRYK2HR.js +1 -0
  250. package/neural-interface/public/vendor/codemirror/chunks/julia-HXEL2T5G.js +1 -0
  251. package/neural-interface/public/vendor/codemirror/chunks/livescript-MV7CI2JZ.js +1 -0
  252. package/neural-interface/public/vendor/codemirror/chunks/lua-E36NHOOD.js +1 -0
  253. package/neural-interface/public/vendor/codemirror/chunks/mathematica-3XOZZCMC.js +1 -0
  254. package/neural-interface/public/vendor/codemirror/chunks/mbox-ODYGFKS7.js +1 -0
  255. package/neural-interface/public/vendor/codemirror/chunks/mirc-WB43AWF5.js +1 -0
  256. package/neural-interface/public/vendor/codemirror/chunks/mllike-ZT6ET7ZH.js +1 -0
  257. package/neural-interface/public/vendor/codemirror/chunks/modelica-LLMZPFGA.js +1 -0
  258. package/neural-interface/public/vendor/codemirror/chunks/mscgen-2OPNNYFH.js +1 -0
  259. package/neural-interface/public/vendor/codemirror/chunks/mumps-6P3HWJH6.js +1 -0
  260. package/neural-interface/public/vendor/codemirror/chunks/nginx-TCGKQTRW.js +1 -0
  261. package/neural-interface/public/vendor/codemirror/chunks/nsis-ATIGIXTJ.js +1 -0
  262. package/neural-interface/public/vendor/codemirror/chunks/ntriples-5PLBI5OV.js +1 -0
  263. package/neural-interface/public/vendor/codemirror/chunks/octave-QF2S3NL6.js +1 -0
  264. package/neural-interface/public/vendor/codemirror/chunks/oz-JFIVFFH2.js +1 -0
  265. package/neural-interface/public/vendor/codemirror/chunks/pascal-JG6SW76V.js +1 -0
  266. package/neural-interface/public/vendor/codemirror/chunks/perl-4B3IWVVO.js +1 -0
  267. package/neural-interface/public/vendor/codemirror/chunks/pig-ABEBH4MI.js +1 -0
  268. package/neural-interface/public/vendor/codemirror/chunks/powershell-H32XE7TL.js +1 -0
  269. package/neural-interface/public/vendor/codemirror/chunks/properties-NN644MMA.js +1 -0
  270. package/neural-interface/public/vendor/codemirror/chunks/protobuf-YKWQK2J3.js +1 -0
  271. package/neural-interface/public/vendor/codemirror/chunks/pug-RIYXEKFW.js +1 -0
  272. package/neural-interface/public/vendor/codemirror/chunks/puppet-JZQ5WPEV.js +1 -0
  273. package/neural-interface/public/vendor/codemirror/chunks/python-EBCGGHAC.js +1 -0
  274. package/neural-interface/public/vendor/codemirror/chunks/q-5UMH2YQY.js +1 -0
  275. package/neural-interface/public/vendor/codemirror/chunks/r-7XMGG453.js +1 -0
  276. package/neural-interface/public/vendor/codemirror/chunks/rpm-IEV7TSLR.js +1 -0
  277. package/neural-interface/public/vendor/codemirror/chunks/ruby-T4SPFPNM.js +1 -0
  278. package/neural-interface/public/vendor/codemirror/chunks/sas-GEDX67ET.js +1 -0
  279. package/neural-interface/public/vendor/codemirror/chunks/scheme-FTLOWKPC.js +1 -0
  280. package/neural-interface/public/vendor/codemirror/chunks/shell-HUFRKFSJ.js +1 -0
  281. package/neural-interface/public/vendor/codemirror/chunks/sieve-P5QUDVYO.js +1 -0
  282. package/neural-interface/public/vendor/codemirror/chunks/smalltalk-2SORJNQI.js +1 -0
  283. package/neural-interface/public/vendor/codemirror/chunks/solr-M22TGAR5.js +1 -0
  284. package/neural-interface/public/vendor/codemirror/chunks/sparql-4M3KL752.js +1 -0
  285. package/neural-interface/public/vendor/codemirror/chunks/spreadsheet-3K23LA4N.js +1 -0
  286. package/neural-interface/public/vendor/codemirror/chunks/sql-VHRFMUBI.js +1 -0
  287. package/neural-interface/public/vendor/codemirror/chunks/stex-QZDAQUY2.js +1 -0
  288. package/neural-interface/public/vendor/codemirror/chunks/stylus-7ZDKAKBD.js +1 -0
  289. package/neural-interface/public/vendor/codemirror/chunks/swift-WCLCLGMR.js +1 -0
  290. package/neural-interface/public/vendor/codemirror/chunks/tcl-JLMU6WOK.js +1 -0
  291. package/neural-interface/public/vendor/codemirror/chunks/textile-4CHDKZ4T.js +1 -0
  292. package/neural-interface/public/vendor/codemirror/chunks/tiddlywiki-DKMCZZQ4.js +1 -0
  293. package/neural-interface/public/vendor/codemirror/chunks/tiki-F4JIG36Q.js +1 -0
  294. package/neural-interface/public/vendor/codemirror/chunks/toml-BHMHTIM2.js +1 -0
  295. package/neural-interface/public/vendor/codemirror/chunks/troff-YQ2KV5NT.js +1 -0
  296. package/neural-interface/public/vendor/codemirror/chunks/ttcn-ZHRCVFJY.js +1 -0
  297. package/neural-interface/public/vendor/codemirror/chunks/ttcn-cfg-KJOVTY4X.js +1 -0
  298. package/neural-interface/public/vendor/codemirror/chunks/turtle-535P5N6I.js +1 -0
  299. package/neural-interface/public/vendor/codemirror/chunks/vb-76UMQHOT.js +1 -0
  300. package/neural-interface/public/vendor/codemirror/chunks/vbscript-CGNDTK6Z.js +1 -0
  301. package/neural-interface/public/vendor/codemirror/chunks/velocity-VSJDO5T5.js +1 -0
  302. package/neural-interface/public/vendor/codemirror/chunks/verilog-4T6ETXIP.js +1 -0
  303. package/neural-interface/public/vendor/codemirror/chunks/vhdl-T7FNAXUN.js +1 -0
  304. package/neural-interface/public/vendor/codemirror/chunks/webidl-P6MJSJ6J.js +1 -0
  305. package/neural-interface/public/vendor/codemirror/chunks/xquery-UOVILRGN.js +1 -0
  306. package/neural-interface/public/vendor/codemirror/chunks/yacas-CV2APROL.js +1 -0
  307. package/neural-interface/public/vendor/codemirror/chunks/z80-3KFNVM4M.js +1 -0
  308. package/neural-interface/public/vendor/codemirror/codemirror-6.43.14-75f05e67.min.js +2 -0
  309. package/neural-interface/public/vendor/codemirror/manifest.json +60 -0
  310. package/neural-interface/scripts/build-vendor.mjs +78 -2
  311. package/neural-interface/scripts/vendor-codemirror-entry.js +121 -0
  312. package/neural-interface/server.js +873 -1028
  313. package/neural-interface/templates/rulesets/README.md +1 -1
  314. package/package.json +2 -8
  315. package/setup.js +44 -7
  316. package/benchmarks/browser-live-results.json +0 -79
  317. package/benchmarks/browser-v2-results.json +0 -258
  318. package/neural-interface/lib/codex-capabilities.d.ts +0 -41
  319. package/neural-interface/public/category-logos/claude.svg +0 -1
  320. package/neural-interface/public/category-logos/gemini-color.svg +0 -1
  321. package/neural-interface/public/category-logos/openai.svg +0 -1
  322. package/neural-interface/public/category-logos/synabun.png +0 -0
  323. package/neural-interface/public/claude.svg +0 -1
  324. package/neural-interface/public/gallery.svg +0 -6
  325. package/neural-interface/public/leonardoai.svg +0 -1
  326. package/neural-interface/public/mcp.svg +0 -4
  327. package/neural-interface/public/opencode-logo-dark-square.svg +0 -1
  328. package/neural-interface/public/pin-svgrepo-com.svg +0 -25
  329. package/neural-interface/public/sessionicon.svg +0 -8
  330. package/neural-interface/public/toolbar-album.svg +0 -8
  331. package/neural-interface/public/toolbar-question.svg +0 -6
  332. package/neural-interface/public/toolbar-sessions.svg +0 -6
  333. package/neural-interface/scripts/codex-protocol-fixture.mjs +0 -83
  334. package/skills/synabun/synabunicon.png +0 -0
@@ -6,6 +6,76 @@
6
6
  import { getVariant } from './registry.js';
7
7
  import { t } from './i18n.js';
8
8
 
9
+ /**
10
+ * The File Explorer's editor panel (slides from the file explorer's right edge).
11
+ * The editor itself is CodeMirror, mounted in #fe-editor-host by shared/editor/editor-panel.js,
12
+ * which also fills the shortcuts list, the tab strip (#fe-editor-tabs, there while two or more
13
+ * files are open) and the bars, and builds the find and go-to-line bars.
14
+ */
15
+ export function getEditorPanelHTML() {
16
+ return `<!-- File Editor (separate panel, slides from file explorer's right edge) -->
17
+ <div id="fe-editor-panel" class="fe-editor-panel">
18
+ <div class="fe-editor-header">
19
+ <button class="fe-editor-back" id="fe-editor-back" data-tooltip="${t('editor.header.close')}" aria-label="${t('editor.header.close')}">
20
+ <svg viewBox="0 0 24 24"><polyline points="15 18 9 12 15 6"/></svg>
21
+ </button>
22
+ <span class="fe-editor-dot" id="fe-editor-dot"></span>
23
+ <span class="fe-editor-filepath" id="fe-editor-filepath"></span>
24
+ <div style="flex:1"></div>
25
+ <button class="fe-editor-action" id="fe-editor-find-btn" data-tooltip="${t('editor.header.find')}" aria-label="${t('editor.header.find')}">
26
+ <svg viewBox="0 0 24 24"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
27
+ </button>
28
+ <button class="fe-editor-action" id="fe-editor-word-wrap" data-tooltip="${t('editor.header.wordWrap')}" aria-label="${t('editor.header.wordWrap')}" aria-pressed="true">
29
+ <svg viewBox="0 0 24 24"><path d="M3 6h18M3 12h15a3 3 0 1 1 0 6h-4"/><polyline points="16 16 14 18 16 20"/><path d="M3 18h7"/></svg>
30
+ </button>
31
+ <button class="fe-editor-action" id="fe-editor-view-btn" data-tooltip="${t('editor.header.view')}" aria-label="${t('editor.header.view')}" aria-haspopup="menu" aria-expanded="false">
32
+ <svg viewBox="0 0 24 24"><path d="M4 7h2.5M11.5 7H20M4 17h8.5M17.5 17H20"/><circle cx="9" cy="7" r="2.5"/><circle cx="15" cy="17" r="2.5"/></svg>
33
+ </button>
34
+ <button class="fe-editor-action" id="fe-editor-diff-btn" data-tooltip="${t('editor.header.diff')}" aria-label="${t('editor.header.diff')}" aria-pressed="false" hidden>
35
+ <svg viewBox="0 0 24 24"><path d="M12 3v10M7 8h10M7 19h10"/></svg>
36
+ </button>
37
+ <div class="fe-editor-help-wrap">
38
+ <button class="fe-editor-action fe-editor-help-btn" id="fe-editor-help-btn" data-tooltip="${t('editor.header.shortcuts')}" aria-label="${t('editor.header.shortcuts')}" aria-expanded="false" aria-controls="fe-editor-keybinds">
39
+ <svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>
40
+ </button>
41
+ <div class="fe-editor-keybinds" id="fe-editor-keybinds"></div>
42
+ </div>
43
+ <div class="fe-editor-sep"></div>
44
+ <div class="fe-editor-view-toggle" id="fe-editor-view-toggle" style="display:none">
45
+ <button class="fe-editor-toggle-btn active" data-mode="raw" aria-pressed="true">${t('editor.header.raw')}</button>
46
+ <button class="fe-editor-toggle-btn" data-mode="preview" aria-pressed="false">${t('editor.header.preview')}</button>
47
+ </div>
48
+ <div class="fe-editor-sep" id="fe-editor-sep-preview" style="display:none"></div>
49
+ <button class="fe-editor-btn" id="fe-editor-discard" disabled>${t('editor.header.discard')}</button>
50
+ <button class="fe-editor-btn fe-editor-save" id="fe-editor-save" disabled>${t('editor.header.save')}</button>
51
+ <button class="fe-editor-btn" id="fe-editor-close">${t('editor.header.closeButton')}</button>
52
+ </div>
53
+ <div class="fe-editor-tabs" id="fe-editor-tabs" role="tablist" aria-label="${t('editor.tabs.label')}" hidden></div>
54
+ <div class="fe-editor-bars" id="fe-editor-bars"></div>
55
+ <div class="fe-editor-body">
56
+ <div class="fe-editor-host" id="fe-editor-host"></div>
57
+ <div class="fe-editor-preview" id="fe-editor-preview"></div>
58
+ <div class="fe-editor-message" id="fe-editor-message" hidden>
59
+ <div class="fe-editor-message-text" id="fe-editor-message-text" role="status"></div>
60
+ <button class="fe-editor-btn" id="fe-editor-message-retry" hidden>${t('editor.error.retry')}</button>
61
+ </div>
62
+ </div>
63
+ <div class="fe-editor-statusbar is-empty" id="fe-editor-statusbar">
64
+ <button type="button" class="fe-editor-status-btn" id="fe-editor-lang"></button>
65
+ <span class="fe-editor-sep"></span>
66
+ <button type="button" class="fe-editor-status-btn" id="fe-editor-indent"></button>
67
+ <span class="fe-editor-sep"></span>
68
+ <button type="button" class="fe-editor-status-btn" id="fe-editor-eol"></button>
69
+ <span class="fe-editor-sep"></span>
70
+ <span id="fe-editor-encoding">UTF-8</span>
71
+ <div style="flex:1"></div>
72
+ <button type="button" class="fe-editor-status-btn" id="fe-editor-cursor"></button>
73
+ <span class="fe-editor-sep"></span>
74
+ <span id="fe-editor-size"></span>
75
+ </div>
76
+ </div>`;
77
+ }
78
+
9
79
  /**
10
80
  * Returns the full shared HTML string for injection into <body>.
11
81
  * Variant-specific elements (camera HUD, controls panel, minimap, etc.)
@@ -212,6 +282,15 @@ export function getSharedHTML() {
212
282
  <span class="menu-shortcut" data-keybind-for="toggle-file-explorer"></span>
213
283
  </div>
214
284
  <div class="menu-sep"></div>
285
+ <div class="menu-item menu-toggle" id="menu-toggle-grid-snap">
286
+ <span class="menu-check">&#10003;</span>
287
+ <span class="menu-text">${t('toolbar.snapToGrid')}</span>
288
+ </div>
289
+ <div class="menu-item" id="menu-tile-terminals">
290
+ <span class="menu-check"></span>
291
+ <span class="menu-text">${t('toolbar.tileTerminals')}</span>
292
+ </div>
293
+ <div class="menu-sep"></div>
215
294
  <div id="menu-variant-slot"></div>
216
295
  <div class="menu-sep" id="menu-variant-sep" style="display:none"></div>
217
296
  <div class="menu-item" id="menu-help">
@@ -425,45 +504,48 @@ ${is3D ? `
425
504
  </div>
426
505
  </div>
427
506
 
428
- <!-- Top-Right Controls (Trash + Grid + Workspace) -->
507
+ <!-- Top-Right Controls: one row. The glass dock (workspace switcher, then the tools), then #topright-buttons: the
508
+ tools toggle (#topright-tools-btn, shows and hides the dock) and the agent side panels, always one row of their own.
509
+ Snap to grid and Tile terminals are on the whiteboard rail (#wb-toolbar) and in View. The session pills
510
+ (#term-minimized-tray) are a row under the bar, right-aligned with it (styles.css: "Fit"). -->
429
511
  <div id="topright-controls">
430
512
  <div id="topright-inner">
431
- <button id="topright-trash-btn" class="topright-icon-btn" data-tooltip="${t('nav.trash')}">
432
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M4 6h16"/><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/><line x1="10" y1="10" x2="10" y2="18"/><line x1="14" y1="10" x2="14" y2="18"/></svg>
433
- <span class="count-badge count-badge--red" id="titlebar-trash-count"></span>
434
- </button>
435
-
436
- <button id="ws-grid-toggle" class="topright-icon-btn" data-tooltip="Snap to Grid">
437
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><circle cx="6" cy="6" r="1.5"/><circle cx="12" cy="6" r="1.5"/><circle cx="18" cy="6" r="1.5"/><circle cx="6" cy="12" r="1.5"/><circle cx="12" cy="12" r="1.5"/><circle cx="18" cy="12" r="1.5"/><circle cx="6" cy="18" r="1.5"/><circle cx="12" cy="18" r="1.5"/><circle cx="18" cy="18" r="1.5"/></svg>
438
- </button>
439
-
440
- <button id="ws-tile-btn" class="topright-icon-btn" data-tooltip="Tile terminals">
441
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="8" height="8" rx="2"/><rect x="13" y="3" width="8" height="8" rx="2"/><rect x="3" y="13" width="8" height="8" rx="2"/><rect x="13" y="13" width="8" height="8" rx="2"/></svg>
442
- </button>
513
+ <div id="workspace-overlay">
514
+ <button id="ws-indicator" type="button" aria-expanded="false" aria-controls="ws-dropdown" aria-label="${t('toolbar.workspaceNone')}" data-tooltip="${t('toolbar.workspaceNone')}">
515
+ <svg class="ws-icon" viewBox="0 0 24 24"><path d="M12 2L2 7l10 5 10-5-10-5z"/><path d="M2 17l10 5 10-5"/><path d="M2 12l10 5 10-5"/></svg>
516
+ <span id="ws-active-name">No workspace</span>
517
+ <svg class="ws-chevron" viewBox="0 0 24 24"><path d="M6 9l6 6 6-6"/></svg>
518
+ </button>
519
+ <button id="ws-quick-save" class="ws-quick-save" type="button" aria-label="${t('toolbar.quickSave')}" data-tooltip="${t('toolbar.quickSave')}"><svg viewBox="0 0 24 24"><path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"/><polyline points="17 21 17 13 7 13 7 21"/><polyline points="7 3 7 8 15 8"/></svg></button>
520
+ <div id="ws-dropdown" style="display:none;">
521
+ <div class="ws-save-bar">
522
+ <input type="text" id="ws-name-input" placeholder="Save workspace..." autocomplete="off" spellcheck="false">
523
+ <button id="ws-save-btn" data-tooltip="Save"><svg viewBox="0 0 24 24"><path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"/><polyline points="17 21 17 13 7 13 7 21"/><polyline points="7 3 7 8 15 8"/></svg></button>
524
+ </div>
525
+ <button id="ws-clear-btn" class="ws-new-btn"><svg viewBox="0 0 24 24"><path d="M3 6h18"/><path d="M8 6V4h8v2"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/></svg>Clear workspace</button>
526
+ <div class="ws-divider"></div>
527
+ <div id="ws-list" class="ws-list"></div>
528
+ <div class="ws-divider"></div>
529
+ <div class="ws-footer">
530
+ <button id="ws-export-btn" class="ws-footer-btn" title="Export all workspaces"><svg viewBox="0 0 24 24"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>Export</button>
531
+ <button id="ws-import-btn" class="ws-footer-btn" title="Import workspaces"><svg viewBox="0 0 24 24"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>Import</button>
532
+ </div>
533
+ <input type="file" id="ws-import-file" accept=".json" style="display:none;">
534
+ </div>
535
+ </div>
443
536
 
444
537
  <span class="tr-divider"></span>
445
538
 
446
- <button id="topright-update-btn" class="topright-icon-btn" style="display:none" data-tooltip="Update available">
447
- <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
448
- <span class="count-badge count-badge--green" id="update-badge"></span>
449
- </button>
450
-
451
- <button id="topright-keybinds-btn" class="topright-icon-btn" data-tooltip="Keybinds">
452
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="4" width="20" height="16" rx="3"/><circle cx="7" cy="9" r="1" fill="currentColor" stroke="none"/><circle cx="12" cy="9" r="1" fill="currentColor" stroke="none"/><circle cx="17" cy="9" r="1" fill="currentColor" stroke="none"/><path d="M7 15h10"/></svg>
453
- </button>
454
-
455
- <button id="topright-memory-explorer-btn" class="topright-icon-btn" data-tooltip="Memory Explorer">
539
+ <button id="topright-memory-explorer-btn" class="topright-icon-btn" aria-label="${t('toolbar.memoryExplorer')}" data-tooltip="${t('toolbar.memoryExplorer')}">
456
540
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M12 5a3 3 0 1 0-5.997.125 4 4 0 0 0-2.526 5.77 4 4 0 0 0 .556 6.588A4 4 0 1 0 12 18Z"/><path d="M12 5a3 3 0 1 1 5.997.125 4 4 0 0 1 2.526 5.77 4 4 0 0 1-.556 6.588A4 4 0 1 1 12 18Z"/><path d="M15 13a4.5 4.5 0 0 1-3-4 4.5 4.5 0 0 1-3 4"/></svg>
457
541
  </button>
458
542
 
459
- <button id="topright-file-explorer-btn" class="topright-icon-btn" data-tooltip="File Explorer">
543
+ <button id="topright-file-explorer-btn" class="topright-icon-btn" aria-label="${t('toolbar.fileExplorer')}" data-tooltip="${t('toolbar.fileExplorer')}">
460
544
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg>
461
545
  </button>
462
546
 
463
- <span class="tr-divider"></span>
464
-
465
547
  <div id="bookmarks-overlay">
466
- <button id="topright-bookmarks-btn" class="topright-icon-btn" data-tooltip="Bookmarks">
548
+ <button id="topright-bookmarks-btn" class="topright-icon-btn" aria-label="${t('nav.bookmarks')}" data-tooltip="${t('nav.bookmarks')}">
467
549
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M19 21l-7-5-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z"/></svg>
468
550
  <span class="count-badge count-badge--gold" id="bookmark-count"></span>
469
551
  </button>
@@ -471,40 +553,36 @@ ${is3D ? `
471
553
  <div id="bookmarks-list"></div>
472
554
  </div>
473
555
  </div>
556
+
557
+ <button id="topright-trash-btn" class="topright-icon-btn" aria-label="${t('nav.trash')}" data-tooltip="${t('nav.trash')}">
558
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M4 6h16"/><path d="M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/><line x1="10" y1="10" x2="10" y2="18"/><line x1="14" y1="10" x2="14" y2="18"/></svg>
559
+ <span class="count-badge count-badge--red" id="titlebar-trash-count"></span>
560
+ </button>
561
+
562
+ <span class="tr-divider"></span>
563
+
474
564
  <div id="invite-overlay">
475
- <button id="invite-btn" class="topright-icon-btn" data-tooltip="Share / Invite">
565
+ <button id="invite-btn" class="topright-icon-btn" aria-label="${t('toolbar.share')}" data-tooltip="${t('toolbar.share')}">
476
566
  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><circle cx="18" cy="5" r="3"/><circle cx="6" cy="12" r="3"/><circle cx="18" cy="19" r="3"/><line x1="8.59" y1="13.51" x2="15.42" y2="17.49"/><line x1="15.41" y1="6.51" x2="8.59" y2="10.49"/></svg>
477
567
  <span class="count-badge count-badge--blue" id="invite-session-count" style="display:none"></span>
478
568
  </button>
479
569
  <div id="invite-dropdown" style="display:none;"></div>
480
570
  </div>
481
571
 
482
- <span class="tr-divider"></span>
572
+ <button id="topright-keybinds-btn" class="topright-icon-btn" aria-label="${t('toolbar.keybinds')}" data-tooltip="${t('toolbar.keybinds')}">
573
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="4" width="20" height="16" rx="3"/><circle cx="7" cy="9" r="1" fill="currentColor" stroke="none"/><circle cx="12" cy="9" r="1" fill="currentColor" stroke="none"/><circle cx="17" cy="9" r="1" fill="currentColor" stroke="none"/><path d="M7 15h10"/></svg>
574
+ </button>
483
575
 
484
- <div id="workspace-overlay">
485
- <div id="ws-indicator">
486
- <svg class="ws-icon" viewBox="0 0 24 24"><path d="M12 2L2 7l10 5 10-5-10-5z"/><path d="M2 17l10 5 10-5"/><path d="M2 12l10 5 10-5"/></svg>
487
- <span id="ws-active-name">No workspace</span>
488
- <button id="ws-quick-save" class="ws-quick-save" data-tooltip="Quick save"><svg viewBox="0 0 24 24"><path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"/><polyline points="17 21 17 13 7 13 7 21"/><polyline points="7 3 7 8 15 8"/></svg></button>
489
- <svg class="ws-chevron" viewBox="0 0 24 24"><path d="M6 9l6 6 6-6"/></svg>
490
- </div>
491
- <div id="ws-dropdown" style="display:none;">
492
- <div class="ws-save-bar">
493
- <input type="text" id="ws-name-input" placeholder="Save workspace..." autocomplete="off" spellcheck="false">
494
- <button id="ws-save-btn" data-tooltip="Save"><svg viewBox="0 0 24 24"><path d="M19 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11l5 5v11a2 2 0 0 1-2 2z"/><polyline points="17 21 17 13 7 13 7 21"/><polyline points="7 3 7 8 15 8"/></svg></button>
495
- </div>
496
- <button id="ws-clear-btn" class="ws-new-btn"><svg viewBox="0 0 24 24"><path d="M3 6h18"/><path d="M8 6V4h8v2"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"/></svg>Clear workspace</button>
497
- <div class="ws-divider"></div>
498
- <div id="ws-list" class="ws-list"></div>
499
- <div class="ws-divider"></div>
500
- <div class="ws-footer">
501
- <button id="ws-export-btn" class="ws-footer-btn" title="Export all workspaces"><svg viewBox="0 0 24 24"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>Export</button>
502
- <button id="ws-import-btn" class="ws-footer-btn" title="Import workspaces"><svg viewBox="0 0 24 24"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="17 8 12 3 7 8"/><line x1="12" y1="3" x2="12" y2="15"/></svg>Import</button>
503
- </div>
504
- <input type="file" id="ws-import-file" accept=".json" style="display:none;">
505
- </div>
506
- </div>
576
+ <button id="topright-update-btn" class="topright-icon-btn" style="display:none" data-tooltip="Update available">
577
+ <svg viewBox="0 0 24 24" width="16" height="16" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>
578
+ <span class="count-badge count-badge--green" id="update-badge"></span>
579
+ </button>
507
580
  </div>
581
+ <div id="topright-buttons">
582
+ <button id="topright-tools-btn" class="topright-icon-btn" type="button" aria-expanded="true" aria-controls="topright-inner" aria-label="${t('toolbar.hideTools')}" data-tooltip="${t('toolbar.hideTools')}">
583
+ <svg viewBox="0 0 24 24"><path d="M13 17l5-5-5-5"/><path d="M6 17l5-5-5-5"/></svg>
584
+ <span class="topright-tools-dot" aria-hidden="true"></span>
585
+ </button>
508
586
  <button id="topright-assistant-panel-btn" class="topright-icon-btn" data-tooltip="${t('assistant.panel.open')}">
509
587
  <svg viewBox="0 0 24 24" fill="currentColor"><rect x="8" y="5.5" width="11" height="5" rx="2.5" transform="rotate(-12 13.5 8)"/><rect x="4.5" y="12.5" width="11" height="5" rx="2.5" transform="rotate(-12 10 15)"/></svg>
510
588
  </button>
@@ -520,12 +598,7 @@ ${is3D ? `
520
598
  <svg viewBox="0 0 24 30" fill="currentColor"><path d="M18 6H6V24H18V6ZM24 30H0V0H24V30Z"/></svg>
521
599
  <span class="count-badge count-badge--green" id="opencode-update-badge"></span>
522
600
  </button>
523
- <button id="topright-collapse-btn" class="topright-collapse-btn" data-tooltip="Hide all toolbars">
524
- <svg viewBox="0 0 24 24" class="collapse-chevron"><polyline points="9 18 15 12 9 6"/></svg>
525
- <span class="collapse-dots">
526
- <span></span><span></span><span></span>
527
- </span>
528
- </button>
601
+ </div>
529
602
  <div id="term-minimized-tray"></div>
530
603
  </div>
531
604
 
@@ -626,130 +699,46 @@ ${is3D ? `
626
699
  <div id="file-explorer-panel">
627
700
  <div class="fe-project-row">
628
701
  <div class="fe-project-selector" id="fe-project-selector">
629
- <button class="fe-project-btn" id="fe-project-btn">
630
- <svg class="fe-project-icon" viewBox="0 0 24 24"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg>
631
- <span class="fe-project-label" id="fe-project-label">Project</span>
632
- <svg class="fe-project-chevron" viewBox="0 0 24 24"><polyline points="6 9 12 15 18 9"/></svg>
702
+ <button type="button" class="fe-project-btn" id="fe-project-btn">
703
+ <svg class="fe-project-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/></svg>
704
+ <span class="fe-project-label" id="fe-project-label">${t('fileExplorer.project.none')}</span>
705
+ <svg class="fe-project-chevron" viewBox="0 0 24 24" aria-hidden="true"><polyline points="6 9 12 15 18 9"/></svg>
633
706
  </button>
634
707
  <div class="fe-project-dropdown" id="fe-project-dropdown"></div>
635
708
  </div>
636
- <button class="fe-branch-btn" id="fe-branch-btn" style="display:none">
637
- <svg viewBox="0 0 24 24"><line x1="6" y1="3" x2="6" y2="15"/><circle cx="18" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><path d="M18 9a9 9 0 0 1-9 9"/></svg>
709
+ <button type="button" class="fe-branch-btn" id="fe-branch-btn" style="display:none">
710
+ <svg viewBox="0 0 24 24" aria-hidden="true"><line x1="6" y1="3" x2="6" y2="15"/><circle cx="18" cy="6" r="3"/><circle cx="6" cy="18" r="3"/><path d="M18 9a9 9 0 0 1-9 9"/></svg>
638
711
  <span class="fe-branch-btn-name" id="fe-branch-btn-name"></span>
639
712
  <span class="fe-branch-btn-badge" id="fe-branch-btn-badge"></span>
640
713
  </button>
641
714
  </div>
642
715
  <div class="fe-filter">
643
- <svg class="fe-filter-icon" viewBox="0 0 24 24"><circle cx="11" cy="11" r="7"/><line x1="16.5" y1="16.5" x2="21" y2="21"/></svg>
644
- <input type="text" id="fe-filter-input" placeholder="Search files..." autocomplete="off" spellcheck="false">
645
- <button id="fe-filter-clear">&times;</button>
716
+ <svg class="fe-filter-icon" viewBox="0 0 24 24" aria-hidden="true"><path d="M3 5h18l-7 8v6l-4-2v-4z"/></svg>
717
+ <input type="text" id="fe-filter-input" placeholder="${t('fileExplorer.filter.placeholder')}" aria-label="${t('fileExplorer.filter.label')}" autocomplete="off" spellcheck="false">
718
+ <button type="button" id="fe-filter-clear" aria-label="${t('fileExplorer.filter.clear')}" hidden>&times;</button>
646
719
  </div>
647
- <div class="fe-toolbar">
648
- <button class="detail-action-btn" id="fe-collapse-all" data-tooltip="Collapse all"><svg viewBox="0 0 24 24"><path d="M4 6h16M4 12h16M4 18h16"/></svg></button>
649
- <button class="detail-action-btn" id="fe-expand-all" data-tooltip="Expand all"><svg viewBox="0 0 24 24"><path d="M4 6h16M4 12h10M4 18h16M18 9v6"/></svg></button>
720
+ <div class="fe-toolbar" role="toolbar" aria-label="${t('fileExplorer.title')}">
721
+ <button type="button" class="detail-action-btn" id="fe-new-file" data-tooltip="${t('fileExplorer.toolbar.newFile')}" aria-label="${t('fileExplorer.toolbar.newFile')}"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><polyline points="14 2 14 8 20 8"/><line x1="12" y1="12" x2="12" y2="18"/><line x1="9" y1="15" x2="15" y2="15"/></svg></button>
722
+ <button type="button" class="detail-action-btn" id="fe-new-folder" data-tooltip="${t('fileExplorer.toolbar.newFolder')}" aria-label="${t('fileExplorer.toolbar.newFolder')}"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"/><line x1="12" y1="11" x2="12" y2="17"/><line x1="9" y1="14" x2="15" y2="14"/></svg></button>
650
723
  <div class="detail-action-sep"></div>
651
- <button class="detail-action-btn" id="fe-sort-btn" data-tooltip="Sort: name"><svg viewBox="0 0 24 24"><path d="M3 6h7M3 12h5M3 18h3M16 4v16M12 16l4 4 4-4"/></svg></button>
724
+ <button type="button" class="detail-action-btn" id="fe-goto-file" data-tooltip="${t('fileExplorer.toolbar.goToFile')}" aria-label="${t('fileExplorer.toolbar.goToFile')}"><svg viewBox="0 0 24 24" aria-hidden="true"><circle cx="11" cy="11" r="7"/><line x1="16.5" y1="16.5" x2="21" y2="21"/></svg></button>
725
+ <button type="button" class="detail-action-btn" id="fe-reveal-active" data-tooltip="${t('fileExplorer.toolbar.revealActive')}" aria-label="${t('fileExplorer.toolbar.revealActive')}" disabled><svg viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="8"/><circle cx="12" cy="12" r="2"/><line x1="12" y1="1" x2="12" y2="4"/><line x1="12" y1="20" x2="12" y2="23"/><line x1="1" y1="12" x2="4" y2="12"/><line x1="20" y1="12" x2="23" y2="12"/></svg></button>
726
+ <button type="button" class="detail-action-btn" id="fe-changed-only" data-tooltip="${t('fileExplorer.toolbar.changedOnly')}" aria-label="${t('fileExplorer.toolbar.changedOnly')}" aria-pressed="false"><svg viewBox="0 0 24 24" aria-hidden="true"><circle cx="18" cy="18" r="3"/><circle cx="6" cy="6" r="3"/><path d="M6 21V9a9 9 0 0 0 9 9"/></svg></button>
652
727
  <div class="detail-action-sep"></div>
653
- <button class="detail-action-btn fe-disabled" id="fe-undo-btn" data-tooltip="Undo delete"><svg viewBox="0 0 24 24"><polyline points="1 4 1 10 7 10"/><path d="M3.51 15a9 9 0 1 0 2.13-9.36L1 10"/></svg></button>
654
- <button class="detail-action-btn fe-disabled" id="fe-redo-btn" data-tooltip="Redo delete"><svg viewBox="0 0 24 24"><polyline points="23 4 23 10 17 10"/><path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10"/></svg></button>
655
- <div class="detail-action-sep"></div>
656
- <button class="detail-action-btn" id="fe-refresh" data-tooltip="Refresh"><svg viewBox="0 0 24 24"><polyline points="23 4 23 10 17 10"/><path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10"/></svg></button>
728
+ <button type="button" class="detail-action-btn" id="fe-collapse-all" data-tooltip="${t('fileExplorer.toolbar.collapseAll')}" aria-label="${t('fileExplorer.toolbar.collapseAll')}"><svg viewBox="0 0 24 24" aria-hidden="true"><path d="M4 14h6v6"/><path d="M20 10h-6V4"/><path d="M14 10l7-7"/><path d="M3 21l7-7"/></svg></button>
729
+ <button type="button" class="detail-action-btn" id="fe-refresh" data-tooltip="${t('fileExplorer.toolbar.refresh')}" aria-label="${t('fileExplorer.toolbar.refresh')}"><svg viewBox="0 0 24 24" aria-hidden="true"><polyline points="23 4 23 10 17 10"/><path d="M20.49 15a9 9 0 1 1-2.12-9.36L23 10"/></svg></button>
730
+ <button type="button" class="detail-action-btn" id="fe-more" data-tooltip="${t('fileExplorer.toolbar.more')}" aria-label="${t('fileExplorer.toolbar.more')}" aria-haspopup="menu"><svg viewBox="0 0 24 24" aria-hidden="true"><circle cx="5" cy="12" r="1.5"/><circle cx="12" cy="12" r="1.5"/><circle cx="19" cy="12" r="1.5"/></svg></button>
657
731
  </div>
658
732
  <div id="fe-tree" class="fe-tree"></div>
733
+ <div class="fe-notice" id="fe-notice" role="status" hidden><span class="fe-notice-text"></span><button type="button" class="fe-notice-action" hidden></button><button type="button" class="fe-notice-close">&times;</button></div>
659
734
  <div class="fe-footer">
660
- <span id="fe-count">0 items</span>
735
+ <span id="fe-count" aria-live="polite"></span>
736
+ <span class="fe-restart-hint" id="fe-restart-hint" role="img" tabindex="0" data-tooltip="${t('fileExplorer.state.restartHint')}" aria-label="${t('fileExplorer.state.restartHint')}" hidden><svg viewBox="0 0 24 24" aria-hidden="true"><circle cx="12" cy="12" r="9"/><line x1="12" y1="11" x2="12" y2="16"/><circle cx="12" cy="8" r="0.6"/></svg></span>
661
737
  </div>
662
- <div class="fe-resize-handle" id="fe-resize-handle"></div>
738
+ <div class="fe-resize-handle" id="fe-resize-handle" role="separator" aria-orientation="vertical" aria-label="${t('fileExplorer.resize')}" tabindex="0"></div>
663
739
  </div>
664
740
 
665
- <!-- File Editor (separate panel, slides from file explorer's right edge) -->
666
- <div id="fe-editor-panel" class="fe-editor-panel">
667
- <div class="fe-editor-header">
668
- <button class="fe-editor-back" id="fe-editor-back" data-tooltip="Close editor">
669
- <svg viewBox="0 0 24 24"><polyline points="15 18 9 12 15 6"/></svg>
670
- </button>
671
- <span class="fe-editor-dot" id="fe-editor-dot"></span>
672
- <span class="fe-editor-filepath" id="fe-editor-filepath"></span>
673
- <div style="flex:1"></div>
674
- <button class="fe-editor-action" id="fe-editor-find-btn" data-tooltip="Find (Ctrl+F)">
675
- <svg viewBox="0 0 24 24"><circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/></svg>
676
- </button>
677
- <button class="fe-editor-action" id="fe-editor-word-wrap" data-tooltip="Toggle word wrap">
678
- <svg viewBox="0 0 24 24"><path d="M3 6h18M3 12h15a3 3 0 1 1 0 6h-4"/><polyline points="16 16 14 18 16 20"/><path d="M3 18h7"/></svg>
679
- </button>
680
- <div class="fe-editor-help-wrap">
681
- <button class="fe-editor-action fe-editor-help-btn" id="fe-editor-help-btn" data-tooltip="Keyboard shortcuts">
682
- <svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="10"/><path d="M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3"/><line x1="12" y1="17" x2="12.01" y2="17"/></svg>
683
- </button>
684
- <div class="fe-editor-keybinds" id="fe-editor-keybinds">
685
- <div class="fe-editor-keybinds-title">Keyboard Shortcuts</div>
686
- <div class="fe-editor-kb"><kbd>Ctrl+S</kbd> <span>Save</span></div>
687
- <div class="fe-editor-kb"><kbd>Ctrl+F</kbd> <span>Find</span></div>
688
- <div class="fe-editor-kb"><kbd>Ctrl+H</kbd> <span>Replace</span></div>
689
- <div class="fe-editor-kb"><kbd>Ctrl+G</kbd> <span>Go to Line</span></div>
690
- <div class="fe-editor-kb"><kbd>Ctrl+D</kbd> <span>Duplicate Line</span></div>
691
- <div class="fe-editor-kb"><kbd>Ctrl+/</kbd> <span>Toggle Comment</span></div>
692
- <div class="fe-editor-kb"><kbd>Tab</kbd> <span>Indent</span></div>
693
- <div class="fe-editor-kb"><kbd>Shift+Tab</kbd> <span>Unindent</span></div>
694
- <div class="fe-editor-kb"><kbd>Enter</kbd> <span>Auto-indent</span></div>
695
- <div class="fe-editor-kb"><kbd>Esc</kbd> <span>Close panel</span></div>
696
- </div>
697
- </div>
698
- <div class="fe-editor-sep"></div>
699
- <div class="fe-editor-view-toggle" id="fe-editor-view-toggle" style="display:none">
700
- <button class="fe-editor-toggle-btn active" data-mode="raw">Raw</button>
701
- <button class="fe-editor-toggle-btn" data-mode="preview">Preview</button>
702
- </div>
703
- <div class="fe-editor-sep" id="fe-editor-sep-preview" style="display:none"></div>
704
- <button class="fe-editor-btn" id="fe-editor-discard" disabled>Discard</button>
705
- <button class="fe-editor-btn fe-editor-save" id="fe-editor-save" disabled>Save</button>
706
- <button class="fe-editor-btn" id="fe-editor-close">Close</button>
707
- </div>
708
- <div class="fe-editor-find" id="fe-editor-find">
709
- <div class="fe-editor-find-row">
710
- <input type="text" class="fe-editor-find-input" id="fe-editor-find-input" placeholder="Find..." spellcheck="false" autocomplete="off" />
711
- <span class="fe-editor-find-count" id="fe-editor-find-count"></span>
712
- <button class="fe-editor-find-nav" id="fe-editor-find-prev" data-tooltip="Previous">
713
- <svg viewBox="0 0 24 24"><polyline points="18 15 12 9 6 15"/></svg>
714
- </button>
715
- <button class="fe-editor-find-nav" id="fe-editor-find-next" data-tooltip="Next">
716
- <svg viewBox="0 0 24 24"><polyline points="6 9 12 15 18 9"/></svg>
717
- </button>
718
- <button class="fe-editor-find-nav" id="fe-editor-find-close" data-tooltip="Close">
719
- <svg viewBox="0 0 24 24"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
720
- </button>
721
- </div>
722
- <div class="fe-editor-replace-row">
723
- <input type="text" class="fe-editor-replace-input" id="fe-editor-replace-input" placeholder="Replace..." spellcheck="false" autocomplete="off" />
724
- <button class="fe-editor-replace-btn" id="fe-editor-replace">Replace</button>
725
- <button class="fe-editor-replace-btn" id="fe-editor-replace-all">All</button>
726
- </div>
727
- </div>
728
- <div class="fe-editor-goto" id="fe-editor-goto">
729
- <span class="fe-editor-goto-label">Go to Line</span>
730
- <input type="number" class="fe-editor-goto-input" id="fe-editor-goto-input" min="1" placeholder="Line..." />
731
- </div>
732
- <div class="fe-editor-body">
733
- <div class="fe-editor-gutter" id="fe-editor-gutter"></div>
734
- <div class="fe-editor-line-highlight" id="fe-editor-line-highlight"></div>
735
- <pre class="fe-editor-highlight" id="fe-editor-highlight" aria-hidden="true"><code id="fe-editor-highlight-code"></code></pre>
736
- <textarea class="fe-editor-textarea" id="fe-editor-textarea"
737
- spellcheck="false" autocorrect="off" autocapitalize="off"></textarea>
738
- <div class="fe-editor-preview" id="fe-editor-preview"></div>
739
- <div class="fe-editor-scrollmap" id="fe-editor-scrollmap">
740
- <div class="fe-editor-scrollmap-thumb" id="fe-editor-scrollmap-thumb"></div>
741
- </div>
742
- </div>
743
- <div class="fe-editor-statusbar">
744
- <span id="fe-editor-lang"></span>
745
- <div style="flex:1"></div>
746
- <span id="fe-editor-cursor">Ln 1, Col 1</span>
747
- <span class="fe-editor-sep"></span>
748
- <span id="fe-editor-size"></span>
749
- <span class="fe-editor-sep"></span>
750
- <span>UTF-8</span>
751
- </div>
752
- </div>
741
+ ${getEditorPanelHTML()}
753
742
 
754
743
  <!-- Detail cards are spawned dynamically by ui-detail.js -->
755
744
 
@@ -833,6 +822,12 @@ ${is3D ? `
833
822
  <svg viewBox="0 0 24 24"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/></svg>
834
823
  </button>
835
824
  <div class="wb-tool-sep"></div>
825
+ <button class="wb-tool wb-toggle" id="ws-grid-toggle" type="button" aria-pressed="false" aria-label="${t('toolbar.snapToGrid')}" data-tooltip="${t('toolbar.snapToGrid')}">
826
+ <svg viewBox="0 0 24 24"><g fill="currentColor" stroke="none"><circle cx="6" cy="6" r="1.6"/><circle cx="12" cy="6" r="1.6"/><circle cx="18" cy="6" r="1.6"/><circle cx="6" cy="12" r="1.6"/><circle cx="12" cy="12" r="1.6"/><circle cx="18" cy="12" r="1.6"/><circle cx="6" cy="18" r="1.6"/><circle cx="12" cy="18" r="1.6"/><circle cx="18" cy="18" r="1.6"/></g></svg>
827
+ </button>
828
+ <button class="wb-tool" id="ws-tile-btn" type="button" aria-label="${t('toolbar.tileTerminals')}" data-tooltip="${t('toolbar.tileTerminals')}">
829
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="8" height="8" rx="2"/><rect x="13" y="3" width="8" height="8" rx="2"/><rect x="3" y="13" width="8" height="8" rx="2"/><rect x="13" y="13" width="8" height="8" rx="2"/></svg>
830
+ </button>
836
831
  <button class="wb-tool wb-tool-sm" id="wb-toggle-logo" data-tooltip="Toggle logo">
837
832
  <img src="logo-synabun.png" alt="" style="width:18px;height:auto;opacity:0.6;">
838
833
  </button>
@@ -18,6 +18,8 @@
18
18
 
19
19
  import { state, emit } from '../state.js';
20
20
  import { injectStyles } from './ocp-v2-styles.js';
21
+ import { getDefaultStore } from './ocp-v2-state.js';
22
+ import { wireFileLinks } from '../ui-file-links.js';
21
23
  import { mountRenderer } from './ocp-v2-render.js';
22
24
  import { mountCompose } from './ocp-v2-send.js';
23
25
  import { trackContextGauge } from './ocp-v2-context-gauge.js';
@@ -212,6 +214,8 @@ export function createChildPanel({
212
214
  messages.className = 'ocpv2-messages';
213
215
  messagesContainer.appendChild(messages);
214
216
  panel.appendChild(messagesContainer);
217
+ // File links open in the code editor, as in the main panel: a sub-agent works in its parent's directory.
218
+ wireFileLinks(messagesContainer, { cwd: () => store.getState().cwd || getDefaultStore().getState().cwd || '' });
215
219
 
216
220
  // This panel's own questions (closing it with prompts waiting, deleting a
217
221
  // message) show above its compose box.
@@ -0,0 +1,47 @@
1
+ // OpenCode panel — the greeting in the empty state (shared/greeting/, lib/greeting/).
2
+ //
3
+ // What SynaBun says when a person comes back and opens a new session: one or
4
+ // two sentences, written by SynaBun ahead of time (the session's model never
5
+ // greets). Only for a session with nothing in it that a person opened: never
6
+ // an automation run's. The greeting's id goes back with the first message
7
+ // (`greetingId` on message:send), so the model is told once what was said.
8
+ // A server older than this page simply answers nothing.
9
+
10
+ import { clearGreeting, forgetGreeting, mountGreeting } from '../greeting/greeting-card.js';
11
+
12
+ const SURFACE = 'opencode-panel';
13
+ let pending = null; // { id, sessionId } — the greeting on screen, until a first message carries it
14
+
15
+ /**
16
+ * The empty state is on screen. `host`: its element (kept between renders, so asked once).
17
+ * ctx: { sessionId, cwd, automation, onOpenMemory(id), isCurrent() }
18
+ */
19
+ export function offerGreeting(host, { sessionId = null, cwd = '', automation = false, onOpenMemory = null, isCurrent = null } = {}) {
20
+ if (!host) return;
21
+ const key = sessionId || '';
22
+ if (host.dataset.greetingFor === key && host.dataset.greetingAsked === '1') return;
23
+ host.dataset.greetingFor = key;
24
+ host.dataset.greetingAsked = '1';
25
+ clearGreeting(host);
26
+ if (automation) return;
27
+ mountGreeting(host, {
28
+ surface: SURFACE, session: sessionId || null, cwd,
29
+ onOpenMemory,
30
+ isCurrent: () => host.dataset.greetingFor === key && (typeof isCurrent !== 'function' || isCurrent() !== false),
31
+ }).then((greeting) => {
32
+ if (greeting && host.dataset.greetingFor === key) pending = { id: greeting.id, sessionId: sessionId || null };
33
+ }).catch(() => { /* a session always opens */ });
34
+ }
35
+
36
+ /** The id to send with a person's message to `sessionId`, once ('' when this session opened with no greeting). */
37
+ export function takeGreetingId(sessionId) {
38
+ const held = pending;
39
+ if (!held) return '';
40
+ // A greeting shown before the session had an id belongs to the first session a message goes to.
41
+ if (held.sessionId && sessionId && held.sessionId !== sessionId) return '';
42
+ pending = null;
43
+ if (held.sessionId) forgetGreeting(SURFACE, held.sessionId);
44
+ return held.id || '';
45
+ }
46
+
47
+ export const _test = { reset() { pending = null; }, pending: () => pending };