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
@@ -1,23 +1,26 @@
1
+ import { wireDropdowns, closeDropdowns, setDropdownDisabled, dropdownOf } from '../cc-dropdown.js';
2
+ import { configureToolPickerTranslation, toolPickerHTML, updateToolPicker, readToolPicker, toolWord } from '../tool-list-picker.js';
3
+ import { toolListView } from '../tool-list-view.js';
1
4
  // ═══════════════════════════════════════════
2
5
  // SynaBun Assistant — brain picker (toolbar fields)
3
6
  // ═══════════════════════════════════════════
4
7
  // Dropdown fields for the brain: model (provider icon + model; switching
5
8
  // provider happens inside the model menu, grouped by provider), effort (or the
6
9
  // OpenCode agent), permission mode and account (Claude/Codex, inline only when
7
- // there is more than one to pick) in the composer row; project and MCP profile
10
+ // there is more than one to pick) in the composer row; project and SynaBun tools
8
11
  // in the toolbar. Every field opens an asst-menu popover (it flips when there
9
- // is no room). A provider/account/profile change reports
12
+ // is no room). A provider/account/tools change reports
10
13
  // { requiresSwitch: true } so the panel sends `switch_brain`.
11
14
 
12
15
  import {
13
16
  ensureModelsForProfile,
14
17
  fetchClaudeAccounts,
15
18
  fetchCodexAccounts,
16
- fetchMcpProfilePresets,
19
+ fetchToolCatalog,
17
20
  fetchOpencodeAgents,
18
21
  getCachedClaudeAccounts,
19
22
  getCachedCodexAccounts,
20
- getCachedMcpProfilePresets,
23
+ getCachedToolCatalog,
21
24
  getCachedOpencodeAgents,
22
25
  getClaudeWorkerAccountId,
23
26
  getCodexWorkerAccountId,
@@ -29,6 +32,7 @@ import {
29
32
  import { getHiddenModels, HIDDEN_MODELS_EVENT, hiddenModelMatch } from '../ocp-hidden-models.js';
30
33
  import { getProviderMeta } from '../provider-icons.js';
31
34
  import { on } from '../state.js';
35
+ import { registerLaunchPrefetch } from '../launch-prefetch.js';
32
36
  import { fetchAssistantCatalog, fetchProjects, patchClaudeAccount, patchCodexAccount, setClaudeWorkerAccount, setCodexWorkerAccount } from './asst-api.js';
33
37
  import { accountBadge, accountIdentity, accountName, accountText } from '../account-view.js';
34
38
  import { autoAccountLabel } from '../account-usage.js';
@@ -54,6 +58,9 @@ import {
54
58
  } from './asst-state.js';
55
59
 
56
60
  let _projectsCache = null;
61
+ // Providers whose field menus have everything they read loaded once (models, catalog, accounts or agents,
62
+ // presets, projects): their menus open from it at once and read it again in the background.
63
+ const _warmProviders = new Set();
57
64
 
58
65
  /** SynaBun's registered projects as the last load saw them ([{ path, label }]; [] before the first). */
59
66
  export function cachedProjects() { return _projectsCache || []; }
@@ -321,11 +328,41 @@ export async function loadModelCatalog({ force = false } = {}) {
321
328
  // while it loaded: the next open asks again.
322
329
  _catalogAt = remote && epoch === _catalogEpoch ? Date.now() : 0;
323
330
  _catalogPartial = !remote;
331
+ if (_catalogAt) keepCatalog(out, sets);
324
332
  return out;
325
333
  })().finally(() => { _catalogLoading = null; });
326
334
  return _catalogLoading;
327
335
  }
328
336
 
337
+ // The last complete catalog is also kept in sessionStorage (this tab only): after a reload the model menus
338
+ // paint from it at once. Read back, it is due: the first load asks the server again.
339
+ const CATALOG_STORE_KEY = 'synabun:assistant-model-catalog:v1';
340
+ function keepCatalog(catalog, sets) {
341
+ try {
342
+ if (typeof sessionStorage === 'undefined') return;
343
+ const hidden = {};
344
+ for (const provider of PROVIDERS) hidden[provider] = [...(sets?.[provider] || [])];
345
+ const rowOnly = {};
346
+ for (const provider of PROVIDERS) rowOnly[provider] = [...(sets?.rowOnly?.[provider] || [])];
347
+ sessionStorage.setItem(CATALOG_STORE_KEY, JSON.stringify({ catalog, hidden, rowOnly }));
348
+ } catch { /* full or unavailable */ }
349
+ }
350
+ (() => {
351
+ try {
352
+ if (typeof sessionStorage === 'undefined' || _catalog) return;
353
+ const kept = JSON.parse(sessionStorage.getItem(CATALOG_STORE_KEY) || 'null');
354
+ if (!kept?.catalog || typeof kept.catalog !== 'object') return;
355
+ _catalog = kept.catalog;
356
+ _catalogAt = 0;
357
+ const sets = { rowOnly: {} };
358
+ for (const provider of PROVIDERS) {
359
+ sets[provider] = new Set(Array.isArray(kept.hidden?.[provider]) ? kept.hidden[provider] : []);
360
+ sets.rowOnly[provider] = new Set(Array.isArray(kept.rowOnly?.[provider]) ? kept.rowOnly[provider] : []);
361
+ }
362
+ _hidden = sets;
363
+ } catch { /* unreadable: the first load builds it */ }
364
+ })();
365
+
329
366
  /** The last loadModelCatalog() result, synchronously (null before the first load). */
