@vellumai/assistant 0.5.1 → 0.5.3
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/ARCHITECTURE.md +163 -54
- package/docs/architecture/integrations.md +62 -67
- package/docs/credential-execution-service.md +3 -3
- package/docs/skills.md +100 -0
- package/package.json +1 -1
- package/src/__tests__/agent-loop.test.ts +111 -0
- package/src/__tests__/always-loaded-tools-guard.test.ts +3 -4
- package/src/__tests__/app-builder-tool-scripts.test.ts +13 -151
- package/src/__tests__/app-dir-path-guard.test.ts +78 -0
- package/src/__tests__/app-executors.test.ts +1 -291
- package/src/__tests__/app-git-history.test.ts +4 -4
- package/src/__tests__/app-routes-csp.test.ts +1 -0
- package/src/__tests__/app-store-dir-names.test.ts +426 -0
- package/src/__tests__/attachments-store.test.ts +169 -21
- package/src/__tests__/attachments.test.ts +115 -1
- package/src/__tests__/btw-routes.test.ts +1 -0
- package/src/__tests__/canonical-guardian-store.test.ts +38 -0
- package/src/__tests__/channel-reply-delivery.test.ts +55 -0
- package/src/__tests__/checker.test.ts +54 -0
- package/src/__tests__/claude-code-skill-regression.test.ts +2 -0
- package/src/__tests__/claude-code-tool-profiles.test.ts +2 -0
- package/src/__tests__/compaction.benchmark.test.ts +2 -1
- package/src/__tests__/config-schema-cmd.test.ts +68 -21
- package/src/__tests__/config-schema.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +156 -5
- package/src/__tests__/conversation-agent-loop.test.ts +297 -2
- package/src/__tests__/conversation-attachments.test.ts +17 -19
- package/src/__tests__/conversation-disk-view-integration.test.ts +277 -0
- package/src/__tests__/conversation-disk-view.test.ts +810 -0
- package/src/__tests__/conversation-error.test.ts +1 -1
- package/src/__tests__/conversation-fork-crud.test.ts +551 -0
- package/src/__tests__/conversation-fork-route.test.ts +386 -0
- package/src/__tests__/conversation-history-web-search.test.ts +1 -1
- package/src/__tests__/conversation-key-store-disk-view.test.ts +130 -0
- package/src/__tests__/conversation-media-retry.test.ts +8 -2
- package/src/__tests__/conversation-memory-dirty-tail.test.ts +150 -0
- package/src/__tests__/conversation-provider-retry-repair.test.ts +7 -0
- package/src/__tests__/conversation-queue.test.ts +36 -1
- package/src/__tests__/conversation-routes-disk-view.test.ts +439 -0
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +2 -2
- package/src/__tests__/conversation-routes-slash-commands.test.ts +2 -7
- package/src/__tests__/conversation-runtime-assembly.test.ts +17 -2
- package/src/__tests__/conversation-skill-tools.test.ts +4 -9
- package/src/__tests__/conversation-slash-commands.test.ts +149 -0
- package/src/__tests__/conversation-store.test.ts +24 -21
- package/src/__tests__/conversation-surfaces-state-update.test.ts +246 -0
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +1 -0
- package/src/__tests__/conversation-title-service.test.ts +137 -0
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +25 -315
- package/src/__tests__/conversation-tool-setup-memory-scope.test.ts +1 -0
- package/src/__tests__/conversation-tool-setup-side-effect-flag.test.ts +1 -0
- package/src/__tests__/conversation-wipe.test.ts +226 -0
- package/src/__tests__/conversation-workspace-cache-state.test.ts +44 -2
- package/src/__tests__/conversation-workspace-injection.test.ts +11 -0
- package/src/__tests__/credential-security-invariants.test.ts +3 -0
- package/src/__tests__/credential-vault-unit.test.ts +5 -10
- package/src/__tests__/cu-unified-flow.test.ts +1 -0
- package/src/__tests__/db-conversation-fork-lineage-migration.test.ts +241 -0
- package/src/__tests__/db-llm-request-log-provider-migration.test.ts +214 -0
- package/src/__tests__/db-memory-archive-migration.test.ts +372 -0
- package/src/__tests__/db-memory-brief-state-migration.test.ts +213 -0
- package/src/__tests__/db-memory-reducer-checkpoints.test.ts +273 -0
- package/src/__tests__/diagnostics-export.test.ts +70 -1
- package/src/__tests__/first-greeting.test.ts +80 -0
- package/src/__tests__/gateway-only-guard.test.ts +1 -0
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +3 -7
- package/src/__tests__/history-repair.test.ts +32 -10
- package/src/__tests__/http-conversation-lineage.test.ts +251 -0
- package/src/__tests__/image-source-path-reinject.test.ts +136 -0
- package/src/__tests__/inline-command-runner.test.ts +311 -0
- package/src/__tests__/inline-skill-authoring-guard.test.ts +220 -0
- package/src/__tests__/inline-skill-load-permissions.test.ts +435 -0
- package/src/__tests__/list-messages-attachments.test.ts +96 -0
- package/src/__tests__/llm-context-normalization.test.ts +1116 -0
- package/src/__tests__/llm-context-route-provider.test.ts +217 -0
- package/src/__tests__/llm-request-log-turn-query.test.ts +270 -0
- package/src/__tests__/media-generate-image.test.ts +47 -94
- package/src/__tests__/memory-brief-open-loops.test.ts +530 -0
- package/src/__tests__/memory-brief-time.test.ts +285 -0
- package/src/__tests__/memory-brief-wrapper.test.ts +311 -0
- package/src/__tests__/memory-chunk-archive.test.ts +400 -0
- package/src/__tests__/memory-chunk-dual-write.test.ts +453 -0
- package/src/__tests__/memory-episode-archive.test.ts +370 -0
- package/src/__tests__/memory-episode-dual-write.test.ts +626 -0
- package/src/__tests__/memory-lifecycle-e2e.test.ts +3 -1
- package/src/__tests__/memory-observation-archive.test.ts +375 -0
- package/src/__tests__/memory-observation-dual-write.test.ts +318 -0
- package/src/__tests__/memory-recall-quality.test.ts +7 -7
- package/src/__tests__/memory-reducer-store.test.ts +728 -0
- package/src/__tests__/memory-reducer-types.test.ts +699 -0
- package/src/__tests__/memory-reducer.test.ts +698 -0
- package/src/__tests__/memory-regressions.test.ts +6 -4
- package/src/__tests__/memory-simplified-config.test.ts +281 -0
- package/src/__tests__/migration-cross-version-compatibility.test.ts +4 -1
- package/src/__tests__/migration-export-http.test.ts +3 -1
- package/src/__tests__/migration-import-commit-http.test.ts +18 -4
- package/src/__tests__/migration-import-preflight-http.test.ts +1 -3
- package/src/__tests__/mime-builder.test.ts +3 -2
- package/src/__tests__/non-member-access-request.test.ts +12 -1
- package/src/__tests__/notification-decision-identity.test.ts +52 -0
- package/src/__tests__/oauth-apps-routes.test.ts +103 -0
- package/src/__tests__/oauth-store.test.ts +115 -0
- package/src/__tests__/parse-identity-fields.test.ts +129 -0
- package/src/__tests__/provider-error-scenarios.test.ts +1 -3
- package/src/__tests__/provider-failover-actual-provider.test.ts +66 -0
- package/src/__tests__/recording-handler.test.ts +17 -0
- package/src/__tests__/registry.test.ts +3 -8
- package/src/__tests__/relay-server.test.ts +1 -1
- package/src/__tests__/runtime-attachment-metadata.test.ts +7 -3
- package/src/__tests__/schema-transforms.test.ts +165 -5
- package/src/__tests__/server-history-render.test.ts +2 -2
- package/src/__tests__/skill-load-inline-command.test.ts +598 -0
- package/src/__tests__/skill-load-inline-includes.test.ts +644 -0
- package/src/__tests__/skills-inline-command-expansions.test.ts +301 -0
- package/src/__tests__/skills-transitive-hash.test.ts +333 -0
- package/src/__tests__/slack-app-setup-skill-regression.test.ts +3 -1
- package/src/__tests__/slack-inbound-verification.test.ts +2 -2
- package/src/__tests__/starter-task-flow.test.ts +1 -0
- package/src/__tests__/suggestion-routes.test.ts +443 -0
- package/src/__tests__/swarm-conversation-integration.test.ts +1 -0
- package/src/__tests__/swarm-recursion.test.ts +1 -0
- package/src/__tests__/swarm-tool.test.ts +1 -0
- package/src/__tests__/tool-execution-abort-cleanup.test.ts +1 -0
- package/src/__tests__/tool-preview-lifecycle.test.ts +32 -5
- package/src/__tests__/top-level-renderer.test.ts +22 -0
- package/src/__tests__/turn-boundary-resolution.test.ts +243 -0
- package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +320 -0
- package/src/__tests__/web-fetch.test.ts +6 -2
- package/src/__tests__/workspace-migration-006-services-config.test.ts +335 -0
- package/src/__tests__/workspace-migration-007-web-search-provider-rename.test.ts +312 -0
- package/src/__tests__/workspace-migration-009-backfill-conversation-disk-view.test.ts +278 -0
- package/src/__tests__/workspace-migration-010-app-dir-rename.test.ts +275 -0
- package/src/__tests__/workspace-migration-012-rename-conversation-disk-view-dirs.test.ts +77 -0
- package/src/__tests__/workspace-migration-013-repair-conversation-disk-view.test.ts +401 -0
- package/src/__tests__/workspace-migration-backfill-installation-id.test.ts +328 -0
- package/src/__tests__/workspace-migration-seed-device-id.test.ts +6 -10
- package/src/agent/attachments.ts +27 -1
- package/src/agent/loop.ts +29 -1
- package/src/avatar/traits-png-sync.ts +80 -25
- package/src/bundler/app-bundler.ts +4 -4
- package/src/calls/call-domain.ts +1 -0
- package/src/calls/voice-session-bridge.ts +1 -0
- package/src/cli/commands/auth.ts +92 -0
- package/src/cli/commands/avatar.ts +7 -6
- package/src/cli/commands/config.ts +2 -0
- package/src/cli/commands/oauth/providers.ts +29 -0
- package/src/cli/program.ts +12 -0
- package/src/cli.ts +15 -48
- package/src/config/bundled-skills/app-builder/SKILL.md +103 -28
- package/src/config/bundled-skills/app-builder/TOOLS.json +5 -199
- package/src/config/bundled-skills/app-builder/tools/{app-query.ts → app-refresh.ts} +2 -2
- package/src/config/bundled-skills/contacts/tools/google-contacts.ts +2 -3
- package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +6 -9
- package/src/config/bundled-skills/gmail/tools/gmail-attachments.ts +4 -6
- package/src/config/bundled-skills/gmail/tools/gmail-draft.ts +2 -3
- package/src/config/bundled-skills/gmail/tools/gmail-filters.ts +2 -3
- package/src/config/bundled-skills/gmail/tools/gmail-follow-up.ts +2 -3
- package/src/config/bundled-skills/gmail/tools/gmail-forward.ts +2 -3
- package/src/config/bundled-skills/gmail/tools/gmail-label.ts +4 -6
- package/src/config/bundled-skills/gmail/tools/gmail-outreach-scan.ts +2 -3
- package/src/config/bundled-skills/gmail/tools/gmail-send-draft.ts +2 -3
- package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +2 -3
- package/src/config/bundled-skills/gmail/tools/gmail-trash.ts +2 -3
- package/src/config/bundled-skills/gmail/tools/gmail-unsubscribe.ts +2 -3
- package/src/config/bundled-skills/gmail/tools/gmail-vacation.ts +2 -3
- package/src/config/bundled-skills/google-calendar/tools/shared.ts +1 -1
- package/src/config/bundled-skills/image-studio/SKILL.md +2 -2
- package/src/config/bundled-skills/image-studio/TOOLS.json +2 -2
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +45 -72
- package/src/config/bundled-skills/media-processing/tools/extract-keyframes.ts +2 -2
- package/src/config/bundled-skills/messaging/tools/shared.ts +1 -1
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +19 -3
- package/src/config/bundled-skills/skill-management/SKILL.md +1 -1
- package/src/config/bundled-skills/skill-management/TOOLS.json +2 -2
- package/src/config/bundled-skills/slack/tools/shared.ts +19 -4
- package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +2 -3
- package/src/config/bundled-skills/transcribe/SKILL.md +1 -1
- package/src/config/bundled-skills/transcribe/TOOLS.json +2 -6
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +19 -83
- package/src/config/bundled-tool-registry.ts +2 -14
- package/src/config/feature-flag-registry.json +24 -0
- package/src/config/loader.ts +65 -0
- package/src/config/raw-config-utils.ts +58 -0
- package/src/config/schema-utils.ts +28 -7
- package/src/config/schema.ts +20 -0
- package/src/config/schemas/elevenlabs.ts +18 -0
- package/src/config/schemas/memory-lifecycle.ts +4 -2
- package/src/config/schemas/memory-simplified.ts +101 -0
- package/src/config/schemas/memory-storage.ts +1 -1
- package/src/config/schemas/memory.ts +4 -0
- package/src/config/schemas/services.ts +8 -6
- package/src/config/skills.ts +50 -4
- package/src/contacts/contact-store.ts +13 -6
- package/src/contacts/contacts-write.ts +0 -1
- package/src/context/window-manager.ts +13 -2
- package/src/daemon/conversation-agent-loop-handlers.ts +54 -8
- package/src/daemon/conversation-agent-loop.ts +127 -20
- package/src/daemon/conversation-attachments.ts +18 -36
- package/src/daemon/conversation-error.ts +2 -1
- package/src/daemon/conversation-history.ts +18 -4
- package/src/daemon/conversation-lifecycle.ts +50 -16
- package/src/daemon/conversation-messaging.ts +70 -26
- package/src/daemon/conversation-process.ts +58 -34
- package/src/daemon/conversation-runtime-assembly.ts +22 -38
- package/src/daemon/conversation-slash.ts +121 -256
- package/src/daemon/conversation-surfaces.ts +170 -24
- package/src/daemon/conversation-tool-setup.ts +0 -6
- package/src/daemon/conversation-workspace.ts +21 -1
- package/src/daemon/conversation.ts +69 -30
- package/src/daemon/first-greeting.ts +35 -0
- package/src/daemon/handlers/config-embeddings.ts +156 -0
- package/src/daemon/handlers/config-model.ts +62 -26
- package/src/daemon/handlers/conversations.ts +0 -23
- package/src/daemon/handlers/identity.ts +12 -1
- package/src/daemon/handlers/recording.ts +26 -21
- package/src/daemon/host-cu-proxy.ts +2 -2
- package/src/daemon/lifecycle.ts +115 -65
- package/src/daemon/message-protocol.ts +3 -0
- package/src/daemon/message-types/conversations.ts +18 -0
- package/src/daemon/message-types/messages.ts +1 -0
- package/src/daemon/message-types/shared.ts +2 -0
- package/src/daemon/message-types/surfaces.ts +2 -0
- package/src/daemon/message-types/upgrades.ts +23 -0
- package/src/daemon/server.ts +83 -12
- package/src/daemon/shutdown-handlers.ts +8 -5
- package/src/daemon/startup-error.ts +9 -0
- package/src/daemon/tool-side-effects.ts +11 -28
- package/src/events/tool-permission-telemetry-listener.ts +1 -3
- package/src/followups/followup-store.ts +47 -1
- package/src/instrument.ts +0 -4
- package/src/media/app-icon-generator.ts +2 -2
- package/src/memory/app-git-service.ts +28 -16
- package/src/memory/app-store.ts +230 -41
- package/src/memory/archive-store.ts +400 -0
- package/src/memory/attachments-store.ts +558 -130
- package/src/memory/brief-formatting.ts +33 -0
- package/src/memory/brief-open-loops.ts +266 -0
- package/src/memory/brief-time.ts +161 -0
- package/src/memory/brief.ts +75 -0
- package/src/memory/conversation-attention-store.ts +70 -0
- package/src/memory/conversation-crud.ts +591 -8
- package/src/memory/conversation-directories.ts +125 -0
- package/src/memory/conversation-disk-view.ts +390 -0
- package/src/memory/conversation-key-store.ts +17 -5
- package/src/memory/conversation-queries.ts +5 -1
- package/src/memory/conversation-title-service.ts +21 -49
- package/src/memory/db-init.ts +40 -0
- package/src/memory/embedding-backend.ts +42 -53
- package/src/memory/embedding-gemini.test.ts +4 -4
- package/src/memory/embedding-local.ts +1 -3
- package/src/memory/embedding-ollama.ts +1 -3
- package/src/memory/embedding-openai.ts +1 -3
- package/src/memory/indexer.ts +114 -21
- package/src/memory/items-extractor.ts +42 -13
- package/src/memory/job-handlers/conversation-starters.ts +6 -1
- package/src/memory/job-handlers/embedding.test.ts +2 -4
- package/src/memory/job-handlers/embedding.ts +83 -0
- package/src/memory/job-utils.ts +1 -1
- package/src/memory/jobs-store.ts +6 -0
- package/src/memory/jobs-worker.ts +12 -0
- package/src/memory/llm-request-log-store.ts +100 -1
- package/src/memory/migrations/102-alter-table-columns.ts +5 -0
- package/src/memory/migrations/146-schedule-oneshot-routing.ts +3 -3
- package/src/memory/migrations/147-migrate-reminders-to-schedules.ts +66 -70
- package/src/memory/migrations/148-drop-reminders-table.ts +5 -9
- package/src/memory/migrations/160-drop-loopback-port-column.ts +1 -3
- package/src/memory/migrations/174-rename-thread-starters-table.ts +0 -7
- package/src/memory/migrations/178-oauth-providers-managed-service-config-key.ts +15 -0
- package/src/memory/migrations/179-llm-request-log-message-id.ts +16 -0
- package/src/memory/migrations/180-backfill-inline-attachments-to-disk.ts +66 -0
- package/src/memory/migrations/181-rename-thread-starters-checkpoints.ts +46 -0
- package/src/memory/migrations/182-oauth-providers-display-metadata.ts +20 -0
- package/src/memory/migrations/183-add-conversation-fork-lineage.ts +22 -0
- package/src/memory/migrations/184-llm-request-log-provider.ts +12 -0
- package/src/memory/migrations/185-memory-brief-state.ts +52 -0
- package/src/memory/migrations/186-memory-archive.ts +109 -0
- package/src/memory/migrations/187-memory-reducer-checkpoints.ts +19 -0
- package/src/memory/migrations/index.ts +10 -0
- package/src/memory/migrations/registry.ts +13 -0
- package/src/memory/qdrant-client.ts +23 -4
- package/src/memory/reducer-store.ts +271 -0
- package/src/memory/reducer-types.ts +99 -0
- package/src/memory/reducer.ts +453 -0
- package/src/memory/retriever.test.ts +601 -2
- package/src/memory/retriever.ts +85 -9
- package/src/memory/schema/conversations.ts +9 -0
- package/src/memory/schema/index.ts +2 -0
- package/src/memory/schema/infrastructure.ts +13 -7
- package/src/memory/schema/memory-archive.ts +121 -0
- package/src/memory/schema/memory-brief.ts +55 -0
- package/src/memory/schema/oauth.ts +6 -0
- package/src/memory/search/semantic.ts +17 -4
- package/src/messaging/providers/gmail/mime-builder.ts +3 -1
- package/src/notifications/copy-composer.ts +26 -0
- package/src/notifications/decision-engine.ts +14 -1
- package/src/notifications/emit-signal.ts +1 -1
- package/src/notifications/signal.ts +36 -0
- package/src/oauth/byo-connection.test.ts +1 -45
- package/src/oauth/byo-connection.ts +2 -8
- package/src/oauth/connect-orchestrator.ts +15 -11
- package/src/oauth/connection-resolver.test.ts +191 -0
- package/src/oauth/connection-resolver.ts +66 -38
- package/src/oauth/connection.ts +0 -1
- package/src/oauth/oauth-store.ts +99 -47
- package/src/oauth/platform-connection.test.ts +0 -1
- package/src/oauth/platform-connection.ts +11 -3
- package/src/oauth/seed-providers.ts +78 -3
- package/src/oauth/token-persistence.ts +16 -10
- package/src/permissions/checker.ts +160 -14
- package/src/permissions/defaults.ts +14 -0
- package/src/prompts/templates/BOOTSTRAP.md +2 -0
- package/src/providers/anthropic/client.ts +8 -1
- package/src/providers/failover.ts +4 -1
- package/src/providers/gemini/client.ts +50 -0
- package/src/providers/model-catalog.ts +92 -0
- package/src/providers/model-intents.ts +29 -20
- package/src/providers/openai/client.ts +49 -0
- package/src/providers/types.ts +2 -0
- package/src/runtime/access-request-helper.ts +16 -7
- package/src/runtime/auth/credential-service.ts +3 -1
- package/src/runtime/auth/route-policy.ts +14 -1
- package/src/runtime/btw-sidechain.ts +101 -0
- package/src/runtime/channel-reply-delivery.ts +17 -1
- package/src/runtime/http-router.ts +3 -1
- package/src/runtime/http-server.ts +196 -141
- package/src/runtime/http-types.ts +1 -0
- package/src/runtime/migrations/vbundle-builder.ts +5 -1
- package/src/runtime/routes/access-request-decision.ts +41 -0
- package/src/runtime/routes/app-management-routes.ts +6 -3
- package/src/runtime/routes/app-routes.ts +7 -3
- package/src/runtime/routes/approval-routes.ts +1 -0
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +34 -2
- package/src/runtime/routes/attachment-routes.ts +45 -15
- package/src/runtime/routes/btw-routes.ts +21 -61
- package/src/runtime/routes/conversation-management-routes.ts +74 -0
- package/src/runtime/routes/conversation-query-routes.ts +187 -10
- package/src/runtime/routes/conversation-routes.ts +269 -28
- package/src/runtime/routes/conversation-starter-routes.ts +9 -11
- package/src/runtime/routes/diagnostics-routes.ts +1 -0
- package/src/runtime/routes/identity-routes.ts +2 -35
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +2 -2
- package/src/runtime/routes/llm-context-normalization.ts +1212 -0
- package/src/runtime/routes/log-export-routes.ts +3 -0
- package/src/runtime/routes/memory-item-routes.test.ts +34 -0
- package/src/runtime/routes/memory-item-routes.ts +94 -5
- package/src/runtime/routes/migration-routes.ts +4 -1
- package/src/runtime/routes/oauth-apps.ts +291 -0
- package/src/runtime/routes/secret-routes.ts +30 -1
- package/src/runtime/routes/settings-routes.ts +14 -0
- package/src/runtime/routes/surface-action-routes.ts +68 -1
- package/src/runtime/routes/trace-event-routes.ts +4 -1
- package/src/schedule/schedule-store.ts +30 -21
- package/src/security/secure-keys.ts +21 -0
- package/src/signals/bash.ts +1 -1
- package/src/skills/inline-command-expansions.ts +204 -0
- package/src/skills/inline-command-render.ts +127 -0
- package/src/skills/inline-command-runner.ts +242 -0
- package/src/skills/transitive-version-hash.ts +88 -0
- package/src/swarm/backend-claude-code.ts +3 -6
- package/src/tasks/task-store.ts +43 -1
- package/src/telemetry/usage-telemetry-reporter.test.ts +3 -2
- package/src/telemetry/usage-telemetry-reporter.ts +3 -1
- package/src/tools/AGENTS.md +6 -10
- package/src/tools/apps/executors.ts +17 -232
- package/src/tools/claude-code/claude-code.ts +2 -3
- package/src/tools/credentials/vault.ts +7 -12
- package/src/tools/host-filesystem/read.ts +13 -10
- package/src/tools/network/__tests__/web-search.test.ts +4 -2
- package/src/tools/permission-checker.ts +8 -1
- package/src/tools/schedule/list.ts +2 -7
- package/src/tools/schema-transforms.ts +5 -0
- package/src/tools/shared/filesystem/format-diff.ts +2 -7
- package/src/tools/skills/execute.ts +1 -1
- package/src/tools/skills/load.ts +140 -6
- package/src/tools/tool-manifest.ts +0 -6
- package/src/tools/ui-surface/definitions.ts +2 -2
- package/src/util/device-id.ts +28 -5
- package/src/util/platform.ts +24 -0
- package/src/util/pricing.ts +1 -0
- package/src/util/retry.ts +1 -3
- package/src/workspace/migrations/003-seed-device-id.ts +3 -4
- package/src/workspace/migrations/006-services-config.ts +5 -0
- package/src/workspace/migrations/008-voice-timeout-and-max-steps.ts +12 -0
- package/src/workspace/migrations/009-backfill-conversation-disk-view.ts +10 -0
- package/src/workspace/migrations/010-app-dir-rename.ts +223 -0
- package/src/workspace/migrations/{002-backfill-installation-id.ts → 011-backfill-installation-id.ts} +24 -13
- package/src/workspace/migrations/012-rename-conversation-disk-view-dirs.ts +64 -0
- package/src/workspace/migrations/013-repair-conversation-disk-view.ts +11 -0
- package/src/workspace/migrations/rebuild-conversation-disk-view.ts +186 -0
- package/src/workspace/migrations/registry.ts +11 -1
- package/src/workspace/top-level-renderer.ts +12 -0
- package/src/__tests__/asset-materialize-tool.test.ts +0 -523
- package/src/__tests__/asset-search-tool.test.ts +0 -536
- package/src/__tests__/fixtures/media-reuse-fixtures.ts +0 -56
- package/src/__tests__/media-reuse-story.e2e.test.ts +0 -762
- package/src/__tests__/media-visibility-policy.test.ts +0 -190
- package/src/config/bundled-skills/app-builder/tools/app-file-edit.ts +0 -14
- package/src/config/bundled-skills/app-builder/tools/app-file-list.ts +0 -13
- package/src/config/bundled-skills/app-builder/tools/app-file-read.ts +0 -21
- package/src/config/bundled-skills/app-builder/tools/app-file-write.ts +0 -14
- package/src/config/bundled-skills/app-builder/tools/app-list.ts +0 -13
- package/src/config/bundled-skills/app-builder/tools/app-update.ts +0 -23
- package/src/daemon/media-visibility-policy.ts +0 -59
- package/src/tools/assets/materialize.ts +0 -248
- package/src/tools/assets/search.ts +0 -400
|
@@ -11,7 +11,10 @@ import type { MemoryJob } from "../jobs-store.js";
|
|
|
11
11
|
import { extractMediaBlocks } from "../message-content.js";
|
|
12
12
|
import {
|
|
13
13
|
mediaAssets,
|
|
14
|
+
memoryChunks,
|
|
15
|
+
memoryEpisodes,
|
|
14
16
|
memoryItems,
|
|
17
|
+
memoryObservations,
|
|
15
18
|
memorySegments,
|
|
16
19
|
memorySummaries,
|
|
17
20
|
messages,
|
|
@@ -34,6 +37,7 @@ export async function embedSegmentJob(
|
|
|
34
37
|
conversation_id: segment.conversationId,
|
|
35
38
|
message_id: segment.messageId,
|
|
36
39
|
created_at: segment.createdAt,
|
|
40
|
+
memory_scope_id: segment.scopeId,
|
|
37
41
|
});
|
|
38
42
|
}
|
|
39
43
|
|
|
@@ -58,6 +62,7 @@ export async function embedItemJob(
|
|
|
58
62
|
confidence: item.confidence,
|
|
59
63
|
created_at: item.firstSeenAt,
|
|
60
64
|
last_seen_at: item.lastSeenAt,
|
|
65
|
+
memory_scope_id: item.scopeId,
|
|
61
66
|
});
|
|
62
67
|
}
|
|
63
68
|
|
|
@@ -83,10 +88,31 @@ export async function embedSummaryJob(
|
|
|
83
88
|
kind: summary.scope,
|
|
84
89
|
created_at: summary.startAt,
|
|
85
90
|
last_seen_at: summary.endAt,
|
|
91
|
+
memory_scope_id: summary.scopeId,
|
|
86
92
|
},
|
|
87
93
|
);
|
|
88
94
|
}
|
|
89
95
|
|
|
96
|
+
export async function embedChunkJob(
|
|
97
|
+
job: MemoryJob,
|
|
98
|
+
config: AssistantConfig,
|
|
99
|
+
): Promise<void> {
|
|
100
|
+
const chunkId = asString(job.payload.chunkId);
|
|
101
|
+
if (!chunkId) return;
|
|
102
|
+
const db = getDb();
|
|
103
|
+
const chunk = db
|
|
104
|
+
.select()
|
|
105
|
+
.from(memoryChunks)
|
|
106
|
+
.where(eq(memoryChunks.id, chunkId))
|
|
107
|
+
.get();
|
|
108
|
+
if (!chunk) return;
|
|
109
|
+
await embedAndUpsert(config, "chunk", chunk.id, chunk.content, {
|
|
110
|
+
observation_id: chunk.observationId,
|
|
111
|
+
created_at: chunk.createdAt,
|
|
112
|
+
memory_scope_id: chunk.scopeId,
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
|
|
90
116
|
export async function embedMediaJob(
|
|
91
117
|
job: MemoryJob,
|
|
92
118
|
config: AssistantConfig,
|
|
@@ -116,6 +142,41 @@ export async function embedMediaJob(
|
|
|
116
142
|
created_at: asset.createdAt,
|
|
117
143
|
kind: asset.mediaType,
|
|
118
144
|
subject: asset.title,
|
|
145
|
+
memory_scope_id: "default",
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export async function embedObservationJob(
|
|
150
|
+
job: MemoryJob,
|
|
151
|
+
config: AssistantConfig,
|
|
152
|
+
): Promise<void> {
|
|
153
|
+
const observationId = asString(job.payload.observationId);
|
|
154
|
+
const chunkId = asString(job.payload.chunkId);
|
|
155
|
+
if (!observationId || !chunkId) return;
|
|
156
|
+
|
|
157
|
+
const db = getDb();
|
|
158
|
+
const observation = db
|
|
159
|
+
.select()
|
|
160
|
+
.from(memoryObservations)
|
|
161
|
+
.where(eq(memoryObservations.id, observationId))
|
|
162
|
+
.get();
|
|
163
|
+
if (!observation) return;
|
|
164
|
+
|
|
165
|
+
const chunk = db
|
|
166
|
+
.select()
|
|
167
|
+
.from(memoryChunks)
|
|
168
|
+
.where(eq(memoryChunks.id, chunkId))
|
|
169
|
+
.get();
|
|
170
|
+
if (!chunk) return;
|
|
171
|
+
|
|
172
|
+
await embedAndUpsert(config, "observation", chunk.id, chunk.content, {
|
|
173
|
+
observation_id: observationId,
|
|
174
|
+
conversation_id: observation.conversationId,
|
|
175
|
+
role: observation.role,
|
|
176
|
+
modality: observation.modality,
|
|
177
|
+
source: observation.source,
|
|
178
|
+
created_at: observation.createdAt,
|
|
179
|
+
memory_scope_id: observation.scopeId,
|
|
119
180
|
});
|
|
120
181
|
}
|
|
121
182
|
|
|
@@ -155,3 +216,25 @@ export async function embedAttachmentJob(
|
|
|
155
216
|
memory_scope_id: memoryScopeId,
|
|
156
217
|
});
|
|
157
218
|
}
|
|
219
|
+
|
|
220
|
+
export async function embedEpisodeJob(
|
|
221
|
+
job: MemoryJob,
|
|
222
|
+
config: AssistantConfig,
|
|
223
|
+
): Promise<void> {
|
|
224
|
+
const episodeId = asString(job.payload.episodeId);
|
|
225
|
+
if (!episodeId) return;
|
|
226
|
+
const db = getDb();
|
|
227
|
+
const episode = db
|
|
228
|
+
.select()
|
|
229
|
+
.from(memoryEpisodes)
|
|
230
|
+
.where(eq(memoryEpisodes.id, episodeId))
|
|
231
|
+
.get();
|
|
232
|
+
if (!episode) return;
|
|
233
|
+
const text = `[episode] ${episode.title}: ${episode.summary}`;
|
|
234
|
+
await embedAndUpsert(config, "episode", episode.id, text, {
|
|
235
|
+
conversation_id: episode.conversationId,
|
|
236
|
+
created_at: episode.startAt,
|
|
237
|
+
last_seen_at: episode.endAt,
|
|
238
|
+
memory_scope_id: episode.scopeId,
|
|
239
|
+
});
|
|
240
|
+
}
|
package/src/memory/job-utils.ts
CHANGED
|
@@ -142,7 +142,7 @@ export function truncate(text: string, max: number): string {
|
|
|
142
142
|
|
|
143
143
|
export async function embedAndUpsert(
|
|
144
144
|
config: AssistantConfig,
|
|
145
|
-
targetType: "segment" | "item" | "summary" | "media",
|
|
145
|
+
targetType: "segment" | "item" | "summary" | "observation" | "chunk" | "episode" | "media",
|
|
146
146
|
targetId: string,
|
|
147
147
|
input: EmbeddingInput,
|
|
148
148
|
extraPayload?: Record<string, unknown>,
|
package/src/memory/jobs-store.ts
CHANGED
|
@@ -12,6 +12,9 @@ export type MemoryJobType =
|
|
|
12
12
|
| "embed_segment"
|
|
13
13
|
| "embed_item"
|
|
14
14
|
| "embed_summary"
|
|
15
|
+
| "embed_chunk"
|
|
16
|
+
| "embed_episode"
|
|
17
|
+
| "embed_observation"
|
|
15
18
|
| "extract_items"
|
|
16
19
|
| "extract_entities"
|
|
17
20
|
| "cleanup_stale_superseded_items"
|
|
@@ -34,6 +37,9 @@ const EMBED_JOB_TYPES: MemoryJobType[] = [
|
|
|
34
37
|
"embed_segment",
|
|
35
38
|
"embed_item",
|
|
36
39
|
"embed_summary",
|
|
40
|
+
"embed_chunk",
|
|
41
|
+
"embed_episode",
|
|
42
|
+
"embed_observation",
|
|
37
43
|
"embed_media",
|
|
38
44
|
"embed_attachment",
|
|
39
45
|
];
|
|
@@ -11,8 +11,11 @@ import { generateConversationStartersJob } from "./job-handlers/conversation-sta
|
|
|
11
11
|
// ── Per-job-type handlers ──────────────────────────────────────────
|
|
12
12
|
import {
|
|
13
13
|
embedAttachmentJob,
|
|
14
|
+
embedChunkJob,
|
|
15
|
+
embedEpisodeJob,
|
|
14
16
|
embedItemJob,
|
|
15
17
|
embedMediaJob,
|
|
18
|
+
embedObservationJob,
|
|
16
19
|
embedSegmentJob,
|
|
17
20
|
embedSummaryJob,
|
|
18
21
|
} from "./job-handlers/embedding.js";
|
|
@@ -267,6 +270,15 @@ async function processJob(
|
|
|
267
270
|
case "embed_summary":
|
|
268
271
|
await embedSummaryJob(job, config);
|
|
269
272
|
return;
|
|
273
|
+
case "embed_chunk":
|
|
274
|
+
await embedChunkJob(job, config);
|
|
275
|
+
return;
|
|
276
|
+
case "embed_episode":
|
|
277
|
+
await embedEpisodeJob(job, config);
|
|
278
|
+
return;
|
|
279
|
+
case "embed_observation":
|
|
280
|
+
await embedObservationJob(job, config);
|
|
281
|
+
return;
|
|
270
282
|
case "extract_items":
|
|
271
283
|
await extractItemsJob(job);
|
|
272
284
|
return;
|
|
@@ -1,6 +1,11 @@
|
|
|
1
|
-
import { and, eq, gte, lte } from "drizzle-orm";
|
|
1
|
+
import { and, eq, gte, inArray, isNull, lte } from "drizzle-orm";
|
|
2
2
|
import { v4 as uuid } from "uuid";
|
|
3
3
|
|
|
4
|
+
import {
|
|
5
|
+
getAssistantMessageIdsInTurn,
|
|
6
|
+
getMessageById,
|
|
7
|
+
messageMetadataSchema,
|
|
8
|
+
} from "./conversation-crud.js";
|
|
4
9
|
import { getDb } from "./db.js";
|
|
5
10
|
import { llmRequestLogs } from "./schema.js";
|
|
6
11
|
|
|
@@ -8,12 +13,16 @@ export function recordRequestLog(
|
|
|
8
13
|
conversationId: string,
|
|
9
14
|
requestPayload: string,
|
|
10
15
|
responsePayload: string,
|
|
16
|
+
messageId?: string,
|
|
17
|
+
provider?: string,
|
|
11
18
|
): void {
|
|
12
19
|
const db = getDb();
|
|
13
20
|
db.insert(llmRequestLogs)
|
|
14
21
|
.values({
|
|
15
22
|
id: uuid(),
|
|
16
23
|
conversationId,
|
|
24
|
+
messageId: messageId ?? null,
|
|
25
|
+
provider: provider ?? null,
|
|
17
26
|
requestPayload,
|
|
18
27
|
responsePayload,
|
|
19
28
|
createdAt: Date.now(),
|
|
@@ -46,3 +55,93 @@ export function queryRequestLogs(
|
|
|
46
55
|
.orderBy(llmRequestLogs.createdAt)
|
|
47
56
|
.all();
|
|
48
57
|
}
|
|
58
|
+
|
|
59
|
+
export function backfillMessageIdOnLogs(
|
|
60
|
+
conversationId: string,
|
|
61
|
+
messageId: string,
|
|
62
|
+
): void {
|
|
63
|
+
const db = getDb();
|
|
64
|
+
db.update(llmRequestLogs)
|
|
65
|
+
.set({ messageId })
|
|
66
|
+
.where(
|
|
67
|
+
and(
|
|
68
|
+
eq(llmRequestLogs.conversationId, conversationId),
|
|
69
|
+
isNull(llmRequestLogs.messageId),
|
|
70
|
+
),
|
|
71
|
+
)
|
|
72
|
+
.run();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Internal helper: query `llm_request_logs` for rows matching any of the
|
|
77
|
+
* given message IDs, ordered by `createdAt ASC`. Uses the existing
|
|
78
|
+
* `idx_llm_request_logs_message_id` index via `inArray`.
|
|
79
|
+
*/
|
|
80
|
+
function selectLogsByMessageIds(messageIds: string[]): Array<{
|
|
81
|
+
id: string;
|
|
82
|
+
conversationId: string;
|
|
83
|
+
messageId: string | null;
|
|
84
|
+
provider: string | null;
|
|
85
|
+
requestPayload: string;
|
|
86
|
+
responsePayload: string;
|
|
87
|
+
createdAt: number;
|
|
88
|
+
}> {
|
|
89
|
+
if (messageIds.length === 0) return [];
|
|
90
|
+
const db = getDb();
|
|
91
|
+
return db
|
|
92
|
+
.select({
|
|
93
|
+
id: llmRequestLogs.id,
|
|
94
|
+
conversationId: llmRequestLogs.conversationId,
|
|
95
|
+
messageId: llmRequestLogs.messageId,
|
|
96
|
+
provider: llmRequestLogs.provider,
|
|
97
|
+
requestPayload: llmRequestLogs.requestPayload,
|
|
98
|
+
responsePayload: llmRequestLogs.responsePayload,
|
|
99
|
+
createdAt: llmRequestLogs.createdAt,
|
|
100
|
+
})
|
|
101
|
+
.from(llmRequestLogs)
|
|
102
|
+
.where(inArray(llmRequestLogs.messageId, messageIds))
|
|
103
|
+
.orderBy(llmRequestLogs.createdAt)
|
|
104
|
+
.all();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function getRequestLogsByMessageId(messageId: string): Array<{
|
|
108
|
+
id: string;
|
|
109
|
+
conversationId: string;
|
|
110
|
+
messageId: string | null;
|
|
111
|
+
provider: string | null;
|
|
112
|
+
requestPayload: string;
|
|
113
|
+
responsePayload: string;
|
|
114
|
+
createdAt: number;
|
|
115
|
+
}> {
|
|
116
|
+
// Resolve all assistant message IDs in the same turn so the inspector
|
|
117
|
+
// shows every LLM call from the entire agent turn, not just the queried message.
|
|
118
|
+
const turnMessageIds = getAssistantMessageIdsInTurn(messageId);
|
|
119
|
+
const turnLogs = selectLogsByMessageIds(turnMessageIds);
|
|
120
|
+
if (turnLogs.length > 0) {
|
|
121
|
+
return turnLogs;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Fork-source fallback: if no logs found for the turn, check whether
|
|
125
|
+
// the queried message was forked from a source and resolve that source's turn.
|
|
126
|
+
const message = getMessageById(messageId);
|
|
127
|
+
if (!message?.metadata) {
|
|
128
|
+
return [];
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
try {
|
|
132
|
+
const parsed = messageMetadataSchema.safeParse(
|
|
133
|
+
JSON.parse(message.metadata),
|
|
134
|
+
);
|
|
135
|
+
const sourceMessageId =
|
|
136
|
+
parsed.success && typeof parsed.data.forkSourceMessageId === "string"
|
|
137
|
+
? parsed.data.forkSourceMessageId
|
|
138
|
+
: null;
|
|
139
|
+
if (!sourceMessageId || sourceMessageId === messageId) {
|
|
140
|
+
return [];
|
|
141
|
+
}
|
|
142
|
+
const sourceTurnIds = getAssistantMessageIdsInTurn(sourceMessageId);
|
|
143
|
+
return selectLogsByMessageIds(sourceTurnIds);
|
|
144
|
+
} catch {
|
|
145
|
+
return [];
|
|
146
|
+
}
|
|
147
|
+
}
|
|
@@ -261,6 +261,11 @@ export function addCoreColumns(database: DrizzleDb): void {
|
|
|
261
261
|
} catch {
|
|
262
262
|
/* already exists */
|
|
263
263
|
}
|
|
264
|
+
try {
|
|
265
|
+
database.run(/*sql*/ `ALTER TABLE attachments ADD COLUMN source_path TEXT`);
|
|
266
|
+
} catch {
|
|
267
|
+
/* already exists */
|
|
268
|
+
}
|
|
264
269
|
|
|
265
270
|
// cron_jobs
|
|
266
271
|
try {
|
|
@@ -15,9 +15,9 @@ export function migrateScheduleOneShotRouting(database: DrizzleDb): void {
|
|
|
15
15
|
const raw = getSqliteFrom(database);
|
|
16
16
|
|
|
17
17
|
// Check if migration is already done by inspecting whether the status column exists
|
|
18
|
-
const tableInfo = raw
|
|
19
|
-
|
|
20
|
-
|
|
18
|
+
const tableInfo = raw.query("PRAGMA table_info(cron_jobs)").all() as Array<{
|
|
19
|
+
name: string;
|
|
20
|
+
}>;
|
|
21
21
|
const hasStatusColumn = tableInfo.some((col) => col.name === "status");
|
|
22
22
|
if (hasStatusColumn) {
|
|
23
23
|
// Ensure all indexes exist even if the column migration already ran
|
|
@@ -30,40 +30,37 @@ import { withCrashRecovery } from "./validate-migration-state.js";
|
|
|
30
30
|
* preserved for the subsequent cleanup PR.
|
|
31
31
|
*/
|
|
32
32
|
export function migrateRemindersToSchedules(database: DrizzleDb): void {
|
|
33
|
-
withCrashRecovery(
|
|
34
|
-
database
|
|
35
|
-
"migration_reminders_to_schedules_v1",
|
|
36
|
-
() => {
|
|
37
|
-
const raw = getSqliteFrom(database);
|
|
33
|
+
withCrashRecovery(database, "migration_reminders_to_schedules_v1", () => {
|
|
34
|
+
const raw = getSqliteFrom(database);
|
|
38
35
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
36
|
+
// Guard: if the reminders table doesn't exist, nothing to migrate.
|
|
37
|
+
const hasReminders = raw
|
|
38
|
+
.query(
|
|
39
|
+
"SELECT name FROM sqlite_master WHERE type='table' AND name='reminders'",
|
|
40
|
+
)
|
|
41
|
+
.get();
|
|
42
|
+
if (!hasReminders) return;
|
|
46
43
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
44
|
+
// Read all reminders into memory. We use the reminder's original ID as
|
|
45
|
+
// the cron_jobs primary key so that INSERT OR IGNORE deduplicates
|
|
46
|
+
// correctly if the migration re-runs after a crash.
|
|
47
|
+
const reminders = raw.query("SELECT * FROM reminders").all() as Array<{
|
|
48
|
+
id: string;
|
|
49
|
+
label: string;
|
|
50
|
+
message: string;
|
|
51
|
+
fire_at: number;
|
|
52
|
+
mode: string;
|
|
53
|
+
status: string;
|
|
54
|
+
fired_at: number | null;
|
|
55
|
+
routing_intent: string;
|
|
56
|
+
routing_hints_json: string;
|
|
57
|
+
created_at: number;
|
|
58
|
+
updated_at: number;
|
|
59
|
+
}>;
|
|
63
60
|
|
|
64
|
-
|
|
61
|
+
if (reminders.length === 0) return;
|
|
65
62
|
|
|
66
|
-
|
|
63
|
+
const insert = raw.query(/*sql*/ `
|
|
67
64
|
INSERT OR IGNORE INTO cron_jobs (
|
|
68
65
|
id, name, enabled, cron_expression, schedule_syntax, timezone,
|
|
69
66
|
message, next_run_at, last_run_at, last_status, retry_count,
|
|
@@ -77,53 +74,52 @@ export function migrateRemindersToSchedules(database: DrizzleDb): void {
|
|
|
77
74
|
)
|
|
78
75
|
`);
|
|
79
76
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
77
|
+
// Mark migrated pending reminders as fired so the legacy
|
|
78
|
+
// claimDueReminders path doesn't fire them a second time.
|
|
79
|
+
const markFired = raw.query(/*sql*/ `
|
|
83
80
|
UPDATE reminders SET status = 'fired', fired_at = ?
|
|
84
81
|
WHERE id = ? AND status = 'pending'
|
|
85
82
|
`);
|
|
86
83
|
|
|
87
|
-
|
|
88
|
-
|
|
84
|
+
try {
|
|
85
|
+
raw.exec("BEGIN");
|
|
89
86
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
87
|
+
for (const r of reminders) {
|
|
88
|
+
const statusMap: Record<string, string> = {
|
|
89
|
+
pending: "active",
|
|
90
|
+
firing: "firing",
|
|
91
|
+
fired: "fired",
|
|
92
|
+
cancelled: "cancelled",
|
|
93
|
+
};
|
|
97
94
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
95
|
+
insert.run(
|
|
96
|
+
r.id,
|
|
97
|
+
r.label,
|
|
98
|
+
r.status === "pending" ? 1 : 0,
|
|
99
|
+
// message, next_run_at, last_run_at, last_status
|
|
100
|
+
r.message,
|
|
101
|
+
r.fire_at,
|
|
102
|
+
r.fired_at,
|
|
103
|
+
r.status === "fired" ? "ok" : null,
|
|
104
|
+
// mode, routing_intent, routing_hints_json, status
|
|
105
|
+
r.mode,
|
|
106
|
+
r.routing_intent,
|
|
107
|
+
r.routing_hints_json,
|
|
108
|
+
statusMap[r.status] ?? "active",
|
|
109
|
+
// created_at, updated_at
|
|
110
|
+
r.created_at,
|
|
111
|
+
r.updated_at,
|
|
112
|
+
);
|
|
116
113
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
}
|
|
114
|
+
if (r.status === "pending") {
|
|
115
|
+
markFired.run(Date.now(), r.id);
|
|
120
116
|
}
|
|
121
|
-
|
|
122
|
-
raw.exec("COMMIT");
|
|
123
|
-
} catch (err) {
|
|
124
|
-
raw.exec("ROLLBACK");
|
|
125
|
-
throw err;
|
|
126
117
|
}
|
|
127
|
-
|
|
128
|
-
|
|
118
|
+
|
|
119
|
+
raw.exec("COMMIT");
|
|
120
|
+
} catch (err) {
|
|
121
|
+
raw.exec("ROLLBACK");
|
|
122
|
+
throw err;
|
|
123
|
+
}
|
|
124
|
+
});
|
|
129
125
|
}
|
|
@@ -6,13 +6,9 @@ import { withCrashRecovery } from "./validate-migration-state.js";
|
|
|
6
6
|
* migrated into cron_jobs as one-shot schedules (migration 147).
|
|
7
7
|
*/
|
|
8
8
|
export function migrateDropRemindersTable(database: DrizzleDb): void {
|
|
9
|
-
withCrashRecovery(
|
|
10
|
-
database
|
|
11
|
-
"
|
|
12
|
-
(
|
|
13
|
-
|
|
14
|
-
raw.run("DROP INDEX IF EXISTS idx_reminders_status_fire_at");
|
|
15
|
-
raw.run("DROP TABLE IF EXISTS reminders");
|
|
16
|
-
},
|
|
17
|
-
);
|
|
9
|
+
withCrashRecovery(database, "migration_drop_reminders_table_v1", () => {
|
|
10
|
+
const raw = getSqliteFrom(database);
|
|
11
|
+
raw.run("DROP INDEX IF EXISTS idx_reminders_status_fire_at");
|
|
12
|
+
raw.run("DROP TABLE IF EXISTS reminders");
|
|
13
|
+
});
|
|
18
14
|
}
|
|
@@ -4,9 +4,7 @@ import { getSqliteFrom } from "../db-connection.js";
|
|
|
4
4
|
export function migrateDropLoopbackPortColumn(database: DrizzleDb): void {
|
|
5
5
|
const raw = getSqliteFrom(database);
|
|
6
6
|
try {
|
|
7
|
-
raw.exec(
|
|
8
|
-
/*sql*/ `ALTER TABLE oauth_providers DROP COLUMN loopback_port`,
|
|
9
|
-
);
|
|
7
|
+
raw.exec(/*sql*/ `ALTER TABLE oauth_providers DROP COLUMN loopback_port`);
|
|
10
8
|
} catch {
|
|
11
9
|
// Column already dropped or doesn't exist — nothing to do.
|
|
12
10
|
}
|
|
@@ -40,13 +40,6 @@ export function migrateRenameThreadStartersTable(database: DrizzleDb): void {
|
|
|
40
40
|
raw.exec(
|
|
41
41
|
/*sql*/ `CREATE INDEX IF NOT EXISTS idx_conversation_starters_card_type ON conversation_starters(card_type, scope_id)`,
|
|
42
42
|
);
|
|
43
|
-
|
|
44
|
-
// Migrate checkpoint keys from old thread_starters: prefix to
|
|
45
|
-
// conversation_starters: so existing checkpoint data is found by
|
|
46
|
-
// the renamed code paths and unnecessary re-generation is avoided.
|
|
47
|
-
raw.exec(
|
|
48
|
-
/*sql*/ `UPDATE memory_checkpoints SET key = replace(key, 'thread_starters:', 'conversation_starters:') WHERE key LIKE 'thread_starters:%'`,
|
|
49
|
-
);
|
|
50
43
|
},
|
|
51
44
|
);
|
|
52
45
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { DrizzleDb } from "../db-connection.js";
|
|
2
|
+
import { getSqliteFrom } from "../db-connection.js";
|
|
3
|
+
|
|
4
|
+
export function migrateOAuthProvidersManagedServiceConfigKey(
|
|
5
|
+
database: DrizzleDb,
|
|
6
|
+
): void {
|
|
7
|
+
const raw = getSqliteFrom(database);
|
|
8
|
+
try {
|
|
9
|
+
raw.exec(
|
|
10
|
+
/*sql*/ `ALTER TABLE oauth_providers ADD COLUMN managed_service_config_key TEXT`,
|
|
11
|
+
);
|
|
12
|
+
} catch {
|
|
13
|
+
// Column already exists — nothing to do.
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { DrizzleDb } from "../db-connection.js";
|
|
2
|
+
import { getSqliteFrom } from "../db-connection.js";
|
|
3
|
+
|
|
4
|
+
export function migrateLlmRequestLogMessageId(database: DrizzleDb): void {
|
|
5
|
+
const raw = getSqliteFrom(database);
|
|
6
|
+
try {
|
|
7
|
+
raw.exec(/*sql*/ `ALTER TABLE llm_request_logs ADD COLUMN message_id TEXT`);
|
|
8
|
+
} catch {
|
|
9
|
+
// Column already exists — nothing to do.
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
raw.exec(/*sql*/ `
|
|
13
|
+
CREATE INDEX IF NOT EXISTS idx_llm_request_logs_message_id
|
|
14
|
+
ON llm_request_logs(message_id)
|
|
15
|
+
`);
|
|
16
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { writeAttachmentToDisk } from "../attachments-store.js";
|
|
2
|
+
import type { DrizzleDb } from "../db-connection.js";
|
|
3
|
+
import { getSqliteFrom } from "../db-connection.js";
|
|
4
|
+
import { withCrashRecovery } from "./validate-migration-state.js";
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Backfill existing inline (base64-in-DB) attachments to disk.
|
|
8
|
+
*
|
|
9
|
+
* Finds attachment rows that have non-empty data_base64 but no file_path,
|
|
10
|
+
* writes each one to disk, and updates the row to store the file path
|
|
11
|
+
* while clearing the inline data.
|
|
12
|
+
*
|
|
13
|
+
* Processes in batches of 50 to avoid holding large amounts of base64 data
|
|
14
|
+
* in memory at once.
|
|
15
|
+
*/
|
|
16
|
+
export function migrateBackfillInlineAttachmentsToDisk(
|
|
17
|
+
database: DrizzleDb,
|
|
18
|
+
): void {
|
|
19
|
+
withCrashRecovery(
|
|
20
|
+
database,
|
|
21
|
+
"migration_backfill_inline_attachments_v1",
|
|
22
|
+
() => {
|
|
23
|
+
const raw = getSqliteFrom(database);
|
|
24
|
+
const BATCH_SIZE = 50;
|
|
25
|
+
let totalMigrated = 0;
|
|
26
|
+
|
|
27
|
+
for (;;) {
|
|
28
|
+
const rows = raw
|
|
29
|
+
.query(
|
|
30
|
+
`SELECT id, original_filename, data_base64 FROM attachments
|
|
31
|
+
WHERE (file_path IS NULL OR file_path = '')
|
|
32
|
+
AND data_base64 != ''
|
|
33
|
+
AND length(data_base64) > 0
|
|
34
|
+
LIMIT ?`,
|
|
35
|
+
)
|
|
36
|
+
.all(BATCH_SIZE) as Array<{
|
|
37
|
+
id: string;
|
|
38
|
+
original_filename: string;
|
|
39
|
+
data_base64: string;
|
|
40
|
+
}>;
|
|
41
|
+
|
|
42
|
+
if (rows.length === 0) break;
|
|
43
|
+
|
|
44
|
+
for (const row of rows) {
|
|
45
|
+
const filePath = writeAttachmentToDisk(
|
|
46
|
+
row.data_base64,
|
|
47
|
+
row.original_filename,
|
|
48
|
+
);
|
|
49
|
+
raw
|
|
50
|
+
.query(
|
|
51
|
+
`UPDATE attachments SET file_path = ?, data_base64 = '' WHERE id = ?`,
|
|
52
|
+
)
|
|
53
|
+
.run(filePath, row.id);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
totalMigrated += rows.length;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (totalMigrated > 0) {
|
|
60
|
+
// Log is intentionally not imported to keep migration self-contained;
|
|
61
|
+
// the checkpoint value records completion.
|
|
62
|
+
console.log(`Migrated ${totalMigrated} inline attachments to disk`);
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
);
|
|
66
|
+
}
|