synabun 2.0.10 → 2.2.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 (656) hide show
  1. package/CHANGELOG.md +207 -0
  2. package/README.md +25 -2
  3. package/THIRD-PARTY-LICENSES.md +22 -0
  4. package/bin/synabun.js +71 -24
  5. package/docs/whatsapp.md +13 -13
  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/lib/claude-hooks.js +172 -18
  10. package/lib/client-config-repair.js +30 -17
  11. package/lib/desktop-app.js +7 -1
  12. package/lib/external-tools.js +7 -6
  13. package/lib/first-launch-protection.js +57 -12
  14. package/lib/mcp-dist.js +176 -0
  15. package/lib/release-npm-ci.mjs +138 -0
  16. package/lib/release-publish.mjs +91 -0
  17. package/lib/release-scan.mjs +50 -0
  18. package/lib/server-crash-record.js +123 -0
  19. package/lib/server-exit.js +318 -0
  20. package/lib/server-supervisor.js +508 -0
  21. package/lib/start-launcher.js +37 -4
  22. package/lib/tools-cli.js +45 -0
  23. package/lib/update-snapshot.js +302 -0
  24. package/lib/virustotal.mjs +203 -0
  25. package/lib/windows-crash-event.js +269 -0
  26. package/mcp-server/dist/http.d.ts +20 -1
  27. package/mcp-server/dist/http.d.ts.map +1 -1
  28. package/mcp-server/dist/http.js +59 -12
  29. package/mcp-server/dist/http.js.map +1 -1
  30. package/mcp-server/dist/index.d.ts +33 -27
  31. package/mcp-server/dist/index.d.ts.map +1 -1
  32. package/mcp-server/dist/index.js +128 -143
  33. package/mcp-server/dist/index.js.map +1 -1
  34. package/mcp-server/dist/preload.js +1 -1
  35. package/mcp-server/dist/preload.js.map +1 -1
  36. package/mcp-server/dist/services/budget-judgments.d.ts +1 -1
  37. package/mcp-server/dist/services/budget-judgments.d.ts.map +1 -1
  38. package/mcp-server/dist/services/budget-judgments.js +5 -3
  39. package/mcp-server/dist/services/budget-judgments.js.map +1 -1
  40. package/mcp-server/dist/services/codex-config-heal.d.ts +6 -2
  41. package/mcp-server/dist/services/codex-config-heal.d.ts.map +1 -1
  42. package/mcp-server/dist/services/codex-config-heal.js +81 -28
  43. package/mcp-server/dist/services/codex-config-heal.js.map +1 -1
  44. package/mcp-server/dist/services/identity.d.ts +2 -2
  45. package/mcp-server/dist/services/identity.js +2 -2
  46. package/mcp-server/dist/services/memory-judge-backfill.d.ts +6 -0
  47. package/mcp-server/dist/services/memory-judge-backfill.d.ts.map +1 -1
  48. package/mcp-server/dist/services/memory-judge-backfill.js +7 -1
  49. package/mcp-server/dist/services/memory-judge-backfill.js.map +1 -1
  50. package/mcp-server/dist/services/memory-sessions.d.ts +1 -1
  51. package/mcp-server/dist/services/memory-sessions.d.ts.map +1 -1
  52. package/mcp-server/dist/services/memory-sessions.js +28 -2
  53. package/mcp-server/dist/services/memory-sessions.js.map +1 -1
  54. package/mcp-server/dist/services/neural-interface.d.ts +18 -11
  55. package/mcp-server/dist/services/neural-interface.d.ts.map +1 -1
  56. package/mcp-server/dist/services/neural-interface.js +67 -11
  57. package/mcp-server/dist/services/neural-interface.js.map +1 -1
  58. package/mcp-server/dist/services/server-instructions.d.ts +7 -2
  59. package/mcp-server/dist/services/server-instructions.d.ts.map +1 -1
  60. package/mcp-server/dist/services/server-instructions.js +22 -63
  61. package/mcp-server/dist/services/server-instructions.js.map +1 -1
  62. package/mcp-server/dist/services/tool-catalog.d.ts +120 -0
  63. package/mcp-server/dist/services/tool-catalog.d.ts.map +1 -0
  64. package/mcp-server/dist/services/tool-catalog.js +339 -0
  65. package/mcp-server/dist/services/tool-catalog.js.map +1 -0
  66. package/mcp-server/dist/services/tool-list-refresh-barrier.d.ts +12 -0
  67. package/mcp-server/dist/services/tool-list-refresh-barrier.d.ts.map +1 -0
  68. package/mcp-server/dist/services/tool-list-refresh-barrier.js +40 -0
  69. package/mcp-server/dist/services/tool-list-refresh-barrier.js.map +1 -0
  70. package/mcp-server/dist/services/tool-list.d.ts +108 -0
  71. package/mcp-server/dist/services/tool-list.d.ts.map +1 -0
  72. package/mcp-server/dist/services/tool-list.js +334 -0
  73. package/mcp-server/dist/services/tool-list.js.map +1 -0
  74. package/mcp-server/dist/services/tool-runtime.d.ts +161 -0
  75. package/mcp-server/dist/services/tool-runtime.d.ts.map +1 -0
  76. package/mcp-server/dist/services/tool-runtime.js +400 -0
  77. package/mcp-server/dist/services/tool-runtime.js.map +1 -0
  78. package/mcp-server/dist/services/typesafe-config.js +1 -1
  79. package/mcp-server/dist/services/typesafe-config.js.map +1 -1
  80. package/mcp-server/dist/services/whiteboard-geometry.d.ts +26 -2
  81. package/mcp-server/dist/services/whiteboard-geometry.d.ts.map +1 -1
  82. package/mcp-server/dist/services/whiteboard-geometry.js +91 -8
  83. package/mcp-server/dist/services/whiteboard-geometry.js.map +1 -1
  84. package/mcp-server/dist/tools/agents.d.ts +14 -14
  85. package/mcp-server/dist/tools/agents.d.ts.map +1 -1
  86. package/mcp-server/dist/tools/agents.js +29 -19
  87. package/mcp-server/dist/tools/agents.js.map +1 -1
  88. package/mcp-server/dist/tools/browser-batch.d.ts +3 -3
  89. package/mcp-server/dist/tools/choice.d.ts +6 -0
  90. package/mcp-server/dist/tools/choice.d.ts.map +1 -1
  91. package/mcp-server/dist/tools/choice.js +18 -13
  92. package/mcp-server/dist/tools/choice.js.map +1 -1
  93. package/mcp-server/dist/tools/git-tools.js +2 -2
  94. package/mcp-server/dist/tools/git-tools.js.map +1 -1
  95. package/mcp-server/dist/tools/image-tools.d.ts +1 -1
  96. package/mcp-server/dist/tools/image-tools.js +1 -1
  97. package/mcp-server/dist/tools/morelogin.d.ts.map +1 -1
  98. package/mcp-server/dist/tools/morelogin.js +9 -6
  99. package/mcp-server/dist/tools/morelogin.js.map +1 -1
  100. package/mcp-server/dist/tools/skill-tools.d.ts +505 -0
  101. package/mcp-server/dist/tools/skill-tools.d.ts.map +1 -0
  102. package/mcp-server/dist/tools/skill-tools.js +642 -0
  103. package/mcp-server/dist/tools/skill-tools.js.map +1 -0
  104. package/mcp-server/dist/tools/skill.d.ts +7 -0
  105. package/mcp-server/dist/tools/skill.d.ts.map +1 -0
  106. package/mcp-server/dist/tools/skill.js +11 -0
  107. package/mcp-server/dist/tools/skill.js.map +1 -0
  108. package/mcp-server/dist/tools/tool-groups.d.ts +68 -0
  109. package/mcp-server/dist/tools/tool-groups.d.ts.map +1 -0
  110. package/mcp-server/dist/tools/tool-groups.js +147 -0
  111. package/mcp-server/dist/tools/tool-groups.js.map +1 -0
  112. package/mcp-server/dist/tools/whiteboard-format.d.ts.map +1 -1
  113. package/mcp-server/dist/tools/whiteboard-format.js +7 -4
  114. package/mcp-server/dist/tools/whiteboard-format.js.map +1 -1
  115. package/mcp-server/dist/tools/whiteboard-tools.d.ts +64 -13
  116. package/mcp-server/dist/tools/whiteboard-tools.d.ts.map +1 -1
  117. package/mcp-server/dist/tools/whiteboard-tools.js +30 -5
  118. package/mcp-server/dist/tools/whiteboard-tools.js.map +1 -1
  119. package/mcp-server/package-lock.json +2 -2
  120. package/mcp-server/package.json +1 -1
  121. package/mcp-server/src/http.ts +75 -12
  122. package/mcp-server/src/index.ts +147 -154
  123. package/mcp-server/src/preload.ts +12 -12
  124. package/mcp-server/src/services/budget-judgments.ts +5 -3
  125. package/mcp-server/src/services/codex-config-heal.ts +80 -29
  126. package/mcp-server/src/services/identity.ts +2 -2
  127. package/mcp-server/src/services/memory-judge-backfill.ts +7 -1
  128. package/mcp-server/src/services/memory-sessions.ts +24 -3
  129. package/mcp-server/src/services/neural-interface.ts +81 -21
  130. package/mcp-server/src/services/server-instructions.ts +29 -64
  131. package/mcp-server/src/services/tool-catalog.ts +403 -0
  132. package/mcp-server/src/services/tool-list-refresh-barrier.ts +33 -0
  133. package/mcp-server/src/services/tool-list.ts +410 -0
  134. package/mcp-server/src/services/tool-runtime.ts +457 -0
  135. package/mcp-server/src/services/typesafe-config.ts +1 -1
  136. package/mcp-server/src/services/whiteboard-geometry.ts +94 -9
  137. package/mcp-server/src/tools/agents.ts +29 -20
  138. package/mcp-server/src/tools/choice.ts +17 -12
  139. package/mcp-server/src/tools/git-tools.ts +2 -2
  140. package/mcp-server/src/tools/image-tools.ts +1 -1
  141. package/mcp-server/src/tools/morelogin.ts +6 -4
  142. package/mcp-server/src/tools/skill-tools.ts +592 -0
  143. package/mcp-server/src/tools/skill.ts +13 -0
  144. package/mcp-server/src/tools/tool-groups.ts +164 -0
  145. package/mcp-server/src/tools/whiteboard-format.ts +9 -3
  146. package/mcp-server/src/tools/whiteboard-tools.ts +39 -5
  147. package/neural-interface/i18n/en.json +3953 -228
  148. package/neural-interface/i18n/pt-BR.json +3901 -179
  149. package/neural-interface/lib/agent-sandbox-elevation.js +6 -0
  150. package/neural-interface/lib/antigravity/acp-client-host.js +554 -0
  151. package/neural-interface/lib/antigravity/acp-connection.js +299 -0
  152. package/neural-interface/lib/antigravity/bypass.js +100 -0
  153. package/neural-interface/lib/antigravity/catalog.js +273 -0
  154. package/neural-interface/lib/antigravity/home.js +260 -0
  155. package/neural-interface/lib/antigravity/migrate-gemini.js +139 -0
  156. package/neural-interface/lib/antigravity/panel-bridge.js +1058 -0
  157. package/neural-interface/lib/antigravity/policy-hook.mjs +78 -0
  158. package/neural-interface/lib/antigravity/policy.js +74 -0
  159. package/neural-interface/lib/antigravity/tool-call.js +178 -0
  160. package/neural-interface/lib/antigravity/transcripts.js +252 -0
  161. package/neural-interface/lib/antigravity/usage.js +43 -0
  162. package/neural-interface/lib/assistant-api.js +128 -28
  163. package/neural-interface/lib/assistant-brains/antigravity.js +423 -0
  164. package/neural-interface/lib/assistant-brains/claude.js +4 -3
  165. package/neural-interface/lib/assistant-brains/codex-browser-policy-hook.mjs +12 -2
  166. package/neural-interface/lib/assistant-brains/codex-route-gate-hook.mjs +32 -9
  167. package/neural-interface/lib/assistant-brains/codex.js +9 -5
  168. package/neural-interface/lib/assistant-brains/opencode.js +120 -54
  169. package/neural-interface/lib/assistant-brains/opencode2-browser-policy/index.js +28 -13
  170. package/neural-interface/lib/assistant-brains/opencode2-route-gate/index.js +59 -19
  171. package/neural-interface/lib/assistant-budget-planner.js +7 -3
  172. package/neural-interface/lib/assistant-budget-split.js +42 -15
  173. package/neural-interface/lib/assistant-catalog.js +81 -15
  174. package/neural-interface/lib/assistant-config.js +6 -3
  175. package/neural-interface/lib/assistant-dispatch.js +1073 -200
  176. package/neural-interface/lib/assistant-envelope.js +156 -2
  177. package/neural-interface/lib/assistant-evidence.js +80 -0
  178. package/neural-interface/lib/assistant-hidden-models.js +7 -5
  179. package/neural-interface/lib/assistant-persona.js +93 -19
  180. package/neural-interface/lib/assistant-plan-permissions.js +25 -9
  181. package/neural-interface/lib/assistant-route-gate-codex.js +3 -0
  182. package/neural-interface/lib/assistant-route-gate.js +6 -4
  183. package/neural-interface/lib/assistant-router.js +245 -38
  184. package/neural-interface/lib/assistant-runtime.js +214 -30
  185. package/neural-interface/lib/assistant-task-prompt.js +87 -21
  186. package/neural-interface/lib/assistant-tools.js +51 -0
  187. package/neural-interface/lib/assistant-usage.js +29 -0
  188. package/neural-interface/lib/backup-service.js +626 -4
  189. package/neural-interface/lib/backup-zip-reader.js +10 -5
  190. package/neural-interface/lib/backup-zip-writer.js +257 -0
  191. package/neural-interface/lib/browser-execution.js +10 -2
  192. package/neural-interface/lib/browser-guard-cdp.js +84 -0
  193. package/neural-interface/lib/browser-network-guard.js +476 -0
  194. package/neural-interface/lib/browser-policy-roots.js +64 -0
  195. package/neural-interface/lib/browser-tool-policy.js +198 -38
  196. package/neural-interface/lib/claude-agent-bridge.js +11 -2
  197. package/neural-interface/lib/claude-history-cache.js +210 -0
  198. package/neural-interface/lib/claude-hooks-status.js +103 -0
  199. package/neural-interface/lib/claude-model-catalog.js +5 -1
  200. package/neural-interface/lib/claude-temporary.js +5 -11
  201. package/neural-interface/lib/cli-install-api.js +1 -1
  202. package/neural-interface/lib/cli-install.js +163 -154
  203. package/neural-interface/lib/cli-resolver.js +13 -3
  204. package/neural-interface/lib/cli-update-planner.js +52 -41
  205. package/neural-interface/lib/cloudflared/tunnel.js +42 -2
  206. package/neural-interface/lib/codex-mcp-approvals.js +11 -0
  207. package/neural-interface/lib/codex-rollout-reader.js +52 -0
  208. package/neural-interface/lib/codex-worker-app-server.js +191 -0
  209. package/neural-interface/lib/confined-fs.js +30 -3
  210. package/neural-interface/lib/crash-notice-api.js +98 -0
  211. package/neural-interface/lib/editor-completion-opencode.js +68 -68
  212. package/neural-interface/lib/editor-git-api.js +3 -20
  213. package/neural-interface/lib/exec-loop-command.js +13 -10
  214. package/neural-interface/lib/file-explorer-api.js +74 -40
  215. package/neural-interface/lib/file-explorer-watch.js +9 -3
  216. package/neural-interface/lib/git-bash/install.js +52 -6
  217. package/neural-interface/lib/git-bash/manager.js +59 -17
  218. package/neural-interface/lib/git-bash/pins.js +12 -0
  219. package/neural-interface/lib/git-read.js +2 -2
  220. package/neural-interface/lib/git-status-runner.js +390 -0
  221. package/neural-interface/lib/git-status-watchdog.js +40 -0
  222. package/neural-interface/lib/greeting/budgets.js +1 -0
  223. package/neural-interface/lib/greeting/engine.js +2 -2
  224. package/neural-interface/lib/greeting/sources.js +10 -12
  225. package/neural-interface/lib/greeting/writer.js +1 -1
  226. package/neural-interface/lib/http-guards.js +8 -2
  227. package/neural-interface/lib/install-details.js +4 -1
  228. package/neural-interface/lib/mcp-agent-servers.js +67 -0
  229. package/neural-interface/lib/mcp-client-config.js +35 -33
  230. package/neural-interface/lib/mcp-external-servers.js +332 -0
  231. package/neural-interface/lib/mcp-installer.js +2 -1
  232. package/neural-interface/lib/{mcp-profile-refresh-coordinator.js → mcp-tools-refresh-coordinator.js} +4 -4
  233. package/neural-interface/lib/memory-session-capture.js +17 -3
  234. package/neural-interface/lib/morelogin.js +177 -25
  235. package/neural-interface/lib/native-loop-providers.js +965 -66
  236. package/neural-interface/lib/native-loop-runtime.js +290 -42
  237. package/neural-interface/lib/opencode-config.js +557 -0
  238. package/neural-interface/lib/opencode-db-schema.js +17 -34
  239. package/neural-interface/lib/opencode-history.js +48 -218
  240. package/neural-interface/lib/opencode-mcp-ready.js +108 -0
  241. package/neural-interface/lib/opencode-native-boundary.js +53 -0
  242. package/neural-interface/lib/opencode-protocol.js +249 -112
  243. package/neural-interface/lib/opencode-runtime-config.js +32 -22
  244. package/neural-interface/lib/opencode-serve-records.js +39 -21
  245. package/neural-interface/lib/opencode-v2-client.js +48 -153
  246. package/neural-interface/lib/opencode-v2-ws-requests.js +36 -210
  247. package/neural-interface/lib/opencode-worker-data.js +27 -0
  248. package/neural-interface/lib/opencode2-client.js +73 -37
  249. package/neural-interface/lib/opencode2-proxy.js +23 -63
  250. package/neural-interface/lib/opencode2-translate.js +51 -2
  251. package/neural-interface/lib/owner-authority.js +249 -0
  252. package/neural-interface/lib/page-session.js +275 -0
  253. package/neural-interface/lib/path-confine.js +12 -9
  254. package/neural-interface/lib/peer-identity.js +793 -0
  255. package/neural-interface/lib/pty-host/core.js +28 -1
  256. package/neural-interface/lib/pty-host/lifetime.js +12 -0
  257. package/neural-interface/lib/pty-host/manager.js +12 -1
  258. package/neural-interface/lib/remote-policy.js +1 -1
  259. package/neural-interface/lib/request-gate.js +20 -2
  260. package/neural-interface/lib/rulesets/api.js +7 -6
  261. package/neural-interface/lib/rulesets/fs-safe.js +1 -1
  262. package/neural-interface/lib/rulesets/installer.js +180 -36
  263. package/neural-interface/lib/rulesets/json-edit.js +1 -1
  264. package/neural-interface/lib/rulesets/render.js +1 -1
  265. package/neural-interface/lib/session-cache-builder.js +81 -31
  266. package/neural-interface/lib/session-title-generator.js +58 -36
  267. package/neural-interface/lib/skills/api-v2.js +495 -0
  268. package/neural-interface/lib/skills/bundle.js +418 -0
  269. package/neural-interface/lib/skills/catalog.js +298 -0
  270. package/neural-interface/lib/skills/creation-api.js +191 -0
  271. package/neural-interface/lib/skills/creation-brief.js +247 -0
  272. package/neural-interface/lib/skills/creation-sources.js +285 -0
  273. package/neural-interface/lib/skills/creation.js +843 -0
  274. package/neural-interface/lib/skills/deploy.js +569 -0
  275. package/neural-interface/lib/skills/digest.js +119 -0
  276. package/neural-interface/lib/skills/discover.js +111 -0
  277. package/neural-interface/lib/skills/draft-confinement.js +216 -0
  278. package/neural-interface/lib/skills/eval-confinement.js +399 -0
  279. package/neural-interface/lib/skills/eval-sandbox.js +280 -0
  280. package/neural-interface/lib/skills/eval-trace.js +135 -0
  281. package/neural-interface/lib/skills/evals-api.js +212 -0
  282. package/neural-interface/lib/skills/evals.js +1573 -0
  283. package/neural-interface/lib/skills/export.js +203 -0
  284. package/neural-interface/lib/skills/frontmatter.js +64 -0
  285. package/neural-interface/lib/skills/health.js +75 -0
  286. package/neural-interface/lib/skills/json-edit.js +165 -0
  287. package/neural-interface/lib/skills/known-bridge-digests.json +441 -0
  288. package/neural-interface/lib/skills/known-bridges.js +96 -0
  289. package/neural-interface/lib/skills/library.js +823 -0
  290. package/neural-interface/lib/skills/local-store.js +21 -0
  291. package/neural-interface/lib/skills/migration.js +433 -0
  292. package/neural-interface/lib/skills/operations.js +45 -0
  293. package/neural-interface/lib/skills/ownership.js +427 -0
  294. package/neural-interface/lib/skills/packages.js +88 -0
  295. package/neural-interface/lib/skills/reviews.js +212 -0
  296. package/neural-interface/lib/skills/revision.js +80 -0
  297. package/neural-interface/lib/skills/roots.js +269 -0
  298. package/neural-interface/lib/skills/runtime-checks.js +358 -0
  299. package/neural-interface/lib/skills/scan-assets.js +252 -0
  300. package/neural-interface/lib/skills/scan-context.js +26 -0
  301. package/neural-interface/lib/skills/scan-shell.js +324 -0
  302. package/neural-interface/lib/skills/scan.js +364 -0
  303. package/neural-interface/lib/skills/scanners.js +54 -0
  304. package/neural-interface/lib/skills/service.js +530 -0
  305. package/neural-interface/lib/skills/telemetry.js +119 -0
  306. package/neural-interface/lib/sqlite-integrity-worker.js +22 -0
  307. package/neural-interface/lib/synabun-version.js +1 -1
  308. package/neural-interface/lib/system-activity.js +1 -1
  309. package/neural-interface/lib/tool-lists.js +124 -0
  310. package/neural-interface/lib/whatsapp/brain.js +7 -3
  311. package/neural-interface/lib/whatsapp/bridge.js +6 -3
  312. package/neural-interface/lib/whatsapp/cards.js +22 -9
  313. package/neural-interface/lib/whatsapp/config.js +1 -1
  314. package/neural-interface/lib/worker-confinement.js +1268 -0
  315. package/neural-interface/lib/worker-guard-setting.js +56 -0
  316. package/neural-interface/lib/worker-mcp-channel.js +175 -0
  317. package/neural-interface/lib/worker-question.js +74 -0
  318. package/neural-interface/lib/worker-relay-ports.js +227 -0
  319. package/neural-interface/lib/worker-resume.js +238 -0
  320. package/neural-interface/lib/worker-sandbox.js +329 -0
  321. package/neural-interface/package-lock.json +34 -12
  322. package/neural-interface/package.json +3 -2
  323. package/neural-interface/public/index.html +3 -1
  324. package/neural-interface/public/index2d.html +19 -11
  325. package/neural-interface/public/onboarding.html +3 -3
  326. package/neural-interface/public/shared/account-menu.js +8 -5
  327. package/neural-interface/public/shared/agent-runtime-options.js +125 -31
  328. package/neural-interface/public/shared/agy/agy-bypass.js +47 -0
  329. package/neural-interface/public/shared/agy/agy-client.js +266 -0
  330. package/neural-interface/public/shared/agy/agy-commands.js +120 -0
  331. package/neural-interface/public/shared/agy/agy-copy.js +326 -0
  332. package/neural-interface/public/shared/agy/agy-diff.js +161 -0
  333. package/neural-interface/public/shared/agy/agy-events.js +469 -0
  334. package/neural-interface/public/shared/agy/agy-greeting.js +26 -0
  335. package/neural-interface/public/shared/agy/agy-options.js +232 -0
  336. package/neural-interface/public/shared/agy/agy-panel.js +2543 -0
  337. package/neural-interface/public/shared/agy/agy-render.js +392 -0
  338. package/neural-interface/public/shared/agy/agy-setup.js +149 -0
  339. package/neural-interface/public/shared/agy/agy-styles.js +604 -0
  340. package/neural-interface/public/shared/agy/agy-tabs-logic.js +181 -0
  341. package/neural-interface/public/shared/api.js +1527 -1336
  342. package/neural-interface/public/shared/app-frame.js +192 -0
  343. package/neural-interface/public/shared/assistant/asst-agents-dock.js +36 -6
  344. package/neural-interface/public/shared/assistant/asst-api.js +1 -1
  345. package/neural-interface/public/shared/assistant/asst-ask-styles.js +270 -0
  346. package/neural-interface/public/shared/assistant/asst-ask-tail.js +118 -0
  347. package/neural-interface/public/shared/assistant/asst-ask.js +397 -0
  348. package/neural-interface/public/shared/assistant/asst-brain-picker.js +105 -44
  349. package/neural-interface/public/shared/assistant/asst-budget.js +5 -4
  350. package/neural-interface/public/shared/assistant/asst-control.js +205 -26
  351. package/neural-interface/public/shared/assistant/asst-followups-card.js +383 -0
  352. package/neural-interface/public/shared/assistant/asst-followups.js +417 -0
  353. package/neural-interface/public/shared/assistant/asst-hosts.js +16 -7
  354. package/neural-interface/public/shared/assistant/asst-limit-dock.js +45 -0
  355. package/neural-interface/public/shared/assistant/asst-limit-wait.js +327 -0
  356. package/neural-interface/public/shared/assistant/asst-limit.js +168 -0
  357. package/neural-interface/public/shared/assistant/asst-mascot.js +49 -12
  358. package/neural-interface/public/shared/assistant/asst-menu.js +7 -6
  359. package/neural-interface/public/shared/assistant/asst-panel.js +151 -19
  360. package/neural-interface/public/shared/assistant/asst-rack-styles.js +66 -49
  361. package/neural-interface/public/shared/assistant/asst-render.js +445 -82
  362. package/neural-interface/public/shared/assistant/asst-route.js +304 -53
  363. package/neural-interface/public/shared/assistant/asst-routes-editor.js +9 -8
  364. package/neural-interface/public/shared/assistant/asst-scenes.js +56 -1
  365. package/neural-interface/public/shared/assistant/asst-sidepanel.js +117 -10
  366. package/neural-interface/public/shared/assistant/asst-slash.js +17 -9
  367. package/neural-interface/public/shared/assistant/asst-state.js +87 -24
  368. package/neural-interface/public/shared/assistant/asst-stop.js +127 -0
  369. package/neural-interface/public/shared/assistant/asst-styles.js +93 -21
  370. package/neural-interface/public/shared/assistant/asst-tool-kinds.js +190 -23
  371. package/neural-interface/public/shared/assistant/asst-usage.js +2 -1
  372. package/neural-interface/public/shared/automation-context.js +5 -2
  373. package/neural-interface/public/shared/cc-dropdown.js +89 -19
  374. package/neural-interface/public/shared/cdx/cdx-context-menu.js +10 -9
  375. package/neural-interface/public/shared/cdx/cdx-copy.js +16 -0
  376. package/neural-interface/public/shared/cdx/cdx-output-model.js +22 -1
  377. package/neural-interface/public/shared/cdx/cdx-output.js +34 -10
  378. package/neural-interface/public/shared/cdx/cdx-panel.js +59 -151
  379. package/neural-interface/public/shared/cdx/cdx-preview.js +12 -0
  380. package/neural-interface/public/shared/cdx/cdx-protocol.js +39 -11
  381. package/neural-interface/public/shared/cdx/cdx-render.js +57 -38
  382. package/neural-interface/public/shared/cdx/cdx-requests.js +14 -4
  383. package/neural-interface/public/shared/cdx/cdx-skill-hints.js +54 -0
  384. package/neural-interface/public/shared/cdx/cdx-styles.js +15 -3
  385. package/neural-interface/public/shared/cdx/cdx-tabs.js +127 -44
  386. package/neural-interface/public/shared/cdx/cdx-ws.js +0 -1
  387. package/neural-interface/public/shared/cli-install-controller.js +218 -0
  388. package/neural-interface/public/shared/cli-install-view.js +11 -12
  389. package/neural-interface/public/shared/cli-status.js +11 -10
  390. package/neural-interface/public/shared/constants.js +5 -4
  391. package/neural-interface/public/shared/context-menu-areas.js +34 -0
  392. package/neural-interface/public/shared/context-menu-logic.js +243 -0
  393. package/neural-interface/public/shared/context-menu-model.js +367 -0
  394. package/neural-interface/public/shared/context-menu.js +372 -0
  395. package/neural-interface/public/shared/cp/cp-context-menu.js +10 -9
  396. package/neural-interface/public/shared/cp/cp-restore.js +162 -0
  397. package/neural-interface/public/shared/cp/cp-tool-cards.js +10 -3
  398. package/neural-interface/public/shared/crash-notice-view.js +168 -0
  399. package/neural-interface/public/shared/desktop-bridge.js +17 -0
  400. package/neural-interface/public/shared/desktop-titlebar-view.js +12 -0
  401. package/neural-interface/public/shared/desktop-titlebar.js +13 -4
  402. package/neural-interface/public/shared/desktop-update-view.js +21 -0
  403. package/neural-interface/public/shared/editor/editor-panel-logic.js +2 -2
  404. package/neural-interface/public/shared/explorer/fx-api.js +4 -4
  405. package/neural-interface/public/shared/explorer/fx-links.js +3 -3
  406. package/neural-interface/public/shared/explorer/fx-logic.js +1 -1
  407. package/neural-interface/public/shared/explorer/fx-main.js +48 -16
  408. package/neural-interface/public/shared/explorer/fx-tree.js +1 -0
  409. package/neural-interface/public/shared/greeting/greeting-card.js +2 -2
  410. package/neural-interface/public/shared/greeting/greeting-view.js +1 -0
  411. package/neural-interface/public/shared/html-shell.js +30 -15
  412. package/neural-interface/public/shared/i18n.js +2 -0
  413. package/neural-interface/public/shared/ocp-v2/ocp-v2-approvals.js +7 -7
  414. package/neural-interface/public/shared/ocp-v2/ocp-v2-binding.js +4 -4
  415. package/neural-interface/public/shared/ocp-v2/ocp-v2-changes-logic.js +3 -101
  416. package/neural-interface/public/shared/ocp-v2/ocp-v2-childpanel.js +2 -0
  417. package/neural-interface/public/shared/ocp-v2/ocp-v2-compact-button.js +1 -3
  418. package/neural-interface/public/shared/ocp-v2/ocp-v2-composer-logic.js +2 -6
  419. package/neural-interface/public/shared/ocp-v2/ocp-v2-context-menu.js +11 -11
  420. package/neural-interface/public/shared/ocp-v2/ocp-v2-context-model.js +0 -3
  421. package/neural-interface/public/shared/ocp-v2/ocp-v2-events.js +8 -4
  422. package/neural-interface/public/shared/ocp-v2/ocp-v2-manager.js +7 -7
  423. package/neural-interface/public/shared/ocp-v2/ocp-v2-outcome-notifications.js +16 -0
  424. package/neural-interface/public/shared/ocp-v2/ocp-v2-panel.js +74 -259
  425. package/neural-interface/public/shared/ocp-v2/ocp-v2-plan.js +1 -2
  426. package/neural-interface/public/shared/ocp-v2/ocp-v2-projectbar.js +95 -202
  427. package/neural-interface/public/shared/ocp-v2/ocp-v2-rehydrate.js +13 -4
  428. package/neural-interface/public/shared/ocp-v2/ocp-v2-render.js +13 -22
  429. package/neural-interface/public/shared/ocp-v2/ocp-v2-send.js +4 -4
  430. package/neural-interface/public/shared/ocp-v2/ocp-v2-session-actions.js +8 -61
  431. package/neural-interface/public/shared/ocp-v2/ocp-v2-sessions-logic.js +2 -91
  432. package/neural-interface/public/shared/ocp-v2/ocp-v2-slash-hints.js +16 -15
  433. package/neural-interface/public/shared/ocp-v2/ocp-v2-state.js +8 -21
  434. package/neural-interface/public/shared/ocp-v2/ocp-v2-status-logic.js +1 -99
  435. package/neural-interface/public/shared/ocp-v2/ocp-v2-status.js +5 -35
  436. package/neural-interface/public/shared/ocp-v2/ocp-v2-styles.js +17 -21
  437. package/neural-interface/public/shared/ocp-v2/{ocp-v2-profile-inheritance.js → ocp-v2-tools-inheritance.js} +16 -16
  438. package/neural-interface/public/shared/ocp-v2/ocp-v2-ws.js +60 -50
  439. package/neural-interface/public/shared/page-session.js +96 -0
  440. package/neural-interface/public/shared/provider-icons.js +4 -2
  441. package/neural-interface/public/shared/registry.js +5 -3
  442. package/neural-interface/public/shared/retired-2d.js +3 -0
  443. package/neural-interface/public/shared/schedules-view.js +195 -61
  444. package/neural-interface/public/shared/settings/settings-claude-hooks.js +135 -0
  445. package/neural-interface/public/shared/settings/settings-data.js +3 -1
  446. package/neural-interface/public/shared/settings/settings-ia.js +6 -6
  447. package/neural-interface/public/shared/settings/settings-opencode.js +89 -0
  448. package/neural-interface/public/shared/settings/settings-rules.js +2 -2
  449. package/neural-interface/public/shared/settings/settings-skill-folders-pane.js +265 -0
  450. package/neural-interface/public/shared/settings/settings-skill-folders.js +130 -0
  451. package/neural-interface/public/shared/settings/settings-worker-guard.js +72 -0
  452. package/neural-interface/public/shared/showcase-privacy.js +6 -1
  453. package/neural-interface/public/shared/sidepanel-session-status.js +3 -3
  454. package/neural-interface/public/shared/skills/ss-args.js +96 -0
  455. package/neural-interface/public/shared/skills/ss-creation.js +222 -0
  456. package/neural-interface/public/shared/skills/ss-dialog.js +133 -0
  457. package/neural-interface/public/shared/skills/ss-doc.js +173 -0
  458. package/neural-interface/public/shared/skills/ss-eval-adapters.js +269 -0
  459. package/neural-interface/public/shared/skills/ss-eval-grade.js +359 -0
  460. package/neural-interface/public/shared/skills/ss-eval-optimise.js +153 -0
  461. package/neural-interface/public/shared/skills/ss-eval-plan.js +315 -0
  462. package/neural-interface/public/shared/skills/ss-evals.js +417 -0
  463. package/neural-interface/public/shared/skills/ss-form.js +159 -0
  464. package/neural-interface/public/shared/skills/ss-frontmatter.js +376 -0
  465. package/neural-interface/public/shared/skills/ss-ids.js +32 -0
  466. package/neural-interface/public/shared/skills/ss-lint.js +149 -0
  467. package/neural-interface/public/shared/skills/ss-presets.js +117 -0
  468. package/neural-interface/public/shared/skills/ss-profiles.js +513 -0
  469. package/neural-interface/public/shared/skills/ss-resources.js +165 -0
  470. package/neural-interface/public/shared/skills/ss-review-view.js +190 -0
  471. package/neural-interface/public/shared/skills/ss-tabs.js +79 -0
  472. package/neural-interface/public/shared/skills/ss-unicode.js +135 -0
  473. package/neural-interface/public/shared/skills/studio/sx-actions.js +222 -0
  474. package/neural-interface/public/shared/skills/studio/sx-cm.js +101 -0
  475. package/neural-interface/public/shared/skills/studio/sx-create-ai-view.js +749 -0
  476. package/neural-interface/public/shared/skills/studio/sx-create-ai.js +237 -0
  477. package/neural-interface/public/shared/skills/studio/sx-create-view.js +254 -0
  478. package/neural-interface/public/shared/skills/studio/sx-create.js +126 -0
  479. package/neural-interface/public/shared/skills/studio/sx-diff-view.js +43 -0
  480. package/neural-interface/public/shared/skills/studio/sx-diff.js +133 -0
  481. package/neural-interface/public/shared/skills/studio/sx-docs.js +480 -0
  482. package/neural-interface/public/shared/skills/studio/sx-dom.js +230 -0
  483. package/neural-interface/public/shared/skills/studio/sx-edit-view.js +848 -0
  484. package/neural-interface/public/shared/skills/studio/sx-editor-model.js +193 -0
  485. package/neural-interface/public/shared/skills/studio/sx-errors.js +22 -0
  486. package/neural-interface/public/shared/skills/studio/sx-fixes-view.js +359 -0
  487. package/neural-interface/public/shared/skills/studio/sx-fixes.js +327 -0
  488. package/neural-interface/public/shared/skills/studio/sx-geometry.js +82 -0
  489. package/neural-interface/public/shared/skills/studio/sx-import.js +262 -0
  490. package/neural-interface/public/shared/skills/studio/sx-inspector.js +308 -0
  491. package/neural-interface/public/shared/skills/studio/sx-install-flow.js +282 -0
  492. package/neural-interface/public/shared/skills/studio/sx-install.js +313 -0
  493. package/neural-interface/public/shared/skills/studio/sx-library-view.js +748 -0
  494. package/neural-interface/public/shared/skills/studio/sx-library.js +479 -0
  495. package/neural-interface/public/shared/skills/studio/sx-main.js +690 -0
  496. package/neural-interface/public/shared/skills/studio/sx-operations-view.js +98 -0
  497. package/neural-interface/public/shared/skills/studio/sx-operations.js +11 -0
  498. package/neural-interface/public/shared/skills/studio/sx-plan.js +158 -0
  499. package/neural-interface/public/shared/skills/studio/sx-publish-view.js +621 -0
  500. package/neural-interface/public/shared/skills/studio/sx-review-view.js +369 -0
  501. package/neural-interface/public/shared/skills/studio/sx-review.js +148 -0
  502. package/neural-interface/public/shared/skills/studio/sx-scan.js +35 -0
  503. package/neural-interface/public/shared/skills/studio/sx-snippets.js +96 -0
  504. package/neural-interface/public/shared/skills/studio/sx-subject.js +249 -0
  505. package/neural-interface/public/shared/skills/studio/sx-test-view.js +994 -0
  506. package/neural-interface/public/shared/skills/studio/sx-test.js +328 -0
  507. package/neural-interface/public/shared/skills/studio/sx-versions-view.js +241 -0
  508. package/neural-interface/public/shared/skills/studio/sx-workspace-view.js +426 -0
  509. package/neural-interface/public/shared/state.js +1 -1
  510. package/neural-interface/public/shared/streaming-markdown.js +58 -0
  511. package/neural-interface/public/shared/styleguide/sg-panel.js +4 -2
  512. package/neural-interface/public/shared/styles.css +1822 -1756
  513. package/neural-interface/public/shared/synabun-mascot.js +1115 -9
  514. package/neural-interface/public/shared/text-cache.js +29 -0
  515. package/neural-interface/public/shared/tool-list-picker.js +55 -0
  516. package/neural-interface/public/shared/tool-list-storage.js +24 -0
  517. package/neural-interface/public/shared/tool-list-view.js +112 -0
  518. package/neural-interface/public/shared/topright-overflow-logic.js +54 -0
  519. package/neural-interface/public/shared/tour/tour-actor.js +268 -0
  520. package/neural-interface/public/shared/tour/tour-beats.js +336 -0
  521. package/neural-interface/public/shared/tour/tour-engine.js +884 -0
  522. package/neural-interface/public/shared/tour/tour-ink.js +390 -0
  523. package/neural-interface/public/shared/tour/tour-stage.js +440 -0
  524. package/neural-interface/public/shared/tour/tour-state.js +40 -0
  525. package/neural-interface/public/shared/tour/tour-tips.js +99 -0
  526. package/neural-interface/public/shared/tour/tour.css +144 -0
  527. package/neural-interface/public/shared/ui-antigravity-panel.js +19 -0
  528. package/neural-interface/public/shared/ui-assistant.js +2 -0
  529. package/neural-interface/public/shared/ui-automation-studio.js +111 -140
  530. package/neural-interface/public/shared/ui-claude-panel.js +376 -82
  531. package/neural-interface/public/shared/ui-cli-banner.js +23 -167
  532. package/neural-interface/public/shared/ui-command-runner.js +6 -3
  533. package/neural-interface/public/shared/ui-context-menu.js +295 -0
  534. package/neural-interface/public/shared/ui-cost-widget.js +57 -59
  535. package/neural-interface/public/shared/ui-crash-notice.js +187 -0
  536. package/neural-interface/public/shared/ui-detail.js +15 -3
  537. package/neural-interface/public/shared/ui-file-explorer.js +48 -6
  538. package/neural-interface/public/shared/ui-file-links.js +2 -2
  539. package/neural-interface/public/shared/ui-games.js +2 -2
  540. package/neural-interface/public/shared/ui-image-gallery.js +50 -47
  541. package/neural-interface/public/shared/ui-judgments.js +1 -1
  542. package/neural-interface/public/shared/ui-keybinds.js +33 -2
  543. package/neural-interface/public/shared/ui-link.js +3 -3
  544. package/neural-interface/public/shared/ui-menubar.js +10 -20
  545. package/neural-interface/public/shared/ui-native-loop-router-state.js +5 -0
  546. package/neural-interface/public/shared/ui-native-loop-router.js +11 -1
  547. package/neural-interface/public/shared/ui-navbar.js +49 -24
  548. package/neural-interface/public/shared/ui-notifications.js +1 -0
  549. package/neural-interface/public/shared/ui-panels.js +96 -65
  550. package/neural-interface/public/shared/ui-resume.js +9 -7
  551. package/neural-interface/public/shared/ui-schedules-studio.js +546 -431
  552. package/neural-interface/public/shared/ui-scroll-follow.js +16 -5
  553. package/neural-interface/public/shared/ui-sessions.js +27 -15
  554. package/neural-interface/public/shared/ui-settings.js +683 -526
  555. package/neural-interface/public/shared/ui-sidepanel-session-entry.js +9 -2
  556. package/neural-interface/public/shared/ui-sidepanel-sessions.js +4 -4
  557. package/neural-interface/public/shared/ui-sidepanel-state.js +23 -12
  558. package/neural-interface/public/shared/ui-sidepanel-tray.js +48 -7
  559. package/neural-interface/public/shared/ui-sidepanel-windows.js +18 -13
  560. package/neural-interface/public/shared/ui-skills.js +33 -2830
  561. package/neural-interface/public/shared/ui-styleguide.js +5 -2
  562. package/neural-interface/public/shared/ui-sync.js +15 -5
  563. package/neural-interface/public/shared/ui-terminal.js +270 -190
  564. package/neural-interface/public/shared/ui-tool-updates.js +6 -4
  565. package/neural-interface/public/shared/ui-tooltip.js +81 -51
  566. package/neural-interface/public/shared/ui-topright-overflow.js +233 -0
  567. package/neural-interface/public/shared/ui-trash.js +6 -4
  568. package/neural-interface/public/shared/ui-tutorial-layout.js +3 -117
  569. package/neural-interface/public/shared/ui-tutorial-preview.js +103 -0
  570. package/neural-interface/public/shared/ui-tutorial-steps.js +3 -65
  571. package/neural-interface/public/shared/ui-tutorial.css +47 -100
  572. package/neural-interface/public/shared/ui-tutorial.js +285 -509
  573. package/neural-interface/public/shared/ui-update.js +38 -2
  574. package/neural-interface/public/shared/ui-whiteboard.js +312 -59
  575. package/neural-interface/public/shared/ui-worker-end.js +5 -1
  576. package/neural-interface/public/shared/ui-workspaces.js +3 -2
  577. package/neural-interface/public/shared/view-variant.js +66 -0
  578. package/neural-interface/public/shared/whatsapp/wa-view.js +3 -3
  579. package/neural-interface/public/shared/whiteboard-list.js +172 -0
  580. package/neural-interface/public/shared/worker-end.js +10 -3
  581. package/neural-interface/public/shared/worker-questions.js +34 -0
  582. package/neural-interface/public/shared/worker-restart.js +12 -0
  583. package/neural-interface/public/sidepanel-session.html +2 -2
  584. package/neural-interface/public/variant/2d/background.js +2 -1
  585. package/neural-interface/public/variant/2d/context-menu.js +8 -2
  586. package/neural-interface/public/variant/2d/graph.js +42 -20
  587. package/neural-interface/public/variant/2d/hulls.js +14 -9
  588. package/neural-interface/public/variant/2d/lasso.js +11 -7
  589. package/neural-interface/public/variant/2d/main.js +32 -1
  590. package/neural-interface/public/variant/2d/minimap.js +11 -13
  591. package/neural-interface/public/variant/3d/main.js +69 -6
  592. package/neural-interface/public/variant/3d/map-controls.js +24 -9
  593. package/neural-interface/public/vendor/caveat/OFL.txt +93 -0
  594. package/neural-interface/public/vendor/caveat/caveat-latin-400-normal.woff2 +0 -0
  595. package/neural-interface/public/vendor/caveat/caveat-latin-700-normal.woff2 +0 -0
  596. package/neural-interface/public/vendor/caveat/caveat.css +17 -0
  597. package/neural-interface/public/vendor/caveat/manifest.json +12 -0
  598. package/neural-interface/public/vendor/yaml/LICENSE +13 -0
  599. package/neural-interface/public/vendor/yaml/manifest.json +4 -0
  600. package/neural-interface/public/vendor/yaml/yaml-2.9.1.min.js +137 -0
  601. package/neural-interface/scripts/build-vendor.mjs +32 -0
  602. package/neural-interface/server.js +4553 -2855
  603. package/neural-interface/templates/rulesets/README.md +1 -1
  604. package/neural-interface/templates/rulesets/core.md +1 -1
  605. package/neural-interface/templates/rulesets/legacy-hashes.json +23 -5
  606. package/neural-interface/templates/rulesets/manifest.json +8 -8
  607. package/npm-shrinkwrap.json +34 -12
  608. package/package.json +17 -3
  609. package/postinstall.js +9 -4
  610. package/preuninstall.js +1 -1
  611. package/setup.js +97 -322
  612. package/skills/skill-forge/SKILL.md +177 -0
  613. package/skills/skill-forge/evals/evals.json +54 -0
  614. package/skills/skill-forge/references/package.md +105 -0
  615. package/skills/skill-forge/references/review-and-recovery.md +63 -0
  616. package/skills/skill-forge/references/runtime-profiles.md +20 -0
  617. package/skills/skill-forge/references/sources-and-capabilities.md +51 -0
  618. package/skills/synabun/SKILL.md +10 -7
  619. package/skills/synabun/modules/audit.md +1 -5
  620. package/skills/synabun/modules/changelog.md +1 -5
  621. package/skills/synabun/modules/idea.md +1 -1
  622. package/skills/synabun/modules/memorize.md +6 -9
  623. package/skills/synabun/modules/schedule.md +6 -6
  624. package/mcp-server/dist/services/profiles.d.ts +0 -120
  625. package/mcp-server/dist/services/profiles.d.ts.map +0 -1
  626. package/mcp-server/dist/services/profiles.js +0 -387
  627. package/mcp-server/dist/services/profiles.js.map +0 -1
  628. package/mcp-server/dist/tools/leonardo-browser-tools.d.ts +0 -97
  629. package/mcp-server/dist/tools/leonardo-browser-tools.d.ts.map +0 -1
  630. package/mcp-server/dist/tools/leonardo-browser-tools.js +0 -228
  631. package/mcp-server/dist/tools/leonardo-browser-tools.js.map +0 -1
  632. package/mcp-server/dist/tools/leonardo.d.ts +0 -13
  633. package/mcp-server/dist/tools/leonardo.d.ts.map +0 -1
  634. package/mcp-server/dist/tools/leonardo.js +0 -21
  635. package/mcp-server/dist/tools/leonardo.js.map +0 -1
  636. package/mcp-server/dist/tools/profile.d.ts +0 -17
  637. package/mcp-server/dist/tools/profile.d.ts.map +0 -1
  638. package/mcp-server/dist/tools/profile.js +0 -114
  639. package/mcp-server/dist/tools/profile.js.map +0 -1
  640. package/mcp-server/src/services/profiles.ts +0 -428
  641. package/mcp-server/src/tools/leonardo-browser-tools.ts +0 -291
  642. package/mcp-server/src/tools/leonardo.ts +0 -30
  643. package/mcp-server/src/tools/profile.ts +0 -122
  644. package/neural-interface/lib/assistant-brains/opencode-browser-policy.js +0 -47
  645. package/neural-interface/lib/assistant-brains/opencode-route-gate.js +0 -62
  646. package/neural-interface/lib/mcp-profile-servers.js +0 -120
  647. package/neural-interface/public/shared/ui-tutorial-draw.js +0 -311
  648. package/skills/leonardo/SKILL.md +0 -168
  649. package/skills/leonardo/icon.svg +0 -1
  650. package/skills/leonardo/modules/browser-guide.md +0 -378
  651. package/skills/leonardo/modules/image-prompter.md +0 -283
  652. package/skills/leonardo/modules/model-advisor.md +0 -100
  653. package/skills/leonardo/modules/prompt-library.md +0 -110
  654. package/skills/leonardo/modules/style-guide.md +0 -186
  655. package/skills/leonardo/modules/video-prompter.md +0 -317
  656. /package/neural-interface/templates/rulesets/{gemini.md → antigravity.md} +0 -0
