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
@@ -1,7 +1,7 @@
1
1
  // ═══════════════════════════════════════════
2
2
  // SynaBun — CLI Update Planner
3
3
  //
4
- // Works out HOW each external CLI (Claude Code, Codex, OpenCode, Gemini) was
4
+ // Works out HOW each external CLI (Claude Code, Codex, OpenCode, Antigravity) was
5
5
  // installed, and therefore which command actually updates it and which
6
6
  // "latest version" it should be compared against.
7
7
  //
@@ -16,12 +16,17 @@
16
16
  // PATH, so the update silently does nothing and the badge never clears.
17
17
  // ═══════════════════════════════════════════
18
18
 
19
- /** npm package name per tool key. */
19
+ /**
20
+ * npm package name per tool key. OpenCode has none: npm's opencode-ai is
21
+ * OpenCode 1, which SynaBun does not drive, and OpenCode 2 is installed by its
22
+ * own script, Homebrew or WinGet (lib/opencode-protocol.js). Neither has the
23
+ * Antigravity CLI (`agy`): Google ships it as a binary, through its own
24
+ * installer script or the Homebrew cask antigravity-cli, and it updates itself
25
+ * (`agy update`).
26
+ */
20
27
  export const NPM_PKGS = {
21
28
  'claude-code': '@anthropic-ai/claude-code',
22
29
  'codex': '@openai/codex',
23
- 'gemini': '@google/gemini-cli',
24
- 'opencode': 'opencode-ai',
25
30
  };
26
31
 
27
32
  /**
@@ -32,21 +37,23 @@ export const NPM_PKGS = {
32
37
  export const BREW_FALLBACK_TOKENS = {
33
38
  'claude-code': 'claude-code',
34
39
  'codex': 'codex',
35
- 'gemini': 'gemini-cli',
36
- 'opencode': 'opencode',
40
+ 'antigravity': 'antigravity-cli',
41
+ // OpenCode 2's own tap (its `opencode` formula there is still OpenCode 1).
42
+ 'opencode': 'anomalyco/tap/opencode-v2',
37
43
  };
38
44
 
39
45
  /**
40
46
  * Whether each tool ships as a Homebrew cask or a formula. This is a property
41
- * of the package, not of the machine — claude-code and codex exist ONLY as
42
- * casks, gemini-cli and opencode ONLY as formulae. Needed when a tool is not
47
+ * of the package, not of the machine — claude-code, codex and antigravity-cli
48
+ * exist ONLY as casks, opencode ONLY as a formula. Needed when a tool is not
43
49
  * installed and there is no path to classify: guessing the wrong flavour
44
- * produces a command that simply errors ("Cask 'gemini-cli' is unavailable").
50
+ * produces a command that simply errors ("No available formula with the name
51
+ * 'antigravity-cli'").
45
52
  */
46
53
  export const BREW_KINDS = {
47
54
  'claude-code': 'cask',
48
55
  'codex': 'cask',
49
- 'gemini': 'formula',
56
+ 'antigravity': 'cask',
50
57
  'opencode': 'formula',
51
58
  };
52
59
 
@@ -55,23 +62,22 @@ const SELF_UPDATERS = {
55
62
  'claude-code': 'claude update',
56
63
  'codex': 'codex update',
57
64
  'opencode': 'opencode upgrade',
58
- // gemini has no self-updater.
65
+ 'antigravity': 'agy update',
59
66
  };
60
67
 
61
68
  /**
62
- * OpenCode's `upgrade --method` accepts exactly these values. Mapping our
63
- * detected source onto it lets OpenCode do its own install-aware work for
64
- * the channels we cannot drive directly.
69
+ * The `upgrade --method` of OpenCode 2 for a detected source (its own installer
70
+ * script, a JavaScript package manager, WinGet). Mapping our detected source
71
+ * onto it lets OpenCode do its own install-aware work for the channels we
72
+ * cannot drive directly.
65
73
  */
66
74
  const OPENCODE_METHODS = {
67
75
  'standalone': 'curl',
68
76
  'npm': 'npm',
69
77
  'pnpm': 'pnpm',
70
78
  'bun': 'bun',
71
- 'brew-formula': 'brew',
72
- 'brew-cask': 'brew',
73
- 'choco': 'choco',
74
- 'scoop': 'scoop',
79
+ 'yarn': 'yarn',
80
+ 'winget': 'winget',
75
81
  };
76
82
 
77
83
  /** Sources that mean "a package manager other than the tool itself owns this". */
@@ -196,7 +202,7 @@ const TOOL_COMMANDS = {
196
202
  'claude-code': 'claude',
197
203
  'codex': 'codex',
198
204
  'opencode': 'opencode',
199
- 'gemini': 'gemini',
205
+ 'antigravity': 'agy',
200
206
  };
