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
@@ -0,0 +1,89 @@
1
+ // ═══════════════════════════════════════════
2
+ // SETTINGS — the OpenCode SynaBun found, in words
3
+ // ═══════════════════════════════════════════
4
+ //
5
+ // What `GET /api/opencode/status` (`installed`, server.js opencodeInstallState) and
6
+ // `POST /api/cli/detect/opencode` (`support`) say about the OpenCode binary: which version it is,
7
+ // or why SynaBun does not drive it and how to get OpenCode 2. The server decides
8
+ // (lib/opencode-protocol.js opencodeSupportFor gives `code`); the page words it in its own
9
+ // language. Pure: no DOM and no imports, so node runs it (tests/settings-opencode-view.test.mjs).
10
+ //
11
+ // describeOpencodeInstall(installed, { th, tx }) → { tone, status, html, text }
12
+ //
13
+ // `installed` is `{ installed, version, supported, code, path, minimum, commands }`: `supported`
14
+ // is true for a version SynaBun drives, false for one it refuses (`code` says why: 'opencode1',
15
+ // 'outdated', 'newer'), null while the version is not known (a command line, a version that could
16
+ // not be read: the serve's own answer decides when it starts). `th(key, html)` and `tx(key, params)`
17
+ // are the kit's: `th` escapes the string and puts raw HTML in its `{names}` (every value here is
18
+ // escaped first), `tx` gives the plain text, for a toast.
19
+
20
+ const esc = (value) => String(value ?? '').replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
21
+ const code = (text) => `<code class="stg-code">${esc(text)}</code>`;
22
+
23
+ // Written out whole, so the key checks find every one (tests/settings-ia.test.mjs, build_en.py --used).
24
+ const REFUSAL_KEYS = {
25
+ opencode1: 'settings.redesign.opencode.refusal.opencode1',
26
+ outdated: 'settings.redesign.opencode.refusal.outdated',
27
+ newer: 'settings.redesign.opencode.refusal.newer',
28
+ };
29
+ const UPDATE_COMMAND = 'opencode upgrade';
30
+
31
+ /** "2.1.4" from "opencode v2.1.4" (a prerelease kept whole), as the server's own sentence shows it. */
32
+ export function shownOpencodeVersion(version) {
33
+ return String(version ?? '').trim().replace(/^opencode\s+/i, '').replace(/^v(?=\d)/i, '');
34
+ }
35
+
36
+ function commandList(commands) {
37
+ return (Array.isArray(commands) ? commands : []).map((command) => String(command ?? '').trim()).filter(Boolean);
38
+ }
39
+
40
+ /** The install commands as one phrase: `a`, or `a or b` (each its own <code> in the HTML). */
41
+ export function opencodeCommandsPhrase(commands, { th, tx }) {
42
+ const list = commandList(commands);
43
+ const join = (words, wrap, translate) => words.slice(1).reduce(
44
+ (phrase, command) => translate('settings.redesign.opencode.commandOr', { first: phrase, second: wrap(command) }),
45
+ wrap(words[0]),
46
+ );
47
+ if (!list.length) return { html: '', text: '' };
48
+ return { html: join(list, code, th), text: join(list, (command) => command, tx) };
49
+ }
50
+
51
+ /**
52
+ * The note under the OpenCode service bar: `tone` '' | 'ok' | 'warn', `status` the short word for
53
+ * the status bar when OpenCode cannot run ('notInstalled' | 'notSupported' | null), `html` the note
54
+ * (empty: no note), `text` the same sentence as plain text.
55
+ */
56
+ export function describeOpencodeInstall(installed, { th, tx }) {
57
+ const none = { tone: '', status: null, html: '', text: '' };
58
+ if (!installed || typeof installed !== 'object') return none;
59
+ const commands = opencodeCommandsPhrase(installed.commands, { th, tx });
60
+ if (installed.installed === false) {
61
+ return {
62
+ tone: 'warn',
63
+ status: 'notInstalled',
64
+ html: th('settings.redesign.opencode.notInstalled', { commands: commands.html }),
65
+ text: tx('settings.redesign.opencode.notInstalled', { commands: commands.text }),
66
+ };
67
+ }
68
+ const version = shownOpencodeVersion(installed.version);
69
+ const path = String(installed.path || 'opencode');
70
+ if (installed.supported === false && REFUSAL_KEYS[installed.code]) {
71
+ const key = REFUSAL_KEYS[installed.code];
72
+ const minimum = String(installed.minimum || '');
73
+ return {
74
+ tone: 'warn',
75
+ status: 'notSupported',
76
+ html: th(key, { path: code(path), version: esc(version), commands: commands.html, update: code(UPDATE_COMMAND), minimum: esc(minimum) }),
77
+ text: tx(key, { path, version, commands: commands.text, update: UPDATE_COMMAND, minimum }),
78
+ };
79
+ }
80
+ if (installed.supported === true && version) {
81
+ return {
82
+ tone: 'ok',
83
+ status: null,
84
+ html: th('settings.redesign.opencode.installedVersion', { version: esc(version), path: code(path) }),
85
+ text: tx('settings.redesign.opencode.installedVersion', { version, path }),
86
+ };
87
+ }
88
+ return none;
89
+ }
@@ -20,9 +20,9 @@
20
20
  // `tx` in Settings; the wizard reads the same catalogue, i18n/en.json).
21
21
 
22
22
  /** The tools SynaBun installs rules for, in the order both surfaces list them. Cursor is copy-only. */