@@ -17,7 +17,7 @@
17
17
  // `footer`: items under the list that stay in view while the list scrolls.
18
18
  // Every menu is measured at the width it is shown at, never wider than its box less the margins,
19
19
  // and opens where that box has room (the list scrolls inside it). The box is the Assistant
20
- // panel or root around the anchor, else the window.
20
+ // panel or root around the anchor, else the app frame (app-frame.js; the window on a page without it).
21
21
  // `bounds`: an element (or () => DOMRect) to use as that box instead: the menu is then exactly
22
22
  // `width` wide (or the box's room) and follows the box on resize.
23
23
  // `onEscape`: returns true when it handled Esc (e.g. went back a view): the menu stays open.
@@ -44,6 +44,8 @@
44
44
  // any group left empty. The handle's update({ title, items, footer, focus }) redraws
45
45
  // an open menu in place (focus: the data-id to land on; the filter's text still applies).
46
46
 
47
+ import { frameRect } from '../app-frame.js';
48
+
47
49
  let _open = null;
48
50
  let _uid = 0;
49
51
  let _lastDown = null;
@@ -290,14 +292,13 @@ const BOUNDED_MIN_WIDTH = 248;
290
292
  const MENU_MIN_HEIGHT = 96;
291
293
  const BOUNDED_MIN_HEIGHT = 140;
