synabun 2.0.9 → 2.1.0

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 (679) hide show
  1. package/CHANGELOG.md +115 -0
  2. package/README.md +25 -2
  3. package/THIRD-PARTY-LICENSES.md +68 -4
  4. package/bin/synabun.js +71 -24
  5. package/docs/whatsapp.md +2 -2
  6. package/hooks/claude-code/pre-websearch.mjs +12 -1
  7. package/hooks/claude-code/shared.mjs +5 -0
  8. package/hooks/claude-code/stop.mjs +1 -1
  9. package/launcher.mjs +9 -3
  10. package/lib/claude-hooks.js +172 -18
  11. package/lib/client-config-repair.js +17 -8
  12. package/lib/desktop-app.js +7 -1
  13. package/lib/external-tools.js +1 -1
  14. package/lib/first-launch-protection.js +57 -12
  15. package/lib/mcp-dist.js +176 -0
  16. package/lib/release-npm-ci.mjs +138 -0
  17. package/lib/release-publish.mjs +91 -0
  18. package/lib/release-scan.mjs +50 -0
  19. package/lib/server-crash-record.js +123 -0
  20. package/lib/server-exit.js +318 -0
  21. package/lib/server-supervisor.js +508 -0
  22. package/lib/start-launcher.js +43 -5
  23. package/lib/tools-cli.js +45 -0
  24. package/lib/update-snapshot.js +228 -0
  25. package/lib/virustotal.mjs +192 -0
  26. package/lib/windows-crash-event.js +269 -0
  27. package/mcp-server/dist/http.d.ts +20 -1
  28. package/mcp-server/dist/http.d.ts.map +1 -1
  29. package/mcp-server/dist/http.js +59 -12
  30. package/mcp-server/dist/http.js.map +1 -1
  31. package/mcp-server/dist/index.d.ts +33 -27
  32. package/mcp-server/dist/index.d.ts.map +1 -1
  33. package/mcp-server/dist/index.js +128 -143
  34. package/mcp-server/dist/index.js.map +1 -1
  35. package/mcp-server/dist/preload.js +1 -1
  36. package/mcp-server/dist/preload.js.map +1 -1
  37. package/mcp-server/dist/services/codex-config-heal.d.ts +6 -2
  38. package/mcp-server/dist/services/codex-config-heal.d.ts.map +1 -1
  39. package/mcp-server/dist/services/codex-config-heal.js +81 -28
  40. package/mcp-server/dist/services/codex-config-heal.js.map +1 -1
  41. package/mcp-server/dist/services/memory-judge-backfill.d.ts +6 -0
  42. package/mcp-server/dist/services/memory-judge-backfill.d.ts.map +1 -1
  43. package/mcp-server/dist/services/memory-judge-backfill.js +7 -1
  44. package/mcp-server/dist/services/memory-judge-backfill.js.map +1 -1
  45. package/mcp-server/dist/services/neural-interface.d.ts +16 -10
  46. package/mcp-server/dist/services/neural-interface.d.ts.map +1 -1
  47. package/mcp-server/dist/services/neural-interface.js +67 -11
  48. package/mcp-server/dist/services/neural-interface.js.map +1 -1
  49. package/mcp-server/dist/services/server-instructions.d.ts +7 -2
  50. package/mcp-server/dist/services/server-instructions.d.ts.map +1 -1
  51. package/mcp-server/dist/services/server-instructions.js +20 -62
  52. package/mcp-server/dist/services/server-instructions.js.map +1 -1
  53. package/mcp-server/dist/services/tool-catalog.d.ts +120 -0
  54. package/mcp-server/dist/services/tool-catalog.d.ts.map +1 -0
  55. package/mcp-server/dist/services/tool-catalog.js +339 -0
  56. package/mcp-server/dist/services/tool-catalog.js.map +1 -0
  57. package/mcp-server/dist/services/tool-list-refresh-barrier.d.ts +12 -0
  58. package/mcp-server/dist/services/tool-list-refresh-barrier.d.ts.map +1 -0
  59. package/mcp-server/dist/services/tool-list-refresh-barrier.js +40 -0
  60. package/mcp-server/dist/services/tool-list-refresh-barrier.js.map +1 -0
  61. package/mcp-server/dist/services/tool-list.d.ts +108 -0
  62. package/mcp-server/dist/services/tool-list.d.ts.map +1 -0
  63. package/mcp-server/dist/services/tool-list.js +334 -0
  64. package/mcp-server/dist/services/tool-list.js.map +1 -0
  65. package/mcp-server/dist/services/tool-runtime.d.ts +161 -0
  66. package/mcp-server/dist/services/tool-runtime.d.ts.map +1 -0
  67. package/mcp-server/dist/services/tool-runtime.js +400 -0
  68. package/mcp-server/dist/services/tool-runtime.js.map +1 -0
  69. package/mcp-server/dist/services/whiteboard-geometry.d.ts +26 -2
  70. package/mcp-server/dist/services/whiteboard-geometry.d.ts.map +1 -1
  71. package/mcp-server/dist/services/whiteboard-geometry.js +91 -8
  72. package/mcp-server/dist/services/whiteboard-geometry.js.map +1 -1
  73. package/mcp-server/dist/tools/agents.d.ts +10 -10
  74. package/mcp-server/dist/tools/agents.d.ts.map +1 -1
  75. package/mcp-server/dist/tools/agents.js +22 -13
  76. package/mcp-server/dist/tools/agents.js.map +1 -1
  77. package/mcp-server/dist/tools/browser-batch.d.ts +3 -3
  78. package/mcp-server/dist/tools/image-tools.d.ts +1 -1
  79. package/mcp-server/dist/tools/image-tools.js +1 -1
  80. package/mcp-server/dist/tools/skill-tools.d.ts +505 -0
  81. package/mcp-server/dist/tools/skill-tools.d.ts.map +1 -0
  82. package/mcp-server/dist/tools/skill-tools.js +639 -0
  83. package/mcp-server/dist/tools/skill-tools.js.map +1 -0
  84. package/mcp-server/dist/tools/skill.d.ts +7 -0
  85. package/mcp-server/dist/tools/skill.d.ts.map +1 -0
  86. package/mcp-server/dist/tools/skill.js +11 -0
  87. package/mcp-server/dist/tools/skill.js.map +1 -0
  88. package/mcp-server/dist/tools/tool-groups.d.ts +68 -0
  89. package/mcp-server/dist/tools/tool-groups.d.ts.map +1 -0
  90. package/mcp-server/dist/tools/tool-groups.js +147 -0
  91. package/mcp-server/dist/tools/tool-groups.js.map +1 -0
  92. package/mcp-server/dist/tools/whiteboard-format.d.ts.map +1 -1
  93. package/mcp-server/dist/tools/whiteboard-format.js +7 -4
  94. package/mcp-server/dist/tools/whiteboard-format.js.map +1 -1
  95. package/mcp-server/dist/tools/whiteboard-tools.d.ts +64 -13
  96. package/mcp-server/dist/tools/whiteboard-tools.d.ts.map +1 -1
  97. package/mcp-server/dist/tools/whiteboard-tools.js +30 -5
  98. package/mcp-server/dist/tools/whiteboard-tools.js.map +1 -1
  99. package/mcp-server/package-lock.json +2 -2
  100. package/mcp-server/package.json +1 -1
  101. package/mcp-server/src/http.ts +75 -12
  102. package/mcp-server/src/index.ts +147 -154
  103. package/mcp-server/src/preload.ts +12 -12
  104. package/mcp-server/src/services/codex-config-heal.ts +80 -29
  105. package/mcp-server/src/services/memory-judge-backfill.ts +7 -1
  106. package/mcp-server/src/services/neural-interface.ts +79 -20
  107. package/mcp-server/src/services/server-instructions.ts +27 -63
  108. package/mcp-server/src/services/tool-catalog.ts +403 -0
  109. package/mcp-server/src/services/tool-list-refresh-barrier.ts +33 -0
  110. package/mcp-server/src/services/tool-list.ts +410 -0
  111. package/mcp-server/src/services/tool-runtime.ts +457 -0
  112. package/mcp-server/src/services/whiteboard-geometry.ts +94 -9
  113. package/mcp-server/src/tools/agents.ts +22 -14
  114. package/mcp-server/src/tools/image-tools.ts +1 -1
  115. package/mcp-server/src/tools/skill-tools.ts +589 -0
  116. package/mcp-server/src/tools/skill.ts +13 -0
  117. package/mcp-server/src/tools/tool-groups.ts +164 -0
  118. package/mcp-server/src/tools/whiteboard-format.ts +9 -3
  119. package/mcp-server/src/tools/whiteboard-tools.ts +39 -5
  120. package/neural-interface/i18n/en.json +3680 -206
  121. package/neural-interface/i18n/pt-BR.json +3628 -157
  122. package/neural-interface/lib/account-usage.js +5 -3
  123. package/neural-interface/lib/app-controls-api.js +161 -0
  124. package/neural-interface/lib/assistant-api.js +148 -35
  125. package/neural-interface/lib/assistant-brains/claude.js +4 -3
  126. package/neural-interface/lib/assistant-brains/codex-browser-policy-hook.mjs +12 -2
  127. package/neural-interface/lib/assistant-brains/codex-route-gate-hook.mjs +32 -9
  128. package/neural-interface/lib/assistant-brains/codex.js +9 -5
  129. package/neural-interface/lib/assistant-brains/opencode.js +122 -44
  130. package/neural-interface/lib/assistant-brains/opencode2-browser-policy/index.js +59 -0
  131. package/neural-interface/lib/assistant-brains/opencode2-route-gate/index.js +97 -0
  132. package/neural-interface/lib/assistant-catalog.js +23 -9
  133. package/neural-interface/lib/assistant-dispatch.js +874 -156
  134. package/neural-interface/lib/assistant-envelope.js +22 -2
  135. package/neural-interface/lib/assistant-persona.js +80 -11
  136. package/neural-interface/lib/assistant-plan-permissions.js +10 -9
  137. package/neural-interface/lib/assistant-route-gate-codex.js +3 -0
  138. package/neural-interface/lib/assistant-route-gate.js +6 -4
  139. package/neural-interface/lib/assistant-router.js +13 -8
  140. package/neural-interface/lib/assistant-runtime.js +183 -26
  141. package/neural-interface/lib/assistant-task-prompt.js +78 -14
  142. package/neural-interface/lib/assistant-tools.js +51 -0
  143. package/neural-interface/lib/backup-service.js +620 -3
  144. package/neural-interface/lib/backup-zip-reader.js +10 -5
  145. package/neural-interface/lib/backup-zip-writer.js +257 -0
  146. package/neural-interface/lib/browser-execution.js +10 -2
  147. package/neural-interface/lib/browser-guard-cdp.js +83 -0
  148. package/neural-interface/lib/browser-network-guard.js +284 -0
  149. package/neural-interface/lib/browser-policy-roots.js +64 -0
  150. package/neural-interface/lib/browser-tool-policy.js +186 -31
  151. package/neural-interface/lib/claude-agent-bridge.js +4 -2
  152. package/neural-interface/lib/claude-hooks-status.js +103 -0
  153. package/neural-interface/lib/claude-model-catalog.js +64 -14
  154. package/neural-interface/lib/claude-temporary.js +5 -11
  155. package/neural-interface/lib/cli-install.js +18 -138
  156. package/neural-interface/lib/cli-resolver.js +4 -1
  157. package/neural-interface/lib/cli-update-planner.js +32 -31
  158. package/neural-interface/lib/cloudflared/tunnel.js +42 -2
  159. package/neural-interface/lib/codex-mcp-approvals.js +11 -0
  160. package/neural-interface/lib/codex-settings-schema.js +109 -47
  161. package/neural-interface/lib/codex-worker-app-server.js +172 -0
  162. package/neural-interface/lib/confined-fs.js +30 -3
  163. package/neural-interface/lib/crash-notice-api.js +98 -0
  164. package/neural-interface/lib/editor-completion-opencode.js +164 -67
  165. package/neural-interface/lib/exec-loop-command.js +4 -1
  166. package/neural-interface/lib/http-guards.js +8 -2
  167. package/neural-interface/lib/install-details.js +4 -1
  168. package/neural-interface/lib/launch-cache.js +293 -0
  169. package/neural-interface/lib/login-start.js +524 -0
  170. package/neural-interface/lib/mcp-agent-servers.js +67 -0
  171. package/neural-interface/lib/mcp-client-config.js +0 -29
  172. package/neural-interface/lib/mcp-external-servers.js +323 -0
  173. package/neural-interface/lib/{mcp-profile-refresh-coordinator.js → mcp-tools-refresh-coordinator.js} +4 -4
  174. package/neural-interface/lib/morelogin.js +30 -0
  175. package/neural-interface/lib/native-loop-providers.js +565 -50
  176. package/neural-interface/lib/native-loop-runtime.js +287 -41
  177. package/neural-interface/lib/opencode-config.js +557 -0
  178. package/neural-interface/lib/opencode-db-schema.js +58 -0
  179. package/neural-interface/lib/opencode-history.js +49 -204
  180. package/neural-interface/lib/opencode-mcp-ready.js +108 -0
  181. package/neural-interface/lib/opencode-native-boundary.js +44 -0
  182. package/neural-interface/lib/opencode-protocol.js +310 -0
  183. package/neural-interface/lib/opencode-provider-view.js +81 -0
  184. package/neural-interface/lib/opencode-runtime-config.js +32 -15
  185. package/neural-interface/lib/opencode-serve-records.js +624 -0
  186. package/neural-interface/lib/opencode-v2-client.js +53 -131
  187. package/neural-interface/lib/opencode-v2-ws-requests.js +35 -195
  188. package/neural-interface/lib/opencode-worker-activity.js +229 -0
  189. package/neural-interface/lib/opencode-worker-data.js +27 -0
  190. package/neural-interface/lib/opencode2-client.js +796 -0
  191. package/neural-interface/lib/opencode2-proxy.js +76 -0
  192. package/neural-interface/lib/opencode2-translate.js +1057 -0
  193. package/neural-interface/lib/owner-authority.js +249 -0
  194. package/neural-interface/lib/page-session.js +275 -0
  195. package/neural-interface/lib/peer-identity.js +763 -0
  196. package/neural-interface/lib/process-identity.js +361 -0
  197. package/neural-interface/lib/request-gate.js +17 -2
  198. package/neural-interface/lib/rulesets/api.js +1 -1
  199. package/neural-interface/lib/rulesets/fs-safe.js +1 -1
  200. package/neural-interface/lib/rulesets/installer.js +92 -27
  201. package/neural-interface/lib/rulesets/json-edit.js +1 -1
  202. package/neural-interface/lib/session-cache-builder.js +18 -10
  203. package/neural-interface/lib/session-title-generator.js +58 -18
  204. package/neural-interface/lib/skills/api-v2.js +495 -0
  205. package/neural-interface/lib/skills/bundle.js +418 -0
  206. package/neural-interface/lib/skills/catalog.js +294 -0
  207. package/neural-interface/lib/skills/creation-api.js +191 -0
  208. package/neural-interface/lib/skills/creation-brief.js +247 -0
  209. package/neural-interface/lib/skills/creation-sources.js +267 -0
  210. package/neural-interface/lib/skills/creation.js +843 -0
  211. package/neural-interface/lib/skills/deploy.js +564 -0
  212. package/neural-interface/lib/skills/digest.js +119 -0
  213. package/neural-interface/lib/skills/discover.js +111 -0
  214. package/neural-interface/lib/skills/draft-confinement.js +214 -0
  215. package/neural-interface/lib/skills/eval-confinement.js +397 -0
  216. package/neural-interface/lib/skills/eval-sandbox.js +280 -0
  217. package/neural-interface/lib/skills/eval-trace.js +119 -0
  218. package/neural-interface/lib/skills/evals-api.js +212 -0
  219. package/neural-interface/lib/skills/evals.js +1573 -0
  220. package/neural-interface/lib/skills/export.js +200 -0
  221. package/neural-interface/lib/skills/frontmatter.js +64 -0
  222. package/neural-interface/lib/skills/health.js +75 -0
  223. package/neural-interface/lib/skills/json-edit.js +165 -0
  224. package/neural-interface/lib/skills/known-bridge-digests.json +387 -0
  225. package/neural-interface/lib/skills/known-bridges.js +96 -0
  226. package/neural-interface/lib/skills/library.js +823 -0
  227. package/neural-interface/lib/skills/local-store.js +21 -0
  228. package/neural-interface/lib/skills/migration.js +433 -0
  229. package/neural-interface/lib/skills/operations.js +45 -0
  230. package/neural-interface/lib/skills/ownership.js +427 -0
  231. package/neural-interface/lib/skills/packages.js +88 -0
  232. package/neural-interface/lib/skills/reviews.js +212 -0
  233. package/neural-interface/lib/skills/revision.js +80 -0
  234. package/neural-interface/lib/skills/roots.js +262 -0
  235. package/neural-interface/lib/skills/runtime-checks.js +355 -0
  236. package/neural-interface/lib/skills/scan-assets.js +252 -0
  237. package/neural-interface/lib/skills/scan-context.js +26 -0
  238. package/neural-interface/lib/skills/scan-shell.js +324 -0
  239. package/neural-interface/lib/skills/scan.js +364 -0
  240. package/neural-interface/lib/skills/scanners.js +54 -0
  241. package/neural-interface/lib/skills/service.js +522 -0
  242. package/neural-interface/lib/skills/telemetry.js +113 -0
  243. package/neural-interface/lib/sqlite-integrity-worker.js +22 -0
  244. package/neural-interface/lib/style-guide/api.js +4 -3
  245. package/neural-interface/lib/tool-lists.js +124 -0
  246. package/neural-interface/lib/untrusted-file-headers.js +27 -0
  247. package/neural-interface/lib/whatsapp/bridge.js +6 -3
  248. package/neural-interface/lib/worker-confinement.js +1192 -0
  249. package/neural-interface/lib/worker-guard-setting.js +56 -0
  250. package/neural-interface/lib/worker-mcp-channel.js +175 -0
  251. package/neural-interface/lib/worker-relay-ports.js +227 -0
  252. package/neural-interface/lib/worker-resume.js +229 -0
  253. package/neural-interface/lib/worker-sandbox.js +299 -0
  254. package/neural-interface/package-lock.json +1354 -50
  255. package/neural-interface/package.json +6 -2
  256. package/neural-interface/public/index.html +5 -3
  257. package/neural-interface/public/index2d.html +19 -11
  258. package/neural-interface/public/onboarding.html +2 -2
  259. package/neural-interface/public/shared/account-menu.js +8 -5
  260. package/neural-interface/public/shared/agent-runtime-options.js +76 -16
  261. package/neural-interface/public/shared/api.js +1527 -1336
  262. package/neural-interface/public/shared/app-frame.js +192 -0
  263. package/neural-interface/public/shared/assistant/asst-agents-dock.js +205 -19
  264. package/neural-interface/public/shared/assistant/asst-api.js +11 -3
  265. package/neural-interface/public/shared/assistant/asst-ask-styles.js +270 -0
  266. package/neural-interface/public/shared/assistant/asst-ask-tail.js +118 -0
  267. package/neural-interface/public/shared/assistant/asst-ask.js +397 -0
  268. package/neural-interface/public/shared/assistant/asst-brain-picker.js +241 -112
  269. package/neural-interface/public/shared/assistant/asst-composer.js +1 -1
  270. package/neural-interface/public/shared/assistant/asst-control.js +157 -26
  271. package/neural-interface/public/shared/assistant/asst-followups-card.js +383 -0
  272. package/neural-interface/public/shared/assistant/asst-followups.js +417 -0
  273. package/neural-interface/public/shared/assistant/asst-hosts.js +49 -2
  274. package/neural-interface/public/shared/assistant/asst-limit-dock.js +40 -0
  275. package/neural-interface/public/shared/assistant/asst-limit-wait.js +294 -0
  276. package/neural-interface/public/shared/assistant/asst-limit.js +168 -0
  277. package/neural-interface/public/shared/assistant/asst-mascot.js +49 -12
  278. package/neural-interface/public/shared/assistant/asst-menu.js +84 -12
  279. package/neural-interface/public/shared/assistant/asst-panel.js +303 -44
  280. package/neural-interface/public/shared/assistant/asst-rack-styles.js +93 -58
  281. package/neural-interface/public/shared/assistant/asst-redact.js +186 -0
  282. package/neural-interface/public/shared/assistant/asst-render.js +770 -100
  283. package/neural-interface/public/shared/assistant/asst-route.js +83 -12
  284. package/neural-interface/public/shared/assistant/asst-run-stage.js +231 -0
  285. package/neural-interface/public/shared/assistant/asst-sanitize.js +193 -3
  286. package/neural-interface/public/shared/assistant/asst-scene-styles.js +273 -0
  287. package/neural-interface/public/shared/assistant/asst-scenes.js +530 -0
  288. package/neural-interface/public/shared/assistant/asst-sidepanel-styles.js +3 -15
  289. package/neural-interface/public/shared/assistant/asst-sidepanel.js +67 -4
  290. package/neural-interface/public/shared/assistant/asst-slash.js +9 -7
  291. package/neural-interface/public/shared/assistant/asst-state.js +25 -15
  292. package/neural-interface/public/shared/assistant/asst-stop.js +127 -0
  293. package/neural-interface/public/shared/assistant/asst-styles.js +102 -21
  294. package/neural-interface/public/shared/assistant/asst-tool-kinds.js +165 -13
  295. package/neural-interface/public/shared/automation-context.js +5 -2
  296. package/neural-interface/public/shared/cc-dropdown.js +550 -0
  297. package/neural-interface/public/shared/cdx/cdx-context-menu.js +10 -9
  298. package/neural-interface/public/shared/cdx/cdx-copy.js +16 -0
  299. package/neural-interface/public/shared/cdx/cdx-output-model.js +22 -1
  300. package/neural-interface/public/shared/cdx/cdx-output.js +8 -7
  301. package/neural-interface/public/shared/cdx/cdx-panel.js +58 -150
  302. package/neural-interface/public/shared/cdx/cdx-protocol.js +28 -1
  303. package/neural-interface/public/shared/cdx/cdx-render.js +62 -32
  304. package/neural-interface/public/shared/cdx/cdx-requests.js +3 -3
  305. package/neural-interface/public/shared/cdx/cdx-skill-hints.js +54 -0
  306. package/neural-interface/public/shared/cdx/cdx-styles.js +15 -3
  307. package/neural-interface/public/shared/cdx/cdx-tabs.js +201 -74
  308. package/neural-interface/public/shared/cdx/cdx-ws.js +0 -1
  309. package/neural-interface/public/shared/cli-install-view.js +4 -8
  310. package/neural-interface/public/shared/cli-status.js +2 -2
  311. package/neural-interface/public/shared/constants.js +2 -2
  312. package/neural-interface/public/shared/context-menu-areas.js +34 -0
  313. package/neural-interface/public/shared/context-menu-logic.js +243 -0
  314. package/neural-interface/public/shared/context-menu-model.js +366 -0
  315. package/neural-interface/public/shared/context-menu.js +372 -0
  316. package/neural-interface/public/shared/cp/cp-context-menu.js +10 -9
  317. package/neural-interface/public/shared/cp/cp-markdown.js +4 -57
  318. package/neural-interface/public/shared/crash-notice-view.js +168 -0
  319. package/neural-interface/public/shared/data-cache.js +223 -0
  320. package/neural-interface/public/shared/desktop-bridge.js +11 -0
  321. package/neural-interface/public/shared/desktop-titlebar-view.js +78 -1
  322. package/neural-interface/public/shared/desktop-titlebar.js +214 -28
  323. package/neural-interface/public/shared/desktop-update-view.js +35 -5
  324. package/neural-interface/public/shared/editor/editor-panel-logic.js +2 -2
  325. package/neural-interface/public/shared/file-links.js +73 -8
  326. package/neural-interface/public/shared/html-shell.js +78 -86
  327. package/neural-interface/public/shared/i18n.js +2 -0
  328. package/neural-interface/public/shared/launch-prefetch.js +59 -0
  329. package/neural-interface/public/shared/ocp-v2/ocp-v2-approvals.js +7 -7
  330. package/neural-interface/public/shared/ocp-v2/ocp-v2-binding.js +4 -4
  331. package/neural-interface/public/shared/ocp-v2/ocp-v2-caps.js +3 -2
  332. package/neural-interface/public/shared/ocp-v2/ocp-v2-changes-logic.js +3 -101
  333. package/neural-interface/public/shared/ocp-v2/ocp-v2-childpanel.js +9 -2
  334. package/neural-interface/public/shared/ocp-v2/ocp-v2-compact-button.js +1 -3
  335. package/neural-interface/public/shared/ocp-v2/ocp-v2-composer-logic.js +2 -6
  336. package/neural-interface/public/shared/ocp-v2/ocp-v2-context-menu.js +11 -11
  337. package/neural-interface/public/shared/ocp-v2/ocp-v2-context-model.js +0 -3
  338. package/neural-interface/public/shared/ocp-v2/ocp-v2-events.js +8 -4
  339. package/neural-interface/public/shared/ocp-v2/ocp-v2-manager.js +7 -7
  340. package/neural-interface/public/shared/ocp-v2/ocp-v2-modelpicker.js +54 -17
  341. package/neural-interface/public/shared/ocp-v2/ocp-v2-outcome-notifications.js +16 -0
  342. package/neural-interface/public/shared/ocp-v2/ocp-v2-panel.js +140 -254
  343. package/neural-interface/public/shared/ocp-v2/ocp-v2-plan.js +1 -2
  344. package/neural-interface/public/shared/ocp-v2/ocp-v2-projectbar.js +97 -203
  345. package/neural-interface/public/shared/ocp-v2/ocp-v2-providers.js +11 -9
  346. package/neural-interface/public/shared/ocp-v2/ocp-v2-rehydrate.js +15 -4
  347. package/neural-interface/public/shared/ocp-v2/ocp-v2-render.js +7 -22
  348. package/neural-interface/public/shared/ocp-v2/ocp-v2-send-logic.js +401 -0
  349. package/neural-interface/public/shared/ocp-v2/ocp-v2-send.js +20 -13
  350. package/neural-interface/public/shared/ocp-v2/ocp-v2-session-actions.js +8 -61
  351. package/neural-interface/public/shared/ocp-v2/ocp-v2-sessions-logic.js +53 -82
  352. package/neural-interface/public/shared/ocp-v2/ocp-v2-slash-hints.js +16 -15
  353. package/neural-interface/public/shared/ocp-v2/ocp-v2-state.js +8 -21
  354. package/neural-interface/public/shared/ocp-v2/ocp-v2-status-logic.js +1 -99
  355. package/neural-interface/public/shared/ocp-v2/ocp-v2-status.js +5 -35
  356. package/neural-interface/public/shared/ocp-v2/ocp-v2-styles.js +48 -40
  357. package/neural-interface/public/shared/ocp-v2/{ocp-v2-profile-inheritance.js → ocp-v2-tools-inheritance.js} +16 -16
  358. package/neural-interface/public/shared/ocp-v2/ocp-v2-ws.js +205 -62
  359. package/neural-interface/public/shared/opencode-providers.js +39 -0
  360. package/neural-interface/public/shared/page-session.js +96 -0
  361. package/neural-interface/public/shared/registry.js +5 -3
  362. package/neural-interface/public/shared/retired-2d.js +3 -0
  363. package/neural-interface/public/shared/schedules-view.js +452 -0
  364. package/neural-interface/public/shared/settings/settings-app-pane.js +335 -0
  365. package/neural-interface/public/shared/settings/settings-app.js +243 -0
  366. package/neural-interface/public/shared/settings/settings-claude-hooks.js +135 -0
  367. package/neural-interface/public/shared/settings/settings-data.js +90 -0
  368. package/neural-interface/public/shared/settings/settings-ia.js +23 -6
  369. package/neural-interface/public/shared/settings/settings-opencode.js +89 -0
  370. package/neural-interface/public/shared/settings/settings-skill-folders-pane.js +265 -0
  371. package/neural-interface/public/shared/settings/settings-skill-folders.js +130 -0
  372. package/neural-interface/public/shared/settings/settings-worker-guard.js +72 -0
  373. package/neural-interface/public/shared/sidepanel-session-status.js +49 -0
  374. package/neural-interface/public/shared/skills/ss-args.js +96 -0
  375. package/neural-interface/public/shared/skills/ss-creation.js +219 -0
  376. package/neural-interface/public/shared/skills/ss-dialog.js +130 -0
  377. package/neural-interface/public/shared/skills/ss-doc.js +173 -0
  378. package/neural-interface/public/shared/skills/ss-eval-adapters.js +269 -0
  379. package/neural-interface/public/shared/skills/ss-eval-grade.js +359 -0
  380. package/neural-interface/public/shared/skills/ss-eval-optimise.js +153 -0
  381. package/neural-interface/public/shared/skills/ss-eval-plan.js +315 -0
  382. package/neural-interface/public/shared/skills/ss-evals.js +417 -0
  383. package/neural-interface/public/shared/skills/ss-form.js +159 -0
  384. package/neural-interface/public/shared/skills/ss-frontmatter.js +376 -0
  385. package/neural-interface/public/shared/skills/ss-ids.js +32 -0
  386. package/neural-interface/public/shared/skills/ss-lint.js +141 -0
  387. package/neural-interface/public/shared/skills/ss-presets.js +117 -0
  388. package/neural-interface/public/shared/skills/ss-profiles.js +475 -0
  389. package/neural-interface/public/shared/skills/ss-resources.js +165 -0
  390. package/neural-interface/public/shared/skills/ss-review-view.js +190 -0
  391. package/neural-interface/public/shared/skills/ss-tabs.js +79 -0
  392. package/neural-interface/public/shared/skills/ss-unicode.js +135 -0
  393. package/neural-interface/public/shared/skills/studio/sx-actions.js +222 -0
  394. package/neural-interface/public/shared/skills/studio/sx-cm.js +101 -0
  395. package/neural-interface/public/shared/skills/studio/sx-create-ai-view.js +749 -0
  396. package/neural-interface/public/shared/skills/studio/sx-create-ai.js +236 -0
  397. package/neural-interface/public/shared/skills/studio/sx-create-view.js +254 -0
  398. package/neural-interface/public/shared/skills/studio/sx-create.js +126 -0
  399. package/neural-interface/public/shared/skills/studio/sx-diff-view.js +43 -0
  400. package/neural-interface/public/shared/skills/studio/sx-diff.js +133 -0
  401. package/neural-interface/public/shared/skills/studio/sx-docs.js +480 -0
  402. package/neural-interface/public/shared/skills/studio/sx-dom.js +229 -0
  403. package/neural-interface/public/shared/skills/studio/sx-edit-view.js +848 -0
  404. package/neural-interface/public/shared/skills/studio/sx-editor-model.js +193 -0
  405. package/neural-interface/public/shared/skills/studio/sx-errors.js +22 -0
  406. package/neural-interface/public/shared/skills/studio/sx-geometry.js +82 -0
  407. package/neural-interface/public/shared/skills/studio/sx-import.js +262 -0
  408. package/neural-interface/public/shared/skills/studio/sx-inspector.js +308 -0
  409. package/neural-interface/public/shared/skills/studio/sx-install-flow.js +279 -0
  410. package/neural-interface/public/shared/skills/studio/sx-install.js +296 -0
  411. package/neural-interface/public/shared/skills/studio/sx-library-view.js +639 -0
  412. package/neural-interface/public/shared/skills/studio/sx-library.js +475 -0
  413. package/neural-interface/public/shared/skills/studio/sx-main.js +681 -0
  414. package/neural-interface/public/shared/skills/studio/sx-operations-view.js +98 -0
  415. package/neural-interface/public/shared/skills/studio/sx-operations.js +11 -0
  416. package/neural-interface/public/shared/skills/studio/sx-plan.js +158 -0
  417. package/neural-interface/public/shared/skills/studio/sx-publish-view.js +621 -0
  418. package/neural-interface/public/shared/skills/studio/sx-review-view.js +369 -0
  419. package/neural-interface/public/shared/skills/studio/sx-review.js +148 -0
  420. package/neural-interface/public/shared/skills/studio/sx-scan.js +35 -0
  421. package/neural-interface/public/shared/skills/studio/sx-snippets.js +96 -0
  422. package/neural-interface/public/shared/skills/studio/sx-subject.js +248 -0
  423. package/neural-interface/public/shared/skills/studio/sx-test-view.js +994 -0
  424. package/neural-interface/public/shared/skills/studio/sx-test.js +328 -0
  425. package/neural-interface/public/shared/skills/studio/sx-versions-view.js +241 -0
  426. package/neural-interface/public/shared/skills/studio/sx-workspace-view.js +425 -0
  427. package/neural-interface/public/shared/styleguide/sg-panel.js +4 -2
  428. package/neural-interface/public/shared/styles.css +2065 -2150
  429. package/neural-interface/public/shared/synabun-mascot.js +1115 -9
  430. package/neural-interface/public/shared/tool-list-picker.js +55 -0
  431. package/neural-interface/public/shared/tool-list-storage.js +24 -0
  432. package/neural-interface/public/shared/tool-list-view.js +112 -0
  433. package/neural-interface/public/shared/tour/tour-actor.js +268 -0
  434. package/neural-interface/public/shared/tour/tour-beats.js +336 -0
  435. package/neural-interface/public/shared/tour/tour-engine.js +884 -0
  436. package/neural-interface/public/shared/tour/tour-ink.js +390 -0
  437. package/neural-interface/public/shared/tour/tour-stage.js +440 -0
  438. package/neural-interface/public/shared/tour/tour-state.js +40 -0
  439. package/neural-interface/public/shared/tour/tour-tips.js +99 -0
  440. package/neural-interface/public/shared/tour/tour.css +144 -0
  441. package/neural-interface/public/shared/ui-assistant.js +27 -5
  442. package/neural-interface/public/shared/ui-automation-studio.js +155 -152
  443. package/neural-interface/public/shared/ui-bookmarks.js +2 -1
  444. package/neural-interface/public/shared/ui-claude-panel.js +153 -13
  445. package/neural-interface/public/shared/ui-codex-panel.js +1 -0
  446. package/neural-interface/public/shared/ui-command-runner.js +6 -3
  447. package/neural-interface/public/shared/ui-context-menu.js +295 -0
  448. package/neural-interface/public/shared/ui-cost-widget.js +57 -59
  449. package/neural-interface/public/shared/ui-crash-notice.js +187 -0
  450. package/neural-interface/public/shared/ui-detail.js +21 -9
  451. package/neural-interface/public/shared/ui-file-links.js +1 -0
  452. package/neural-interface/public/shared/ui-image-gallery.js +56 -52
  453. package/neural-interface/public/shared/ui-invite.js +18 -2
  454. package/neural-interface/public/shared/ui-keybinds.js +26 -1
  455. package/neural-interface/public/shared/ui-link.js +9 -9
  456. package/neural-interface/public/shared/ui-menubar.js +229 -40
  457. package/neural-interface/public/shared/ui-native-loop-router-state.js +5 -0
  458. package/neural-interface/public/shared/ui-native-loop-router.js +9 -1
  459. package/neural-interface/public/shared/ui-navbar.js +4 -24
  460. package/neural-interface/public/shared/ui-opencode-panel-v2.js +1 -0
  461. package/neural-interface/public/shared/ui-panels.js +96 -65
  462. package/neural-interface/public/shared/ui-schedules-studio.js +2267 -953
  463. package/neural-interface/public/shared/ui-sessions.js +20 -7
  464. package/neural-interface/public/shared/ui-settings.js +679 -496
  465. package/neural-interface/public/shared/ui-sidebar.js +4 -4
  466. package/neural-interface/public/shared/ui-sidepanel-session-entry.js +13 -0
  467. package/neural-interface/public/shared/ui-sidepanel-sessions.js +56 -5
  468. package/neural-interface/public/shared/ui-sidepanel-state.js +23 -12
  469. package/neural-interface/public/shared/ui-sidepanel-tray.js +84 -8
  470. package/neural-interface/public/shared/ui-sidepanel-windows.js +16 -11
  471. package/neural-interface/public/shared/ui-skills.js +42 -2781
  472. package/neural-interface/public/shared/ui-styleguide.js +5 -2
  473. package/neural-interface/public/shared/ui-sync.js +22 -5
  474. package/neural-interface/public/shared/ui-terminal.js +159 -199
  475. package/neural-interface/public/shared/ui-tool-updates.js +3 -1
  476. package/neural-interface/public/shared/ui-tooltip.js +10 -5
  477. package/neural-interface/public/shared/ui-trash.js +14 -5
  478. package/neural-interface/public/shared/ui-tutorial-layout.js +3 -117
  479. package/neural-interface/public/shared/ui-tutorial-preview.js +103 -0
  480. package/neural-interface/public/shared/ui-tutorial-steps.js +3 -61
  481. package/neural-interface/public/shared/ui-tutorial.css +47 -100
  482. package/neural-interface/public/shared/ui-tutorial.js +285 -499
  483. package/neural-interface/public/shared/ui-update.js +121 -16
  484. package/neural-interface/public/shared/ui-whiteboard.js +313 -59
  485. package/neural-interface/public/shared/ui-worker-end.js +4 -0
  486. package/neural-interface/public/shared/ui-workspaces.js +3 -2
  487. package/neural-interface/public/shared/view-variant.js +66 -0
  488. package/neural-interface/public/shared/whatsapp/wa-view.js +1 -1
  489. package/neural-interface/public/shared/whiteboard-list.js +172 -0
  490. package/neural-interface/public/shared/worker-end.js +10 -3
  491. package/neural-interface/public/shared/worker-restart.js +12 -0
  492. package/neural-interface/public/sidepanel-session.html +1 -1
  493. package/neural-interface/public/variant/2d/background.js +2 -1
  494. package/neural-interface/public/variant/2d/context-menu.js +8 -2
  495. package/neural-interface/public/variant/2d/graph.js +42 -20
  496. package/neural-interface/public/variant/2d/hulls.js +14 -9
  497. package/neural-interface/public/variant/2d/lasso.js +11 -7
  498. package/neural-interface/public/variant/2d/main.js +36 -2
  499. package/neural-interface/public/variant/2d/minimap.js +11 -13
  500. package/neural-interface/public/variant/3d/main.js +72 -6
  501. package/neural-interface/public/variant/3d/map-controls.js +24 -9
  502. package/neural-interface/public/vendor/caveat/OFL.txt +93 -0
  503. package/neural-interface/public/vendor/caveat/caveat-latin-400-normal.woff2 +0 -0
  504. package/neural-interface/public/vendor/caveat/caveat-latin-700-normal.woff2 +0 -0
  505. package/neural-interface/public/vendor/caveat/caveat.css +17 -0
  506. package/neural-interface/public/vendor/caveat/manifest.json +12 -0
  507. package/neural-interface/public/vendor/highlight/LICENSE +29 -0
  508. package/neural-interface/public/vendor/highlight/github-dark-dimmed-11.12.0.min.css +9 -0
  509. package/neural-interface/public/vendor/highlight/highlight-11.12.0.min.js +1262 -0
  510. package/neural-interface/public/vendor/highlight/manifest.json +5 -0
  511. package/neural-interface/public/vendor/html2canvas/LICENSE +22 -0
  512. package/neural-interface/public/vendor/html2canvas/html2canvas-1.4.1.min.js +20 -0
  513. package/neural-interface/public/vendor/html2canvas/manifest.json +4 -0
  514. package/neural-interface/public/vendor/marked/LICENSE.md +44 -0
  515. package/neural-interface/public/vendor/marked/manifest.json +4 -0
  516. package/neural-interface/public/vendor/marked/marked-14.1.4.esm.js +2502 -0
  517. package/neural-interface/public/vendor/mermaid/LICENSE +21 -0
  518. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/abnfDiagram-PAR5IXJI.mjs +1 -0
  519. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/architecture-7GRP2DOG-M7G3SWCO.mjs +1 -0
  520. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/architectureDiagram-2PNWDENW.mjs +36 -0
  521. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/blockDiagram-PUWGUBOA.mjs +129 -0
  522. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/c4Diagram-3NLNHZP5.mjs +38 -0
  523. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-2NMSUPJH.mjs +1 -0
  524. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-32MCUW2P.mjs +206 -0
  525. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-3NPNU5GP.mjs +1 -0
  526. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-3SMGFRGC.mjs +1 -0
  527. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-4CAJECRU.mjs +14 -0
  528. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-4OADUZ5Q.mjs +10 -0
  529. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-5IMINLNL.mjs +1 -0
  530. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-5IQCK5RY.mjs +3 -0
  531. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-5MVFYWFU.mjs +1 -0
  532. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-AQ6EADP3.mjs +1 -0
  533. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-AZZRMDJM.mjs +15 -0
  534. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-CLS4B6BI.mjs +168 -0
  535. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-DZP67EKU.mjs +70 -0
  536. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-EICP7K5X.mjs +1 -0
  537. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-GDY2UAB4.mjs +1 -0
  538. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-H7VHZCWX.mjs +1 -0
  539. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-IJBDOHL6.mjs +1 -0
  540. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-JFFVMJIA.mjs +1 -0
  541. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-JQRUD6KW.mjs +1 -0
  542. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-JZGDI5JK.mjs +1 -0
  543. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-KD6SPIPN.mjs +2 -0
  544. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-NF366YI6.mjs +231 -0
  545. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-NUDPKBEF.mjs +32 -0
  546. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-OJINMHTS.mjs +1 -0
  547. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-Q6NGPIAH.mjs +2 -0
  548. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-QJSWEUOL.mjs +132 -0
  549. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-R7JDMUKV.mjs +1 -0
  550. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-RCXAM2GK.mjs +1 -0
  551. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-RT4MAWR3.mjs +1 -0
  552. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-SFMINX4W.mjs +1 -0
  553. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-SLDQ463B.mjs +88 -0
  554. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-STOV2HOB.mjs +1 -0
  555. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-T5OCTHI4.mjs +1 -0
  556. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-TCEHX7R3.mjs +1 -0
  557. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-VQC2EELJ.mjs +1 -0
  558. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-VRZKL3EH.mjs +1 -0
  559. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-VTHDQ7BV.mjs +1 -0
  560. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-VY2OSTJR.mjs +2 -0
  561. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-WUBWJARI.mjs +1 -0
  562. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-YBMQ5JGJ.mjs +2 -0
  563. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-YDMLL4PJ.mjs +1 -0
  564. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-Z6V44ARX.mjs +62 -0
  565. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-ZJJ7VQJP.mjs +339 -0
  566. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-ZNLK7HRR.mjs +1 -0
  567. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-ZQN7UHIL.mjs +1 -0
  568. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-ZS6VBONO.mjs +174 -0
  569. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/chunk-ZUNWM646.mjs +1 -0
  570. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/classDiagram-FGAMPOII.mjs +1 -0
  571. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/classDiagram-v2-AI5RJEK4.mjs +1 -0
  572. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/cose-bilkent-Q72C2OJ3.mjs +1 -0
  573. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/cynefin-OW5HDTMX-6OCTWOGG.mjs +1 -0
  574. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/cynefinDiagram-2OOWUY4M.mjs +62 -0
  575. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/dagre-MPVFI544.mjs +4 -0
  576. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/diagram-AE4NWXFW.mjs +24 -0
  577. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/diagram-BUJID5UG.mjs +41 -0
  578. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/diagram-C44CZ5NI.mjs +24 -0
  579. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/diagram-EYOLEXXS.mjs +30 -0
  580. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/diagram-P7B6PWOJ.mjs +3 -0
  581. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/ebnfDiagram-FTPZ3PV6.mjs +1 -0
  582. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/erDiagram-H3ERR26V.mjs +99 -0
  583. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/eventmodeling-NTZA5JFV-WKSWQHFS.mjs +1 -0
  584. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/flowDiagram-YHGXBVSY.mjs +1 -0
  585. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/ganttDiagram-RWFTB7ED.mjs +292 -0
  586. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/gitGraph-4MIJSDKK-JH2HKYUO.mjs +1 -0
  587. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/gitGraphDiagram-MAR6GKOP.mjs +106 -0
  588. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/info-A6RAGUB7-3TX3OFWW.mjs +1 -0
  589. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/infoDiagram-LV547AFH.mjs +2 -0
  590. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/ishikawaDiagram-PUJQGNDS.mjs +70 -0
  591. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/journeyDiagram-EW5QJT4W.mjs +139 -0
  592. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/kanban-definition-JSQERAZB.mjs +89 -0
  593. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/katex-CZ4GXH2S.mjs +257 -0
  594. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/mindmap-definition-VBJCLQLM.mjs +96 -0
  595. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/packet-AYTQ26CC-MKII6P3Y.mjs +1 -0
  596. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/pegDiagram-7WILOQTJ.mjs +1 -0
  597. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/pie-WAS4IAKB-6B4OPMJ5.mjs +1 -0
  598. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/pieDiagram-EFA7CBSB.mjs +39 -0
  599. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/quadrantDiagram-WARVYA7P.mjs +7 -0
  600. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/radar-RG4KPBEZ-UPTR3XUL.mjs +1 -0
  601. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/railroad-74A4TZTK-MEFUPFMS.mjs +1 -0
  602. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/railroad-abnf-HS5TGJTU-R5YG2S5D.mjs +1 -0
  603. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/railroad-ebnf-LZEXJU2U-G5QEX2L6.mjs +1 -0
  604. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/railroad-peg-WCYAUIDC-H5I2ZRY2.mjs +1 -0
  605. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/railroadDiagram-5NIQVNLQ.mjs +1 -0
  606. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/requirementDiagram-SXREGOKZ.mjs +84 -0
  607. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/sankeyDiagram-VV74M2VP.mjs +40 -0
  608. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/sequenceDiagram-52ZFIFDL.mjs +162 -0
  609. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/sizeCapture-FGA5AGYP.mjs +1 -0
  610. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/stateDiagram-3QAKPIVI.mjs +1 -0
  611. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/stateDiagram-v2-HN2P4RDZ.mjs +1 -0
  612. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/swimlanes-QLVP42QD.mjs +1 -0
  613. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/swimlanesDiagram-JKPDBFCN.mjs +8 -0
  614. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/timeline-definition-GS45XAXW.mjs +120 -0
  615. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/treeView-Q6P3EWNA-ZRJGANNQ.mjs +1 -0
  616. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/treemap-WGGIJYW6-K64VN5AS.mjs +1 -0
  617. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/vennDiagram-QIQU2ZRJ.mjs +34 -0
  618. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/wardley-WFR3VGLG-D67OWCCH.mjs +1 -0
  619. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/wardleyDiagram-U6YNM66N.mjs +78 -0
  620. package/neural-interface/public/vendor/mermaid/chunks/mermaid.esm.min/xychartDiagram-XJAZEDNM.mjs +7 -0
  621. package/neural-interface/public/vendor/mermaid/manifest.json +4 -0
  622. package/neural-interface/public/vendor/mermaid/mermaid-11.17.2.esm.min.mjs +14 -0
  623. package/neural-interface/public/vendor/yaml/LICENSE +13 -0
  624. package/neural-interface/public/vendor/yaml/manifest.json +4 -0
  625. package/neural-interface/public/vendor/yaml/yaml-2.9.1.min.js +137 -0
  626. package/neural-interface/scripts/build-vendor.mjs +116 -3
  627. package/neural-interface/server.js +4834 -2541
  628. package/neural-interface/templates/rulesets/core.md +1 -1
  629. package/neural-interface/templates/rulesets/legacy-hashes.json +18 -0
  630. package/neural-interface/templates/rulesets/manifest.json +8 -8
  631. package/npm-shrinkwrap.json +18 -12
  632. package/package.json +16 -3
  633. package/postinstall.js +9 -4
  634. package/preuninstall.js +1 -1
  635. package/setup.js +97 -322
  636. package/skills/skill-forge/SKILL.md +177 -0
  637. package/skills/skill-forge/evals/evals.json +54 -0
  638. package/skills/skill-forge/references/package.md +105 -0
  639. package/skills/skill-forge/references/review-and-recovery.md +63 -0
  640. package/skills/skill-forge/references/runtime-profiles.md +20 -0
  641. package/skills/skill-forge/references/sources-and-capabilities.md +51 -0
  642. package/skills/synabun/SKILL.md +10 -7
  643. package/skills/synabun/modules/audit.md +1 -5
  644. package/skills/synabun/modules/changelog.md +1 -5
  645. package/skills/synabun/modules/idea.md +1 -1
  646. package/skills/synabun/modules/memorize.md +6 -9
  647. package/skills/synabun/modules/schedule.md +5 -5
  648. package/mcp-server/dist/services/profiles.d.ts +0 -120
  649. package/mcp-server/dist/services/profiles.d.ts.map +0 -1
  650. package/mcp-server/dist/services/profiles.js +0 -387
  651. package/mcp-server/dist/services/profiles.js.map +0 -1
  652. package/mcp-server/dist/tools/leonardo-browser-tools.d.ts +0 -97
  653. package/mcp-server/dist/tools/leonardo-browser-tools.d.ts.map +0 -1
  654. package/mcp-server/dist/tools/leonardo-browser-tools.js +0 -228
  655. package/mcp-server/dist/tools/leonardo-browser-tools.js.map +0 -1
  656. package/mcp-server/dist/tools/leonardo.d.ts +0 -13
  657. package/mcp-server/dist/tools/leonardo.d.ts.map +0 -1
  658. package/mcp-server/dist/tools/leonardo.js +0 -21
  659. package/mcp-server/dist/tools/leonardo.js.map +0 -1
  660. package/mcp-server/dist/tools/profile.d.ts +0 -17
  661. package/mcp-server/dist/tools/profile.d.ts.map +0 -1
  662. package/mcp-server/dist/tools/profile.js +0 -114
  663. package/mcp-server/dist/tools/profile.js.map +0 -1
  664. package/mcp-server/src/services/profiles.ts +0 -428
  665. package/mcp-server/src/tools/leonardo-browser-tools.ts +0 -291
  666. package/mcp-server/src/tools/leonardo.ts +0 -30
  667. package/mcp-server/src/tools/profile.ts +0 -122
  668. package/neural-interface/lib/assistant-brains/opencode-browser-policy.js +0 -47
  669. package/neural-interface/lib/assistant-brains/opencode-route-gate.js +0 -62
  670. package/neural-interface/lib/mcp-profile-servers.js +0 -120
  671. package/neural-interface/public/shared/ui-tutorial-draw.js +0 -311
  672. package/skills/leonardo/SKILL.md +0 -168
  673. package/skills/leonardo/icon.svg +0 -1
  674. package/skills/leonardo/modules/browser-guide.md +0 -378
  675. package/skills/leonardo/modules/image-prompter.md +0 -283
  676. package/skills/leonardo/modules/model-advisor.md +0 -100
  677. package/skills/leonardo/modules/prompt-library.md +0 -110
  678. package/skills/leonardo/modules/style-guide.md +0 -186
  679. package/skills/leonardo/modules/video-prompter.md +0 -317
