@vellumai/assistant 0.5.6 → 0.5.8

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 (442) hide show
  1. package/.env.example +16 -2
  2. package/ARCHITECTURE.md +6 -75
  3. package/Dockerfile +3 -2
  4. package/README.md +0 -2
  5. package/bun.lock +0 -414
  6. package/docker-entrypoint.sh +9 -0
  7. package/docs/architecture/keychain-broker.md +45 -240
  8. package/docs/architecture/memory.md +13 -11
  9. package/docs/architecture/security.md +0 -17
  10. package/docs/credential-execution-service.md +2 -2
  11. package/node_modules/@vellumai/ces-contracts/package.json +1 -0
  12. package/node_modules/@vellumai/ces-contracts/src/error.ts +1 -1
  13. package/node_modules/@vellumai/ces-contracts/src/grants.ts +1 -1
  14. package/node_modules/@vellumai/ces-contracts/src/handles.ts +1 -1
  15. package/node_modules/@vellumai/ces-contracts/src/index.ts +1 -1
  16. package/node_modules/@vellumai/ces-contracts/src/rpc.ts +120 -1
  17. package/node_modules/@vellumai/credential-storage/package.json +1 -0
  18. package/node_modules/@vellumai/egress-proxy/package.json +1 -0
  19. package/package.json +2 -3
  20. package/src/__tests__/actor-token-service.test.ts +0 -114
  21. package/src/__tests__/approval-cascade.test.ts +0 -1
  22. package/src/__tests__/assistant-feature-flags-integration.test.ts +30 -29
  23. package/src/__tests__/browser-fill-credential.test.ts +1 -1
  24. package/src/__tests__/browser-skill-endstate.test.ts +6 -5
  25. package/src/__tests__/btw-routes.test.ts +0 -39
  26. package/src/__tests__/call-controller.test.ts +0 -1
  27. package/src/__tests__/call-domain.test.ts +0 -128
  28. package/src/__tests__/ces-rpc-credential-backend.test.ts +199 -0
  29. package/src/__tests__/ces-startup-timeout.test.ts +40 -0
  30. package/src/__tests__/channel-approval-routes.test.ts +0 -5
  31. package/src/__tests__/channel-readiness-service.test.ts +1 -60
  32. package/src/__tests__/checker.test.ts +4 -2
  33. package/src/__tests__/cli-command-risk-guard.test.ts +112 -0
  34. package/src/__tests__/config-schema-cmd.test.ts +0 -2
  35. package/src/__tests__/config-schema.test.ts +3 -1
  36. package/src/__tests__/conversation-abort-tool-results.test.ts +0 -1
  37. package/src/__tests__/conversation-agent-loop-overflow.test.ts +0 -2
  38. package/src/__tests__/conversation-agent-loop.test.ts +2 -4
  39. package/src/__tests__/conversation-attention-telegram.test.ts +0 -5
  40. package/src/__tests__/conversation-confirmation-signals.test.ts +0 -1
  41. package/src/__tests__/conversation-error.test.ts +15 -1
  42. package/src/__tests__/conversation-init.benchmark.test.ts +0 -2
  43. package/src/__tests__/conversation-messaging-secret-redirect.test.ts +1 -1
  44. package/src/__tests__/conversation-pre-run-repair.test.ts +0 -1
  45. package/src/__tests__/conversation-provider-retry-repair.test.ts +0 -1
  46. package/src/__tests__/conversation-queue.test.ts +0 -1
  47. package/src/__tests__/conversation-skill-tools.test.ts +0 -54
  48. package/src/__tests__/conversation-slash-queue.test.ts +0 -1
  49. package/src/__tests__/conversation-slash-unknown.test.ts +0 -1
  50. package/src/__tests__/conversation-title-service.test.ts +87 -0
  51. package/src/__tests__/conversation-workspace-injection.test.ts +0 -1
  52. package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -1
  53. package/src/__tests__/credential-execution-client.test.ts +5 -2
  54. package/src/__tests__/credential-execution-feature-gates.test.ts +59 -30
  55. package/src/__tests__/credential-execution-managed-contract.test.ts +35 -20
  56. package/src/__tests__/credential-security-e2e.test.ts +1 -67
  57. package/src/__tests__/credential-security-invariants.test.ts +6 -50
  58. package/src/__tests__/credentials-cli.test.ts +82 -3
  59. package/src/__tests__/daemon-credential-client.test.ts +123 -0
  60. package/src/__tests__/db-migration-rollback.test.ts +2015 -1
  61. package/src/__tests__/deterministic-verification-control-plane.test.ts +1 -0
  62. package/src/__tests__/docker-signing-key-bootstrap.test.ts +34 -143
  63. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +6 -4
  64. package/src/__tests__/gateway-client-managed-outbound.test.ts +79 -1
  65. package/src/__tests__/guardian-routing-state.test.ts +0 -5
  66. package/src/__tests__/host-shell-tool.test.ts +6 -7
  67. package/src/__tests__/http-user-message-parity.test.ts +3 -103
  68. package/src/__tests__/inbound-invite-redemption.test.ts +0 -4
  69. package/src/__tests__/inline-skill-load-permissions.test.ts +6 -8
  70. package/src/__tests__/intent-routing.test.ts +0 -13
  71. package/src/__tests__/jobs-store-qdrant-breaker.test.ts +178 -0
  72. package/src/__tests__/journal-context.test.ts +335 -0
  73. package/src/__tests__/keychain-broker-client.test.ts +161 -22
  74. package/src/__tests__/memory-context-benchmark.benchmark.test.ts +0 -3
  75. package/src/__tests__/memory-jobs-worker-backoff.test.ts +150 -0
  76. package/src/__tests__/memory-lifecycle-e2e.test.ts +70 -25
  77. package/src/__tests__/memory-recall-quality.test.ts +48 -17
  78. package/src/__tests__/memory-regressions.test.ts +408 -363
  79. package/src/__tests__/memory-retrieval.benchmark.test.ts +0 -3
  80. package/src/__tests__/migration-export-http.test.ts +2 -2
  81. package/src/__tests__/migration-import-commit-http.test.ts +2 -2
  82. package/src/__tests__/migration-import-preflight-http.test.ts +2 -2
  83. package/src/__tests__/migration-validate-http.test.ts +2 -2
  84. package/src/__tests__/non-member-access-request.test.ts +2 -7
  85. package/src/__tests__/notification-decision-fallback.test.ts +4 -0
  86. package/src/__tests__/notification-decision-identity.test.ts +4 -0
  87. package/src/__tests__/notification-decision-strategy.test.ts +71 -0
  88. package/src/__tests__/oauth-cli.test.ts +5 -1
  89. package/src/__tests__/permission-types.test.ts +1 -0
  90. package/src/__tests__/provider-commit-message-generator.test.ts +0 -37
  91. package/src/__tests__/provider-error-scenarios.test.ts +0 -267
  92. package/src/__tests__/provider-managed-proxy-integration.test.ts +5 -6
  93. package/src/__tests__/provider-streaming.benchmark.test.ts +2 -81
  94. package/src/__tests__/qdrant-manager.test.ts +28 -2
  95. package/src/__tests__/registry.test.ts +0 -6
  96. package/src/__tests__/relay-server.test.ts +1 -2
  97. package/src/__tests__/runtime-attachment-metadata.test.ts +0 -4
  98. package/src/__tests__/script-proxy-injection-runtime.test.ts +1 -1
  99. package/src/__tests__/secret-onetime-send.test.ts +1 -1
  100. package/src/__tests__/secret-routes-managed-proxy.test.ts +0 -4
  101. package/src/__tests__/secure-keys.test.ts +95 -272
  102. package/src/__tests__/shell-identity.test.ts +96 -6
  103. package/src/__tests__/skill-feature-flags-integration.test.ts +22 -14
  104. package/src/__tests__/skill-feature-flags.test.ts +46 -45
  105. package/src/__tests__/skill-load-feature-flag.test.ts +7 -10
  106. package/src/__tests__/skill-load-inline-command.test.ts +8 -12
  107. package/src/__tests__/skill-load-inline-includes.test.ts +6 -10
  108. package/src/__tests__/skill-load-tool.test.ts +0 -2
  109. package/src/__tests__/skill-memory.test.ts +17 -3
  110. package/src/__tests__/skill-projection-feature-flag.test.ts +33 -29
  111. package/src/__tests__/skills.test.ts +0 -2
  112. package/src/__tests__/slack-inbound-verification.test.ts +0 -4
  113. package/src/__tests__/stale-approval-dedup.test.ts +171 -0
  114. package/src/__tests__/stt-hints.test.ts +437 -0
  115. package/src/__tests__/suggestion-routes.test.ts +1 -32
  116. package/src/__tests__/system-prompt.test.ts +0 -1
  117. package/src/__tests__/task-memory-cleanup.test.ts +14 -0
  118. package/src/__tests__/tool-executor-shell-integration.test.ts +5 -3
  119. package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +0 -5
  120. package/src/__tests__/trusted-contact-multichannel.test.ts +0 -4
  121. package/src/__tests__/twilio-routes-twiml.test.ts +139 -1
  122. package/src/__tests__/update-bulletin.test.ts +0 -2
  123. package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +6 -9
  124. package/src/__tests__/voice-quality.test.ts +58 -0
  125. package/src/__tests__/voice-scoped-grant-consumer.test.ts +0 -7
  126. package/src/__tests__/workspace-migration-015-migrate-credentials-to-keychain.test.ts +252 -0
  127. package/src/__tests__/workspace-migration-016-migrate-credentials-from-keychain.test.ts +220 -0
  128. package/src/__tests__/workspace-migration-down-functions.test.ts +1009 -0
  129. package/src/__tests__/workspace-migrations-runner.test.ts +114 -0
  130. package/src/acp/agent-process.ts +9 -1
  131. package/src/agent/loop.ts +1 -1
  132. package/src/approvals/guardian-request-resolvers.ts +164 -38
  133. package/src/calls/__tests__/tts-text-sanitizer.test.ts +254 -0
  134. package/src/calls/audio-store.test.ts +97 -0
  135. package/src/calls/audio-store.ts +205 -0
  136. package/src/calls/call-controller.ts +90 -8
  137. package/src/calls/call-domain.ts +3 -0
  138. package/src/calls/call-store.ts +10 -3
  139. package/src/calls/fish-audio-client.ts +129 -0
  140. package/src/calls/relay-server.ts +27 -0
  141. package/src/calls/stt-hints.ts +189 -0
  142. package/src/calls/tts-text-sanitizer.ts +61 -0
  143. package/src/calls/twilio-routes.ts +34 -5
  144. package/src/calls/types.ts +1 -0
  145. package/src/calls/voice-ingress-preflight.ts +0 -42
  146. package/src/calls/voice-quality.ts +38 -5
  147. package/src/calls/voice-session-bridge.ts +7 -12
  148. package/src/cli/commands/avatar.ts +2 -2
  149. package/src/cli/commands/config.ts +1 -4
  150. package/src/cli/commands/credentials.ts +128 -82
  151. package/src/cli/commands/doctor.ts +2 -2
  152. package/src/cli/commands/keys.ts +7 -7
  153. package/src/cli/commands/memory.ts +1 -1
  154. package/src/cli/commands/oauth/connections.ts +11 -29
  155. package/src/cli/commands/oauth/index.ts +7 -0
  156. package/src/cli/commands/oauth/platform.ts +525 -0
  157. package/src/cli/commands/platform.ts +3 -3
  158. package/src/cli/lib/daemon-credential-client.ts +284 -0
  159. package/src/cli.ts +1 -1
  160. package/src/config/assistant-feature-flags.ts +186 -5
  161. package/src/config/bundled-skills/AGENTS.md +34 -0
  162. package/src/config/bundled-skills/acp/SKILL.md +10 -0
  163. package/src/config/bundled-skills/app-builder/SKILL.md +0 -4
  164. package/src/config/bundled-skills/messaging/SKILL.md +5 -5
  165. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +2 -2
  166. package/src/config/bundled-skills/phone-calls/TOOLS.json +4 -0
  167. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +1 -0
  168. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +1 -0
  169. package/src/config/bundled-skills/settings/SKILL.md +15 -2
  170. package/src/config/bundled-skills/settings/TOOLS.json +47 -2
  171. package/src/config/bundled-skills/settings/tools/avatar-remove.ts +59 -0
  172. package/src/config/bundled-skills/settings/tools/avatar-update.ts +80 -0
  173. package/src/config/bundled-skills/settings/tools/voice-config-update.ts +42 -0
  174. package/src/config/bundled-skills/slack/SKILL.md +1 -1
  175. package/src/config/bundled-tool-registry.ts +5 -11
  176. package/src/config/defaults.ts +0 -2
  177. package/src/config/env-registry.ts +5 -5
  178. package/src/config/env.ts +21 -14
  179. package/src/config/feature-flag-registry.json +49 -9
  180. package/src/config/loader.ts +106 -42
  181. package/src/config/schema.ts +9 -29
  182. package/src/config/schemas/calls.ts +30 -0
  183. package/src/config/schemas/fish-audio.ts +39 -0
  184. package/src/config/schemas/inference.ts +2 -2
  185. package/src/config/schemas/journal.ts +16 -0
  186. package/src/config/schemas/memory-processing.ts +2 -2
  187. package/src/config/schemas/security.ts +0 -4
  188. package/src/config/types.ts +1 -1
  189. package/src/contacts/contact-store.ts +39 -0
  190. package/src/contacts/types.ts +2 -0
  191. package/src/credential-execution/approval-bridge.ts +1 -0
  192. package/src/credential-execution/executable-discovery.ts +28 -4
  193. package/src/credential-execution/feature-gates.ts +16 -0
  194. package/src/credential-execution/process-manager.ts +38 -0
  195. package/src/credential-execution/startup-timeout.ts +36 -0
  196. package/src/daemon/approval-generators.ts +3 -9
  197. package/src/daemon/assistant-attachments.ts +9 -0
  198. package/src/daemon/config-watcher.ts +5 -0
  199. package/src/daemon/conversation-error.ts +13 -1
  200. package/src/daemon/conversation-memory.ts +1 -2
  201. package/src/daemon/conversation-process.ts +18 -1
  202. package/src/daemon/conversation-surfaces.ts +30 -1
  203. package/src/daemon/conversation-tool-setup.ts +0 -105
  204. package/src/daemon/conversation.ts +21 -1
  205. package/src/daemon/guardian-action-generators.ts +3 -9
  206. package/src/daemon/handlers/config-vercel.ts +92 -0
  207. package/src/daemon/handlers/skills.ts +2 -15
  208. package/src/daemon/install-symlink.ts +195 -0
  209. package/src/daemon/lifecycle.ts +234 -51
  210. package/src/daemon/message-types/conversations.ts +4 -4
  211. package/src/daemon/message-types/diagnostics.ts +3 -22
  212. package/src/daemon/message-types/messages.ts +0 -2
  213. package/src/daemon/message-types/upgrades.ts +8 -0
  214. package/src/daemon/server.ts +32 -95
  215. package/src/events/domain-events.ts +2 -1
  216. package/src/inbound/platform-callback-registration.ts +3 -3
  217. package/src/instrument.ts +8 -5
  218. package/src/memory/app-store.ts +31 -0
  219. package/src/memory/conversation-title-service.ts +50 -1
  220. package/src/memory/db-init.ts +16 -0
  221. package/src/memory/indexer.ts +19 -10
  222. package/src/memory/items-extractor.ts +328 -321
  223. package/src/memory/job-handlers/conversation-starters.ts +4 -1
  224. package/src/memory/job-handlers/summarization.ts +26 -16
  225. package/src/memory/jobs-store.ts +63 -6
  226. package/src/memory/jobs-worker.ts +31 -7
  227. package/src/memory/journal-memory.ts +214 -0
  228. package/src/memory/migrations/001-job-deferrals.ts +19 -0
  229. package/src/memory/migrations/004-entity-relation-dedup.ts +10 -0
  230. package/src/memory/migrations/005-fingerprint-scope-unique.ts +76 -0
  231. package/src/memory/migrations/006-scope-salted-fingerprints.ts +50 -0
  232. package/src/memory/migrations/007-assistant-id-to-self.ts +10 -0
  233. package/src/memory/migrations/008-remove-assistant-id-columns.ts +34 -0
  234. package/src/memory/migrations/009-llm-usage-events-drop-assistant-id.ts +26 -0
  235. package/src/memory/migrations/014-backfill-inbox-thread-state.ts +10 -0
  236. package/src/memory/migrations/015-drop-active-search-index.ts +17 -0
  237. package/src/memory/migrations/019-notification-tables-schema-migration.ts +12 -0
  238. package/src/memory/migrations/020-rename-macos-ios-channel-to-vellum.ts +121 -0
  239. package/src/memory/migrations/024-embedding-vector-blob.ts +74 -0
  240. package/src/memory/migrations/026a-embeddings-nullable-vector-json.ts +82 -0
  241. package/src/memory/migrations/036-normalize-phone-identities.ts +11 -0
  242. package/src/memory/migrations/116-messages-fts.ts +106 -1
  243. package/src/memory/migrations/126-backfill-guardian-principal-id.ts +52 -0
  244. package/src/memory/migrations/127-guardian-principal-id-not-null.ts +77 -0
  245. package/src/memory/migrations/134-contacts-notes-column.ts +13 -0
  246. package/src/memory/migrations/135-backfill-contact-interaction-stats.ts +20 -0
  247. package/src/memory/migrations/136-drop-assistant-id-columns.ts +52 -0
  248. package/src/memory/migrations/140-backfill-usage-cache-accounting.ts +13 -0
  249. package/src/memory/migrations/141-rename-verification-table.ts +54 -0
  250. package/src/memory/migrations/142-rename-verification-session-id-column.ts +25 -0
  251. package/src/memory/migrations/143-rename-guardian-verification-values.ts +35 -0
  252. package/src/memory/migrations/144-rename-voice-to-phone.ts +136 -0
  253. package/src/memory/migrations/145-drop-accounts-table.ts +32 -0
  254. package/src/memory/migrations/147-migrate-reminders-to-schedules.ts +14 -1
  255. package/src/memory/migrations/148-drop-reminders-table.ts +35 -1
  256. package/src/memory/migrations/150-oauth-apps-client-secret-path.ts +69 -1
  257. package/src/memory/migrations/162-guardian-timestamps-epoch-ms.ts +290 -0
  258. package/src/memory/migrations/169-rename-gmail-provider-key-to-google.ts +51 -1
  259. package/src/memory/migrations/174-rename-thread-starters-table.ts +47 -1
  260. package/src/memory/migrations/176-drop-capability-card-state.ts +13 -0
  261. package/src/memory/migrations/180-backfill-inline-attachments-to-disk.ts +16 -0
  262. package/src/memory/migrations/181-rename-thread-starters-checkpoints.ts +28 -1
  263. package/src/memory/migrations/190-call-session-skip-disclosure.ts +15 -0
  264. package/src/memory/migrations/191-backfill-audio-attachment-mime-types.ts +64 -0
  265. package/src/memory/migrations/192-contacts-user-file-column.ts +15 -0
  266. package/src/memory/migrations/193-add-source-type-columns.ts +81 -0
  267. package/src/memory/migrations/index.ts +5 -0
  268. package/src/memory/migrations/registry.ts +98 -0
  269. package/src/memory/migrations/validate-migration-state.ts +137 -11
  270. package/src/memory/qdrant-circuit-breaker.ts +9 -0
  271. package/src/memory/qdrant-manager.ts +64 -7
  272. package/src/memory/retriever.test.ts +37 -25
  273. package/src/memory/retriever.ts +24 -49
  274. package/src/memory/schema/calls.ts +1 -0
  275. package/src/memory/schema/contacts.ts +1 -0
  276. package/src/memory/schema/memory-core.ts +2 -0
  277. package/src/memory/search/formatting.ts +7 -44
  278. package/src/memory/search/staleness.ts +4 -0
  279. package/src/memory/search/tier-classifier.ts +10 -2
  280. package/src/memory/search/types.ts +2 -5
  281. package/src/memory/task-memory-cleanup.ts +4 -3
  282. package/src/notifications/adapters/slack.ts +168 -6
  283. package/src/notifications/broadcaster.ts +1 -0
  284. package/src/notifications/copy-composer.ts +59 -2
  285. package/src/notifications/decision-engine.ts +4 -1
  286. package/src/notifications/signal.ts +2 -0
  287. package/src/notifications/types.ts +2 -0
  288. package/src/oauth/connection-resolver.ts +6 -4
  289. package/src/permissions/checker.ts +0 -38
  290. package/src/permissions/shell-identity.ts +76 -22
  291. package/src/permissions/types.ts +4 -2
  292. package/src/platform/client.ts +35 -7
  293. package/src/prompts/journal-context.ts +133 -0
  294. package/src/prompts/persona-resolver.ts +194 -0
  295. package/src/prompts/system-prompt.ts +44 -4
  296. package/src/prompts/templates/SOUL.md +10 -0
  297. package/src/prompts/templates/users/default.md +1 -0
  298. package/src/providers/provider-send-message.ts +3 -32
  299. package/src/providers/registry.ts +29 -179
  300. package/src/providers/types.ts +1 -1
  301. package/src/runtime/access-request-helper.ts +4 -0
  302. package/src/runtime/auth/__tests__/credential-service.test.ts +0 -1
  303. package/src/runtime/auth/__tests__/external-assistant-id.test.ts +13 -68
  304. package/src/runtime/auth/__tests__/guard-tests.test.ts +9 -50
  305. package/src/runtime/auth/external-assistant-id.ts +13 -59
  306. package/src/runtime/auth/route-policy.ts +17 -1
  307. package/src/runtime/auth/token-service.ts +43 -138
  308. package/src/runtime/channel-readiness-service.ts +1 -16
  309. package/src/runtime/gateway-client.ts +47 -4
  310. package/src/runtime/guardian-decision-types.ts +45 -4
  311. package/src/runtime/http-server.ts +31 -3
  312. package/src/runtime/middleware/error-handler.ts +1 -9
  313. package/src/runtime/routes/access-request-decision.ts +2 -2
  314. package/src/runtime/routes/app-management-routes.ts +2 -1
  315. package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +219 -30
  316. package/src/runtime/routes/approval-strategies/guardian-text-engine-strategy.ts +37 -14
  317. package/src/runtime/routes/audio-routes.ts +40 -0
  318. package/src/runtime/routes/btw-routes.ts +0 -17
  319. package/src/runtime/routes/channel-readiness-routes.ts +9 -4
  320. package/src/runtime/routes/conversation-query-routes.ts +63 -1
  321. package/src/runtime/routes/conversation-routes.ts +4 -44
  322. package/src/runtime/routes/debug-routes.ts +12 -9
  323. package/src/runtime/routes/diagnostics-routes.ts +1 -477
  324. package/src/runtime/routes/guardian-approval-interception.ts +168 -11
  325. package/src/runtime/routes/guardian-approval-prompt.ts +6 -1
  326. package/src/runtime/routes/guardian-approval-reply-helpers.ts +103 -21
  327. package/src/runtime/routes/identity-routes.ts +19 -30
  328. package/src/runtime/routes/inbound-message-handler.ts +31 -1
  329. package/src/runtime/routes/inbound-stages/acl-enforcement.ts +64 -5
  330. package/src/runtime/routes/inbound-stages/background-dispatch.ts +52 -40
  331. package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +4 -33
  332. package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +1 -1
  333. package/src/runtime/routes/integrations/twilio.ts +52 -10
  334. package/src/runtime/routes/integrations/vercel.ts +89 -0
  335. package/src/runtime/routes/log-export-routes.ts +5 -0
  336. package/src/runtime/routes/memory-item-routes.test.ts +3 -3
  337. package/src/runtime/routes/memory-item-routes.ts +46 -14
  338. package/src/runtime/routes/migration-rollback-routes.ts +209 -0
  339. package/src/runtime/routes/migration-routes.ts +17 -1
  340. package/src/runtime/routes/notification-routes.ts +58 -0
  341. package/src/runtime/routes/schedule-routes.ts +65 -0
  342. package/src/runtime/routes/secret-routes.ts +141 -10
  343. package/src/runtime/routes/settings-routes.ts +41 -1
  344. package/src/runtime/routes/tts-routes.ts +96 -0
  345. package/src/runtime/routes/upgrade-broadcast-routes.ts +26 -2
  346. package/src/runtime/routes/workspace-commit-routes.ts +62 -0
  347. package/src/runtime/routes/workspace-routes.test.ts +22 -1
  348. package/src/runtime/routes/workspace-routes.ts +1 -1
  349. package/src/runtime/routes/workspace-utils.ts +86 -2
  350. package/src/security/ces-credential-client.ts +75 -29
  351. package/src/security/ces-rpc-credential-backend.ts +86 -0
  352. package/src/security/credential-backend.ts +22 -92
  353. package/src/security/keychain-broker-client.ts +10 -2
  354. package/src/security/secure-keys.ts +113 -115
  355. package/src/skills/catalog-install.ts +6 -32
  356. package/src/skills/skill-memory.ts +1 -0
  357. package/src/subagent/manager.ts +2 -5
  358. package/src/telemetry/usage-telemetry-reporter.ts +4 -2
  359. package/src/tools/acp/spawn.ts +78 -1
  360. package/src/tools/calls/call-start.ts +1 -0
  361. package/src/tools/credentials/vault.ts +5 -3
  362. package/src/tools/executor.ts +0 -4
  363. package/src/tools/memory/definitions.ts +3 -2
  364. package/src/tools/memory/handlers.ts +10 -7
  365. package/src/tools/network/script-proxy/session-manager.ts +19 -4
  366. package/src/tools/network/web-fetch.ts +3 -1
  367. package/src/tools/skills/execute.ts +1 -1
  368. package/src/tools/terminal/safe-env.ts +1 -0
  369. package/src/tools/types.ts +0 -8
  370. package/src/util/browser.ts +15 -0
  371. package/src/util/errors.ts +0 -12
  372. package/src/util/platform.ts +4 -51
  373. package/src/workspace/git-service.ts +5 -2
  374. package/src/workspace/migrations/001-avatar-rename.ts +15 -0
  375. package/src/workspace/migrations/003-seed-device-id.ts +17 -1
  376. package/src/workspace/migrations/004-extract-collect-usage-data.ts +33 -0
  377. package/src/workspace/migrations/005-add-send-diagnostics.ts +3 -0
  378. package/src/workspace/migrations/006-services-config.ts +49 -0
  379. package/src/workspace/migrations/007-web-search-provider-rename.ts +27 -0
  380. package/src/workspace/migrations/008-voice-timeout-and-max-steps.ts +3 -0
  381. package/src/workspace/migrations/009-backfill-conversation-disk-view.ts +4 -0
  382. package/src/workspace/migrations/010-app-dir-rename.ts +78 -0
  383. package/src/workspace/migrations/011-backfill-installation-id.ts +11 -0
  384. package/src/workspace/migrations/012-rename-conversation-disk-view-dirs.ts +44 -0
  385. package/src/workspace/migrations/013-repair-conversation-disk-view.ts +5 -0
  386. package/src/workspace/migrations/015-migrate-credentials-to-keychain.ts +153 -0
  387. package/src/workspace/migrations/016-extract-feature-flags-to-protected.ts +156 -0
  388. package/src/workspace/migrations/016-migrate-credentials-from-keychain.ts +150 -0
  389. package/src/workspace/migrations/017-seed-persona-dirs.ts +96 -0
  390. package/src/workspace/migrations/018-rekey-compound-credential-keys.ts +184 -0
  391. package/src/workspace/migrations/019-scope-journal-to-guardian.ts +103 -0
  392. package/src/workspace/migrations/migrate-to-workspace-volume.ts +27 -5
  393. package/src/workspace/migrations/registry.ts +12 -0
  394. package/src/workspace/migrations/runner.ts +106 -2
  395. package/src/workspace/migrations/types.ts +4 -0
  396. package/src/workspace/provider-commit-message-generator.ts +12 -21
  397. package/src/__tests__/claude-code-skill-regression.test.ts +0 -206
  398. package/src/__tests__/claude-code-tool-profiles.test.ts +0 -99
  399. package/src/__tests__/diagnostics-export.test.ts +0 -288
  400. package/src/__tests__/local-gateway-health.test.ts +0 -209
  401. package/src/__tests__/provider-fail-open-selection.test.ts +0 -271
  402. package/src/__tests__/provider-failover-actual-provider.test.ts +0 -66
  403. package/src/__tests__/secret-ingress-handler.test.ts +0 -120
  404. package/src/__tests__/swarm-conversation-integration.test.ts +0 -358
  405. package/src/__tests__/swarm-dag-pathological.test.ts +0 -547
  406. package/src/__tests__/swarm-orchestrator.test.ts +0 -463
  407. package/src/__tests__/swarm-plan-validator.test.ts +0 -384
  408. package/src/__tests__/swarm-recursion.test.ts +0 -197
  409. package/src/__tests__/swarm-router-planner.test.ts +0 -234
  410. package/src/__tests__/swarm-tool.test.ts +0 -185
  411. package/src/__tests__/swarm-worker-backend.test.ts +0 -144
  412. package/src/__tests__/swarm-worker-runner.test.ts +0 -288
  413. package/src/commands/__tests__/cc-command-registry.test.ts +0 -396
  414. package/src/commands/cc-command-registry.ts +0 -248
  415. package/src/config/bundled-skills/claude-code/SKILL.md +0 -53
  416. package/src/config/bundled-skills/claude-code/TOOLS.json +0 -47
  417. package/src/config/bundled-skills/claude-code/tools/claude-code.ts +0 -12
  418. package/src/config/bundled-skills/orchestration/SKILL.md +0 -33
  419. package/src/config/bundled-skills/orchestration/TOOLS.json +0 -35
  420. package/src/config/bundled-skills/orchestration/tools/swarm-delegate.ts +0 -12
  421. package/src/config/schemas/swarm.ts +0 -82
  422. package/src/logfire.ts +0 -135
  423. package/src/memory/search/lexical.ts +0 -48
  424. package/src/providers/failover.ts +0 -186
  425. package/src/runtime/local-gateway-health.ts +0 -275
  426. package/src/security/secret-ingress.ts +0 -68
  427. package/src/swarm/backend-claude-code.ts +0 -225
  428. package/src/swarm/checkpoint.ts +0 -137
  429. package/src/swarm/graph-utils.ts +0 -53
  430. package/src/swarm/index.ts +0 -55
  431. package/src/swarm/limits.ts +0 -66
  432. package/src/swarm/orchestrator.ts +0 -424
  433. package/src/swarm/plan-validator.ts +0 -117
  434. package/src/swarm/router-planner.ts +0 -162
  435. package/src/swarm/router-prompts.ts +0 -39
  436. package/src/swarm/synthesizer.ts +0 -81
  437. package/src/swarm/types.ts +0 -72
  438. package/src/swarm/worker-backend.ts +0 -131
  439. package/src/swarm/worker-prompts.ts +0 -80
  440. package/src/swarm/worker-runner.ts +0 -170
  441. package/src/tools/claude-code/claude-code.ts +0 -610
  442. package/src/tools/swarm/delegate.ts +0 -205
