@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
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory pairing request store with TTL.
|
|
3
|
+
*
|
|
4
|
+
* Each pairing request lives for at most TTL_MS (5 minutes) before
|
|
5
|
+
* being swept as expired. Status transitions:
|
|
6
|
+
* registered → pending → approved | denied | expired
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { createHash, timingSafeEqual } from 'node:crypto';
|
|
10
|
+
import { getLogger } from '../util/logger.js';
|
|
11
|
+
|
|
12
|
+
const log = getLogger('pairing-store');
|
|
13
|
+
|
|
14
|
+
const TTL_MS = 5 * 60 * 1000; // 5 minutes
|
|
15
|
+
const SWEEP_INTERVAL_MS = 30_000; // 30 seconds
|
|
16
|
+
|
|
17
|
+
export type PairingStatus = 'registered' | 'pending' | 'approved' | 'denied' | 'expired';
|
|
18
|
+
|
|
19
|
+
export interface PairingRequest {
|
|
20
|
+
pairingRequestId: string;
|
|
21
|
+
hashedPairingSecret: string;
|
|
22
|
+
hashedDeviceId?: string;
|
|
23
|
+
deviceName?: string;
|
|
24
|
+
status: PairingStatus;
|
|
25
|
+
gatewayUrl: string;
|
|
26
|
+
localLanUrl: string | null;
|
|
27
|
+
bearerToken?: string;
|
|
28
|
+
createdAt: number;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function hashValue(value: string): string {
|
|
32
|
+
return createHash('sha256').update(value).digest('hex');
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
function timingSafeCompare(a: string, b: string): boolean {
|
|
36
|
+
const bufA = Buffer.from(a);
|
|
37
|
+
const bufB = Buffer.from(b);
|
|
38
|
+
if (bufA.length !== bufB.length) return false;
|
|
39
|
+
return timingSafeEqual(bufA, bufB);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export class PairingStore {
|
|
43
|
+
private requests = new Map<string, PairingRequest>();
|
|
44
|
+
private sweepTimer: ReturnType<typeof setInterval> | null = null;
|
|
45
|
+
|
|
46
|
+
start(): void {
|
|
47
|
+
this.sweepTimer = setInterval(() => this.sweep(), SWEEP_INTERVAL_MS);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
stop(): void {
|
|
51
|
+
if (this.sweepTimer) {
|
|
52
|
+
clearInterval(this.sweepTimer);
|
|
53
|
+
this.sweepTimer = null;
|
|
54
|
+
}
|
|
55
|
+
this.requests.clear();
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Pre-register a pairing request (called when QR is displayed).
|
|
60
|
+
* Idempotent: if the same ID exists and secret matches, overwrite.
|
|
61
|
+
* Returns false with 'conflict' if ID exists but secret doesn't match.
|
|
62
|
+
*/
|
|
63
|
+
register(params: {
|
|
64
|
+
pairingRequestId: string;
|
|
65
|
+
pairingSecret: string;
|
|
66
|
+
gatewayUrl: string;
|
|
67
|
+
localLanUrl?: string | null;
|
|
68
|
+
}): { ok: true } | { ok: false; reason: 'conflict' } {
|
|
69
|
+
const hashedSecret = hashValue(params.pairingSecret);
|
|
70
|
+
const existing = this.requests.get(params.pairingRequestId);
|
|
71
|
+
|
|
72
|
+
if (existing) {
|
|
73
|
+
if (!timingSafeCompare(existing.hashedPairingSecret, hashedSecret)) {
|
|
74
|
+
return { ok: false, reason: 'conflict' };
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
this.requests.set(params.pairingRequestId, {
|
|
79
|
+
pairingRequestId: params.pairingRequestId,
|
|
80
|
+
hashedPairingSecret: hashedSecret,
|
|
81
|
+
status: 'registered',
|
|
82
|
+
gatewayUrl: params.gatewayUrl,
|
|
83
|
+
localLanUrl: params.localLanUrl ?? null,
|
|
84
|
+
createdAt: Date.now(),
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
log.info({ pairingRequestId: params.pairingRequestId }, 'Pairing request registered');
|
|
88
|
+
return { ok: true };
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* iOS initiates a pairing request. Validates the secret and transitions
|
|
93
|
+
* the entry to "pending" (or "approved" if auto-approved).
|
|
94
|
+
*/
|
|
95
|
+
beginRequest(params: {
|
|
96
|
+
pairingRequestId: string;
|
|
97
|
+
pairingSecret: string;
|
|
98
|
+
deviceId: string;
|
|
99
|
+
deviceName: string;
|
|
100
|
+
}): { ok: true; entry: PairingRequest } | { ok: false; reason: 'not_found' | 'invalid_secret' | 'expired' } {
|
|
101
|
+
const entry = this.requests.get(params.pairingRequestId);
|
|
102
|
+
if (!entry) {
|
|
103
|
+
return { ok: false, reason: 'not_found' };
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (entry.status === 'expired' || entry.status === 'denied') {
|
|
107
|
+
return { ok: false, reason: 'expired' };
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const hashedSecret = hashValue(params.pairingSecret);
|
|
111
|
+
if (!timingSafeCompare(entry.hashedPairingSecret, hashedSecret)) {
|
|
112
|
+
return { ok: false, reason: 'invalid_secret' };
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
entry.hashedDeviceId = hashValue(params.deviceId);
|
|
116
|
+
entry.deviceName = params.deviceName;
|
|
117
|
+
if (entry.status === 'registered') {
|
|
118
|
+
entry.status = 'pending';
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return { ok: true, entry };
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Approve a pairing request. Sets the bearer token for iOS to retrieve.
|
|
126
|
+
*/
|
|
127
|
+
approve(pairingRequestId: string, bearerToken: string): PairingRequest | null {
|
|
128
|
+
const entry = this.requests.get(pairingRequestId);
|
|
129
|
+
if (!entry) return null;
|
|
130
|
+
entry.status = 'approved';
|
|
131
|
+
entry.bearerToken = bearerToken;
|
|
132
|
+
return entry;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Deny a pairing request.
|
|
137
|
+
*/
|
|
138
|
+
deny(pairingRequestId: string): PairingRequest | null {
|
|
139
|
+
const entry = this.requests.get(pairingRequestId);
|
|
140
|
+
if (!entry) return null;
|
|
141
|
+
entry.status = 'denied';
|
|
142
|
+
return entry;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Get a pairing request by ID.
|
|
147
|
+
*/
|
|
148
|
+
get(pairingRequestId: string): PairingRequest | null {
|
|
149
|
+
return this.requests.get(pairingRequestId) ?? null;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Validate the secret for a status poll request (timing-safe).
|
|
154
|
+
*/
|
|
155
|
+
validateSecret(pairingRequestId: string, secret: string): boolean {
|
|
156
|
+
const entry = this.requests.get(pairingRequestId);
|
|
157
|
+
if (!entry) return false;
|
|
158
|
+
const hashedSecret = hashValue(secret);
|
|
159
|
+
return timingSafeCompare(entry.hashedPairingSecret, hashedSecret);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
private sweep(): void {
|
|
163
|
+
const now = Date.now();
|
|
164
|
+
for (const [id, entry] of this.requests) {
|
|
165
|
+
if (now - entry.createdAt > TTL_MS) {
|
|
166
|
+
if (entry.status !== 'approved') {
|
|
167
|
+
entry.status = 'expired';
|
|
168
|
+
}
|
|
169
|
+
// Remove entries older than 2x TTL regardless of status
|
|
170
|
+
if (now - entry.createdAt > TTL_MS * 2) {
|
|
171
|
+
this.requests.delete(id);
|
|
172
|
+
log.debug({ pairingRequestId: id }, 'Pairing request swept');
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { initializeProviders } from '../providers/registry.js';
|
|
2
|
+
import { initializeTools } from '../tools/registry.js';
|
|
3
|
+
import { registerWatcherProvider } from '../watcher/provider-registry.js';
|
|
4
|
+
import { gmailProvider } from '../watcher/providers/gmail.js';
|
|
5
|
+
import { googleCalendarProvider } from '../watcher/providers/google-calendar.js';
|
|
6
|
+
import { slackProvider as slackWatcherProvider } from '../watcher/providers/slack.js';
|
|
7
|
+
import { githubProvider } from '../watcher/providers/github.js';
|
|
8
|
+
import { linearProvider } from '../watcher/providers/linear.js';
|
|
9
|
+
import { registerMessagingProvider } from '../messaging/registry.js';
|
|
10
|
+
import { slackProvider as slackMessagingProvider } from '../messaging/providers/slack/adapter.js';
|
|
11
|
+
import { gmailMessagingProvider } from '../messaging/providers/gmail/adapter.js';
|
|
12
|
+
import { telegramBotMessagingProvider } from '../messaging/providers/telegram-bot/adapter.js';
|
|
13
|
+
import { smsMessagingProvider } from '../messaging/providers/sms/adapter.js';
|
|
14
|
+
import { whatsappMessagingProvider } from '../messaging/providers/whatsapp/adapter.js';
|
|
15
|
+
import { initWatcherEngine } from '../watcher/engine.js';
|
|
16
|
+
import type { AssistantConfig } from '../config/types.js';
|
|
17
|
+
import { getLogger } from '../util/logger.js';
|
|
18
|
+
|
|
19
|
+
const log = getLogger('lifecycle');
|
|
20
|
+
|
|
21
|
+
export async function initializeProvidersAndTools(config: AssistantConfig): Promise<void> {
|
|
22
|
+
log.info('Daemon startup: initializing providers and tools');
|
|
23
|
+
initializeProviders(config);
|
|
24
|
+
await initializeTools();
|
|
25
|
+
log.info('Daemon startup: providers and tools initialized');
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function registerWatcherProviders(): void {
|
|
29
|
+
registerWatcherProvider(gmailProvider);
|
|
30
|
+
registerWatcherProvider(googleCalendarProvider);
|
|
31
|
+
registerWatcherProvider(slackWatcherProvider);
|
|
32
|
+
registerWatcherProvider(githubProvider);
|
|
33
|
+
registerWatcherProvider(linearProvider);
|
|
34
|
+
initWatcherEngine();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function registerMessagingProviders(): void {
|
|
38
|
+
registerMessagingProvider(slackMessagingProvider);
|
|
39
|
+
registerMessagingProvider(gmailMessagingProvider);
|
|
40
|
+
registerMessagingProvider(telegramBotMessagingProvider);
|
|
41
|
+
registerMessagingProvider(smsMessagingProvider);
|
|
42
|
+
registerMessagingProvider(whatsappMessagingProvider);
|
|
43
|
+
}
|
|
@@ -23,6 +23,9 @@ const log = getLogger('ride-shotgun-handler');
|
|
|
23
23
|
/** Active network recorders keyed by watchId. */
|
|
24
24
|
const activeRecorders = new Map<string, NetworkRecorder>();
|
|
25
25
|
|
|
26
|
+
/** Active progress interval timers keyed by watchId, cleared on session completion. */
|
|
27
|
+
const activeProgressIntervals = new Map<string, NodeJS.Timeout>();
|
|
28
|
+
|
|
26
29
|
/** Return domain-specific URL patterns that indicate a successful login. */
|
|
27
30
|
function getLoginSignals(targetDomain?: string): string[] {
|
|
28
31
|
if (targetDomain === 'x.com' || targetDomain === 'twitter.com') {
|
|
@@ -52,6 +55,13 @@ async function completeSession(session: WatchSession): Promise<void> {
|
|
|
52
55
|
session.timeoutHandle = undefined;
|
|
53
56
|
}
|
|
54
57
|
|
|
58
|
+
// Clear progress interval timer if one was registered for this session
|
|
59
|
+
const progressTimer = activeProgressIntervals.get(session.watchId);
|
|
60
|
+
if (progressTimer) {
|
|
61
|
+
clearInterval(progressTimer);
|
|
62
|
+
activeProgressIntervals.delete(session.watchId);
|
|
63
|
+
}
|
|
64
|
+
|
|
55
65
|
const { watchId, sessionId } = session;
|
|
56
66
|
log.info(
|
|
57
67
|
{ watchId, sessionId, observationCount: session.observations.length },
|
|
@@ -135,9 +145,62 @@ export async function handleRideShotgunStart(
|
|
|
135
145
|
activeRecorders.set(watchId, recorder);
|
|
136
146
|
log.info({ watchId, targetDomain, attempt }, 'Network recording started for learn session');
|
|
137
147
|
|
|
148
|
+
// Send periodic progress updates with network entry counts and idle detection
|
|
149
|
+
let lastNetworkEntryCount = 0;
|
|
150
|
+
let lastActivityTimestamp = Date.now();
|
|
151
|
+
let idleHintSent = false;
|
|
152
|
+
|
|
153
|
+
const progressInterval: NodeJS.Timeout = setInterval(() => {
|
|
154
|
+
if (session.status !== 'active') {
|
|
155
|
+
clearInterval(progressInterval);
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
const currentCount = recorder.entryCount;
|
|
160
|
+
|
|
161
|
+
// Track activity: reset idle timer when count changes
|
|
162
|
+
if (currentCount !== lastNetworkEntryCount) {
|
|
163
|
+
lastNetworkEntryCount = currentCount;
|
|
164
|
+
lastActivityTimestamp = Date.now();
|
|
165
|
+
// If we previously sent an idle hint, clear it now that activity resumed
|
|
166
|
+
if (idleHintSent) {
|
|
167
|
+
idleHintSent = false;
|
|
168
|
+
log.info({ watchId, currentCount }, 'Activity resumed — clearing idleHint');
|
|
169
|
+
ctx.send(socket, {
|
|
170
|
+
type: 'ride_shotgun_progress',
|
|
171
|
+
watchId,
|
|
172
|
+
message: `Recording network traffic...`,
|
|
173
|
+
networkEntryCount: currentCount,
|
|
174
|
+
statusMessage: 'Recording network traffic...',
|
|
175
|
+
idleHint: false,
|
|
176
|
+
});
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Idle detection: if some initial activity happened and no new entries for 15s, hint once
|
|
182
|
+
const idleMs = Date.now() - lastActivityTimestamp;
|
|
183
|
+
let idleHint: boolean | undefined;
|
|
184
|
+
if (!idleHintSent && currentCount > 0 && idleMs >= 15_000) {
|
|
185
|
+
idleHint = true;
|
|
186
|
+
idleHintSent = true;
|
|
187
|
+
log.info({ watchId, currentCount, idleMs }, 'Idle detected — sending idleHint');
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
ctx.send(socket, {
|
|
191
|
+
type: 'ride_shotgun_progress',
|
|
192
|
+
watchId,
|
|
193
|
+
message: `Recording network traffic...`,
|
|
194
|
+
networkEntryCount: currentCount,
|
|
195
|
+
statusMessage: 'Recording network traffic...',
|
|
196
|
+
...(idleHint !== undefined ? { idleHint } : {}),
|
|
197
|
+
});
|
|
198
|
+
}, 5000);
|
|
199
|
+
activeProgressIntervals.set(watchId, progressInterval);
|
|
200
|
+
|
|
138
201
|
// For x.com, auto-navigate Chrome through key pages to capture the full API surface.
|
|
139
202
|
// Skip login detection — auto-navigation will complete the session when done.
|
|
140
|
-
if (targetDomain === 'x.com' || targetDomain === 'twitter.com') {
|
|
203
|
+
if ((targetDomain === 'x.com' || targetDomain === 'twitter.com') && msg.autoNavigate !== false) {
|
|
141
204
|
// Don't set onLoginDetected — it would kill the session after the first
|
|
142
205
|
// GraphQL call (5s grace), before auto-navigation finishes.
|
|
143
206
|
const abortSignal = { aborted: false };
|
|
@@ -192,8 +255,10 @@ export async function handleRideShotgunStart(
|
|
|
192
255
|
completeSession(session);
|
|
193
256
|
}
|
|
194
257
|
});
|
|
258
|
+
} else if (msg.autoNavigate === false && targetDomain) {
|
|
259
|
+
// Manual mode: just record network traffic until timeout or early stop — no login detection shortcut.
|
|
195
260
|
} else {
|
|
196
|
-
// No targetDomain: use login detection
|
|
261
|
+
// No targetDomain or targetDomain without explicit autoNavigate=false: use login detection
|
|
197
262
|
recorder.onLoginDetected = () => {
|
|
198
263
|
log.info({ watchId }, 'Login detected — auto-stopping learn session');
|
|
199
264
|
completeSession(session);
|
package/src/daemon/server.ts
CHANGED
|
@@ -15,6 +15,7 @@ import { IngressBlockedError } from '../util/errors.js';
|
|
|
15
15
|
import * as conversationStore from '../memory/conversation-store.js';
|
|
16
16
|
import * as attachmentsStore from '../memory/attachments-store.js';
|
|
17
17
|
import { Session, DEFAULT_MEMORY_POLICY, type SessionMemoryPolicy } from './session.js';
|
|
18
|
+
import { parseChannelId, type ChannelId } from '../channels/types.js';
|
|
18
19
|
import { resolveChannelCapabilities } from './session-runtime-assembly.js';
|
|
19
20
|
import { ComputerUseSession } from './computer-use-session.js';
|
|
20
21
|
import {
|
|
@@ -31,7 +32,6 @@ import { ensureBlobDir, sweepStaleBlobs } from './ipc-blob-store.js';
|
|
|
31
32
|
import { bootstrapHomeBaseAppLink } from '../home-base/bootstrap.js';
|
|
32
33
|
import { SessionEvictor } from './session-evictor.js';
|
|
33
34
|
import { getSubagentManager } from '../subagent/index.js';
|
|
34
|
-
import { tryRouteCallMessage } from '../calls/call-bridge.js';
|
|
35
35
|
import { resolveSlash } from './session-slash.js';
|
|
36
36
|
import { createUserMessage, createAssistantMessage } from '../agent/message-types.js';
|
|
37
37
|
import { registerDaemonCallbacks } from '../work-items/work-item-runner.js';
|
|
@@ -53,6 +53,24 @@ function readPackageVersion(): string | undefined {
|
|
|
53
53
|
|
|
54
54
|
const daemonVersion = readPackageVersion();
|
|
55
55
|
|
|
56
|
+
function resolveTurnChannel(sourceChannel?: string, transportChannelId?: string): ChannelId {
|
|
57
|
+
if (sourceChannel != null) {
|
|
58
|
+
const parsed = parseChannelId(sourceChannel);
|
|
59
|
+
if (!parsed) {
|
|
60
|
+
throw new Error(`Invalid sourceChannel: ${sourceChannel}`);
|
|
61
|
+
}
|
|
62
|
+
return parsed;
|
|
63
|
+
}
|
|
64
|
+
if (transportChannelId != null) {
|
|
65
|
+
const parsed = parseChannelId(transportChannelId);
|
|
66
|
+
if (!parsed) {
|
|
67
|
+
throw new Error(`Invalid transport.channelId: ${transportChannelId}`);
|
|
68
|
+
}
|
|
69
|
+
return parsed;
|
|
70
|
+
}
|
|
71
|
+
return 'macos';
|
|
72
|
+
}
|
|
73
|
+
|
|
56
74
|
export class DaemonServer {
|
|
57
75
|
private server: net.Server | null = null;
|
|
58
76
|
private tcpServer: tls.Server | null = null;
|
|
@@ -358,7 +376,7 @@ export class DaemonServer {
|
|
|
358
376
|
const parseDurationMs = Number(process.hrtime.bigint() - parseStartNs) / 1_000_000;
|
|
359
377
|
for (const entry of parsed) {
|
|
360
378
|
const msg = entry.msg;
|
|
361
|
-
if (typeof msg === 'object' && msg
|
|
379
|
+
if (typeof msg === 'object' && msg != null && (msg as { type?: unknown }).type === 'cu_observation') {
|
|
362
380
|
const maybeSessionId = (msg as { sessionId?: unknown }).sessionId;
|
|
363
381
|
const sessionId = typeof maybeSessionId === 'string' ? maybeSessionId : 'unknown';
|
|
364
382
|
const previousSequence = this.cuObservationParseSequence.get(sessionId) ?? 0;
|
|
@@ -488,6 +506,20 @@ export class DaemonServer {
|
|
|
488
506
|
}
|
|
489
507
|
}
|
|
490
508
|
|
|
509
|
+
get lastConfigFingerprint(): string {
|
|
510
|
+
return this.configWatcher.lastFingerprint;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
set lastConfigFingerprint(value: string) {
|
|
514
|
+
this.configWatcher.lastFingerprint = value;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
refreshConfigFromSources(): boolean {
|
|
518
|
+
const changed = this.configWatcher.refreshConfigFromSources();
|
|
519
|
+
if (changed) this.evictSessionsForReload();
|
|
520
|
+
return changed;
|
|
521
|
+
}
|
|
522
|
+
|
|
491
523
|
private async sendInitialSession(socket: net.Socket): Promise<void> {
|
|
492
524
|
const conversation = conversationStore.getLatestConversation();
|
|
493
525
|
if (!conversation) {
|
|
@@ -669,6 +701,12 @@ export class DaemonServer {
|
|
|
669
701
|
session.setAssistantId(options?.assistantId ?? 'self');
|
|
670
702
|
session.setGuardianContext(options?.guardianContext ?? null);
|
|
671
703
|
session.setChannelCapabilities(resolveChannelCapabilities(sourceChannel));
|
|
704
|
+
session.setCommandIntent(options?.commandIntent ?? null);
|
|
705
|
+
const resolvedChannel = resolveTurnChannel(sourceChannel, options?.transport?.channelId);
|
|
706
|
+
session.setTurnChannelContext({
|
|
707
|
+
userMessageChannel: resolvedChannel,
|
|
708
|
+
assistantMessageChannel: resolvedChannel,
|
|
709
|
+
});
|
|
672
710
|
|
|
673
711
|
const attachments = attachmentIds
|
|
674
712
|
? attachmentsStore.getAttachmentsByIds(attachmentIds).map((a) => ({
|
|
@@ -682,21 +720,6 @@ export class DaemonServer {
|
|
|
682
720
|
const requestId = crypto.randomUUID();
|
|
683
721
|
const messageId = session.persistUserMessage(content, attachments, requestId);
|
|
684
722
|
|
|
685
|
-
let bridgeHandled = false;
|
|
686
|
-
try {
|
|
687
|
-
const bridgeResult = await tryRouteCallMessage(conversationId, content, messageId);
|
|
688
|
-
bridgeHandled = bridgeResult.handled;
|
|
689
|
-
} catch (err) {
|
|
690
|
-
log.warn({ err, conversationId }, 'Call bridge check failed (non-fatal), proceeding with agent loop');
|
|
691
|
-
}
|
|
692
|
-
|
|
693
|
-
if (bridgeHandled) {
|
|
694
|
-
resetSessionProcessingState(session);
|
|
695
|
-
session.drainQueue('loop_complete');
|
|
696
|
-
log.info({ conversationId, messageId }, 'User message consumed by call bridge, skipping agent loop');
|
|
697
|
-
return { messageId };
|
|
698
|
-
}
|
|
699
|
-
|
|
700
723
|
session.runAgentLoop(content, messageId, () => {}).catch((err) => {
|
|
701
724
|
log.error({ err, conversationId }, 'Background agent loop failed');
|
|
702
725
|
});
|
|
@@ -725,6 +748,12 @@ export class DaemonServer {
|
|
|
725
748
|
session.setAssistantId(options?.assistantId ?? 'self');
|
|
726
749
|
session.setGuardianContext(options?.guardianContext ?? null);
|
|
727
750
|
session.setChannelCapabilities(resolveChannelCapabilities(sourceChannel));
|
|
751
|
+
session.setCommandIntent(options?.commandIntent ?? null);
|
|
752
|
+
const resolvedChannel2 = resolveTurnChannel(sourceChannel, options?.transport?.channelId);
|
|
753
|
+
session.setTurnChannelContext({
|
|
754
|
+
userMessageChannel: resolvedChannel2,
|
|
755
|
+
assistantMessageChannel: resolvedChannel2,
|
|
756
|
+
});
|
|
728
757
|
|
|
729
758
|
const attachments = attachmentIds
|
|
730
759
|
? attachmentsStore.getAttachmentsByIds(attachmentIds).map((a) => ({
|
|
@@ -738,19 +767,33 @@ export class DaemonServer {
|
|
|
738
767
|
const slashResult = resolveSlash(content);
|
|
739
768
|
|
|
740
769
|
if (slashResult.kind === 'unknown') {
|
|
770
|
+
const serverTurnCtx = session.getTurnChannelContext();
|
|
771
|
+
const serverChannelMeta = serverTurnCtx
|
|
772
|
+
? { userMessageChannel: serverTurnCtx.userMessageChannel, assistantMessageChannel: serverTurnCtx.assistantMessageChannel }
|
|
773
|
+
: undefined;
|
|
741
774
|
const userMsg = createUserMessage(content, attachments);
|
|
742
775
|
const persisted = conversationStore.addMessage(
|
|
743
776
|
conversationId,
|
|
744
777
|
'user',
|
|
745
778
|
JSON.stringify(userMsg.content),
|
|
779
|
+
serverChannelMeta,
|
|
746
780
|
);
|
|
747
781
|
session.getMessages().push(userMsg);
|
|
748
782
|
|
|
783
|
+
if (serverTurnCtx) {
|
|
784
|
+
try {
|
|
785
|
+
conversationStore.setConversationOriginChannelIfUnset(conversationId, serverTurnCtx.userMessageChannel);
|
|
786
|
+
} catch (err) {
|
|
787
|
+
log.warn({ err, conversationId }, 'Failed to set origin channel (best-effort)');
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
|
|
749
791
|
const assistantMsg = createAssistantMessage(slashResult.message);
|
|
750
792
|
conversationStore.addMessage(
|
|
751
793
|
conversationId,
|
|
752
794
|
'assistant',
|
|
753
795
|
JSON.stringify(assistantMsg.content),
|
|
796
|
+
serverChannelMeta,
|
|
754
797
|
);
|
|
755
798
|
session.getMessages().push(assistantMsg);
|
|
756
799
|
return { messageId: persisted.id };
|
|
@@ -771,22 +814,6 @@ export class DaemonServer {
|
|
|
771
814
|
throw err;
|
|
772
815
|
}
|
|
773
816
|
|
|
774
|
-
let bridgeHandled = false;
|
|
775
|
-
try {
|
|
776
|
-
const bridgeResult = await tryRouteCallMessage(conversationId, resolvedContent, messageId);
|
|
777
|
-
bridgeHandled = bridgeResult.handled;
|
|
778
|
-
} catch (err) {
|
|
779
|
-
log.warn({ err, conversationId }, 'Call bridge check failed (non-fatal), proceeding with agent loop');
|
|
780
|
-
}
|
|
781
|
-
|
|
782
|
-
if (bridgeHandled) {
|
|
783
|
-
(session as unknown as { preactivatedSkillIds?: string[] }).preactivatedSkillIds = undefined;
|
|
784
|
-
resetSessionProcessingState(session);
|
|
785
|
-
session.drainQueue('loop_complete');
|
|
786
|
-
log.info({ conversationId, messageId }, 'User message consumed by call bridge, skipping agent loop');
|
|
787
|
-
return { messageId };
|
|
788
|
-
}
|
|
789
|
-
|
|
790
817
|
await session.runAgentLoop(resolvedContent, messageId, () => {});
|
|
791
818
|
|
|
792
819
|
return { messageId };
|
|
@@ -809,14 +836,3 @@ export class DaemonServer {
|
|
|
809
836
|
}
|
|
810
837
|
|
|
811
838
|
}
|
|
812
|
-
|
|
813
|
-
function resetSessionProcessingState(session: Session): void {
|
|
814
|
-
const s = session as unknown as {
|
|
815
|
-
processing: boolean;
|
|
816
|
-
abortController: AbortController | null;
|
|
817
|
-
currentRequestId: string | undefined;
|
|
818
|
-
};
|
|
819
|
-
s.processing = false;
|
|
820
|
-
s.abortController = null;
|
|
821
|
-
s.currentRequestId = undefined;
|
|
822
|
-
}
|