@vellumai/assistant 0.6.2 → 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/docs/architecture/memory.md +1 -1
- 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__/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__/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 +16 -1
- 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 +2 -2
- package/src/__tests__/conversation-attachments.test.ts +80 -4
- package/src/__tests__/conversation-confirmation-signals.test.ts +155 -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 -1
- 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__/integration-status.test.ts +6 -7
- package/src/__tests__/list-messages-tool-merge.test.ts +37 -12
- 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__/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 +75 -57
- 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__/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 -1
- 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-tools.test.ts +9 -0
- package/src/__tests__/tool-approval-handler.test.ts +73 -0
- 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 +14 -29
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +109 -0
- package/src/__tests__/v2-consent-policy.test.ts +103 -0
- package/src/acp/client-handler.ts +30 -4
- package/src/agent/loop.ts +12 -6
- 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 +53 -3
- package/src/cli/commands/browser-relay.ts +339 -409
- package/src/cli/commands/credentials.ts +3 -3
- 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 +44 -44
- 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 +6 -3
- 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/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 +1 -1
- package/src/config/bundled-skills/app-builder/SKILL.md +26 -249
- 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 +1 -1
- package/src/config/bundled-skills/outlook/SKILL.md +7 -0
- 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 +44 -5
- 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 +8 -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 -15
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +186 -0
- package/src/daemon/app-source-watcher.ts +35 -0
- package/src/daemon/context-overflow-approval.ts +5 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +17 -2
- package/src/daemon/conversation-agent-loop.ts +58 -24
- package/src/daemon/conversation-attachments.ts +40 -0
- package/src/daemon/conversation-process.ts +48 -1
- package/src/daemon/conversation-runtime-assembly.ts +118 -36
- package/src/daemon/conversation-surfaces.ts +37 -36
- package/src/daemon/conversation-tool-setup.ts +74 -8
- package/src/daemon/conversation-workspace.ts +12 -0
- package/src/daemon/conversation.ts +226 -8
- package/src/daemon/date-context.ts +10 -10
- package/src/daemon/first-greeting.ts +3 -2
- package/src/daemon/handlers/conversations.ts +9 -140
- package/src/daemon/handlers/shared.ts +58 -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 +65 -11
- package/src/daemon/message-protocol.ts +7 -0
- package/src/daemon/message-types/conversations.ts +55 -13
- package/src/daemon/message-types/host-browser.ts +100 -0
- package/src/daemon/message-types/messages.ts +5 -5
- package/src/daemon/message-types/skills.ts +10 -0
- package/src/daemon/message-types/subagents.ts +2 -0
- package/src/daemon/server.ts +92 -12
- package/src/daemon/tool-side-effects.ts +6 -0
- package/src/daemon/transport-hints.ts +5 -24
- package/src/inbound/platform-callback-registration.ts +18 -17
- package/src/mcp/client.ts +59 -24
- package/src/memory/app-store.ts +31 -1
- package/src/memory/conversation-crud.ts +23 -0
- 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 +176 -17
- 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/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/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 +3 -3
- 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 +126 -87
- package/src/oauth/token-persistence.ts +1 -1
- package/src/permissions/permission-mode.ts +4 -11
- package/src/permissions/prompter.ts +13 -1
- package/src/permissions/v2-consent-policy.ts +87 -0
- package/src/prompts/system-prompt.ts +18 -21
- package/src/prompts/templates/BOOTSTRAP-REFERENCE.md +3 -65
- package/src/prompts/templates/BOOTSTRAP.md +59 -105
- 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 +2 -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/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 +2 -1
- package/src/runtime/routes/conversation-management-routes.ts +108 -0
- package/src/runtime/routes/conversation-routes.ts +301 -27
- package/src/runtime/routes/conversation-starter-routes.ts +78 -16
- 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-routes.ts +42 -22
- 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/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 -82
- package/src/tools/registry.ts +0 -2
- package/src/tools/secret-detection-handler.ts +34 -0
- package/src/tools/shared/filesystem/image-read.ts +61 -40
- 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/shell.ts +21 -16
- package/src/tools/tool-approval-handler.ts +48 -2
- package/src/tools/types.ts +2 -0
- package/src/util/platform.ts +14 -19
- 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
|
@@ -13,6 +13,11 @@ import { z } from "zod";
|
|
|
13
13
|
import { getConversationByKey } from "../../memory/conversation-key-store.js";
|
|
14
14
|
import { addRule } from "../../permissions/trust-store.js";
|
|
15
15
|
import type { UserDecision } from "../../permissions/types.js";
|
|
16
|
+
import {
|
|
17
|
+
isConversationHostAccessDecision,
|
|
18
|
+
isConversationHostAccessEnablePrompt,
|
|
19
|
+
isPermissionControlsV2Enabled,
|
|
20
|
+
} from "../../permissions/v2-consent-policy.js";
|
|
16
21
|
import { getTool } from "../../tools/registry.js";
|
|
17
22
|
import { getLogger } from "../../util/logger.js";
|
|
18
23
|
import { requireBoundGuardian } from "../auth/require-bound-guardian.js";
|
|
@@ -23,6 +28,39 @@ import * as pendingInteractions from "../pending-interactions.js";
|
|
|
23
28
|
|
|
24
29
|
const log = getLogger("approval-routes");
|
|
25
30
|
|
|
31
|
+
function canonicalizeV2ConfirmDecision(params: {
|
|
32
|
+
decision: string;
|
|
33
|
+
interaction: NonNullable<ReturnType<typeof pendingInteractions.get>>;
|
|
34
|
+
}): UserDecision | null {
|
|
35
|
+
const { decision, interaction } = params;
|
|
36
|
+
if (decision === "allow" || decision === "deny") {
|
|
37
|
+
return decision;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const details = interaction.confirmationDetails;
|
|
41
|
+
if (!details || isConversationHostAccessEnablePrompt(details)) {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (
|
|
46
|
+
(decision === "allow_10m" || decision === "allow_conversation") &&
|
|
47
|
+
details.temporaryOptionsAvailable?.includes(decision)
|
|
48
|
+
) {
|
|
49
|
+
return "allow";
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (
|
|
53
|
+
(decision === "always_allow" ||
|
|
54
|
+
decision === "always_allow_high_risk" ||
|
|
55
|
+
decision === "always_deny") &&
|
|
56
|
+
details.persistentDecisionsAllowed
|
|
57
|
+
) {
|
|
58
|
+
return decision === "always_deny" ? "deny" : "allow";
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
|
|
26
64
|
/**
|
|
27
65
|
* POST /v1/confirm — resolve a pending confirmation by requestId.
|
|
28
66
|
* Requires AuthContext with guardian-bound actor.
|
|
@@ -47,6 +85,25 @@ export async function handleConfirm(
|
|
|
47
85
|
return httpError("BAD_REQUEST", "requestId is required", 400);
|
|
48
86
|
}
|
|
49
87
|
|
|
88
|
+
const peeked = pendingInteractions.get(requestId);
|
|
89
|
+
if (!peeked) {
|
|
90
|
+
log.warn(
|
|
91
|
+
{ requestId, decision },
|
|
92
|
+
"Confirmation POST for unknown requestId (already consumed or never registered)",
|
|
93
|
+
);
|
|
94
|
+
return httpError(
|
|
95
|
+
"NOT_FOUND",
|
|
96
|
+
"No pending interaction found for this requestId",
|
|
97
|
+
404,
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
const v2Enabled = isPermissionControlsV2Enabled();
|
|
102
|
+
const effectiveDecision = v2Enabled
|
|
103
|
+
? typeof decision === "string"
|
|
104
|
+
? canonicalizeV2ConfirmDecision({ decision, interaction: peeked })
|
|
105
|
+
: null
|
|
106
|
+
: decision;
|
|
50
107
|
const validConfirmDecisions = [
|
|
51
108
|
"allow",
|
|
52
109
|
"allow_10m",
|
|
@@ -57,28 +114,37 @@ export async function handleConfirm(
|
|
|
57
114
|
"always_allow_high_risk",
|
|
58
115
|
];
|
|
59
116
|
if (
|
|
60
|
-
|
|
61
|
-
!
|
|
117
|
+
(v2Enabled && effectiveDecision == null) ||
|
|
118
|
+
(!v2Enabled &&
|
|
119
|
+
(typeof decision !== "string" ||
|
|
120
|
+
!validConfirmDecisions.includes(decision)))
|
|
62
121
|
) {
|
|
63
122
|
return httpError(
|
|
64
123
|
"BAD_REQUEST",
|
|
65
|
-
|
|
124
|
+
v2Enabled
|
|
125
|
+
? "decision must resolve to allow or deny under permission-controls-v2"
|
|
126
|
+
: `decision must be one of: ${validConfirmDecisions.join(", ")}`,
|
|
66
127
|
400,
|
|
67
128
|
);
|
|
68
129
|
}
|
|
69
130
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
"
|
|
131
|
+
if (
|
|
132
|
+
peeked.confirmationDetails &&
|
|
133
|
+
isConversationHostAccessEnablePrompt(peeked.confirmationDetails) &&
|
|
134
|
+
!isConversationHostAccessDecision(effectiveDecision as UserDecision)
|
|
135
|
+
) {
|
|
136
|
+
return httpError(
|
|
137
|
+
"FORBIDDEN",
|
|
138
|
+
"Conversation host-access prompts only accept allow or deny",
|
|
139
|
+
403,
|
|
77
140
|
);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (v2Enabled && (selectedPattern || selectedScope)) {
|
|
78
144
|
return httpError(
|
|
79
|
-
"
|
|
80
|
-
"
|
|
81
|
-
|
|
145
|
+
"FORBIDDEN",
|
|
146
|
+
"Scoped or persistent approval selections are not supported under permission-controls-v2",
|
|
147
|
+
403,
|
|
82
148
|
);
|
|
83
149
|
}
|
|
84
150
|
|
|
@@ -138,7 +204,7 @@ export async function handleConfirm(
|
|
|
138
204
|
log.info(
|
|
139
205
|
{
|
|
140
206
|
requestId,
|
|
141
|
-
decision,
|
|
207
|
+
decision: effectiveDecision,
|
|
142
208
|
toolName: interaction.confirmationDetails?.toolName,
|
|
143
209
|
conversationId: interaction.conversationId,
|
|
144
210
|
},
|
|
@@ -147,13 +213,13 @@ export async function handleConfirm(
|
|
|
147
213
|
|
|
148
214
|
// ACP permissions: resolve directly without a Conversation object.
|
|
149
215
|
if (interaction.directResolve) {
|
|
150
|
-
interaction.directResolve(
|
|
216
|
+
interaction.directResolve(effectiveDecision as UserDecision);
|
|
151
217
|
return Response.json({ accepted: true });
|
|
152
218
|
}
|
|
153
219
|
|
|
154
220
|
interaction.conversation!.handleConfirmationResponse(
|
|
155
221
|
requestId,
|
|
156
|
-
|
|
222
|
+
effectiveDecision as UserDecision,
|
|
157
223
|
selectedPattern,
|
|
158
224
|
selectedScope,
|
|
159
225
|
undefined,
|
|
@@ -233,6 +299,14 @@ export async function handleTrustRule(
|
|
|
233
299
|
const authError = requireBoundGuardian(authContext);
|
|
234
300
|
if (authError) return authError;
|
|
235
301
|
|
|
302
|
+
if (isPermissionControlsV2Enabled()) {
|
|
303
|
+
return httpError(
|
|
304
|
+
"FORBIDDEN",
|
|
305
|
+
"Persistent trust rules are not supported under permission-controls-v2",
|
|
306
|
+
403,
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
|
|
236
310
|
const body = (await req.json()) as {
|
|
237
311
|
requestId?: string;
|
|
238
312
|
pattern?: string;
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Route handler for the `assistant browser chrome relay` CLI shim.
|
|
3
|
+
*
|
|
4
|
+
* Accepts a single CDP command from out-of-process callers (the CLI
|
|
5
|
+
* subprocess spawned by skill scripts) and routes it to the user's
|
|
6
|
+
* Chrome via the connected chrome-extension WebSocket. The legacy
|
|
7
|
+
* relay CLI was deleted with PR #24329; this route is the runtime
|
|
8
|
+
* surface that lets the in-tree Amazon and Influencer skills keep
|
|
9
|
+
* shelling out to `assistant browser chrome relay <action>` until
|
|
10
|
+
* they migrate onto the new CDP-based skill API.
|
|
11
|
+
*
|
|
12
|
+
* Round-trip:
|
|
13
|
+
* 1. Caller POSTs `{ cdpMethod, cdpParams, cdpSessionId }`.
|
|
14
|
+
* 2. We register a pending interaction with a `directBrowserResolve`
|
|
15
|
+
* callback (no Conversation attached) and push a host_browser_request
|
|
16
|
+
* frame onto the connected chrome-extension WebSocket.
|
|
17
|
+
* 3. The chrome extension drives chrome.debugger and POSTs the result
|
|
18
|
+
* to /v1/host-browser-result.
|
|
19
|
+
* 4. host-browser-routes invokes our directBrowserResolve callback,
|
|
20
|
+
* which resolves the awaiting promise here.
|
|
21
|
+
* 5. We return `{ result | error }` to the caller.
|
|
22
|
+
*
|
|
23
|
+
* If no chrome extension is connected we fail fast with 503 — the legacy
|
|
24
|
+
* Amazon/Influencer scripts treat that as a recoverable error and prompt
|
|
25
|
+
* the user to load the extension.
|
|
26
|
+
*/
|
|
27
|
+
import { v4 as uuid } from "uuid";
|
|
28
|
+
import { z } from "zod";
|
|
29
|
+
|
|
30
|
+
import { findGuardianForChannel } from "../../contacts/contact-store.js";
|
|
31
|
+
import type { ServerMessage } from "../../daemon/message-protocol.js";
|
|
32
|
+
import { getLogger } from "../../util/logger.js";
|
|
33
|
+
import { getChromeExtensionRegistry } from "../chrome-extension-registry.js";
|
|
34
|
+
import { httpError } from "../http-errors.js";
|
|
35
|
+
import type { RouteDefinition } from "../http-router.js";
|
|
36
|
+
import * as pendingInteractions from "../pending-interactions.js";
|
|
37
|
+
|
|
38
|
+
const log = getLogger("browser-cdp-routes");
|
|
39
|
+
|
|
40
|
+
/** Default per-call timeout while waiting for the chrome-extension result POST. */
|
|
41
|
+
const DEFAULT_TIMEOUT_MS = 30_000;
|
|
42
|
+
|
|
43
|
+
/** Synthetic conversation id stamped on host_browser_request envelopes from the CLI shim. */
|
|
44
|
+
const CLI_FAKE_CONVERSATION_ID = "cli-browser-relay";
|
|
45
|
+
|
|
46
|
+
const RequestBody = z.object({
|
|
47
|
+
cdpMethod: z.string().min(1),
|
|
48
|
+
cdpParams: z.record(z.string(), z.unknown()).optional(),
|
|
49
|
+
cdpSessionId: z.string().optional(),
|
|
50
|
+
/** Optional client-side timeout hint, in milliseconds. */
|
|
51
|
+
timeoutMs: z.number().int().positive().max(120_000).optional(),
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
const ResponseBody = z.object({
|
|
55
|
+
result: z.unknown().optional(),
|
|
56
|
+
error: z
|
|
57
|
+
.object({
|
|
58
|
+
code: z.string(),
|
|
59
|
+
message: z.string(),
|
|
60
|
+
})
|
|
61
|
+
.optional(),
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Resolve the local guardian principal id used as the chrome-extension
|
|
66
|
+
* registry key. Mirrors the lookup performed by
|
|
67
|
+
* /v1/browser-extension-pair so the registry get() / send() calls hit
|
|
68
|
+
* the same key.
|
|
69
|
+
*/
|
|
70
|
+
function resolveLocalGuardianId(): string | null {
|
|
71
|
+
try {
|
|
72
|
+
const result = findGuardianForChannel("vellum");
|
|
73
|
+
if (result?.contact.principalId) {
|
|
74
|
+
return result.contact.principalId;
|
|
75
|
+
}
|
|
76
|
+
} catch (err) {
|
|
77
|
+
log.warn({ err }, "Failed to look up local vellum guardian");
|
|
78
|
+
}
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* POST /v1/browser-cdp — drive a single CDP command through the chrome-
|
|
84
|
+
* extension proxy on behalf of an out-of-process CLI caller.
|
|
85
|
+
*
|
|
86
|
+
* Authenticated like other /v1/* routes (the route policy below requires
|
|
87
|
+
* `settings.write`, which the CLI shim's daemon-delivery JWT carries via
|
|
88
|
+
* the `gateway_service_v1` profile).
|
|
89
|
+
*/
|
|
90
|
+
export async function handleBrowserCdp(req: Request): Promise<Response> {
|
|
91
|
+
let body: unknown;
|
|
92
|
+
try {
|
|
93
|
+
body = await req.json();
|
|
94
|
+
} catch {
|
|
95
|
+
return httpError("BAD_REQUEST", "invalid JSON body", 400);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
const parsed = RequestBody.safeParse(body);
|
|
99
|
+
if (!parsed.success) {
|
|
100
|
+
return httpError(
|
|
101
|
+
"BAD_REQUEST",
|
|
102
|
+
`invalid request body: ${parsed.error.message}`,
|
|
103
|
+
400,
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const { cdpMethod, cdpParams, cdpSessionId, timeoutMs } = parsed.data;
|
|
108
|
+
|
|
109
|
+
const guardianId = resolveLocalGuardianId();
|
|
110
|
+
if (!guardianId) {
|
|
111
|
+
return Response.json(
|
|
112
|
+
{
|
|
113
|
+
error: {
|
|
114
|
+
code: "EXTENSION_NOT_CONNECTED",
|
|
115
|
+
message:
|
|
116
|
+
"No local vellum guardian — load the chrome extension and pair it first",
|
|
117
|
+
},
|
|
118
|
+
},
|
|
119
|
+
{ status: 503 },
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const registry = getChromeExtensionRegistry();
|
|
124
|
+
if (!registry.get(guardianId)) {
|
|
125
|
+
return Response.json(
|
|
126
|
+
{
|
|
127
|
+
error: {
|
|
128
|
+
code: "EXTENSION_NOT_CONNECTED",
|
|
129
|
+
message:
|
|
130
|
+
"No chrome extension connected for the local guardian — open Chrome, load the Vellum extension, and click Connect",
|
|
131
|
+
},
|
|
132
|
+
},
|
|
133
|
+
{ status: 503 },
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const requestId = uuid();
|
|
138
|
+
const effectiveTimeoutMs = timeoutMs ?? DEFAULT_TIMEOUT_MS;
|
|
139
|
+
|
|
140
|
+
const result = await new Promise<{ content: string; isError: boolean }>(
|
|
141
|
+
(resolve) => {
|
|
142
|
+
const timer = setTimeout(() => {
|
|
143
|
+
// Drain the pending interaction so a late-arriving POST from
|
|
144
|
+
// the extension lands in 404 territory rather than resolving a
|
|
145
|
+
// promise no one is awaiting.
|
|
146
|
+
pendingInteractions.resolve(requestId);
|
|
147
|
+
resolve({
|
|
148
|
+
content: `Timed out waiting for chrome extension result after ${effectiveTimeoutMs}ms`,
|
|
149
|
+
isError: true,
|
|
150
|
+
});
|
|
151
|
+
}, effectiveTimeoutMs);
|
|
152
|
+
|
|
153
|
+
pendingInteractions.register(requestId, {
|
|
154
|
+
conversation: null,
|
|
155
|
+
conversationId: CLI_FAKE_CONVERSATION_ID,
|
|
156
|
+
kind: "host_browser",
|
|
157
|
+
directBrowserResolve: (response) => {
|
|
158
|
+
clearTimeout(timer);
|
|
159
|
+
resolve(response);
|
|
160
|
+
},
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
const envelope: ServerMessage = {
|
|
164
|
+
type: "host_browser_request",
|
|
165
|
+
requestId,
|
|
166
|
+
conversationId: CLI_FAKE_CONVERSATION_ID,
|
|
167
|
+
cdpMethod,
|
|
168
|
+
cdpParams,
|
|
169
|
+
...(cdpSessionId !== undefined ? { cdpSessionId } : {}),
|
|
170
|
+
timeout_seconds: Math.ceil(effectiveTimeoutMs / 1000),
|
|
171
|
+
} as ServerMessage;
|
|
172
|
+
|
|
173
|
+
const ok = registry.send(guardianId, envelope);
|
|
174
|
+
if (!ok) {
|
|
175
|
+
clearTimeout(timer);
|
|
176
|
+
pendingInteractions.resolve(requestId);
|
|
177
|
+
resolve({
|
|
178
|
+
content:
|
|
179
|
+
"Failed to send host_browser_request to chrome extension (no active connection)",
|
|
180
|
+
isError: true,
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
},
|
|
184
|
+
);
|
|
185
|
+
|
|
186
|
+
if (result.isError) {
|
|
187
|
+
return Response.json(
|
|
188
|
+
{
|
|
189
|
+
error: {
|
|
190
|
+
code: "CDP_ERROR",
|
|
191
|
+
message: result.content,
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
{ status: 502 },
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// The chrome extension serializes the CDP result via JSON.stringify(frame.result).
|
|
199
|
+
// Parse it back here so the CLI shim sees a structured object instead of
|
|
200
|
+
// a string-wrapped JSON blob.
|
|
201
|
+
let parsedResult: unknown;
|
|
202
|
+
try {
|
|
203
|
+
parsedResult = JSON.parse(result.content);
|
|
204
|
+
} catch {
|
|
205
|
+
parsedResult = result.content;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return Response.json({ result: parsedResult });
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// ---------------------------------------------------------------------------
|
|
212
|
+
// Route definitions
|
|
213
|
+
// ---------------------------------------------------------------------------
|
|
214
|
+
|
|
215
|
+
export function browserCdpRouteDefinitions(): RouteDefinition[] {
|
|
216
|
+
return [
|
|
217
|
+
{
|
|
218
|
+
endpoint: "browser-cdp",
|
|
219
|
+
method: "POST",
|
|
220
|
+
summary: "Drive a single CDP command via the chrome extension",
|
|
221
|
+
description:
|
|
222
|
+
"Routes a Chrome DevTools Protocol command through the connected chrome extension. Used by the `assistant browser chrome relay` CLI shim that the in-tree Amazon and Influencer skills shell out to.",
|
|
223
|
+
tags: ["browser"],
|
|
224
|
+
requestBody: RequestBody,
|
|
225
|
+
responseBody: ResponseBody,
|
|
226
|
+
handler: async ({ req }) => handleBrowserCdp(req),
|
|
227
|
+
},
|
|
228
|
+
];
|
|
229
|
+
}
|