330
367
  export function cachedModelCatalog() { return _catalog; }
331
368
 
@@ -346,6 +383,8 @@ export function invalidateModelCatalog() {
346
383
  _catalogAt = 0;
347
384
  _catalogPartial = false;
348
385
  _catalogEpoch += 1;
386
+ // A reload must not paint the lists this replaced.
387
+ try { if (typeof sessionStorage !== 'undefined') sessionStorage.removeItem(CATALOG_STORE_KEY); } catch { /* unavailable */ }
349
388
  }
350
389
 
351
390
  /**
@@ -366,6 +405,15 @@ function modelListsChanged() {
366
405
  for (const listener of [..._catalogListeners]) {
367
406
  try { listener(); } catch { /* a listener's failure is its own */ }
368
407
  }
408
+ scheduleCatalogReload();
409
+ }
410
+
411
+ // In a page: the new lists are read right away, so the next menu opens from them (an open that comes
412
+ // first joins this read).
413
+ let _catalogReloadTimer = null;
414
+ function scheduleCatalogReload() {
415
+ if (typeof document === 'undefined' || _catalogReloadTimer) return;
416
+ _catalogReloadTimer = setTimeout(() => { _catalogReloadTimer = null; loadModelCatalog().catch(() => {}); }, 250);
369
417
  }
370
418
 
