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
@@ -3,13 +3,12 @@
3
3
  import { clampEffortId, getEffortLevelsForModel, modelEffortIds, fetchClaudeAccounts, fetchCodexAccounts, getCachedClaudeAccounts, getCachedCodexAccounts, getClaudeWorkerAccountId, getCodexWorkerAccountId } from '../agent-runtime-options.js';
4
4
  import { accountSummary, accountName, accountBadge, accountIdentity } from '../account-view.js';
5
5
  import { accountUsageText, autoAccountLabel } from '../account-usage.js';
6
- import { getProviderMeta } from '../provider-icons.js';
7
6
  import { getRouting, putRouting } from './asst-api.js';
8
7
  import { catalogModelRow, hiddenModelFor, ICON_CARET, openModelMenu } from './asst-brain-picker.js';
9
8
  import { closeMenu, currentMenu } from './asst-menu.js';
10
9
  import { loadRouteModels, routeModelLabel, routeModelsStatus, watchRouteModels } from './asst-route-models.js';
11
10
  import { designRouteSight, openModelsManager, routeCatalogRow, routeModeLabel } from './asst-route.js';
12
- import { DEFAULT_ROUTE_MODE, normalizeRouteMode, ROUTE_MODES } from './asst-state.js';
11
+ import { DEFAULT_ROUTE_MODE, normalizeRouteMode, PROVIDERS, providerMeta, ROUTE_MODES } from './asst-state.js';
13
12
 
14
13
  const ICON_ROUTE = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round"><path d="M4 7h15l-4-4M20 17H5l4 4"/></svg>';
15
14
  const ICON_X = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round"><path d="m6 6 12 12M18 6 6 18"/></svg>';
