@vellumai/assistant 0.5.6 → 0.5.8
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/.env.example +16 -2
- package/ARCHITECTURE.md +6 -75
- package/Dockerfile +3 -2
- package/README.md +0 -2
- package/bun.lock +0 -414
- package/docker-entrypoint.sh +9 -0
- package/docs/architecture/keychain-broker.md +45 -240
- package/docs/architecture/memory.md +13 -11
- package/docs/architecture/security.md +0 -17
- package/docs/credential-execution-service.md +2 -2
- package/node_modules/@vellumai/ces-contracts/package.json +1 -0
- package/node_modules/@vellumai/ces-contracts/src/error.ts +1 -1
- package/node_modules/@vellumai/ces-contracts/src/grants.ts +1 -1
- package/node_modules/@vellumai/ces-contracts/src/handles.ts +1 -1
- package/node_modules/@vellumai/ces-contracts/src/index.ts +1 -1
- package/node_modules/@vellumai/ces-contracts/src/rpc.ts +120 -1
- package/node_modules/@vellumai/credential-storage/package.json +1 -0
- package/node_modules/@vellumai/egress-proxy/package.json +1 -0
- package/package.json +2 -3
- package/src/__tests__/actor-token-service.test.ts +0 -114
- package/src/__tests__/approval-cascade.test.ts +0 -1
- package/src/__tests__/assistant-feature-flags-integration.test.ts +30 -29
- package/src/__tests__/browser-fill-credential.test.ts +1 -1
- package/src/__tests__/browser-skill-endstate.test.ts +6 -5
- package/src/__tests__/btw-routes.test.ts +0 -39
- package/src/__tests__/call-controller.test.ts +0 -1
- package/src/__tests__/call-domain.test.ts +0 -128
- package/src/__tests__/ces-rpc-credential-backend.test.ts +199 -0
- package/src/__tests__/ces-startup-timeout.test.ts +40 -0
- package/src/__tests__/channel-approval-routes.test.ts +0 -5
- package/src/__tests__/channel-readiness-service.test.ts +1 -60
- package/src/__tests__/checker.test.ts +4 -2
- package/src/__tests__/cli-command-risk-guard.test.ts +112 -0
- package/src/__tests__/config-schema-cmd.test.ts +0 -2
- package/src/__tests__/config-schema.test.ts +3 -1
- package/src/__tests__/conversation-abort-tool-results.test.ts +0 -1
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +0 -2
- package/src/__tests__/conversation-agent-loop.test.ts +2 -4
- package/src/__tests__/conversation-attention-telegram.test.ts +0 -5
- package/src/__tests__/conversation-confirmation-signals.test.ts +0 -1
- package/src/__tests__/conversation-error.test.ts +15 -1
- package/src/__tests__/conversation-init.benchmark.test.ts +0 -2
- package/src/__tests__/conversation-messaging-secret-redirect.test.ts +1 -1
- package/src/__tests__/conversation-pre-run-repair.test.ts +0 -1
- package/src/__tests__/conversation-provider-retry-repair.test.ts +0 -1
- package/src/__tests__/conversation-queue.test.ts +0 -1
- package/src/__tests__/conversation-skill-tools.test.ts +0 -54
- package/src/__tests__/conversation-slash-queue.test.ts +0 -1
- package/src/__tests__/conversation-slash-unknown.test.ts +0 -1
- package/src/__tests__/conversation-title-service.test.ts +87 -0
- package/src/__tests__/conversation-workspace-injection.test.ts +0 -1
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +0 -1
- package/src/__tests__/credential-execution-client.test.ts +5 -2
- package/src/__tests__/credential-execution-feature-gates.test.ts +59 -30
- package/src/__tests__/credential-execution-managed-contract.test.ts +35 -20
- package/src/__tests__/credential-security-e2e.test.ts +1 -67
- package/src/__tests__/credential-security-invariants.test.ts +6 -50
- package/src/__tests__/credentials-cli.test.ts +82 -3
- package/src/__tests__/daemon-credential-client.test.ts +123 -0
- package/src/__tests__/db-migration-rollback.test.ts +2015 -1
- package/src/__tests__/deterministic-verification-control-plane.test.ts +1 -0
- package/src/__tests__/docker-signing-key-bootstrap.test.ts +34 -143
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +6 -4
- package/src/__tests__/gateway-client-managed-outbound.test.ts +79 -1
- package/src/__tests__/guardian-routing-state.test.ts +0 -5
- package/src/__tests__/host-shell-tool.test.ts +6 -7
- package/src/__tests__/http-user-message-parity.test.ts +3 -103
- package/src/__tests__/inbound-invite-redemption.test.ts +0 -4
- package/src/__tests__/inline-skill-load-permissions.test.ts +6 -8
- package/src/__tests__/intent-routing.test.ts +0 -13
- package/src/__tests__/jobs-store-qdrant-breaker.test.ts +178 -0
- package/src/__tests__/journal-context.test.ts +335 -0
- package/src/__tests__/keychain-broker-client.test.ts +161 -22
- package/src/__tests__/memory-context-benchmark.benchmark.test.ts +0 -3
- package/src/__tests__/memory-jobs-worker-backoff.test.ts +150 -0
- package/src/__tests__/memory-lifecycle-e2e.test.ts +70 -25
- package/src/__tests__/memory-recall-quality.test.ts +48 -17
- package/src/__tests__/memory-regressions.test.ts +408 -363
- package/src/__tests__/memory-retrieval.benchmark.test.ts +0 -3
- package/src/__tests__/migration-export-http.test.ts +2 -2
- package/src/__tests__/migration-import-commit-http.test.ts +2 -2
- package/src/__tests__/migration-import-preflight-http.test.ts +2 -2
- package/src/__tests__/migration-validate-http.test.ts +2 -2
- package/src/__tests__/non-member-access-request.test.ts +2 -7
- package/src/__tests__/notification-decision-fallback.test.ts +4 -0
- package/src/__tests__/notification-decision-identity.test.ts +4 -0
- package/src/__tests__/notification-decision-strategy.test.ts +71 -0
- package/src/__tests__/oauth-cli.test.ts +5 -1
- package/src/__tests__/permission-types.test.ts +1 -0
- package/src/__tests__/provider-commit-message-generator.test.ts +0 -37
- package/src/__tests__/provider-error-scenarios.test.ts +0 -267
- package/src/__tests__/provider-managed-proxy-integration.test.ts +5 -6
- package/src/__tests__/provider-streaming.benchmark.test.ts +2 -81
- package/src/__tests__/qdrant-manager.test.ts +28 -2
- package/src/__tests__/registry.test.ts +0 -6
- package/src/__tests__/relay-server.test.ts +1 -2
- package/src/__tests__/runtime-attachment-metadata.test.ts +0 -4
- package/src/__tests__/script-proxy-injection-runtime.test.ts +1 -1
- package/src/__tests__/secret-onetime-send.test.ts +1 -1
- package/src/__tests__/secret-routes-managed-proxy.test.ts +0 -4
- package/src/__tests__/secure-keys.test.ts +95 -272
- package/src/__tests__/shell-identity.test.ts +96 -6
- package/src/__tests__/skill-feature-flags-integration.test.ts +22 -14
- package/src/__tests__/skill-feature-flags.test.ts +46 -45
- package/src/__tests__/skill-load-feature-flag.test.ts +7 -10
- package/src/__tests__/skill-load-inline-command.test.ts +8 -12
- package/src/__tests__/skill-load-inline-includes.test.ts +6 -10
- package/src/__tests__/skill-load-tool.test.ts +0 -2
- package/src/__tests__/skill-memory.test.ts +17 -3
- package/src/__tests__/skill-projection-feature-flag.test.ts +33 -29
- package/src/__tests__/skills.test.ts +0 -2
- package/src/__tests__/slack-inbound-verification.test.ts +0 -4
- package/src/__tests__/stale-approval-dedup.test.ts +171 -0
- package/src/__tests__/stt-hints.test.ts +437 -0
- package/src/__tests__/suggestion-routes.test.ts +1 -32
- package/src/__tests__/system-prompt.test.ts +0 -1
- package/src/__tests__/task-memory-cleanup.test.ts +14 -0
- package/src/__tests__/tool-executor-shell-integration.test.ts +5 -3
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +0 -5
- package/src/__tests__/trusted-contact-multichannel.test.ts +0 -4
- package/src/__tests__/twilio-routes-twiml.test.ts +139 -1
- package/src/__tests__/update-bulletin.test.ts +0 -2
- package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +6 -9
- package/src/__tests__/voice-quality.test.ts +58 -0
- package/src/__tests__/voice-scoped-grant-consumer.test.ts +0 -7
- package/src/__tests__/workspace-migration-015-migrate-credentials-to-keychain.test.ts +252 -0
- package/src/__tests__/workspace-migration-016-migrate-credentials-from-keychain.test.ts +220 -0
- package/src/__tests__/workspace-migration-down-functions.test.ts +1009 -0
- package/src/__tests__/workspace-migrations-runner.test.ts +114 -0
- package/src/acp/agent-process.ts +9 -1
- package/src/agent/loop.ts +1 -1
- package/src/approvals/guardian-request-resolvers.ts +164 -38
- package/src/calls/__tests__/tts-text-sanitizer.test.ts +254 -0
- package/src/calls/audio-store.test.ts +97 -0
- package/src/calls/audio-store.ts +205 -0
- package/src/calls/call-controller.ts +90 -8
- package/src/calls/call-domain.ts +3 -0
- package/src/calls/call-store.ts +10 -3
- package/src/calls/fish-audio-client.ts +129 -0
- package/src/calls/relay-server.ts +27 -0
- package/src/calls/stt-hints.ts +189 -0
- package/src/calls/tts-text-sanitizer.ts +61 -0
- package/src/calls/twilio-routes.ts +34 -5
- package/src/calls/types.ts +1 -0
- package/src/calls/voice-ingress-preflight.ts +0 -42
- package/src/calls/voice-quality.ts +38 -5
- package/src/calls/voice-session-bridge.ts +7 -12
- package/src/cli/commands/avatar.ts +2 -2
- package/src/cli/commands/config.ts +1 -4
- package/src/cli/commands/credentials.ts +128 -82
- package/src/cli/commands/doctor.ts +2 -2
- package/src/cli/commands/keys.ts +7 -7
- package/src/cli/commands/memory.ts +1 -1
- package/src/cli/commands/oauth/connections.ts +11 -29
- package/src/cli/commands/oauth/index.ts +7 -0
- package/src/cli/commands/oauth/platform.ts +525 -0
- package/src/cli/commands/platform.ts +3 -3
- package/src/cli/lib/daemon-credential-client.ts +284 -0
- package/src/cli.ts +1 -1
- package/src/config/assistant-feature-flags.ts +186 -5
- package/src/config/bundled-skills/AGENTS.md +34 -0
- package/src/config/bundled-skills/acp/SKILL.md +10 -0
- package/src/config/bundled-skills/app-builder/SKILL.md +0 -4
- package/src/config/bundled-skills/messaging/SKILL.md +5 -5
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +2 -2
- package/src/config/bundled-skills/phone-calls/TOOLS.json +4 -0
- package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +1 -0
- package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +1 -0
- package/src/config/bundled-skills/settings/SKILL.md +15 -2
- package/src/config/bundled-skills/settings/TOOLS.json +47 -2
- package/src/config/bundled-skills/settings/tools/avatar-remove.ts +59 -0
- package/src/config/bundled-skills/settings/tools/avatar-update.ts +80 -0
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +42 -0
- package/src/config/bundled-skills/slack/SKILL.md +1 -1
- package/src/config/bundled-tool-registry.ts +5 -11
- package/src/config/defaults.ts +0 -2
- package/src/config/env-registry.ts +5 -5
- package/src/config/env.ts +21 -14
- package/src/config/feature-flag-registry.json +49 -9
- package/src/config/loader.ts +106 -42
- package/src/config/schema.ts +9 -29
- package/src/config/schemas/calls.ts +30 -0
- package/src/config/schemas/fish-audio.ts +39 -0
- package/src/config/schemas/inference.ts +2 -2
- package/src/config/schemas/journal.ts +16 -0
- package/src/config/schemas/memory-processing.ts +2 -2
- package/src/config/schemas/security.ts +0 -4
- package/src/config/types.ts +1 -1
- package/src/contacts/contact-store.ts +39 -0
- package/src/contacts/types.ts +2 -0
- package/src/credential-execution/approval-bridge.ts +1 -0
- package/src/credential-execution/executable-discovery.ts +28 -4
- package/src/credential-execution/feature-gates.ts +16 -0
- package/src/credential-execution/process-manager.ts +38 -0
- package/src/credential-execution/startup-timeout.ts +36 -0
- package/src/daemon/approval-generators.ts +3 -9
- package/src/daemon/assistant-attachments.ts +9 -0
- package/src/daemon/config-watcher.ts +5 -0
- package/src/daemon/conversation-error.ts +13 -1
- package/src/daemon/conversation-memory.ts +1 -2
- package/src/daemon/conversation-process.ts +18 -1
- package/src/daemon/conversation-surfaces.ts +30 -1
- package/src/daemon/conversation-tool-setup.ts +0 -105
- package/src/daemon/conversation.ts +21 -1
- package/src/daemon/guardian-action-generators.ts +3 -9
- package/src/daemon/handlers/config-vercel.ts +92 -0
- package/src/daemon/handlers/skills.ts +2 -15
- package/src/daemon/install-symlink.ts +195 -0
- package/src/daemon/lifecycle.ts +234 -51
- package/src/daemon/message-types/conversations.ts +4 -4
- package/src/daemon/message-types/diagnostics.ts +3 -22
- package/src/daemon/message-types/messages.ts +0 -2
- package/src/daemon/message-types/upgrades.ts +8 -0
- package/src/daemon/server.ts +32 -95
- package/src/events/domain-events.ts +2 -1
- package/src/inbound/platform-callback-registration.ts +3 -3
- package/src/instrument.ts +8 -5
- package/src/memory/app-store.ts +31 -0
- package/src/memory/conversation-title-service.ts +50 -1
- package/src/memory/db-init.ts +16 -0
- package/src/memory/indexer.ts +19 -10
- package/src/memory/items-extractor.ts +328 -321
- package/src/memory/job-handlers/conversation-starters.ts +4 -1
- package/src/memory/job-handlers/summarization.ts +26 -16
- package/src/memory/jobs-store.ts +63 -6
- package/src/memory/jobs-worker.ts +31 -7
- package/src/memory/journal-memory.ts +214 -0
- package/src/memory/migrations/001-job-deferrals.ts +19 -0
- package/src/memory/migrations/004-entity-relation-dedup.ts +10 -0
- package/src/memory/migrations/005-fingerprint-scope-unique.ts +76 -0
- package/src/memory/migrations/006-scope-salted-fingerprints.ts +50 -0
- package/src/memory/migrations/007-assistant-id-to-self.ts +10 -0
- package/src/memory/migrations/008-remove-assistant-id-columns.ts +34 -0
- package/src/memory/migrations/009-llm-usage-events-drop-assistant-id.ts +26 -0
- package/src/memory/migrations/014-backfill-inbox-thread-state.ts +10 -0
- package/src/memory/migrations/015-drop-active-search-index.ts +17 -0
- package/src/memory/migrations/019-notification-tables-schema-migration.ts +12 -0
- package/src/memory/migrations/020-rename-macos-ios-channel-to-vellum.ts +121 -0
- package/src/memory/migrations/024-embedding-vector-blob.ts +74 -0
- package/src/memory/migrations/026a-embeddings-nullable-vector-json.ts +82 -0
- package/src/memory/migrations/036-normalize-phone-identities.ts +11 -0
- package/src/memory/migrations/116-messages-fts.ts +106 -1
- package/src/memory/migrations/126-backfill-guardian-principal-id.ts +52 -0
- package/src/memory/migrations/127-guardian-principal-id-not-null.ts +77 -0
- package/src/memory/migrations/134-contacts-notes-column.ts +13 -0
- package/src/memory/migrations/135-backfill-contact-interaction-stats.ts +20 -0
- package/src/memory/migrations/136-drop-assistant-id-columns.ts +52 -0
- package/src/memory/migrations/140-backfill-usage-cache-accounting.ts +13 -0
- package/src/memory/migrations/141-rename-verification-table.ts +54 -0
- package/src/memory/migrations/142-rename-verification-session-id-column.ts +25 -0
- package/src/memory/migrations/143-rename-guardian-verification-values.ts +35 -0
- package/src/memory/migrations/144-rename-voice-to-phone.ts +136 -0
- package/src/memory/migrations/145-drop-accounts-table.ts +32 -0
- package/src/memory/migrations/147-migrate-reminders-to-schedules.ts +14 -1
- package/src/memory/migrations/148-drop-reminders-table.ts +35 -1
- package/src/memory/migrations/150-oauth-apps-client-secret-path.ts +69 -1
- package/src/memory/migrations/162-guardian-timestamps-epoch-ms.ts +290 -0
- package/src/memory/migrations/169-rename-gmail-provider-key-to-google.ts +51 -1
- package/src/memory/migrations/174-rename-thread-starters-table.ts +47 -1
- package/src/memory/migrations/176-drop-capability-card-state.ts +13 -0
- package/src/memory/migrations/180-backfill-inline-attachments-to-disk.ts +16 -0
- package/src/memory/migrations/181-rename-thread-starters-checkpoints.ts +28 -1
- package/src/memory/migrations/190-call-session-skip-disclosure.ts +15 -0
- package/src/memory/migrations/191-backfill-audio-attachment-mime-types.ts +64 -0
- package/src/memory/migrations/192-contacts-user-file-column.ts +15 -0
- package/src/memory/migrations/193-add-source-type-columns.ts +81 -0
- package/src/memory/migrations/index.ts +5 -0
- package/src/memory/migrations/registry.ts +98 -0
- package/src/memory/migrations/validate-migration-state.ts +137 -11
- package/src/memory/qdrant-circuit-breaker.ts +9 -0
- package/src/memory/qdrant-manager.ts +64 -7
- package/src/memory/retriever.test.ts +37 -25
- package/src/memory/retriever.ts +24 -49
- package/src/memory/schema/calls.ts +1 -0
- package/src/memory/schema/contacts.ts +1 -0
- package/src/memory/schema/memory-core.ts +2 -0
- package/src/memory/search/formatting.ts +7 -44
- package/src/memory/search/staleness.ts +4 -0
- package/src/memory/search/tier-classifier.ts +10 -2
- package/src/memory/search/types.ts +2 -5
- package/src/memory/task-memory-cleanup.ts +4 -3
- package/src/notifications/adapters/slack.ts +168 -6
- package/src/notifications/broadcaster.ts +1 -0
- package/src/notifications/copy-composer.ts +59 -2
- package/src/notifications/decision-engine.ts +4 -1
- package/src/notifications/signal.ts +2 -0
- package/src/notifications/types.ts +2 -0
- package/src/oauth/connection-resolver.ts +6 -4
- package/src/permissions/checker.ts +0 -38
- package/src/permissions/shell-identity.ts +76 -22
- package/src/permissions/types.ts +4 -2
- package/src/platform/client.ts +35 -7
- package/src/prompts/journal-context.ts +133 -0
- package/src/prompts/persona-resolver.ts +194 -0
- package/src/prompts/system-prompt.ts +44 -4
- package/src/prompts/templates/SOUL.md +10 -0
- package/src/prompts/templates/users/default.md +1 -0
- package/src/providers/provider-send-message.ts +3 -32
- package/src/providers/registry.ts +29 -179
- package/src/providers/types.ts +1 -1
- package/src/runtime/access-request-helper.ts +4 -0
- package/src/runtime/auth/__tests__/credential-service.test.ts +0 -1
- package/src/runtime/auth/__tests__/external-assistant-id.test.ts +13 -68
- package/src/runtime/auth/__tests__/guard-tests.test.ts +9 -50
- package/src/runtime/auth/external-assistant-id.ts +13 -59
- package/src/runtime/auth/route-policy.ts +17 -1
- package/src/runtime/auth/token-service.ts +43 -138
- package/src/runtime/channel-readiness-service.ts +1 -16
- package/src/runtime/gateway-client.ts +47 -4
- package/src/runtime/guardian-decision-types.ts +45 -4
- package/src/runtime/http-server.ts +31 -3
- package/src/runtime/middleware/error-handler.ts +1 -9
- package/src/runtime/routes/access-request-decision.ts +2 -2
- package/src/runtime/routes/app-management-routes.ts +2 -1
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +219 -30
- package/src/runtime/routes/approval-strategies/guardian-text-engine-strategy.ts +37 -14
- package/src/runtime/routes/audio-routes.ts +40 -0
- package/src/runtime/routes/btw-routes.ts +0 -17
- package/src/runtime/routes/channel-readiness-routes.ts +9 -4
- package/src/runtime/routes/conversation-query-routes.ts +63 -1
- package/src/runtime/routes/conversation-routes.ts +4 -44
- package/src/runtime/routes/debug-routes.ts +12 -9
- package/src/runtime/routes/diagnostics-routes.ts +1 -477
- package/src/runtime/routes/guardian-approval-interception.ts +168 -11
- package/src/runtime/routes/guardian-approval-prompt.ts +6 -1
- package/src/runtime/routes/guardian-approval-reply-helpers.ts +103 -21
- package/src/runtime/routes/identity-routes.ts +19 -30
- package/src/runtime/routes/inbound-message-handler.ts +31 -1
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +64 -5
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +52 -40
- package/src/runtime/routes/inbound-stages/secret-ingress-check.ts +4 -33
- package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +1 -1
- package/src/runtime/routes/integrations/twilio.ts +52 -10
- package/src/runtime/routes/integrations/vercel.ts +89 -0
- package/src/runtime/routes/log-export-routes.ts +5 -0
- package/src/runtime/routes/memory-item-routes.test.ts +3 -3
- package/src/runtime/routes/memory-item-routes.ts +46 -14
- package/src/runtime/routes/migration-rollback-routes.ts +209 -0
- package/src/runtime/routes/migration-routes.ts +17 -1
- package/src/runtime/routes/notification-routes.ts +58 -0
- package/src/runtime/routes/schedule-routes.ts +65 -0
- package/src/runtime/routes/secret-routes.ts +141 -10
- package/src/runtime/routes/settings-routes.ts +41 -1
- package/src/runtime/routes/tts-routes.ts +96 -0
- package/src/runtime/routes/upgrade-broadcast-routes.ts +26 -2
- package/src/runtime/routes/workspace-commit-routes.ts +62 -0
- package/src/runtime/routes/workspace-routes.test.ts +22 -1
- package/src/runtime/routes/workspace-routes.ts +1 -1
- package/src/runtime/routes/workspace-utils.ts +86 -2
- package/src/security/ces-credential-client.ts +75 -29
- package/src/security/ces-rpc-credential-backend.ts +86 -0
- package/src/security/credential-backend.ts +22 -92
- package/src/security/keychain-broker-client.ts +10 -2
- package/src/security/secure-keys.ts +113 -115
- package/src/skills/catalog-install.ts +6 -32
- package/src/skills/skill-memory.ts +1 -0
- package/src/subagent/manager.ts +2 -5
- package/src/telemetry/usage-telemetry-reporter.ts +4 -2
- package/src/tools/acp/spawn.ts +78 -1
- package/src/tools/calls/call-start.ts +1 -0
- package/src/tools/credentials/vault.ts +5 -3
- package/src/tools/executor.ts +0 -4
- package/src/tools/memory/definitions.ts +3 -2
- package/src/tools/memory/handlers.ts +10 -7
- package/src/tools/network/script-proxy/session-manager.ts +19 -4
- package/src/tools/network/web-fetch.ts +3 -1
- package/src/tools/skills/execute.ts +1 -1
- package/src/tools/terminal/safe-env.ts +1 -0
- package/src/tools/types.ts +0 -8
- package/src/util/browser.ts +15 -0
- package/src/util/errors.ts +0 -12
- package/src/util/platform.ts +4 -51
- package/src/workspace/git-service.ts +5 -2
- package/src/workspace/migrations/001-avatar-rename.ts +15 -0
- package/src/workspace/migrations/003-seed-device-id.ts +17 -1
- package/src/workspace/migrations/004-extract-collect-usage-data.ts +33 -0
- package/src/workspace/migrations/005-add-send-diagnostics.ts +3 -0
- package/src/workspace/migrations/006-services-config.ts +49 -0
- package/src/workspace/migrations/007-web-search-provider-rename.ts +27 -0
- package/src/workspace/migrations/008-voice-timeout-and-max-steps.ts +3 -0
- package/src/workspace/migrations/009-backfill-conversation-disk-view.ts +4 -0
- package/src/workspace/migrations/010-app-dir-rename.ts +78 -0
- package/src/workspace/migrations/011-backfill-installation-id.ts +11 -0
- package/src/workspace/migrations/012-rename-conversation-disk-view-dirs.ts +44 -0
- package/src/workspace/migrations/013-repair-conversation-disk-view.ts +5 -0
- package/src/workspace/migrations/015-migrate-credentials-to-keychain.ts +153 -0
- package/src/workspace/migrations/016-extract-feature-flags-to-protected.ts +156 -0
- package/src/workspace/migrations/016-migrate-credentials-from-keychain.ts +150 -0
- package/src/workspace/migrations/017-seed-persona-dirs.ts +96 -0
- package/src/workspace/migrations/018-rekey-compound-credential-keys.ts +184 -0
- package/src/workspace/migrations/019-scope-journal-to-guardian.ts +103 -0
- package/src/workspace/migrations/migrate-to-workspace-volume.ts +27 -5
- package/src/workspace/migrations/registry.ts +12 -0
- package/src/workspace/migrations/runner.ts +106 -2
- package/src/workspace/migrations/types.ts +4 -0
- package/src/workspace/provider-commit-message-generator.ts +12 -21
- package/src/__tests__/claude-code-skill-regression.test.ts +0 -206
- package/src/__tests__/claude-code-tool-profiles.test.ts +0 -99
- package/src/__tests__/diagnostics-export.test.ts +0 -288
- package/src/__tests__/local-gateway-health.test.ts +0 -209
- package/src/__tests__/provider-fail-open-selection.test.ts +0 -271
- package/src/__tests__/provider-failover-actual-provider.test.ts +0 -66
- package/src/__tests__/secret-ingress-handler.test.ts +0 -120
- package/src/__tests__/swarm-conversation-integration.test.ts +0 -358
- package/src/__tests__/swarm-dag-pathological.test.ts +0 -547
- package/src/__tests__/swarm-orchestrator.test.ts +0 -463
- package/src/__tests__/swarm-plan-validator.test.ts +0 -384
- package/src/__tests__/swarm-recursion.test.ts +0 -197
- package/src/__tests__/swarm-router-planner.test.ts +0 -234
- package/src/__tests__/swarm-tool.test.ts +0 -185
- package/src/__tests__/swarm-worker-backend.test.ts +0 -144
- package/src/__tests__/swarm-worker-runner.test.ts +0 -288
- package/src/commands/__tests__/cc-command-registry.test.ts +0 -396
- package/src/commands/cc-command-registry.ts +0 -248
- package/src/config/bundled-skills/claude-code/SKILL.md +0 -53
- package/src/config/bundled-skills/claude-code/TOOLS.json +0 -47
- package/src/config/bundled-skills/claude-code/tools/claude-code.ts +0 -12
- package/src/config/bundled-skills/orchestration/SKILL.md +0 -33
- package/src/config/bundled-skills/orchestration/TOOLS.json +0 -35
- package/src/config/bundled-skills/orchestration/tools/swarm-delegate.ts +0 -12
- package/src/config/schemas/swarm.ts +0 -82
- package/src/logfire.ts +0 -135
- package/src/memory/search/lexical.ts +0 -48
- package/src/providers/failover.ts +0 -186
- package/src/runtime/local-gateway-health.ts +0 -275
- package/src/security/secret-ingress.ts +0 -68
- package/src/swarm/backend-claude-code.ts +0 -225
- package/src/swarm/checkpoint.ts +0 -137
- package/src/swarm/graph-utils.ts +0 -53
- package/src/swarm/index.ts +0 -55
- package/src/swarm/limits.ts +0 -66
- package/src/swarm/orchestrator.ts +0 -424
- package/src/swarm/plan-validator.ts +0 -117
- package/src/swarm/router-planner.ts +0 -162
- package/src/swarm/router-prompts.ts +0 -39
- package/src/swarm/synthesizer.ts +0 -81
- package/src/swarm/types.ts +0 -72
- package/src/swarm/worker-backend.ts +0 -131
- package/src/swarm/worker-prompts.ts +0 -80
- package/src/swarm/worker-runner.ts +0 -170
- package/src/tools/claude-code/claude-code.ts +0 -610
- package/src/tools/swarm/delegate.ts +0 -205
|
@@ -1,6 +1,83 @@
|
|
|
1
1
|
import { type DrizzleDb, getSqliteFrom } from "../db-connection.js";
|
|
2
2
|
import { withCrashRecovery } from "./validate-migration-state.js";
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Reverse v16: rebuild channel_guardian_bindings to make guardian_principal_id
|
|
6
|
+
* nullable again (removing the NOT NULL constraint added by the forward migration).
|
|
7
|
+
*/
|
|
8
|
+
export function downGuardianPrincipalIdNotNull(database: DrizzleDb): void {
|
|
9
|
+
const raw = getSqliteFrom(database);
|
|
10
|
+
|
|
11
|
+
const tableExists = raw
|
|
12
|
+
.query(
|
|
13
|
+
`SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'channel_guardian_bindings'`,
|
|
14
|
+
)
|
|
15
|
+
.get();
|
|
16
|
+
if (!tableExists) return;
|
|
17
|
+
|
|
18
|
+
// Check if guardian_principal_id has NOT NULL — if not, already rolled back
|
|
19
|
+
const colInfo = raw
|
|
20
|
+
.query(
|
|
21
|
+
`SELECT "notnull" FROM pragma_table_info('channel_guardian_bindings') WHERE name = 'guardian_principal_id'`,
|
|
22
|
+
)
|
|
23
|
+
.get() as { notnull: number } | null;
|
|
24
|
+
if (!colInfo || colInfo.notnull === 0) return;
|
|
25
|
+
|
|
26
|
+
raw.exec("PRAGMA foreign_keys = OFF");
|
|
27
|
+
try {
|
|
28
|
+
raw.exec("BEGIN");
|
|
29
|
+
|
|
30
|
+
raw.exec(/*sql*/ `
|
|
31
|
+
CREATE TABLE channel_guardian_bindings_new (
|
|
32
|
+
id TEXT PRIMARY KEY,
|
|
33
|
+
assistant_id TEXT NOT NULL,
|
|
34
|
+
channel TEXT NOT NULL,
|
|
35
|
+
guardian_external_user_id TEXT NOT NULL,
|
|
36
|
+
guardian_delivery_chat_id TEXT NOT NULL,
|
|
37
|
+
guardian_principal_id TEXT,
|
|
38
|
+
status TEXT NOT NULL DEFAULT 'active',
|
|
39
|
+
verified_at INTEGER NOT NULL,
|
|
40
|
+
verified_via TEXT NOT NULL DEFAULT 'challenge',
|
|
41
|
+
metadata_json TEXT,
|
|
42
|
+
created_at INTEGER NOT NULL,
|
|
43
|
+
updated_at INTEGER NOT NULL
|
|
44
|
+
)
|
|
45
|
+
`);
|
|
46
|
+
|
|
47
|
+
raw.exec(/*sql*/ `
|
|
48
|
+
INSERT INTO channel_guardian_bindings_new
|
|
49
|
+
SELECT id, assistant_id, channel, guardian_external_user_id,
|
|
50
|
+
guardian_delivery_chat_id, guardian_principal_id,
|
|
51
|
+
status, verified_at, verified_via, metadata_json,
|
|
52
|
+
created_at, updated_at
|
|
53
|
+
FROM channel_guardian_bindings
|
|
54
|
+
`);
|
|
55
|
+
|
|
56
|
+
raw.exec(/*sql*/ `DROP TABLE channel_guardian_bindings`);
|
|
57
|
+
raw.exec(
|
|
58
|
+
/*sql*/ `ALTER TABLE channel_guardian_bindings_new RENAME TO channel_guardian_bindings`,
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
// Recreate the unique index for active bindings
|
|
62
|
+
raw.exec(/*sql*/ `
|
|
63
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_channel_guardian_bindings_active
|
|
64
|
+
ON channel_guardian_bindings(assistant_id, channel)
|
|
65
|
+
WHERE status = 'active'
|
|
66
|
+
`);
|
|
67
|
+
|
|
68
|
+
raw.exec("COMMIT");
|
|
69
|
+
} catch (e) {
|
|
70
|
+
try {
|
|
71
|
+
raw.exec("ROLLBACK");
|
|
72
|
+
} catch {
|
|
73
|
+
/* no active transaction */
|
|
74
|
+
}
|
|
75
|
+
throw e;
|
|
76
|
+
} finally {
|
|
77
|
+
raw.exec("PRAGMA foreign_keys = ON");
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
4
81
|
/**
|
|
5
82
|
* Enforce NOT NULL on channel_guardian_bindings.guardian_principal_id.
|
|
6
83
|
*
|
|
@@ -2,6 +2,19 @@ import { getLogger } from "../../util/logger.js";
|
|
|
2
2
|
import { type DrizzleDb, getSqliteFrom } from "../db-connection.js";
|
|
3
3
|
import { withCrashRecovery } from "./validate-migration-state.js";
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Reverse v17: no-op — the original separate columns (relationship, importance,
|
|
7
|
+
* response_expectation, preferred_tone) cannot be reliably restored from the
|
|
8
|
+
* consolidated notes TEXT column.
|
|
9
|
+
*
|
|
10
|
+
* The forward migration concatenated multiple typed fields into a single
|
|
11
|
+
* free-text notes field and then dropped the original columns. Parsing the
|
|
12
|
+
* notes back into structured fields would be lossy and error-prone.
|
|
13
|
+
*/
|
|
14
|
+
export function downContactsNotesColumn(_database: DrizzleDb): void {
|
|
15
|
+
// Lossy — original structured columns cannot be restored from notes text.
|
|
16
|
+
}
|
|
17
|
+
|
|
5
18
|
const log = getLogger("migration-134");
|
|
6
19
|
|
|
7
20
|
export function migrateContactsNotesColumn(database: DrizzleDb): void {
|
|
@@ -1,6 +1,26 @@
|
|
|
1
1
|
import { type DrizzleDb, getSqliteFrom } from "../db-connection.js";
|
|
2
2
|
import { withCrashRecovery } from "./validate-migration-state.js";
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Reverse v18: set contacts.last_interaction back to NULL.
|
|
6
|
+
*
|
|
7
|
+
* The forward migration backfilled last_interaction from channel data.
|
|
8
|
+
* Rolling back simply clears the column — the data can be re-derived by
|
|
9
|
+
* re-running the forward migration.
|
|
10
|
+
*/
|
|
11
|
+
export function downBackfillContactInteractionStats(database: DrizzleDb): void {
|
|
12
|
+
const raw = getSqliteFrom(database);
|
|
13
|
+
|
|
14
|
+
const colExists = raw
|
|
15
|
+
.query(
|
|
16
|
+
`SELECT 1 FROM pragma_table_info('contacts') WHERE name = 'last_interaction'`,
|
|
17
|
+
)
|
|
18
|
+
.get();
|
|
19
|
+
if (!colExists) return;
|
|
20
|
+
|
|
21
|
+
raw.exec(/*sql*/ `UPDATE contacts SET last_interaction = NULL`);
|
|
22
|
+
}
|
|
23
|
+
|
|
4
24
|
/**
|
|
5
25
|
* Backfill contacts.last_interaction from the max lastSeenAt across each
|
|
6
26
|
* contact's channels. interactionCount cannot be reliably derived from
|
|
@@ -2,6 +2,58 @@ import { getLogger } from "../../util/logger.js";
|
|
|
2
2
|
import { type DrizzleDb, getSqliteFrom } from "../db-connection.js";
|
|
3
3
|
import { withCrashRecovery } from "./validate-migration-state.js";
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* Reverse v19: add assistant_id columns back to all 16 tables via
|
|
7
|
+
* ALTER TABLE ADD COLUMN, defaulting to 'self'.
|
|
8
|
+
*
|
|
9
|
+
* This restores the column that the forward migration dropped. All rows
|
|
10
|
+
* get assistant_id = 'self' since that was the only value before dropping.
|
|
11
|
+
*/
|
|
12
|
+
export function downDropAssistantIdColumns(database: DrizzleDb): void {
|
|
13
|
+
const raw = getSqliteFrom(database);
|
|
14
|
+
|
|
15
|
+
const tables = [
|
|
16
|
+
"contacts",
|
|
17
|
+
"assistant_ingress_invites",
|
|
18
|
+
"assistant_inbox_thread_state",
|
|
19
|
+
"call_sessions",
|
|
20
|
+
"channel_guardian_verification_challenges",
|
|
21
|
+
"channel_guardian_approval_requests",
|
|
22
|
+
"channel_guardian_rate_limits",
|
|
23
|
+
"guardian_action_requests",
|
|
24
|
+
"scoped_approval_grants",
|
|
25
|
+
"notification_events",
|
|
26
|
+
"notification_preferences",
|
|
27
|
+
"notification_deliveries",
|
|
28
|
+
"conversation_attention_events",
|
|
29
|
+
"conversation_assistant_attention_state",
|
|
30
|
+
"actor_token_records",
|
|
31
|
+
"actor_refresh_token_records",
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
for (const table of tables) {
|
|
35
|
+
// Skip if table doesn't exist
|
|
36
|
+
const tableExists = raw
|
|
37
|
+
.query(`SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ?`)
|
|
38
|
+
.get(table);
|
|
39
|
+
if (!tableExists) continue;
|
|
40
|
+
|
|
41
|
+
// Skip if column already exists (idempotent)
|
|
42
|
+
const colExists = raw
|
|
43
|
+
.query(`SELECT 1 FROM pragma_table_info(?) WHERE name = 'assistant_id'`)
|
|
44
|
+
.get(table);
|
|
45
|
+
if (colExists) continue;
|
|
46
|
+
|
|
47
|
+
try {
|
|
48
|
+
raw.exec(
|
|
49
|
+
/*sql*/ `ALTER TABLE ${table} ADD COLUMN assistant_id TEXT NOT NULL DEFAULT 'self'`,
|
|
50
|
+
);
|
|
51
|
+
} catch {
|
|
52
|
+
/* column may already exist from partial run */
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
5
57
|
const log = getLogger("migration-136");
|
|
6
58
|
|
|
7
59
|
/**
|
|
@@ -8,6 +8,19 @@ import { resolvePricingForUsageWithOverrides } from "../../util/pricing.js";
|
|
|
8
8
|
import { type DrizzleDb, getSqliteFrom } from "../db-connection.js";
|
|
9
9
|
import { withCrashRecovery } from "./validate-migration-state.js";
|
|
10
10
|
|
|
11
|
+
/**
|
|
12
|
+
* Reverse v20: no-op — cannot reliably identify which llm_usage_events rows
|
|
13
|
+
* were updated by the backfill vs already had correct cache accounting.
|
|
14
|
+
*
|
|
15
|
+
* The forward migration updated input_tokens, output_tokens, cache token
|
|
16
|
+
* columns, estimated_cost_usd, and pricing_status based on request logs.
|
|
17
|
+
* There is no marker distinguishing backfilled rows from naturally-written
|
|
18
|
+
* ones, so a reversal cannot be performed without risking data corruption.
|
|
19
|
+
*/
|
|
20
|
+
export function downBackfillUsageCacheAccounting(_database: DrizzleDb): void {
|
|
21
|
+
// Lossy — cannot identify which rows were backfilled.
|
|
22
|
+
}
|
|
23
|
+
|
|
11
24
|
const log = getLogger("memory-db");
|
|
12
25
|
|
|
13
26
|
const CHECKPOINT_KEY = "migration_backfill_usage_cache_accounting_v1";
|
|
@@ -1,6 +1,60 @@
|
|
|
1
1
|
import { type DrizzleDb, getSqliteFrom } from "../db-connection.js";
|
|
2
2
|
import { withCrashRecovery } from "./validate-migration-state.js";
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Reverse v21: rename channel_verification_sessions back to
|
|
6
|
+
* channel_guardian_verification_challenges and recreate old indexes.
|
|
7
|
+
*/
|
|
8
|
+
export function downRenameVerificationTable(database: DrizzleDb): void {
|
|
9
|
+
const raw = getSqliteFrom(database);
|
|
10
|
+
|
|
11
|
+
// Check the new table exists before attempting anything
|
|
12
|
+
const newTableExists = raw
|
|
13
|
+
.query(
|
|
14
|
+
`SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'channel_verification_sessions'`,
|
|
15
|
+
)
|
|
16
|
+
.get();
|
|
17
|
+
if (!newTableExists) return;
|
|
18
|
+
|
|
19
|
+
// If the old table already exists, skip (already rolled back)
|
|
20
|
+
const oldTableExists = raw
|
|
21
|
+
.query(
|
|
22
|
+
`SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'channel_guardian_verification_challenges'`,
|
|
23
|
+
)
|
|
24
|
+
.get();
|
|
25
|
+
if (oldTableExists) return;
|
|
26
|
+
|
|
27
|
+
// Rename back to old name
|
|
28
|
+
raw.exec(
|
|
29
|
+
/*sql*/ `ALTER TABLE channel_verification_sessions RENAME TO channel_guardian_verification_challenges`,
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
// Drop new-style indexes and recreate old-style ones
|
|
33
|
+
raw.exec(/*sql*/ `DROP INDEX IF EXISTS idx_verification_sessions_lookup`);
|
|
34
|
+
raw.exec(/*sql*/ `DROP INDEX IF EXISTS idx_verification_sessions_active`);
|
|
35
|
+
raw.exec(/*sql*/ `DROP INDEX IF EXISTS idx_verification_sessions_identity`);
|
|
36
|
+
raw.exec(
|
|
37
|
+
/*sql*/ `DROP INDEX IF EXISTS idx_verification_sessions_destination`,
|
|
38
|
+
);
|
|
39
|
+
raw.exec(/*sql*/ `DROP INDEX IF EXISTS idx_verification_sessions_bootstrap`);
|
|
40
|
+
|
|
41
|
+
raw.exec(
|
|
42
|
+
/*sql*/ `CREATE INDEX IF NOT EXISTS idx_channel_guardian_challenges_lookup ON channel_guardian_verification_challenges(channel, challenge_hash, status)`,
|
|
43
|
+
);
|
|
44
|
+
raw.exec(
|
|
45
|
+
/*sql*/ `CREATE INDEX IF NOT EXISTS idx_guardian_sessions_active ON channel_guardian_verification_challenges(channel, status)`,
|
|
46
|
+
);
|
|
47
|
+
raw.exec(
|
|
48
|
+
/*sql*/ `CREATE INDEX IF NOT EXISTS idx_guardian_sessions_identity ON channel_guardian_verification_challenges(channel, expected_external_user_id, expected_chat_id, status)`,
|
|
49
|
+
);
|
|
50
|
+
raw.exec(
|
|
51
|
+
/*sql*/ `CREATE INDEX IF NOT EXISTS idx_guardian_sessions_destination ON channel_guardian_verification_challenges(channel, destination_address)`,
|
|
52
|
+
);
|
|
53
|
+
raw.exec(
|
|
54
|
+
/*sql*/ `CREATE INDEX IF NOT EXISTS idx_guardian_sessions_bootstrap ON channel_guardian_verification_challenges(channel, bootstrap_token_hash, status)`,
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
4
58
|
/**
|
|
5
59
|
* One-shot migration: rename channel_guardian_verification_challenges →
|
|
6
60
|
* channel_verification_sessions, including all indexes that reference the
|
|
@@ -1,6 +1,31 @@
|
|
|
1
1
|
import { type DrizzleDb, getSqliteFrom } from "../db-connection.js";
|
|
2
2
|
import { withCrashRecovery } from "./validate-migration-state.js";
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Reverse v22: rename verification_session_id back to
|
|
6
|
+
* guardian_verification_session_id in call_sessions.
|
|
7
|
+
*/
|
|
8
|
+
export function downRenameVerificationSessionIdColumn(
|
|
9
|
+
database: DrizzleDb,
|
|
10
|
+
): void {
|
|
11
|
+
const raw = getSqliteFrom(database);
|
|
12
|
+
|
|
13
|
+
const columns = raw.query(`PRAGMA table_info(call_sessions)`).all() as Array<{
|
|
14
|
+
name: string;
|
|
15
|
+
}>;
|
|
16
|
+
const hasNewColumn = columns.some(
|
|
17
|
+
(c) => c.name === "verification_session_id",
|
|
18
|
+
);
|
|
19
|
+
const hasOldColumn = columns.some(
|
|
20
|
+
(c) => c.name === "guardian_verification_session_id",
|
|
21
|
+
);
|
|
22
|
+
if (!hasNewColumn || hasOldColumn) return;
|
|
23
|
+
|
|
24
|
+
raw.exec(
|
|
25
|
+
/*sql*/ `ALTER TABLE call_sessions RENAME COLUMN verification_session_id TO guardian_verification_session_id`,
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
4
29
|
/**
|
|
5
30
|
* One-shot migration: rename the guardian_verification_session_id column
|
|
6
31
|
* in call_sessions to verification_session_id, dropping the "guardian_"
|
|
@@ -1,6 +1,41 @@
|
|
|
1
1
|
import { type DrizzleDb, getSqliteFrom } from "../db-connection.js";
|
|
2
2
|
import { withCrashRecovery } from "./validate-migration-state.js";
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Reverse v23: add the "guardian_" prefix back to verification-related
|
|
6
|
+
* call_mode and event_type values.
|
|
7
|
+
*/
|
|
8
|
+
export function downRenameGuardianVerificationValues(
|
|
9
|
+
database: DrizzleDb,
|
|
10
|
+
): void {
|
|
11
|
+
const raw = getSqliteFrom(database);
|
|
12
|
+
|
|
13
|
+
// Rename call_mode values back
|
|
14
|
+
raw.exec(
|
|
15
|
+
/*sql*/ `UPDATE call_sessions SET call_mode = 'guardian_verification' WHERE call_mode = 'verification'`,
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
// Rename event_type values back
|
|
19
|
+
raw.exec(
|
|
20
|
+
/*sql*/ `UPDATE call_events SET event_type = 'guardian_voice_verification_started' WHERE event_type = 'voice_verification_started'`,
|
|
21
|
+
);
|
|
22
|
+
raw.exec(
|
|
23
|
+
/*sql*/ `UPDATE call_events SET event_type = 'guardian_voice_verification_succeeded' WHERE event_type = 'voice_verification_succeeded'`,
|
|
24
|
+
);
|
|
25
|
+
raw.exec(
|
|
26
|
+
/*sql*/ `UPDATE call_events SET event_type = 'guardian_voice_verification_failed' WHERE event_type = 'voice_verification_failed'`,
|
|
27
|
+
);
|
|
28
|
+
raw.exec(
|
|
29
|
+
/*sql*/ `UPDATE call_events SET event_type = 'outbound_guardian_voice_verification_started' WHERE event_type = 'outbound_voice_verification_started'`,
|
|
30
|
+
);
|
|
31
|
+
raw.exec(
|
|
32
|
+
/*sql*/ `UPDATE call_events SET event_type = 'outbound_guardian_voice_verification_succeeded' WHERE event_type = 'outbound_voice_verification_succeeded'`,
|
|
33
|
+
);
|
|
34
|
+
raw.exec(
|
|
35
|
+
/*sql*/ `UPDATE call_events SET event_type = 'outbound_guardian_voice_verification_failed' WHERE event_type = 'outbound_voice_verification_failed'`,
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
4
39
|
/**
|
|
5
40
|
* One-shot migration: rename persisted `guardian_verification` and
|
|
6
41
|
* `guardian_voice_verification_*` / `outbound_guardian_voice_verification_*`
|
|
@@ -1,6 +1,142 @@
|
|
|
1
1
|
import { type DrizzleDb, getSqliteFrom } from "../db-connection.js";
|
|
2
2
|
import { withCrashRecovery } from "./validate-migration-state.js";
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Reverse v24: rename "phone" channel values back to "voice" across all
|
|
6
|
+
* tables with channel text columns.
|
|
7
|
+
*/
|
|
8
|
+
export function downRenameVoiceToPhone(database: DrizzleDb): void {
|
|
9
|
+
const raw = getSqliteFrom(database);
|
|
10
|
+
|
|
11
|
+
// contact_channels.type
|
|
12
|
+
raw.exec(
|
|
13
|
+
/*sql*/ `UPDATE contact_channels SET type = 'voice' WHERE type = 'phone'`,
|
|
14
|
+
);
|
|
15
|
+
|
|
16
|
+
// conversations.origin_channel
|
|
17
|
+
raw.exec(
|
|
18
|
+
/*sql*/ `UPDATE conversations SET origin_channel = 'voice' WHERE origin_channel = 'phone'`,
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
// conversations.origin_interface
|
|
22
|
+
raw.exec(
|
|
23
|
+
/*sql*/ `UPDATE conversations SET origin_interface = 'voice' WHERE origin_interface = 'phone'`,
|
|
24
|
+
);
|
|
25
|
+
|
|
26
|
+
// messages.metadata — reverse the JSON string replacement
|
|
27
|
+
raw.exec(
|
|
28
|
+
/*sql*/ `UPDATE messages SET metadata = REPLACE(metadata, '"phone"', '"voice"') WHERE metadata LIKE '%"phone"%'`,
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
// assistant_ingress_invites.source_channel
|
|
32
|
+
raw.exec(
|
|
33
|
+
/*sql*/ `UPDATE assistant_ingress_invites SET source_channel = 'voice' WHERE source_channel = 'phone'`,
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
// assistant_inbox_thread_state.source_channel
|
|
37
|
+
raw.exec(
|
|
38
|
+
/*sql*/ `UPDATE assistant_inbox_thread_state SET source_channel = 'voice' WHERE source_channel = 'phone'`,
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
// guardian_action_requests.source_channel
|
|
42
|
+
raw.exec(
|
|
43
|
+
/*sql*/ `UPDATE guardian_action_requests SET source_channel = 'voice' WHERE source_channel = 'phone'`,
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
// guardian_action_requests.answered_by_channel
|
|
47
|
+
raw.exec(
|
|
48
|
+
/*sql*/ `UPDATE guardian_action_requests SET answered_by_channel = 'voice' WHERE answered_by_channel = 'phone'`,
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
// channel_verification_sessions.channel (the forward migration ran after v21 rename)
|
|
52
|
+
raw.exec(
|
|
53
|
+
/*sql*/ `UPDATE channel_verification_sessions SET channel = 'voice' WHERE channel = 'phone'`,
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
// channel_guardian_approval_requests.channel
|
|
57
|
+
raw.exec(
|
|
58
|
+
/*sql*/ `UPDATE channel_guardian_approval_requests SET channel = 'voice' WHERE channel = 'phone'`,
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
// channel_guardian_rate_limits.channel
|
|
62
|
+
// Dedup: remove phone rows that would collide with existing voice rows
|
|
63
|
+
raw.exec(/*sql*/ `DELETE FROM channel_guardian_rate_limits WHERE channel = 'phone' AND EXISTS (
|
|
64
|
+
SELECT 1 FROM channel_guardian_rate_limits AS t2
|
|
65
|
+
WHERE t2.channel = 'voice'
|
|
66
|
+
AND t2.actor_external_user_id = channel_guardian_rate_limits.actor_external_user_id
|
|
67
|
+
AND t2.actor_chat_id = channel_guardian_rate_limits.actor_chat_id
|
|
68
|
+
)`);
|
|
69
|
+
raw.exec(
|
|
70
|
+
/*sql*/ `UPDATE channel_guardian_rate_limits SET channel = 'voice' WHERE channel = 'phone'`,
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
// notification_events.source_channel
|
|
74
|
+
raw.exec(
|
|
75
|
+
/*sql*/ `UPDATE notification_events SET source_channel = 'voice' WHERE source_channel = 'phone'`,
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
// notification_deliveries.channel
|
|
79
|
+
raw.exec(
|
|
80
|
+
/*sql*/ `UPDATE notification_deliveries SET channel = 'voice' WHERE channel = 'phone'`,
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
// external_conversation_bindings.source_channel
|
|
84
|
+
raw.exec(
|
|
85
|
+
/*sql*/ `UPDATE external_conversation_bindings SET source_channel = 'voice' WHERE source_channel = 'phone'`,
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
// channel_inbound_events.source_channel
|
|
89
|
+
raw.exec(
|
|
90
|
+
/*sql*/ `UPDATE channel_inbound_events SET source_channel = 'voice' WHERE source_channel = 'phone'`,
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
// conversation_attention_events.source_channel
|
|
94
|
+
raw.exec(
|
|
95
|
+
/*sql*/ `UPDATE conversation_attention_events SET source_channel = 'voice' WHERE source_channel = 'phone'`,
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
// conversation_assistant_attention_state.last_seen_source_channel
|
|
99
|
+
raw.exec(
|
|
100
|
+
/*sql*/ `UPDATE conversation_assistant_attention_state SET last_seen_source_channel = 'voice' WHERE last_seen_source_channel = 'phone'`,
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
// canonical_guardian_requests.source_channel
|
|
104
|
+
raw.exec(
|
|
105
|
+
/*sql*/ `UPDATE canonical_guardian_requests SET source_channel = 'voice' WHERE source_channel = 'phone'`,
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
// canonical_guardian_deliveries.destination_channel
|
|
109
|
+
raw.exec(
|
|
110
|
+
/*sql*/ `UPDATE canonical_guardian_deliveries SET destination_channel = 'voice' WHERE destination_channel = 'phone'`,
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
// guardian_action_deliveries.destination_channel
|
|
114
|
+
raw.exec(
|
|
115
|
+
/*sql*/ `UPDATE guardian_action_deliveries SET destination_channel = 'voice' WHERE destination_channel = 'phone'`,
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
// scoped_approval_grants: request_channel, decision_channel, execution_channel
|
|
119
|
+
raw.exec(
|
|
120
|
+
/*sql*/ `UPDATE scoped_approval_grants SET request_channel = 'voice' WHERE request_channel = 'phone'`,
|
|
121
|
+
);
|
|
122
|
+
raw.exec(
|
|
123
|
+
/*sql*/ `UPDATE scoped_approval_grants SET decision_channel = 'voice' WHERE decision_channel = 'phone'`,
|
|
124
|
+
);
|
|
125
|
+
raw.exec(
|
|
126
|
+
/*sql*/ `UPDATE scoped_approval_grants SET execution_channel = 'voice' WHERE execution_channel = 'phone'`,
|
|
127
|
+
);
|
|
128
|
+
|
|
129
|
+
// sequences.channel
|
|
130
|
+
raw.exec(
|
|
131
|
+
/*sql*/ `UPDATE sequences SET channel = 'voice' WHERE channel = 'phone'`,
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
// followups.channel
|
|
135
|
+
raw.exec(
|
|
136
|
+
/*sql*/ `UPDATE followups SET channel = 'voice' WHERE channel = 'phone'`,
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
|
|
4
140
|
/**
|
|
5
141
|
* One-shot migration: rename stored "voice" channel values to "phone" across
|
|
6
142
|
* all tables that persist channel identifiers as text.
|
|
@@ -17,3 +17,35 @@ export function migrateDropAccountsTable(database: DrizzleDb): void {
|
|
|
17
17
|
raw.exec(/*sql*/ `DROP TABLE IF EXISTS accounts`);
|
|
18
18
|
});
|
|
19
19
|
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Reverse: recreate the accounts table with its original schema.
|
|
23
|
+
*
|
|
24
|
+
* Data is permanently lost — the table was dropped. This only restores the
|
|
25
|
+
* empty table structure so that earlier migrations referencing it can operate.
|
|
26
|
+
*/
|
|
27
|
+
export function migrateDropAccountsTableDown(database: DrizzleDb): void {
|
|
28
|
+
const raw = getSqliteFrom(database);
|
|
29
|
+
|
|
30
|
+
raw.exec(/*sql*/ `
|
|
31
|
+
CREATE TABLE IF NOT EXISTS accounts (
|
|
32
|
+
id TEXT PRIMARY KEY,
|
|
33
|
+
service TEXT NOT NULL,
|
|
34
|
+
username TEXT,
|
|
35
|
+
email TEXT,
|
|
36
|
+
display_name TEXT,
|
|
37
|
+
status TEXT NOT NULL DEFAULT 'active',
|
|
38
|
+
credential_ref TEXT,
|
|
39
|
+
metadata_json TEXT,
|
|
40
|
+
created_at INTEGER NOT NULL,
|
|
41
|
+
updated_at INTEGER NOT NULL
|
|
42
|
+
)
|
|
43
|
+
`);
|
|
44
|
+
|
|
45
|
+
raw.exec(
|
|
46
|
+
/*sql*/ `CREATE INDEX IF NOT EXISTS idx_accounts_service ON accounts(service)`,
|
|
47
|
+
);
|
|
48
|
+
raw.exec(
|
|
49
|
+
/*sql*/ `CREATE INDEX IF NOT EXISTS idx_accounts_status ON accounts(status)`,
|
|
50
|
+
);
|
|
51
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { DrizzleDb } from "../db-connection.js";
|
|
2
|
+
import { getSqliteFrom } from "../db-connection.js";
|
|
2
3
|
import { withCrashRecovery } from "./validate-migration-state.js";
|
|
3
4
|
|
|
4
5
|
/**
|
|
@@ -123,3 +124,15 @@ export function migrateRemindersToSchedules(database: DrizzleDb): void {
|
|
|
123
124
|
}
|
|
124
125
|
});
|
|
125
126
|
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Reverse: no-op.
|
|
130
|
+
*
|
|
131
|
+
* Cannot reliably identify which cron_jobs rows were migrated from reminders
|
|
132
|
+
* versus created natively as schedules. Rows share the same table and there
|
|
133
|
+
* is no origin marker. Deleting the wrong rows would destroy user-created
|
|
134
|
+
* schedules.
|
|
135
|
+
*/
|
|
136
|
+
export function migrateRemindersToSchedulesDown(_database: DrizzleDb): void {
|
|
137
|
+
// No-op — see comment above.
|
|
138
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { DrizzleDb } from "../db-connection.js";
|
|
2
|
+
import { getSqliteFrom } from "../db-connection.js";
|
|
2
3
|
import { withCrashRecovery } from "./validate-migration-state.js";
|
|
3
4
|
|
|
4
5
|
/**
|
|
@@ -12,3 +13,36 @@ export function migrateDropRemindersTable(database: DrizzleDb): void {
|
|
|
12
13
|
raw.run("DROP TABLE IF EXISTS reminders");
|
|
13
14
|
});
|
|
14
15
|
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Reverse: recreate the reminders table with its original schema.
|
|
19
|
+
*
|
|
20
|
+
* Data is permanently lost — the table was dropped. This only restores the
|
|
21
|
+
* empty table structure so that earlier migrations referencing it can operate.
|
|
22
|
+
* Includes the routing_intent and routing_hints_json columns added by
|
|
23
|
+
* migration 118.
|
|
24
|
+
*/
|
|
25
|
+
export function migrateDropRemindersTableDown(database: DrizzleDb): void {
|
|
26
|
+
const raw = getSqliteFrom(database);
|
|
27
|
+
|
|
28
|
+
raw.exec(/*sql*/ `
|
|
29
|
+
CREATE TABLE IF NOT EXISTS reminders (
|
|
30
|
+
id TEXT PRIMARY KEY,
|
|
31
|
+
label TEXT NOT NULL,
|
|
32
|
+
message TEXT NOT NULL,
|
|
33
|
+
fire_at INTEGER NOT NULL,
|
|
34
|
+
mode TEXT NOT NULL,
|
|
35
|
+
status TEXT NOT NULL,
|
|
36
|
+
fired_at INTEGER,
|
|
37
|
+
conversation_id TEXT,
|
|
38
|
+
routing_intent TEXT NOT NULL DEFAULT 'all_channels',
|
|
39
|
+
routing_hints_json TEXT NOT NULL DEFAULT '{}',
|
|
40
|
+
created_at INTEGER NOT NULL,
|
|
41
|
+
updated_at INTEGER NOT NULL
|
|
42
|
+
)
|
|
43
|
+
`);
|
|
44
|
+
|
|
45
|
+
raw.exec(
|
|
46
|
+
/*sql*/ `CREATE INDEX IF NOT EXISTS idx_reminders_status_fire_at ON reminders(status, fire_at)`,
|
|
47
|
+
);
|
|
48
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { DrizzleDb } from "../db-connection.js";
|
|
2
|
+
import { getSqliteFrom } from "../db-connection.js";
|
|
2
3
|
import { withCrashRecovery } from "./validate-migration-state.js";
|
|
3
4
|
|
|
4
5
|
/**
|
|
@@ -96,3 +97,70 @@ export function migrateOAuthAppsClientSecretPath(database: DrizzleDb): void {
|
|
|
96
97
|
},
|
|
97
98
|
);
|
|
98
99
|
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Reverse: drop the client_secret_credential_path column from oauth_apps.
|
|
103
|
+
*
|
|
104
|
+
* Rebuilds the table without the column (SQLite doesn't support DROP COLUMN
|
|
105
|
+
* on older versions). Idempotent — skips if the column doesn't exist.
|
|
106
|
+
*/
|
|
107
|
+
export function migrateOAuthAppsClientSecretPathDown(
|
|
108
|
+
database: DrizzleDb,
|
|
109
|
+
): void {
|
|
110
|
+
const raw = getSqliteFrom(database);
|
|
111
|
+
|
|
112
|
+
// Guard: table must exist
|
|
113
|
+
const tableExists = raw
|
|
114
|
+
.query(
|
|
115
|
+
`SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'oauth_apps'`,
|
|
116
|
+
)
|
|
117
|
+
.get();
|
|
118
|
+
if (!tableExists) return;
|
|
119
|
+
|
|
120
|
+
// Guard: if the column doesn't exist, nothing to do
|
|
121
|
+
const colInfo = raw
|
|
122
|
+
.query(
|
|
123
|
+
`SELECT 1 FROM pragma_table_info('oauth_apps') WHERE name = 'client_secret_credential_path'`,
|
|
124
|
+
)
|
|
125
|
+
.get();
|
|
126
|
+
if (!colInfo) return;
|
|
127
|
+
|
|
128
|
+
raw.exec("PRAGMA foreign_keys = OFF");
|
|
129
|
+
try {
|
|
130
|
+
raw.exec("BEGIN");
|
|
131
|
+
|
|
132
|
+
raw.exec(/*sql*/ `
|
|
133
|
+
CREATE TABLE oauth_apps_rollback (
|
|
134
|
+
id TEXT PRIMARY KEY,
|
|
135
|
+
provider_key TEXT NOT NULL REFERENCES oauth_providers(provider_key),
|
|
136
|
+
client_id TEXT NOT NULL,
|
|
137
|
+
created_at INTEGER NOT NULL,
|
|
138
|
+
updated_at INTEGER NOT NULL
|
|
139
|
+
)
|
|
140
|
+
`);
|
|
141
|
+
|
|
142
|
+
raw.exec(/*sql*/ `
|
|
143
|
+
INSERT INTO oauth_apps_rollback
|
|
144
|
+
SELECT id, provider_key, client_id, created_at, updated_at
|
|
145
|
+
FROM oauth_apps
|
|
146
|
+
`);
|
|
147
|
+
|
|
148
|
+
raw.exec(/*sql*/ `DROP TABLE oauth_apps`);
|
|
149
|
+
raw.exec(/*sql*/ `ALTER TABLE oauth_apps_rollback RENAME TO oauth_apps`);
|
|
150
|
+
|
|
151
|
+
raw.exec(
|
|
152
|
+
/*sql*/ `CREATE UNIQUE INDEX IF NOT EXISTS idx_oauth_apps_provider_client ON oauth_apps(provider_key, client_id)`,
|
|
153
|
+
);
|
|
154
|
+
|
|
155
|
+
raw.exec("COMMIT");
|
|
156
|
+
} catch (e) {
|
|
157
|
+
try {
|
|
158
|
+
raw.exec("ROLLBACK");
|
|
159
|
+
} catch {
|
|
160
|
+
/* no active transaction */
|
|
161
|
+
}
|
|
162
|
+
throw e;
|
|
163
|
+
} finally {
|
|
164
|
+
raw.exec("PRAGMA foreign_keys = ON");
|
|
165
|
+
}
|
|
166
|
+
}
|