@vellumai/assistant 0.3.5 → 0.3.7
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 +27 -3
- package/src/config/env-registry.ts +169 -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 +157 -1138
- 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 +254 -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 +74 -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 +321 -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 +62 -0
- package/src/daemon/ipc-contract-inventory.ts +55 -29
- package/src/daemon/ipc-contract.ts +227 -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 +98 -4
- package/src/daemon/session-runtime-assembly.ts +149 -15
- package/src/daemon/session-surfaces.ts +26 -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 +12 -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 +163 -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 +126 -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/assistant-event-hub.ts +3 -1
- 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 +289 -745
- 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 +144 -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 +13 -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 +80 -18
- 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 +25 -18
- 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
|
@@ -1,244 +0,0 @@
|
|
|
1
|
-
import { describe, test, expect, beforeEach, mock } from 'bun:test';
|
|
2
|
-
import { mkdtempSync } from 'node:fs';
|
|
3
|
-
import { tmpdir } from 'node:os';
|
|
4
|
-
import { join } from 'node:path';
|
|
5
|
-
|
|
6
|
-
const testDir = mkdtempSync(join(tmpdir(), 'session-process-bridge-test-'));
|
|
7
|
-
|
|
8
|
-
// ── Platform + logger mocks ─────────────────────────────────────────
|
|
9
|
-
|
|
10
|
-
mock.module('../util/platform.js', () => ({
|
|
11
|
-
getDataDir: () => testDir,
|
|
12
|
-
isMacOS: () => process.platform === 'darwin',
|
|
13
|
-
isLinux: () => process.platform === 'linux',
|
|
14
|
-
isWindows: () => process.platform === 'win32',
|
|
15
|
-
getSocketPath: () => join(testDir, 'test.sock'),
|
|
16
|
-
getPidPath: () => join(testDir, 'test.pid'),
|
|
17
|
-
getDbPath: () => join(testDir, 'test.db'),
|
|
18
|
-
getLogPath: () => join(testDir, 'test.log'),
|
|
19
|
-
ensureDataDir: () => {},
|
|
20
|
-
}));
|
|
21
|
-
|
|
22
|
-
mock.module('../util/logger.js', () => ({
|
|
23
|
-
getLogger: () =>
|
|
24
|
-
new Proxy({} as Record<string, unknown>, {
|
|
25
|
-
get: () => () => {},
|
|
26
|
-
}),
|
|
27
|
-
}));
|
|
28
|
-
|
|
29
|
-
mock.module('../config/loader.js', () => ({
|
|
30
|
-
getConfig: () => ({
|
|
31
|
-
apiKeys: { anthropic: 'test-key' },
|
|
32
|
-
model: 'claude-sonnet-4-20250514',
|
|
33
|
-
provider: 'anthropic',
|
|
34
|
-
memory: { enabled: false },
|
|
35
|
-
calls: { enabled: false },
|
|
36
|
-
contextWindow: { maxInputTokens: 200000 },
|
|
37
|
-
}),
|
|
38
|
-
}));
|
|
39
|
-
|
|
40
|
-
// ── Mock the call bridge ─────────────────────────────────────────────
|
|
41
|
-
|
|
42
|
-
import type { CallBridgeResult } from '../calls/call-bridge.js';
|
|
43
|
-
|
|
44
|
-
const mockTryRouteCallMessage = mock(
|
|
45
|
-
(_convId: string, _text: string, _msgId?: string): Promise<CallBridgeResult> =>
|
|
46
|
-
Promise.resolve({ handled: false, reason: 'no_active_call' }),
|
|
47
|
-
);
|
|
48
|
-
|
|
49
|
-
mock.module('../calls/call-bridge.js', () => ({
|
|
50
|
-
tryRouteCallMessage: (...args: [string, string, string?]) => mockTryRouteCallMessage(...args),
|
|
51
|
-
}));
|
|
52
|
-
|
|
53
|
-
// ── Mock slash resolution ────────────────────────────────────────────
|
|
54
|
-
|
|
55
|
-
mock.module('./session-slash.js', () => ({
|
|
56
|
-
resolveSlash: (content: string) => ({ kind: 'passthrough' as const, content }),
|
|
57
|
-
}));
|
|
58
|
-
|
|
59
|
-
// ── Import after mocks ──────────────────────────────────────────────
|
|
60
|
-
|
|
61
|
-
import type { ServerMessage } from '../daemon/ipc-protocol.js';
|
|
62
|
-
import type { ProcessSessionContext } from '../daemon/session-process.js';
|
|
63
|
-
import { processMessage, drainQueue } from '../daemon/session-process.js';
|
|
64
|
-
import { MessageQueue } from '../daemon/session-queue-manager.js';
|
|
65
|
-
|
|
66
|
-
// ── Session mock factory ─────────────────────────────────────────────
|
|
67
|
-
|
|
68
|
-
function createMockSession(overrides?: Partial<ProcessSessionContext>): ProcessSessionContext {
|
|
69
|
-
return {
|
|
70
|
-
conversationId: 'test-conv',
|
|
71
|
-
messages: [],
|
|
72
|
-
processing: false,
|
|
73
|
-
abortController: null,
|
|
74
|
-
currentRequestId: undefined,
|
|
75
|
-
queue: new MessageQueue(),
|
|
76
|
-
traceEmitter: {
|
|
77
|
-
emit: () => {},
|
|
78
|
-
} as unknown as ProcessSessionContext['traceEmitter'],
|
|
79
|
-
usageStats: { inputTokens: 0, outputTokens: 0, estimatedCost: 0 },
|
|
80
|
-
persistUserMessage: mock((_content: string, _attachments: unknown[], _requestId?: string) => 'mock-msg-id'),
|
|
81
|
-
runAgentLoop: mock(async () => {}),
|
|
82
|
-
...overrides,
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// ── Tests ────────────────────────────────────────────────────────────
|
|
87
|
-
|
|
88
|
-
describe('session-process bridge consumption', () => {
|
|
89
|
-
beforeEach(() => {
|
|
90
|
-
mockTryRouteCallMessage.mockReset();
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
// ── Direct processMessage path ───────────────────────────────
|
|
94
|
-
|
|
95
|
-
test('processMessage emits assistant_text_delta + message_complete when bridge consumes with userFacingText', async () => {
|
|
96
|
-
mockTryRouteCallMessage.mockResolvedValue({
|
|
97
|
-
handled: true,
|
|
98
|
-
userFacingText: 'Instruction relayed to active call.',
|
|
99
|
-
});
|
|
100
|
-
|
|
101
|
-
const events: ServerMessage[] = [];
|
|
102
|
-
const onEvent = (msg: ServerMessage) => events.push(msg);
|
|
103
|
-
const session = createMockSession();
|
|
104
|
-
|
|
105
|
-
await processMessage(session, 'ask about pricing', [], onEvent);
|
|
106
|
-
|
|
107
|
-
// Should have emitted text delta then message_complete
|
|
108
|
-
const textDelta = events.find((e) => e.type === 'assistant_text_delta');
|
|
109
|
-
expect(textDelta).toBeDefined();
|
|
110
|
-
expect((textDelta as { text: string }).text).toBe('Instruction relayed to active call.');
|
|
111
|
-
|
|
112
|
-
const complete = events.find((e) => e.type === 'message_complete');
|
|
113
|
-
expect(complete).toBeDefined();
|
|
114
|
-
|
|
115
|
-
// Should NOT have called runAgentLoop
|
|
116
|
-
expect(session.runAgentLoop).not.toHaveBeenCalled();
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
test('processMessage emits failure text when bridge consumes with failure userFacingText', async () => {
|
|
120
|
-
mockTryRouteCallMessage.mockResolvedValue({
|
|
121
|
-
handled: true,
|
|
122
|
-
reason: 'instruction_relay_failed',
|
|
123
|
-
userFacingText: 'Failed to relay instruction to the active call.',
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
const events: ServerMessage[] = [];
|
|
127
|
-
const onEvent = (msg: ServerMessage) => events.push(msg);
|
|
128
|
-
const session = createMockSession();
|
|
129
|
-
|
|
130
|
-
await processMessage(session, 'change the topic', [], onEvent);
|
|
131
|
-
|
|
132
|
-
const textDelta = events.find((e) => e.type === 'assistant_text_delta');
|
|
133
|
-
expect(textDelta).toBeDefined();
|
|
134
|
-
expect((textDelta as { text: string }).text).toBe('Failed to relay instruction to the active call.');
|
|
135
|
-
|
|
136
|
-
const complete = events.find((e) => e.type === 'message_complete');
|
|
137
|
-
expect(complete).toBeDefined();
|
|
138
|
-
|
|
139
|
-
// Only one message_complete
|
|
140
|
-
const completeCount = events.filter((e) => e.type === 'message_complete').length;
|
|
141
|
-
expect(completeCount).toBe(1);
|
|
142
|
-
|
|
143
|
-
expect(session.runAgentLoop).not.toHaveBeenCalled();
|
|
144
|
-
});
|
|
145
|
-
|
|
146
|
-
test('processMessage skips text delta when bridge consumes without userFacingText', async () => {
|
|
147
|
-
mockTryRouteCallMessage.mockResolvedValue({
|
|
148
|
-
handled: true,
|
|
149
|
-
});
|
|
150
|
-
|
|
151
|
-
const events: ServerMessage[] = [];
|
|
152
|
-
const onEvent = (msg: ServerMessage) => events.push(msg);
|
|
153
|
-
const session = createMockSession();
|
|
154
|
-
|
|
155
|
-
await processMessage(session, 'hello', [], onEvent);
|
|
156
|
-
|
|
157
|
-
const textDelta = events.find((e) => e.type === 'assistant_text_delta');
|
|
158
|
-
expect(textDelta).toBeUndefined();
|
|
159
|
-
|
|
160
|
-
const complete = events.find((e) => e.type === 'message_complete');
|
|
161
|
-
expect(complete).toBeDefined();
|
|
162
|
-
|
|
163
|
-
expect(session.runAgentLoop).not.toHaveBeenCalled();
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
test('processMessage falls through to agent loop when bridge does not consume', async () => {
|
|
167
|
-
mockTryRouteCallMessage.mockResolvedValue({
|
|
168
|
-
handled: false,
|
|
169
|
-
reason: 'no_active_call',
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
const events: ServerMessage[] = [];
|
|
173
|
-
const onEvent = (msg: ServerMessage) => events.push(msg);
|
|
174
|
-
const session = createMockSession();
|
|
175
|
-
|
|
176
|
-
await processMessage(session, 'normal message', [], onEvent);
|
|
177
|
-
|
|
178
|
-
expect(session.runAgentLoop).toHaveBeenCalled();
|
|
179
|
-
});
|
|
180
|
-
|
|
181
|
-
// ── Queued routeOrProcess path ───────────────────────────────
|
|
182
|
-
|
|
183
|
-
test('drainQueue emits assistant_text_delta + message_complete for bridge-consumed queued message', async () => {
|
|
184
|
-
mockTryRouteCallMessage.mockResolvedValue({
|
|
185
|
-
handled: true,
|
|
186
|
-
userFacingText: 'Instruction relayed to active call.',
|
|
187
|
-
});
|
|
188
|
-
|
|
189
|
-
const events: ServerMessage[] = [];
|
|
190
|
-
const onEvent = (msg: ServerMessage) => events.push(msg);
|
|
191
|
-
const session = createMockSession({ processing: true });
|
|
192
|
-
|
|
193
|
-
// Enqueue a message
|
|
194
|
-
session.queue.push({
|
|
195
|
-
content: 'ask about pricing',
|
|
196
|
-
attachments: [],
|
|
197
|
-
requestId: 'req-1',
|
|
198
|
-
onEvent,
|
|
199
|
-
});
|
|
200
|
-
|
|
201
|
-
drainQueue(session);
|
|
202
|
-
|
|
203
|
-
// Wait for async routeOrProcess
|
|
204
|
-
await new Promise((r) => setTimeout(r, 50));
|
|
205
|
-
|
|
206
|
-
const textDelta = events.find((e) => e.type === 'assistant_text_delta');
|
|
207
|
-
expect(textDelta).toBeDefined();
|
|
208
|
-
expect((textDelta as { text: string }).text).toBe('Instruction relayed to active call.');
|
|
209
|
-
|
|
210
|
-
// message_complete (from dequeue + bridge consumption — only one expected for this request)
|
|
211
|
-
const completeEvents = events.filter((e) => e.type === 'message_complete');
|
|
212
|
-
expect(completeEvents.length).toBe(1);
|
|
213
|
-
|
|
214
|
-
expect(session.runAgentLoop).not.toHaveBeenCalled();
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
test('drainQueue emits failure text for bridge-consumed queued message with relay failure', async () => {
|
|
218
|
-
mockTryRouteCallMessage.mockResolvedValue({
|
|
219
|
-
handled: true,
|
|
220
|
-
reason: 'instruction_relay_failed',
|
|
221
|
-
userFacingText: 'Failed to relay instruction to the active call.',
|
|
222
|
-
});
|
|
223
|
-
|
|
224
|
-
const events: ServerMessage[] = [];
|
|
225
|
-
const onEvent = (msg: ServerMessage) => events.push(msg);
|
|
226
|
-
const session = createMockSession({ processing: true });
|
|
227
|
-
|
|
228
|
-
session.queue.push({
|
|
229
|
-
content: 'change the topic',
|
|
230
|
-
attachments: [],
|
|
231
|
-
requestId: 'req-2',
|
|
232
|
-
onEvent,
|
|
233
|
-
});
|
|
234
|
-
|
|
235
|
-
drainQueue(session);
|
|
236
|
-
await new Promise((r) => setTimeout(r, 50));
|
|
237
|
-
|
|
238
|
-
const textDelta = events.find((e) => e.type === 'assistant_text_delta');
|
|
239
|
-
expect(textDelta).toBeDefined();
|
|
240
|
-
expect((textDelta as { text: string }).text).toBe('Failed to relay instruction to the active call.');
|
|
241
|
-
|
|
242
|
-
expect(session.runAgentLoop).not.toHaveBeenCalled();
|
|
243
|
-
});
|
|
244
|
-
});
|
package/src/calls/call-bridge.ts
DELETED
|
@@ -1,168 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Call message bridge: intercepts user messages in-thread and routes them
|
|
3
|
-
* to the live call orchestrator — either as answers to pending questions
|
|
4
|
-
* or as mid-call steering instructions.
|
|
5
|
-
*
|
|
6
|
-
* Decision priority:
|
|
7
|
-
* 1. If a pending question exists → answer path (existing behavior).
|
|
8
|
-
* 2. If no pending question but an active call exists → instruction path.
|
|
9
|
-
*
|
|
10
|
-
* When the bridge consumes a message it returns `{ handled: true }` so
|
|
11
|
-
* the caller can skip agent processing.
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
import { getLogger } from '../util/logger.js';
|
|
15
|
-
import {
|
|
16
|
-
getActiveCallSessionForConversation,
|
|
17
|
-
getPendingQuestion,
|
|
18
|
-
answerPendingQuestion,
|
|
19
|
-
recordCallEvent,
|
|
20
|
-
getCallSession,
|
|
21
|
-
} from './call-store.js';
|
|
22
|
-
import { getCallOrchestrator } from './call-state.js';
|
|
23
|
-
import { relayInstruction } from './call-domain.js';
|
|
24
|
-
import * as conversationStore from '../memory/conversation-store.js';
|
|
25
|
-
|
|
26
|
-
const log = getLogger('call-bridge');
|
|
27
|
-
|
|
28
|
-
export interface CallBridgeResult {
|
|
29
|
-
handled: boolean;
|
|
30
|
-
reason?: string;
|
|
31
|
-
/** User-facing text persisted in-thread by the bridge (success ack or failure notice). */
|
|
32
|
-
userFacingText?: string;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Attempt to route a user message to an active call — as an answer to
|
|
37
|
-
* a pending question (priority) or as a mid-call steering instruction.
|
|
38
|
-
*
|
|
39
|
-
* @param conversationId - The conversation the message belongs to.
|
|
40
|
-
* @param userText - The user's message text.
|
|
41
|
-
* @param _userMessageId - The persisted message ID (reserved for future use).
|
|
42
|
-
* @returns `{ handled: true }` if the message was consumed by the call system,
|
|
43
|
-
* `{ handled: false, reason }` otherwise.
|
|
44
|
-
*/
|
|
45
|
-
export async function tryRouteCallMessage(
|
|
46
|
-
conversationId: string,
|
|
47
|
-
userText: string,
|
|
48
|
-
_userMessageId?: string,
|
|
49
|
-
): Promise<CallBridgeResult> {
|
|
50
|
-
// 1. Find an active call for this conversation
|
|
51
|
-
const callSession = getActiveCallSessionForConversation(conversationId);
|
|
52
|
-
if (!callSession) {
|
|
53
|
-
return { handled: false, reason: 'no_active_call' };
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// 2. Check for a pending question — answer path takes priority
|
|
57
|
-
const pendingQuestion = getPendingQuestion(callSession.id);
|
|
58
|
-
if (pendingQuestion) {
|
|
59
|
-
return handleAnswer(conversationId, callSession.id, pendingQuestion, userText);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// 3. No pending question — instruction path
|
|
63
|
-
return handleInstruction(conversationId, callSession.id, userText);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
/** @deprecated Use `tryRouteCallMessage` instead. */
|
|
67
|
-
export const tryHandlePendingCallAnswer = tryRouteCallMessage;
|
|
68
|
-
|
|
69
|
-
// ── Answer path ─────────────────────────────────────────────────────
|
|
70
|
-
|
|
71
|
-
async function handleAnswer(
|
|
72
|
-
conversationId: string,
|
|
73
|
-
callSessionId: string,
|
|
74
|
-
pendingQuestion: { id: string; questionText: string },
|
|
75
|
-
userText: string,
|
|
76
|
-
): Promise<CallBridgeResult> {
|
|
77
|
-
// Empty text (e.g. attachment-only messages) should not be consumed as
|
|
78
|
-
// an answer — fall through to normal processing so attachments are handled.
|
|
79
|
-
if (!userText.trim()) {
|
|
80
|
-
return { handled: false, reason: 'empty_answer_text' };
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
const orchestrator = getCallOrchestrator(callSessionId);
|
|
84
|
-
if (!orchestrator) {
|
|
85
|
-
// The call may have ended between the question being asked and the
|
|
86
|
-
// user replying. Persist a follow-up message so the user knows.
|
|
87
|
-
const freshSession = getCallSession(callSessionId);
|
|
88
|
-
const ended = freshSession && (freshSession.status === 'completed' || freshSession.status === 'failed');
|
|
89
|
-
if (ended) {
|
|
90
|
-
conversationStore.addMessage(
|
|
91
|
-
conversationId,
|
|
92
|
-
'assistant',
|
|
93
|
-
JSON.stringify([{
|
|
94
|
-
type: 'text',
|
|
95
|
-
text: 'The call ended before your answer could be relayed to the caller.',
|
|
96
|
-
}]),
|
|
97
|
-
);
|
|
98
|
-
}
|
|
99
|
-
return { handled: false, reason: 'orchestrator_not_found' };
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
if (orchestrator.getState() !== 'waiting_on_user') {
|
|
103
|
-
return { handled: false, reason: 'orchestrator_not_waiting' };
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
const accepted = await orchestrator.handleUserAnswer(userText);
|
|
107
|
-
if (!accepted) {
|
|
108
|
-
return { handled: false, reason: 'orchestrator_rejected' };
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
answerPendingQuestion(pendingQuestion.id, userText);
|
|
112
|
-
recordCallEvent(callSessionId, 'user_answered', { answer: userText });
|
|
113
|
-
|
|
114
|
-
log.info(
|
|
115
|
-
{ conversationId, callSessionId, questionId: pendingQuestion.id },
|
|
116
|
-
'User reply routed as call answer via bridge',
|
|
117
|
-
);
|
|
118
|
-
|
|
119
|
-
return { handled: true };
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
// ── Instruction path ────────────────────────────────────────────────
|
|
123
|
-
|
|
124
|
-
async function handleInstruction(
|
|
125
|
-
conversationId: string,
|
|
126
|
-
callSessionId: string,
|
|
127
|
-
userText: string,
|
|
128
|
-
): Promise<CallBridgeResult> {
|
|
129
|
-
// Empty text (e.g. attachment-only messages) should not be relayed —
|
|
130
|
-
// fall through to normal processing so attachments are handled.
|
|
131
|
-
if (!userText.trim()) {
|
|
132
|
-
return { handled: false, reason: 'empty_instruction_text' };
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
const result = await relayInstruction({ callSessionId, instructionText: userText });
|
|
136
|
-
|
|
137
|
-
if (!result.ok) {
|
|
138
|
-
log.warn(
|
|
139
|
-
{ conversationId, callSessionId, error: result.error },
|
|
140
|
-
'Instruction relay failed via bridge',
|
|
141
|
-
);
|
|
142
|
-
|
|
143
|
-
const failureText = 'Failed to relay instruction to the active call.';
|
|
144
|
-
conversationStore.addMessage(
|
|
145
|
-
conversationId,
|
|
146
|
-
'assistant',
|
|
147
|
-
JSON.stringify([{ type: 'text', text: failureText }]),
|
|
148
|
-
);
|
|
149
|
-
|
|
150
|
-
// Consumed: caller should NOT fall through to the agent loop
|
|
151
|
-
return { handled: true, reason: 'instruction_relay_failed', userFacingText: failureText };
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
// Persist a concise acknowledgement so the user sees confirmation
|
|
155
|
-
const ackText = 'Instruction relayed to active call.';
|
|
156
|
-
conversationStore.addMessage(
|
|
157
|
-
conversationId,
|
|
158
|
-
'assistant',
|
|
159
|
-
JSON.stringify([{ type: 'text', text: ackText }]),
|
|
160
|
-
);
|
|
161
|
-
|
|
162
|
-
log.info(
|
|
163
|
-
{ conversationId, callSessionId },
|
|
164
|
-
'User message routed as call instruction via bridge',
|
|
165
|
-
);
|
|
166
|
-
|
|
167
|
-
return { handled: true, userFacingText: ackText };
|
|
168
|
-
}
|
|
@@ -1,137 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Generic capability registry with tier-based classification.
|
|
3
|
-
*
|
|
4
|
-
* The registry is domain-agnostic: any domain (sports, surveillance, lecture
|
|
5
|
-
* recording, etc.) can register its own capabilities. Basketball-specific
|
|
6
|
-
* capabilities are registered as one example via `registerDefaults()`.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import type { CapabilityTier } from '../../../../memory/media-store.js';
|
|
10
|
-
|
|
11
|
-
// ---------------------------------------------------------------------------
|
|
12
|
-
// Types
|
|
13
|
-
// ---------------------------------------------------------------------------
|
|
14
|
-
|
|
15
|
-
export interface Capability {
|
|
16
|
-
/** Unique name used as the key in tracking profiles (e.g. 'turnover'). */
|
|
17
|
-
name: string;
|
|
18
|
-
/** Human-readable description of what this capability detects/tracks. */
|
|
19
|
-
description: string;
|
|
20
|
-
/** Maturity tier governing confidence disclaimers and default inclusion. */
|
|
21
|
-
tier: CapabilityTier;
|
|
22
|
-
/** Domain this capability belongs to (e.g. 'basketball', 'surveillance'). */
|
|
23
|
-
domain: string;
|
|
24
|
-
/** Granularity level (e.g. 'team', 'per-player'). */
|
|
25
|
-
granularity?: string;
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// ---------------------------------------------------------------------------
|
|
29
|
-
// Registry (singleton in-memory Map)
|
|
30
|
-
// ---------------------------------------------------------------------------
|
|
31
|
-
|
|
32
|
-
const registry = new Map<string, Capability>();
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Register a capability. Overwrites any existing capability with the same name.
|
|
36
|
-
*/
|
|
37
|
-
export function registerCapability(cap: Capability): void {
|
|
38
|
-
registry.set(cap.name, cap);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Get all registered capabilities, optionally filtered by domain.
|
|
43
|
-
*/
|
|
44
|
-
export function getCapabilities(domain?: string): Capability[] {
|
|
45
|
-
const all = Array.from(registry.values());
|
|
46
|
-
if (!domain) return all;
|
|
47
|
-
return all.filter((c) => c.domain === domain);
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Get capabilities filtered by tier.
|
|
52
|
-
*/
|
|
53
|
-
export function getCapabilitiesByTier(tier: CapabilityTier): Capability[] {
|
|
54
|
-
return Array.from(registry.values()).filter((c) => c.tier === tier);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Look up a single capability by name.
|
|
59
|
-
*/
|
|
60
|
-
export function getCapabilityByName(name: string): Capability | undefined {
|
|
61
|
-
return registry.get(name);
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Get all unique domain names in the registry.
|
|
66
|
-
*/
|
|
67
|
-
export function getRegisteredDomains(): string[] {
|
|
68
|
-
const domains = new Set<string>();
|
|
69
|
-
for (const cap of registry.values()) {
|
|
70
|
-
domains.add(cap.domain);
|
|
71
|
-
}
|
|
72
|
-
return Array.from(domains);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// ---------------------------------------------------------------------------
|
|
76
|
-
// Default registrations — basketball as one example domain
|
|
77
|
-
// ---------------------------------------------------------------------------
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Register the default basketball capabilities as an example domain.
|
|
81
|
-
* Other domains should call `registerCapability()` with their own entries.
|
|
82
|
-
*/
|
|
83
|
-
export function registerDefaults(): void {
|
|
84
|
-
// Ready tier: production-quality detection
|
|
85
|
-
registerCapability({
|
|
86
|
-
name: 'turnover',
|
|
87
|
-
description: 'Team-level turnover detection',
|
|
88
|
-
tier: 'ready',
|
|
89
|
-
domain: 'basketball',
|
|
90
|
-
granularity: 'team',
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
// Beta tier: functional but may have accuracy gaps
|
|
94
|
-
registerCapability({
|
|
95
|
-
name: 'field_goal',
|
|
96
|
-
description: 'Team-level field goal detection',
|
|
97
|
-
tier: 'beta',
|
|
98
|
-
domain: 'basketball',
|
|
99
|
-
granularity: 'team',
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
registerCapability({
|
|
103
|
-
name: 'rebound',
|
|
104
|
-
description: 'Team-level rebound detection',
|
|
105
|
-
tier: 'beta',
|
|
106
|
-
domain: 'basketball',
|
|
107
|
-
granularity: 'team',
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
registerCapability({
|
|
111
|
-
name: 'turnover_per_player',
|
|
112
|
-
description: 'Per-player turnover attribution',
|
|
113
|
-
tier: 'beta',
|
|
114
|
-
domain: 'basketball',
|
|
115
|
-
granularity: 'per-player',
|
|
116
|
-
});
|
|
117
|
-
|
|
118
|
-
// Experimental tier: early-stage, expect noise
|
|
119
|
-
registerCapability({
|
|
120
|
-
name: 'field_goal_per_player',
|
|
121
|
-
description: 'Per-player field goal attribution',
|
|
122
|
-
tier: 'experimental',
|
|
123
|
-
domain: 'basketball',
|
|
124
|
-
granularity: 'per-player',
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
registerCapability({
|
|
128
|
-
name: 'rebound_per_player',
|
|
129
|
-
description: 'Per-player rebound attribution',
|
|
130
|
-
tier: 'experimental',
|
|
131
|
-
domain: 'basketball',
|
|
132
|
-
granularity: 'per-player',
|
|
133
|
-
});
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// Auto-register defaults on first import
|
|
137
|
-
registerDefaults();
|