@vellumai/assistant 0.5.5 → 0.5.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/.env.example +16 -2
- package/ARCHITECTURE.md +6 -75
- package/Dockerfile +4 -5
- package/README.md +0 -2
- package/bun.lock +0 -414
- package/docs/architecture/keychain-broker.md +45 -240
- 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/rpc.ts +119 -0
- 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 +1 -2
- package/src/__tests__/assistant-feature-flags-integration.test.ts +30 -29
- package/src/__tests__/browser-skill-endstate.test.ts +6 -5
- package/src/__tests__/btw-routes.test.ts +0 -39
- package/src/__tests__/call-domain.test.ts +0 -128
- package/src/__tests__/ces-rpc-credential-backend.test.ts +199 -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 -1
- package/src/__tests__/config-schema.test.ts +3 -3
- package/src/__tests__/context-window-manager.test.ts +78 -0
- package/src/__tests__/conversation-attention-telegram.test.ts +0 -5
- package/src/__tests__/conversation-init.benchmark.test.ts +0 -2
- package/src/__tests__/conversation-skill-tools.test.ts +0 -54
- package/src/__tests__/conversation-title-service.test.ts +117 -1
- package/src/__tests__/credential-execution-feature-gates.test.ts +28 -14
- package/src/__tests__/credential-execution-managed-contract.test.ts +33 -18
- package/src/__tests__/credential-security-e2e.test.ts +0 -66
- package/src/__tests__/credential-security-invariants.test.ts +4 -45
- package/src/__tests__/credentials-cli.test.ts +78 -0
- package/src/__tests__/db-migration-rollback.test.ts +2015 -1
- package/src/__tests__/docker-signing-key-bootstrap.test.ts +98 -0
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +6 -4
- 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__/keychain-broker-client.test.ts +161 -22
- package/src/__tests__/memory-jobs-worker-backoff.test.ts +150 -0
- package/src/__tests__/memory-regressions.test.ts +8 -30
- 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 +0 -5
- package/src/__tests__/notification-decision-fallback.test.ts +4 -0
- package/src/__tests__/notification-decision-identity.test.ts +4 -0
- package/src/__tests__/permission-types.test.ts +1 -0
- package/src/__tests__/provider-managed-proxy-integration.test.ts +5 -6
- package/src/__tests__/qdrant-manager.test.ts +28 -2
- package/src/__tests__/registry.test.ts +0 -6
- package/src/__tests__/require-fresh-approval.test.ts +4 -0
- package/src/__tests__/runtime-attachment-metadata.test.ts +0 -4
- package/src/__tests__/secret-routes-managed-proxy.test.ts +0 -4
- package/src/__tests__/secure-keys.test.ts +83 -263
- 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-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__/suggestion-routes.test.ts +1 -32
- package/src/__tests__/system-prompt.test.ts +0 -1
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +4 -0
- package/src/__tests__/tool-executor-shell-integration.test.ts +5 -3
- package/src/__tests__/tool-executor.test.ts +4 -0
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +0 -5
- package/src/__tests__/trusted-contact-multichannel.test.ts +0 -4
- 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-scoped-grant-consumer.test.ts +0 -6
- 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 +218 -0
- package/src/__tests__/workspace-migration-down-functions.test.ts +1009 -0
- package/src/__tests__/workspace-migrations-runner.test.ts +114 -0
- package/src/calls/audio-store.test.ts +97 -0
- package/src/calls/audio-store.ts +205 -0
- package/src/calls/call-controller.ts +85 -7
- package/src/calls/call-domain.ts +3 -0
- package/src/calls/call-store.ts +10 -3
- package/src/calls/fish-audio-client.ts +117 -0
- package/src/calls/relay-server.ts +27 -0
- package/src/calls/twilio-routes.ts +2 -1
- package/src/calls/types.ts +1 -0
- package/src/calls/voice-ingress-preflight.ts +0 -42
- package/src/calls/voice-quality.ts +26 -5
- package/src/calls/voice-session-bridge.ts +6 -12
- package/src/cli/commands/config.ts +1 -4
- package/src/cli/commands/conversations.ts +0 -18
- package/src/cli/commands/credentials.ts +34 -4
- package/src/cli/commands/oauth/index.ts +7 -0
- package/src/cli/commands/oauth/platform.ts +179 -0
- package/src/cli/commands/platform.ts +3 -3
- package/src/config/assistant-feature-flags.ts +186 -5
- package/src/config/bundled-skills/messaging/SKILL.md +5 -5
- package/src/config/bundled-skills/phone-calls/TOOLS.json +4 -0
- package/src/config/bundled-skills/settings/TOOLS.json +2 -2
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +42 -0
- package/src/config/bundled-tool-registry.ts +1 -11
- package/src/config/env-registry.ts +1 -1
- package/src/config/env.ts +16 -16
- package/src/config/feature-flag-registry.json +48 -16
- package/src/config/loader.ts +98 -31
- package/src/config/schema.ts +4 -25
- package/src/config/schemas/calls.ts +13 -0
- package/src/config/schemas/fish-audio.ts +39 -0
- package/src/config/schemas/memory.ts +0 -4
- package/src/config/schemas/platform.ts +1 -1
- package/src/config/schemas/security.ts +4 -4
- package/src/config/types.ts +0 -1
- package/src/contacts/contact-store.ts +39 -0
- package/src/contacts/types.ts +2 -0
- package/src/context/window-manager.ts +53 -2
- 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/daemon/assistant-attachments.ts +9 -0
- package/src/daemon/config-watcher.ts +6 -4
- package/src/daemon/conversation-agent-loop.ts +0 -60
- package/src/daemon/conversation-memory.ts +0 -117
- package/src/daemon/conversation-runtime-assembly.ts +0 -2
- package/src/daemon/conversation-tool-setup.ts +0 -105
- package/src/daemon/conversation.ts +10 -1
- package/src/daemon/handlers/config-vercel.ts +92 -0
- package/src/daemon/handlers/conversations.ts +0 -11
- package/src/daemon/handlers/skills.ts +2 -15
- package/src/daemon/install-symlink.ts +195 -0
- package/src/daemon/lifecycle.ts +229 -96
- package/src/daemon/message-types/conversations.ts +3 -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 +30 -92
- package/src/events/domain-events.ts +2 -1
- package/src/followups/followup-store.ts +5 -2
- package/src/inbound/platform-callback-registration.ts +3 -3
- package/src/instrument.ts +8 -5
- package/src/memory/conversation-crud.ts +0 -236
- package/src/memory/conversation-title-service.ts +76 -11
- package/src/memory/db-init.ts +15 -11
- package/src/memory/indexer.ts +15 -106
- package/src/memory/items-extractor.ts +15 -1
- package/src/memory/job-handlers/conversation-starters.ts +4 -1
- package/src/memory/job-handlers/embedding.ts +0 -79
- package/src/memory/job-utils.ts +1 -1
- package/src/memory/jobs-store.ts +30 -13
- package/src/memory/jobs-worker.ts +31 -27
- 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/189-drop-simplified-memory.ts +42 -0
- 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/index.ts +5 -3
- package/src/memory/migrations/registry.ts +90 -0
- package/src/memory/migrations/validate-migration-state.ts +137 -11
- package/src/memory/qdrant-circuit-breaker.ts +9 -0
- package/src/memory/qdrant-client.ts +4 -6
- package/src/memory/qdrant-manager.ts +64 -7
- package/src/memory/schema/calls.ts +1 -0
- package/src/memory/schema/contacts.ts +1 -0
- package/src/memory/schema/conversations.ts +0 -3
- package/src/memory/schema/index.ts +0 -2
- package/src/messaging/draft-store.ts +2 -2
- package/src/notifications/decision-engine.ts +4 -1
- package/src/oauth/connection-resolver.ts +6 -4
- package/src/permissions/checker.ts +0 -38
- package/src/permissions/defaults.ts +3 -3
- package/src/permissions/shell-identity.ts +76 -22
- package/src/permissions/trust-client.ts +2 -13
- package/src/permissions/trust-store.ts +8 -3
- package/src/permissions/types.ts +4 -2
- package/src/platform/client.ts +35 -7
- package/src/prompts/persona-resolver.ts +138 -0
- package/src/prompts/system-prompt.ts +36 -4
- package/src/prompts/templates/users/default.md +1 -0
- package/src/providers/registry.ts +27 -40
- 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/external-assistant-id.ts +13 -59
- package/src/runtime/auth/route-policy.ts +29 -1
- package/src/runtime/auth/token-service.ts +53 -15
- package/src/runtime/channel-readiness-service.ts +1 -16
- package/src/runtime/http-server.ts +29 -2
- package/src/runtime/middleware/error-handler.ts +1 -9
- package/src/runtime/routes/audio-routes.ts +40 -0
- package/src/runtime/routes/btw-routes.ts +0 -17
- package/src/runtime/routes/conversation-management-routes.ts +0 -36
- package/src/runtime/routes/conversation-query-routes.ts +106 -2
- package/src/runtime/routes/conversation-routes.ts +4 -43
- package/src/runtime/routes/diagnostics-routes.ts +1 -477
- package/src/runtime/routes/identity-routes.ts +18 -29
- 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/vercel.ts +89 -0
- package/src/runtime/routes/log-export-routes.ts +5 -0
- package/src/runtime/routes/memory-item-routes.test.ts +221 -3
- package/src/runtime/routes/memory-item-routes.ts +144 -4
- 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/settings-routes.ts +41 -1
- package/src/runtime/routes/tts-routes.ts +86 -0
- package/src/runtime/routes/upgrade-broadcast-routes.ts +175 -0
- 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/schedule/schedule-store.ts +0 -21
- package/src/security/ces-credential-client.ts +59 -22
- package/src/security/ces-rpc-credential-backend.ts +85 -0
- package/src/security/credential-backend.ts +12 -88
- package/src/security/keychain-broker-client.ts +10 -2
- package/src/security/secure-keys.ts +94 -113
- package/src/skills/catalog-install.ts +13 -7
- package/src/skills/inline-command-render.ts +5 -1
- package/src/skills/inline-command-runner.ts +30 -2
- package/src/telemetry/usage-telemetry-reporter.ts +4 -2
- package/src/tools/calls/call-start.ts +1 -0
- package/src/tools/executor.ts +0 -4
- package/src/tools/memory/handlers.ts +1 -129
- package/src/tools/network/script-proxy/session-manager.ts +19 -4
- package/src/tools/network/web-fetch.ts +3 -1
- package/src/tools/permission-checker.ts +18 -0
- package/src/tools/skills/execute.ts +1 -1
- package/src/tools/skills/load.ts +9 -2
- package/src/tools/types.ts +0 -8
- package/src/util/errors.ts +0 -12
- package/src/util/platform.ts +8 -55
- package/src/util/xml.ts +8 -0
- package/src/workspace/git-service.ts +5 -2
- package/src/workspace/heartbeat-service.ts +5 -24
- 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 +95 -0
- package/src/workspace/migrations/migrate-to-workspace-volume.ts +23 -1
- package/src/workspace/migrations/registry.ts +8 -0
- package/src/workspace/migrations/runner.ts +106 -2
- package/src/workspace/migrations/types.ts +4 -0
- package/src/__tests__/archive-recall.test.ts +0 -560
- 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__/conversation-memory-dirty-tail.test.ts +0 -150
- package/src/__tests__/conversation-switch-memory-reduction.test.ts +0 -474
- package/src/__tests__/db-memory-archive-migration.test.ts +0 -372
- package/src/__tests__/db-memory-brief-state-migration.test.ts +0 -213
- package/src/__tests__/db-memory-reducer-checkpoints.test.ts +0 -273
- package/src/__tests__/diagnostics-export.test.ts +0 -288
- package/src/__tests__/local-gateway-health.test.ts +0 -209
- package/src/__tests__/memory-brief-open-loops.test.ts +0 -530
- package/src/__tests__/memory-brief-time.test.ts +0 -285
- package/src/__tests__/memory-brief-wrapper.test.ts +0 -311
- package/src/__tests__/memory-chunk-archive.test.ts +0 -400
- package/src/__tests__/memory-chunk-dual-write.test.ts +0 -453
- package/src/__tests__/memory-episode-archive.test.ts +0 -370
- package/src/__tests__/memory-episode-dual-write.test.ts +0 -626
- package/src/__tests__/memory-observation-archive.test.ts +0 -375
- package/src/__tests__/memory-observation-dual-write.test.ts +0 -318
- package/src/__tests__/memory-reducer-job.test.ts +0 -538
- package/src/__tests__/memory-reducer-scheduling.test.ts +0 -473
- package/src/__tests__/memory-reducer-store.test.ts +0 -728
- package/src/__tests__/memory-reducer-types.test.ts +0 -707
- package/src/__tests__/memory-reducer.test.ts +0 -704
- package/src/__tests__/memory-simplified-config.test.ts +0 -281
- package/src/__tests__/secret-ingress-handler.test.ts +0 -120
- package/src/__tests__/simplified-memory-e2e.test.ts +0 -666
- package/src/__tests__/simplified-memory-runtime.test.ts +0 -616
- 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/memory-simplified.ts +0 -101
- package/src/config/schemas/swarm.ts +0 -82
- package/src/logfire.ts +0 -135
- package/src/memory/archive-recall.ts +0 -516
- package/src/memory/archive-store.ts +0 -400
- package/src/memory/brief-formatting.ts +0 -33
- package/src/memory/brief-open-loops.ts +0 -266
- package/src/memory/brief-time.ts +0 -162
- package/src/memory/brief.ts +0 -75
- package/src/memory/job-handlers/backfill-simplified-memory.ts +0 -462
- package/src/memory/job-handlers/reduce-conversation-memory.ts +0 -229
- package/src/memory/migrations/185-memory-brief-state.ts +0 -52
- package/src/memory/migrations/186-memory-archive.ts +0 -109
- package/src/memory/migrations/187-memory-reducer-checkpoints.ts +0 -19
- package/src/memory/reducer-scheduler.ts +0 -242
- package/src/memory/reducer-store.ts +0 -271
- package/src/memory/reducer-types.ts +0 -106
- package/src/memory/reducer.ts +0 -467
- package/src/memory/schema/memory-archive.ts +0 -121
- package/src/memory/schema/memory-brief.ts +0 -55
- 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,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
|
+
}
|
|
@@ -281,3 +281,293 @@ function rebuildScopedApprovalGrants(raw: RawDb): void {
|
|
|
281
281
|
raw.exec("PRAGMA foreign_keys = ON");
|
|
282
282
|
}
|
|
283
283
|
}
|
|
284
|
+
|
|
285
|
+
// ---------------------------------------------------------------------------
|
|
286
|
+
// Down functions
|
|
287
|
+
// ---------------------------------------------------------------------------
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Reverse v29: convert epoch ms timestamps back to ISO 8601 text in guardian
|
|
291
|
+
* tables.
|
|
292
|
+
*
|
|
293
|
+
* Uses SQLite's datetime() to reconstruct ISO 8601 strings from the integer
|
|
294
|
+
* values. The millisecond component is appended manually since datetime()
|
|
295
|
+
* only returns second precision.
|
|
296
|
+
*/
|
|
297
|
+
export function migrateGuardianTimestampsEpochMsDown(
|
|
298
|
+
database: DrizzleDb,
|
|
299
|
+
): void {
|
|
300
|
+
const raw = getSqliteFrom(database);
|
|
301
|
+
|
|
302
|
+
// Convert canonical_guardian_requests timestamp columns back to ISO 8601
|
|
303
|
+
raw.exec(/*sql*/ `
|
|
304
|
+
UPDATE canonical_guardian_requests
|
|
305
|
+
SET created_at = strftime('%Y-%m-%dT%H:%M:%S', created_at / 1000, 'unixepoch') || '.' || printf('%03d', created_at % 1000) || 'Z',
|
|
306
|
+
updated_at = strftime('%Y-%m-%dT%H:%M:%S', updated_at / 1000, 'unixepoch') || '.' || printf('%03d', updated_at % 1000) || 'Z',
|
|
307
|
+
expires_at = CASE
|
|
308
|
+
WHEN expires_at IS NOT NULL
|
|
309
|
+
THEN strftime('%Y-%m-%dT%H:%M:%S', expires_at / 1000, 'unixepoch') || '.' || printf('%03d', expires_at % 1000) || 'Z'
|
|
310
|
+
ELSE NULL
|
|
311
|
+
END
|
|
312
|
+
WHERE typeof(created_at) = 'integer'
|
|
313
|
+
`);
|
|
314
|
+
|
|
315
|
+
// Convert canonical_guardian_deliveries timestamp columns back to ISO 8601
|
|
316
|
+
raw.exec(/*sql*/ `
|
|
317
|
+
UPDATE canonical_guardian_deliveries
|
|
318
|
+
SET created_at = strftime('%Y-%m-%dT%H:%M:%S', created_at / 1000, 'unixepoch') || '.' || printf('%03d', created_at % 1000) || 'Z',
|
|
319
|
+
updated_at = strftime('%Y-%m-%dT%H:%M:%S', updated_at / 1000, 'unixepoch') || '.' || printf('%03d', updated_at % 1000) || 'Z'
|
|
320
|
+
WHERE typeof(created_at) = 'integer'
|
|
321
|
+
`);
|
|
322
|
+
|
|
323
|
+
// Convert scoped_approval_grants timestamp columns back to ISO 8601
|
|
324
|
+
raw.exec(/*sql*/ `
|
|
325
|
+
UPDATE scoped_approval_grants
|
|
326
|
+
SET expires_at = strftime('%Y-%m-%dT%H:%M:%S', expires_at / 1000, 'unixepoch') || '.' || printf('%03d', expires_at % 1000) || 'Z',
|
|
327
|
+
created_at = strftime('%Y-%m-%dT%H:%M:%S', created_at / 1000, 'unixepoch') || '.' || printf('%03d', created_at % 1000) || 'Z',
|
|
328
|
+
updated_at = strftime('%Y-%m-%dT%H:%M:%S', updated_at / 1000, 'unixepoch') || '.' || printf('%03d', updated_at % 1000) || 'Z',
|
|
329
|
+
consumed_at = CASE
|
|
330
|
+
WHEN consumed_at IS NOT NULL
|
|
331
|
+
THEN strftime('%Y-%m-%dT%H:%M:%S', consumed_at / 1000, 'unixepoch') || '.' || printf('%03d', consumed_at % 1000) || 'Z'
|
|
332
|
+
ELSE NULL
|
|
333
|
+
END
|
|
334
|
+
WHERE typeof(created_at) = 'integer'
|
|
335
|
+
`);
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Reverse v30: rebuild guardian tables with TEXT affinity on timestamp columns.
|
|
340
|
+
*
|
|
341
|
+
* Restores the original TEXT column declarations so that timestamp columns
|
|
342
|
+
* have TEXT affinity (the state before the INTEGER rebuild).
|
|
343
|
+
*/
|
|
344
|
+
export function migrateGuardianTimestampsRebuildDown(
|
|
345
|
+
database: DrizzleDb,
|
|
346
|
+
): void {
|
|
347
|
+
const raw = getSqliteFrom(database);
|
|
348
|
+
|
|
349
|
+
rebuildCanonicalGuardianRequestsToText(raw);
|
|
350
|
+
rebuildCanonicalGuardianDeliveriesToText(raw);
|
|
351
|
+
rebuildScopedApprovalGrantsToText(raw);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
function hasTextAffinity(raw: RawDb, table: string, column: string): boolean {
|
|
355
|
+
const row = raw
|
|
356
|
+
.query(
|
|
357
|
+
`SELECT type FROM pragma_table_info('${table}') WHERE name = '${column}'`,
|
|
358
|
+
)
|
|
359
|
+
.get() as { type: string } | null;
|
|
360
|
+
if (!row) return true; // column doesn't exist — nothing to fix
|
|
361
|
+
return row.type.toUpperCase() === "TEXT";
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
function rebuildCanonicalGuardianRequestsToText(raw: RawDb): void {
|
|
365
|
+
if (hasTextAffinity(raw, "canonical_guardian_requests", "created_at")) return;
|
|
366
|
+
|
|
367
|
+
raw.exec("PRAGMA foreign_keys = OFF");
|
|
368
|
+
try {
|
|
369
|
+
raw.exec("BEGIN");
|
|
370
|
+
|
|
371
|
+
raw.exec(/*sql*/ `
|
|
372
|
+
CREATE TABLE canonical_guardian_requests_rb (
|
|
373
|
+
id TEXT PRIMARY KEY,
|
|
374
|
+
kind TEXT NOT NULL,
|
|
375
|
+
source_type TEXT NOT NULL,
|
|
376
|
+
source_channel TEXT,
|
|
377
|
+
conversation_id TEXT,
|
|
378
|
+
requester_external_user_id TEXT,
|
|
379
|
+
requester_chat_id TEXT,
|
|
380
|
+
guardian_external_user_id TEXT,
|
|
381
|
+
guardian_principal_id TEXT,
|
|
382
|
+
call_session_id TEXT,
|
|
383
|
+
pending_question_id TEXT,
|
|
384
|
+
question_text TEXT,
|
|
385
|
+
request_code TEXT,
|
|
386
|
+
tool_name TEXT,
|
|
387
|
+
input_digest TEXT,
|
|
388
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
389
|
+
answer_text TEXT,
|
|
390
|
+
decided_by_external_user_id TEXT,
|
|
391
|
+
decided_by_principal_id TEXT,
|
|
392
|
+
followup_state TEXT,
|
|
393
|
+
expires_at TEXT,
|
|
394
|
+
created_at TEXT NOT NULL,
|
|
395
|
+
updated_at TEXT NOT NULL
|
|
396
|
+
)
|
|
397
|
+
`);
|
|
398
|
+
|
|
399
|
+
raw.exec(/*sql*/ `
|
|
400
|
+
INSERT INTO canonical_guardian_requests_rb
|
|
401
|
+
SELECT id, kind, source_type, source_channel, conversation_id,
|
|
402
|
+
requester_external_user_id, requester_chat_id,
|
|
403
|
+
guardian_external_user_id, guardian_principal_id,
|
|
404
|
+
call_session_id, pending_question_id, question_text,
|
|
405
|
+
request_code, tool_name, input_digest, status, answer_text,
|
|
406
|
+
decided_by_external_user_id, decided_by_principal_id,
|
|
407
|
+
followup_state, expires_at, created_at, updated_at
|
|
408
|
+
FROM canonical_guardian_requests
|
|
409
|
+
`);
|
|
410
|
+
|
|
411
|
+
raw.exec(/*sql*/ `DROP TABLE canonical_guardian_requests`);
|
|
412
|
+
raw.exec(
|
|
413
|
+
/*sql*/ `ALTER TABLE canonical_guardian_requests_rb RENAME TO canonical_guardian_requests`,
|
|
414
|
+
);
|
|
415
|
+
|
|
416
|
+
raw.exec(
|
|
417
|
+
/*sql*/ `CREATE INDEX IF NOT EXISTS idx_canonical_guardian_requests_status ON canonical_guardian_requests(status)`,
|
|
418
|
+
);
|
|
419
|
+
raw.exec(
|
|
420
|
+
/*sql*/ `CREATE INDEX IF NOT EXISTS idx_canonical_guardian_requests_guardian ON canonical_guardian_requests(guardian_external_user_id, status)`,
|
|
421
|
+
);
|
|
422
|
+
raw.exec(
|
|
423
|
+
/*sql*/ `CREATE INDEX IF NOT EXISTS idx_canonical_guardian_requests_conversation ON canonical_guardian_requests(conversation_id, status)`,
|
|
424
|
+
);
|
|
425
|
+
raw.exec(
|
|
426
|
+
/*sql*/ `CREATE INDEX IF NOT EXISTS idx_canonical_guardian_requests_source ON canonical_guardian_requests(source_type, status)`,
|
|
427
|
+
);
|
|
428
|
+
raw.exec(
|
|
429
|
+
/*sql*/ `CREATE INDEX IF NOT EXISTS idx_canonical_guardian_requests_kind ON canonical_guardian_requests(kind, status)`,
|
|
430
|
+
);
|
|
431
|
+
raw.exec(
|
|
432
|
+
/*sql*/ `CREATE INDEX IF NOT EXISTS idx_canonical_guardian_requests_request_code ON canonical_guardian_requests(request_code)`,
|
|
433
|
+
);
|
|
434
|
+
|
|
435
|
+
raw.exec("COMMIT");
|
|
436
|
+
} catch (e) {
|
|
437
|
+
try {
|
|
438
|
+
raw.exec("ROLLBACK");
|
|
439
|
+
} catch {
|
|
440
|
+
/* no active transaction */
|
|
441
|
+
}
|
|
442
|
+
throw e;
|
|
443
|
+
} finally {
|
|
444
|
+
raw.exec("PRAGMA foreign_keys = ON");
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
function rebuildCanonicalGuardianDeliveriesToText(raw: RawDb): void {
|
|
449
|
+
if (hasTextAffinity(raw, "canonical_guardian_deliveries", "created_at"))
|
|
450
|
+
return;
|
|
451
|
+
|
|
452
|
+
raw.exec("PRAGMA foreign_keys = OFF");
|
|
453
|
+
try {
|
|
454
|
+
raw.exec("BEGIN");
|
|
455
|
+
|
|
456
|
+
raw.exec(/*sql*/ `
|
|
457
|
+
CREATE TABLE canonical_guardian_deliveries_rb (
|
|
458
|
+
id TEXT PRIMARY KEY,
|
|
459
|
+
request_id TEXT NOT NULL REFERENCES canonical_guardian_requests(id) ON DELETE CASCADE,
|
|
460
|
+
destination_channel TEXT NOT NULL,
|
|
461
|
+
destination_conversation_id TEXT,
|
|
462
|
+
destination_chat_id TEXT,
|
|
463
|
+
destination_message_id TEXT,
|
|
464
|
+
status TEXT NOT NULL DEFAULT 'pending',
|
|
465
|
+
created_at TEXT NOT NULL,
|
|
466
|
+
updated_at TEXT NOT NULL
|
|
467
|
+
)
|
|
468
|
+
`);
|
|
469
|
+
|
|
470
|
+
raw.exec(/*sql*/ `
|
|
471
|
+
INSERT INTO canonical_guardian_deliveries_rb
|
|
472
|
+
SELECT id, request_id, destination_channel, destination_conversation_id,
|
|
473
|
+
destination_chat_id, destination_message_id, status,
|
|
474
|
+
created_at, updated_at
|
|
475
|
+
FROM canonical_guardian_deliveries
|
|
476
|
+
`);
|
|
477
|
+
|
|
478
|
+
raw.exec(/*sql*/ `DROP TABLE canonical_guardian_deliveries`);
|
|
479
|
+
raw.exec(
|
|
480
|
+
/*sql*/ `ALTER TABLE canonical_guardian_deliveries_rb RENAME TO canonical_guardian_deliveries`,
|
|
481
|
+
);
|
|
482
|
+
|
|
483
|
+
raw.exec(
|
|
484
|
+
/*sql*/ `CREATE INDEX IF NOT EXISTS idx_canonical_guardian_deliveries_request_id ON canonical_guardian_deliveries(request_id)`,
|
|
485
|
+
);
|
|
486
|
+
raw.exec(
|
|
487
|
+
/*sql*/ `CREATE INDEX IF NOT EXISTS idx_canonical_guardian_deliveries_status ON canonical_guardian_deliveries(status)`,
|
|
488
|
+
);
|
|
489
|
+
raw.exec(
|
|
490
|
+
/*sql*/ `CREATE INDEX IF NOT EXISTS idx_canonical_guardian_deliveries_destination ON canonical_guardian_deliveries(destination_channel, destination_chat_id)`,
|
|
491
|
+
);
|
|
492
|
+
|
|
493
|
+
raw.exec("COMMIT");
|
|
494
|
+
} catch (e) {
|
|
495
|
+
try {
|
|
496
|
+
raw.exec("ROLLBACK");
|
|
497
|
+
} catch {
|
|
498
|
+
/* no active transaction */
|
|
499
|
+
}
|
|
500
|
+
throw e;
|
|
501
|
+
} finally {
|
|
502
|
+
raw.exec("PRAGMA foreign_keys = ON");
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
function rebuildScopedApprovalGrantsToText(raw: RawDb): void {
|
|
507
|
+
if (hasTextAffinity(raw, "scoped_approval_grants", "created_at")) return;
|
|
508
|
+
|
|
509
|
+
raw.exec("PRAGMA foreign_keys = OFF");
|
|
510
|
+
try {
|
|
511
|
+
raw.exec("BEGIN");
|
|
512
|
+
|
|
513
|
+
raw.exec(/*sql*/ `
|
|
514
|
+
CREATE TABLE scoped_approval_grants_rb (
|
|
515
|
+
id TEXT PRIMARY KEY,
|
|
516
|
+
scope_mode TEXT NOT NULL,
|
|
517
|
+
request_id TEXT,
|
|
518
|
+
tool_name TEXT,
|
|
519
|
+
input_digest TEXT,
|
|
520
|
+
request_channel TEXT NOT NULL,
|
|
521
|
+
decision_channel TEXT NOT NULL,
|
|
522
|
+
execution_channel TEXT,
|
|
523
|
+
conversation_id TEXT,
|
|
524
|
+
call_session_id TEXT,
|
|
525
|
+
requester_external_user_id TEXT,
|
|
526
|
+
guardian_external_user_id TEXT,
|
|
527
|
+
status TEXT NOT NULL,
|
|
528
|
+
expires_at TEXT NOT NULL,
|
|
529
|
+
consumed_at TEXT,
|
|
530
|
+
consumed_by_request_id TEXT,
|
|
531
|
+
created_at TEXT NOT NULL,
|
|
532
|
+
updated_at TEXT NOT NULL
|
|
533
|
+
)
|
|
534
|
+
`);
|
|
535
|
+
|
|
536
|
+
raw.exec(/*sql*/ `
|
|
537
|
+
INSERT INTO scoped_approval_grants_rb
|
|
538
|
+
SELECT id, scope_mode, request_id, tool_name, input_digest,
|
|
539
|
+
request_channel, decision_channel, execution_channel,
|
|
540
|
+
conversation_id, call_session_id,
|
|
541
|
+
requester_external_user_id, guardian_external_user_id,
|
|
542
|
+
status, expires_at, consumed_at, consumed_by_request_id,
|
|
543
|
+
created_at, updated_at
|
|
544
|
+
FROM scoped_approval_grants
|
|
545
|
+
`);
|
|
546
|
+
|
|
547
|
+
raw.exec(/*sql*/ `DROP TABLE scoped_approval_grants`);
|
|
548
|
+
raw.exec(
|
|
549
|
+
/*sql*/ `ALTER TABLE scoped_approval_grants_rb RENAME TO scoped_approval_grants`,
|
|
550
|
+
);
|
|
551
|
+
|
|
552
|
+
raw.exec(
|
|
553
|
+
/*sql*/ `CREATE INDEX IF NOT EXISTS idx_scoped_grants_request_id ON scoped_approval_grants(request_id) WHERE request_id IS NOT NULL`,
|
|
554
|
+
);
|
|
555
|
+
raw.exec(
|
|
556
|
+
/*sql*/ `CREATE INDEX IF NOT EXISTS idx_scoped_grants_tool_sig ON scoped_approval_grants(tool_name, input_digest) WHERE tool_name IS NOT NULL`,
|
|
557
|
+
);
|
|
558
|
+
raw.exec(
|
|
559
|
+
/*sql*/ `CREATE INDEX IF NOT EXISTS idx_scoped_grants_status_expires ON scoped_approval_grants(status, expires_at)`,
|
|
560
|
+
);
|
|
561
|
+
|
|
562
|
+
raw.exec("COMMIT");
|
|
563
|
+
} catch (e) {
|
|
564
|
+
try {
|
|
565
|
+
raw.exec("ROLLBACK");
|
|
566
|
+
} catch {
|
|
567
|
+
/* no active transaction */
|
|
568
|
+
}
|
|
569
|
+
throw e;
|
|
570
|
+
} finally {
|
|
571
|
+
raw.exec("PRAGMA foreign_keys = ON");
|
|
572
|
+
}
|
|
573
|
+
}
|