@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
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import { mkdtempSync, rmSync } from "node:fs";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { Database } from "bun:sqlite";
|
|
5
|
+
import {
|
|
6
|
+
afterAll,
|
|
7
|
+
afterEach,
|
|
8
|
+
beforeEach,
|
|
9
|
+
describe,
|
|
10
|
+
expect,
|
|
11
|
+
mock,
|
|
12
|
+
test,
|
|
13
|
+
} from "bun:test";
|
|
14
|
+
|
|
15
|
+
import { drizzle } from "drizzle-orm/bun-sqlite";
|
|
16
|
+
|
|
17
|
+
const testDir = mkdtempSync(join(tmpdir(), "memory-reducer-checkpoints-"));
|
|
18
|
+
const dbPath = join(testDir, "test.db");
|
|
19
|
+
const originalBunTest = process.env.BUN_TEST;
|
|
20
|
+
|
|
21
|
+
mock.module("../util/platform.js", () => ({
|
|
22
|
+
getDataDir: () => testDir,
|
|
23
|
+
isMacOS: () => process.platform === "darwin",
|
|
24
|
+
isLinux: () => process.platform === "linux",
|
|
25
|
+
isWindows: () => process.platform === "win32",
|
|
26
|
+
getPidPath: () => join(testDir, "test.pid"),
|
|
27
|
+
getDbPath: () => dbPath,
|
|
28
|
+
getLogPath: () => join(testDir, "test.log"),
|
|
29
|
+
ensureDataDir: () => {},
|
|
30
|
+
getConversationsDir: () => join(testDir, "conversations"),
|
|
31
|
+
}));
|
|
32
|
+
|
|
33
|
+
mock.module("../util/logger.js", () => ({
|
|
34
|
+
getLogger: () =>
|
|
35
|
+
new Proxy({} as Record<string, unknown>, {
|
|
36
|
+
get: () => () => {},
|
|
37
|
+
}),
|
|
38
|
+
}));
|
|
39
|
+
|
|
40
|
+
import { initializeDb, resetDb } from "../memory/db.js";
|
|
41
|
+
import { getSqliteFrom } from "../memory/db-connection.js";
|
|
42
|
+
import { migrateMemoryReducerCheckpoints } from "../memory/migrations/187-memory-reducer-checkpoints.js";
|
|
43
|
+
import * as schema from "../memory/schema.js";
|
|
44
|
+
|
|
45
|
+
function createTestDb() {
|
|
46
|
+
const sqlite = new Database(":memory:");
|
|
47
|
+
sqlite.exec("PRAGMA journal_mode=WAL");
|
|
48
|
+
sqlite.exec("PRAGMA foreign_keys = ON");
|
|
49
|
+
return drizzle(sqlite, { schema });
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function getColumnInfo(
|
|
53
|
+
raw: Database,
|
|
54
|
+
): Array<{ name: string; notnull: number }> {
|
|
55
|
+
return raw.query(`PRAGMA table_info(conversations)`).all() as Array<{
|
|
56
|
+
name: string;
|
|
57
|
+
notnull: number;
|
|
58
|
+
}>;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function bootstrapPreCheckpointConversations(raw: Database): void {
|
|
62
|
+
raw.exec(/*sql*/ `
|
|
63
|
+
CREATE TABLE conversations (
|
|
64
|
+
id TEXT PRIMARY KEY,
|
|
65
|
+
title TEXT,
|
|
66
|
+
created_at INTEGER NOT NULL,
|
|
67
|
+
updated_at INTEGER NOT NULL,
|
|
68
|
+
total_input_tokens INTEGER NOT NULL DEFAULT 0,
|
|
69
|
+
total_output_tokens INTEGER NOT NULL DEFAULT 0,
|
|
70
|
+
total_estimated_cost REAL NOT NULL DEFAULT 0,
|
|
71
|
+
context_summary TEXT,
|
|
72
|
+
context_compacted_message_count INTEGER NOT NULL DEFAULT 0,
|
|
73
|
+
context_compacted_at INTEGER,
|
|
74
|
+
conversation_type TEXT NOT NULL DEFAULT 'standard',
|
|
75
|
+
source TEXT NOT NULL DEFAULT 'user',
|
|
76
|
+
memory_scope_id TEXT NOT NULL DEFAULT 'default',
|
|
77
|
+
origin_channel TEXT,
|
|
78
|
+
origin_interface TEXT,
|
|
79
|
+
fork_parent_conversation_id TEXT,
|
|
80
|
+
fork_parent_message_id TEXT,
|
|
81
|
+
is_auto_title INTEGER NOT NULL DEFAULT 1,
|
|
82
|
+
schedule_job_id TEXT
|
|
83
|
+
)
|
|
84
|
+
`);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function removeTestDbFiles(): void {
|
|
88
|
+
rmSync(dbPath, { force: true });
|
|
89
|
+
rmSync(`${dbPath}-shm`, { force: true });
|
|
90
|
+
rmSync(`${dbPath}-wal`, { force: true });
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
describe("memory reducer checkpoint columns migration", () => {
|
|
94
|
+
beforeEach(() => {
|
|
95
|
+
process.env.BUN_TEST = "0";
|
|
96
|
+
resetDb();
|
|
97
|
+
removeTestDbFiles();
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
afterEach(() => {
|
|
101
|
+
resetDb();
|
|
102
|
+
removeTestDbFiles();
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
afterAll(() => {
|
|
106
|
+
if (originalBunTest === undefined) {
|
|
107
|
+
delete process.env.BUN_TEST;
|
|
108
|
+
} else {
|
|
109
|
+
process.env.BUN_TEST = originalBunTest;
|
|
110
|
+
}
|
|
111
|
+
resetDb();
|
|
112
|
+
removeTestDbFiles();
|
|
113
|
+
try {
|
|
114
|
+
rmSync(testDir, { recursive: true });
|
|
115
|
+
} catch {
|
|
116
|
+
/* best effort */
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
test("fresh DB initialization includes nullable reducer checkpoint columns", () => {
|
|
121
|
+
initializeDb();
|
|
122
|
+
|
|
123
|
+
const raw = new Database(dbPath);
|
|
124
|
+
const columns = getColumnInfo(raw);
|
|
125
|
+
|
|
126
|
+
const checkpointColumns = columns.filter(
|
|
127
|
+
(c) =>
|
|
128
|
+
c.name === "memory_reduced_through_message_id" ||
|
|
129
|
+
c.name === "memory_dirty_tail_since_message_id" ||
|
|
130
|
+
c.name === "memory_last_reduced_at",
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
expect(checkpointColumns).toHaveLength(3);
|
|
134
|
+
expect(checkpointColumns.every((c) => c.notnull === 0)).toBe(true);
|
|
135
|
+
|
|
136
|
+
raw.close();
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
test("migration upgrades the pre-checkpoint schema without disturbing existing rows", () => {
|
|
140
|
+
const db = createTestDb();
|
|
141
|
+
const raw = getSqliteFrom(db);
|
|
142
|
+
const now = Date.now();
|
|
143
|
+
|
|
144
|
+
bootstrapPreCheckpointConversations(raw);
|
|
145
|
+
raw.exec(/*sql*/ `
|
|
146
|
+
INSERT INTO conversations (
|
|
147
|
+
id,
|
|
148
|
+
title,
|
|
149
|
+
created_at,
|
|
150
|
+
updated_at,
|
|
151
|
+
conversation_type,
|
|
152
|
+
source,
|
|
153
|
+
memory_scope_id,
|
|
154
|
+
is_auto_title
|
|
155
|
+
) VALUES (
|
|
156
|
+
'conv-upgrade',
|
|
157
|
+
'Existing conversation',
|
|
158
|
+
${now},
|
|
159
|
+
${now},
|
|
160
|
+
'standard',
|
|
161
|
+
'user',
|
|
162
|
+
'default',
|
|
163
|
+
1
|
|
164
|
+
)
|
|
165
|
+
`);
|
|
166
|
+
|
|
167
|
+
migrateMemoryReducerCheckpoints(db);
|
|
168
|
+
|
|
169
|
+
const columnNames = getColumnInfo(raw).map((c) => c.name);
|
|
170
|
+
expect(columnNames).toContain("memory_reduced_through_message_id");
|
|
171
|
+
expect(columnNames).toContain("memory_dirty_tail_since_message_id");
|
|
172
|
+
expect(columnNames).toContain("memory_last_reduced_at");
|
|
173
|
+
|
|
174
|
+
const row = raw
|
|
175
|
+
.query(
|
|
176
|
+
`SELECT id, title, memory_reduced_through_message_id, memory_dirty_tail_since_message_id, memory_last_reduced_at
|
|
177
|
+
FROM conversations WHERE id = 'conv-upgrade'`,
|
|
178
|
+
)
|
|
179
|
+
.get() as {
|
|
180
|
+
id: string;
|
|
181
|
+
title: string | null;
|
|
182
|
+
memory_reduced_through_message_id: string | null;
|
|
183
|
+
memory_dirty_tail_since_message_id: string | null;
|
|
184
|
+
memory_last_reduced_at: number | null;
|
|
185
|
+
} | null;
|
|
186
|
+
|
|
187
|
+
expect(row).toEqual({
|
|
188
|
+
id: "conv-upgrade",
|
|
189
|
+
title: "Existing conversation",
|
|
190
|
+
memory_reduced_through_message_id: null,
|
|
191
|
+
memory_dirty_tail_since_message_id: null,
|
|
192
|
+
memory_last_reduced_at: null,
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
raw.close();
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
test("re-running the migration preserves populated checkpoint values", () => {
|
|
199
|
+
const db = createTestDb();
|
|
200
|
+
const raw = getSqliteFrom(db);
|
|
201
|
+
const now = Date.now();
|
|
202
|
+
|
|
203
|
+
bootstrapPreCheckpointConversations(raw);
|
|
204
|
+
raw.exec(/*sql*/ `
|
|
205
|
+
INSERT INTO conversations (
|
|
206
|
+
id,
|
|
207
|
+
title,
|
|
208
|
+
created_at,
|
|
209
|
+
updated_at,
|
|
210
|
+
conversation_type,
|
|
211
|
+
source,
|
|
212
|
+
memory_scope_id,
|
|
213
|
+
is_auto_title
|
|
214
|
+
) VALUES (
|
|
215
|
+
'conv-rerun',
|
|
216
|
+
'Reduced conversation',
|
|
217
|
+
${now},
|
|
218
|
+
${now},
|
|
219
|
+
'standard',
|
|
220
|
+
'user',
|
|
221
|
+
'default',
|
|
222
|
+
1
|
|
223
|
+
)
|
|
224
|
+
`);
|
|
225
|
+
|
|
226
|
+
migrateMemoryReducerCheckpoints(db);
|
|
227
|
+
raw.exec(/*sql*/ `
|
|
228
|
+
UPDATE conversations
|
|
229
|
+
SET memory_reduced_through_message_id = 'msg-100',
|
|
230
|
+
memory_dirty_tail_since_message_id = 'msg-101',
|
|
231
|
+
memory_last_reduced_at = ${now}
|
|
232
|
+
WHERE id = 'conv-rerun'
|
|
233
|
+
`);
|
|
234
|
+
|
|
235
|
+
expect(() => migrateMemoryReducerCheckpoints(db)).not.toThrow();
|
|
236
|
+
|
|
237
|
+
const row = raw
|
|
238
|
+
.query(
|
|
239
|
+
`SELECT memory_reduced_through_message_id, memory_dirty_tail_since_message_id, memory_last_reduced_at
|
|
240
|
+
FROM conversations WHERE id = 'conv-rerun'`,
|
|
241
|
+
)
|
|
242
|
+
.get() as {
|
|
243
|
+
memory_reduced_through_message_id: string | null;
|
|
244
|
+
memory_dirty_tail_since_message_id: string | null;
|
|
245
|
+
memory_last_reduced_at: number | null;
|
|
246
|
+
} | null;
|
|
247
|
+
|
|
248
|
+
expect(row).toEqual({
|
|
249
|
+
memory_reduced_through_message_id: "msg-100",
|
|
250
|
+
memory_dirty_tail_since_message_id: "msg-101",
|
|
251
|
+
memory_last_reduced_at: now,
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
raw.close();
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
test("getConversation exposes the new checkpoint fields as null for new rows", async () => {
|
|
258
|
+
initializeDb();
|
|
259
|
+
|
|
260
|
+
// Dynamic import to avoid circular module init issues — conversation-crud
|
|
261
|
+
// depends on getDb being initialized which happens in initializeDb above.
|
|
262
|
+
const { createConversation, getConversation } =
|
|
263
|
+
await import("../memory/conversation-crud.js");
|
|
264
|
+
|
|
265
|
+
const created = createConversation("Test conversation");
|
|
266
|
+
const loaded = getConversation(created.id);
|
|
267
|
+
|
|
268
|
+
expect(loaded).not.toBeNull();
|
|
269
|
+
expect(loaded!.memoryReducedThroughMessageId).toBeNull();
|
|
270
|
+
expect(loaded!.memoryDirtyTailSinceMessageId).toBeNull();
|
|
271
|
+
expect(loaded!.memoryLastReducedAt).toBeNull();
|
|
272
|
+
});
|
|
273
|
+
});
|
|
@@ -5,11 +5,13 @@
|
|
|
5
5
|
* (specific ID → most recent assistant → any message → empty conversation).
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import { mkdtempSync, rmSync } from "node:fs";
|
|
8
|
+
import { mkdtempSync, readFileSync, rmSync } from "node:fs";
|
|
9
9
|
import { tmpdir } from "node:os";
|
|
10
10
|
import { join } from "node:path";
|
|
11
11
|
import { afterAll, beforeEach, describe, expect, mock, test } from "bun:test";
|
|
12
12
|
|
|
13
|
+
import JSZip from "jszip";
|
|
14
|
+
|
|
13
15
|
const testDir = mkdtempSync(join(tmpdir(), "diagnostics-export-test-"));
|
|
14
16
|
|
|
15
17
|
mock.module("../util/platform.js", () => ({
|
|
@@ -90,6 +92,27 @@ function seedMessage(
|
|
|
90
92
|
);
|
|
91
93
|
}
|
|
92
94
|
|
|
95
|
+
function seedLlmRequestLog(
|
|
96
|
+
id: string,
|
|
97
|
+
conversationId: string,
|
|
98
|
+
provider: string | null,
|
|
99
|
+
requestPayload: unknown,
|
|
100
|
+
responsePayload: unknown,
|
|
101
|
+
createdAt: number,
|
|
102
|
+
): void {
|
|
103
|
+
db().run(
|
|
104
|
+
"INSERT INTO llm_request_logs (id, conversation_id, provider, request_payload, response_payload, created_at) VALUES (?, ?, ?, ?, ?, ?)",
|
|
105
|
+
[
|
|
106
|
+
id,
|
|
107
|
+
conversationId,
|
|
108
|
+
provider,
|
|
109
|
+
JSON.stringify(requestPayload),
|
|
110
|
+
JSON.stringify(responsePayload),
|
|
111
|
+
createdAt,
|
|
112
|
+
],
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
93
116
|
function seedConversationKey(
|
|
94
117
|
conversationKey: string,
|
|
95
118
|
conversationId: string,
|
|
@@ -102,6 +125,7 @@ function seedConversationKey(
|
|
|
102
125
|
|
|
103
126
|
function cleanDb(): void {
|
|
104
127
|
db().run("DELETE FROM messages");
|
|
128
|
+
db().run("DELETE FROM llm_request_logs");
|
|
105
129
|
db().run("DELETE FROM conversation_keys");
|
|
106
130
|
db().run("DELETE FROM conversations");
|
|
107
131
|
}
|
|
@@ -216,4 +240,49 @@ describe("diagnostics export", () => {
|
|
|
216
240
|
const json = (await res.json()) as { success: boolean };
|
|
217
241
|
expect(json.success).toBe(true);
|
|
218
242
|
});
|
|
243
|
+
|
|
244
|
+
test("preserves llm request provider identity in the exported JSONL", async () => {
|
|
245
|
+
const convId = "conv-7";
|
|
246
|
+
const now = Date.now();
|
|
247
|
+
|
|
248
|
+
seedConversation(convId);
|
|
249
|
+
seedMessage("msg-user-7", convId, "user", "hello", now - 1000);
|
|
250
|
+
seedMessage("msg-assistant-7", convId, "assistant", "world", now);
|
|
251
|
+
seedLlmRequestLog(
|
|
252
|
+
"log-7",
|
|
253
|
+
convId,
|
|
254
|
+
"openrouter",
|
|
255
|
+
{ model: "openai/gpt-4.1-mini", input: "hello" },
|
|
256
|
+
{ output: "world" },
|
|
257
|
+
now,
|
|
258
|
+
);
|
|
259
|
+
|
|
260
|
+
const res = await callExport({ conversationId: convId });
|
|
261
|
+
expect(res.status).toBe(200);
|
|
262
|
+
const json = (await res.json()) as { success: boolean; filePath: string };
|
|
263
|
+
expect(json.success).toBe(true);
|
|
264
|
+
|
|
265
|
+
const zip = await JSZip.loadAsync(readFileSync(json.filePath));
|
|
266
|
+
const llmRequests = zip.file("llm_requests.jsonl");
|
|
267
|
+
expect(llmRequests).not.toBeNull();
|
|
268
|
+
|
|
269
|
+
const lines = (await llmRequests!.async("string")).trim().split("\n");
|
|
270
|
+
expect(lines).toHaveLength(1);
|
|
271
|
+
|
|
272
|
+
const row = JSON.parse(lines[0]) as {
|
|
273
|
+
id: string;
|
|
274
|
+
conversationId: string;
|
|
275
|
+
provider?: string | null;
|
|
276
|
+
request: unknown;
|
|
277
|
+
response: unknown;
|
|
278
|
+
};
|
|
279
|
+
|
|
280
|
+
expect(row).toMatchObject({
|
|
281
|
+
id: "log-7",
|
|
282
|
+
conversationId: convId,
|
|
283
|
+
provider: "openrouter",
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
rmSync(json.filePath, { force: true });
|
|
287
|
+
});
|
|
219
288
|
});
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, rmSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
import { afterEach, beforeEach, describe, expect, it, mock } from "bun:test";
|
|
5
|
+
|
|
6
|
+
let tempDir: string;
|
|
7
|
+
|
|
8
|
+
mock.module("../util/platform.js", () => ({
|
|
9
|
+
getWorkspacePromptPath: mock((file: string) => join(tempDir, file)),
|
|
10
|
+
getWorkspaceDir: () => tempDir,
|
|
11
|
+
getRootDir: () => tempDir,
|
|
12
|
+
getDataDir: () => join(tempDir, "data"),
|
|
13
|
+
getPlatformName: () => "darwin",
|
|
14
|
+
isMacOS: () => false,
|
|
15
|
+
isLinux: () => false,
|
|
16
|
+
isWindows: () => false,
|
|
17
|
+
ensureDataDir: () => {},
|
|
18
|
+
getDbPath: () => "",
|
|
19
|
+
getLogPath: () => "",
|
|
20
|
+
getHistoryPath: () => "",
|
|
21
|
+
getHooksDir: () => "",
|
|
22
|
+
getSessionTokenPath: () => "",
|
|
23
|
+
getPlatformTokenPath: () => "",
|
|
24
|
+
getPidPath: () => "",
|
|
25
|
+
}));
|
|
26
|
+
|
|
27
|
+
const { isWakeUpGreeting, getCannedFirstGreeting, CANNED_FIRST_GREETING } =
|
|
28
|
+
await import("../daemon/first-greeting.js");
|
|
29
|
+
|
|
30
|
+
describe("first-greeting", () => {
|
|
31
|
+
beforeEach(() => {
|
|
32
|
+
tempDir = join(tmpdir(), `first-greeting-test-${Date.now()}`);
|
|
33
|
+
mkdirSync(tempDir, { recursive: true });
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
afterEach(() => {
|
|
37
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
describe("isWakeUpGreeting", () => {
|
|
41
|
+
it("returns true for wake-up greeting with 0 messages and BOOTSTRAP.md present", () => {
|
|
42
|
+
writeFileSync(join(tempDir, "BOOTSTRAP.md"), "bootstrap content");
|
|
43
|
+
expect(isWakeUpGreeting("Wake up, my friend.", 0)).toBe(true);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it("returns true for case variations", () => {
|
|
47
|
+
writeFileSync(join(tempDir, "BOOTSTRAP.md"), "bootstrap content");
|
|
48
|
+
expect(isWakeUpGreeting("wake up, my friend.", 0)).toBe(true);
|
|
49
|
+
expect(isWakeUpGreeting("WAKE UP, MY FRIEND.", 0)).toBe(true);
|
|
50
|
+
expect(isWakeUpGreeting("Wake Up, My Friend.", 0)).toBe(true);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it("returns false when content doesn't match wake-up greeting", () => {
|
|
54
|
+
writeFileSync(join(tempDir, "BOOTSTRAP.md"), "bootstrap content");
|
|
55
|
+
expect(isWakeUpGreeting("Hello", 0)).toBe(false);
|
|
56
|
+
expect(isWakeUpGreeting("Hey there", 0)).toBe(false);
|
|
57
|
+
expect(isWakeUpGreeting("Wake up", 0)).toBe(false);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it("returns false when conversationMessageCount > 0", () => {
|
|
61
|
+
writeFileSync(join(tempDir, "BOOTSTRAP.md"), "bootstrap content");
|
|
62
|
+
expect(isWakeUpGreeting("Wake up, my friend.", 1)).toBe(false);
|
|
63
|
+
expect(isWakeUpGreeting("Wake up, my friend.", 5)).toBe(false);
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("returns false when BOOTSTRAP.md doesn't exist", () => {
|
|
67
|
+
expect(existsSync(join(tempDir, "BOOTSTRAP.md"))).toBe(false);
|
|
68
|
+
expect(isWakeUpGreeting("Wake up, my friend.", 0)).toBe(false);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
describe("getCannedFirstGreeting", () => {
|
|
73
|
+
it("returns the expected greeting string", () => {
|
|
74
|
+
const greeting = getCannedFirstGreeting();
|
|
75
|
+
expect(greeting).toBe(CANNED_FIRST_GREETING);
|
|
76
|
+
expect(greeting).toContain("brand new");
|
|
77
|
+
expect(greeting).toContain("no name, no memories");
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
});
|
|
@@ -24,6 +24,7 @@ const ALLOWLIST = new Set([
|
|
|
24
24
|
// --- Intentional local daemon-control paths ---
|
|
25
25
|
"assistant/src/cli/commands/conversations.ts", // CLI wipe talks to runtime directly
|
|
26
26
|
"clients/shared/Network/DaemonClient.swift",
|
|
27
|
+
"clients/shared/App/Auth/PlatformOAuthService.swift", // comment explaining runtimeUrl vs platformUrl
|
|
27
28
|
"clients/macos/vellum-assistant/App/AppDelegate.swift",
|
|
28
29
|
"clients/macos/vellum-assistant/Features/Settings/SettingsConnectTab.swift",
|
|
29
30
|
".claude/skills/update/SKILL.md", // daemon health check script
|
|
@@ -268,13 +268,9 @@ describe("handleConfirmationResponse canonical status sync", () => {
|
|
|
268
268
|
undefined,
|
|
269
269
|
{ source: "button" },
|
|
270
270
|
]);
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
{
|
|
275
|
-
status: "approved",
|
|
276
|
-
},
|
|
277
|
-
);
|
|
271
|
+
// Canonical status sync is now handled inside Conversation.handleConfirmationResponse,
|
|
272
|
+
// which this test mocks out — so the handler itself no longer calls resolveCanonicalGuardianRequest.
|
|
273
|
+
expect(resolveCanonicalGuardianRequestMock).not.toHaveBeenCalled();
|
|
278
274
|
expect(resolveMock).toHaveBeenCalledWith("req-confirm-allow");
|
|
279
275
|
});
|
|
280
276
|
});
|
|
@@ -491,12 +491,17 @@ describe("repairHistory", () => {
|
|
|
491
491
|
expect(assistantMsg.content[1]).toMatchObject({
|
|
492
492
|
type: "web_search_tool_result",
|
|
493
493
|
tool_use_id: "stu_1",
|
|
494
|
-
content: {
|
|
494
|
+
content: {
|
|
495
|
+
type: "web_search_tool_result_error",
|
|
496
|
+
error_code: "unavailable",
|
|
497
|
+
},
|
|
495
498
|
});
|
|
496
499
|
|
|
497
500
|
// User message has no web_search_tool_result
|
|
498
501
|
const userMsg = repaired[2];
|
|
499
|
-
expect(
|
|
502
|
+
expect(
|
|
503
|
+
userMsg.content.every((b) => b.type !== "web_search_tool_result"),
|
|
504
|
+
).toBe(true);
|
|
500
505
|
});
|
|
501
506
|
|
|
502
507
|
test("migrates legacy web_search_tool_result from user message to assistant message", () => {
|
|
@@ -527,7 +532,9 @@ describe("repairHistory", () => {
|
|
|
527
532
|
{
|
|
528
533
|
type: "web_search_tool_result",
|
|
529
534
|
tool_use_id: "srvtoolu_abc",
|
|
530
|
-
content: [
|
|
535
|
+
content: [
|
|
536
|
+
{ type: "web_search_result", url: "https://example.com" },
|
|
537
|
+
],
|
|
531
538
|
},
|
|
532
539
|
{ type: "tool_result", tool_use_id: "tu_1", content: "files" },
|
|
533
540
|
],
|
|
@@ -545,8 +552,12 @@ describe("repairHistory", () => {
|
|
|
545
552
|
|
|
546
553
|
// The assistant message now has the server pair + client tool_use
|
|
547
554
|
const assistantMsg = repaired[1];
|
|
548
|
-
const serverToolUse = assistantMsg.content.find(
|
|
549
|
-
|
|
555
|
+
const serverToolUse = assistantMsg.content.find(
|
|
556
|
+
(b) => b.type === "server_tool_use",
|
|
557
|
+
);
|
|
558
|
+
const webSearchResult = assistantMsg.content.find(
|
|
559
|
+
(b) => b.type === "web_search_tool_result",
|
|
560
|
+
);
|
|
550
561
|
expect(serverToolUse).toBeDefined();
|
|
551
562
|
expect(webSearchResult).toBeDefined();
|
|
552
563
|
|
|
@@ -554,7 +565,9 @@ describe("repairHistory", () => {
|
|
|
554
565
|
const userMsg = repaired[2];
|
|
555
566
|
expect(stats.orphanToolResultsDowngraded).toBe(1);
|
|
556
567
|
expect(userMsg.content.some((b) => b.type === "tool_result")).toBe(true);
|
|
557
|
-
expect(
|
|
568
|
+
expect(
|
|
569
|
+
userMsg.content.every((b) => b.type !== "web_search_tool_result"),
|
|
570
|
+
).toBe(true);
|
|
558
571
|
});
|
|
559
572
|
|
|
560
573
|
test("trailing server_tool_use gets synthetic result in same assistant message", () => {
|
|
@@ -584,7 +597,10 @@ describe("repairHistory", () => {
|
|
|
584
597
|
expect(repaired[1].content[1]).toMatchObject({
|
|
585
598
|
type: "web_search_tool_result",
|
|
586
599
|
tool_use_id: "stu_1",
|
|
587
|
-
content: {
|
|
600
|
+
content: {
|
|
601
|
+
type: "web_search_tool_result_error",
|
|
602
|
+
error_code: "unavailable",
|
|
603
|
+
},
|
|
588
604
|
});
|
|
589
605
|
});
|
|
590
606
|
|
|
@@ -696,11 +712,15 @@ describe("repairHistory", () => {
|
|
|
696
712
|
|
|
697
713
|
// Assistant message has the server pair
|
|
698
714
|
const assistantMsg = repaired[1];
|
|
699
|
-
expect(
|
|
715
|
+
expect(
|
|
716
|
+
assistantMsg.content.some((b) => b.type === "web_search_tool_result"),
|
|
717
|
+
).toBe(true);
|
|
700
718
|
|
|
701
719
|
// User message has no web_search_tool_result — the tool_result was downgraded to text
|
|
702
720
|
const userMsg = repaired[2];
|
|
703
|
-
expect(
|
|
721
|
+
expect(
|
|
722
|
+
userMsg.content.every((b) => b.type !== "web_search_tool_result"),
|
|
723
|
+
).toBe(true);
|
|
704
724
|
expect(userMsg.content.every((b) => b.type !== "tool_result")).toBe(true);
|
|
705
725
|
});
|
|
706
726
|
|
|
@@ -720,7 +740,9 @@ describe("repairHistory", () => {
|
|
|
720
740
|
{
|
|
721
741
|
type: "web_search_tool_result",
|
|
722
742
|
tool_use_id: "tu_1",
|
|
723
|
-
content: [
|
|
743
|
+
content: [
|
|
744
|
+
{ type: "web_search_result", url: "https://example.com" },
|
|
745
|
+
],
|
|
724
746
|
},
|
|
725
747
|
],
|
|
726
748
|
},
|