371
419
  /**
@@ -397,6 +445,12 @@ on('sync:opencode:hidden-models-changed', modelListsChanged);
397
445
  on('sync:assistant:hidden-models-changed', modelListsChanged);
398
446
  on('sync:assistant:catalog-changed', modelListsChanged);
399
447
 
448
+ // Launch: the menus' lists are read once the page has painted, so the first model menu opens from them.
449
+ if (typeof document !== 'undefined') {
450
+ registerLaunchPrefetch('assistant-model-catalog', () => loadModelCatalog(), { order: 10, owner: true });
451
+ registerLaunchPrefetch('assistant-accounts', () => Promise.allSettled([fetchClaudeAccounts(), fetchCodexAccounts(), fetchToolCatalog(), fetchOpencodeAgents()]), { order: 14, owner: true });
452
+ }
453
+
400
454
  function sameModel(selected, m) {
401
455
  if (!selected) return false;
402
456
  return selected === m.id || selected === m.selector;
@@ -435,74 +489,29 @@ export async function openModelMenu(anchor, opts = {}) {
435
489
  if (!anchor) return null;
436
490
  const tr = tf(t);
437
491
  const b = normalizeBrain(brain);
438
- anchor.setAttribute('aria-busy', 'true');
439
- // Open immediately: a slow provider still has a visible, cancellable state.
440
- const loading = opts.routingEditor ? openMenu(anchor, {
441
- title, className: 'asst-model-menu asst-route-model-menu',
442
- items: [{ kind: 'info', label: tr('assistant.routes.editorState.loadingModels', 'Loading models…') }],
443
- width: 380, zIndex: opts.zIndex ?? null, repositionOnResize: true,
444
- }) : null;
445
- if (loading) loading.el.setAttribute('aria-busy', 'true');
446
- if (loading) { loading.el.setAttribute('role', 'dialog'); anchor.setAttribute('aria-haspopup', 'dialog'); }
492
+ // The kept catalog paints the menu at once (it is read again in the background below, and an open menu
493
+ // follows it in place); only a first open, or a reload the user asked for, waits for the lists.
494
+ const kept = opts.forceReload === true ? null : cachedModelCatalog();
447
495
  let catalog = {};
448
496
  let failed = false;
449
- try { catalog = await loadModelCatalog({ force: opts.forceReload === true }); } catch { failed = true; } finally { anchor.removeAttribute('aria-busy'); }
450
- if (!anchor.isConnected || (loading && currentMenu() !== loading.el)) return null;
451
- const metadata = modelCatalogStatus();
452
- const items = [];
453
- if (Array.isArray(opts.accountItems) && opts.accountItems.length) {
454
- items.push({ kind: 'header', label: opts.accountTitle || tr('assistant.brain.account', 'Account profile') }, ...opts.accountItems, { kind: 'separator' });
455
- }
456
- if (includeHere) {
457
- items.push({ kind: 'radio', id: '__here', label: hereLabel || tr('assistant.routes.brainDecides', 'Let the brain decide'), selected: !current, onSelect: () => onSelect?.({ here: true }) });
458
- }
459
- const list = Array.isArray(providers) && providers.length ? PROVIDERS.filter(p => providers.includes(p)) : PROVIDERS;
460
- let listed = 0;
461
- for (const provider of list) {
462
- const models = (catalog[provider] || []).filter(m => typeof accept !== 'function' || accept(provider, m));
463
- if (!models.length && !opts.routingEditor) continue;
464
- listed += models.length;
465
- const meta = getProviderMeta(provider);
466
- const hiddenCount = metadata.hiddenCounts[provider] || 0;
467
- const note = opts.routingEditor ? tr('assistant.routes.menu.hiddenCount', '{count} hidden in Models', { count: hiddenCount }) : warnSwitch && provider !== b.provider ? tr('assistant.brain.newConversation', 'starts a new conversation') : '';
468
- items.push({ kind: 'header', label: meta.label, icon: meta.icon, color: meta.color, note });
469
- for (const m of models) {
470
- items.push({
471
- kind: 'radio',
472
- id: `${provider}:${m.id}`,
473
- label: m.label,
474
- desc: modelDesc(m, tr, opts.routingEditor),
475
- title: `${m.label || m.id} · ${m.id}`,
476
- tag: tierTag(m, tr),
477
- keywords: `${meta.label} ${m.id}`,
478
- selected: !!current && current.provider === provider && sameModel(current.model, m),
479
- onSelect: () => onSelect?.({ provider, model: m.id, label: m.label, tier: m.tier || null, vision: m.vision ?? null, outputs: m.outputs || null, efforts: m.efforts || null, price: m.price || null }),
480
- });
481
- }
482
- if (opts.routingEditor && !models.length) items.push({ kind: 'info', label: typeof accept === 'function' ? tr('assistant.routes.menu.noCompatible', 'No compatible models shown for this provider.') : tr('assistant.routes.menu.providerEmpty', 'No models shown for this provider.') });
483
- }
484
- // Nothing passes the filter (e.g. no model makes video yet): say so instead of an empty list.
485
- if (!listed && typeof accept === 'function' && emptyLabel) items.push({ kind: 'info', label: emptyLabel });
486
- if (opts.routingEditor && !listed && typeof accept !== 'function') items.push({ kind: 'info', label: tr('assistant.routes.editorState.modelsEmpty', 'No models are available. Check Models or connect a provider, then reload.') });
487
- if (allowCustom) {
488
- items.push({ kind: 'separator' });
489
- items.push({
490
- kind: 'input',
491
- placeholder: tr('assistant.brain.modelCustom', 'Custom model id…'),
492
- onSubmit: (v) => {
493
- const provider = current?.provider || b.provider;
494
- const disabled = hiddenModelFor(provider, v);
495
- if (disabled) {
496
- onToast?.(tr('assistant.brain.modelDisabled', "{model} is disabled in the Assistant's Models list.", { model: disabled }));
497
- return;
498
- }
499
- onSelect?.({ provider, model: v, label: modelShortName(v), custom: true });
500
- },
501
- });
502
- }
503
- if (!opts.routingEditor && typeof opts.onManageModels === 'function') {
504
- items.push({ id: '__manage_models', label: tr('assistant.models.manage', 'Manage models…'), onSelect: () => opts.onManageModels() });
497
+ let loading = null;
498
+ if (kept) {
499
+ catalog = kept;
500
+ } else {
501
+ anchor.setAttribute('aria-busy', 'true');
502
+ // Open immediately: a slow provider still has a visible, cancellable state.
503
+ loading = opts.routingEditor ? openMenu(anchor, {
504
+ title, className: 'asst-model-menu asst-route-model-menu',
505
+ items: [{ kind: 'info', label: tr('assistant.routes.editorState.loadingModels', 'Loading models…') }],
506
+ width: 380, zIndex: opts.zIndex ?? null, repositionOnResize: true,
507
+ }) : null;
508
+ if (loading) loading.el.setAttribute('aria-busy', 'true');
509
+ if (loading) { loading.el.setAttribute('role', 'dialog'); anchor.setAttribute('aria-haspopup', 'dialog'); }
510
+ try { catalog = await loadModelCatalog({ force: opts.forceReload === true }); } catch { failed = true; } finally { anchor.removeAttribute('aria-busy'); }
511
+ if (!anchor.isConnected || (loading && currentMenu() !== loading.el)) return null;
505
512
  }
513
+ if (opts.shouldOpen && !opts.shouldOpen()) return null;
514
+ const items = buildModelMenuItems(catalog);
506
515
  const menu = openMenu(anchor, {
507
516
  title: title || tr('assistant.brain.model', 'Model'),
508
517
  items,
@@ -516,7 +525,79 @@ export async function openModelMenu(anchor, opts = {}) {
516
525
  repositionOnResize: true,
517
526
  filterEmptyLabel: tr('assistant.routes.menu.noMatches', 'No matching models. Check Models for hidden choices.'),
518
527
  });
519
- if (opts.routingEditor && menu) {
528
+ if (opts.routingEditor && menu) decorateRouteMenu(menu, failed);
529
+ // Painted from the kept catalog: read it again (fresh within its minute, else a background request) and
530
+ // redraw the open menu in place when the lists changed, leaving the filter, the scroll and the focus alone.
531
+ if (kept && menu && !opts.routingEditor) {
532
+ loadModelCatalog().then((next) => {
533
+ if (!next || next === kept || currentMenu() !== menu.el || !anchor.isConnected) return;
534
+ const nextItems = buildModelMenuItems(next);
535
+ if (menuItemsSignature(nextItems) !== menuItemsSignature(items)) menu.update({ items: nextItems, keepPlace: true });
536
+ }).catch(() => { /* the kept list stays */ });
537
+ }
538
+ return menu;
539
+
540
+ function buildModelMenuItems(catalog) {
541
+ const metadata = modelCatalogStatus();
542
+ const items = [];
543
+ if (Array.isArray(opts.accountItems) && opts.accountItems.length) {
544
+ items.push({ kind: 'header', label: opts.accountTitle || tr('assistant.brain.account', 'Account profile') }, ...opts.accountItems, { kind: 'separator' });
545
+ }
546
+ if (includeHere) {
547
+ items.push({ kind: 'radio', id: '__here', label: hereLabel || tr('assistant.routes.brainDecides', 'Let the brain decide'), selected: !current, onSelect: () => onSelect?.({ here: true }) });
548
+ }
549
+ const list = Array.isArray(providers) && providers.length ? PROVIDERS.filter(p => providers.includes(p)) : PROVIDERS;
550
+ let listed = 0;
551
+ for (const provider of list) {
552
+ const models = (catalog[provider] || []).filter(m => typeof accept !== 'function' || accept(provider, m));
553
+ if (!models.length && !opts.routingEditor) continue;
554
+ listed += models.length;
555
+ const meta = getProviderMeta(provider);
556
+ const hiddenCount = metadata.hiddenCounts[provider] || 0;
557
+ const note = opts.routingEditor ? tr('assistant.routes.menu.hiddenCount', '{count} hidden in Models', { count: hiddenCount }) : warnSwitch && provider !== b.provider ? tr('assistant.brain.newConversation', 'starts a new conversation') : '';
558
+ items.push({ kind: 'header', label: meta.label, icon: meta.icon, color: meta.color, note });
559
+ for (const m of models) {
560
+ items.push({
561
+ kind: 'radio',
562
+ id: `${provider}:${m.id}`,
563
+ label: m.label,
564
+ desc: modelDesc(m, tr, opts.routingEditor),
565
+ title: `${m.label || m.id} · ${m.id}`,
566
+ tag: tierTag(m, tr),
567
+ keywords: `${meta.label} ${m.id}`,
568
+ selected: !!current && current.provider === provider && sameModel(current.model, m),
569
+ onSelect: () => onSelect?.({ provider, model: m.id, label: m.label, tier: m.tier || null, vision: m.vision ?? null, outputs: m.outputs || null, efforts: m.efforts || null, price: m.price || null }),
570
+ });
571
+ }
572
+ if (opts.routingEditor && !models.length) items.push({ kind: 'info', label: typeof accept === 'function' ? tr('assistant.routes.menu.noCompatible', 'No compatible models shown for this provider.') : tr('assistant.routes.menu.providerEmpty', 'No models shown for this provider.') });
573
+ }
574
+ // Nothing passes the filter (e.g. no model makes video yet): say so instead of an empty list.
575
+ if (!listed && typeof accept === 'function' && emptyLabel) items.push({ kind: 'info', label: emptyLabel });
576
+ if (opts.routingEditor && !listed && typeof accept !== 'function') items.push({ kind: 'info', label: tr('assistant.routes.editorState.modelsEmpty', 'No models are available. Check Models or connect a provider, then reload.') });
577
+ if (allowCustom) {
578
+ items.push({ kind: 'separator' });
579
+ items.push({
580
+ kind: 'input',
581
+ placeholder: tr('assistant.brain.modelCustom', 'Custom model id…'),
582
+ onSubmit: (v) => {
583
+ const provider = current?.provider || b.provider;
584
+ const disabled = hiddenModelFor(provider, v);
585
+ if (disabled) {
586
+ onToast?.(tr('assistant.brain.modelDisabled', "{model} is disabled in the Assistant's Models list.", { model: disabled }));
587
+ return;
588
+ }
589
+ onSelect?.({ provider, model: v, label: modelShortName(v), custom: true });
590
+ },
591
+ });
592
+ }
593
+ if (!opts.routingEditor && typeof opts.onManageModels === 'function') {
594
+ items.push({ id: '__manage_models', label: tr('assistant.models.manage', 'Manage models…'), onSelect: () => opts.onManageModels() });
595
+ }
596
+ return items;
597
+ }
598
+
599
+ function decorateRouteMenu(menu, failed) {
600
+ const metadata = modelCatalogStatus();
520
601
  // Search and a custom-id input belong to a dialog; choices are a radio group.
521
602
  // A menu role cannot contain these form fields or recovery buttons.
522
603
  menu.el.setAttribute('role', 'dialog');
@@ -546,7 +627,11 @@ export async function openModelMenu(anchor, opts = {}) {
546
627
  }
547
628
  menu.el.append(footer); menu.reposition();
548
629
  }