@@ -1,39 +0,0 @@
1
- /**
2
- * System prompt for the router planner LLM call.
3
- */
4
- export const ROUTER_SYSTEM_PROMPT = `You are a task decomposition planner. Given a user objective, break it down into a set of parallel and sequential tasks that can be executed by specialist workers.
5
-
6
- Available worker roles:
7
- - researcher: Can search the web, read files, and gather information. Cannot write or edit files.
8
- - coder: Can read, write, and edit files, run shell commands, and implement code changes.
9
- - reviewer: Can read and search files to review code. Cannot write or edit files.
10
-
11
- Rules:
12
- 1. Output ONLY a valid JSON object. No prose, no markdown, no explanation.
13
- 2. Each task must have a unique "id" (short slug), a "role", an "objective" (clear instruction), and "dependencies" (array of task IDs that must complete first).
14
- 3. Maximize parallelism: only add a dependency if the task truly needs output from another.
15
- 4. Keep the plan minimal — avoid unnecessary tasks. Prefer fewer, well-scoped tasks.
16
- 5. Do not create tasks for the "router" role.
17
- 6. The total number of tasks must not exceed the provided limit.
18
-
19
- Output schema:
20
- {
21
- "tasks": [
22
- {
23
- "id": "string",
24
- "role": "researcher" | "coder" | "reviewer",
25
- "objective": "string",
26
- "dependencies": ["task-id", ...]
27
- }
28
- ]
29
- }`;
30
-
31
- /**
32
- * Build the user message for the router planner.
33
- */
34
- export function buildPlannerUserMessage(
35
- objective: string,
36
- maxTasks: number,
37
- ): string {
38
- return `Objective: ${objective}\n\nMaximum tasks allowed: ${maxTasks}\n\nReturn ONLY the JSON plan.`;
39
- }
@@ -1,81 +0,0 @@
1
- import type { Message, ModelIntent, Provider } from "../providers/types.js";
2
- import type { SwarmTaskResult } from "./types.js";
3
-
4
- /**
5
- * Synthesize a final answer from all worker results using an LLM.
6
- * Falls back to a deterministic markdown summary if the LLM call fails.
7
- */
8
- export async function synthesizeResults(opts: {
9
- objective: string;
10
- results: SwarmTaskResult[];
11
- provider: Provider;
12
- modelIntent?: ModelIntent;
13
- }): Promise<string> {
14
- const { objective, results, provider, modelIntent } = opts;
15
-
16
- // Cap individual summaries and total input to avoid blowing up context on large plans
17
- const MAX_SUMMARY_CHARS = 500;
18
- const MAX_TOTAL_CHARS = 12_000;
19
-
20
- let taskSummaries = results
21
- .map((r) => {
22
- const status = r.status === "completed" ? "completed" : "FAILED";
23
- const summary =
24
- r.summary.length > MAX_SUMMARY_CHARS
25
- ? r.summary.slice(0, MAX_SUMMARY_CHARS) + "..."
26
- : r.summary;
27
- return `[${r.taskId}] (${status}): ${summary}`;
28
- })
29
- .join("\n");
30
-
31
- if (taskSummaries.length > MAX_TOTAL_CHARS) {
32
- taskSummaries =
33
- taskSummaries.slice(0, MAX_TOTAL_CHARS) + "\n... (truncated)";
34
- }
35
-
36
- const systemPrompt =
37
- "You are a synthesis assistant. Combine the outputs from multiple specialist workers into a coherent, concise final answer. Focus on the user's original objective.";
38
-
39
- const userMessage = `Original objective: ${objective}
40
-
41
- Worker results:
42
- ${taskSummaries}
43
-
44
- Synthesize these results into a clear, complete answer for the user.`;
45
-
46
- try {
47
- const messages: Message[] = [
48
- { role: "user", content: [{ type: "text", text: userMessage }] },
49
- ];
50
-
51
- const response = await provider.sendMessage(
52
- messages,
53
- undefined,
54
- systemPrompt,
55
- { config: { max_tokens: 4096, modelIntent } },
56
- );
57
-
58
- const textBlock = response.content.find((b) => b.type === "text");
59
- if (textBlock && textBlock.type === "text") {
60
- return textBlock.text;
61
- }
62
-
63
- return buildFallbackSynthesis(objective, results);
64
- } catch {
65
- return buildFallbackSynthesis(objective, results);
66
- }
67
- }
68
-
69
- function buildFallbackSynthesis(
70
- objective: string,
71
- results: SwarmTaskResult[],
72
- ): string {
73
- const lines: string[] = [`## Results: ${objective}`, ""];
74
-
75
- for (const r of results) {
76
- const icon = r.status === "completed" ? "OK" : "FAIL";
77
- lines.push(`- [${icon}] **${r.taskId}**: ${r.summary}`);
78
- }
79
-
80
- return lines.join("\n");
81
- }
@@ -1,72 +0,0 @@
1
- /**
2
- * Swarm runtime types for multi-worker task orchestration.
3
- */
4
-
5
- export type SwarmRole = "router" | "researcher" | "coder" | "reviewer";
6
-
7
- export const VALID_SWARM_ROLES: readonly SwarmRole[] = [
8
- "router",
9
- "researcher",
10
- "coder",
11
- "reviewer",
12
- ] as const;
13
-
14
- export interface SwarmTaskNode {
15
- /** Unique identifier within the plan. */
16
- id: string;
17
- /** Role that will execute this task. */
18
- role: SwarmRole;
19
- /** Human-readable objective for the worker. */
20
- objective: string;
21
- /** IDs of tasks that must complete before this one can start. */
22
- dependencies: string[];
23
- }
24
-
25
- export interface SwarmPlan {
26
- /** Top-level objective that was decomposed into tasks. */
27
- objective: string;
28
- /** Ordered list of tasks forming a DAG. */
29
- tasks: SwarmTaskNode[];
30
- }
31
-
32
- export type SwarmTaskStatus =
33
- | "queued"
34
- | "running"
35
- | "completed"
36
- | "failed"
37
- | "blocked";
38
-
39
- export interface SwarmTaskResult {
40
- taskId: string;
41
- status: "completed" | "failed";
42
- /** Structured summary from the worker. */
43
- summary: string;
44
- /** Artifacts produced (file paths, code snippets, etc.). */
45
- artifacts: string[];
46
- /** Issues encountered during execution. */
47
- issues: string[];
48
- /** Suggested follow-up steps. */
49
- nextSteps: string[];
50
- /** Raw unprocessed output from the worker backend. */
51
- rawOutput: string;
52
- /** Wall-clock duration in milliseconds. */
53
- durationMs: number;
54
- /** Number of retry attempts before final result. */
55
- retryCount: number;
56
- }
57
-
58
- export interface SwarmExecutionSummary {
59
- objective: string;
60
- plan: SwarmPlan;
61
- results: SwarmTaskResult[];
62
- /** Synthesized final answer combining all worker outputs. */
63
- finalAnswer: string;
64
- /** Aggregate stats. */
65
- stats: {
66
- totalTasks: number;
67
- completed: number;
68
- failed: number;
69
- blocked: number;
70
- totalDurationMs: number;
71
- };
72
- }
@@ -1,131 +0,0 @@
1
- import type { SwarmRole } from "./types.js";
2
-
3
- /**
4
- * Profile names that scope tool access for worker tasks.
5
- */
6
- export type WorkerProfile = "general" | "researcher" | "coder" | "reviewer";
7
-
8
- /**
9
- * Maps swarm roles to worker profiles.
10
- */
11
- export function roleToProfile(role: SwarmRole): WorkerProfile {
12
- switch (role) {
13
- case "researcher":
14
- return "researcher";
15
- case "coder":
16
- return "coder";
17
- case "reviewer":
18
- return "reviewer";
19
- case "router":
20
- return "general";
21
- default:
22
- return "general";
23
- }
24
- }
25
-
26
- /**
27
- * Per-profile tool access policy. The sets are checked in order:
28
- * 1. If tool is in `deny`, block unconditionally.
29
- * 2. If tool is in `allow`, auto-approve.
30
- * 3. If tool is in `approvalRequired`, prompt user.
31
- * 4. Otherwise follow default approval flow.
32
- */
33
- export interface ProfilePolicy {
34
- allow: Set<string>;
35
- deny: Set<string>;
36
- approvalRequired: Set<string>;
37
- }
38
-
39
- const READ_ONLY_TOOLS = new Set([
40
- "Read",
41
- "Glob",
42
- "Grep",
43
- "WebSearch",
44
- "WebFetch",
45
- "LS",
46
- "Bash(grep *)",
47
- "Bash(rg *)",
48
- "Bash(find *)",
49
- ]);
50
-
51
- const WRITE_TOOLS = new Set(["Edit", "Write", "MultiEdit", "NotebookEdit"]);
52
-
53
- /**
54
- * Return the tool access policy for a given profile.
55
- */
56
- export function getProfilePolicy(profile: WorkerProfile): ProfilePolicy {
57
- switch (profile) {
58
- case "general":
59
- return {
60
- allow: new Set(READ_ONLY_TOOLS),
61
- deny: new Set(),
62
- approvalRequired: new Set(["Bash", ...WRITE_TOOLS]),
63
- };
64
-
65
- case "researcher":
66
- return {
67
- allow: new Set(READ_ONLY_TOOLS),
68
- deny: new Set([...WRITE_TOOLS, "Bash"]),
69
- approvalRequired: new Set(),
70
- };
71
-
72
- case "coder":
73
- return {
74
- allow: new Set(READ_ONLY_TOOLS),
75
- deny: new Set(),
76
- approvalRequired: new Set(["Bash", ...WRITE_TOOLS]),
77
- };
78
-
79
- case "reviewer":
80
- return {
81
- allow: new Set(READ_ONLY_TOOLS),
82
- deny: new Set([...WRITE_TOOLS, "Bash"]),
83
- approvalRequired: new Set(),
84
- };
85
-
86
- default:
87
- return {
88
- allow: new Set(READ_ONLY_TOOLS),
89
- deny: new Set(),
90
- approvalRequired: new Set(["Bash", ...WRITE_TOOLS]),
91
- };
92
- }
93
- }
94
-
95
- // ---------------------------------------------------------------------------
96
- // Worker Backend
97
- // ---------------------------------------------------------------------------
98
-
99
- export type WorkerFailureReason =
100
- | "backend_unavailable"
101
- | "timeout"
102
- | "cancelled"
103
- | "malformed_output"
104
- | "tool_denied";
105
-
106
- export interface SwarmWorkerBackendResult {
107
- success: boolean;
108
- output: string;
109
- failureReason?: WorkerFailureReason;
110
- durationMs: number;
111
- }
112
-
113
- export interface SwarmWorkerBackendInput {
114
- prompt: string;
115
- profile: WorkerProfile;
116
- workingDir: string;
117
- modelIntent?: string;
118
- timeoutMs?: number;
119
- signal?: AbortSignal;
120
- }
121
-
122
- /**
123
- * Abstraction over execution backends for swarm workers.
124
- */
125
- export interface SwarmWorkerBackend {
126
- readonly name: string;
127
- /** Check whether the backend is available (e.g. API key present). */
128
- isAvailable(): boolean | Promise<boolean>;
129
- /** Run a task with the given input. */
130
- runTask(input: SwarmWorkerBackendInput): Promise<SwarmWorkerBackendResult>;
131
- }
@@ -1,80 +0,0 @@
1
- import { parseJsonSafe } from "../util/json.js";
2
- import { truncate } from "../util/truncate.js";
3
- import type { SwarmRole, SwarmTaskResult } from "./types.js";
4
-
5
- /**
6
- * Build a role-specific worker prompt for a swarm task.
7
- */
8
- export function buildWorkerPrompt(opts: {
9
- role: SwarmRole;
10
- objective: string;
11
- upstreamContext?: string;
12
- dependencyOutputs?: Array<{ taskId: string; summary: string }>;
13
- }): string {
14
- const parts: string[] = [];
15
-
16
- parts.push(
17
- `You are a ${opts.role} worker in a swarm. Your objective:\n${opts.objective}`,
18
- );
19
-
20
- if (opts.upstreamContext) {
21
- parts.push(`\nContext from the orchestrator:\n${opts.upstreamContext}`);
22
- }
23
-
24
- if (opts.dependencyOutputs && opts.dependencyOutputs.length > 0) {
25
- parts.push("\nOutputs from prerequisite tasks:");
26
- for (const dep of opts.dependencyOutputs) {
27
- parts.push(`- [${dep.taskId}]: ${dep.summary}`);
28
- }
29
- }
30
-
31
- parts.push(WORKER_OUTPUT_CONTRACT);
32
-
33
- return parts.join("\n");
34
- }
35
-
36
- const WORKER_OUTPUT_CONTRACT = `
37
-
38
- When you are finished, output your result as a single fenced JSON block:
39
-
40
- \`\`\`json
41
- {
42
- "summary": "Brief summary of what you accomplished",
43
- "artifacts": ["list of file paths, code snippets, or other outputs"],
44
- "issues": ["list of problems encountered, if any"],
45
- "nextSteps": ["suggested follow-up actions, if any"]
46
- }
47
- \`\`\`
48
-
49
- If you cannot produce valid JSON, just write a plain-text summary.`;
50
-
51
- /**
52
- * Parse the worker's raw output into a structured result shape.
53
- * Scans fenced JSON blocks from last to first, picking the last one that
54
- * matches the worker-result contract (has a `summary` string field).
55
- * Falls back to treating the entire output as a plain-text summary.
56
- */
57
- export function parseWorkerOutput(
58
- raw: string,
59
- ): Pick<SwarmTaskResult, "summary" | "artifacts" | "issues" | "nextSteps"> {
60
- const jsonBlocks = Array.from(raw.matchAll(/```json\s*\n([\s\S]*?)\n```/g));
61
-
62
- // Walk backwards to prefer the final valid contract block.
63
- for (let i = jsonBlocks.length - 1; i >= 0; i--) {
64
- const parsed = parseJsonSafe<Record<string, unknown>>(jsonBlocks[i][1]);
65
- if (!parsed || typeof parsed.summary !== "string") continue;
66
- return {
67
- summary: parsed.summary,
68
- artifacts: Array.isArray(parsed.artifacts) ? parsed.artifacts : [],
69
- issues: Array.isArray(parsed.issues) ? parsed.issues : [],
70
- nextSteps: Array.isArray(parsed.nextSteps) ? parsed.nextSteps : [],
71
- };
72
- }
73
-
74
- return {
75
- summary: truncate(raw, 500, ""),
76
- artifacts: [],
77
- issues: [],
78
- nextSteps: [],
79
- };
80
- }
@@ -1,170 +0,0 @@
1
- import type { SwarmTaskNode, SwarmTaskResult } from "./types.js";
2
- import type { SwarmWorkerBackend } from "./worker-backend.js";
3
- import { roleToProfile } from "./worker-backend.js";
4
- import { buildWorkerPrompt, parseWorkerOutput } from "./worker-prompts.js";
5
-
6
- export type WorkerStatusKind = "queued" | "running" | "completed" | "failed";
7
-
8
- export type WorkerStatusCallback = (
9
- taskId: string,
10
- status: WorkerStatusKind,
11
- ) => void;
12
-
13
- export interface RunWorkerTaskOptions {
14
- task: SwarmTaskNode;
15
- /** Top-level objective context passed from the orchestrator. */
16
- upstreamContext?: string;
17
- /** Summaries from completed dependency tasks. */
18
- dependencyOutputs?: Array<{ taskId: string; summary: string }>;
19
- backend: SwarmWorkerBackend;
20
- workingDir: string;
21
- modelIntent?: string;
22
- timeoutMs: number;
23
- onStatus?: WorkerStatusCallback;
24
- signal?: AbortSignal;
25
- }
26
-
27
- function emitStatus(
28
- onStatus: WorkerStatusCallback | undefined,
29
- taskId: string,
30
- status: WorkerStatusKind,
31
- ): void {
32
- if (!onStatus) return;
33
- try {
34
- onStatus(taskId, status);
35
- } catch {
36
- // Observer failures must not abort worker execution.
37
- }
38
- }
39
-
40
- /**
41
- * Execute a single swarm worker task through the given backend.
42
- * Returns a normalized SwarmTaskResult regardless of success or failure.
43
- */
44
- export async function runWorkerTask(
45
- opts: RunWorkerTaskOptions,
46
- ): Promise<SwarmTaskResult> {
47
- const { task, backend, workingDir, timeoutMs, onStatus, signal } = opts;
48
-
49
- if (signal?.aborted) {
50
- return {
51
- taskId: task.id,
52
- status: "failed",
53
- summary: "Cancelled",
54
- artifacts: [],
55
- issues: ["aborted"],
56
- nextSteps: [],
57
- rawOutput: "",
58
- durationMs: 0,
59
- retryCount: 0,
60
- };
61
- }
62
-
63
- emitStatus(onStatus, task.id, "queued");
64
-
65
- // Check backend availability
66
- if (!(await backend.isAvailable())) {
67
- emitStatus(onStatus, task.id, "failed");
68
- return {
69
- taskId: task.id,
70
- status: "failed",
71
- summary: `Backend "${backend.name}" is not available. Check API key and SDK configuration.`,
72
- artifacts: [],
73
- issues: [`Backend "${backend.name}" unavailable`],
74
- nextSteps: ["Configure the backend or use a different one"],
75
- rawOutput: "",
76
- durationMs: 0,
77
- retryCount: 0,
78
- };
79
- }
80
-
81
- emitStatus(onStatus, task.id, "running");
82
-
83
- const prompt = buildWorkerPrompt({
84
- role: task.role,
85
- objective: task.objective,
86
- upstreamContext: opts.upstreamContext,
87
- dependencyOutputs: opts.dependencyOutputs,
88
- });
89
-
90
- const profile = roleToProfile(task.role);
91
-
92
- try {
93
- const backendPromise = backend.runTask({
94
- prompt,
95
- profile,
96
- workingDir,
97
- modelIntent: opts.modelIntent,
98
- timeoutMs,
99
- signal,
100
- });
101
-
102
- // Enforce timeout via Promise.race
103
- const timeoutPromise = new Promise<"timeout">((resolve) => {
104
- const timer = setTimeout(() => resolve("timeout"), timeoutMs);
105
- // Don't keep the process alive just for this timer
106
- if (typeof timer === "object" && "unref" in timer) timer.unref();
107
- });
108
-
109
- const raceResult = await Promise.race([backendPromise, timeoutPromise]);
110
-
111
- if (raceResult === "timeout") {
112
- emitStatus(onStatus, task.id, "failed");
113
- return {
114
- taskId: task.id,
115
- status: "failed",
116
- summary: `Worker timed out after ${timeoutMs}ms`,
117
- artifacts: [],
118
- issues: ["timeout"],
119
- nextSteps: [],
120
- rawOutput: "",
121
- durationMs: timeoutMs,
122
- retryCount: 0,
123
- };
124
- }
125
-
126
- const result = raceResult;
127
-
128
- if (result.success) {
129
- const parsed = parseWorkerOutput(result.output);
130
- emitStatus(onStatus, task.id, "completed");
131
- return {
132
- taskId: task.id,
133
- status: "completed",
134
- ...parsed,
135
- rawOutput: result.output,
136
- durationMs: result.durationMs,
137
- retryCount: 0,
138
- };
139
- }
140
-
141
- // Backend returned a failure
142
- emitStatus(onStatus, task.id, "failed");
143
- return {
144
- taskId: task.id,
145
- status: "failed",
146
- summary:
147
- result.output || `Task failed: ${result.failureReason ?? "unknown"}`,
148
- artifacts: [],
149
- issues: [result.failureReason ?? "unknown_failure"],
150
- nextSteps: [],
151
- rawOutput: result.output,
152
- durationMs: result.durationMs,
153
- retryCount: 0,
154
- };
155
- } catch (err) {
156
- emitStatus(onStatus, task.id, "failed");
157
- const message = err instanceof Error ? err.message : String(err);
158
- return {
159
- taskId: task.id,
160
- status: "failed",
161
- summary: `Unexpected error: ${message}`,
162
- artifacts: [],
163
- issues: [message],
164
- nextSteps: [],
165
- rawOutput: "",
166
- durationMs: 0,
167
- retryCount: 0,
168
- };
169
- }
170
- }