vellum 0.2.13 → 0.3.2

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 (1019) hide show
  1. package/bin/vellum.js +2 -0
  2. package/package.json +6 -65
  3. package/.dockerignore +0 -27
  4. package/.env.example +0 -22
  5. package/Dockerfile +0 -99
  6. package/Dockerfile.sandbox +0 -5
  7. package/README.md +0 -169
  8. package/bun.lock +0 -1743
  9. package/bunfig.toml +0 -2
  10. package/docs/skills.md +0 -158
  11. package/drizzle/0000_dizzy_maggott.sql +0 -301
  12. package/drizzle/meta/0000_snapshot.json +0 -1999
  13. package/drizzle/meta/_journal.json +0 -13
  14. package/drizzle.config.ts +0 -7
  15. package/eslint.config.mjs +0 -17
  16. package/hook-templates/debug-prompt-logger/hook.json +0 -7
  17. package/hook-templates/debug-prompt-logger/run.sh +0 -68
  18. package/knip.json +0 -9
  19. package/scripts/capture-x-graphql.ts +0 -545
  20. package/scripts/ipc/check-contract-inventory.ts +0 -104
  21. package/scripts/ipc/check-swift-decoder-drift.ts +0 -164
  22. package/scripts/ipc/generate-swift.ts +0 -492
  23. package/scripts/test-filesystem-tools.sh +0 -48
  24. package/scripts/test.sh +0 -127
  25. package/src/__tests__/__snapshots__/ipc-snapshot.test.ts.snap +0 -2316
  26. package/src/__tests__/account-registry.test.ts +0 -245
  27. package/src/__tests__/active-skill-tools.test.ts +0 -378
  28. package/src/__tests__/agent-heartbeat-service.test.ts +0 -250
  29. package/src/__tests__/agent-loop-thinking.test.ts +0 -81
  30. package/src/__tests__/agent-loop.test.ts +0 -1135
  31. package/src/__tests__/anthropic-provider.test.ts +0 -778
  32. package/src/__tests__/app-builder-tool-scripts.test.ts +0 -290
  33. package/src/__tests__/app-bundler.test.ts +0 -292
  34. package/src/__tests__/app-executors.test.ts +0 -613
  35. package/src/__tests__/app-open-proxy.test.ts +0 -62
  36. package/src/__tests__/asset-materialize-tool.test.ts +0 -452
  37. package/src/__tests__/asset-search-tool.test.ts +0 -477
  38. package/src/__tests__/assistant-attachment-directive.test.ts +0 -401
  39. package/src/__tests__/assistant-attachments.test.ts +0 -437
  40. package/src/__tests__/assistant-event-hub.test.ts +0 -226
  41. package/src/__tests__/assistant-event.test.ts +0 -123
  42. package/src/__tests__/attachments-store.test.ts +0 -476
  43. package/src/__tests__/attachments.test.ts +0 -134
  44. package/src/__tests__/audit-log-rotation.test.ts +0 -154
  45. package/src/__tests__/browser-fill-credential.test.ts +0 -309
  46. package/src/__tests__/browser-manager.test.ts +0 -203
  47. package/src/__tests__/browser-runtime-check.test.ts +0 -55
  48. package/src/__tests__/browser-skill-baseline-tool-payload.test.ts +0 -68
  49. package/src/__tests__/browser-skill-endstate.test.ts +0 -195
  50. package/src/__tests__/bundle-scanner.test.ts +0 -313
  51. package/src/__tests__/call-bridge.test.ts +0 -425
  52. package/src/__tests__/call-constants.test.ts +0 -40
  53. package/src/__tests__/call-orchestrator.test.ts +0 -512
  54. package/src/__tests__/call-recovery.test.ts +0 -518
  55. package/src/__tests__/call-routes-http.test.ts +0 -459
  56. package/src/__tests__/call-state-machine.test.ts +0 -143
  57. package/src/__tests__/call-state.test.ts +0 -174
  58. package/src/__tests__/call-store.test.ts +0 -691
  59. package/src/__tests__/checker.test.ts +0 -3960
  60. package/src/__tests__/clarification-resolver.test.ts +0 -159
  61. package/src/__tests__/classifier.test.ts +0 -67
  62. package/src/__tests__/claude-code-skill-regression.test.ts +0 -127
  63. package/src/__tests__/claude-code-tool-profiles.test.ts +0 -88
  64. package/src/__tests__/cli-discover.test.ts +0 -85
  65. package/src/__tests__/cli.test.ts +0 -81
  66. package/src/__tests__/clipboard.test.ts +0 -80
  67. package/src/__tests__/commit-guarantee.test.ts +0 -335
  68. package/src/__tests__/commit-message-enrichment-service.test.ts +0 -550
  69. package/src/__tests__/compaction.benchmark.test.ts +0 -176
  70. package/src/__tests__/computer-use-session-compaction.test.ts +0 -132
  71. package/src/__tests__/computer-use-session-lifecycle.test.ts +0 -293
  72. package/src/__tests__/computer-use-session-working-dir.test.ts +0 -117
  73. package/src/__tests__/computer-use-skill-baseline.test.ts +0 -74
  74. package/src/__tests__/computer-use-skill-endstate.test.ts +0 -89
  75. package/src/__tests__/computer-use-skill-lifecycle-cleanup.test.ts +0 -217
  76. package/src/__tests__/computer-use-skill-manifest-regression.test.ts +0 -107
  77. package/src/__tests__/computer-use-skill-proxy-bridge.test.ts +0 -54
  78. package/src/__tests__/computer-use-tools.test.ts +0 -250
  79. package/src/__tests__/config-schema.test.ts +0 -1343
  80. package/src/__tests__/conflict-store.test.ts +0 -330
  81. package/src/__tests__/connection-policy.test.ts +0 -102
  82. package/src/__tests__/contacts-tools.test.ts +0 -331
  83. package/src/__tests__/context-memory-e2e.test.ts +0 -434
  84. package/src/__tests__/context-token-estimator.test.ts +0 -135
  85. package/src/__tests__/context-window-manager.test.ts +0 -376
  86. package/src/__tests__/contradiction-checker.test.ts +0 -216
  87. package/src/__tests__/conversation-store.test.ts +0 -612
  88. package/src/__tests__/credential-broker-browser-fill.test.ts +0 -517
  89. package/src/__tests__/credential-broker-server-use.test.ts +0 -554
  90. package/src/__tests__/credential-broker.test.ts +0 -167
  91. package/src/__tests__/credential-host-pattern-match.test.ts +0 -104
  92. package/src/__tests__/credential-metadata-store.test.ts +0 -779
  93. package/src/__tests__/credential-policy-validate.test.ts +0 -121
  94. package/src/__tests__/credential-resolve.test.ts +0 -328
  95. package/src/__tests__/credential-security-e2e.test.ts +0 -352
  96. package/src/__tests__/credential-security-invariants.test.ts +0 -567
  97. package/src/__tests__/credential-selection.test.ts +0 -354
  98. package/src/__tests__/credential-vault.test.ts +0 -852
  99. package/src/__tests__/daemon-assistant-events.test.ts +0 -164
  100. package/src/__tests__/daemon-server-session-init.test.ts +0 -522
  101. package/src/__tests__/date-context.test.ts +0 -373
  102. package/src/__tests__/db-schedule-syntax-migration.test.ts +0 -129
  103. package/src/__tests__/delete-managed-skill-tool.test.ts +0 -97
  104. package/src/__tests__/diff.test.ts +0 -121
  105. package/src/__tests__/domain-normalize.test.ts +0 -112
  106. package/src/__tests__/domain-policy.test.ts +0 -124
  107. package/src/__tests__/doordash-client.test.ts +0 -186
  108. package/src/__tests__/doordash-session.test.ts +0 -152
  109. package/src/__tests__/dynamic-page-surface.test.ts +0 -91
  110. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +0 -132
  111. package/src/__tests__/edit-engine.test.ts +0 -180
  112. package/src/__tests__/elevenlabs-client.test.ts +0 -209
  113. package/src/__tests__/email-cli.test.ts +0 -283
  114. package/src/__tests__/encrypted-store.test.ts +0 -332
  115. package/src/__tests__/entity-extractor.test.ts +0 -190
  116. package/src/__tests__/ephemeral-permissions.test.ts +0 -312
  117. package/src/__tests__/evaluate-typescript-tool.test.ts +0 -286
  118. package/src/__tests__/event-bus.test.ts +0 -222
  119. package/src/__tests__/file-edit-tool.test.ts +0 -122
  120. package/src/__tests__/file-ops-service.test.ts +0 -330
  121. package/src/__tests__/file-read-tool.test.ts +0 -75
  122. package/src/__tests__/file-write-tool.test.ts +0 -113
  123. package/src/__tests__/fixtures/credential-security-fixtures.ts +0 -181
  124. package/src/__tests__/fixtures/media-reuse-fixtures.ts +0 -126
  125. package/src/__tests__/fixtures/mock-signup-server.ts +0 -387
  126. package/src/__tests__/fixtures/proxy-fixtures.ts +0 -147
  127. package/src/__tests__/followup-tools.test.ts +0 -303
  128. package/src/__tests__/forbidden-legacy-symbols.test.ts +0 -71
  129. package/src/__tests__/fuzzy-match-property.test.ts +0 -216
  130. package/src/__tests__/fuzzy-match.test.ts +0 -138
  131. package/src/__tests__/gateway-only-enforcement.test.ts +0 -436
  132. package/src/__tests__/gemini-image-service.test.ts +0 -261
  133. package/src/__tests__/gemini-provider.test.ts +0 -651
  134. package/src/__tests__/get-weather.test.ts +0 -318
  135. package/src/__tests__/gmail-integration.test.ts +0 -73
  136. package/src/__tests__/handlers-cu-observation-blob.test.ts +0 -351
  137. package/src/__tests__/handlers-ipc-blob-probe.test.ts +0 -190
  138. package/src/__tests__/handlers-slack-config.test.ts +0 -199
  139. package/src/__tests__/handlers-task-submit-slash.test.ts +0 -38
  140. package/src/__tests__/handlers-twitter-config.test.ts +0 -718
  141. package/src/__tests__/headless-browser-interactions.test.ts +0 -536
  142. package/src/__tests__/headless-browser-navigate.test.ts +0 -211
  143. package/src/__tests__/headless-browser-read-tools.test.ts +0 -261
  144. package/src/__tests__/headless-browser-snapshot.test.ts +0 -185
  145. package/src/__tests__/history-repair-observability.test.ts +0 -56
  146. package/src/__tests__/history-repair.test.ts +0 -510
  147. package/src/__tests__/home-base-bootstrap.test.ts +0 -82
  148. package/src/__tests__/hooks-blocking.test.ts +0 -128
  149. package/src/__tests__/hooks-cli.test.ts +0 -144
  150. package/src/__tests__/hooks-config.test.ts +0 -93
  151. package/src/__tests__/hooks-discovery.test.ts +0 -199
  152. package/src/__tests__/hooks-integration.test.ts +0 -189
  153. package/src/__tests__/hooks-manager.test.ts +0 -187
  154. package/src/__tests__/hooks-runner.test.ts +0 -178
  155. package/src/__tests__/hooks-settings.test.ts +0 -154
  156. package/src/__tests__/hooks-templates.test.ts +0 -137
  157. package/src/__tests__/hooks-ts-runner.test.ts +0 -125
  158. package/src/__tests__/hooks-watch.test.ts +0 -100
  159. package/src/__tests__/host-file-edit-tool.test.ts +0 -104
  160. package/src/__tests__/host-file-read-tool.test.ts +0 -61
  161. package/src/__tests__/host-file-write-tool.test.ts +0 -77
  162. package/src/__tests__/host-shell-tool.test.ts +0 -311
  163. package/src/__tests__/ingress-url-consistency.test.ts +0 -214
  164. package/src/__tests__/intent-routing.test.ts +0 -259
  165. package/src/__tests__/ipc-blob-store.test.ts +0 -315
  166. package/src/__tests__/ipc-contract-inventory.test.ts +0 -54
  167. package/src/__tests__/ipc-contract.test.ts +0 -74
  168. package/src/__tests__/ipc-protocol.test.ts +0 -113
  169. package/src/__tests__/ipc-roundtrip.benchmark.test.ts +0 -237
  170. package/src/__tests__/ipc-snapshot.test.ts +0 -1698
  171. package/src/__tests__/ipc-validate.test.ts +0 -357
  172. package/src/__tests__/key-migration.test.ts +0 -183
  173. package/src/__tests__/keychain.test.ts +0 -258
  174. package/src/__tests__/llm-usage-store.test.ts +0 -221
  175. package/src/__tests__/managed-skill-lifecycle.test.ts +0 -257
  176. package/src/__tests__/managed-store.test.ts +0 -608
  177. package/src/__tests__/media-generate-image.test.ts +0 -238
  178. package/src/__tests__/media-reuse-story.e2e.test.ts +0 -676
  179. package/src/__tests__/media-visibility-policy.test.ts +0 -141
  180. package/src/__tests__/memory-context-benchmark.benchmark.test.ts +0 -235
  181. package/src/__tests__/memory-lifecycle-e2e.test.ts +0 -481
  182. package/src/__tests__/memory-query-builder.test.ts +0 -59
  183. package/src/__tests__/memory-recall-quality.test.ts +0 -846
  184. package/src/__tests__/memory-regressions.experimental.test.ts +0 -538
  185. package/src/__tests__/memory-regressions.test.ts +0 -4336
  186. package/src/__tests__/memory-retrieval-budget.test.ts +0 -49
  187. package/src/__tests__/memory-retrieval.benchmark.test.ts +0 -430
  188. package/src/__tests__/migration-cli-flows.test.ts +0 -169
  189. package/src/__tests__/migration-ordering.test.ts +0 -249
  190. package/src/__tests__/mock-signup-server.test.ts +0 -528
  191. package/src/__tests__/oauth-callback-registry.test.ts +0 -85
  192. package/src/__tests__/oauth2-gateway-transport.test.ts +0 -285
  193. package/src/__tests__/onboarding-starter-tasks.test.ts +0 -176
  194. package/src/__tests__/onboarding-template-contract.test.ts +0 -58
  195. package/src/__tests__/openai-provider.test.ts +0 -753
  196. package/src/__tests__/parallel-tool.benchmark.test.ts +0 -294
  197. package/src/__tests__/parser.test.ts +0 -472
  198. package/src/__tests__/path-classifier.test.ts +0 -73
  199. package/src/__tests__/path-policy.test.ts +0 -435
  200. package/src/__tests__/platform-move-helper.test.ts +0 -99
  201. package/src/__tests__/platform-socket-path.test.ts +0 -52
  202. package/src/__tests__/platform-workspace-migration.test.ts +0 -1000
  203. package/src/__tests__/platform.test.ts +0 -131
  204. package/src/__tests__/playbook-tools.test.ts +0 -342
  205. package/src/__tests__/prebuilt-home-base-seed.test.ts +0 -75
  206. package/src/__tests__/pricing.test.ts +0 -256
  207. package/src/__tests__/profile-compiler.test.ts +0 -374
  208. package/src/__tests__/provider-commit-message-generator.test.ts +0 -342
  209. package/src/__tests__/provider-registry-ollama.test.ts +0 -16
  210. package/src/__tests__/provider-streaming.benchmark.test.ts +0 -773
  211. package/src/__tests__/proxy-approval-callback.test.ts +0 -601
  212. package/src/__tests__/public-ingress-urls.test.ts +0 -222
  213. package/src/__tests__/ratelimit.test.ts +0 -297
  214. package/src/__tests__/recurrence-engine-rruleset.test.ts +0 -78
  215. package/src/__tests__/recurrence-engine.test.ts +0 -69
  216. package/src/__tests__/recurrence-types.test.ts +0 -71
  217. package/src/__tests__/registry.test.ts +0 -494
  218. package/src/__tests__/relay-server.test.ts +0 -688
  219. package/src/__tests__/reminder-store.test.ts +0 -223
  220. package/src/__tests__/reminder.test.ts +0 -229
  221. package/src/__tests__/request-file-tool.test.ts +0 -158
  222. package/src/__tests__/run-orchestrator-assistant-events.test.ts +0 -222
  223. package/src/__tests__/run-orchestrator.test.ts +0 -200
  224. package/src/__tests__/runtime-attachment-metadata.test.ts +0 -189
  225. package/src/__tests__/runtime-events-sse-parity.test.ts +0 -343
  226. package/src/__tests__/runtime-events-sse.test.ts +0 -162
  227. package/src/__tests__/runtime-runs-http.test.ts +0 -433
  228. package/src/__tests__/runtime-runs.test.ts +0 -273
  229. package/src/__tests__/sandbox-diagnostics.test.ts +0 -408
  230. package/src/__tests__/sandbox-host-parity.test.ts +0 -950
  231. package/src/__tests__/scaffold-managed-skill-tool.test.ts +0 -253
  232. package/src/__tests__/schedule-store.test.ts +0 -482
  233. package/src/__tests__/schedule-tools.test.ts +0 -700
  234. package/src/__tests__/scheduler-recurrence.test.ts +0 -329
  235. package/src/__tests__/script-proxy-certs.test.ts +0 -90
  236. package/src/__tests__/script-proxy-connect-tunnel.test.ts +0 -177
  237. package/src/__tests__/script-proxy-decision-trace.test.ts +0 -156
  238. package/src/__tests__/script-proxy-http-forwarder.test.ts +0 -281
  239. package/src/__tests__/script-proxy-injection-runtime.test.ts +0 -401
  240. package/src/__tests__/script-proxy-mitm-handler.test.ts +0 -407
  241. package/src/__tests__/script-proxy-policy-runtime.test.ts +0 -287
  242. package/src/__tests__/script-proxy-policy.test.ts +0 -310
  243. package/src/__tests__/script-proxy-rewrite-specificity.test.ts +0 -135
  244. package/src/__tests__/script-proxy-router.test.ts +0 -180
  245. package/src/__tests__/script-proxy-session-manager.test.ts +0 -382
  246. package/src/__tests__/script-proxy-session-runtime.test.ts +0 -113
  247. package/src/__tests__/secret-allowlist.test.ts +0 -229
  248. package/src/__tests__/secret-ingress-handler.test.ts +0 -99
  249. package/src/__tests__/secret-onetime-send.test.ts +0 -130
  250. package/src/__tests__/secret-prompt-log-hygiene.test.ts +0 -106
  251. package/src/__tests__/secret-response-routing.test.ts +0 -93
  252. package/src/__tests__/secret-scanner-executor.test.ts +0 -348
  253. package/src/__tests__/secret-scanner.test.ts +0 -857
  254. package/src/__tests__/secure-keys.test.ts +0 -323
  255. package/src/__tests__/server-history-render.test.ts +0 -431
  256. package/src/__tests__/session-abort-tool-results.test.ts +0 -240
  257. package/src/__tests__/session-conflict-gate.test.ts +0 -700
  258. package/src/__tests__/session-error.test.ts +0 -369
  259. package/src/__tests__/session-evictor.test.ts +0 -188
  260. package/src/__tests__/session-init.benchmark.test.ts +0 -462
  261. package/src/__tests__/session-load-history-repair.test.ts +0 -222
  262. package/src/__tests__/session-pre-run-repair.test.ts +0 -213
  263. package/src/__tests__/session-profile-injection.test.ts +0 -444
  264. package/src/__tests__/session-provider-retry-repair.test.ts +0 -306
  265. package/src/__tests__/session-queue.test.ts +0 -1535
  266. package/src/__tests__/session-runtime-assembly.test.ts +0 -476
  267. package/src/__tests__/session-runtime-workspace.test.ts +0 -183
  268. package/src/__tests__/session-skill-tools.test.ts +0 -2431
  269. package/src/__tests__/session-slash-known.test.ts +0 -368
  270. package/src/__tests__/session-slash-queue.test.ts +0 -288
  271. package/src/__tests__/session-slash-unknown.test.ts +0 -271
  272. package/src/__tests__/session-surfaces-task-progress.test.ts +0 -104
  273. package/src/__tests__/session-tool-setup-app-refresh.test.ts +0 -473
  274. package/src/__tests__/session-tool-setup-memory-scope.test.ts +0 -140
  275. package/src/__tests__/session-tool-setup-side-effect-flag.test.ts +0 -140
  276. package/src/__tests__/session-undo.test.ts +0 -75
  277. package/src/__tests__/session-workspace-cache-state.test.ts +0 -246
  278. package/src/__tests__/session-workspace-injection.test.ts +0 -327
  279. package/src/__tests__/session-workspace-tool-tracking.test.ts +0 -240
  280. package/src/__tests__/shared-filesystem-errors.test.ts +0 -78
  281. package/src/__tests__/shell-credential-ref.test.ts +0 -187
  282. package/src/__tests__/shell-parser-fuzz.test.ts +0 -544
  283. package/src/__tests__/shell-parser-property.test.ts +0 -433
  284. package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -272
  285. package/src/__tests__/signup-e2e.test.ts +0 -353
  286. package/src/__tests__/size-guard.test.ts +0 -117
  287. package/src/__tests__/skill-include-graph.test.ts +0 -303
  288. package/src/__tests__/skill-load-tool.test.ts +0 -409
  289. package/src/__tests__/skill-projection.benchmark.test.ts +0 -328
  290. package/src/__tests__/skill-script-runner-host.test.ts +0 -489
  291. package/src/__tests__/skill-script-runner-sandbox.test.ts +0 -349
  292. package/src/__tests__/skill-script-runner.test.ts +0 -159
  293. package/src/__tests__/skill-tool-factory.test.ts +0 -252
  294. package/src/__tests__/skill-tool-manifest.test.ts +0 -658
  295. package/src/__tests__/skill-version-hash.test.ts +0 -182
  296. package/src/__tests__/skills.test.ts +0 -680
  297. package/src/__tests__/slash-commands-catalog.test.ts +0 -86
  298. package/src/__tests__/slash-commands-parser.test.ts +0 -119
  299. package/src/__tests__/slash-commands-resolver.test.ts +0 -193
  300. package/src/__tests__/slash-commands-rewrite.test.ts +0 -39
  301. package/src/__tests__/speaker-identification.test.ts +0 -52
  302. package/src/__tests__/starter-bundle.test.ts +0 -136
  303. package/src/__tests__/starter-task-flow.test.ts +0 -143
  304. package/src/__tests__/subagent-manager-notify.test.ts +0 -404
  305. package/src/__tests__/subagent-tools.test.ts +0 -218
  306. package/src/__tests__/subagent-types.test.ts +0 -78
  307. package/src/__tests__/swarm-orchestrator.test.ts +0 -428
  308. package/src/__tests__/swarm-plan-validator.test.ts +0 -330
  309. package/src/__tests__/swarm-recursion.test.ts +0 -165
  310. package/src/__tests__/swarm-router-planner.test.ts +0 -208
  311. package/src/__tests__/swarm-session-integration.test.ts +0 -274
  312. package/src/__tests__/swarm-tool.test.ts +0 -145
  313. package/src/__tests__/swarm-worker-backend.test.ts +0 -129
  314. package/src/__tests__/swarm-worker-runner.test.ts +0 -272
  315. package/src/__tests__/system-prompt.test.ts +0 -439
  316. package/src/__tests__/task-compiler.test.ts +0 -284
  317. package/src/__tests__/task-runner.test.ts +0 -216
  318. package/src/__tests__/task-scheduler.test.ts +0 -217
  319. package/src/__tests__/task-tools.test.ts +0 -595
  320. package/src/__tests__/terminal-sandbox-docker.test.ts +0 -1064
  321. package/src/__tests__/terminal-sandbox.integration.test.ts +0 -178
  322. package/src/__tests__/terminal-sandbox.test.ts +0 -202
  323. package/src/__tests__/test-support/browser-skill-harness.ts +0 -90
  324. package/src/__tests__/test-support/computer-use-skill-harness.ts +0 -45
  325. package/src/__tests__/tool-audit-listener.test.ts +0 -113
  326. package/src/__tests__/tool-domain-event-publisher.test.ts +0 -253
  327. package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +0 -500
  328. package/src/__tests__/tool-executor-lifecycle-events.test.ts +0 -516
  329. package/src/__tests__/tool-executor-redaction.test.ts +0 -289
  330. package/src/__tests__/tool-executor.test.ts +0 -2055
  331. package/src/__tests__/tool-metrics-listener.test.ts +0 -225
  332. package/src/__tests__/tool-notification-listener.test.ts +0 -49
  333. package/src/__tests__/tool-policy.test.ts +0 -54
  334. package/src/__tests__/tool-profiling-listener.test.ts +0 -268
  335. package/src/__tests__/tool-result-truncation.test.ts +0 -217
  336. package/src/__tests__/tool-trace-listener.test.ts +0 -226
  337. package/src/__tests__/top-level-renderer.test.ts +0 -121
  338. package/src/__tests__/top-level-scanner.test.ts +0 -141
  339. package/src/__tests__/trace-emitter.test.ts +0 -173
  340. package/src/__tests__/trust-store.test.ts +0 -2031
  341. package/src/__tests__/turn-commit.test.ts +0 -554
  342. package/src/__tests__/twilio-provider.test.ts +0 -179
  343. package/src/__tests__/twilio-routes-twiml.test.ts +0 -127
  344. package/src/__tests__/twilio-routes.test.ts +0 -822
  345. package/src/__tests__/twitter-auth-handler.test.ts +0 -666
  346. package/src/__tests__/url-safety.test.ts +0 -418
  347. package/src/__tests__/view-image-tool.test.ts +0 -217
  348. package/src/__tests__/weather-skill-regression.test.ts +0 -225
  349. package/src/__tests__/web-fetch.test.ts +0 -869
  350. package/src/__tests__/web-search.test.ts +0 -584
  351. package/src/__tests__/workspace-git-service.test.ts +0 -1153
  352. package/src/__tests__/workspace-heartbeat-service.test.ts +0 -486
  353. package/src/__tests__/workspace-lifecycle.test.ts +0 -292
  354. package/src/agent/attachments.ts +0 -35
  355. package/src/agent/loop.ts +0 -500
  356. package/src/agent/message-types.ts +0 -17
  357. package/src/agent-heartbeat/agent-heartbeat-service.ts +0 -155
  358. package/src/autonomy/autonomy-resolver.ts +0 -60
  359. package/src/autonomy/autonomy-store.ts +0 -122
  360. package/src/autonomy/disposition-mapper.ts +0 -31
  361. package/src/autonomy/index.ts +0 -11
  362. package/src/autonomy/types.ts +0 -39
  363. package/src/bundler/app-bundler.ts +0 -295
  364. package/src/bundler/bundle-scanner.ts +0 -535
  365. package/src/bundler/bundle-signer.ts +0 -124
  366. package/src/bundler/manifest.ts +0 -21
  367. package/src/bundler/signature-verifier.ts +0 -184
  368. package/src/calls/call-bridge.ts +0 -95
  369. package/src/calls/call-constants.ts +0 -48
  370. package/src/calls/call-domain.ts +0 -278
  371. package/src/calls/call-orchestrator.ts +0 -412
  372. package/src/calls/call-recovery.ts +0 -207
  373. package/src/calls/call-state-machine.ts +0 -68
  374. package/src/calls/call-state.ts +0 -87
  375. package/src/calls/call-store.ts +0 -416
  376. package/src/calls/elevenlabs-client.ts +0 -89
  377. package/src/calls/elevenlabs-config.ts +0 -29
  378. package/src/calls/relay-server.ts +0 -390
  379. package/src/calls/speaker-identification.ts +0 -213
  380. package/src/calls/twilio-config.ts +0 -45
  381. package/src/calls/twilio-provider.ts +0 -178
  382. package/src/calls/twilio-routes.ts +0 -316
  383. package/src/calls/types.ts +0 -37
  384. package/src/calls/voice-provider.ts +0 -14
  385. package/src/calls/voice-quality.ts +0 -92
  386. package/src/cli/autonomy.ts +0 -188
  387. package/src/cli/config-commands.ts +0 -334
  388. package/src/cli/contacts.ts +0 -149
  389. package/src/cli/core-commands.ts +0 -784
  390. package/src/cli/doordash.ts +0 -1055
  391. package/src/cli/email-guardrails.ts +0 -200
  392. package/src/cli/email.ts +0 -405
  393. package/src/cli/ipc-client.ts +0 -82
  394. package/src/cli/main-screen.tsx +0 -53
  395. package/src/cli/map.ts +0 -270
  396. package/src/cli/twitter.ts +0 -575
  397. package/src/cli.ts +0 -937
  398. package/src/commands/__tests__/cc-command-registry.test.ts +0 -319
  399. package/src/commands/cc-command-registry.ts +0 -209
  400. package/src/config/bundled-skills/.gitkeep +0 -0
  401. package/src/config/bundled-skills/agentmail/SKILL.md +0 -128
  402. package/src/config/bundled-skills/agentmail/icon.svg +0 -21
  403. package/src/config/bundled-skills/app-builder/SKILL.md +0 -1404
  404. package/src/config/bundled-skills/app-builder/TOOLS.json +0 -279
  405. package/src/config/bundled-skills/app-builder/icon.svg +0 -9
  406. package/src/config/bundled-skills/app-builder/tools/app-create.ts +0 -15
  407. package/src/config/bundled-skills/app-builder/tools/app-delete.ts +0 -10
  408. package/src/config/bundled-skills/app-builder/tools/app-file-edit.ts +0 -11
  409. package/src/config/bundled-skills/app-builder/tools/app-file-list.ts +0 -10
  410. package/src/config/bundled-skills/app-builder/tools/app-file-read.ts +0 -18
  411. package/src/config/bundled-skills/app-builder/tools/app-file-write.ts +0 -11
  412. package/src/config/bundled-skills/app-builder/tools/app-list.ts +0 -10
  413. package/src/config/bundled-skills/app-builder/tools/app-query.ts +0 -10
  414. package/src/config/bundled-skills/app-builder/tools/app-update.ts +0 -20
  415. package/src/config/bundled-skills/browser/SKILL.md +0 -28
  416. package/src/config/bundled-skills/browser/TOOLS.json +0 -234
  417. package/src/config/bundled-skills/browser/tools/browser-click.ts +0 -9
  418. package/src/config/bundled-skills/browser/tools/browser-close.ts +0 -9
  419. package/src/config/bundled-skills/browser/tools/browser-extract.ts +0 -9
  420. package/src/config/bundled-skills/browser/tools/browser-fill-credential.ts +0 -9
  421. package/src/config/bundled-skills/browser/tools/browser-navigate.ts +0 -9
  422. package/src/config/bundled-skills/browser/tools/browser-press-key.ts +0 -9
  423. package/src/config/bundled-skills/browser/tools/browser-screenshot.ts +0 -9
  424. package/src/config/bundled-skills/browser/tools/browser-snapshot.ts +0 -9
  425. package/src/config/bundled-skills/browser/tools/browser-type.ts +0 -9
  426. package/src/config/bundled-skills/browser/tools/browser-wait-for.ts +0 -9
  427. package/src/config/bundled-skills/claude-code/SKILL.md +0 -50
  428. package/src/config/bundled-skills/claude-code/TOOLS.json +0 -40
  429. package/src/config/bundled-skills/claude-code/tools/claude-code.ts +0 -9
  430. package/src/config/bundled-skills/computer-use/SKILL.md +0 -17
  431. package/src/config/bundled-skills/computer-use/TOOLS.json +0 -326
  432. package/src/config/bundled-skills/computer-use/tools/computer-use-click.ts +0 -9
  433. package/src/config/bundled-skills/computer-use/tools/computer-use-done.ts +0 -9
  434. package/src/config/bundled-skills/computer-use/tools/computer-use-double-click.ts +0 -9
  435. package/src/config/bundled-skills/computer-use/tools/computer-use-drag.ts +0 -9
  436. package/src/config/bundled-skills/computer-use/tools/computer-use-key.ts +0 -9
  437. package/src/config/bundled-skills/computer-use/tools/computer-use-open-app.ts +0 -9
  438. package/src/config/bundled-skills/computer-use/tools/computer-use-request-control.ts +0 -9
  439. package/src/config/bundled-skills/computer-use/tools/computer-use-respond.ts +0 -9
  440. package/src/config/bundled-skills/computer-use/tools/computer-use-right-click.ts +0 -9
  441. package/src/config/bundled-skills/computer-use/tools/computer-use-run-applescript.ts +0 -9
  442. package/src/config/bundled-skills/computer-use/tools/computer-use-scroll.ts +0 -9
  443. package/src/config/bundled-skills/computer-use/tools/computer-use-type-text.ts +0 -9
  444. package/src/config/bundled-skills/computer-use/tools/computer-use-wait.ts +0 -9
  445. package/src/config/bundled-skills/contacts/SKILL.md +0 -39
  446. package/src/config/bundled-skills/contacts/TOOLS.json +0 -122
  447. package/src/config/bundled-skills/contacts/tools/contact-merge.ts +0 -9
  448. package/src/config/bundled-skills/contacts/tools/contact-search.ts +0 -9
  449. package/src/config/bundled-skills/contacts/tools/contact-upsert.ts +0 -9
  450. package/src/config/bundled-skills/document/SKILL.md +0 -26
  451. package/src/config/bundled-skills/document/TOOLS.json +0 -53
  452. package/src/config/bundled-skills/document/tools/document-create.ts +0 -9
  453. package/src/config/bundled-skills/document/tools/document-update.ts +0 -9
  454. package/src/config/bundled-skills/doordash/SKILL.md +0 -163
  455. package/src/config/bundled-skills/followups/SKILL.md +0 -32
  456. package/src/config/bundled-skills/followups/TOOLS.json +0 -100
  457. package/src/config/bundled-skills/followups/icon.svg +0 -24
  458. package/src/config/bundled-skills/followups/tools/followup-create.ts +0 -9
  459. package/src/config/bundled-skills/followups/tools/followup-list.ts +0 -9
  460. package/src/config/bundled-skills/followups/tools/followup-resolve.ts +0 -9
  461. package/src/config/bundled-skills/google-calendar/SKILL.md +0 -51
  462. package/src/config/bundled-skills/google-calendar/TOOLS.json +0 -108
  463. package/src/config/bundled-skills/google-calendar/calendar-client.ts +0 -165
  464. package/src/config/bundled-skills/google-calendar/tools/calendar-check-availability.ts +0 -21
  465. package/src/config/bundled-skills/google-calendar/tools/calendar-create-event.ts +0 -42
  466. package/src/config/bundled-skills/google-calendar/tools/calendar-get-event.ts +0 -13
  467. package/src/config/bundled-skills/google-calendar/tools/calendar-list-events.ts +0 -30
  468. package/src/config/bundled-skills/google-calendar/tools/calendar-rsvp.ts +0 -41
  469. package/src/config/bundled-skills/google-calendar/tools/shared.ts +0 -18
  470. package/src/config/bundled-skills/google-calendar/types.ts +0 -97
  471. package/src/config/bundled-skills/image-studio/SKILL.md +0 -32
  472. package/src/config/bundled-skills/image-studio/TOOLS.json +0 -42
  473. package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +0 -115
  474. package/src/config/bundled-skills/macos-automation/SKILL.md +0 -66
  475. package/src/config/bundled-skills/messaging/SKILL.md +0 -130
  476. package/src/config/bundled-skills/messaging/TOOLS.json +0 -357
  477. package/src/config/bundled-skills/messaging/tools/gmail-archive.ts +0 -23
  478. package/src/config/bundled-skills/messaging/tools/gmail-batch-archive.ts +0 -23
  479. package/src/config/bundled-skills/messaging/tools/gmail-batch-label.ts +0 -25
  480. package/src/config/bundled-skills/messaging/tools/gmail-draft.ts +0 -26
  481. package/src/config/bundled-skills/messaging/tools/gmail-label.ts +0 -25
  482. package/src/config/bundled-skills/messaging/tools/gmail-trash.ts +0 -23
  483. package/src/config/bundled-skills/messaging/tools/gmail-unsubscribe.ts +0 -84
  484. package/src/config/bundled-skills/messaging/tools/messaging-analyze-activity.ts +0 -18
  485. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +0 -125
  486. package/src/config/bundled-skills/messaging/tools/messaging-auth-test.ts +0 -16
  487. package/src/config/bundled-skills/messaging/tools/messaging-draft.ts +0 -49
  488. package/src/config/bundled-skills/messaging/tools/messaging-list-conversations.ts +0 -21
  489. package/src/config/bundled-skills/messaging/tools/messaging-mark-read.ts +0 -25
  490. package/src/config/bundled-skills/messaging/tools/messaging-read.ts +0 -28
  491. package/src/config/bundled-skills/messaging/tools/messaging-reply.ts +0 -29
  492. package/src/config/bundled-skills/messaging/tools/messaging-search.ts +0 -22
  493. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +0 -27
  494. package/src/config/bundled-skills/messaging/tools/shared.ts +0 -71
  495. package/src/config/bundled-skills/messaging/tools/slack-add-reaction.ts +0 -25
  496. package/src/config/bundled-skills/messaging/tools/slack-leave-channel.ts +0 -23
  497. package/src/config/bundled-skills/phone-calls/SKILL.md +0 -414
  498. package/src/config/bundled-skills/playbooks/SKILL.md +0 -31
  499. package/src/config/bundled-skills/playbooks/TOOLS.json +0 -126
  500. package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +0 -9
  501. package/src/config/bundled-skills/playbooks/tools/playbook-delete.ts +0 -9
  502. package/src/config/bundled-skills/playbooks/tools/playbook-list.ts +0 -9
  503. package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +0 -9
  504. package/src/config/bundled-skills/public-ingress/SKILL.md +0 -183
  505. package/src/config/bundled-skills/reminder/SKILL.md +0 -20
  506. package/src/config/bundled-skills/reminder/TOOLS.json +0 -67
  507. package/src/config/bundled-skills/reminder/tools/reminder-cancel.ts +0 -9
  508. package/src/config/bundled-skills/reminder/tools/reminder-create.ts +0 -9
  509. package/src/config/bundled-skills/reminder/tools/reminder-list.ts +0 -9
  510. package/src/config/bundled-skills/schedule/SKILL.md +0 -74
  511. package/src/config/bundled-skills/schedule/TOOLS.json +0 -135
  512. package/src/config/bundled-skills/schedule/tools/schedule-create.ts +0 -9
  513. package/src/config/bundled-skills/schedule/tools/schedule-delete.ts +0 -9
  514. package/src/config/bundled-skills/schedule/tools/schedule-list.ts +0 -9
  515. package/src/config/bundled-skills/schedule/tools/schedule-update.ts +0 -9
  516. package/src/config/bundled-skills/self-upgrade/SKILL.md +0 -68
  517. package/src/config/bundled-skills/start-the-day/SKILL.md +0 -70
  518. package/src/config/bundled-skills/start-the-day/icon.svg +0 -13
  519. package/src/config/bundled-skills/subagent/SKILL.md +0 -25
  520. package/src/config/bundled-skills/subagent/TOOLS.json +0 -107
  521. package/src/config/bundled-skills/subagent/tools/subagent-abort.ts +0 -9
  522. package/src/config/bundled-skills/subagent/tools/subagent-message.ts +0 -9
  523. package/src/config/bundled-skills/subagent/tools/subagent-read.ts +0 -9
  524. package/src/config/bundled-skills/subagent/tools/subagent-spawn.ts +0 -9
  525. package/src/config/bundled-skills/subagent/tools/subagent-status.ts +0 -9
  526. package/src/config/bundled-skills/tasks/SKILL.md +0 -28
  527. package/src/config/bundled-skills/tasks/TOOLS.json +0 -281
  528. package/src/config/bundled-skills/tasks/tools/task-delete.ts +0 -9
  529. package/src/config/bundled-skills/tasks/tools/task-list-add.ts +0 -9
  530. package/src/config/bundled-skills/tasks/tools/task-list-remove.ts +0 -9
  531. package/src/config/bundled-skills/tasks/tools/task-list-show.ts +0 -9
  532. package/src/config/bundled-skills/tasks/tools/task-list-update.ts +0 -9
  533. package/src/config/bundled-skills/tasks/tools/task-list.ts +0 -9
  534. package/src/config/bundled-skills/tasks/tools/task-queue-run.ts +0 -9
  535. package/src/config/bundled-skills/tasks/tools/task-run.ts +0 -9
  536. package/src/config/bundled-skills/tasks/tools/task-save.ts +0 -9
  537. package/src/config/bundled-skills/transcribe/SKILL.md +0 -25
  538. package/src/config/bundled-skills/transcribe/TOOLS.json +0 -32
  539. package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +0 -370
  540. package/src/config/bundled-skills/twitter/SKILL.md +0 -134
  541. package/src/config/bundled-skills/watcher/SKILL.md +0 -27
  542. package/src/config/bundled-skills/watcher/TOOLS.json +0 -147
  543. package/src/config/bundled-skills/watcher/tools/watcher-create.ts +0 -9
  544. package/src/config/bundled-skills/watcher/tools/watcher-delete.ts +0 -9
  545. package/src/config/bundled-skills/watcher/tools/watcher-digest.ts +0 -9
  546. package/src/config/bundled-skills/watcher/tools/watcher-list.ts +0 -9
  547. package/src/config/bundled-skills/watcher/tools/watcher-update.ts +0 -9
  548. package/src/config/bundled-skills/weather/SKILL.md +0 -37
  549. package/src/config/bundled-skills/weather/TOOLS.json +0 -32
  550. package/src/config/bundled-skills/weather/icon.svg +0 -24
  551. package/src/config/bundled-skills/weather/tools/get-weather.ts +0 -9
  552. package/src/config/computer-use-prompt.ts +0 -97
  553. package/src/config/defaults.ts +0 -252
  554. package/src/config/loader.ts +0 -339
  555. package/src/config/schema.ts +0 -1356
  556. package/src/config/skill-state.ts +0 -95
  557. package/src/config/skills.ts +0 -972
  558. package/src/config/system-prompt.ts +0 -675
  559. package/src/config/templates/BOOTSTRAP.md +0 -70
  560. package/src/config/templates/IDENTITY.md +0 -25
  561. package/src/config/templates/LOOKS.md +0 -25
  562. package/src/config/templates/SOUL.md +0 -37
  563. package/src/config/templates/USER.md +0 -19
  564. package/src/config/types.ts +0 -40
  565. package/src/config/vellum-skills/deploy-fullstack-vercel/SKILL.md +0 -179
  566. package/src/config/vellum-skills/document-writer/SKILL.md +0 -195
  567. package/src/config/vellum-skills/google-oauth-setup/SKILL.md +0 -199
  568. package/src/config/vellum-skills/slack-oauth-setup/SKILL.md +0 -153
  569. package/src/config/vellum-skills/telegram-setup/SKILL.md +0 -102
  570. package/src/contacts/contact-store.ts +0 -410
  571. package/src/contacts/index.ts +0 -11
  572. package/src/contacts/types.ts +0 -28
  573. package/src/context/token-estimator.ts +0 -108
  574. package/src/context/tool-result-truncation.ts +0 -128
  575. package/src/context/window-manager.ts +0 -531
  576. package/src/daemon/assistant-attachments.ts +0 -689
  577. package/src/daemon/classifier.ts +0 -110
  578. package/src/daemon/computer-use-session.ts +0 -903
  579. package/src/daemon/connection-policy.ts +0 -41
  580. package/src/daemon/date-context.ts +0 -136
  581. package/src/daemon/handlers/apps.ts +0 -461
  582. package/src/daemon/handlers/browser.ts +0 -54
  583. package/src/daemon/handlers/computer-use.ts +0 -187
  584. package/src/daemon/handlers/config.ts +0 -707
  585. package/src/daemon/handlers/diagnostics.ts +0 -338
  586. package/src/daemon/handlers/documents.ts +0 -173
  587. package/src/daemon/handlers/home-base.ts +0 -78
  588. package/src/daemon/handlers/identity.ts +0 -127
  589. package/src/daemon/handlers/index.ts +0 -128
  590. package/src/daemon/handlers/misc.ts +0 -331
  591. package/src/daemon/handlers/open-bundle-handler.ts +0 -80
  592. package/src/daemon/handlers/publish.ts +0 -187
  593. package/src/daemon/handlers/sessions.ts +0 -539
  594. package/src/daemon/handlers/shared.ts +0 -569
  595. package/src/daemon/handlers/signing.ts +0 -37
  596. package/src/daemon/handlers/skills.ts +0 -501
  597. package/src/daemon/handlers/subagents.ts +0 -210
  598. package/src/daemon/handlers/twitter-auth.ts +0 -198
  599. package/src/daemon/handlers/work-items.ts +0 -632
  600. package/src/daemon/handlers/workspace-files.ts +0 -75
  601. package/src/daemon/handlers.ts +0 -17
  602. package/src/daemon/history-repair.ts +0 -214
  603. package/src/daemon/ipc-blob-store.ts +0 -231
  604. package/src/daemon/ipc-contract-inventory.json +0 -463
  605. package/src/daemon/ipc-contract-inventory.ts +0 -126
  606. package/src/daemon/ipc-contract.ts +0 -2352
  607. package/src/daemon/ipc-protocol.ts +0 -75
  608. package/src/daemon/ipc-validate.ts +0 -171
  609. package/src/daemon/lifecycle.ts +0 -580
  610. package/src/daemon/main.ts +0 -21
  611. package/src/daemon/media-visibility-policy.ts +0 -57
  612. package/src/daemon/ride-shotgun-handler.ts +0 -309
  613. package/src/daemon/server.ts +0 -1207
  614. package/src/daemon/session-agent-loop.ts +0 -922
  615. package/src/daemon/session-attachments.ts +0 -196
  616. package/src/daemon/session-conflict-gate.ts +0 -128
  617. package/src/daemon/session-dynamic-profile.ts +0 -63
  618. package/src/daemon/session-error.ts +0 -290
  619. package/src/daemon/session-evictor.ts +0 -196
  620. package/src/daemon/session-history.ts +0 -437
  621. package/src/daemon/session-lifecycle.ts +0 -147
  622. package/src/daemon/session-media-retry.ts +0 -147
  623. package/src/daemon/session-memory.ts +0 -212
  624. package/src/daemon/session-messaging.ts +0 -145
  625. package/src/daemon/session-notifiers.ts +0 -193
  626. package/src/daemon/session-process.ts +0 -264
  627. package/src/daemon/session-queue-manager.ts +0 -82
  628. package/src/daemon/session-runtime-assembly.ts +0 -447
  629. package/src/daemon/session-skill-tools.ts +0 -356
  630. package/src/daemon/session-slash.ts +0 -305
  631. package/src/daemon/session-surfaces.ts +0 -702
  632. package/src/daemon/session-tool-setup.ts +0 -524
  633. package/src/daemon/session-usage.ts +0 -72
  634. package/src/daemon/session-workspace.ts +0 -19
  635. package/src/daemon/session.ts +0 -400
  636. package/src/daemon/trace-emitter.ts +0 -82
  637. package/src/daemon/video-thumbnail.ts +0 -60
  638. package/src/daemon/watch-handler.ts +0 -274
  639. package/src/doordash/client.ts +0 -999
  640. package/src/doordash/queries.ts +0 -1311
  641. package/src/doordash/query-extractor.ts +0 -93
  642. package/src/doordash/session.ts +0 -82
  643. package/src/email/provider.ts +0 -117
  644. package/src/email/providers/agentmail.ts +0 -317
  645. package/src/email/providers/index.ts +0 -58
  646. package/src/email/service.ts +0 -303
  647. package/src/email/types.ts +0 -126
  648. package/src/events/bus.ts +0 -157
  649. package/src/events/domain-events.ts +0 -83
  650. package/src/events/index.ts +0 -18
  651. package/src/events/tool-audit-listener.ts +0 -80
  652. package/src/events/tool-domain-event-publisher.ts +0 -111
  653. package/src/events/tool-metrics-listener.ts +0 -159
  654. package/src/events/tool-notification-listener.ts +0 -17
  655. package/src/events/tool-profiling-listener.ts +0 -158
  656. package/src/events/tool-trace-listener.ts +0 -75
  657. package/src/export/formatter.ts +0 -98
  658. package/src/followups/followup-store.ts +0 -168
  659. package/src/followups/index.ts +0 -10
  660. package/src/followups/types.ts +0 -29
  661. package/src/gallery/default-gallery.ts +0 -795
  662. package/src/gallery/gallery-manifest.ts +0 -24
  663. package/src/home-base/app-link-store.ts +0 -82
  664. package/src/home-base/bootstrap.ts +0 -68
  665. package/src/home-base/prebuilt/index.html +0 -662
  666. package/src/home-base/prebuilt/seed-metadata.json +0 -21
  667. package/src/home-base/prebuilt/seed.ts +0 -112
  668. package/src/home-base/prebuilt-home-base-updater.ts +0 -30
  669. package/src/hooks/cli.ts +0 -163
  670. package/src/hooks/config.ts +0 -88
  671. package/src/hooks/discovery.ts +0 -110
  672. package/src/hooks/manager.ts +0 -128
  673. package/src/hooks/runner.ts +0 -123
  674. package/src/hooks/templates.ts +0 -52
  675. package/src/hooks/types.ts +0 -72
  676. package/src/inbound/public-ingress-urls.ts +0 -123
  677. package/src/index.ts +0 -75
  678. package/src/instrument.ts +0 -60
  679. package/src/logfire.ts +0 -99
  680. package/src/media/gemini-image-service.ts +0 -136
  681. package/src/memory/account-store.ts +0 -108
  682. package/src/memory/admin.ts +0 -211
  683. package/src/memory/app-store.ts +0 -556
  684. package/src/memory/attachments-store.ts +0 -397
  685. package/src/memory/channel-delivery-store.ts +0 -353
  686. package/src/memory/checkpoints.ts +0 -52
  687. package/src/memory/clarification-resolver.ts +0 -298
  688. package/src/memory/conflict-intent.ts +0 -114
  689. package/src/memory/conflict-store.ts +0 -342
  690. package/src/memory/contradiction-checker.ts +0 -330
  691. package/src/memory/conversation-key-store.ts +0 -107
  692. package/src/memory/conversation-store.ts +0 -470
  693. package/src/memory/db.ts +0 -1825
  694. package/src/memory/embedding-backend.ts +0 -229
  695. package/src/memory/embedding-gemini.ts +0 -52
  696. package/src/memory/embedding-local.ts +0 -75
  697. package/src/memory/embedding-ollama.ts +0 -55
  698. package/src/memory/embedding-openai.ts +0 -25
  699. package/src/memory/entity-extractor.ts +0 -474
  700. package/src/memory/fingerprint.ts +0 -20
  701. package/src/memory/indexer.ts +0 -156
  702. package/src/memory/items-extractor.ts +0 -461
  703. package/src/memory/job-handlers/backfill.ts +0 -139
  704. package/src/memory/job-handlers/cleanup.ts +0 -58
  705. package/src/memory/job-handlers/conflict.ts +0 -121
  706. package/src/memory/job-handlers/embedding.ts +0 -61
  707. package/src/memory/job-handlers/extraction.ts +0 -123
  708. package/src/memory/job-handlers/index-maintenance.ts +0 -54
  709. package/src/memory/job-handlers/summarization.ts +0 -286
  710. package/src/memory/job-utils.ts +0 -170
  711. package/src/memory/jobs-store.ts +0 -401
  712. package/src/memory/jobs-worker.ts +0 -274
  713. package/src/memory/llm-request-log-store.ts +0 -45
  714. package/src/memory/llm-usage-store.ts +0 -60
  715. package/src/memory/message-content.ts +0 -54
  716. package/src/memory/profile-compiler.ts +0 -160
  717. package/src/memory/published-pages-store.ts +0 -137
  718. package/src/memory/qdrant-client.ts +0 -366
  719. package/src/memory/qdrant-manager.ts +0 -242
  720. package/src/memory/query-builder.ts +0 -45
  721. package/src/memory/retrieval-budget.ts +0 -30
  722. package/src/memory/retriever.ts +0 -653
  723. package/src/memory/runs-store.ts +0 -255
  724. package/src/memory/schema.ts +0 -588
  725. package/src/memory/search/entity.ts +0 -298
  726. package/src/memory/search/formatting.ts +0 -207
  727. package/src/memory/search/lexical.ts +0 -227
  728. package/src/memory/search/ranking.ts +0 -401
  729. package/src/memory/search/semantic.ts +0 -121
  730. package/src/memory/search/types.ts +0 -137
  731. package/src/memory/segmenter.ts +0 -68
  732. package/src/memory/shared-app-links-store.ts +0 -138
  733. package/src/memory/tool-usage-store.ts +0 -62
  734. package/src/messaging/activity-analyzer.ts +0 -76
  735. package/src/messaging/draft-store.ts +0 -88
  736. package/src/messaging/index.ts +0 -3
  737. package/src/messaging/provider-types.ts +0 -80
  738. package/src/messaging/provider.ts +0 -43
  739. package/src/messaging/providers/gmail/adapter.ts +0 -193
  740. package/src/messaging/providers/gmail/client.ts +0 -204
  741. package/src/messaging/providers/gmail/types.ts +0 -90
  742. package/src/messaging/providers/slack/adapter.ts +0 -202
  743. package/src/messaging/providers/slack/client.ts +0 -198
  744. package/src/messaging/providers/slack/types.ts +0 -119
  745. package/src/messaging/registry.ts +0 -34
  746. package/src/messaging/style-analyzer.ts +0 -159
  747. package/src/messaging/thread-summarizer.ts +0 -306
  748. package/src/messaging/triage-engine.ts +0 -323
  749. package/src/messaging/types.ts +0 -55
  750. package/src/permissions/checker.ts +0 -636
  751. package/src/permissions/defaults.ts +0 -254
  752. package/src/permissions/prompter.ts +0 -102
  753. package/src/permissions/secret-prompter.ts +0 -114
  754. package/src/permissions/trust-store.ts +0 -584
  755. package/src/permissions/types.ts +0 -62
  756. package/src/playbooks/index.ts +0 -2
  757. package/src/playbooks/playbook-compiler.ts +0 -90
  758. package/src/playbooks/types.ts +0 -55
  759. package/src/providers/anthropic/client.ts +0 -751
  760. package/src/providers/failover.ts +0 -129
  761. package/src/providers/fireworks/client.ts +0 -20
  762. package/src/providers/gemini/client.ts +0 -285
  763. package/src/providers/ollama/client.ts +0 -30
  764. package/src/providers/openai/client.ts +0 -337
  765. package/src/providers/openrouter/client.ts +0 -20
  766. package/src/providers/ratelimit.ts +0 -93
  767. package/src/providers/registry.ts +0 -146
  768. package/src/providers/retry.ts +0 -106
  769. package/src/providers/stream-timeout.ts +0 -38
  770. package/src/providers/types.ts +0 -109
  771. package/src/runtime/assistant-event-hub.ts +0 -120
  772. package/src/runtime/assistant-event.ts +0 -82
  773. package/src/runtime/gateway-client.ts +0 -42
  774. package/src/runtime/http-server.ts +0 -1056
  775. package/src/runtime/http-types.ts +0 -66
  776. package/src/runtime/routes/app-routes.ts +0 -174
  777. package/src/runtime/routes/attachment-routes.ts +0 -133
  778. package/src/runtime/routes/call-routes.ts +0 -140
  779. package/src/runtime/routes/channel-routes.ts +0 -382
  780. package/src/runtime/routes/conversation-routes.ts +0 -352
  781. package/src/runtime/routes/events-routes.ts +0 -79
  782. package/src/runtime/routes/run-routes.ts +0 -262
  783. package/src/runtime/routes/secret-routes.ts +0 -76
  784. package/src/runtime/run-orchestrator.ts +0 -296
  785. package/src/schedule/recurrence-engine.ts +0 -138
  786. package/src/schedule/recurrence-types.ts +0 -67
  787. package/src/schedule/schedule-store.ts +0 -497
  788. package/src/schedule/scheduler.ts +0 -171
  789. package/src/security/encrypted-store.ts +0 -238
  790. package/src/security/keychain.ts +0 -252
  791. package/src/security/oauth-callback-registry.ts +0 -66
  792. package/src/security/oauth2.ts +0 -274
  793. package/src/security/redaction.ts +0 -89
  794. package/src/security/secret-allowlist.ts +0 -164
  795. package/src/security/secret-ingress.ts +0 -57
  796. package/src/security/secret-scanner.ts +0 -543
  797. package/src/security/secure-keys.ts +0 -180
  798. package/src/security/token-manager.ts +0 -141
  799. package/src/services/published-app-updater.ts +0 -69
  800. package/src/services/vercel-deploy.ts +0 -73
  801. package/src/skills/active-skill-tools.ts +0 -81
  802. package/src/skills/clawhub.ts +0 -414
  803. package/src/skills/include-graph.ts +0 -146
  804. package/src/skills/managed-store.ts +0 -233
  805. package/src/skills/path-classifier.ts +0 -128
  806. package/src/skills/slash-commands.ts +0 -174
  807. package/src/skills/tool-manifest.ts +0 -165
  808. package/src/skills/version-hash.ts +0 -110
  809. package/src/slack/slack-webhook.ts +0 -61
  810. package/src/subagent/index.ts +0 -19
  811. package/src/subagent/manager.ts +0 -511
  812. package/src/subagent/types.ts +0 -69
  813. package/src/swarm/backend-claude-code.ts +0 -145
  814. package/src/swarm/index.ts +0 -44
  815. package/src/swarm/limits.ts +0 -37
  816. package/src/swarm/orchestrator.ts +0 -279
  817. package/src/swarm/plan-validator.ts +0 -151
  818. package/src/swarm/router-planner.ts +0 -100
  819. package/src/swarm/router-prompts.ts +0 -36
  820. package/src/swarm/synthesizer.ts +0 -62
  821. package/src/swarm/types.ts +0 -62
  822. package/src/swarm/worker-backend.ts +0 -121
  823. package/src/swarm/worker-prompts.ts +0 -79
  824. package/src/swarm/worker-runner.ts +0 -164
  825. package/src/tasks/SPEC.md +0 -139
  826. package/src/tasks/candidate-store.ts +0 -86
  827. package/src/tasks/ephemeral-permissions.ts +0 -50
  828. package/src/tasks/task-compiler.ts +0 -199
  829. package/src/tasks/task-runner.ts +0 -90
  830. package/src/tasks/task-scheduler.ts +0 -20
  831. package/src/tasks/task-store.ts +0 -127
  832. package/src/tasks/tool-sanitizer.ts +0 -36
  833. package/src/tools/apps/definitions.ts +0 -59
  834. package/src/tools/apps/executors.ts +0 -313
  835. package/src/tools/apps/open-proxy.ts +0 -43
  836. package/src/tools/apps/registry.ts +0 -16
  837. package/src/tools/assets/materialize.ts +0 -218
  838. package/src/tools/assets/search.ts +0 -361
  839. package/src/tools/browser/__tests__/auth-cache.test.ts +0 -219
  840. package/src/tools/browser/__tests__/auth-detector.test.ts +0 -362
  841. package/src/tools/browser/__tests__/jit-auth.test.ts +0 -189
  842. package/src/tools/browser/api-map.ts +0 -293
  843. package/src/tools/browser/auth-cache.ts +0 -149
  844. package/src/tools/browser/auth-detector.ts +0 -347
  845. package/src/tools/browser/auto-navigate.ts +0 -270
  846. package/src/tools/browser/browser-execution.ts +0 -980
  847. package/src/tools/browser/browser-handoff.ts +0 -79
  848. package/src/tools/browser/browser-manager.ts +0 -715
  849. package/src/tools/browser/browser-screencast.ts +0 -217
  850. package/src/tools/browser/headless-browser.ts +0 -450
  851. package/src/tools/browser/jit-auth.ts +0 -51
  852. package/src/tools/browser/network-recorder.ts +0 -349
  853. package/src/tools/browser/network-recording-types.ts +0 -49
  854. package/src/tools/browser/recording-store.ts +0 -49
  855. package/src/tools/browser/runtime-check.ts +0 -43
  856. package/src/tools/browser/x-auto-navigate.ts +0 -207
  857. package/src/tools/calls/call-end.ts +0 -67
  858. package/src/tools/calls/call-start.ts +0 -73
  859. package/src/tools/calls/call-status.ts +0 -81
  860. package/src/tools/claude-code/claude-code.ts +0 -428
  861. package/src/tools/computer-use/definitions.ts +0 -443
  862. package/src/tools/computer-use/registry.ts +0 -22
  863. package/src/tools/computer-use/request-computer-control.ts +0 -53
  864. package/src/tools/computer-use/skill-proxy-bridge.ts +0 -28
  865. package/src/tools/contacts/contact-merge.ts +0 -55
  866. package/src/tools/contacts/contact-search.ts +0 -58
  867. package/src/tools/contacts/contact-upsert.ts +0 -64
  868. package/src/tools/credentials/account-registry.ts +0 -127
  869. package/src/tools/credentials/broker-types.ts +0 -107
  870. package/src/tools/credentials/broker.ts +0 -372
  871. package/src/tools/credentials/domain-policy.ts +0 -51
  872. package/src/tools/credentials/host-pattern-match.ts +0 -60
  873. package/src/tools/credentials/metadata-store.ts +0 -335
  874. package/src/tools/credentials/policy-types.ts +0 -52
  875. package/src/tools/credentials/policy-validate.ts +0 -80
  876. package/src/tools/credentials/resolve.ts +0 -122
  877. package/src/tools/credentials/selection.ts +0 -159
  878. package/src/tools/credentials/tool-policy.ts +0 -25
  879. package/src/tools/credentials/vault.ts +0 -657
  880. package/src/tools/document/document-tool.ts +0 -92
  881. package/src/tools/document/editor-template.ts +0 -237
  882. package/src/tools/executor.ts +0 -944
  883. package/src/tools/filesystem/edit.ts +0 -127
  884. package/src/tools/filesystem/fuzzy-match.ts +0 -202
  885. package/src/tools/filesystem/read.ts +0 -71
  886. package/src/tools/filesystem/view-image.ts +0 -199
  887. package/src/tools/filesystem/write.ts +0 -79
  888. package/src/tools/followups/followup_create.ts +0 -76
  889. package/src/tools/followups/followup_list.ts +0 -60
  890. package/src/tools/followups/followup_resolve.ts +0 -56
  891. package/src/tools/host-filesystem/edit.ts +0 -125
  892. package/src/tools/host-filesystem/read.ts +0 -80
  893. package/src/tools/host-filesystem/write.ts +0 -76
  894. package/src/tools/host-terminal/cli-discover.ts +0 -180
  895. package/src/tools/host-terminal/host-shell.ts +0 -191
  896. package/src/tools/memory/definitions.ts +0 -69
  897. package/src/tools/memory/handlers.ts +0 -246
  898. package/src/tools/memory/register.ts +0 -66
  899. package/src/tools/network/__tests__/web-search.test.ts +0 -427
  900. package/src/tools/network/domain-normalize.ts +0 -85
  901. package/src/tools/network/script-proxy/__tests__/logging.test.ts +0 -248
  902. package/src/tools/network/script-proxy/__tests__/policy.test.ts +0 -234
  903. package/src/tools/network/script-proxy/__tests__/router.test.ts +0 -76
  904. package/src/tools/network/script-proxy/certs.ts +0 -237
  905. package/src/tools/network/script-proxy/connect-tunnel.ts +0 -82
  906. package/src/tools/network/script-proxy/http-forwarder.ts +0 -151
  907. package/src/tools/network/script-proxy/index.ts +0 -28
  908. package/src/tools/network/script-proxy/logging.ts +0 -196
  909. package/src/tools/network/script-proxy/mitm-handler.ts +0 -269
  910. package/src/tools/network/script-proxy/policy.ts +0 -152
  911. package/src/tools/network/script-proxy/router.ts +0 -60
  912. package/src/tools/network/script-proxy/server.ts +0 -136
  913. package/src/tools/network/script-proxy/session-manager.ts +0 -534
  914. package/src/tools/network/script-proxy/types.ts +0 -125
  915. package/src/tools/network/url-safety.ts +0 -227
  916. package/src/tools/network/web-fetch.ts +0 -713
  917. package/src/tools/network/web-search.ts +0 -319
  918. package/src/tools/playbooks/index.ts +0 -4
  919. package/src/tools/playbooks/playbook-create.ts +0 -96
  920. package/src/tools/playbooks/playbook-delete.ts +0 -52
  921. package/src/tools/playbooks/playbook-list.ts +0 -74
  922. package/src/tools/playbooks/playbook-update.ts +0 -111
  923. package/src/tools/registry.ts +0 -295
  924. package/src/tools/reminder/reminder-store.ts +0 -148
  925. package/src/tools/reminder/reminder.ts +0 -80
  926. package/src/tools/schedule/create.ts +0 -81
  927. package/src/tools/schedule/delete.ts +0 -28
  928. package/src/tools/schedule/list.ts +0 -69
  929. package/src/tools/schedule/update.ts +0 -90
  930. package/src/tools/shared/filesystem/edit-engine.ts +0 -56
  931. package/src/tools/shared/filesystem/errors.ts +0 -85
  932. package/src/tools/shared/filesystem/file-ops-service.ts +0 -215
  933. package/src/tools/shared/filesystem/format-diff.ts +0 -35
  934. package/src/tools/shared/filesystem/path-policy.ts +0 -125
  935. package/src/tools/shared/filesystem/size-guard.ts +0 -41
  936. package/src/tools/shared/filesystem/types.ts +0 -80
  937. package/src/tools/shared/shell-output.ts +0 -52
  938. package/src/tools/skills/delete-managed.ts +0 -60
  939. package/src/tools/skills/load.ts +0 -139
  940. package/src/tools/skills/sandbox-runner.ts +0 -279
  941. package/src/tools/skills/scaffold-managed.ts +0 -150
  942. package/src/tools/skills/script-contract.ts +0 -6
  943. package/src/tools/skills/skill-script-runner.ts +0 -86
  944. package/src/tools/skills/skill-tool-factory.ts +0 -64
  945. package/src/tools/skills/vellum-catalog.ts +0 -217
  946. package/src/tools/subagent/abort.ts +0 -33
  947. package/src/tools/subagent/message.ts +0 -39
  948. package/src/tools/subagent/read.ts +0 -67
  949. package/src/tools/subagent/spawn.ts +0 -46
  950. package/src/tools/subagent/status.ts +0 -45
  951. package/src/tools/swarm/delegate.ts +0 -183
  952. package/src/tools/system/request-permission.ts +0 -98
  953. package/src/tools/system/version.ts +0 -43
  954. package/src/tools/tasks/index.ts +0 -27
  955. package/src/tools/tasks/task-delete.ts +0 -82
  956. package/src/tools/tasks/task-list.ts +0 -44
  957. package/src/tools/tasks/task-run.ts +0 -97
  958. package/src/tools/tasks/task-save.ts +0 -47
  959. package/src/tools/tasks/work-item-enqueue.ts +0 -234
  960. package/src/tools/tasks/work-item-list.ts +0 -55
  961. package/src/tools/tasks/work-item-remove.ts +0 -60
  962. package/src/tools/tasks/work-item-run.ts +0 -78
  963. package/src/tools/tasks/work-item-update.ts +0 -114
  964. package/src/tools/terminal/backends/docker.ts +0 -372
  965. package/src/tools/terminal/backends/native.ts +0 -190
  966. package/src/tools/terminal/backends/types.ts +0 -26
  967. package/src/tools/terminal/evaluate-typescript.ts +0 -275
  968. package/src/tools/terminal/parser.ts +0 -415
  969. package/src/tools/terminal/safe-env.ts +0 -37
  970. package/src/tools/terminal/sandbox-diagnostics.ts +0 -149
  971. package/src/tools/terminal/sandbox.ts +0 -44
  972. package/src/tools/terminal/shell.ts +0 -257
  973. package/src/tools/tool-manifest.ts +0 -198
  974. package/src/tools/types.ts +0 -183
  975. package/src/tools/ui-surface/definitions.ts +0 -244
  976. package/src/tools/ui-surface/registry.ts +0 -14
  977. package/src/tools/watch/screen-watch.ts +0 -130
  978. package/src/tools/watch/watch-state.ts +0 -119
  979. package/src/tools/watcher/create.ts +0 -64
  980. package/src/tools/watcher/delete.ts +0 -27
  981. package/src/tools/watcher/digest.ts +0 -50
  982. package/src/tools/watcher/list.ts +0 -60
  983. package/src/tools/watcher/update.ts +0 -56
  984. package/src/tools/weather/service.ts +0 -551
  985. package/src/twitter/client.ts +0 -690
  986. package/src/twitter/session.ts +0 -91
  987. package/src/usage/actors.ts +0 -24
  988. package/src/usage/types.ts +0 -37
  989. package/src/util/clipboard.ts +0 -33
  990. package/src/util/content-id.ts +0 -16
  991. package/src/util/diff.ts +0 -181
  992. package/src/util/errors.ts +0 -129
  993. package/src/util/logger.ts +0 -243
  994. package/src/util/platform.ts +0 -607
  995. package/src/util/pricing.ts +0 -150
  996. package/src/util/spinner.ts +0 -51
  997. package/src/util/time.ts +0 -16
  998. package/src/util/truncate.ts +0 -6
  999. package/src/util/xml.ts +0 -4
  1000. package/src/version.ts +0 -3
  1001. package/src/watcher/constants.ts +0 -11
  1002. package/src/watcher/engine.ts +0 -199
  1003. package/src/watcher/provider-registry.ts +0 -15
  1004. package/src/watcher/provider-types.ts +0 -48
  1005. package/src/watcher/providers/gmail.ts +0 -198
  1006. package/src/watcher/providers/google-calendar.ts +0 -228
  1007. package/src/watcher/providers/slack.ts +0 -129
  1008. package/src/watcher/watcher-store.ts +0 -419
  1009. package/src/work-items/work-item-runner.ts +0 -171
  1010. package/src/work-items/work-item-store.ts +0 -325
  1011. package/src/workspace/commit-message-enrichment-service.ts +0 -284
  1012. package/src/workspace/commit-message-provider.ts +0 -95
  1013. package/src/workspace/git-service.ts +0 -840
  1014. package/src/workspace/heartbeat-service.ts +0 -345
  1015. package/src/workspace/provider-commit-message-generator.ts +0 -285
  1016. package/src/workspace/top-level-renderer.ts +0 -19
  1017. package/src/workspace/top-level-scanner.ts +0 -41
  1018. package/src/workspace/turn-commit.ts +0 -175
  1019. package/tsconfig.json +0 -21