292
294
 
293
- /** The box a menu stays inside: its bounds clipped to the window (the window when it has none). */
295
+ /** The box a menu stays inside: its bounds clipped to the app frame (the frame when it has none). */
294
296
  function boundsBox(bounds) {
295
- const vw = window.innerWidth;
296
- const vh = window.innerHeight;
297
+ const f = frameRect();
297
298
  let r = null;
298
299
  try { r = typeof bounds === 'function' ? bounds() : bounds?.getBoundingClientRect?.(); } catch { r = null; }
299
- if (!r || !(r.width > 0) || !(r.height > 0)) return { left: 0, top: 0, right: vw, bottom: vh };
300
- return { left: Math.max(0, r.left), top: Math.max(0, r.top), right: Math.min(vw, r.right), bottom: Math.min(vh, r.bottom) };
300
+ if (!r || !(r.width > 0) || !(r.height > 0)) return { left: f.left, top: f.top, right: f.right, bottom: f.bottom };
301
+ return { left: Math.max(f.left, r.left), top: Math.max(f.top, r.top), right: Math.min(f.right, r.right), bottom: Math.min(f.bottom, r.bottom) };
301
302
  }
302
303
 
303
304
  /** Where a menu without `bounds` stays: the Assistant around its anchor (the sidepanel, or a tab's own root). */
