@vellumai/assistant 0.7.0 → 0.7.2
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 +38 -56
- package/Dockerfile +2 -0
- package/README.md +3 -4
- package/__tests__/permissions/gateway-threshold-reader.test.ts +88 -142
- package/bun.lock +29 -26
- package/docs/architecture/security.md +38 -16
- package/docs/plugins.md +7 -9
- package/knip.json +2 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +1 -0
- package/node_modules/@vellumai/gateway-client/src/ipc-client.ts +39 -1
- package/node_modules/@vellumai/gateway-client/src/types.ts +11 -0
- package/node_modules/@vellumai/service-contracts/package.json +2 -0
- package/node_modules/@vellumai/service-contracts/src/__tests__/contracts.test.ts +4 -0
- package/node_modules/@vellumai/service-contracts/src/__tests__/ingress.test.ts +107 -0
- package/node_modules/@vellumai/service-contracts/src/index.ts +5 -1
- package/node_modules/@vellumai/service-contracts/src/ingress.ts +24 -0
- package/node_modules/@vellumai/service-contracts/src/twilio-ingress.ts +84 -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 +9 -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/node_modules/@vellumai/twilio-client/bun.lock +24 -0
- package/node_modules/@vellumai/twilio-client/package.json +18 -0
- package/node_modules/@vellumai/twilio-client/src/__tests__/twilio-client.test.ts +128 -0
- package/node_modules/@vellumai/twilio-client/src/index.ts +179 -0
- package/node_modules/@vellumai/twilio-client/tsconfig.json +20 -0
- package/openapi.yaml +869 -129
- package/package.json +8 -3
- 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-builder-tool-scripts.test.ts +3 -3
- package/src/__tests__/app-bundler.test.ts +170 -1
- package/src/__tests__/app-control-flow.test.ts +374 -0
- package/src/__tests__/app-control-no-global-cgevent.test.ts +98 -0
- package/src/__tests__/app-control-tool-schemas.test.ts +621 -0
- package/src/__tests__/app-conversation-ids-backfill.test.ts +278 -0
- package/src/__tests__/app-conversation-ids.test.ts +151 -0
- package/src/__tests__/app-executors.test.ts +30 -43
- package/src/__tests__/approval-cascade.test.ts +0 -15
- package/src/__tests__/approval-routes-http.test.ts +29 -23
- package/src/__tests__/assistant-event-hub-machine-name.test.ts +146 -0
- package/src/__tests__/assistant-event-hub-targeted.test.ts +257 -0
- package/src/__tests__/assistant-event-hub.test.ts +235 -79
- package/src/__tests__/assistant-event.test.ts +10 -5
- package/src/__tests__/assistant-events-sse-hardening.test.ts +44 -17
- package/src/__tests__/assistant-feature-flags-integration.test.ts +11 -36
- package/src/__tests__/background-shell-host-bash.test.ts +46 -56
- package/src/__tests__/bootstrap-turn-cleanup.test.ts +44 -0
- package/src/__tests__/btw-routes.test.ts +13 -4
- package/src/__tests__/call-controller.test.ts +50 -2
- package/src/__tests__/call-domain.test.ts +0 -2
- package/src/__tests__/call-routes-http.test.ts +0 -2
- 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__/channel-readiness-service.test.ts +59 -1
- package/src/__tests__/checker.test.ts +23 -38
- 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-loader-backfill.test.ts +90 -155
- package/src/__tests__/config-loader-platform-defaults.test.ts +196 -0
- package/src/__tests__/config-schema-cmd.test.ts +0 -1
- package/src/__tests__/config-schema.test.ts +6 -48
- package/src/__tests__/config-set-platform-guard.test.ts +48 -4
- package/src/__tests__/config-watcher-cleanup-throttle.test.ts +2 -2
- package/src/__tests__/config-watcher.test.ts +14 -2
- 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-app-control-instantiation.test.ts +392 -0
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +237 -0
- 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-init.benchmark.test.ts +0 -2
- package/src/__tests__/conversation-lifecycle.test.ts +40 -4
- package/src/__tests__/conversation-process-app-control-preactivation.test.ts +283 -0
- 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 +7 -161
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +120 -104
- package/src/__tests__/conversation-routes-slash-commands.test.ts +76 -66
- package/src/__tests__/conversation-runtime-assembly.test.ts +257 -3
- package/src/__tests__/conversation-slash-commands.test.ts +24 -8
- 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-action-delivery.test.ts +202 -0
- package/src/__tests__/conversation-surfaces-app-control.test.ts +317 -0
- 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-feature-gates.test.ts +5 -12
- package/src/__tests__/credential-execution-managed-contract.test.ts +3 -131
- 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__/credentials-cli.test.ts +5 -12
- package/src/__tests__/cu-unified-flow.test.ts +206 -27
- package/src/__tests__/daemon-assistant-events.test.ts +34 -21
- package/src/__tests__/daemon-credential-client.test.ts +102 -17
- package/src/__tests__/db-connection-isolation.test.ts +125 -0
- package/src/__tests__/db-migration-rollback.test.ts +101 -0
- package/src/__tests__/db-schedule-syntax-migration.test.ts +2 -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__/dynamic-skill-workflow-prompt.test.ts +0 -1
- 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__/gateway-only-enforcement.test.ts +0 -1
- 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__/guardian-verification-voice-binding.test.ts +0 -2
- package/src/__tests__/handlers-skills-memory-v2-reseed.test.ts +30 -11
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +2 -84
- 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 +1007 -8
- package/src/__tests__/helpers/call-route-handler.ts +7 -1
- package/src/__tests__/helpers/channel-test-adapter.ts +2 -2
- package/src/__tests__/helpers/create-guardian-binding.ts +91 -0
- package/src/__tests__/host-app-control-proxy.test.ts +602 -0
- package/src/__tests__/host-app-control-routes.test.ts +263 -0
- package/src/__tests__/host-bash-proxy.test.ts +270 -147
- package/src/__tests__/host-bash-routes.test.ts +294 -0
- package/src/__tests__/host-browser-proxy.test.ts +126 -198
- package/src/__tests__/host-browser-routes.test.ts +50 -54
- package/src/__tests__/host-cu-proxy.test.ts +78 -144
- package/src/__tests__/host-cu-routes-targeted.test.ts +300 -0
- package/src/__tests__/host-file-edit-tool.test.ts +47 -1
- package/src/__tests__/host-file-proxy-targeted.test.ts +339 -0
- package/src/__tests__/host-file-proxy.test.ts +62 -122
- package/src/__tests__/host-file-read-tool.test.ts +59 -21
- package/src/__tests__/host-file-routes-targeted.test.ts +262 -0
- package/src/__tests__/host-file-write-tool.test.ts +42 -1
- package/src/__tests__/host-proxy-base.test.ts +312 -0
- package/src/__tests__/host-shell-tool.test.ts +53 -70
- package/src/__tests__/host-transfer-pending-interactions.test.ts +2 -18
- package/src/__tests__/host-transfer-proxy-targeted.test.ts +583 -0
- package/src/__tests__/host-transfer-proxy.test.ts +145 -56
- package/src/__tests__/host-transfer-routes-targeted.test.ts +447 -0
- package/src/__tests__/http-user-message-parity.test.ts +1 -6
- package/src/__tests__/identity-intro-cache.test.ts +29 -0
- package/src/__tests__/identity-routes.test.ts +103 -1
- package/src/__tests__/inbound-slack-persistence.test.ts +31 -0
- package/src/__tests__/init-feature-flag-overrides.test.ts +26 -3
- 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 -67
- package/src/__tests__/inline-skill-load-permissions.test.ts +5 -13
- package/src/__tests__/install-skill-routing.test.ts +1 -13
- package/src/__tests__/integration-status.test.ts +85 -5
- package/src/__tests__/intent-routing.test.ts +0 -1
- package/src/__tests__/jobs-store-qdrant-breaker.test.ts +95 -5
- package/src/__tests__/lifecycle-memory-v2-seed.test.ts +17 -0
- 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 -11
- package/src/__tests__/manual-token-reconciliation.test.ts +334 -0
- package/src/__tests__/mcp-auth-routes.test.ts +197 -0
- package/src/__tests__/mcp-cli.test.ts +338 -2
- package/src/__tests__/memory-jobs-worker-lanes.test.ts +188 -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 +172 -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__/mock-gateway-ipc.ts +1 -0
- 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-cli.test.ts +0 -2
- package/src/__tests__/oauth-store.test.ts +19 -0
- package/src/__tests__/oauth2-gateway-transport.test.ts +0 -1
- package/src/__tests__/persistence-secret-redaction.test.ts +299 -0
- package/src/__tests__/platform-bash-auto-approve.test.ts +26 -21
- package/src/__tests__/prechat-onboarding-contract.test.ts +34 -8
- package/src/__tests__/pricing.test.ts +68 -4
- package/src/__tests__/process-message-background-slack.test.ts +333 -0
- package/src/__tests__/provider-commit-message-generator.test.ts +0 -1
- 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__/public-ingress-urls.test.ts +97 -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 -23
- package/src/__tests__/retry-backoff.test.ts +87 -0
- 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 +13 -18
- package/src/__tests__/sanitize-config-for-transfer.test.ts +24 -2
- package/src/__tests__/schedule-retry.test.ts +715 -0
- package/src/__tests__/script-proxy-mitm-handler.test.ts +1 -1
- 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 +1 -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 +12 -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 -57
- package/src/__tests__/skill-feature-flags.test.ts +43 -41
- package/src/__tests__/skill-load-feature-flag.test.ts +13 -14
- package/src/__tests__/skill-load-inline-command.test.ts +0 -51
- package/src/__tests__/skill-load-inline-includes.test.ts +0 -43
- package/src/__tests__/skill-projection.benchmark.test.ts +0 -1
- package/src/__tests__/skill-script-runner-sandbox.test.ts +0 -12
- 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-channel-config.test.ts +9 -14
- 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-ask-mode.test.ts +0 -1
- package/src/__tests__/system-prompt.test.ts +115 -14
- package/src/__tests__/telegram-config.test.ts +0 -1
- package/src/__tests__/terminal-tools.test.ts +0 -89
- package/src/__tests__/test-preload.ts +8 -0
- package/src/__tests__/thread-backfill.test.ts +945 -31
- package/src/__tests__/tool-approval-handler.test.ts +3 -4
- package/src/__tests__/tool-audit-listener.test.ts +48 -0
- package/src/__tests__/tool-domain-event-publisher.test.ts +0 -36
- package/src/__tests__/tool-execute-pipeline.test.ts +0 -7
- package/src/__tests__/tool-execution-abort-cleanup.test.ts +0 -17
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +9 -19
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +4 -8
- package/src/__tests__/tool-executor.test.ts +12 -20
- 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__/twilio-config.test.ts +3 -16
- package/src/__tests__/twilio-routes.test.ts +3 -5
- package/src/__tests__/twilio-validation.test.ts +93 -0
- 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 +47 -138
- package/src/__tests__/verification-control-plane-policy.test.ts +6 -11
- package/src/__tests__/voice-ingress-preflight.test.ts +19 -0
- package/src/__tests__/voice-session-bridge.test.ts +5 -5
- package/src/__tests__/workspace-migration-006-services-config.test.ts +3 -2
- 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-backfill-installation-id.test.ts +1 -5
- package/src/__tests__/workspace-migration-down-functions.test.ts +8 -8
- package/src/__tests__/workspace-migration-memory-v2-init.test.ts +8 -30
- package/src/__tests__/workspace-migration-unify-llm-callsite-configs.test.ts +10 -6
- 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__/paths.test.ts +0 -22
- package/src/backup/__tests__/restore.test.ts +94 -177
- package/src/backup/paths.ts +2 -15
- package/src/backup/restore.ts +107 -231
- package/src/browser-session/events.ts +0 -9
- package/src/bundler/app-bundler.ts +51 -3
- package/src/calls/call-store.ts +1 -34
- package/src/calls/guardian-question-copy.ts +0 -108
- package/src/calls/relay-server.ts +4 -68
- package/src/calls/twilio-config.ts +2 -17
- package/src/calls/twilio-rest.ts +31 -141
- package/src/calls/twilio-routes.ts +12 -13
- package/src/calls/voice-session-bridge.ts +7 -38
- package/src/channels/types.ts +8 -42
- package/src/cli/commands/__tests__/backup.test.ts +6 -277
- package/src/cli/commands/__tests__/cache.test.ts +152 -5
- package/src/cli/commands/__tests__/gateway.test.ts +288 -0
- package/src/cli/commands/__tests__/memory-v2.test.ts +18 -28
- package/src/cli/commands/__tests__/trust.test.ts +21 -387
- package/src/cli/commands/__tests__/webhooks.test.ts +0 -1
- package/src/cli/commands/backup.ts +6 -331
- package/src/cli/commands/cache-fs.ts +8 -0
- package/src/cli/commands/cache.ts +153 -82
- package/src/cli/commands/clients.ts +64 -7
- package/src/cli/commands/completions.ts +3 -3
- package/src/cli/commands/contacts.ts +304 -76
- package/src/cli/commands/conversations.ts +2 -5
- package/src/cli/commands/credentials.ts +15 -7
- package/src/cli/commands/domain.ts +66 -15
- package/src/cli/commands/gateway.ts +183 -0
- package/src/cli/commands/keys.ts +13 -7
- package/src/cli/commands/mcp.ts +116 -156
- package/src/cli/commands/memory-v2.ts +320 -53
- package/src/cli/commands/oauth/shared.ts +2 -29
- package/src/cli/commands/pending.ts +102 -0
- package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +0 -1
- package/src/cli/commands/platform/__tests__/connect.test.ts +0 -2
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +0 -2
- package/src/cli/commands/platform/__tests__/status.test.ts +13 -15
- package/src/cli/commands/platform/disconnect.ts +5 -4
- package/src/cli/commands/platform/index.ts +0 -18
- 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 +115 -19
- package/src/cli/program.ts +4 -0
- package/src/cli.ts +0 -21
- package/src/config/__tests__/feature-flag-registry-guard.test.ts +2 -2
- package/src/config/assistant-feature-flags.ts +67 -10
- package/src/config/bundled-skills/acp/SKILL.md +6 -0
- package/src/config/bundled-skills/acp/TOOLS.json +1 -22
- package/src/config/bundled-skills/app-builder/SKILL.md +14 -109
- package/src/config/bundled-skills/app-builder/TOOLS.json +1 -28
- package/src/config/bundled-skills/app-builder/tools/app-create.ts +1 -10
- package/src/config/bundled-skills/app-control/SKILL.md +75 -0
- package/src/config/bundled-skills/app-control/TOOLS.json +299 -0
- package/src/config/bundled-skills/app-control/tools/app-control-click.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-combo.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-drag.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-observe.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-press.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-sequence.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-start.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-stop.ts +12 -0
- package/src/config/bundled-skills/app-control/tools/app-control-type.ts +12 -0
- package/src/config/bundled-skills/computer-use/SKILL.md +6 -0
- package/src/config/bundled-skills/computer-use/TOOLS.json +67 -43
- package/src/config/bundled-skills/contacts/TOOLS.json +0 -16
- package/src/config/bundled-skills/document/TOOLS.json +0 -8
- package/src/config/bundled-skills/followups/TOOLS.json +0 -12
- package/src/config/bundled-skills/image-studio/SKILL.md +4 -0
- package/src/config/bundled-skills/image-studio/TOOLS.json +0 -4
- package/src/config/bundled-skills/media-processing/TOOLS.json +0 -24
- package/src/config/bundled-skills/messaging/TOOLS.json +14 -44
- package/src/config/bundled-skills/phone-calls/TOOLS.json +0 -12
- package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +19 -4
- package/src/config/bundled-skills/playbooks/TOOLS.json +0 -16
- package/src/config/bundled-skills/schedule/TOOLS.json +14 -14
- package/src/config/bundled-skills/sequences/TOOLS.json +0 -36
- package/src/config/bundled-skills/settings/SKILL.md +4 -0
- package/src/config/bundled-skills/settings/TOOLS.json +0 -12
- package/src/config/bundled-skills/skill-management/SKILL.md +6 -0
- package/src/config/bundled-skills/skill-management/TOOLS.json +0 -8
- package/src/config/bundled-skills/subagent/SKILL.md +6 -2
- package/src/config/bundled-skills/subagent/TOOLS.json +0 -20
- package/src/config/bundled-skills/transcribe/SKILL.md +4 -0
- package/src/config/bundled-skills/transcribe/TOOLS.json +0 -4
- package/src/config/bundled-tool-registry.ts +21 -0
- package/src/config/env-registry.ts +12 -4
- package/src/config/env.ts +22 -26
- package/src/config/feature-flag-registry.json +40 -152
- 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 +76 -102
- package/src/config/sanitize-for-transfer.ts +2 -0
- package/src/config/schema.ts +2 -158
- package/src/config/schemas/__tests__/memory-lifecycle.test.ts +80 -0
- package/src/config/schemas/__tests__/memory-v2.test.ts +8 -4
- package/src/config/schemas/call-site-catalog.ts +271 -0
- package/src/config/schemas/calls.ts +5 -14
- package/src/config/schemas/heartbeat.ts +63 -0
- package/src/config/schemas/inference.ts +1 -1
- package/src/config/schemas/ingress.ts +11 -7
- package/src/config/schemas/llm.ts +34 -11
- package/src/config/schemas/memory-lifecycle.ts +77 -24
- package/src/config/schemas/memory-retrieval.ts +2 -2
- package/src/config/schemas/memory-v2.ts +57 -4
- package/src/config/schemas/platform.ts +6 -0
- package/src/config/schemas/security.ts +1 -42
- package/src/config/schemas/services.ts +7 -21
- package/src/config/schemas/skills.ts +5 -11
- 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 -47
- package/src/contacts/contacts-write.ts +1 -132
- package/src/context/window-manager.ts +43 -5
- package/src/credential-execution/feature-gates.ts +10 -10
- package/src/credential-execution/process-manager.ts +46 -51
- 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__/conversation-tool-setup.test.ts +126 -5
- package/src/daemon/__tests__/daemon-skill-host.test.ts +2 -9
- package/src/daemon/bootstrap-turn-cleanup.ts +45 -0
- package/src/daemon/config-watcher.ts +4 -3
- package/src/daemon/connection-policy.ts +1 -26
- package/src/daemon/conversation-agent-loop-handlers.ts +74 -7
- package/src/daemon/conversation-agent-loop.ts +309 -64
- package/src/daemon/conversation-history.ts +8 -8
- package/src/daemon/conversation-launch.ts +20 -135
- package/src/daemon/conversation-lifecycle.ts +8 -1
- package/src/daemon/conversation-messaging.ts +1 -0
- package/src/daemon/conversation-process.ts +97 -172
- 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 +144 -29
- package/src/daemon/conversation-tool-setup.ts +18 -87
- package/src/daemon/conversation-usage.ts +36 -0
- package/src/daemon/conversation.ts +134 -231
- 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/doordash-steps.ts +1 -1
- 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 +27 -72
- package/src/daemon/handlers/skills.ts +42 -93
- package/src/daemon/host-app-control-proxy.ts +293 -0
- package/src/daemon/host-bash-proxy.ts +124 -92
- package/src/daemon/host-browser-proxy.ts +111 -88
- package/src/daemon/host-cu-proxy.ts +100 -104
- package/src/daemon/host-file-proxy.ts +136 -91
- package/src/daemon/host-proxy-base.ts +294 -0
- package/src/daemon/host-proxy-preactivation.ts +82 -0
- package/src/daemon/host-transfer-proxy.ts +303 -147
- package/src/daemon/lifecycle.ts +164 -132
- package/src/daemon/message-protocol.ts +3 -8
- package/src/daemon/message-types/contacts.ts +23 -1
- package/src/daemon/message-types/conversations.ts +18 -8
- package/src/daemon/message-types/host-app-control.ts +150 -0
- package/src/daemon/message-types/host-bash.ts +5 -0
- package/src/daemon/message-types/host-cu.ts +3 -0
- package/src/daemon/message-types/host-file.ts +5 -0
- package/src/daemon/message-types/host-transfer.ts +4 -0
- package/src/daemon/message-types/messages.ts +10 -9
- package/src/daemon/message-types/schedules.ts +8 -3
- package/src/daemon/message-types/skills.ts +2 -2
- package/src/daemon/message-types/workspace.ts +1 -1
- package/src/daemon/process-message.ts +119 -239
- package/src/daemon/server.ts +13 -462
- package/src/daemon/shutdown-handlers.ts +2 -5
- package/src/daemon/tool-setup-types.ts +51 -0
- package/src/daemon/tool-side-effects.ts +126 -108
- 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 +5 -2
- 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 +21 -9
- package/src/heartbeat/__tests__/heartbeat-run-store.test.ts +216 -0
- package/src/heartbeat/heartbeat-run-store.ts +236 -0
- package/src/heartbeat/heartbeat-service.ts +303 -54
- package/src/home/__tests__/feed-writer.test.ts +0 -4
- package/src/home/__tests__/post-connect-feed.test.ts +99 -0
- package/src/home/__tests__/relationship-state-writer.test.ts +41 -9
- package/src/home/__tests__/suggested-prompts.test.ts +89 -0
- package/src/home/feed-writer.ts +1 -2
- package/src/home/post-connect-feed.ts +68 -0
- package/src/home/relationship-state-writer.ts +33 -95
- package/src/home/suggested-prompts.ts +46 -10
- package/src/inbound/public-ingress-urls.ts +32 -34
- package/src/ipc/__tests__/browser-ipc.test.ts +2 -12
- package/src/ipc/__tests__/route-error-envelope.test.ts +80 -0
- package/src/ipc/__tests__/skill-server-bidirectional.test.ts +0 -1
- package/src/ipc/assistant-server.ts +17 -11
- package/src/ipc/cli-client.ts +32 -1
- 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/live-voice-metrics.ts +10 -10
- package/src/live-voice/protocol.ts +4 -13
- package/src/mcp/__tests__/mcp-auth-orchestrator.test.ts +304 -0
- package/src/mcp/manager.ts +0 -5
- package/src/mcp/mcp-auth-orchestrator.ts +213 -0
- package/src/mcp/mcp-auth-state.ts +133 -0
- package/src/mcp/mcp-oauth-provider.ts +19 -0
- package/src/memory/__tests__/fixtures/memory-v2-activation-fixtures.ts +55 -0
- package/src/memory/__tests__/jobs-store-job-classes.test.ts +24 -0
- package/src/memory/__tests__/memory-v2-activation-log-store.test.ts +127 -0
- package/src/memory/__tests__/qdrant-client-sentinel.test.ts +49 -0
- package/src/memory/__tests__/sparse-tokenize.test.ts +66 -0
- package/src/memory/anisotropy.test.ts +247 -0
- package/src/memory/anisotropy.ts +443 -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/auto-analysis-constants.ts +17 -0
- package/src/memory/auto-analysis-guard.ts +5 -15
- package/src/memory/canonical-guardian-store.ts +7 -7
- package/src/memory/context-search/__tests__/agent-runner-redaction.test.ts +122 -0
- package/src/memory/context-search/agent-protocol.ts +6 -6
- package/src/memory/context-search/agent-runner.ts +32 -7
- package/src/memory/context-search/sources/memory-v2.ts +590 -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 +30 -5
- package/src/memory/conversation-disk-view.ts +1 -5
- package/src/memory/conversation-key-store.ts +2 -15
- package/src/memory/conversation-starter-checkpoints.ts +63 -0
- package/src/memory/db-connection.ts +62 -0
- package/src/memory/db-init.ts +18 -0
- package/src/memory/embedding-backend.ts +12 -42
- 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 +49 -8
- package/src/memory/graph/conversation-graph-memory.ts +35 -36
- package/src/memory/graph/graph-search.ts +8 -0
- package/src/memory/graph/injection.test.ts +2 -2
- package/src/memory/graph/injection.ts +1 -1
- package/src/memory/graph/retriever.ts +28 -0
- package/src/memory/graph/tools.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/__tests__/embed-concept-page.test.ts +8 -2
- package/src/memory/jobs/embed-concept-page.ts +28 -2
- package/src/memory/jobs/embed-pkb-file.test.ts +2 -2
- package/src/memory/jobs-store.ts +66 -23
- package/src/memory/jobs-worker.ts +114 -79
- 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/237-heartbeat-runs.ts +45 -0
- package/src/memory/migrations/238-schedule-retry-policy.ts +20 -0
- package/src/memory/migrations/__tests__/234-memory-v2-activation-logs.test.ts +182 -0
- package/src/memory/migrations/index.ts +19 -0
- package/src/memory/migrations/registry.ts +32 -0
- package/src/memory/pkb/pkb-search.ts +7 -0
- package/src/memory/qdrant-client.ts +50 -20
- package/src/memory/raw-query.ts +2 -68
- package/src/memory/schema/conversations.ts +7 -0
- package/src/memory/schema/infrastructure.ts +40 -0
- package/src/memory/search/semantic.ts +12 -16
- package/src/memory/sparse-tokenize.ts +49 -0
- 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 +361 -180
- 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 +424 -33
- 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__/sim.test.ts +166 -6
- package/src/memory/v2/__tests__/skill-store.test.ts +115 -3
- package/src/memory/v2/__tests__/sparse-bm25.test.ts +292 -0
- package/src/memory/v2/__tests__/static-context.test.ts +152 -0
- package/src/memory/v2/activation.ts +215 -163
- package/src/memory/v2/backfill-jobs.ts +15 -100
- package/src/memory/v2/consolidation-job.ts +17 -17
- package/src/memory/v2/constants.ts +7 -0
- package/src/memory/v2/edge-index.ts +191 -0
- package/src/memory/v2/injection.ts +241 -84
- 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 +385 -88
- package/src/memory/v2/prompts/sweep.ts +3 -3
- package/src/memory/v2/qdrant.ts +99 -1
- package/src/memory/v2/sim.ts +126 -16
- package/src/memory/v2/skill-qdrant.ts +12 -3
- package/src/memory/v2/skill-store.ts +71 -8
- package/src/memory/v2/sparse-bm25.ts +245 -0
- package/src/memory/v2/static-context.ts +63 -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/gmail/types.ts +0 -49
- 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 +123 -52
- 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 -32
- package/src/notifications/README.md +10 -10
- package/src/notifications/broadcaster.ts +1 -1
- package/src/notifications/guardian-question-mode.ts +5 -5
- package/src/oauth/connect-orchestrator.ts +4 -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 +95 -0
- package/src/oauth/manual-token-connection.ts +26 -34
- package/src/oauth/oauth-store.ts +6 -4
- package/src/outbound-proxy/certs.ts +0 -7
- package/src/outbound-proxy/index.ts +1 -59
- package/src/outbound-proxy/logging.ts +1 -1
- package/src/outbound-proxy/policy.ts +6 -5
- package/src/outbound-proxy/router.ts +2 -1
- package/src/permissions/approval-policy.test.ts +6 -275
- package/src/permissions/approval-policy.ts +0 -51
- package/src/permissions/approval-provenance.test.ts +184 -0
- package/src/permissions/approval-provenance.ts +70 -0
- package/src/permissions/checker.test.ts +0 -1
- package/src/permissions/checker.ts +7 -18
- package/src/permissions/gateway-threshold-reader.ts +6 -1
- package/src/permissions/prompter.ts +43 -3
- package/src/permissions/secret-prompter.ts +25 -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/bootstrap-cleanup.ts +27 -0
- package/src/prompts/system-prompt.ts +37 -88
- package/src/prompts/templates/BOOTSTRAP.md +52 -6
- package/src/prompts/templates/SOUL.md +13 -1
- 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/speech-to-text/provider-catalog.ts +7 -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 +570 -52
- package/src/runtime/assistant-event.ts +2 -6
- package/src/runtime/auth/__tests__/middleware.test.ts +11 -56
- package/src/runtime/auth/context.ts +0 -9
- package/src/runtime/auth/middleware.ts +1 -97
- package/src/runtime/auth/route-policy.ts +30 -9
- package/src/runtime/auth/token-service.ts +0 -11
- package/src/runtime/btw-sidechain.ts +2 -3
- package/src/runtime/channel-approvals.ts +6 -2
- package/src/runtime/channel-invite-transport.ts +2 -48
- package/src/runtime/channel-invite-transports/email.ts +1 -1
- package/src/runtime/channel-invite-transports/slack.ts +1 -1
- package/src/runtime/channel-invite-transports/telegram.ts +1 -1
- package/src/runtime/channel-invite-transports/voice.ts +1 -1
- package/src/runtime/channel-invite-transports/whatsapp.ts +1 -1
- package/src/runtime/channel-invite-types.ts +54 -0
- package/src/runtime/channel-readiness-service.ts +32 -13
- 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 +16 -402
- package/src/runtime/http-types.ts +5 -5
- 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-import-parity.test.ts +413 -0
- package/src/runtime/migrations/__tests__/vbundle-import-policy.test.ts +260 -0
- package/src/runtime/migrations/__tests__/vbundle-import-version-compat.test.ts +189 -0
- 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 +296 -80
- package/src/runtime/migrations/__tests__/vbundle-streaming-validator.test.ts +143 -23
- package/src/runtime/migrations/__tests__/vbundle-symlink-importer.test.ts +451 -0
- package/src/runtime/migrations/__tests__/vbundle-symlink-streaming-importer.test.ts +0 -0
- package/src/runtime/migrations/__tests__/vbundle-symlink-streaming.test.ts +515 -0
- package/src/runtime/migrations/__tests__/vbundle-symlink-tar.test.ts +437 -0
- package/src/runtime/migrations/__tests__/vbundle-symlink-walker.test.ts +319 -0
- package/src/runtime/migrations/__tests__/vbundle-tar-stream.test.ts +2 -2
- package/src/runtime/migrations/__tests__/vbundle-validator-v1-schema.test.ts +421 -0
- package/src/runtime/migrations/migration-transport.ts +49 -16
- 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 +457 -136
- package/src/runtime/migrations/vbundle-import-analyzer.ts +13 -11
- package/src/runtime/migrations/vbundle-import-policy.ts +172 -0
- package/src/runtime/migrations/vbundle-importer.ts +251 -74
- package/src/runtime/migrations/vbundle-metadata-merge.ts +1 -1
- package/src/runtime/migrations/vbundle-streaming-importer.ts +329 -38
- package/src/runtime/migrations/vbundle-streaming-validator.ts +203 -28
- package/src/runtime/migrations/vbundle-tar-stream.ts +15 -6
- package/src/runtime/migrations/vbundle-validator.ts +328 -41
- package/src/runtime/pending-interactions.ts +48 -13
- package/src/runtime/routes/__tests__/acp-routes.test.ts +0 -1
- package/src/runtime/routes/__tests__/backup-routes.test.ts +49 -168
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +333 -0
- package/src/runtime/routes/__tests__/gateway-log-routes.test.ts +242 -0
- package/src/runtime/routes/__tests__/heartbeat-routes.test.ts +112 -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-interception-types.ts +13 -0
- package/src/runtime/routes/approval-routes.ts +55 -14
- package/src/runtime/routes/approval-strategies/guardian-text-engine-strategy.ts +1 -1
- package/src/runtime/routes/avatar-routes.ts +3 -5
- package/src/runtime/routes/backup-routes.ts +15 -38
- package/src/runtime/routes/browser-routes.ts +1 -15
- package/src/runtime/routes/btw-routes.ts +14 -37
- 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 +46 -12
- package/src/runtime/routes/consolidation-routes.ts +115 -0
- package/src/runtime/routes/contact-prompt-routes.ts +183 -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 +156 -9
- package/src/runtime/routes/conversation-routes.ts +72 -539
- package/src/runtime/routes/conversation-starter-routes.ts +19 -40
- package/src/runtime/routes/document-pdf-renderer.ts +165 -0
- package/src/runtime/routes/documents-routes.ts +83 -18
- package/src/runtime/routes/errors.ts +19 -4
- package/src/runtime/routes/events-routes.ts +68 -94
- package/src/runtime/routes/filing-routes.ts +18 -1
- package/src/runtime/routes/gateway-log-routes.ts +79 -0
- package/src/runtime/routes/guardian-action-routes.ts +4 -9
- package/src/runtime/routes/guardian-approval-interception.ts +2 -8
- package/src/runtime/routes/heartbeat-routes.ts +103 -38
- package/src/runtime/routes/host-app-control-routes.ts +134 -0
- package/src/runtime/routes/host-bash-routes.ts +37 -6
- package/src/runtime/routes/host-browser-routes.ts +96 -25
- package/src/runtime/routes/host-cu-routes.ts +48 -13
- package/src/runtime/routes/host-file-routes.ts +35 -11
- package/src/runtime/routes/host-transfer-routes.ts +73 -37
- package/src/runtime/routes/http-adapter.ts +1 -0
- package/src/runtime/routes/identity-intro-cache.ts +30 -0
- package/src/runtime/routes/identity-routes.ts +93 -49
- package/src/runtime/routes/inbound-message-handler.ts +581 -146
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +2 -95
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +3 -0
- package/src/runtime/routes/inbound-stages/edit-intercept.ts +0 -8
- package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +0 -20
- package/src/runtime/routes/inbound-stages/transcribe-audio.ts +5 -13
- package/src/runtime/routes/index.ts +12 -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/mcp-auth-routes.ts +132 -0
- package/src/runtime/routes/memory-item-routes.ts +10 -12
- package/src/runtime/routes/memory-v2-routes.ts +451 -16
- package/src/runtime/routes/migration-routes.ts +284 -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 +10 -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/runtime/verification-templates.ts +4 -7
- package/src/schedule/integration-status.ts +66 -2
- package/src/schedule/recurrence-engine.ts +4 -1
- package/src/schedule/retry-backoff.ts +18 -0
- package/src/schedule/retry-policy.ts +82 -0
- package/src/schedule/schedule-recovery.ts +64 -0
- package/src/schedule/schedule-store.ts +106 -18
- package/src/schedule/scheduler-types.ts +25 -0
- package/src/schedule/scheduler.ts +63 -38
- package/src/security/oauth-callback-registry.ts +8 -0
- 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/sequence/analytics.ts +5 -5
- package/src/sequence/engine.ts +1 -1
- 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-files.ts +2 -8
- package/src/skills/catalog-install.ts +1 -0
- package/src/skills/clawhub.ts +2 -2
- package/src/skills/include-graph.ts +5 -5
- package/src/skills/inline-command-runner.ts +1 -7
- package/src/skills/remote-skill-policy.ts +5 -5
- package/src/skills/skill-file-provider.ts +1 -1
- package/src/skills/skill-file-types.ts +13 -0
- package/src/skills/skillssh-audit-types.ts +28 -0
- package/src/skills/skillssh-registry.ts +8 -21
- package/src/subagent/manager.ts +67 -84
- package/src/tasks/task-store.ts +1 -28
- package/src/telemetry/types.ts +8 -0
- package/src/telemetry/usage-telemetry-reporter.test.ts +59 -15
- package/src/telemetry/usage-telemetry-reporter.ts +4 -5
- package/src/tools/acp/spawn.test.ts +1 -2
- package/src/tools/acp/steer.test.ts +1 -2
- package/src/tools/app-control/skill-proxy-bridge.ts +28 -0
- package/src/tools/apps/executors.ts +56 -69
- package/src/tools/browser/__tests__/browser-status.test.ts +55 -135
- package/src/tools/browser/browser-execution.ts +31 -147
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +145 -70
- package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +12 -6
- package/src/tools/browser/cdp-client/factory.ts +62 -91
- package/src/tools/browser/cdp-client/index.ts +1 -27
- package/src/tools/computer-use/definitions.ts +42 -20
- package/src/tools/executor.ts +46 -31
- package/src/tools/host-filesystem/edit.ts +29 -2
- package/src/tools/host-filesystem/read.ts +29 -2
- package/src/tools/host-filesystem/transfer.test.ts +45 -42
- package/src/tools/host-filesystem/transfer.ts +35 -4
- package/src/tools/host-filesystem/write.ts +29 -2
- package/src/tools/host-terminal/host-shell.ts +62 -3
- package/src/tools/network/script-proxy/index.ts +1 -10
- package/src/tools/permission-checker.ts +66 -1
- package/src/tools/schedule/create.ts +6 -0
- package/src/tools/schedule/list.ts +2 -0
- package/src/tools/schedule/update.ts +10 -0
- package/src/tools/shared/filesystem/file-ops-service.ts +2 -0
- package/src/tools/shared/filesystem/path-policy.ts +25 -1
- package/src/tools/skills/load.ts +0 -32
- 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/tool-approval-handler.ts +1 -5
- package/src/tools/types.ts +16 -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/hatched-date.ts +86 -0
- package/src/workspace/migrations/003-seed-device-id.ts +1 -1
- package/src/workspace/migrations/006-services-config.ts +8 -5
- package/src/workspace/migrations/016-extract-feature-flags-to-protected.ts +3 -9
- package/src/workspace/migrations/021-move-signals-to-workspace.ts +4 -10
- package/src/workspace/migrations/022-move-hooks-to-workspace.ts +4 -10
- package/src/workspace/migrations/023-move-config-files-to-workspace.ts +4 -11
- package/src/workspace/migrations/024-move-runtime-files-to-workspace.ts +3 -10
- package/src/workspace/migrations/040-seed-latency-callsite-defaults.ts +3 -2
- package/src/workspace/migrations/050-seed-main-agent-opus-callsite.ts +6 -4
- package/src/workspace/migrations/052-seed-default-inference-profiles.ts +3 -3
- package/src/workspace/migrations/059-move-pid-to-workspace.ts +3 -8
- package/src/workspace/migrations/060-memory-v2-init.ts +2 -18
- package/src/workspace/migrations/061-move-backup-key-to-workspace.ts +54 -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/AGENTS.md +1 -1
- package/src/workspace/migrations/migrate-to-workspace-volume.ts +4 -10
- package/src/workspace/migrations/registry.ts +8 -0
- package/src/workspace/migrations/utils.ts +21 -0
- package/src/workspace/provider-commit-message-generator.ts +3 -3
- package/src/__tests__/host-browser-e2e-cloud.test.ts +0 -904
- package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +0 -296
- package/src/__tests__/host-browser-ws-events-e2e.test.ts +0 -431
- 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/__tests__/twilio-rest.test.ts +0 -34
- package/src/backup/__tests__/backup-key.test.ts +0 -152
- package/src/backup/__tests__/backup-worker.test.ts +0 -754
- package/src/backup/__tests__/offsite-writer.test.ts +0 -641
- package/src/backup/__tests__/stream-crypt.test.ts +0 -228
- package/src/backup/backup-key.ts +0 -137
- package/src/backup/backup-worker.ts +0 -438
- package/src/backup/offsite-writer.ts +0 -222
- package/src/backup/stream-crypt.ts +0 -263
- 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/daemon/message-types/pairing.ts +0 -58
- 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/outbound-proxy/config.ts +0 -94
- package/src/outbound-proxy/health.ts +0 -62
- package/src/outbound-proxy/types.ts +0 -150
- 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/capability-tokens.ts +0 -190
- 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/signals/mcp-reload.ts +0 -18
- 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
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
* - workspace/: the entire ~/.vellum/workspace/ directory tree (DB, config,
|
|
7
7
|
* skills, prompts, attachments, etc.) — excluding large/regenerable
|
|
8
8
|
* dirs (embedding-models/, data/qdrant/)
|
|
9
|
-
* - trust/trust.json: trust rules (optional)
|
|
10
9
|
*/
|
|
11
10
|
|
|
12
11
|
import { createHash, randomUUID } from "node:crypto";
|
|
@@ -20,15 +19,18 @@ import {
|
|
|
20
19
|
readdirSync,
|
|
21
20
|
readFileSync,
|
|
22
21
|
readSync,
|
|
22
|
+
realpathSync,
|
|
23
23
|
} from "node:fs";
|
|
24
24
|
import { stat, unlink } from "node:fs/promises";
|
|
25
25
|
import { tmpdir } from "node:os";
|
|
26
|
-
import { join, relative } from "node:path";
|
|
26
|
+
import { dirname, join, relative, resolve, sep } from "node:path";
|
|
27
27
|
import { Readable } from "node:stream";
|
|
28
28
|
import { pipeline } from "node:stream/promises";
|
|
29
29
|
import { createGzip, gzipSync } from "node:zlib";
|
|
30
30
|
|
|
31
31
|
import { sanitizeConfigForTransfer } from "../../config/sanitize-for-transfer.js";
|
|
32
|
+
import { getLogger } from "../../util/logger.js";
|
|
33
|
+
import type { VBundleOriginMode } from "./origin-mode.js";
|
|
32
34
|
import type {
|
|
33
35
|
ManifestFileEntryType,
|
|
34
36
|
ManifestType,
|
|
@@ -41,17 +43,54 @@ import type {
|
|
|
41
43
|
export interface VBundleFileEntry {
|
|
42
44
|
path: string;
|
|
43
45
|
data: Uint8Array;
|
|
46
|
+
/** When set, `data` is ignored: the entry is emitted as a tar typeflag-2 (symlink) record with empty body, and `linkTarget` is the symlink target encoded relative to the symlink's own directory inside the archive. */
|
|
47
|
+
linkTarget?: string;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** v1 manifest `assistant` block. */
|
|
51
|
+
export interface VBundleAssistantInfo {
|
|
52
|
+
id: string;
|
|
53
|
+
name: string;
|
|
54
|
+
runtime_version: string;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** v1 manifest `origin` block. */
|
|
58
|
+
export interface VBundleOriginInfo {
|
|
59
|
+
mode: VBundleOriginMode;
|
|
60
|
+
platform_version?: string;
|
|
61
|
+
hostname?: string;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** v1 manifest `compatibility` block. */
|
|
65
|
+
export interface VBundleCompatibility {
|
|
66
|
+
min_runtime_version: string;
|
|
67
|
+
max_runtime_version: string | null;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** v1 manifest `export_options` block. */
|
|
71
|
+
export interface VBundleExportOptions {
|
|
72
|
+
include_logs: boolean;
|
|
73
|
+
include_browser_state: boolean;
|
|
74
|
+
include_memory_vectors: boolean;
|
|
44
75
|
}
|
|
45
76
|
|
|
46
77
|
export interface BuildVBundleOptions {
|
|
47
78
|
/** Files to include in the archive. Must include data/db/assistant.db. */
|
|
48
79
|
files: VBundleFileEntry[];
|
|
49
|
-
/**
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
|
|
80
|
+
/** Identity of the assistant that produced this bundle. */
|
|
81
|
+
assistant: VBundleAssistantInfo;
|
|
82
|
+
/** Where this bundle was produced. */
|
|
83
|
+
origin: VBundleOriginInfo;
|
|
84
|
+
/** Runtime-version compatibility window for importers. */
|
|
85
|
+
compatibility: VBundleCompatibility;
|
|
86
|
+
/** Which optional bundle contents this export carries. */
|
|
87
|
+
exportOptions: VBundleExportOptions;
|
|
88
|
+
/**
|
|
89
|
+
* Whether secrets were stripped from the bundle before archiving.
|
|
90
|
+
* Required at the type level — defaulting silently is exactly how the
|
|
91
|
+
* prior schema mismatch went unnoticed.
|
|
92
|
+
*/
|
|
93
|
+
secretsRedacted: boolean;
|
|
55
94
|
}
|
|
56
95
|
|
|
57
96
|
export interface BuildVBundleResult {
|
|
@@ -74,13 +113,24 @@ interface InMemoryEntry {
|
|
|
74
113
|
size: number;
|
|
75
114
|
}
|
|
76
115
|
|
|
77
|
-
/**
|
|
78
|
-
|
|
116
|
+
/** Symlink entry — emitted as a tar typeflag-2 record with empty body. */
|
|
117
|
+
interface SymlinkMetadata {
|
|
118
|
+
archivePath: string;
|
|
119
|
+
linkTarget: string;
|
|
120
|
+
size: 0;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/** Union of disk-backed, in-memory, and symlink tar stream entries. */
|
|
124
|
+
type TarStreamEntry = FileMetadata | InMemoryEntry | SymlinkMetadata;
|
|
79
125
|
|
|
80
126
|
function isInMemoryEntry(entry: TarStreamEntry): entry is InMemoryEntry {
|
|
81
127
|
return "data" in entry;
|
|
82
128
|
}
|
|
83
129
|
|
|
130
|
+
function isSymlinkEntry(entry: TarStreamEntry): entry is SymlinkMetadata {
|
|
131
|
+
return "linkTarget" in entry;
|
|
132
|
+
}
|
|
133
|
+
|
|
84
134
|
// ---------------------------------------------------------------------------
|
|
85
135
|
// Hash helpers
|
|
86
136
|
// ---------------------------------------------------------------------------
|
|
@@ -199,7 +249,11 @@ function createPaxPathEntry(name: string): Uint8Array {
|
|
|
199
249
|
return result;
|
|
200
250
|
}
|
|
201
251
|
|
|
202
|
-
function createTarEntry(
|
|
252
|
+
function createTarEntry(
|
|
253
|
+
name: string,
|
|
254
|
+
data: Uint8Array,
|
|
255
|
+
linkTarget?: string,
|
|
256
|
+
): Uint8Array {
|
|
203
257
|
const encoder = new TextEncoder();
|
|
204
258
|
const nameBytes = encoder.encode(name);
|
|
205
259
|
|
|
@@ -208,6 +262,14 @@ function createTarEntry(name: string, data: Uint8Array): Uint8Array {
|
|
|
208
262
|
const needsPax = nameBytes.length > 100;
|
|
209
263
|
const paxEntry = needsPax ? createPaxPathEntry(name) : null;
|
|
210
264
|
|
|
265
|
+
const isSymlink = linkTarget !== undefined;
|
|
266
|
+
const linkTargetBytes = isSymlink ? encoder.encode(linkTarget) : null;
|
|
267
|
+
if (linkTargetBytes && linkTargetBytes.length > 100) {
|
|
268
|
+
throw new Error(
|
|
269
|
+
`Symlink target "${linkTarget}" is ${linkTargetBytes.length} bytes, exceeding the ustar linkname-field 100-byte limit. The walker should guard against this case before calling createTarEntry.`,
|
|
270
|
+
);
|
|
271
|
+
}
|
|
272
|
+
|
|
211
273
|
const header = new Uint8Array(BLOCK_SIZE);
|
|
212
274
|
|
|
213
275
|
// File name (0-99) — truncated if >100 bytes; PAX header carries the full name
|
|
@@ -222,14 +284,19 @@ function createTarEntry(name: string, data: Uint8Array): Uint8Array {
|
|
|
222
284
|
// Group ID (116-123)
|
|
223
285
|
writeOctal(header, 116, 8, 0);
|
|
224
286
|
|
|
225
|
-
// File size (124-135)
|
|
226
|
-
writeOctal(header, 124, 12, data.length);
|
|
287
|
+
// File size (124-135) — symlink entries always carry size 0
|
|
288
|
+
writeOctal(header, 124, 12, isSymlink ? 0 : data.length);
|
|
227
289
|
|
|
228
290
|
// Modification time (136-147)
|
|
229
291
|
writeOctal(header, 136, 12, Math.floor(Date.now() / 1000));
|
|
230
292
|
|
|
231
|
-
// Type flag (156): regular file
|
|
232
|
-
header[156] = "0".charCodeAt(0);
|
|
293
|
+
// Type flag (156): regular file ("0") or symlink ("2")
|
|
294
|
+
header[156] = (isSymlink ? "2" : "0").charCodeAt(0);
|
|
295
|
+
|
|
296
|
+
// Linkname (157-256) — only set for symlinks; null-padded by default
|
|
297
|
+
if (linkTargetBytes) {
|
|
298
|
+
header.set(linkTargetBytes, 157);
|
|
299
|
+
}
|
|
233
300
|
|
|
234
301
|
// USTAR magic (257-262)
|
|
235
302
|
const magic = encoder.encode("ustar\0");
|
|
@@ -239,16 +306,22 @@ function createTarEntry(name: string, data: Uint8Array): Uint8Array {
|
|
|
239
306
|
header[263] = "0".charCodeAt(0);
|
|
240
307
|
header[264] = "0".charCodeAt(0);
|
|
241
308
|
|
|
242
|
-
// Compute and write checksum (148-155)
|
|
309
|
+
// Compute and write checksum (148-155) — must be last so the linkname
|
|
310
|
+
// (and every other field) contributes to the sum.
|
|
243
311
|
const checksum = computeHeaderChecksum(header);
|
|
244
312
|
writeOctal(header, 148, 7, checksum);
|
|
245
313
|
header[155] = 0x20; // trailing space
|
|
246
314
|
|
|
247
|
-
//
|
|
248
|
-
const
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
315
|
+
// Symlink entries are header-only — no body, no padding.
|
|
316
|
+
const fileEntry = isSymlink
|
|
317
|
+
? header
|
|
318
|
+
: (() => {
|
|
319
|
+
const paddedData = padToBlock(data);
|
|
320
|
+
const combined = new Uint8Array(header.length + paddedData.length);
|
|
321
|
+
combined.set(header, 0);
|
|
322
|
+
combined.set(paddedData, header.length);
|
|
323
|
+
return combined;
|
|
324
|
+
})();
|
|
252
325
|
|
|
253
326
|
if (paxEntry) {
|
|
254
327
|
const result = new Uint8Array(paxEntry.length + fileEntry.length);
|
|
@@ -261,11 +334,11 @@ function createTarEntry(name: string, data: Uint8Array): Uint8Array {
|
|
|
261
334
|
}
|
|
262
335
|
|
|
263
336
|
function createTarArchive(
|
|
264
|
-
entries: Array<{ name: string; data: Uint8Array }>,
|
|
337
|
+
entries: Array<{ name: string; data: Uint8Array; linkTarget?: string }>,
|
|
265
338
|
): Uint8Array {
|
|
266
339
|
const parts: Uint8Array[] = [];
|
|
267
340
|
for (const entry of entries) {
|
|
268
|
-
parts.push(createTarEntry(entry.name, entry.data));
|
|
341
|
+
parts.push(createTarEntry(entry.name, entry.data, entry.linkTarget));
|
|
269
342
|
}
|
|
270
343
|
// End-of-archive: two zero blocks
|
|
271
344
|
parts.push(new Uint8Array(BLOCK_SIZE * 2));
|
|
@@ -284,50 +357,98 @@ function createTarArchive(
|
|
|
284
357
|
// Core builder
|
|
285
358
|
// ---------------------------------------------------------------------------
|
|
286
359
|
|
|
360
|
+
/**
|
|
361
|
+
* Build the v1 manifest object and its serialized JSON bytes for a vbundle.
|
|
362
|
+
*
|
|
363
|
+
* Shared by the buffered (`buildVBundle`) and streaming
|
|
364
|
+
* (`streamExportVBundle`) emit sites so the manifest shape and self-checksum
|
|
365
|
+
* computation live in exactly one place.
|
|
366
|
+
*
|
|
367
|
+
* The checksum is computed over the canonicalized manifest with the
|
|
368
|
+
* `checksum` field set to the empty string (per the schema spec) — both
|
|
369
|
+
* producers and the validator agree on this exact wire shape.
|
|
370
|
+
*/
|
|
371
|
+
function buildManifestObject(input: {
|
|
372
|
+
contents: ManifestFileEntryType[];
|
|
373
|
+
assistant: VBundleAssistantInfo;
|
|
374
|
+
origin: VBundleOriginInfo;
|
|
375
|
+
compatibility: VBundleCompatibility;
|
|
376
|
+
exportOptions: VBundleExportOptions;
|
|
377
|
+
secretsRedacted: boolean;
|
|
378
|
+
now: Date;
|
|
379
|
+
}): { manifest: ManifestType; manifestData: Uint8Array } {
|
|
380
|
+
const manifestWithEmptyChecksum = {
|
|
381
|
+
schema_version: 1 as const,
|
|
382
|
+
bundle_id: randomUUID(),
|
|
383
|
+
created_at: input.now.toISOString(),
|
|
384
|
+
assistant: input.assistant,
|
|
385
|
+
origin: input.origin,
|
|
386
|
+
compatibility: input.compatibility,
|
|
387
|
+
contents: input.contents,
|
|
388
|
+
checksum: "",
|
|
389
|
+
secrets_redacted: input.secretsRedacted,
|
|
390
|
+
export_options: input.exportOptions,
|
|
391
|
+
};
|
|
392
|
+
const checksum = sha256Hex(canonicalizeJson(manifestWithEmptyChecksum));
|
|
393
|
+
const manifest: ManifestType = { ...manifestWithEmptyChecksum, checksum };
|
|
394
|
+
const manifestData = new TextEncoder().encode(JSON.stringify(manifest));
|
|
395
|
+
return { manifest, manifestData };
|
|
396
|
+
}
|
|
397
|
+
|
|
287
398
|
/**
|
|
288
399
|
* Build a .vbundle archive from the given files and metadata.
|
|
289
400
|
*
|
|
290
401
|
* Generates a valid manifest with SHA-256 checksums for all files and
|
|
291
|
-
* a self-referencing
|
|
402
|
+
* a self-referencing `checksum`. The archive is returned
|
|
292
403
|
* as gzip-compressed tar bytes.
|
|
293
404
|
*/
|
|
294
405
|
export function buildVBundle(options: BuildVBundleOptions): BuildVBundleResult {
|
|
295
406
|
const {
|
|
296
407
|
files,
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
408
|
+
assistant,
|
|
409
|
+
origin,
|
|
410
|
+
compatibility,
|
|
411
|
+
exportOptions,
|
|
412
|
+
secretsRedacted,
|
|
300
413
|
} = options;
|
|
301
414
|
|
|
302
|
-
// Build file entries for the manifest
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
// Compute the manifest self-checksum
|
|
319
|
-
const manifestSha256 = sha256Hex(canonicalizeJson(manifestWithoutChecksum));
|
|
320
|
-
const manifest: ManifestType = {
|
|
321
|
-
...manifestWithoutChecksum,
|
|
322
|
-
manifest_sha256: manifestSha256,
|
|
323
|
-
};
|
|
415
|
+
// Build file entries for the manifest. Symlink entries hash the link target
|
|
416
|
+
// string (not the empty data buffer) and declare size_bytes: 0.
|
|
417
|
+
const fileEntries: ManifestFileEntryType[] = files.map((f) =>
|
|
418
|
+
f.linkTarget !== undefined
|
|
419
|
+
? {
|
|
420
|
+
path: f.path,
|
|
421
|
+
sha256: sha256Hex(f.linkTarget),
|
|
422
|
+
size_bytes: 0,
|
|
423
|
+
link_target: f.linkTarget,
|
|
424
|
+
}
|
|
425
|
+
: {
|
|
426
|
+
path: f.path,
|
|
427
|
+
sha256: sha256Hex(f.data),
|
|
428
|
+
size_bytes: f.data.length,
|
|
429
|
+
},
|
|
430
|
+
);
|
|
324
431
|
|
|
325
|
-
const manifestData =
|
|
432
|
+
const { manifest, manifestData } = buildManifestObject({
|
|
433
|
+
contents: fileEntries,
|
|
434
|
+
assistant,
|
|
435
|
+
origin,
|
|
436
|
+
compatibility,
|
|
437
|
+
exportOptions,
|
|
438
|
+
secretsRedacted,
|
|
439
|
+
now: new Date(),
|
|
440
|
+
});
|
|
326
441
|
|
|
327
|
-
// Build tar entries: manifest first, then all files
|
|
442
|
+
// Build tar entries: manifest first, then all files. Symlink entries forward
|
|
443
|
+
// `linkTarget` so createTarEntry emits a typeflag-2 header; `data` is unused
|
|
444
|
+
// in that branch but must still be a valid Uint8Array.
|
|
328
445
|
const tarEntries = [
|
|
329
446
|
{ name: "manifest.json", data: manifestData },
|
|
330
|
-
...files.map((f) =>
|
|
447
|
+
...files.map((f) =>
|
|
448
|
+
f.linkTarget !== undefined
|
|
449
|
+
? { name: f.path, data: new Uint8Array(0), linkTarget: f.linkTarget }
|
|
450
|
+
: { name: f.path, data: f.data },
|
|
451
|
+
),
|
|
331
452
|
];
|
|
332
453
|
|
|
333
454
|
const tar = createTarArchive(tarEntries);
|
|
@@ -343,33 +464,143 @@ export function buildVBundle(options: BuildVBundleOptions): BuildVBundleResult {
|
|
|
343
464
|
interface WalkDirectoryOptions {
|
|
344
465
|
/** Include binary files (files containing null bytes). Default: false. */
|
|
345
466
|
includeBinary?: boolean;
|
|
346
|
-
/** Directory names to skip (matched against
|
|
467
|
+
/** Directory names to skip (matched against relative path from walk root). */
|
|
347
468
|
skipDirs?: string[];
|
|
469
|
+
/** File names to skip (matched against the entry basename). */
|
|
470
|
+
skipFiles?: string[];
|
|
348
471
|
}
|
|
349
472
|
|
|
350
473
|
/**
|
|
351
|
-
*
|
|
352
|
-
*
|
|
474
|
+
* Resolve and classify a symlink encountered during a walk.
|
|
475
|
+
*
|
|
476
|
+
* Returns one of:
|
|
477
|
+
* { kind: "class1", linkTarget } — emit as a tar typeflag-2 entry whose
|
|
478
|
+
* `linkname` field holds `linkTarget` (the symlink target encoded as a
|
|
479
|
+
* POSIX path relative to the symlink's own directory).
|
|
480
|
+
* { kind: "drop", reason } — drop the symlink. Reasons cover broken
|
|
481
|
+
* links, targets outside the workspace (class 2), targets inside a
|
|
482
|
+
* skipped directory (class 3), directory targets (out of scope), and
|
|
483
|
+
* link targets whose UTF-8 encoding exceeds the 100-byte ustar
|
|
484
|
+
* `linkname` field limit.
|
|
485
|
+
*/
|
|
486
|
+
type SymlinkClassification =
|
|
487
|
+
| { kind: "class1"; linkTarget: string }
|
|
488
|
+
| { kind: "drop"; reason: string };
|
|
489
|
+
|
|
490
|
+
function classifySymlink(args: {
|
|
491
|
+
fullPath: string;
|
|
492
|
+
walkRoot: string;
|
|
493
|
+
skipDirs: readonly string[];
|
|
494
|
+
}): SymlinkClassification {
|
|
495
|
+
const { fullPath, walkRoot, skipDirs } = args;
|
|
496
|
+
|
|
497
|
+
let absoluteTarget: string;
|
|
498
|
+
try {
|
|
499
|
+
absoluteTarget = realpathSync(fullPath);
|
|
500
|
+
} catch {
|
|
501
|
+
return { kind: "drop", reason: "broken symlink (realpath failed)" };
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
let targetStat;
|
|
505
|
+
try {
|
|
506
|
+
targetStat = lstatSync(absoluteTarget);
|
|
507
|
+
} catch {
|
|
508
|
+
return { kind: "drop", reason: "broken symlink (target stat failed)" };
|
|
509
|
+
}
|
|
510
|
+
if (!targetStat.isFile()) {
|
|
511
|
+
return { kind: "drop", reason: "target is not a regular file" };
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
let dirAbs: string;
|
|
515
|
+
try {
|
|
516
|
+
dirAbs = realpathSync(walkRoot);
|
|
517
|
+
} catch {
|
|
518
|
+
dirAbs = resolve(walkRoot);
|
|
519
|
+
}
|
|
520
|
+
const targetAbs = resolve(absoluteTarget);
|
|
521
|
+
const insideWorkspace =
|
|
522
|
+
targetAbs === dirAbs || targetAbs.startsWith(dirAbs + sep);
|
|
523
|
+
if (!insideWorkspace) {
|
|
524
|
+
return { kind: "drop", reason: "target outside workspace" };
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
const targetRelToWorkspace = relative(dirAbs, targetAbs);
|
|
528
|
+
if (
|
|
529
|
+
skipDirs.some(
|
|
530
|
+
(s) =>
|
|
531
|
+
targetRelToWorkspace === s || targetRelToWorkspace.startsWith(s + "/"),
|
|
532
|
+
)
|
|
533
|
+
) {
|
|
534
|
+
return { kind: "drop", reason: "target inside skipDir" };
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
// Canonicalize the symlink's parent directory so the relative linkTarget
|
|
538
|
+
// computation lines up with `absoluteTarget` (which is canonical from
|
|
539
|
+
// realpathSync). On macOS, walking through /var/folders/... and resolving
|
|
540
|
+
// the target through /private/var/folders/... would otherwise produce a
|
|
541
|
+
// long ../../../private/... path that exceeds the 100-byte ustar limit.
|
|
542
|
+
let parentAbs: string;
|
|
543
|
+
try {
|
|
544
|
+
parentAbs = realpathSync(dirname(fullPath));
|
|
545
|
+
} catch {
|
|
546
|
+
parentAbs = resolve(dirname(fullPath));
|
|
547
|
+
}
|
|
548
|
+
const linkTarget = relative(parentAbs, absoluteTarget);
|
|
549
|
+
if (new TextEncoder().encode(linkTarget).length > 100) {
|
|
550
|
+
return {
|
|
551
|
+
kind: "drop",
|
|
552
|
+
reason: "encoded link target exceeds 100-byte ustar limit",
|
|
553
|
+
};
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
return { kind: "class1", linkTarget };
|
|
557
|
+
}
|
|
558
|
+
|
|
559
|
+
/**
|
|
560
|
+
* Recursively walk a directory and return all regular files (and bundleable
|
|
561
|
+
* symlinks) as VBundleFileEntry objects with paths prefixed by
|
|
562
|
+
* `archivePrefix`. Symlinks that resolve to a regular file inside the walk
|
|
563
|
+
* root and outside any skipDir are emitted as typeflag-2 entries (data
|
|
564
|
+
* empty, `linkTarget` populated). All other symlinks (broken, directory
|
|
565
|
+
* target, target outside workspace, target inside skipDir, encoded
|
|
566
|
+
* linkTarget over 100 bytes) are reported via the returned `droppedSymlinks`
|
|
567
|
+
* array as workspace-relative paths of the symlink itself.
|
|
353
568
|
*
|
|
354
569
|
* By default, binary files (detected via null-byte heuristic in the first
|
|
355
570
|
* 8 KB) are skipped. Pass `includeBinary: true` to include them.
|
|
356
571
|
*/
|
|
357
|
-
function walkDirectory(
|
|
572
|
+
export function walkDirectory(
|
|
358
573
|
dir: string,
|
|
359
574
|
archivePrefix: string,
|
|
360
575
|
options: WalkDirectoryOptions = {},
|
|
361
|
-
): VBundleFileEntry[] {
|
|
362
|
-
const { includeBinary = false, skipDirs = [] } = options;
|
|
576
|
+
): { files: VBundleFileEntry[]; droppedSymlinks: string[] } {
|
|
577
|
+
const { includeBinary = false, skipDirs = [], skipFiles = [] } = options;
|
|
363
578
|
const entries: VBundleFileEntry[] = [];
|
|
579
|
+
const droppedSymlinks: string[] = [];
|
|
364
580
|
|
|
365
581
|
function walk(currentDir: string): void {
|
|
366
582
|
const dirEntries = readdirSync(currentDir, { withFileTypes: true });
|
|
367
583
|
for (const entry of dirEntries) {
|
|
368
584
|
const fullPath = join(currentDir, entry.name);
|
|
369
585
|
|
|
370
|
-
// Skip symlinks
|
|
371
586
|
const stat = lstatSync(fullPath);
|
|
372
|
-
if (stat.isSymbolicLink())
|
|
587
|
+
if (stat.isSymbolicLink()) {
|
|
588
|
+
const classification = classifySymlink({
|
|
589
|
+
fullPath,
|
|
590
|
+
walkRoot: dir,
|
|
591
|
+
skipDirs,
|
|
592
|
+
});
|
|
593
|
+
if (classification.kind === "class1") {
|
|
594
|
+
entries.push({
|
|
595
|
+
path: `${archivePrefix}/${relative(dir, fullPath)}`,
|
|
596
|
+
data: new Uint8Array(0),
|
|
597
|
+
linkTarget: classification.linkTarget,
|
|
598
|
+
});
|
|
599
|
+
} else {
|
|
600
|
+
droppedSymlinks.push(relative(dir, fullPath));
|
|
601
|
+
}
|
|
602
|
+
continue;
|
|
603
|
+
}
|
|
373
604
|
|
|
374
605
|
if (stat.isDirectory()) {
|
|
375
606
|
// Check skip list against the relative path from the walk root
|
|
@@ -379,6 +610,9 @@ function walkDirectory(
|
|
|
379
610
|
}
|
|
380
611
|
walk(fullPath);
|
|
381
612
|
} else if (stat.isFile()) {
|
|
613
|
+
// Skip files by basename (e.g. backup key)
|
|
614
|
+
if (skipFiles.includes(entry.name)) continue;
|
|
615
|
+
|
|
382
616
|
// Skip SQLite auxiliary files — these are ephemeral and race-prone
|
|
383
617
|
// with the live DB connection. The WAL is checkpointed before the
|
|
384
618
|
// walk, so the main .db file has all committed rows.
|
|
@@ -415,7 +649,7 @@ function walkDirectory(
|
|
|
415
649
|
}
|
|
416
650
|
|
|
417
651
|
walk(dir);
|
|
418
|
-
return entries;
|
|
652
|
+
return { files: entries, droppedSymlinks };
|
|
419
653
|
}
|
|
420
654
|
|
|
421
655
|
// ---------------------------------------------------------------------------
|
|
@@ -423,12 +657,16 @@ function walkDirectory(
|
|
|
423
657
|
// ---------------------------------------------------------------------------
|
|
424
658
|
|
|
425
659
|
export interface BuildExportVBundleOptions {
|
|
426
|
-
/**
|
|
427
|
-
|
|
428
|
-
/**
|
|
429
|
-
|
|
430
|
-
/**
|
|
431
|
-
|
|
660
|
+
/** Identity of the assistant that produced this bundle. */
|
|
661
|
+
assistant: VBundleAssistantInfo;
|
|
662
|
+
/** Where this bundle was produced. */
|
|
663
|
+
origin: VBundleOriginInfo;
|
|
664
|
+
/** Runtime-version compatibility window for importers. */
|
|
665
|
+
compatibility: VBundleCompatibility;
|
|
666
|
+
/** Which optional bundle contents this export carries. */
|
|
667
|
+
exportOptions: VBundleExportOptions;
|
|
668
|
+
/** Whether secrets were stripped from the bundle before archiving. */
|
|
669
|
+
secretsRedacted: boolean;
|
|
432
670
|
/**
|
|
433
671
|
* Absolute path to the workspace directory (~/.vellum/workspace/).
|
|
434
672
|
* When provided and exists, the entire directory tree is walked and
|
|
@@ -455,7 +693,7 @@ export interface BuildExportVBundleOptions {
|
|
|
455
693
|
* Walks the entire workspace directory (~/.vellum/workspace/) and includes
|
|
456
694
|
* all files in the archive, skipping only large/regenerable directories
|
|
457
695
|
* (embedding-models/, data/qdrant/). Binary files (SQLite DB, attachments)
|
|
458
|
-
* are included.
|
|
696
|
+
* are included.
|
|
459
697
|
*
|
|
460
698
|
* The WAL is checkpointed before the walk so the exported DB file contains
|
|
461
699
|
* all committed rows.
|
|
@@ -464,10 +702,12 @@ export function buildExportVBundle(
|
|
|
464
702
|
options: BuildExportVBundleOptions,
|
|
465
703
|
): BuildVBundleResult {
|
|
466
704
|
const {
|
|
467
|
-
|
|
468
|
-
|
|
705
|
+
assistant,
|
|
706
|
+
origin,
|
|
707
|
+
compatibility,
|
|
708
|
+
exportOptions,
|
|
709
|
+
secretsRedacted,
|
|
469
710
|
checkpoint,
|
|
470
|
-
trustPath,
|
|
471
711
|
workspaceDir,
|
|
472
712
|
credentials,
|
|
473
713
|
} = options;
|
|
@@ -488,12 +728,22 @@ export function buildExportVBundle(
|
|
|
488
728
|
existsSync(workspaceDir) &&
|
|
489
729
|
lstatSync(workspaceDir).isDirectory()
|
|
490
730
|
) {
|
|
491
|
-
files
|
|
492
|
-
|
|
731
|
+
const { files: walkedFiles, droppedSymlinks } = walkDirectory(
|
|
732
|
+
workspaceDir,
|
|
733
|
+
"workspace",
|
|
734
|
+
{
|
|
493
735
|
includeBinary: true,
|
|
494
736
|
skipDirs: ["embedding-models", "data/qdrant", "signals", "deprecated"],
|
|
495
|
-
|
|
737
|
+
skipFiles: [".backup.key"],
|
|
738
|
+
},
|
|
496
739
|
);
|
|
740
|
+
files.push(...walkedFiles);
|
|
741
|
+
if (droppedSymlinks.length > 0) {
|
|
742
|
+
getLogger("vbundle-builder").warn(
|
|
743
|
+
{ count: droppedSymlinks.length, paths: droppedSymlinks },
|
|
744
|
+
`Dropped ${droppedSymlinks.length} symlinks pointing outside workspace or into skipped directories`,
|
|
745
|
+
);
|
|
746
|
+
}
|
|
497
747
|
}
|
|
498
748
|
|
|
499
749
|
// Sanitize workspace/config.json to strip environment-specific fields
|
|
@@ -504,12 +754,6 @@ export function buildExportVBundle(
|
|
|
504
754
|
configEntry.data = new TextEncoder().encode(sanitized);
|
|
505
755
|
}
|
|
506
756
|
|
|
507
|
-
// Include trust rules if the file exists.
|
|
508
|
-
if (trustPath && existsSync(trustPath)) {
|
|
509
|
-
const trustData = new Uint8Array(readFileSync(trustPath));
|
|
510
|
-
files.push({ path: "trust/trust.json", data: trustData });
|
|
511
|
-
}
|
|
512
|
-
|
|
513
757
|
// Include credential entries if provided
|
|
514
758
|
if (credentials?.length) {
|
|
515
759
|
for (const { account, value } of credentials) {
|
|
@@ -520,8 +764,11 @@ export function buildExportVBundle(
|
|
|
520
764
|
|
|
521
765
|
return buildVBundle({
|
|
522
766
|
files,
|
|
523
|
-
|
|
524
|
-
|
|
767
|
+
assistant,
|
|
768
|
+
origin,
|
|
769
|
+
compatibility,
|
|
770
|
+
exportOptions,
|
|
771
|
+
secretsRedacted,
|
|
525
772
|
});
|
|
526
773
|
}
|
|
527
774
|
|
|
@@ -531,26 +778,48 @@ export function buildExportVBundle(
|
|
|
531
778
|
|
|
532
779
|
/**
|
|
533
780
|
* Walk a directory tree and collect file metadata (paths + sizes) without
|
|
534
|
-
* reading file contents into memory.
|
|
535
|
-
*
|
|
536
|
-
*
|
|
781
|
+
* reading file contents into memory. Mirrors `walkDirectory`'s filtering
|
|
782
|
+
* logic (SQLite auxiliary skip, binary detection, skipDirs) and symlink
|
|
783
|
+
* classification — bundleable symlinks are emitted as `SymlinkMetadata`
|
|
784
|
+
* entries; non-bundleable symlinks are reported via `droppedSymlinks`.
|
|
537
785
|
*/
|
|
538
|
-
function walkDirectoryForMetadata(
|
|
786
|
+
export function walkDirectoryForMetadata(
|
|
539
787
|
dir: string,
|
|
540
788
|
archivePrefix: string,
|
|
541
789
|
options: WalkDirectoryOptions = {},
|
|
542
|
-
):
|
|
543
|
-
|
|
790
|
+
): {
|
|
791
|
+
files: FileMetadata[];
|
|
792
|
+
symlinks: SymlinkMetadata[];
|
|
793
|
+
droppedSymlinks: string[];
|
|
794
|
+
} {
|
|
795
|
+
const { includeBinary = false, skipDirs = [], skipFiles = [] } = options;
|
|
544
796
|
const entries: FileMetadata[] = [];
|
|
797
|
+
const symlinks: SymlinkMetadata[] = [];
|
|
798
|
+
const droppedSymlinks: string[] = [];
|
|
545
799
|
|
|
546
800
|
function walk(currentDir: string): void {
|
|
547
801
|
const dirEntries = readdirSync(currentDir, { withFileTypes: true });
|
|
548
802
|
for (const entry of dirEntries) {
|
|
549
803
|
const fullPath = join(currentDir, entry.name);
|
|
550
804
|
|
|
551
|
-
// Skip symlinks
|
|
552
805
|
const fileStat = lstatSync(fullPath);
|
|
553
|
-
if (fileStat.isSymbolicLink())
|
|
806
|
+
if (fileStat.isSymbolicLink()) {
|
|
807
|
+
const classification = classifySymlink({
|
|
808
|
+
fullPath,
|
|
809
|
+
walkRoot: dir,
|
|
810
|
+
skipDirs,
|
|
811
|
+
});
|
|
812
|
+
if (classification.kind === "class1") {
|
|
813
|
+
symlinks.push({
|
|
814
|
+
archivePath: `${archivePrefix}/${relative(dir, fullPath)}`,
|
|
815
|
+
linkTarget: classification.linkTarget,
|
|
816
|
+
size: 0,
|
|
817
|
+
});
|
|
818
|
+
} else {
|
|
819
|
+
droppedSymlinks.push(relative(dir, fullPath));
|
|
820
|
+
}
|
|
821
|
+
continue;
|
|
822
|
+
}
|
|
554
823
|
|
|
555
824
|
if (fileStat.isDirectory()) {
|
|
556
825
|
// Check skip list against the relative path from the walk root
|
|
@@ -560,6 +829,9 @@ function walkDirectoryForMetadata(
|
|
|
560
829
|
}
|
|
561
830
|
walk(fullPath);
|
|
562
831
|
} else if (fileStat.isFile()) {
|
|
832
|
+
// Skip files by basename (e.g. backup key)
|
|
833
|
+
if (skipFiles.includes(entry.name)) continue;
|
|
834
|
+
|
|
563
835
|
// Skip SQLite auxiliary files — these are ephemeral and race-prone
|
|
564
836
|
if (
|
|
565
837
|
entry.name.endsWith(".db-wal") ||
|
|
@@ -603,7 +875,7 @@ function walkDirectoryForMetadata(
|
|
|
603
875
|
}
|
|
604
876
|
|
|
605
877
|
walk(dir);
|
|
606
|
-
return entries;
|
|
878
|
+
return { files: entries, symlinks, droppedSymlinks };
|
|
607
879
|
}
|
|
608
880
|
|
|
609
881
|
/**
|
|
@@ -629,8 +901,18 @@ async function computeFileSha256(
|
|
|
629
901
|
/**
|
|
630
902
|
* Create just the 512-byte tar header block for a regular file entry.
|
|
631
903
|
* Extracted from `createTarEntry` logic — does NOT include data or padding.
|
|
904
|
+
*
|
|
905
|
+
* When `linkTarget` is provided, the header is emitted as a tar typeflag-2
|
|
906
|
+
* (symlink) record: typeflag is "2", the link target is written into the
|
|
907
|
+
* `linkname` field (header[157..256], 100-byte limit), and `size` is forced
|
|
908
|
+
* to 0 in the header field. Caller is responsible for not yielding any body
|
|
909
|
+
* or padding bytes for symlink entries.
|
|
632
910
|
*/
|
|
633
|
-
function createTarHeaderBlock(
|
|
911
|
+
function createTarHeaderBlock(
|
|
912
|
+
name: string,
|
|
913
|
+
size: number,
|
|
914
|
+
linkTarget?: string,
|
|
915
|
+
): Uint8Array {
|
|
634
916
|
const encoder = new TextEncoder();
|
|
635
917
|
const nameBytes = encoder.encode(name);
|
|
636
918
|
|
|
@@ -648,14 +930,26 @@ function createTarHeaderBlock(name: string, size: number): Uint8Array {
|
|
|
648
930
|
// Group ID (116-123)
|
|
649
931
|
writeOctal(header, 116, 8, 0);
|
|
650
932
|
|
|
651
|
-
// File size (124-135)
|
|
652
|
-
writeOctal(header, 124, 12, size);
|
|
933
|
+
// File size (124-135) — symlink entries always declare size=0
|
|
934
|
+
writeOctal(header, 124, 12, linkTarget !== undefined ? 0 : size);
|
|
653
935
|
|
|
654
936
|
// Modification time (136-147)
|
|
655
937
|
writeOctal(header, 136, 12, Math.floor(Date.now() / 1000));
|
|
656
938
|
|
|
657
|
-
// Type flag (156): regular file
|
|
658
|
-
header[156] =
|
|
939
|
+
// Type flag (156): regular file ("0") or symlink ("2")
|
|
940
|
+
header[156] =
|
|
941
|
+
linkTarget !== undefined ? "2".charCodeAt(0) : "0".charCodeAt(0);
|
|
942
|
+
|
|
943
|
+
// Linkname (157-256, 100 bytes) — only set for symlink entries
|
|
944
|
+
if (linkTarget !== undefined) {
|
|
945
|
+
const linkBytes = encoder.encode(linkTarget);
|
|
946
|
+
if (linkBytes.length > 100) {
|
|
947
|
+
throw new Error(
|
|
948
|
+
`symlink target exceeds 100-byte ustar linkname limit (${linkBytes.length} bytes): ${linkTarget}`,
|
|
949
|
+
);
|
|
950
|
+
}
|
|
951
|
+
header.set(linkBytes, 157);
|
|
952
|
+
}
|
|
659
953
|
|
|
660
954
|
// USTAR magic (257-262)
|
|
661
955
|
const magic = encoder.encode("ustar\0");
|
|
@@ -665,7 +959,8 @@ function createTarHeaderBlock(name: string, size: number): Uint8Array {
|
|
|
665
959
|
header[263] = "0".charCodeAt(0);
|
|
666
960
|
header[264] = "0".charCodeAt(0);
|
|
667
961
|
|
|
668
|
-
// Compute and write checksum (148-155)
|
|
962
|
+
// Compute and write checksum (148-155). Must run AFTER linkname is set
|
|
963
|
+
// so the checksum covers the symlink target bytes.
|
|
669
964
|
const checksum = computeHeaderChecksum(header);
|
|
670
965
|
writeOctal(header, 148, 7, checksum);
|
|
671
966
|
header[155] = 0x20; // trailing space
|
|
@@ -677,13 +972,21 @@ function createTarHeaderBlock(name: string, size: number): Uint8Array {
|
|
|
677
972
|
* If name exceeds 100 bytes, returns the PAX extended header entry
|
|
678
973
|
* concatenated with the regular header block. Otherwise returns just
|
|
679
974
|
* the header block.
|
|
975
|
+
*
|
|
976
|
+
* `linkTarget` is forwarded to `createTarHeaderBlock` so symlink entries
|
|
977
|
+
* still get a PAX path header for long names while emitting a typeflag-2
|
|
978
|
+
* ustar block.
|
|
680
979
|
*/
|
|
681
|
-
function createPaxAndHeaderBlocks(
|
|
980
|
+
function createPaxAndHeaderBlocks(
|
|
981
|
+
name: string,
|
|
982
|
+
size: number,
|
|
983
|
+
linkTarget?: string,
|
|
984
|
+
): Uint8Array {
|
|
682
985
|
const encoder = new TextEncoder();
|
|
683
986
|
const nameBytes = encoder.encode(name);
|
|
684
987
|
const needsPax = nameBytes.length > 100;
|
|
685
988
|
|
|
686
|
-
const header = createTarHeaderBlock(name, size);
|
|
989
|
+
const header = createTarHeaderBlock(name, size, linkTarget);
|
|
687
990
|
|
|
688
991
|
if (needsPax) {
|
|
689
992
|
const paxEntry = createPaxPathEntry(name);
|
|
@@ -721,7 +1024,15 @@ async function* generateTarStream(
|
|
|
721
1024
|
|
|
722
1025
|
// File entries
|
|
723
1026
|
for (const file of files) {
|
|
724
|
-
|
|
1027
|
+
if (isSymlinkEntry(file)) {
|
|
1028
|
+
// Symlink entry: typeflag-2 header carries the linkname; no body, no
|
|
1029
|
+
// padding. Skip the entrySize/body/padding logic entirely so the
|
|
1030
|
+
// surrounding stream stays block-aligned.
|
|
1031
|
+
yield createPaxAndHeaderBlocks(file.archivePath, 0, file.linkTarget);
|
|
1032
|
+
continue;
|
|
1033
|
+
}
|
|
1034
|
+
|
|
1035
|
+
const entrySize = file.size;
|
|
725
1036
|
yield createPaxAndHeaderBlocks(file.archivePath, entrySize);
|
|
726
1037
|
|
|
727
1038
|
if (isInMemoryEntry(file)) {
|
|
@@ -799,10 +1110,12 @@ export async function streamExportVBundle(
|
|
|
799
1110
|
options: BuildExportVBundleOptions,
|
|
800
1111
|
): Promise<StreamExportVBundleResult> {
|
|
801
1112
|
const {
|
|
802
|
-
|
|
803
|
-
|
|
1113
|
+
assistant,
|
|
1114
|
+
origin,
|
|
1115
|
+
compatibility,
|
|
1116
|
+
exportOptions,
|
|
1117
|
+
secretsRedacted,
|
|
804
1118
|
checkpoint,
|
|
805
|
-
trustPath,
|
|
806
1119
|
workspaceDir,
|
|
807
1120
|
credentials,
|
|
808
1121
|
} = options;
|
|
@@ -813,6 +1126,7 @@ export async function streamExportVBundle(
|
|
|
813
1126
|
}
|
|
814
1127
|
|
|
815
1128
|
const allFileMetadata: FileMetadata[] = [];
|
|
1129
|
+
const symlinkEntries: SymlinkMetadata[] = [];
|
|
816
1130
|
|
|
817
1131
|
// Walk the entire workspace directory, including binary files
|
|
818
1132
|
if (
|
|
@@ -820,23 +1134,22 @@ export async function streamExportVBundle(
|
|
|
820
1134
|
existsSync(workspaceDir) &&
|
|
821
1135
|
lstatSync(workspaceDir).isDirectory()
|
|
822
1136
|
) {
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
if (
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
});
|
|
1137
|
+
const {
|
|
1138
|
+
files: walkedFiles,
|
|
1139
|
+
symlinks: walkedSymlinks,
|
|
1140
|
+
droppedSymlinks,
|
|
1141
|
+
} = walkDirectoryForMetadata(workspaceDir, "workspace", {
|
|
1142
|
+
includeBinary: true,
|
|
1143
|
+
skipDirs: ["embedding-models", "data/qdrant", "signals", "deprecated"],
|
|
1144
|
+
skipFiles: [".backup.key"],
|
|
1145
|
+
});
|
|
1146
|
+
allFileMetadata.push(...walkedFiles);
|
|
1147
|
+
symlinkEntries.push(...walkedSymlinks);
|
|
1148
|
+
if (droppedSymlinks.length > 0) {
|
|
1149
|
+
getLogger("vbundle-builder").warn(
|
|
1150
|
+
{ count: droppedSymlinks.length, paths: droppedSymlinks },
|
|
1151
|
+
`Dropped ${droppedSymlinks.length} symlinks pointing outside workspace or into skipped directories`,
|
|
1152
|
+
);
|
|
840
1153
|
}
|
|
841
1154
|
}
|
|
842
1155
|
|
|
@@ -886,7 +1199,7 @@ export async function streamExportVBundle(
|
|
|
886
1199
|
fileEntries.push({
|
|
887
1200
|
path: file.archivePath,
|
|
888
1201
|
sha256,
|
|
889
|
-
|
|
1202
|
+
size_bytes: file.size,
|
|
890
1203
|
});
|
|
891
1204
|
}
|
|
892
1205
|
|
|
@@ -896,25 +1209,32 @@ export async function streamExportVBundle(
|
|
|
896
1209
|
fileEntries.push({
|
|
897
1210
|
path: entry.archivePath,
|
|
898
1211
|
sha256,
|
|
899
|
-
|
|
1212
|
+
size_bytes: entry.size,
|
|
900
1213
|
});
|
|
901
1214
|
}
|
|
902
1215
|
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
};
|
|
1216
|
+
// Add symlink entries to the manifest. The sha256 is computed over the
|
|
1217
|
+
// link target string (UTF-8 encoded) so the streaming validator can
|
|
1218
|
+
// verify the manifest declared the same target the tar header carries.
|
|
1219
|
+
// size_bytes is always 0 for symlink entries.
|
|
1220
|
+
for (const entry of symlinkEntries) {
|
|
1221
|
+
fileEntries.push({
|
|
1222
|
+
path: entry.archivePath,
|
|
1223
|
+
sha256: sha256Hex(entry.linkTarget),
|
|
1224
|
+
size_bytes: 0,
|
|
1225
|
+
link_target: entry.linkTarget,
|
|
1226
|
+
});
|
|
1227
|
+
}
|
|
916
1228
|
|
|
917
|
-
const manifestData =
|
|
1229
|
+
const { manifest, manifestData } = buildManifestObject({
|
|
1230
|
+
contents: fileEntries,
|
|
1231
|
+
assistant,
|
|
1232
|
+
origin,
|
|
1233
|
+
compatibility,
|
|
1234
|
+
exportOptions,
|
|
1235
|
+
secretsRedacted,
|
|
1236
|
+
now: new Date(),
|
|
1237
|
+
});
|
|
918
1238
|
|
|
919
1239
|
// ------------------------------------------------------------------
|
|
920
1240
|
// Pass 2: Stream tar through gzip into a temp file
|
|
@@ -926,6 +1246,7 @@ export async function streamExportVBundle(
|
|
|
926
1246
|
...allFileMetadata,
|
|
927
1247
|
...sanitizedConfigEntries,
|
|
928
1248
|
...inMemoryEntries,
|
|
1249
|
+
...symlinkEntries,
|
|
929
1250
|
];
|
|
930
1251
|
const tarGenerator = generateTarStream(manifestData, allEntries);
|
|
931
1252
|
const tarReadable = Readable.from(tarGenerator);
|