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
@@ -0,0 +1,457 @@
1
+ /**
2
+ * The tool selection of one MCP server runtime: which SynaBun groups it advertises, and how.
3
+ *
4
+ * strict: the runtime advertises exactly its groups (OpenCode, Gemini, any other stdio client). focus: it
5
+ * advertises every group and its groups only steer the instructions (Claude Code's ToolSearch, Codex's deferred
6
+ * catalog, which Codex snapshots at the start of a turn). Gated groups follow the caller's role and grant in both
7
+ * modes, never a list.
8
+ *
9
+ * Each MCP server owns one ToolRuntime: the HTTP transport keeps several servers in one process, and a
10
+ * module-global selection once made one client's change land on another client's server.
11
+ */
12
+ import type { RegisteredTool } from '@modelcontextprotocol/sdk/server/mcp.js';
13
+ import { existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from 'fs';
14
+ import { basename, dirname, join } from 'path';
15
+ import { config } from '../config.js';
16
+ import { isHttpMode, sanitizeDesktopGrant, sanitizeRole, type CallerRole } from './identity.js';
17
+ import { ALWAYS_ON_TOOLS, SELECTABLE_GROUP_IDS, TOOL_LIST_LIMITS, TOOL_GROUPS, isGatedGroup, isSelectableGroup, sortGroups } from './tool-catalog.js';
18
+ import { parseToolList, resolveToolList, type AddedGroup, type CustomPresets } from './tool-list.js';
19
+
20
+ export type ToolMode = 'strict' | 'focus';
21
+ export type CallerCapability = 'computer';
22
+
23
+ /** The list of this runtime (comma-joined group ids) and the file its tool_groups changes go to. */
24
+ export const TOOLS_ENV = 'SYNABUN_TOOLS';
25
+ export const TOOLS_PATH_ENV = 'SYNABUN_TOOLS_PATH';
26
+ /** deferred / focus: a focus host; profiled / strict: a strict one. */
27
+ export const TOOL_CATALOG_MODE_ENV = 'SYNABUN_TOOL_CATALOG_MODE';
28
+ /** Read as aliases through the legacy conversion (an older Neural Interface, a user's own config.toml or Gemini settings); never written. */
29
+ export const LEGACY_PROFILE_ENV = 'SYNABUN_PROFILE';
30
+ export const LEGACY_RUNTIME_PROFILE_PATH_ENV = 'SYNABUN_RUNTIME_PROFILE_PATH';
31
+
32
+ /** The owner's Default tools: Settings and `synabun tools set` write it; a runtime reads it when it starts, never later. */
33
+ export const DEFAULT_TOOLS_PATH = join(config.dataHome, 'data', 'default-tools.json');
34
+ const LEGACY_DEFAULT_PROFILE_PATHS = [join(config.dataDir, 'active-profile.json'), join(config.dataHome, 'data', 'active-profile.json')];
35
+ const REGISTRY_PATH = join(config.dataHome, 'data', 'mcp-registry.json');
36
+
37
+ /** Groups only a caller with this role sees: the role decides, so no list can reveal or hide them. */
38
+ export const ROLE_GATED_GROUPS: Readonly<Record<string, CallerRole>> = Object.freeze(Object.fromEntries(
39
+ TOOL_GROUPS.filter((group) => group.gate === 'role:assistant').map((group) => [group.id, 'assistant' as const]),
40
+ ));
41
+ /** Groups a capability the caller proves unlocks: `computer` needs a desktop grant (and macOS). */
42
+ export const CAPABILITY_GATED_GROUPS: Readonly<Record<string, CallerCapability>> = Object.freeze(Object.fromEntries(
43
+ TOOL_GROUPS.filter((group) => group.gate === 'grant:computer').map((group) => [group.id, 'computer' as const]),
44
+ ));
45
+
46
+ export function isRoleGatedGroup(group: string): boolean {
47
+ return Object.prototype.hasOwnProperty.call(ROLE_GATED_GROUPS, group);
48
+ }
49
+
50
+ export function isCapabilityGatedGroup(group: string): boolean {
51
+ return Object.prototype.hasOwnProperty.call(CAPABILITY_GATED_GROUPS, group);
52
+ }
53
+
54
+ /** Where a runtime's selection came from (tool_groups get shows it). */
55
+ export type ToolSelectionSource =
56
+ | 'tools-file' | 'tools-env' | 'legacy-runtime-file' | 'claude-code' | 'legacy-profile-env'
57
+ | 'default-tools' | 'legacy-default' | 'all' | 'http' | 'header' | 'channel' | 'explicit' | 'tool_groups';
58
+
59
+ export interface ToolSelection {
60
+ /** Selectable groups, catalog order. */
61
+ groups: string[];
62
+ mode: ToolMode;
63
+ /** The host's own mode, when a list that could not be read made this selection strict. */
64
+ hostMode?: ToolMode;
65
+ /** Why the list could not be read: the runtime then has its always-on and gated tools only. */
66
+ listError: string | null;
67
+ source: ToolSelectionSource;
68
+ /** Groups the runtime got without naming them (browser for a browser group). */
69
+ added: AddedGroup[];
70
+ }
71
+
72
+ const SOURCE_NAMES: Partial<Record<ToolSelectionSource, string>> = {
73
+ 'tools-file': 'SYNABUN_TOOLS_PATH',
74
+ 'tools-env': 'SYNABUN_TOOLS',
75
+ 'legacy-runtime-file': 'SYNABUN_RUNTIME_PROFILE_PATH',
76
+ 'legacy-profile-env': 'SYNABUN_PROFILE',
77
+ 'default-tools': 'default-tools.json',
78
+ 'legacy-default': 'active-profile.json',
79
+ header: 'X-Synabun-Tools',
80
+ channel: 'the worker channel',
81
+ };
82
+
83
+ /** The selection of a host's own list, with its host mode. */
84
+ export function selectionOf(groups: readonly string[], mode: ToolMode, source: ToolSelectionSource, added: AddedGroup[] = []): ToolSelection {
85
+ return { groups: sortGroups(groups).filter(isSelectableGroup), mode, listError: null, source, added };
86
+ }
87
+
88
+ /** What a list that could not be read leaves: memory tools only (and the gated ones), strict until tool_groups succeeds. */
89
+ export function unreadableSelection(source: ToolSelectionSource, reason: string, hostMode: ToolMode): ToolSelection {
90
+ const name = SOURCE_NAMES[source];
91
+ return { groups: [], mode: 'strict', hostMode, listError: name ? `${name}: ${reason}` : reason, source, added: [] };
92
+ }
93
+
94
+ export function isClaudeCode(env: NodeJS.ProcessEnv = process.env): boolean {
95
+ return env.CLAUDECODE === '1';
96
+ }
97
+
98
+ /** focus for Codex (SYNABUN_TOOL_CATALOG_MODE=deferred, or a managed Codex sidepanel), strict otherwise. */
99
+ export function readHostMode(env: NodeJS.ProcessEnv = process.env): ToolMode {
100
+ const configured = String(env[TOOL_CATALOG_MODE_ENV] || '').trim().toLowerCase();
101
+ if (configured === 'deferred' || configured === 'focus') return 'focus';
102
+ if (configured === 'profiled' || configured === 'strict') return 'strict';
103
+ // Managed Codex sidepanels have always used this runtime prefix: one spawned before its launch environment
104
+ // named the catalog mode is a focus host all the same.
105
+ if (/^codex-sp-/.test(String(env.SYNABUN_TERMINAL_SESSION || ''))) return 'focus';
106
+ return 'strict';
107
+ }
108
+
109
+ const loggedProblems = new Set<string>();
110
+ function logOnce(message: string): void {
111
+ if (loggedProblems.has(message)) return;
112
+ loggedProblems.add(message);
113
+ console.error(`[SynaBun] ${message}`);
114
+ }
115
+
116
+ /** The registry's presets, read only to convert a stored profile name. */
117
+ export function readCustomPresets(): CustomPresets | null {
118
+ try {
119
+ if (!existsSync(REGISTRY_PATH)) return null;
120
+ const registry = JSON.parse(readFileSync(REGISTRY_PATH, 'utf-8'));
121
+ const profiles = registry?.profiles;
122
+ return profiles && typeof profiles === 'object' && !Array.isArray(profiles) ? profiles as CustomPresets : null;
123
+ } catch (err) {
124
+ logOnce(`Could not read the MCP registry for stored profile names: ${err instanceof Error ? err.message : String(err)}`);
125
+ return null;
126
+ }
127
+ }
128
+
129
+ function fromList(value: unknown, source: ToolSelectionSource, hostMode: ToolMode, legacy: boolean): ToolSelection {
130
+ const parsed = parseToolList(value, legacy ? { legacy: true, customPresets: readCustomPresets() } : {});
131
+ if (!parsed.ok) return unreadableSelection(source, parsed.message, hostMode);
132
+ const resolved = resolveToolList(parsed.items, { source: 'runtime' });
133
+ if (!resolved.ok) return unreadableSelection(source, resolved.message, hostMode);
134
+ return selectionOf(resolved.groups, hostMode, source, resolved.added);
135
+ }
136
+
137
+ /**
138
+ * The selection of a list given in code or by a request (a header, the worker channel), resolved like a runtime's
139
+ * own: `all` expanded, a browser group's `browser` added. One that cannot be read is memory tools only, strict.
140
+ */
141
+ export function selectionFromList(value: unknown, mode: ToolMode, source: ToolSelectionSource, { legacy = false }: { legacy?: boolean } = {}): ToolSelection {
142
+ return fromList(value, source, mode, legacy);
143
+ }
144
+
145
+ /** A runtime file holds `{ "tools": [...] }`; one an older Neural Interface wrote holds `{ "profile": "..." }`. */
146
+ function fromFile(path: string | undefined, source: ToolSelectionSource, hostMode: ToolMode): ToolSelection | null {
147
+ const file = String(path || '').trim();
148
+ if (!file) return null;
149
+ let text: string;
150
+ try {
151
+ if (!existsSync(file)) return null;
152
+ text = readFileSync(file, 'utf-8');
153
+ } catch (err) {
154
+ return unreadableSelection(source, `${basename(file)} could not be read (${err instanceof Error ? err.message : String(err)})`, hostMode);
155
+ }
156
+ let data: unknown;
157
+ try {
158
+ data = JSON.parse(text);
159
+ } catch {
160
+ return unreadableSelection(source, `${basename(file)} is not JSON`, hostMode);
161
+ }
162
+ const record = data && typeof data === 'object' && !Array.isArray(data) ? data as Record<string, unknown> : null;
163
+ if (record && Array.isArray(record.tools)) return fromList(record.tools, source, hostMode, false);
164
+ if (record && typeof record.profile === 'string') return fromList(record.profile, source, hostMode, true);
165
+ return unreadableSelection(source, `${basename(file)} names no tools`, hostMode);
166
+ }
167
+
168
+ function fromEnv(value: string | undefined, source: ToolSelectionSource, hostMode: ToolMode, legacy: boolean): ToolSelection | null {
169
+ if (value === undefined || !value.trim()) return null;
170
+ return fromList(value, source, hostMode, legacy);
171
+ }
172
+
173
+ /**
174
+ * The selection a runtime starts with, the first of: its runtime file (SYNABUN_TOOLS_PATH), its list
175
+ * (SYNABUN_TOOLS), the runtime file of an older Neural Interface (SYNABUN_RUNTIME_PROFILE_PATH), Claude Code
176
+ * (CLAUDECODE=1: focus on every group), the old SYNABUN_PROFILE, the owner's Default tools, the old
177
+ * active-profile.json, every group. The runtime's own pins come before CLAUDECODE, so a strict runtime that
178
+ * inherited it from a parent shell keeps its list. A list that cannot be read is not skipped: the runtime starts
179
+ * with memory tools only and says why (fail closed, never every group).
180
+ */
181
+ export function readInitialTools(env: NodeJS.ProcessEnv = process.env): ToolSelection {
182
+ const hostMode = readHostMode(env);
183
+ const steps: Array<() => ToolSelection | null> = [
184
+ () => fromFile(env[TOOLS_PATH_ENV], 'tools-file', hostMode),
185
+ () => fromEnv(env[TOOLS_ENV], 'tools-env', hostMode, false),
186
+ () => fromFile(env[LEGACY_RUNTIME_PROFILE_PATH_ENV], 'legacy-runtime-file', hostMode),
187
+ () => (isClaudeCode(env) ? selectionOf(SELECTABLE_GROUP_IDS, 'focus', 'claude-code') : null),
188
+ () => fromEnv(env[LEGACY_PROFILE_ENV], 'legacy-profile-env', hostMode, true),
189
+ () => fromFile(DEFAULT_TOOLS_PATH, 'default-tools', hostMode),
190
+ () => {
191
+ for (const path of LEGACY_DEFAULT_PROFILE_PATHS) {
192
+ const selection = fromFile(path, 'legacy-default', hostMode);
193
+ if (selection) return selection;
194
+ }
195
+ return null;
196
+ },
197
+ ];
198
+ for (const step of steps) {
199
+ const selection = step();
200
+ if (!selection) continue;
201
+ if (selection.listError) logOnce(`Could not read this runtime's tool list (${selection.listError}); only memory tools are loaded.`);
202
+ return selection;
203
+ }
204
+ return selectionOf(SELECTABLE_GROUP_IDS, hostMode, 'all');
205
+ }
206
+
207
+ /**
208
+ * The value an older Neural Interface's /api/mcp/runtime-profile and runtime file understand for these groups: a
209
+ * comma list (every selectable id is one of its group names), or its always-on pseudo-group `memory` for none.
210
+ */
211
+ export function legacyProfileValue(groups: readonly string[]): string {
212
+ const ids = sortGroups(groups).filter(isSelectableGroup);
213
+ return ids.length ? ids.join(',') : 'memory';
214
+ }
215
+
216
+ function writeJsonFile(path: string, value: unknown): boolean {
217
+ const temp = `${path}.synabun-${process.pid}-${Date.now()}.tmp`;
218
+ try {
219
+ const dir = dirname(path);
220
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
221
+ writeFileSync(temp, JSON.stringify(value, null, 2) + '\n', 'utf-8');
222
+ renameSync(temp, path);
223
+ return true;
224
+ } catch (err) {
225
+ try { unlinkSync(temp); } catch { /* never written */ }
226
+ console.error(`[SynaBun] Failed to save this runtime's tools at ${path}:`, err);
227
+ return false;
228
+ }
229
+ }
230
+
231
+ /**
232
+ * Save this runtime's groups where a restarted child of the same runtime reads them, never the shared default.
233
+ * Over HTTP there is no such file: process.env is the Neural Interface's own, not a caller's.
234
+ */
235
+ export function runtimeToolsWithExternalRefs(groups: readonly string[]): string[] {
236
+ const tools = sortGroups(groups).filter(isSelectableGroup);
237
+ if (isHttpMode()) return tools; // HTTP identity belongs to the request; NI preserves the outer run's refs.
238
+ const path = String(process.env[TOOLS_PATH_ENV] || process.env[LEGACY_RUNTIME_PROFILE_PATH_ENV] || '').trim();
239
+ let previous: unknown = process.env[TOOLS_ENV] || '';
240
+ try { if (path && existsSync(path)) previous = JSON.parse(readFileSync(path, 'utf8')).tools ?? previous; } catch { /* launch env remains the fallback */ }
241
+ const parsed = parseToolList(previous);
242
+ const refs = parsed.ok ? parsed.items.filter(item => item.startsWith('mcp:')) : [];
243
+ const compact = tools.length + refs.length > TOOL_LIST_LIMITS.maxItems && SELECTABLE_GROUP_IDS.every(id => tools.includes(id));
244
+ return [...(compact ? ['all'] : tools), ...refs];
245
+ }
246
+ export function persistRuntimeTools(groups: readonly string[]): 'tools-file' | 'legacy-runtime-file' | null {
247
+ if (isHttpMode()) return null;
248
+ const tools = runtimeToolsWithExternalRefs(groups);
249
+ const toolsPath = String(process.env[TOOLS_PATH_ENV] || '').trim();
250
+ if (toolsPath) return writeJsonFile(toolsPath, { tools, updatedAt: new Date().toISOString() }) ? 'tools-file' : null;
251
+ const legacyPath = String(process.env[LEGACY_RUNTIME_PROFILE_PATH_ENV] || '').trim();
252
+ if (legacyPath) return writeJsonFile(legacyPath, { profile: legacyProfileValue(groups), tools }) ? 'legacy-runtime-file' : null;
253
+ return null;
254
+ }
255
+
256
+ export function logCodexConfigNoticeOnce(): void {
257
+ logOnce(
258
+ 'Changing this runtime\'s tools never rewrites ~/.codex/config.toml: the canonical Codex registration loads every '
259
+ + 'SynaBun tool (SYNABUN_TOOLS=all, deferred catalog) and a tool list only sets a Codex runtime\'s focus.',
260
+ );
261
+ }
262
+
263
+ export interface ToolApplyResult {
264
+ groups: string[];
265
+ /** The groups the instructions name: the selection plus the gated groups the role and grant unlock. */
266
+ activeGroups: string[];
267
+ /** Groups that became active, and groups that stopped being active. */
268
+ enabled: string[];
269
+ disabled: string[];
270
+ added: AddedGroup[];
271
+ /** Tools this server advertises now. */
272
+ totalTools: number;
273
+ changed: boolean;
274
+ /** Whether any tool appeared in or left the host's tool list. */
275
+ advertisedChanged: boolean;
276
+ mode: ToolMode;
277
+ listError: string | null;
278
+ }
279
+
280
+ export interface ToolRuntimeOptions {
281
+ role?: CallerRole | null;
282
+ capabilities?: CallerCapability[] | null;
283
+ platform?: string;
284
+ }
285
+
286
+ function sameList(a: readonly string[], b: readonly string[]): boolean {
287
+ return a.length === b.length && a.every((item, index) => item === b[index]);
288
+ }
289
+
290
+ export class ToolRuntime {
291
+ private groups: string[];
292
+ private mode: ToolMode;
293
+ private hostMode: ToolMode;
294
+ private listError: string | null;
295
+ private source: ToolSelectionSource;
296
+ private added: AddedGroup[];
297
+ private role: CallerRole | null;
298
+ private capabilities: Set<CallerCapability>;
299
+ private readonly platform: string;
300
+ private activeGroups: Set<string>;
301
+ private readonly toolGroups = new Map<string, RegisteredTool[]>();
302
+ private ungroupedTools: number = ALWAYS_ON_TOOLS.length;
303
+ private onToolsChanged: (() => void | Promise<void>) | null = null;
304
+ private notificationTimer: ReturnType<typeof setTimeout> | null = null;
305
+
306
+ constructor(selection: ToolSelection = readInitialTools(), options: ToolRuntimeOptions = {}) {
307
+ // stdio children of the Codex/OpenCode assistant brains receive the role through their launch env; HTTP
308
+ // sessions bind it later (setRole). The desktop grant the same way (setCapabilities).
309
+ this.role = options.role !== undefined ? options.role : sanitizeRole(process.env.SYNABUN_ROLE);
310
+ this.capabilities = new Set(options.capabilities ?? (sanitizeDesktopGrant(process.env.SYNABUN_DESKTOP_GRANT) ? ['computer'] : []));
311
+ this.platform = options.platform || process.platform;
312
+ this.groups = sortGroups(selection.groups).filter(isSelectableGroup);
313
+ this.mode = selection.mode;
314
+ this.hostMode = selection.hostMode ?? selection.mode;
315
+ this.listError = selection.listError ?? null;
316
+ this.source = selection.source;
317
+ this.added = [...(selection.added || [])];
318
+ this.activeGroups = this.resolveActive(this.groups);
319
+ }
320
+
321
+ getGroups(): string[] { return [...this.groups]; }
322
+ /** The groups the instructions name: the selection plus the gated groups the role and grant unlock. */
323
+ getActiveGroups(): Set<string> { return this.activeGroups; }
324
+ getMode(): ToolMode { return this.mode; }
325
+ /** The mode the host has once its list reads: focus for Codex and Claude Code, strict otherwise. */
326
+ getHostMode(): ToolMode { return this.hostMode; }
327
+ getListError(): string | null { return this.listError; }
328
+ getSource(): ToolSelectionSource { return this.source; }
329
+ getAdded(): AddedGroup[] { return [...this.added]; }
330
+ getRole(): CallerRole | null { return this.role; }
331
+ getCapabilities(): CallerCapability[] { return [...this.capabilities]; }
332
+
333
+ getSelection(): ToolSelection {
334
+ return { groups: this.getGroups(), mode: this.mode, hostMode: this.hostMode, listError: this.listError, source: this.source, added: this.getAdded() };
335
+ }
336
+
337
+ /** Plain setter: callers apply() afterwards so the gated groups follow (index.ts setServerRole does both). */
338
+ setRole(role: CallerRole | null): void { this.role = role; }
339
+ /** Plain setter, like setRole. */
340
+ setCapabilities(capabilities: CallerCapability[]): void { this.capabilities = new Set(capabilities); }
341
+
342
+ setToolGroup(name: string, tools: RegisteredTool[]): void {
343
+ this.toolGroups.set(name, tools);
344
+ }
345
+
346
+ /** How many registered tools sit outside every group (the always-on tools, and any compatibility name). */
347
+ setUngroupedToolCount(count: number): void {
348
+ this.ungroupedTools = count;
349
+ }
350
+
351
+ setOnToolsChanged(fn: (() => void | Promise<void>) | null): void {
352
+ this.onToolsChanged = fn;
353
+ }
354
+
355
+ // HTTP clients can refresh over their open notification stream without destroying an in-flight call.
356
+ private inBandRefresh: (() => Promise<boolean>) | null = null;
357
+ setInBandRefresh(fn: () => Promise<boolean>): void { this.inBandRefresh = fn; }
358
+ hasInBandRefresh(): boolean { return !!this.inBandRefresh; }
359
+ refreshBeforeReply(): Promise<boolean> { return this.inBandRefresh?.() ?? Promise.resolve(false); }
360
+
361
+ dispose(): void {
362
+ if (this.notificationTimer) clearTimeout(this.notificationTimer);
363
+ this.notificationTimer = null;
364
+ this.onToolsChanged = null;
365
+ this.inBandRefresh = null;
366
+ }
367
+
368
+ /**
369
+ * Coalesce one delayed tools/list_changed. The delay matters: OpenCode used to get the notification while the
370
+ * tool call that caused it was still in flight, and could abort or cache the old tool round trip.
371
+ */
372
+ scheduleToolsChangedNotification(delayMs = 10): boolean {
373
+ if (!this.onToolsChanged) return false;
374
+ if (this.notificationTimer) clearTimeout(this.notificationTimer);
375
+ this.notificationTimer = setTimeout(() => {
376
+ this.notificationTimer = null;
377
+ try {
378
+ void Promise.resolve(this.onToolsChanged?.()).catch((err) => {
379
+ console.error('[SynaBun] tools/list_changed notifier failed:', err);
380
+ });
381
+ } catch (err) {
382
+ console.error('[SynaBun] tools/list_changed notifier failed:', err);
383
+ }
384
+ }, Math.max(0, delayMs));
385
+ this.notificationTimer.unref?.();
386
+ return true;
387
+ }
388
+
389
+ /** The selection with the gates applied: a gated group is active iff this runtime's role or grant unlocks it. */
390
+ private resolveActive(groups: readonly string[]): Set<string> {
391
+ const active = new Set(groups.filter(isSelectableGroup));
392
+ for (const [group, role] of Object.entries(ROLE_GATED_GROUPS)) if (this.role === role) active.add(group);
393
+ for (const [group, capability] of Object.entries(CAPABILITY_GATED_GROUPS)) {
394
+ if (this.capabilities.has(capability) && (capability !== 'computer' || this.platform === 'darwin')) active.add(group);
395
+ }
396
+ return active;
397
+ }
398
+
399
+ /** Tools this server advertises: the ones outside every group and each group's enabled tools. */
400
+ getAdvertisedToolCount(): number {
401
+ let total = this.ungroupedTools;
402
+ for (const tools of this.toolGroups.values()) total += tools.filter((tool) => tool.enabled).length;
403
+ return total;
404
+ }
405
+
406
+ /**
407
+ * Apply a new selection (or re-apply the current one after a role or grant change). Tools are flipped directly:
408
+ * RegisteredTool.enable()/disable() would each send a notification, and the caller sends one after its answer.
409
+ */
410
+ apply(next: Partial<ToolSelection> = {}): ToolApplyResult {
411
+ const groups = next.groups ? sortGroups(next.groups).filter(isSelectableGroup) : this.groups;
412
+ const mode = next.mode ?? this.mode;
413
+ const listError = next.listError !== undefined ? next.listError : this.listError;
414
+ const previous = { groups: this.groups, mode: this.mode, listError: this.listError, active: this.activeGroups };
415
+ const active = this.resolveActive(groups);
416
+
417
+ let advertisedChanged = false;
418
+ for (const [group, tools] of this.toolGroups) {
419
+ // A gated group ignores the mode: a focus host gets every other group up front, never one its role or grant does not unlock.
420
+ const advertise = isGatedGroup(group) ? active.has(group) : mode === 'focus' || active.has(group);
421
+ for (const tool of tools) {
422
+ if (tool.enabled === advertise) continue;
423
+ tool.enabled = advertise;
424
+ advertisedChanged = true;
425
+ }
426
+ }
427
+
428
+ const enabled = sortGroups([...active].filter((group) => !previous.active.has(group)));
429
+ const disabled = sortGroups([...previous.active].filter((group) => !active.has(group)));
430
+ this.groups = groups;
431
+ this.mode = mode;
432
+ this.listError = listError;
433
+ this.activeGroups = active;
434
+ if (next.hostMode) this.hostMode = next.hostMode;
435
+ if (next.source) this.source = next.source;
436
+ if (next.added) this.added = [...next.added];
437
+
438
+ const totalTools = this.getAdvertisedToolCount();
439
+ const changed = enabled.length > 0 || disabled.length > 0 || previous.mode !== mode
440
+ || previous.listError !== listError || !sameList(previous.groups, groups);
441
+ if (changed) {
442
+ console.error(`[SynaBun] Tools (${mode}): ${groups.join(',') || 'memory only'} (${totalTools} tools, +${enabled.join(',') || 'none'}, -${disabled.join(',') || 'none'})`);
443
+ }
444
+ return {
445
+ groups: [...groups],
446
+ activeGroups: sortGroups(active),
447
+ enabled,
448
+ disabled,
449
+ added: [...this.added],
450
+ totalTools,
451
+ changed,
452
+ advertisedChanged,
453
+ mode,
454
+ listError,
455
+ };
456
+ }
457
+ }
@@ -28,7 +28,7 @@ export interface WbRect { x: number; y: number; width: number; height: number }
28
28
  /** Persisted whiteboard element — the union of every element type's fields. */
29
29
  export interface WbElement {
30
30
  id: string; type: string; x?: number; y?: number; width?: number; height?: number;
31
- content?: string; items?: string[]; ordered?: boolean; fontSize?: number; color?: string;
31
+ content?: string; items?: string[]; levels?: number[]; ordered?: boolean; fontSize?: number; color?: string;
32
32
  bold?: boolean; italic?: boolean; shape?: string; points?: WbPoint[]; pathD?: string;
33
33
  startAnchor?: string | null; endAnchor?: string | null; strokeWidth?: number; rotation?: number;
34
34
  zIndex?: number; dataUrl?: string; dataUrlBytes?: number; url?: string; sectionType?: string; label?: string;
@@ -145,8 +145,91 @@ function contentString(v: unknown): string | undefined {
145
145
  return v == null ? undefined : String(v);
146
146
  }
147
147
 
148
- function itemStrings(v: unknown): string[] | undefined {
149
- return Array.isArray(v) ? v.map(item => (typeof item === 'string' ? item : String(item ?? ''))) : undefined;
148
+ // ── List nesting ──
149
+ // A list stores `items: string[]` and, only while some item is nested, `levels: number[]` beside them (levels[i]
150
+ // is the depth of items[i], 0 = top level; no `levels` = all 0, so older boards read unchanged). Callers may send
151
+ // items as { text, level } objects. Rules: the first item is level 0, an item is at most one level deeper than
152
+ // the item above it, no item is deeper than LIST_MAX_LEVEL. The browser and server.js read the same format
153
+ // through neural-interface/public/shared/whiteboard-list.js; keep the two on the same rules.
154
+
155
+ /** Deepest list level (the client's WB_LIST_MAX_LEVEL). */
156
+ export const LIST_MAX_LEVEL = 4;
157
+
158
+ /** One list item as a caller may send it: a plain string (level 0) or { text, level }. */
159
+ export type WbListItemInput = string | { text: string; level?: number };
160
+
161
+ function listItemText(item: unknown): string {
162
+ if (typeof item === 'string') return item;
163
+ if (item && typeof item === 'object') {
164
+ const t = (item as { text?: unknown }).text;
165
+ return t == null ? '' : String(t);
166
+ }
167
+ return item == null ? '' : String(item);
168
+ }
169
+
170
+ function listLevelOf(value: unknown): number {
171
+ const n = Math.floor(Number(value));
172
+ return Number.isFinite(n) && n > 0 ? Math.min(n, LIST_MAX_LEVEL) : 0;
173
+ }
174
+
175
+ /**
176
+ * A list's items in either form -> `{ items, levels }` that keep the nesting rules (levels as long as items).
177
+ * A plain string takes `levels[i]` (0 without one); a { text, level } object's own level wins.
178
+ */
179
+ export function normalizeListItems(items: unknown, levels?: unknown): { items: string[]; levels: number[] } {
180
+ const list = Array.isArray(items) ? items : [];
181
+ const given = Array.isArray(levels) ? levels : [];
182
+ const out: number[] = [];
183
+ let above = -1;
184
+ list.forEach((item, i) => {
185
+ const own = item && typeof item === 'object' ? (item as { level?: unknown }).level : undefined;
186
+ const level = Math.min(listLevelOf(own !== undefined ? own : given[i]), above + 1);
187
+ out.push(level);
188
+ above = level;
189
+ });
190
+ return { items: list.map(listItemText), levels: out };
191
+ }
192
+
193
+ /** True when some item of the list is nested (only then is `levels` stored). */
194
+ export function hasNestedLevels(levels: readonly number[] | undefined): boolean {
195
+ return Array.isArray(levels) && levels.some(level => level > 0);
196
+ }
197
+
198
+ /**
199
+ * The marker before each list item: a bullet per level (disc, circle, square, cycling) or the item's number in
200
+ * its level's style (1, a, i, cycling) with ".". Numbering restarts under every item above, as in the browser.
201
+ */
202
+ export function listMarkers(levels: readonly number[], ordered: boolean): string[] {
203
+ const bullets = ['•', '◦', '▪'];
204
+ const counters: number[] = [];
205
+ return levels.map((raw) => {
206
+ const level = listLevelOf(raw);
207
+ if (!ordered) return bullets[level % 3];
208
+ counters.length = level + 1;
209
+ counters[level] = (counters[level] || 0) + 1;
210
+ const n = counters[level];
211
+ const style = level % 3;
212
+ return `${style === 1 ? alphaCounter(n) : style === 2 ? romanCounter(n) : String(n)}.`;
213
+ });
214
+ }
215
+
216
+ function alphaCounter(n: number): string {
217
+ let out = '';
218
+ while (n > 0) { n -= 1; out = String.fromCharCode(97 + (n % 26)) + out; n = Math.floor(n / 26); }
219
+ return out;
220
+ }
221
+
222
+ function romanCounter(n: number): string {
223
+ const table: [number, string][] = [[1000, 'm'], [900, 'cm'], [500, 'd'], [400, 'cd'], [100, 'c'], [90, 'xc'], [50, 'l'], [40, 'xl'], [10, 'x'], [9, 'ix'], [5, 'v'], [4, 'iv'], [1, 'i']];
224
+ let out = '';
225
+ for (const [value, digits] of table) while (n >= value) { out += digits; n -= value; }
226
+ return out;
227
+ }
228
+
229
+ /** Size estimate of a list element from its stored items and levels. */
230
+ function estimateListElement(el: WbElement): { width: number; height: number } {
231
+ const list = normalizeListItems(el.items, el.levels);
232
+ return estimateListSize(Array.isArray(el.items) ? list.items : undefined, positiveDim(el.fontSize) ?? 18, list.levels);
150
233
  }
151
234
 
152
235
  /** Stored size, or the type's fallback when a dimension is missing (see `elementBox`). */
@@ -160,7 +243,7 @@ function storedOrDefaultSize(el: WbElement): { width: number; height: number } {
160
243
  return { width: w ?? est.width, height: h ?? est.height };
161
244
  }
162
245
  case 'list': {
163
- const est = estimateListSize(itemStrings(el.items), positiveDim(el.fontSize) ?? 18);
246
+ const est = estimateListElement(el);
164
247
  return { width: w ?? est.width, height: h ?? est.height };
165
248
  }
166
249
  case 'shape':
@@ -240,14 +323,16 @@ export function estimateTextSize(content: string | undefined, fontSize = 22): {
240
323
 
241
324
  /**
242
325
  * Estimate the rendered size of a list element before the browser measures it.
243
- * Same font metrics as text, plus the 1.4em bullet indent; line-height 1.5.
326
+ * Same font metrics as text, plus the 1.4em bullet indent and 1.4em more per
327
+ * nesting level (`levels[i]`, 0 when missing); line-height 1.5.
244
328
  */
245
- export function estimateListSize(items: string[] | undefined, fontSize = 18): { width: number; height: number } {
329
+ export function estimateListSize(items: string[] | undefined, fontSize = 18, levels?: readonly number[]): { width: number; height: number } {
246
330
  const list = items ?? [];
247
331
  const rows = Math.max(1, list.length);
248
- const maxChars = list.length ? Math.max(...list.map(codePointLength)) : 0;
332
+ const indents = list.map((item, i) => codePointLength(item) * 0.6 + (1 + listLevelOf(levels?.[i])) * 1.4);
333
+ const widest = list.length ? Math.max(...indents) : 1.4;
249
334
  return {
250
- width: Math.max(120, Math.round(maxChars * fontSize * 0.6 + 1.4 * fontSize + 30)),
335
+ width: Math.max(120, Math.round(widest * fontSize + 30)),
251
336
  height: Math.max(30, Math.round(rows * fontSize * 1.5 + 22)),
252
337
  };
253
338
  }
@@ -277,7 +362,7 @@ export function ensureElementGeometry(el: WbElement, opts: { force?: boolean } =
277
362
  if (force || el.measured !== true || missing) {
278
363
  const size = el.type === 'text'
279
364
  ? estimateTextSize(contentString(el.content), positiveDim(el.fontSize) ?? 22)
280
- : estimateListSize(itemStrings(el.items), positiveDim(el.fontSize) ?? 18);
365
+ : estimateListElement(el);
281
366
  el.width = size.width;
282
367
  el.height = size.height;
283
368
  el.estimated = true;