549
- return menu;
630
+ }
631
+
632
+ /** What a model menu lists, for telling a fresher read from the one on screen. */
633
+ function menuItemsSignature(items) {
634
+ return JSON.stringify((items || []).map((item) => [item.kind || '', item.id ?? '', item.label || '', item.desc || '', item.tag || '', item.note || '', !!item.selected]));
550
635
  }
551
636
 
552
637
  // ── Picker ──────────────────────────────────────────────────────────────────
@@ -554,7 +639,7 @@ export async function openModelMenu(anchor, opts = {}) {
554
639
  // Creation order is DOM order within a slot: model · effort · variant · mode · tests · account in the composer.
555
640
  // `effort` is the OpenCode agent for OpenCode; `variant` is OpenCode's effort (the model's variants).
556
641
  // `tests` is the session's Test density, not a brain field: it shows only while the host supplies a level.
557
- const FIELDS = ['model', 'effort', 'variant', 'mode', 'tests', 'account', 'project', 'mcp'];
642
+ const FIELDS = ['model', 'effort', 'variant', 'mode', 'tests', 'account', 'project'];
558
643
  // Slot of each field: the composer row (the brain and how it acts) · the toolbar (where it works).
559
644
  const FIELD_GROUP = { model: 'brain', effort: 'brain', variant: 'brain', mode: 'brain', tests: 'brain', account: 'brain', project: 'context', mcp: 'context' };
560
645
 
@@ -569,6 +654,7 @@ const FIELD_GROUP = { model: 'brain', effort: 'brain', variant: 'brain', mode: '
569
654
  * onProjects(projects) — the registered projects were (re)loaded }
570
655
  */
571
656
  export function createBrainPicker(host, hooks = {}) {
657
+ configureToolPickerTranslation(hooks.t);
572
658
  const t = tf(hooks.t);
573
659
  const placement = hooks.menuPlacement || 'below';
574
660
 
@@ -593,6 +679,31 @@ export function createBrainPicker(host, hooks = {}) {
593
679
  buttons[field] = btn;
594
680
  }
595
681
 
682
+ const toolsSlot = el('div', 'asst-tools-picker');
683
+ (single ? root : host.context || root).appendChild(toolsSlot);
684
+ const toolsLife = new AbortController();
685
+ wireDropdowns(toolsSlot, { signal: toolsLife.signal });
686
+ let toolsSessionId = null;
687
+ toolsSlot.addEventListener('cc-dropdown-open', () => { toolsSessionId = hooks.getSessionId?.() ?? null; }, { signal: toolsLife.signal });
688
+ toolsSlot.addEventListener('change', (event) => {
689
+ if (currentBrain().provider !== 'opencode' || toolsSessionId !== (hooks.getSessionId?.() ?? null)) return;
690
+ commit({ tools: readToolPicker(event.target, { inherit: false }) }, 'tools');
691
+ }, { signal: toolsLife.signal });
692
+ function renderTools(brain) {
693
+ if (toolsSessionId !== (hooks.getSessionId?.() ?? null)) closeDropdowns(toolsSlot, { cancel: true });
694
+ const catalog = getCachedToolCatalog();
695
+ toolsSlot.hidden = brain.provider !== 'opencode' || !catalog;
696
+ if (toolsSlot.hidden) { closeDropdowns(toolsSlot, { cancel: true }); toolsSlot.innerHTML = ''; return; }
697
+ let input = toolsSlot.querySelector('input');
698
+ const options = { catalog, includeServers: false, label: t('assistant.brain.mcp') };
699
+ const tools = brain.tools ?? [...new Set([...(catalog.default || []).filter(id => id !== 'git'), 'browser'])];
700
+ if (!input) {
701
+ toolsSlot.innerHTML = toolPickerHTML(`asst-tools-${globalThis.crypto.randomUUID()}`, tools, options);
702
+ input = toolsSlot.querySelector('input');
703
+ } else if (!dropdownOf(input)?.classList.contains('open')) updateToolPicker(input, tools, options);
704
+ setDropdownDisabled(input, hooks.getRunning?.() === true);
705
+ }
706
+
596
707
  let destroyed = false;
597
708
  let loading = null;
598
709
  // The empty state's "Choose a project" (mountEmptyProject): the project field's second button.
@@ -613,8 +724,7 @@ export function createBrainPicker(host, hooks = {}) {
613
724
  codex: getCachedCodexAccounts(),
614
725
  },
615
726
  agents: getCachedOpencodeAgents(),
616
- mcpProfiles: getCachedMcpProfilePresets(),
617
- defaultMcpProfile: 'full',
727
+ toolCatalog: getCachedToolCatalog(),
618
728
  projects: _projectsCache || [],
619
729
  };
620
730
  }
