synabun 2.1.0 → 2.2.1

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 (332) hide show
  1. package/CHANGELOG.md +139 -0
  2. package/README.md +1 -1
  3. package/docs/whatsapp.md +11 -11
  4. package/lib/client-config-repair.js +13 -9
  5. package/lib/external-tools.js +6 -5
  6. package/lib/update-snapshot.js +77 -3
  7. package/lib/virustotal.mjs +12 -1
  8. package/mcp-server/dist/index.js +1 -1
  9. package/mcp-server/dist/index.js.map +1 -1
  10. package/mcp-server/dist/services/budget-judgments.d.ts +1 -1
  11. package/mcp-server/dist/services/budget-judgments.d.ts.map +1 -1
  12. package/mcp-server/dist/services/budget-judgments.js +5 -3
  13. package/mcp-server/dist/services/budget-judgments.js.map +1 -1
  14. package/mcp-server/dist/services/identity.d.ts +2 -2
  15. package/mcp-server/dist/services/identity.js +2 -2
  16. package/mcp-server/dist/services/memory-sessions.d.ts +1 -1
  17. package/mcp-server/dist/services/memory-sessions.d.ts.map +1 -1
  18. package/mcp-server/dist/services/memory-sessions.js +28 -2
  19. package/mcp-server/dist/services/memory-sessions.js.map +1 -1
  20. package/mcp-server/dist/services/neural-interface.d.ts +2 -1
  21. package/mcp-server/dist/services/neural-interface.d.ts.map +1 -1
  22. package/mcp-server/dist/services/neural-interface.js.map +1 -1
  23. package/mcp-server/dist/services/server-instructions.d.ts.map +1 -1
  24. package/mcp-server/dist/services/server-instructions.js +2 -1
  25. package/mcp-server/dist/services/server-instructions.js.map +1 -1
  26. package/mcp-server/dist/services/tool-catalog.js +1 -1
  27. package/mcp-server/dist/services/tool-catalog.js.map +1 -1
  28. package/mcp-server/dist/services/tool-list.d.ts +1 -1
  29. package/mcp-server/dist/services/tool-list.d.ts.map +1 -1
  30. package/mcp-server/dist/services/tool-runtime.d.ts +2 -2
  31. package/mcp-server/dist/services/tool-runtime.d.ts.map +1 -1
  32. package/mcp-server/dist/services/tool-runtime.js +1 -1
  33. package/mcp-server/dist/services/tool-runtime.js.map +1 -1
  34. package/mcp-server/dist/services/typesafe-config.js +1 -1
  35. package/mcp-server/dist/services/typesafe-config.js.map +1 -1
  36. package/mcp-server/dist/tools/agents.d.ts +8 -8
  37. package/mcp-server/dist/tools/agents.d.ts.map +1 -1
  38. package/mcp-server/dist/tools/agents.js +10 -9
  39. package/mcp-server/dist/tools/agents.js.map +1 -1
  40. package/mcp-server/dist/tools/choice.d.ts +6 -0
  41. package/mcp-server/dist/tools/choice.d.ts.map +1 -1
  42. package/mcp-server/dist/tools/choice.js +18 -13
  43. package/mcp-server/dist/tools/choice.js.map +1 -1
  44. package/mcp-server/dist/tools/git-tools.js +2 -2
  45. package/mcp-server/dist/tools/git-tools.js.map +1 -1
  46. package/mcp-server/dist/tools/morelogin.d.ts.map +1 -1
  47. package/mcp-server/dist/tools/morelogin.js +9 -6
  48. package/mcp-server/dist/tools/morelogin.js.map +1 -1
  49. package/mcp-server/dist/tools/skill-tools.d.ts +8 -8
  50. package/mcp-server/dist/tools/skill-tools.d.ts.map +1 -1
  51. package/mcp-server/dist/tools/skill-tools.js +11 -8
  52. package/mcp-server/dist/tools/skill-tools.js.map +1 -1
  53. package/mcp-server/package-lock.json +2 -2
  54. package/mcp-server/package.json +1 -1
  55. package/mcp-server/src/index.ts +1 -1
  56. package/mcp-server/src/services/budget-judgments.ts +5 -3
  57. package/mcp-server/src/services/identity.ts +2 -2
  58. package/mcp-server/src/services/memory-sessions.ts +24 -3
  59. package/mcp-server/src/services/neural-interface.ts +2 -1
  60. package/mcp-server/src/services/server-instructions.ts +2 -1
  61. package/mcp-server/src/services/tool-catalog.ts +1 -1
  62. package/mcp-server/src/services/tool-list.ts +1 -1
  63. package/mcp-server/src/services/tool-runtime.ts +2 -2
  64. package/mcp-server/src/services/typesafe-config.ts +1 -1
  65. package/mcp-server/src/tools/agents.ts +10 -9
  66. package/mcp-server/src/tools/choice.ts +17 -12
  67. package/mcp-server/src/tools/git-tools.ts +2 -2
  68. package/mcp-server/src/tools/morelogin.ts +6 -4
  69. package/mcp-server/src/tools/skill-tools.ts +11 -8
  70. package/neural-interface/i18n/en.json +504 -39
  71. package/neural-interface/i18n/pt-BR.json +504 -39
  72. package/neural-interface/lib/agent-sandbox-elevation.js +6 -0
  73. package/neural-interface/lib/antigravity/acp-client-host.js +554 -0
  74. package/neural-interface/lib/antigravity/acp-connection.js +299 -0
  75. package/neural-interface/lib/antigravity/bypass.js +100 -0
  76. package/neural-interface/lib/antigravity/catalog.js +273 -0
  77. package/neural-interface/lib/antigravity/home.js +260 -0
  78. package/neural-interface/lib/antigravity/migrate-gemini.js +139 -0
  79. package/neural-interface/lib/antigravity/panel-bridge.js +1058 -0
  80. package/neural-interface/lib/antigravity/policy-hook.mjs +78 -0
  81. package/neural-interface/lib/antigravity/policy.js +74 -0
  82. package/neural-interface/lib/antigravity/tool-call.js +178 -0
  83. package/neural-interface/lib/antigravity/transcripts.js +252 -0
  84. package/neural-interface/lib/antigravity/usage.js +43 -0
  85. package/neural-interface/lib/assistant-api.js +1 -0
  86. package/neural-interface/lib/assistant-brains/antigravity.js +423 -0
  87. package/neural-interface/lib/assistant-brains/codex.js +6 -1
  88. package/neural-interface/lib/assistant-budget-planner.js +7 -3
  89. package/neural-interface/lib/assistant-budget-split.js +42 -15
  90. package/neural-interface/lib/assistant-catalog.js +76 -9
  91. package/neural-interface/lib/assistant-config.js +6 -3
  92. package/neural-interface/lib/assistant-dispatch.js +211 -50
  93. package/neural-interface/lib/assistant-envelope.js +153 -1
  94. package/neural-interface/lib/assistant-evidence.js +80 -0
  95. package/neural-interface/lib/assistant-hidden-models.js +7 -5
  96. package/neural-interface/lib/assistant-persona.js +16 -11
  97. package/neural-interface/lib/assistant-plan-permissions.js +15 -0
  98. package/neural-interface/lib/assistant-router.js +237 -35
  99. package/neural-interface/lib/assistant-runtime.js +158 -12
  100. package/neural-interface/lib/assistant-task-prompt.js +10 -8
  101. package/neural-interface/lib/assistant-tools.js +2 -2
  102. package/neural-interface/lib/assistant-usage.js +29 -0
  103. package/neural-interface/lib/backup-service.js +6 -1
  104. package/neural-interface/lib/browser-guard-cdp.js +5 -4
  105. package/neural-interface/lib/browser-network-guard.js +274 -82
  106. package/neural-interface/lib/browser-tool-policy.js +12 -7
  107. package/neural-interface/lib/claude-agent-bridge.js +7 -0
  108. package/neural-interface/lib/claude-history-cache.js +210 -0
  109. package/neural-interface/lib/claude-model-catalog.js +5 -1
  110. package/neural-interface/lib/cli-install-api.js +1 -1
  111. package/neural-interface/lib/cli-install.js +160 -31
  112. package/neural-interface/lib/cli-resolver.js +9 -2
  113. package/neural-interface/lib/cli-update-planner.js +25 -15
  114. package/neural-interface/lib/codex-rollout-reader.js +52 -0
  115. package/neural-interface/lib/codex-worker-app-server.js +25 -6
  116. package/neural-interface/lib/editor-git-api.js +3 -20
  117. package/neural-interface/lib/exec-loop-command.js +9 -2
  118. package/neural-interface/lib/file-explorer-api.js +74 -40
  119. package/neural-interface/lib/file-explorer-watch.js +9 -3
  120. package/neural-interface/lib/git-bash/install.js +52 -6
  121. package/neural-interface/lib/git-bash/manager.js +59 -17
  122. package/neural-interface/lib/git-bash/pins.js +12 -0
  123. package/neural-interface/lib/git-read.js +2 -2
  124. package/neural-interface/lib/git-status-runner.js +390 -0
  125. package/neural-interface/lib/git-status-watchdog.js +40 -0
  126. package/neural-interface/lib/greeting/budgets.js +1 -0
  127. package/neural-interface/lib/greeting/engine.js +2 -2
  128. package/neural-interface/lib/greeting/sources.js +10 -12
  129. package/neural-interface/lib/greeting/writer.js +1 -1
  130. package/neural-interface/lib/mcp-client-config.js +37 -6
  131. package/neural-interface/lib/mcp-external-servers.js +40 -7
  132. package/neural-interface/lib/mcp-installer.js +2 -1
  133. package/neural-interface/lib/memory-session-capture.js +17 -3
  134. package/neural-interface/lib/morelogin.js +147 -25
  135. package/neural-interface/lib/native-loop-providers.js +423 -23
  136. package/neural-interface/lib/native-loop-runtime.js +23 -2
  137. package/neural-interface/lib/opencode-native-boundary.js +165 -22
  138. package/neural-interface/lib/owner-authority.js +1 -1
  139. package/neural-interface/lib/path-confine.js +12 -9
  140. package/neural-interface/lib/peer-identity.js +80 -6
  141. package/neural-interface/lib/pty-host/core.js +28 -1
  142. package/neural-interface/lib/pty-host/lifetime.js +12 -0
  143. package/neural-interface/lib/pty-host/manager.js +12 -1
  144. package/neural-interface/lib/remote-policy.js +1 -1
  145. package/neural-interface/lib/request-gate.js +3 -0
  146. package/neural-interface/lib/rulesets/api.js +6 -5
  147. package/neural-interface/lib/rulesets/fs-safe.js +1 -1
  148. package/neural-interface/lib/rulesets/installer.js +89 -10
  149. package/neural-interface/lib/rulesets/render.js +1 -1
  150. package/neural-interface/lib/session-cache-builder.js +64 -1
  151. package/neural-interface/lib/skills/catalog.js +5 -1
  152. package/neural-interface/lib/skills/creation-brief.js +1 -1
  153. package/neural-interface/lib/skills/creation-sources.js +19 -1
  154. package/neural-interface/lib/skills/deploy.js +9 -4
  155. package/neural-interface/lib/skills/draft-confinement.js +3 -1
  156. package/neural-interface/lib/skills/eval-confinement.js +3 -1
  157. package/neural-interface/lib/skills/eval-trace.js +16 -0
  158. package/neural-interface/lib/skills/export.js +5 -2
  159. package/neural-interface/lib/skills/known-bridge-digests.json +58 -4
  160. package/neural-interface/lib/skills/ownership.js +1 -1
  161. package/neural-interface/lib/skills/roots.js +10 -3
  162. package/neural-interface/lib/skills/runtime-checks.js +6 -3
  163. package/neural-interface/lib/skills/service.js +15 -7
  164. package/neural-interface/lib/skills/telemetry.js +6 -0
  165. package/neural-interface/lib/synabun-version.js +1 -1
  166. package/neural-interface/lib/system-activity.js +1 -1
  167. package/neural-interface/lib/whatsapp/brain.js +7 -3
  168. package/neural-interface/lib/whatsapp/cards.js +22 -9
  169. package/neural-interface/lib/whatsapp/config.js +1 -1
  170. package/neural-interface/lib/worker-confinement.js +77 -1
  171. package/neural-interface/lib/worker-question.js +74 -0
  172. package/neural-interface/lib/worker-resume.js +13 -4
  173. package/neural-interface/lib/worker-sandbox.js +46 -16
  174. package/neural-interface/package-lock.json +18 -2
  175. package/neural-interface/package.json +2 -1
  176. package/neural-interface/public/onboarding.html +1 -1
  177. package/neural-interface/public/shared/agent-runtime-options.js +89 -11
  178. package/neural-interface/public/shared/agy/agy-bypass.js +47 -0
  179. package/neural-interface/public/shared/agy/agy-client.js +266 -0
  180. package/neural-interface/public/shared/agy/agy-commands.js +120 -0
  181. package/neural-interface/public/shared/agy/agy-copy.js +326 -0
  182. package/neural-interface/public/shared/agy/agy-diff.js +161 -0
  183. package/neural-interface/public/shared/agy/agy-events.js +469 -0
  184. package/neural-interface/public/shared/agy/agy-greeting.js +26 -0
  185. package/neural-interface/public/shared/agy/agy-options.js +232 -0
  186. package/neural-interface/public/shared/agy/agy-panel.js +2543 -0
  187. package/neural-interface/public/shared/agy/agy-render.js +392 -0
  188. package/neural-interface/public/shared/agy/agy-setup.js +149 -0
  189. package/neural-interface/public/shared/agy/agy-styles.js +604 -0
  190. package/neural-interface/public/shared/agy/agy-tabs-logic.js +181 -0
  191. package/neural-interface/public/shared/api.js +4 -4
  192. package/neural-interface/public/shared/assistant/asst-agents-dock.js +3 -4
  193. package/neural-interface/public/shared/assistant/asst-api.js +15 -3
  194. package/neural-interface/public/shared/assistant/asst-brain-picker.js +56 -9
  195. package/neural-interface/public/shared/assistant/asst-budget.js +5 -4
  196. package/neural-interface/public/shared/assistant/asst-computer.js +26 -2
  197. package/neural-interface/public/shared/assistant/asst-control.js +48 -0
  198. package/neural-interface/public/shared/assistant/asst-hosts.js +16 -7
  199. package/neural-interface/public/shared/assistant/asst-limit-dock.js +6 -1
  200. package/neural-interface/public/shared/assistant/asst-limit-wait.js +38 -5
  201. package/neural-interface/public/shared/assistant/asst-motion-gate.js +80 -0
  202. package/neural-interface/public/shared/assistant/asst-panel.js +46 -9
  203. package/neural-interface/public/shared/assistant/asst-render.js +112 -18
  204. package/neural-interface/public/shared/assistant/asst-route.js +237 -57
  205. package/neural-interface/public/shared/assistant/asst-routes-editor.js +9 -8
  206. package/neural-interface/public/shared/assistant/asst-scene-styles.js +55 -23
  207. package/neural-interface/public/shared/assistant/asst-scenes.js +279 -80
  208. package/neural-interface/public/shared/assistant/asst-sidepanel-styles.js +4 -4
  209. package/neural-interface/public/shared/assistant/asst-sidepanel.js +51 -7
  210. package/neural-interface/public/shared/assistant/asst-slash.js +8 -2
  211. package/neural-interface/public/shared/assistant/asst-state.js +76 -9
  212. package/neural-interface/public/shared/assistant/asst-style-cache.js +44 -0
  213. package/neural-interface/public/shared/assistant/asst-styles.js +58 -4
  214. package/neural-interface/public/shared/assistant/asst-tool-kinds.js +34 -7
  215. package/neural-interface/public/shared/assistant/asst-usage.js +2 -1
  216. package/neural-interface/public/shared/cdx/cdx-output.js +26 -3
  217. package/neural-interface/public/shared/cdx/cdx-panel.js +14 -2
  218. package/neural-interface/public/shared/cdx/cdx-preview.js +12 -0
  219. package/neural-interface/public/shared/cdx/cdx-protocol.js +11 -10
  220. package/neural-interface/public/shared/cdx/cdx-render.js +10 -9
  221. package/neural-interface/public/shared/cdx/cdx-requests.js +11 -1
  222. package/neural-interface/public/shared/cdx/cdx-styles.js +4 -0
  223. package/neural-interface/public/shared/cdx/cdx-tabs.js +75 -5
  224. package/neural-interface/public/shared/cli-install-controller.js +218 -0
  225. package/neural-interface/public/shared/cli-install-view.js +7 -4
  226. package/neural-interface/public/shared/cli-status.js +9 -8
  227. package/neural-interface/public/shared/constants.js +3 -2
  228. package/neural-interface/public/shared/context-menu-model.js +1 -0
  229. package/neural-interface/public/shared/cp/cp-permissions.js +12 -0
  230. package/neural-interface/public/shared/cp/cp-restore.js +162 -0
  231. package/neural-interface/public/shared/cp/cp-tool-cards.js +10 -3
  232. package/neural-interface/public/shared/desktop-bridge.js +17 -0
  233. package/neural-interface/public/shared/desktop-titlebar-view.js +12 -0
  234. package/neural-interface/public/shared/desktop-titlebar.js +13 -4
  235. package/neural-interface/public/shared/desktop-update-view.js +1 -0
  236. package/neural-interface/public/shared/explorer/fx-api.js +4 -4
  237. package/neural-interface/public/shared/explorer/fx-links.js +3 -3
  238. package/neural-interface/public/shared/explorer/fx-logic.js +1 -1
  239. package/neural-interface/public/shared/explorer/fx-main.js +48 -16
  240. package/neural-interface/public/shared/explorer/fx-tree.js +1 -0
  241. package/neural-interface/public/shared/greeting/greeting-card.js +2 -2
  242. package/neural-interface/public/shared/greeting/greeting-view.js +1 -0
  243. package/neural-interface/public/shared/html-shell.js +21 -4
  244. package/neural-interface/public/shared/loading-teardown.js +34 -0
  245. package/neural-interface/public/shared/ocp-v2/ocp-v2-childpanel.js +6 -1
  246. package/neural-interface/public/shared/ocp-v2/ocp-v2-panel.js +28 -7
  247. package/neural-interface/public/shared/ocp-v2/ocp-v2-rehydrate.js +13 -4
  248. package/neural-interface/public/shared/ocp-v2/ocp-v2-render.js +17 -1
  249. package/neural-interface/public/shared/ocp-v2/ocp-v2-send.js +6 -0
  250. package/neural-interface/public/shared/ocp-v2/ocp-v2-styles.js +101 -68
  251. package/neural-interface/public/shared/ocp-v2/ocp-v2-ws.js +46 -3
  252. package/neural-interface/public/shared/provider-icons.js +4 -2
  253. package/neural-interface/public/shared/settings/settings-rules.js +2 -2
  254. package/neural-interface/public/shared/settings/settings-skill-folders-pane.js +1 -1
  255. package/neural-interface/public/shared/settings/settings-skill-folders.js +2 -2
  256. package/neural-interface/public/shared/showcase-privacy.js +6 -1
  257. package/neural-interface/public/shared/sidepanel-session-status.js +3 -3
  258. package/neural-interface/public/shared/skills/ss-creation.js +6 -3
  259. package/neural-interface/public/shared/skills/ss-dialog.js +5 -2
  260. package/neural-interface/public/shared/skills/ss-lint.js +9 -1
  261. package/neural-interface/public/shared/skills/ss-profiles.js +44 -6
  262. package/neural-interface/public/shared/skills/ss-review-view.js +2 -2
  263. package/neural-interface/public/shared/skills/studio/sx-actions.js +1 -1
  264. package/neural-interface/public/shared/skills/studio/sx-create-ai-view.js +1 -1
  265. package/neural-interface/public/shared/skills/studio/sx-create-ai.js +2 -1
  266. package/neural-interface/public/shared/skills/studio/sx-dom.js +2 -1
  267. package/neural-interface/public/shared/skills/studio/sx-fixes-view.js +359 -0
  268. package/neural-interface/public/shared/skills/studio/sx-fixes.js +327 -0
  269. package/neural-interface/public/shared/skills/studio/sx-inspector.js +1 -1
  270. package/neural-interface/public/shared/skills/studio/sx-install-flow.js +9 -6
  271. package/neural-interface/public/shared/skills/studio/sx-install.js +20 -3
  272. package/neural-interface/public/shared/skills/studio/sx-library-view.js +144 -35
  273. package/neural-interface/public/shared/skills/studio/sx-library.js +6 -2
  274. package/neural-interface/public/shared/skills/studio/sx-main.js +11 -2
  275. package/neural-interface/public/shared/skills/studio/sx-review-view.js +1 -1
  276. package/neural-interface/public/shared/skills/studio/sx-subject.js +7 -6
  277. package/neural-interface/public/shared/skills/studio/sx-workspace-view.js +6 -5
  278. package/neural-interface/public/shared/state.js +1 -1
  279. package/neural-interface/public/shared/storage-retry.js +47 -0
  280. package/neural-interface/public/shared/storage.js +25 -4
  281. package/neural-interface/public/shared/streaming-markdown.js +58 -0
  282. package/neural-interface/public/shared/styles.css +362 -35
  283. package/neural-interface/public/shared/synabun-mascot.js +27 -8
  284. package/neural-interface/public/shared/synabun-ticker.js +147 -12
  285. package/neural-interface/public/shared/text-cache.js +29 -0
  286. package/neural-interface/public/shared/tool-list-picker.js +2 -2
  287. package/neural-interface/public/shared/tool-list-view.js +2 -2
  288. package/neural-interface/public/shared/topright-overflow-logic.js +54 -0
  289. package/neural-interface/public/shared/ui-antigravity-panel.js +19 -0
  290. package/neural-interface/public/shared/ui-assistant.js +2 -0
  291. package/neural-interface/public/shared/ui-automation-studio.js +20 -12
  292. package/neural-interface/public/shared/ui-claude-panel.js +374 -134
  293. package/neural-interface/public/shared/ui-cli-banner.js +23 -167
  294. package/neural-interface/public/shared/ui-file-explorer.js +48 -6
  295. package/neural-interface/public/shared/ui-file-links.js +2 -2
  296. package/neural-interface/public/shared/ui-games.js +2 -2
  297. package/neural-interface/public/shared/ui-judgments.js +1 -1
  298. package/neural-interface/public/shared/ui-keybinds.js +8 -2
  299. package/neural-interface/public/shared/ui-link.js +3 -3
  300. package/neural-interface/public/shared/ui-loading.js +5 -4
  301. package/neural-interface/public/shared/ui-menubar.js +2 -2
  302. package/neural-interface/public/shared/ui-native-loop-router.js +4 -0
  303. package/neural-interface/public/shared/ui-navbar.js +45 -0
  304. package/neural-interface/public/shared/ui-notifications.js +1 -0
  305. package/neural-interface/public/shared/ui-resume.js +9 -7
  306. package/neural-interface/public/shared/ui-schedules-studio.js +41 -10
  307. package/neural-interface/public/shared/ui-scroll-follow.js +16 -5
  308. package/neural-interface/public/shared/ui-sessions.js +22 -12
  309. package/neural-interface/public/shared/ui-settings.js +90 -65
  310. package/neural-interface/public/shared/ui-sidepanel-session-entry.js +9 -2
  311. package/neural-interface/public/shared/ui-sidepanel-sessions.js +3 -3
  312. package/neural-interface/public/shared/ui-sidepanel-tray.js +48 -7
  313. package/neural-interface/public/shared/ui-sidepanel-windows.js +3 -3
  314. package/neural-interface/public/shared/ui-terminal.js +146 -10
  315. package/neural-interface/public/shared/ui-tool-updates.js +3 -3
  316. package/neural-interface/public/shared/ui-tooltip.js +71 -46
  317. package/neural-interface/public/shared/ui-topright-overflow.js +233 -0
  318. package/neural-interface/public/shared/ui-whiteboard.js +1 -1
  319. package/neural-interface/public/shared/ui-worker-end.js +1 -1
  320. package/neural-interface/public/shared/whatsapp/wa-view.js +2 -2
  321. package/neural-interface/public/shared/worker-questions.js +34 -0
  322. package/neural-interface/public/sidepanel-session.html +1 -1
  323. package/neural-interface/server.js +731 -466
  324. package/neural-interface/templates/rulesets/README.md +1 -1
  325. package/neural-interface/templates/rulesets/legacy-hashes.json +5 -5
  326. package/neural-interface/templates/rulesets/manifest.json +1 -1
  327. package/npm-shrinkwrap.json +18 -2
  328. package/package.json +2 -1
  329. package/skills/skill-forge/SKILL.md +4 -4
  330. package/skills/synabun/SKILL.md +1 -1
  331. package/skills/synabun/modules/schedule.md +3 -3
  332. /package/neural-interface/templates/rulesets/{gemini.md → antigravity.md} +0 -0