@@ -37,7 +36,8 @@ function choiceKey(p) { return p ? JSON.stringify([p.kind || 'direct', p.provide
37
36
  export function routeAccountView(pref, task, brain, accounts, workers = {}, t = null) {
38
37
  const tr = translator(t);
39
38
  const empty = { label: tr('assistant.routes.editorUnusedValue', '—'), readOnly: true, options: [], hint: '' };
40
- if (!pref || pref.provider === 'opencode') return empty;
39
+ // Only Claude Code and Codex run under an account (OpenCode and Antigravity sign in inside their own CLIs).
40
+ if (!pref || pref.provider === 'opencode' || pref.provider === 'antigravity') return empty;
41
41
  const direct = task.id === 'chat' || routeExecutionKind(pref, task, brain) === 'direct';
42
42
  const provider = task.id === 'chat' ? brain.provider : pref.provider;
43
43
  if (!['claude-code', 'codex'].includes(provider)) return empty;
@@ -381,7 +381,8 @@ export async function openRoutesEditor(hooks = {}) {
381
381
  state.menuFocus = modelBtn.dataset.focusKey;
382
382
  const emptyLabel = task.requires ? tr('assistant.routes.noCapableModel', 'No model in your catalog can make {medium} yet.', { medium: tr(`assistant.routes.medium.${task.requires === 'video' ? 'videos' : 'images'}`, task.requires) }) : tr('assistant.routes.noSeeingModel', 'No model in your catalog can see images yet.');
383
383
  const menu = await openModelMenu(modelBtn, {
384
- brain: brain(), t: hooks.t, includeHere: true, hereLabel: tr('assistant.routes.brainDecides', 'Assistant chooses'), title: task.label,
384
+ // Every provider a route can name (Antigravity included).
385
+ brain: brain(), t: hooks.t, includeHere: true, hereLabel: tr('assistant.routes.brainDecides', 'Assistant chooses'), title: task.label, providers: PROVIDERS,
385
386
  current: pref ? { provider: pref.provider, model: pref.model } : null, onToast: hooks.onToast,
386
387
  routingEditor: true, onManageModels: () => manageModels(modelBtn.dataset.focusKey),
387
388
  ...(task.requires ? { accept: (_p, m) => m.outputs?.[task.requires] === true, allowCustom: false, emptyLabel } : {}),
@@ -400,7 +401,7 @@ export async function openRoutesEditor(hooks = {}) {
400
401
  // Keys are stable across translations; accessible names use the translated field.
401
402
  modelBtn.dataset.focusKey = `${task.id}-model`; caret(modelBtn); modelBtn.setAttribute('aria-haspopup', 'dialog');
402
403
  modelBtn.title = label;
403
- if (pref?.provider) { const mark = el('span', 'asst-icon'); mark.setAttribute('aria-hidden', 'true'); mark.innerHTML = getProviderMeta(pref.provider).icon; mark.style.color = getProviderMeta(pref.provider).color; modelBtn.prepend(mark); }
404
+ if (pref?.provider) { const mark = el('span', 'asst-icon'); mark.setAttribute('aria-hidden', 'true'); mark.innerHTML = providerMeta(pref.provider).icon; mark.style.color = providerMeta(pref.provider).color; modelBtn.prepend(mark); }
404
405
  modelCell.append(modelBtn);
405
406
  const source = el('span', 'asst-routes-source');
406
407
  let sourceText = pref ? tr('assistant.routes.source.yours', 'Your choice') : tr('assistant.routes.source.default', 'Assistant chooses');
@@ -433,14 +434,14 @@ export async function openRoutesEditor(hooks = {}) {
433
434
  if (effortValue !== unusedValue && effortValue !== effortText) effortBtn.setAttribute('aria-label', tr('assistant.routes.fieldLabel', '{task}: {field}, {value}', { task: task.label, field: tr('assistant.routes.columns.effort', 'Effort'), value: `${effortValue} · ${effortText}` }));
434
435
  const effortCell = el('div', 'asst-routes-cell asst-routes-effort-cell'); effortCell.append(el('span', 'asst-routes-cell-label', tr('assistant.routes.columns.effort', 'Effort')), effortBtn); node.append(effortCell);
435
436
  const kind = routeExecutionKind(pref, task, brain());
436
- const runLabel = task.id === 'chat' ? tr('assistant.routes.inConversation', 'In conversation') : !pref ? task.dispatchOnly ? tr('assistant.routes.workerChooses', 'Worker · assistant chooses') : tr('assistant.routes.brainDecides', 'Assistant chooses') : kind === 'direct' ? tr('assistant.routes.inConversation', 'In conversation') : tr('assistant.routes.onWorker', '{provider} worker', { provider: getProviderMeta(pref.provider).label });
437
+ const runLabel = task.id === 'chat' ? tr('assistant.routes.inConversation', 'In conversation') : !pref ? task.dispatchOnly ? tr('assistant.routes.workerChooses', 'Worker · assistant chooses') : tr('assistant.routes.brainDecides', 'Assistant chooses') : kind === 'direct' ? tr('assistant.routes.inConversation', 'In conversation') : tr('assistant.routes.onWorker', '{provider} worker', { provider: providerMeta(pref.provider).label });
437
438
  const run = fieldButton('asst-routes-run', task, tr('assistant.routes.columns.run', 'Runs in'), runLabel, () => openMenuFor(run, tr('assistant.routes.columns.run', 'Runs in'), [
438
439
  { kind: 'radio', id: 'direct', label: tr('assistant.routes.inConversation', 'In conversation'), desc: tr('assistant.routes.conversationDesc', 'Continue this conversation on the chosen model for this task.'), selected: kind === 'direct', onSelect: () => setChoice(task.id, { ...pref, kind: 'direct' }, run.dataset.focusKey) },
439
- { kind: 'radio', id: 'dispatch', label: tr('assistant.routes.onWorker', '{provider} worker', { provider: getProviderMeta(pref?.provider).label }), desc: tr('assistant.routes.workerDesc', 'Hand the task to a worker and show its result here.'), selected: kind === 'dispatch', onSelect: () => setChoice(task.id, { ...pref, kind: 'dispatch' }, run.dataset.focusKey) },
440
+ { kind: 'radio', id: 'dispatch', label: tr('assistant.routes.onWorker', '{provider} worker', { provider: providerMeta(pref?.provider).label }), desc: tr('assistant.routes.workerDesc', 'Hand the task to a worker and show its result here.'), selected: kind === 'dispatch', onSelect: () => setChoice(task.id, { ...pref, kind: 'dispatch' }, run.dataset.focusKey) },
440
441
  ]));
441
442
  run.dataset.focusKey = `${task.id}-run`; run.disabled = !pref || task.dispatchOnly || pref.provider !== brain().provider || task.id === 'chat';
442
443
  const inConversation = task.id === 'chat' || (pref && kind === 'direct');
443
- const runValue = inConversation ? tr('assistant.routes.editorInConversation', 'This conversation') : pref ? getProviderMeta(pref.provider).label : unusedValue;
444
+ const runValue = inConversation ? tr('assistant.routes.editorInConversation', 'This conversation') : pref ? providerMeta(pref.provider).label : unusedValue;
444
445
  run.querySelector('.asst-dd-label').textContent = runValue;
445
446
  if (inConversation) run.setAttribute('aria-label', tr('assistant.routes.fieldLabel', '{task}: {field}, {value}', { task: task.label, field: tr('assistant.routes.columns.run', 'Runs in'), value: runValue }));
446
447
  if (!run.disabled) caret(run);
@@ -116,8 +116,12 @@ export function runChip(run, t = tFallback) {
116
116
  }
117
117
  if (awaitsAnswer(run)) return { tone: 'action', label: t('assistant.run.waitingInput', 'waiting for your answer') };
118
118
  const tone = runTone(run);
119
+ // A held run whose card the user answered "here": the assistant does it, this worker never started.
120
+ if (run?.completionReason === 'route_here') return { tone, label: t('assistant.run.routedHere', 'not started: done here instead') };
119
121
  if (run?.turnState === 'awaiting_permission') return { tone, label: t('assistant.run.needsApproval', 'needs approval') };
120
122
  if (run?.turnState === 'needs_input') return { tone, label: t('assistant.run.needsInput', 'needs input') };
123
+ // A Claude Code worker a server restart cut off, until the next start has resumed it (lib/assistant-dispatch.js).
124
+ if (run?.state === 'suspended' || run?.state === 'resuming') return { tone, label: t('assistant.run.resuming', 'resuming after a server restart') };
121
125
  if (run?.queued && run.status !== 'running') return { tone, label: t('assistant.run.queued', 'queued') };
122
126
  if (isRunIdle(run)) {
123
127
  const outcome = run.outcome || run.lastResult?.status;
@@ -167,6 +171,46 @@ export const CODEX_ITEM_EVENTS = Object.freeze({
167
171
  */
168
172
  export const OPENCODE_TOOL_STATES = Object.freeze(['running', 'completed', 'error']);
169
173
 
174
+ // The path-like fields of an Antigravity tool call's arguments (lib/worker-confinement.js reads the same ones).
175
+ const ACP_PATH_KEYS = ['path', 'file_path', 'filePath', 'Path', 'AbsolutePath', 'TargetFile', 'DirectoryPath', 'SearchPath'];
176
+
177
+ /**
178
+ * An Antigravity (ACP) tool call as an activity: its `kind` says what it does (read, edit, delete,
179
+ * move, search, execute, think, fetch, switch_mode, other), its `rawInput` holds the tool's own
180
+ * arguments and its `locations` the files it touches. Another tool (an MCP server's) is read by its
181
+ * name, as for the other providers. null for a mode switch.
182
+ */
183
+ function acpToolActivity(call) {
184
+ const args = obj(call.rawInput);
185
+ const kind = str(call.kind) || 'other';
186
+ const title = str(call.title).trim();
187
+ const paths = [...new Set([
188
+ ...(Array.isArray(call.locations) ? call.locations : []).map((location) => str(location?.path)),
189
+ ...ACP_PATH_KEYS.map((key) => (typeof args[key] === 'string' ? args[key] : '')),
190
+ ].filter(Boolean))];
191
+ const pick = (...values) => values.map((v) => (typeof v === 'string' ? v.trim() : '')).find(Boolean) || '';
192
+ switch (kind) {
193
+ case 'execute': {
194
+ const command = Array.isArray(args.command) ? args.command.map(str).join(' ') : pick(args.command, args.CommandLine, args.cmd);
195
+ return { kind: 'shell', name: 'exec_command', input: { command: command || title } };
196
+ }
197
+ case 'read': return { kind: 'read', name: 'read', input: { file_path: paths[0] || title } };
198
+ case 'edit': case 'delete': case 'move':
199
+ return { kind: 'edit', name: kind === 'edit' ? 'edit' : 'apply_patch', input: paths.length > 1 ? { changes: paths.map((path) => ({ path })) } : { file_path: paths[0] || title } };
200
+ case 'search': return { kind: 'search', name: 'grep', input: { pattern: pick(args.pattern, args.query, args.Query, args.Pattern) || title, path: paths[0] || '' } };
201
+ case 'fetch': {
202
+ const url = pick(args.url, args.Url, args.href);
203
+ return url ? { kind: 'web', name: 'WebFetch', input: { url } } : { kind: 'web', name: 'WebSearch', input: { query: pick(args.query, args.Query) || title } };
204
+ }
205
+ case 'think': return { kind: 'think', name: 'thinking', input: {} };
206
+ case 'switch_mode': return null;
207
+ default: {
208
+ const name = pick(call.name, args.toolName, title) || 'tool';
209
+ return { kind: kindOf(name, args), name, input: args };
210
+ }
211
+ }
212
+ }
213
+
170
214
  /**
171
215
  * A worker's provider event ({ provider, eventType?, event }, the payload of
172
216
  * sync:sidepanel:provider-event) as what it is doing: { kind, name, input }
@@ -175,7 +219,11 @@ export const OPENCODE_TOOL_STATES = Object.freeze(['running', 'completed', 'erro
175
219
  * stage and the tray keep only compactActivity() of it. OpenCode names its
176
220
  * tools bash, read, edit, write, patch, glob, grep, list, webfetch,
177
221
  * websearch, codesearch, task, todowrite, and MCP tools `<server>_<tool>`
178
- * (SynaBun_browser_navigate): kindOf() reads all of them.
222
+ * (SynaBun_browser_navigate): kindOf() reads all of them. An Antigravity
223
+ * worker's events are ACP session updates (eventType = their `sessionUpdate`):
224
+ * a tool call when it is announced (`tool_call`, or an update that starts it
225
+ * and names its kind), a thought chunk as thinking, a plan as planning; its
226
+ * message text is no activity, as for the others.
179
227
  */
180
228
  export function activityOf(payload) {
181
229
  const provider = str(payload?.provider);
@@ -220,6 +268,13 @@ export function activityOf(payload) {
220
268
  const input = obj(part.state?.input);
221
269
  return { kind: kindOf(name, input), name, input };
222
270
  }
271
+ if (provider === 'antigravity') {
272
+ const type = str(payload.eventType || event.sessionUpdate);
273
+ if (type === 'agent_thought_chunk') return { kind: 'think', name: 'thinking', input: {} };
274
+ if (type === 'plan') return { kind: 'plan', name: 'update_plan', input: { todos: Array.isArray(event.entries) ? event.entries : [] } };
275
+ if (type === 'tool_call' || (type === 'tool_call_update' && str(event.kind) && event.status === 'in_progress')) return acpToolActivity(event);
276
+ return null;
277
+ }
223
278
  return null;
224
279
  }
225
280
 
@@ -22,7 +22,7 @@ import { getProviderMeta } from '../provider-icons.js';
22
22
  import { showGuestToast } from '../ui-sync.js';
23
23
  import { registerSidepanel, setSidepanelVisible, syncSidepanelLayout, focusSidepanel } from '../ui-sidepanel-windows.js';
24
24
  import {
25
- assistantBlocked, assistantOwnerOf, fetchLiveAssistantSessions, noteAssistantFocus, openAssistant, registerAssistantHost,
25
+ assistantBlocked, assistantOwnerOf, noteAssistantFocus, openAssistant, readLiveAssistantSessions, registerAssistantHost,
26
26
  } from '../ui-assistant.js';
27
27
  import { mountAssistant } from './asst-panel.js';
28
28
  import { openModelsManager } from './asst-route.js';
@@ -30,6 +30,7 @@ import { brainLabel, readStoredBrain, restoredSessionName } from './asst-state.j
30
30
  import { closeMenu, isMenuOpen, openMenu } from './asst-menu.js';
31
31
  import { injectAssistantSidepanelStyles } from './asst-sidepanel-styles.js';
32
32
  import { createMascot, mascotCameoSvg } from '../synabun-mascot.js';
33
+ import { createTutorialPreview } from '../ui-tutorial-preview.js';
33
34
 
34
35
  const PANEL_OWNER = 'assistant-sidepanel';
35
36
  const HOST_ID = 'sidepanel';
@@ -55,6 +56,12 @@ let _toastTimer = null;
55
56
  let _renaming = false;
56
57
  const _tabs = []; // { sessionId, viewport, toolbar, ctl, pill, label, userRenamed, status, brain }
57
58
  let _activeIdx = -1;
59
+ let _tourPresenting = false;
60
+ // The saved tabs ({ activeIdx, tabs }) while the session list could not be read (a server that is
61
+ // starting answers before its Assistant routes exist): they stay saved and are asked about again.
62
+ let _unrestored = null;
63
+ let _restoring = null; // that restore under way: a session start waits for it
64
+ const RESTORE_RETRY_MS = [500, 1000, 2000, 4000, 8000, 15_000];
58
65
 
59
66
  // ── Helpers ──────────────────────────────────────────────────────────────────
60
67
 
@@ -92,11 +99,13 @@ function conversationOf(tab) {
92
99
 
93
100
  function saveTabs() {
94
101
  try {
95
- if (!_tabs.length) { storage.removeItem(KEYS.ASSISTANT_PANEL_TABS); return; }
102
+ // Saved tabs not restored yet stay saved (their names with them), after the open ones.
103
+ const waiting = (_unrestored?.tabs || []).filter(entry => !findTab(entry.sessionId));
104
+ if (!_tabs.length) { if (!waiting.length) storage.removeItem(KEYS.ASSISTANT_PANEL_TABS); return; }
96
105
  storage.setItem(KEYS.ASSISTANT_PANEL_TABS, JSON.stringify({
97
106
  v: 1,
98
107
  activeIdx: Math.max(0, _activeIdx),
99
- tabs: _tabs.map(tab => ({ sessionId: tab.sessionId, label: tab.userRenamed ? tab.label : '', userRenamed: !!tab.userRenamed })),
108
+ tabs: [..._tabs.map(tab => ({ sessionId: tab.sessionId, label: tab.userRenamed ? tab.label : '', userRenamed: !!tab.userRenamed })), ...waiting],
100
109
  }));
101
110
  } catch { /* storage unavailable */ }
102
111
  }
@@ -408,13 +417,23 @@ function focusSession(sessionId, { prompt = '' } = {}) {
408
417
  if (prompt) _tabs[idx].ctl?.send(prompt);
409
418
  }
410
419
 
411
- async function startSession() {
420
+ async function startSession(prompt = '') {
412
421
  if (_starting || _tabs.length) return;
413
422
  _starting = true;
414
423
  _startError = '';
415
424
  renderPlaceholder('starting');
416
425
  try {
417
- const res = await openAssistant({ host: HOST_ID });
426
+ // The saved tabs come back before a new session is made: the restore under way (the server is
427
+ // starting), or once more for the ones it could not ask about.
428
+ if (!_restoring && _unrestored) startRestore(_unrestored, []);
429
+ if (_restoring) await _restoring.catch(() => { /* a new session, then */ });
430
+ if (_tabs.length) {
431
+ const tab = activeTab() || _tabs[0];
432
+ switchTo(_tabs.indexOf(tab));
433
+ if (prompt) { tab.ctl?.insertText?.(prompt); tab.ctl?.focus?.(); } // a conversation's draft, never sent for them
434
+ return;
435
+ }
436
+ const res = await openAssistant(prompt ? { host: HOST_ID, prompt } : { host: HOST_ID });
418
437
  if (!_tabs.length) renderPlaceholder(res ? null : 'failed');
419
438
  } finally {
420
439
  _starting = false;
@@ -563,8 +582,8 @@ function applyVisibility(nextVisible) {
563
582
  const tab = activeTab();
564
583
  if (_visible) {
565
584
  state.lastActivePanel = 'assistant';
566
- if (!_tabs.length) startSession();
567
- else if (tab) {
585
+ if (!_tabs.length && !_tourPresenting) startSession();
586
+ else if (tab && !_tourPresenting) {
568
587
  if (tab.status === 'done') tab.status = 'idle';
569
588
  try { tab.ctl?.onShown(); } catch { /* ignore */ }
570
589
  noteAssistantFocus(tab.sessionId, HOST_ID);
@@ -617,6 +636,67 @@ export function assistantPanelPeekable() {
617
636
  return !assistantBlocked() && _tabs.length > 0;
618
637
  }
619
638
 
639
+ /**
640
+ * Present the panel for the Workspace tour (ui-tutorial.js), reversibly: it never
641
+ * creates a session. The tour plays on the active tab when its empty state shows
642
+ * its character (the tab's own controls, composer and director: tourHost());
643
+ * otherwise (no tab, or a conversation on screen) on a session-free preview laid
644
+ * over the tab. Returns { host, live, restore({ reason }) } or null when the
645
+ * Assistant is blocked. restore() puts back the panel's visibility, the docked
646
+ * peers and the last-active panels, unless the tour ended on its hand-off to a
647
+ * live tab ('done'): then the panel stays and the tab's composer takes the focus.
648
+ */
649
+ export function beginAssistantTour({ onPreviewSend = () => {} } = {}) {
650
+ if (assistantBlocked()) return null;
651
+ ensurePanel();
652
+ const wasVisible = _visible;
653
+ const previousPanel = state.lastActivePanel;
654
+ const previousSidepanel = state.lastActiveSidepanel;
655
+ const peers = ['#topright-claude-panel-btn', '#topright-codex-panel-btn', '#topright-opencode-panel-btn', '#topright-antigravity-panel-btn']
656
+ .map(s => document.querySelector(s)).filter(b => b?.classList.contains('active'));
657
+ _tourPresenting = true;
658
+ const tab = activeTab();
659
+ let liveHost = null;
660
+ try { liveHost = tab?.ctl?.tourHost?.() || null; } catch { liveHost = null; }
661
+ const preview = liveHost ? null : createTutorialPreview(_panel, { onSend: (text) => onPreviewSend(text) });
662
+ if (preview) _panel.classList.add('tour-covering');
663
+ setVisible(true);
664
+ let restored = false;
665
+ const host = liveHost || preview.host;
666
+ return {
667
+ host,
668
+ live: !!liveHost,
669
+ /**
670
+ * The user sent `text` from the preview's composer (after restore({ reason: 'sent' })):
671
+ * with no session, it starts one with that message (the user's own send); with a
672
+ * conversation on screen, it becomes that conversation's draft, never sent for them.
673
+ */
674
+ deliver(text) {
675
+ const message = String(text || '').trim();
676
+ if (!message) return;
677
+ const current = activeTab();
678
+ if (current?.ctl) { focusSession(current.sessionId); current.ctl.insertText?.(message); current.ctl.focus?.(); return; }
679
+ startSession(message);
680
+ },
681
+ restore({ reason = 'skip' } = {}) {
682
+ if (restored) return;
683
+ restored = true;
684
+ closeMenu();
685
+ preview?.destroy();
686
+ _panel.classList.remove('tour-covering');
687
+ _tourPresenting = false;
688
+ const keep = (reason === 'done' && !!liveHost) || reason === 'sent';
689
+ if (keep) {
690
+ if (tab && findTab(tab.sessionId)) { try { tab.ctl?.onShown(); } catch { /* ignore */ } }
691
+ return;
692
+ }
693
+ if (!wasVisible) setVisible(false);
694
+ for (const button of peers) if (!button.classList.contains('active')) button.click();
695
+ state.lastActivePanel = previousPanel; state.lastActiveSidepanel = previousSidepanel;
696
+ },
697
+ };
698
+ }
699
+
620
700
  /** The top-right SynaBun button. */
621
701
  export async function toggleAssistantPanel() {
622
702
  if (assistantBlocked()) {
@@ -668,7 +748,30 @@ export async function initAssistantPanel() {
668
748
 
669
749
  const saved = readSavedTabs();
670
750
  if (!saved?.tabs.length) return;
671
- const live = await fetchLiveAssistantSessions();
751
+ await startRestore(saved, RESTORE_RETRY_MS);
752
+ }
753
+
754
+ function startRestore(saved, retries) {
755
+ _restoring = restoreSavedTabs(saved, retries).finally(() => { _restoring = null; });
756
+ return _restoring;
757
+ }
758
+
759
+ /**
760
+ * The saved tabs come back (hidden, as pills) for the sessions the server still has open. A list
761
+ * that cannot be read restores nothing and forgets nothing: the tabs stay saved, names included
762
+ * (saveTabs), the list is asked again after each wait of `retries`, then at the next session start.
763
+ */
764
+ async function restoreSavedTabs(saved, retries) {
765
+ _unrestored = saved;
766
+ let live = await readLiveAssistantSessions();
767
+ for (const wait of retries) {
768
+ if (live || assistantBlocked()) break;
769
+ await new Promise(done => setTimeout(done, wait));
770
+ live = await readLiveAssistantSessions();
771
+ }
772
+ if (!live) return;
773
+ _unrestored = null;
774
+ const hadTabs = _tabs.length > 0; // one opened meanwhile stays the one showing
672
775
  for (const entry of saved.tabs) {
673
776
  const meta = live.get(entry.sessionId);
674
777
  if (!meta) continue;
@@ -683,8 +786,12 @@ export async function initAssistantPanel() {
683
786
  restoring: true,
684
787
  });
685
788
  }
686
- if (_tabs.length) {
687
- _activeIdx = Math.min(Math.max(0, saved.activeIdx), _tabs.length - 1);
789
+ if (_tabs.length && !hadTabs) {
790
+ // The tab that was showing, by its session: a saved tab before it that did not come back (a draft,
791
+ // an ended session) must not hand the header to its neighbour.
792
+ const shownId = saved.tabs[saved.activeIdx]?.sessionId;
793
+ const shown = _tabs.findIndex(tab => tab.sessionId === shownId);
794
+ _activeIdx = shown >= 0 ? shown : Math.min(Math.max(0, saved.activeIdx), _tabs.length - 1);
688
795
  markActive();
689
796
  renderHeader();
690
797
  renderPills();
@@ -4,10 +4,10 @@
4
4
  // Pure module (no DOM, no i18n import) so node:test can exercise it. The
5
5
  // composer resolves `descKey` through i18n and falls back to `desc`.
6
6
 
7
- import { normalizeComputerMode, normalizeProvider, normalizeRouteMode } from './asst-state.js';
7
+ import { isBrainProvider, normalizeComputerMode, normalizeProvider, normalizeRouteMode } from './asst-state.js';
8
8
 
9
9
  export const SLASH_COMMANDS = [
10
- { name: 'dispatch', usage: '/dispatch <provider> [--model m] [--effort e] [--agent a] [--project p] [--mcp profile] [--account id] [--ask] [--title "t"] <task>', descKey: 'assistant.slash.dispatch', desc: 'Dispatch a task to a sidepanel agent' },
10
+ { name: 'dispatch', usage: '/dispatch <provider> [--model m] [--effort e] [--agent a] [--project p] [--tools a,b] [--account id] [--ask] [--title "t"] <task>', descKey: 'assistant.slash.dispatch', desc: 'Dispatch a task to a sidepanel agent' },
11
11
  { name: 'agents', usage: '/agents [all]', descKey: 'assistant.slash.agents', desc: 'List dispatched runs' },
12
12
  { name: 'recall', usage: '/recall <query>', descKey: 'assistant.slash.recall', desc: 'Search memories' },
13
13
  { name: 'remember', usage: '/remember <text>', descKey: 'assistant.slash.remember', desc: 'Store a memory' },
@@ -17,7 +17,7 @@ export const SLASH_COMMANDS = [
17
17
  { name: 'models', usage: '/models [list | archived | hide <id…> | show <id…>]', descKey: 'assistant.slash.models', desc: 'Switch models off or on for the Assistant (or open the Models list)' },
18
18
  { name: 'budget', usage: '/budget', descKey: 'assistant.slash.budget', desc: 'Set the session budget and view provider shares' },
19
19
  { name: 'computer', usage: '/computer [on|off]', descKey: 'assistant.slash.computer', desc: 'Let the assistant use your Mac' },
20
- { name: 'stop', usage: '/stop [runId|all]', descKey: 'assistant.slash.stop', desc: 'Stop a run, everything, or the current turn' },
20
+ { name: 'stop', usage: '/stop [runId|title|all]', descKey: 'assistant.slash.stop', desc: 'Stop a run, everything, or the current turn' },
21
21
  { name: 'new', usage: '/new [provider]', descKey: 'assistant.slash.new', desc: 'Start a fresh session' },
22
22
  { name: 'resume', usage: '/resume [sessionId]', descKey: 'assistant.slash.resume', desc: 'Resume a previous session' },
23
23
  { name: 'compact', usage: '/compact', descKey: 'assistant.slash.compact', desc: 'Compact the context' },
@@ -33,7 +33,7 @@ export const DISPATCH_FLAGS = {
33
33
  effort: 'effort', e: 'effort',
34
34
  agent: 'agent',
35
35
  project: 'project', p: 'project', cwd: 'project',
36
- mcp: 'mcp', profile: 'mcp',
36
+ tools: 'tools',
37
37
  account: 'account', a: 'account',
38
38
  title: 'title', t: 'title',
39
39
  budget: 'budget',
@@ -143,6 +143,8 @@ function parseModel(rest) {
143
143
  provider = normalizeProvider(first);
144
144
  model = null;
145
145
  }
146
+ // /model switches the brain: a provider that only runs dispatched work (none of the four today) is refused, not swapped.
147
+ if (provider && !isBrainProvider(provider)) return { name: 'model', provider, model, effort: tokens[1] || null, error: 'not_brain' };
146
148
  return { name: 'model', provider, model, effort: tokens[1] || null };
147
149
  }
148
150
 
@@ -182,7 +184,11 @@ export function parseSlashCommand(text) {
182
184
  return enabled == null ? { name, mode: null, error: 'invalid_mode', value: restTrim } : { name, mode: enabled ? 'on' : 'off' };
183
185
  }
184
186
  case 'stop': return { name, target: restTrim && !/^all$/i.test(restTrim) ? restTrim : null, all: /^all$/i.test(restTrim) };
185
- case 'new': return { name, provider: restTrim ? normalizeProvider(restTrim) : null };
187
+ case 'new': {
188
+ const provider = restTrim ? normalizeProvider(restTrim) : null;
189
+ // A new session's brain: a provider that only runs dispatched work cannot be one (Antigravity can, since it runs the brain too).
190
+ return provider && !isBrainProvider(provider) ? { name, provider, error: 'not_brain' } : { name, provider };
191
+ }
186
192
  case 'resume': return { name, sessionId: restTrim || null };
187
193
  case 'compact':
188
194
  case 'clear':
@@ -219,10 +225,10 @@ export function matchSlashCommands(query) {
219
225
 
220
226
  /**
221
227
  * Build the POST /api/assistant/dispatch body from a parsed /dispatch command.
222
- * Only explicit flags set model/effort — the brain's project, MCP profile and
228
+ * Only explicit flags set model/effort — the brain's project and
223
229
  * (same-provider) account are inherited, models are left to the server default.
224
230
  */
225
- export function buildDispatchSpec(parsed, brain = {}, { assistantSessionId = null } = {}) {
231
+ export function buildDispatchSpec(parsed, brain = {}, { assistantSessionId = null, toolCatalog = null } = {}) {
226
232
  if (!parsed || parsed.name !== 'dispatch' || parsed.error) return null;
227
233
  const o = parsed.options || {};
228
234
  const spec = {
@@ -236,8 +242,7 @@ export function buildDispatchSpec(parsed, brain = {}, { assistantSessionId = nul
236
242
  if (o.model) spec.model = o.model;
237
243
  if (o.effort) spec.effort = o.effort;
238
244
  if (o.agent) spec.agent = o.agent;
239
- const mcp = o.mcp || brain.mcpProfile;
240
- if (mcp) spec.mcpProfile = mcp;
245
+ if (o.tools !== undefined) spec.tools = String(o.tools).split(',').map(id => id.trim()).filter(Boolean);
241
246
  const account = o.account || (brain.provider === parsed.provider ? brain.accountId : null);
242
247
  if (account) {
243
248
  if (parsed.provider === 'codex') spec.codexAccountId = account;
@@ -247,6 +252,9 @@ export function buildDispatchSpec(parsed, brain = {}, { assistantSessionId = nul
247
252
  if (o.budget !== undefined && Number.isFinite(Number(o.budget))) spec.budgetUsd = Number(o.budget);
248
253
  if (o.minutes !== undefined && Number.isFinite(Number(o.minutes))) spec.maxMinutes = Number(o.minutes);
249
254
  if (o.browser) spec.usesBrowser = true;
255
+ // A browser-reading slash launch uses the workspace guard, just like a routed browser task.
256
+ // Group metadata comes from the catalog, never from a second list of browser ids.
257
+ if (o.browser || (spec.tools || []).some(id => id === 'all' || toolCatalog?.groups?.some(group => group.id === id && group.browser))) spec.capability = 'workspace';
250
258
  if (assistantSessionId) spec.assistantSessionId = assistantSessionId;
251
259
  return spec;
252
260
  }