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,9 @@
1
+ import { retainExternalRefs } from './mcp-external-servers.js';
2
+ import { storedToolList, toolListRecord, readStoredToolListRecord } from './tool-lists.js';
1
3
  import { existsSync, mkdirSync, readFileSync, renameSync, unlinkSync, writeFileSync } from 'node:fs';
2
4
  import { dirname, resolve } from 'node:path';
3
5
 
4
- export const NATIVE_LOOP_PROFILES = new Set(['claude-code', 'codex', 'opencode']);
6
+ export const NATIVE_LOOP_PROFILES = new Set(['claude-code', 'codex', 'opencode', 'antigravity']);
5
7
 
6
8
  export function isNativeLoopProfile(profile) {
7
9
  return NATIVE_LOOP_PROFILES.has(String(profile || ''));
@@ -20,6 +22,7 @@ function cleanDescriptor(record) {
20
22
  provider: record.provider,
21
23
  providerSessionId: record.providerSessionId || null,
22
24
  providerThreadId: record.providerThreadId || null,
25
+ ...(record.antigravityHome ? { antigravityHome: record.antigravityHome } : {}),
23
26
  source: record.source,
24
27
  focus: !!record.focus,
25
28
  status: record.status,
@@ -30,7 +33,9 @@ function cleanDescriptor(record) {
30
33
  contextMode: record.contextMode || null,
31
34
  modelContextWindow: record.modelContextWindow || null,
32
35
  effort: record.effort || null,
33
- mcpProfile: record.mcpProfile || null,
36
+ tools: storedToolList(record),
37
+ externalMcpVersion: 2,
38
+ ...(record.toolListError ? { toolListError: record.toolListError } : {}),
34
39
  accountId: record.accountId || null,
35
40
  currentIteration: record.currentIteration || 0,
36
41
  totalIterations: record.totalIterations || 0,
@@ -49,13 +54,23 @@ function cleanDescriptor(record) {
49
54
  // existing consumers (router, sidepanels, schedules) are unaffected.
50
55
  runMode: record.runMode || 'loop',
51
56
  turnState: record.turnState || null,
57
+ pending: record.status === 'running' ? (record.pendingRequests || []) : [],
52
58
  // What the last turn's result said (task mode: done, blocked or needs_input; the dispatcher's
53
59
  // lastResult.status): an idle warm worker whose turn ended asking waits on the user.
54
60
  outcome: record.outcome || null,
55
61
  assistantSessionId: record.assistantSessionId || null,
62
+ // A dispatched worker a server restart cut off (status 'suspended') waits for its resume on the next start;
63
+ // `resumes` counts how often it was resumed (assistant-dispatch.js resumeRun).
64
+ suspendedAt: record.suspendedAt || null,
65
+ suspendReason: record.suspendReason || null,
66
+ resumes: Number(record.resumes) || 0,
67
+ resumedAt: record.resumedAt || null,
56
68
  };
57
69
  }
58
70
 
71
+ /** Run statuses that hold a run in the ledger as live: it runs, or waits for its resume after a restart. */
72
+ const LIVE_STATUSES = new Set(['starting', 'running', 'suspended']);
73
+
59
74
  function readJson(path, fallback = null) {
60
75
  try { return JSON.parse(readFileSync(path, 'utf8')); }
61
76
  catch { return fallback; }
@@ -76,6 +91,7 @@ export class NativeLoopRuntime {
76
91
  constructor({
77
92
  stateDir,
78
93
  ledgerPath,
94
+ toolListOptions = () => ({}),
79
95
  providerFactories = {},
80
96
  buildPrompt,
81
97
  onEvent = () => {},
@@ -95,10 +111,14 @@ export class NativeLoopRuntime {
95
111
  // A truthy `met` ends the run early with stoppedReason 'goal_met'; the
96
112
  // iteration and time caps stay the fallback.
97
113
  judgeGoal = null,
114
+ // How long a dispatched worker the restart cut off waits, from this start, for its dispatcher to resume it
115
+ // (or end it) before it ends as interrupted by itself.
116
+ resumeHoldMs = 60_000,
98
117
  } = {}) {
99
118
  if (!stateDir) throw new Error('NativeLoopRuntime requires stateDir');
100
119
  if (typeof buildPrompt !== 'function') throw new Error('NativeLoopRuntime requires buildPrompt');
101
120
  this.stateDir = stateDir;
121
+ this.toolListOptions = toolListOptions;
102
122
  this.judgeGoal = typeof judgeGoal === 'function' ? judgeGoal : null;
103
123
  this.ledgerPath = ledgerPath || resolve(dirname(stateDir), 'native-loop-runs.json');
104
124
  this.providerFactories = { ...providerFactories };
@@ -113,6 +133,8 @@ export class NativeLoopRuntime {
113
133
  this.providerStartupTimeoutMs = providerStartupTimeoutMs;
114
134
  this.claimTtlMs = claimTtlMs;
115
135
  this.ledgerFlushMs = Math.max(50, Number(ledgerFlushMs) || 200);
136
+ this.resumeHoldMs = Math.max(1000, Number(resumeHoldMs) || 60_000);
137
+ this._holdTimers = new Map();
116
138
  this.records = new Map();
117
139
  this._pendingPersist = false;
118
140
  this._persistTimer = null;
@@ -164,6 +186,14 @@ export class NativeLoopRuntime {
164
186
  return this._emit('sidepanel:run-updated', record, { reason: 'turn-state' });
165
187
  }
166
188
 
189
+ /** A live worker's requests, durable for a late attach or page reload. Resolvers stay in the dispatcher. */
190
+ setPendingRequests(runId, requests) {
191
+ const record = this.records.get(runId);
192
+ if (!record) return null;
193
+ record.pendingRequests = structuredClone(requests || []);
194
+ return this._emit('sidepanel:run-updated', record, { reason: 'pending-requests' });
195
+ }
196
+
167
197
  /**
168
198
  * Task-mode helper: records what the wrapper's last turn reported ('done' |
169
199
  * 'blocked' | 'needs_input', the dispatcher's lastResult.status) and
@@ -184,8 +214,33 @@ export class NativeLoopRuntime {
184
214
  if (!Array.isArray(rows)) return;
185
215
  for (const row of rows) {
186
216
  if (!row?.runId) continue;
187
- const record = { ...row, adapter: null, timer: null, execution: null };
188
- if (record.status === 'starting' || record.status === 'running') {
217
+ let stored;
218
+ try { stored = readStoredToolListRecord(row, this.toolListOptions()); }
219
+ catch (error) {
220
+ // A historical run may name a custom preset the owner has since deleted. Refuse that
221
+ // run, preserve the original selection for diagnosis, and keep the rest of the server up.
222
+ stored = { ...row, tools: [], status: 'failed', stoppedReason: 'tools_invalid',
223
+ error: error.message, toolListError: { code: error.code, message: error.message,
224
+ original: row.tools ?? row.mcpProfile ?? null } };
225
+ delete stored.mcpProfile;
226
+ }
227
+ const record = { ...stored, adapter: null, timer: null, execution: null };
228
+ const cutOff = record.status === 'starting' || record.status === 'running' || record.status === 'suspended';
229
+ if (cutOff && record.runMode === 'task' && isNativeLoopProfile(record.provider)) {
230
+ // A dispatched Claude Code worker the restart cut off (suspended by the last shutdown, or left running by a
231
+ // crash): held for its dispatcher, which resumes it (assistant-dispatch.js resumeRun) or ends it. Its state file
232
+ // stays as it is. Nobody takes it within resumeHoldMs: it ends as interrupted, as every cut-off run did before.
233
+ record.status = 'suspended';
234
+ record.suspendedAt = record.suspendedAt || iso(this.now());
235
+ record.suspendReason = record.suspendReason || 'server_restart';
236
+ record.turnState = 'suspended';
237
+ record.pendingRequests = [];
238
+ record.stopping = false;
239
+ this.records.set(record.runId, record);
240
+ this._hold(record);
241
+ continue;
242
+ }
243
+ if (cutOff) {
189
244
  record.status = 'interrupted';
190
245
  record.stoppedReason = 'server_restart';
191
246
  record.completedAt = record.completedAt || iso(this.now());
@@ -208,9 +263,9 @@ export class NativeLoopRuntime {
208
263
 
209
264
  _writeLedgerNow() {
210
265
  const records = [...this.records.values()];
211
- const active = records.filter((record) => ['starting', 'running'].includes(record.status));
266
+ const active = records.filter((record) => LIVE_STATUSES.has(record.status));
212
267
  const terminal = records
213
- .filter((record) => !['starting', 'running'].includes(record.status))
268
+ .filter((record) => !LIVE_STATUSES.has(record.status))
214
269
  .sort((a, b) => String(b.startedAt || '').localeCompare(String(a.startedAt || '')));
215
270
  const retained = [...active, ...terminal.slice(0, Math.max(0, 500 - active.length))];
216
271
  const retainedIds = new Set(retained.map((record) => record.runId));
@@ -221,7 +276,7 @@ export class NativeLoopRuntime {
221
276
  }
222
277
  }
223
278
  const rows = retained
224
- .map(cleanDescriptor)
279
+ .map(record => toolListRecord(cleanDescriptor(record)))
225
280
  .sort((a, b) => String(b.startedAt || '').localeCompare(String(a.startedAt || '')));
226
281
  try { writeJsonAtomic(this.ledgerPath, rows); }
227
282
  catch (error) { this.log(null, 'ledger:error', error.message); }
@@ -265,11 +320,13 @@ export class NativeLoopRuntime {
265
320
 
266
321
  _readState(runId) {
267
322
  const path = this._statePath(runId);
268
- return existsSync(path) ? readJson(path, null) : null;
323
+ const state = existsSync(path) ? readJson(path, null) : null;
324
+ return state ? readStoredToolListRecord(state, this.toolListOptions()) : null;
269
325
  }
270
326
 
271
327
  _writeState(runId, state) {
272
- writeJsonAtomic(this._statePath(runId), state);
328
+ const { permissionBroker: _broker, ...stored } = state;
329
+ writeJsonAtomic(this._statePath(runId), toolListRecord(stored, this.toolListOptions()));
273
330
  }
274
331
 
275
332
  _writeTerminalState(record, patch) {
@@ -285,8 +342,9 @@ export class NativeLoopRuntime {
285
342
  record.version = (Number(record.version) || 0) + 1;
286
343
  record.updatedAt = iso(this.now());
287
344
  // Force-flush on terminal transitions (a crash between throttled flushes
288
- // would otherwise leave the run listed as running after a restart).
289
- const terminal = ['completed', 'failed', 'stopped', 'interrupted'].includes(record.status);
345
+ // would otherwise leave the run listed as running after a restart), and on
346
+ // a suspension (the next start resumes the run from this ledger).
347
+ const terminal = ['completed', 'failed', 'stopped', 'interrupted', 'suspended'].includes(record.status);
290
348
  this._persistLedger({ force: terminal });
291
349
  const descriptor = cleanDescriptor(record);
292
350
  const message = { type, run: descriptor, ...extra };
@@ -298,6 +356,7 @@ export class NativeLoopRuntime {
298
356
  _setIdentity(record, identity = {}) {
299
357
  const providerSessionId = identity.providerSessionId || identity.sessionId || null;
300
358
  const providerThreadId = identity.providerThreadId || identity.threadId || null;
359
+ const antigravityHome = typeof identity.antigravityHome === "string" && identity.antigravityHome ? identity.antigravityHome : null;
301
360
  let changed = false;
302
361
  if (providerSessionId && providerSessionId !== record.providerSessionId) {
303
362
  record.providerSessionId = providerSessionId;
@@ -307,6 +366,10 @@ export class NativeLoopRuntime {
307
366
  record.providerThreadId = providerThreadId;
308
367
  changed = true;
309
368
  }
369
+ if (antigravityHome && antigravityHome !== record.antigravityHome) {
370
+ record.antigravityHome = antigravityHome;
371
+ changed = true;
372
+ }
310
373
  if (changed) this._emit('sidepanel:run-updated', record, { reason: 'identity' });
311
374
  if ((record.providerSessionId || record.providerThreadId) && record._resolveIdentity) {
312
375
  record._resolveIdentity(cleanDescriptor(record));
@@ -333,7 +396,7 @@ export class NativeLoopRuntime {
333
396
  mkdirSync(this.stateDir, { recursive: true });
334
397
  const startedAt = state.startedAt || iso(this.now());
335
398
  const nativeState = {
336
- ...state,
399
+ ...toolListRecord(state, this.toolListOptions()),
337
400
  runId,
338
401
  terminalSessionId: runId,
339
402
  active: true,
@@ -351,6 +414,7 @@ export class NativeLoopRuntime {
351
414
  provider: state.profile,
352
415
  providerSessionId: null,
353
416
  providerThreadId: null,
417
+ antigravityHome: typeof state.antigravityHome === "string" && state.antigravityHome ? state.antigravityHome : null,
354
418
  source,
355
419
  focus,
356
420
  status: 'starting',
@@ -361,7 +425,7 @@ export class NativeLoopRuntime {
361
425
  contextMode: state.contextMode || null,
362
426
  modelContextWindow: state.modelContextWindow || null,
363
427
  effort: state.effort || null,
364
- mcpProfile: state.mcpProfile || null,
428
+ tools: storedToolList(state, this.toolListOptions()),
365
429
  accountId: state.codexAccountId || null,
366
430
  currentIteration: Number(state.currentIteration) || 0,
367
431
  totalIterations: Number(state.totalIterations) || 1,
@@ -400,6 +464,24 @@ export class NativeLoopRuntime {
400
464
  record.timer.unref?.();
401
465
  }
402
466
 
467
+ this._bootstrap(record, factory, nativeState, { source, profile: state.profile });
468
+
469
+ // For back-compat: callers that awaited launch() to know whether the run was
470
+ // accepted can observe the descriptor. The failure (if any) is delivered via
471
+ // sidepanel:run-failed and via record.bootstrap rejecting with the original
472
+ // startup error. The descriptor itself resolves immediately with the
473
+ // 'starting' state so the HTTP caller is never gated on provider boot.
474
+ return cleanDescriptor(record);
475
+ }
476
+
477
+ /**
478
+ * Start the provider of a run whose record is in place (launch, resume) and drive it. Sets record.bootstrap: it
479
+ * resolves once the provider started and rejects with the startup error. A provider that cannot start ends the
480
+ * run as failed, or (`failAs: 'interrupted'`, a resume) as interrupted with the reason resume_failed.
481
+ */
482
+ _bootstrap(record, factory, nativeState, { source = record.source, profile = record.provider, failAs = 'failed' } = {}) {
483
+ const runId = record.runId;
484
+ const state = { profile };
403
485
  const startupSignal = record.startupAbortController.signal;
404
486
  const factoryPromise = Promise.resolve().then(() => factory({
405
487
  ...nativeState,
@@ -418,7 +500,8 @@ export class NativeLoopRuntime {
418
500
  if (!adapter || candidateCleaned) return;
419
501
  candidateCleaned = true;
420
502
  try { await adapter.abort?.(reason); } catch {}
421
- try { await adapter.dispose?.({ preserveSession: true }); } catch {}
503
+ // Suspended for a server shutdown while it started (suspend): its process is ended now, as a started one's is.
504
+ try { await adapter.dispose?.({ preserveSession: true, ...(record.status === 'suspended' ? { terminate: true } : {}) }); } catch {}
422
505
  };
423
506
  const finishBootstrap = async () => {
424
507
  clearTimeout(startupTimer);
@@ -479,6 +562,7 @@ export class NativeLoopRuntime {
479
562
  runId,
480
563
  emit: (event) => this._emitProviderEvent(record, event),
481
564
  setTurnState: (turnState) => this.setTurnState(runId, turnState),
565
+ setPendingRequests: (requests) => this.setPendingRequests(runId, requests),
482
566
  setOutcome: (outcome) => this.setOutcome(runId, outcome),
483
567
  readState: () => this._readState(runId),
484
568
  })
@@ -497,11 +581,15 @@ export class NativeLoopRuntime {
497
581
  if (candidate) await cleanupCandidate(candidate, error?.code || 'startup_failed');
498
582
  else factoryPromise.then((adapter) => cleanupCandidate(adapter, error?.code || 'startup_failed')).catch(() => {});
499
583
  }
500
- await this._fail(
501
- record,
502
- error,
503
- error?.code === 'NATIVE_LOOP_PROVIDER_START_TIMEOUT' ? 'provider_startup_timeout' : 'provider_error',
504
- );
584
+ if (failAs === 'interrupted') {
585
+ await this._fail(record, error, 'resume_failed', { status: 'interrupted' });
586
+ } else {
587
+ await this._fail(
588
+ record,
589
+ error,
590
+ error?.code === 'NATIVE_LOOP_PROVIDER_START_TIMEOUT' ? 'provider_startup_timeout' : 'provider_error',
591
+ );
592
+ }
505
593
  } finally {
506
594
  await finishBootstrap();
507
595
  // Re-throw so record.bootstrap rejects with the original startup error.
@@ -516,15 +604,147 @@ export class NativeLoopRuntime {
516
604
  // timer holds the process until cleanup. Swallow the unhandled rejection
517
605
  // here because callers that care must await record.bootstrap explicitly.
518
606
  bootstrap.catch(() => {});
607
+ return bootstrap;
608
+ }
519
609
 
520
- // For back-compat: callers that awaited launch() to know whether the run was
521
- // accepted can observe the descriptor. The failure (if any) is delivered via
522
- // sidepanel:run-failed and via record.bootstrap rejecting with the original
523
- // startup error. The descriptor itself resolves immediately with the
524
- // 'starting' state so the HTTP caller is never gated on provider boot.
610
+ /**
611
+ * Continue a suspended run (a dispatched worker a server restart cut off; assistant-dispatch.js resumeRun) as the
612
+ * same record: its runId, tab, claim, title and startedAt stay, its version keeps growing. The state file is written
613
+ * again at iteration 0 of 1, so the drive runs the run's one task iteration again (the dispatcher's wrapper decides
614
+ * what that turn sends), and the provider factory gets what `state` carries to continue the provider session
615
+ * (resumeSessionId, costBaseUsd). Resolves with the descriptor once the provider started; a provider that cannot
616
+ * start ends the run as interrupted (resume_failed) and the promise rejects with why.
617
+ */
618
+ async resume({ runId, state, buildPrompt = null, wrapAdapter = null } = {}) {
619
+ const record = this.records.get(runId);
620
+ if (!record) throw new Error(`Native loop ${runId} is not known`);
621
+ if (record.status !== 'suspended') throw new Error(`Native loop ${runId} is ${record.status}, not suspended`);
622
+ if (buildPrompt !== null && typeof buildPrompt !== 'function') throw new Error('Native loop buildPrompt override must be a function');
623
+ if (wrapAdapter !== null && typeof wrapAdapter !== 'function') throw new Error('Native loop wrapAdapter override must be a function');
624
+ if (!state?.profile || !isNativeLoopProfile(state.profile)) throw new Error(`Unsupported native loop profile: ${state?.profile || 'unknown'}`);
625
+ const factory = this.providerFactories[state.profile];
626
+ if (!factory) throw new Error(`Native provider unavailable: ${state.profile}`);
627
+ this._clearHold(record);
628
+ mkdirSync(this.stateDir, { recursive: true });
629
+ const totalIterations = Number(state.totalIterations) || 1;
630
+ const nativeState = {
631
+ ...toolListRecord(state, this.toolListOptions()),
632
+ runId,
633
+ terminalSessionId: runId,
634
+ active: true,
635
+ pending: false,
636
+ driverType: 'native',
637
+ runtimeType: 'native',
638
+ surface: 'sidepanel',
639
+ startedAt: record.startedAt || state.startedAt || iso(this.now()),
640
+ currentIteration: 0,
641
+ totalIterations,
642
+ };
643
+ this._writeState(runId, nativeState);
644
+ Object.assign(record, {
645
+ status: 'starting',
646
+ stoppedReason: null,
647
+ completedAt: null,
648
+ error: null,
649
+ adapter: null,
650
+ timer: null,
651
+ execution: null,
652
+ stopping: false,
653
+ startupAbortController: new AbortController(),
654
+ turnState: 'starting',
655
+ currentIteration: 0,
656
+ totalIterations,
657
+ browserSessionId: state.browserSessionId || null,
658
+ browserTabId: state.browserTabId || null,
659
+ suspendedAt: null,
660
+ suspendReason: null,
661
+ ...(typeof state.antigravityHome === "string" && state.antigravityHome ? { antigravityHome: state.antigravityHome } : {}),
662
+ resumes: (Number(record.resumes) || 0) + 1,
663
+ resumedAt: iso(this.now()),
664
+ buildPrompt,
665
+ wrapAdapter,
666
+ });
667
+ record.identityPromise = new Promise((resolveIdentity) => { record._resolveIdentity = resolveIdentity; });
668
+ record.startupCancelPromise = new Promise((resolveCancel) => { record._cancelStartup = resolveCancel; });
669
+ this._emit('sidepanel:run-updated', record, { reason: 'resuming' });
670
+ await this._bootstrap(record, factory, nativeState, { profile: state.profile, failAs: 'interrupted' });
525
671
  return cleanDescriptor(record);
526
672
  }
527
673
 
674
+ /** The hold of a run the restart cut off: it ends as interrupted when nobody resumes it in time. */
675
+ _hold(record) {
676
+ this._clearHold(record);
677
+ const timer = setTimeout(() => {
678
+ this._holdTimers.delete(record.runId);
679
+ this.endSuspended(record.runId, record.suspendReason || 'server_restart').catch(() => {});
680
+ }, this.resumeHoldMs);
681
+ timer.unref?.();
682
+ this._holdTimers.set(record.runId, timer);
683
+ }
684
+
685
+ _clearHold(record) {
686
+ const timer = this._holdTimers.get(record?.runId);
687
+ if (timer) { clearTimeout(timer); this._holdTimers.delete(record.runId); }
688
+ }
689
+
690
+ /** Whether a run waits for its resume after a restart (suspended). */
691
+ isSuspended(runId) {
692
+ return this.records.get(runId)?.status === 'suspended';
693
+ }
694
+
695
+ /**
696
+ * The dispatcher takes a suspended run over (it resumes it or ends it itself): its hold no longer ends it.
697
+ * Returns whether the run is suspended.
698
+ */
699
+ keepSuspended(runId) {
700
+ const record = this.records.get(runId);
701
+ if (!record || record.status !== 'suspended') return false;
702
+ this._clearHold(record);
703
+ return true;
704
+ }
705
+
706
+ /**
707
+ * A suspended run that will not be resumed ends as interrupted (`reason`, by default why it was suspended), with an
708
+ * event, so a tab that waited for its resume shows how it ended. `error`: why it was not resumed.
709
+ */
710
+ async endSuspended(runId, reason = null, { error = null } = {}) {
711
+ const record = this.records.get(runId);
712
+ if (!record || record.status !== 'suspended') return false;
713
+ this._clearHold(record);
714
+ record.status = 'interrupted';
715
+ record.stoppedReason = reason || record.suspendReason || 'server_restart';
716
+ record.completedAt = iso(this.now());
717
+ if (error) record.error = String(error);
718
+ this._writeTerminalState(record, { active: false, pending: false, completedAt: record.completedAt, stoppedReason: record.stoppedReason, ...(error ? { error: record.error } : {}) });
719
+ this._releaseRuntimeRefs(record);
720
+ this._emit('sidepanel:run-stopped', record);
721
+ try { await this.onFinish(cleanDescriptor(record)); } catch {}
722
+ return true;
723
+ }
724
+
725
+ /**
726
+ * Suspend a running dispatched worker for a server shutdown (shutdown's `keep`): its CLI is ended (the adapter's
727
+ * dispose with terminate), its state file stays active, and the record waits as suspended for the next start to
728
+ * resume it. No run-stopped event and no end: a run-updated with the reason 'suspended'.
729
+ */
730
+ async suspend(runId, reason = 'server_shutdown') {
731
+ const record = this.records.get(runId);
732
+ if (!record || !['starting', 'running'].includes(record.status) || record.stopping) return false;
733
+ record.stopping = true;
734
+ clearTimeout(record.timer);
735
+ record.status = 'suspended';
736
+ record.suspendedAt = iso(this.now());
737
+ record.suspendReason = reason;
738
+ if (record._resolveIdentity) { record._resolveIdentity(null); record._resolveIdentity = null; }
739
+ try { record.startupAbortController?.abort(reason); } catch {}
740
+ if (record._cancelStartup) { record._cancelStartup(reason); record._cancelStartup = null; }
741
+ try { await record.adapter?.dispose?.({ preserveSession: true, terminate: true }); } catch {}
742
+ this._releaseRuntimeRefs(record, { turnState: 'suspended' });
743
+ record.stopping = false;
744
+ this._emit('sidepanel:run-updated', record, { reason: 'suspended' });
745
+ return true;
746
+ }
747
+
528
748
  async _drive(record) {
529
749
  let failures = 0;
530
750
  while (this.isAlive(record.runId)) {
@@ -618,7 +838,7 @@ export class NativeLoopRuntime {
618
838
  }
619
839
  }
620
840
 
621
- _releaseRuntimeRefs(record) {
841
+ _releaseRuntimeRefs(record, { turnState = 'terminal' } = {}) {
622
842
  if (!record) return;
623
843
  record.adapter = null;
624
844
  record.timer = null;
@@ -630,7 +850,9 @@ export class NativeLoopRuntime {
630
850
  record.startupAbortController = null;
631
851
  record.buildPrompt = null;
632
852
  record.wrapAdapter = null;
633
- if (record.turnState && record.turnState !== 'terminal') record.turnState = 'terminal';
853
+ record.pendingRequests = [];
854
+ if (turnState === 'suspended') record.turnState = 'suspended';
855
+ else if (record.turnState && record.turnState !== 'terminal') record.turnState = 'terminal';
634
856
  }
635
857
 
636
858
  async _complete(record, reason = 'completed') {
@@ -646,10 +868,11 @@ export class NativeLoopRuntime {
646
868
  try { await this.onFinish(cleanDescriptor(record)); } catch {}
647
869
  }
648
870
 
649
- async _fail(record, error, reason = 'provider_error') {
650
- if (!record || ['completed', 'failed', 'stopped', 'interrupted'].includes(record.status)) return;
871
+ /** `status`: 'failed', or 'interrupted' for a resume that could not start (reason resume_failed). */
872
+ async _fail(record, error, reason = 'provider_error', { status = 'failed' } = {}) {
873
+ if (!record || ['completed', 'failed', 'stopped', 'interrupted', 'suspended'].includes(record.status)) return;
651
874
  clearTimeout(record.timer);
652
- record.status = 'failed';
875
+ record.status = status === 'interrupted' ? 'interrupted' : 'failed';
653
876
  record.error = error?.message || String(error);
654
877
  record.stoppedReason = reason;
655
878
  record.completedAt = iso(this.now());
@@ -660,12 +883,27 @@ export class NativeLoopRuntime {
660
883
  try { await record.adapter?.abort?.(reason); } catch {}
661
884
  try { await record.adapter?.dispose?.({ preserveSession: true }); } catch {}
662
885
  this._releaseRuntimeRefs(record);
663
- this._emit('sidepanel:run-failed', record);
886
+ this._emit(record.status === 'interrupted' ? 'sidepanel:run-stopped' : 'sidepanel:run-failed', record);
664
887
  try { await this.onFinish(cleanDescriptor(record)); } catch {}
665
888
  }
666
889
 
667
- async stop(runId, reason = 'user') {
890
+ /**
891
+ * `terminate` (a server shutdown): the provider's process is ended at once (the Claude adapter's dispose), never
892
+ * left to finish its tool call after the server is gone. A suspended run (waiting for its resume) ends as stopped.
893
+ */
894
+ async stop(runId, reason = 'user', { terminate = false } = {}) {
668
895
  const record = this.records.get(runId);
896
+ if (record?.status === 'suspended' && !record.stopping) {
897
+ this._clearHold(record);
898
+ record.status = 'stopped';
899
+ record.stoppedReason = reason;
900
+ record.completedAt = iso(this.now());
901
+ this._writeTerminalState(record, { active: false, pending: false, completedAt: record.completedAt, stoppedReason: reason });
902
+ this._releaseRuntimeRefs(record);
903
+ this._emit('sidepanel:run-stopped', record);
904
+ try { await this.onFinish(cleanDescriptor(record)); } catch {}
905
+ return true;
906
+ }
669
907
  if (!record || !['starting', 'running'].includes(record.status) || record.stopping) return false;
670
908
  record.stopping = true;
671
909
  clearTimeout(record.timer);
@@ -677,7 +915,7 @@ export class NativeLoopRuntime {
677
915
  if (record._cancelStartup) { record._cancelStartup(reason); record._cancelStartup = null; }
678
916
  this._writeTerminalState(record, { active: false, pending: false, completedAt: record.completedAt, stoppedReason: reason });
679
917
  try { await record.adapter?.abort?.(reason); } catch {}
680
- try { await record.adapter?.dispose?.({ preserveSession: true }); } catch {}
918
+ try { await record.adapter?.dispose?.({ preserveSession: true, ...(terminate ? { terminate: true } : {}) }); } catch {}
681
919
  this._releaseRuntimeRefs(record);
682
920
  this._emit('sidepanel:run-stopped', record);
683
921
  try { await this.onFinish(cleanDescriptor(record)); } catch {}
@@ -735,19 +973,21 @@ export class NativeLoopRuntime {
735
973
  return released;
736
974
  }
737
975
 
738
- setMcpProfile(runId, profile) {
976
+ setTools(runId, tools) {
739
977
  const record = this.records.get(runId);
740
- const normalized = String(profile || '').toLowerCase().trim();
741
- if (!record || !normalized) return null;
742
- if (record.mcpProfile === normalized) return cleanDescriptor(record);
743
- record.mcpProfile = normalized;
978
+ if (!record) return null;
979
+ if (!Array.isArray(tools)) throw Object.assign(new Error('tools must be an array'), { code: 'TOOLS_INVALID', status: 400 });
980
+ const normalized = storedToolList({ tools: retainExternalRefs(tools, record.tools) });
981
+ if (JSON.stringify(record.tools) === JSON.stringify(normalized)) return cleanDescriptor(record);
982
+ record.tools = normalized;
983
+ delete record.mcpProfile;
744
984
  try {
745
985
  const state = this._readState(record.runId);
746
- if (state) this._writeState(record.runId, { ...state, mcpProfile: normalized });
986
+ if (state) this._writeState(record.runId, { ...state, tools: normalized });
747
987
  } catch (error) {
748
988
  this.log(record.runId, 'native:state-write-error', error?.message || String(error));
749
989
  }
750
- return this._emit('sidepanel:run-updated', record, { reason: 'mcp-profile' });
990
+ return this._emit('sidepanel:run-updated', record, { reason: 'mcp-tools' });
751
991
  }
752
992
 
753
993
  get(runId) {
@@ -757,15 +997,23 @@ export class NativeLoopRuntime {
757
997
 
758
998
  list({ activeOnly = false } = {}) {
759
999
  return [...this.records.values()]
760
- .filter((record) => !activeOnly || ['starting', 'running'].includes(record.status))
1000
+ .filter((record) => !activeOnly || LIVE_STATUSES.has(record.status))
761
1001
  .map(cleanDescriptor)
762
1002
  .sort((a, b) => String(b.startedAt || '').localeCompare(String(a.startedAt || '')));
763
1003
  }
764
1004
 
765
- async shutdown(reason = 'server_shutdown') {
1005
+ /**
1006
+ * The server is going down. `keep`: the runs its dispatcher suspends to resume on the next start
1007
+ * (assistant-dispatch.js suspendForShutdown); every other running run is stopped. Either way each provider process
1008
+ * is ended now (terminate), so nothing outlives the server. A run still waiting for its resume stays suspended.
1009
+ */
1010
+ async shutdown(reason = 'server_shutdown', { keep = [] } = {}) {
1011
+ const kept = new Set((Array.isArray(keep) ? keep : []).map(String));
766
1012
  await Promise.allSettled([...this.records.values()]
767
1013
  .filter((record) => ['starting', 'running'].includes(record.status))
768
- .map((record) => this.stop(record.runId, reason)));
1014
+ .map((record) => (kept.has(record.runId) ? this.suspend(record.runId, reason) : this.stop(record.runId, reason, { terminate: true }))));
1015
+ for (const timer of this._holdTimers.values()) clearTimeout(timer);
1016
+ this._holdTimers.clear();
769
1017
  this._persistLedger({ force: true });
770
1018
  }
771
1019
  }