@vellumai/assistant 0.3.4 → 0.3.6

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 (506) hide show
  1. package/Dockerfile +2 -0
  2. package/README.md +88 -2
  3. package/eslint.config.mjs +31 -0
  4. package/package.json +1 -1
  5. package/scripts/ipc/check-swift-decoder-drift.ts +4 -1
  6. package/scripts/ipc/generate-swift.ts +31 -2
  7. package/src/__tests__/__snapshots__/ipc-snapshot.test.ts.snap +438 -1
  8. package/src/__tests__/approval-conversation-turn.test.ts +214 -0
  9. package/src/__tests__/approval-hardcoded-copy-guard.test.ts +41 -0
  10. package/src/__tests__/approval-message-composer.test.ts +253 -0
  11. package/src/__tests__/browser-manager.test.ts +1 -0
  12. package/src/__tests__/call-conversation-messages.test.ts +130 -0
  13. package/src/__tests__/call-domain.test.ts +12 -2
  14. package/src/__tests__/call-orchestrator.test.ts +799 -249
  15. package/src/__tests__/call-pointer-messages.test.ts +148 -0
  16. package/src/__tests__/call-recovery.test.ts +3 -0
  17. package/src/__tests__/call-routes-http.test.ts +32 -2
  18. package/src/__tests__/call-store.test.ts +3 -0
  19. package/src/__tests__/channel-approval-routes.test.ts +1277 -98
  20. package/src/__tests__/channel-approval.test.ts +37 -0
  21. package/src/__tests__/channel-approvals.test.ts +36 -50
  22. package/src/__tests__/channel-guardian.test.ts +630 -22
  23. package/src/__tests__/channel-readiness-service.test.ts +324 -0
  24. package/src/__tests__/checker.test.ts +14 -7
  25. package/src/__tests__/clarification-resolver.test.ts +44 -24
  26. package/src/__tests__/commit-message-enrichment-service.test.ts +9 -4
  27. package/src/__tests__/computer-use-session-working-dir.test.ts +8 -0
  28. package/src/__tests__/config-schema.test.ts +14 -8
  29. package/src/__tests__/context-window-manager.test.ts +30 -2
  30. package/src/__tests__/contradiction-checker.test.ts +20 -5
  31. package/src/__tests__/credential-security-invariants.test.ts +7 -2
  32. package/src/__tests__/daemon-lifecycle.test.ts +13 -12
  33. package/src/__tests__/db-migration-rollback.test.ts +752 -0
  34. package/src/__tests__/dictation-mode-detection.test.ts +63 -0
  35. package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +2 -0
  36. package/src/__tests__/entity-search.test.ts +615 -0
  37. package/src/__tests__/fuzzy-match-property.test.ts +5 -5
  38. package/src/__tests__/guardian-action-store.test.ts +123 -0
  39. package/src/__tests__/guardian-action-sweep.test.ts +277 -0
  40. package/src/__tests__/guardian-dispatch.test.ts +389 -0
  41. package/src/__tests__/guardian-question-copy.test.ts +47 -0
  42. package/src/__tests__/handlers-telegram-config.test.ts +4 -2
  43. package/src/__tests__/handlers-twilio-config.test.ts +533 -0
  44. package/src/__tests__/intent-routing.test.ts +2 -0
  45. package/src/__tests__/ipc-snapshot.test.ts +291 -1
  46. package/src/__tests__/memory-upsert-concurrency.test.ts +828 -0
  47. package/src/__tests__/messaging-send-tool.test.ts +65 -0
  48. package/src/__tests__/model-intents.test.ts +96 -0
  49. package/src/__tests__/no-direct-anthropic-sdk-imports.test.ts +42 -0
  50. package/src/__tests__/oauth2-gateway-transport.test.ts +130 -0
  51. package/src/__tests__/onboarding-starter-tasks.test.ts +2 -0
  52. package/src/__tests__/provider-commit-message-generator.test.ts +89 -13
  53. package/src/__tests__/provider-error-scenarios.test.ts +621 -0
  54. package/src/__tests__/provider-fail-open-selection.test.ts +119 -0
  55. package/src/__tests__/qdrant-manager.test.ts +27 -20
  56. package/src/__tests__/relay-server.test.ts +779 -40
  57. package/src/__tests__/run-orchestrator-assistant-events.test.ts +6 -0
  58. package/src/__tests__/run-orchestrator.test.ts +42 -4
  59. package/src/__tests__/runtime-runs-http.test.ts +17 -1
  60. package/src/__tests__/runtime-runs.test.ts +16 -0
  61. package/src/__tests__/schedule-store.test.ts +18 -4
  62. package/src/__tests__/scheduler-recurrence.test.ts +13 -4
  63. package/src/__tests__/session-abort-tool-results.test.ts +6 -0
  64. package/src/__tests__/session-agent-loop.test.ts +857 -0
  65. package/src/__tests__/session-conflict-gate.test.ts +6 -0
  66. package/src/__tests__/session-pre-run-repair.test.ts +6 -0
  67. package/src/__tests__/session-profile-injection.test.ts +6 -0
  68. package/src/__tests__/session-provider-retry-repair.test.ts +6 -0
  69. package/src/__tests__/session-queue.test.ts +6 -0
  70. package/src/__tests__/session-runtime-assembly.test.ts +321 -13
  71. package/src/__tests__/session-slash-known.test.ts +6 -0
  72. package/src/__tests__/session-slash-queue.test.ts +6 -0
  73. package/src/__tests__/session-slash-unknown.test.ts +6 -0
  74. package/src/__tests__/session-surfaces-task-progress.test.ts +2 -0
  75. package/src/__tests__/session-tool-setup-app-refresh.test.ts +1 -0
  76. package/src/__tests__/session-tool-setup-memory-scope.test.ts +1 -0
  77. package/src/__tests__/session-tool-setup-side-effect-flag.test.ts +1 -0
  78. package/src/__tests__/session-workspace-injection.test.ts +6 -0
  79. package/src/__tests__/session-workspace-tool-tracking.test.ts +6 -0
  80. package/src/__tests__/skills.test.ts +2 -0
  81. package/src/__tests__/sms-messaging-provider.test.ts +126 -0
  82. package/src/__tests__/starter-task-flow.test.ts +2 -0
  83. package/src/__tests__/swarm-dag-pathological.test.ts +535 -0
  84. package/src/__tests__/system-prompt.test.ts +2 -0
  85. package/src/__tests__/task-management-tools.test.ts +2 -2
  86. package/src/__tests__/task-runner.test.ts +14 -4
  87. package/src/__tests__/terminal-tools.test.ts +25 -19
  88. package/src/__tests__/tool-execution-abort-cleanup.test.ts +545 -0
  89. package/src/__tests__/tool-executor-shell-integration.test.ts +11 -11
  90. package/src/__tests__/tool-executor.test.ts +23 -24
  91. package/src/__tests__/trust-store.test.ts +3 -3
  92. package/src/__tests__/twilio-rest.test.ts +29 -0
  93. package/src/__tests__/twilio-routes-elevenlabs.test.ts +3 -0
  94. package/src/__tests__/twilio-routes-twiml.test.ts +11 -0
  95. package/src/__tests__/twilio-routes.test.ts +167 -11
  96. package/src/__tests__/twitter-cli-error-shaping.test.ts +2 -2
  97. package/src/__tests__/user-reference.test.ts +2 -0
  98. package/src/__tests__/voice-quality.test.ts +222 -0
  99. package/src/__tests__/web-search.test.ts +46 -30
  100. package/src/__tests__/work-item-output.test.ts +110 -0
  101. package/src/agent/loop.ts +1 -1
  102. package/src/agent-heartbeat/agent-heartbeat-service.ts +2 -10
  103. package/src/amazon/client.ts +1418 -0
  104. package/src/amazon/request-extractor.ts +135 -0
  105. package/src/amazon/session.ts +109 -0
  106. package/src/autonomy/autonomy-store.ts +5 -5
  107. package/src/browser-extension-relay/client.ts +124 -0
  108. package/src/browser-extension-relay/protocol.ts +63 -0
  109. package/src/browser-extension-relay/server.ts +177 -0
  110. package/src/bundler/app-bundler.ts +3 -3
  111. package/src/bundler/bundle-signer.ts +1 -1
  112. package/src/bundler/signature-verifier.ts +1 -1
  113. package/src/calls/call-conversation-messages.ts +33 -0
  114. package/src/calls/call-domain.ts +114 -10
  115. package/src/calls/call-orchestrator.ts +268 -59
  116. package/src/calls/call-pointer-messages.ts +53 -0
  117. package/src/calls/call-recovery.ts +3 -8
  118. package/src/calls/call-store.ts +69 -87
  119. package/src/calls/elevenlabs-config.ts +3 -2
  120. package/src/calls/guardian-action-sweep.ts +105 -0
  121. package/src/calls/guardian-dispatch.ts +203 -0
  122. package/src/calls/guardian-question-copy.ts +133 -0
  123. package/src/calls/relay-server.ts +466 -8
  124. package/src/calls/speaker-identification.ts +1 -1
  125. package/src/calls/twilio-config.ts +22 -14
  126. package/src/calls/twilio-provider.ts +6 -4
  127. package/src/calls/twilio-rest.ts +308 -7
  128. package/src/calls/twilio-routes.ts +65 -12
  129. package/src/calls/types.ts +3 -1
  130. package/src/channels/types.ts +25 -0
  131. package/src/cli/amazon.ts +815 -0
  132. package/src/cli/config-commands.ts +2 -2
  133. package/src/cli/core-commands.ts +4 -3
  134. package/src/cli/influencer.ts +244 -0
  135. package/src/cli/map.ts +89 -6
  136. package/src/cli.ts +1 -1
  137. package/src/config/agent-schema.ts +171 -0
  138. package/src/config/bundled-skills/amazon/SKILL.md +127 -0
  139. package/src/config/bundled-skills/amazon/icon.svg +13 -0
  140. package/src/config/bundled-skills/api-mapping/SKILL.md +78 -0
  141. package/src/config/bundled-skills/browser/SKILL.md +1 -0
  142. package/src/config/bundled-skills/browser/TOOLS.json +17 -0
  143. package/src/config/bundled-skills/browser/tools/browser-wait-for-download.ts +25 -0
  144. package/src/config/bundled-skills/doordash/SKILL.md +51 -51
  145. package/src/config/bundled-skills/email-setup/SKILL.md +14 -5
  146. package/src/config/bundled-skills/google-oauth-setup/SKILL.md +183 -0
  147. package/src/config/bundled-skills/influencer/SKILL.md +144 -0
  148. package/src/config/bundled-skills/knowledge-graph/SKILL.md +15 -0
  149. package/src/config/bundled-skills/knowledge-graph/TOOLS.json +56 -0
  150. package/src/config/bundled-skills/knowledge-graph/tools/graph-query.ts +185 -0
  151. package/src/config/bundled-skills/macos-automation/icon.svg +12 -0
  152. package/src/config/bundled-skills/media-processing/SKILL.md +176 -0
  153. package/src/config/bundled-skills/media-processing/TOOLS.json +230 -0
  154. package/src/config/bundled-skills/media-processing/__tests__/concurrency-pool.test.ts +77 -0
  155. package/src/config/bundled-skills/media-processing/__tests__/cost-tracker.test.ts +69 -0
  156. package/src/config/bundled-skills/media-processing/__tests__/preprocess.test.ts +303 -0
  157. package/src/config/bundled-skills/media-processing/services/concurrency-pool.ts +55 -0
  158. package/src/config/bundled-skills/media-processing/services/cost-tracker.ts +86 -0
  159. package/src/config/bundled-skills/media-processing/services/gemini-map.ts +339 -0
  160. package/src/config/bundled-skills/media-processing/services/preprocess.ts +551 -0
  161. package/src/config/bundled-skills/media-processing/services/processing-pipeline.ts +259 -0
  162. package/src/config/bundled-skills/media-processing/services/reduce.ts +197 -0
  163. package/src/config/bundled-skills/media-processing/tools/analyze-keyframes.ts +136 -0
  164. package/src/config/bundled-skills/media-processing/tools/extract-keyframes.ts +59 -0
  165. package/src/config/bundled-skills/media-processing/tools/generate-clip.ts +195 -0
  166. package/src/config/bundled-skills/media-processing/tools/ingest-media.ts +197 -0
  167. package/src/config/bundled-skills/media-processing/tools/media-diagnostics.ts +143 -0
  168. package/src/config/bundled-skills/media-processing/tools/media-status.ts +75 -0
  169. package/src/config/bundled-skills/media-processing/tools/query-media-events.ts +65 -0
  170. package/src/config/bundled-skills/messaging/SKILL.md +33 -8
  171. package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +4 -7
  172. package/src/config/bundled-skills/messaging/tools/messaging-reply.ts +2 -1
  173. package/src/config/bundled-skills/messaging/tools/messaging-send.ts +5 -1
  174. package/src/config/bundled-skills/phone-calls/SKILL.md +88 -23
  175. package/src/config/bundled-skills/twitter/SKILL.md +19 -3
  176. package/src/config/bundled-skills/twitter/icon.svg +14 -0
  177. package/src/config/bundled-tool-registry.ts +310 -0
  178. package/src/config/calls-schema.ts +181 -0
  179. package/src/config/core-schema.ts +309 -0
  180. package/src/config/defaults.ts +28 -3
  181. package/src/config/env-registry.ts +162 -0
  182. package/src/config/env.ts +175 -0
  183. package/src/config/loader.ts +6 -6
  184. package/src/config/memory-schema.ts +528 -0
  185. package/src/config/sandbox-schema.ts +55 -0
  186. package/src/config/schema.ts +158 -1133
  187. package/src/config/skill-state.ts +1 -1
  188. package/src/config/skills-schema.ts +32 -0
  189. package/src/config/skills.ts +35 -24
  190. package/src/config/system-prompt.ts +131 -56
  191. package/src/config/templates/IDENTITY.md +2 -2
  192. package/src/config/templates/SOUL.md +1 -1
  193. package/src/config/types.ts +1 -0
  194. package/src/config/user-reference.ts +4 -9
  195. package/src/config/vellum-skills/catalog.json +6 -7
  196. package/src/config/vellum-skills/chatgpt-import/tools/chatgpt-import.ts +5 -1
  197. package/src/config/vellum-skills/slack-oauth-setup/SKILL.md +4 -3
  198. package/src/config/vellum-skills/sms-setup/SKILL.md +216 -0
  199. package/src/config/vellum-skills/twilio-setup/SKILL.md +40 -8
  200. package/src/context/window-manager.ts +27 -7
  201. package/src/daemon/approval-generators.ts +186 -0
  202. package/src/daemon/approved-devices-store.ts +140 -0
  203. package/src/daemon/assistant-attachments.ts +1 -1
  204. package/src/daemon/classifier.ts +35 -32
  205. package/src/daemon/config-watcher.ts +1 -1
  206. package/src/daemon/daemon-control.ts +217 -0
  207. package/src/daemon/handlers/apps.ts +2 -3
  208. package/src/daemon/handlers/config-channels.ts +158 -0
  209. package/src/daemon/handlers/config-inbox.ts +540 -0
  210. package/src/daemon/handlers/config-ingress.ts +231 -0
  211. package/src/daemon/handlers/config-integrations.ts +258 -0
  212. package/src/daemon/handlers/config-model.ts +143 -0
  213. package/src/daemon/handlers/config-parental.ts +163 -0
  214. package/src/daemon/handlers/config-scheduling.ts +172 -0
  215. package/src/daemon/handlers/config-slack.ts +92 -0
  216. package/src/daemon/handlers/config-telegram.ts +301 -0
  217. package/src/daemon/handlers/config-tools.ts +177 -0
  218. package/src/daemon/handlers/config-trust.ts +104 -0
  219. package/src/daemon/handlers/config-twilio.ts +1080 -0
  220. package/src/daemon/handlers/config.ts +53 -1689
  221. package/src/daemon/handlers/diagnostics.ts +1 -1
  222. package/src/daemon/handlers/dictation.ts +180 -0
  223. package/src/daemon/handlers/documents.ts +18 -32
  224. package/src/daemon/handlers/identity.ts +14 -23
  225. package/src/daemon/handlers/index.ts +11 -0
  226. package/src/daemon/handlers/misc.ts +3 -5
  227. package/src/daemon/handlers/pairing.ts +98 -0
  228. package/src/daemon/handlers/sessions.ts +56 -5
  229. package/src/daemon/handlers/shared.ts +6 -1
  230. package/src/daemon/handlers/skills.ts +1 -1
  231. package/src/daemon/handlers/twitter-auth.ts +2 -0
  232. package/src/daemon/handlers/work-items.ts +17 -9
  233. package/src/daemon/handlers/workspace-files.ts +4 -3
  234. package/src/daemon/install-cli-launchers.ts +113 -0
  235. package/src/daemon/ipc-contract/apps.ts +356 -0
  236. package/src/daemon/ipc-contract/browser.ts +74 -0
  237. package/src/daemon/ipc-contract/computer-use.ts +151 -0
  238. package/src/daemon/ipc-contract/diagnostics.ts +56 -0
  239. package/src/daemon/ipc-contract/documents.ts +74 -0
  240. package/src/daemon/ipc-contract/inbox.ts +209 -0
  241. package/src/daemon/ipc-contract/integrations.ts +284 -0
  242. package/src/daemon/ipc-contract/memory.ts +48 -0
  243. package/src/daemon/ipc-contract/messages.ts +211 -0
  244. package/src/daemon/ipc-contract/pairing.ts +45 -0
  245. package/src/daemon/ipc-contract/parental-control.ts +95 -0
  246. package/src/daemon/ipc-contract/schedules.ts +97 -0
  247. package/src/daemon/ipc-contract/sessions.ts +315 -0
  248. package/src/daemon/ipc-contract/shared.ts +42 -0
  249. package/src/daemon/ipc-contract/skills.ts +120 -0
  250. package/src/daemon/ipc-contract/subagents.ts +58 -0
  251. package/src/daemon/ipc-contract/surfaces.ts +250 -0
  252. package/src/daemon/ipc-contract/trust.ts +60 -0
  253. package/src/daemon/ipc-contract/work-items.ts +225 -0
  254. package/src/daemon/ipc-contract/workspace.ts +113 -0
  255. package/src/daemon/ipc-contract-inventory.json +70 -0
  256. package/src/daemon/ipc-contract-inventory.ts +55 -29
  257. package/src/daemon/ipc-contract.ts +229 -2426
  258. package/src/daemon/ipc-protocol.ts +1 -1
  259. package/src/daemon/ipc-validate.ts +7 -0
  260. package/src/daemon/lifecycle.ts +97 -377
  261. package/src/daemon/pairing-store.ts +177 -0
  262. package/src/daemon/providers-setup.ts +43 -0
  263. package/src/daemon/ride-shotgun-handler.ts +68 -3
  264. package/src/daemon/server.ts +66 -46
  265. package/src/daemon/session-agent-loop-handlers.ts +421 -0
  266. package/src/daemon/session-agent-loop.ts +117 -275
  267. package/src/daemon/session-dynamic-profile.ts +1 -1
  268. package/src/daemon/session-history.ts +1 -1
  269. package/src/daemon/session-media-retry.ts +1 -1
  270. package/src/daemon/session-messaging.ts +37 -2
  271. package/src/daemon/session-notifiers.ts +5 -25
  272. package/src/daemon/session-process.ts +99 -59
  273. package/src/daemon/session-queue-manager.ts +96 -4
  274. package/src/daemon/session-runtime-assembly.ts +199 -10
  275. package/src/daemon/session-surfaces.ts +19 -4
  276. package/src/daemon/session-tool-setup.ts +30 -30
  277. package/src/daemon/session-workspace.ts +1 -1
  278. package/src/daemon/session.ts +35 -2
  279. package/src/daemon/shutdown-handlers.ts +122 -0
  280. package/src/daemon/trace-emitter.ts +1 -1
  281. package/src/daemon/watch-handler.ts +36 -33
  282. package/src/doordash/cart-queries.ts +787 -0
  283. package/src/doordash/client.ts +144 -127
  284. package/src/doordash/order-queries.ts +85 -0
  285. package/src/doordash/queries.ts +10 -1308
  286. package/src/doordash/search-queries.ts +203 -0
  287. package/src/doordash/session.ts +3 -2
  288. package/src/doordash/store-queries.ts +246 -0
  289. package/src/doordash/types.ts +367 -0
  290. package/src/email/providers/agentmail.ts +2 -1
  291. package/src/email/providers/index.ts +3 -2
  292. package/src/email/service.ts +3 -2
  293. package/src/errors.ts +43 -0
  294. package/src/home-base/prebuilt/seed.ts +1 -1
  295. package/src/hooks/cli.ts +6 -5
  296. package/src/hooks/config.ts +6 -8
  297. package/src/hooks/discovery.ts +6 -5
  298. package/src/hooks/manager.ts +4 -3
  299. package/src/hooks/runner.ts +2 -2
  300. package/src/hooks/templates.ts +5 -5
  301. package/src/inbound/public-ingress-urls.ts +6 -4
  302. package/src/index.ts +4 -2
  303. package/src/influencer/client.ts +1104 -0
  304. package/src/instrument.ts +4 -3
  305. package/src/logfire.ts +4 -3
  306. package/src/memory/admin.ts +25 -35
  307. package/src/memory/attachments-store.ts +4 -7
  308. package/src/memory/channel-delivery-store.ts +30 -1
  309. package/src/memory/channel-guardian-store.ts +202 -2
  310. package/src/memory/clarification-resolver.ts +37 -33
  311. package/src/memory/conflict-store.ts +67 -61
  312. package/src/memory/contradiction-checker.ts +141 -117
  313. package/src/memory/conversation-store.ts +335 -51
  314. package/src/memory/db-connection.ts +27 -4
  315. package/src/memory/db-init.ts +265 -4
  316. package/src/memory/db.ts +14 -1
  317. package/src/memory/embedding-backend.ts +27 -5
  318. package/src/memory/embedding-ollama.ts +2 -1
  319. package/src/memory/entity-extractor.ts +38 -35
  320. package/src/memory/guardian-action-store.ts +430 -0
  321. package/src/memory/inbox-escalation-projection.ts +59 -0
  322. package/src/memory/inbox-thread-store.ts +218 -0
  323. package/src/memory/ingress-invite-store.ts +338 -0
  324. package/src/memory/ingress-member-store.ts +350 -0
  325. package/src/memory/items-extractor.ts +91 -97
  326. package/src/memory/job-handlers/index-maintenance.ts +3 -3
  327. package/src/memory/job-handlers/media-processing.ts +69 -0
  328. package/src/memory/job-handlers/summarization.ts +32 -26
  329. package/src/memory/job-utils.ts +3 -10
  330. package/src/memory/jobs-store.ts +8 -10
  331. package/src/memory/jobs-worker.ts +55 -36
  332. package/src/memory/media-store.ts +759 -0
  333. package/src/memory/migrations/001-job-deferrals.ts +45 -0
  334. package/src/memory/migrations/002-tool-invocations-fk.ts +43 -0
  335. package/src/memory/migrations/003-memory-fts-backfill.ts +24 -0
  336. package/src/memory/migrations/004-entity-relation-dedup.ts +87 -0
  337. package/src/memory/migrations/005-fingerprint-scope-unique.ts +80 -0
  338. package/src/memory/migrations/006-scope-salted-fingerprints.ts +62 -0
  339. package/src/memory/migrations/007-assistant-id-to-self.ts +254 -0
  340. package/src/memory/migrations/008-remove-assistant-id-columns.ts +208 -0
  341. package/src/memory/migrations/009-llm-usage-events-drop-assistant-id.ts +83 -0
  342. package/src/memory/migrations/010-ext-conv-bindings-channel-chat-unique.ts +56 -0
  343. package/src/memory/migrations/011-call-sessions-provider-sid-dedup.ts +63 -0
  344. package/src/memory/migrations/012-call-sessions-add-initiated-from.ts +19 -0
  345. package/src/memory/migrations/013-guardian-action-tables.ts +68 -0
  346. package/src/memory/migrations/014-backfill-inbox-thread-state.ts +76 -0
  347. package/src/memory/migrations/015-drop-active-search-index.ts +27 -0
  348. package/src/memory/migrations/016-memory-segments-indexes.ts +11 -0
  349. package/src/memory/migrations/017-memory-items-indexes.ts +10 -0
  350. package/src/memory/migrations/018-remaining-table-indexes.ts +13 -0
  351. package/src/memory/migrations/index.ts +24 -0
  352. package/src/memory/migrations/registry.ts +79 -0
  353. package/src/memory/migrations/validate-migration-state.ts +69 -0
  354. package/src/memory/qdrant-manager.ts +49 -8
  355. package/src/memory/query-builder.ts +1 -1
  356. package/src/memory/raw-query.ts +119 -0
  357. package/src/memory/recall-cache.ts +4 -1
  358. package/src/memory/retriever.ts +165 -47
  359. package/src/memory/schema-migration.ts +25 -984
  360. package/src/memory/schema.ts +228 -7
  361. package/src/memory/search/entity.ts +205 -31
  362. package/src/memory/search/lexical.ts +81 -52
  363. package/src/memory/search/ranking.ts +27 -23
  364. package/src/memory/search/semantic.ts +157 -19
  365. package/src/memory/search/types.ts +24 -0
  366. package/src/memory/shared-app-links-store.ts +4 -5
  367. package/src/memory/validation.ts +19 -0
  368. package/src/messaging/draft-store.ts +5 -6
  369. package/src/messaging/provider-types.ts +2 -0
  370. package/src/messaging/providers/sms/adapter.ts +201 -0
  371. package/src/messaging/providers/sms/client.ts +93 -0
  372. package/src/messaging/providers/sms/types.ts +7 -0
  373. package/src/messaging/providers/telegram-bot/adapter.ts +2 -5
  374. package/src/messaging/providers/whatsapp/adapter.ts +136 -0
  375. package/src/messaging/providers/whatsapp/client.ts +67 -0
  376. package/src/messaging/style-analyzer.ts +5 -4
  377. package/src/messaging/thread-summarizer.ts +61 -69
  378. package/src/messaging/triage-engine.ts +62 -71
  379. package/src/migrations/config-merge.ts +53 -0
  380. package/src/migrations/data-layout.ts +68 -0
  381. package/src/migrations/data-merge.ts +33 -0
  382. package/src/migrations/hooks-merge.ts +90 -0
  383. package/src/migrations/index.ts +6 -0
  384. package/src/migrations/log.ts +23 -0
  385. package/src/migrations/skills-merge.ts +33 -0
  386. package/src/migrations/workspace-layout.ts +79 -0
  387. package/src/permissions/checker.ts +133 -11
  388. package/src/permissions/prompter.ts +14 -0
  389. package/src/permissions/shell-identity.ts +31 -1
  390. package/src/permissions/trust-store.ts +21 -1
  391. package/src/providers/anthropic/client.ts +4 -4
  392. package/src/providers/failover.ts +2 -2
  393. package/src/providers/model-intents.ts +70 -0
  394. package/src/providers/ollama/client.ts +2 -1
  395. package/src/providers/provider-send-message.ts +176 -0
  396. package/src/providers/registry.ts +71 -30
  397. package/src/providers/retry.ts +35 -1
  398. package/src/providers/types.ts +12 -1
  399. package/src/runtime/approval-conversation-turn.ts +97 -0
  400. package/src/runtime/approval-message-composer.ts +253 -0
  401. package/src/runtime/channel-approval-parser.ts +36 -2
  402. package/src/runtime/channel-approvals.ts +11 -24
  403. package/src/runtime/channel-guardian-service.ts +88 -21
  404. package/src/runtime/channel-readiness-service.ts +418 -0
  405. package/src/runtime/channel-readiness-types.ts +35 -0
  406. package/src/runtime/channel-retry-sweep.ts +184 -0
  407. package/src/runtime/guardian-context-resolver.ts +108 -0
  408. package/src/runtime/http-server.ts +275 -717
  409. package/src/runtime/http-types.ts +59 -3
  410. package/src/runtime/middleware/auth.ts +116 -0
  411. package/src/runtime/middleware/error-handler.ts +33 -0
  412. package/src/runtime/middleware/twilio-validation.ts +127 -0
  413. package/src/runtime/routes/app-routes.ts +1 -1
  414. package/src/runtime/routes/call-routes.ts +51 -7
  415. package/src/runtime/routes/channel-delivery-routes.ts +170 -0
  416. package/src/runtime/routes/channel-guardian-routes.ts +1191 -0
  417. package/src/runtime/routes/channel-inbound-routes.ts +1152 -0
  418. package/src/runtime/routes/channel-route-shared.ts +144 -0
  419. package/src/runtime/routes/channel-routes.ts +32 -1588
  420. package/src/runtime/routes/conversation-routes.ts +50 -7
  421. package/src/runtime/routes/events-routes.ts +2 -2
  422. package/src/runtime/routes/identity-routes.ts +126 -0
  423. package/src/runtime/routes/pairing-routes.ts +143 -0
  424. package/src/runtime/routes/run-routes.ts +15 -1
  425. package/src/runtime/run-orchestrator.ts +86 -35
  426. package/src/schedule/schedule-store.ts +36 -32
  427. package/src/schedule/scheduler.ts +3 -3
  428. package/src/security/encrypted-store.ts +5 -7
  429. package/src/security/oauth2.ts +45 -15
  430. package/src/security/parental-control-store.ts +183 -0
  431. package/src/security/secret-allowlist.ts +4 -3
  432. package/src/security/secret-scanner.ts +5 -5
  433. package/src/security/secure-keys.ts +1 -1
  434. package/src/security/token-manager.ts +3 -2
  435. package/src/services/vercel-deploy.ts +6 -2
  436. package/src/skills/tool-manifest.ts +3 -3
  437. package/src/skills/vellum-catalog-remote.ts +75 -16
  438. package/src/slack/slack-webhook.ts +2 -1
  439. package/src/swarm/orchestrator.ts +92 -1
  440. package/src/swarm/router-planner.ts +6 -9
  441. package/src/swarm/worker-prompts.ts +9 -12
  442. package/src/tasks/task-compiler.ts +19 -28
  443. package/src/tasks/task-runner.ts +1 -1
  444. package/src/tools/assets/materialize.ts +2 -2
  445. package/src/tools/assets/search.ts +15 -14
  446. package/src/tools/browser/__tests__/auth-detector.test.ts +1 -0
  447. package/src/tools/browser/auto-navigate.ts +1 -0
  448. package/src/tools/browser/browser-execution.ts +10 -1
  449. package/src/tools/browser/browser-manager.ts +119 -4
  450. package/src/tools/browser/network-recorder.ts +5 -0
  451. package/src/tools/calls/call-start.ts +1 -0
  452. package/src/tools/credentials/broker.ts +11 -2
  453. package/src/tools/credentials/metadata-store.ts +18 -14
  454. package/src/tools/credentials/post-connect-hooks.ts +61 -0
  455. package/src/tools/credentials/vault.ts +49 -23
  456. package/src/tools/execution-target.ts +11 -1
  457. package/src/tools/executor.ts +68 -9
  458. package/src/tools/host-terminal/cli-discover.ts +1 -1
  459. package/src/tools/network/script-proxy/http-forwarder.ts +1 -1
  460. package/src/tools/network/script-proxy/mitm-handler.ts +1 -1
  461. package/src/tools/network/script-proxy/server.ts +1 -1
  462. package/src/tools/network/script-proxy/session-manager.ts +6 -5
  463. package/src/tools/network/web-fetch.ts +18 -2
  464. package/src/tools/network/web-search.ts +8 -4
  465. package/src/tools/reminder/reminder-store.ts +14 -15
  466. package/src/tools/schedule/create.ts +1 -0
  467. package/src/tools/schedule/list.ts +2 -1
  468. package/src/tools/shared/filesystem/file-ops-service.ts +5 -7
  469. package/src/tools/skills/skill-script-runner.ts +24 -9
  470. package/src/tools/skills/skill-tool-factory.ts +1 -0
  471. package/src/tools/tasks/work-item-enqueue.ts +2 -2
  472. package/src/tools/terminal/evaluate-typescript.ts +21 -12
  473. package/src/tools/terminal/parser.ts +50 -0
  474. package/src/tools/types.ts +2 -0
  475. package/src/tools/watcher/delete.ts +6 -0
  476. package/src/tools/weather/service.ts +1 -1
  477. package/src/twitter/client.ts +190 -24
  478. package/src/twitter/router.ts +1 -1
  479. package/src/twitter/session.ts +4 -3
  480. package/src/util/clipboard.ts +1 -1
  481. package/src/util/errors.ts +65 -8
  482. package/src/util/fs.ts +40 -0
  483. package/src/util/json.ts +10 -0
  484. package/src/util/log-redact.ts +189 -0
  485. package/src/util/logger.ts +19 -17
  486. package/src/util/object.ts +3 -0
  487. package/src/util/platform.ts +105 -363
  488. package/src/util/pricing.ts +1 -1
  489. package/src/util/promise-guard.ts +1 -1
  490. package/src/util/retry.ts +19 -0
  491. package/src/util/row-mapper.ts +79 -0
  492. package/src/util/silently.ts +21 -0
  493. package/src/watcher/engine.ts +5 -1
  494. package/src/watcher/provider-types.ts +20 -0
  495. package/src/watcher/providers/github.ts +156 -0
  496. package/src/watcher/providers/gmail.ts +1 -0
  497. package/src/watcher/providers/google-calendar.ts +1 -0
  498. package/src/watcher/providers/linear.ts +460 -0
  499. package/src/watcher/providers/slack.ts +1 -0
  500. package/src/work-items/work-item-runner.ts +1 -1
  501. package/src/workspace/git-service.ts +1 -1
  502. package/src/workspace/provider-commit-message-generator.ts +51 -22
  503. package/src/__tests__/call-bridge.test.ts +0 -517
  504. package/src/__tests__/session-process-bridge.test.ts +0 -244
  505. package/src/calls/call-bridge.ts +0 -168
  506. package/src/config/vellum-skills/google-oauth-setup/SKILL.md +0 -199