@@ -108,14 +108,22 @@ export function createAssistantHosts({
108
108
  return { host: hostId, sessionId, focused: true };
109
109
  }
110
110
 
111
- /** Map(id → session) of the sessions still open on the server (boot's saved-tab restore). */
111
+ /**
112
+ * Map(id → session) of the sessions still open on the server, or null when the list could not be
113
+ * read (a server that is starting answers before its Assistant routes exist): a host restoring its
114
+ * saved tabs from it keeps them then, instead of reading "none is open".
115
+ */
116
+ async function readLive() {
117
+ let list;
118
+ try { list = await api.list(); } catch { return null; }
119
+ return new Map((Array.isArray(list) ? list : [])
120
+ .filter(s => s?.id && isAssistantSessionLive(s))
121
+ .map(s => [s.id, s]));
122
+ }
123
+
124
+ /** Map(id → session) of the sessions still open on the server (boot's saved-tab restore); a failing server reads as none. */
112
125
  async function fetchLive() {
113
- try {
114
- const list = await api.list();
115
- return new Map((Array.isArray(list) ? list : [])
116
- .filter(s => s?.id && isAssistantSessionLive(s))
117
- .map(s => [s.id, s]));
118
- } catch { return new Map(); }
126
+ return (await readLive()) || new Map();
119
127
  }
120
128
 
121
129
  /**
@@ -302,6 +310,7 @@ export function createAssistantHosts({
302
310
  gone,
303
311
  noteFocus,
304
312
  fetchLive,
313
+ readLive,
305
314
  isLive: isAssistantSessionLive,
306
315
  lastUsed: () => lastOpen(),
307
316
  hosts: () => [...adapters.keys()],
@@ -20,7 +20,12 @@ export function createLimitDock(transcript, { t, createWait = createLimitWait, c
20
20
  host.replaceChildren();
21
21
  active = key;
22
22
  provider = next?.[1].provider;
23
- wait = next ? createWait({ t, ...next[1], onRetry: next[1].onRetry ? () => entries.get(key)?.onRetry?.() : null }) : null;
23
+ wait = next ? createWait({
24
+ t, ...next[1],
25
+ onRetry: next[1].onRetry ? () => entries.get(key)?.onRetry?.() : null,
26
+ onSwitchProvider: next[1].onSwitchProvider ? (anchor) => entries.get(key)?.onSwitchProvider?.(anchor) : null,
27
+ onClose: next[1].onClose ? () => entries.get(key)?.onClose?.() : null,
28
+ }) : null;
24
29
  if (wait) host.appendChild(wait.el);
25
30
  } else if (wait) wait.update({ resetsAt: next[1].resetsAt });
26
31
  host.hidden = !wait;
@@ -6,10 +6,15 @@
6
6
  // mascot dozes inside a gold ring that fills toward the reset, a live
7
7
  // hh:mm:ss countdown and the local reset time beside it. At zero it wakes
8
8
  // ("Usage limit restored") and offers Retry now. With no reset time known it
9
- // waits with "Reset time unknown" and offers the retry at once. The clock is
10
- // the shared ticker at 1 fps, only while it counts and only while the card is
11
- // on the page; under prefers-reduced-motion the mascot is a still and nothing
12
- // eases. Its sheet is its own (injectLimitWaitStyles), like the rack's.
9
+ // waits with "Reset time unknown" and offers the retry at once. While it
10
+ // blocks, a host that passes onSwitchProvider also offers "Continue with
11
+ // another provider" (the host owns the picker and what a pick does); a host
12
+ // that passes onClose always offers Close, which only dismisses the card —
13
+ // the limit itself is untouched — and Esc does the same while focus is
14
+ // inside. The clock is the shared ticker at 1 fps, only while it counts and
15
+ // only while the card is on the page; under prefers-reduced-motion the mascot
16
+ // is a still and nothing eases. Its sheet is its own (injectLimitWaitStyles),
17
+ // like the rack's.
13
18
 
14
19
  import * as mascotLib from '../synabun-mascot.js';
15
20
  import { isReducedMotion, subscribe } from '../synabun-ticker.js';
@@ -37,10 +42,12 @@ function localTime(ms, now) {
37
42
  }
38
43
 
39
44
  /**
40
- * createLimitWait({ t, resetsAt, since, provider, onRetry, retryLabel, announce(text) })
45
+ * createLimitWait({ t, resetsAt, since, provider, onRetry, retryLabel, onSwitchProvider, onClose, announce(text) })
41
46
  * → { el, get state(), update({ resetsAt, since }), retried(), stale(), destroy() }
42
47
  * `resetsAt`: epoch ms / s or ISO, or null (unknown). `since`: when the wait began (the ring's start).
43
48
  * `provider`: the name in the meta line ("Codex"). `onRetry()`: Retry now; null: no button.
49
+ * `onSwitchProvider(anchorEl)`: Continue with another provider, while blocking; null: no button.
50
+ * `onClose()`: Close (and Esc, while focus is inside); null: no button.
44
51
  */
45
52
  export function createLimitWait(opts = {}) {
46
53
  injectLimitWaitStyles();
@@ -84,6 +91,16 @@ export function createLimitWait(opts = {}) {
84
91
  const actions = $('.asst-limit-wait-actions');
85
92
  const live = $('.asst-limit-wait-live');
86
93
 
94
+ // Continue with another provider: only while actively blocking (waiting / unknown). Opens the
95
+ // host's own provider picker (never a native select); the host decides what happens on a pick.
96
+ let switchBtn = null;
97
+ if (typeof opts.onSwitchProvider === 'function') {
98
+ switchBtn = el('button', 'asst-btn asst-btn-secondary asst-limit-wait-switch', t('assistant.limitWait.switchProvider', 'Continue with another provider'));
99
+ switchBtn.type = 'button';
100
+ switchBtn.addEventListener('click', () => { if (!destroyed) opts.onSwitchProvider(switchBtn); });
101
+ actions.appendChild(switchBtn);
102
+ }
103
+
87
104
  let retryBtn = null;
88
105
  if (typeof opts.onRetry === 'function') {
89
106
  retryBtn = el('button', 'asst-btn asst-btn-primary asst-limit-wait-retry');
@@ -96,6 +113,21 @@ export function createLimitWait(opts = {}) {
96
113
  actions.appendChild(retryBtn);
97
114
  }
98
115
 
116
+ // Dismisses the card only; the limit itself is untouched (the host decides how it resurfaces).
117
+ let closeBtn = null;
118
+ if (typeof opts.onClose === 'function') {
119
+ closeBtn = el('button', 'asst-btn asst-btn-secondary asst-limit-wait-close', t('common.close', 'Close'));
120
+ closeBtn.type = 'button';
121
+ closeBtn.addEventListener('click', () => { if (!destroyed) opts.onClose(); });
122
+ actions.appendChild(closeBtn);
123
+ // Not a dialog (role="group"): Esc closes it only while focus is inside.
124
+ card.addEventListener('keydown', (e) => {
125
+ if (e.key !== 'Escape' || destroyed) return;
126
+ e.stopPropagation();
127
+ opts.onClose();
128
+ });
129
+ }
130
+
99
131
  function setPose(next) {
100
132
  if (pose === next || destroyed) return;
101
133
  pose = next;
@@ -146,6 +178,7 @@ export function createLimitWait(opts = {}) {
146
178
  : (opts.retryLabel || t('assistant.limitWait.retry', 'Retry now'));
147
179
  retryBtn.textContent = label;
148
180
  }
181
+ if (switchBtn) switchBtn.hidden = !(next === 'waiting' || next === 'unknown');
149
182
  if (next === 'waiting') { setPose('sleep'); setRing(limitCountdown({ resetsAt, since }, now).progress || 0); }
150
183
  else if (next === 'unknown') { setPose('wait'); setRing(0.18, true); }
151
184
  else if (next === 'restored') { setPose(was === 'waiting' ? 'success' : 'idle'); setRing(1); }
@@ -0,0 +1,80 @@
1
+ // ═══════════════════════════════════════════
2
+ // SynaBun Assistant — loops run only on screen
3
+ // ═══════════════════════════════════════════
4
+ // The transcript's decorative loops (a run card's cameo, its stage's scene and
5
+ // sweep; a live rack's sweep, ticks and scene; a route line's sweep and icon)
6
+ // run only while their holder is on screen. One IntersectionObserver per
7
+ // renderer marks a holder that is not (scrolled out of its transcript, its tab
8
+ // hidden, its window minimised to nothing) with `data-offscreen`; the
9
+ // stylesheet pauses every animation under it (asst-styles.js), and the loop
10
+ // picks up where it stopped when the holder is back. Every frame the page
11
+ // draws restyles each running animation on the main thread, composited or
12
+ // not, so a loop nobody sees is never free; the observer is the browser's own,
13
+ // so watching costs nothing while the transcript scrolls.
14
+ //
15
+ // createMotionGate({ IntersectionObserver }?) → { watch(el), unwatch(el), disconnect(), size() }
16
+ //
17
+ // No observer (an old engine, a test without one): nothing is marked, every
18
+ // loop runs as before. DOM-light on purpose: tests/assistant-motion-gate.test.mjs
19
+ // drives it with a stand-in observer.
20
+
21
+ export const OFFSCREEN_ATTR = 'data-offscreen';
22
+ const PRUNE_EVERY = 32; // watched holders between two sweeps for ones that left the document
23
+
24
+ export function createMotionGate({ IntersectionObserver: IO = globalThis.IntersectionObserver } = {}) {
25
+ const watched = new Set();
26
+ let io = null; // undefined: no observer here
27
+
28
+ function mark(el, off) {
29
+ try {
30
+ if (off) { if (!el.hasAttribute(OFFSCREEN_ATTR)) el.setAttribute(OFFSCREEN_ATTR, ''); }
31
+ else if (el.hasAttribute(OFFSCREEN_ATTR)) el.removeAttribute(OFFSCREEN_ATTR);
32
+ } catch { /* not an element */ }
33
+ }
34
+
35
+ function observer() {
36
+ if (io !== null) return io;
37
+ if (typeof IO !== 'function') { io = undefined; return io; }
38
+ try {
39
+ io = new IO((entries) => {
40
+ for (const entry of entries) {
41
+ const el = entry.target;
42
+ if (!watched.has(el)) continue;
43
+ if (el.isConnected === false) { unwatch(el); continue; }
44
+ mark(el, !entry.isIntersecting);
45
+ }
46
+ });
47
+ } catch { io = undefined; }
48
+ return io;
49
+ }
50
+
51
+ /** Holders removed while already off screen get no report: drop them now and then. */
52
+ function prune() {
53
+ for (const el of Array.from(watched)) if (el.isConnected === false) unwatch(el);
54
+ }
55
+
56
+ function watch(el) {
57
+ if (!el || watched.has(el)) return false;
58
+ const o = observer();
59
+ if (!o) return false;
60
+ watched.add(el);
61
+ try { o.observe(el); } catch { watched.delete(el); return false; }
62
+ if (watched.size % PRUNE_EVERY === 0) prune();
63
+ return true;
64
+ }
65
+
66
+ function unwatch(el) {
67
+ if (!watched.delete(el)) return;
68
+ try { io?.unobserve(el); } catch { /* already gone */ }
69
+ mark(el, false);
70
+ }
71
+
72
+ function disconnect() {
73
+ try { io?.disconnect(); } catch { /* already gone */ }
74
+ for (const el of watched) mark(el, false);
75
+ watched.clear();
76
+ if (io) io = null;
77
+ }
78
+
79
+ return { watch, unwatch, disconnect, size: () => watched.size };
80
+ }
@@ -35,7 +35,6 @@ import { t } from '../i18n.js';
35
35
  import '../account-i18n.js';
36
36
  import { forgetGreeting, mountGreeting } from '../greeting/greeting-card.js';
37
37
  import { notify, NOTIF_TYPE } from '../ui-notifications.js';
38
- import { getProviderMeta } from '../provider-icons.js';
39
38
  import { isGuest, hasPermission } from '../ui-sync.js';
40
39
  import { getWhiteboardElementById } from '../ui-whiteboard.js';
41
40
  import { focusNativeLoopRun } from '../ui-native-loop-router.js';
@@ -51,7 +50,7 @@ import { buildPromptText, createComposer } from './asst-composer.js';
51
50
  import { buildDispatchSpec, parseSlashCommand, slashHelpMarkdown } from './asst-slash.js';
52
51
  import { resolveStopTarget } from './asst-stop.js';
53
52
  import { plural } from './asst-tool-kinds.js';
54
- import { cachedProjects, createBrainPicker, testDensityLabel } from './asst-brain-picker.js';
53
+ import { cachedProjects, createBrainPicker, openModelMenu, testDensityLabel } from './asst-brain-picker.js';
55
54
  import { createRovingToolbar } from './asst-roving.js';
56
55
  import { openAccountsManager } from './asst-accounts.js';
57
56
  import { createAgentsDock } from './asst-agents-dock.js';
@@ -62,8 +61,8 @@ import { createRouteModeControl, openModelsManager, openRoutesEditor, refreshMod
62
61
  import { budgetChipText, budgetSpendText, budgetTone, closeBudgetEditor, createBudgetController, mountBudgetChip, openBudgetEditor } from './asst-budget.js';
63
62
  import { computerRemoteView, createComputerPanel, createComputerToggle, normalizeComputerRemote, openFrameLightbox, closeFrameLightbox, requestDesktopStop } from './asst-computer.js';
64
63
  import {
65
- applyLimit, applyLimitPacket, applyUsagePacket, brainLabel, createRenameWriter, createTabState, DEFAULT_ROUTE_MODE, deserializeTabState, fmtCost, fmtRunLine, limitExpiresIn, limitNoticeText, modelShortName,
66
- 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,
67
66
  serializeTabState, sessionStatus, tabStorageKey, userSessionTitle,
68
67
  } from './asst-state.js';
69
68
  import {
@@ -244,8 +243,9 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
244
243
  if (host.toolbarSlot) host.toolbarSlot.appendChild(barEl);
245
244
 
246
245
  // ── Helpers ──
247
- const providerIcon = (p) => getProviderMeta(p).icon;
248
- 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;
249
249
  const visible = () => { try { return host.isVisible ? !!host.isVisible() : true; } catch { return true; } };
250
250
 
251
251
  // ── Just-in-time tips (../tour/tour-tips.js): once each, ever; never in a replay or while the tour runs ──
@@ -537,6 +537,7 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
537
537
  onFollowup: (text) => { submit(clickPayload(text)); },
538
538
  onFollowupOther: () => composer.focus(),
539
539
  onLimitRetry: (text) => { submit(clickPayload(text)); },
540
+ onSwitchProvider: (anchor, meta) => continueOnAnotherProvider(anchor, meta),
540
541
  limitInfo: () => st.limit,
541
542
  brainProvider: () => st.brain.provider,
542
543
  heroOrigin: () => { try { return host.takeHeroOrigin?.() || null; } catch { return null; } },
@@ -1117,7 +1118,7 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
1117
1118
  computerPanel.applyStatus(status);
1118
1119
  applyFeatures();
1119
1120
  })
1120
- .catch(() => { st.features.computer = false; applyFeatures(); });
1121
+ .catch((err) => { st.features.computer = false; computerPanel.checkFailed?.(err); applyFeatures(); });
1121
1122
  }
1122
1123
  }
1123
1124
 
@@ -1480,6 +1481,7 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
1480
1481
  compact();
1481
1482
  return true;
1482
1483
  case 'new':
1484
+ if (parsed.error === 'not_brain') { toast(notBrainText(parsed.provider)); return false; }
1483
1485
  newSession(parsed.provider || null);
1484
1486
  return true;
1485
1487
  case 'resume':
@@ -1507,6 +1509,7 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
1507
1509
  if (parsed.error) { toast(tt('assistant.slash.needsText', 'Usage: /remember <text>')); return false; }
1508
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 }) });
1509
1511
  case 'model': {
1512
+ if (parsed.error === 'not_brain') { toast(notBrainText(parsed.provider)); return false; }
1510
1513
  if (!parsed.model && !parsed.provider) { picker.openField('model'); return true; }
1511
1514
  const next = { ...st.brain };
1512
1515
  let requiresSwitch = false;
@@ -1555,10 +1558,15 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
1555
1558
  }