@@ -687,7 +797,7 @@ export function createBrainPicker(host, hooks = {}) {
687
797
  const efforts = effortsFor(brain);
688
798
  const level = efforts.find(e => e.id === brain.effort);
689
799
  const hasEfforts = efforts.some(e => e.id !== 'off');
690
- const presets = getCachedMcpProfilePresets();
800
+ const toolCatalog = getCachedToolCatalog();
691
801
  return {
692
802
  meta,
693
803
  model: modelLabel(brain),
@@ -699,7 +809,7 @@ export function createBrainPicker(host, hooks = {}) {
699
809
  variant: level ? level.label : (brain.effort || t('assistant.brain.variantDefault', 'default variant')),
700
810
  project: brain.project ? projectLabel(brain.project, _projectsCache || []) : t('assistant.brain.projectHome', 'Home'),
701
811
  mode: permissionModeLabel(brain, (id, fallback) => t(`assistant.brain.modes.${id}`, fallback)),
702
- mcp: presets[brain.mcpProfile]?.label || brain.mcpProfile || 'full',
812
+ mcp: toolListView(toolCatalog, brain.tools, { translate: hooks.t }).summary,
703
813
  account: ACCOUNT_PROVIDERS.has(brain.provider) ? accountLabel(brain) : '',
704
814
  };
705
815
  }
@@ -874,7 +984,7 @@ export function createBrainPicker(host, hooks = {}) {
874
984
  const testsLabel = tests ? testDensityLabel(tests, hooks.t) : '';
875
985
  setBtn('tests', { label: testsLabel, icon: testsIcon(testDensityBars(tests)), hidden: !tests, tooltip: `${t('assistant.tests.title', 'Test density')}: ${testsLabel}` });
876
986
  if (tests) buttons.tests.dataset.level = tests; else delete buttons.tests.dataset.level;
877
- setBtn('mcp', { label: v.mcp, icon: ICON_PLUG, tooltip: `${t('assistant.brain.mcp', 'MCP tool profile')}: ${v.mcp}` });
987
+ renderTools(brain);
878
988
  renderEmptyProject(brain);
879
989
  }
880
990
 
@@ -941,7 +1051,6 @@ export function createBrainPicker(host, hooks = {}) {
941
1051
  { field: 'project', label: t('assistant.brain.project', 'Working project'), value: brain.project || v.project, icon: ICON_FOLDER, hidden: false },
942
1052
  { field: 'mode', label: t('assistant.brain.mode', 'Permission mode'), value: v.mode, icon: ICON_SHIELD, hidden: false },
943
1053
  { field: 'tests', label: t('assistant.tests.title', 'Test density'), value: testDensity() ? testDensityLabel(testDensity(), hooks.t) : '', icon: testsIcon(testDensityBars(testDensity())), hidden: !testDensity() },
944
- { field: 'mcp', label: t('assistant.brain.mcp', 'MCP tool profile'), value: v.mcp, icon: ICON_PLUG, hidden: false },
945
1054
  { field: 'account', label: t('assistant.brain.accountShort', 'Account'), value: accountValue(brain), icon: ICON_ACCOUNT, hidden: !ACCOUNT_PROVIDERS.has(brain.provider) },
946
1055
  ];
947
1056
  }
