@vellumai/assistant 0.3.5 → 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/README.md +51 -0
- 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 +18 -2
- package/src/__tests__/__snapshots__/ipc-snapshot.test.ts.snap +338 -1
- package/src/__tests__/approval-conversation-turn.test.ts +214 -0
- package/src/__tests__/browser-manager.test.ts +1 -0
- package/src/__tests__/call-conversation-messages.test.ts +130 -0
- package/src/__tests__/call-orchestrator.test.ts +752 -271
- 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 +5 -0
- package/src/__tests__/call-store.test.ts +3 -0
- package/src/__tests__/channel-approval-routes.test.ts +1260 -85
- package/src/__tests__/channel-approval.test.ts +37 -0
- package/src/__tests__/channel-approvals.test.ts +4 -65
- package/src/__tests__/channel-guardian.test.ts +556 -0
- package/src/__tests__/channel-readiness-service.test.ts +74 -7
- 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 +12 -7
- 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 +6 -2
- package/src/__tests__/db-migration-rollback.test.ts +752 -0
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +2 -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 +126 -0
- package/src/__tests__/intent-routing.test.ts +2 -0
- package/src/__tests__/ipc-snapshot.test.ts +228 -1
- package/src/__tests__/memory-upsert-concurrency.test.ts +828 -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 +2 -0
- package/src/__tests__/run-orchestrator.test.ts +20 -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 +237 -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 +2 -1
- 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 +141 -21
- 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 +45 -29
- 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 +106 -5
- package/src/calls/call-orchestrator.ts +252 -54
- 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 +7 -5
- package/src/calls/twilio-provider.ts +6 -4
- package/src/calls/twilio-rest.ts +40 -15
- package/src/calls/twilio-routes.ts +60 -45
- 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/macos-automation/icon.svg +12 -0
- package/src/config/bundled-skills/media-processing/SKILL.md +72 -95
- package/src/config/bundled-skills/media-processing/TOOLS.json +57 -147
- 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 +7 -9
- package/src/config/bundled-skills/media-processing/services/reduce.ts +197 -0
- package/src/config/bundled-skills/media-processing/tools/analyze-keyframes.ts +88 -253
- package/src/config/bundled-skills/media-processing/tools/extract-keyframes.ts +22 -153
- package/src/config/bundled-skills/media-processing/tools/generate-clip.ts +2 -2
- package/src/config/bundled-skills/media-processing/tools/media-diagnostics.ts +28 -51
- package/src/config/bundled-skills/media-processing/tools/query-media-events.ts +35 -270
- package/src/config/bundled-skills/messaging/SKILL.md +12 -2
- 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/phone-calls/SKILL.md +86 -21
- 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 +26 -2
- 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 +156 -1137
- 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 +107 -56
- 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 +0 -7
- package/src/config/vellum-skills/chatgpt-import/tools/chatgpt-import.ts +5 -1
- package/src/config/vellum-skills/slack-oauth-setup/SKILL.md +1 -0
- package/src/config/vellum-skills/sms-setup/SKILL.md +112 -14
- 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 -2463
- package/src/daemon/handlers/diagnostics.ts +1 -1
- package/src/daemon/handlers/dictation.ts +4 -6
- package/src/daemon/handlers/documents.ts +18 -32
- package/src/daemon/handlers/index.ts +9 -0
- package/src/daemon/handlers/misc.ts +3 -5
- package/src/daemon/handlers/pairing.ts +98 -0
- package/src/daemon/handlers/sessions.ts +54 -5
- package/src/daemon/handlers/shared.ts +3 -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 +2 -2
- 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 +60 -0
- package/src/daemon/ipc-contract-inventory.ts +55 -29
- package/src/daemon/ipc-contract.ts +226 -2527
- package/src/daemon/ipc-protocol.ts +1 -1
- package/src/daemon/ipc-validate.ts +7 -0
- package/src/daemon/lifecycle.ts +97 -379
- package/src/daemon/pairing-store.ts +177 -0
- package/src/daemon/providers-setup.ts +43 -0
- package/src/daemon/ride-shotgun-handler.ts +67 -2
- package/src/daemon/server.ts +60 -44
- package/src/daemon/session-agent-loop-handlers.ts +421 -0
- package/src/daemon/session-agent-loop.ts +113 -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 +149 -15
- package/src/daemon/session-surfaces.ts +19 -4
- package/src/daemon/session-tool-setup.ts +28 -30
- package/src/daemon/session-workspace.ts +1 -1
- package/src/daemon/session.ts +24 -1
- 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 +3 -1
- 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 +200 -1
- 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 +121 -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 +11 -42
- package/src/memory/job-handlers/summarization.ts +32 -26
- package/src/memory/job-utils.ts +3 -10
- package/src/memory/jobs-store.ts +6 -9
- package/src/memory/jobs-worker.ts +51 -36
- 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 +160 -47
- package/src/memory/schema-migration.ts +25 -984
- package/src/memory/schema.ts +130 -7
- package/src/memory/search/entity.ts +10 -19
- package/src/memory/search/lexical.ts +81 -52
- package/src/memory/search/ranking.ts +21 -22
- package/src/memory/search/semantic.ts +157 -19
- 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/providers/sms/adapter.ts +3 -6
- 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 +119 -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 +115 -5
- package/src/runtime/channel-approval-parser.ts +36 -2
- package/src/runtime/channel-approvals.ts +0 -21
- package/src/runtime/channel-guardian-service.ts +48 -7
- package/src/runtime/channel-readiness-service.ts +160 -34
- package/src/runtime/channel-readiness-types.ts +10 -4
- 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 -743
- package/src/runtime/http-types.ts +56 -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 +49 -6
- 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 -1634
- 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 +52 -34
- 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/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/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/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 +7 -3
- 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/watcher/delete.ts +6 -0
- package/src/tools/weather/service.ts +1 -1
- package/src/twitter/client.ts +190 -24
- 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 +72 -365
- 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/bundled-skills/media-processing/services/capability-registry.ts +0 -137
- package/src/config/bundled-skills/media-processing/services/event-detection-service.ts +0 -280
- package/src/config/bundled-skills/media-processing/services/feedback-aggregation.ts +0 -144
- package/src/config/bundled-skills/media-processing/services/feedback-store.ts +0 -136
- package/src/config/bundled-skills/media-processing/services/retrieval-service.ts +0 -95
- package/src/config/bundled-skills/media-processing/services/timeline-service.ts +0 -267
- package/src/config/bundled-skills/media-processing/tools/detect-events.ts +0 -110
- package/src/config/bundled-skills/media-processing/tools/recalibrate.ts +0 -235
- package/src/config/bundled-skills/media-processing/tools/select-tracking-profile.ts +0 -142
- package/src/config/bundled-skills/media-processing/tools/submit-feedback.ts +0 -150
- package/src/config/vellum-skills/google-oauth-setup/SKILL.md +0 -199
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* before it is sent to the provider. They are pure (no side effects).
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
+
import type { ChannelId, TurnChannelContext } from '../channels/types.js';
|
|
8
9
|
import type { Message } from '../providers/types.js';
|
|
9
10
|
import { listAppFiles, getAppsDir } from '../memory/app-store.js';
|
|
10
11
|
import { statSync } from 'node:fs';
|
|
@@ -15,7 +16,7 @@ import { join } from 'node:path';
|
|
|
15
16
|
* interacting. Used to gate UI-specific references and permission asks.
|
|
16
17
|
*/
|
|
17
18
|
export interface ChannelCapabilities {
|
|
18
|
-
/** The raw channel identifier (e.g. "
|
|
19
|
+
/** The raw channel identifier (e.g. "macos", "telegram", "sms"). */
|
|
19
20
|
channel: string;
|
|
20
21
|
/** Whether this channel can render the dashboard UI (apps, dynamic pages). */
|
|
21
22
|
dashboardCapable: boolean;
|
|
@@ -27,7 +28,7 @@ export interface ChannelCapabilities {
|
|
|
27
28
|
|
|
28
29
|
/** Guardian identity/trust context for external chat channels. */
|
|
29
30
|
export interface GuardianRuntimeContext {
|
|
30
|
-
sourceChannel:
|
|
31
|
+
sourceChannel: ChannelId;
|
|
31
32
|
actorRole: 'guardian' | 'non-guardian' | 'unverified_channel';
|
|
32
33
|
guardianChatId?: string;
|
|
33
34
|
guardianExternalUserId?: string;
|
|
@@ -39,14 +40,35 @@ export interface GuardianRuntimeContext {
|
|
|
39
40
|
|
|
40
41
|
/** Derive channel capabilities from a raw source channel identifier. */
|
|
41
42
|
export function resolveChannelCapabilities(sourceChannel?: string | null): ChannelCapabilities {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
43
|
+
// Normalise legacy pseudo-channel IDs to canonical ChannelId values.
|
|
44
|
+
let channel: string;
|
|
45
|
+
switch (sourceChannel) {
|
|
46
|
+
case null:
|
|
47
|
+
case undefined:
|
|
48
|
+
case 'dashboard':
|
|
49
|
+
case 'http-api':
|
|
50
|
+
case 'mac':
|
|
51
|
+
channel = 'macos';
|
|
52
|
+
break;
|
|
53
|
+
default:
|
|
54
|
+
channel = sourceChannel;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
switch (channel) {
|
|
58
|
+
case 'macos':
|
|
59
|
+
return { channel, dashboardCapable: true, supportsDynamicUi: true, supportsVoiceInput: true };
|
|
60
|
+
case 'ios':
|
|
61
|
+
return { channel, dashboardCapable: false, supportsDynamicUi: false, supportsVoiceInput: true };
|
|
62
|
+
case 'telegram':
|
|
63
|
+
case 'sms':
|
|
64
|
+
case 'voice':
|
|
65
|
+
case 'whatsapp':
|
|
66
|
+
case 'slack':
|
|
67
|
+
case 'email':
|
|
68
|
+
return { channel, dashboardCapable: false, supportsDynamicUi: false, supportsVoiceInput: false };
|
|
69
|
+
default:
|
|
70
|
+
return { channel, dashboardCapable: false, supportsDynamicUi: false, supportsVoiceInput: false };
|
|
71
|
+
}
|
|
50
72
|
}
|
|
51
73
|
|
|
52
74
|
/** Context about the active workspace surface, passed to applyRuntimeInjections. */
|
|
@@ -276,11 +298,82 @@ export function injectChannelCapabilityContext(message: Message, caps: ChannelCa
|
|
|
276
298
|
};
|
|
277
299
|
}
|
|
278
300
|
|
|
301
|
+
/** Channel command intent metadata (e.g. Telegram /start). */
|
|
302
|
+
export interface ChannelCommandContext {
|
|
303
|
+
type: string;
|
|
304
|
+
payload?: string;
|
|
305
|
+
languageCode?: string;
|
|
306
|
+
}
|
|
307
|
+
|
|
279
308
|
/**
|
|
280
|
-
* Prepend
|
|
281
|
-
* model
|
|
309
|
+
* Prepend channel command context to the last user message so the
|
|
310
|
+
* model knows this turn was triggered by a channel command (e.g. /start).
|
|
282
311
|
*/
|
|
283
|
-
export function
|
|
312
|
+
export function injectChannelCommandContext(message: Message, ctx: ChannelCommandContext): Message {
|
|
313
|
+
const lines: string[] = ['<channel_command_context>'];
|
|
314
|
+
lines.push(`command_type: ${ctx.type}`);
|
|
315
|
+
if (ctx.payload) {
|
|
316
|
+
lines.push(`payload: ${ctx.payload}`);
|
|
317
|
+
}
|
|
318
|
+
if (ctx.languageCode) {
|
|
319
|
+
lines.push(`language_code: ${ctx.languageCode}`);
|
|
320
|
+
}
|
|
321
|
+
lines.push('</channel_command_context>');
|
|
322
|
+
|
|
323
|
+
const block = lines.join('\n');
|
|
324
|
+
return {
|
|
325
|
+
...message,
|
|
326
|
+
content: [
|
|
327
|
+
{ type: 'text', text: block },
|
|
328
|
+
...message.content,
|
|
329
|
+
],
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// ---------------------------------------------------------------------------
|
|
334
|
+
// Channel turn context injection
|
|
335
|
+
// ---------------------------------------------------------------------------
|
|
336
|
+
|
|
337
|
+
/** Parameters for building the channel turn context block. */
|
|
338
|
+
export interface ChannelTurnContextParams {
|
|
339
|
+
turnContext: TurnChannelContext;
|
|
340
|
+
conversationOriginChannel: ChannelId | null;
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* Build the `<channel_turn_context>` text block that informs the model
|
|
345
|
+
* which channels are active for the current turn and the conversation's
|
|
346
|
+
* origin channel.
|
|
347
|
+
*/
|
|
348
|
+
export function buildChannelTurnContextBlock(params: ChannelTurnContextParams): string {
|
|
349
|
+
const { turnContext, conversationOriginChannel } = params;
|
|
350
|
+
const lines: string[] = ['<channel_turn_context>'];
|
|
351
|
+
lines.push(`user_message_channel: ${turnContext.userMessageChannel}`);
|
|
352
|
+
lines.push(`assistant_message_channel: ${turnContext.assistantMessageChannel}`);
|
|
353
|
+
lines.push(`conversation_origin_channel: ${conversationOriginChannel ?? 'unknown'}`);
|
|
354
|
+
lines.push('</channel_turn_context>');
|
|
355
|
+
return lines.join('\n');
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Prepend channel turn context to the last user message so the model
|
|
360
|
+
* knows which channels are involved in this turn.
|
|
361
|
+
*/
|
|
362
|
+
export function injectChannelTurnContext(message: Message, params: ChannelTurnContextParams): Message {
|
|
363
|
+
const block = buildChannelTurnContextBlock(params);
|
|
364
|
+
return {
|
|
365
|
+
...message,
|
|
366
|
+
content: [
|
|
367
|
+
{ type: 'text', text: block },
|
|
368
|
+
...message.content,
|
|
369
|
+
],
|
|
370
|
+
};
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
/**
|
|
374
|
+
* Build the `<guardian_context>` text block used for model grounding.
|
|
375
|
+
*/
|
|
376
|
+
export function buildGuardianContextBlock(ctx: GuardianRuntimeContext): string {
|
|
284
377
|
const lines: string[] = ['<guardian_context>'];
|
|
285
378
|
lines.push(`source_channel: ${ctx.sourceChannel}`);
|
|
286
379
|
lines.push(`actor_role: ${ctx.actorRole}`);
|
|
@@ -291,8 +384,15 @@ export function injectGuardianContext(message: Message, ctx: GuardianRuntimeCont
|
|
|
291
384
|
lines.push(`requester_chat_id: ${ctx.requesterChatId ?? 'unknown'}`);
|
|
292
385
|
lines.push(`denial_reason: ${ctx.denialReason ?? 'none'}`);
|
|
293
386
|
lines.push('</guardian_context>');
|
|
387
|
+
return lines.join('\n');
|
|
388
|
+
}
|
|
294
389
|
|
|
295
|
-
|
|
390
|
+
/**
|
|
391
|
+
* Prepend guardian trust/identity facts to the last user message so the
|
|
392
|
+
* model can reason about guardian status from deterministic runtime facts.
|
|
393
|
+
*/
|
|
394
|
+
export function injectGuardianContext(message: Message, ctx: GuardianRuntimeContext): Message {
|
|
395
|
+
const block = buildGuardianContextBlock(ctx);
|
|
296
396
|
return {
|
|
297
397
|
...message,
|
|
298
398
|
content: [
|
|
@@ -324,7 +424,7 @@ export function stripUserTextBlocksByPrefix(messages: Message[], prefixes: strin
|
|
|
324
424
|
if (nextContent.length === message.content.length) return message;
|
|
325
425
|
if (nextContent.length === 0) return null;
|
|
326
426
|
return { ...message, content: nextContent };
|
|
327
|
-
}).filter((message): message is NonNullable<typeof message> => message
|
|
427
|
+
}).filter((message): message is NonNullable<typeof message> => message != null);
|
|
328
428
|
}
|
|
329
429
|
|
|
330
430
|
// ---------------------------------------------------------------------------
|
|
@@ -398,9 +498,21 @@ export function stripActiveSurfaceContext(messages: Message[]): Message[] {
|
|
|
398
498
|
// Declarative strip pipeline
|
|
399
499
|
// ---------------------------------------------------------------------------
|
|
400
500
|
|
|
501
|
+
/** Strip `<channel_command_context>` blocks injected by `injectChannelCommandContext`. */
|
|
502
|
+
export function stripChannelCommandContext(messages: Message[]): Message[] {
|
|
503
|
+
return stripUserTextBlocksByPrefix(messages, ['<channel_command_context>']);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
/** Strip `<channel_turn_context>` blocks injected by `injectChannelTurnContext`. */
|
|
507
|
+
export function stripChannelTurnContext(messages: Message[]): Message[] {
|
|
508
|
+
return stripUserTextBlocksByPrefix(messages, ['<channel_turn_context>']);
|
|
509
|
+
}
|
|
510
|
+
|
|
401
511
|
/** Prefixes stripped by the pipeline (order doesn't matter — single pass). */
|
|
402
512
|
const RUNTIME_INJECTION_PREFIXES = [
|
|
403
513
|
'<channel_capabilities>',
|
|
514
|
+
'<channel_command_context>',
|
|
515
|
+
'<channel_turn_context>',
|
|
404
516
|
'<guardian_context>',
|
|
405
517
|
'<workspace_top_level>',
|
|
406
518
|
TEMPORAL_INJECTED_PREFIX,
|
|
@@ -442,6 +554,8 @@ export function applyRuntimeInjections(
|
|
|
442
554
|
activeSurface?: ActiveSurfaceContext | null;
|
|
443
555
|
workspaceTopLevelContext?: string | null;
|
|
444
556
|
channelCapabilities?: ChannelCapabilities | null;
|
|
557
|
+
channelCommandContext?: ChannelCommandContext | null;
|
|
558
|
+
channelTurnContext?: ChannelTurnContextParams | null;
|
|
445
559
|
guardianContext?: GuardianRuntimeContext | null;
|
|
446
560
|
temporalContext?: string | null;
|
|
447
561
|
},
|
|
@@ -478,6 +592,26 @@ export function applyRuntimeInjections(
|
|
|
478
592
|
}
|
|
479
593
|
}
|
|
480
594
|
|
|
595
|
+
if (options.channelCommandContext) {
|
|
596
|
+
const userTail = result[result.length - 1];
|
|
597
|
+
if (userTail && userTail.role === 'user') {
|
|
598
|
+
result = [
|
|
599
|
+
...result.slice(0, -1),
|
|
600
|
+
injectChannelCommandContext(userTail, options.channelCommandContext),
|
|
601
|
+
];
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
if (options.channelTurnContext) {
|
|
606
|
+
const userTail = result[result.length - 1];
|
|
607
|
+
if (userTail && userTail.role === 'user') {
|
|
608
|
+
result = [
|
|
609
|
+
...result.slice(0, -1),
|
|
610
|
+
injectChannelTurnContext(userTail, options.channelTurnContext),
|
|
611
|
+
];
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
|
|
481
615
|
if (options.guardianContext) {
|
|
482
616
|
const userTail = result[result.length - 1];
|
|
483
617
|
if (userTail && userTail.role === 'user') {
|
|
@@ -17,16 +17,13 @@ import {
|
|
|
17
17
|
getPrebuiltHomeBasePreview,
|
|
18
18
|
findSeededHomeBaseApp,
|
|
19
19
|
} from '../home-base/prebuilt/seed.js';
|
|
20
|
+
import { isPlainObject } from '../util/object.js';
|
|
20
21
|
|
|
21
22
|
const log = getLogger('session-surfaces');
|
|
22
23
|
|
|
23
24
|
const MAX_UNDO_DEPTH = 10;
|
|
24
25
|
const TASK_PROGRESS_TEMPLATE_FIELDS = ['title', 'status', 'steps'] as const;
|
|
25
26
|
|
|
26
|
-
function isPlainObject(value: unknown): value is Record<string, unknown> {
|
|
27
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
27
|
function normalizeCardShowData(input: Record<string, unknown>, rawData: Record<string, unknown>): CardSurfaceData {
|
|
31
28
|
const normalized: Record<string, unknown> = { ...rawData };
|
|
32
29
|
|
|
@@ -128,6 +125,24 @@ export interface SurfaceSessionContext {
|
|
|
128
125
|
onEvent: (msg: ServerMessage) => void,
|
|
129
126
|
requestId?: string,
|
|
130
127
|
): Promise<string>;
|
|
128
|
+
/** Serialize operations on a given surface to prevent read-modify-write races. */
|
|
129
|
+
withSurface<T>(surfaceId: string, fn: () => T | Promise<T>): Promise<T>;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Per-surface async mutex using Promise chaining.
|
|
134
|
+
* Operations on the same surfaceId are serialized; different surfaces run concurrently.
|
|
135
|
+
*/
|
|
136
|
+
export function createSurfaceMutex(): <T>(surfaceId: string, fn: () => T | Promise<T>) => Promise<T> {
|
|
137
|
+
const chains = new Map<string, Promise<void>>();
|
|
138
|
+
|
|
139
|
+
return <T>(surfaceId: string, fn: () => T | Promise<T>): Promise<T> => {
|
|
140
|
+
const prev = chains.get(surfaceId) ?? Promise.resolve();
|
|
141
|
+
const next = prev.then(fn, fn);
|
|
142
|
+
// Keep the chain alive but swallow errors so one failure doesn't block subsequent ops
|
|
143
|
+
chains.set(surfaceId, next.then(() => {}, () => {}));
|
|
144
|
+
return next;
|
|
145
|
+
};
|
|
131
146
|
}
|
|
132
147
|
|
|
133
148
|
/**
|
|
@@ -15,6 +15,7 @@ import type { SecretPrompter } from '../permissions/secret-prompter.js';
|
|
|
15
15
|
import { addRule, findHighestPriorityRule } from '../permissions/trust-store.js';
|
|
16
16
|
import { generateAllowlistOptions, generateScopeOptions, normalizeWebFetchUrl } from '../permissions/checker.js';
|
|
17
17
|
import { getLogger } from '../util/logger.js';
|
|
18
|
+
import { isPlainObject } from '../util/object.js';
|
|
18
19
|
|
|
19
20
|
const log = getLogger('session-tool-setup');
|
|
20
21
|
import { getAllToolDefinitions } from '../tools/registry.js';
|
|
@@ -77,22 +78,21 @@ export function buildToolDefinitions(): ToolDefinition[] {
|
|
|
77
78
|
|
|
78
79
|
// ── DoorDash task_progress auto-update ────────────────────────────────
|
|
79
80
|
|
|
80
|
-
function isPlainObject(value: unknown): value is Record<string, unknown> {
|
|
81
|
-
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
81
|
interface DoordashStep { label: string; status: string; detail?: string }
|
|
85
82
|
|
|
86
83
|
/**
|
|
87
|
-
* Map a `vellum doordash <subcommand>` to the
|
|
84
|
+
* Map a `doordash <subcommand>` (or `vellum doordash <subcommand>`) to the
|
|
85
|
+
* step label it corresponds to.
|
|
88
86
|
*/
|
|
89
87
|
function doordashCommandToStep(cmd: string): string | null {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
if (
|
|
93
|
-
if (
|
|
94
|
-
if (
|
|
95
|
-
if (
|
|
88
|
+
// Match both standalone `doordash` and legacy `vellum doordash` prefixes
|
|
89
|
+
const dd = /(?:vellum )?doordash /;
|
|
90
|
+
if (new RegExp(dd.source + 'status\\b').test(cmd) || new RegExp(dd.source + 'refresh\\b').test(cmd) || new RegExp(dd.source + 'login\\b').test(cmd)) return 'Check session';
|
|
91
|
+
if (new RegExp(dd.source + 'search\\b').test(cmd) || new RegExp(dd.source + 'search-items\\b').test(cmd)) return 'Search restaurants';
|
|
92
|
+
if (new RegExp(dd.source + 'menu\\b').test(cmd) || new RegExp(dd.source + 'item\\b').test(cmd) || new RegExp(dd.source + 'store-search\\b').test(cmd)) return 'Browse menu';
|
|
93
|
+
if (new RegExp(dd.source + 'cart\\b').test(cmd)) return 'Add to cart';
|
|
94
|
+
if (new RegExp(dd.source + 'checkout\\b').test(cmd) || new RegExp(dd.source + 'payment-methods\\b').test(cmd)) return 'Add to cart';
|
|
95
|
+
if (new RegExp(dd.source + 'order\\b').test(cmd)) return 'Place order';
|
|
96
96
|
return null;
|
|
97
97
|
}
|
|
98
98
|
|
|
@@ -151,7 +151,8 @@ export function createToolExecutor(
|
|
|
151
151
|
// Pre-execution: mark the current DoorDash step as in_progress when command starts
|
|
152
152
|
if (name === 'bash' || name === 'host_bash') {
|
|
153
153
|
const preCmd = input.command as string | undefined;
|
|
154
|
-
|
|
154
|
+
const preStepLabel = preCmd ? doordashCommandToStep(preCmd) : null;
|
|
155
|
+
if (preStepLabel) {
|
|
155
156
|
const surfaceId = 'doordash-progress';
|
|
156
157
|
const stored = ctx.surfaceState.get(surfaceId);
|
|
157
158
|
if (stored && stored.surfaceType === 'card') {
|
|
@@ -159,23 +160,20 @@ export function createToolExecutor(
|
|
|
159
160
|
if (card.template === 'task_progress' && isPlainObject(card.templateData)) {
|
|
160
161
|
const steps = (card.templateData as Record<string, unknown>).steps;
|
|
161
162
|
if (Array.isArray(steps)) {
|
|
162
|
-
const
|
|
163
|
-
if (
|
|
164
|
-
const
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
ctx.
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
data: updatedData,
|
|
177
|
-
});
|
|
178
|
-
}
|
|
163
|
+
const stepIndex = (steps as DoordashStep[]).findIndex(s => s.label === preStepLabel);
|
|
164
|
+
if (stepIndex >= 0 && (steps as DoordashStep[])[stepIndex].status !== 'in_progress') {
|
|
165
|
+
const updatedSteps = (steps as DoordashStep[]).map((s, i) =>
|
|
166
|
+
i === stepIndex ? { ...s, status: 'in_progress' } : s
|
|
167
|
+
);
|
|
168
|
+
const updatedTemplateData = { ...card.templateData as Record<string, unknown>, steps: updatedSteps };
|
|
169
|
+
const updatedData = { ...card, templateData: updatedTemplateData };
|
|
170
|
+
stored.data = updatedData as import('./ipc-contract.js').CardSurfaceData;
|
|
171
|
+
ctx.sendToClient({
|
|
172
|
+
type: 'ui_surface_update',
|
|
173
|
+
sessionId: ctx.conversationId,
|
|
174
|
+
surfaceId,
|
|
175
|
+
data: updatedData,
|
|
176
|
+
});
|
|
179
177
|
}
|
|
180
178
|
}
|
|
181
179
|
}
|
|
@@ -312,7 +310,7 @@ export function createToolExecutor(
|
|
|
312
310
|
// Auto-emit task_progress card on first DoorDash CLI command
|
|
313
311
|
if (name === 'bash' || name === 'host_bash') {
|
|
314
312
|
const cmd = input.command as string | undefined;
|
|
315
|
-
if (cmd
|
|
313
|
+
if (cmd && doordashCommandToStep(cmd)) {
|
|
316
314
|
const surfaceId = 'doordash-progress';
|
|
317
315
|
|
|
318
316
|
if (!ctx.surfaceState.has(surfaceId)) {
|
|
@@ -12,7 +12,7 @@ export interface WorkspaceSessionContext {
|
|
|
12
12
|
|
|
13
13
|
/** Refresh workspace top-level directory context if needed. */
|
|
14
14
|
export function refreshWorkspaceTopLevelContextIfNeeded(ctx: WorkspaceSessionContext): void {
|
|
15
|
-
if (!ctx.workspaceTopLevelDirty && ctx.workspaceTopLevelContext
|
|
15
|
+
if (!ctx.workspaceTopLevelDirty && ctx.workspaceTopLevelContext != null) return;
|
|
16
16
|
const snapshot = scanTopLevelDirectories(ctx.workingDir);
|
|
17
17
|
ctx.workspaceTopLevelContext = renderWorkspaceTopLevelContext(snapshot);
|
|
18
18
|
ctx.workspaceTopLevelDirty = false;
|
package/src/daemon/session.ts
CHANGED
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
*/
|
|
17
17
|
|
|
18
18
|
import type { Message } from '../providers/types.js';
|
|
19
|
+
import type { TurnChannelContext } from '../channels/types.js';
|
|
19
20
|
import type { ServerMessage, UsageStats, UserMessageAttachment, SurfaceType, SurfaceData } from './ipc-protocol.js';
|
|
20
21
|
import { AgentLoop } from '../agent/loop.js';
|
|
21
22
|
import type { Provider } from '../providers/types.js';
|
|
@@ -37,12 +38,13 @@ import { ContextWindowManager } from '../context/window-manager.js';
|
|
|
37
38
|
import { getHookManager } from '../hooks/manager.js';
|
|
38
39
|
import { ConflictGate } from './session-conflict-gate.js';
|
|
39
40
|
import { MessageQueue } from './session-queue-manager.js';
|
|
40
|
-
import type { QueueDrainReason } from './session-queue-manager.js';
|
|
41
|
+
import type { QueueDrainReason, QueueMetrics } from './session-queue-manager.js';
|
|
41
42
|
import type { ChannelCapabilities, GuardianRuntimeContext } from './session-runtime-assembly.js';
|
|
42
43
|
import type { AssistantAttachmentDraft } from './assistant-attachments.js';
|
|
43
44
|
import {
|
|
44
45
|
handleSurfaceAction as handleSurfaceActionImpl,
|
|
45
46
|
handleSurfaceUndo as handleSurfaceUndoImpl,
|
|
47
|
+
createSurfaceMutex,
|
|
46
48
|
} from './session-surfaces.js';
|
|
47
49
|
import {
|
|
48
50
|
undo as undoImpl,
|
|
@@ -129,19 +131,23 @@ export class Session {
|
|
|
129
131
|
/** @internal */ channelCapabilities?: ChannelCapabilities;
|
|
130
132
|
/** @internal */ guardianContext?: GuardianRuntimeContext;
|
|
131
133
|
/** @internal */ assistantId?: string;
|
|
134
|
+
/** @internal */ commandIntent?: { type: string; payload?: string; languageCode?: string };
|
|
132
135
|
/** @internal */ pendingSurfaceActions = new Map<string, { surfaceType: SurfaceType }>();
|
|
133
136
|
/** @internal */ lastSurfaceAction = new Map<string, { actionId: string; data?: Record<string, unknown> }>();
|
|
134
137
|
/** @internal */ surfaceState = new Map<string, { surfaceType: SurfaceType; data: SurfaceData }>();
|
|
135
138
|
/** @internal */ surfaceUndoStacks = new Map<string, string[]>();
|
|
139
|
+
/** @internal */ withSurface = createSurfaceMutex();
|
|
136
140
|
/** @internal */ currentTurnSurfaces: Array<{ surfaceId: string; surfaceType: SurfaceType; title?: string; data: SurfaceData; actions?: Array<{ id: string; label: string; style?: string }>; display?: string }> = [];
|
|
137
141
|
/** @internal */ onEscalateToComputerUse?: (task: string, sourceSessionId: string) => boolean;
|
|
138
142
|
/** @internal */ workspaceTopLevelContext: string | null = null;
|
|
139
143
|
/** @internal */ workspaceTopLevelDirty = true;
|
|
140
144
|
public readonly traceEmitter: TraceEmitter;
|
|
141
145
|
public memoryPolicy: SessionMemoryPolicy;
|
|
146
|
+
/** @internal */ streamThinking: boolean;
|
|
142
147
|
/** @internal */ turnCount = 0;
|
|
143
148
|
public lastAssistantAttachments: AssistantAttachmentDraft[] = [];
|
|
144
149
|
public lastAttachmentWarnings: string[] = [];
|
|
150
|
+
/** @internal */ currentTurnChannelContext: TurnChannelContext | null = null;
|
|
145
151
|
|
|
146
152
|
constructor(
|
|
147
153
|
conversationId: string,
|
|
@@ -192,6 +198,7 @@ export class Session {
|
|
|
192
198
|
);
|
|
193
199
|
|
|
194
200
|
const config = getConfig();
|
|
201
|
+
this.streamThinking = config.thinking.streamThinking ?? false;
|
|
195
202
|
const resolveTools = createResolveToolsCallback(toolDefs, this);
|
|
196
203
|
|
|
197
204
|
this.agentLoop = new AgentLoop(
|
|
@@ -285,6 +292,10 @@ export class Session {
|
|
|
285
292
|
return this.queue.length;
|
|
286
293
|
}
|
|
287
294
|
|
|
295
|
+
getQueueMetrics(): QueueMetrics {
|
|
296
|
+
return this.queue.getMetrics();
|
|
297
|
+
}
|
|
298
|
+
|
|
288
299
|
hasQueuedMessages(): boolean {
|
|
289
300
|
return !this.queue.isEmpty;
|
|
290
301
|
}
|
|
@@ -337,6 +348,18 @@ export class Session {
|
|
|
337
348
|
this.assistantId = assistantId ?? undefined;
|
|
338
349
|
}
|
|
339
350
|
|
|
351
|
+
setCommandIntent(intent: { type: string; payload?: string; languageCode?: string } | null): void {
|
|
352
|
+
this.commandIntent = intent ?? undefined;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
setTurnChannelContext(ctx: TurnChannelContext): void {
|
|
356
|
+
this.currentTurnChannelContext = ctx;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
getTurnChannelContext(): TurnChannelContext | null {
|
|
360
|
+
return this.currentTurnChannelContext;
|
|
361
|
+
}
|
|
362
|
+
|
|
340
363
|
persistUserMessage(
|
|
341
364
|
content: string,
|
|
342
365
|
attachments: UserMessageAttachment[],
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import * as Sentry from '@sentry/node';
|
|
2
|
+
import { getSqlite, resetDb } from '../memory/db.js';
|
|
3
|
+
import { browserManager } from '../tools/browser/browser-manager.js';
|
|
4
|
+
import { getEnrichmentService } from '../workspace/commit-message-enrichment-service.js';
|
|
5
|
+
import { getLogger } from '../util/logger.js';
|
|
6
|
+
import type { DaemonServer } from './server.js';
|
|
7
|
+
import type { RuntimeHttpServer } from '../runtime/http-server.js';
|
|
8
|
+
import type { HeartbeatService } from '../workspace/heartbeat-service.js';
|
|
9
|
+
import type { AgentHeartbeatService } from '../agent-heartbeat/agent-heartbeat-service.js';
|
|
10
|
+
import type { QdrantManager } from '../memory/qdrant-manager.js';
|
|
11
|
+
import type { HookManager } from '../hooks/manager.js';
|
|
12
|
+
|
|
13
|
+
const log = getLogger('lifecycle');
|
|
14
|
+
|
|
15
|
+
export interface ShutdownDeps {
|
|
16
|
+
server: DaemonServer;
|
|
17
|
+
heartbeat: HeartbeatService;
|
|
18
|
+
agentHeartbeat: AgentHeartbeatService;
|
|
19
|
+
hookManager: HookManager;
|
|
20
|
+
runtimeHttp: RuntimeHttpServer | null;
|
|
21
|
+
scheduler: { stop(): void };
|
|
22
|
+
memoryWorker: { stop(): void };
|
|
23
|
+
qdrantManager: QdrantManager;
|
|
24
|
+
cleanupPidFile: () => void;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function installShutdownHandlers(deps: ShutdownDeps): void {
|
|
28
|
+
let shuttingDown = false;
|
|
29
|
+
|
|
30
|
+
const shutdown = async () => {
|
|
31
|
+
if (shuttingDown) return;
|
|
32
|
+
shuttingDown = true;
|
|
33
|
+
log.info('Shutting down daemon...');
|
|
34
|
+
|
|
35
|
+
deps.hookManager.stopWatching();
|
|
36
|
+
|
|
37
|
+
// Force exit if graceful shutdown takes too long.
|
|
38
|
+
// Set this BEFORE awaiting heartbeat stop and triggering daemon-stop hooks
|
|
39
|
+
// so it covers all potentially-blocking async shutdown work.
|
|
40
|
+
const forceTimer = setTimeout(() => {
|
|
41
|
+
log.warn('Graceful shutdown timed out, forcing exit');
|
|
42
|
+
deps.cleanupPidFile();
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}, 10_000);
|
|
45
|
+
forceTimer.unref();
|
|
46
|
+
|
|
47
|
+
await deps.heartbeat.stop();
|
|
48
|
+
await deps.agentHeartbeat.stop();
|
|
49
|
+
|
|
50
|
+
try {
|
|
51
|
+
await deps.hookManager.trigger('daemon-stop', { pid: process.pid });
|
|
52
|
+
} catch {
|
|
53
|
+
// Don't let hook failures block shutdown
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Commit any uncommitted workspace changes before stopping the server.
|
|
57
|
+
// This ensures no workspace state is lost during graceful shutdown.
|
|
58
|
+
try {
|
|
59
|
+
log.info({ phase: 'pre_stop' }, 'Committing pending workspace changes');
|
|
60
|
+
await deps.heartbeat.commitAllPending();
|
|
61
|
+
} catch (err) {
|
|
62
|
+
log.warn({ err, phase: 'pre_stop' }, 'Shutdown workspace commit failed');
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
await deps.server.stop();
|
|
66
|
+
|
|
67
|
+
// Final commit sweep: catch any writes that occurred during server.stop()
|
|
68
|
+
// (e.g. in-flight tool executions completing during drain).
|
|
69
|
+
try {
|
|
70
|
+
log.info({ phase: 'post_stop' }, 'Final workspace commit sweep');
|
|
71
|
+
await deps.heartbeat.commitAllPending();
|
|
72
|
+
} catch (err) {
|
|
73
|
+
log.warn({ err, phase: 'post_stop' }, 'Post-stop workspace commit failed');
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Flush in-flight enrichment jobs so shutdown commit notes are not dropped.
|
|
77
|
+
// The enrichment service's shutdown() drains active jobs and discards pending ones.
|
|
78
|
+
try {
|
|
79
|
+
await getEnrichmentService().shutdown();
|
|
80
|
+
} catch (err) {
|
|
81
|
+
log.warn({ err }, 'Enrichment service shutdown failed (non-fatal)');
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (deps.runtimeHttp) await deps.runtimeHttp.stop();
|
|
85
|
+
await browserManager.closeAllPages();
|
|
86
|
+
deps.scheduler.stop();
|
|
87
|
+
deps.memoryWorker.stop();
|
|
88
|
+
await deps.qdrantManager.stop();
|
|
89
|
+
|
|
90
|
+
// Checkpoint WAL and close SQLite so no writes are lost on exit.
|
|
91
|
+
// Checkpoint and close are in separate try blocks so that close()
|
|
92
|
+
// always runs even if checkpointing throws (e.g. SQLITE_BUSY).
|
|
93
|
+
try {
|
|
94
|
+
getSqlite().exec('PRAGMA wal_checkpoint(TRUNCATE)');
|
|
95
|
+
} catch (err) {
|
|
96
|
+
log.warn({ err }, 'WAL checkpoint failed (non-fatal)');
|
|
97
|
+
}
|
|
98
|
+
try {
|
|
99
|
+
resetDb();
|
|
100
|
+
} catch (err) {
|
|
101
|
+
log.warn({ err }, 'Database close failed (non-fatal)');
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
await Sentry.flush(2000);
|
|
105
|
+
clearTimeout(forceTimer);
|
|
106
|
+
deps.cleanupPidFile();
|
|
107
|
+
process.exit(0);
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
process.on('SIGTERM', shutdown);
|
|
111
|
+
process.on('SIGINT', shutdown);
|
|
112
|
+
|
|
113
|
+
process.on('unhandledRejection', (reason) => {
|
|
114
|
+
log.error({ err: reason }, 'Unhandled promise rejection');
|
|
115
|
+
Sentry.captureException(reason);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
process.on('uncaughtException', (err) => {
|
|
119
|
+
log.error({ err }, 'Uncaught exception');
|
|
120
|
+
Sentry.captureException(err);
|
|
121
|
+
});
|
|
122
|
+
}
|
|
@@ -69,7 +69,7 @@ function normalizeAttributes(
|
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
function normalizeValue(value: unknown): string | number | boolean | null {
|
|
72
|
-
if (value
|
|
72
|
+
if (value == null) return null;
|
|
73
73
|
if (typeof value === 'boolean' || typeof value === 'number') return value;
|
|
74
74
|
if (typeof value === 'string') return truncate(value, ATTRIBUTE_VALUE_MAX_LENGTH);
|
|
75
75
|
// Coerce non-primitives to string
|