@@ -1,3 +1,4 @@
1
+ import { fetchToolCatalog } from '../agent-runtime-options.js';
1
2
  // ═══════════════════════════════════════════
2
3
  // SynaBun Assistant — panel (mount / lifecycle)
3
4
  // ═══════════════════════════════════════════
@@ -34,12 +35,12 @@ import { t } from '../i18n.js';
34
35
  import '../account-i18n.js';
35
36
  import { forgetGreeting, mountGreeting } from '../greeting/greeting-card.js';
36
37
  import { notify, NOTIF_TYPE } from '../ui-notifications.js';
37
- import { getProviderMeta } from '../provider-icons.js';
38
38
  import { isGuest, hasPermission } from '../ui-sync.js';
39
39
  import { getWhiteboardElementById } from '../ui-whiteboard.js';
40
40
  import { focusNativeLoopRun } from '../ui-native-loop-router.js';
41
41
  import { wireFileLinks } from '../ui-file-links.js';
42
42
  import { injectAssistantStyles } from './asst-styles.js';
43
+ import { tipsSeen, tourOffered } from '../tour/tour-state.js';
43
44
  import { createAssistantSocket } from './asst-ws.js';
44
45
  import { createRenderer, ICON_ASSISTANT, mdInto } from './asst-render.js';