23
- export const RULES_INSTALL_HOSTS = Object.freeze(['claude', 'gemini', 'codex', 'opencode']);
23
+ export const RULES_INSTALL_HOSTS = Object.freeze(['claude', 'antigravity', 'codex', 'opencode']);
24
24
 
25
- export const RULES_HOST_LABELS = Object.freeze({ claude: 'Claude Code', codex: 'Codex', opencode: 'OpenCode', gemini: 'Gemini', cursor: 'Cursor', coexistence: 'coexistence' });
25
+ export const RULES_HOST_LABELS = Object.freeze({ claude: 'Claude Code', codex: 'Codex', opencode: 'OpenCode', antigravity: 'Antigravity', cursor: 'Cursor', coexistence: 'coexistence' });
26
26
 
27
27
  /** The states that count as "the rules are in place". `shadowed` is installed too, only not loaded (Codex's override file). */
28
28
  export const RULES_IN_PLACE = Object.freeze(['installed', 'newer', 'shadowed']);
@@ -0,0 +1,265 @@
1
+ // ═══════════════════════════════════════════
2
+ // SynaBun Neural Interface — Settings → Skills: the skill folders block
3
+ // ═══════════════════════════════════════════
4
+ //
5
+ // Under the skill chips: the move of SynaBun's old Codex prompt / OpenCode command bridges to native skill
6
+ // folders (review it, move them, undo the last move) and the switch that lets installs go into the shared
7
+ // ~/.agents/skills. Nothing moves when Settings opens: the owner reads the plan and presses Move (the server checks
8
+ // the plan's digest, installs the native folder first, keeps each bridge's bytes in the move's journal, and leaves
9
+ // every file that is not SynaBun's where it is). Words and states come from settings-skill-folders.js; requests
10
+ // carry the X-SynaBun-UI header the owner-only routes ask for (api.js). A change made anywhere else (another window,
11
+ // the Studio, an agent's submission, an install) reaches the block and the chips through `skills:changed`, in place,
12
+ // never under a plan the owner is reading.
13
+
14
+ import * as kit from './settings-kit.js';
15
+ import { chipState, installedToast, lastUndoable, readFoldersStatus, readMigrationOutcome, readMigrationPlan, readRevertOutcome, toggledAssistants } from './settings-skill-folders.js';
16
+ import { fetchClaudeCodeSkills, fetchSkillsConfig, fetchSkillsMigrations, fetchSkillsStatus, planSkillsBridgeMigration, planSkillsBridgeMigrationConfirmed, revertSkillsMigration, runSkillsBridgeMigration, saveSkillsConfig } from '../api.js';
17
+ import { on } from '../state.js';
18
+
19
+ export { chipState, installedToast };
20
+
21
+ const params = (p) => Object.fromEntries(Object.entries(p || {}).map(([k, v]) => [k, v && typeof v === 'object' && typeof v.key === 'string' ? kit.tx(v.key) : v]));
22
+ const say = (m) => (m ? kit.tx(m.key, params(m.params)) : '');
23
+
24
+ /** The block's markup (filled in by wireSkillFolders once the server answers). */
25
+ export function skillFoldersHTML() {
26
+ return `
27
+ <div class="stg-skill-folders" id="stg-skill-folders">
28
+ ${kit.subhead(kit.te('settings.redesign.skills.folders.title'))}
29
+ <div class="stg-help" id="stg-skill-folders-status" role="status" aria-live="polite" style="margin-top:0">${kit.te('settings.redesign.skills.folders.loading')}</div>
30
+ <div class="stg-help" id="stg-skill-folders-others" hidden></div>
31
+ <ul class="stg-help" id="stg-skill-folders-plan" hidden></ul>
32
+ <div class="cc-skill-targets" role="group" id="stg-skill-folders-actions">
33
+ <button type="button" class="cc-skill-target" id="stg-skill-folders-review" hidden>${kit.te('settings.redesign.skills.folders.review')}</button>
34
+ <button type="button" class="cc-skill-target" id="stg-skill-folders-move" hidden>${kit.te('settings.redesign.skills.folders.move')}</button>
35
+ <button type="button" class="cc-skill-target" id="stg-skill-folders-cancel" hidden>${kit.te('settings.redesign.skills.folders.cancel')}</button>
36
+ <button type="button" class="cc-skill-target" id="stg-skill-folders-undo" hidden>${kit.te('settings.redesign.skills.folders.undo')}</button>
37
+ </div>
38
+ <div class="cc-skill-row" id="stg-skill-folders-assistants" hidden>
39
+ <div class="cc-skill-info">
40
+ <span class="cc-skill-name">${kit.te('settings.redesign.skills.assistants.title')}</span>
41
+ <span class="cc-skill-desc" id="stg-skill-folders-assistants-help">${kit.te('settings.redesign.skills.assistants.help')}</span>
42
+ </div>
43
+ <div class="cc-skill-targets" role="group" aria-label="${kit.te('settings.redesign.skills.assistants.title')}" id="stg-skill-folders-assistants-chips"></div>
44
+ </div>
45
+ <div class="cc-skill-row" id="stg-skill-folders-shared" hidden>
46
+ <div class="cc-skill-info">
47
+ <span class="cc-skill-name">${kit.te('settings.redesign.skills.folders.sharedLabel')}</span>
48
+ <span class="cc-skill-desc">${kit.te('settings.redesign.skills.folders.sharedHelp')}</span>
49
+ </div>
50
+ <div class="cc-skill-targets"><button type="button" class="cc-skill-target" id="stg-skill-folders-shared-toggle" aria-pressed="false">${kit.te('settings.redesign.skills.folders.sharedOff')}</button></div>
51
+ </div>
52
+ </div>`;
53
+ }
54
+
55
+ /**
56
+ * Read the skills again and redraw each runtime chip in place (its state, pressed, title). A chip that is being
57
+ * clicked is left to its own request.
58
+ * @param {HTMLElement} root the Settings overlay
59
+ */
60
+ export async function refreshSkillChips(root) {
61
+ let skills;
62
+ try { skills = (await fetchClaudeCodeSkills())?.skills; } catch { return; }
63
+ if (!Array.isArray(skills)) return;
64
+ const byDir = new Map(skills.map((skill) => [skill.dirName, skill]));
65
+ for (const chip of root.querySelectorAll('.cc-skill-target[data-cc-skill][data-cc-target]')) {
66
+ const skill = byDir.get(chip.dataset.ccSkill);
67
+ if (!skill || chip.style.pointerEvents === 'none') continue;
68
+ const target = chip.dataset.ccTarget;
69
+ const installed = skill.installedTargets || { claude: !!skill.installed, codex: false, opencode: false, antigravity: false };
70
+ const now = chipState(skill.targetStates?.[target], !!installed[target]);
71
+ chip.classList.toggle('on', now.on);
72
+ chip.dataset.state = now.on ? 'on' : 'off';
73
+ chip.dataset.installState = now.state;
74
+ chip.setAttribute('aria-pressed', now.on ? 'true' : 'false');
75
+ chip.title = kit.tx(now.key, { skill: skill.name || skill.dirName, assistant: chip.textContent.trim() });
76
+ const row = chip.closest('.cc-skill-row');
77
+ if (row) row.classList.toggle('installed', !!row.querySelector('.cc-skill-target.on'));
78
+ }
79
+ }
80
+
81
+ /**
82
+ * Fill the block in and wire its buttons.
83
+ * @param {HTMLElement} root the Settings overlay
84
+ * @param {{ toast?: (msg: string, ms?: number) => void, onChanged?: () => void, signal?: AbortSignal }} [o]
85
+ * `onChanged`: something here (or elsewhere) changed the skills; `signal`: the panel's life (its listeners end with it)
86
+ */
87
+ export async function wireSkillFolders(root, { toast = () => {}, onChanged = () => {}, signal = null } = {}) {
88
+ const box = root.querySelector('#stg-skill-folders');
89
+ if (!box) return;
90
+ const $ = (id) => box.querySelector(`#${id}`);
91
+ const status = $('stg-skill-folders-status');
92
+ const others = $('stg-skill-folders-others');
93
+ const planList = $('stg-skill-folders-plan');
94
+ const review = $('stg-skill-folders-review');
95
+ const move = $('stg-skill-folders-move');
96
+ const cancel = $('stg-skill-folders-cancel');
97
+ const undo = $('stg-skill-folders-undo');
98
+ const shared = $('stg-skill-folders-shared');
99
+ const sharedToggle = $('stg-skill-folders-shared-toggle');
100
+ const assistantsRow = $('stg-skill-folders-assistants');
101
+ const assistantChips = $('stg-skill-folders-assistants-chips');
102
+ const assistantsHelp = $('stg-skill-folders-assistants-help');
103
+ let plan = null;
104
+ let undoable = null;
105
+ let working = false;
106
+ let assistants = null;
107
+ const ticked = new Set(); // the offered bridges the owner ticked ("Move it too")
108
+
109
+ const busy = (yes) => { working = yes; for (const b of [review, move, cancel, undo, sharedToggle, ...assistantChips.querySelectorAll('button'), ...planList.querySelectorAll('input')]) if (b) b.disabled = yes; };
110
+ const showPlan = (reading) => {
111
+ planList.replaceChildren(...reading.lines.map((line) => {
112
+ const li = document.createElement('li');
113
+ li.dataset.tone = line.tone;
114
+ if (line.offer) {
115
+ // A bridge file of a shipped skill that is not proven SynaBun's: moved only when the owner ticks it here.
116
+ const label = document.createElement('label');
117
+ label.className = 'stg-skill-folders-offer';
118
+ const box = document.createElement('input');
119
+ box.type = 'checkbox'; box.checked = !!line.offer.on; box.dataset.bridge = line.bridgeId; box.dataset.digest = line.offer.digest;
120
+ box.setAttribute('aria-label', kit.tx('settings.redesign.skills.folders.offerTick', { name: line.params.name }));
121
+ const text = document.createElement('span');
122
+ text.textContent = say(line);
123
+ label.append(box, text);
124
+ li.append(label);
125
+ } else li.textContent = say(line);
126
+ return li;
127
+ }));
128
+ planList.hidden = !reading.lines.length;
129
+ };
130
+ // A plan on screen: its lines, Move only when something would move, Cancel to put the block back.
131
+ const present = (next) => {
132
+ plan = next;
133
+ const reading = readMigrationPlan(plan, ticked);
134
+ showPlan(reading);
135
+ if (reading.empty) status.textContent = say(reading.empty);
136
+ move.hidden = reading.movable === 0;
137
+ cancel.hidden = false;
138
+ review.hidden = true;
139
+ };
140
+ // An offer ticked or unticked: the plan is asked again with the confirmations (a confirmed plan is another plan,
141
+ // taken by its own digest), and shown.
142
+ planList.addEventListener('change', async (e) => {
143
+ const box = e.target;
144
+ if (!box?.dataset?.bridge) return;
145
+ if (box.checked) ticked.add(box.dataset.bridge); else ticked.delete(box.dataset.bridge);
146
+ busy(true);
147
+ try {
148
+ const confirm = Object.fromEntries([...planList.querySelectorAll('input[data-bridge]')].filter((b) => ticked.has(b.dataset.bridge)).map((b) => [b.dataset.bridge, b.dataset.digest]));
149
+ present((await planSkillsBridgeMigrationConfirmed(confirm)).plan);
150
+ } catch (err) { toast(kit.tx('settings.redesign.skills.folders.failed', { message: err.message }), 6000); }
151
+ finally { busy(false); }
152
+ });
153
+ const drawAssistants = () => {
154
+ if (!assistants) { assistantsRow.hidden = true; return; }
155
+ assistantsRow.hidden = false;
156
+ assistantChips.replaceChildren(...assistants.chips.map((chip) => {
157
+ const b = document.createElement('button');
158
+ b.type = 'button';
159
+ b.className = `cc-skill-target${chip.on ? ' on' : ''}`;
160
+ b.dataset.assistant = chip.id;
161
+ b.setAttribute('aria-pressed', chip.on ? 'true' : 'false');
162
+ b.textContent = kit.tx(chip.key);
163
+ b.title = kit.tx(chip.on ? 'settings.redesign.skills.assistants.chipOn' : 'settings.redesign.skills.assistants.chipOff', { assistant: kit.tx(chip.key) });
164
+ return b;
165
+ }));
166
+ const detected = assistants.detectedWords.map((w) => kit.tx(w.key)).join(', ');
167
+ assistantsHelp.textContent = `${kit.tx('settings.redesign.skills.assistants.help')} ${kit.tx(assistants.auto ? 'settings.redesign.skills.assistants.detected' : 'settings.redesign.skills.assistants.chosen', { detected })}`;
168
+ if (!assistants.auto) {
169
+ const reset = document.createElement('button');
170
+ reset.type = 'button'; reset.className = 'cc-skill-target'; reset.dataset.assistant = 'auto';
171
+ reset.textContent = kit.tx('settings.redesign.skills.assistants.useDetected');
172
+ reset.title = kit.tx('settings.redesign.skills.assistants.detected', { detected });
173
+ assistantChips.append(reset);
174
+ }
175
+ };
176
+ assistantChips.addEventListener('click', async (e) => {
177
+ const chip = e.target.closest?.('button[data-assistant]');
178
+ if (!chip || chip.disabled || !assistants) return;
179
+ const next = chip.dataset.assistant === 'auto' ? null : toggledAssistants(assistants.effective, chip.dataset.assistant);
180
+ busy(true);
181
+ try { await saveSkillsConfig({ assistants: next }); }
182
+ catch (err) { toast(kit.tx('settings.redesign.skills.folders.failed', { message: err.message }), 6000); }
183
+ finally { busy(false); }
184
+ await refresh();
185
+ });
186
+ async function refresh() {
187
+ let answer = null;
188
+ try { answer = await fetchSkillsStatus(); } catch { answer = null; }
189
+ const reading = readFoldersStatus(answer);
190
+ status.textContent = say(reading.message);
191
+ if (!reading.available) { for (const el of [others, planList, review, move, cancel, undo, shared, assistantsRow]) el.hidden = true; return; }
192
+ // The owner's assistants: the status carries them on a server with the preference; GET /config is the fuller read.
193
+ assistants = reading.assistants;
194
+ if (assistants) { try { const cfg = await fetchSkillsConfig(); if (cfg?.assistants) assistants = readFoldersStatus({ ok: true, bridges: {}, assistants: cfg.assistants }).assistants; } catch { /* the status' view */ } }
195
+ drawAssistants();
196
+ ticked.clear();
197
+ others.hidden = !reading.others;
198
+ others.textContent = say(reading.others);
199
+ review.hidden = !reading.canReview;
200
+ move.hidden = true; cancel.hidden = true; planList.hidden = true; plan = null;
201
+ shared.hidden = false;
202
+ sharedToggle.classList.toggle('on', reading.sharedAgentsRoot);
203
+ sharedToggle.setAttribute('aria-pressed', reading.sharedAgentsRoot ? 'true' : 'false');
204
+ sharedToggle.textContent = kit.tx(reading.sharedAgentsRoot ? 'settings.redesign.skills.folders.sharedOn' : 'settings.redesign.skills.folders.sharedOff');
205
+ try { undoable = lastUndoable((await fetchSkillsMigrations()).migrations); } catch { undoable = null; }
206
+ undo.hidden = !undoable;
207
+ }
208
+
209
+ review.addEventListener('click', async () => {
210
+ busy(true);
211
+ try {
212
+ present((await planSkillsBridgeMigration()).plan);
213
+ } catch (err) { toast(kit.tx('settings.redesign.skills.folders.failed', { message: err.message }), 6000); }
214
+ finally { busy(false); }
215
+ });
216
+ cancel.addEventListener('click', () => refresh());
217
+ move.addEventListener('click', async () => {
218
+ const reading = readMigrationPlan(plan, ticked);
219
+ if (!reading.planDigest) return;
220
+ busy(true);
221
+ try {
222
+ const out = await runSkillsBridgeMigration(reading.planDigest, reading.confirm);
223
+ toast(say(readMigrationOutcome(out)), 8000);
224
+ onChanged();
225
+ } catch (err) {
226
+ // The bridges or their destinations changed since the plan was shown: nothing moved, the new plan is shown.
227
+ if (err.code === 'plan_changed' && err.body?.plan) { present(err.body.plan); toast(kit.tx('settings.redesign.skills.folders.planChanged'), 8000); return; }
228
+ toast(kit.tx('settings.redesign.skills.folders.failed', { message: err.message }), 6000);
229
+ } finally { busy(false); }
230
+ await refresh();
231
+ });
232
+ undo.addEventListener('click', async () => {
233
+ if (!undoable) return;
234
+ busy(true);
235
+ try {
236
+ const out = await revertSkillsMigration(undoable.journalId);
237
+ toast(say(readRevertOutcome(out)), 8000);
238
+ onChanged();
239
+ } catch (err) { toast(kit.tx('settings.redesign.skills.folders.failed', { message: err.message }), 6000); }
240
+ finally { busy(false); }
241
+ await refresh();
242
+ });
243
+ sharedToggle.addEventListener('click', async () => {
244
+ const next = sharedToggle.getAttribute('aria-pressed') !== 'true';
245
+ busy(true);
246
+ try { await saveSkillsConfig({ sharedAgentsRoot: next }); }
247
+ catch (err) { toast(kit.tx('settings.redesign.skills.folders.failed', { message: err.message }), 6000); }
248
+ finally { busy(false); }
249
+ await refresh();
250
+ });
251
+ // Changes from anywhere else: the chips follow at once; the block follows unless a plan is on screen or a request
252
+ // of its own is under way (a move is taken only by the digest of the plan shown, so a stale plan moves nothing).
253
+ let soon = 0;
254
+ const stop = on('sync:skills:changed', () => {
255
+ clearTimeout(soon);
256
+ soon = setTimeout(() => {
257
+ if (!box.isConnected) { stop(); return; }
258
+ onChanged();
259
+ if (!plan && !working) refresh();
260
+ }, 300);
261
+ });
262
+ signal?.addEventListener('abort', () => { stop(); clearTimeout(soon); }, { once: true });
263
+ if (signal?.aborted) { stop(); return; }
264
+ await refresh();
265
+ }
@@ -0,0 +1,130 @@
1
+ // ═══════════════════════════════════════════
2
+ // SynaBun Neural Interface — Settings → Skills: skill folders, read (no DOM)
3
+ // ═══════════════════════════════════════════
4
+ //
5
+ // What the Skills Service says (GET /api/skills-studio/v2/status, the bridge migration's plan and outcome) turned
6
+ // into what Settings → Skills shows: whether the old Codex prompt / OpenCode command bridges can move to native
7
+ // skill folders, what each would do, the outcome of a move or an undo, the shared ~/.agents/skills switch, and
8
+ // each runtime chip's state (a native folder, an old bridge, someone else's folder). Every sentence is a
9
+ // settings.redesign.skills.* key; the pane (settings-skill-folders-pane.js) draws it.
10
+
11
+ const RUNTIME = { claude: 'settings.redesign.product.claude', codex: 'settings.redesign.product.codex', opencode: 'settings.redesign.product.opencode', antigravity: 'settings.redesign.product.antigravity' };
12
+
13
+ /** What the status answer says, or that the server cannot say it yet (one from before the Skills Service). */
14
+ export function readFoldersStatus(answer) {
15
+ if (!answer || answer.ok !== true || !answer.bridges) return { available: false, message: { key: 'settings.redesign.skills.folders.unavailable' } };
16
+ const synabun = Number(answer.bridges.synabun) || 0;
17
+ const other = Number(answer.bridges.other) || 0;
18
+ return {
19
+ available: true,
20
+ sharedAgentsRoot: answer.config?.sharedAgentsRoot === true,
21
+ assistants: readAssistants(answer.assistants),
22
+ bridges: { synabun, other },
23
+ message: synabun === 0 ? { key: 'settings.redesign.skills.folders.bridgesNone' } : synabun === 1 ? { key: 'settings.redesign.skills.folders.bridgesOne' } : { key: 'settings.redesign.skills.folders.bridgesMany', params: { count: synabun } },
24
+ others: other === 0 ? null : other === 1 ? { key: 'settings.redesign.skills.folders.othersOne' } : { key: 'settings.redesign.skills.folders.othersMany', params: { count: other } },
25
+ canReview: synabun > 0,
26
+ };
27
+ }
28
+
29
+ const ASSISTANTS = ['claude', 'codex', 'opencode', 'antigravity'];
30
+
31
+ /**
32
+ * The owner's assistants (GET /v2/config `assistants`: chosen, detected, effective): one chip per runtime, on when
33
+ * it is in effect, and whether the list is the detected one (nothing chosen yet). A server from before this has none.
34
+ */
35
+ export function readAssistants(view) {
36
+ if (!view || !Array.isArray(view.effective)) return null;
37
+ const effective = view.effective.filter((r) => ASSISTANTS.includes(r));
38
+ const detected = (Array.isArray(view.detected) ? view.detected : []).filter((r) => ASSISTANTS.includes(r));
39
+ return {
40
+ auto: !Array.isArray(view.chosen),
41
+ effective, detected,
42
+ chips: ASSISTANTS.map((id) => ({ id, key: RUNTIME[id], on: effective.includes(id), detected: detected.includes(id) })),
43
+ detectedWords: detected.map((id) => ({ key: RUNTIME[id] })),
44
+ };
45
+ }
46
+
47
+ /** The list a chip's click sends (PUT /v2/config `assistants`): toggled, never empty (the last one stays on). */
48
+ export function toggledAssistants(effective, id) {
49
+ const now = (Array.isArray(effective) ? effective : []).filter((r) => ASSISTANTS.includes(r));
50
+ if (now.includes(id)) { const next = now.filter((r) => r !== id); return next.length ? next : now; }
51
+ return ASSISTANTS.filter((r) => now.includes(r) || r === id);
52
+ }
53
+
54
+ /**
55
+ * The lines of a migration plan, one per bridge of SynaBun's, and whether anything would move. The prompt and
56
+ * command files that are not SynaBun's are only counted (the status says how many): they are never moved, and a
57
+ * line each would bury the ones that are; except the bridge file of a skill SynaBun ships that is not proven its
58
+ * own (`offer`): that one is listed with a tick, "Move it too", and moves only once the owner confirms its bytes.
59
+ * @param {object} plan @param {Set<string>|string[]} [ticked] the offers the owner ticked (bridge ids)
60
+ */
61
+ export function readMigrationPlan(plan, ticked = []) {
62
+ const steps = Array.isArray(plan?.steps) ? plan.steps : [];
63
+ const on = new Set(ticked);
64
+ const lines = steps.filter((s) => s.action !== 'leave' || s.proof !== 'none' || s.ledgerRecord || s.offer).map((s) => {
65
+ const params = { runtime: { key: RUNTIME[s.runtime] || RUNTIME.codex }, name: `/${s.name}`, destination: s.native?.destination || '', why: s.why || '' };
66
+ if (s.action === 'migrate') return { tone: 'ok', key: s.proof === 'owner-confirmed' ? 'settings.redesign.skills.folders.stepConfirmed' : 'settings.redesign.skills.folders.stepMigrate', params, bridgeId: s.bridgeId, offer: s.proof === 'owner-confirmed' ? { digest: s.digest, on: true } : null };
67
+ if (s.action === 'blocked') return { tone: 'warn', key: 'settings.redesign.skills.folders.stepBlocked', params };
68
+ if (s.offer) return { tone: 'offer', key: 'settings.redesign.skills.folders.stepOffer', params, bridgeId: s.bridgeId, offer: { digest: s.offer.digest, on: on.has(s.bridgeId) } };
69
+ return { tone: 'muted', key: 'settings.redesign.skills.folders.stepLeave', params };
70
+ });
71
+ const movable = steps.filter((s) => s.action === 'migrate').length;
72
+ const confirm = Object.fromEntries(steps.filter((s) => s.proof === 'owner-confirmed').map((s) => [s.bridgeId, s.digest]));
73
+ return { lines, movable, offered: steps.filter((s) => s.action === 'leave' && s.offer).length, confirm, planDigest: typeof plan?.planDigest === 'string' ? plan.planDigest : null, empty: movable === 0 ? { key: 'settings.redesign.skills.folders.nothing' } : null };
74
+ }
75
+
76
+ /** What a move answered: done, in part (which and why), nothing to do. */
77
+ export function readMigrationOutcome(out) {
78
+ if (!out) return { tone: 'warn', key: 'settings.redesign.skills.folders.failed', params: { message: '' } };
79
+ if (out.nothingToDo) return { tone: 'muted', key: 'settings.redesign.skills.folders.nothing' };
80
+ if (out.status === 'done') return { tone: 'ok', key: 'settings.redesign.skills.folders.moved', params: { id: out.journalId } };
81
+ const failed = (out.results || []).filter((r) => r.outcome !== 'migrated').map((r) => `/${r.name}: ${r.error || r.outcome}`).join('; ');
82
+ if (out.status === 'failed') return { tone: 'warn', key: 'settings.redesign.skills.folders.failed', params: { message: failed } };
83
+ return { tone: 'warn', key: 'settings.redesign.skills.folders.movedPartly', params: { details: failed } };
84
+ }
85
+
86
+ /** What an undo answered. */
87
+ export function readRevertOutcome(out) {
88
+ if (!out) return { tone: 'warn', key: 'settings.redesign.skills.folders.failed', params: { message: '' } };
89
+ if (out.status === 'reverted') return { tone: 'ok', key: 'settings.redesign.skills.folders.undone' };
90
+ const details = (out.results || []).filter((r) => r.bridge === 'conflict' || r.bridge === 'failed' || r.native === 'kept').map((r) => r.why || r.path).join('; ');
91
+ return { tone: 'warn', key: 'settings.redesign.skills.folders.undonePartly', params: { details } };
92
+ }
93
+
94
+ /** The last move that can be undone, from GET /migrations (newest first). */
95
+ export function lastUndoable(list) {
96
+ const rows = (Array.isArray(list) ? list : []).filter((m) => m && (m.status === 'done' || m.status === 'partial' || m.status === 'partially-reverted') && m.migrated > 0);
97
+ rows.sort((a, b) => (a.createdAt < b.createdAt ? 1 : -1));
98
+ return rows[0] || null;
99
+ }
100
+
101
+ /**
102
+ * A runtime chip of a skill: its state (`native`: SynaBun's skill folder; `bridge`: an old bridge not moved yet;
103
+ * `shared`: SynaBun's copy in ~/.agents/skills, which Codex and OpenCode both read; `other`: a folder of that name
104
+ * SynaBun did not install, in the runtime's folder or the shared one; `installed`: a server from before the skill
105
+ * folders says only that it is there; `off`) and its title key.
106
+ * @param {object|undefined} state the skill's targetStates[runtime] from GET /api/skills
107
+ * @param {boolean} installed the older single flag (installedTargets[runtime])
108
+ */
109
+ export function chipState(state, installed) {
110
+ if (!state) return installed ? { state: 'installed', on: true, key: 'settings.redesign.skills.chip.installed' } : { state: 'off', on: false, key: 'settings.redesign.skills.installFor' };
111
+ if (state.native === 'native' || state.native === 'modified') return { state: 'native', on: true, key: 'settings.redesign.skills.chip.native' };
112
+ if (state.bridge) return { state: 'bridge', on: true, key: 'settings.redesign.skills.chip.bridge' };
113
+ if (state.shared === 'native') return { state: 'shared', on: true, key: 'settings.redesign.skills.chip.shared' };
114
+ if (state.native === 'other') return { state: 'other', on: false, key: 'settings.redesign.skills.chip.other' };
115
+ if (state.shared === 'other') return { state: 'other', on: false, key: 'settings.redesign.skills.chip.otherShared' };
116
+ return { state: 'off', on: false, key: 'settings.redesign.skills.installFor' };
117
+ }
118
+
119
+ /**
120
+ * The toast after a chip installed a skill: a skill folder of its own, whether an old bridge of it is still there,
121
+ * and what the runtime needs to see it (`refresh` of the install answer: automatic, reload-skills, new-session).
122
+ */
123
+ export function installedToast(answer) {
124
+ if (answer?.shared) return 'settings.redesign.skills.chip.installedShared';
125
+ if (answer?.bridge) return 'settings.redesign.skills.chip.installedBridgeLeft';
126
+ const kinds = new Set((Array.isArray(answer?.refresh) ? answer.refresh : []).map((r) => r?.kind));
127
+ if (kinds.has('new-session')) return 'settings.redesign.skills.chip.installedNewSession';
128
+ if (kinds.has('reload-skills')) return 'settings.redesign.skills.chip.installedReload';
129
+ return 'settings.redesign.skills.chip.installedNative';
130
+ }
@@ -0,0 +1,72 @@
1
+ // ═══════════════════════════════════════════
2
+ // SETTINGS — Protect workers, in words
3
+ // ═══════════════════════════════════════════
4
+ //
5
+ // What `GET /api/assistant/worker-guard` (lib/assistant-api.js; the setting in lib/worker-guard-setting.js, what
6
+ // it means in lib/worker-confinement.js) says about Settings → Automations → Automation behavior → Protect
7
+ // workers: the mode in effect (enforce, warn, off), whether it can be changed, and what stands in the way. Pure:
8
+ // no DOM and no import, so node runs it (tests/settings-worker-guard-view.test.mjs).
9
+ //
10
+ // readWorkerGuardResponse({ status, body, error }) what the server answered → a reading
11
+ // describeWorkerGuard(reading, { tx }) the row as ui-settings.js draws it
12
+ // describeWorkerGuardSaveFailure(input, { tx }) the sentence for a choice that could not be saved
13
+ //
14
+ // `tx(key, params)` is the caller's translate function over the settings.redesign.* strings (the kit's `tx`).
15
+ // The row never shows a healthy-looking control for something that is not happening: a server started before
16
+ // the setting existed shows the default, disabled, and says a restart is missing.
17
+
18
+ const K = 'settings.redesign.hooks.workerGuard';
19
+
20
+ export const WORKER_GUARD_MODES = Object.freeze(['enforce', 'warn', 'off']);
21
+ export const WORKER_GUARD_DEFAULT = 'enforce';
22
+
23
+ const clean = (value, max = 200) => {
24
+ const text = String(value ?? '').replace(/\s+/g, ' ').trim();
25
+ return text.length > max ? `${text.slice(0, max - 1)}…` : text;
26
+ };
27
+
28
+ /**
29
+ * What the server answered.
30
+ *
31
+ * ready the setting is there: `mode` is in effect, `modes` the choices
32
+ * old-server 404: the running server was started before the setting existed
33
+ * failed 503 WORKER_GUARD_UNAVAILABLE: the setting did not start; `reason` is the error
34
+ * unreadable anything else (no answer, a refusal, a body that is not the payload)
35
+ */
36
+ export function readWorkerGuardResponse({ status = 0, body = null, error = null } = {}) {
37
+ const code = Number(status) || 0;
38
+ if (code === 404) return { state: 'old-server', mode: WORKER_GUARD_DEFAULT, modes: [...WORKER_GUARD_MODES], reason: null };
39
+ if (code === 503) return { state: 'failed', mode: WORKER_GUARD_DEFAULT, modes: [...WORKER_GUARD_MODES], reason: clean(body?.reason || body?.error) || null };
40
+ if (code >= 200 && code < 300 && body && typeof body === 'object' && body.ok !== false && WORKER_GUARD_MODES.includes(body.mode)) {
41
+ const modes = Array.isArray(body.modes) && body.modes.every((m) => WORKER_GUARD_MODES.includes(m)) && body.modes.length ? body.modes : [...WORKER_GUARD_MODES];
42
+ return { state: 'ready', mode: body.mode, modes, reason: null };
43
+ }
44
+ return { state: 'unreadable', mode: WORKER_GUARD_DEFAULT, modes: [...WORKER_GUARD_MODES], reason: clean(error || body?.error || (code ? `HTTP ${code}` : '')) || null };
45
+ }
46
+
47
+ /** The row: { ready, disabled, mode, options: [{ value, label, help }], note: { text, tone } | null, applies }. */
48
+ export function describeWorkerGuard(reading, { tx }) {
49
+ const r = reading || readWorkerGuardResponse({ status: 0 });
50
+ const options = (r.modes || WORKER_GUARD_MODES).map((value) => ({ value, label: tx(`${K}.mode.${value}`), help: tx(`${K}.modeHelp.${value}`) }));
51
+ let note = null;
52
+ if (r.state === 'old-server') note = { text: tx(`${K}.restart`), tone: 'warn' };
53
+ else if (r.state === 'failed') note = { text: r.reason ? tx(`${K}.failed`, { reason: r.reason }) : tx(`${K}.failedNoReason`), tone: 'warn' };
54
+ else if (r.state === 'unreadable') note = { text: r.reason ? tx(`${K}.unreadable`, { reason: r.reason }) : tx(`${K}.unreadableNoReason`), tone: 'warn' };
55
+ return {
56
+ ready: r.state === 'ready',
57
+ disabled: r.state !== 'ready',
58
+ mode: r.mode || WORKER_GUARD_DEFAULT,
59
+ options,
60
+ note,
61
+ applies: tx(`${K}.applies`),
62
+ };
63
+ }
64
+
65
+ /** The sentence under the row when a choice could not be saved: { status, body, error, mode }. */
66
+ export function describeWorkerGuardSaveFailure({ status = 0, body = null, error = null, mode = '' } = {}, { tx }) {
67
+ const code = Number(status) || 0;
68
+ const name = tx(`${K}.mode.${WORKER_GUARD_MODES.includes(mode) ? mode : WORKER_GUARD_DEFAULT}`);
69
+ if (code === 404) return tx(`${K}.save.oldServer`, { mode: name });
70
+ if (!code) return tx(`${K}.save.noAnswer`, { mode: name, reason: clean(error) || '' });
71
+ return tx(`${K}.save.failed`, { mode: name, reason: clean(body?.error || error) || `HTTP ${code}` });
72
+ }
@@ -55,13 +55,18 @@ export const WHOLESALE_SELECTORS = [
55
55
  // OpenCode side panel transcript
56
56
  '.ocpv2-part-text', '.ocpv2-reasoning-body', '.ocpv2-tc-summary', '.ocpv2-tc-meta', '.ocpv2-tc-body',
57
57
  '.ocpv2-tool-input', '.ocpv2-tool-output', '.ocpv2-sb-summary',
58
+ // Antigravity side panel: session names, the transcript, tool and request cards, the plan, what waits to be sent
59
+ '.agy-session-label', '.agy-tab-label', '.agy-sess-list .agy-pop-item-title', '.agy-sess-list .agy-pop-item-meta',
60
+ '.agy-msg-text', '.agy-msg .agy-md', '.agy-msg-image', '.agy-thought-body',
61
+ '.agy-card-title', '.agy-card-subtitle', '.agy-card-text', '.agy-card-body', '.agy-card-error', '.agy-plan-text',
62
+ '.agy-queue-text', '.agy-chip', '.agy-folder-chip',
58
63
  // Assistant transcript, run and worker cards
59
64
  '.asst-msg-text', '.asst-md', '.asst-thinking-content', '.asst-run-title', '.asst-run-summary', '.asst-run-escalate-reason',
60
65
  '.asst-tool-detail', '.asst-tool-body', '.asst-tool-section', '.asst-tl-said', '.asst-tl-subject', '.asst-bubble-text',
61
66
  '.asst-station-sub', '.asst-station-log', '.asst-auto-title', '.asst-auto-summary', '.asst-auto-detail',
62
67
  // Composers, once they hold text (an empty one keeps its placeholder sharp)
63
68
  '#cp-input:not(:placeholder-shown)', '#cxp-input:not(:placeholder-shown)', '.ocpv2-compose-input:not(:placeholder-shown)',
64
- '.asst-input:not(:placeholder-shown)',
69
+ '.asst-input:not(:placeholder-shown)', '.agy-input:not(:placeholder-shown)',
65
70
  // Terminal output (the WebGL canvas and the DOM renderer alike) and the terminal's browser tab
66
71
  '.term-viewport .xterm-screen', '.term-float-tab-body .xterm', '.browser-canvas', '.browser-url-input', '.browser-title-label',
67
72
  // Resume results
@@ -8,8 +8,8 @@
8
8
  // Assistant (sessionStatus). The same source as the tray pills, never a second
9
9
  // guess. DOM-free.
10
10
 
11
- const WORKING = /^(cp|cxp|ocpv2|asp)-pill-running$/;
12
- const NEEDS_YOU = /^((cp|cxp|asp)-pill-attention|ocpv2-pill-waiting)$/;
11
+ const WORKING = /^(cp|cxp|ocpv2|agy|asp)-pill-running$/;
12
+ const NEEDS_YOU = /^((cp|cxp|agy|asp)-pill-attention|ocpv2-pill-waiting)$/;
13
13
 
14
14
  /** The states a detached window's pill shows: a session in it needs you > one works > none. */
15
15
  export const SESSION_WINDOW_STATES = Object.freeze(['action', 'working', 'idle']);
@@ -44,6 +44,6 @@ export function normalizeSessionWindowStatus(status) {
44
44
  */
45
45
  export function runAwaitsAnswer(run) {
46
46
  if (run?.status !== 'starting' && run?.status !== 'running') return false;
47
- if (run.turnState === 'needs_input') return true;
47
+ if (run.turnState === 'needs_input' || run.turnState === 'awaiting_permission' || run.pending?.some((p) => p.kind === 'question')) return true;
48
48
  return run.turnState === 'idle' && (run.outcome || run.lastResult?.status) === 'needs_input';
49
49
  }