@@ -24,6 +24,7 @@ export const DESKTOP_COPY = Object.freeze({
24
24
  tooltip: 'SynaBun update available: v{current} → v{latest}',
25
25
  tooltipDownloading: 'Downloading SynaBun v{latest}',
26
26
  tooltipReady: 'SynaBun v{latest} is ready: it installs when SynaBun is idle',
27
+ tooltipReadyOff: 'SynaBun v{latest} is ready to install',
27
28
  titleAvailable: 'Update available',
28
29
  titleDownloading: 'Downloading the update',
29
30
  titleDownloaded: 'Update ready',
@@ -46,6 +47,9 @@ export const DESKTOP_COPY = Object.freeze({
46
47
  hide: 'Hide',
47
48
  hideHint: 'The download continues while this is hidden. SynaBun installs the update by itself when nothing is running.',
48
49
  readyBody: 'SynaBun v{version} is downloaded. It installs by itself once nothing is running: SynaBun shows a one-minute notice, then restarts into it. It also installs when you quit SynaBun.',
50
+ // Automatic updates off (Settings > App): it waits for Install now.
51
+ offBody: 'Automatic updates are off. Install now downloads it and restarts SynaBun into it once nothing is running.',
52
+ readyBodyOff: 'SynaBun v{version} is downloaded. Automatic updates are off: it installs when you choose Install now.',
49
53
  waitingBody: 'Waiting for: {list}.',
50
54
  countdownBody: 'SynaBun restarts into v{version} in {seconds} s.',
51
55
  postponedBody: 'Postponed until {time}. It also installs when you quit SynaBun.',
@@ -62,14 +66,20 @@ export const DESKTOP_COPY = Object.freeze({
62
66
  errorFallback: 'SynaBun could not check for updates. Check the connection and try again.',
63
67
  errorNext: 'SynaBun keeps the version it runs and tries again at its next check. You can try now, or download the new version yourself.',
64
68
  manualLink: 'Download it yourself',
69
+ settingsLink: 'Update settings',
65
70
  close: 'Close',
66
71
  retry: 'Try again',
67
72
  testFeed: 'test feed',
68
73
  metaAvailable: 'From the SynaBun app',
69
74
  metaDownloading: 'Downloading: {percent}%',
70
75
  metaDownloaded: 'Ready: installs when SynaBun is idle',
76
+ metaReadyOff: 'Ready to install',
71
77
  metaCountdown: 'Restarting to install it',
72
78
  metaPostponed: 'Postponed: installs on quit or later',
79
+ // The button at the top right while a downloaded update waits for a restart, as Discord's green one.
80
+ restartButton: 'Restart to update',
81
+ restartTooltip: 'SynaBun v{latest} is ready: restart to update',
82
+ restartSoon: 'Restarting soon',
73
83
  }),
74
84
  // What an update waits for (the app's server names it, GET /api/system/activity).
75
85
  busy: Object.freeze({
@@ -193,6 +203,8 @@ export function readDesktopUpdateState(state) {
193
203
  manualFile: text(s.manualFile, 4096),
194
204
  testFeed: s.testFeed === true,
195
205
  auto: readAuto(s.auto),
206
+ // Settings > App; an app from before the setting says nothing: on.
207
+ autoUpdate: s.autoUpdate !== false,
196
208
  updated: readUpdated(s.updated),
197
209
  releasesUrl: readReleasesUrl(s.releasesUrl),
198
210
  };
@@ -236,6 +248,7 @@ export function versionDataFromDesktop(state) {
236
248
  testFeed: s.testFeed,
237
249
  checkedAt: s.checkedAt,
238
250
  auto: s.auto,
251
+ autoUpdate: s.autoUpdate,
239
252
  };
240
253
  }
241
254
 
@@ -311,11 +324,12 @@ export function desktopUpdateView(state, {
311
324
  case 'available':
312
325
  view.dot = 1;
313
326
  view.title = say('titleAvailable');
314
- view.body = [say('snapshot', { version })];
327
+ view.body = s.autoUpdate ? [say('snapshot', { version })] : [say('offBody'), say('snapshot', { version })];
315
328
  view.notesLabel = say('notesLabel');
316
329
  view.notes = s.notes || say('notesEmpty');
317
330
  view.backup = { id: 'backup', label: say('backup') };
318
- view.actions = [action('later', 'ghost', 'later'), action('download', 'primary', 'download')];
331
+ // Automatic updates off: one click downloads and installs it (no download on its own to wait for).
332
+ view.actions = [action('later', 'ghost', 'later'), s.autoUpdate ? action('download', 'primary', 'download') : action('install-now', 'primary', 'installNow')];
319
333
  break;
320
334
  case 'downloading':
321
335
  view.dot = 2;
@@ -328,8 +342,8 @@ export function desktopUpdateView(state, {
328
342
  case 'downloaded': {
329
343
  view.dot = 3;
330
344
  view.title = say('titleDownloaded');
331
- view.body = [say('readyBody', { version })];
332
345
  const auto = s.auto;
346
+ view.body = [s.autoUpdate || auto?.now ? say('readyBody', { version }) : say('readyBodyOff', { version })];
333
347
  if (auto?.phase === 'countdown' && auto.installAt) {
334
348
  view.body.push(say('countdownBody', { version, seconds: secondsUntil(auto.installAt, now) }));
335
349
  view.ticking = true;
@@ -395,7 +409,7 @@ export function desktopUpdateMeta(state, { t = fillDesktopCopy } = {}) {
395
409
  case 'downloaded':
396
410
  if (s.auto?.phase === 'countdown') return t('update.metaCountdown');
397
411
  if (s.auto?.phase === 'postponed') return t('update.metaPostponed');
398
- return t('update.metaDownloaded');
412
+ return s.autoUpdate || s.auto?.now ? t('update.metaDownloaded') : t('update.metaReadyOff');
399
413
  case 'installing': return t('update.titleInstalling');
400
414
  case 'available': case 'move': case 'manual': return t('update.metaAvailable');
401
415
  default: return '';
@@ -408,10 +422,26 @@ export function desktopUpdateTooltip(state, { t = fillDesktopCopy } = {}) {
408
422
  const params = { current: s.current, latest: s.latest || '' };
409
423
  const step = desktopUpdateStep(s);
410
424
  if (step === 'downloading') return t('update.tooltipDownloading', params);
411
- if (step === 'downloaded') return t('update.tooltipReady', params);
425
+ if (step === 'downloaded') return t(s.autoUpdate || s.auto?.now ? 'update.tooltipReady' : 'update.tooltipReadyOff', params);
412
426
  return t('update.tooltip', params);
413
427
  }
414
428
 
429
+ /**
430
+ * The top right button while a downloaded update waits for a restart into it, or null: { label, tooltip, asked }.
431
+ * Only an update this copy installs by restarting (not one to move to Applications or to install by hand). After
432
+ * Restart to update, while something still runs, it says that the restart is coming (`asked`).
433
+ */
434
+ export function desktopRestartButton(state, { t = fillDesktopCopy } = {}) {
435
+ const s = readDesktopUpdateState(state);
436
+ if (desktopUpdateStep(s) !== 'downloaded' || s.install !== 'restart' || s.manualFile) return null;
437
+ const asked = s.auto?.now === true;
438
+ return {
439
+ label: t(asked ? 'update.restartSoon' : 'update.restartButton'),
440
+ tooltip: t('update.restartTooltip', { latest: s.latest || '', current: s.current }),
441
+ asked,
442
+ };
443
+ }
444
+
415
445
  /**
416
446
  * The notice at the bottom right, or null:
417
447
  * countdown SynaBun is idle and restarts into the update: the seconds left, and Later
@@ -80,9 +80,9 @@ export function matchesExpectedMarkdown(content, expected) {
80
80
  return String(content).replace(/\r\n/g, '\n') === expected.replace(/\r\n/g, '\n');
81
81
  }
82
82
 
83
- /** Whether a path is the user's OpenCode configuration file. */
83
+ /** Whether a path is the user's OpenCode configuration file (OpenCode 2's opencode.json or opencode.jsonc). */
84
84
  export function isOpencodeConfigPath(path) {
85
- return String(path || '').replace(/\\/g, '/').endsWith('/.config/opencode/config.json');
85
+ return /\/\.config\/opencode\/opencode\.jsonc?$/.test(String(path || '').replace(/\\/g, '/'));
86
86
  }
87
87
 
88
88
  const OUTSIDE_ROOTS = 'Path outside registered project roots';
@@ -36,20 +36,54 @@ const SCHEME_RE = /^([a-z][a-z0-9+.-]*):/i;
36
36
  const PLACE_ONLY_RE = /^\d+(?::\d+)?(?:#.*)?$/;
37
37
  const LINE_SUFFIX_RE = /:(\d+)(?::(\d+))?$/;
38
38
  const LINE_HASH_RE = /^#L(\d+)(?:C(\d+))?(?:-L?\d+(?:C\d+)?)?$/i;
39
+ // Schemes a browser runs or draws content from: never a file's name, not even before a line number.
40
+ const ACTIVE_SCHEMES = new Set(['javascript', 'vbscript', 'livescript', 'data', 'blob', 'filesystem', 'about', 'view-source']);
41
+ // What a scheme can hide behind: a browser drops tabs and line breaks anywhere in a URL and controls at its
42
+ // ends; format characters show nothing; an entity can be left over from a second escape.
43
+ const HIDDEN_RE = /[\u0000-\u001f\u007f-\u009f\u00ad\u200b-\u200f\u2028\u2029\u2060-\u2064\ufeff]/g;
44
+ const ENTITY_RE = /&(?:#(\d+)|#x([0-9a-f]+)|([a-z]+));?/gi;
45
+ const NAMED_ENTITIES = { colon: ':', tab: '\t', newline: '\n', nbsp: ' ', sol: '/', bsol: '\\', num: '#', quest: '?', period: '.', amp: '&', semi: ';', lpar: '(', rpar: ')' };
39
46
 
40
47
  const slashes = (path) => String(path ?? '').replace(/\\/g, '/');
41
48
 
49
+ function decodeEntities(text) {
50
+ let out = text;
51
+ for (let round = 0; round < 4; round += 1) { // `&amp;#106;` is `&#106;` once more
52
+ const next = out.replace(ENTITY_RE, (whole, dec, hex, name) => {
53
+ if (name) return NAMED_ENTITIES[name.toLowerCase()] ?? whole;
54
+ const code = dec ? Number(dec) : parseInt(hex, 16);
55
+ return code > 0 && code <= 0x10ffff ? String.fromCodePoint(code) : '';
56
+ });
57
+ if (next === out) break;
58
+ out = next;
59
+ }
60
+ return out;
61
+ }
62
+
63
+ /** A target as its scheme is read: entities decoded, hidden characters dropped, no spaces at the ends, lower case. */
64
+ function schemeView(value) {
65
+ return decodeEntities(value).replace(HIDDEN_RE, '').trim().toLowerCase();
66
+ }
67
+
68
+ // An active scheme, read with its spaces squeezed out too: `java script:` is no URL to a browser, and no file either.
69
+ const isActive = (seen) => ACTIVE_SCHEMES.has(SCHEME_RE.exec(seen.replace(/\s+/g, ''))?.[1]);
70
+
42
71
  /** How a target reads: a `path`, a `file` URL, a `web` address (http, https), or null for anything else. */
43
72
  function kindOf(value) {
44
73
  if (!value || value.length > MAX_TARGET_LENGTH) return null;
45
- if (value.startsWith('#') || value.startsWith('?') || value.startsWith('//')) return null;
74
+ const seen = schemeView(value);
75
+ if (!seen || seen.startsWith('#') || seen.startsWith('?') || seen.startsWith('//') || isActive(seen)) return null;
46
76
  if (DRIVE_RE.test(value)) return 'path';
47
- const scheme = SCHEME_RE.exec(value);
77
+ const scheme = SCHEME_RE.exec(seen);
48
78
  if (!scheme) return 'path';
49
- const name = scheme[1].toLowerCase();
79
+ // A scheme put together from hidden characters or entities (`JaVa\tScript:`, `&#106;avascript:`) is no
80
+ // file's and no address of this app.
81
+ const written = SCHEME_RE.exec(value);
82
+ if (!written || written[1].toLowerCase() !== scheme[1]) return null;
83
+ const name = scheme[1];
50
84
  if (name === 'file') return 'file';
51
85
  if (name === 'http' || name === 'https') return 'web';
52
- const rest = value.slice(scheme[0].length);
86
+ const rest = value.slice(written[0].length);
53
87
  if (rest.startsWith('//')) return null;
54
88
  return PLACE_ONLY_RE.test(rest) ? 'path' : null;
55
89
  }
@@ -231,6 +265,33 @@ export function fillFileLinkCopy(key, params = {}) {
231
265
 
232
266
  // ── The click ──
233
267
 
268
+ /**
269
+ * Whether a link would run a script or draw data when the browser follows it: its `href` (or an SVG link's
270
+ * `xlink:href`) read the way kindOf reads a target (entities decoded, controls and invisible characters dropped,
271
+ * lower case), and the scheme the browser itself resolved. Nothing else an anchor carries is asked.
272
+ * @param {Element} anchor
273
+ */
274
+ export function isActiveLink(anchor) {
275
+ for (const name of ['href', 'xlink:href']) {
276
+ const value = anchor.getAttribute?.(name);
277
+ if (value != null && isActive(schemeView(String(value)))) return true;
278
+ }
279
+ const resolved = typeof anchor.protocol === 'string' ? anchor.protocol.replace(/:$/, '').toLowerCase() : '';
280
+ return ACTIVE_SCHEMES.has(resolved);
281
+ }
282
+
283
+ // A kept target is the sanitiser's note of the href as written (safeHref resolved it against the page, or dropped
284
+ // it). It counts only while it is a file's and the href says the same thing; anything else is the href's to say.
285
+ function keptTarget(anchor, href) {
286
+ const kept = anchor.getAttribute('data-file-target');
287
+ if (!kept || localFileHref(kept) == null) return null;
288
+ if (href == null) return kept; // file:, C:\…, name.ext:12: the sanitiser writes no href for them
289
+ try {
290
+ const base = anchor.baseURI || `${new URL(href).origin}/`;
291
+ return new URL(kept.trim(), base).href === new URL(href, base).href ? kept : null;
292
+ } catch { return null; }
293
+ }
294
+
234
295
  /**
235
296
  * What a link points at, as the agent wrote it.
236
297
  * @param {Element} anchor
@@ -239,9 +300,9 @@ export function fillFileLinkCopy(key, params = {}) {
239
300
  * @returns {{ raw: string, text: boolean } | null}
240
301
  */
241
302
  export function readFileLink(anchor, { textLinks = '' } = {}) {
242
- const kept = anchor.getAttribute('data-file-target');
243
- if (kept) return { raw: kept, text: false };
244
303
  const href = anchor.getAttribute('href');
304
+ const kept = keptTarget(anchor, href);
305
+ if (kept) return { raw: kept, text: false };
245
306
  if (textLinks && anchor.matches(textLinks) && (!href || href === '#')) return { raw: anchor.textContent || '', text: true };
246
307
  return href ? { raw: href, text: false } : null;
247
308
  }
@@ -255,7 +316,8 @@ export function readFileLink(anchor, { textLinks = '' } = {}) {
255
316
  * @param {() => string} page.origin the page's origin
256
317
  * @param {(key: string, params?: object) => string} page.say a `fileLinks.*` sentence
257
318
  * @param {(message: string) => void} page.notify shows a short message
258
- * @param {(anchor: Element) => void} page.follow goes where a link of this app leads, as the browser would
319
+ * @param {(anchor: Element) => void} page.follow goes where a link of this app leads, as the browser would (only
320
+ * ever for an http(s) address of this app that is the anchor's own href: never a script link)
259
321
  */
260
322
  export function createFileLinkHandlers(page) {
261
323
  const whereOf = (anchor, options) => {
@@ -302,12 +364,15 @@ export function createFileLinkHandlers(page) {
302
364
  * @param {(message: string) => void} [options.notify] shows the reason a link was not opened
303
365
  * @returns {Promise<string> | null} null when the click is not this handler's (the browser follows the
304
366
  * link as before); else the click is taken and the promise says how it ended: 'opened', 'copied',
305
- * 'followed', or the reason the user was told
367
+ * 'followed', 'blocked' (a script or data link), or the reason the user was told
306
368
  */
307
369
  function handleClick(event, options = {}) {
308
370
  if (event.defaultPrevented || event.button > 0) return null;
309
371
  const anchor = event.target?.closest?.('a');
310
372
  if (!anchor || (options.within && !options.within.contains(anchor))) return null;
373
+ // A script or data link in an agent's message goes nowhere, however it is spelled and whatever else the anchor
374
+ // says (a kept target, a download): the Codex panel's Markdown is not sanitised, so its href can still be one.
375
+ if (isActiveLink(anchor)) { event.preventDefault(); return Promise.resolve('blocked'); }
311
376
  if (anchor.hasAttribute?.('download')) return null; // a file the app itself offers
312
377
  const link = readFileLink(anchor, options);
313
378
  if (!link) return null;
@@ -5,6 +5,7 @@
5
5
 
6
6
  import { getVariant } from './registry.js';
7
7
  import { t } from './i18n.js';
8
+ import { FRAMED_CLASS } from './app-frame.js';
8
9
 
9
10
  /**
10
11
  * The File Explorer's editor panel (slides from the file explorer's right edge).
@@ -86,6 +87,10 @@ export function getSharedHTML() {
86
87
  const is3D = variant === '3d';
87
88
 
88
89
  return `
90
+ <!-- App frame (styles.css APP FRAME): the card's interior under the graph, its border and gutter over the windows -->
91
+ <div id="app-frame-surface" aria-hidden="true"></div>
92
+ <div id="app-frame" aria-hidden="true"></div>
93
+
89
94
  <!-- Loading Overlay -->
90
95
  <div id="loading-overlay">
91
96
  <div id="loading-mascot" data-state="asleep">
@@ -148,12 +153,6 @@ export function getSharedHTML() {
148
153
  <div class="bar-left">
149
154
  <img src="synabun.png?v=2" alt="SynaBun" id="titlebar-logo" style="height:24px;width:auto;cursor:pointer;" data-tooltip="${t('tooltip.toggleExplorer')}">
150
155
  <div class="bar-sep"></div>
151
- <div class="view-toggle">
152
- <a class="view-toggle-btn${is3D ? '' : ' active'}" href="${is3D ? '/index2d.html' : '#'}" id="nav-2d-link">${t('nav.toggle2d')}</a>
153
- <a class="view-toggle-btn${is3D ? ' active' : ''}" href="${is3D ? '#' : '/'}" id="nav-3d-link">${t('nav.toggle3d')}</a>
154
- <span class="view-toggle-sep"></span>
155
- </div>
156
- <div class="bar-sep"></div>
157
156
 
158
157
  <!-- OS-style menubar -->
159
158
  <div class="menubar">
@@ -203,26 +202,30 @@ export function getSharedHTML() {
203
202
  <span class="menu-text"><span class="menu-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="12" cy="12" r="10"/><ellipse cx="12" cy="12" rx="4" ry="10"/><line x1="2" y1="12" x2="22" y2="12"/><path d="M4.5 7h15M4.5 17h15" stroke-width="1"/></svg></span> ${t('menu.apps.browser')}</span>
204
203
  <span class="menu-shortcut" data-keybind-for="launch-browser"></span>
205
204
  </div>
206
- <div class="menu-item" id="menu-terminal-youtube">
207
- <span class="menu-check"></span>
208
- <span class="menu-text"><span class="menu-icon"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z"/></svg></span> ${t('menu.apps.youtube')}</span>
209
- <span class="menu-shortcut" data-keybind-for="launch-youtube"></span>
210
- </div>
211
- <div class="menu-item" id="menu-terminal-discord">
212
- <span class="menu-check"></span>
213
- <span class="menu-text"><span class="menu-icon"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028c.462-.63.874-1.295 1.226-1.994a.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.956-2.419 2.157-2.419 1.21 0 2.176 1.095 2.157 2.42 0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.955-2.419 2.157-2.419 1.21 0 2.176 1.095 2.157 2.42 0 1.333-.946 2.418-2.157 2.418z"/></svg></span> Discord</span>
214
- </div>
215
- <div class="menu-item" id="menu-terminal-x">
216
- <span class="menu-check"></span>
217
- <span class="menu-text"><span class="menu-icon"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg></span> X</span>
218
- </div>
219
- <div class="menu-item" id="menu-terminal-whatsapp">
220
- <span class="menu-check"></span>
221
- <span class="menu-text"><span class="menu-icon"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413z"/></svg></span> WhatsApp</span>
222
- </div>
223
- <div class="menu-item" id="menu-app-leonardo" hidden>
224
- <span class="menu-check"></span>
225
- <span class="menu-text"><span class="menu-icon"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M9.5 2l1.5 3.5L14.5 7l-3.5 1.5L9.5 12l-1.5-3.5L4.5 7l3.5-1.5L9.5 2zM19 10l1 2 2 1-2 1-1 2-1-2-2-1 2-1 1-2zM5 17l1 2 2 1-2 1-1 2-1-2-2-1 2-1 1-2z"/></svg></span> Leonardo.AI</span>
205
+ <!-- Browser apps: a submenu (ui-menubar.js wireSubmenus) -->
206
+ <div class="menu-item menu-submenu-parent" id="menu-browser-apps" data-submenu="browser-apps" aria-haspopup="menu" aria-expanded="false">
207
+ <span class="menu-check"></span>
208
+ <span class="menu-text"><span class="menu-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="3" y="3" width="7" height="7" rx="1"/><rect x="14" y="3" width="7" height="7" rx="1"/><rect x="3" y="14" width="7" height="7" rx="1"/><rect x="14" y="14" width="7" height="7" rx="1"/></svg></span> ${t('menu.apps.browserApps')}</span>
209
+ <span class="menu-submenu-arrow" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"/></svg></span>
210
+ </div>
211
+ <div class="menubar-submenu" data-submenu-for="browser-apps" role="menu">
212
+ <div class="menu-item" id="menu-terminal-youtube">
213
+ <span class="menu-check"></span>
214
+ <span class="menu-text"><span class="menu-icon"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M23.498 6.186a3.016 3.016 0 0 0-2.122-2.136C19.505 3.545 12 3.545 12 3.545s-7.505 0-9.377.505A3.017 3.017 0 0 0 .502 6.186C0 8.07 0 12 0 12s0 3.93.502 5.814a3.016 3.016 0 0 0 2.122 2.136c1.871.505 9.376.505 9.376.505s7.505 0 9.377-.505a3.015 3.015 0 0 0 2.122-2.136C24 15.93 24 12 24 12s0-3.93-.502-5.814zM9.545 15.568V8.432L15.818 12l-6.273 3.568z"/></svg></span> ${t('menu.apps.youtube')}</span>
215
+ <span class="menu-shortcut" data-keybind-for="launch-youtube"></span>
216
+ </div>
217
+ <div class="menu-item" id="menu-terminal-discord">
218
+ <span class="menu-check"></span>
219
+ <span class="menu-text"><span class="menu-icon"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M20.317 4.37a19.791 19.791 0 0 0-4.885-1.515.074.074 0 0 0-.079.037c-.21.375-.444.864-.608 1.25a18.27 18.27 0 0 0-5.487 0 12.64 12.64 0 0 0-.617-1.25.077.077 0 0 0-.079-.037A19.736 19.736 0 0 0 3.677 4.37a.07.07 0 0 0-.032.027C.533 9.046-.32 13.58.099 18.057a.082.082 0 0 0 .031.057 19.9 19.9 0 0 0 5.993 3.03.078.078 0 0 0 .084-.028c.462-.63.874-1.295 1.226-1.994a.076.076 0 0 0-.041-.106 13.107 13.107 0 0 1-1.872-.892.077.077 0 0 1-.008-.128 10.2 10.2 0 0 0 .372-.292.074.074 0 0 1 .077-.01c3.928 1.793 8.18 1.793 12.062 0a.074.074 0 0 1 .078.01c.12.098.246.198.373.292a.077.077 0 0 1-.006.127 12.299 12.299 0 0 1-1.873.892.077.077 0 0 0-.041.107c.36.698.772 1.362 1.225 1.993a.076.076 0 0 0 .084.028 19.839 19.839 0 0 0 6.002-3.03.077.077 0 0 0 .032-.054c.5-5.177-.838-9.674-3.549-13.66a.061.061 0 0 0-.031-.03zM8.02 15.33c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.956-2.419 2.157-2.419 1.21 0 2.176 1.095 2.157 2.42 0 1.333-.956 2.418-2.157 2.418zm7.975 0c-1.183 0-2.157-1.085-2.157-2.419 0-1.333.955-2.419 2.157-2.419 1.21 0 2.176 1.095 2.157 2.42 0 1.333-.946 2.418-2.157 2.418z"/></svg></span> Discord</span>
220
+ </div>
221
+ <div class="menu-item" id="menu-terminal-x">
222
+ <span class="menu-check"></span>
223
+ <span class="menu-text"><span class="menu-icon"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M18.244 2.25h3.308l-7.227 8.26 8.502 11.24H16.17l-5.214-6.817L4.99 21.75H1.68l7.73-8.835L1.254 2.25H8.08l4.713 6.231zm-1.161 17.52h1.833L7.084 4.126H5.117z"/></svg></span> X</span>
224
+ </div>
225
+ <div class="menu-item" id="menu-terminal-whatsapp">
226
+ <span class="menu-check"></span>
227
+ <span class="menu-text"><span class="menu-icon"><svg viewBox="0 0 24 24" fill="currentColor"><path d="M17.472 14.382c-.297-.149-1.758-.867-2.03-.967-.273-.099-.471-.148-.67.15-.197.297-.767.966-.94 1.164-.173.199-.347.223-.644.075-.297-.15-1.255-.463-2.39-1.475-.883-.788-1.48-1.761-1.653-2.059-.173-.297-.018-.458.13-.606.134-.133.298-.347.446-.52.149-.174.198-.298.298-.497.099-.198.05-.371-.025-.52-.075-.149-.669-1.612-.916-2.207-.242-.579-.487-.5-.669-.51-.173-.008-.371-.01-.57-.01-.198 0-.52.074-.792.372-.272.297-1.04 1.016-1.04 2.479 0 1.462 1.065 2.875 1.213 3.074.149.198 2.096 3.2 5.077 4.487.709.306 1.262.489 1.694.625.712.227 1.36.195 1.871.118.571-.085 1.758-.719 2.006-1.413.248-.694.248-1.289.173-1.413-.074-.124-.272-.198-.57-.347m-5.421 7.403h-.004a9.87 9.87 0 01-5.031-1.378l-.361-.214-3.741.982.998-3.648-.235-.374a9.86 9.86 0 01-1.51-5.26c.001-5.45 4.436-9.884 9.888-9.884 2.64 0 5.122 1.03 6.988 2.898a9.825 9.825 0 012.893 6.994c-.003 5.45-4.437 9.884-9.885 9.884m8.413-18.297A11.815 11.815 0 0012.05 0C5.495 0 .16 5.335.157 11.892c0 2.096.547 4.142 1.588 5.945L.057 24l6.305-1.654a11.882 11.882 0 005.683 1.448h.005c6.554 0 11.89-5.335 11.893-11.893a11.821 11.821 0 00-3.48-8.413z"/></svg></span> WhatsApp</span>
228
+ </div>
226
229
  </div>
227
230
  <div class="menu-sep"></div>
228
231
  <div class="menu-item" id="menu-command-runner">
@@ -239,6 +242,48 @@ export function getSharedHTML() {
239
242
  <span class="menu-shortcut">T</span>
240
243
  </div>
241
244
  <div class="menu-sep"></div>
245
+ ${is3D ? ` <!-- Map (3D memory map) -->
246
+ <div class="menu-item menu-submenu-parent" id="menu-map-label" data-menu="graph" data-submenu="map" aria-haspopup="menu" aria-expanded="false">
247
+ <span class="menu-check"></span>
248
+ <span class="menu-text"><span class="menu-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="1 6 1 22 8 18 16 22 23 18 23 2 16 6 8 2 1 6"/><line x1="8" y1="2" x2="8" y2="18"/><line x1="16" y1="6" x2="16" y2="22"/></svg></span> ${t('nav.map')}</span>
249
+ <span class="menu-submenu-arrow" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"/></svg></span>
250
+ </div>
251
+ <div class="menubar-submenu" data-submenu-for="map" role="menu">
252
+ <div class="menu-item" id="menu-map-frame-all">
253
+ <span class="menu-check"></span>
254
+ <span class="menu-text">${t('map.menu.frameAll')}</span>
255
+ <span class="menu-shortcut" data-keybind-for="map-frame-all"></span>
256
+ </div>
257
+ <div class="menu-item menu-toggle" id="menu-map-neighbors">
258
+ <span class="menu-check">&#10003;</span>
259
+ <span class="menu-text">${t('map.menu.neighbors')}</span>
260
+ </div>
261
+ <div class="menu-item menu-toggle" id="menu-map-recency">
262
+ <span class="menu-check">&#10003;</span>
263
+ <span class="menu-text">${t('map.menu.recency')}</span>
264
+ </div>
265
+ <div class="menu-item menu-toggle" id="menu-map-grid">
266
+ <span class="menu-check">&#10003;</span>
267
+ <span class="menu-text">${t('map.menu.grid')}</span>
268
+ </div>
269
+ <div class="menu-item" id="menu-map-rebuild">
270
+ <span class="menu-check"></span>
271
+ <span class="menu-text">${t('map.menu.rebuild')}</span>
272
+ </div>
273
+ </div>
274
+ ` : ''} <!-- Games -->
275
+ <div class="menu-item menu-submenu-parent" id="menu-games-label" data-submenu="games" aria-haspopup="menu" aria-expanded="false">
276
+ <span class="menu-check"></span>
277
+ <span class="menu-text"><span class="menu-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="6" y1="11" x2="10" y2="11"/><line x1="8" y1="9" x2="8" y2="13"/><line x1="15" y1="12" x2="15.01" y2="12"/><line x1="18" y1="10" x2="18.01" y2="10"/><path d="M17.32 5H6.68a4 4 0 0 0-3.978 3.59c-.006.052-.01.101-.017.152C2.604 9.416 2 14.456 2 16a3 3 0 0 0 3 3c1 0 1.5-.5 2-1l1.414-1.414A2 2 0 0 1 9.828 16h4.344a2 2 0 0 1 1.414.586L17 18c.5.5 1 1 2 1a3 3 0 0 0 3-3c0-1.545-.604-6.584-.685-7.258-.007-.05-.011-.1-.017-.151A4 4 0 0 0 17.32 5z"/></svg></span> ${t('nav.games')}</span>
278
+ <span class="menu-submenu-arrow" aria-hidden="true"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="9 18 15 12 9 6"/></svg></span>
279
+ </div>
280
+ <div class="menubar-submenu" data-submenu-for="games" role="menu">
281
+ <div class="menu-item" id="menu-game-tictactoe">
282
+ <span class="menu-check"></span>
283
+ <span class="menu-text"><span class="menu-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="8" y1="2" x2="8" y2="22"/><line x1="16" y1="2" x2="16" y2="22"/><line x1="2" y1="8" x2="22" y2="8"/><line x1="2" y1="16" x2="22" y2="16"/></svg></span> ${t('menu.games.ticTacToe')}</span>
284
+ </div>
285
+ </div>
286
+ <div class="menu-sep"></div>
242
287
  <div class="menu-item" id="menu-install-app" style="display:none">
243
288
  <span class="menu-check"></span>
244
289
  <span class="menu-text"><span class="menu-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" 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></span> Install as App</span>
@@ -301,39 +346,8 @@ export function getSharedHTML() {
301
346
  </div>
302
347
  </div>
303
348
 
304
- ${is3D ? `
305
- <!-- Map menu (3D memory map) -->
306
- <div class="menubar-item" data-menu="graph">
307
- <button class="menubar-label">${t('nav.map')}</button>
308
- <div class="menubar-dropdown glass">
309
- <div class="menu-item" id="menu-map-frame-all">
310
- <span class="menu-check"></span>
311
- <span class="menu-text">${t('map.menu.frameAll')}</span>
312
- <span class="menu-shortcut" data-keybind-for="map-frame-all"></span>
313
- </div>
314
- <div class="menu-sep"></div>
315
- <div class="menu-item menu-toggle" id="menu-map-neighbors">
316
- <span class="menu-check">&#10003;</span>
317
- <span class="menu-text">${t('map.menu.neighbors')}</span>
318
- </div>
319
- <div class="menu-item menu-toggle" id="menu-map-recency">
320
- <span class="menu-check">&#10003;</span>
321
- <span class="menu-text">${t('map.menu.recency')}</span>
322
- </div>
323
- <div class="menu-item menu-toggle" id="menu-map-grid">
324
- <span class="menu-check">&#10003;</span>
325
- <span class="menu-text">${t('map.menu.grid')}</span>
326
- </div>
327
- <div class="menu-sep"></div>
328
- <div class="menu-item" id="menu-map-rebuild">
329
- <span class="menu-check"></span>
330
- <span class="menu-text">${t('map.menu.rebuild')}</span>
331
- </div>
332
- </div>
333
- </div>
334
-
335
- ` : `
336
- <!-- Graph menu -->
349
+ ${is3D ? '' : `
350
+ <!-- Graph menu (2D; the 3D Map's controls are a section of Apps) -->
337
351
  <div class="menubar-item" data-menu="graph">
338
352
  <button class="menubar-label">${t('nav.graph')}</button>
339
353
  <div class="menubar-dropdown glass">
@@ -423,23 +437,6 @@ ${is3D ? `
423
437
  <span class="menu-shortcut">A</span>
424
438
  </div>
425
439
  <div class="menu-sep"></div>
426
- <div class="menu-item" id="menu-automations-schedules">
427
- <span class="menu-check"></span>
428
- <span class="menu-text"><span class="menu-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg></span> Schedules</span>
429
- </div>
430
- <div class="menu-item" id="menu-automations-schedule-new">
431
- <span class="menu-check"></span>
432
- <span class="menu-text">New Cron Schedule</span>
433
- </div>
434
- <div class="menu-item" id="menu-automations-quick-timer">
435
- <span class="menu-check"></span>
436
- <span class="menu-text">Quick Timer</span>
437
- </div>
438
- <div class="menu-item" id="menu-automations-schedule-groups">
439
- <span class="menu-check"></span>
440
- <span class="menu-text">Schedule Groups</span>
441
- </div>
442
- <div class="menu-sep"></div>
443
440
  <div class="menu-item" id="menu-automations-new">
444
441
  <span class="menu-check"></span>
445
442
  <span class="menu-text">${t('menu.automations.newAutomation')}</span>
@@ -451,16 +448,8 @@ ${is3D ? `
451
448
  </div>
452
449
  </div>
453
450
 
454
- <!-- Games menu -->
455
- <div class="menubar-item" data-menu="games">
456
- <button class="menubar-label">${t('nav.games')}</button>
457
- <div class="menubar-dropdown glass">
458
- <div class="menu-item" id="menu-game-tictactoe">
459
- <span class="menu-check"></span>
460
- <span class="menu-text"><span class="menu-icon"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="8" y1="2" x2="8" y2="22"/><line x1="16" y1="2" x2="16" y2="22"/><line x1="2" y1="8" x2="22" y2="8"/><line x1="2" y1="16" x2="22" y2="16"/></svg></span> ${t('menu.games.ticTacToe')}</span>
461
- </div>
462
- </div>
463
- </div>
451
+ <!-- Schedules (opens and closes the Schedules window; no dropdown) -->
452
+ <button type="button" class="menubar-label menubar-action" id="menubar-schedules-btn" aria-expanded="false" aria-controls="schedules-studio-panel">${t('nav.schedules')}</button>
464
453
 
465
454
  <!-- Settings (text button) -->
466
455
  <button class="menubar-label menubar-action" id="menubar-settings-btn">${t('nav.settings')}</button>
@@ -868,5 +857,8 @@ ${getEditorPanelHTML()}
868
857
  * Call this once at the start of variant main.js, BEFORE any DOM queries.
869
858
  */
870
859
  export function injectSharedHTML() {
860
+ // The workspace sits in the inset rounded frame (app-frame.js): set before the shell lands, so nothing is laid
861
+ // out once without it.
862
+ document.documentElement.classList.add(FRAMED_CLASS);
871
863
  document.body.insertAdjacentHTML('afterbegin', getSharedHTML());
872
864
  }
@@ -246,6 +246,8 @@ export function setLocaleChoice(choice) {
246
246
  const value = choice === SYSTEM_LOCALE ? SYSTEM_LOCALE : (SUPPORTED_LOCALES.includes(choice) ? choice : null);
247
247
  if (!value) return false;
248
248
  storage.setItem(LOCALE_STORAGE_KEY, value);
249
+ // Windows that open again after the reload (the Schedules window) note it now, while they are open.
250
+ try { globalThis.window?.dispatchEvent?.(new CustomEvent('synabun:locale-change', { detail: { choice: value } })); } catch { /* nobody listens */ }
249
251
  // The store writes to the server after a pause; the reload must read the new choice.
250
252
  // (A write still pending when the page unloads goes out as a beacon, so a slow server only delays the reload.)
251
253
  const written = Promise.resolve().then(() => storageModule.flushStorage?.()).catch(() => {});
@@ -0,0 +1,59 @@
1
+ // ═══════════════════════════════════════════
2
+ // SynaBun Neural Interface — launch prefetch
3
+ // ═══════════════════════════════════════════
4
+ // What windows, menus and dropdowns wait for when they open, read once the
5
+ // page has painted: in idle time, one step after another with a pause
6
+ // between two, so the page never stutters for it and the first open of each
7
+ // window paints from the data cache (data-cache.js). Each module registers
8
+ // its own steps (registerLaunchPrefetch); the page starts the queue after its
9
+ // first paint (startLaunchPrefetch). A step that fails is the window's to ask
10
+ // again when it opens. `owner` steps read what an invite guest may not.
11
+
12
+ import { whenIdle } from './data-cache.js';
13
+
14
+ const STEP_LIMIT_MS = 15_000; // a step that hangs does not hold the ones after it
15
+ const STEP_GAP_MS = 120;
16
+
17
+ const steps = [];
18
+ let started = false;
19
+ let running = false;
20
+ let guest = () => false;
21
+
22
+ /** Add a step: `run()` reads something into a cache. Lower `order` runs first. */
23
+ export function registerLaunchPrefetch(name, run, { order = 50, owner = false } = {}) {
24
+ if (typeof run !== 'function' || steps.some((step) => step.name === name)) return;
25
+ steps.push({ name, run, order, owner, done: false });
26
+ steps.sort((a, b) => a.order - b.order);
27
+ if (started) pump();
28
+ }
29
+
30
+ /** Start the queue (once): after the first paint, `delayMs` later and in idle time. */
31
+ export function startLaunchPrefetch({ delayMs = 600, isGuest = () => false } = {}) {
32
+ if (started) return;
33
+ started = true;
34
+ guest = typeof isGuest === 'function' ? isGuest : () => false;
35
+ setTimeout(pump, delayMs);
36
+ }
37
+
38
+ function pump() {
39
+ if (running) return;
40
+ const next = steps.find((step) => !step.done);
41
+ if (!next) return;
42
+ running = true;
43
+ whenIdle(async () => {
44
+ next.done = true;
45
+ let skip = false;
46
+ try { skip = next.owner && guest(); } catch { skip = false; }
47
+ if (!skip) {
48
+ let timer = null;
49
+ try {
50
+ await Promise.race([
51
+ Promise.resolve().then(next.run),
52
+ new Promise((done) => { timer = setTimeout(done, STEP_LIMIT_MS); }),
53
+ ]);
54
+ } catch { /* the window asks again when it opens */ }
55
+ clearTimeout(timer);
56
+ }
57
+ setTimeout(() => { running = false; pump(); }, STEP_GAP_MS);
58
+ }, { timeout: 2000 });
59
+ }
@@ -200,14 +200,14 @@ export async function setAutoAccept(store, api, enabled, { cwd, isDescendant } =
200
200
  }
201
201
 
202
202
  /**
203
- * How long an "Always allow" lasts, for the card. On OpenCode 1.18.34 the
204
- * answer is kept by the serve process that runs the session: the patterns are
205
- * allowed for the project on that serve until it restarts. It is not written
206
- * to OpenCode's saved-permissions store (`/api/permission/saved` stays empty
207
- * after an "always"; checked against a live serve), so there is no list of
208
- * earlier answers to show or take back.
203
+ * How far an "Always allow" reaches, for the card. OpenCode 2 saves the answer
204
+ * for the session's project: after an "always" reply on 2.1.4,
205
+ * `GET /api/permission/saved` lists `{ projectID, action, resource }` with the
206
+ * card's pattern (checked against a live serve), so it holds in every session
207
+ * of that project and outlives the serve. The panel shows no list of saved
208
+ * answers; OpenCode's own saved permissions are where one is taken back.
209
209
  */
210
- export const ALWAYS_ALLOW_SCOPE = 'until this session\u2019s OpenCode runtime restarts';
210
+ export const ALWAYS_ALLOW_SCOPE = 'in every session of this project: OpenCode saves the answer';
211
211
 
212
212
  // ── Questions ───────────────────────────────────────────────────────────────
213
213
  // The answer path of a question card, whatever built the card: a request in
@@ -63,7 +63,7 @@ function frozenCopy(value, seen = new Map()) {
63
63
  * isCurrent() an extra veto, e.g. "this child panel is still the open one"
64
64
  * Returns a frozen token:
65
65
  * binding, sessionId, cwd, directory (cwd, else the session's directory),
66
- * model, variant, agent, mode, mcpProfile, sessionInfo (model and
66
+ * model, variant, agent, mode, tools, sessionInfo (model and
67
67
  * sessionInfo are frozen copies, nested objects included)
68
68
  * isCurrent() the store is still on this binding
69
69
  * isStale() the opposite
@@ -90,7 +90,7 @@ export function captureBinding(store, { sessionId, isCurrent } = {}) {
90
90
  variant: s.variant || null,
91
91
  agent: s.agent || null,
92
92
  mode: s.mode || null,
93
- mcpProfile: s.mcpProfile || null,
93
+ tools: s.tools ? frozenCopy(s.tools) : null,
94
94
  sessionInfo: s.sessionInfo ? frozenCopy(s.sessionInfo) : null,
95
95
  isCurrent: current,
96
96
  isStale: () => !current(),
@@ -218,8 +218,8 @@ export function boundReader(store) {
218
218
  // another tab after it. Both were started on the same binding.
219
219
  //
220
220
  // So where the panel goes has an identity of its own. Every choice of the user
221
- // (a tab, a session in the menu, New session, another project, a new worktree)
222
- // begins an intent, and a navigation binds the panel only while its intent is
221
+ // (a tab, a session in the menu, New session, another project) begins an
222
+ // intent, and a navigation binds the panel only while its intent is
223
223
  // the latest one: after every wait it checks `isCurrent()`, and it binds
224
224
  // through `apply()`. A later choice always wins over an older one that is
225
225
  // still in flight. A rebinding nobody announced (the active tab was closed)