45
46
  import { createMascotDirector, MASCOT_TIMING, turnEndPose } from './asst-mascot.js';
@@ -47,7 +48,9 @@ import { lastInputAt, onKey, onPointer } from '../synabun-ticker.js';
47
48
  import { buildControlResponse, closedControlState, normalizeControlRequest, renderControlCard } from './asst-control.js';
48
49
  import { buildPromptText, createComposer } from './asst-composer.js';
49
50
  import { buildDispatchSpec, parseSlashCommand, slashHelpMarkdown } from './asst-slash.js';
50
- import { cachedProjects, createBrainPicker, testDensityLabel } from './asst-brain-picker.js';
51
+ import { resolveStopTarget } from './asst-stop.js';
52
+ import { plural } from './asst-tool-kinds.js';
53
+ import { cachedProjects, createBrainPicker, openModelMenu, testDensityLabel } from './asst-brain-picker.js';
51
54
  import { createRovingToolbar } from './asst-roving.js';
52
55
  import { openAccountsManager } from './asst-accounts.js';
53
56
  import { createAgentsDock } from './asst-agents-dock.js';
@@ -58,8 +61,8 @@ import { createRouteModeControl, openModelsManager, openRoutesEditor, refreshMod
58
61
  import { budgetChipText, budgetSpendText, budgetTone, closeBudgetEditor, createBudgetController, mountBudgetChip, openBudgetEditor } from './asst-budget.js';
59
62
  import { computerRemoteView, createComputerPanel, createComputerToggle, normalizeComputerRemote, openFrameLightbox, closeFrameLightbox, requestDesktopStop } from './asst-computer.js';
60
63
  import {
61
- applyLimit, applyLimitPacket, applyUsagePacket, brainLabel, createRenameWriter, createTabState, DEFAULT_ROUTE_MODE, deserializeTabState, fmtCost, fmtRunLine, limitExpiresIn, limitNoticeText, modelShortName,
62
- brainModePatch, normalizeBrain, normalizeComputerMode, permissionModeLabel, normalizeRouteMode, normalizeTestDensity, projectLabel, providerShortLabel, readStoredBrain, runFromPayload,
64
+ applyLimit, applyLimitPacket, applyUsagePacket, BRAIN_PROVIDERS, brainLabel, createRenameWriter, createTabState, DEFAULT_ROUTE_MODE, deserializeTabState, fmtCost, fmtRunLine, limitExpiresIn, limitNoticeText, modelShortName,
65
+ brainModePatch, isBrainProvider, normalizeBrain, normalizeComputerMode, permissionModeLabel, normalizeRouteMode, normalizeTestDensity, projectLabel, providerMeta, providerShortLabel, readStoredBrain, runFromPayload,
63
66
  serializeTabState, sessionStatus, tabStorageKey, userSessionTitle,
64
67
  } from './asst-state.js';
65
68
  import {
@@ -240,9 +243,27 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
240
243
  if (host.toolbarSlot) host.toolbarSlot.appendChild(barEl);
241
244
 
242
245
  // ── Helpers ──
243
- const providerIcon = (p) => getProviderMeta(p).icon;
244
- const providerColor = (p) => getProviderMeta(p).color;
246
+ // A worker-only provider provider-icons.js does not know yet keeps its own name (asst-state.js providerMeta).
247
+ const providerIcon = (p) => providerMeta(p).icon;
248
+ const providerColor = (p) => providerMeta(p).color;
245
249
  const visible = () => { try { return host.isVisible ? !!host.isVisible() : true; } catch { return true; } };
250
+
251
+ // ── Just-in-time tips (../tour/tour-tips.js): once each, ever; never in a replay or while the tour runs ──
252
+ function tip(id, targetOf) {
253
+ if (destroyed || replaying || !visible() || guestBlocked() || tipsSeen(storage).has(id)) return;
254
+ requestAnimationFrame(() => {
255
+ if (destroyed) return;
256
+ let target = null;
257
+ try { target = targetOf(); } catch { target = null; }
258
+ if (!target?.isConnected) return;
259
+ import('../tour/tour-tips.js')
260
+ .then(async ({ ensureTourStyles, showTip }) => {
261
+ await ensureTourStyles();
262
+ if (!destroyed && target.isConnected) showTip(id, { storage, tr: (key) => t(key), root, target, renderer, reduced: () => matchMedia('(prefers-reduced-motion: reduce)').matches });
263
+ })
264
+ .catch(() => { /* a tip is never worth an error */ });
265
+ });
266
+ }
246
267
  const hostId = host.id || null; // routing only (assistant:new / resume / focused) — never a feature switch
247
268
 
248
269
  function persist() {
@@ -506,7 +527,19 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
506
527
  emptyBudgetChip?.destroy();
507
528
  emptyBudgetChip = null;
508
529
  },
509
- onSuggestion: (template) => composer.fillTemplate(template),
530
+ // The first-visit row asks for the Workspace tour on this panel (ui-tutorial.js); the others fill the composer.
531
+ onSuggestion: (template, s) => {
532
+ if (s?.action === 'tour') { emit('tour:open', { host: controller.tourHost(), from: 'starter' }); return; }
533
+ composer.fillTemplate(template);
534
+ },
535
+ // A follow-up under a finished message, or Retry now on a usage-limit card: sent as the user's next
536
+ // message (queued while a turn runs, like a typed one). "Something else…" is the composer.
537
+ onFollowup: (text) => { submit(clickPayload(text)); },
538
+ onFollowupOther: () => composer.focus(),
539
+ onLimitRetry: (text) => { submit(clickPayload(text)); },
540
+ onSwitchProvider: (anchor, meta) => continueOnAnotherProvider(anchor, meta),
541
+ limitInfo: () => st.limit,
542
+ brainProvider: () => st.brain.provider,
510
543
  heroOrigin: () => { try { return host.takeHeroOrigin?.() || null; } catch { return null; } },
511
544
  onMascotChange: () => director?.retarget(),
512
545
  onInit: (ev) => {
@@ -536,12 +569,20 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
536
569
  },
537
570
  });
