@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
package/src/workspace/migrations/{002-backfill-installation-id.ts → 011-backfill-installation-id.ts}
RENAMED
|
@@ -11,13 +11,13 @@ import { getExternalAssistantId } from "../../runtime/auth/external-assistant-id
|
|
|
11
11
|
import type { WorkspaceMigration } from "./types.js";
|
|
12
12
|
|
|
13
13
|
export const backfillInstallationIdMigration: WorkspaceMigration = {
|
|
14
|
-
id: "
|
|
14
|
+
id: "011-backfill-installation-id",
|
|
15
15
|
description:
|
|
16
16
|
"Backfill installationId into lockfile from SQLite checkpoint and clean up stale row",
|
|
17
17
|
run(_workspaceDir: string): void {
|
|
18
18
|
// a. Read existing installation ID from SQLite, or generate a new one.
|
|
19
|
-
// On fresh installs the memory_checkpoints table may not exist yet
|
|
20
|
-
//
|
|
19
|
+
// On fresh installs the memory_checkpoints table may not exist yet,
|
|
20
|
+
// so treat errors as null.
|
|
21
21
|
let existingId: string | null = null;
|
|
22
22
|
try {
|
|
23
23
|
existingId = getMemoryCheckpoint("telemetry:installation_id");
|
|
@@ -26,19 +26,30 @@ export const backfillInstallationIdMigration: WorkspaceMigration = {
|
|
|
26
26
|
}
|
|
27
27
|
const installationId = existingId || randomUUID();
|
|
28
28
|
|
|
29
|
-
// b. Read the lockfile
|
|
29
|
+
// b. Read the lockfile — check both the current and legacy lockfile paths
|
|
30
|
+
// to support installs that haven't migrated the filename yet.
|
|
30
31
|
const base = process.env.BASE_DATA_DIR?.trim() || homedir();
|
|
31
|
-
const
|
|
32
|
-
|
|
32
|
+
const lockCandidates = [
|
|
33
|
+
join(base, ".vellum.lock.json"),
|
|
34
|
+
join(base, ".vellum.lockfile.json"),
|
|
35
|
+
];
|
|
33
36
|
|
|
34
|
-
let
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
if (!
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
37
|
+
let lockPath: string | undefined;
|
|
38
|
+
let lockData: Record<string, unknown> | undefined;
|
|
39
|
+
for (const candidate of lockCandidates) {
|
|
40
|
+
if (!existsSync(candidate)) continue;
|
|
41
|
+
try {
|
|
42
|
+
const raw = JSON.parse(readFileSync(candidate, "utf-8"));
|
|
43
|
+
if (raw && typeof raw === "object" && !Array.isArray(raw)) {
|
|
44
|
+
lockPath = candidate;
|
|
45
|
+
lockData = raw as Record<string, unknown>;
|
|
46
|
+
break;
|
|
47
|
+
}
|
|
48
|
+
} catch {
|
|
49
|
+
// Malformed — try next candidate.
|
|
50
|
+
}
|
|
41
51
|
}
|
|
52
|
+
if (!lockPath || !lockData) return;
|
|
42
53
|
|
|
43
54
|
// c. Find the assistant entry that corresponds to this daemon instance
|
|
44
55
|
const assistants = lockData.assistants as
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workspace migration 012: Rename legacy conversation disk-view directories
|
|
3
|
+
* from `{conversationId}_{timestamp}` to `{timestamp}_{conversationId}`.
|
|
4
|
+
*
|
|
5
|
+
* Idempotent and conservative:
|
|
6
|
+
* - skips directories that already use the new format
|
|
7
|
+
* - skips non-matching directories
|
|
8
|
+
* - leaves an existing target directory alone rather than clobbering it
|
|
9
|
+
* - continues past per-directory rename failures
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import { existsSync, readdirSync, renameSync } from "node:fs";
|
|
13
|
+
import { join } from "node:path";
|
|
14
|
+
|
|
15
|
+
import type { WorkspaceMigration } from "./types.js";
|
|
16
|
+
|
|
17
|
+
const LEGACY_CONVERSATION_DIR_PATTERN =
|
|
18
|
+
/^(.*)_(\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}\.\d{3}Z)$/;
|
|
19
|
+
|
|
20
|
+
function parseLegacyConversationDirName(
|
|
21
|
+
dirName: string,
|
|
22
|
+
): { conversationId: string; timestamp: string } | null {
|
|
23
|
+
const match = dirName.match(LEGACY_CONVERSATION_DIR_PATTERN);
|
|
24
|
+
if (!match) return null;
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
conversationId: match[1],
|
|
28
|
+
timestamp: match[2],
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export const renameConversationDiskViewDirsMigration: WorkspaceMigration = {
|
|
33
|
+
id: "012-rename-conversation-disk-view-dirs",
|
|
34
|
+
description:
|
|
35
|
+
"Rename legacy conversation disk-view directories to timestamp-first names",
|
|
36
|
+
|
|
37
|
+
run(workspaceDir: string): void {
|
|
38
|
+
const conversationsDir = join(workspaceDir, "conversations");
|
|
39
|
+
if (!existsSync(conversationsDir)) return;
|
|
40
|
+
|
|
41
|
+
const entries = readdirSync(conversationsDir, { withFileTypes: true })
|
|
42
|
+
.filter((entry) => entry.isDirectory())
|
|
43
|
+
.map((entry) => entry.name)
|
|
44
|
+
.sort();
|
|
45
|
+
|
|
46
|
+
for (const dirName of entries) {
|
|
47
|
+
const parsed = parseLegacyConversationDirName(dirName);
|
|
48
|
+
if (!parsed) continue;
|
|
49
|
+
|
|
50
|
+
const sourcePath = join(conversationsDir, dirName);
|
|
51
|
+
const targetName = `${parsed.timestamp}_${parsed.conversationId}`;
|
|
52
|
+
const targetPath = join(conversationsDir, targetName);
|
|
53
|
+
|
|
54
|
+
if (sourcePath === targetPath) continue;
|
|
55
|
+
if (existsSync(targetPath)) continue;
|
|
56
|
+
|
|
57
|
+
try {
|
|
58
|
+
renameSync(sourcePath, targetPath);
|
|
59
|
+
} catch {
|
|
60
|
+
// Best-effort: leave the old directory in place if a single rename fails.
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
},
|
|
64
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { rebuildConversationDiskViewFromDb } from "./rebuild-conversation-disk-view.js";
|
|
2
|
+
import type { WorkspaceMigration } from "./types.js";
|
|
3
|
+
|
|
4
|
+
export const repairConversationDiskViewMigration: WorkspaceMigration = {
|
|
5
|
+
id: "013-repair-conversation-disk-view",
|
|
6
|
+
description:
|
|
7
|
+
"Repair missing conversation disk-view folders skipped by the conversationKey creation path",
|
|
8
|
+
run(_workspaceDir: string): void {
|
|
9
|
+
rebuildConversationDiskViewFromDb();
|
|
10
|
+
},
|
|
11
|
+
};
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import {
|
|
2
|
+
existsSync,
|
|
3
|
+
mkdirSync,
|
|
4
|
+
readdirSync,
|
|
5
|
+
readFileSync,
|
|
6
|
+
rmSync,
|
|
7
|
+
writeFileSync,
|
|
8
|
+
} from "node:fs";
|
|
9
|
+
import { join } from "node:path";
|
|
10
|
+
|
|
11
|
+
import { asc, eq } from "drizzle-orm";
|
|
12
|
+
|
|
13
|
+
import { resolveConversationDirectoryPaths } from "../../memory/conversation-directories.js";
|
|
14
|
+
import {
|
|
15
|
+
initConversationDir,
|
|
16
|
+
syncMessageToDisk,
|
|
17
|
+
updateMetaFile,
|
|
18
|
+
} from "../../memory/conversation-disk-view.js";
|
|
19
|
+
import { getDb } from "../../memory/db.js";
|
|
20
|
+
import { conversations, messages } from "../../memory/schema.js";
|
|
21
|
+
import { getLogger } from "../../util/logger.js";
|
|
22
|
+
|
|
23
|
+
const log = getLogger("workspace-migrations");
|
|
24
|
+
|
|
25
|
+
function hasExpectedDiskViewArtifacts(
|
|
26
|
+
conv: { updatedAt: number },
|
|
27
|
+
dirPath: string,
|
|
28
|
+
): boolean {
|
|
29
|
+
const metaPath = join(dirPath, "meta.json");
|
|
30
|
+
const messagesPath = join(dirPath, "messages.jsonl");
|
|
31
|
+
const attachDir = join(dirPath, "attachments");
|
|
32
|
+
if (
|
|
33
|
+
!existsSync(metaPath) ||
|
|
34
|
+
!existsSync(messagesPath) ||
|
|
35
|
+
!existsSync(attachDir)
|
|
36
|
+
)
|
|
37
|
+
return false;
|
|
38
|
+
|
|
39
|
+
try {
|
|
40
|
+
const existing = JSON.parse(readFileSync(metaPath, "utf-8"));
|
|
41
|
+
const expectedUpdatedAt = new Date(conv.updatedAt).toISOString();
|
|
42
|
+
return existing.updatedAt === expectedUpdatedAt;
|
|
43
|
+
} catch {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function convergeDualConversationDirsToCanonical(
|
|
49
|
+
conv: { updatedAt: number },
|
|
50
|
+
canonicalDirPath: string,
|
|
51
|
+
legacyDirPath: string,
|
|
52
|
+
): void {
|
|
53
|
+
if (!existsSync(canonicalDirPath) || !existsSync(legacyDirPath)) return;
|
|
54
|
+
if (!hasExpectedDiskViewArtifacts(conv, canonicalDirPath)) return;
|
|
55
|
+
rmSync(legacyDirPath, { recursive: true, force: true });
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function getProjectedAttachmentFilenames(messagesPath: string): Set<string> {
|
|
59
|
+
const filenames = new Set<string>();
|
|
60
|
+
if (!existsSync(messagesPath)) return filenames;
|
|
61
|
+
|
|
62
|
+
const raw = readFileSync(messagesPath, "utf-8");
|
|
63
|
+
for (const line of raw.split("\n")) {
|
|
64
|
+
if (!line.trim()) continue;
|
|
65
|
+
try {
|
|
66
|
+
const parsed = JSON.parse(line) as { attachments?: unknown };
|
|
67
|
+
if (!Array.isArray(parsed.attachments)) continue;
|
|
68
|
+
for (const attachment of parsed.attachments) {
|
|
69
|
+
if (typeof attachment === "string") {
|
|
70
|
+
filenames.add(attachment);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
} catch {
|
|
74
|
+
// Ignore malformed lines. A later replay will rewrite them.
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return filenames;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function pruneUnreferencedProjectedAttachments(
|
|
82
|
+
attachDir: string,
|
|
83
|
+
messagesPath: string,
|
|
84
|
+
): void {
|
|
85
|
+
if (!existsSync(attachDir)) return;
|
|
86
|
+
|
|
87
|
+
const referenced = getProjectedAttachmentFilenames(messagesPath);
|
|
88
|
+
for (const entry of readdirSync(attachDir)) {
|
|
89
|
+
if (referenced.has(entry)) continue;
|
|
90
|
+
rmSync(join(attachDir, entry), { recursive: true, force: true });
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Rebuild the conversation disk view for all persisted conversations.
|
|
96
|
+
*
|
|
97
|
+
* Conversations are processed by ascending createdAt so replay ordering is
|
|
98
|
+
* stable and deterministic across runs.
|
|
99
|
+
*/
|
|
100
|
+
export function rebuildConversationDiskViewFromDb(): void {
|
|
101
|
+
const db = getDb();
|
|
102
|
+
|
|
103
|
+
const allConversations = db
|
|
104
|
+
.select()
|
|
105
|
+
.from(conversations)
|
|
106
|
+
.orderBy(asc(conversations.createdAt))
|
|
107
|
+
.all();
|
|
108
|
+
|
|
109
|
+
const total = allConversations.length;
|
|
110
|
+
let processed = 0;
|
|
111
|
+
|
|
112
|
+
for (const conv of allConversations) {
|
|
113
|
+
const {
|
|
114
|
+
canonicalDirPath,
|
|
115
|
+
legacyDirPath,
|
|
116
|
+
resolvedDirPath: dirPath,
|
|
117
|
+
} = resolveConversationDirectoryPaths(conv.id, conv.createdAt);
|
|
118
|
+
const metaPath = join(dirPath, "meta.json");
|
|
119
|
+
const messagesPath = join(dirPath, "messages.jsonl");
|
|
120
|
+
const attachDir = join(dirPath, "attachments");
|
|
121
|
+
|
|
122
|
+
// Check if already migrated (idempotent)
|
|
123
|
+
if (existsSync(metaPath) && hasExpectedDiskViewArtifacts(conv, dirPath)) {
|
|
124
|
+
// Prefer the timestamp-first canonical directory whenever both sibling
|
|
125
|
+
// directories exist and the canonical projection is complete.
|
|
126
|
+
convergeDualConversationDirsToCanonical(
|
|
127
|
+
conv,
|
|
128
|
+
canonicalDirPath,
|
|
129
|
+
legacyDirPath,
|
|
130
|
+
);
|
|
131
|
+
processed++;
|
|
132
|
+
if (processed % 50 === 0) {
|
|
133
|
+
log.info(`Backfilled ${processed}/${total} conversations to disk`);
|
|
134
|
+
}
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Create dir + meta.json (initConversationDir sets updatedAt = createdAt)
|
|
139
|
+
initConversationDir(conv);
|
|
140
|
+
|
|
141
|
+
// Clear stale data from any previous interrupted run so append-only
|
|
142
|
+
// syncMessageToDisk calls below don't produce duplicates.
|
|
143
|
+
if (existsSync(messagesPath)) {
|
|
144
|
+
rmSync(messagesPath, { force: true });
|
|
145
|
+
}
|
|
146
|
+
writeFileSync(messagesPath, "");
|
|
147
|
+
|
|
148
|
+
// Preserve already materialized attachment files across repair replay.
|
|
149
|
+
// Some rows have data_base64 compacted away and only retain their
|
|
150
|
+
// conversation-scoped file_path, so removing attachments/ here would
|
|
151
|
+
// make the content unrecoverable.
|
|
152
|
+
mkdirSync(attachDir, { recursive: true });
|
|
153
|
+
|
|
154
|
+
// Query all messages for this conversation and sync each to disk
|
|
155
|
+
const convMessages = db
|
|
156
|
+
.select()
|
|
157
|
+
.from(messages)
|
|
158
|
+
.where(eq(messages.conversationId, conv.id))
|
|
159
|
+
.orderBy(asc(messages.createdAt))
|
|
160
|
+
.all();
|
|
161
|
+
|
|
162
|
+
for (const msg of convMessages) {
|
|
163
|
+
syncMessageToDisk(conv.id, msg.id, conv.createdAt);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Write the real updatedAt only AFTER all messages are synced so the
|
|
167
|
+
// idempotency check won't skip a conversation with incomplete messages
|
|
168
|
+
// if the migration is interrupted mid-loop.
|
|
169
|
+
updateMetaFile(conv);
|
|
170
|
+
pruneUnreferencedProjectedAttachments(attachDir, messagesPath);
|
|
171
|
+
convergeDualConversationDirsToCanonical(
|
|
172
|
+
conv,
|
|
173
|
+
canonicalDirPath,
|
|
174
|
+
legacyDirPath,
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
processed++;
|
|
178
|
+
if (processed % 50 === 0) {
|
|
179
|
+
log.info(`Backfilled ${processed}/${total} conversations to disk`);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (total > 0) {
|
|
184
|
+
log.info(`Backfilled ${processed}/${total} conversations to disk`);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import { avatarRenameMigration } from "./001-avatar-rename.js";
|
|
2
|
-
import { backfillInstallationIdMigration } from "./002-backfill-installation-id.js";
|
|
3
2
|
import { seedDeviceIdMigration } from "./003-seed-device-id.js";
|
|
4
3
|
import { extractCollectUsageDataMigration } from "./004-extract-collect-usage-data.js";
|
|
5
4
|
import { addSendDiagnosticsMigration } from "./005-add-send-diagnostics.js";
|
|
6
5
|
import { servicesConfigMigration } from "./006-services-config.js";
|
|
7
6
|
import { webSearchProviderRenameMigration } from "./007-web-search-provider-rename.js";
|
|
7
|
+
import { voiceTimeoutAndMaxStepsMigration } from "./008-voice-timeout-and-max-steps.js";
|
|
8
|
+
import { backfillConversationDiskViewMigration } from "./009-backfill-conversation-disk-view.js";
|
|
9
|
+
import { appDirRenameMigration } from "./010-app-dir-rename.js";
|
|
10
|
+
import { backfillInstallationIdMigration } from "./011-backfill-installation-id.js";
|
|
11
|
+
import { renameConversationDiskViewDirsMigration } from "./012-rename-conversation-disk-view-dirs.js";
|
|
12
|
+
import { repairConversationDiskViewMigration } from "./013-repair-conversation-disk-view.js";
|
|
8
13
|
import type { WorkspaceMigration } from "./types.js";
|
|
9
14
|
|
|
10
15
|
/**
|
|
@@ -19,4 +24,9 @@ export const WORKSPACE_MIGRATIONS: WorkspaceMigration[] = [
|
|
|
19
24
|
addSendDiagnosticsMigration,
|
|
20
25
|
servicesConfigMigration,
|
|
21
26
|
webSearchProviderRenameMigration,
|
|
27
|
+
voiceTimeoutAndMaxStepsMigration,
|
|
28
|
+
backfillConversationDiskViewMigration,
|
|
29
|
+
appDirRenameMigration,
|
|
30
|
+
renameConversationDiskViewDirsMigration,
|
|
31
|
+
repairConversationDiskViewMigration,
|
|
22
32
|
];
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import type { TopLevelSnapshot } from "./top-level-scanner.js";
|
|
2
2
|
|
|
3
|
+
export interface WorkspaceTopLevelRenderOptions {
|
|
4
|
+
currentConversationPath?: string | null;
|
|
5
|
+
currentConversationAttachmentsPath?: string | null;
|
|
6
|
+
}
|
|
7
|
+
|
|
3
8
|
/**
|
|
4
9
|
* Render a workspace top-level snapshot into a compact XML-like block
|
|
5
10
|
* suitable for injection into user messages.
|
|
@@ -8,11 +13,18 @@ import type { TopLevelSnapshot } from "./top-level-scanner.js";
|
|
|
8
13
|
*/
|
|
9
14
|
export function renderWorkspaceTopLevelContext(
|
|
10
15
|
snapshot: TopLevelSnapshot,
|
|
16
|
+
options: WorkspaceTopLevelRenderOptions = {},
|
|
11
17
|
): string {
|
|
12
18
|
const lines: string[] = ["<workspace_top_level>"];
|
|
13
19
|
lines.push(`Root: ${snapshot.rootPath}`);
|
|
14
20
|
lines.push(`Directories: ${snapshot.directories.join(", ")}`);
|
|
15
21
|
lines.push(`Files: ${snapshot.files.join(", ")}`);
|
|
22
|
+
if (options.currentConversationPath) {
|
|
23
|
+
lines.push(`Current conversation folder: ${options.currentConversationPath}`);
|
|
24
|
+
}
|
|
25
|
+
if (options.currentConversationAttachmentsPath) {
|
|
26
|
+
lines.push(`Attachment files: ${options.currentConversationAttachmentsPath}`);
|
|
27
|
+
}
|
|
16
28
|
if (snapshot.truncated) {
|
|
17
29
|
lines.push("(list truncated — more entries exist)");
|
|
18
30
|
}
|