201
207
 
202
208
  /**
@@ -248,6 +254,15 @@ function planUpdateCommand(toolKey, installSource, { brewToken = null, platform
248
254
  : `brew upgrade ${token}`;
249
255
  }
250
256
 
257
+ // OpenCode 2 updates itself through the channel it came from (brew is handled above).
258
+ if (toolKey === 'opencode') {
259
+ // Its installer script is bash: a copy in %USERPROFILE%\.opencode\bin on Windows is no OpenCode 2 install.
260
+ if (installSource === 'standalone' && platform === 'win32') return null;
261
+ if (OPENCODE_METHODS[installSource]) return `opencode upgrade --method ${OPENCODE_METHODS[installSource]}`;
262
+ if (['volta', 'scoop', 'choco'].includes(installSource)) return null; // not an OpenCode 2 channel: the caller shows a hint
263
+ return selfUpdate;
264
+ }
265
+
251
266
  if (!npmPkg) return selfUpdate;
252
267
 
253
268
  switch (installSource) {
@@ -255,24 +270,15 @@ function planUpdateCommand(toolKey, installSource, { brewToken = null, platform
255
270
  case 'yarn': return `yarn global add ${npmPkg}@latest`;
256
271
  case 'volta': return `volta install ${npmPkg}@latest`;
257
272
  case 'bun':
273
+ return `bun add -g ${npmPkg}@latest`;
258
274
  case 'pnpm':
259
- // OpenCode drives these itself; the others take the plain global add.
260
- if (toolKey === 'opencode') return `opencode upgrade --method ${OPENCODE_METHODS[installSource]}`;
261
- return installSource === 'bun'
262
- ? `bun add -g ${npmPkg}@latest`
263
- : `pnpm add -g ${npmPkg}@latest`;
275
+ return `pnpm add -g ${npmPkg}@latest`;
264
276
  case 'scoop':
265
277
  case 'choco':
266
- if (toolKey === 'opencode') return `opencode upgrade --method ${OPENCODE_METHODS[installSource]}`;
267
- return null; // no safe automated path — caller shows a hint
268
278
  case 'winget':
269
- return null;
279
+ return null; // no safe automated path — caller shows a hint
270
280
  case 'standalone':
271
281
  // The tool's own installer put it here, so its own updater is right.
272
- // OpenCode's `curl` method runs its bash install script, which Windows
273
- // does not have: a copy in %USERPROFILE%\.opencode\bin there came from
274
- // the release archive (lib/cli-install.js) and has no updater to call.
275
- if (toolKey === 'opencode') return platform === 'win32' ? null : 'opencode upgrade --method curl';
276
282
  return selfUpdate;
277
283
  case 'native':
278
284
  return selfUpdate;
@@ -373,10 +379,13 @@ export function installSourceLabel(source) {
373
379
  /**
374
380
  * The install command each vendor documents first for an operating system
375
381
  * (checked 2026-10-17): Anthropic's native installer (code.claude.com/docs/en/setup),
376
- * OpenAI's standalone installer (learn.chatgpt.com/docs/codex/cli), OpenCode's
377
- * install script (opencode.ai/docs; on Windows, where the script does not run,
378
- * npm, the first method its docs list that works in any terminal). These are
379
- * the same official sources the Install button runs (lib/cli-install.js).
382
+ * OpenAI's standalone installer (learn.chatgpt.com/docs/codex/cli), OpenCode 2's
383
+ * install script (https://opencode.ai/v2/install, the one `opencode upgrade`
384
+ * runs; on Windows, where the script does not run, WinGet), and (checked
385
+ * 2026-10-30) Google's Antigravity CLI installer
386
+ * (antigravity.google/docs/getting-started). These are the same official
387
+ * sources the Install button runs (lib/cli-install.js), which on a Mac with
388
+ * Homebrew installs the Antigravity CLI's cask instead.
380
389
  */