538
571
 
572
+ /** What a click sends: the text alone, shaped like a typed message with nothing attached. */
573
+ function clickPayload(text) {
574
+ return { text: String(text ?? ''), images: [], files: [], uploads: [], memories: [] };
575
+ }
576
+
539
577
  function emptySuggestions() {
540
578
  const project = projectLabel(st.brain.project, cachedProjects()) || tt('assistant.empty.thisProject', 'this project');
541
579
  const list = [];
580
+ // Until the Workspace tour is completed or skipped, its starter comes first. It never opens by itself.
581
+ if (tourOffered(storage) && !guestBlocked()) list.push({ id: 'tour', action: 'tour', kind: 'ask', label: tt('tour.starter', 'Show me the workspace'), meta: tt('tour.starterTime', '2 min') });
542
582
  if (computerAvailable()) list.push({ id: 'computer', label: tt('assistant.empty.suggestComputer', 'Use my Mac to…'), template: tt('assistant.empty.templateComputer', 'Use my Mac to {caret}') });
543
583
  list.push({ id: 'web', label: tt('assistant.empty.suggestWeb', 'Look up … on the web'), template: tt('assistant.empty.templateWeb', 'Look up {caret} on the web') });
544
584
  list.push({ id: 'fix', label: tt('assistant.empty.suggestFix', 'Fix … in {project}', { project }), template: tt('assistant.empty.templateFix', 'Fix {caret} in {project}', { project }) });
585
+ list.push({ id: 'skill', label: tt('assistant.empty.suggestSkill', 'Create Skill'), template: tt('assistant.empty.templateSkill', 'Create a skill that {caret}') });
545
586
  list.push({ id: 'schedule', label: tt('assistant.empty.suggestSchedule', 'Schedule …'), template: tt('assistant.empty.templateSchedule', 'Schedule {caret}') });
546
587
  list.push({ id: 'remember', label: tt('assistant.empty.suggestRemember', 'Remember …'), template: tt('assistant.empty.templateRemember', 'Remember {caret}') });
547
588
  return list;
@@ -553,7 +594,7 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
553
594
  describeSlash: (cmd) => tt(cmd.descKey, cmd.desc),
554
595
  resolveMemory: (id) => appState.allNodes?.find(n => n.id === id) || null,
555
596
  resolveWhiteboardImage: (id) => { const wb = getWhiteboardElementById(id); return wb?.type === 'image' && wb.dataUrl ? { dataUrl: wb.dataUrl } : null; },
556
- onDraftChange: (text) => { st.draft = text; persist(); director?.type(!!String(text || '').trim()); },
597
+ onDraftChange: (text) => { st.draft = text; persist(); director?.type(!!String(text || '').trim()); renderer.setDrafting?.(!!String(text || '').trim()); },
557
598
  onFocusChange: (focused) => { if (focused) director?.touch(); else director?.stopTyping(); },
558
599
  onAbort: () => abort(),
559
600
  onToast: toast,
@@ -591,6 +632,7 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
591
632
  const accountHooks = () => ({ t, onChanged: () => picker.refresh(true), onSelect: (id) => applyBrain({ ...st.brain, accountId: id }, { requiresSwitch: true, field: 'account' }) });
592
633
  // Model · effort · permission mode · account sit in the composer row next to attach; project and MCP in the toolbar.
593
634
  const picker = createBrainPicker({ brain: composer.el.querySelector('.asst-composer-brain'), context: barGroups.context }, {
635
+ getSessionId: () => st.sessionId,
594
636
  t,
595
637
  mascot: () => director,
596
638
  getBrain: () => st.brain,
@@ -677,6 +719,17 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
677
719
  agentsBtn.setAttribute('aria-pressed', st.dockOpen ? 'true' : 'false');
678
720
 
679
721
  const usage = createUsageGauge(root.querySelector('.asst-usage-host'), { t, sessionId });
722
+ // The first usage strip on screen gets its tip (once, ever).
723
+ const usageHostEl = root.querySelector('.asst-usage-host');
724
+ if (typeof MutationObserver === 'function' && !tipsSeen(storage).has('usage')) {
725
+ const usageTipWatch = new MutationObserver(() => {
726
+ if (usageHostEl.hidden) return;
727
+ usageTipWatch.disconnect();
728
+ tip('usage', () => usageHostEl.querySelector('.asst-usage-strip') || usageHostEl);
729
+ });
730
+ usageTipWatch.observe(usageHostEl, { attributes: true, attributeFilter: ['hidden'] });
731
+ unsubs.push(() => usageTipWatch.disconnect());
732
+ }
680
733
  if (st.usageView) { usage.apply({ type: 'assistant:usage', ...st.usageView }); usage.setConnection('reconnecting'); }
681
734
  let usageFetchSeq = 0;
682
735
  let usageSocketOpened = false;
@@ -721,6 +774,7 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
721
774
  clearTimeout(limitTimer);
722
775
  limitTimer = null;
723
776
  const limit = st.limit;
777
+ renderer.noteLimit(limit); // the waiting card of this turn's limit error counts to the reported reset
724
778
  limitEl.hidden = !limit;
725
779
  limitEl.dataset.status = limit?.status || '';
726
780
  const text = limitNoticeText(limit, tt);
@@ -870,7 +924,7 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
870
924
  return;
871
925
  case 'assistant:dispatch': {
872
926
  const run = runFromPayload(packet);
873
- if (run) { dock.upsertRun(run); renderer.upsertRunCard(dock.getRun(run.runId) || run); }
927
+ if (run) { dock.upsertRun(run); renderer.upsertRunCard(dock.getRun(run.runId) || run); tip('run', () => renderer.getRunCard(run.runId)); }
874
928
  return;
875
929
  }
876
930
  case 'assistant:permission-request':
@@ -914,7 +968,7 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
914
968
  switch (ev.type) {
915
969
  case 'synabun.dispatch': {
916
970
  const run = runFromPayload(ev);
917
- if (run) { dock.upsertRun(run); renderer.upsertRunCard(dock.getRun(run.runId) || run); }
971
+ if (run) { dock.upsertRun(run); renderer.upsertRunCard(dock.getRun(run.runId) || run); tip('run', () => renderer.getRunCard(run.runId)); }
918
972
  return;
919
973
  }
920
974
  case 'synabun.dispatch_result': {
@@ -972,7 +1026,7 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
972
1026
  const next = normalizeBrain({ ...st.brain, ...meta.brain, provider: meta.brain.provider || meta.brain.brain || st.brain.provider });
973
1027
  if (JSON.stringify(next) !== JSON.stringify(st.brain)) { st.brain = next; picker.render(); host.setBrain?.(next); persist(); }
974
1028
  } else if (typeof meta.brain === 'string') {
975
- const next = normalizeBrain({ ...st.brain, provider: meta.brain, model: meta.model ?? st.brain.model, effort: meta.effort ?? st.brain.effort, accountId: meta.accountId ?? st.brain.accountId, mcpProfile: meta.mcpProfile ?? st.brain.mcpProfile, project: meta.cwd ?? st.brain.project });
1029
+ const next = normalizeBrain({ ...st.brain, provider: meta.brain, model: meta.model ?? st.brain.model, effort: meta.effort ?? st.brain.effort, accountId: meta.accountId ?? st.brain.accountId, tools: meta.tools ?? st.brain.tools, project: meta.cwd ?? st.brain.project });
976
1030
  if (JSON.stringify(next) !== JSON.stringify(st.brain)) { st.brain = next; picker.render(); host.setBrain?.(next); persist(); }
977
1031
  }
978
1032
  if (meta.budget && typeof meta.budget === 'object') budgetController.receiveSession(meta.budget);
@@ -1156,6 +1210,7 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
1156
1210
  if (st.computerRemote) { explainRemoteComputer(); return; }
1157
1211
  const next = enabled === true;
1158
1212
  const wasActive = st.desktopActive;
1213
+ if (next && !st.computerEffective) tip('computer', () => (isRendered(computerToggle.el) ? computerToggle.el : moreBtn));
1159
1214
  st.computerUse = next;
1160
1215
  st.computerEffective = next;
1161
1216
  persist();
@@ -1181,7 +1236,7 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
1181
1236
  elapsedMs: st.turnStartedAt ? Date.now() - st.turnStartedAt : 0,
1182
1237
  }) : null;
1183
1238
  const answer = wasRunning && !aborted ? renderer.turnAnswer() : '';
1184
- renderer.finishTurn({ holdMs: pose ? MASCOT_TIMING.oneShotMs[pose] : 0 });
1239
+ renderer.finishTurn({ holdMs: pose ? MASCOT_TIMING.oneShotMs[pose] : 0, guess: !aborted && !errored });
1185
1240
  if (wasRunning) director.turnEnded(pose);
1186
1241
  if (answer && !silent) announce(tt('assistant.announce.replied', 'SynaBun replied: {text}', { text: answer }));
1187
1242
  st.running = false;
@@ -1221,6 +1276,8 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
1221
1276
  providerIcon,
1222
1277
  scrollEnd: () => renderer.scrollEnd(),
1223
1278
  onRespond: (n, decision) => respondControl(n, decision),
1279
+ // A question card's Esc, and its answer when focus was in it: back to the message box.
1280
+ focusComposer: () => composer.focus(),
1224
1281
  renderRoute: (_container, n) => mountRouteCard(n),
1225
1282
  });
1226
1283
  if (!entry) return;
@@ -1262,6 +1319,7 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
1262
1319
  renderer.appendNode(card.el);
1263
1320
  routeCards.set(card.routeId, card);
1264
1321
  routeChip.render();
1322
+ tip('route', () => card.el);
1265
1323
  requestAnimationFrame(() => { if (!destroyed && !card.collapsed) card.focusIfIdle(); });
1266
1324
  return card;
1267
1325
  }
@@ -1423,6 +1481,7 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
1423
1481
  compact();
1424
1482
  return true;
1425
1483
  case 'new':
1484
+ if (parsed.error === 'not_brain') { toast(notBrainText(parsed.provider)); return false; }
1426
1485
  newSession(parsed.provider || null);
1427
1486
  return true;
1428
1487
  case 'resume':
@@ -1430,8 +1489,9 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
1430
1489
  else renames.settled().then(() => { if (!destroyed) sock.send({ type: 'list_sessions' }); }); // a rename on its way is in the list
1431
1490
  return true;
1432
1491
  case 'stop':
1492
+ // /stop all: every run of the session, at once. /stop <target>: the one run it names, or nothing.
1433
1493
  if (parsed.all) await stopAll();
1434
- else if (parsed.target) await stopRun(parsed.target);
1494
+ else if (parsed.target) await stopNamedRun(parsed.target);
1435
1495
  else abort();
1436
1496
  return true;
1437
1497
  case 'agents': {
@@ -1449,6 +1509,7 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
1449
1509
  if (parsed.error) { toast(tt('assistant.slash.needsText', 'Usage: /remember <text>')); return false; }
1450
1510
  return queueOrSend({ ...payload, display: payload.text, text: tt('assistant.prompts.remember', 'Store this in SynaBun memory with the remember tool (pick a fitting category, project, tags and importance): {text}', { text: parsed.text }) });
1451
1511
  case 'model': {
1512
+ if (parsed.error === 'not_brain') { toast(notBrainText(parsed.provider)); return false; }
1452
1513
  if (!parsed.model && !parsed.provider) { picker.openField('model'); return true; }
1453
1514
  const next = { ...st.brain };
1454
1515
  let requiresSwitch = false;
@@ -1497,10 +1558,15 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
1497
1558
  }
1498
1559
  }
