@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
|
@@ -61,7 +61,7 @@ const SENSITIVE_KEYS = new Set([
|
|
|
61
61
|
function redactDeep(value: unknown): unknown {
|
|
62
62
|
if (typeof value === 'string') return redact(value);
|
|
63
63
|
if (Array.isArray(value)) return value.map(redactDeep);
|
|
64
|
-
if (value
|
|
64
|
+
if (value != null && typeof value === 'object') {
|
|
65
65
|
const out: Record<string, unknown> = {};
|
|
66
66
|
for (const [k, v] of Object.entries(value as Record<string, unknown>)) {
|
|
67
67
|
if (SENSITIVE_KEYS.has(k.toLowerCase())) {
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import * as net from 'node:net';
|
|
2
|
-
import {
|
|
3
|
-
import { getFailoverProvider, listProviders } from '../../providers/registry.js';
|
|
2
|
+
import { getConfiguredProvider } from '../../providers/provider-send-message.js';
|
|
4
3
|
import type { DictationRequest } from '../ipc-protocol.js';
|
|
5
4
|
import { log, defineHandlers, type HandlerContext } from './shared.js';
|
|
6
5
|
|
|
@@ -147,15 +146,14 @@ export async function handleDictationRequest(
|
|
|
147
146
|
: msg.transcription; // command prompt already embeds the selected text and instruction
|
|
148
147
|
|
|
149
148
|
try {
|
|
150
|
-
const
|
|
151
|
-
if (!
|
|
152
|
-
log.warn(
|
|
149
|
+
const provider = getConfiguredProvider();
|
|
150
|
+
if (!provider) {
|
|
151
|
+
log.warn('Dictation: no provider available, returning raw transcription');
|
|
153
152
|
const fallbackText = mode === 'command' ? (msg.context.selectedText ?? msg.transcription) : msg.transcription;
|
|
154
153
|
ctx.send(socket, { type: 'dictation_response', text: fallbackText, mode });
|
|
155
154
|
return;
|
|
156
155
|
}
|
|
157
156
|
|
|
158
|
-
const provider = getFailoverProvider(config.provider, config.providerOrder);
|
|
159
157
|
const response = await provider.sendMessage(
|
|
160
158
|
[{ role: 'user', content: [{ type: 'text', text: userText }] }],
|
|
161
159
|
[], // no tools
|
|
@@ -2,12 +2,23 @@ import { defineHandlers } from './shared.js';
|
|
|
2
2
|
import type { HandlerContext } from './shared.js';
|
|
3
3
|
import type { DocumentSaveRequest, DocumentLoadRequest, DocumentListRequest } from '../ipc-protocol.js';
|
|
4
4
|
import type * as net from 'node:net';
|
|
5
|
-
import
|
|
6
|
-
import { getDb } from '../../memory/db.js';
|
|
5
|
+
import { rawRun, rawGet, rawAll } from '../../memory/db.js';
|
|
7
6
|
import { getLogger } from '../../util/logger.js';
|
|
8
7
|
|
|
9
8
|
const log = getLogger('documents');
|
|
10
9
|
|
|
10
|
+
interface DocumentRow {
|
|
11
|
+
surface_id: string;
|
|
12
|
+
conversation_id: string;
|
|
13
|
+
title: string;
|
|
14
|
+
content: string;
|
|
15
|
+
word_count: number;
|
|
16
|
+
created_at: number;
|
|
17
|
+
updated_at: number;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
type DocumentListRow = Omit<DocumentRow, 'content'>;
|
|
21
|
+
|
|
11
22
|
export function handleDocumentSave(msg: DocumentSaveRequest, socket: net.Socket, ctx: HandlerContext): void {
|
|
12
23
|
log.info({
|
|
13
24
|
surfaceId: msg.surfaceId,
|
|
@@ -18,13 +29,9 @@ export function handleDocumentSave(msg: DocumentSaveRequest, socket: net.Socket,
|
|
|
18
29
|
}, 'Received save request');
|
|
19
30
|
|
|
20
31
|
try {
|
|
21
|
-
const db = getDb();
|
|
22
|
-
// Get the raw SQLite client from Drizzle
|
|
23
|
-
const sqlite = (db as unknown as { $client: Database }).$client;
|
|
24
32
|
const now = Date.now();
|
|
25
33
|
|
|
26
|
-
|
|
27
|
-
sqlite.run(
|
|
34
|
+
rawRun(
|
|
28
35
|
`INSERT INTO documents (surface_id, conversation_id, title, content, word_count, created_at, updated_at)
|
|
29
36
|
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
30
37
|
ON CONFLICT(surface_id) DO UPDATE SET
|
|
@@ -32,7 +39,7 @@ export function handleDocumentSave(msg: DocumentSaveRequest, socket: net.Socket,
|
|
|
32
39
|
content = excluded.content,
|
|
33
40
|
word_count = excluded.word_count,
|
|
34
41
|
updated_at = excluded.updated_at`,
|
|
35
|
-
|
|
42
|
+
msg.surfaceId, msg.conversationId, msg.title, msg.content, msg.wordCount, now, now,
|
|
36
43
|
);
|
|
37
44
|
|
|
38
45
|
ctx.send(socket, {
|
|
@@ -55,22 +62,11 @@ export function handleDocumentSave(msg: DocumentSaveRequest, socket: net.Socket,
|
|
|
55
62
|
|
|
56
63
|
export function handleDocumentLoad(msg: DocumentLoadRequest, socket: net.Socket, ctx: HandlerContext): void {
|
|
57
64
|
try {
|
|
58
|
-
const
|
|
59
|
-
const sqlite = (db as unknown as { $client: Database }).$client;
|
|
60
|
-
|
|
61
|
-
const result = sqlite.prepare(/*sql*/ `
|
|
65
|
+
const result = rawGet<DocumentRow>(/*sql*/ `
|
|
62
66
|
SELECT surface_id, conversation_id, title, content, word_count, created_at, updated_at
|
|
63
67
|
FROM documents
|
|
64
68
|
WHERE surface_id = ?
|
|
65
|
-
|
|
66
|
-
surface_id: string;
|
|
67
|
-
conversation_id: string;
|
|
68
|
-
title: string;
|
|
69
|
-
content: string;
|
|
70
|
-
word_count: number;
|
|
71
|
-
created_at: number;
|
|
72
|
-
updated_at: number;
|
|
73
|
-
} | undefined;
|
|
69
|
+
`, msg.surfaceId);
|
|
74
70
|
|
|
75
71
|
if (result) {
|
|
76
72
|
ctx.send(socket, {
|
|
@@ -119,9 +115,6 @@ export function handleDocumentLoad(msg: DocumentLoadRequest, socket: net.Socket,
|
|
|
119
115
|
|
|
120
116
|
export function handleDocumentList(msg: DocumentListRequest, socket: net.Socket, ctx: HandlerContext): void {
|
|
121
117
|
try {
|
|
122
|
-
const db = getDb();
|
|
123
|
-
const sqlite = (db as unknown as { $client: Database }).$client;
|
|
124
|
-
|
|
125
118
|
let query = /*sql*/ `
|
|
126
119
|
SELECT surface_id, conversation_id, title, word_count, created_at, updated_at
|
|
127
120
|
FROM documents
|
|
@@ -135,14 +128,7 @@ export function handleDocumentList(msg: DocumentListRequest, socket: net.Socket,
|
|
|
135
128
|
|
|
136
129
|
query += ' ORDER BY updated_at DESC';
|
|
137
130
|
|
|
138
|
-
const results =
|
|
139
|
-
surface_id: string;
|
|
140
|
-
conversation_id: string;
|
|
141
|
-
title: string;
|
|
142
|
-
word_count: number;
|
|
143
|
-
created_at: number;
|
|
144
|
-
updated_at: number;
|
|
145
|
-
}>;
|
|
131
|
+
const results = rawAll<DocumentListRow>(query, ...params);
|
|
146
132
|
|
|
147
133
|
ctx.send(socket, {
|
|
148
134
|
type: 'document_list_response',
|
|
@@ -23,6 +23,8 @@ import { twitterAuthHandlers } from './twitter-auth.js';
|
|
|
23
23
|
import { workspaceFileHandlers } from './workspace-files.js';
|
|
24
24
|
import { identityHandlers } from './identity.js';
|
|
25
25
|
import { dictationHandlers } from './dictation.js';
|
|
26
|
+
import { inboxInviteHandlers } from './config-inbox.js';
|
|
27
|
+
import { pairingHandlers } from './pairing.js';
|
|
26
28
|
|
|
27
29
|
// Re-export types and utilities for backwards compatibility
|
|
28
30
|
export type {
|
|
@@ -88,6 +90,11 @@ const inlineHandlers = defineHandlers({
|
|
|
88
90
|
},
|
|
89
91
|
integration_disconnect: () => { /* no-op — integration registry removed */ },
|
|
90
92
|
|
|
93
|
+
// Stub handler: assistant_inbox — real implementation will be added in a follow-up PR.
|
|
94
|
+
assistant_inbox: (_msg, socket, ctx) => {
|
|
95
|
+
ctx.send(socket, { type: 'assistant_inbox_response', success: false, error: 'Not yet implemented' });
|
|
96
|
+
},
|
|
97
|
+
|
|
91
98
|
});
|
|
92
99
|
|
|
93
100
|
const handlers = {
|
|
@@ -109,6 +116,8 @@ const handlers = {
|
|
|
109
116
|
...workspaceFileHandlers,
|
|
110
117
|
...identityHandlers,
|
|
111
118
|
...dictationHandlers,
|
|
119
|
+
...inboxInviteHandlers,
|
|
120
|
+
...pairingHandlers,
|
|
112
121
|
...inlineHandlers,
|
|
113
122
|
} satisfies DispatchMap;
|
|
114
123
|
|
|
@@ -3,8 +3,7 @@ import { v4 as uuid } from 'uuid';
|
|
|
3
3
|
import { readFileSync } from 'node:fs';
|
|
4
4
|
import { createHash } from 'node:crypto';
|
|
5
5
|
import * as conversationStore from '../../memory/conversation-store.js';
|
|
6
|
-
import {
|
|
7
|
-
import { getFailoverProvider, listProviders } from '../../providers/registry.js';
|
|
6
|
+
import { getConfiguredProvider } from '../../providers/provider-send-message.js';
|
|
8
7
|
import type { Provider } from '../../providers/types.js';
|
|
9
8
|
import { classifyInteraction } from '../classifier.js';
|
|
10
9
|
import { checkIngressForSecrets } from '../../security/secret-ingress.js';
|
|
@@ -172,10 +171,9 @@ export async function handleSuggestionRequest(
|
|
|
172
171
|
}
|
|
173
172
|
|
|
174
173
|
// Try LLM suggestion using the configured provider
|
|
175
|
-
const
|
|
176
|
-
if (
|
|
174
|
+
const provider = getConfiguredProvider();
|
|
175
|
+
if (provider) {
|
|
177
176
|
try {
|
|
178
|
-
const provider = getFailoverProvider(config.provider, config.providerOrder);
|
|
179
177
|
let promise = suggestionInFlight.get(m.id);
|
|
180
178
|
if (!promise) {
|
|
181
179
|
promise = generateSuggestion(provider, text);
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import * as net from 'node:net';
|
|
2
|
+
import type {
|
|
3
|
+
PairingApprovalResponse,
|
|
4
|
+
ApprovedDeviceRemove,
|
|
5
|
+
} from '../ipc-protocol.js';
|
|
6
|
+
import { log, defineHandlers, type HandlerContext } from './shared.js';
|
|
7
|
+
import {
|
|
8
|
+
approveDevice,
|
|
9
|
+
removeDevice,
|
|
10
|
+
clearAllDevices,
|
|
11
|
+
listDevices,
|
|
12
|
+
} from '../approved-devices-store.js';
|
|
13
|
+
import type { PairingStore } from '../pairing-store.js';
|
|
14
|
+
|
|
15
|
+
/** Module-level reference set by the daemon server at startup. */
|
|
16
|
+
let pairingStoreRef: PairingStore | null = null;
|
|
17
|
+
let bearerTokenRef: string | undefined;
|
|
18
|
+
|
|
19
|
+
export function initPairingHandlers(store: PairingStore, bearerToken: string | undefined): void {
|
|
20
|
+
pairingStoreRef = store;
|
|
21
|
+
bearerTokenRef = bearerToken;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function handlePairingApprovalResponse(
|
|
25
|
+
msg: PairingApprovalResponse,
|
|
26
|
+
_socket: net.Socket,
|
|
27
|
+
_ctx: HandlerContext,
|
|
28
|
+
): void {
|
|
29
|
+
if (!pairingStoreRef) {
|
|
30
|
+
log.warn('Pairing store not initialized');
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const entry = pairingStoreRef.get(msg.pairingRequestId);
|
|
35
|
+
if (!entry) {
|
|
36
|
+
log.warn({ pairingRequestId: msg.pairingRequestId }, 'Pairing request not found for approval response');
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Idempotent: if already approved/denied, just re-broadcast the current status
|
|
41
|
+
if (entry.status === 'approved' || entry.status === 'denied') {
|
|
42
|
+
log.info({ pairingRequestId: msg.pairingRequestId, status: entry.status }, 'Duplicate approval response, no-op');
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (msg.decision === 'deny') {
|
|
47
|
+
pairingStoreRef.deny(msg.pairingRequestId);
|
|
48
|
+
log.info({ pairingRequestId: msg.pairingRequestId }, 'Pairing request denied');
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// approve_once or always_allow
|
|
53
|
+
if (!bearerTokenRef) {
|
|
54
|
+
log.error('Cannot approve pairing: no bearer token configured');
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
pairingStoreRef.approve(msg.pairingRequestId, bearerTokenRef);
|
|
59
|
+
log.info({ pairingRequestId: msg.pairingRequestId, decision: msg.decision }, 'Pairing request approved');
|
|
60
|
+
|
|
61
|
+
// If always_allow, persist the device to the allowlist
|
|
62
|
+
if (msg.decision === 'always_allow' && entry.hashedDeviceId) {
|
|
63
|
+
approveDevice(entry.hashedDeviceId, entry.deviceName ?? 'Unknown Device');
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function handleApprovedDevicesList(socket: net.Socket, ctx: HandlerContext): void {
|
|
68
|
+
const devices = listDevices();
|
|
69
|
+
ctx.send(socket, {
|
|
70
|
+
type: 'approved_devices_list_response',
|
|
71
|
+
devices,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function handleApprovedDeviceRemove(
|
|
76
|
+
msg: ApprovedDeviceRemove,
|
|
77
|
+
socket: net.Socket,
|
|
78
|
+
ctx: HandlerContext,
|
|
79
|
+
): void {
|
|
80
|
+
const success = removeDevice(msg.hashedDeviceId);
|
|
81
|
+
ctx.send(socket, {
|
|
82
|
+
type: 'approved_device_remove_response',
|
|
83
|
+
success,
|
|
84
|
+
});
|
|
85
|
+
log.info({ hashedDeviceId: msg.hashedDeviceId, success }, 'Device removal requested via IPC');
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function handleApprovedDevicesClear(_socket: net.Socket, _ctx: HandlerContext): void {
|
|
89
|
+
clearAllDevices();
|
|
90
|
+
log.info('All approved devices cleared via IPC');
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export const pairingHandlers = defineHandlers({
|
|
94
|
+
pairing_approval_response: handlePairingApprovalResponse,
|
|
95
|
+
approved_devices_list: (_msg, socket, ctx) => handleApprovedDevicesList(socket, ctx),
|
|
96
|
+
approved_device_remove: handleApprovedDeviceRemove,
|
|
97
|
+
approved_devices_clear: (_msg, socket, ctx) => handleApprovedDevicesClear(socket, ctx),
|
|
98
|
+
});
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import * as net from 'node:net';
|
|
2
|
+
import { isChannelId, parseChannelId } from '../../channels/types.js';
|
|
3
|
+
import { silentlyWithLog } from '../../util/silently.js';
|
|
2
4
|
import { v4 as uuid } from 'uuid';
|
|
3
5
|
import * as conversationStore from '../../memory/conversation-store.js';
|
|
4
6
|
import * as externalConversationStore from '../../memory/external-conversation-store.js';
|
|
@@ -14,6 +16,7 @@ import type {
|
|
|
14
16
|
SecretResponse,
|
|
15
17
|
SessionCreateRequest,
|
|
16
18
|
SessionSwitchRequest,
|
|
19
|
+
SessionRenameRequest,
|
|
17
20
|
CancelRequest,
|
|
18
21
|
DeleteQueuedMessage,
|
|
19
22
|
HistoryRequest,
|
|
@@ -22,6 +25,7 @@ import type {
|
|
|
22
25
|
UsageRequest,
|
|
23
26
|
SandboxSetRequest,
|
|
24
27
|
ServerMessage,
|
|
28
|
+
ConversationSearchRequest,
|
|
25
29
|
} from '../ipc-protocol.js';
|
|
26
30
|
import { getConfig } from '../../config/loader.js';
|
|
27
31
|
import { getSubagentManager } from '../../subagent/index.js';
|
|
@@ -80,7 +84,20 @@ export async function handleUserMessage(
|
|
|
80
84
|
attributes: { source: 'user_message' },
|
|
81
85
|
});
|
|
82
86
|
|
|
83
|
-
const
|
|
87
|
+
const ipcChannel = parseChannelId(msg.channel) ?? 'macos';
|
|
88
|
+
const queuedChannelMetadata = {
|
|
89
|
+
userMessageChannel: ipcChannel,
|
|
90
|
+
assistantMessageChannel: ipcChannel,
|
|
91
|
+
};
|
|
92
|
+
const result = session.enqueueMessage(
|
|
93
|
+
msg.content ?? '',
|
|
94
|
+
msg.attachments ?? [],
|
|
95
|
+
sendEvent,
|
|
96
|
+
requestId,
|
|
97
|
+
msg.activeSurfaceId,
|
|
98
|
+
msg.currentPage,
|
|
99
|
+
queuedChannelMetadata,
|
|
100
|
+
);
|
|
84
101
|
if (result.rejected) {
|
|
85
102
|
rlog.warn('Message rejected — queue is full');
|
|
86
103
|
session.traceEmitter.emit('request_error', 'Message rejected — queue is full', {
|
|
@@ -114,8 +131,13 @@ export async function handleUserMessage(
|
|
|
114
131
|
}
|
|
115
132
|
|
|
116
133
|
rlog.info('Processing user message');
|
|
134
|
+
session.setTurnChannelContext({
|
|
135
|
+
userMessageChannel: ipcChannel,
|
|
136
|
+
assistantMessageChannel: ipcChannel,
|
|
137
|
+
});
|
|
117
138
|
session.setAssistantId('self');
|
|
118
139
|
session.setGuardianContext(null);
|
|
140
|
+
session.setCommandIntent(null);
|
|
119
141
|
// Fire-and-forget: don't block the IPC handler so the connection can
|
|
120
142
|
// continue receiving messages (e.g. cancel, confirmations, or
|
|
121
143
|
// additional user_message that will be queued by the session).
|
|
@@ -210,12 +232,14 @@ export function handleSessionList(socket: net.Socket, ctx: HandlerContext, offse
|
|
|
210
232
|
type: 'session_list_response',
|
|
211
233
|
sessions: conversations.map((c) => {
|
|
212
234
|
const binding = bindings.get(c.id);
|
|
235
|
+
const originChannel = parseChannelId(c.originChannel);
|
|
213
236
|
return {
|
|
214
237
|
id: c.id,
|
|
215
238
|
title: c.title ?? 'Untitled',
|
|
216
239
|
updatedAt: c.updatedAt,
|
|
217
240
|
threadType: normalizeThreadType(c.threadType),
|
|
218
|
-
|
|
241
|
+
source: c.source ?? 'user',
|
|
242
|
+
...(binding && isChannelId(binding.sourceChannel) ? {
|
|
219
243
|
channelBinding: {
|
|
220
244
|
sourceChannel: binding.sourceChannel,
|
|
221
245
|
externalChatId: binding.externalChatId,
|
|
@@ -224,6 +248,7 @@ export function handleSessionList(socket: net.Socket, ctx: HandlerContext, offse
|
|
|
224
248
|
username: binding.username,
|
|
225
249
|
},
|
|
226
250
|
} : {}),
|
|
251
|
+
...(originChannel ? { conversationOriginChannel: originChannel } : {}),
|
|
227
252
|
};
|
|
228
253
|
}),
|
|
229
254
|
hasMore: offset + conversations.length < totalCount,
|
|
@@ -276,6 +301,11 @@ export async function handleSessionCreate(
|
|
|
276
301
|
ctx.socketToSession.set(socket, conversation.id);
|
|
277
302
|
const sendEvent = (event: ServerMessage) => ctx.send(socket, event);
|
|
278
303
|
const requestId = uuid();
|
|
304
|
+
const transportChannel = parseChannelId(msg.transport?.channelId) ?? 'macos';
|
|
305
|
+
session.setTurnChannelContext({
|
|
306
|
+
userMessageChannel: transportChannel,
|
|
307
|
+
assistantMessageChannel: transportChannel,
|
|
308
|
+
});
|
|
279
309
|
session.processMessage(msg.initialMessage, [], sendEvent, requestId).catch((err) => {
|
|
280
310
|
const message = err instanceof Error ? err.message : String(err);
|
|
281
311
|
log.error({ err, sessionId: conversation.id }, 'Error processing initial message');
|
|
@@ -323,6 +353,24 @@ export async function handleSessionSwitch(
|
|
|
323
353
|
});
|
|
324
354
|
}
|
|
325
355
|
|
|
356
|
+
export function handleSessionRename(
|
|
357
|
+
msg: SessionRenameRequest,
|
|
358
|
+
socket: net.Socket,
|
|
359
|
+
ctx: HandlerContext,
|
|
360
|
+
): void {
|
|
361
|
+
const conversation = conversationStore.getConversation(msg.sessionId);
|
|
362
|
+
if (!conversation) {
|
|
363
|
+
ctx.send(socket, { type: 'error', message: `Session ${msg.sessionId} not found` });
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
conversationStore.updateConversationTitle(msg.sessionId, msg.title);
|
|
367
|
+
ctx.send(socket, {
|
|
368
|
+
type: 'session_title_updated',
|
|
369
|
+
sessionId: msg.sessionId,
|
|
370
|
+
title: msg.title,
|
|
371
|
+
});
|
|
372
|
+
}
|
|
373
|
+
|
|
326
374
|
export function handleCancel(msg: CancelRequest, socket: net.Socket, ctx: HandlerContext): void {
|
|
327
375
|
const sessionId = msg.sessionId || ctx.socketToSession.get(socket);
|
|
328
376
|
if (sessionId) {
|
|
@@ -403,9 +451,12 @@ export function handleHistoryRequest(
|
|
|
403
451
|
if (a.mimeType.startsWith('video/') && !a.thumbnailBase64) {
|
|
404
452
|
const attachmentId = a.id;
|
|
405
453
|
const base64 = a.dataBase64;
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
454
|
+
silentlyWithLog(
|
|
455
|
+
generateVideoThumbnail(base64).then((thumb) => {
|
|
456
|
+
if (thumb) setAttachmentThumbnail(attachmentId, thumb);
|
|
457
|
+
}),
|
|
458
|
+
'video thumbnail generation',
|
|
459
|
+
);
|
|
409
460
|
}
|
|
410
461
|
|
|
411
462
|
return {
|
|
@@ -541,6 +592,22 @@ export function handleDeleteQueuedMessage(
|
|
|
541
592
|
}
|
|
542
593
|
}
|
|
543
594
|
|
|
595
|
+
export function handleConversationSearch(
|
|
596
|
+
msg: ConversationSearchRequest,
|
|
597
|
+
socket: net.Socket,
|
|
598
|
+
ctx: HandlerContext,
|
|
599
|
+
): void {
|
|
600
|
+
const results = conversationStore.searchConversations(msg.query, {
|
|
601
|
+
limit: msg.limit,
|
|
602
|
+
maxMessagesPerConversation: msg.maxMessagesPerConversation,
|
|
603
|
+
});
|
|
604
|
+
ctx.send(socket, {
|
|
605
|
+
type: 'conversation_search_response',
|
|
606
|
+
query: msg.query,
|
|
607
|
+
results,
|
|
608
|
+
});
|
|
609
|
+
}
|
|
610
|
+
|
|
544
611
|
export const sessionHandlers = defineHandlers({
|
|
545
612
|
user_message: handleUserMessage,
|
|
546
613
|
confirmation_response: handleConfirmationResponse,
|
|
@@ -549,6 +616,7 @@ export const sessionHandlers = defineHandlers({
|
|
|
549
616
|
session_create: handleSessionCreate,
|
|
550
617
|
sessions_clear: (_msg, socket, ctx) => handleSessionsClear(socket, ctx),
|
|
551
618
|
session_switch: handleSessionSwitch,
|
|
619
|
+
session_rename: handleSessionRename,
|
|
552
620
|
cancel: handleCancel,
|
|
553
621
|
delete_queued_message: handleDeleteQueuedMessage,
|
|
554
622
|
history_request: handleHistoryRequest,
|
|
@@ -556,4 +624,5 @@ export const sessionHandlers = defineHandlers({
|
|
|
556
624
|
regenerate: handleRegenerate,
|
|
557
625
|
usage_request: handleUsageRequest,
|
|
558
626
|
sandbox_set: handleSandboxSet,
|
|
627
|
+
conversation_search: handleConversationSearch,
|
|
559
628
|
});
|
|
@@ -105,6 +105,8 @@ export interface SessionCreateOptions {
|
|
|
105
105
|
memoryScopeId?: string;
|
|
106
106
|
isPrivateThread?: boolean;
|
|
107
107
|
strictPrivateSideEffects?: boolean;
|
|
108
|
+
/** Channel command intent metadata (e.g. Telegram /start). */
|
|
109
|
+
commandIntent?: { type: string; payload?: string; languageCode?: string };
|
|
108
110
|
}
|
|
109
111
|
|
|
110
112
|
/**
|
|
@@ -252,7 +254,7 @@ export function wireEscalationHandler(
|
|
|
252
254
|
}
|
|
253
255
|
|
|
254
256
|
export function isRecord(value: unknown): value is Record<string, unknown> {
|
|
255
|
-
return typeof value === 'object' && value
|
|
257
|
+
return typeof value === 'object' && value != null;
|
|
256
258
|
}
|
|
257
259
|
|
|
258
260
|
export function formatBytes(sizeBytes: number): string {
|
|
@@ -423,7 +423,7 @@ export async function handleSkillsSearch(
|
|
|
423
423
|
ctx: HandlerContext,
|
|
424
424
|
): Promise<void> {
|
|
425
425
|
try {
|
|
426
|
-
// Search vellum-skills catalog (
|
|
426
|
+
// Search vellum-skills catalog (platform API with bundled fallback)
|
|
427
427
|
const catalogEntries = await listCatalogEntries();
|
|
428
428
|
const query = (msg.query ?? '').toLowerCase();
|
|
429
429
|
const matchingCatalog = catalogEntries.filter((e) => {
|
|
@@ -72,6 +72,7 @@ export async function handleTwitterAuthStart(
|
|
|
72
72
|
clientId,
|
|
73
73
|
clientSecret,
|
|
74
74
|
extraParams: {},
|
|
75
|
+
tokenEndpointAuthMethod: clientSecret ? 'client_secret_basic' : undefined,
|
|
75
76
|
};
|
|
76
77
|
|
|
77
78
|
const result = await startOAuth2Flow(oauthConfig, {
|
|
@@ -131,6 +132,7 @@ export async function handleTwitterAuthStart(
|
|
|
131
132
|
oauth2TokenUrl: 'https://api.x.com/2/oauth2/token',
|
|
132
133
|
oauth2ClientId: clientId,
|
|
133
134
|
oauth2ClientSecret: clientSecret ?? null,
|
|
135
|
+
oauth2TokenEndpointAuthMethod: clientSecret ? 'client_secret_basic' : undefined,
|
|
134
136
|
grantedScopes: result.grantedScopes,
|
|
135
137
|
expiresAt: result.tokens.expiresIn ? Date.now() + result.tokens.expiresIn * 1000 : null,
|
|
136
138
|
});
|
|
@@ -393,7 +393,7 @@ export async function handleWorkItemRunTask(
|
|
|
393
393
|
// Compute required tools using the same resolution logic as preflight:
|
|
394
394
|
// work-item snapshot first, then task template, then all registered tools.
|
|
395
395
|
let requiredTools: string[];
|
|
396
|
-
if (workItem.requiredTools
|
|
396
|
+
if (workItem.requiredTools != null) {
|
|
397
397
|
requiredTools = sanitizeToolList(JSON.parse(workItem.requiredTools));
|
|
398
398
|
} else {
|
|
399
399
|
requiredTools = task.requiredTools
|
|
@@ -513,7 +513,7 @@ export async function handleWorkItemPreflight(
|
|
|
513
513
|
// back to the task template (or all registered tools) when the
|
|
514
514
|
// snapshot is null.
|
|
515
515
|
let requiredTools: string[];
|
|
516
|
-
if (workItem.requiredTools
|
|
516
|
+
if (workItem.requiredTools != null) {
|
|
517
517
|
requiredTools = sanitizeToolList(JSON.parse(workItem.requiredTools));
|
|
518
518
|
} else {
|
|
519
519
|
const task = getTask(workItem.taskId);
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import * as net from 'node:net';
|
|
2
|
-
import {
|
|
2
|
+
import { readFileSync } from 'node:fs';
|
|
3
3
|
import { join, resolve, sep } from 'node:path';
|
|
4
|
+
import { pathExists } from '../../util/fs.js';
|
|
4
5
|
import { getWorkspaceDir } from '../../util/platform.js';
|
|
5
6
|
import { log, defineHandlers, type HandlerContext } from './shared.js';
|
|
6
7
|
import type { WorkspaceFileReadRequest } from '../ipc-protocol.js';
|
|
@@ -13,7 +14,7 @@ function handleWorkspaceFilesList(socket: net.Socket, ctx: HandlerContext): void
|
|
|
13
14
|
const files = WORKSPACE_FILES.map((name) => ({
|
|
14
15
|
path: name,
|
|
15
16
|
name,
|
|
16
|
-
exists:
|
|
17
|
+
exists: pathExists(join(base, name)),
|
|
17
18
|
}));
|
|
18
19
|
ctx.send(socket, { type: 'workspace_files_list_response', files });
|
|
19
20
|
}
|
|
@@ -42,7 +43,7 @@ function handleWorkspaceFileRead(
|
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
try {
|
|
45
|
-
if (!
|
|
46
|
+
if (!pathExists(resolved)) {
|
|
46
47
|
ctx.send(socket, {
|
|
47
48
|
type: 'workspace_file_read_response',
|
|
48
49
|
path: requested,
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Installs standalone CLI launcher scripts in ~/.vellum/bin/ so that
|
|
3
|
+
* integration commands (e.g. `doordash`, `map`) can be invoked directly
|
|
4
|
+
* without requiring `vellum` on PATH.
|
|
5
|
+
*
|
|
6
|
+
* Each launcher is a shell script that hardcodes absolute paths to `bun`
|
|
7
|
+
* and the CLI entrypoint, forwarding all arguments to the appropriate
|
|
8
|
+
* subcommand.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { execSync } from 'node:child_process';
|
|
12
|
+
import { existsSync, mkdirSync, writeFileSync, chmodSync } from 'node:fs';
|
|
13
|
+
import { join } from 'node:path';
|
|
14
|
+
import { homedir } from 'node:os';
|
|
15
|
+
import { getLogger } from '../util/logger.js';
|
|
16
|
+
|
|
17
|
+
const log = getLogger('install-cli-launchers');
|
|
18
|
+
|
|
19
|
+
/** Integration subcommands that should get standalone launchers. */
|
|
20
|
+
const INTEGRATION_COMMANDS = ['doordash', 'map'];
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Resolve the absolute path to the bun binary.
|
|
24
|
+
* Prefers process.execPath (works when running under bun), then falls
|
|
25
|
+
* back to `which bun`.
|
|
26
|
+
*/
|
|
27
|
+
function resolveBunPath(): string {
|
|
28
|
+
// process.execPath points to the bun binary when running under bun
|
|
29
|
+
if (process.execPath && process.execPath.includes('bun')) {
|
|
30
|
+
return process.execPath;
|
|
31
|
+
}
|
|
32
|
+
try {
|
|
33
|
+
return execSync('which bun', { encoding: 'utf-8' }).trim();
|
|
34
|
+
} catch {
|
|
35
|
+
throw new Error('Could not find bun binary');
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Resolve the absolute path to the CLI entrypoint (index.ts).
|
|
41
|
+
* Uses import.meta.dirname to find the source tree root.
|
|
42
|
+
*/
|
|
43
|
+
function resolveCliEntrypoint(): string {
|
|
44
|
+
// This file is at assistant/src/daemon/install-cli-launchers.ts
|
|
45
|
+
// The CLI entrypoint is at assistant/src/index.ts
|
|
46
|
+
const thisDir = import.meta.dirname ?? __dirname;
|
|
47
|
+
return join(thisDir, '..', 'index.ts');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Check whether a given command name conflicts with an existing system
|
|
52
|
+
* binary (i.e. something other than our own launcher).
|
|
53
|
+
*/
|
|
54
|
+
function hasSystemConflict(name: string, binDir: string): boolean {
|
|
55
|
+
try {
|
|
56
|
+
const result = execSync(`which ${name}`, { encoding: 'utf-8' }).trim();
|
|
57
|
+
// If `which` resolves to our own bin dir, that's not a conflict
|
|
58
|
+
if (result.startsWith(binDir)) return false;
|
|
59
|
+
return true;
|
|
60
|
+
} catch {
|
|
61
|
+
// `which` failed — no conflict
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Install standalone CLI launcher scripts in ~/.vellum/bin/.
|
|
68
|
+
*
|
|
69
|
+
* For each integration command, generates a shell script that execs
|
|
70
|
+
* bun with the CLI entrypoint and the subcommand name prepended.
|
|
71
|
+
* Uses the short name by default (e.g. `doordash`), falling back to
|
|
72
|
+
* `vellum-<name>` if the short name conflicts with an existing system binary.
|
|
73
|
+
*/
|
|
74
|
+
export function installCliLaunchers(): void {
|
|
75
|
+
const binDir = join(homedir(), '.vellum', 'bin');
|
|
76
|
+
|
|
77
|
+
let bunPath: string;
|
|
78
|
+
try {
|
|
79
|
+
bunPath = resolveBunPath();
|
|
80
|
+
} catch (err) {
|
|
81
|
+
log.warn({ err }, 'Cannot install CLI launchers: bun not found');
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const entrypoint = resolveCliEntrypoint();
|
|
86
|
+
if (!existsSync(entrypoint)) {
|
|
87
|
+
// In compiled builds (e.g. macOS app via `bun build --compile`), the
|
|
88
|
+
// source tree isn't available. Launcher scripts are a dev-mode
|
|
89
|
+
// convenience; compiled builds use their own command dispatch, so we
|
|
90
|
+
// silently skip installation.
|
|
91
|
+
log.debug({ entrypoint }, 'CLI entrypoint not found (compiled build?) — skipping launcher installation');
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (!existsSync(binDir)) {
|
|
96
|
+
mkdirSync(binDir, { recursive: true });
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
for (const name of INTEGRATION_COMMANDS) {
|
|
100
|
+
const launcherName = hasSystemConflict(name, binDir) ? `vellum-${name}` : name;
|
|
101
|
+
const launcherPath = join(binDir, launcherName);
|
|
102
|
+
|
|
103
|
+
const script = `#!/bin/bash
|
|
104
|
+
exec "${bunPath}" "${entrypoint}" ${name} "$@"
|
|
105
|
+
`;
|
|
106
|
+
|
|
107
|
+
writeFileSync(launcherPath, script);
|
|
108
|
+
chmodSync(launcherPath, 0o755);
|
|
109
|
+
log.debug({ launcherName, launcherPath }, 'Installed CLI launcher');
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
log.info({ binDir, commands: INTEGRATION_COMMANDS }, 'CLI launchers installed');
|
|
113
|
+
}
|