1556
1559
  }
1557
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
+
1558
1566
  function dispatchErrorText(parsed) {
1559
1567
  switch (parsed.error) {
1560
- case 'missing_provider': return tt('assistant.slash.dispatchProvider', 'Usage: /dispatch <claude|codex|opencode> [flags] <task>');
1561
- 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 });
1562
1570
  case 'unknown_flag': return tt('assistant.slash.dispatchUnknownFlag', 'Unknown flag --{flag}', { flag: parsed.flag });
1563
1571
  case 'missing_flag_value': return tt('assistant.slash.dispatchFlagValue', 'Flag --{flag} needs a value', { flag: parsed.flag });
1564
1572
  case 'missing_task': return tt('assistant.slash.dispatchTask', 'Add the task text after the flags');
@@ -1607,6 +1615,8 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
1607
1615
  }
1608
1616
 
1609
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;
1610
1620
  const b = provider ? normalizeBrain({ ...st.brain, provider, model: '', effort: null, agent: null, accountId: null }) : st.brain;
1611
1621
  // This one is still empty: it is the new session (the server keeps one draft, not a pile of them).
1612
1622
  // /new <provider> switches its brain as the picker does; what only this page showed (/help) is cleared.
@@ -1663,6 +1673,33 @@ export function mountAssistant(viewport, { sessionId, brain, host = {}, session
1663
1673
  });
1664
1674
  }
1665
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
+
1666
1703
  // ── Runs ──
1667
1704
  async function focusRun(runId) {
1668
1705
  if (!runId) return;