1499
1560
 
1561
+ /** /model or /new naming a provider that runs dispatched work only (none today: all four can be the brain). */
1562
+ function notBrainText(provider) {
1563
+ return tt('assistant.slash.notBrain', '{provider} runs dispatched work only, never the Assistant itself. Send it a task with /dispatch {id} <task>.', { provider: providerShortLabel(provider), id: provider });
1564
+ }
1565
+
1500
1566
  function dispatchErrorText(parsed) {
1501
1567
  switch (parsed.error) {
1502
- case 'missing_provider': return tt('assistant.slash.dispatchProvider', 'Usage: /dispatch <claude|codex|opencode> [flags] <task>');
1503
- case 'invalid_provider': return tt('assistant.slash.dispatchInvalidProvider', 'Unknown provider "{provider}". Use claude, codex or opencode.', { provider: parsed.provider });
1568
+ case 'missing_provider': return tt('assistant.slash.dispatchProvider', 'Usage: /dispatch <claude|codex|opencode|antigravity> [flags] <task>');
1569
+ case 'invalid_provider': return tt('assistant.slash.dispatchInvalidProvider', 'Unknown provider "{provider}". Use claude, codex, opencode or antigravity.', { provider: parsed.provider });
1504
1570
  case 'unknown_flag': return tt('assistant.slash.dispatchUnknownFlag', 'Unknown flag --{flag}', { flag: parsed.flag });
1505
1571
  case 'missing_flag_value': return tt('assistant.slash.dispatchFlagValue', 'Flag --{flag} needs a value', { flag: parsed.flag });
1506
1572
  case 'missing_task': return tt('assistant.slash.dispatchTask', 'Add the task text after the flags');
@@ -1514,7 +1580,7 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
1514
1580
  }
1515
1581
 
1516
1582
  async function dispatch(parsed, payload) {
1517
- const spec = buildDispatchSpec(parsed, st.brain, { assistantSessionId: sessionId });
1583
+ const spec = buildDispatchSpec(parsed, st.brain, { assistantSessionId: sessionId, toolCatalog: await fetchToolCatalog() });
1518
1584
  renderer.appendUser(payload.text);
1519
1585
  try {
1520
1586
  const res = await dispatchAssistantRun(spec);
@@ -1549,6 +1615,8 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
1549
1615
  }
1550
1616
 
1551
1617
  function newSession(provider) {
1618
+ // Only a brain provider names a new session's brain (Claude Code, Codex, OpenCode or Antigravity).
1619
+ if (provider && !isBrainProvider(provider)) provider = null;
1552
1620
  const b = provider ? normalizeBrain({ ...st.brain, provider, model: '', effort: null, agent: null, accountId: null }) : st.brain;
1553
1621
  // This one is still empty: it is the new session (the server keeps one draft, not a pile of them).
1554
1622
  // /new <provider> switches its brain as the picker does; what only this page showed (/help) is cleared.
@@ -1585,7 +1653,7 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
1585
1653
  if (meta.silent) return;
1586
1654
  if (meta.requiresSwitch) {
1587
1655
  const b = st.brain;
1588
- if (!meta.restartBrain) sock.send({ type: 'switch_brain', brain: b.provider, model: b.model || undefined, effort: b.effort || undefined, accountId: b.accountId || undefined, mcpProfile: b.mcpProfile || undefined, cwd: b.project || undefined, agent: b.agent || undefined, permissionMode: b.permissionMode, planMode: b.planMode === true });
1656
+ if (!meta.restartBrain) sock.send({ type: 'switch_brain', brain: b.provider, model: b.model || undefined, effort: b.effort || undefined, accountId: b.accountId || undefined, tools: b.tools ?? undefined, cwd: b.project || undefined, agent: b.agent || undefined, permissionMode: b.permissionMode, planMode: b.planMode === true });
1589
1657
  renderer.appendDivider(`${tt('assistant.status.brain', 'brain')} → ${brainLabel(b)}`);
1590
1658
  renderer.forgetSeen(); // the new brain's ids start over
1591
1659
  } else if (before.permissionMode !== st.brain.permissionMode || !!before.planMode !== !!st.brain.planMode) {
@@ -1605,6 +1673,33 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
1605
1673
  });
1606
1674
  }
1607
1675
 
1676
+ // "Continue with another provider" on the Assistant's own limit-wait card: the same model menu
1677
+ // the toolbar's model field opens (never a native select), minus the limited provider, then the
1678
+ // existing switch (applyBrain → switch_brain) and, where the blocked prompt is known, Retry now's
1679
+ // own resend (submit) — in that order, so the server sees the switch before the retried prompt.
1680
+ function continueOnAnotherProvider(anchor, { excludeProvider = '', retryText = '' } = {}) {
1681
+ if (!anchor) return;
1682
+ const providers = BRAIN_PROVIDERS.filter((p) => p !== excludeProvider);
1683
+ if (!providers.length) return;
1684
+ openModelMenu(anchor, {
1685
+ brain: st.brain,
1686
+ t,
1687
+ providers,
1688
+ title: tt('assistant.limitWait.switchProvider', 'Continue with another provider'),
1689
+ warnSwitch: true,
1690
+ allowCustom: false, // a custom id here would resolve to the (still limited) current provider
1691
+ onToast: toast,
1692
+ onManageModels: () => openModels(),
1693
+ onSelect: async (target) => {
1694
+ if (!target?.provider) return;
1695
+ await picker.switchProvider(target.provider, target.model || '');
1696
+ if (destroyed) return;
1697
+ renderer.clearLimitWait();
1698
+ if (retryText) submit(clickPayload(retryText));
1699
+ },
1700
+ }).catch(() => {});
1701
+ }
1702
+
1608
1703
  // ── Runs ──
1609
1704
  async function focusRun(runId) {
1610
1705
  if (!runId) return;
@@ -1638,9 +1733,29 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
1638
1733
  }
1639
1734
  }
1640
1735
 
1736
+ /**
1737
+ * /stop <target>: the run of this session it names (its id or the start of it, its title, the words
1738
+ * of its title: asst-stop.js), and only that one. A target that fits none, or more than one, stops nothing.
1739
+ */
1740
+ async function stopNamedRun(target) {
1741
+ const found = resolveStopTarget(target, dock.getRuns());
1742
+ if (found.run && !found.error) return stopRun(found.run.runId);
1743
+ if (found.passthrough) return stopRun(found.passthrough); // a full id the tray has not loaded: the server knows
1744
+ const name = (run) => `${run.title || run.runId}${run.title ? ` (${String(run.runId).slice(0, 8)})` : ''}`;
1745
+ const message = found.error === 'ambiguous'
1746
+ ? tt('assistant.slash.stopAmbiguous', '"{target}" matches {count} agents: {list}. Nothing was stopped; name one of them.', { target, count: found.matches.length, list: found.matches.map(name).join(', ') })
1747
+ : found.error === 'finished'
1748
+ ? tt('assistant.slash.stopFinished', '{name} has already finished.', { name: name(found.run) })
1749
+ : tt('assistant.slash.stopNoMatch', 'No agent of this session matches "{target}". Nothing was stopped; /agents lists them.', { target });
1750
+ renderer.appendStatus(message);
1751
+ }
1752
+
1641
1753
  async function stopAll() {
1642
- try { await killAllAssistantRuns(sessionId); toast(tt('assistant.status.stopAllRequested', 'Stopping all dispatched agents…')); }
1643
- catch (err) { renderer.appendError(`${tt('assistant.status.stopFailed', 'Stop failed')}: ${err?.message || err}`); }
1754
+ try {
1755
+ const res = await killAllAssistantRuns(sessionId);
1756
+ const count = Array.isArray(res?.stopped) ? res.stopped.length : null;
1757
+ toast(count === null ? tt('assistant.status.stopAllRequested', 'Stopping all dispatched agents…') : plural(tt, 'assistant.status.stopAllDone', count, 'Stopped {count} agent.', 'Stopped {count} agents.'));
1758
+ } catch (err) { renderer.appendError(`${tt('assistant.status.stopFailed', 'Stop failed')}: ${err?.message || err}`); }
1644
1759
  }
1645
1760
 
1646
1761
  async function escalateRun(runId, target) {
@@ -1852,6 +1967,7 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
1852
1967
  items.push({ kind: 'info', label: tt('assistant.topbar.cost', 'Session cost'), value: fmtCost(totalCost()) || '$0.00' });
1853
1968
  if (Number(st.dispatchUsd) > 0) items.push({ kind: 'info', label: tt('assistant.topbar.agentsCost', 'Agents'), value: fmtCost(st.dispatchUsd) });
1854
1969
  openMenu(moreBtn, { label: tt('assistant.toolbar.more', 'More options'), items, role: 'menu', placement: 'below', width: 280 });
1970
+ tip('more', () => document.querySelector('.asst-dd-menu'));
1855
1971
  }
1856
1972
 
1857
1973
  // Assistant → Models: switch models off (hidden from routing, dispatch and every model menu).
@@ -2145,6 +2261,22 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
2145
2261
  resume,
2146
2262
  setRouteMode: (mode) => setRouteMode(mode),
2147
2263
  setComputerUse: (enabled) => setComputerUse(enabled),
2264
+ /**
2265
+ * What the Workspace tour presents on (public/shared/tour/): this panel's own board,
2266
+ * its controls and its director, while the empty state shows its character and nothing
2267
+ * runs. null otherwise (the tour then uses a session-free preview).
2268
+ */
2269
+ tourHost() {
2270
+ const hero = renderer.mascot();
2271
+ if (destroyed || st.running || hero?.kind !== 'hero' || hero.parked?.()) return null;
2272
+ return {
2273
+ root, transcript: transcriptEl, announcer, bar: barEl, renderer, director, composer,
2274
+ live: true,
2275
+ computer: computerAvailable(),
2276
+ refreshStarters: () => renderer.refreshEmpty(),
2277
+ focusComposer: () => composer.focus(),
2278
+ };
2279
+ },
2148
2280
  attachMemory: (node) => composer.addMemory(node),
2149
2281
  attachImageDataUrl: (dataUrl, name) => composer.addImageDataUrl(dataUrl, name),
2150
2282
  insertText: (text) => composer.insertText(text),
@@ -8,9 +8,9 @@
8
8
  // mascot stands over its task class's scene (asst-scenes.js; the motion is
9
9
  // asst-scene-styles.js): one column, as wide as the scene.
10
10
  //
11
- // Rules: gold only means live (the awake row's ring and tick, the caret, the
12
- // sweep); a rack a card holds (data-state="waiting") drops its gold: "Waiting
13
- // for you" in the warn tone with ◆, no caret, stopped clocks. Motion answers
11
+ // Rules: gold only means live (the awake row's ring and tick, the bubble's
12
+ // verb, the sweep); a rack a card holds (data-state="waiting") drops its gold:
13
+ // "Waiting for you" in the warn tone with ◆, stopped clocks. Motion answers
14
14
  // events and stays under 300 ms; infinite animations run only on the live
15
15
  // rack, pause while the UI is dragged (body.ui-interacting) and everything is
16
16
  // static under prefers-reduced-motion (the sweep is not drawn at all). No
@@ -117,6 +117,7 @@ export const RACK_CSS = `
117
117
  grid-area: caption;
118
118
  align-self: end;
119
119
  min-width: 0;
120
+ margin-left: 8px; /* flush with the bubble's body (its notch takes the first 8px) */
120
121
  margin-bottom: 6px; /* the gap over the bubble: an empty caption takes no room */
121
122
  overflow: hidden;
122
123
  display: -webkit-box;
@@ -128,95 +129,107 @@ export const RACK_CSS = `
128
129
  }
129
130
  .asst-rack-caption:empty { display: none; }
130
131
 
