@vellumai/assistant 0.6.1 → 0.6.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bun.lock +40 -40
- package/bunfig.toml +3 -0
- package/docker-entrypoint.sh +12 -2
- package/docs/architecture/memory.md +1 -1
- package/node_modules/@vellumai/ces-contracts/src/handles.ts +7 -9
- package/node_modules/@vellumai/ces-contracts/src/rpc.ts +42 -0
- package/openapi.yaml +184 -69
- package/package.json +41 -41
- package/scripts/generate-openapi.ts +1 -2
- package/src/__tests__/acp-session.test.ts +43 -0
- package/src/__tests__/app-builder-tool-scripts.test.ts +1 -0
- package/src/__tests__/app-executors.test.ts +1 -0
- package/src/__tests__/app-source-watcher.test.ts +37 -11
- package/src/__tests__/approval-routes-http.test.ts +178 -1
- package/src/__tests__/assistant-event-hub.test.ts +30 -0
- package/src/__tests__/browser-fill-credential.test.ts +229 -94
- package/src/__tests__/browser-manager.test.ts +40 -27
- package/src/__tests__/catalog-files.test.ts +862 -0
- package/src/__tests__/channel-approvals.test.ts +53 -0
- package/src/__tests__/checker.test.ts +104 -170
- package/src/__tests__/cli-command-risk-guard.test.ts +1 -1
- package/src/__tests__/config-managed-gemini-defaults.test.ts +326 -0
- package/src/__tests__/config-schema-cmd.test.ts +2 -2
- package/src/__tests__/config-schema.test.ts +125 -48
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +23 -0
- package/src/__tests__/context-overflow-approval.test.ts +21 -6
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop.test.ts +1 -1
- package/src/__tests__/conversation-analysis-routes.test.ts +169 -0
- package/src/__tests__/conversation-attachments.test.ts +80 -4
- package/src/__tests__/conversation-confirmation-signals.test.ts +155 -0
- package/src/__tests__/conversation-directories-parse.test.ts +105 -0
- package/src/__tests__/conversation-fork-crud.test.ts +17 -0
- package/src/__tests__/conversation-history-web-search.test.ts +1 -0
- package/src/__tests__/conversation-host-access-routes.test.ts +229 -0
- package/src/__tests__/conversation-inject-context.test.ts +103 -0
- package/src/__tests__/conversation-queue.test.ts +45 -2
- package/src/__tests__/conversation-routes-disk-view.test.ts +5 -0
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +16 -0
- package/src/__tests__/conversation-routes-slash-commands.test.ts +1 -0
- package/src/__tests__/conversation-runtime-assembly.test.ts +269 -46
- package/src/__tests__/conversation-starter-routes.test.ts +126 -0
- package/src/__tests__/conversation-starters-cadence.test.ts +161 -0
- package/src/__tests__/conversation-store.test.ts +195 -0
- package/src/__tests__/conversation-workspace-cache-state.test.ts +193 -0
- package/src/__tests__/credential-execution-approval-bridge.test.ts +32 -3
- package/src/__tests__/credential-security-invariants.test.ts +1 -0
- package/src/__tests__/credential-vault-unit.test.ts +4 -4
- package/src/__tests__/credential-vault.test.ts +152 -13
- package/src/__tests__/credentials-cli.test.ts +2 -2
- package/src/__tests__/date-context.test.ts +4 -4
- package/src/__tests__/embedding-managed-proxy-selection.test.ts +256 -0
- package/src/__tests__/extension-id-sync-guard.test.ts +155 -0
- package/src/__tests__/fixtures/mock-chrome-extension.ts +375 -0
- package/src/__tests__/gateway-only-guard.test.ts +3 -0
- package/src/__tests__/gemini-provider.test.ts +2 -2
- package/src/__tests__/guardian-routing-invariants.test.ts +70 -2
- package/src/__tests__/headless-browser-interactions.test.ts +707 -371
- package/src/__tests__/headless-browser-navigate.test.ts +389 -47
- package/src/__tests__/headless-browser-read-tools.test.ts +266 -103
- package/src/__tests__/headless-browser-snapshot.test.ts +240 -77
- package/src/__tests__/host-bash-proxy.test.ts +150 -1
- package/src/__tests__/host-browser-e2e-cloud.test.ts +462 -0
- package/src/__tests__/host-browser-e2e-self-hosted-capability.test.ts +286 -0
- package/src/__tests__/host-browser-e2e-self-hosted.test.ts +374 -0
- package/src/__tests__/host-browser-event-routes.test.ts +350 -0
- package/src/__tests__/host-browser-proxy.test.ts +444 -0
- package/src/__tests__/host-browser-routes.test.ts +198 -0
- package/src/__tests__/host-browser-ws-events-e2e.test.ts +320 -0
- package/src/__tests__/host-cu-proxy.test.ts +171 -1
- package/src/__tests__/host-file-proxy.test.ts +185 -1
- package/src/__tests__/host-file-read-tool.test.ts +52 -0
- package/src/__tests__/host-proxy-interface.test.ts +165 -0
- package/src/__tests__/host-shell-tool.test.ts +1 -11
- package/src/__tests__/http-user-message-parity.test.ts +1 -0
- package/src/__tests__/init-feature-flag-overrides.test.ts +167 -0
- package/src/__tests__/inline-command-runner.test.ts +7 -5
- package/src/__tests__/integration-status.test.ts +6 -7
- package/src/__tests__/list-messages-tool-merge.test.ts +37 -12
- package/src/__tests__/log-export-workspace.test.ts +190 -0
- package/src/__tests__/managed-credential-catalog-cli.test.ts +12 -14
- package/src/__tests__/mcp-client-auth.test.ts +40 -4
- package/src/__tests__/mcp-health-check.test.ts +10 -3
- package/src/__tests__/migration-cross-version-compatibility.test.ts +3 -1
- package/src/__tests__/migration-export-http.test.ts +61 -2
- package/src/__tests__/migration-export-streaming.test.ts +66 -0
- package/src/__tests__/migration-import-commit-http.test.ts +101 -1
- package/src/__tests__/native-host-marker-sync-guard.test.ts +157 -0
- package/src/__tests__/navigate-settings-tab.test.ts +14 -1
- package/src/__tests__/notification-broadcaster.test.ts +65 -0
- package/src/__tests__/oauth-apps-routes.test.ts +17 -12
- package/src/__tests__/oauth-cli.test.ts +707 -60
- package/src/__tests__/oauth-connect-orchestrator.test.ts +116 -24
- package/src/__tests__/oauth-provider-seed-logos.test.ts +23 -0
- package/src/__tests__/oauth-provider-serializer.test.ts +146 -10
- package/src/__tests__/oauth-provider-visibility.test.ts +19 -21
- package/src/__tests__/oauth-providers-routes.test.ts +50 -14
- package/src/__tests__/oauth-store.test.ts +1386 -182
- package/src/__tests__/oauth2-gateway-transport.test.ts +211 -20
- package/src/__tests__/onboarding-template-contract.test.ts +74 -55
- package/src/__tests__/openai-provider.test.ts +2 -2
- package/src/__tests__/outlook-categories.test.ts +1 -1
- package/src/__tests__/outlook-client-automation.test.ts +1 -1
- package/src/__tests__/outlook-compose-tools.test.ts +1 -1
- package/src/__tests__/outlook-email-watcher.test.ts +1 -1
- package/src/__tests__/outlook-follow-up.test.ts +1 -1
- package/src/__tests__/outlook-messaging-provider.test.ts +2 -2
- package/src/__tests__/outlook-trash.test.ts +1 -1
- package/src/__tests__/outlook-unsubscribe.test.ts +1 -1
- package/src/__tests__/permission-checker-host-gate.test.ts +74 -14
- package/src/__tests__/permission-mode.test.ts +28 -56
- package/src/__tests__/pkb-autoinject.test.ts +96 -0
- package/src/__tests__/platform-callback-registration.test.ts +19 -0
- package/src/__tests__/post-turn-tool-result-truncation.test.ts +296 -0
- package/src/__tests__/proxy-approval-callback.test.ts +18 -0
- package/src/__tests__/require-fresh-approval.test.ts +40 -3
- package/src/__tests__/sandbox-diagnostics.test.ts +1 -32
- package/src/__tests__/sanitize-config-for-transfer.test.ts +132 -0
- package/src/__tests__/schedule-routes.test.ts +162 -0
- package/src/__tests__/secret-detection-handler.test.ts +84 -0
- package/src/__tests__/secret-ingress-http.test.ts +1 -0
- package/src/__tests__/send-endpoint-busy.test.ts +3 -0
- package/src/__tests__/set-permission-mode.test.ts +13 -250
- package/src/__tests__/skills-file-content-endpoint.test.ts +670 -0
- package/src/__tests__/skills-files-catalog-fallback.test.ts +450 -0
- package/src/__tests__/slack-channel-config.test.ts +12 -15
- package/src/__tests__/subagent-detail.test.ts +44 -2
- package/src/__tests__/subagent-disposal.test.ts +1 -0
- package/src/__tests__/subagent-fork-notifications.test.ts +291 -0
- package/src/__tests__/subagent-fork-spawn.test.ts +384 -0
- package/src/__tests__/subagent-manager-notify.test.ts +1 -0
- package/src/__tests__/subagent-notify-parent.test.ts +1 -0
- package/src/__tests__/subagent-spawn-tool-fork.test.ts +411 -0
- package/src/__tests__/subagent-tools.test.ts +1 -0
- package/src/__tests__/subagent-types.test.ts +1 -0
- package/src/__tests__/system-prompt-ask-mode.test.ts +27 -71
- package/src/__tests__/system-prompt.test.ts +72 -1
- package/src/__tests__/task-scheduler.test.ts +32 -6
- package/src/__tests__/telegram-config.test.ts +10 -13
- package/src/__tests__/terminal-sandbox.test.ts +1 -1
- package/src/__tests__/terminal-tools.test.ts +11 -5
- package/src/__tests__/test-preload.ts +14 -0
- package/src/__tests__/tool-approval-handler.test.ts +73 -0
- package/src/__tests__/tool-domain-event-publisher.test.ts +0 -1
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +1 -8
- package/src/__tests__/tool-executor.test.ts +0 -1
- package/src/__tests__/tool-side-effects-slack-dm.test.ts +22 -0
- package/src/__tests__/top-level-renderer.test.ts +73 -1
- package/src/__tests__/transport-hints-queue.test.ts +62 -0
- package/src/__tests__/trust-store.test.ts +4 -4
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +109 -0
- package/src/__tests__/v2-consent-policy.test.ts +103 -0
- package/src/__tests__/workspace-migration-030-seed-pkb-autoinject.test.ts +168 -0
- package/src/__tests__/workspace-policy.test.ts +2 -7
- package/src/acp/client-handler.ts +30 -4
- package/src/agent/loop.ts +12 -35
- package/src/approvals/guardian-request-resolvers.ts +21 -15
- package/src/browser-session/__tests__/manager.test.ts +297 -0
- package/src/browser-session/backends/cdp-inspect.ts +30 -0
- package/src/browser-session/backends/extension.ts +26 -0
- package/src/browser-session/backends/local.ts +24 -0
- package/src/browser-session/events.ts +164 -0
- package/src/browser-session/index.ts +27 -0
- package/src/browser-session/manager.ts +159 -0
- package/src/browser-session/types.ts +28 -0
- package/src/channels/__tests__/types.test.ts +134 -0
- package/src/channels/types.ts +55 -0
- package/src/cli/__tests__/run-assistant-command.ts +34 -7
- package/src/cli/__tests__/unknown-command.test.ts +33 -0
- package/src/cli/commands/browser-relay.ts +339 -409
- package/src/cli/commands/credentials.ts +3 -3
- package/src/cli/commands/default-action.ts +68 -1
- package/src/cli/commands/email.ts +18 -13
- package/src/cli/commands/mcp.ts +16 -4
- package/src/cli/commands/oauth/__tests__/connect.test.ts +68 -41
- package/src/cli/commands/oauth/__tests__/disconnect.test.ts +21 -21
- package/src/cli/commands/oauth/__tests__/mode.test.ts +17 -17
- package/src/cli/commands/oauth/__tests__/ping.test.ts +16 -16
- package/src/cli/commands/oauth/__tests__/providers-delete.test.ts +31 -33
- package/src/cli/commands/oauth/__tests__/providers-register.test.ts +329 -0
- package/src/cli/commands/oauth/__tests__/providers-update.test.ts +116 -12
- package/src/cli/commands/oauth/__tests__/status.test.ts +10 -10
- package/src/cli/commands/oauth/__tests__/token.test.ts +7 -7
- package/src/cli/commands/oauth/apps.ts +7 -4
- package/src/cli/commands/oauth/connect.ts +16 -2
- package/src/cli/commands/oauth/disconnect.ts +1 -1
- package/src/cli/commands/oauth/providers.ts +200 -36
- package/src/cli/commands/oauth/shared.ts +5 -5
- package/src/cli/commands/platform/__tests__/callback-routes-list.test.ts +259 -0
- package/src/cli/commands/platform/__tests__/connect.test.ts +1 -1
- package/src/cli/commands/platform/__tests__/disconnect.test.ts +1 -1
- package/src/cli/commands/platform/__tests__/status.test.ts +1 -1
- package/src/cli/commands/platform/index.ts +107 -10
- package/src/cli/commands/usage.ts +10 -9
- package/src/cli/lib/daemon-credential-client.ts +4 -0
- package/src/cli/program.ts +10 -3
- package/src/config/assistant-feature-flags.ts +59 -55
- package/src/config/bundled-skills/app-builder/SKILL.md +33 -173
- package/src/config/bundled-skills/app-builder/references/CUSTOM_ROUTES.md +105 -0
- package/src/config/bundled-skills/app-builder/references/INTERACTION_HOOKS.md +56 -0
- package/src/config/bundled-skills/app-builder/references/WIDGETS.md +125 -0
- package/src/config/bundled-skills/contacts/SKILL.md +3 -0
- package/src/config/bundled-skills/document/SKILL.md +4 -0
- package/src/config/bundled-skills/gmail/SKILL.md +12 -7
- package/src/config/bundled-skills/gmail/TOOLS.json +1 -1
- package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +2 -1
- package/src/config/bundled-skills/outlook/SKILL.md +7 -0
- package/src/config/bundled-skills/settings/TOOLS.json +1 -1
- package/src/config/bundled-skills/settings/tools/navigate-settings-tab.ts +8 -3
- package/src/config/bundled-skills/subagent/SKILL.md +21 -0
- package/src/config/bundled-skills/subagent/TOOLS.json +8 -4
- package/src/config/bundled-skills/tasks/SKILL.md +5 -0
- package/src/config/env-registry.ts +14 -0
- package/src/config/env.ts +21 -0
- package/src/config/feature-flag-registry.json +46 -7
- package/src/config/loader.ts +56 -1
- package/src/config/sanitize-for-transfer.ts +47 -0
- package/src/config/schema.ts +46 -5
- package/src/config/schemas/host-browser.ts +66 -0
- package/src/config/schemas/memory-lifecycle.ts +1 -1
- package/src/config/schemas/memory-retrieval.ts +103 -0
- package/src/config/schemas/security.ts +0 -6
- package/src/config/schemas/services.ts +16 -0
- package/src/config/types.ts +0 -1
- package/src/context/post-turn-tool-result-truncation.ts +176 -0
- package/src/context/window-manager.ts +19 -1
- package/src/credential-execution/approval-bridge.ts +49 -16
- package/src/credential-execution/managed-catalog.ts +3 -7
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +186 -0
- package/src/daemon/app-source-watcher.ts +35 -0
- package/src/daemon/config-watcher.ts +6 -2
- package/src/daemon/context-overflow-approval.ts +5 -1
- package/src/daemon/conversation-agent-loop-handlers.ts +17 -2
- package/src/daemon/conversation-agent-loop.ts +74 -19
- package/src/daemon/conversation-attachments.ts +40 -1
- package/src/daemon/conversation-messaging.ts +3 -0
- package/src/daemon/conversation-process.ts +66 -3
- package/src/daemon/conversation-queue-manager.ts +8 -0
- package/src/daemon/conversation-runtime-assembly.ts +159 -20
- package/src/daemon/conversation-surfaces.ts +78 -12
- package/src/daemon/conversation-tool-setup.ts +74 -11
- package/src/daemon/conversation-workspace.ts +12 -0
- package/src/daemon/conversation.ts +227 -11
- package/src/daemon/date-context.ts +10 -10
- package/src/daemon/first-greeting.ts +3 -2
- package/src/daemon/handlers/conversations.ts +9 -139
- package/src/daemon/handlers/shared.ts +65 -0
- package/src/daemon/handlers/skills.ts +232 -37
- package/src/daemon/host-bash-proxy.ts +48 -13
- package/src/daemon/host-browser-proxy.ts +191 -0
- package/src/daemon/host-cu-proxy.ts +36 -11
- package/src/daemon/host-file-proxy.ts +57 -9
- package/src/daemon/lifecycle.ts +86 -12
- package/src/daemon/message-protocol.ts +7 -0
- package/src/daemon/message-types/conversations.ts +59 -13
- package/src/daemon/message-types/host-browser.ts +100 -0
- package/src/daemon/message-types/messages.ts +5 -6
- package/src/daemon/message-types/notifications.ts +12 -0
- package/src/daemon/message-types/settings.ts +12 -0
- package/src/daemon/message-types/skills.ts +10 -0
- package/src/daemon/message-types/subagents.ts +2 -0
- package/src/daemon/server.ts +112 -35
- package/src/daemon/tool-side-effects.ts +6 -0
- package/src/daemon/transport-hints.ts +14 -0
- package/src/inbound/platform-callback-registration.ts +18 -17
- package/src/index.ts +1 -1
- package/src/mcp/client.ts +59 -24
- package/src/memory/app-store.ts +31 -1
- package/src/memory/conversation-crud.ts +38 -10
- package/src/memory/conversation-directories.ts +39 -0
- package/src/memory/conversation-group-migration.ts +65 -5
- package/src/memory/conversation-starters-cadence.ts +76 -0
- package/src/memory/conversation-title-service.ts +5 -2
- package/src/memory/db-init.ts +12 -0
- package/src/memory/embedding-backend.test.ts +75 -0
- package/src/memory/embedding-backend.ts +131 -5
- package/src/memory/embedding-gemini.test.ts +54 -0
- package/src/memory/embedding-gemini.ts +20 -9
- package/src/memory/embedding-local.ts +177 -18
- package/src/memory/graph/capability-seed.ts +3 -5
- package/src/memory/graph/consolidation.ts +10 -23
- package/src/memory/graph/extraction-job.ts +15 -0
- package/src/memory/graph/retriever.ts +40 -22
- package/src/memory/graph/store.test.ts +7 -3
- package/src/memory/graph/store.ts +47 -12
- package/src/memory/group-crud.ts +25 -9
- package/src/memory/llm-usage-store.ts +45 -4
- package/src/memory/migrations/213-oauth-providers-scope-separator.ts +13 -0
- package/src/memory/migrations/214-oauth-providers-refresh-url.ts +11 -0
- package/src/memory/migrations/215-oauth-providers-revoke.ts +14 -0
- package/src/memory/migrations/216-oauth-providers-token-auth-method.ts +30 -0
- package/src/memory/migrations/217-conversation-host-access.ts +40 -0
- package/src/memory/migrations/218-oauth-providers-logo-url.ts +11 -0
- package/src/memory/migrations/index.ts +6 -0
- package/src/memory/migrations/registry.ts +8 -0
- package/src/memory/schema/conversations.ts +1 -0
- package/src/memory/schema/oauth.ts +18 -13
- package/src/messaging/provider.ts +1 -1
- package/src/notifications/broadcaster.ts +6 -0
- package/src/notifications/conversation-pairing.ts +12 -4
- package/src/notifications/emit-signal.ts +14 -0
- package/src/notifications/signal.ts +11 -0
- package/src/oauth/AGENTS.md +76 -0
- package/src/oauth/__tests__/identity-verifier.test.ts +24 -19
- package/src/oauth/__tests__/seed-providers-managed.test.ts +32 -0
- package/src/oauth/byo-connection.test.ts +8 -8
- package/src/oauth/byo-connection.ts +7 -7
- package/src/oauth/connect-orchestrator.ts +23 -21
- package/src/oauth/connect-types.ts +3 -3
- package/src/oauth/connection-resolver.test.ts +17 -4
- package/src/oauth/connection-resolver.ts +16 -16
- package/src/oauth/connection.ts +1 -1
- package/src/oauth/manual-token-connection.ts +13 -13
- package/src/oauth/oauth-store.ts +214 -100
- package/src/oauth/platform-connection.test.ts +5 -5
- package/src/oauth/platform-connection.ts +4 -4
- package/src/oauth/provider-serializer.ts +31 -5
- package/src/oauth/revoke.ts +76 -0
- package/src/oauth/seed-providers.ts +127 -87
- package/src/oauth/token-persistence.ts +1 -1
- package/src/permissions/checker.ts +3 -3
- package/src/permissions/defaults.ts +7 -8
- package/src/permissions/permission-mode.ts +4 -11
- package/src/permissions/prompter.ts +13 -3
- package/src/permissions/v2-consent-policy.ts +87 -0
- package/src/platform/client.ts +1 -1
- package/src/prompts/system-prompt.ts +18 -21
- package/src/prompts/templates/BOOTSTRAP-REFERENCE.md +3 -65
- package/src/prompts/templates/BOOTSTRAP.md +59 -96
- package/src/prompts/templates/SOUL.md +11 -11
- package/src/providers/anthropic/client.ts +1 -0
- package/src/providers/types.ts +1 -1
- package/src/runtime/AGENTS.md +23 -0
- package/src/runtime/__tests__/browser-extension-pair-routes.test.ts +715 -0
- package/src/runtime/__tests__/capability-tokens.test.ts +258 -0
- package/src/runtime/__tests__/chrome-extension-registry.test.ts +518 -0
- package/src/runtime/assistant-event-hub.ts +24 -2
- package/src/runtime/auth/__tests__/guard-tests.test.ts +1 -0
- package/src/runtime/auth/__tests__/middleware.test.ts +116 -1
- package/src/runtime/auth/__tests__/route-policy.test.ts +8 -0
- package/src/runtime/auth/middleware.ts +98 -0
- package/src/runtime/auth/route-policy.ts +6 -7
- package/src/runtime/auth/token-service.ts +8 -0
- package/src/runtime/capability-tokens.ts +414 -0
- package/src/runtime/channel-approvals.ts +18 -5
- package/src/runtime/chrome-extension-registry.ts +332 -0
- package/src/runtime/confirmation-request-guardian-bridge.ts +6 -0
- package/src/runtime/guardian-decision-types.ts +7 -0
- package/src/runtime/http-server.ts +425 -70
- package/src/runtime/migrations/__tests__/rebind-secrets-credentials.test.ts +172 -0
- package/src/runtime/migrations/__tests__/vbundle-builder-credentials.test.ts +276 -0
- package/src/runtime/migrations/__tests__/vbundle-import-credentials.test.ts +162 -0
- package/src/runtime/migrations/migration-transport.ts +6 -0
- package/src/runtime/migrations/migration-wizard.ts +22 -2
- package/src/runtime/migrations/rebind-secrets-screen.ts +76 -15
- package/src/runtime/migrations/vbundle-builder.ts +145 -38
- package/src/runtime/migrations/vbundle-import-analyzer.ts +19 -0
- package/src/runtime/migrations/vbundle-importer.ts +55 -5
- package/src/runtime/pending-interactions.ts +29 -13
- package/src/runtime/routes/approval-routes.ts +90 -16
- package/src/runtime/routes/browser-cdp-routes.ts +229 -0
- package/src/runtime/routes/browser-extension-pair-routes.ts +497 -0
- package/src/runtime/routes/conversation-analysis-routes.ts +18 -5
- package/src/runtime/routes/conversation-management-routes.ts +108 -0
- package/src/runtime/routes/conversation-routes.ts +308 -28
- package/src/runtime/routes/conversation-starter-routes.ts +78 -16
- package/src/runtime/routes/group-routes.ts +22 -8
- package/src/runtime/routes/guardian-action-routes.ts +24 -13
- package/src/runtime/routes/host-browser-routes.ts +279 -0
- package/src/runtime/routes/host-file-routes.ts +9 -1
- package/src/runtime/routes/identity-routes.ts +259 -16
- package/src/runtime/routes/log-export/AGENTS.md +104 -0
- package/src/runtime/routes/log-export/__tests__/workspace-allowlist-error-contract.test.ts +103 -0
- package/src/runtime/routes/log-export/__tests__/workspace-allowlist.test.ts +716 -0
- package/src/runtime/routes/log-export/workspace-allowlist.ts +458 -0
- package/src/runtime/routes/log-export-routes.ts +60 -25
- package/src/runtime/routes/memory-item-routes.ts +1 -7
- package/src/runtime/routes/migration-routes.ts +87 -2
- package/src/runtime/routes/oauth-apps.ts +15 -17
- package/src/runtime/routes/oauth-providers.ts +4 -0
- package/src/runtime/routes/schedule-routes.ts +24 -11
- package/src/runtime/routes/settings-routes.ts +9 -97
- package/src/runtime/routes/skills-routes.ts +52 -2
- package/src/runtime/routes/subagents-routes.ts +14 -10
- package/src/runtime/routes/usage-routes.ts +8 -7
- package/src/runtime/routes/workspace-routes.test.ts +22 -0
- package/src/runtime/routes/workspace-routes.ts +8 -1
- package/src/runtime/routes/workspace-utils.ts +2 -0
- package/src/schedule/scheduler.ts +7 -5
- package/src/security/ces-credential-client.ts +20 -0
- package/src/security/ces-rpc-credential-backend.ts +17 -0
- package/src/security/credential-backend.ts +5 -0
- package/src/security/oauth2.ts +42 -25
- package/src/security/secure-keys.ts +118 -25
- package/src/security/token-manager.ts +23 -10
- package/src/skills/catalog-files.ts +492 -0
- package/src/skills/inline-command-runner.ts +12 -14
- package/src/subagent/manager.ts +131 -26
- package/src/subagent/types.ts +19 -0
- package/src/tools/apps/executors.ts +11 -2
- package/src/tools/browser/__tests__/auth-detector.test.ts +202 -108
- package/src/tools/browser/auth-detector.ts +43 -12
- package/src/tools/browser/browser-execution.ts +645 -340
- package/src/tools/browser/browser-manager.ts +36 -12
- package/src/tools/browser/cdp-client/__tests__/accessibility-snapshot.test.ts +318 -0
- package/src/tools/browser/cdp-client/__tests__/cdp-dom-helpers.test.ts +1175 -0
- package/src/tools/browser/cdp-client/__tests__/cdp-inspect-client.test.ts +870 -0
- package/src/tools/browser/cdp-client/__tests__/extension-cdp-client.test.ts +330 -0
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +377 -0
- package/src/tools/browser/cdp-client/__tests__/fixtures/ax-tree-nested-frames.json +64 -0
- package/src/tools/browser/cdp-client/__tests__/fixtures/ax-tree-simple.json +69 -0
- package/src/tools/browser/cdp-client/__tests__/local-cdp-client.test.ts +310 -0
- package/src/tools/browser/cdp-client/__tests__/types.test.ts +96 -0
- package/src/tools/browser/cdp-client/accessibility-snapshot.ts +387 -0
- package/src/tools/browser/cdp-client/cdp-dom-helpers.ts +695 -0
- package/src/tools/browser/cdp-client/cdp-inspect/__tests__/discovery.test.ts +743 -0
- package/src/tools/browser/cdp-client/cdp-inspect/__tests__/ws-transport.test.ts +580 -0
- package/src/tools/browser/cdp-client/cdp-inspect/discovery.ts +578 -0
- package/src/tools/browser/cdp-client/cdp-inspect/ws-transport.ts +579 -0
- package/src/tools/browser/cdp-client/cdp-inspect-client.ts +635 -0
- package/src/tools/browser/cdp-client/errors.ts +34 -0
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +125 -0
- package/src/tools/browser/cdp-client/factory.ts +204 -0
- package/src/tools/browser/cdp-client/index.ts +14 -0
- package/src/tools/browser/cdp-client/local-cdp-client.ts +187 -0
- package/src/tools/browser/cdp-client/types.ts +52 -0
- package/src/tools/filesystem/edit.ts +1 -1
- package/src/tools/filesystem/list.ts +1 -1
- package/src/tools/filesystem/read.ts +1 -1
- package/src/tools/filesystem/write.ts +2 -1
- package/src/tools/host-filesystem/edit.ts +1 -1
- package/src/tools/host-filesystem/read.ts +12 -15
- package/src/tools/host-filesystem/write.ts +1 -1
- package/src/tools/host-terminal/host-shell.ts +21 -16
- package/src/tools/permission-checker.ts +77 -100
- package/src/tools/registry.ts +0 -2
- package/src/tools/secret-detection-handler.ts +34 -1
- package/src/tools/shared/filesystem/image-read.ts +61 -40
- package/src/tools/skills/sandbox-runner.ts +3 -6
- package/src/tools/subagent/spawn.ts +47 -3
- package/src/tools/subagent/status.ts +2 -0
- package/src/tools/system/register.ts +2 -16
- package/src/tools/terminal/safe-env.ts +7 -0
- package/src/tools/terminal/sandbox-diagnostics.ts +4 -4
- package/src/tools/terminal/sandbox.ts +4 -1
- package/src/tools/terminal/shell.ts +24 -21
- package/src/tools/tool-approval-handler.ts +48 -2
- package/src/tools/types.ts +2 -3
- package/src/util/platform.ts +14 -19
- package/src/watcher/provider-types.ts +1 -1
- package/src/workspace/migrations/029-seed-pkb.ts +1 -0
- package/src/workspace/migrations/030-seed-pkb-autoinject.ts +73 -0
- package/src/workspace/migrations/registry.ts +2 -0
- package/src/workspace/top-level-renderer.ts +19 -1
- package/src/__tests__/chrome-cdp.test.ts +0 -419
- package/src/__tests__/permission-mode-sse.test.ts +0 -418
- package/src/__tests__/permission-mode-store.test.ts +0 -277
- package/src/browser-extension-relay/protocol.ts +0 -63
- package/src/browser-extension-relay/server.ts +0 -203
- package/src/config/schemas/sandbox.ts +0 -14
- package/src/permissions/permission-mode-store.ts +0 -180
- package/src/tools/browser/chrome-cdp.ts +0 -239
- package/src/tools/system/set-permission-mode.ts +0 -103
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
import {
|
|
2
|
+
existsSync,
|
|
3
|
+
mkdirSync,
|
|
4
|
+
readFileSync,
|
|
5
|
+
rmSync,
|
|
6
|
+
writeFileSync,
|
|
7
|
+
} from "node:fs";
|
|
8
|
+
import { join } from "node:path";
|
|
9
|
+
import {
|
|
10
|
+
afterAll,
|
|
11
|
+
afterEach,
|
|
12
|
+
beforeEach,
|
|
13
|
+
describe,
|
|
14
|
+
expect,
|
|
15
|
+
mock,
|
|
16
|
+
test,
|
|
17
|
+
} from "bun:test";
|
|
18
|
+
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
// Mocks — declared before imports that depend on platform/logger
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
|
|
23
|
+
const WORKSPACE_DIR = process.env.VELLUM_WORKSPACE_DIR!;
|
|
24
|
+
const CONFIG_PATH = join(WORKSPACE_DIR, "config.json");
|
|
25
|
+
|
|
26
|
+
function ensureTestDir(): void {
|
|
27
|
+
const dirs = [
|
|
28
|
+
WORKSPACE_DIR,
|
|
29
|
+
join(WORKSPACE_DIR, "data"),
|
|
30
|
+
join(WORKSPACE_DIR, "data", "memory"),
|
|
31
|
+
join(WORKSPACE_DIR, "data", "memory", "knowledge"),
|
|
32
|
+
join(WORKSPACE_DIR, "data", "logs"),
|
|
33
|
+
];
|
|
34
|
+
for (const dir of dirs) {
|
|
35
|
+
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function makeLoggerStub(): Record<string, unknown> {
|
|
40
|
+
const stub: Record<string, unknown> = {};
|
|
41
|
+
for (const m of [
|
|
42
|
+
"info",
|
|
43
|
+
"warn",
|
|
44
|
+
"error",
|
|
45
|
+
"debug",
|
|
46
|
+
"trace",
|
|
47
|
+
"fatal",
|
|
48
|
+
"silent",
|
|
49
|
+
"child",
|
|
50
|
+
]) {
|
|
51
|
+
stub[m] = m === "child" ? () => makeLoggerStub() : () => {};
|
|
52
|
+
}
|
|
53
|
+
return stub;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
mock.module("../util/logger.js", () => ({
|
|
57
|
+
getLogger: () => makeLoggerStub(),
|
|
58
|
+
}));
|
|
59
|
+
|
|
60
|
+
// ---------------------------------------------------------------------------
|
|
61
|
+
// Feature flag mock — controls whether managed-gemini-embeddings-enabled is on
|
|
62
|
+
// ---------------------------------------------------------------------------
|
|
63
|
+
|
|
64
|
+
let featureFlagEnabled = false;
|
|
65
|
+
|
|
66
|
+
mock.module("../config/assistant-feature-flags.js", () => ({
|
|
67
|
+
isAssistantFeatureFlagEnabled: (key: string) => {
|
|
68
|
+
if (key === "managed-gemini-embeddings-enabled") return featureFlagEnabled;
|
|
69
|
+
return true;
|
|
70
|
+
},
|
|
71
|
+
_setOverridesForTesting: () => {},
|
|
72
|
+
clearFeatureFlagOverridesCache: () => {},
|
|
73
|
+
initFeatureFlagOverrides: async () => {},
|
|
74
|
+
getAssistantFeatureFlagDefaults: () => ({}),
|
|
75
|
+
}));
|
|
76
|
+
|
|
77
|
+
// Restore all mocked modules after this file's tests complete to prevent
|
|
78
|
+
// cross-test contamination when running grouped with other test files.
|
|
79
|
+
afterAll(() => {
|
|
80
|
+
mock.restore();
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
import { invalidateConfigCache, loadConfig } from "../config/loader.js";
|
|
84
|
+
import { _setStorePath } from "../security/encrypted-store.js";
|
|
85
|
+
|
|
86
|
+
// ---------------------------------------------------------------------------
|
|
87
|
+
// Helpers
|
|
88
|
+
// ---------------------------------------------------------------------------
|
|
89
|
+
|
|
90
|
+
function writeConfig(obj: unknown): void {
|
|
91
|
+
writeFileSync(CONFIG_PATH, JSON.stringify(obj, null, 2) + "\n");
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function readConfig(): Record<string, unknown> {
|
|
95
|
+
return JSON.parse(readFileSync(CONFIG_PATH, "utf-8"));
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/** Stash and restore IS_PLATFORM across each test. */
|
|
99
|
+
let originalIsPlatform: string | undefined;
|
|
100
|
+
|
|
101
|
+
// ---------------------------------------------------------------------------
|
|
102
|
+
// Tests
|
|
103
|
+
// ---------------------------------------------------------------------------
|
|
104
|
+
|
|
105
|
+
describe("managed Gemini embedding defaults (via loadConfig)", () => {
|
|
106
|
+
beforeEach(() => {
|
|
107
|
+
ensureTestDir();
|
|
108
|
+
const resetPaths = [
|
|
109
|
+
CONFIG_PATH,
|
|
110
|
+
join(WORKSPACE_DIR, "keys.enc"),
|
|
111
|
+
join(WORKSPACE_DIR, "data"),
|
|
112
|
+
join(WORKSPACE_DIR, "data", "memory"),
|
|
113
|
+
];
|
|
114
|
+
for (const path of resetPaths) {
|
|
115
|
+
if (existsSync(path)) {
|
|
116
|
+
rmSync(path, { recursive: true, force: true });
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
ensureTestDir();
|
|
120
|
+
_setStorePath(join(WORKSPACE_DIR, "keys.enc"));
|
|
121
|
+
invalidateConfigCache();
|
|
122
|
+
|
|
123
|
+
// Reset mock state
|
|
124
|
+
featureFlagEnabled = false;
|
|
125
|
+
originalIsPlatform = process.env.IS_PLATFORM;
|
|
126
|
+
delete process.env.IS_PLATFORM;
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
afterEach(() => {
|
|
130
|
+
_setStorePath(null);
|
|
131
|
+
invalidateConfigCache();
|
|
132
|
+
|
|
133
|
+
// Restore IS_PLATFORM
|
|
134
|
+
if (originalIsPlatform !== undefined) {
|
|
135
|
+
process.env.IS_PLATFORM = originalIsPlatform;
|
|
136
|
+
} else {
|
|
137
|
+
delete process.env.IS_PLATFORM;
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
test("applies managed Gemini defaults when FF on + IS_PLATFORM + provider auto", () => {
|
|
142
|
+
writeConfig({});
|
|
143
|
+
|
|
144
|
+
featureFlagEnabled = true;
|
|
145
|
+
process.env.IS_PLATFORM = "true";
|
|
146
|
+
|
|
147
|
+
const config = loadConfig();
|
|
148
|
+
|
|
149
|
+
// In-memory config should have managed Gemini defaults
|
|
150
|
+
expect(config.memory.embeddings.provider).toBe("gemini");
|
|
151
|
+
expect(config.memory.embeddings.geminiModel).toBe(
|
|
152
|
+
"gemini-embedding-2-preview",
|
|
153
|
+
);
|
|
154
|
+
expect(config.memory.embeddings.geminiDimensions).toBe(3072);
|
|
155
|
+
expect(config.memory.qdrant.vectorSize).toBe(3072);
|
|
156
|
+
|
|
157
|
+
// Config file on disk should also be updated
|
|
158
|
+
const raw = readConfig();
|
|
159
|
+
const memoryRaw = raw.memory as Record<string, unknown>;
|
|
160
|
+
const embeddingsRaw = memoryRaw.embeddings as Record<string, unknown>;
|
|
161
|
+
const qdrantRaw = memoryRaw.qdrant as Record<string, unknown>;
|
|
162
|
+
expect(embeddingsRaw.provider).toBe("gemini");
|
|
163
|
+
expect(embeddingsRaw.geminiModel).toBe("gemini-embedding-2-preview");
|
|
164
|
+
expect(embeddingsRaw.geminiDimensions).toBe(3072);
|
|
165
|
+
expect(qdrantRaw.vectorSize).toBe(3072);
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
test("does NOT apply when feature flag is OFF", () => {
|
|
169
|
+
writeConfig({});
|
|
170
|
+
|
|
171
|
+
featureFlagEnabled = false;
|
|
172
|
+
process.env.IS_PLATFORM = "true";
|
|
173
|
+
|
|
174
|
+
const config = loadConfig();
|
|
175
|
+
|
|
176
|
+
expect(config.memory.embeddings.provider).toBe("auto");
|
|
177
|
+
expect(config.memory.qdrant.vectorSize).toBe(384);
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
test("does NOT apply when IS_PLATFORM is not set", () => {
|
|
181
|
+
writeConfig({});
|
|
182
|
+
|
|
183
|
+
featureFlagEnabled = true;
|
|
184
|
+
delete process.env.IS_PLATFORM;
|
|
185
|
+
|
|
186
|
+
const config = loadConfig();
|
|
187
|
+
|
|
188
|
+
expect(config.memory.embeddings.provider).toBe("auto");
|
|
189
|
+
expect(config.memory.qdrant.vectorSize).toBe(384);
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
test("does NOT apply when provider is explicitly set to local", () => {
|
|
193
|
+
writeConfig({
|
|
194
|
+
memory: { embeddings: { provider: "local" } },
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
featureFlagEnabled = true;
|
|
198
|
+
process.env.IS_PLATFORM = "true";
|
|
199
|
+
|
|
200
|
+
const config = loadConfig();
|
|
201
|
+
expect(config.memory.embeddings.provider).toBe("local");
|
|
202
|
+
expect(config.memory.qdrant.vectorSize).toBe(384);
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
test("does NOT apply when provider is explicitly set to openai", () => {
|
|
206
|
+
writeConfig({
|
|
207
|
+
memory: { embeddings: { provider: "openai" } },
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
featureFlagEnabled = true;
|
|
211
|
+
process.env.IS_PLATFORM = "true";
|
|
212
|
+
|
|
213
|
+
const config = loadConfig();
|
|
214
|
+
expect(config.memory.embeddings.provider).toBe("openai");
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
test("does NOT apply when provider is explicitly set to gemini", () => {
|
|
218
|
+
writeConfig({
|
|
219
|
+
memory: {
|
|
220
|
+
embeddings: { provider: "gemini", geminiDimensions: 768 },
|
|
221
|
+
qdrant: { vectorSize: 768 },
|
|
222
|
+
},
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
featureFlagEnabled = true;
|
|
226
|
+
process.env.IS_PLATFORM = "true";
|
|
227
|
+
|
|
228
|
+
const config = loadConfig();
|
|
229
|
+
|
|
230
|
+
// Already gemini — should not overwrite user's custom dimensions
|
|
231
|
+
expect(config.memory.embeddings.provider).toBe("gemini");
|
|
232
|
+
expect(config.memory.embeddings.geminiDimensions).toBe(768);
|
|
233
|
+
expect(config.memory.qdrant.vectorSize).toBe(768);
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
test("does NOT apply when provider is explicitly set to ollama", () => {
|
|
237
|
+
writeConfig({
|
|
238
|
+
memory: { embeddings: { provider: "ollama" } },
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
featureFlagEnabled = true;
|
|
242
|
+
process.env.IS_PLATFORM = "true";
|
|
243
|
+
|
|
244
|
+
const config = loadConfig();
|
|
245
|
+
expect(config.memory.embeddings.provider).toBe("ollama");
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
test("is idempotent — second loadConfig is a no-op after migration", () => {
|
|
249
|
+
writeConfig({});
|
|
250
|
+
|
|
251
|
+
featureFlagEnabled = true;
|
|
252
|
+
process.env.IS_PLATFORM = "true";
|
|
253
|
+
|
|
254
|
+
const config = loadConfig();
|
|
255
|
+
expect(config.memory.embeddings.provider).toBe("gemini");
|
|
256
|
+
|
|
257
|
+
// Read file content after first migration
|
|
258
|
+
const contentAfterFirst = readFileSync(CONFIG_PATH, "utf-8");
|
|
259
|
+
|
|
260
|
+
// Second call — provider is now "gemini", not "auto", so migration skipped
|
|
261
|
+
invalidateConfigCache();
|
|
262
|
+
const config2 = loadConfig();
|
|
263
|
+
expect(config2.memory.embeddings.provider).toBe("gemini");
|
|
264
|
+
|
|
265
|
+
// File on disk should not have changed
|
|
266
|
+
const contentAfterSecond = readFileSync(CONFIG_PATH, "utf-8");
|
|
267
|
+
expect(contentAfterSecond).toBe(contentAfterFirst);
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
test("preserves existing config values while setting managed defaults", () => {
|
|
271
|
+
writeConfig({
|
|
272
|
+
provider: "anthropic",
|
|
273
|
+
model: "claude-opus-4-6",
|
|
274
|
+
memory: {
|
|
275
|
+
enabled: true,
|
|
276
|
+
qdrant: { collection: "my-collection", onDisk: false },
|
|
277
|
+
},
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
featureFlagEnabled = true;
|
|
281
|
+
process.env.IS_PLATFORM = "true";
|
|
282
|
+
|
|
283
|
+
const config = loadConfig();
|
|
284
|
+
|
|
285
|
+
// Managed defaults applied
|
|
286
|
+
expect(config.memory.embeddings.provider).toBe("gemini");
|
|
287
|
+
expect(config.memory.embeddings.geminiModel).toBe(
|
|
288
|
+
"gemini-embedding-2-preview",
|
|
289
|
+
);
|
|
290
|
+
expect(config.memory.qdrant.vectorSize).toBe(3072);
|
|
291
|
+
|
|
292
|
+
// Existing values preserved
|
|
293
|
+
const raw = readConfig();
|
|
294
|
+
expect(raw.provider).toBe("anthropic");
|
|
295
|
+
expect(raw.model).toBe("claude-opus-4-6");
|
|
296
|
+
const memoryRaw = raw.memory as Record<string, unknown>;
|
|
297
|
+
expect(memoryRaw.enabled).toBe(true);
|
|
298
|
+
const qdrantRaw = memoryRaw.qdrant as Record<string, unknown>;
|
|
299
|
+
expect(qdrantRaw.collection).toBe("my-collection");
|
|
300
|
+
expect(qdrantRaw.onDisk).toBe(false);
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
test("does NOT apply when both FF off and IS_PLATFORM not set", () => {
|
|
304
|
+
writeConfig({});
|
|
305
|
+
|
|
306
|
+
featureFlagEnabled = false;
|
|
307
|
+
delete process.env.IS_PLATFORM;
|
|
308
|
+
|
|
309
|
+
const config = loadConfig();
|
|
310
|
+
|
|
311
|
+
expect(config.memory.embeddings.provider).toBe("auto");
|
|
312
|
+
expect(config.memory.qdrant.vectorSize).toBe(384);
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
test("applies when IS_PLATFORM is '1'", () => {
|
|
316
|
+
writeConfig({});
|
|
317
|
+
|
|
318
|
+
featureFlagEnabled = true;
|
|
319
|
+
process.env.IS_PLATFORM = "1";
|
|
320
|
+
|
|
321
|
+
const config = loadConfig();
|
|
322
|
+
|
|
323
|
+
expect(config.memory.embeddings.provider).toBe("gemini");
|
|
324
|
+
expect(config.memory.embeddings.geminiDimensions).toBe(3072);
|
|
325
|
+
});
|
|
326
|
+
});
|
|
@@ -87,7 +87,7 @@ describe("getSchemaAtPath", () => {
|
|
|
87
87
|
expect(result).not.toBeNull();
|
|
88
88
|
// maxTokens has a default, so it should be parseable
|
|
89
89
|
const parsed = (result as z.ZodType).parse(undefined);
|
|
90
|
-
expect(parsed).toBe(
|
|
90
|
+
expect(parsed).toBe(64000);
|
|
91
91
|
});
|
|
92
92
|
|
|
93
93
|
test("navigates nested paths (memory.segmentation → object schema)", () => {
|
|
@@ -188,7 +188,7 @@ describe("z.toJSONSchema integration", () => {
|
|
|
188
188
|
expect(properties.calls).toBeDefined();
|
|
189
189
|
expect(properties.memory).toBeDefined();
|
|
190
190
|
expect(properties.timeouts).toBeDefined();
|
|
191
|
-
expect(properties.
|
|
191
|
+
expect(properties.permissions).toBeDefined();
|
|
192
192
|
});
|
|
193
193
|
|
|
194
194
|
test("full schema emits real properties for transformed fields (ingress)", () => {
|
|
@@ -81,7 +81,7 @@ describe("AssistantConfigSchema", () => {
|
|
|
81
81
|
"inference-provider-native",
|
|
82
82
|
);
|
|
83
83
|
expect(result.services["web-search"].mode).toBe("your-own");
|
|
84
|
-
expect(result.maxTokens).toBe(
|
|
84
|
+
expect(result.maxTokens).toBe(64000);
|
|
85
85
|
expect(result.thinking).toEqual({
|
|
86
86
|
enabled: true,
|
|
87
87
|
streamThinking: true,
|
|
@@ -107,9 +107,6 @@ describe("AssistantConfigSchema", () => {
|
|
|
107
107
|
toolExecutionTimeoutSec: 120,
|
|
108
108
|
providerStreamTimeoutSec: 1800,
|
|
109
109
|
});
|
|
110
|
-
expect(result.sandbox).toEqual({
|
|
111
|
-
enabled: false,
|
|
112
|
-
});
|
|
113
110
|
expect(result.rateLimit).toEqual({
|
|
114
111
|
maxRequestsPerMinute: 0,
|
|
115
112
|
});
|
|
@@ -169,7 +166,7 @@ describe("AssistantConfigSchema", () => {
|
|
|
169
166
|
enqueueIntervalMs: 6 * 60 * 60 * 1000,
|
|
170
167
|
supersededItemRetentionMs: 30 * 24 * 60 * 60 * 1000,
|
|
171
168
|
conversationRetentionDays: 0,
|
|
172
|
-
llmRequestLogRetentionMs:
|
|
169
|
+
llmRequestLogRetentionMs: 1 * 24 * 60 * 60 * 1000,
|
|
173
170
|
});
|
|
174
171
|
});
|
|
175
172
|
|
|
@@ -400,29 +397,10 @@ describe("AssistantConfigSchema", () => {
|
|
|
400
397
|
}
|
|
401
398
|
});
|
|
402
399
|
|
|
403
|
-
test("sandbox with only enabled still parses", () => {
|
|
404
|
-
const result = AssistantConfigSchema.parse({ sandbox: { enabled: false } });
|
|
405
|
-
expect(result.sandbox.enabled).toBe(false);
|
|
406
|
-
});
|
|
407
|
-
|
|
408
|
-
test("rejects unknown sandbox fields", () => {
|
|
409
|
-
const result = AssistantConfigSchema.safeParse({
|
|
410
|
-
sandbox: { backend: "docker" },
|
|
411
|
-
});
|
|
412
|
-
// Unknown keys are stripped by Zod passthrough/strip, so parse should still succeed
|
|
413
|
-
// but the unknown field should not appear in the output
|
|
414
|
-
if (result.success) {
|
|
415
|
-
expect(
|
|
416
|
-
(result.data.sandbox as Record<string, unknown>)["backend"],
|
|
417
|
-
).toBeUndefined();
|
|
418
|
-
}
|
|
419
|
-
});
|
|
420
|
-
|
|
421
400
|
test("defaults permissions.mode to workspace", () => {
|
|
422
401
|
const result = AssistantConfigSchema.parse({});
|
|
423
402
|
expect(result.permissions).toEqual({
|
|
424
403
|
mode: "workspace",
|
|
425
|
-
askBeforeActing: true,
|
|
426
404
|
hostAccess: false,
|
|
427
405
|
});
|
|
428
406
|
});
|
|
@@ -861,6 +839,125 @@ describe("AssistantConfigSchema", () => {
|
|
|
861
839
|
});
|
|
862
840
|
expect(result.calls.callerIdentity.allowPerCallOverride).toBe(true);
|
|
863
841
|
});
|
|
842
|
+
|
|
843
|
+
// ── hostBrowser.cdpInspect config ─────────────────────────────────
|
|
844
|
+
|
|
845
|
+
test("applies hostBrowser.cdpInspect defaults", () => {
|
|
846
|
+
const result = AssistantConfigSchema.parse({});
|
|
847
|
+
expect(result.hostBrowser).toEqual({
|
|
848
|
+
cdpInspect: {
|
|
849
|
+
enabled: false,
|
|
850
|
+
host: "localhost",
|
|
851
|
+
port: 9222,
|
|
852
|
+
probeTimeoutMs: 500,
|
|
853
|
+
},
|
|
854
|
+
});
|
|
855
|
+
});
|
|
856
|
+
|
|
857
|
+
test("accepts hostBrowser.cdpInspect enabled with custom host/port", () => {
|
|
858
|
+
const result = AssistantConfigSchema.parse({
|
|
859
|
+
hostBrowser: {
|
|
860
|
+
cdpInspect: {
|
|
861
|
+
enabled: true,
|
|
862
|
+
host: "127.0.0.1",
|
|
863
|
+
port: 9333,
|
|
864
|
+
},
|
|
865
|
+
},
|
|
866
|
+
});
|
|
867
|
+
expect(result.hostBrowser.cdpInspect.enabled).toBe(true);
|
|
868
|
+
expect(result.hostBrowser.cdpInspect.host).toBe("127.0.0.1");
|
|
869
|
+
expect(result.hostBrowser.cdpInspect.port).toBe(9333);
|
|
870
|
+
// Unset field should still receive its default.
|
|
871
|
+
expect(result.hostBrowser.cdpInspect.probeTimeoutMs).toBe(500);
|
|
872
|
+
});
|
|
873
|
+
|
|
874
|
+
test("accepts hostBrowser.cdpInspect custom probeTimeoutMs", () => {
|
|
875
|
+
const result = AssistantConfigSchema.parse({
|
|
876
|
+
hostBrowser: { cdpInspect: { probeTimeoutMs: 1000 } },
|
|
877
|
+
});
|
|
878
|
+
expect(result.hostBrowser.cdpInspect.probeTimeoutMs).toBe(1000);
|
|
879
|
+
});
|
|
880
|
+
|
|
881
|
+
test("rejects hostBrowser.cdpInspect.port below 1", () => {
|
|
882
|
+
const result = AssistantConfigSchema.safeParse({
|
|
883
|
+
hostBrowser: { cdpInspect: { port: 0 } },
|
|
884
|
+
});
|
|
885
|
+
expect(result.success).toBe(false);
|
|
886
|
+
if (!result.success) {
|
|
887
|
+
expect(
|
|
888
|
+
result.error.issues.some((issue) =>
|
|
889
|
+
issue.path.join(".").includes("hostBrowser.cdpInspect.port"),
|
|
890
|
+
),
|
|
891
|
+
).toBe(true);
|
|
892
|
+
}
|
|
893
|
+
});
|
|
894
|
+
|
|
895
|
+
test("rejects hostBrowser.cdpInspect.port above 65535", () => {
|
|
896
|
+
const result = AssistantConfigSchema.safeParse({
|
|
897
|
+
hostBrowser: { cdpInspect: { port: 70000 } },
|
|
898
|
+
});
|
|
899
|
+
expect(result.success).toBe(false);
|
|
900
|
+
if (!result.success) {
|
|
901
|
+
expect(
|
|
902
|
+
result.error.issues.some((issue) =>
|
|
903
|
+
issue.path.join(".").includes("hostBrowser.cdpInspect.port"),
|
|
904
|
+
),
|
|
905
|
+
).toBe(true);
|
|
906
|
+
}
|
|
907
|
+
});
|
|
908
|
+
|
|
909
|
+
test("rejects non-integer hostBrowser.cdpInspect.port", () => {
|
|
910
|
+
const result = AssistantConfigSchema.safeParse({
|
|
911
|
+
hostBrowser: { cdpInspect: { port: 9222.5 } },
|
|
912
|
+
});
|
|
913
|
+
expect(result.success).toBe(false);
|
|
914
|
+
});
|
|
915
|
+
|
|
916
|
+
test("rejects hostBrowser.cdpInspect.probeTimeoutMs below 50", () => {
|
|
917
|
+
const result = AssistantConfigSchema.safeParse({
|
|
918
|
+
hostBrowser: { cdpInspect: { probeTimeoutMs: 10 } },
|
|
919
|
+
});
|
|
920
|
+
expect(result.success).toBe(false);
|
|
921
|
+
if (!result.success) {
|
|
922
|
+
expect(
|
|
923
|
+
result.error.issues.some((issue) =>
|
|
924
|
+
issue.path
|
|
925
|
+
.join(".")
|
|
926
|
+
.includes("hostBrowser.cdpInspect.probeTimeoutMs"),
|
|
927
|
+
),
|
|
928
|
+
).toBe(true);
|
|
929
|
+
}
|
|
930
|
+
});
|
|
931
|
+
|
|
932
|
+
test("rejects hostBrowser.cdpInspect.probeTimeoutMs above 5000", () => {
|
|
933
|
+
const result = AssistantConfigSchema.safeParse({
|
|
934
|
+
hostBrowser: { cdpInspect: { probeTimeoutMs: 10000 } },
|
|
935
|
+
});
|
|
936
|
+
expect(result.success).toBe(false);
|
|
937
|
+
if (!result.success) {
|
|
938
|
+
expect(
|
|
939
|
+
result.error.issues.some((issue) =>
|
|
940
|
+
issue.path
|
|
941
|
+
.join(".")
|
|
942
|
+
.includes("hostBrowser.cdpInspect.probeTimeoutMs"),
|
|
943
|
+
),
|
|
944
|
+
).toBe(true);
|
|
945
|
+
}
|
|
946
|
+
});
|
|
947
|
+
|
|
948
|
+
test("rejects non-integer hostBrowser.cdpInspect.probeTimeoutMs", () => {
|
|
949
|
+
const result = AssistantConfigSchema.safeParse({
|
|
950
|
+
hostBrowser: { cdpInspect: { probeTimeoutMs: 500.5 } },
|
|
951
|
+
});
|
|
952
|
+
expect(result.success).toBe(false);
|
|
953
|
+
});
|
|
954
|
+
|
|
955
|
+
test("rejects non-boolean hostBrowser.cdpInspect.enabled", () => {
|
|
956
|
+
const result = AssistantConfigSchema.safeParse({
|
|
957
|
+
hostBrowser: { cdpInspect: { enabled: "yes" } },
|
|
958
|
+
});
|
|
959
|
+
expect(result.success).toBe(false);
|
|
960
|
+
});
|
|
864
961
|
});
|
|
865
962
|
|
|
866
963
|
// ---------------------------------------------------------------------------
|
|
@@ -1002,7 +1099,7 @@ describe("loadConfig with schema validation", () => {
|
|
|
1002
1099
|
const config = loadConfig();
|
|
1003
1100
|
expect(config.services.inference.provider).toBe("anthropic");
|
|
1004
1101
|
expect(config.services.inference.model).toBe("claude-opus-4-6");
|
|
1005
|
-
expect(config.maxTokens).toBe(
|
|
1102
|
+
expect(config.maxTokens).toBe(64000);
|
|
1006
1103
|
expect(config.thinking).toEqual({
|
|
1007
1104
|
enabled: true,
|
|
1008
1105
|
streamThinking: true,
|
|
@@ -1034,7 +1131,7 @@ describe("loadConfig with schema validation", () => {
|
|
|
1034
1131
|
test("falls back to default for invalid maxTokens", () => {
|
|
1035
1132
|
writeConfig({ maxTokens: -100 });
|
|
1036
1133
|
const config = loadConfig();
|
|
1037
|
-
expect(config.maxTokens).toBe(
|
|
1134
|
+
expect(config.maxTokens).toBe(64000);
|
|
1038
1135
|
});
|
|
1039
1136
|
|
|
1040
1137
|
test("falls back to defaults for invalid nested values", () => {
|
|
@@ -1059,13 +1156,13 @@ describe("loadConfig with schema validation", () => {
|
|
|
1059
1156
|
expect(config.services.inference.provider).toBe("openai");
|
|
1060
1157
|
expect(config.services.inference.model).toBe("gpt-4");
|
|
1061
1158
|
expect(config.thinking.enabled).toBe(true);
|
|
1062
|
-
expect(config.maxTokens).toBe(
|
|
1159
|
+
expect(config.maxTokens).toBe(64000);
|
|
1063
1160
|
});
|
|
1064
1161
|
|
|
1065
1162
|
test("handles no config file", () => {
|
|
1066
1163
|
const config = loadConfig();
|
|
1067
1164
|
expect(config.services.inference.provider).toBe("anthropic");
|
|
1068
|
-
expect(config.maxTokens).toBe(
|
|
1165
|
+
expect(config.maxTokens).toBe(64000);
|
|
1069
1166
|
});
|
|
1070
1167
|
|
|
1071
1168
|
test("partial nested objects get defaults for missing fields", () => {
|
|
@@ -1084,25 +1181,6 @@ describe("loadConfig with schema validation", () => {
|
|
|
1084
1181
|
expect(config.secretDetection.action).toBe("redact");
|
|
1085
1182
|
});
|
|
1086
1183
|
|
|
1087
|
-
test("falls back for invalid sandbox.enabled", () => {
|
|
1088
|
-
writeConfig({ sandbox: { enabled: "yes" } });
|
|
1089
|
-
const config = loadConfig();
|
|
1090
|
-
expect(config.sandbox.enabled).toBe(false);
|
|
1091
|
-
});
|
|
1092
|
-
|
|
1093
|
-
test("loads sandbox with only enabled field", () => {
|
|
1094
|
-
writeConfig({ sandbox: { enabled: false } });
|
|
1095
|
-
const config = loadConfig();
|
|
1096
|
-
expect(config.sandbox.enabled).toBe(false);
|
|
1097
|
-
});
|
|
1098
|
-
|
|
1099
|
-
test("strips unknown sandbox fields", () => {
|
|
1100
|
-
writeConfig({ sandbox: { enabled: true, backend: "docker" } });
|
|
1101
|
-
const config = loadConfig();
|
|
1102
|
-
expect(config.sandbox.enabled).toBe(true);
|
|
1103
|
-
expect("backend" in config.sandbox).toBe(false);
|
|
1104
|
-
});
|
|
1105
|
-
|
|
1106
1184
|
test("falls back for invalid contextWindow relationship", () => {
|
|
1107
1185
|
writeConfig({
|
|
1108
1186
|
contextWindow: { targetBudgetRatio: 0.8, compactThreshold: 0.8 },
|
|
@@ -1131,7 +1209,6 @@ describe("loadConfig with schema validation", () => {
|
|
|
1131
1209
|
const config = loadConfig();
|
|
1132
1210
|
expect(config.permissions).toEqual({
|
|
1133
1211
|
mode: "workspace",
|
|
1134
|
-
askBeforeActing: true,
|
|
1135
1212
|
hostAccess: false,
|
|
1136
1213
|
});
|
|
1137
1214
|
});
|
|
@@ -10,6 +10,8 @@
|
|
|
10
10
|
|
|
11
11
|
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
12
12
|
|
|
13
|
+
import { _setOverridesForTesting } from "../config/assistant-feature-flags.js";
|
|
14
|
+
|
|
13
15
|
mock.module("../util/logger.js", () => ({
|
|
14
16
|
getLogger: () =>
|
|
15
17
|
new Proxy({} as Record<string, unknown>, {
|
|
@@ -133,6 +135,7 @@ describe("bridgeConfirmationRequestToGuardian", () => {
|
|
|
133
135
|
resetTables();
|
|
134
136
|
emittedSignals.length = 0;
|
|
135
137
|
mockOnConversationCreatedCallbacks.length = 0;
|
|
138
|
+
_setOverridesForTesting({});
|
|
136
139
|
});
|
|
137
140
|
|
|
138
141
|
test("emits guardian.question for trusted-contact sessions", () => {
|
|
@@ -223,6 +226,26 @@ describe("bridgeConfirmationRequestToGuardian", () => {
|
|
|
223
226
|
expect(emittedSignals).toHaveLength(0);
|
|
224
227
|
});
|
|
225
228
|
|
|
229
|
+
test("skips trusted-contact bridging entirely under permission-controls-v2", () => {
|
|
230
|
+
_setOverridesForTesting({ "permission-controls-v2": true });
|
|
231
|
+
|
|
232
|
+
const canonicalRequest = makeCanonicalRequest();
|
|
233
|
+
const trustContext = makeTrustedContactContext();
|
|
234
|
+
|
|
235
|
+
const result = bridgeConfirmationRequestToGuardian({
|
|
236
|
+
canonicalRequest,
|
|
237
|
+
trustContext,
|
|
238
|
+
conversationId: "conv-1",
|
|
239
|
+
toolName: "bash",
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
expect("skipped" in result && result.skipped).toBe(true);
|
|
243
|
+
if ("skipped" in result) {
|
|
244
|
+
expect(result.reason).toBe("v2_model_mediated");
|
|
245
|
+
}
|
|
246
|
+
expect(emittedSignals).toHaveLength(0);
|
|
247
|
+
});
|
|
248
|
+
|
|
226
249
|
test("skips when no guardian binding exists for channel", () => {
|
|
227
250
|
const canonicalRequest = makeCanonicalRequest({ sourceChannel: "phone" });
|
|
228
251
|
const trustContext = makeTrustedContactContext({
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { describe, expect, mock, test } from "bun:test";
|
|
1
|
+
import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
2
2
|
|
|
3
|
+
import { _setOverridesForTesting } from "../config/assistant-feature-flags.js";
|
|
3
4
|
import {
|
|
4
5
|
CONTEXT_OVERFLOW_TOOL_NAME,
|
|
5
6
|
requestCompressionApproval,
|
|
@@ -20,8 +21,22 @@ function createMockPrompter(decision: UserDecision): PermissionPrompter {
|
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
describe("requestCompressionApproval", () => {
|
|
24
|
+
beforeEach(() => {
|
|
25
|
+
_setOverridesForTesting({});
|
|
26
|
+
});
|
|
27
|
+
|
|
23
28
|
// ── Prompt shape ──
|
|
24
29
|
|
|
30
|
+
test("auto-approves without prompting under v2", async () => {
|
|
31
|
+
_setOverridesForTesting({ "permission-controls-v2": true });
|
|
32
|
+
|
|
33
|
+
const prompter = createMockPrompter("deny");
|
|
34
|
+
const result = await requestCompressionApproval(prompter);
|
|
35
|
+
|
|
36
|
+
expect(result).toEqual({ approved: true });
|
|
37
|
+
expect(prompter.prompt).not.toHaveBeenCalled();
|
|
38
|
+
});
|
|
39
|
+
|
|
25
40
|
test("uses the reserved pseudo tool name", async () => {
|
|
26
41
|
const prompter = createMockPrompter("allow");
|
|
27
42
|
await requestCompressionApproval(prompter);
|
|
@@ -55,8 +70,8 @@ describe("requestCompressionApproval", () => {
|
|
|
55
70
|
await requestCompressionApproval(prompter);
|
|
56
71
|
|
|
57
72
|
const args = (prompter.prompt as ReturnType<typeof mock>).mock.calls[0];
|
|
58
|
-
// persistentDecisionsAllowed is index
|
|
59
|
-
expect(args[
|
|
73
|
+
// persistentDecisionsAllowed is index 8
|
|
74
|
+
expect(args[8]).toBe(false);
|
|
60
75
|
});
|
|
61
76
|
|
|
62
77
|
test("includes a description in the input", async () => {
|
|
@@ -119,8 +134,8 @@ describe("requestCompressionApproval", () => {
|
|
|
119
134
|
});
|
|
120
135
|
|
|
121
136
|
const args = (prompter.prompt as ReturnType<typeof mock>).mock.calls[0];
|
|
122
|
-
// signal is index
|
|
123
|
-
expect(args[
|
|
137
|
+
// signal is index 9
|
|
138
|
+
expect(args[9]).toBe(controller.signal);
|
|
124
139
|
});
|
|
125
140
|
|
|
126
141
|
test("works without signal option", async () => {
|
|
@@ -130,7 +145,7 @@ describe("requestCompressionApproval", () => {
|
|
|
130
145
|
|
|
131
146
|
const args = (prompter.prompt as ReturnType<typeof mock>).mock.calls[0];
|
|
132
147
|
// signal should be undefined when not provided
|
|
133
|
-
expect(args[
|
|
148
|
+
expect(args[9]).toBeUndefined();
|
|
134
149
|
});
|
|
135
150
|
|
|
136
151
|
// ── Tool name constant ──
|