@@ -25,6 +25,26 @@ import {
25
25
  } from './queries.js';
26
26
  import { loadCapturedQueries } from './query-extractor.js';
27
27
  import { truncate } from '../util/truncate.js';
28
+ import { ProviderError, RateLimitError } from '../util/errors.js';
29
+ import type {
30
+ DDFacetFeed,
31
+ DDSearchClickData,
32
+ DDStorepageFeed,
33
+ DDRetailStorePageFeed,
34
+ DDRetailSearchResult,
35
+ DDRetailItemCustom,
36
+ DDItemPage,
37
+ DDOptionChoice,
38
+ DDNestedExtra,
39
+ DDOptionList,
40
+ DDCart,
41
+ DDDropoffOption,
42
+ DDPaymentMethod,
43
+ DDCreateOrderResult,
44
+ DDMenuCategory,
45
+ } from './types.js';
46
+
47
+ export { RateLimitError };
28
48
 
29
49
  const GRAPHQL_BASE = 'https://www.doordash.com/graphql';
30
50
  const CDP_BASE = 'http://localhost:9222';
@@ -51,14 +71,6 @@ export class SessionExpiredError extends Error {
51
71
  }
52
72
  }
53
73
 
54
- /** Thrown when DoorDash returns HTTP 403 (rate limited). */
55
- export class RateLimitError extends Error {
56
- constructor(reason: string) {
57
- super(reason);
58
- this.name = 'RateLimitError';
59
- }
60
- }
61
-
62
74
  function requireSession(): DoorDashSession {
63
75
  const session = loadSession();
64
76
  if (!session) {
@@ -216,10 +228,10 @@ async function graphql<T = unknown>(
216
228
 
217
229
  if (json.errors?.length) {
218
230
  const msgs = json.errors.map(e => e.message || JSON.stringify(e)).join('; ');
219
- throw new Error(`Unexpected response from DoorDash API: ${msgs}`);
231
+ throw new ProviderError(`Unexpected response from DoorDash API: ${msgs}`, 'doordash');
220
232
  }
221
233
  if (!json.data) {
222
- throw new Error('Unexpected response format from DoorDash API');
234
+ throw new ProviderError('Unexpected response format from DoorDash API', 'doordash');
223
235
  }
224
236
  return json.data;
225
237
  } catch (err) {
@@ -251,7 +263,7 @@ export interface SearchResult {
251
263
  }
252
264
 
253
265
  export async function search(query: string): Promise<SearchResult[]> {
254
- const data = await graphql<{ autocompleteFacetFeed: unknown }>(
266
+ const data = await graphql<{ autocompleteFacetFeed: DDFacetFeed }>(
255
267
  'autocompleteFacetFeed',
256
268
  getQuery('autocompleteFacetFeed', SEARCH_QUERY),
257
269
  { query, serializedBundleGlobalSearchContext: null },
@@ -264,7 +276,7 @@ export async function search(query: string): Promise<SearchResult[]> {
264
276
  * This works for convenience/retail stores that don't expose menus through storepageFeed.
265
277
  */
266
278
  export async function searchItems(query: string, opts?: { debug?: boolean }): Promise<SearchResult[]> {
267
- const data = await graphql<{ homePageFacetFeed: unknown }>(
279
+ const data = await graphql<{ homePageFacetFeed: DDFacetFeed }>(
268
280
  'homePageFacetFeed',
269
281
  getQuery('homePageFacetFeed', HOME_PAGE_QUERY),
270
282
  {
@@ -292,7 +304,7 @@ export async function retailSearch(storeId: string, query: string, opts?: { limi
292
304
  totalCount: number;
293
305
  suggestedKeyword?: string;
294
306
  }> {
295
- const data = await graphql<{ retailSearch: Record<string, unknown> }>(
307
+ const data = await graphql<{ retailSearch: DDRetailSearchResult }>(
296
308
  'convenienceSearchQuery',
297
309
  getQuery('convenienceSearchQuery', RETAIL_SEARCH_QUERY),
298
310
  {
@@ -310,28 +322,28 @@ export async function retailSearch(storeId: string, query: string, opts?: { limi
310
322
  },
311
323
  );
312
324
  const result = data.retailSearch;
313
- const legoItems = (result.legoRetailItems ?? []) as Array<Record<string, unknown>>;
314
- const summary = (result.searchSummary ?? {}) as Record<string, unknown>;
325
+ const legoItems = result.legoRetailItems ?? [];
326
+ const summary = result.searchSummary ?? {};
315
327
 
316
328
  const items: MenuItem[] = [];
317
329
  for (const facet of legoItems) {
318
330
  try {
319
- const customStr = facet.custom as string | undefined;
331
+ const customStr = facet.custom;
320
332
  if (!customStr) continue;
321
- const custom = JSON.parse(customStr) as Record<string, unknown>;
322
- const itemData = custom.item_data as Record<string, unknown> | undefined;
333
+ const custom = JSON.parse(customStr) as DDRetailItemCustom;
334
+ const itemData = custom.item_data;
323
335
  if (!itemData) continue;
324
- const price = itemData.price as Record<string, unknown> | undefined;
325
- const image = custom.image as Record<string, Record<string, string>> | undefined;
336
+ const price = itemData.price;
337
+ const image = custom.image;
326
338
  items.push({
327
339
  id: String(itemData.item_id ?? ''),
328
340
  name: String(itemData.item_name ?? ''),
329
- description: itemData.description as string | undefined,
330
- price: price?.display_string as string | undefined,
341
+ description: itemData.description,
342
+ price: price?.display_string,
331
343
  imageUrl: image?.remote?.uri,
332
344
  storeId: String(itemData.store_id ?? ''),
333
345
  menuId: String(itemData.menu_id ?? ''),
334
- unitAmount: price?.unit_amount as number | undefined,
346
+ unitAmount: price?.unit_amount,
335
347
  });
336
348
  } catch { /* skip malformed entries */ }
337
349
  }
@@ -339,7 +351,7 @@ export async function retailSearch(storeId: string, query: string, opts?: { limi
339
351
  return {
340
352
  items,
341
353
  totalCount: Number(summary.totalCount ?? items.length),
342
- suggestedKeyword: summary.suggestedSearchKeyword as string | undefined,
354
+ suggestedKeyword: summary.suggestedSearchKeyword,
343
355
  };
344
356
  }
345
357
 
@@ -375,7 +387,7 @@ export async function getStoreMenu(
375
387
  menuId?: string,
376
388
  opts?: { debug?: boolean },
377
389
  ): Promise<StoreInfo> {
378
- const data = await graphql<{ storepageFeed: Record<string, unknown> }>(
390
+ const data = await graphql<{ storepageFeed: DDStorepageFeed }>(
379
391
  'storepageFeed',
380
392
  getQuery('storepageFeed', STORE_PAGE_QUERY),
381
393
  {
@@ -389,11 +401,11 @@ export async function getStoreMenu(
389
401
  },
390
402
  );
391
403
  const feed = data.storepageFeed;
392
- const rawItemLists = (feed.itemLists ?? []) as unknown[];
393
- const rawCarousels = (feed.carousels ?? []) as unknown[];
404
+ const rawItemLists = feed.itemLists ?? [];
405
+ const rawCarousels = feed.carousels ?? [];
394
406
 
395
407
  if (opts?.debug) {
396
- const menuBook = feed.menuBook as Record<string, unknown> | undefined;
408
+ const menuBook = feed.menuBook;
397
409
  process.stderr.write(
398
410
  `[debug] storepageFeed keys: ${Object.keys(feed).join(', ')}\n` +
399
411
  `[debug] itemLists count: ${rawItemLists.length}, carousels count: ${rawCarousels.length}\n` +
@@ -423,7 +435,7 @@ export async function getRetailStoreMenu(
423
435
  storeId: string,
424
436
  opts?: { debug?: boolean },
425
437
  ): Promise<StoreInfo> {
426
- const data = await graphql<{ retailStorePageFeed: Record<string, unknown> }>(
438
+ const data = await graphql<{ retailStorePageFeed: DDRetailStorePageFeed }>(
427
439
  'storeFeed',
428
440
  getQuery('storeFeed', RETAIL_STORE_FEED_QUERY),
429
441
  {
@@ -435,9 +447,9 @@ export async function getRetailStoreMenu(
435
447
  );
436
448
  if (opts?.debug) {
437
449
  const feed = data.retailStorePageFeed;
438
- const l1Cats = (feed.l1Categories ?? []) as unknown[];
439
- const collections = (feed.collections ?? []) as unknown[];
440
- const page = feed.page as Record<string, unknown> | undefined;
450
+ const l1Cats = feed.l1Categories ?? [];
451
+ const collections = feed.collections ?? [];
452
+ const page = feed.page;
441
453
  process.stderr.write(
442
454
  `[debug] retailStorePageFeed keys: ${Object.keys(feed).join(', ')}\n` +
443
455
  `[debug] l1Categories count: ${l1Cats.length}, collections count: ${collections.length}\n` +
@@ -492,7 +504,7 @@ export async function getItemDetails(
492
504
  storeId: string,
493
505
  itemId: string,
494
506
  ): Promise<ItemDetails> {
495
- const data = await graphql<{ itemPage: Record<string, unknown> }>(
507
+ const data = await graphql<{ itemPage: DDItemPage }>(
496
508
  'itemPage',
497
509
  getQuery('itemPage', ITEM_PAGE_QUERY),
498
510
  {
@@ -535,7 +547,7 @@ export async function addToCart(opts: {
535
547
  specialInstructions?: string;
536
548
  }): Promise<CartSummary> {
537
549
  // Use updateCartItemV2 — DoorDash now uses this for both adding and updating cart items
538
- const data = await graphql<{ updateCartItemV2: Record<string, unknown> }>(
550
+ const data = await graphql<{ updateCartItemV2: DDCart }>(
539
551
  'updateCartItem',
540
552
  getQuery('updateCartItem', UPDATE_CART_ITEM_QUERY),
541
553
  {
@@ -580,7 +592,7 @@ export async function removeFromCart(
580
592
  cartId: string,
581
593
  itemId: string,
582
594
  ): Promise<CartSummary> {
583
- const data = await graphql<{ removeCartItemV2: Record<string, unknown> }>(
595
+ const data = await graphql<{ removeCartItemV2: DDCart }>(
584
596
  'removeCartItem',
585
597
  getQuery('removeCartItem', REMOVE_CART_ITEM_QUERY),
586
598
  {
@@ -596,7 +608,7 @@ export async function removeFromCart(
596
608
  }
597
609
 
598
610
  export async function viewCart(cartId: string): Promise<CartSummary> {
599
- const data = await graphql<{ orderCart: Record<string, unknown> }>(
611
+ const data = await graphql<{ orderCart: DDCart }>(
600
612
  'detailedCartItems',
601
613
  getQuery('detailedCartItems', DETAILED_CART_QUERY),
602
614
  { orderCartId: cartId, isCardPayment: true },
@@ -605,7 +617,13 @@ export async function viewCart(cartId: string): Promise<CartSummary> {
605
617
  }
606
618
 
607
619
  export async function listCarts(storeId?: string): Promise<CartSummary[]> {
608
- const input: Record<string, unknown> = {
620
+ const input: {
621
+ cartFilter: { shouldIncludeSubmitted: boolean };
622
+ cartContextFilter?: {
623
+ experienceCase: string;
624
+ multiCartExperienceContext: { storeId: string };
625
+ };
626
+ } = {
609
627
  cartFilter: { shouldIncludeSubmitted: true },
610
628
  };
611
629
  if (storeId) {
@@ -614,7 +632,7 @@ export async function listCarts(storeId?: string): Promise<CartSummary[]> {
614
632
  multiCartExperienceContext: { storeId },
615
633
  };
616
634
  }
617
- const data = await graphql<{ listCarts: Record<string, unknown>[] }>(
635
+ const data = await graphql<{ listCarts: DDCart[] }>(
618
636
  'listCarts',
619
637
  getQuery('listCarts', LIST_CARTS_QUERY),
620
638
  { input },
@@ -634,7 +652,7 @@ export async function getDropoffOptions(
634
652
  addressId?: string,
635
653
  ): Promise<DropoffOption[]> {
636
654
  const data = await graphql<{
637
- dropoffOptions: Array<Record<string, unknown>>;
655
+ dropoffOptions: DDDropoffOption[];
638
656
  }>('dropoffOptions', getQuery('dropoffOptions', DROPOFF_OPTIONS_QUERY), {
639
657
  cartId,
640
658
  addressId: addressId ?? null,
@@ -656,7 +674,7 @@ export interface PaymentMethod {
656
674
  }
657
675
 
658
676
  export async function getPaymentMethods(): Promise<PaymentMethod[]> {
659
- const data = await graphql<{ getPaymentMethodList: Array<Record<string, unknown>> }>(
677
+ const data = await graphql<{ getPaymentMethodList: DDPaymentMethod[] }>(
660
678
  'paymentMethodQuery',
661
679
  getQuery('paymentMethodQuery', PAYMENT_METHODS_QUERY),
662
680
  {
@@ -696,7 +714,7 @@ export async function placeOrder(opts: {
696
714
  const methods = await getPaymentMethods();
697
715
  const defaultMethod = methods.find(m => m.isDefault) ?? methods[0];
698
716
  if (!defaultMethod) {
699
- throw new Error('No payment method found. Add a payment method in the DoorDash app first.');
717
+ throw new ProviderError('No payment method found. Add a payment method in the DoorDash app first.', 'doordash');
700
718
  }
701
719
  pmUuid = defaultMethod.uuid;
702
720
  // defaultMethod.type is the card brand (e.g. "Visa"), not the PaymentMethodType enum
@@ -708,7 +726,7 @@ export async function placeOrder(opts: {
708
726
  ? JSON.stringify([{ typename: 'DropoffPreference', option_id: opts.dropoffOptionId, is_default: true, instructions: '' }])
709
727
  : '[]';
710
728
 
711
- const data = await graphql<{ createOrderFromCart: Record<string, unknown> }>(
729
+ const data = await graphql<{ createOrderFromCart: DDCreateOrderResult }>(
712
730
  'createOrderFromCart',
713
731
  getQuery('createOrderFromCart', CREATE_ORDER_FROM_CART_QUERY),
714
732
  {
@@ -756,22 +774,21 @@ export async function placeOrder(opts: {
756
774
  // Response extraction helpers
757
775
  // ---------------------------------------------------------------------------
758
776
 
759
- function extractSearchResults(feed: unknown): SearchResult[] {
777
+ function extractSearchResults(feed: DDFacetFeed | null | undefined): SearchResult[] {
760
778
  const results: SearchResult[] = [];
761
- if (!feed || typeof feed !== 'object') return results;
762
- const f = feed as Record<string, unknown>;
763
- const bodies = (f.body ?? []) as Array<Record<string, unknown>>;
779
+ if (!feed) return results;
780
+ const bodies = feed.body ?? [];
764
781
  for (const section of bodies) {
765
- const items = (section.body ?? []) as Array<Record<string, unknown>>;
782
+ const items = section.body ?? [];
766
783
  for (const item of items) {
767
- const text = item.text as Record<string, string> | undefined;
768
- const images = item.images as Record<string, Record<string, string>> | undefined;
769
- const events = item.events as Record<string, Record<string, string>> | undefined;
784
+ const text = item.text;
785
+ const images = item.images;
786
+ const events = item.events;
770
787
  let storeId: string | undefined;
771
788
  // Try click event data first
772
789
  if (events?.click?.data) {
773
790
  try {
774
- const clickData = JSON.parse(events.click.data) as Record<string, unknown>;
791
+ const clickData = JSON.parse(events.click.data) as DDSearchClickData;
775
792
  storeId = String(clickData.store_id ?? clickData.storeId ?? '');
776
793
  } catch { /* ignore */ }
777
794
  }
@@ -796,16 +813,16 @@ function extractSearchResults(feed: unknown): SearchResult[] {
796
813
  return results;
797
814
  }
798
815
 
799
- function extractStoreInfo(feed: Record<string, unknown>): StoreInfo {
800
- const header = (feed.storeHeader ?? {}) as Record<string, unknown>;
801
- const menuBook = (feed.menuBook ?? {}) as Record<string, unknown>;
802
- const itemLists = (feed.itemLists ?? []) as Array<Record<string, unknown>>;
803
- const address = header.address as Record<string, string> | undefined;
804
- const ratings = header.ratings as Record<string, unknown> | undefined;
805
- const deliveryFee = header.deliveryFeeLayout as Record<string, string> | undefined;
806
- const deliveryTime = header.deliveryTimeLayout as Record<string, string> | undefined;
816
+ function extractStoreInfo(feed: DDStorepageFeed): StoreInfo {
817
+ const header = feed.storeHeader ?? {};
818
+ const menuBook = feed.menuBook ?? {};
819
+ const itemLists = feed.itemLists ?? [];
820
+ const address = header.address;
821
+ const ratings = header.ratings;
822
+ const deliveryFee = header.deliveryFeeLayout;
823
+ const deliveryTime = header.deliveryTimeLayout;
807
824
 
808
- const categories = ((menuBook.menuCategories ?? []) as Array<Record<string, unknown>>).map(c => ({
825
+ const categories = (menuBook.menuCategories ?? []).map((c: DDMenuCategory) => ({
809
826
  id: String(c.id),
810
827
  name: String(c.name),
811
828
  numItems: Number(c.numItems ?? 0),
@@ -813,28 +830,28 @@ function extractStoreInfo(feed: Record<string, unknown>): StoreInfo {
813
830
 
814
831
  const items: MenuItem[] = [];
815
832
  for (const list of itemLists) {
816
- for (const item of (list.items ?? []) as Array<Record<string, unknown>>) {
833
+ for (const item of list.items ?? []) {
817
834
  items.push({
818
835
  id: String(item.id),
819
836
  name: String(item.name ?? ''),
820
- description: item.description as string | undefined,
821
- price: item.displayPrice as string | undefined,
822
- imageUrl: item.imageUrl as string | undefined,
823
- storeId: item.storeId as string | undefined,
837
+ description: item.description,
838
+ price: item.displayPrice,
839
+ imageUrl: item.imageUrl,
840
+ storeId: item.storeId,
824
841
  });
825
842
  }
826
843
  }
827
844
 
828
845
  // Also extract from carousels (used by convenience/pharmacy stores)
829
- const carousels = (feed.carousels ?? []) as Array<Record<string, unknown>>;
846
+ const carousels = feed.carousels ?? [];
830
847
  for (const carousel of carousels) {
831
- for (const item of (carousel.items ?? []) as Array<Record<string, unknown>>) {
848
+ for (const item of carousel.items ?? []) {
832
849
  items.push({
833
850
  id: String(item.id),
834
851
  name: String(item.name ?? ''),
835
- description: item.description as string | undefined,
836
- price: item.displayPrice as string | undefined,
837
- imageUrl: item.imgUrl as string | undefined,
852
+ description: item.description,
853
+ price: item.displayPrice,
854
+ imageUrl: item.imgUrl,
838
855
  });
839
856
  }
840
857
  }
@@ -842,55 +859,55 @@ function extractStoreInfo(feed: Record<string, unknown>): StoreInfo {
842
859
  return {
843
860
  id: String(header.id ?? ''),
844
861
  name: String(header.name ?? ''),
845
- description: header.description as string | undefined,
862
+ description: header.description,
846
863
  address: address?.displayAddress,
847
- rating: ratings?.averageRating as number | undefined,
848
- numRatings: ratings?.numRatingsDisplayString as string | undefined,
864
+ rating: ratings?.averageRating,
865
+ numRatings: ratings?.numRatingsDisplayString,
849
866
  deliveryFee: deliveryFee?.title,
850
867
  deliveryTime: deliveryTime?.title,
851
- priceRange: header.priceRangeDisplayString as string | undefined,
868
+ priceRange: header.priceRangeDisplayString,
852
869
  categories,
853
870
  items,
854
871
  };
855
872
  }
856
873
 
857
- function extractNestedOptions(extrasList: Array<Record<string, unknown>>): ItemDetails['options'][number]['choices'][number]['nestedOptions'] {
874
+ function extractNestedOptions(extrasList: DDNestedExtra[]): ItemDetails['options'][number]['choices'][number]['nestedOptions'] {
858
875
  return extrasList.map(nested => ({
859
876
  id: String(nested.id),
860
877
  name: String(nested.name ?? ''),
861
878
  required: !nested.isOptional,
862
- choices: ((nested.options ?? []) as Array<Record<string, unknown>>).map(o => ({
879
+ choices: (nested.options ?? []).map(o => ({
863
880
  id: String(o.id),
864
881
  name: String(o.name ?? ''),
865
- price: o.displayString as string | undefined,
882
+ price: o.displayString,
866
883
  })),
867
884
  }));
868
885
  }
869
886
 
870
- function extractItemDetails(page: Record<string, unknown>): ItemDetails {
871
- const header = (page.itemHeader ?? {}) as Record<string, unknown>;
872
- const optionLists = (page.optionLists ?? []) as Array<Record<string, unknown>>;
873
- const itemPreferences = page.itemPreferences as Record<string, unknown> | undefined;
887
+ function extractItemDetails(page: DDItemPage): ItemDetails {
888
+ const header = page.itemHeader ?? {};
889
+ const optionLists = page.optionLists ?? [];
890
+ const itemPreferences = page.itemPreferences;
874
891
 
875
892
  const result: ItemDetails = {
876
893
  id: String(header.id ?? ''),
877
894
  name: String(header.name ?? ''),
878
- description: header.description as string | undefined,
879
- price: header.displayString as string | undefined,
880
- unitAmount: header.unitAmount as number | undefined,
881
- currency: header.currency as string | undefined,
882
- imageUrl: header.imgUrl as string | undefined,
883
- menuId: header.menuId as string | undefined,
884
- options: optionLists.map(ol => {
885
- const choices = ((ol.options ?? []) as Array<Record<string, unknown>>).map(o => {
895
+ description: header.description,
896
+ price: header.displayString,
897
+ unitAmount: header.unitAmount,
898
+ currency: header.currency,
899
+ imageUrl: header.imgUrl,
900
+ menuId: header.menuId,
901
+ options: optionLists.map((ol: DDOptionList) => {
902
+ const choices = (ol.options ?? []).map((o: DDOptionChoice) => {
886
903
  const choice: ItemDetails['options'][number]['choices'][number] = {
887
904
  id: String(o.id),
888
905
  name: String(o.name ?? ''),
889
- price: o.displayString as string | undefined,
890
- unitAmount: o.unitAmount as number | undefined,
891
- defaultQuantity: o.defaultQuantity as number | undefined,
906
+ price: o.displayString,
907
+ unitAmount: o.unitAmount,
908
+ defaultQuantity: o.defaultQuantity,
892
909
  };
893
- const nestedExtrasList = (o.nestedExtrasList ?? []) as Array<Record<string, unknown>>;
910
+ const nestedExtrasList = o.nestedExtrasList ?? [];
894
911
  if (nestedExtrasList.length > 0) {
895
912
  choice.nestedOptions = extractNestedOptions(nestedExtrasList);
896
913
  }
@@ -901,18 +918,18 @@ function extractItemDetails(page: Record<string, unknown>): ItemDetails {
901
918
  id: String(ol.id),
902
919
  name: String(ol.name ?? ''),
903
920
  required: !ol.isOptional,
904
- minSelections: ol.minNumOptions as number | undefined,
905
- maxSelections: ol.maxNumOptions as number | undefined,
921
+ minSelections: ol.minNumOptions,
922
+ maxSelections: ol.maxNumOptions,
906
923
  choices,
907
924
  };
908
925
  }),
909
926
  };
910
927
 
911
928
  if (itemPreferences) {
912
- const specialInstructions = (itemPreferences.specialInstructions ?? {}) as Record<string, unknown>;
929
+ const specialInstructions = itemPreferences.specialInstructions ?? {};
913
930
  result.specialInstructionsConfig = {
914
931
  maxLength: Number(specialInstructions.characterMaxLength ?? 500),
915
- placeholderText: specialInstructions.placeholderText as string | undefined,
932
+ placeholderText: specialInstructions.placeholderText,
916
933
  isEnabled: specialInstructions.isEnabled !== false,
917
934
  };
918
935
  }
@@ -920,15 +937,15 @@ function extractItemDetails(page: Record<string, unknown>): ItemDetails {
920
937
  return result;
921
938
  }
922
939
 
923
- function extractRetailStoreInfo(feed: Record<string, unknown>): StoreInfo {
924
- const storeDetails = (feed.storeDetails ?? {}) as Record<string, unknown>;
925
- const storeHeader = (storeDetails.storeHeader ?? {}) as Record<string, unknown>;
926
- const ratings = storeHeader.ratings as Record<string, unknown> | undefined;
927
- const deliveryFee = storeHeader.deliveryFeeLayout as Record<string, string> | undefined;
928
- const status = storeHeader.status as Record<string, Record<string, unknown>> | undefined;
940
+ function extractRetailStoreInfo(feed: DDRetailStorePageFeed): StoreInfo {
941
+ const storeDetails = feed.storeDetails ?? {};
942
+ const storeHeader = storeDetails.storeHeader ?? {};
943
+ const ratings = storeHeader.ratings;
944
+ const deliveryFee = storeHeader.deliveryFeeLayout;
945
+ const status = storeHeader.status;
929
946
 
930
- const l1Categories = (feed.l1Categories ?? []) as Array<Record<string, unknown>>;
931
- const collections = (feed.collections ?? []) as Array<Record<string, unknown>>;
947
+ const l1Categories = feed.l1Categories ?? [];
948
+ const collections = feed.collections ?? [];
932
949
 
933
950
  const categories = l1Categories.map(c => ({
934
951
  id: String(c.id),
@@ -939,61 +956,61 @@ function extractRetailStoreInfo(feed: Record<string, unknown>): StoreInfo {
939
956
  const items: MenuItem[] = [];
940
957
  for (const collection of collections) {
941
958
  // Retail collections use `products`, not `items`
942
- const products = (collection.products ?? collection.items ?? []) as Array<Record<string, unknown>>;
959
+ const products = collection.products ?? collection.items ?? [];
943
960
  for (const item of products) {
944
- const price = item.price as Record<string, unknown> | undefined;
961
+ const price = item.price;
945
962
  items.push({
946
963
  id: String(item.id),
947
964
  name: String(item.name ?? ''),
948
- description: item.description as string | undefined,
949
- price: (price?.displayString ?? item.displayPrice) as string | undefined,
950
- imageUrl: (item.imageUrl ?? item.imgUrl) as string | undefined,
951
- storeId: item.storeId as string | undefined,
965
+ description: item.description,
966
+ price: price?.displayString ?? item.displayPrice,
967
+ imageUrl: item.imageUrl ?? item.imgUrl,
968
+ storeId: item.storeId,
952
969
  });
953
970
  }
954
971
  }
955
972
 
956
- const address = storeHeader.address as Record<string, string> | undefined;
973
+ const address = storeHeader.address;
957
974
 
958
975
  return {
959
976
  id: String(storeDetails.id ?? ''),
960
977
  name: String(storeHeader.name ?? storeDetails.name ?? ''),
961
- description: storeHeader.description as string | undefined,
978
+ description: storeHeader.description,
962
979
  address: address?.displayAddress,
963
- rating: ratings?.averageRating as number | undefined,
964
- numRatings: ratings?.numRatingsDisplayString as string | undefined,
980
+ rating: ratings?.averageRating,
981
+ numRatings: ratings?.numRatingsDisplayString,
965
982
  deliveryFee: deliveryFee?.title,
966
- deliveryTime: status?.delivery?.etaDisplayString as string | undefined,
967
- priceRange: storeHeader.priceRangeDisplayString as string | undefined,
983
+ deliveryTime: status?.delivery?.etaDisplayString,
984
+ priceRange: storeHeader.priceRangeDisplayString,
968
985
  categories,
969
986
  items,
970
987
  isRetail: true,
971
988
  };
972
989
  }
973
990
 
974
- function extractCartSummary(cart: Record<string, unknown>): CartSummary {
975
- const restaurant = (cart.restaurant ?? {}) as Record<string, unknown>;
976
- const orders = (cart.orders ?? []) as Array<Record<string, unknown>>;
991
+ function extractCartSummary(cart: DDCart): CartSummary {
992
+ const restaurant = cart.restaurant ?? {};
993
+ const orders = cart.orders ?? [];
977
994
 
978
995
  const items: CartSummary['items'] = [];
979
996
  for (const order of orders) {
980
- for (const oi of (order.orderItems ?? []) as Array<Record<string, unknown>>) {
981
- const item = (oi.item ?? {}) as Record<string, unknown>;
997
+ for (const oi of order.orderItems ?? []) {
998
+ const item = oi.item ?? {};
982
999
  items.push({
983
1000
  id: String(oi.id ?? ''),
984
1001
  name: String(item.name ?? ''),
985
1002
  quantity: Number(oi.quantity ?? 1),
986
- price: oi.priceDisplayString as string | undefined,
1003
+ price: oi.priceDisplayString,
987
1004
  });
988
1005
  }
989
1006
  }
990
1007
 
991
1008
  return {
992
1009
  cartId: String(cart.id ?? ''),
993
- storeName: restaurant.name as string | undefined,
994
- storeId: restaurant.id as string | undefined,
995
- subtotal: cart.subtotal as number | undefined,
996
- total: cart.total as number | undefined,
1010
+ storeName: restaurant.name,
1011
+ storeId: restaurant.id,
1012
+ subtotal: cart.subtotal,
1013
+ total: cart.total,
997
1014
  items,
998
1015
  };
999
1016
  }
@@ -0,0 +1,85 @@
1
+ /**
2
+ * GraphQL queries for DoorDash checkout: order creation, delivery options, and payment methods.
3
+ * Each query is fully self-contained with all required fragment definitions.
4
+ */
5
+
6
+ // ---------------------------------------------------------------------------
7
+ // DROPOFF_OPTIONS_QUERY
8
+ // ---------------------------------------------------------------------------
9
+
10
+ export const DROPOFF_OPTIONS_QUERY = `
11
+ query dropoffOptions($cartId: ID, $addressId: ID) {
12
+ dropoffOptions(cartId: $cartId, addressId: $addressId) {
13
+ id displayString isDefault isEnabled placeholderText disabledMessage
14
+ proofOfDeliveryType __typename
15
+ }
16
+ }`;
17
+
18
+ // ---------------------------------------------------------------------------
19
+ // CREATE_ORDER_FROM_CART_QUERY
20
+ // ---------------------------------------------------------------------------
21
+
22
+ export const CREATE_ORDER_FROM_CART_QUERY = `
23
+ mutation createOrderFromCart($cartId: ID!, $total: Int!, $sosDeliveryFee: Int!, $isPickupOrder: Boolean!, $verifiedAgeRequirement: Boolean!, $deliveryTime: String!, $menuOptions: [String], $stripeToken: String, $attributionData: String, $fulfillsOwnDeliveries: Boolean, $budgetId: String, $teamId: String, $giftOptions: GiftOptionsInput, $recipientShippingDetails: RecipientShippingDetails, $storeId: String, $tipAmounts: [TipAmount!], $paymentMethod: Int, $deliveryOptionType: DeliveryOptionType, $workOrderOptions: WorkOrderOptionsInput, $isCardPayment: Boolean, $clientFraudContext: PaymentClientFraudContextInput, $programId: String, $membershipId: String, $dropoffPreferences: String, $routineReorderDetails: RoutineReorderDetails, $supplementalPaymentDetailsList: [SupplementalPaymentDetails!], $monitoringContext: CreateOrderFromCartMonitoringContextInput, $rewardBalanceApplied: RewardBalanceDetailsInput, $deliveryOptionInfo: DeliveryOptionInfo, $hasAccessibilityRequirements: Boolean, $shouldApplyCredits: Boolean, $dasherPickupInstructions: String, $paymentMethodUuid: String, $paymentMethodType: PaymentMethodType, $deviceTimezone: String, $paymentMethodBrand: String, $submitPlatform: String) {
24
+ createOrderFromCart(
25
+ cartId: $cartId
26
+ total: $total
27
+ sosDeliveryFee: $sosDeliveryFee
28
+ isPickupOrder: $isPickupOrder
29
+ verifiedAgeRequirement: $verifiedAgeRequirement
30
+ deliveryTime: $deliveryTime
31
+ menuOptions: $menuOptions
32
+ stripeToken: $stripeToken
33
+ attributionData: $attributionData
34
+ fulfillsOwnDeliveries: $fulfillsOwnDeliveries
35
+ budgetId: $budgetId
36
+ teamId: $teamId
37
+ giftOptions: $giftOptions
38
+ recipientShippingDetails: $recipientShippingDetails
39
+ storeId: $storeId
40
+ tipAmounts: $tipAmounts
41
+ paymentMethod: $paymentMethod
42
+ deliveryOptionType: $deliveryOptionType
43
+ workOrderOptions: $workOrderOptions
44
+ isCardPayment: $isCardPayment
45
+ clientFraudContext: $clientFraudContext
46
+ programId: $programId
47
+ membershipId: $membershipId
48
+ dropoffPreferences: $dropoffPreferences
49
+ routineReorderDetails: $routineReorderDetails
50
+ supplementalPaymentDetailsList: $supplementalPaymentDetailsList
51
+ monitoringContext: $monitoringContext
52
+ rewardBalanceApplied: $rewardBalanceApplied
53
+ deliveryOptionInfo: $deliveryOptionInfo
54
+ hasAccessibilityRequirements: $hasAccessibilityRequirements
55
+ shouldApplyCredits: $shouldApplyCredits
56
+ dasherPickupInstructions: $dasherPickupInstructions
57
+ paymentMethodUuid: $paymentMethodUuid
58
+ paymentMethodType: $paymentMethodType
59
+ deviceTimezone: $deviceTimezone
60
+ paymentMethodBrand: $paymentMethodBrand
61
+ submitPlatform: $submitPlatform
62
+ ) {
63
+ cartId
64
+ orderUuid
65
+ isFirstOrderCart
66
+ isFirstNewVerticalsOrderCart
67
+ __typename
68
+ }
69
+ }`;
70
+
71
+ // ---------------------------------------------------------------------------
72
+ // PAYMENT_METHODS_QUERY
73
+ // ---------------------------------------------------------------------------
74
+
75
+ export const PAYMENT_METHODS_QUERY = `
76
+ query paymentMethodQuery {
77
+ getPaymentMethodList {
78
+ id
79
+ type
80
+ last4
81
+ isDefault
82
+ paymentMethodUuid
83
+ __typename
84
+ }
85
+ }`;