@vellumai/assistant 0.7.0 → 0.7.1
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 +6 -7
- package/Dockerfile +1 -0
- package/README.md +2 -2
- package/__tests__/permissions/gateway-threshold-reader.test.ts +79 -139
- package/bun.lock +3 -0
- package/docs/architecture/security.md +18 -16
- package/knip.json +1 -0
- package/node_modules/@vellumai/skill-host-contracts/__tests__/client.test.ts +1 -5
- package/node_modules/@vellumai/skill-host-contracts/src/assistant-event.ts +0 -5
- package/node_modules/@vellumai/skill-host-contracts/src/client.ts +10 -16
- package/node_modules/@vellumai/skill-host-contracts/src/skill-host.ts +1 -9
- package/node_modules/@vellumai/skill-host-contracts/src/tool-types.ts +12 -12
- package/node_modules/@vellumai/slack-text/bun.lock +24 -0
- package/node_modules/@vellumai/slack-text/package.json +18 -0
- package/node_modules/@vellumai/slack-text/src/index.test.ts +153 -0
- package/node_modules/@vellumai/slack-text/src/index.ts +235 -0
- package/node_modules/@vellumai/slack-text/tsconfig.json +20 -0
- package/openapi.yaml +294 -107
- package/package.json +4 -2
- package/scripts/generate-openapi.ts +16 -111
- package/src/__tests__/agent-wake-override-profile.test.ts +23 -1
- package/src/__tests__/anthropic-provider.test.ts +56 -13
- package/src/__tests__/app-conversation-ids-backfill.test.ts +278 -0
- package/src/__tests__/app-conversation-ids.test.ts +151 -0
- package/src/__tests__/approval-cascade.test.ts +0 -15
- package/src/__tests__/approval-routes-http.test.ts +6 -17
- package/src/__tests__/assistant-event-hub.test.ts +126 -77
- package/src/__tests__/assistant-event.test.ts +0 -5
- package/src/__tests__/assistant-events-sse-hardening.test.ts +37 -15
- package/src/__tests__/assistant-feature-flags-integration.test.ts +0 -29
- package/src/__tests__/background-shell-host-bash.test.ts +34 -43
- package/src/__tests__/call-controller.test.ts +1 -1
- package/src/__tests__/call-site-routing-provider.test.ts +193 -0
- package/src/__tests__/channel-approval-routes.test.ts +10 -296
- package/src/__tests__/channel-approvals.test.ts +25 -17
- package/src/__tests__/channel-guardian.test.ts +100 -146
- package/src/__tests__/checker.test.ts +20 -34
- package/src/__tests__/compact-event-conversation-id-guard.test.ts +50 -0
- package/src/__tests__/compaction-events.test.ts +2 -0
- package/src/__tests__/config-schema.test.ts +6 -48
- package/src/__tests__/config-watcher.test.ts +12 -0
- package/src/__tests__/connection-policy.test.ts +1 -52
- package/src/__tests__/contacts-write.test.ts +2 -64
- package/src/__tests__/context-image-dimensions.test.ts +1 -1
- package/src/__tests__/context-search-memory-source.test.ts +120 -1
- package/src/__tests__/context-search-memory-v2-source.test.ts +383 -0
- package/src/__tests__/context-search-pkb-source.test.ts +49 -0
- package/src/__tests__/context-search-workspace-source.test.ts +9 -22
- package/src/__tests__/context-window-manager.test.ts +46 -0
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +2 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +102 -29
- package/src/__tests__/conversation-agent-loop.test.ts +980 -13
- package/src/__tests__/conversation-analysis-routes.test.ts +12 -10
- package/src/__tests__/conversation-attention-telegram.test.ts +11 -3
- package/src/__tests__/conversation-confirmation-signals.test.ts +0 -291
- package/src/__tests__/conversation-history-web-search.test.ts +4 -3
- package/src/__tests__/conversation-inference-profile-route.test.ts +12 -23
- package/src/__tests__/conversation-lifecycle.test.ts +4 -4
- package/src/__tests__/conversation-process-callsite.test.ts +79 -2
- package/src/__tests__/conversation-queue.test.ts +3 -8
- package/src/__tests__/conversation-routes-disk-view.test.ts +1 -161
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +0 -32
- package/src/__tests__/conversation-routes-slash-commands.test.ts +75 -66
- package/src/__tests__/conversation-runtime-assembly.test.ts +257 -3
- package/src/__tests__/conversation-slash-commands.test.ts +24 -4
- package/src/__tests__/conversation-slash-queue.test.ts +2 -0
- package/src/__tests__/conversation-speed-override.test.ts +0 -3
- package/src/__tests__/conversation-starter-routes.test.ts +79 -2
- package/src/__tests__/conversation-surfaces-standalone-payloads.test.ts +12 -5
- package/src/__tests__/conversation-surfaces-standalone.test.ts +18 -14
- package/src/__tests__/conversation-surfaces-state-update.test.ts +3 -2
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +8 -46
- package/src/__tests__/conversation-usage.test.ts +253 -3
- package/src/__tests__/credential-execution-shell-lockdown.test.ts +0 -39
- package/src/__tests__/credential-health-service.test.ts +68 -0
- package/src/__tests__/credential-security-e2e.test.ts +4 -3
- package/src/__tests__/credential-security-invariants.test.ts +1 -5
- package/src/__tests__/credential-token-resolver.test.ts +180 -0
- package/src/__tests__/cu-unified-flow.test.ts +33 -16
- package/src/__tests__/daemon-assistant-events.test.ts +34 -21
- package/src/__tests__/daemon-credential-client.test.ts +4 -1
- package/src/__tests__/db-connection-isolation.test.ts +125 -0
- package/src/__tests__/db-migration-rollback.test.ts +101 -0
- package/src/__tests__/db-slack-compaction-watermark-migration.test.ts +169 -0
- package/src/__tests__/deterministic-verification-control-plane.test.ts +7 -80
- package/src/__tests__/document-conversations.test.ts +332 -0
- package/src/__tests__/embedding-managed-proxy-selection.test.ts +2 -2
- package/src/__tests__/emit-event-signal.test.ts +4 -6
- package/src/__tests__/events-client-registration.test.ts +193 -49
- package/src/__tests__/filing-service.test.ts +58 -7
- package/src/__tests__/first-greeting.test.ts +156 -150
- package/src/__tests__/fixtures/mock-chrome-extension.ts +108 -66
- package/src/__tests__/get-skill-detail-audit.test.ts +3 -8
- package/src/__tests__/guardian-binding-drift-heal.test.ts +1 -1
- package/src/__tests__/guardian-dispatch.test.ts +1 -1
- package/src/__tests__/guardian-grant-minting.test.ts +7 -2
- package/src/__tests__/guardian-routing-invariants.test.ts +7 -2
- package/src/__tests__/guardian-routing-state.test.ts +1 -1
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +32 -11
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +2 -83
- package/src/__tests__/headless-browser-mode.test.ts +4 -9
- package/src/__tests__/headless-browser-navigate.test.ts +21 -20
- package/src/__tests__/heartbeat-service.test.ts +289 -7
- package/src/__tests__/helpers/channel-test-adapter.ts +2 -2
- package/src/__tests__/helpers/create-guardian-binding.ts +91 -0
- package/src/__tests__/host-bash-proxy.test.ts +46 -122
- package/src/__tests__/host-browser-e2e-cloud.test.ts +36 -497
- package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +26 -96
- package/src/__tests__/host-browser-proxy.test.ts +111 -185
- package/src/__tests__/host-browser-routes.test.ts +45 -75
- package/src/__tests__/host-browser-ws-events-e2e.test.ts +26 -30
- package/src/__tests__/host-cu-proxy.test.ts +56 -111
- package/src/__tests__/host-file-proxy.test.ts +44 -98
- package/src/__tests__/host-file-read-tool.test.ts +42 -21
- package/src/__tests__/host-shell-tool.test.ts +33 -68
- package/src/__tests__/host-transfer-pending-interactions.test.ts +2 -18
- package/src/__tests__/host-transfer-proxy.test.ts +43 -53
- package/src/__tests__/http-user-message-parity.test.ts +0 -6
- package/src/__tests__/inbound-slack-persistence.test.ts +31 -0
- package/src/__tests__/injector-chain.test.ts +10 -5
- package/src/__tests__/injector-pkb-v2-silenced.test.ts +124 -0
- package/src/__tests__/inline-command-runner.test.ts +0 -66
- package/src/__tests__/inline-skill-load-permissions.test.ts +0 -2
- package/src/__tests__/install-skill-routing.test.ts +1 -13
- package/src/__tests__/llm-callsite-catalog.test.ts +34 -0
- package/src/__tests__/llm-catalog-parity.test.ts +90 -0
- package/src/__tests__/llm-context-resolution.test.ts +180 -0
- package/src/__tests__/llm-resolver.test.ts +80 -12
- package/src/__tests__/llm-usage-store.test.ts +269 -4
- package/src/__tests__/log-export-routes.test.ts +89 -0
- package/src/__tests__/managed-profile-guard.test.ts +225 -0
- package/src/__tests__/managed-skill-lifecycle.test.ts +0 -10
- package/src/__tests__/manual-token-reconciliation.test.ts +334 -0
- package/src/__tests__/memory-v2-static-injector.test.ts +95 -0
- package/src/__tests__/migration-cross-version-compatibility.test.ts +197 -291
- package/src/__tests__/migration-export-http.test.ts +33 -26
- package/src/__tests__/migration-export-streaming.test.ts +18 -10
- package/src/__tests__/migration-export-to-gcs.test.ts +49 -9
- package/src/__tests__/migration-import-commit-http.test.ts +66 -21
- package/src/__tests__/migration-import-from-gcs.test.ts +50 -9
- package/src/__tests__/migration-import-from-url.test.ts +20 -6
- package/src/__tests__/migration-import-preflight-http.test.ts +95 -95
- package/src/__tests__/migration-parity-persistence.test.ts +62 -25
- package/src/__tests__/migration-transport.test.ts +115 -23
- package/src/__tests__/migration-validate-http.test.ts +105 -80
- package/src/__tests__/migration-wizard.test.ts +133 -27
- package/src/__tests__/non-member-access-request.test.ts +1 -1
- package/src/__tests__/notification-guardian-path.test.ts +1 -1
- package/src/__tests__/oauth-store.test.ts +19 -0
- package/src/__tests__/platform-bash-auto-approve.test.ts +21 -12
- package/src/__tests__/prechat-onboarding-contract.test.ts +31 -7
- package/src/__tests__/pricing.test.ts +68 -4
- package/src/__tests__/process-message-background-slack.test.ts +331 -0
- package/src/__tests__/provider-managed-proxy-integration.test.ts +153 -17
- package/src/__tests__/provider-send-message-override-profile.test.ts +50 -0
- package/src/__tests__/provider-usage-tracking.test.ts +208 -0
- package/src/__tests__/reaction-persistence.test.ts +9 -6
- package/src/__tests__/rebind-secrets-screen.test.ts +53 -16
- package/src/__tests__/recording-handler.test.ts +64 -81
- package/src/__tests__/regenerate-fire-and-forget-trace.test.ts +4 -3
- package/src/__tests__/relay-server.test.ts +18 -13
- package/src/__tests__/require-fresh-approval.test.ts +13 -22
- package/src/__tests__/runtime-attachment-metadata.test.ts +1 -1
- package/src/__tests__/runtime-events-sse-parity.test.ts +3 -4
- package/src/__tests__/runtime-events-sse.test.ts +3 -12
- package/src/__tests__/search-skills-unified.test.ts +9 -15
- package/src/__tests__/secret-ingress-cli.test.ts +2 -5
- package/src/__tests__/secret-ingress-http.test.ts +0 -4
- package/src/__tests__/secret-onetime-send.test.ts +4 -2
- package/src/__tests__/secret-prompt-log-hygiene.test.ts +24 -7
- package/src/__tests__/secret-prompter-channel-fallback.test.ts +42 -47
- package/src/__tests__/secret-response-routing.test.ts +29 -15
- package/src/__tests__/secret-routes-managed-proxy.test.ts +5 -1
- package/src/__tests__/secret-scanner.test.ts +2 -545
- package/src/__tests__/send-endpoint-busy.test.ts +9 -24
- package/src/__tests__/settings-routes.test.ts +1 -1
- package/src/__tests__/shell-credential-ref.test.ts +0 -8
- package/src/__tests__/shell-tool-proxy-mode.test.ts +0 -56
- package/src/__tests__/skill-script-runner-sandbox.test.ts +0 -11
- package/src/__tests__/skill-tool-factory.test.ts +97 -0
- package/src/__tests__/skills-file-content-endpoint.test.ts +9 -30
- package/src/__tests__/skills-files-catalog-fallback.test.ts +11 -17
- package/src/__tests__/slack-inbound-verification.test.ts +1 -62
- package/src/__tests__/subagent-fork-notifications.test.ts +57 -47
- package/src/__tests__/subagent-manager-notify.test.ts +70 -70
- package/src/__tests__/subagent-notify-parent.test.ts +80 -83
- package/src/__tests__/system-prompt.test.ts +115 -13
- package/src/__tests__/terminal-tools.test.ts +0 -89
- package/src/__tests__/thread-backfill.test.ts +945 -31
- package/src/__tests__/tool-domain-event-publisher.test.ts +0 -36
- package/src/__tests__/tool-execute-pipeline.test.ts +0 -6
- package/src/__tests__/tool-execution-abort-cleanup.test.ts +0 -16
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +9 -19
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +4 -7
- package/src/__tests__/tool-executor.test.ts +12 -19
- package/src/__tests__/tool-metrics-listener.test.ts +0 -35
- package/src/__tests__/tool-side-effects-slack-dm.test.ts +1 -0
- package/src/__tests__/tool-trace-listener.test.ts +0 -17
- package/src/__tests__/transfer-progress-screen.test.ts +63 -26
- package/src/__tests__/trusted-contact-lifecycle-notifications.test.ts +2 -149
- package/src/__tests__/trusted-contact-multichannel.test.ts +2 -4
- package/src/__tests__/trusted-contact-verification.test.ts +1 -1
- package/src/__tests__/tts-catalog-parity.test.ts +16 -5
- package/src/__tests__/usage-attribution.test.ts +247 -0
- package/src/__tests__/usage-cli.test.ts +143 -0
- package/src/__tests__/usage-grouped-buckets.test.ts +155 -0
- package/src/__tests__/usage-routes.test.ts +150 -0
- package/src/__tests__/validation-results-screen.test.ts +39 -16
- package/src/__tests__/vbundle-pax-and-symlink.test.ts +12 -3
- package/src/__tests__/vellum-self-knowledge-inline-command.test.ts +49 -137
- package/src/__tests__/verification-control-plane-policy.test.ts +4 -7
- package/src/__tests__/voice-session-bridge.test.ts +5 -5
- package/src/__tests__/workspace-migration-062-drop-memory-v2-edges-json.test.ts +103 -0
- package/src/__tests__/workspace-migration-063-release-notes-dynamic-model-context.test.ts +77 -0
- package/src/__tests__/workspace-migration-064-unwind-main-agent-opus-seed.test.ts +225 -0
- package/src/__tests__/workspace-migration-memory-v2-init.test.ts +8 -30
- package/src/acp/index.ts +0 -15
- package/src/acp/session-manager.ts +37 -34
- package/src/agent/loop.ts +16 -1
- package/src/approvals/AGENTS.md +4 -0
- package/src/approvals/__tests__/guardian-feed-event.test.ts +10 -3
- package/src/approvals/guardian-request-resolvers.ts +10 -2
- package/src/backup/__tests__/backup-worker.test.ts +36 -8
- package/src/backup/__tests__/paths.test.ts +2 -2
- package/src/backup/__tests__/restore.test.ts +45 -28
- package/src/backup/backup-worker.ts +36 -2
- package/src/backup/paths.ts +9 -6
- package/src/browser-session/events.ts +0 -9
- package/src/calls/call-store.ts +1 -34
- package/src/calls/guardian-question-copy.ts +0 -108
- package/src/calls/relay-server.ts +0 -24
- package/src/calls/twilio-rest.ts +0 -38
- package/src/calls/twilio-routes.ts +1 -1
- package/src/calls/voice-session-bridge.ts +7 -38
- package/src/channels/types.ts +1 -36
- package/src/cli/commands/__tests__/cache.test.ts +152 -5
- package/src/cli/commands/__tests__/memory-v2.test.ts +14 -28
- package/src/cli/commands/__tests__/trust.test.ts +21 -387
- package/src/cli/commands/backup.ts +4 -4
- package/src/cli/commands/cache-fs.ts +8 -0
- package/src/cli/commands/cache.ts +153 -82
- package/src/cli/commands/clients.ts +63 -5
- package/src/cli/commands/completions.ts +3 -3
- package/src/cli/commands/contacts.ts +231 -76
- package/src/cli/commands/keys.ts +4 -1
- package/src/cli/commands/memory-v2.ts +24 -52
- package/src/cli/commands/oauth/shared.ts +2 -29
- package/src/cli/commands/pending.ts +102 -0
- package/src/cli/commands/skills.ts +77 -35
- package/src/cli/commands/trust.ts +70 -430
- package/src/cli/commands/usage.ts +25 -16
- package/src/cli/lib/daemon-credential-client.ts +14 -0
- package/src/cli/program.ts +2 -0
- package/src/cli.ts +0 -21
- package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
- package/src/config/bundled-skills/messaging/TOOLS.json +14 -4
- package/src/config/env-registry.ts +12 -2
- package/src/config/env.ts +3 -14
- package/src/config/feature-flag-registry.json +30 -30
- package/src/config/llm-callsite-catalog.ts +12 -0
- package/src/config/llm-context-resolution.ts +80 -0
- package/src/config/llm-resolver.ts +58 -22
- package/src/config/loader.ts +3 -3
- package/src/config/schema.ts +2 -158
- package/src/config/schemas/__tests__/memory-v2.test.ts +1 -0
- package/src/config/schemas/call-site-catalog.ts +271 -0
- package/src/config/schemas/calls.ts +5 -5
- package/src/config/schemas/inference.ts +1 -1
- package/src/config/schemas/ingress.ts +1 -1
- package/src/config/schemas/llm.ts +31 -3
- package/src/config/schemas/memory-retrieval.ts +2 -2
- package/src/config/schemas/memory-v2.ts +9 -0
- package/src/config/schemas/security.ts +1 -42
- package/src/config/schemas/services.ts +6 -6
- package/src/config/schemas/skills.ts +5 -5
- package/src/config/schemas/tts.ts +1 -1
- package/src/config/seed-inference-profiles.ts +117 -0
- package/src/config/skills.ts +0 -90
- package/src/config/types.ts +3 -6
- package/src/contacts/contact-store.ts +0 -17
- package/src/contacts/contacts-write.ts +1 -105
- package/src/context/window-manager.ts +44 -5
- package/src/credential-execution/process-manager.ts +34 -10
- package/src/credential-health/credential-health-service.ts +21 -16
- package/src/daemon/__tests__/conversation-surfaces-launch.test.ts +75 -82
- package/src/daemon/__tests__/daemon-skill-host.test.ts +2 -9
- package/src/daemon/connection-policy.ts +1 -26
- package/src/daemon/conversation-agent-loop-handlers.ts +53 -4
- package/src/daemon/conversation-agent-loop.ts +277 -36
- package/src/daemon/conversation-history.ts +8 -8
- package/src/daemon/conversation-launch.ts +20 -135
- package/src/daemon/conversation-lifecycle.ts +1 -1
- package/src/daemon/conversation-messaging.ts +1 -0
- package/src/daemon/conversation-process.ts +83 -163
- package/src/daemon/conversation-runtime-assembly.ts +219 -76
- package/src/daemon/conversation-slash.ts +47 -5
- package/src/daemon/conversation-store.ts +7 -31
- package/src/daemon/conversation-surfaces.ts +22 -28
- package/src/daemon/conversation-tool-setup.ts +3 -33
- package/src/daemon/conversation-usage.ts +36 -0
- package/src/daemon/conversation.ts +117 -233
- package/src/daemon/daemon-control.ts +3 -71
- package/src/daemon/daemon-skill-host.ts +8 -11
- package/src/daemon/dictation-profile-store.ts +2 -26
- package/src/daemon/first-greeting.ts +44 -156
- package/src/daemon/handlers/config-channels.ts +12 -12
- package/src/daemon/handlers/config-ingress.ts +4 -165
- package/src/daemon/handlers/config-model.ts +1 -1
- package/src/daemon/handlers/config-voice.ts +0 -42
- package/src/daemon/handlers/conversations.ts +11 -190
- package/src/daemon/handlers/recording.ts +26 -158
- package/src/daemon/handlers/shared.ts +23 -71
- package/src/daemon/handlers/skills.ts +42 -93
- package/src/daemon/host-bash-proxy.ts +67 -45
- package/src/daemon/host-browser-proxy.ts +65 -27
- package/src/daemon/host-cu-proxy.ts +40 -39
- package/src/daemon/host-file-proxy.ts +58 -37
- package/src/daemon/host-transfer-proxy.ts +84 -46
- package/src/daemon/lifecycle.ts +49 -15
- package/src/daemon/message-types/conversations.ts +7 -0
- package/src/daemon/message-types/host-bash.ts +1 -0
- package/src/daemon/message-types/host-cu.ts +1 -0
- package/src/daemon/message-types/host-file.ts +1 -0
- package/src/daemon/message-types/host-transfer.ts +1 -0
- package/src/daemon/message-types/messages.ts +10 -9
- package/src/daemon/message-types/workspace.ts +1 -1
- package/src/daemon/process-message.ts +102 -239
- package/src/daemon/server.ts +13 -462
- package/src/daemon/shutdown-handlers.ts +2 -2
- package/src/daemon/tool-side-effects.ts +125 -107
- package/src/daemon/trust-context.ts +13 -0
- package/src/daemon/wake-target-adapter.ts +4 -9
- package/src/events/domain-events.ts +0 -8
- package/src/events/tool-audit-listener.ts +3 -1
- package/src/events/tool-domain-event-publisher.ts +0 -10
- package/src/events/tool-metrics-listener.ts +0 -17
- package/src/events/tool-trace-listener.ts +0 -14
- package/src/filing/filing-service.ts +13 -1
- package/src/heartbeat/__tests__/heartbeat-feed-event.test.ts +6 -2
- package/src/heartbeat/heartbeat-service.ts +23 -5
- package/src/home/__tests__/feed-writer.test.ts +0 -4
- package/src/home/__tests__/relationship-state-writer.test.ts +30 -0
- package/src/home/feed-writer.ts +1 -2
- package/src/home/relationship-state-writer.ts +16 -3
- package/src/ipc/__tests__/browser-ipc.test.ts +2 -12
- package/src/ipc/__tests__/skill-server-bidirectional.test.ts +0 -1
- package/src/ipc/assistant-server.ts +3 -10
- package/src/ipc/routes/__tests__/memory-v2-backfill.test.ts +39 -20
- package/src/ipc/routes/route-adapter.ts +1 -1
- package/src/ipc/routes/trust-rules.test.ts +0 -95
- package/src/ipc/skill-ipc-types.ts +41 -0
- package/src/ipc/skill-routes/__tests__/events-ipc.test.ts +13 -27
- package/src/ipc/skill-routes/__tests__/identity.test.ts +4 -23
- package/src/ipc/skill-routes/events.ts +12 -23
- package/src/ipc/skill-routes/identity.ts +4 -17
- package/src/ipc/skill-routes/index.ts +1 -1
- package/src/ipc/skill-server.ts +6 -39
- package/src/live-voice/__tests__/runtime-websocket-shell.test.ts +0 -8
- package/src/live-voice/protocol.ts +4 -13
- package/src/mcp/manager.ts +0 -5
- package/src/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +55 -0
- package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +127 -0
- package/src/memory/app-git-service.ts +0 -32
- package/src/memory/app-store.ts +154 -0
- package/src/memory/attachments-store.ts +6 -0
- package/src/memory/context-search/sources/memory-v2.ts +578 -0
- package/src/memory/context-search/sources/memory.ts +5 -0
- package/src/memory/context-search/sources/pkb.ts +10 -1
- package/src/memory/context-search/sources/workspace.ts +3 -2
- package/src/memory/conversation-crud.ts +29 -4
- package/src/memory/conversation-disk-view.ts +1 -5
- package/src/memory/conversation-starter-checkpoints.ts +63 -0
- package/src/memory/db-connection.ts +62 -0
- package/src/memory/db-init.ts +14 -0
- package/src/memory/embedding-backend.ts +3 -21
- package/src/memory/embedding-gemini.ts +0 -2
- package/src/memory/embedding-local.ts +6 -6
- package/src/memory/embedding-ollama.ts +6 -6
- package/src/memory/embedding-openai.ts +6 -6
- package/src/memory/embedding-types.ts +21 -0
- package/src/memory/graph/__tests__/conversation-graph-memory-v2-routing.test.ts +3 -7
- package/src/memory/graph/conversation-graph-memory.ts +35 -13
- package/src/memory/graph/injection.test.ts +2 -2
- package/src/memory/graph/injection.ts +1 -1
- package/src/memory/guardian-action-store.ts +0 -83
- package/src/memory/guardian-approvals.ts +0 -48
- package/src/memory/indexer.ts +1 -15
- package/src/memory/job-handlers/conversation-starters.ts +36 -53
- package/src/memory/job-utils.ts +0 -6
- package/src/memory/jobs-store.ts +0 -1
- package/src/memory/jobs-worker.ts +2 -16
- package/src/memory/llm-request-log-store.ts +0 -41
- package/src/memory/llm-usage-store.ts +129 -43
- package/src/memory/memory-v2-activation-log-store.ts +115 -0
- package/src/memory/migrations/233-document-conversations.ts +54 -0
- package/src/memory/migrations/234-memory-v2-activation-logs.ts +55 -0
- package/src/memory/migrations/235-llm-usage-attribution.ts +31 -0
- package/src/memory/migrations/235-slack-compaction-watermark.ts +44 -0
- package/src/memory/migrations/236-tool-invocations-matched-rule-id.ts +26 -0
- package/src/memory/migrations/__tests__/234-memory-v2-activation-logs.test.ts +182 -0
- package/src/memory/migrations/index.ts +14 -0
- package/src/memory/migrations/registry.ts +24 -0
- package/src/memory/raw-query.ts +2 -68
- package/src/memory/schema/conversations.ts +7 -0
- package/src/memory/schema/infrastructure.ts +25 -0
- package/src/memory/search/semantic.ts +5 -16
- package/src/memory/tool-usage-store.ts +2 -0
- package/src/memory/usage-buckets.ts +40 -1
- package/src/memory/usage-grouped-buckets.ts +127 -0
- package/src/memory/v2/__tests__/activation.test.ts +289 -90
- package/src/memory/v2/__tests__/backfill-jobs.test.ts +2 -129
- package/src/memory/v2/__tests__/consolidation-job.test.ts +28 -11
- package/src/memory/v2/__tests__/edge-index.test.ts +278 -0
- package/src/memory/v2/__tests__/injection.test.ts +384 -15
- package/src/memory/v2/__tests__/migration.test.ts +64 -36
- package/src/memory/v2/__tests__/page-store.test.ts +191 -8
- package/src/memory/v2/__tests__/prompts-consolidation.test.ts +181 -0
- package/src/memory/v2/__tests__/skill-store.test.ts +115 -3
- package/src/memory/v2/__tests__/static-context.test.ts +153 -0
- package/src/memory/v2/activation.ts +168 -97
- package/src/memory/v2/backfill-jobs.ts +15 -100
- package/src/memory/v2/consolidation-job.ts +14 -12
- package/src/memory/v2/edge-index.ts +191 -0
- package/src/memory/v2/injection.ts +182 -58
- package/src/memory/v2/migration.ts +57 -64
- package/src/memory/v2/now-text.ts +2 -3
- package/src/memory/v2/page-store.ts +168 -31
- package/src/memory/v2/prompts/consolidation.ts +118 -42
- package/src/memory/v2/prompts/sweep.ts +3 -3
- package/src/memory/v2/skill-store.ts +55 -7
- package/src/memory/v2/static-context.ts +62 -0
- package/src/memory/v2/types.ts +10 -20
- package/src/memory/validation.ts +0 -11
- package/src/messaging/draft-store.ts +0 -6
- package/src/messaging/provider-types.ts +8 -0
- package/src/messaging/provider.ts +7 -0
- package/src/messaging/providers/gmail/client.ts +1 -121
- package/src/messaging/providers/outlook/client.ts +0 -73
- package/src/messaging/providers/slack/__tests__/adapter-mention-rendering.test.ts +226 -0
- package/src/messaging/providers/slack/adapter.ts +122 -21
- package/src/messaging/providers/slack/backfill.test.ts +95 -6
- package/src/messaging/providers/slack/backfill.ts +89 -11
- package/src/messaging/providers/slack/client.ts +10 -124
- package/src/messaging/providers/slack/message-metadata.ts +12 -2
- package/src/messaging/providers/slack/render-transcript.test.ts +56 -0
- package/src/messaging/providers/slack/render-transcript.ts +126 -25
- package/src/messaging/providers/slack/types.ts +1 -0
- package/src/oauth/connection-resolver.test.ts +8 -0
- package/src/oauth/connection-resolver.ts +8 -16
- package/src/oauth/credential-token-resolver.ts +97 -0
- package/src/oauth/manual-token-connection.ts +30 -34
- package/src/oauth/oauth-store.ts +6 -4
- package/src/outbound-proxy/certs.ts +0 -7
- package/src/outbound-proxy/config.ts +0 -74
- package/src/outbound-proxy/health.ts +0 -44
- package/src/outbound-proxy/index.ts +0 -22
- package/src/permissions/approval-provenance.test.ts +184 -0
- package/src/permissions/approval-provenance.ts +70 -0
- package/src/permissions/checker.ts +4 -1
- package/src/permissions/gateway-threshold-reader.ts +4 -1
- package/src/permissions/prompter.ts +9 -2
- package/src/permissions/secret-prompter.ts +21 -48
- package/src/permissions/types.ts +33 -0
- package/src/permissions/workspace-policy.ts +0 -5
- package/src/platform/sync-identity.ts +0 -8
- package/src/plugins/defaults/injectors.ts +69 -2
- package/src/plugins/defaults/overflow-reduce.ts +3 -2
- package/src/plugins/types.ts +8 -0
- package/src/prompts/system-prompt.ts +34 -70
- package/src/prompts/templates/BOOTSTRAP.md +52 -6
- package/src/prompts/update-bulletin-job.ts +2 -0
- package/src/providers/__tests__/retry-callsite.test.ts +138 -1
- package/src/providers/anthropic/client.ts +72 -33
- package/src/providers/call-site-routing.ts +42 -3
- package/src/providers/gemini/client.ts +18 -2
- package/src/providers/managed-proxy/context.ts +0 -5
- package/src/providers/model-catalog.ts +105 -19
- package/src/providers/openai/chat-completions-provider.ts +6 -0
- package/src/providers/openai/responses-provider.ts +7 -1
- package/src/providers/provider-send-message.ts +45 -2
- package/src/providers/ratelimit.ts +7 -2
- package/src/providers/registry.ts +14 -9
- package/src/providers/retry.ts +96 -8
- package/src/providers/types.ts +13 -0
- package/src/providers/usage-tracking.ts +96 -0
- package/src/runtime/AGENTS.md +10 -6
- package/src/runtime/__tests__/agent-wake.test.ts +89 -0
- package/src/runtime/agent-wake.ts +39 -2
- package/src/runtime/assistant-event-hub.ts +541 -45
- package/src/runtime/assistant-event.ts +1 -6
- package/src/runtime/auth/context.ts +0 -9
- package/src/runtime/auth/middleware.ts +1 -1
- package/src/runtime/auth/route-policy.ts +11 -9
- package/src/runtime/auth/token-service.ts +0 -11
- package/src/runtime/channel-approvals.ts +6 -2
- package/src/runtime/channel-verification-service.ts +3 -5
- package/src/runtime/http-errors.ts +0 -34
- package/src/runtime/http-router.ts +6 -3
- package/src/runtime/http-server.ts +22 -82
- package/src/runtime/http-types.ts +5 -0
- package/src/runtime/interactive-ui.ts +0 -1
- package/src/runtime/middleware/auth.ts +0 -20
- package/src/runtime/migrations/__tests__/v1-test-helpers.ts +112 -0
- package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +11 -4
- package/src/runtime/migrations/__tests__/vbundle-builder-v1-shape.test.ts +253 -0
- package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +19 -6
- package/src/runtime/migrations/__tests__/vbundle-legacy-user-md.test.ts +71 -27
- package/src/runtime/migrations/__tests__/vbundle-metadata-merge-integration.test.ts +41 -2
- package/src/runtime/migrations/__tests__/vbundle-streaming-importer.test.ts +143 -79
- package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +143 -23
- package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +2 -2
- package/src/runtime/migrations/__tests__/vbundle-validator-v1-schema.test.ts +371 -0
- package/src/runtime/migrations/migration-transport.ts +46 -13
- package/src/runtime/migrations/migration-wizard.ts +2 -2
- package/src/runtime/migrations/origin-mode.ts +40 -0
- package/src/runtime/migrations/vbundle-builder.ts +133 -79
- package/src/runtime/migrations/vbundle-import-analyzer.ts +9 -7
- package/src/runtime/migrations/vbundle-importer.ts +7 -7
- package/src/runtime/migrations/vbundle-metadata-merge.ts +1 -1
- package/src/runtime/migrations/vbundle-streaming-importer.ts +3 -3
- package/src/runtime/migrations/vbundle-streaming-validator.ts +48 -26
- package/src/runtime/migrations/vbundle-validator.ts +214 -41
- package/src/runtime/pending-interactions.ts +13 -4
- package/src/runtime/routes/__tests__/acp-routes.test.ts +0 -1
- package/src/runtime/routes/__tests__/backup-routes.test.ts +28 -19
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +235 -0
- package/src/runtime/routes/__tests__/llm-call-sites-routes.test.ts +58 -0
- package/src/runtime/routes/__tests__/migration-export-secrets-redacted.test.ts +54 -0
- package/src/runtime/routes/__tests__/migration-import-credential-filter.test.ts +19 -6
- package/src/runtime/routes/__tests__/user-route-dispatcher.test.ts +7 -7
- package/src/runtime/routes/acp-routes.test.ts +0 -3
- package/src/runtime/routes/acp-routes.ts +3 -7
- package/src/runtime/routes/app-management-routes.ts +18 -9
- package/src/runtime/routes/approval-routes.ts +55 -14
- package/src/runtime/routes/avatar-routes.ts +3 -5
- package/src/runtime/routes/browser-routes.ts +1 -15
- package/src/runtime/routes/channel-guardian-routes.ts +1 -5
- package/src/runtime/routes/channel-readiness-routes.ts +3 -7
- package/src/runtime/routes/channel-route-shared.ts +2 -28
- package/src/runtime/routes/client-routes.ts +45 -12
- package/src/runtime/routes/consolidation-routes.ts +115 -0
- package/src/runtime/routes/conversation-list-routes.ts +12 -29
- package/src/runtime/routes/conversation-management-routes.ts +14 -51
- package/src/runtime/routes/conversation-query-routes.ts +120 -8
- package/src/runtime/routes/conversation-routes.ts +44 -528
- package/src/runtime/routes/conversation-starter-routes.ts +19 -40
- package/src/runtime/routes/documents-routes.ts +53 -18
- package/src/runtime/routes/events-routes.ts +59 -91
- package/src/runtime/routes/filing-routes.ts +18 -1
- package/src/runtime/routes/guardian-action-routes.ts +4 -9
- package/src/runtime/routes/host-bash-routes.ts +3 -2
- package/src/runtime/routes/host-browser-routes.ts +9 -33
- package/src/runtime/routes/host-cu-routes.ts +6 -1
- package/src/runtime/routes/host-file-routes.ts +3 -2
- package/src/runtime/routes/host-transfer-routes.ts +11 -15
- package/src/runtime/routes/identity-routes.ts +78 -6
- package/src/runtime/routes/inbound-message-handler.ts +580 -137
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +2 -88
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +3 -0
- package/src/runtime/routes/index.ts +4 -0
- package/src/runtime/routes/integrations/slack/channel.ts +0 -24
- package/src/runtime/routes/llm-call-sites-routes.ts +22 -0
- package/src/runtime/routes/memory-v2-routes.ts +10 -15
- package/src/runtime/routes/migration-routes.ts +188 -31
- package/src/runtime/routes/playground/guard.ts +1 -1
- package/src/runtime/routes/playground/index.ts +0 -2
- package/src/runtime/routes/recording-routes.ts +4 -24
- package/src/runtime/routes/rename-conversation-routes.ts +2 -6
- package/src/runtime/routes/schedule-routes.ts +3 -6
- package/src/runtime/routes/secret-routes.ts +87 -18
- package/src/runtime/routes/settings-routes.ts +29 -28
- package/src/runtime/routes/skills-routes.ts +12 -31
- package/src/runtime/routes/suggest-trust-rule-routes.ts +32 -1
- package/src/runtime/routes/task-routes.ts +6 -6
- package/src/runtime/routes/trust-rules-routes.ts +3 -94
- package/src/runtime/routes/types.ts +4 -4
- package/src/runtime/routes/upgrade-broadcast-routes.ts +3 -10
- package/src/runtime/routes/usage-routes.ts +87 -10
- package/src/runtime/routes/user-routes.ts +17 -31
- package/src/runtime/routes/work-items-routes.ts +1 -4
- package/src/runtime/services/__tests__/analyze-conversation.test.ts +2 -2
- package/src/runtime/services/analyze-conversation.ts +7 -17
- package/src/runtime/services/conversation-serializer.ts +2 -4
- package/src/runtime/verification-outbound-actions.ts +1 -1
- package/src/runtime/verification-rate-limiter.ts +1 -1
- package/src/schedule/schedule-store.ts +0 -16
- package/src/security/secret-scanner.ts +14 -547
- package/src/security/secure-keys.ts +31 -11
- package/src/security/token-manager.ts +7 -3
- package/src/signals/cancel.ts +16 -25
- package/src/signals/conversation-undo.ts +2 -27
- package/src/signals/emit-event.ts +1 -2
- package/src/signals/user-message.ts +108 -22
- package/src/skills/catalog-install.ts +1 -0
- package/src/skills/clawhub.ts +2 -2
- package/src/skills/inline-command-runner.ts +1 -7
- package/src/subagent/manager.ts +67 -84
- package/src/tasks/task-store.ts +1 -28
- package/src/telemetry/types.ts +6 -0
- package/src/telemetry/usage-telemetry-reporter.test.ts +38 -15
- package/src/telemetry/usage-telemetry-reporter.ts +3 -5
- package/src/tools/acp/spawn.test.ts +1 -2
- package/src/tools/acp/steer.test.ts +1 -2
- package/src/tools/browser/__tests__/browser-status.test.ts +44 -127
- package/src/tools/browser/browser-execution.ts +31 -147
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +92 -68
- package/src/tools/browser/cdp-client/factory.ts +48 -76
- package/src/tools/browser/cdp-client/index.ts +1 -14
- package/src/tools/executor.ts +44 -31
- package/src/tools/host-filesystem/edit.ts +3 -2
- package/src/tools/host-filesystem/read.ts +3 -2
- package/src/tools/host-filesystem/transfer.test.ts +45 -42
- package/src/tools/host-filesystem/transfer.ts +4 -3
- package/src/tools/host-filesystem/write.ts +3 -2
- package/src/tools/host-terminal/host-shell.ts +4 -3
- package/src/tools/network/script-proxy/index.ts +1 -10
- package/src/tools/permission-checker.ts +66 -1
- package/src/tools/skills/sandbox-runner.ts +1 -6
- package/src/tools/skills/skill-tool-factory.ts +32 -0
- package/src/tools/terminal/safe-env.ts +1 -0
- package/src/tools/terminal/shell.ts +2 -78
- package/src/tools/types.ts +12 -39
- package/src/tts/__tests__/provider-catalog.test.ts +2 -2
- package/src/tts/provider-catalog.ts +1 -1
- package/src/usage/actors.ts +2 -1
- package/src/usage/attribution.ts +185 -0
- package/src/usage/pricing.ts +166 -0
- package/src/usage/types.ts +14 -0
- package/src/util/json.ts +13 -0
- package/src/util/logger.ts +3 -3
- package/src/util/pricing.ts +50 -3
- package/src/work-items/work-item-runner.ts +15 -42
- package/src/workspace/migrations/050-seed-main-agent-opus-callsite.ts +4 -3
- package/src/workspace/migrations/052-seed-default-inference-profiles.ts +3 -3
- package/src/workspace/migrations/060-memory-v2-init.ts +2 -18
- package/src/workspace/migrations/061-move-backup-key-to-workspace.ts +59 -0
- package/src/workspace/migrations/062-drop-memory-v2-edges-json.ts +27 -0
- package/src/workspace/migrations/063-release-notes-dynamic-model-context.ts +70 -0
- package/src/workspace/migrations/064-unwind-main-agent-opus-seed.ts +64 -0
- package/src/workspace/migrations/registry.ts +8 -0
- package/src/workspace/provider-commit-message-generator.ts +3 -3
- package/src/__tests__/sandbox-diagnostics.test.ts +0 -138
- package/src/__tests__/sandbox-host-parity.test.ts +0 -1024
- package/src/__tests__/secret-detection-handler.test.ts +0 -67
- package/src/__tests__/secret-scanner-executor.test.ts +0 -450
- package/src/__tests__/tcc-sandbox-deny.test.ts +0 -198
- package/src/__tests__/terminal-sandbox.test.ts +0 -374
- package/src/__tests__/tool-notification-listener.test.ts +0 -65
- package/src/context/__tests__/microcompact.test.ts +0 -805
- package/src/context/microcompact.ts +0 -443
- package/src/daemon/handlers/slack-channel-oauth-install.ts +0 -197
- package/src/events/tool-notification-listener.ts +0 -17
- package/src/ipc/routes/__tests__/memory-v2-validate.test.ts +0 -219
- package/src/memory/v2/__tests__/edges.test.ts +0 -435
- package/src/memory/v2/edges.ts +0 -217
- package/src/prompts/__tests__/system-prompt-memory-v2.test.ts +0 -197
- package/src/runtime/__tests__/chrome-extension-registry.test.ts +0 -518
- package/src/runtime/__tests__/client-registry.test.ts +0 -271
- package/src/runtime/chrome-extension-registry.ts +0 -368
- package/src/runtime/client-registry.ts +0 -254
- package/src/runtime/routes/inbound-stages/verification-intercept.ts +0 -329
- package/src/tools/secret-detection-handler.ts +0 -269
- package/src/tools/terminal/backends/native.ts +0 -327
- package/src/tools/terminal/backends/types.ts +0 -37
- package/src/tools/terminal/sandbox-diagnostics.ts +0 -87
- package/src/tools/terminal/sandbox.ts +0 -40
|
@@ -87,6 +87,10 @@ mock.module("../config/env.js", () => ({
|
|
|
87
87
|
setIngressPublicBaseUrl: () => {},
|
|
88
88
|
}));
|
|
89
89
|
|
|
90
|
+
import {
|
|
91
|
+
buildTestManifest,
|
|
92
|
+
defaultV1Options,
|
|
93
|
+
} from "../runtime/migrations/__tests__/v1-test-helpers.js";
|
|
90
94
|
import { buildVBundle } from "../runtime/migrations/vbundle-builder.js";
|
|
91
95
|
import {
|
|
92
96
|
analyzeImport,
|
|
@@ -101,7 +105,6 @@ import {
|
|
|
101
105
|
handleMigrationValidate,
|
|
102
106
|
} from "../runtime/routes/migration-routes.js";
|
|
103
107
|
import { callHandler } from "./helpers/call-route-handler.js";
|
|
104
|
-
|
|
105
108
|
// ---------------------------------------------------------------------------
|
|
106
109
|
// Test fixture data
|
|
107
110
|
// ---------------------------------------------------------------------------
|
|
@@ -233,19 +236,6 @@ function sha256Hex(data: Uint8Array | string): string {
|
|
|
233
236
|
return createHash("sha256").update(data).digest("hex");
|
|
234
237
|
}
|
|
235
238
|
|
|
236
|
-
function canonicalizeJson(obj: unknown): string {
|
|
237
|
-
return JSON.stringify(obj, (_key, value) => {
|
|
238
|
-
if (value && typeof value === "object" && !Array.isArray(value)) {
|
|
239
|
-
const sorted: Record<string, unknown> = {};
|
|
240
|
-
for (const k of Object.keys(value as Record<string, unknown>).sort()) {
|
|
241
|
-
sorted[k] = (value as Record<string, unknown>)[k];
|
|
242
|
-
}
|
|
243
|
-
return sorted;
|
|
244
|
-
}
|
|
245
|
-
return value;
|
|
246
|
-
});
|
|
247
|
-
}
|
|
248
|
-
|
|
249
239
|
interface VBundleFile {
|
|
250
240
|
path: string;
|
|
251
241
|
data: Uint8Array;
|
|
@@ -253,34 +243,26 @@ interface VBundleFile {
|
|
|
253
243
|
|
|
254
244
|
function createValidVBundle(
|
|
255
245
|
files?: VBundleFile[],
|
|
256
|
-
overrides?: Partial<{
|
|
257
|
-
schema_version: string;
|
|
258
|
-
source: string;
|
|
259
|
-
description: string;
|
|
260
|
-
}>,
|
|
246
|
+
overrides?: Partial<{ schema_version: number }>,
|
|
261
247
|
): Uint8Array {
|
|
262
248
|
const dbData = new Uint8Array([0x53, 0x51, 0x4c, 0x69, 0x74, 0x65]);
|
|
263
249
|
const bundleFiles = files ?? [{ path: "data/db/assistant.db", data: dbData }];
|
|
264
250
|
|
|
265
|
-
const
|
|
251
|
+
const contents = bundleFiles.map((f) => ({
|
|
266
252
|
path: f.path,
|
|
267
253
|
sha256: sha256Hex(f.data),
|
|
268
|
-
|
|
254
|
+
size_bytes: f.data.length,
|
|
269
255
|
}));
|
|
270
256
|
|
|
271
|
-
const
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
const manifest = {
|
|
281
|
-
...manifestWithoutChecksum,
|
|
282
|
-
manifest_sha256: manifestSha256,
|
|
283
|
-
};
|
|
257
|
+
const manifest = buildTestManifest({
|
|
258
|
+
contents,
|
|
259
|
+
overrides: {
|
|
260
|
+
bundle_id: "00000000-0000-4000-8000-000000000000",
|
|
261
|
+
...(overrides?.schema_version !== undefined
|
|
262
|
+
? { schema_version: overrides.schema_version }
|
|
263
|
+
: {}),
|
|
264
|
+
},
|
|
265
|
+
});
|
|
284
266
|
const manifestData = new TextEncoder().encode(JSON.stringify(manifest));
|
|
285
267
|
|
|
286
268
|
const tarEntries = [
|
|
@@ -374,85 +356,22 @@ interface ImportCommitResponse {
|
|
|
374
356
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
375
357
|
|
|
376
358
|
describe("schema version compatibility", () => {
|
|
377
|
-
test("bundle with schema_version 1
|
|
378
|
-
const vbundle = createValidVBundle(
|
|
379
|
-
schema_version: "1.0",
|
|
380
|
-
});
|
|
381
|
-
const result = validateVBundle(vbundle);
|
|
382
|
-
|
|
383
|
-
expect(result.is_valid).toBe(true);
|
|
384
|
-
expect(result.manifest?.schema_version).toBe("1.0");
|
|
385
|
-
});
|
|
386
|
-
|
|
387
|
-
test("bundle with schema_version 2.0 validates successfully (forward compat)", () => {
|
|
388
|
-
// A structurally valid bundle with a future version should still pass
|
|
389
|
-
// validation because the schema_version field is a string and the
|
|
390
|
-
// archive structure is unchanged.
|
|
391
|
-
const vbundle = createValidVBundle(undefined, {
|
|
392
|
-
schema_version: "2.0",
|
|
393
|
-
});
|
|
359
|
+
test("bundle with schema_version 1 validates successfully", () => {
|
|
360
|
+
const vbundle = createValidVBundle();
|
|
394
361
|
const result = validateVBundle(vbundle);
|
|
395
362
|
|
|
396
363
|
expect(result.is_valid).toBe(true);
|
|
397
|
-
expect(result.manifest?.schema_version).toBe(
|
|
364
|
+
expect(result.manifest?.schema_version).toBe(1);
|
|
398
365
|
});
|
|
399
366
|
|
|
400
|
-
test("bundle with schema_version
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
367
|
+
test("bundle with schema_version != 1 is rejected by the v1 validator", () => {
|
|
368
|
+
// The v1 validator pins `schema_version: z.literal(1)`. Bundles that
|
|
369
|
+
// claim a different schema version are rejected outright; this used to
|
|
370
|
+
// be permissive when schema_version was a free-form string.
|
|
371
|
+
const vbundle = createValidVBundle(undefined, { schema_version: 2 });
|
|
404
372
|
const result = validateVBundle(vbundle);
|
|
405
373
|
|
|
406
|
-
expect(result.is_valid).toBe(
|
|
407
|
-
expect(result.manifest?.schema_version).toBe("99.0");
|
|
408
|
-
});
|
|
409
|
-
|
|
410
|
-
test("bundle with arbitrary version string validates when structurally valid", () => {
|
|
411
|
-
const vbundle = createValidVBundle(undefined, {
|
|
412
|
-
schema_version: "alpha-preview-3",
|
|
413
|
-
});
|
|
414
|
-
const result = validateVBundle(vbundle);
|
|
415
|
-
|
|
416
|
-
expect(result.is_valid).toBe(true);
|
|
417
|
-
expect(result.manifest?.schema_version).toBe("alpha-preview-3");
|
|
418
|
-
});
|
|
419
|
-
|
|
420
|
-
test("future-versioned bundle can be imported successfully", () => {
|
|
421
|
-
const newDbData = new Uint8Array([0xfa, 0xce, 0xb0, 0x0c]);
|
|
422
|
-
const vbundle = createValidVBundle(
|
|
423
|
-
[{ path: "data/db/assistant.db", data: newDbData }],
|
|
424
|
-
{ schema_version: "3.0" },
|
|
425
|
-
);
|
|
426
|
-
|
|
427
|
-
const resolver = new DefaultPathResolver(testDir);
|
|
428
|
-
const result = commitImport({
|
|
429
|
-
archiveData: vbundle,
|
|
430
|
-
pathResolver: resolver,
|
|
431
|
-
});
|
|
432
|
-
|
|
433
|
-
expect(result.ok).toBe(true);
|
|
434
|
-
if (result.ok) {
|
|
435
|
-
expect(result.report.manifest.schema_version).toBe("3.0");
|
|
436
|
-
expect(result.report.success).toBe(true);
|
|
437
|
-
}
|
|
438
|
-
});
|
|
439
|
-
|
|
440
|
-
test("future-versioned bundle shows correct version in preflight report", () => {
|
|
441
|
-
const vbundle = createValidVBundle(undefined, {
|
|
442
|
-
schema_version: "5.0-beta",
|
|
443
|
-
});
|
|
444
|
-
|
|
445
|
-
const resolver = new DefaultPathResolver(testDir);
|
|
446
|
-
const validationResult = validateVBundle(vbundle);
|
|
447
|
-
expect(validationResult.manifest).toBeDefined();
|
|
448
|
-
|
|
449
|
-
const report = analyzeImport({
|
|
450
|
-
manifest: validationResult.manifest!,
|
|
451
|
-
pathResolver: resolver,
|
|
452
|
-
});
|
|
453
|
-
|
|
454
|
-
expect(report.manifest.schema_version).toBe("5.0-beta");
|
|
455
|
-
expect(report.can_import).toBe(true);
|
|
374
|
+
expect(result.is_valid).toBe(false);
|
|
456
375
|
});
|
|
457
376
|
});
|
|
458
377
|
|
|
@@ -541,20 +460,19 @@ describe("missing or malformed version fields", () => {
|
|
|
541
460
|
);
|
|
542
461
|
});
|
|
543
462
|
|
|
544
|
-
test("
|
|
545
|
-
// The
|
|
546
|
-
//
|
|
547
|
-
const vbundle = createValidVBundle(undefined, { schema_version:
|
|
463
|
+
test("zero schema_version is rejected by the v1 validator", () => {
|
|
464
|
+
// The v1 schema pins schema_version to the literal `1`; any other
|
|
465
|
+
// numeric value (including 0) is rejected.
|
|
466
|
+
const vbundle = createValidVBundle(undefined, { schema_version: 0 });
|
|
548
467
|
const result = validateVBundle(vbundle);
|
|
549
468
|
|
|
550
|
-
expect(result.is_valid).toBe(
|
|
551
|
-
expect(result.manifest?.schema_version).toBe("");
|
|
469
|
+
expect(result.is_valid).toBe(false);
|
|
552
470
|
});
|
|
553
471
|
|
|
554
472
|
test("missing created_at produces MANIFEST_SCHEMA_ERROR", () => {
|
|
555
473
|
const dbData = new Uint8Array([0x53, 0x51, 0x4c, 0x69, 0x74, 0x65]);
|
|
556
474
|
const manifestObj = {
|
|
557
|
-
schema_version:
|
|
475
|
+
schema_version: 1,
|
|
558
476
|
// created_at intentionally omitted
|
|
559
477
|
files: [
|
|
560
478
|
{
|
|
@@ -572,15 +490,20 @@ describe("missing or malformed version fields", () => {
|
|
|
572
490
|
const result = validateVBundle(vbundle);
|
|
573
491
|
|
|
574
492
|
expect(result.is_valid).toBe(false);
|
|
493
|
+
// The v1 schema reports errors per missing required field; we just
|
|
494
|
+
// assert at least one MANIFEST_SCHEMA_ERROR fires for any of the
|
|
495
|
+
// newly-required fields. The legacy assertion looking for "created_at"
|
|
496
|
+
// in the message specifically is no longer meaningful — the validator
|
|
497
|
+
// surfaces the first missing field it finds, which under the v1
|
|
498
|
+
// schema may be `bundle_id`, `assistant`, `origin`, etc.
|
|
575
499
|
const error = result.errors.find((e) => e.code === "MANIFEST_SCHEMA_ERROR");
|
|
576
500
|
expect(error).toBeDefined();
|
|
577
|
-
expect(error!.message).toContain("created_at");
|
|
578
501
|
});
|
|
579
502
|
|
|
580
503
|
test("missing files array produces MANIFEST_SCHEMA_ERROR", () => {
|
|
581
504
|
const dbData = new Uint8Array([0x53, 0x51, 0x4c, 0x69, 0x74, 0x65]);
|
|
582
505
|
const manifestObj = {
|
|
583
|
-
schema_version:
|
|
506
|
+
schema_version: 1,
|
|
584
507
|
created_at: new Date().toISOString(),
|
|
585
508
|
// files intentionally omitted
|
|
586
509
|
manifest_sha256: "placeholder",
|
|
@@ -600,7 +523,7 @@ describe("missing or malformed version fields", () => {
|
|
|
600
523
|
test("missing manifest_sha256 produces MANIFEST_SCHEMA_ERROR", () => {
|
|
601
524
|
const dbData = new Uint8Array([0x53, 0x51, 0x4c, 0x69, 0x74, 0x65]);
|
|
602
525
|
const manifestObj = {
|
|
603
|
-
schema_version:
|
|
526
|
+
schema_version: 1,
|
|
604
527
|
created_at: new Date().toISOString(),
|
|
605
528
|
files: [
|
|
606
529
|
{
|
|
@@ -626,7 +549,7 @@ describe("missing or malformed version fields", () => {
|
|
|
626
549
|
test("file entry missing sha256 produces MANIFEST_SCHEMA_ERROR", () => {
|
|
627
550
|
const dbData = new Uint8Array([0x53, 0x51, 0x4c, 0x69, 0x74, 0x65]);
|
|
628
551
|
const manifestObj = {
|
|
629
|
-
schema_version:
|
|
552
|
+
schema_version: 1,
|
|
630
553
|
created_at: new Date().toISOString(),
|
|
631
554
|
files: [
|
|
632
555
|
{
|
|
@@ -652,7 +575,7 @@ describe("missing or malformed version fields", () => {
|
|
|
652
575
|
test("file entry with negative size produces MANIFEST_SCHEMA_ERROR", () => {
|
|
653
576
|
const dbData = new Uint8Array([0x53, 0x51, 0x4c, 0x69, 0x74, 0x65]);
|
|
654
577
|
const manifestObj = {
|
|
655
|
-
schema_version:
|
|
578
|
+
schema_version: 1,
|
|
656
579
|
created_at: new Date().toISOString(),
|
|
657
580
|
files: [
|
|
658
581
|
{
|
|
@@ -744,7 +667,10 @@ describe("round-trip: export -> validate -> preflight -> import", () => {
|
|
|
744
667
|
body: toArrayBuffer(archiveData),
|
|
745
668
|
},
|
|
746
669
|
);
|
|
747
|
-
const preflightRes = await callHandler(
|
|
670
|
+
const preflightRes = await callHandler(
|
|
671
|
+
handleMigrationImportPreflight,
|
|
672
|
+
preflightReq,
|
|
673
|
+
);
|
|
748
674
|
const preflightBody = (await preflightRes.json()) as ImportDryRunResponse;
|
|
749
675
|
|
|
750
676
|
expect(preflightRes.status).toBe(200);
|
|
@@ -793,20 +719,16 @@ describe("round-trip: export -> validate -> preflight -> import", () => {
|
|
|
793
719
|
{ path: "data/db/assistant.db", data: dbData },
|
|
794
720
|
{ path: "config/settings.json", data: configData },
|
|
795
721
|
],
|
|
796
|
-
|
|
797
|
-
source: "round-trip-test",
|
|
798
|
-
description: "Testing round-trip",
|
|
722
|
+
...defaultV1Options(),
|
|
799
723
|
});
|
|
800
724
|
|
|
801
|
-
expect(manifest.schema_version).toBe(
|
|
802
|
-
expect(manifest.
|
|
725
|
+
expect(manifest.schema_version).toBe(1);
|
|
726
|
+
expect(manifest.contents).toHaveLength(2);
|
|
803
727
|
|
|
804
728
|
// Step 2: Validate
|
|
805
729
|
const validationResult = validateVBundle(archive);
|
|
806
730
|
expect(validationResult.is_valid).toBe(true);
|
|
807
|
-
expect(validationResult.manifest?.
|
|
808
|
-
manifest.manifest_sha256,
|
|
809
|
-
);
|
|
731
|
+
expect(validationResult.manifest?.checksum).toBe(manifest.checksum);
|
|
810
732
|
|
|
811
733
|
// Step 3: Analyze (preflight)
|
|
812
734
|
const resolver = new DefaultPathResolver(testDir);
|
|
@@ -827,7 +749,7 @@ describe("round-trip: export -> validate -> preflight -> import", () => {
|
|
|
827
749
|
expect(commitResult.ok).toBe(true);
|
|
828
750
|
if (commitResult.ok) {
|
|
829
751
|
expect(commitResult.report.success).toBe(true);
|
|
830
|
-
expect(commitResult.report.manifest.schema_version).toBe(
|
|
752
|
+
expect(commitResult.report.manifest.schema_version).toBe(1);
|
|
831
753
|
expect(commitResult.report.summary.total_files).toBe(2);
|
|
832
754
|
|
|
833
755
|
// Verify data on disk matches what we built
|
|
@@ -848,14 +770,15 @@ describe("round-trip: export -> validate -> preflight -> import", () => {
|
|
|
848
770
|
const exportRes = await callHandler(handleMigrationExport, exportReq);
|
|
849
771
|
const archiveData = new Uint8Array(await exportRes.arrayBuffer());
|
|
850
772
|
|
|
851
|
-
// The X-Vbundle-Manifest-Sha256 response header should match
|
|
852
|
-
// the
|
|
773
|
+
// The X-Vbundle-Manifest-Sha256 response header value should match
|
|
774
|
+
// the manifest's `checksum` field inside the archive (the legacy
|
|
775
|
+
// header name is preserved across the v1 rename).
|
|
853
776
|
const headerSha = exportRes.headers.get("X-Vbundle-Manifest-Sha256");
|
|
854
777
|
expect(headerSha).toBeDefined();
|
|
855
778
|
|
|
856
779
|
const validationResult = validateVBundle(archiveData);
|
|
857
780
|
expect(validationResult.is_valid).toBe(true);
|
|
858
|
-
expect(validationResult.manifest?.
|
|
781
|
+
expect(validationResult.manifest?.checksum).toBe(headerSha!);
|
|
859
782
|
});
|
|
860
783
|
});
|
|
861
784
|
|
|
@@ -967,7 +890,7 @@ describe("partial failure scenarios", () => {
|
|
|
967
890
|
// Create bundle with corrupted checksum
|
|
968
891
|
const dbData = new Uint8Array([0x53, 0x51, 0x4c, 0x69, 0x74, 0x65]);
|
|
969
892
|
const manifest = {
|
|
970
|
-
schema_version:
|
|
893
|
+
schema_version: 1,
|
|
971
894
|
created_at: new Date().toISOString(),
|
|
972
895
|
files: [
|
|
973
896
|
{
|
|
@@ -1015,7 +938,7 @@ describe("edge cases", () => {
|
|
|
1015
938
|
|
|
1016
939
|
const result = validateVBundle(vbundle);
|
|
1017
940
|
expect(result.is_valid).toBe(true);
|
|
1018
|
-
expect(result.manifest?.
|
|
941
|
+
expect(result.manifest?.contents[0].size_bytes).toBe(0);
|
|
1019
942
|
|
|
1020
943
|
// Import should also succeed
|
|
1021
944
|
const resolver = new DefaultPathResolver(testDir);
|
|
@@ -1042,7 +965,7 @@ describe("edge cases", () => {
|
|
|
1042
965
|
|
|
1043
966
|
const result = validateVBundle(vbundle);
|
|
1044
967
|
expect(result.is_valid).toBe(true);
|
|
1045
|
-
expect(result.manifest?.
|
|
968
|
+
expect(result.manifest?.contents[0].size_bytes).toBe(100 * 1024);
|
|
1046
969
|
});
|
|
1047
970
|
|
|
1048
971
|
test("bundle with duplicate archive paths uses last occurrence in tar", () => {
|
|
@@ -1051,26 +974,17 @@ describe("edge cases", () => {
|
|
|
1051
974
|
const dbData1 = new Uint8Array([0x01, 0x02, 0x03]);
|
|
1052
975
|
const dbData2 = new Uint8Array([0x04, 0x05, 0x06]);
|
|
1053
976
|
|
|
1054
|
-
// Build a valid manifest that references the second data
|
|
1055
|
-
const
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
source: "test",
|
|
1066
|
-
description: "Duplicate path test",
|
|
1067
|
-
files: fileEntries,
|
|
1068
|
-
};
|
|
1069
|
-
const manifestSha256 = sha256Hex(canonicalizeJson(manifestWithoutChecksum));
|
|
1070
|
-
const manifest = {
|
|
1071
|
-
...manifestWithoutChecksum,
|
|
1072
|
-
manifest_sha256: manifestSha256,
|
|
1073
|
-
};
|
|
977
|
+
// Build a valid v1 manifest that references the second data.
|
|
978
|
+
const manifest = buildTestManifest({
|
|
979
|
+
contents: [
|
|
980
|
+
{
|
|
981
|
+
path: "data/db/assistant.db",
|
|
982
|
+
sha256: sha256Hex(dbData2),
|
|
983
|
+
size_bytes: dbData2.length,
|
|
984
|
+
},
|
|
985
|
+
],
|
|
986
|
+
overrides: { bundle_id: "00000000-0000-4000-8000-000000000000" },
|
|
987
|
+
});
|
|
1074
988
|
const manifestData = new TextEncoder().encode(JSON.stringify(manifest));
|
|
1075
989
|
|
|
1076
990
|
// Build tar with duplicate data/db/assistant.db entries
|
|
@@ -1093,22 +1007,16 @@ describe("edge cases", () => {
|
|
|
1093
1007
|
const wrongChecksum =
|
|
1094
1008
|
"0000000000000000000000000000000000000000000000000000000000000000";
|
|
1095
1009
|
|
|
1096
|
-
const
|
|
1097
|
-
|
|
1098
|
-
created_at: new Date().toISOString(),
|
|
1099
|
-
files: [
|
|
1010
|
+
const manifest = buildTestManifest({
|
|
1011
|
+
contents: [
|
|
1100
1012
|
{
|
|
1101
1013
|
path: "data/db/assistant.db",
|
|
1102
1014
|
sha256: wrongChecksum,
|
|
1103
|
-
|
|
1015
|
+
size_bytes: dbData.length,
|
|
1104
1016
|
},
|
|
1105
1017
|
],
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
const manifest = {
|
|
1109
|
-
...manifestWithoutChecksum,
|
|
1110
|
-
manifest_sha256: manifestSha256,
|
|
1111
|
-
};
|
|
1018
|
+
overrides: { bundle_id: "00000000-0000-4000-8000-000000000000" },
|
|
1019
|
+
});
|
|
1112
1020
|
const manifestData = new TextEncoder().encode(JSON.stringify(manifest));
|
|
1113
1021
|
|
|
1114
1022
|
const tar = createTarArchive([
|
|
@@ -1132,27 +1040,21 @@ describe("edge cases", () => {
|
|
|
1132
1040
|
const dbData = new Uint8Array([0x53, 0x51, 0x4c, 0x69, 0x74, 0x65]);
|
|
1133
1041
|
const ghostSha = sha256Hex(new TextEncoder().encode("ghost-content"));
|
|
1134
1042
|
|
|
1135
|
-
const
|
|
1136
|
-
|
|
1137
|
-
created_at: new Date().toISOString(),
|
|
1138
|
-
files: [
|
|
1043
|
+
const manifest = buildTestManifest({
|
|
1044
|
+
contents: [
|
|
1139
1045
|
{
|
|
1140
1046
|
path: "data/db/assistant.db",
|
|
1141
1047
|
sha256: sha256Hex(dbData),
|
|
1142
|
-
|
|
1048
|
+
size_bytes: dbData.length,
|
|
1143
1049
|
},
|
|
1144
1050
|
{
|
|
1145
1051
|
path: "data/extra/ghost.bin",
|
|
1146
1052
|
sha256: ghostSha,
|
|
1147
|
-
|
|
1053
|
+
size_bytes: 13,
|
|
1148
1054
|
},
|
|
1149
1055
|
],
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
const manifest = {
|
|
1153
|
-
...manifestWithoutChecksum,
|
|
1154
|
-
manifest_sha256: manifestSha256,
|
|
1155
|
-
};
|
|
1056
|
+
overrides: { bundle_id: "00000000-0000-4000-8000-000000000000" },
|
|
1057
|
+
});
|
|
1156
1058
|
const manifestData = new TextEncoder().encode(JSON.stringify(manifest));
|
|
1157
1059
|
|
|
1158
1060
|
const tar = createTarArchive([
|
|
@@ -1172,20 +1074,16 @@ describe("edge cases", () => {
|
|
|
1172
1074
|
expect(missingError!.message).toContain("data/extra/ghost.bin");
|
|
1173
1075
|
});
|
|
1174
1076
|
|
|
1175
|
-
test("bundle with
|
|
1176
|
-
//
|
|
1177
|
-
//
|
|
1178
|
-
//
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
const manifest = {
|
|
1186
|
-
...manifestWithoutChecksum,
|
|
1187
|
-
manifest_sha256: manifestSha256,
|
|
1188
|
-
};
|
|
1077
|
+
test("bundle with empty contents is rejected by the v1 contents refine", () => {
|
|
1078
|
+
// The v1 schema's `.refine()` requires `data/db/assistant.db` (legacy)
|
|
1079
|
+
// or its `workspace/`-prefixed counterpart. A manifest declaring an
|
|
1080
|
+
// empty contents array is valid at the field level but rejected by
|
|
1081
|
+
// the refine.
|
|
1082
|
+
const dbBytes = new Uint8Array([0x53, 0x51, 0x4c, 0x69, 0x74, 0x65]);
|
|
1083
|
+
const manifest = buildTestManifest({
|
|
1084
|
+
contents: [],
|
|
1085
|
+
overrides: { bundle_id: "00000000-0000-4000-8000-000000000000" },
|
|
1086
|
+
});
|
|
1189
1087
|
const manifestData = new TextEncoder().encode(JSON.stringify(manifest));
|
|
1190
1088
|
|
|
1191
1089
|
const tar = createTarArchive([
|
|
@@ -1194,7 +1092,9 @@ describe("edge cases", () => {
|
|
|
1194
1092
|
const vbundle = gzipSync(tar);
|
|
1195
1093
|
const result = validateVBundle(vbundle);
|
|
1196
1094
|
|
|
1197
|
-
expect(result.is_valid).toBe(
|
|
1095
|
+
expect(result.is_valid).toBe(false);
|
|
1096
|
+
// Sanity: this manifest WOULD be valid if it included the DB entry.
|
|
1097
|
+
expect(dbBytes).toBeDefined();
|
|
1198
1098
|
});
|
|
1199
1099
|
|
|
1200
1100
|
test("completely empty gzip content (no tar entries) fails gracefully", () => {
|
|
@@ -1244,24 +1144,16 @@ describe("edge cases", () => {
|
|
|
1244
1144
|
const extraData = new TextEncoder().encode("bonus content");
|
|
1245
1145
|
|
|
1246
1146
|
// Manifest only declares the db file
|
|
1247
|
-
const
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
source: "test",
|
|
1258
|
-
files: fileEntries,
|
|
1259
|
-
};
|
|
1260
|
-
const manifestSha256 = sha256Hex(canonicalizeJson(manifestWithoutChecksum));
|
|
1261
|
-
const manifest = {
|
|
1262
|
-
...manifestWithoutChecksum,
|
|
1263
|
-
manifest_sha256: manifestSha256,
|
|
1264
|
-
};
|
|
1147
|
+
const manifest = buildTestManifest({
|
|
1148
|
+
contents: [
|
|
1149
|
+
{
|
|
1150
|
+
path: "data/db/assistant.db",
|
|
1151
|
+
sha256: sha256Hex(dbData),
|
|
1152
|
+
size_bytes: dbData.length,
|
|
1153
|
+
},
|
|
1154
|
+
],
|
|
1155
|
+
overrides: { bundle_id: "00000000-0000-4000-8000-000000000000" },
|
|
1156
|
+
});
|
|
1265
1157
|
const manifestData = new TextEncoder().encode(JSON.stringify(manifest));
|
|
1266
1158
|
|
|
1267
1159
|
// Archive has an extra file not in the manifest
|
|
@@ -1310,16 +1202,29 @@ describe("diagnostic quality", () => {
|
|
|
1310
1202
|
const badHash =
|
|
1311
1203
|
"cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc";
|
|
1312
1204
|
const manifest = {
|
|
1313
|
-
schema_version:
|
|
1205
|
+
schema_version: 1,
|
|
1206
|
+
bundle_id: "00000000-0000-4000-8000-000000000000",
|
|
1314
1207
|
created_at: new Date().toISOString(),
|
|
1315
|
-
|
|
1208
|
+
assistant: { id: "self", name: "Test", runtime_version: "0.0.0-test" },
|
|
1209
|
+
origin: { mode: "self-hosted-local" as const },
|
|
1210
|
+
compatibility: {
|
|
1211
|
+
min_runtime_version: "0.0.0-test",
|
|
1212
|
+
max_runtime_version: null,
|
|
1213
|
+
},
|
|
1214
|
+
contents: [
|
|
1316
1215
|
{
|
|
1317
1216
|
path: "data/db/assistant.db",
|
|
1318
1217
|
sha256: sha256Hex(dbData),
|
|
1319
|
-
|
|
1218
|
+
size_bytes: dbData.length,
|
|
1320
1219
|
},
|
|
1321
1220
|
],
|
|
1322
|
-
|
|
1221
|
+
checksum: badHash,
|
|
1222
|
+
secrets_redacted: false,
|
|
1223
|
+
export_options: {
|
|
1224
|
+
include_logs: false,
|
|
1225
|
+
include_browser_state: false,
|
|
1226
|
+
include_memory_vectors: false,
|
|
1227
|
+
},
|
|
1323
1228
|
};
|
|
1324
1229
|
const manifestData = new TextEncoder().encode(JSON.stringify(manifest));
|
|
1325
1230
|
const tar = createTarArchive([
|
|
@@ -1342,22 +1247,16 @@ describe("diagnostic quality", () => {
|
|
|
1342
1247
|
const wrongSha =
|
|
1343
1248
|
"dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd";
|
|
1344
1249
|
|
|
1345
|
-
const
|
|
1346
|
-
|
|
1347
|
-
created_at: new Date().toISOString(),
|
|
1348
|
-
files: [
|
|
1250
|
+
const manifest = buildTestManifest({
|
|
1251
|
+
contents: [
|
|
1349
1252
|
{
|
|
1350
1253
|
path: "data/db/assistant.db",
|
|
1351
1254
|
sha256: wrongSha,
|
|
1352
|
-
|
|
1255
|
+
size_bytes: dbData.length,
|
|
1353
1256
|
},
|
|
1354
1257
|
],
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
const manifest = {
|
|
1358
|
-
...manifestWithoutChecksum,
|
|
1359
|
-
manifest_sha256: manifestSha256,
|
|
1360
|
-
};
|
|
1258
|
+
overrides: { bundle_id: "00000000-0000-4000-8000-000000000000" },
|
|
1259
|
+
});
|
|
1361
1260
|
const manifestData = new TextEncoder().encode(JSON.stringify(manifest));
|
|
1362
1261
|
const tar = createTarArchive([
|
|
1363
1262
|
{ name: "manifest.json", data: manifestData },
|
|
@@ -1376,22 +1275,16 @@ describe("diagnostic quality", () => {
|
|
|
1376
1275
|
test("FILE_SIZE_MISMATCH includes file path and both sizes", () => {
|
|
1377
1276
|
const dbData = new Uint8Array([0x53, 0x51, 0x4c, 0x69, 0x74, 0x65]);
|
|
1378
1277
|
|
|
1379
|
-
const
|
|
1380
|
-
|
|
1381
|
-
created_at: new Date().toISOString(),
|
|
1382
|
-
files: [
|
|
1278
|
+
const manifest = buildTestManifest({
|
|
1279
|
+
contents: [
|
|
1383
1280
|
{
|
|
1384
1281
|
path: "data/db/assistant.db",
|
|
1385
1282
|
sha256: sha256Hex(dbData),
|
|
1386
|
-
|
|
1283
|
+
size_bytes: 99999,
|
|
1387
1284
|
},
|
|
1388
1285
|
],
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
const manifest = {
|
|
1392
|
-
...manifestWithoutChecksum,
|
|
1393
|
-
manifest_sha256: manifestSha256,
|
|
1394
|
-
};
|
|
1286
|
+
overrides: { bundle_id: "00000000-0000-4000-8000-000000000000" },
|
|
1287
|
+
});
|
|
1395
1288
|
const manifestData = new TextEncoder().encode(JSON.stringify(manifest));
|
|
1396
1289
|
const tar = createTarArchive([
|
|
1397
1290
|
{ name: "manifest.json", data: manifestData },
|
|
@@ -1461,27 +1354,21 @@ describe("multiple error accumulation", () => {
|
|
|
1461
1354
|
|
|
1462
1355
|
// Manifest declares correct db checksum but wrong config checksum and
|
|
1463
1356
|
// also wrong config size
|
|
1464
|
-
const
|
|
1465
|
-
|
|
1466
|
-
created_at: new Date().toISOString(),
|
|
1467
|
-
files: [
|
|
1357
|
+
const manifest = buildTestManifest({
|
|
1358
|
+
contents: [
|
|
1468
1359
|
{
|
|
1469
1360
|
path: "data/db/assistant.db",
|
|
1470
1361
|
sha256: sha256Hex(dbData),
|
|
1471
|
-
|
|
1362
|
+
size_bytes: dbData.length,
|
|
1472
1363
|
},
|
|
1473
1364
|
{
|
|
1474
1365
|
path: "config/settings.json",
|
|
1475
1366
|
sha256: wrongSha,
|
|
1476
|
-
|
|
1367
|
+
size_bytes: 999,
|
|
1477
1368
|
},
|
|
1478
1369
|
],
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
const manifest = {
|
|
1482
|
-
...manifestWithoutChecksum,
|
|
1483
|
-
manifest_sha256: manifestSha256,
|
|
1484
|
-
};
|
|
1370
|
+
overrides: { bundle_id: "00000000-0000-4000-8000-000000000000" },
|
|
1371
|
+
});
|
|
1485
1372
|
const manifestData = new TextEncoder().encode(JSON.stringify(manifest));
|
|
1486
1373
|
|
|
1487
1374
|
const tar = createTarArchive([
|
|
@@ -1535,8 +1422,8 @@ describe("multiple error accumulation", () => {
|
|
|
1535
1422
|
// ═══════════════════════════════════════════════════════════════════════════
|
|
1536
1423
|
|
|
1537
1424
|
describe("builder -> validator consistency", () => {
|
|
1538
|
-
test("buildVBundle
|
|
1539
|
-
const testCases = [
|
|
1425
|
+
test("buildVBundle archives across content shapes pass validation", () => {
|
|
1426
|
+
const testCases: Array<{ files: VBundleFile[] }> = [
|
|
1540
1427
|
{
|
|
1541
1428
|
files: [
|
|
1542
1429
|
{
|
|
@@ -1544,7 +1431,6 @@ describe("builder -> validator consistency", () => {
|
|
|
1544
1431
|
data: new Uint8Array([0x01]),
|
|
1545
1432
|
},
|
|
1546
1433
|
],
|
|
1547
|
-
schemaVersion: "1.0",
|
|
1548
1434
|
},
|
|
1549
1435
|
{
|
|
1550
1436
|
files: [
|
|
@@ -1557,7 +1443,6 @@ describe("builder -> validator consistency", () => {
|
|
|
1557
1443
|
data: new TextEncoder().encode('{"big":"config","keys":[1,2,3]}'),
|
|
1558
1444
|
},
|
|
1559
1445
|
],
|
|
1560
|
-
schemaVersion: "2.0",
|
|
1561
1446
|
},
|
|
1562
1447
|
{
|
|
1563
1448
|
files: [
|
|
@@ -1566,23 +1451,22 @@ describe("builder -> validator consistency", () => {
|
|
|
1566
1451
|
data: new Uint8Array(0), // empty
|
|
1567
1452
|
},
|
|
1568
1453
|
],
|
|
1569
|
-
schemaVersion: "0.1-alpha",
|
|
1570
1454
|
},
|
|
1571
1455
|
];
|
|
1572
1456
|
|
|
1573
1457
|
for (const tc of testCases) {
|
|
1574
1458
|
const { archive } = buildVBundle({
|
|
1575
1459
|
files: tc.files,
|
|
1576
|
-
|
|
1460
|
+
...defaultV1Options(),
|
|
1577
1461
|
});
|
|
1578
1462
|
|
|
1579
1463
|
const result = validateVBundle(archive);
|
|
1580
1464
|
expect(result.is_valid).toBe(true);
|
|
1581
|
-
expect(result.manifest?.schema_version).toBe(
|
|
1465
|
+
expect(result.manifest?.schema_version).toBe(1);
|
|
1582
1466
|
}
|
|
1583
1467
|
});
|
|
1584
1468
|
|
|
1585
|
-
test("builder output
|
|
1469
|
+
test("builder output checksum matches validator computation", () => {
|
|
1586
1470
|
const { archive, manifest } = buildVBundle({
|
|
1587
1471
|
files: [
|
|
1588
1472
|
{
|
|
@@ -1590,24 +1474,27 @@ describe("builder -> validator consistency", () => {
|
|
|
1590
1474
|
data: new Uint8Array([0xca, 0xfe]),
|
|
1591
1475
|
},
|
|
1592
1476
|
],
|
|
1593
|
-
|
|
1477
|
+
...defaultV1Options(),
|
|
1594
1478
|
});
|
|
1595
1479
|
|
|
1596
1480
|
const result = validateVBundle(archive);
|
|
1597
1481
|
expect(result.is_valid).toBe(true);
|
|
1598
|
-
expect(result.manifest?.
|
|
1482
|
+
expect(result.manifest?.checksum).toBe(manifest.checksum);
|
|
1599
1483
|
});
|
|
1600
1484
|
|
|
1601
1485
|
test("builder output file checksums match validator computation", () => {
|
|
1602
1486
|
const fileData = new Uint8Array([0xde, 0xad, 0xbe, 0xef]);
|
|
1603
1487
|
const { archive, manifest } = buildVBundle({
|
|
1604
1488
|
files: [{ path: "data/db/assistant.db", data: fileData }],
|
|
1489
|
+
...defaultV1Options(),
|
|
1605
1490
|
});
|
|
1606
1491
|
|
|
1607
1492
|
const result = validateVBundle(archive);
|
|
1608
1493
|
expect(result.is_valid).toBe(true);
|
|
1609
|
-
expect(result.manifest?.
|
|
1610
|
-
|
|
1494
|
+
expect(result.manifest?.contents[0].sha256).toBe(
|
|
1495
|
+
manifest.contents[0].sha256,
|
|
1496
|
+
);
|
|
1497
|
+
expect(result.manifest?.contents[0].sha256).toBe(sha256Hex(fileData));
|
|
1611
1498
|
});
|
|
1612
1499
|
});
|
|
1613
1500
|
|
|
@@ -1622,21 +1509,34 @@ describe("import analyzer edge cases", () => {
|
|
|
1622
1509
|
|
|
1623
1510
|
const report = analyzeImport({
|
|
1624
1511
|
manifest: {
|
|
1625
|
-
schema_version:
|
|
1626
|
-
|
|
1627
|
-
|
|
1512
|
+
schema_version: 1,
|
|
1513
|
+
bundle_id: "00000000-0000-4000-8000-000000000000",
|
|
1514
|
+
created_at: "2026-03-01T00:00:00Z",
|
|
1515
|
+
assistant: { id: "self", name: "Test", runtime_version: "0.0.0-test" },
|
|
1516
|
+
origin: { mode: "self-hosted-local" },
|
|
1517
|
+
compatibility: {
|
|
1518
|
+
min_runtime_version: "0.0.0-test",
|
|
1519
|
+
max_runtime_version: null,
|
|
1520
|
+
},
|
|
1521
|
+
contents: [
|
|
1628
1522
|
{
|
|
1629
1523
|
path: "data/db/assistant.db",
|
|
1630
1524
|
sha256: sha256Hex(EXISTING_DB_DATA),
|
|
1631
|
-
|
|
1525
|
+
size_bytes: EXISTING_DB_DATA.length,
|
|
1632
1526
|
},
|
|
1633
1527
|
{
|
|
1634
1528
|
path: "config/settings.json",
|
|
1635
1529
|
sha256: sha256Hex(existingConfig),
|
|
1636
|
-
|
|
1530
|
+
size_bytes: existingConfig.length,
|
|
1637
1531
|
},
|
|
1638
1532
|
],
|
|
1639
|
-
|
|
1533
|
+
checksum: "test",
|
|
1534
|
+
secrets_redacted: false,
|
|
1535
|
+
export_options: {
|
|
1536
|
+
include_logs: false,
|
|
1537
|
+
include_browser_state: false,
|
|
1538
|
+
include_memory_vectors: false,
|
|
1539
|
+
},
|
|
1640
1540
|
},
|
|
1641
1541
|
pathResolver: resolver,
|
|
1642
1542
|
});
|
|
@@ -1654,23 +1554,24 @@ describe("import analyzer edge cases", () => {
|
|
|
1654
1554
|
);
|
|
1655
1555
|
|
|
1656
1556
|
const report = analyzeImport({
|
|
1657
|
-
manifest: {
|
|
1658
|
-
|
|
1659
|
-
created_at: new Date().toISOString(),
|
|
1660
|
-
files: [
|
|
1557
|
+
manifest: buildTestManifest({
|
|
1558
|
+
contents: [
|
|
1661
1559
|
{
|
|
1662
1560
|
path: "data/db/assistant.db",
|
|
1663
1561
|
sha256: sha256Hex(new Uint8Array([1])),
|
|
1664
|
-
|
|
1562
|
+
size_bytes: 1,
|
|
1665
1563
|
},
|
|
1666
1564
|
{
|
|
1667
1565
|
path: "config/settings.json",
|
|
1668
1566
|
sha256: sha256Hex(new Uint8Array([2])),
|
|
1669
|
-
|
|
1567
|
+
size_bytes: 1,
|
|
1670
1568
|
},
|
|
1671
1569
|
],
|
|
1672
|
-
|
|
1673
|
-
|
|
1570
|
+
overrides: {
|
|
1571
|
+
bundle_id: "00000000-0000-4000-8000-000000000000",
|
|
1572
|
+
created_at: "2026-03-01T00:00:00Z",
|
|
1573
|
+
},
|
|
1574
|
+
}),
|
|
1674
1575
|
pathResolver: resolver,
|
|
1675
1576
|
});
|
|
1676
1577
|
|
|
@@ -1688,23 +1589,24 @@ describe("import analyzer edge cases", () => {
|
|
|
1688
1589
|
const existingConfig = new Uint8Array(readFileSync(testConfigPath));
|
|
1689
1590
|
|
|
1690
1591
|
const report = analyzeImport({
|
|
1691
|
-
manifest: {
|
|
1692
|
-
|
|
1693
|
-
created_at: new Date().toISOString(),
|
|
1694
|
-
files: [
|
|
1592
|
+
manifest: buildTestManifest({
|
|
1593
|
+
contents: [
|
|
1695
1594
|
{
|
|
1696
1595
|
path: "data/db/assistant.db",
|
|
1697
1596
|
sha256: sha256Hex(new Uint8Array([0xff])),
|
|
1698
|
-
|
|
1597
|
+
size_bytes: 1,
|
|
1699
1598
|
},
|
|
1700
1599
|
{
|
|
1701
1600
|
path: "config/settings.json",
|
|
1702
1601
|
sha256: sha256Hex(existingConfig),
|
|
1703
|
-
|
|
1602
|
+
size_bytes: existingConfig.length,
|
|
1704
1603
|
},
|
|
1705
1604
|
],
|
|
1706
|
-
|
|
1707
|
-
|
|
1605
|
+
overrides: {
|
|
1606
|
+
bundle_id: "00000000-0000-4000-8000-000000000000",
|
|
1607
|
+
created_at: "2026-03-01T00:00:00Z",
|
|
1608
|
+
},
|
|
1609
|
+
}),
|
|
1708
1610
|
pathResolver: resolver,
|
|
1709
1611
|
});
|
|
1710
1612
|
|
|
@@ -1717,23 +1619,24 @@ describe("import analyzer edge cases", () => {
|
|
|
1717
1619
|
const resolver = new DefaultPathResolver(testDir);
|
|
1718
1620
|
|
|
1719
1621
|
const report = analyzeImport({
|
|
1720
|
-
manifest: {
|
|
1721
|
-
|
|
1722
|
-
created_at: new Date().toISOString(),
|
|
1723
|
-
files: [
|
|
1622
|
+
manifest: buildTestManifest({
|
|
1623
|
+
contents: [
|
|
1724
1624
|
{
|
|
1725
1625
|
path: "data/db/assistant.db",
|
|
1726
1626
|
sha256: sha256Hex(EXISTING_DB_DATA),
|
|
1727
|
-
|
|
1627
|
+
size_bytes: EXISTING_DB_DATA.length,
|
|
1728
1628
|
},
|
|
1729
1629
|
{
|
|
1730
1630
|
path: "future/unknown-file.dat",
|
|
1731
1631
|
sha256: sha256Hex(new Uint8Array([0])),
|
|
1732
|
-
|
|
1632
|
+
size_bytes: 1,
|
|
1733
1633
|
},
|
|
1734
1634
|
],
|
|
1735
|
-
|
|
1736
|
-
|
|
1635
|
+
overrides: {
|
|
1636
|
+
bundle_id: "00000000-0000-4000-8000-000000000000",
|
|
1637
|
+
created_at: "2026-03-01T00:00:00Z",
|
|
1638
|
+
},
|
|
1639
|
+
}),
|
|
1737
1640
|
pathResolver: resolver,
|
|
1738
1641
|
});
|
|
1739
1642
|
|
|
@@ -1792,7 +1695,10 @@ describe("HTTP endpoint error consistency", () => {
|
|
|
1792
1695
|
body: toArrayBuffer(invalidData),
|
|
1793
1696
|
},
|
|
1794
1697
|
);
|
|
1795
|
-
const preflightRes = await callHandler(
|
|
1698
|
+
const preflightRes = await callHandler(
|
|
1699
|
+
handleMigrationImportPreflight,
|
|
1700
|
+
preflightReq,
|
|
1701
|
+
);
|
|
1796
1702
|
const preflightBody = (await preflightRes.json()) as ImportDryRunResponse;
|
|
1797
1703
|
|
|
1798
1704
|
expect(validateBody.is_valid).toBe(false);
|