@@ -1,1535 +0,0 @@
1
- import { describe, expect, mock, test, beforeEach, afterAll } from 'bun:test';
2
- import { rmSync, writeFileSync } from 'node:fs';
3
- import type { Message, ProviderResponse } from '../providers/types.js';
4
- import type { AgentEvent, CheckpointInfo, CheckpointDecision } from '../agent/loop.js';
5
- import type { ServerMessage } from '../daemon/ipc-protocol.js';
6
-
7
- // ---------------------------------------------------------------------------
8
- // Mocks — must precede the Session import so Bun applies them at load time.
9
- // ---------------------------------------------------------------------------
10
-
11
- function makeLoggerStub(): Record<string, unknown> {
12
- const stub: Record<string, unknown> = {};
13
- for (const m of ['info', 'warn', 'error', 'debug', 'trace', 'fatal', 'silent', 'child']) {
14
- stub[m] = m === 'child' ? () => makeLoggerStub() : () => {};
15
- }
16
- return stub;
17
- }
18
-
19
- mock.module('../util/logger.js', () => ({
20
- getLogger: () => makeLoggerStub(),
21
- }));
22
-
23
- mock.module('../util/platform.js', () => ({
24
- getSocketPath: () => '/tmp/test.sock',
25
- getDataDir: () => '/tmp',
26
- }));
27
-
28
- mock.module('../providers/registry.js', () => ({
29
- getProvider: () => ({ name: 'mock-provider' }),
30
- initializeProviders: () => {},
31
- }));
32
-
33
- mock.module('../config/loader.js', () => ({
34
- getConfig: () => ({
35
- provider: 'mock-provider',
36
- maxTokens: 4096,
37
- thinking: false,
38
- contextWindow: {
39
- maxInputTokens: 100000,
40
- thresholdTokens: 80000,
41
- preserveRecentMessages: 6,
42
- summaryModel: 'mock-model',
43
- maxSummaryTokens: 512,
44
- },
45
- rateLimit: { maxRequestsPerMinute: 0, maxTokensPerSession: 0 },
46
- timeouts: { permissionTimeoutSec: 1 },
47
- apiKeys: {},
48
- skills: { entries: {}, allowBundled: true },
49
- memory: { retrieval: { injectionStrategy: 'inline' } },
50
- permissions: { mode: 'legacy' },
51
- }),
52
- loadRawConfig: () => ({}),
53
- saveRawConfig: () => {},
54
- invalidateConfigCache: () => {},
55
- }));
56
-
57
- mock.module('../config/system-prompt.js', () => ({
58
- buildSystemPrompt: () => 'system prompt',
59
- }));
60
-
61
- mock.module('../config/skills.js', () => ({
62
- loadSkillCatalog: () => [],
63
- loadSkillBySelector: () => ({ skill: null }),
64
- ensureSkillIcon: async () => null,
65
- }));
66
-
67
- mock.module('../config/skill-state.js', () => ({
68
- resolveSkillStates: () => [],
69
- }));
70
-
71
- mock.module('../skills/slash-commands.js', () => ({
72
- buildInvocableSlashCatalog: () => new Map(),
73
- resolveSlashSkillCommand: () => ({ kind: 'not_slash' }),
74
- rewriteKnownSlashCommandPrompt: () => '',
75
- parseSlashCandidate: () => ({ kind: 'not_slash' }),
76
- }));
77
-
78
- mock.module('../permissions/trust-store.js', () => ({
79
- addRule: () => {},
80
- findHighestPriorityRule: () => null,
81
- clearCache: () => {},
82
- }));
83
-
84
- mock.module('../security/secret-allowlist.js', () => ({
85
- resetAllowlist: () => {},
86
- }));
87
-
88
- mock.module('../memory/admin.js', () => ({
89
- getMemoryConflictAndCleanupStats: () => ({
90
- conflicts: { pending: 0, resolved: 0, oldestPendingAgeMs: null },
91
- cleanup: { resolvedBacklog: 0, supersededBacklog: 0, resolvedCompleted24h: 0, supersededCompleted24h: 0 },
92
- }),
93
- }));
94
-
95
- mock.module('../memory/conversation-store.js', () => ({
96
- getMessages: () => [],
97
- getConversation: () => ({
98
- id: 'conv-1',
99
- contextSummary: null,
100
- contextCompactedMessageCount: 0,
101
- totalInputTokens: 0,
102
- totalOutputTokens: 0,
103
- totalEstimatedCost: 0,
104
- }),
105
- createConversation: () => ({ id: 'conv-1' }),
106
- listConversations: () => [],
107
- addMessage: (_convId: string, _role: string, _content: string) => {
108
- return { id: `msg-${Date.now()}` };
109
- },
110
- updateConversationUsage: () => {},
111
- updateConversationTitle: () => {},
112
- }));
113
-
114
- let linkAttachmentShouldThrow = false;
115
-
116
- mock.module('../memory/attachments-store.js', () => ({
117
- uploadAttachment: () => ({ id: `att-${Date.now()}` }),
118
- linkAttachmentToMessage: () => {
119
- if (linkAttachmentShouldThrow) {
120
- throw new Error('Simulated linkAttachmentToMessage failure');
121
- }
122
- },
123
- }));
124
-
125
- mock.module('../memory/retriever.js', () => ({
126
- buildMemoryRecall: async () => ({
127
- enabled: false,
128
- degraded: false,
129
- injectedText: '',
130
- lexicalHits: 0,
131
- semanticHits: 0,
132
- recencyHits: 0,
133
- injectedTokens: 0,
134
- latencyMs: 0,
135
- }),
136
- injectMemoryRecallIntoUserMessage: (msg: Message) => msg,
137
- stripMemoryRecallMessages: (msgs: Message[]) => msgs,
138
- }));
139
-
140
- mock.module('../context/window-manager.js', () => ({
141
- ContextWindowManager: class {
142
- constructor() {}
143
- async maybeCompact() { return { compacted: false }; }
144
- },
145
- createContextSummaryMessage: () => ({ role: 'user', content: [{ type: 'text', text: 'summary' }] }),
146
- getSummaryFromContextMessage: () => null,
147
- }));
148
-
149
- // ---------------------------------------------------------------------------
150
- // Workspace/git turn-commit test hooks.
151
- // ---------------------------------------------------------------------------
152
-
153
- const turnCommitCalls: Array<{ workspaceDir: string; sessionId: string; turnNumber: number }> = [];
154
- let turnCommitHangForever = false;
155
-
156
- // ---------------------------------------------------------------------------
157
- // Usage event capture for request-ID correlation tests.
158
- // ---------------------------------------------------------------------------
159
-
160
- interface CapturedUsageEvent {
161
- requestId: string | null;
162
- actor: string;
163
- }
164
-
165
- let capturedUsageEvents: CapturedUsageEvent[] = [];
166
-
167
- mock.module('../memory/llm-usage-store.js', () => ({
168
- recordUsageEvent: (input: { requestId: string | null; actor: string }) => {
169
- capturedUsageEvents.push({ requestId: input.requestId, actor: input.actor });
170
- return { id: 'mock-id', createdAt: Date.now(), ...input };
171
- },
172
- listUsageEvents: () => [],
173
- }));
174
-
175
- // ---------------------------------------------------------------------------
176
- // Controllable AgentLoop mock.
177
- //
178
- // Each `run()` call returns a promise that does NOT resolve until the test
179
- // explicitly calls the stored `resolve` callback. This lets us simulate a
180
- // long-running agent loop so we can enqueue messages while the first one is
181
- // still "processing".
182
- // ---------------------------------------------------------------------------
183
-
184
- interface PendingRun {
185
- resolve: (history: Message[]) => void;
186
- reject: (err: Error) => void;
187
- messages: Message[];
188
- onEvent: (event: AgentEvent) => void;
189
- onCheckpoint?: (checkpoint: CheckpointInfo) => CheckpointDecision;
190
- }
191
-
192
- let pendingRuns: PendingRun[] = [];
193
-
194
- mock.module('../agent/loop.js', () => ({
195
- AgentLoop: class {
196
- constructor() {}
197
- async run(
198
- messages: Message[],
199
- onEvent: (event: AgentEvent) => void,
200
- _signal?: AbortSignal,
201
- _requestId?: string,
202
- onCheckpoint?: (checkpoint: CheckpointInfo) => CheckpointDecision,
203
- ): Promise<Message[]> {
204
- return new Promise<Message[]>((resolve, reject) => {
205
- pendingRuns.push({ resolve, reject, messages, onEvent, onCheckpoint });
206
- });
207
- }
208
- },
209
- }));
210
-
211
- // ---------------------------------------------------------------------------
212
- // Import Session AFTER mocks are registered.
213
- // ---------------------------------------------------------------------------
214
-
215
- import { Session, MAX_QUEUE_DEPTH } from '../daemon/session.js';
216
- import type { QueueDrainReason, QueuePolicy } from '../daemon/session.js';
217
-
218
- type SessionWithWorkspaceDeps = Session & {
219
- getWorkspaceGitService?: (_workspaceDir: string) => { ensureInitialized: () => Promise<void> };
220
- commitTurnChanges?: (
221
- workspaceDir: string,
222
- sessionId: string,
223
- turnNumber: number,
224
- provider?: unknown,
225
- deadlineMs?: number,
226
- ) => Promise<void>;
227
- };
228
-
229
- function makeSession(sendToClient?: (msg: ServerMessage) => void): Session {
230
- const provider = {
231
- name: 'mock',
232
- async sendMessage(): Promise<ProviderResponse> {
233
- return {
234
- content: [],
235
- model: 'mock',
236
- usage: { inputTokens: 0, outputTokens: 0 },
237
- stopReason: 'end_turn',
238
- };
239
- },
240
- };
241
- const session = new Session('conv-1', provider, 'system prompt', 4096, sendToClient ?? (() => {}), '/tmp');
242
- const sessionWithWorkspaceDeps = session as SessionWithWorkspaceDeps;
243
- sessionWithWorkspaceDeps.getWorkspaceGitService = () => ({
244
- ensureInitialized: async () => {},
245
- });
246
- sessionWithWorkspaceDeps.commitTurnChanges = async (workspaceDir: string, sessionId: string, turnNumber: number) => {
247
- turnCommitCalls.push({ workspaceDir, sessionId, turnNumber });
248
- if (turnCommitHangForever) {
249
- // Simulate a commit that never resolves within the timeout budget
250
- await new Promise<void>(() => {});
251
- }
252
- };
253
- return session;
254
- }
255
-
256
- /**
257
- * Wait until the pending runs array has at least `count` entries.
258
- * This is needed because `processMessage` is async and goes through
259
- * several awaited steps (context compaction, memory recall) before
260
- * reaching `agentLoop.run()`.
261
- */
262
- async function waitForPendingRun(count: number, timeoutMs = 2000): Promise<void> {
263
- const start = Date.now();
264
- while (pendingRuns.length < count) {
265
- if (Date.now() - start > timeoutMs) {
266
- throw new Error(`Timed out waiting for ${count} pending runs (have ${pendingRuns.length})`);
267
- }
268
- await new Promise((r) => setTimeout(r, 10));
269
- }
270
- }
271
-
272
- async function waitForCondition(predicate: () => boolean, timeoutMs = 2000): Promise<void> {
273
- const start = Date.now();
274
- while (!predicate()) {
275
- if (Date.now() - start > timeoutMs) {
276
- throw new Error('Timed out waiting for condition');
277
- }
278
- await new Promise((r) => setTimeout(r, 10));
279
- }
280
- }
281
-
282
- /**
283
- * Resolve the Nth pending AgentLoop.run() call. Fires the minimal events
284
- * that `runAgentLoop` expects (usage + message_complete) so the session
285
- * cleanly transitions out of its processing state.
286
- */
287
- function resolveRun(index: number) {
288
- const run = pendingRuns[index];
289
- if (!run) throw new Error(`No pending run at index ${index}`);
290
- // Emit the events runAgentLoop expects
291
- const assistantMsg: Message = {
292
- role: 'assistant',
293
- content: [{ type: 'text', text: `reply-${index}` }],
294
- };
295
- run.onEvent({ type: 'usage', inputTokens: 10, outputTokens: 5, model: 'mock', providerDurationMs: 100 });
296
- run.onEvent({ type: 'message_complete', message: assistantMsg });
297
- // Return updated history with the assistant message appended
298
- run.resolve([...run.messages, assistantMsg]);
299
- }
300
-
301
- beforeEach(() => {
302
- turnCommitCalls.length = 0;
303
- turnCommitHangForever = false;
304
- linkAttachmentShouldThrow = false;
305
- });
306
-
307
- afterAll(() => {
308
- mock.restore();
309
- });
310
-
311
- // ---------------------------------------------------------------------------
312
- // Tests
313
- // ---------------------------------------------------------------------------
314
-
315
- describe('Session message queue', () => {
316
- beforeEach(() => {
317
- pendingRuns = [];
318
- });
319
-
320
- test('second message is queued when session is busy (does not throw)', async () => {
321
- const session = makeSession();
322
- await session.loadFromDb();
323
-
324
- const events1: ServerMessage[] = [];
325
- const events2: ServerMessage[] = [];
326
-
327
- // Start first message — this will block on AgentLoop.run
328
- const p1 = session.processMessage('msg-1', [], (e) => events1.push(e), 'req-1');
329
-
330
- // Wait for the first AgentLoop.run to be registered
331
- await waitForPendingRun(1);
332
-
333
- // Session should now be processing
334
- expect(session.isProcessing()).toBe(true);
335
-
336
- // Enqueue second message — should NOT throw
337
- const result = session.enqueueMessage('msg-2', [], (e) => events2.push(e), 'req-2');
338
- expect(result.queued).toBe(true);
339
- expect(result.requestId).toBe('req-2');
340
- expect(session.getQueueDepth()).toBe(1);
341
-
342
- // Complete the first message
343
- resolveRun(0);
344
- await p1;
345
-
346
- // After the first run resolves, the queue drains and triggers a second run.
347
- await waitForPendingRun(2);
348
-
349
- // The dequeued event should have been sent to events2
350
- expect(events2.some((e) => e.type === 'message_dequeued')).toBe(true);
351
-
352
- // A second AgentLoop.run should now be pending
353
- expect(pendingRuns.length).toBe(2);
354
-
355
- // Complete the second run
356
- resolveRun(1);
357
- await new Promise((r) => setTimeout(r, 50));
358
- });
359
-
360
- test('[experimental] queued messages are processed in FIFO order', async () => {
361
- const session = makeSession();
362
- await session.loadFromDb();
363
-
364
- const processedOrder: string[] = [];
365
-
366
- const makeHandler = (label: string) => (e: ServerMessage) => {
367
- if (e.type === 'message_complete') processedOrder.push(label);
368
- };
369
-
370
- // Start first message
371
- const p1 = session.processMessage('msg-1', [], makeHandler('msg-1'), 'req-1');
372
- await waitForPendingRun(1);
373
-
374
- // Enqueue two more
375
- session.enqueueMessage('msg-2', [], makeHandler('msg-2'), 'req-2');
376
- session.enqueueMessage('msg-3', [], makeHandler('msg-3'), 'req-3');
377
- expect(session.getQueueDepth()).toBe(2);
378
-
379
- // Complete first → triggers second
380
- resolveRun(0);
381
- await p1;
382
- await waitForPendingRun(2);
383
-
384
- // Complete second → triggers third
385
- resolveRun(1);
386
- await waitForPendingRun(3);
387
-
388
- // Complete third
389
- resolveRun(2);
390
- await new Promise((r) => setTimeout(r, 50));
391
-
392
- expect(processedOrder).toEqual(['msg-1', 'msg-2', 'msg-3']);
393
- });
394
-
395
- test('message_queued and message_dequeued events are emitted', async () => {
396
- const session = makeSession();
397
- await session.loadFromDb();
398
-
399
- const events2: ServerMessage[] = [];
400
-
401
- // Start first message
402
- const p1 = session.processMessage('msg-1', [], () => {}, 'req-1');
403
- await waitForPendingRun(1);
404
-
405
- // Enqueue second — simulating what handleUserMessage does
406
- const result = session.enqueueMessage('msg-2', [], (e) => events2.push(e), 'req-2');
407
- expect(result.queued).toBe(true);
408
-
409
- // Complete first
410
- resolveRun(0);
411
- await p1;
412
- await waitForPendingRun(2);
413
-
414
- // Check for message_dequeued with correct fields
415
- const dequeued = events2.find((e) => e.type === 'message_dequeued');
416
- expect(dequeued).toBeDefined();
417
- expect(dequeued).toEqual({
418
- type: 'message_dequeued',
419
- sessionId: 'conv-1',
420
- requestId: 'req-2',
421
- });
422
-
423
- // Complete second run so the session finishes cleanly
424
- resolveRun(1);
425
- await new Promise((r) => setTimeout(r, 50));
426
- });
427
-
428
- test('abort() clears the queue and sends generation_cancelled for each queued message', async () => {
429
- const session = makeSession();
430
- await session.loadFromDb();
431
-
432
- const events2: ServerMessage[] = [];
433
- const events3: ServerMessage[] = [];
434
-
435
- // Start first message
436
- session.processMessage('msg-1', [], () => {}, 'req-1');
437
- await waitForPendingRun(1);
438
-
439
- // Enqueue two more
440
- session.enqueueMessage('msg-2', [], (e) => events2.push(e), 'req-2');
441
- session.enqueueMessage('msg-3', [], (e) => events3.push(e), 'req-3');
442
- expect(session.getQueueDepth()).toBe(2);
443
-
444
- // Abort
445
- session.abort();
446
-
447
- // Queue should be empty
448
- expect(session.getQueueDepth()).toBe(0);
449
-
450
- // Both queued messages should receive session-scoped cancellation events.
451
- const cancel2 = events2.find((e) => e.type === 'generation_cancelled');
452
- expect(cancel2).toEqual({ type: 'generation_cancelled', sessionId: 'conv-1' });
453
-
454
- const cancel3 = events3.find((e) => e.type === 'generation_cancelled');
455
- expect(cancel3).toEqual({ type: 'generation_cancelled', sessionId: 'conv-1' });
456
-
457
- // abort() must NOT emit session_error or generic error for queued discards.
458
- const err2 = events2.find((e) => e.type === 'error');
459
- expect(err2).toBeUndefined();
460
- const err3 = events3.find((e) => e.type === 'error');
461
- expect(err3).toBeUndefined();
462
-
463
- const sessionErr2 = events2.find((e) => e.type === 'session_error');
464
- expect(sessionErr2).toBeUndefined();
465
-
466
- const sessionErr3 = events3.find((e) => e.type === 'session_error');
467
- expect(sessionErr3).toBeUndefined();
468
- });
469
-
470
- test('session-scoped errors emit both session_error and generic error', async () => {
471
- const session = makeSession();
472
- await session.loadFromDb();
473
-
474
- const events: ServerMessage[] = [];
475
-
476
- // Start a message — blocks on AgentLoop.run
477
- const p1 = session.processMessage('msg-1', [], (e) => events.push(e), 'req-1');
478
- await waitForPendingRun(1);
479
-
480
- // Reject the AgentLoop.run() with a provider error to trigger the
481
- // runAgentLoop catch block
482
- pendingRuns[0].reject(new Error('Provider returned 500'));
483
- await p1;
484
-
485
- // Should emit session_error (typed, structured)
486
- const sessionErr = events.find((e) => e.type === 'session_error');
487
- expect(sessionErr).toBeDefined();
488
-
489
- // Should also emit generic error for backward compatibility
490
- // (RunOrchestrator relies on error events to detect failures)
491
- const genericErr = events.find((e) => e.type === 'error');
492
- expect(genericErr).toBeDefined();
493
- });
494
-
495
- test('queue depth is reported correctly as messages are added and drained', async () => {
496
- const session = makeSession();
497
- await session.loadFromDb();
498
-
499
- // Start first message
500
- const p1 = session.processMessage('msg-1', [], () => {}, 'req-1');
501
- await waitForPendingRun(1);
502
-
503
- expect(session.getQueueDepth()).toBe(0);
504
-
505
- session.enqueueMessage('msg-2', [], () => {}, 'req-2');
506
- expect(session.getQueueDepth()).toBe(1);
507
-
508
- session.enqueueMessage('msg-3', [], () => {}, 'req-3');
509
- expect(session.getQueueDepth()).toBe(2);
510
-
511
- session.enqueueMessage('msg-4', [], () => {}, 'req-4');
512
- expect(session.getQueueDepth()).toBe(3);
513
-
514
- // Complete first → drains one from queue
515
- resolveRun(0);
516
- await p1;
517
- await waitForPendingRun(2);
518
-
519
- expect(session.getQueueDepth()).toBe(2);
520
-
521
- // Complete second → drains another
522
- resolveRun(1);
523
- await waitForPendingRun(3);
524
-
525
- expect(session.getQueueDepth()).toBe(1);
526
-
527
- // Complete third → drains last
528
- resolveRun(2);
529
- await waitForPendingRun(4);
530
-
531
- expect(session.getQueueDepth()).toBe(0);
532
-
533
- // Complete fourth (final queued message)
534
- resolveRun(3);
535
- await new Promise((r) => setTimeout(r, 50));
536
- });
537
-
538
- test('[experimental] drain continues after a queued message fails to persist', async () => {
539
- const session = makeSession();
540
- await session.loadFromDb();
541
-
542
- const events1: ServerMessage[] = [];
543
- const events2: ServerMessage[] = [];
544
- const events3: ServerMessage[] = [];
545
-
546
- // Start first message — blocks on AgentLoop.run
547
- const p1 = session.processMessage('msg-1', [], (e) => events1.push(e), 'req-1');
548
- await waitForPendingRun(1);
549
-
550
- // Enqueue a message with empty content (will fail persistUserMessage)
551
- session.enqueueMessage('', [], (e) => events2.push(e), 'req-2');
552
- // Enqueue a valid message after the bad one
553
- session.enqueueMessage('msg-3', [], (e) => events3.push(e), 'req-3');
554
- expect(session.getQueueDepth()).toBe(2);
555
-
556
- // Complete first message — triggers drain. The empty message should fail
557
- // to persist, but the drain should continue to msg-3.
558
- resolveRun(0);
559
- await p1;
560
-
561
- // msg-3 should have been dequeued and started a new AgentLoop.run
562
- await waitForPendingRun(2);
563
-
564
- // The empty message should have received an error event
565
- const err2 = events2.find((e) => e.type === 'error');
566
- expect(err2).toBeDefined();
567
- if (err2 && err2.type === 'error') {
568
- expect(err2.message).toContain('required');
569
- }
570
-
571
- // msg-3 should have received a dequeued event
572
- expect(events3.some((e) => e.type === 'message_dequeued')).toBe(true);
573
-
574
- // Complete the third message's run
575
- resolveRun(1);
576
- await new Promise((r) => setTimeout(r, 50));
577
-
578
- // msg-3 should have completed successfully
579
- expect(events3.some((e) => e.type === 'message_complete')).toBe(true);
580
- });
581
-
582
- test('queue rejects when at max depth', async () => {
583
- const session = makeSession();
584
- await session.loadFromDb();
585
-
586
- // Start first message to make session busy
587
- session.processMessage('msg-1', [], () => {}, 'req-1');
588
- await waitForPendingRun(1);
589
-
590
- // Fill the queue to MAX_QUEUE_DEPTH
591
- for (let i = 0; i < MAX_QUEUE_DEPTH; i++) {
592
- const result = session.enqueueMessage(`msg-${i + 2}`, [], () => {}, `req-${i + 2}`);
593
- expect(result.queued).toBe(true);
594
- expect(result.rejected).toBeUndefined();
595
- }
596
- expect(session.getQueueDepth()).toBe(MAX_QUEUE_DEPTH);
597
-
598
- // Next enqueue should be rejected
599
- const rejected = session.enqueueMessage('overflow', [], () => {}, 'req-overflow');
600
- expect(rejected.queued).toBe(false);
601
- expect(rejected.rejected).toBe(true);
602
-
603
- // Queue depth should not have increased
604
- expect(session.getQueueDepth()).toBe(MAX_QUEUE_DEPTH);
605
- });
606
- });
607
-
608
- // ---------------------------------------------------------------------------
609
- // Queue policy primitives
610
- // ---------------------------------------------------------------------------
611
-
612
- describe('Session queue policy helpers', () => {
613
- beforeEach(() => {
614
- pendingRuns = [];
615
- });
616
-
617
- test('hasQueuedMessages() returns false on a fresh session', async () => {
618
- const session = makeSession();
619
- await session.loadFromDb();
620
- expect(session.hasQueuedMessages()).toBe(false);
621
- });
622
-
623
- test('hasQueuedMessages() returns true after enqueuing while processing', async () => {
624
- const session = makeSession();
625
- await session.loadFromDb();
626
-
627
- // Start processing to make the session busy
628
- session.processMessage('msg-1', [], () => {}, 'req-1');
629
- await waitForPendingRun(1);
630
-
631
- // Enqueue a message while processing
632
- session.enqueueMessage('msg-2', [], () => {}, 'req-2');
633
- expect(session.hasQueuedMessages()).toBe(true);
634
-
635
- // Cleanup: resolve the pending run
636
- resolveRun(0);
637
- await waitForPendingRun(2);
638
- resolveRun(1);
639
- await new Promise((r) => setTimeout(r, 50));
640
- });
641
-
642
- test('canHandoffAtCheckpoint() returns false when not processing', async () => {
643
- const session = makeSession();
644
- await session.loadFromDb();
645
-
646
- // Not processing, no queued messages
647
- expect(session.canHandoffAtCheckpoint()).toBe(false);
648
- });
649
-
650
- test('canHandoffAtCheckpoint() returns false when processing but no queued messages', async () => {
651
- const session = makeSession();
652
- await session.loadFromDb();
653
-
654
- // Start processing — but don't enqueue anything
655
- session.processMessage('msg-1', [], () => {}, 'req-1');
656
- await waitForPendingRun(1);
657
-
658
- expect(session.isProcessing()).toBe(true);
659
- expect(session.hasQueuedMessages()).toBe(false);
660
- expect(session.canHandoffAtCheckpoint()).toBe(false);
661
-
662
- // Cleanup
663
- resolveRun(0);
664
- await new Promise((r) => setTimeout(r, 50));
665
- });
666
-
667
- test('canHandoffAtCheckpoint() returns true when processing and queue has messages', async () => {
668
- const session = makeSession();
669
- await session.loadFromDb();
670
-
671
- // Start processing
672
- session.processMessage('msg-1', [], () => {}, 'req-1');
673
- await waitForPendingRun(1);
674
-
675
- // Enqueue a message
676
- session.enqueueMessage('msg-2', [], () => {}, 'req-2');
677
-
678
- expect(session.isProcessing()).toBe(true);
679
- expect(session.hasQueuedMessages()).toBe(true);
680
- expect(session.canHandoffAtCheckpoint()).toBe(true);
681
-
682
- // Cleanup
683
- resolveRun(0);
684
- await waitForPendingRun(2);
685
- resolveRun(1);
686
- await new Promise((r) => setTimeout(r, 50));
687
- });
688
-
689
- test('QueueDrainReason type accepts expected values', () => {
690
- // Compile-time verification that these are valid QueueDrainReason values
691
- const reason1: QueueDrainReason = 'loop_complete';
692
- const reason2: QueueDrainReason = 'checkpoint_handoff';
693
- expect(reason1).toBe('loop_complete');
694
- expect(reason2).toBe('checkpoint_handoff');
695
- });
696
-
697
- test('QueuePolicy type accepts expected shape', () => {
698
- // Compile-time verification that the QueuePolicy interface works
699
- const policy: QueuePolicy = { checkpointHandoffEnabled: true };
700
- expect(policy.checkpointHandoffEnabled).toBe(true);
701
-
702
- const disabledPolicy: QueuePolicy = { checkpointHandoffEnabled: false };
703
- expect(disabledPolicy.checkpointHandoffEnabled).toBe(false);
704
- });
705
- });
706
-
707
- // ---------------------------------------------------------------------------
708
- // Checkpoint handoff tests
709
- // ---------------------------------------------------------------------------
710
-
711
- describe('Session checkpoint handoff', () => {
712
- beforeEach(() => {
713
- pendingRuns = [];
714
- });
715
-
716
- test('[experimental] onCheckpoint yields when there is a queued message', async () => {
717
- const session = makeSession();
718
- await session.loadFromDb();
719
-
720
- const events1: ServerMessage[] = [];
721
-
722
- // Start processing first message
723
- const p1 = session.processMessage('msg-1', [], (e) => events1.push(e), 'req-1');
724
- await waitForPendingRun(1);
725
-
726
- // Enqueue a second message while the first is processing
727
- session.enqueueMessage('msg-2', [], () => {}, 'req-2');
728
- expect(session.hasQueuedMessages()).toBe(true);
729
-
730
- // The pending run should have received an onCheckpoint callback.
731
- // Simulate the agent loop calling it at a turn boundary.
732
- const run = pendingRuns[0];
733
- expect(run.onCheckpoint).toBeDefined();
734
- const decision = run.onCheckpoint!({
735
- turnIndex: 0,
736
- toolCount: 1,
737
- hasToolUse: true,
738
- });
739
-
740
- // Because there is a queued message, the callback should return 'yield'
741
- expect(decision).toBe('yield');
742
-
743
- // Complete the run so the session finishes cleanly
744
- resolveRun(0);
745
- await p1;
746
-
747
- // After yield, the first message should emit generation_handoff
748
- const handoff = events1.find((e) => e.type === 'generation_handoff');
749
- expect(handoff).toBeDefined();
750
- expect(handoff).toMatchObject({
751
- type: 'generation_handoff',
752
- sessionId: 'conv-1',
753
- requestId: 'req-1',
754
- queuedCount: 1,
755
- });
756
-
757
- // The queued message should now be draining (second run started)
758
- await waitForPendingRun(2);
759
- resolveRun(1);
760
- await new Promise((r) => setTimeout(r, 50));
761
- });
762
-
763
- test('onCheckpoint returns continue when queue is empty', async () => {
764
- const session = makeSession();
765
- await session.loadFromDb();
766
-
767
- // Start processing — no enqueued messages
768
- const p1 = session.processMessage('msg-1', [], () => {}, 'req-1');
769
- await waitForPendingRun(1);
770
-
771
- expect(session.hasQueuedMessages()).toBe(false);
772
-
773
- // The pending run should have an onCheckpoint callback
774
- const run = pendingRuns[0];
775
- expect(run.onCheckpoint).toBeDefined();
776
- const decision = run.onCheckpoint!({
777
- turnIndex: 0,
778
- toolCount: 1,
779
- hasToolUse: true,
780
- });
781
-
782
- // No queued messages → continue
783
- expect(decision).toBe('continue');
784
-
785
- // Cleanup
786
- resolveRun(0);
787
- await p1;
788
- });
789
-
790
- test('[experimental] FIFO ordering is preserved through checkpoint handoff', async () => {
791
- const session = makeSession();
792
- await session.loadFromDb();
793
-
794
- const processedOrder: string[] = [];
795
-
796
- const makeHandler = (label: string) => (e: ServerMessage) => {
797
- if (e.type === 'message_complete' || e.type === 'generation_handoff') processedOrder.push(label);
798
- };
799
-
800
- // Start first message
801
- const p1 = session.processMessage('msg-1', [], makeHandler('msg-1'), 'req-1');
802
- await waitForPendingRun(1);
803
-
804
- // Enqueue two messages
805
- session.enqueueMessage('msg-2', [], makeHandler('msg-2'), 'req-2');
806
- session.enqueueMessage('msg-3', [], makeHandler('msg-3'), 'req-3');
807
- expect(session.getQueueDepth()).toBe(2);
808
-
809
- // Simulate the agent loop yielding at the checkpoint (first run)
810
- const run0 = pendingRuns[0];
811
- expect(run0.onCheckpoint).toBeDefined();
812
- const decision = run0.onCheckpoint!({ turnIndex: 0, toolCount: 1, hasToolUse: true });
813
- expect(decision).toBe('yield');
814
-
815
- // Complete first run
816
- resolveRun(0);
817
- await p1;
818
-
819
- // msg-2 should be draining next
820
- await waitForPendingRun(2);
821
-
822
- // Complete second run (msg-2)
823
- resolveRun(1);
824
- await waitForPendingRun(3);
825
-
826
- // Complete third run (msg-3)
827
- resolveRun(2);
828
- await new Promise((r) => setTimeout(r, 50));
829
-
830
- // FIFO order: msg-1 completes first, then msg-2, then msg-3
831
- expect(processedOrder).toEqual(['msg-1', 'msg-2', 'msg-3']);
832
- });
833
-
834
- test('queue-full rejection still works during checkpoint handoff', async () => {
835
- const session = makeSession();
836
- await session.loadFromDb();
837
-
838
- // Start processing
839
- session.processMessage('msg-1', [], () => {}, 'req-1');
840
- await waitForPendingRun(1);
841
-
842
- // Fill the queue to MAX_QUEUE_DEPTH
843
- for (let i = 0; i < MAX_QUEUE_DEPTH; i++) {
844
- const result = session.enqueueMessage(`queued-${i}`, [], () => {}, `req-q-${i}`);
845
- expect(result.queued).toBe(true);
846
- }
847
- expect(session.getQueueDepth()).toBe(MAX_QUEUE_DEPTH);
848
-
849
- // Verify checkpoint would yield (there are queued messages)
850
- const run = pendingRuns[0];
851
- expect(run.onCheckpoint).toBeDefined();
852
- expect(run.onCheckpoint!({ turnIndex: 0, toolCount: 1, hasToolUse: true })).toBe('yield');
853
-
854
- // Next enqueue should still be rejected
855
- const rejected = session.enqueueMessage('overflow', [], () => {}, 'req-overflow');
856
- expect(rejected.queued).toBe(false);
857
- expect(rejected.rejected).toBe(true);
858
-
859
- // Queue depth unchanged
860
- expect(session.getQueueDepth()).toBe(MAX_QUEUE_DEPTH);
861
- });
862
-
863
- test('[experimental] active run with repeated tool turns + queued message triggers checkpoint handoff', async () => {
864
- const session = makeSession();
865
- await session.loadFromDb();
866
-
867
- const events1: ServerMessage[] = [];
868
- const events2: ServerMessage[] = [];
869
-
870
- // Start processing first message
871
- const p1 = session.processMessage('msg-1', [], (e) => events1.push(e), 'req-1');
872
- await waitForPendingRun(1);
873
-
874
- // Enqueue a second message while the first is processing
875
- session.enqueueMessage('msg-2', [], (e) => events2.push(e), 'req-2');
876
- expect(session.hasQueuedMessages()).toBe(true);
877
-
878
- // Simulate tool-use turns: the agent loop calls onCheckpoint at each turn boundary.
879
- // Because there is a queued message, the callback should return 'yield'.
880
- const run = pendingRuns[0];
881
- expect(run.onCheckpoint).toBeDefined();
882
-
883
- // Simulate multiple tool-use turns before the checkpoint fires
884
- // Turn 0 — checkpoint yields because msg-2 is waiting
885
- const decision = run.onCheckpoint!({
886
- turnIndex: 0,
887
- toolCount: 1,
888
- hasToolUse: true,
889
- });
890
- expect(decision).toBe('yield');
891
-
892
- // Complete the run (AgentLoop resolves after yielding)
893
- resolveRun(0);
894
- await p1;
895
-
896
- // Verify generation_handoff was emitted (not plain message_complete)
897
- const handoff = events1.find((e) => e.type === 'generation_handoff');
898
- expect(handoff).toBeDefined();
899
- expect(handoff).toMatchObject({
900
- type: 'generation_handoff',
901
- sessionId: 'conv-1',
902
- requestId: 'req-1',
903
- queuedCount: 1,
904
- });
905
- // message_complete should NOT be in events1 (handoff replaces it)
906
- const messageComplete = events1.find((e) => e.type === 'message_complete' && 'sessionId' in e);
907
- expect(messageComplete).toBeUndefined();
908
-
909
- // The queued message should subsequently drain
910
- await waitForPendingRun(2);
911
- expect(events2.some((e) => e.type === 'message_dequeued')).toBe(true);
912
-
913
- // Complete the second run
914
- resolveRun(1);
915
- await new Promise((r) => setTimeout(r, 50));
916
- });
917
-
918
- test('queued messages still drain FIFO under multiple handoffs', async () => {
919
- const session = makeSession();
920
- await session.loadFromDb();
921
-
922
- const dequeueOrder: string[] = [];
923
-
924
- const eventsA: ServerMessage[] = [];
925
- const makeHandler = (label: string) => (e: ServerMessage) => {
926
- if (e.type === 'message_dequeued') dequeueOrder.push(label);
927
- };
928
-
929
- // Start processing message A
930
- const pA = session.processMessage('msg-A', [], (e) => eventsA.push(e), 'req-A');
931
- await waitForPendingRun(1);
932
-
933
- // Enqueue messages B, C, D
934
- session.enqueueMessage('msg-B', [], makeHandler('B'), 'req-B');
935
- session.enqueueMessage('msg-C', [], makeHandler('C'), 'req-C');
936
- session.enqueueMessage('msg-D', [], makeHandler('D'), 'req-D');
937
- expect(session.getQueueDepth()).toBe(3);
938
-
939
- // Handoff from A -> B
940
- const runA = pendingRuns[0];
941
- expect(runA.onCheckpoint).toBeDefined();
942
- expect(runA.onCheckpoint!({ turnIndex: 0, toolCount: 1, hasToolUse: true })).toBe('yield');
943
- resolveRun(0);
944
- await pA;
945
-
946
- // B should be draining
947
- await waitForPendingRun(2);
948
-
949
- // Handoff from B -> C
950
- const runB = pendingRuns[1];
951
- expect(runB.onCheckpoint).toBeDefined();
952
- expect(runB.onCheckpoint!({ turnIndex: 0, toolCount: 1, hasToolUse: true })).toBe('yield');
953
- resolveRun(1);
954
- await waitForPendingRun(3);
955
-
956
- // Handoff from C -> D
957
- const runC = pendingRuns[2];
958
- expect(runC.onCheckpoint).toBeDefined();
959
- // Only D remains, still should yield
960
- expect(runC.onCheckpoint!({ turnIndex: 0, toolCount: 1, hasToolUse: true })).toBe('yield');
961
- resolveRun(2);
962
- await waitForPendingRun(4);
963
-
964
- // D has no more queued -> checkpoint should return 'continue'
965
- const runD = pendingRuns[3];
966
- expect(runD.onCheckpoint).toBeDefined();
967
- expect(runD.onCheckpoint!({ turnIndex: 0, toolCount: 1, hasToolUse: true })).toBe('continue');
968
-
969
- resolveRun(3);
970
- await new Promise((r) => setTimeout(r, 50));
971
-
972
- // Verify FIFO dequeue order
973
- expect(dequeueOrder).toEqual(['B', 'C', 'D']);
974
- });
975
-
976
- test('[experimental] queued persistence failure does not strand later messages', async () => {
977
- const session = makeSession();
978
- await session.loadFromDb();
979
-
980
- const eventsA: ServerMessage[] = [];
981
- const eventsB: ServerMessage[] = [];
982
- const eventsC: ServerMessage[] = [];
983
-
984
- // Start processing message A
985
- const pA = session.processMessage('msg-A', [], (e) => eventsA.push(e), 'req-A');
986
- await waitForPendingRun(1);
987
-
988
- // Enqueue B (empty content — will fail to persist) and C (valid)
989
- session.enqueueMessage('', [], (e) => eventsB.push(e), 'req-B');
990
- session.enqueueMessage('msg-C', [], (e) => eventsC.push(e), 'req-C');
991
- expect(session.getQueueDepth()).toBe(2);
992
-
993
- // Complete message A — triggers drain. B should fail, C should proceed.
994
- resolveRun(0);
995
- await pA;
996
-
997
- // C should have been dequeued and started a new AgentLoop.run
998
- await waitForPendingRun(2);
999
-
1000
- // B should have received an error event
1001
- const errB = eventsB.find((e) => e.type === 'error');
1002
- expect(errB).toBeDefined();
1003
- if (errB && errB.type === 'error') {
1004
- expect(errB.message).toContain('required');
1005
- }
1006
-
1007
- // C should have received a dequeued event
1008
- expect(eventsC.some((e) => e.type === 'message_dequeued')).toBe(true);
1009
-
1010
- // Complete C's run
1011
- resolveRun(1);
1012
- await new Promise((r) => setTimeout(r, 50));
1013
-
1014
- // C should have completed successfully
1015
- expect(eventsC.some((e) => e.type === 'message_complete')).toBe(true);
1016
- });
1017
-
1018
- test('onCheckpoint callback is passed to both initial and retry runs', async () => {
1019
- const session = makeSession();
1020
- await session.loadFromDb();
1021
-
1022
- // Start processing
1023
- const p1 = session.processMessage('msg-1', [], () => {}, 'req-1');
1024
- await waitForPendingRun(1);
1025
-
1026
- // The first run should have onCheckpoint
1027
- expect(pendingRuns[0].onCheckpoint).toBeDefined();
1028
-
1029
- // Simulate an ordering error: emit error + resolve with same length
1030
- // to trigger the retry path
1031
- const run0 = pendingRuns[0];
1032
- run0.onEvent({
1033
- type: 'error',
1034
- error: new Error('tool_result block not immediately after tool_use block'),
1035
- });
1036
- // Resolve with the same messages (no new messages appended = ordering error)
1037
- run0.resolve([...run0.messages]);
1038
-
1039
- // Wait for the retry run
1040
- await waitForPendingRun(2);
1041
-
1042
- // The retry run should also have onCheckpoint
1043
- expect(pendingRuns[1].onCheckpoint).toBeDefined();
1044
-
1045
- // Complete retry cleanly
1046
- resolveRun(1);
1047
- await p1;
1048
- });
1049
- });
1050
-
1051
- // ---------------------------------------------------------------------------
1052
- // Usage requestId correlation
1053
- // ---------------------------------------------------------------------------
1054
-
1055
- describe('Session usage requestId correlation', () => {
1056
- beforeEach(() => {
1057
- pendingRuns = [];
1058
- capturedUsageEvents = [];
1059
- });
1060
-
1061
- test('usage events recorded during a request carry that request ID', async () => {
1062
- const session = makeSession();
1063
- await session.loadFromDb();
1064
-
1065
- const p1 = session.processMessage('msg-1', [], () => {}, 'req-42');
1066
- await waitForPendingRun(1);
1067
-
1068
- // Complete the run — this triggers recordUsage with the request's ID
1069
- resolveRun(0);
1070
- await p1;
1071
-
1072
- // The usage event should carry the request ID, not null
1073
- const mainAgentUsage = capturedUsageEvents.find((e) => e.actor === 'main_agent');
1074
- expect(mainAgentUsage).toBeDefined();
1075
- expect(mainAgentUsage!.requestId).toBe('req-42');
1076
- });
1077
- });
1078
-
1079
- // ---------------------------------------------------------------------------
1080
- // Terminal trace events on rejection/failure paths
1081
- // ---------------------------------------------------------------------------
1082
-
1083
- describe('Terminal trace events on rejection/failure', () => {
1084
- beforeEach(() => {
1085
- pendingRuns = [];
1086
- });
1087
-
1088
- test('queued persist failure emits request_error trace', async () => {
1089
- const traceEvents: ServerMessage[] = [];
1090
- const session = makeSession((msg) => {
1091
- if ('type' in msg && msg.type === 'trace_event') traceEvents.push(msg);
1092
- });
1093
- await session.loadFromDb();
1094
-
1095
- // Start first message
1096
- const p1 = session.processMessage('msg-1', [], () => {}, 'req-1');
1097
- await waitForPendingRun(1);
1098
-
1099
- // Enqueue empty content (will fail persistUserMessage)
1100
- session.enqueueMessage('', [], () => {}, 'req-bad');
1101
- // Enqueue valid message so drain continues
1102
- session.enqueueMessage('msg-3', [], () => {}, 'req-3');
1103
-
1104
- // Complete first — triggers drain, empty msg fails persist
1105
- resolveRun(0);
1106
- await p1;
1107
- await waitForPendingRun(2);
1108
-
1109
- // Should have a request_error trace for the failed persist
1110
- const errorTrace = traceEvents.find(
1111
- (e) => 'kind' in e && e.kind === 'request_error' && 'requestId' in e && e.requestId === 'req-bad',
1112
- );
1113
- expect(errorTrace).toBeDefined();
1114
-
1115
- // Cleanup
1116
- resolveRun(1);
1117
- await new Promise((r) => setTimeout(r, 50));
1118
- });
1119
- });
1120
-
1121
- // ---------------------------------------------------------------------------
1122
- // Surface-action queue-full trace emission
1123
- // ---------------------------------------------------------------------------
1124
-
1125
- describe('Surface-action queue-full trace', () => {
1126
- beforeEach(() => {
1127
- pendingRuns = [];
1128
- });
1129
-
1130
- test('surface-action queue-full rejection emits request_error trace', async () => {
1131
- const traceEvents: ServerMessage[] = [];
1132
- const session = makeSession((msg) => {
1133
- if ('type' in msg && msg.type === 'trace_event') traceEvents.push(msg);
1134
- });
1135
- await session.loadFromDb();
1136
-
1137
- // Start processing to make the session busy
1138
- session.processMessage('msg-1', [], () => {}, 'req-1');
1139
- await waitForPendingRun(1);
1140
-
1141
- // Fill the queue to MAX_QUEUE_DEPTH
1142
- for (let i = 0; i < MAX_QUEUE_DEPTH; i++) {
1143
- const result = session.enqueueMessage(`queued-${i}`, [], () => {}, `req-q-${i}`);
1144
- expect(result.queued).toBe(true);
1145
- }
1146
- expect(session.getQueueDepth()).toBe(MAX_QUEUE_DEPTH);
1147
-
1148
- // Register a pending surface action so handleSurfaceAction doesn't bail early
1149
- // eslint-disable-next-line @typescript-eslint/no-explicit-any -- access private property for testing
1150
- (session as any).pendingSurfaceActions.set('surf-1', { surfaceType: 'confirmation' });
1151
-
1152
- // Trigger the surface action — queue is full, should be rejected
1153
- session.handleSurfaceAction('surf-1', 'confirm');
1154
-
1155
- // Should have a request_received trace followed by a request_error trace
1156
- const receivedTrace = traceEvents.find(
1157
- (e) => 'kind' in e && e.kind === 'request_received',
1158
- );
1159
- expect(receivedTrace).toBeDefined();
1160
-
1161
- const errorTrace = traceEvents.find(
1162
- (e) => 'kind' in e && e.kind === 'request_error',
1163
- );
1164
- expect(errorTrace).toBeDefined();
1165
- expect(errorTrace).toHaveProperty('attributes');
1166
- // eslint-disable-next-line @typescript-eslint/no-explicit-any -- access trace attributes
1167
- const attrs = (errorTrace as any).attributes;
1168
- expect(attrs.reason).toBe('queue_full');
1169
- expect(attrs.source).toBe('surface_action');
1170
-
1171
- // Queue depth should not have increased
1172
- expect(session.getQueueDepth()).toBe(MAX_QUEUE_DEPTH);
1173
- });
1174
- });
1175
-
1176
- // ---------------------------------------------------------------------------
1177
- // Host attachment approval tests
1178
- // ---------------------------------------------------------------------------
1179
-
1180
- describe('Session host attachment directives', () => {
1181
- beforeEach(() => {
1182
- pendingRuns = [];
1183
- });
1184
-
1185
- test('host attachment prompts and resolves when user allows', async () => {
1186
- const hostPath = '/tmp/vellum-host-attachment-allow.txt';
1187
- writeFileSync(hostPath, 'host attachment content');
1188
-
1189
- try {
1190
- const clientEvents: ServerMessage[] = [];
1191
- const events: ServerMessage[] = [];
1192
- const session = makeSession((msg) => clientEvents.push(msg));
1193
- await session.loadFromDb();
1194
-
1195
- const p1 = session.processMessage('msg-1', [], (e) => events.push(e), 'req-1');
1196
- await waitForPendingRun(1);
1197
-
1198
- const run = pendingRuns[0];
1199
- const assistantMsg: Message = {
1200
- role: 'assistant',
1201
- content: [
1202
- {
1203
- type: 'text',
1204
- text: `Here is your file.\n<vellum-attachment source="host" path="${hostPath}" />`,
1205
- },
1206
- ],
1207
- };
1208
- run.onEvent({ type: 'usage', inputTokens: 10, outputTokens: 5, model: 'mock', providerDurationMs: 100 });
1209
- run.onEvent({ type: 'message_complete', message: assistantMsg });
1210
- run.resolve([...run.messages, assistantMsg]);
1211
-
1212
- await waitForCondition(() => clientEvents.some((e) => e.type === 'confirmation_request'));
1213
- const confirmation = clientEvents.find((e) => e.type === 'confirmation_request');
1214
- expect(confirmation).toBeDefined();
1215
- session.handleConfirmationResponse((confirmation as { requestId: string }).requestId, 'allow');
1216
-
1217
- await p1;
1218
-
1219
- expect(session.lastAssistantAttachments).toHaveLength(1);
1220
- expect(session.lastAssistantAttachments[0].sourceType).toBe('host_file');
1221
- expect(session.lastAttachmentWarnings).toHaveLength(0);
1222
-
1223
- const completion = events.find((e) => e.type === 'message_complete');
1224
- expect(completion).toBeDefined();
1225
- } finally {
1226
- rmSync(hostPath, { force: true });
1227
- }
1228
- });
1229
-
1230
- test('host attachment denial is non-fatal and emits warning text', async () => {
1231
- const hostPath = '/tmp/vellum-host-attachment-deny.txt';
1232
- writeFileSync(hostPath, 'host attachment content');
1233
-
1234
- try {
1235
- const clientEvents: ServerMessage[] = [];
1236
- const events: ServerMessage[] = [];
1237
- const session = makeSession((msg) => clientEvents.push(msg));
1238
- await session.loadFromDb();
1239
-
1240
- const p1 = session.processMessage('msg-1', [], (e) => events.push(e), 'req-1');
1241
- await waitForPendingRun(1);
1242
-
1243
- const run = pendingRuns[0];
1244
- const assistantMsg: Message = {
1245
- role: 'assistant',
1246
- content: [
1247
- {
1248
- type: 'text',
1249
- text: `Here is your file.\n<vellum-attachment source="host" path="${hostPath}" />`,
1250
- },
1251
- ],
1252
- };
1253
- run.onEvent({ type: 'usage', inputTokens: 10, outputTokens: 5, model: 'mock', providerDurationMs: 100 });
1254
- run.onEvent({ type: 'message_complete', message: assistantMsg });
1255
- run.resolve([...run.messages, assistantMsg]);
1256
-
1257
- await waitForCondition(() => clientEvents.some((e) => e.type === 'confirmation_request'));
1258
- const confirmation = clientEvents.find((e) => e.type === 'confirmation_request');
1259
- expect(confirmation).toBeDefined();
1260
- session.handleConfirmationResponse((confirmation as { requestId: string }).requestId, 'deny');
1261
-
1262
- await p1;
1263
-
1264
- expect(session.lastAssistantAttachments).toHaveLength(0);
1265
- expect(session.lastAttachmentWarnings.some((w) => w.includes('access denied by user'))).toBe(true);
1266
-
1267
- const warningDelta = events.find(
1268
- (e) => e.type === 'assistant_text_delta' && e.text.includes('Attachment warning:'),
1269
- );
1270
- expect(warningDelta).toBeDefined();
1271
- const completion = events.find((e) => e.type === 'message_complete');
1272
- expect(completion).toBeDefined();
1273
- } finally {
1274
- rmSync(hostPath, { force: true });
1275
- }
1276
- });
1277
- });
1278
-
1279
- // ---------------------------------------------------------------------------
1280
- // Attachment payload emission tests
1281
- // ---------------------------------------------------------------------------
1282
-
1283
- describe('Session attachment event payloads', () => {
1284
- beforeEach(() => {
1285
- pendingRuns = [];
1286
- });
1287
-
1288
- test('message_complete includes assistant attachments', async () => {
1289
- const events: ServerMessage[] = [];
1290
- const session = makeSession();
1291
- await session.loadFromDb();
1292
-
1293
- const p1 = session.processMessage('msg-1', [], (e) => events.push(e), 'req-1');
1294
- await waitForPendingRun(1);
1295
-
1296
- const run = pendingRuns[0];
1297
- const assistantMsg: Message = {
1298
- role: 'assistant',
1299
- content: [{ type: 'text', text: 'Here is your chart.' }],
1300
- };
1301
- run.onEvent({
1302
- type: 'tool_result',
1303
- toolUseId: 'tool-1',
1304
- content: 'ok',
1305
- isError: false,
1306
- contentBlocks: [
1307
- // eslint-disable-next-line @typescript-eslint/no-explicit-any -- mock content block
1308
- { type: 'image', source: { type: 'base64', media_type: 'image/png', data: 'iVBORw0K' } } as any,
1309
- ],
1310
- });
1311
- run.onEvent({ type: 'usage', inputTokens: 10, outputTokens: 5, model: 'mock', providerDurationMs: 100 });
1312
- run.onEvent({ type: 'message_complete', message: assistantMsg });
1313
- run.resolve([...run.messages, assistantMsg]);
1314
-
1315
- await p1;
1316
-
1317
- const completion = events.find((e) => e.type === 'message_complete' && Array.isArray(e.attachments));
1318
- expect(completion).toBeDefined();
1319
- const attachments = (completion as { attachments: Array<{ mimeType: string; data: string; id?: string }> }).attachments;
1320
- expect(attachments).toHaveLength(1);
1321
- expect(attachments[0].mimeType).toBe('image/png');
1322
- expect(attachments[0].data).toBe('iVBORw0K');
1323
- expect(attachments[0].id).toBeDefined();
1324
- });
1325
-
1326
- test('generation_handoff includes assistant attachments', async () => {
1327
- const events1: ServerMessage[] = [];
1328
- const session = makeSession();
1329
- await session.loadFromDb();
1330
-
1331
- const p1 = session.processMessage('msg-1', [], (e) => events1.push(e), 'req-1');
1332
- await waitForPendingRun(1);
1333
-
1334
- // Queue a second message so the first run yields via checkpoint handoff.
1335
- session.enqueueMessage('msg-2', [], () => {}, 'req-2');
1336
-
1337
- const run = pendingRuns[0];
1338
- expect(run.onCheckpoint).toBeDefined();
1339
- expect(run.onCheckpoint!({ turnIndex: 0, toolCount: 1, hasToolUse: true })).toBe('yield');
1340
-
1341
- const assistantMsg: Message = {
1342
- role: 'assistant',
1343
- content: [{ type: 'text', text: 'Handing off with attachment.' }],
1344
- };
1345
- run.onEvent({
1346
- type: 'tool_result',
1347
- toolUseId: 'tool-1',
1348
- content: 'ok',
1349
- isError: false,
1350
- contentBlocks: [
1351
- // eslint-disable-next-line @typescript-eslint/no-explicit-any -- mock content block
1352
- { type: 'image', source: { type: 'base64', media_type: 'image/png', data: 'iVBORw0K' } } as any,
1353
- ],
1354
- });
1355
- run.onEvent({ type: 'usage', inputTokens: 10, outputTokens: 5, model: 'mock', providerDurationMs: 100 });
1356
- run.onEvent({ type: 'message_complete', message: assistantMsg });
1357
- run.resolve([...run.messages, assistantMsg]);
1358
-
1359
- await p1;
1360
-
1361
- const handoff = events1.find((e) => e.type === 'generation_handoff' && Array.isArray(e.attachments));
1362
- expect(handoff).toBeDefined();
1363
- const attachments = (handoff as { attachments: Array<{ mimeType: string; data: string; id?: string }> }).attachments;
1364
- expect(attachments).toHaveLength(1);
1365
- expect(attachments[0].mimeType).toBe('image/png');
1366
- expect(attachments[0].data).toBe('iVBORw0K');
1367
-
1368
- await waitForPendingRun(2);
1369
- resolveRun(1);
1370
- await new Promise((r) => setTimeout(r, 50));
1371
- });
1372
- });
1373
-
1374
- // ---------------------------------------------------------------------------
1375
- // Regression: cancel semantics + session/global error channel split
1376
- // ---------------------------------------------------------------------------
1377
-
1378
- describe('Regression: cancel semantics and error channel split', () => {
1379
- beforeEach(() => {
1380
- pendingRuns = [];
1381
- });
1382
-
1383
- test('user cancellation emits generation_cancelled, never session_error', async () => {
1384
- const msgEvents: ServerMessage[] = [];
1385
- const session = makeSession();
1386
- await session.loadFromDb();
1387
-
1388
- // Start processing a message — collect events from the per-message callback
1389
- const p1 = session.processMessage('msg-1', [], (e) => msgEvents.push(e), 'req-1');
1390
- await waitForPendingRun(1);
1391
-
1392
- // User cancels — sets the abort signal
1393
- session.abort();
1394
-
1395
- // Resolve the pending run so the abort-check path fires
1396
- resolveRun(0);
1397
- await p1;
1398
-
1399
- // generation_cancelled should be emitted via the per-message callback
1400
- const cancelEvent = msgEvents.find((e) => e.type === 'generation_cancelled');
1401
- expect(cancelEvent).toBeDefined();
1402
-
1403
- // session_error must never appear on cancel
1404
- const sessionErr = msgEvents.find((e) => e.type === 'session_error');
1405
- expect(sessionErr).toBeUndefined();
1406
- });
1407
-
1408
- test('post-processing failure still attempts turn-boundary commit', async () => {
1409
- const events: ServerMessage[] = [];
1410
- const session = makeSession();
1411
- await session.loadFromDb();
1412
- linkAttachmentShouldThrow = true;
1413
-
1414
- const p1 = session.processMessage('msg-1', [], (e) => events.push(e), 'req-1');
1415
- await waitForPendingRun(1);
1416
- const run = pendingRuns[0];
1417
- const assistantMsg: Message = {
1418
- role: 'assistant',
1419
- content: [{ type: 'text', text: 'attachment-trigger' }],
1420
- };
1421
- run.onEvent({
1422
- type: 'tool_result',
1423
- toolUseId: 'tool-1',
1424
- content: 'ok',
1425
- isError: false,
1426
- contentBlocks: [
1427
- // eslint-disable-next-line @typescript-eslint/no-explicit-any -- mock content block
1428
- { type: 'image', source: { type: 'base64', media_type: 'image/png', data: 'iVBORw0K' } } as any,
1429
- ],
1430
- });
1431
- run.onEvent({ type: 'usage', inputTokens: 10, outputTokens: 5, model: 'mock', providerDurationMs: 100 });
1432
- run.onEvent({ type: 'message_complete', message: assistantMsg });
1433
- run.resolve([...run.messages, assistantMsg]);
1434
- await p1;
1435
-
1436
- expect(turnCommitCalls).toHaveLength(1);
1437
- expect(turnCommitCalls[0]).toEqual({
1438
- workspaceDir: '/tmp',
1439
- sessionId: 'conv-1',
1440
- turnNumber: 1,
1441
- });
1442
- const err = events.find((e) => e.type === 'error');
1443
- expect(err).toBeDefined();
1444
- });
1445
-
1446
- test('provider failure during processing emits both session_error and generic error', async () => {
1447
- const allEvents: ServerMessage[] = [];
1448
- const session = makeSession();
1449
- await session.loadFromDb();
1450
-
1451
- const p1 = session.processMessage('msg-1', [], (e) => allEvents.push(e), 'req-1');
1452
- await waitForPendingRun(1);
1453
-
1454
- // Simulate a provider failure
1455
- pendingRuns[0].reject(new Error('Connection refused'));
1456
- await p1;
1457
-
1458
- // Should get session_error (structured)
1459
- const sessionErr = allEvents.find((e) => e.type === 'session_error');
1460
- expect(sessionErr).toBeDefined();
1461
-
1462
- // Should also get generic error for backward compatibility
1463
- const genericErr = allEvents.find((e) => e.type === 'error');
1464
- expect(genericErr).toBeDefined();
1465
- });
1466
-
1467
- test('cancel after queued messages produces no session_error for any queued entry', async () => {
1468
- const session = makeSession();
1469
- await session.loadFromDb();
1470
-
1471
- const eventsPerMsg: ServerMessage[][] = [[], [], []];
1472
-
1473
- session.processMessage('msg-1', [], (e) => eventsPerMsg[0].push(e), 'req-1');
1474
- await waitForPendingRun(1);
1475
-
1476
- session.enqueueMessage('msg-2', [], (e) => eventsPerMsg[1].push(e), 'req-2');
1477
- session.enqueueMessage('msg-3', [], (e) => eventsPerMsg[2].push(e), 'req-3');
1478
-
1479
- session.abort();
1480
-
1481
- // No queued message should have received session_error
1482
- for (const events of eventsPerMsg) {
1483
- const sessionErr = events.find((e) => e.type === 'session_error');
1484
- expect(sessionErr).toBeUndefined();
1485
- }
1486
- });
1487
-
1488
- test('commitTurnChanges never resolving within budget -> turn still completes and drains queue', async () => {
1489
- const session = makeSession();
1490
- await session.loadFromDb();
1491
-
1492
- turnCommitHangForever = true;
1493
-
1494
- try {
1495
- const events1: ServerMessage[] = [];
1496
- const events2: ServerMessage[] = [];
1497
-
1498
- // Start first message (promise intentionally not awaited — we test queue drain behavior)
1499
- const _p1 = session.processMessage('msg-1', [], (e) => events1.push(e), 'req-1');
1500
- await waitForPendingRun(1);
1501
-
1502
- // Enqueue a second message while the first is processing
1503
- session.enqueueMessage('msg-2', [], (e) => events2.push(e), 'req-2');
1504
-
1505
- // Complete the first agent loop run
1506
- resolveRun(0);
1507
-
1508
- // The turn should still complete (timeout fires) and drain the queue
1509
- // even though commitTurnChanges never resolves.
1510
- // The default turnCommitMaxWaitMs is 4000ms in the config mock,
1511
- // but the mock config doesn't set it, so it defaults to 4000ms.
1512
- // We wait for the second run to be registered, which proves the
1513
- // turn completed and the queue drained despite the hanging commit.
1514
- await waitForPendingRun(2, 10_000);
1515
-
1516
- // First message should have completed
1517
- const completion1 = events1.find((e) => e.type === 'message_complete');
1518
- expect(completion1).toBeDefined();
1519
-
1520
- // Second message should have been dequeued
1521
- const dequeued = events2.find((e) => e.type === 'message_dequeued');
1522
- expect(dequeued).toBeDefined();
1523
-
1524
- // The turn commit should have been called
1525
- expect(turnCommitCalls).toHaveLength(1);
1526
-
1527
- // Complete the second run so the test can clean up
1528
- turnCommitHangForever = false;
1529
- resolveRun(1);
1530
- await new Promise((r) => setTimeout(r, 50));
1531
- } finally {
1532
- turnCommitHangForever = false;
1533
- }
1534
- }, 15_000);
1535
- });