381
390
  export function vendorInstallCommand(toolKey, platform = process.platform) {
382
391
  const windows = platform === 'win32';
@@ -388,7 +397,11 @@ export function vendorInstallCommand(toolKey, platform = process.platform) {
388
397
  ? 'powershell -ExecutionPolicy ByPass -c "irm https://chatgpt.com/codex/install.ps1 | iex"'
389
398
  : 'curl -fsSL https://chatgpt.com/codex/install.sh | sh';
390
399
  case 'opencode':
391
- return windows ? `npm install -g ${NPM_PKGS.opencode}` : 'curl -fsSL https://opencode.ai/install | bash';
400
+ return windows ? 'winget install --id Anomaly.OpenCode --exact' : 'curl -fsSL https://opencode.ai/v2/install | bash';
401
+ case 'antigravity':
402
+ // Google's installer: it checks the binary against the SHA-512 of Google's release manifest and puts agy in
403
+ // ~/.local/bin (%LOCALAPPDATA%\agy\bin on Windows). A Homebrew machine is told the cask (buildInstallCommand).
404
+ return windows ? 'irm https://antigravity.google/cli/install.ps1 | iex' : 'curl -fsSL https://antigravity.google/cli/install.sh | bash';
392
405
  default:
393
406
  return NPM_PKGS[toolKey] ? `npm install -g ${NPM_PKGS[toolKey]}` : '';
394
407
  }
@@ -420,7 +433,9 @@ export function buildInstallCommand(toolKey, installSource = 'unknown', { platfo
420
433
  ? `brew install --cask ${token}`
421
434
  : `brew install ${token}`;
422
435
  }
423
- if (!npmPkg) return '';
436
+ // OpenCode 2 and the Antigravity CLI have no npm package: their vendor's installer whatever JavaScript package
437
+ // manager the machine uses.
438
+ if (!npmPkg) return vendorInstallCommand(toolKey, platform || process.platform);
424
439
  switch (installSource) {
425
440
  case 'bun': return `bun add -g ${npmPkg}`;
426
441
  case 'pnpm': return `pnpm add -g ${npmPkg}`;
@@ -438,10 +453,6 @@ function platformInstallCommand(toolKey, installSource, platform) {
438
453
  if (windows && installSource === 'winget') return 'winget install Anthropic.ClaudeCode';
439
454
  return vendor;
440
455
  }
441
- if (toolKey === 'opencode' && windows) {
442
- if (installSource === 'scoop') return 'scoop install opencode';
443
- if (installSource === 'choco') return 'choco install opencode';
444
- }
445
456
  // A JavaScript package manager this machine already uses: keep to it.
446
457
  if (['npm', 'bun', 'pnpm', 'yarn', 'volta'].includes(installSource)) return null;
447
458
  return vendor || null;
@@ -28,6 +28,15 @@
28
28
  //
29
29
  // An ended process is not forgotten: it is asked to end (SIGTERM), killed when
30
30
  // it is still there a moment later (SIGKILL), and kept until it has exited.
31
+ //
32
+ // Each cloudflared it starts is on record from its spawn until it has exited
33
+ // (`records`: lib/opencode-serve-records.js, kind 'quick', in
34
+ // DATA_HOME/runtime/tunnels), with a token of its start in its environment. A
35
+ // server that ends without its exit handlers (a native crash) leaves its
36
+ // cloudflared running on macOS and Linux (Windows ends a child with its parent),
37
+ // the old address still pointing at the port the next server listens on: the
38
+ // next server ends it by that record (server.js sweepLeftoverTunnels), and only
39
+ // while the OS still reports that very process.
31
40
 
32
41
  import { spawn as nodeSpawn } from 'node:child_process';
33
42
 
@@ -69,6 +78,22 @@ export function tunnelArguments(port, source) {
69
78
  return ['tunnel', ...(source === 'system' ? [] : ['--no-autoupdate']), '--url', `http://localhost:${port}`];
70
79
  }
71
80
 
81
+ /** The kind of the tunnel's records (lib/opencode-serve-records.js createServeRecords `kinds`). */
82
+ export const TUNNEL_KINDS = Object.freeze(['quick']);
83
+
84
+ /**
85
+ * Are `args` (a command line's arguments, as the platform reads them: lib/opencode-serve-records.js commandArgs) a
86
+ * quick tunnel to this server's `port` (`… tunnel … --url http://localhost:<port>`, as tunnelArguments makes them)?
87
+ * What a tunnel record must name.
88
+ */
89
+ export function tunnelsToPort(args, port) {
90
+ const p = Number(port);
91
+ if (!Array.isArray(args) || !Number.isInteger(p) || p <= 0 || p > 65535) return false;
92
+ if (!args.includes('tunnel')) return false;
93
+ const url = `http://localhost:${p}`;
94
+ return args.some((arg, i) => arg === `--url=${url}` || (arg === '--url' && args[i + 1] === url));
95
+ }
96
+
72
97
  /** What cloudflared said last that reads like a reason: its last error line, without the timestamp. */
73
98
  function lastReason(output) {
74
99
  const lines = output.split(/\r?\n/).map((line) => line.trim()).filter(Boolean);
@@ -85,8 +110,10 @@ function lastReason(output) {
85
110
  * @param {number} [o.urlTimeoutMs] how long a started cloudflared may take to print its address
86
111
  * @param {number} [o.killAfterMs] how long an ended cloudflared has to exit before it is killed
87
112
  * @param {(line: string) => void} [o.log]
113
+ * @param {{ newToken: () => string, tokenEnv: string, record: (entry: object) => Promise<object|null>, remove: (entry: object) => boolean }} [o.records]
114
+ * where each cloudflared it starts is kept on record until it has exited (lib/opencode-serve-records.js, kind 'quick')
88
115
  */
89
- export function createQuickTunnel({ cloudflared, port, onUrl = () => {}, spawn = nodeSpawn, urlTimeoutMs = 90_000, killAfterMs = 1000, log = () => {} }) {
116
+ export function createQuickTunnel({ cloudflared, port, onUrl = () => {}, spawn = nodeSpawn, urlTimeoutMs = 90_000, killAfterMs = 1000, log = () => {}, records = null }) {
90
117
  let phase = 'idle'; // idle | preparing | starting | running | failed
91
118
  let child = null;
92
119
  let url = null;
@@ -117,7 +144,19 @@ export function createQuickTunnel({ cloudflared, port, onUrl = () => {}, spawn =
117
144
  log(` Tunnel: ${code === 'ended' ? 'stopped' : 'not started'} (${code}): ${message}`);
118
145
  }
119
146
 
147
+ // On record from its spawn until it has exited: what the next server ends when this one crashed (see above).
148
+ function keepOnRecord(proc, token) {
149
+ const pid = Number(proc?.pid) || null;
150
+ if (!pid) return;
151
+ const kept = Promise.resolve().then(() => records.record({ kind: TUNNEL_KINDS[0], port: Number(port), pid, token })).catch(() => null);
152
+ proc.once('exit', () => { kept.then((entry) => { if (entry) records.remove(entry); }).catch(() => {}); });
153
+ }
154
+
120
155
  function launch(found, mine) {
156
+ // The token of this start, in its environment: made before the check below, so nothing runs between them.
157
+ let token = null;
158
+ try { token = records?.tokenEnv ? records.newToken() : null; } catch { token = null; }
159
+ const options = { stdio: ['ignore', 'pipe', 'pipe'], windowsHide: true, ...(token ? { env: { ...process.env, [records.tokenEnv]: token } } : {}) };
121
160
  // Checked once more as it is about to run (the manager's confirm: the very file its check read, still where
122
161
  // nobody else can change it), and started at once by the real path that was checked: nothing runs in between.
123
162
  let path = found.path;
@@ -128,10 +167,11 @@ export function createQuickTunnel({ cloudflared, port, onUrl = () => {}, spawn =
128
167
  }
129
168
  let proc;
130
169
  try {
131
- proc = spawn(path, tunnelArguments(port, found.source), { stdio: ['ignore', 'pipe', 'pipe'], windowsHide: true });
170
+ proc = spawn(path, tunnelArguments(port, found.source), options);
132
171
  } catch (failure) {
133
172
  return fail('launch', `cloudflared could not be started (${failure?.code || failure?.message || failure}).`);
134
173
  }
174
+ if (token) keepOnRecord(proc, token);
135
175
  child = proc;
136
176
  copy = { source: found.source, version: found.version };
137
177
  phase = 'starting';
@@ -1,5 +1,16 @@
1
+ import { codexMcpToolApproval } from '../public/shared/cdx/cdx-protocol.js';
2
+
1
3
  const CODEX_MCP_APPROVAL_MODES = new Set(['auto', 'prompt', 'writes', 'approve']);
2
4
 
5
+ /** Auto is this session's choice; Claude's allow list is not a Codex approval prerequisite. */
6
+ export function shouldAutoAcceptCodexMcpToolApproval(params, { autoAccept = false, role = null } = {}) {
7
+ const approval = codexMcpToolApproval(params);
8
+ if (!approval) return false;
9
+ // agent_route owns the model-choice card. Calling it must not require an
10
+ // additional permission card, even when ordinary tools are set to Ask.
11
+ return autoAccept || (role === 'assistant' && approval.fullName === 'mcp__SynaBun__agent_route');
12
+ }
13
+
3
14
  export function codexConfigKeyPathSegment(value) {
4
15
  const text = String(value || '').trim();
5
16
  if (!text) throw new Error('Codex config key path segments cannot be empty');
@@ -0,0 +1,52 @@
1
+ // ── A Codex rollout, read once for the preview and the history fallback ──
2
+ // The early preview (server.js sendEarlyCodexRolloutPreview) used to readFileSync the
3
+ // whole rollout JSONL before Codex's app-server started, for every thread a tab
4
+ // bootstrapped, and the history fallback read it again right after. This reads it as
5
+ // a stream (the event loop and the app-server's start are not held up) and keeps the
6
+ // parsed items of the last few files by path, size and time, so the fallback that
7
+ // follows reuses them while the file is unchanged.
8
+
9
+ import { createReadStream, statSync } from 'node:fs';
10
+ import { jsonlLines } from './jsonl-lines.js';
11
+
12
+ export function createRolloutReader({
13
+ open = (path) => createReadStream(path, { encoding: 'utf-8' }),
14
+ stat = statSync,
15
+ maxEntries = 4,
16
+ } = {}) {
17
+ const kept = new Map(); // path → { size, mtimeMs, items }
18
+ const running = new Map(); // `${path}|${size}|${mtimeMs}` → promise of items
19
+ const stats = { reads: 0, reused: 0 };
20
+
21
+ /** The items `parse(lines)` makes of the file at `path` (an async iterable of its lines). */
22
+ async function items(path, parse) {
23
+ if (!path) return [];
24
+ let st;
25
+ try { st = stat(path); } catch { return []; }
26
+ const hit = kept.get(path);
27
+ if (hit && hit.size === st.size && hit.mtimeMs === st.mtimeMs) {
28
+ stats.reused++;
29
+ kept.delete(path); kept.set(path, hit);
30
+ return hit.items;
31
+ }
32
+ const key = `${path}|${st.size}|${st.mtimeMs}`;
33
+ if (running.has(key)) { stats.reused++; return running.get(key); }
34
+ const job = (async () => {
35
+ stats.reads++;
36
+ const stream = open(path);
37
+ try {
38
+ const out = await parse(jsonlLines(stream));
39
+ kept.delete(path);
40
+ kept.set(path, { size: st.size, mtimeMs: st.mtimeMs, items: out });
41
+ while (kept.size > maxEntries) kept.delete(kept.keys().next().value);
42
+ return out;
43
+ } finally {
44
+ stream.destroy?.();
45
+ }
46
+ })();
47
+ running.set(key, job);
48
+ try { return await job; } finally { running.delete(key); }
49
+ }
50
+
51
+ return { items, forget: (path) => kept.delete(path), get stats() { return { ...stats }; }, get size() { return kept.size; } };
52
+ }
@@ -0,0 +1,191 @@
1
+ // One app-server per dispatched worker. The SDK-shaped surface keeps the native
2
+ // worker's event/usage contract while thread/resume reopens its durable thread.
3
+ import { spawn, execFileSync } from 'node:child_process';
4
+ import { StringDecoder } from 'node:string_decoder';
5
+
6
+ const toml = (v) => Array.isArray(v) ? `[${v.map(toml).join(',')}]`
7
+ : v && typeof v === 'object' ? `{${Object.entries(v).filter(([, x]) => x != null).map(([k, x]) => `${JSON.stringify(k)}=${toml(x)}`).join(',')}}`
8
+ : JSON.stringify(v);
9
+
10
+ // Match the SDK's leaf overrides: pins/switches address only their intended
11
+ // fields and leave native command/url/env definitions in the native config.
12
+ // Codex splits override paths literally on dots (it does not parse TOML keys).
13
+ // Top-level keys may already be override paths; nested keys are literal segments.
14
+ export function codexWorkerConfigOverrides(config) {
15
+ const overrides = [];
16
+ const visit = (value, path) => {
17
+ if (value == null) return;
18
+ if (typeof value === 'object' && !Array.isArray(value)) {
19
+ for (const [key, child] of Object.entries(value)) {
20
+ if (path && /[.=\x00-\x1f\x7f]/.test(key)) throw new Error('Codex override paths cannot address this config key');
21
+ visit(child, path ? `${path}.${key}` : key);
22
+ }
23
+ } else overrides.push(`${path}=${toml(value)}`);
24
+ };
25
+ visit(config, '');
26
+ return overrides;
27
+ }
28
+
29
+ export class CodexWorkerAppServer {
30
+ constructor({ codexPathOverride, env, config = {}, configArgs = [], apiKey, signal, onProcess = () => {}, onRequest = null, permissionPolicy = 'auto' }) {
31
+ this.onRequest = onRequest;
32
+ this.approvalPolicy = permissionPolicy === 'ask' ? 'untrusted' : 'never';
33
+ this.requestAbort = new AbortController();
34
+ this.incoming = new Map();
35
+ this.requestAbort.signal.addEventListener('abort', () => { for (const pending of this.incoming.values()) pending.abort(); this.incoming.clear(); }, { once: true });
36
+ this.pending = new Map();
37
+ this.seq = 0;
38
+ this.listener = null;
39
+ this.failure = null;
40
+ const args = [...configArgs];
41
+ for (const override of codexWorkerConfigOverrides(config)) args.push('-c', override);
42
+ // Run identity in the command line permits conservative orphan identification.
43
+ args.push('-c', `synabun_worker_run=${JSON.stringify(env.SYNABUN_TERMINAL_SESSION || '')}`, 'app-server');
44
+ this.proc = spawn(codexPathOverride, args, { env, stdio: ['pipe', 'pipe', 'pipe'], windowsHide: true });
45
+ this.exited = new Promise((r) => this.proc.once('close', r));
46
+ onProcess({ pid: this.proc.pid, startedAt: new Date().toISOString() });
47
+ let buffer = '';
48
+ const decoder = new StringDecoder('utf8');
49
+ this.proc.stdout.on('data', (chunk) => {
50
+ buffer += decoder.write(chunk);
51
+ let end;
52
+ while ((end = buffer.indexOf('\n')) >= 0) {
53
+ const line = buffer.slice(0, end); buffer = buffer.slice(end + 1);
54
+ let msg; try { msg = JSON.parse(line); } catch { continue; }
55
+ if (msg.id != null && !msg.method) {
56
+ const p = this.pending.get(msg.id); if (!p) continue;
57
+ this.pending.delete(msg.id); clearTimeout(p.timer);
58
+ msg.error ? p.reject(new Error(msg.error.message || 'Codex RPC failed')) : p.resolve(msg.result);
59
+ } else if (msg.id != null) {
60
+ const controller = new AbortController();
61
+ this.incoming.set(msg.id, controller);
62
+ Promise.resolve().then(() => {
63
+ if (!this.onRequest) throw new Error('Worker has no interactive request handler');
64
+ return this.onRequest(msg, controller.signal);
65
+ }).then((reply) => {
66
+ if (!this.failure && !controller.signal.aborted) this.write({ id: msg.id, ...reply });
67
+ }, (error) => {
68
+ if (!this.failure && !controller.signal.aborted) this.write({ id: msg.id, error: { code: -32000, message: error.message } });
69
+ }).finally(() => this.incoming.delete(msg.id));
70
+ } else {
71
+ if (msg.method === 'serverRequest/resolved') this.incoming.get(msg.params?.requestId)?.abort();
72
+ if (msg.method === 'turn/completed') { for (const pending of this.incoming.values()) pending.abort(); this.incoming.clear(); }
73
+ this.listener?.(msg);
74
+ }
75
+ }
76
+ });
77
+ // Drain stderr without exposing credentials/config to the worker transcript.
78
+ this.proc.stderr.resume();
79
+ this.proc.on('error', (error) => this.fail(error));
80
+ this.proc.stdin.on('error', (error) => this.fail(error));
81
+ this.proc.on('close', (code, signal) => this.fail(new Error(`Codex app-server exited (${signal || code})`)));
82
+ this.ready = (async () => {
83
+ await this.rpc('initialize', { clientInfo: { name: 'synabun-worker', version: '1.0.0' }, capabilities: { experimentalApi: true } });
84
+ this.write({ method: 'initialized', params: {} });
85
+ if (apiKey) await this.rpc('account/login/start', { type: 'apiKey', apiKey });
86
+ })();
87
+ this.ready.catch(() => {});
88
+ this.startupSignal = signal;
89
+ this.cancelStartup = () => { this.dispose().catch(() => {}); };
90
+ signal?.addEventListener('abort', this.cancelStartup, { once: true });
91
+ if (signal?.aborted) this.cancelStartup();
92
+ }
93
+ write(value) { if (!this.proc.stdin.destroyed) this.proc.stdin.write(JSON.stringify(value) + '\n'); }
94
+ fail(error) {
95
+ this.failure = error;
96
+ this.requestAbort.abort();
97
+ for (const p of this.pending.values()) { clearTimeout(p.timer); p.reject(error); }
98
+ this.pending.clear();
99
+ this.listener?.({ method: 'synabun/exit', error });
100
+ }
101
+ rpc(method, params) {
102
+ if (this.failure) return Promise.reject(this.failure);
103
+ return new Promise((resolve, reject) => {
104
+ const id = ++this.seq;
105
+ const timer = setTimeout(() => { this.pending.delete(id); reject(new Error(`Codex ${method} timed out`)); }, 30_000);
106
+ this.pending.set(id, { resolve, reject, timer });
107
+ this.write({ id, method, params });
108
+ });
109
+ }
110
+ startThread(options) { return this.thread(null, options); }
111
+ resumeThread(id, options) { return this.thread(id, options); }
112
+ thread(id, options) {
113
+ const owner = this;
114
+ const sandboxPolicy = options.sandboxMode === 'read-only' ? { type: 'readOnly', networkAccess: !!options.networkAccessEnabled }
115
+ : options.sandboxMode === 'workspace-write' ? { type: 'workspaceWrite', writableRoots: [options.workingDirectory, ...(options.additionalDirectories || [])], networkAccess: !!options.networkAccessEnabled }
116
+ : { type: 'dangerFullAccess' };
117
+ const ready = this.ready.then(async () => {
118
+ const reply = await this.rpc(id ? 'thread/resume' : 'thread/start', {
119
+ ...(id ? { threadId: id } : {}), cwd: options.workingDirectory,
120
+ model: options.model || null, approvalPolicy: owner.approvalPolicy, sandbox: options.sandboxMode,
121
+ config: { web_search: options.webSearchMode || 'disabled', sandbox_workspace_write: { network_access: !!options.networkAccessEnabled, writable_roots: options.additionalDirectories || [] } },
122
+ });
123
+ const actual = reply?.thread?.id;
124
+ if (!actual || (id && actual !== id)) throw new Error('Codex did not resume the requested thread');
125
+ id = actual;
126
+ });
127
+ ready.catch(() => {});
128
+ return {
129
+ get id() { return id; }, ready: () => ready,
130
+ async runStreamed(prompt, { signal, outputSchema } = {}) {
131
+ await ready;
132
+ const queue = []; const text = new Map(); let wake; let done = false; let failure; let turnId;
133
+ const push = (event) => { queue.push(event); wake?.(); };
134
+ const abort = () => {
135
+ failure = Object.assign(new Error('Codex turn aborted'), { name: 'AbortError' }); done = true; wake?.();
136
+ if (turnId) owner.rpc('turn/interrupt', { threadId: id, turnId }).catch(() => {});
137
+ };
138
+ owner.listener = (msg) => {
139
+ const p = msg.params || {};
140
+ if (p.threadId && p.threadId !== id) return;
141
+ if (msg.method === 'synabun/exit') { failure = msg.error; done = true; wake?.(); }
142
+ if (msg.method === 'item/agentMessage/delta') {
143
+ const value = (text.get(p.itemId) || '') + (p.delta || '');
144
+ text.set(p.itemId, value);
145
+ push({ type: 'item.updated', item: { id: p.itemId, type: 'agent_message', text: value } });
146
+ }
147
+ if (msg.method === 'item/started' || msg.method === 'item/completed') {
148
+ const item = p.item || {};
149
+ const types = { agentMessage: 'agent_message', commandExecution: 'command_execution', fileChange: 'file_change', mcpToolCall: 'mcp_tool_call', webSearch: 'web_search', reasoning: 'reasoning' };
150
+ push({ type: msg.method === 'item/started' ? 'item.started' : 'item.completed', item: { ...item, type: types[item.type] || item.type, aggregated_output: item.aggregatedOutput, exit_code: item.exitCode } });
151
+ }
152
+ if (msg.method === 'turn/completed') {
153
+ if (p.turn?.status === 'failed') push({ type: 'turn.failed', error: p.turn.error || { message: 'Codex turn failed' } });
154
+ else if (p.turn?.status === 'interrupted') failure = Object.assign(new Error('Codex turn interrupted'), { name: 'AbortError' });
155
+ else push({ type: 'turn.completed' }); // rollout meter is authoritative across resumes
156
+ done = true; wake?.();
157
+ }
158
+ };
159
+ signal?.addEventListener('abort', abort, { once: true });
160
+ try {
161
+ if (signal?.aborted) throw Object.assign(new Error('Codex turn aborted'), { name: 'AbortError' });
162
+ const reply = await owner.rpc('turn/start', { threadId: id, input: [{ type: 'text', text: String(prompt), text_elements: [] }], approvalPolicy: owner.approvalPolicy, sandboxPolicy, effort: options.modelReasoningEffort || null, ...(outputSchema ? { outputSchema } : {}) });
163
+ turnId = reply?.turn?.id;
164
+ if (signal?.aborted) abort();
165
+ } catch (error) { owner.listener = null; signal?.removeEventListener('abort', abort); throw error; }
166
+ return { events: (async function* () {
167
+ try {
168
+ yield { type: 'thread.started', thread_id: id };
169
+ while (!done || queue.length) {
170
+ if (queue.length) yield queue.shift();
171
+ else await new Promise((r) => { wake = r; });
172
+ }
173
+ if (failure) throw failure;
174
+ } finally { owner.listener = null; signal?.removeEventListener('abort', abort); }
175
+ })() };
176
+ },
177
+ };
178
+ }
179
+ async dispose() {
180
+ this.requestAbort.abort();
181
+ this.startupSignal?.removeEventListener('abort', this.cancelStartup);
182
+ if (this.proc.exitCode !== null || this.proc.signalCode) return;
183
+ if (process.platform === 'win32') {
184
+ try { execFileSync('taskkill', ['/pid', String(this.proc.pid), '/T', '/F'], { timeout: 5000, stdio: 'ignore', windowsHide: true }); } catch {}
185
+ } else this.proc.kill('SIGTERM');
186
+ let timer;
187
+ await Promise.race([this.exited, new Promise((r) => { timer = setTimeout(r, 1500); })]);
188
+ clearTimeout(timer);
189
+ if (this.proc.exitCode === null && !this.proc.signalCode) this.proc.kill('SIGKILL');
190
+ }
191
+ }
@@ -19,7 +19,7 @@
19
19
  // sequence; it does not remove it.
20
20
 
21
21
  import {
22
- openSync, closeSync, fstatSync, lstatSync, readSync, writeSync, ftruncateSync, fsyncSync,
22
+ openSync, closeSync, fstatSync, fchmodSync, lstatSync, readSync, writeSync, ftruncateSync, fsyncSync,
23
23
  mkdirSync, readdirSync, rmSync, unlinkSync, renameSync, realpathSync, createReadStream, constants,
24
24
  } from 'node:fs';
25
25
  import { randomBytes } from 'node:crypto';
@@ -142,6 +142,17 @@ export function writeConfinedFile(base, path, data, { exclusive = false, mode =
142
142
  if (!st.isFile()) throw new PathConfineError(400, 'Not a regular file.');
143
143
  if (!created) ftruncateSync(fd, 0);
144
144
  writeAll(fd, data);
145
+ } catch (err) {
146
+ // A file this call created and could not fill (the disk filled, the data could not be had) is not left
147
+ // half written: it is removed while it is still the file that was opened.
148
+ if (created) {
149
+ try {
150
+ const mine = fstatSync(fd);
151
+ const now = lstatSync(real);
152
+ if (now.dev === mine.dev && now.ino === mine.ino) unlinkSync(real);
153
+ } catch { /* gone already, or no longer ours */ }
154
+ }
155
+ throw err;
145
156
  } finally { try { closeSync(fd); } catch {} }
146
157
  return real;
147
158
  }
@@ -173,14 +184,29 @@ export function removeConfinedEntry(base, path) {
173
184
  return true;
174
185
  }
175
186
 
187
+ /**
188
+ * What is at `path` itself, a link not followed: 'absent', 'file', 'dir', 'link' or 'other' (a FIFO, a
189
+ * socket, a device). Nothing is opened.
190
+ */
191
+ export function entryKind(path) {
192
+ let st;
193
+ try { st = lstatSync(String(path)); } catch { return 'absent'; }
194
+ if (st.isSymbolicLink()) return 'link';
195
+ if (st.isFile()) return 'file';
196
+ if (st.isDirectory()) return 'dir';
197
+ return 'other';
198
+ }
199
+
176
200
  /**
177
201
  * Replace `path` with `data` through a temporary file in the same folder:
178
202
  * created exclusively under an unpredictable name, never through a link, then
179
203
  * renamed over `path` (a rename replaces a link, it does not follow it).
180
204
  * `expect` is the file's state when it was read ({ dev, ino, mtimeMs, size }):
181
- * a file that changed since is not overwritten (409).
205
+ * a file that changed since is not overwritten (409). `exactMode`: the new
206
+ * file gets `mode` as it is, not narrowed by the process umask (a file that
207
+ * replaces another keeps the permissions that one had).
182
208
  */
183
- export function replaceFileAtomic(path, data, { mode = 0o600, expect = null } = {}) {
209
+ export function replaceFileAtomic(path, data, { mode = 0o600, expect = null, exactMode = false } = {}) {
184
210
  const dir = realPathOf(dirname(String(path)));
185
211
  const target = join(dir, basename(String(path)));
186
212
  const tmp = join(dir, `.${basename(target)}.${randomBytes(12).toString('hex')}.tmp`);
@@ -190,6 +216,7 @@ export function replaceFileAtomic(path, data, { mode = 0o600, expect = null } =
190
216
  try {
191
217
  const st = verifyOpened(fd, tmp);
192
218
  if (!st.isFile()) throw moved();
219
+ if (exactMode) fchmodSync(fd, mode & 0o7777);
193
220
  writeAll(fd, data);
194
221
  try { fsyncSync(fd); } catch {}
195
222
  } finally { try { closeSync(fd); } catch {} }