@@ -957,7 +1066,7 @@ export function createBrainPicker(host, hooks = {}) {
957
1066
 
958
1067
  async function ensureLoaded(provider, { force = false } = {}) {
959
1068
  // The catalog too: defaults resolve against the menu's list (context variants, disabled models out).
960
- const jobs = [ensureModelsForProfile(provider, force), fetchMcpProfilePresets(force), loadModelCatalog()];
1069
+ const jobs = [ensureModelsForProfile(provider, force), fetchToolCatalog(force), loadModelCatalog()];
961
1070
  if (provider === 'codex') jobs.push(fetchCodexAccounts(force));
962
1071
  if (provider === 'claude-code') jobs.push(fetchClaudeAccounts(force));
963
1072
  if (provider === 'opencode') jobs.push(fetchOpencodeAgents(force));
@@ -968,6 +1077,7 @@ export function createBrainPicker(host, hooks = {}) {
968
1077
  }).catch(() => { _projectsCache = _projectsCache || []; }));
969
1078
  }
970
1079
  await Promise.allSettled(jobs);
1080
+ if (cachedModelCatalog()) _warmProviders.add(provider);
971
1081
  }
972
1082
 
973
1083
  async function refresh(force = false) {
@@ -995,13 +1105,19 @@ export function createBrainPicker(host, hooks = {}) {
995
1105
  * Open a field menu; `anchorOverride` (e.g. the toolbar "⋯") when the inline
996
1106
  * button is hidden. `restoreFocus`: a pick sends focus back to the anchor.
997
1107
  */
998
- async function openField(field, anchorOverride = null, { restoreFocus = false } = {}) {
1108
+ async function openField(field, anchorOverride = null, { restoreFocus = false, shouldOpen = () => true } = {}) {
1109
+ if (!shouldOpen()) return;
999
1110
  const anchor = anchorFor(field, anchorOverride);
1000
1111
  const brain = currentBrain();
1001
1112
  if (field === 'model') {
1002
- if (ACCOUNT_PROVIDERS.has(brain.provider)) await ensureLoaded(brain.provider);
1113
+ // The account rows come from the kept lists; they are read again in the background once loaded.
1114
+ if (ACCOUNT_PROVIDERS.has(brain.provider)) {
1115
+ if (_warmProviders.has(brain.provider)) ensureLoaded(brain.provider).catch(() => {});
1116
+ else await ensureLoaded(brain.provider);
1117
+ }
1003
1118
  await openModelMenu(anchor, {
1004
1119
  brain,
1120
+ shouldOpen,
1005
1121
  t: hooks.t,
1006
1122
  placement,
1007
1123
  current: { provider: brain.provider, model: brain.model },
@@ -1034,12 +1150,48 @@ export function createBrainPicker(host, hooks = {}) {
1034
1150
  });
1035
1151
  return;
1036
1152
  }
1037
- // Everything else needs the provider catalog — load it lazily on first open.
1038
- anchor.setAttribute('aria-busy', 'true');
1039
- try { await ensureLoaded(brain.provider); } finally { anchor.removeAttribute('aria-busy'); }
1040
- if (destroyed || !anchor.isConnected) return;
1041
- const menu = (title, items, extra = {}) => openMenu(anchor, { title, items, placement, role: 'menu', ...extra });
1153
+ // The account menu reads the kept rows and asks again by itself (asst-account-menu.js).
1154
+ if (field === 'account') {
1155
+ if (!ACCOUNT_PROVIDERS.has(brain.provider)) return;
1156
+ if (!_warmProviders.has(brain.provider)) {
1157
+ anchor.setAttribute('aria-busy', 'true');
1158
+ try { await ensureLoaded(brain.provider); } finally { anchor.removeAttribute('aria-busy'); }
1159
+ if (destroyed || !anchor.isConnected || !shouldOpen()) return;
1160
+ } else {
1161
+ ensureLoaded(brain.provider).catch(() => {});
1162
+ }
1163
+ // Kept inside the panel that holds the anchor (the sidepanel, or the tab's own root).
1164
+ openAccountMenu(anchor, accountMenu(brain, anchor.closest?.('.assistant-panel') || anchor.closest?.('.asst-root') || null));
1165
+ return;
1166
+ }
1167
+ // Everything else needs the provider catalog — load it lazily on first open. Once it is loaded the menu
1168
+ // opens from what is kept, the lists are read again in the background, and an open menu they change is
1169
+ // redrawn in place (the filter, the scroll and the focus stay).
1170
+ const warm = _warmProviders.has(brain.provider);
1171
+ if (!warm) {
1172
+ anchor.setAttribute('aria-busy', 'true');
1173
+ try { await ensureLoaded(brain.provider); } finally { anchor.removeAttribute('aria-busy'); }
1174
+ if (destroyed || !anchor.isConnected || !shouldOpen()) return;
1175
+ }
1176
+ let shown = null;
1177
+ drawField(field, brain, (title, items, extra = {}) => {
1178
+ const opened = openMenu(anchor, { title, items, placement, role: 'menu', ...extra });
1179
+ shown = opened ? { opened, items } : null;
1180
+ return opened;
1181
+ }, { anchor, restoreFocus });
1182
+ if (warm && shown) {
1183
+ ensureLoaded(brain.provider).then(() => {
1184
+ if (destroyed || !shown || currentMenu() !== shown.opened.el || !anchor.isConnected) return;
1185
+ let fresh = null;
1186
+ drawField(field, currentBrain(), (_title, items) => { fresh = items; return null; }, { anchor, restoreFocus });
1187
+ if (fresh && menuItemsSignature(fresh) !== menuItemsSignature(shown.items)) shown.opened.update({ items: fresh, keepPlace: true });
1188
+ }).catch(() => {});
1189
+ }
1190
+ }
1042
1191
 
1192
+ // The menu of one field, from the lists as they are kept now: `menu(title, items, extra)` opens it (or, for a
1193
+ // redraw, only takes the items).
1194
+ function drawField(field, brain, menu, { anchor, restoreFocus = false } = {}) {
1043
1195
  if (field === 'effort') {
1044
1196
  if (brain.provider === 'opencode') {
1045
1197
  const agents = getCachedOpencodeAgents();
@@ -1070,13 +1222,6 @@ export function createBrainPicker(host, hooks = {}) {
1070
1222
  return;
1071
1223
  }
1072
1224
 
1073
- if (field === 'account') {
1074
- if (!ACCOUNT_PROVIDERS.has(brain.provider)) return;
1075
- // Kept inside the panel that holds the anchor (the sidepanel, or the tab's own root).
1076
- openAccountMenu(anchor, accountMenu(brain, anchor.closest?.('.assistant-panel') || anchor.closest?.('.asst-root') || null));
1077
- return;
1078
- }
1079
-
1080
1225
  if (field === 'project') {
1081
1226
  const actor = anchor === heroProject ? heroProjectMascot : null;
1082
1227
  const pick = project => {
@@ -1093,21 +1238,6 @@ export function createBrainPicker(host, hooks = {}) {
1093
1238
  return;
1094
1239
  }
1095
1240
 
1096
- if (field === 'mcp') {
1097
- const presets = getCachedMcpProfilePresets();
1098
- const items = Object.entries(presets).map(([id, preset]) => ({
1099
- kind: 'radio',
1100
- id,
1101
- label: preset?.label || id,
1102
- desc: preset?.description || '',
1103
- tag: preset?.tools != null ? `${preset.tools} ${t('assistant.brain.tools', 'tools')}` : '',
1104
- selected: id === brain.mcpProfile,
1105
- onSelect: () => commit({ mcpProfile: id }, 'mcp'),
1106
- }));
1107
- menu(t('assistant.brain.mcp', 'MCP tool profile'), items);
1108
- return;
1109
- }
1110
-
1111
1241
  if (field === 'mode') {
1112
1242
  const modes = PERMISSION_MODES[brain.provider] || PERMISSION_MODES['claude-code'];
1113
1243
  // Plan mode is its own switch: it combines with every approval mode below.
@@ -1204,15 +1334,14 @@ export function createBrainPicker(host, hooks = {}) {
1204
1334
  if (provider === before.provider) return;
1205
1335
  await ensureLoaded(provider);
1206
1336
  if (destroyed) return;
1207
- const draft = { ...before, provider, model: model || '', effort: null, agent: null, accountId: null };
1337
+ const draft = { ...before, provider, model: model || '', effort: null, agent: null, accountId: null, tools: null };
1208
1338
  // resolveBrainDefaults reads the new provider's catalog.
1209
1339
  const next = resolveBrainDefaults(draft, {
1210
1340
  models: { [provider]: resolvableModels(provider, draft.model) },
1211
1341
  efforts: { [provider]: effortsFor(normalizeBrain(draft)) },
1212
1342
  accounts: { 'claude-code': getCachedClaudeAccounts(), codex: getCachedCodexAccounts() },
1213
1343
  agents: getCachedOpencodeAgents(),
1214
- mcpProfiles: getCachedMcpProfilePresets(),
1215
- defaultMcpProfile: 'full',
1344
+ toolCatalog: getCachedToolCatalog(),
1216
1345
  projects: _projectsCache || [],
1217
1346
  });
1218
1347
  if (model && !next.model) next.model = model;
@@ -1245,6 +1374,6 @@ export function createBrainPicker(host, hooks = {}) {
1245
1374
  mountEmptyProject,
1246
1375
  setBrain() { render(); },
1247
1376
  close: closeMenu,
1248
- destroy() { destroyed = true; fitObserver?.disconnect(); if (fitFrame && typeof cancelAnimationFrame === 'function') cancelAnimationFrame(fitFrame); for (const off of offAccounts) { try { off?.(); } catch {} } closeMenu(); heroProjectMascot?.destroy(); Object.values(buttons).forEach((b) => b.remove()); heroProject?.remove(); heroProject = null; root.remove(); },
1377
+ destroy() { toolsLife.abort(); toolsSlot.remove(); destroyed = true; fitObserver?.disconnect(); if (fitFrame && typeof cancelAnimationFrame === 'function') cancelAnimationFrame(fitFrame); for (const off of offAccounts) { try { off?.(); } catch {} } closeMenu(); heroProjectMascot?.destroy(); Object.values(buttons).forEach((b) => b.remove()); heroProject?.remove(); heroProject = null; root.remove(); },
1249
1378
  };
1250
1379
  }
@@ -204,7 +204,7 @@ export function createComposer(hostEl, hooks = {}) {
204
204
  function renderAttachments() {
205
205
  const chips = [];
206
206
  state.images.forEach((img, i) => {
207
- chips.push(`<span class="asst-chip static" data-kind="image" data-idx="${i}"><img src="data:${esc(img.mediaType)};base64,${img.base64}" alt=""><span class="asst-chip-text">${esc(img.name || 'image')}</span><button type="button" class="asst-chip-x" aria-label="${esc(t('common.remove', 'Remove'))}">${ICON_X}</button></span>`);
207
+ chips.push(`<span class="asst-chip static" data-kind="image" data-idx="${i}"><img src="data:${esc(img.mediaType)};base64,${esc(img.base64)}" alt=""><span class="asst-chip-text">${esc(img.name || 'image')}</span><button type="button" class="asst-chip-x" aria-label="${esc(t('common.remove', 'Remove'))}">${ICON_X}</button></span>`);
208
208
  });
209
209
  state.files.forEach((f, i) => {
210
210
  chips.push(`<span class="asst-chip static" data-kind="file" data-idx="${i}"><span class="asst-chip-text">${esc(f.name)}</span><span class="asst-chip-meta">${esc(Math.ceil(f.content.length / 1024))}k</span><button type="button" class="asst-chip-x" aria-label="${esc(t('common.remove', 'Remove'))}">${ICON_X}</button></span>`);