@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.
- package/Dockerfile +2 -0
- package/README.md +88 -2
- package/eslint.config.mjs +31 -0
- package/package.json +1 -1
- package/scripts/ipc/check-swift-decoder-drift.ts +4 -1
- package/scripts/ipc/generate-swift.ts +31 -2
- package/src/__tests__/__snapshots__/ipc-snapshot.test.ts.snap +438 -1
- package/src/__tests__/approval-conversation-turn.test.ts +214 -0
- package/src/__tests__/approval-hardcoded-copy-guard.test.ts +41 -0
- package/src/__tests__/approval-message-composer.test.ts +253 -0
- package/src/__tests__/browser-manager.test.ts +1 -0
- package/src/__tests__/call-conversation-messages.test.ts +130 -0
- package/src/__tests__/call-domain.test.ts +12 -2
- package/src/__tests__/call-orchestrator.test.ts +799 -249
- package/src/__tests__/call-pointer-messages.test.ts +148 -0
- package/src/__tests__/call-recovery.test.ts +3 -0
- package/src/__tests__/call-routes-http.test.ts +32 -2
- package/src/__tests__/call-store.test.ts +3 -0
- package/src/__tests__/channel-approval-routes.test.ts +1277 -98
- package/src/__tests__/channel-approval.test.ts +37 -0
- package/src/__tests__/channel-approvals.test.ts +36 -50
- package/src/__tests__/channel-guardian.test.ts +630 -22
- package/src/__tests__/channel-readiness-service.test.ts +324 -0
- package/src/__tests__/checker.test.ts +14 -7
- package/src/__tests__/clarification-resolver.test.ts +44 -24
- package/src/__tests__/commit-message-enrichment-service.test.ts +9 -4
- package/src/__tests__/computer-use-session-working-dir.test.ts +8 -0
- package/src/__tests__/config-schema.test.ts +14 -8
- package/src/__tests__/context-window-manager.test.ts +30 -2
- package/src/__tests__/contradiction-checker.test.ts +20 -5
- package/src/__tests__/credential-security-invariants.test.ts +7 -2
- package/src/__tests__/daemon-lifecycle.test.ts +13 -12
- package/src/__tests__/db-migration-rollback.test.ts +752 -0
- package/src/__tests__/dictation-mode-detection.test.ts +63 -0
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +2 -0
- package/src/__tests__/entity-search.test.ts +615 -0
- package/src/__tests__/fuzzy-match-property.test.ts +5 -5
- package/src/__tests__/guardian-action-store.test.ts +123 -0
- package/src/__tests__/guardian-action-sweep.test.ts +277 -0
- package/src/__tests__/guardian-dispatch.test.ts +389 -0
- package/src/__tests__/guardian-question-copy.test.ts +47 -0
- package/src/__tests__/handlers-telegram-config.test.ts +4 -2
- package/src/__tests__/handlers-twilio-config.test.ts +533 -0
- package/src/__tests__/intent-routing.test.ts +2 -0
- package/src/__tests__/ipc-snapshot.test.ts +291 -1
- package/src/__tests__/memory-upsert-concurrency.test.ts +828 -0
- package/src/__tests__/messaging-send-tool.test.ts +65 -0
- package/src/__tests__/model-intents.test.ts +96 -0
- package/src/__tests__/no-direct-anthropic-sdk-imports.test.ts +42 -0
- package/src/__tests__/oauth2-gateway-transport.test.ts +130 -0
- package/src/__tests__/onboarding-starter-tasks.test.ts +2 -0
- package/src/__tests__/provider-commit-message-generator.test.ts +89 -13
- package/src/__tests__/provider-error-scenarios.test.ts +621 -0
- package/src/__tests__/provider-fail-open-selection.test.ts +119 -0
- package/src/__tests__/qdrant-manager.test.ts +27 -20
- package/src/__tests__/relay-server.test.ts +779 -40
- package/src/__tests__/run-orchestrator-assistant-events.test.ts +6 -0
- package/src/__tests__/run-orchestrator.test.ts +42 -4
- package/src/__tests__/runtime-runs-http.test.ts +17 -1
- package/src/__tests__/runtime-runs.test.ts +16 -0
- package/src/__tests__/schedule-store.test.ts +18 -4
- package/src/__tests__/scheduler-recurrence.test.ts +13 -4
- package/src/__tests__/session-abort-tool-results.test.ts +6 -0
- package/src/__tests__/session-agent-loop.test.ts +857 -0
- package/src/__tests__/session-conflict-gate.test.ts +6 -0
- package/src/__tests__/session-pre-run-repair.test.ts +6 -0
- package/src/__tests__/session-profile-injection.test.ts +6 -0
- package/src/__tests__/session-provider-retry-repair.test.ts +6 -0
- package/src/__tests__/session-queue.test.ts +6 -0
- package/src/__tests__/session-runtime-assembly.test.ts +321 -13
- package/src/__tests__/session-slash-known.test.ts +6 -0
- package/src/__tests__/session-slash-queue.test.ts +6 -0
- package/src/__tests__/session-slash-unknown.test.ts +6 -0
- package/src/__tests__/session-surfaces-task-progress.test.ts +2 -0
- package/src/__tests__/session-tool-setup-app-refresh.test.ts +1 -0
- package/src/__tests__/session-tool-setup-memory-scope.test.ts +1 -0
- package/src/__tests__/session-tool-setup-side-effect-flag.test.ts +1 -0
- package/src/__tests__/session-workspace-injection.test.ts +6 -0
- package/src/__tests__/session-workspace-tool-tracking.test.ts +6 -0
- package/src/__tests__/skills.test.ts +2 -0
- package/src/__tests__/sms-messaging-provider.test.ts +126 -0
- package/src/__tests__/starter-task-flow.test.ts +2 -0
- package/src/__tests__/swarm-dag-pathological.test.ts +535 -0
- package/src/__tests__/system-prompt.test.ts +2 -0
- package/src/__tests__/task-management-tools.test.ts +2 -2
- package/src/__tests__/task-runner.test.ts +14 -4
- package/src/__tests__/terminal-tools.test.ts +25 -19
- package/src/__tests__/tool-execution-abort-cleanup.test.ts +545 -0
- package/src/__tests__/tool-executor-shell-integration.test.ts +11 -11
- package/src/__tests__/tool-executor.test.ts +23 -24
- package/src/__tests__/trust-store.test.ts +3 -3
- package/src/__tests__/twilio-rest.test.ts +29 -0
- package/src/__tests__/twilio-routes-elevenlabs.test.ts +3 -0
- package/src/__tests__/twilio-routes-twiml.test.ts +11 -0
- package/src/__tests__/twilio-routes.test.ts +167 -11
- package/src/__tests__/twitter-cli-error-shaping.test.ts +2 -2
- package/src/__tests__/user-reference.test.ts +2 -0
- package/src/__tests__/voice-quality.test.ts +222 -0
- package/src/__tests__/web-search.test.ts +46 -30
- package/src/__tests__/work-item-output.test.ts +110 -0
- package/src/agent/loop.ts +1 -1
- package/src/agent-heartbeat/agent-heartbeat-service.ts +2 -10
- package/src/amazon/client.ts +1418 -0
- package/src/amazon/request-extractor.ts +135 -0
- package/src/amazon/session.ts +109 -0
- package/src/autonomy/autonomy-store.ts +5 -5
- package/src/browser-extension-relay/client.ts +124 -0
- package/src/browser-extension-relay/protocol.ts +63 -0
- package/src/browser-extension-relay/server.ts +177 -0
- package/src/bundler/app-bundler.ts +3 -3
- package/src/bundler/bundle-signer.ts +1 -1
- package/src/bundler/signature-verifier.ts +1 -1
- package/src/calls/call-conversation-messages.ts +33 -0
- package/src/calls/call-domain.ts +114 -10
- package/src/calls/call-orchestrator.ts +268 -59
- package/src/calls/call-pointer-messages.ts +53 -0
- package/src/calls/call-recovery.ts +3 -8
- package/src/calls/call-store.ts +69 -87
- package/src/calls/elevenlabs-config.ts +3 -2
- package/src/calls/guardian-action-sweep.ts +105 -0
- package/src/calls/guardian-dispatch.ts +203 -0
- package/src/calls/guardian-question-copy.ts +133 -0
- package/src/calls/relay-server.ts +466 -8
- package/src/calls/speaker-identification.ts +1 -1
- package/src/calls/twilio-config.ts +22 -14
- package/src/calls/twilio-provider.ts +6 -4
- package/src/calls/twilio-rest.ts +308 -7
- package/src/calls/twilio-routes.ts +65 -12
- package/src/calls/types.ts +3 -1
- package/src/channels/types.ts +25 -0
- package/src/cli/amazon.ts +815 -0
- package/src/cli/config-commands.ts +2 -2
- package/src/cli/core-commands.ts +4 -3
- package/src/cli/influencer.ts +244 -0
- package/src/cli/map.ts +89 -6
- package/src/cli.ts +1 -1
- package/src/config/agent-schema.ts +171 -0
- package/src/config/bundled-skills/amazon/SKILL.md +127 -0
- package/src/config/bundled-skills/amazon/icon.svg +13 -0
- package/src/config/bundled-skills/api-mapping/SKILL.md +78 -0
- package/src/config/bundled-skills/browser/SKILL.md +1 -0
- package/src/config/bundled-skills/browser/TOOLS.json +17 -0
- package/src/config/bundled-skills/browser/tools/browser-wait-for-download.ts +25 -0
- package/src/config/bundled-skills/doordash/SKILL.md +51 -51
- package/src/config/bundled-skills/email-setup/SKILL.md +14 -5
- package/src/config/bundled-skills/google-oauth-setup/SKILL.md +183 -0
- package/src/config/bundled-skills/influencer/SKILL.md +144 -0
- package/src/config/bundled-skills/knowledge-graph/SKILL.md +15 -0
- package/src/config/bundled-skills/knowledge-graph/TOOLS.json +56 -0
- package/src/config/bundled-skills/knowledge-graph/tools/graph-query.ts +185 -0
- package/src/config/bundled-skills/macos-automation/icon.svg +12 -0
- package/src/config/bundled-skills/media-processing/SKILL.md +176 -0
- package/src/config/bundled-skills/media-processing/TOOLS.json +230 -0
- package/src/config/bundled-skills/media-processing/__tests__/concurrency-pool.test.ts +77 -0
- package/src/config/bundled-skills/media-processing/__tests__/cost-tracker.test.ts +69 -0
- package/src/config/bundled-skills/media-processing/__tests__/preprocess.test.ts +303 -0
- package/src/config/bundled-skills/media-processing/services/concurrency-pool.ts +55 -0
- package/src/config/bundled-skills/media-processing/services/cost-tracker.ts +86 -0
- package/src/config/bundled-skills/media-processing/services/gemini-map.ts +339 -0
- package/src/config/bundled-skills/media-processing/services/preprocess.ts +551 -0
- package/src/config/bundled-skills/media-processing/services/processing-pipeline.ts +259 -0
- package/src/config/bundled-skills/media-processing/services/reduce.ts +197 -0
- package/src/config/bundled-skills/media-processing/tools/analyze-keyframes.ts +136 -0
- package/src/config/bundled-skills/media-processing/tools/extract-keyframes.ts +59 -0
- package/src/config/bundled-skills/media-processing/tools/generate-clip.ts +195 -0
- package/src/config/bundled-skills/media-processing/tools/ingest-media.ts +197 -0
- package/src/config/bundled-skills/media-processing/tools/media-diagnostics.ts +143 -0
- package/src/config/bundled-skills/media-processing/tools/media-status.ts +75 -0
- package/src/config/bundled-skills/media-processing/tools/query-media-events.ts +65 -0
- package/src/config/bundled-skills/messaging/SKILL.md +33 -8
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +4 -7
- package/src/config/bundled-skills/messaging/tools/messaging-reply.ts +2 -1
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +5 -1
- package/src/config/bundled-skills/phone-calls/SKILL.md +88 -23
- package/src/config/bundled-skills/twitter/SKILL.md +19 -3
- package/src/config/bundled-skills/twitter/icon.svg +14 -0
- package/src/config/bundled-tool-registry.ts +310 -0
- package/src/config/calls-schema.ts +181 -0
- package/src/config/core-schema.ts +309 -0
- package/src/config/defaults.ts +28 -3
- package/src/config/env-registry.ts +162 -0
- package/src/config/env.ts +175 -0
- package/src/config/loader.ts +6 -6
- package/src/config/memory-schema.ts +528 -0
- package/src/config/sandbox-schema.ts +55 -0
- package/src/config/schema.ts +158 -1133
- package/src/config/skill-state.ts +1 -1
- package/src/config/skills-schema.ts +32 -0
- package/src/config/skills.ts +35 -24
- package/src/config/system-prompt.ts +131 -56
- package/src/config/templates/IDENTITY.md +2 -2
- package/src/config/templates/SOUL.md +1 -1
- package/src/config/types.ts +1 -0
- package/src/config/user-reference.ts +4 -9
- package/src/config/vellum-skills/catalog.json +6 -7
- package/src/config/vellum-skills/chatgpt-import/tools/chatgpt-import.ts +5 -1
- package/src/config/vellum-skills/slack-oauth-setup/SKILL.md +4 -3
- package/src/config/vellum-skills/sms-setup/SKILL.md +216 -0
- package/src/config/vellum-skills/twilio-setup/SKILL.md +40 -8
- package/src/context/window-manager.ts +27 -7
- package/src/daemon/approval-generators.ts +186 -0
- package/src/daemon/approved-devices-store.ts +140 -0
- package/src/daemon/assistant-attachments.ts +1 -1
- package/src/daemon/classifier.ts +35 -32
- package/src/daemon/config-watcher.ts +1 -1
- package/src/daemon/daemon-control.ts +217 -0
- package/src/daemon/handlers/apps.ts +2 -3
- package/src/daemon/handlers/config-channels.ts +158 -0
- package/src/daemon/handlers/config-inbox.ts +540 -0
- package/src/daemon/handlers/config-ingress.ts +231 -0
- package/src/daemon/handlers/config-integrations.ts +258 -0
- package/src/daemon/handlers/config-model.ts +143 -0
- package/src/daemon/handlers/config-parental.ts +163 -0
- package/src/daemon/handlers/config-scheduling.ts +172 -0
- package/src/daemon/handlers/config-slack.ts +92 -0
- package/src/daemon/handlers/config-telegram.ts +301 -0
- package/src/daemon/handlers/config-tools.ts +177 -0
- package/src/daemon/handlers/config-trust.ts +104 -0
- package/src/daemon/handlers/config-twilio.ts +1080 -0
- package/src/daemon/handlers/config.ts +53 -1689
- package/src/daemon/handlers/diagnostics.ts +1 -1
- package/src/daemon/handlers/dictation.ts +180 -0
- package/src/daemon/handlers/documents.ts +18 -32
- package/src/daemon/handlers/identity.ts +14 -23
- package/src/daemon/handlers/index.ts +11 -0
- package/src/daemon/handlers/misc.ts +3 -5
- package/src/daemon/handlers/pairing.ts +98 -0
- package/src/daemon/handlers/sessions.ts +56 -5
- package/src/daemon/handlers/shared.ts +6 -1
- package/src/daemon/handlers/skills.ts +1 -1
- package/src/daemon/handlers/twitter-auth.ts +2 -0
- package/src/daemon/handlers/work-items.ts +17 -9
- package/src/daemon/handlers/workspace-files.ts +4 -3
- package/src/daemon/install-cli-launchers.ts +113 -0
- package/src/daemon/ipc-contract/apps.ts +356 -0
- package/src/daemon/ipc-contract/browser.ts +74 -0
- package/src/daemon/ipc-contract/computer-use.ts +151 -0
- package/src/daemon/ipc-contract/diagnostics.ts +56 -0
- package/src/daemon/ipc-contract/documents.ts +74 -0
- package/src/daemon/ipc-contract/inbox.ts +209 -0
- package/src/daemon/ipc-contract/integrations.ts +284 -0
- package/src/daemon/ipc-contract/memory.ts +48 -0
- package/src/daemon/ipc-contract/messages.ts +211 -0
- package/src/daemon/ipc-contract/pairing.ts +45 -0
- package/src/daemon/ipc-contract/parental-control.ts +95 -0
- package/src/daemon/ipc-contract/schedules.ts +97 -0
- package/src/daemon/ipc-contract/sessions.ts +315 -0
- package/src/daemon/ipc-contract/shared.ts +42 -0
- package/src/daemon/ipc-contract/skills.ts +120 -0
- package/src/daemon/ipc-contract/subagents.ts +58 -0
- package/src/daemon/ipc-contract/surfaces.ts +250 -0
- package/src/daemon/ipc-contract/trust.ts +60 -0
- package/src/daemon/ipc-contract/work-items.ts +225 -0
- package/src/daemon/ipc-contract/workspace.ts +113 -0
- package/src/daemon/ipc-contract-inventory.json +70 -0
- package/src/daemon/ipc-contract-inventory.ts +55 -29
- package/src/daemon/ipc-contract.ts +229 -2426
- package/src/daemon/ipc-protocol.ts +1 -1
- package/src/daemon/ipc-validate.ts +7 -0
- package/src/daemon/lifecycle.ts +97 -377
- package/src/daemon/pairing-store.ts +177 -0
- package/src/daemon/providers-setup.ts +43 -0
- package/src/daemon/ride-shotgun-handler.ts +68 -3
- package/src/daemon/server.ts +66 -46
- package/src/daemon/session-agent-loop-handlers.ts +421 -0
- package/src/daemon/session-agent-loop.ts +117 -275
- package/src/daemon/session-dynamic-profile.ts +1 -1
- package/src/daemon/session-history.ts +1 -1
- package/src/daemon/session-media-retry.ts +1 -1
- package/src/daemon/session-messaging.ts +37 -2
- package/src/daemon/session-notifiers.ts +5 -25
- package/src/daemon/session-process.ts +99 -59
- package/src/daemon/session-queue-manager.ts +96 -4
- package/src/daemon/session-runtime-assembly.ts +199 -10
- package/src/daemon/session-surfaces.ts +19 -4
- package/src/daemon/session-tool-setup.ts +30 -30
- package/src/daemon/session-workspace.ts +1 -1
- package/src/daemon/session.ts +35 -2
- package/src/daemon/shutdown-handlers.ts +122 -0
- package/src/daemon/trace-emitter.ts +1 -1
- package/src/daemon/watch-handler.ts +36 -33
- package/src/doordash/cart-queries.ts +787 -0
- package/src/doordash/client.ts +144 -127
- package/src/doordash/order-queries.ts +85 -0
- package/src/doordash/queries.ts +10 -1308
- package/src/doordash/search-queries.ts +203 -0
- package/src/doordash/session.ts +3 -2
- package/src/doordash/store-queries.ts +246 -0
- package/src/doordash/types.ts +367 -0
- package/src/email/providers/agentmail.ts +2 -1
- package/src/email/providers/index.ts +3 -2
- package/src/email/service.ts +3 -2
- package/src/errors.ts +43 -0
- package/src/home-base/prebuilt/seed.ts +1 -1
- package/src/hooks/cli.ts +6 -5
- package/src/hooks/config.ts +6 -8
- package/src/hooks/discovery.ts +6 -5
- package/src/hooks/manager.ts +4 -3
- package/src/hooks/runner.ts +2 -2
- package/src/hooks/templates.ts +5 -5
- package/src/inbound/public-ingress-urls.ts +6 -4
- package/src/index.ts +4 -2
- package/src/influencer/client.ts +1104 -0
- package/src/instrument.ts +4 -3
- package/src/logfire.ts +4 -3
- package/src/memory/admin.ts +25 -35
- package/src/memory/attachments-store.ts +4 -7
- package/src/memory/channel-delivery-store.ts +30 -1
- package/src/memory/channel-guardian-store.ts +202 -2
- package/src/memory/clarification-resolver.ts +37 -33
- package/src/memory/conflict-store.ts +67 -61
- package/src/memory/contradiction-checker.ts +141 -117
- package/src/memory/conversation-store.ts +335 -51
- package/src/memory/db-connection.ts +27 -4
- package/src/memory/db-init.ts +265 -4
- package/src/memory/db.ts +14 -1
- package/src/memory/embedding-backend.ts +27 -5
- package/src/memory/embedding-ollama.ts +2 -1
- package/src/memory/entity-extractor.ts +38 -35
- package/src/memory/guardian-action-store.ts +430 -0
- package/src/memory/inbox-escalation-projection.ts +59 -0
- package/src/memory/inbox-thread-store.ts +218 -0
- package/src/memory/ingress-invite-store.ts +338 -0
- package/src/memory/ingress-member-store.ts +350 -0
- package/src/memory/items-extractor.ts +91 -97
- package/src/memory/job-handlers/index-maintenance.ts +3 -3
- package/src/memory/job-handlers/media-processing.ts +69 -0
- package/src/memory/job-handlers/summarization.ts +32 -26
- package/src/memory/job-utils.ts +3 -10
- package/src/memory/jobs-store.ts +8 -10
- package/src/memory/jobs-worker.ts +55 -36
- package/src/memory/media-store.ts +759 -0
- package/src/memory/migrations/001-job-deferrals.ts +45 -0
- package/src/memory/migrations/002-tool-invocations-fk.ts +43 -0
- package/src/memory/migrations/003-memory-fts-backfill.ts +24 -0
- package/src/memory/migrations/004-entity-relation-dedup.ts +87 -0
- package/src/memory/migrations/005-fingerprint-scope-unique.ts +80 -0
- package/src/memory/migrations/006-scope-salted-fingerprints.ts +62 -0
- package/src/memory/migrations/007-assistant-id-to-self.ts +254 -0
- package/src/memory/migrations/008-remove-assistant-id-columns.ts +208 -0
- package/src/memory/migrations/009-llm-usage-events-drop-assistant-id.ts +83 -0
- package/src/memory/migrations/010-ext-conv-bindings-channel-chat-unique.ts +56 -0
- package/src/memory/migrations/011-call-sessions-provider-sid-dedup.ts +63 -0
- package/src/memory/migrations/012-call-sessions-add-initiated-from.ts +19 -0
- package/src/memory/migrations/013-guardian-action-tables.ts +68 -0
- package/src/memory/migrations/014-backfill-inbox-thread-state.ts +76 -0
- package/src/memory/migrations/015-drop-active-search-index.ts +27 -0
- package/src/memory/migrations/016-memory-segments-indexes.ts +11 -0
- package/src/memory/migrations/017-memory-items-indexes.ts +10 -0
- package/src/memory/migrations/018-remaining-table-indexes.ts +13 -0
- package/src/memory/migrations/index.ts +24 -0
- package/src/memory/migrations/registry.ts +79 -0
- package/src/memory/migrations/validate-migration-state.ts +69 -0
- package/src/memory/qdrant-manager.ts +49 -8
- package/src/memory/query-builder.ts +1 -1
- package/src/memory/raw-query.ts +119 -0
- package/src/memory/recall-cache.ts +4 -1
- package/src/memory/retriever.ts +165 -47
- package/src/memory/schema-migration.ts +25 -984
- package/src/memory/schema.ts +228 -7
- package/src/memory/search/entity.ts +205 -31
- package/src/memory/search/lexical.ts +81 -52
- package/src/memory/search/ranking.ts +27 -23
- package/src/memory/search/semantic.ts +157 -19
- package/src/memory/search/types.ts +24 -0
- package/src/memory/shared-app-links-store.ts +4 -5
- package/src/memory/validation.ts +19 -0
- package/src/messaging/draft-store.ts +5 -6
- package/src/messaging/provider-types.ts +2 -0
- package/src/messaging/providers/sms/adapter.ts +201 -0
- package/src/messaging/providers/sms/client.ts +93 -0
- package/src/messaging/providers/sms/types.ts +7 -0
- package/src/messaging/providers/telegram-bot/adapter.ts +2 -5
- package/src/messaging/providers/whatsapp/adapter.ts +136 -0
- package/src/messaging/providers/whatsapp/client.ts +67 -0
- package/src/messaging/style-analyzer.ts +5 -4
- package/src/messaging/thread-summarizer.ts +61 -69
- package/src/messaging/triage-engine.ts +62 -71
- package/src/migrations/config-merge.ts +53 -0
- package/src/migrations/data-layout.ts +68 -0
- package/src/migrations/data-merge.ts +33 -0
- package/src/migrations/hooks-merge.ts +90 -0
- package/src/migrations/index.ts +6 -0
- package/src/migrations/log.ts +23 -0
- package/src/migrations/skills-merge.ts +33 -0
- package/src/migrations/workspace-layout.ts +79 -0
- package/src/permissions/checker.ts +133 -11
- package/src/permissions/prompter.ts +14 -0
- package/src/permissions/shell-identity.ts +31 -1
- package/src/permissions/trust-store.ts +21 -1
- package/src/providers/anthropic/client.ts +4 -4
- package/src/providers/failover.ts +2 -2
- package/src/providers/model-intents.ts +70 -0
- package/src/providers/ollama/client.ts +2 -1
- package/src/providers/provider-send-message.ts +176 -0
- package/src/providers/registry.ts +71 -30
- package/src/providers/retry.ts +35 -1
- package/src/providers/types.ts +12 -1
- package/src/runtime/approval-conversation-turn.ts +97 -0
- package/src/runtime/approval-message-composer.ts +253 -0
- package/src/runtime/channel-approval-parser.ts +36 -2
- package/src/runtime/channel-approvals.ts +11 -24
- package/src/runtime/channel-guardian-service.ts +88 -21
- package/src/runtime/channel-readiness-service.ts +418 -0
- package/src/runtime/channel-readiness-types.ts +35 -0
- package/src/runtime/channel-retry-sweep.ts +184 -0
- package/src/runtime/guardian-context-resolver.ts +108 -0
- package/src/runtime/http-server.ts +275 -717
- package/src/runtime/http-types.ts +59 -3
- package/src/runtime/middleware/auth.ts +116 -0
- package/src/runtime/middleware/error-handler.ts +33 -0
- package/src/runtime/middleware/twilio-validation.ts +127 -0
- package/src/runtime/routes/app-routes.ts +1 -1
- package/src/runtime/routes/call-routes.ts +51 -7
- package/src/runtime/routes/channel-delivery-routes.ts +170 -0
- package/src/runtime/routes/channel-guardian-routes.ts +1191 -0
- package/src/runtime/routes/channel-inbound-routes.ts +1152 -0
- package/src/runtime/routes/channel-route-shared.ts +144 -0
- package/src/runtime/routes/channel-routes.ts +32 -1588
- package/src/runtime/routes/conversation-routes.ts +50 -7
- package/src/runtime/routes/events-routes.ts +2 -2
- package/src/runtime/routes/identity-routes.ts +126 -0
- package/src/runtime/routes/pairing-routes.ts +143 -0
- package/src/runtime/routes/run-routes.ts +15 -1
- package/src/runtime/run-orchestrator.ts +86 -35
- package/src/schedule/schedule-store.ts +36 -32
- package/src/schedule/scheduler.ts +3 -3
- package/src/security/encrypted-store.ts +5 -7
- package/src/security/oauth2.ts +45 -15
- package/src/security/parental-control-store.ts +183 -0
- package/src/security/secret-allowlist.ts +4 -3
- package/src/security/secret-scanner.ts +5 -5
- package/src/security/secure-keys.ts +1 -1
- package/src/security/token-manager.ts +3 -2
- package/src/services/vercel-deploy.ts +6 -2
- package/src/skills/tool-manifest.ts +3 -3
- package/src/skills/vellum-catalog-remote.ts +75 -16
- package/src/slack/slack-webhook.ts +2 -1
- package/src/swarm/orchestrator.ts +92 -1
- package/src/swarm/router-planner.ts +6 -9
- package/src/swarm/worker-prompts.ts +9 -12
- package/src/tasks/task-compiler.ts +19 -28
- package/src/tasks/task-runner.ts +1 -1
- package/src/tools/assets/materialize.ts +2 -2
- package/src/tools/assets/search.ts +15 -14
- package/src/tools/browser/__tests__/auth-detector.test.ts +1 -0
- package/src/tools/browser/auto-navigate.ts +1 -0
- package/src/tools/browser/browser-execution.ts +10 -1
- package/src/tools/browser/browser-manager.ts +119 -4
- package/src/tools/browser/network-recorder.ts +5 -0
- package/src/tools/calls/call-start.ts +1 -0
- package/src/tools/credentials/broker.ts +11 -2
- package/src/tools/credentials/metadata-store.ts +18 -14
- package/src/tools/credentials/post-connect-hooks.ts +61 -0
- package/src/tools/credentials/vault.ts +49 -23
- package/src/tools/execution-target.ts +11 -1
- package/src/tools/executor.ts +68 -9
- package/src/tools/host-terminal/cli-discover.ts +1 -1
- package/src/tools/network/script-proxy/http-forwarder.ts +1 -1
- package/src/tools/network/script-proxy/mitm-handler.ts +1 -1
- package/src/tools/network/script-proxy/server.ts +1 -1
- package/src/tools/network/script-proxy/session-manager.ts +6 -5
- package/src/tools/network/web-fetch.ts +18 -2
- package/src/tools/network/web-search.ts +8 -4
- package/src/tools/reminder/reminder-store.ts +14 -15
- package/src/tools/schedule/create.ts +1 -0
- package/src/tools/schedule/list.ts +2 -1
- package/src/tools/shared/filesystem/file-ops-service.ts +5 -7
- package/src/tools/skills/skill-script-runner.ts +24 -9
- package/src/tools/skills/skill-tool-factory.ts +1 -0
- package/src/tools/tasks/work-item-enqueue.ts +2 -2
- package/src/tools/terminal/evaluate-typescript.ts +21 -12
- package/src/tools/terminal/parser.ts +50 -0
- package/src/tools/types.ts +2 -0
- package/src/tools/watcher/delete.ts +6 -0
- package/src/tools/weather/service.ts +1 -1
- package/src/twitter/client.ts +190 -24
- package/src/twitter/router.ts +1 -1
- package/src/twitter/session.ts +4 -3
- package/src/util/clipboard.ts +1 -1
- package/src/util/errors.ts +65 -8
- package/src/util/fs.ts +40 -0
- package/src/util/json.ts +10 -0
- package/src/util/log-redact.ts +189 -0
- package/src/util/logger.ts +19 -17
- package/src/util/object.ts +3 -0
- package/src/util/platform.ts +105 -363
- package/src/util/pricing.ts +1 -1
- package/src/util/promise-guard.ts +1 -1
- package/src/util/retry.ts +19 -0
- package/src/util/row-mapper.ts +79 -0
- package/src/util/silently.ts +21 -0
- package/src/watcher/engine.ts +5 -1
- package/src/watcher/provider-types.ts +20 -0
- package/src/watcher/providers/github.ts +156 -0
- package/src/watcher/providers/gmail.ts +1 -0
- package/src/watcher/providers/google-calendar.ts +1 -0
- package/src/watcher/providers/linear.ts +460 -0
- package/src/watcher/providers/slack.ts +1 -0
- package/src/work-items/work-item-runner.ts +1 -1
- package/src/workspace/git-service.ts +1 -1
- package/src/workspace/provider-commit-message-generator.ts +51 -22
- package/src/__tests__/call-bridge.test.ts +0 -517
- package/src/__tests__/session-process-bridge.test.ts +0 -244
- package/src/calls/call-bridge.ts +0 -168
- package/src/config/vellum-skills/google-oauth-setup/SKILL.md +0 -199
package/src/doordash/client.ts
CHANGED
|
@@ -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
|
|
231
|
+
throw new ProviderError(`Unexpected response from DoorDash API: ${msgs}`, 'doordash');
|
|
220
232
|
}
|
|
221
233
|
if (!json.data) {
|
|
222
|
-
throw new
|
|
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:
|
|
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:
|
|
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:
|
|
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 =
|
|
314
|
-
const summary =
|
|
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
|
|
331
|
+
const customStr = facet.custom;
|
|
320
332
|
if (!customStr) continue;
|
|
321
|
-
const custom = JSON.parse(customStr) as
|
|
322
|
-
const itemData = custom.item_data
|
|
333
|
+
const custom = JSON.parse(customStr) as DDRetailItemCustom;
|
|
334
|
+
const itemData = custom.item_data;
|
|
323
335
|
if (!itemData) continue;
|
|
324
|
-
const price = itemData.price
|
|
325
|
-
const image = custom.image
|
|
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
|
|
330
|
-
price: price?.display_string
|
|
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
|
|
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
|
|
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:
|
|
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 =
|
|
393
|
-
const rawCarousels =
|
|
404
|
+
const rawItemLists = feed.itemLists ?? [];
|
|
405
|
+
const rawCarousels = feed.carousels ?? [];
|
|
394
406
|
|
|
395
407
|
if (opts?.debug) {
|
|
396
|
-
const menuBook = feed.menuBook
|
|
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:
|
|
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 =
|
|
439
|
-
const collections =
|
|
440
|
-
const page = feed.page
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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:
|
|
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
|
|
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:
|
|
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:
|
|
777
|
+
function extractSearchResults(feed: DDFacetFeed | null | undefined): SearchResult[] {
|
|
760
778
|
const results: SearchResult[] = [];
|
|
761
|
-
if (!feed
|
|
762
|
-
const
|
|
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 =
|
|
782
|
+
const items = section.body ?? [];
|
|
766
783
|
for (const item of items) {
|
|
767
|
-
const text = item.text
|
|
768
|
-
const images = item.images
|
|
769
|
-
const events = item.events
|
|
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
|
|
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:
|
|
800
|
-
const header =
|
|
801
|
-
const menuBook =
|
|
802
|
-
const itemLists =
|
|
803
|
-
const address = header.address
|
|
804
|
-
const ratings = header.ratings
|
|
805
|
-
const deliveryFee = header.deliveryFeeLayout
|
|
806
|
-
const deliveryTime = header.deliveryTimeLayout
|
|
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 = (
|
|
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
|
|
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
|
|
821
|
-
price: item.displayPrice
|
|
822
|
-
imageUrl: item.imageUrl
|
|
823
|
-
storeId: item.storeId
|
|
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 =
|
|
846
|
+
const carousels = feed.carousels ?? [];
|
|
830
847
|
for (const carousel of carousels) {
|
|
831
|
-
for (const item of
|
|
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
|
|
836
|
-
price: item.displayPrice
|
|
837
|
-
imageUrl: item.imgUrl
|
|
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
|
|
862
|
+
description: header.description,
|
|
846
863
|
address: address?.displayAddress,
|
|
847
|
-
rating: ratings?.averageRating
|
|
848
|
-
numRatings: ratings?.numRatingsDisplayString
|
|
864
|
+
rating: ratings?.averageRating,
|
|
865
|
+
numRatings: ratings?.numRatingsDisplayString,
|
|
849
866
|
deliveryFee: deliveryFee?.title,
|
|
850
867
|
deliveryTime: deliveryTime?.title,
|
|
851
|
-
priceRange: header.priceRangeDisplayString
|
|
868
|
+
priceRange: header.priceRangeDisplayString,
|
|
852
869
|
categories,
|
|
853
870
|
items,
|
|
854
871
|
};
|
|
855
872
|
}
|
|
856
873
|
|
|
857
|
-
function extractNestedOptions(extrasList:
|
|
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: (
|
|
879
|
+
choices: (nested.options ?? []).map(o => ({
|
|
863
880
|
id: String(o.id),
|
|
864
881
|
name: String(o.name ?? ''),
|
|
865
|
-
price: o.displayString
|
|
882
|
+
price: o.displayString,
|
|
866
883
|
})),
|
|
867
884
|
}));
|
|
868
885
|
}
|
|
869
886
|
|
|
870
|
-
function extractItemDetails(page:
|
|
871
|
-
const header =
|
|
872
|
-
const optionLists =
|
|
873
|
-
const itemPreferences = page.itemPreferences
|
|
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
|
|
879
|
-
price: header.displayString
|
|
880
|
-
unitAmount: header.unitAmount
|
|
881
|
-
currency: header.currency
|
|
882
|
-
imageUrl: header.imgUrl
|
|
883
|
-
menuId: header.menuId
|
|
884
|
-
options: optionLists.map(ol => {
|
|
885
|
-
const choices = (
|
|
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
|
|
890
|
-
unitAmount: o.unitAmount
|
|
891
|
-
defaultQuantity: o.defaultQuantity
|
|
906
|
+
price: o.displayString,
|
|
907
|
+
unitAmount: o.unitAmount,
|
|
908
|
+
defaultQuantity: o.defaultQuantity,
|
|
892
909
|
};
|
|
893
|
-
const nestedExtrasList =
|
|
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
|
|
905
|
-
maxSelections: ol.maxNumOptions
|
|
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 =
|
|
929
|
+
const specialInstructions = itemPreferences.specialInstructions ?? {};
|
|
913
930
|
result.specialInstructionsConfig = {
|
|
914
931
|
maxLength: Number(specialInstructions.characterMaxLength ?? 500),
|
|
915
|
-
placeholderText: specialInstructions.placeholderText
|
|
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:
|
|
924
|
-
const storeDetails =
|
|
925
|
-
const storeHeader =
|
|
926
|
-
const ratings = storeHeader.ratings
|
|
927
|
-
const deliveryFee = storeHeader.deliveryFeeLayout
|
|
928
|
-
const status = storeHeader.status
|
|
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 =
|
|
931
|
-
const collections =
|
|
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 =
|
|
959
|
+
const products = collection.products ?? collection.items ?? [];
|
|
943
960
|
for (const item of products) {
|
|
944
|
-
const price = item.price
|
|
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
|
|
949
|
-
price:
|
|
950
|
-
imageUrl:
|
|
951
|
-
storeId: item.storeId
|
|
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
|
|
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
|
|
978
|
+
description: storeHeader.description,
|
|
962
979
|
address: address?.displayAddress,
|
|
963
|
-
rating: ratings?.averageRating
|
|
964
|
-
numRatings: ratings?.numRatingsDisplayString
|
|
980
|
+
rating: ratings?.averageRating,
|
|
981
|
+
numRatings: ratings?.numRatingsDisplayString,
|
|
965
982
|
deliveryFee: deliveryFee?.title,
|
|
966
|
-
deliveryTime: status?.delivery?.etaDisplayString
|
|
967
|
-
priceRange: storeHeader.priceRangeDisplayString
|
|
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:
|
|
975
|
-
const restaurant =
|
|
976
|
-
const orders =
|
|
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
|
|
981
|
-
const item =
|
|
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
|
|
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
|
|
994
|
-
storeId: restaurant.id
|
|
995
|
-
subtotal: cart.subtotal
|
|
996
|
-
total: cart.total
|
|
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
|
+
}`;
|