132
+ /* ── The bubble: one 18px line (verb · subject · clock), 32px tall at one line, the ledger row's height.
133
+ The verb is gold only while the call runs; the mascot (and the sweep) carry the motion, the bubble
134
+ carries the words and, at the end of the line in the quietest tone, the numbers. Opaque fill (the
135
+ card under the panel tint), so the notch can cover the ring where it meets the edge: no seam. */
131
136
  .asst-bubble {
137
+ --rk-bubble-bg: linear-gradient(var(--rk-fill-1), var(--rk-fill-1)), var(--rk-card);
132
138
  grid-area: bubble;
133
139
  position: relative;
134
140
  justify-self: start;
135
141
  align-self: start;
136
- display: grid;
137
- grid-template-columns: auto minmax(0, 1fr);
138
- align-items: baseline;
139
- column-gap: 7px;
140
- row-gap: 1px;
142
+ display: block; /* a block, not a flex column: a flex item's -webkit-box is blockified and loses its line clamp */
141
143
  max-width: calc(100% - 8px);
142
144
  min-width: 0;
143
145
  margin-left: 8px;
144
- padding: 6px 11px 7px;
145
- border-radius: 3px 12px 12px 12px;
146
- background: var(--rk-fill-1);
146
+ padding: 7px 10px;
147
+ border-radius: 3px 10px 10px 10px;
148
+ background: var(--rk-bubble-bg);
147
149
  box-shadow: inset 0 0 0 1px var(--rk-line);
148
150
  }
149
- /* The tail: an 8px notch on the bubble's edge pointing at the mascot (left beside it, up under it). */
151
+ /* The tail: a 7px notch pointing at the mascot (left beside it, up under it), centred on the first line and
152
+ on the mascot's eyes. An 11px square turned 45° and cut to a triangle, 1px into the bubble so it paints
153
+ over the ring: the ring stops at the notch's legs, no double edge. */
150
154
  .asst-bubble::before {
151
155
  content: '';
152
156
  position: absolute;
153
- left: -5.5px;
154
- top: 7px;
157
+ left: -4.5px;
158
+ top: 10.5px;
155
159
  width: 11px;
156
160
  height: 11px;
157
- background: var(--rk-fill-1);
161
+ background: var(--rk-bubble-bg);
158
162
  box-shadow: inset 1px -1px 0 var(--rk-line);
159
163
  clip-path: polygon(0 0, 0 100%, 100% 100%);
160
164
  transform: rotate(45deg);
161
165
  pointer-events: none;
162
166
  }
163
- .asst-bubble-verb { color: var(--rk-text-2); font-size: 12px; font-weight: 500; line-height: 1.5; white-space: nowrap; }
167
+ /* The line: one text flow, two lines at most (six opened), of the verb, the subject (cut by asst-render.js
168
+ until nothing is clamped) and the numbers, which take the end of the subject's last line and wrap
169
+ under it as a unit when they are long (a computer action and its clock). 2px of room around it for
170
+ the subject's focus ring. */
171
+ .asst-bubble-line {
172
+ display: -webkit-box;
173
+ -webkit-box-orient: vertical;
174
+ -webkit-line-clamp: 2;
175
+ min-width: 0;
176
+ margin: -2px -3px;
177
+ padding: 2px 3px;
178
+ overflow: hidden;
179
+ /* The strut sets the 18px pitch; the words inside sit at line-height 1, so no mix of sizes or fonts grows a line. */
180
+ font-size: 12px;
181
+ line-height: 18px;
182
+ overflow-wrap: anywhere;
183
+ }
184
+ .asst-bubble-line:has(> .asst-bubble-subject[aria-expanded="true"]) { -webkit-line-clamp: 6; }
185
+ .asst-bubble-verb { color: var(--rk-text-2); font-size: 12px; font-weight: 500; line-height: 1; white-space: nowrap; }
186
+ .asst-bubble-verb:not(:empty) { margin-right: 7px; }
164
187
  .asst-bubble[data-state="running"] .asst-bubble-verb { color: var(--rk-gold); }
165
- /* A card holds the call: no gold, no caret, the clock stopped (asst-render.js), "◆ Waiting for you". */
188
+ /* A card holds the call: no gold, the clock stopped (asst-render.js), "◆ Waiting for you". */
166
189
  .asst-bubble[data-state="waiting"] .asst-bubble-verb { color: var(--rk-warn); }
167
190
  .asst-bubble[data-state="waiting"] .asst-bubble-verb::before { content: '◆'; margin-right: 5px; font-size: 9px; vertical-align: 1px; }
168
191
  .asst-bubble-subject {
169
192
  --rk-cut: middle; /* where asst-render.js cuts a long subject: the middle; the head on a narrow stage */
170
193
  position: relative;
171
- min-width: 0;
172
- overflow: hidden;
173
- display: -webkit-box;
174
- -webkit-box-orient: vertical;
175
- -webkit-line-clamp: 2;
176
194
  border-radius: 4px;
177
195
  color: var(--rk-text);
178
196
  font-size: 12px;
179
- line-height: 1.5;
180
- overflow-wrap: anywhere;
197
+ line-height: 1;
181
198
  cursor: pointer;
182
199
  }
183
200
  .asst-bubble-subject.is-mono { font-family: var(--rk-mono); font-size: 11.5px; }
184
201
  .asst-bubble-subject.is-muted { color: var(--rk-text-3); }
185
- .asst-bubble-subject[aria-expanded="true"] { -webkit-line-clamp: 6; cursor: text; user-select: text; }
202
+ .asst-bubble-subject[aria-expanded="true"] { cursor: text; user-select: text; }
186
203
  .asst-bubble-subject .is-dim { color: var(--rk-text-3); }
187
204
  .asst-bubble-subject .is-strong { color: var(--rk-text); font-weight: 600; }
188
- /* Streaming thinking fades in from its cut edge. */
189
- .asst-bubble[data-kind="think"][data-state="running"] .asst-bubble-subject {
205
+ /* A URL or path: one piece per span, a <wbr> between them (asst-render.js writeSubject), so it wraps after "/"
206
+ and at its other separators, never mid-word; a piece wider than its line is cut instead (fitSubject). The
207
+ rest of the subject wraps as the line says. Opened, the whole literal shows: a piece may break again. */
208
+ .asst-bubble-piece { white-space: nowrap; }
209
+ .asst-bubble-subject[aria-expanded="true"] .asst-bubble-piece { white-space: normal; }
210
+ /* Streaming thinking cut from its head ("…the end of the thought") fades in from the cut; whole text is left alone. */
211
+ .asst-bubble[data-kind="think"][data-state="running"] .asst-bubble-subject.is-cut {
190
212
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 12px);
191
213
  mask-image: linear-gradient(90deg, transparent, #000 12px);
192
214
  }
193
- .asst-bubble-caret {
194
- display: none;
195
- width: 6px;
196
- height: 12px;
197
- margin-left: 3px;
198
- vertical-align: -2px;
199
- background: var(--rk-gold);
200
- }
201
- .asst-bubble[data-state="running"] .asst-bubble-caret { display: inline-block; animation: asst-rk-caret 1.06s steps(1) infinite; }
202
215
  .asst-bubble-meta {
203
- grid-column: 2;
204
- display: flex;
205
- flex-wrap: wrap;
206
- gap: 2px 12px;
216
+ display: inline-flex;
217
+ gap: 0 8px;
218
+ margin-left: 7px;
207
219
  color: var(--rk-text-3);
208
220
  font-size: 11px;
209
- line-height: 1.5;
221
+ line-height: 1; /* inside the 18px strut: the smaller type never grows the line */
222
+ white-space: nowrap;
210
223
  font-variant-numeric: tabular-nums;
211
224
  }
212
225
  .asst-bubble-meta:empty { display: none; }
213
226
  .asst-bubble-num { white-space: nowrap; }
214
227
  .asst-bubble-err {
215
- grid-column: 1 / -1;
216
228
  display: -webkit-box;
217
229
  -webkit-box-orient: vertical;
218
230
  -webkit-line-clamp: 2;
219
231
  min-width: 0;
232
+ margin-top: 2px;
220
233
  overflow: hidden;
221
234
  color: var(--rk-red);
222
235
  font-family: var(--rk-mono);
@@ -228,8 +241,8 @@ export const RACK_CSS = `
228
241
  .asst-bubble-copy {
229
242
  position: relative;
230
243
  isolation: isolate;
231
- grid-column: 1 / -1;
232
- justify-self: start;
244
+ display: inline-flex;
245
+ align-items: center;
233
246
  height: var(--rk-pill-h);
234
247
  margin-top: 4px;
235
248
  padding: 0 var(--rk-pill-px);
@@ -242,7 +255,9 @@ export const RACK_CSS = `
242
255
  cursor: pointer;
243
256
  }
244
257
  .asst-bubble-copy:hover { color: var(--rk-text); }
245
- .asst-odo { display: inline-flex; font-variant-numeric: tabular-nums; white-space: pre; }
258
+ /* The clock: tabular digits that roll in place (asst-render.js); its cell keeps "59 s" of room, right-aligned, so
259
+ "9 s" → "10 s" moves nothing. */
260
+ .asst-odo { display: inline-flex; justify-content: flex-end; min-width: 2.4em; font-variant-numeric: tabular-nums; white-space: pre; }
246
261
  .asst-odo-d { display: inline-block; }
247
262
 
248
263
  .asst-rack-sweep { position: absolute; left: 0; right: 0; bottom: 0; height: 1.5px; overflow: hidden; pointer-events: none; }
@@ -553,9 +568,9 @@ export const RACK_CSS = `
553
568
  .asst-rack-stage { grid-template-columns: auto minmax(0, 1fr); grid-template-areas: "face caption" "bubble bubble"; column-gap: 8px; row-gap: 6px; }
554
569
  .asst-rack-set { align-self: center; flex-direction: row; }
555
570
  .asst-rack.is-staged > .asst-rack-stage { padding: 10px 10px 10px; }
556
- .asst-rack-caption { align-self: center; margin-bottom: 0; }
557
- .asst-bubble { justify-self: stretch; max-width: 100%; margin: 4px 0 0; border-radius: 3px 12px 12px 12px; }
558
- .asst-bubble::before { left: 30px; top: -5.5px; box-shadow: inset 1px 1px 0 var(--rk-line); clip-path: polygon(0 100%, 0 0, 100% 0); }
571
+ .asst-rack-caption { align-self: center; margin-left: 0; margin-bottom: 0; }
572
+ .asst-bubble { justify-self: stretch; max-width: 100%; margin: 4px 0 0; border-radius: 3px 10px 10px 10px; }
573
+ .asst-bubble::before { left: 30px; top: -4.5px; box-shadow: inset 1px 1px 0 var(--rk-line); clip-path: polygon(0 100%, 0 0, 100% 0); }
559
574
  .asst-station-hdr { gap: 8px; padding: 0 6px; }
560
575
  .asst-station-time { display: none; }
561
576
  .asst-tick.is-old { display: none; }
@@ -565,7 +580,8 @@ export const RACK_CSS = `
565
580
  .asst-station-sub { margin-left: 12px; }
566
581
  }
567
582
  @container asst (max-width: 320px) {
568
- .asst-bubble { padding: 5px 9px 6px; }
583
+ .asst-bubble { padding: 6px 9px; }
584
+ .asst-bubble::before { top: -4.5px; }
569
585
  .asst-bubble-subject { --rk-cut: head; }
570
586
  .asst-bubble-meta { display: none; }
571
587
  }
@@ -576,6 +592,7 @@ export const RACK_CSS = `
576
592
  }
577
593
 
578
594
  /* ── Motion ─────────────────────────────────────────────────────── */
595
+ /* The caret blink belongs to the scenes' code caret (asst-scene-styles.js); the bubble has none. */
579
596
  @keyframes asst-rk-caret { 0% { opacity: 1; } 50% { opacity: 0; } }
580
597
  @keyframes asst-rk-sweep { from { transform: translateX(-100%); } to { transform: translateX(270%); } }
581
598
  @keyframes asst-rk-tick { 0%, 100% { opacity: 1; } 50% { opacity: .4; } }