@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
|
@@ -3,48 +3,60 @@ import { describe, expect, it } from "bun:test";
|
|
|
3
3
|
import {
|
|
4
4
|
type AuthChallenge,
|
|
5
5
|
detectAuthChallenge,
|
|
6
|
+
detectCaptchaChallenge,
|
|
6
7
|
formatAuthChallenge,
|
|
7
8
|
identifyService,
|
|
8
9
|
isAuthUrl,
|
|
9
10
|
} from "../auth-detector.js";
|
|
10
|
-
import
|
|
11
|
+
import { CdpError } from "../cdp-client/errors.js";
|
|
12
|
+
import type { CdpClient } from "../cdp-client/types.js";
|
|
11
13
|
|
|
12
14
|
// ── Helpers ──────────────────────────────────────────────────────────
|
|
13
15
|
|
|
14
16
|
/**
|
|
15
|
-
*
|
|
16
|
-
* `evaluate()` runs a callback that simulates a DOM structure.
|
|
17
|
+
* Programmable fake CdpClient used in place of a Playwright Page.
|
|
17
18
|
*
|
|
18
|
-
* `
|
|
19
|
-
*
|
|
20
|
-
*
|
|
19
|
+
* `urlValue` drives the response to `document.location.href` reads,
|
|
20
|
+
* `domResult` drives the auth-detector DOM IIFE, and `captchaResult`
|
|
21
|
+
* drives the CAPTCHA detector IIFE. Any of these can be replaced with
|
|
22
|
+
* a function to throw for specific call counts.
|
|
21
23
|
*/
|
|
22
|
-
function
|
|
24
|
+
function fakeCdp(opts: {
|
|
25
|
+
urlValue: string;
|
|
26
|
+
domResult?: unknown;
|
|
27
|
+
captchaResult?: boolean;
|
|
28
|
+
throwOn?: (expression: string) => boolean;
|
|
29
|
+
}): CdpClient {
|
|
23
30
|
return {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
31
|
+
async send<T>(
|
|
32
|
+
method: string,
|
|
33
|
+
params?: Record<string, unknown>,
|
|
34
|
+
): Promise<T> {
|
|
35
|
+
if (method !== "Runtime.evaluate") {
|
|
36
|
+
throw new Error(
|
|
37
|
+
`unexpected CDP method in auth-detector test: ${method}`,
|
|
38
|
+
);
|
|
39
|
+
}
|
|
40
|
+
const expression = String(
|
|
41
|
+
(params as Record<string, unknown>)?.["expression"] ?? "",
|
|
42
|
+
);
|
|
43
|
+
if (opts.throwOn?.(expression)) {
|
|
44
|
+
throw new CdpError("cdp_error", "synthetic failure", {
|
|
45
|
+
cdpMethod: method,
|
|
46
|
+
cdpParams: params,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
if (expression === "document.location.href") {
|
|
50
|
+
return { result: { value: opts.urlValue } } as T;
|
|
51
|
+
}
|
|
52
|
+
// CAPTCHA detector expression starts with "(() => {\n // Cloudflare"
|
|
53
|
+
if (/just a moment/.test(expression)) {
|
|
54
|
+
return { result: { value: opts.captchaResult === true } } as T;
|
|
55
|
+
}
|
|
56
|
+
// Anything else is treated as the auth-detector DOM IIFE.
|
|
57
|
+
return { result: { value: opts.domResult ?? null } } as T;
|
|
45
58
|
},
|
|
46
|
-
|
|
47
|
-
on: () => {},
|
|
59
|
+
dispose() {},
|
|
48
60
|
};
|
|
49
61
|
}
|
|
50
62
|
|
|
@@ -187,33 +199,39 @@ describe("isAuthUrl", () => {
|
|
|
187
199
|
|
|
188
200
|
describe("detectAuthChallenge - login pages", () => {
|
|
189
201
|
it("detects a generic login page with password input", async () => {
|
|
190
|
-
const
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
type: "
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
202
|
+
const cdp = fakeCdp({
|
|
203
|
+
urlValue: "https://example.com/login",
|
|
204
|
+
domResult: {
|
|
205
|
+
type: "login",
|
|
206
|
+
fields: [
|
|
207
|
+
{ type: "email", selector: 'input[type="email"]', label: "email" },
|
|
208
|
+
{
|
|
209
|
+
type: "password",
|
|
210
|
+
selector: 'input[type="password"]',
|
|
211
|
+
label: "password",
|
|
212
|
+
},
|
|
213
|
+
],
|
|
214
|
+
},
|
|
200
215
|
});
|
|
201
216
|
|
|
202
|
-
const result = await detectAuthChallenge(
|
|
217
|
+
const result = await detectAuthChallenge(cdp);
|
|
203
218
|
expect(result).not.toBeNull();
|
|
204
219
|
expect(result!.type).toBe("login");
|
|
205
220
|
expect(result!.fields.some((f) => f.type === "password")).toBe(true);
|
|
206
221
|
});
|
|
207
222
|
|
|
208
223
|
it("detects Google email step via #identifierId", async () => {
|
|
209
|
-
const
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
224
|
+
const cdp = fakeCdp({
|
|
225
|
+
urlValue: "https://accounts.google.com/v3/signin/identifier",
|
|
226
|
+
domResult: {
|
|
227
|
+
type: "login",
|
|
228
|
+
fields: [
|
|
229
|
+
{ type: "email", selector: "#identifierId", label: "Google email" },
|
|
230
|
+
],
|
|
231
|
+
},
|
|
214
232
|
});
|
|
215
233
|
|
|
216
|
-
const result = await detectAuthChallenge(
|
|
234
|
+
const result = await detectAuthChallenge(cdp);
|
|
217
235
|
expect(result).not.toBeNull();
|
|
218
236
|
expect(result!.type).toBe("login");
|
|
219
237
|
expect(result!.service).toBe("Google");
|
|
@@ -221,27 +239,33 @@ describe("detectAuthChallenge - login pages", () => {
|
|
|
221
239
|
});
|
|
222
240
|
|
|
223
241
|
it("detects Google password step", async () => {
|
|
224
|
-
const
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
242
|
+
const cdp = fakeCdp({
|
|
243
|
+
urlValue: "https://accounts.google.com/v3/signin/challenge",
|
|
244
|
+
domResult: {
|
|
245
|
+
type: "login",
|
|
246
|
+
fields: [
|
|
247
|
+
{
|
|
248
|
+
type: "password",
|
|
249
|
+
selector: 'input[type="password"][name="Passwd"]',
|
|
250
|
+
label: "Google password",
|
|
251
|
+
},
|
|
252
|
+
],
|
|
253
|
+
},
|
|
233
254
|
});
|
|
234
255
|
|
|
235
|
-
const result = await detectAuthChallenge(
|
|
256
|
+
const result = await detectAuthChallenge(cdp);
|
|
236
257
|
expect(result).not.toBeNull();
|
|
237
258
|
expect(result!.type).toBe("login");
|
|
238
259
|
expect(result!.service).toBe("Google");
|
|
239
260
|
});
|
|
240
261
|
|
|
241
262
|
it("falls back to URL-only detection when DOM has no auth elements", async () => {
|
|
242
|
-
const
|
|
263
|
+
const cdp = fakeCdp({
|
|
264
|
+
urlValue: "https://accounts.google.com/ServiceLogin",
|
|
265
|
+
domResult: null,
|
|
266
|
+
});
|
|
243
267
|
|
|
244
|
-
const result = await detectAuthChallenge(
|
|
268
|
+
const result = await detectAuthChallenge(cdp);
|
|
245
269
|
expect(result).not.toBeNull();
|
|
246
270
|
expect(result!.type).toBe("login");
|
|
247
271
|
expect(result!.service).toBe("Google");
|
|
@@ -253,36 +277,42 @@ describe("detectAuthChallenge - login pages", () => {
|
|
|
253
277
|
|
|
254
278
|
describe("detectAuthChallenge - 2FA pages", () => {
|
|
255
279
|
it("detects a 2FA page with code input", async () => {
|
|
256
|
-
const
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
280
|
+
const cdp = fakeCdp({
|
|
281
|
+
urlValue: "https://accounts.google.com/signin/v2/challenge",
|
|
282
|
+
domResult: {
|
|
283
|
+
type: "2fa",
|
|
284
|
+
fields: [
|
|
285
|
+
{
|
|
286
|
+
type: "code",
|
|
287
|
+
selector: 'input[name="code"]',
|
|
288
|
+
label: "verification code",
|
|
289
|
+
},
|
|
290
|
+
],
|
|
291
|
+
},
|
|
265
292
|
});
|
|
266
293
|
|
|
267
|
-
const result = await detectAuthChallenge(
|
|
294
|
+
const result = await detectAuthChallenge(cdp);
|
|
268
295
|
expect(result).not.toBeNull();
|
|
269
296
|
expect(result!.type).toBe("2fa");
|
|
270
297
|
expect(result!.fields.some((f) => f.type === "code")).toBe(true);
|
|
271
298
|
});
|
|
272
299
|
|
|
273
300
|
it("detects 2FA via text patterns even without specific input", async () => {
|
|
274
|
-
const
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
301
|
+
const cdp = fakeCdp({
|
|
302
|
+
urlValue: "https://example.com/verify",
|
|
303
|
+
domResult: {
|
|
304
|
+
type: "2fa",
|
|
305
|
+
fields: [
|
|
306
|
+
{
|
|
307
|
+
type: "code",
|
|
308
|
+
selector: "",
|
|
309
|
+
label: "verification code (text detected)",
|
|
310
|
+
},
|
|
311
|
+
],
|
|
312
|
+
},
|
|
283
313
|
});
|
|
284
314
|
|
|
285
|
-
const result = await detectAuthChallenge(
|
|
315
|
+
const result = await detectAuthChallenge(cdp);
|
|
286
316
|
expect(result).not.toBeNull();
|
|
287
317
|
expect(result!.type).toBe("2fa");
|
|
288
318
|
});
|
|
@@ -292,18 +322,21 @@ describe("detectAuthChallenge - 2FA pages", () => {
|
|
|
292
322
|
|
|
293
323
|
describe("detectAuthChallenge - OAuth consent", () => {
|
|
294
324
|
it("detects an OAuth consent page with Allow button", async () => {
|
|
295
|
-
const
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
325
|
+
const cdp = fakeCdp({
|
|
326
|
+
urlValue: "https://accounts.google.com/o/oauth2/v2/auth",
|
|
327
|
+
domResult: {
|
|
328
|
+
type: "oauth_consent",
|
|
329
|
+
fields: [
|
|
330
|
+
{
|
|
331
|
+
type: "approval",
|
|
332
|
+
selector: "#submit_approve_access",
|
|
333
|
+
label: "Allow",
|
|
334
|
+
},
|
|
335
|
+
],
|
|
336
|
+
},
|
|
304
337
|
});
|
|
305
338
|
|
|
306
|
-
const result = await detectAuthChallenge(
|
|
339
|
+
const result = await detectAuthChallenge(cdp);
|
|
307
340
|
expect(result).not.toBeNull();
|
|
308
341
|
expect(result!.type).toBe("oauth_consent");
|
|
309
342
|
expect(result!.service).toBe("Google");
|
|
@@ -311,12 +344,15 @@ describe("detectAuthChallenge - OAuth consent", () => {
|
|
|
311
344
|
});
|
|
312
345
|
|
|
313
346
|
it("detects consent with Approve button", async () => {
|
|
314
|
-
const
|
|
315
|
-
|
|
316
|
-
|
|
347
|
+
const cdp = fakeCdp({
|
|
348
|
+
urlValue: "https://github.com/login/oauth/authorize",
|
|
349
|
+
domResult: {
|
|
350
|
+
type: "oauth_consent",
|
|
351
|
+
fields: [{ type: "approval", selector: "button", label: "Approve" }],
|
|
352
|
+
},
|
|
317
353
|
});
|
|
318
354
|
|
|
319
|
-
const result = await detectAuthChallenge(
|
|
355
|
+
const result = await detectAuthChallenge(cdp);
|
|
320
356
|
expect(result).not.toBeNull();
|
|
321
357
|
expect(result!.type).toBe("oauth_consent");
|
|
322
358
|
});
|
|
@@ -326,36 +362,94 @@ describe("detectAuthChallenge - OAuth consent", () => {
|
|
|
326
362
|
|
|
327
363
|
describe("detectAuthChallenge - non-auth pages", () => {
|
|
328
364
|
it("returns null for a regular page", async () => {
|
|
329
|
-
const
|
|
365
|
+
const cdp = fakeCdp({
|
|
366
|
+
urlValue: "https://example.com/dashboard",
|
|
367
|
+
domResult: null,
|
|
368
|
+
});
|
|
330
369
|
|
|
331
|
-
const result = await detectAuthChallenge(
|
|
370
|
+
const result = await detectAuthChallenge(cdp);
|
|
332
371
|
expect(result).toBeNull();
|
|
333
372
|
});
|
|
334
373
|
|
|
335
374
|
it("returns null for a regular github.com page with no auth elements", async () => {
|
|
336
|
-
const
|
|
337
|
-
"https://github.com/vellum-ai/vellum-assistant",
|
|
338
|
-
null,
|
|
339
|
-
);
|
|
375
|
+
const cdp = fakeCdp({
|
|
376
|
+
urlValue: "https://github.com/vellum-ai/vellum-assistant",
|
|
377
|
+
domResult: null,
|
|
378
|
+
});
|
|
340
379
|
|
|
341
|
-
const result = await detectAuthChallenge(
|
|
380
|
+
const result = await detectAuthChallenge(cdp);
|
|
342
381
|
expect(result).toBeNull();
|
|
343
382
|
});
|
|
344
383
|
|
|
345
384
|
it("returns null for a regular page with no auth elements", async () => {
|
|
346
|
-
const
|
|
385
|
+
const cdp = fakeCdp({
|
|
386
|
+
urlValue: "https://news.ycombinator.com/",
|
|
387
|
+
domResult: null,
|
|
388
|
+
});
|
|
347
389
|
|
|
348
|
-
const result = await detectAuthChallenge(
|
|
390
|
+
const result = await detectAuthChallenge(cdp);
|
|
349
391
|
expect(result).toBeNull();
|
|
350
392
|
});
|
|
351
393
|
|
|
352
|
-
it("returns null when
|
|
353
|
-
const
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
394
|
+
it("returns null when Runtime.evaluate throws a CdpError", async () => {
|
|
395
|
+
const cdp = fakeCdp({
|
|
396
|
+
urlValue: "https://example.com/login",
|
|
397
|
+
domResult: null,
|
|
398
|
+
throwOn: (expr) =>
|
|
399
|
+
!expr.startsWith("document.location.href") &&
|
|
400
|
+
!/just a moment/.test(expr),
|
|
401
|
+
});
|
|
402
|
+
|
|
403
|
+
const result = await detectAuthChallenge(cdp);
|
|
404
|
+
expect(result).toBeNull();
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
it("returns null when getCurrentUrl throws a CdpError", async () => {
|
|
408
|
+
const cdp = fakeCdp({
|
|
409
|
+
urlValue: "https://example.com/login",
|
|
410
|
+
domResult: null,
|
|
411
|
+
throwOn: (expr) => expr === "document.location.href",
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
const result = await detectAuthChallenge(cdp);
|
|
415
|
+
expect(result).toBeNull();
|
|
416
|
+
});
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
// ── CAPTCHA detection ────────────────────────────────────────────────
|
|
420
|
+
|
|
421
|
+
describe("detectCaptchaChallenge", () => {
|
|
422
|
+
it("returns a captcha AuthChallenge when the IIFE returns true", async () => {
|
|
423
|
+
const cdp = fakeCdp({
|
|
424
|
+
urlValue: "https://example.com/blocked",
|
|
425
|
+
captchaResult: true,
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
const result = await detectCaptchaChallenge(cdp);
|
|
429
|
+
expect(result).not.toBeNull();
|
|
430
|
+
expect(result!.type).toBe("captcha");
|
|
431
|
+
expect(result!.url).toBe("https://example.com/blocked");
|
|
432
|
+
expect(result!.fields).toEqual([]);
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
it("returns null when the IIFE returns false", async () => {
|
|
436
|
+
const cdp = fakeCdp({
|
|
437
|
+
urlValue: "https://example.com/home",
|
|
438
|
+
captchaResult: false,
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
const result = await detectCaptchaChallenge(cdp);
|
|
442
|
+
expect(result).toBeNull();
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
it("returns null when Runtime.evaluate throws", async () => {
|
|
446
|
+
const cdp = fakeCdp({
|
|
447
|
+
urlValue: "https://example.com/home",
|
|
448
|
+
captchaResult: true,
|
|
449
|
+
throwOn: (expr) => /just a moment/.test(expr),
|
|
450
|
+
});
|
|
357
451
|
|
|
358
|
-
const result = await
|
|
452
|
+
const result = await detectCaptchaChallenge(cdp);
|
|
359
453
|
expect(result).toBeNull();
|
|
360
454
|
});
|
|
361
455
|
});
|
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import
|
|
1
|
+
import {
|
|
2
|
+
evaluateExpression,
|
|
3
|
+
getCurrentUrl,
|
|
4
|
+
} from "./cdp-client/cdp-dom-helpers.js";
|
|
5
|
+
import type { CdpClient } from "./cdp-client/types.js";
|
|
2
6
|
|
|
3
7
|
export type AuthChallengeType = "login" | "2fa" | "oauth_consent" | "captcha";
|
|
4
8
|
|
|
@@ -106,7 +110,7 @@ interface DomDetectionResult {
|
|
|
106
110
|
* DOM elements. Returns a serialisable result or null.
|
|
107
111
|
*
|
|
108
112
|
* The expression is a self-contained IIFE so it can be passed as a string
|
|
109
|
-
* to `
|
|
113
|
+
* to `Runtime.evaluate()` via {@link evaluateExpression}.
|
|
110
114
|
*/
|
|
111
115
|
const DOM_DETECT_EXPRESSION = `(() => {
|
|
112
116
|
const fields = [];
|
|
@@ -259,23 +263,38 @@ const CAPTCHA_DETECT_EXPRESSION = `(() => {
|
|
|
259
263
|
/**
|
|
260
264
|
* Detect whether the current page presents a CAPTCHA or Cloudflare
|
|
261
265
|
* challenge that requires human interaction.
|
|
266
|
+
*
|
|
267
|
+
* Migrated to CDP: runs {@link CAPTCHA_DETECT_EXPRESSION} via
|
|
268
|
+
* `Runtime.evaluate` and reads the current URL via
|
|
269
|
+
* {@link getCurrentUrl}. Errors (including {@link CdpError}) are
|
|
270
|
+
* swallowed and reported as "no challenge" so the caller can treat
|
|
271
|
+
* this as best-effort detection.
|
|
262
272
|
*/
|
|
263
273
|
export async function detectCaptchaChallenge(
|
|
264
|
-
|
|
274
|
+
cdp: CdpClient,
|
|
275
|
+
signal?: AbortSignal,
|
|
265
276
|
): Promise<AuthChallenge | null> {
|
|
266
277
|
try {
|
|
267
|
-
const isCaptcha =
|
|
278
|
+
const isCaptcha = await evaluateExpression<boolean>(
|
|
279
|
+
cdp,
|
|
268
280
|
CAPTCHA_DETECT_EXPRESSION,
|
|
269
|
-
|
|
281
|
+
{},
|
|
282
|
+
signal,
|
|
283
|
+
);
|
|
270
284
|
if (isCaptcha) {
|
|
285
|
+
const url = await getCurrentUrl(cdp, signal);
|
|
271
286
|
return {
|
|
272
287
|
type: "captcha",
|
|
273
288
|
fields: [],
|
|
274
|
-
url
|
|
289
|
+
url,
|
|
275
290
|
};
|
|
276
291
|
}
|
|
277
292
|
return null;
|
|
278
293
|
} catch {
|
|
294
|
+
// Best-effort detection: swallow CdpError (aborted / disposed /
|
|
295
|
+
// transport failures) and any other runtime error so a failed
|
|
296
|
+
// probe is reported as "no challenge detected" instead of
|
|
297
|
+
// bubbling up through navigation.
|
|
279
298
|
return null;
|
|
280
299
|
}
|
|
281
300
|
}
|
|
@@ -290,19 +309,29 @@ export async function detectCaptchaChallenge(
|
|
|
290
309
|
*
|
|
291
310
|
* Returns an {@link AuthChallenge} if a challenge is detected, or `null`
|
|
292
311
|
* if the page does not appear to be an auth page.
|
|
312
|
+
*
|
|
313
|
+
* Migrated to CDP: runs {@link DOM_DETECT_EXPRESSION} via
|
|
314
|
+
* `Runtime.evaluate` and reads the current URL via
|
|
315
|
+
* {@link getCurrentUrl}. Errors (including {@link CdpError}) are
|
|
316
|
+
* swallowed and reported as "no challenge" so the caller can treat
|
|
317
|
+
* this as best-effort detection.
|
|
293
318
|
*/
|
|
294
319
|
export async function detectAuthChallenge(
|
|
295
|
-
|
|
320
|
+
cdp: CdpClient,
|
|
321
|
+
signal?: AbortSignal,
|
|
296
322
|
): Promise<AuthChallenge | null> {
|
|
297
323
|
try {
|
|
298
|
-
const currentUrl =
|
|
324
|
+
const currentUrl = await getCurrentUrl(cdp, signal);
|
|
299
325
|
const service = identifyService(currentUrl);
|
|
300
326
|
const urlIsAuth = isAuthUrl(currentUrl);
|
|
301
327
|
|
|
302
|
-
// DOM-based detection
|
|
303
|
-
const domResult =
|
|
328
|
+
// DOM-based detection via Runtime.evaluate
|
|
329
|
+
const domResult = await evaluateExpression<DomDetectionResult | null>(
|
|
330
|
+
cdp,
|
|
304
331
|
DOM_DETECT_EXPRESSION,
|
|
305
|
-
|
|
332
|
+
{},
|
|
333
|
+
signal,
|
|
334
|
+
);
|
|
306
335
|
|
|
307
336
|
if (domResult) {
|
|
308
337
|
return {
|
|
@@ -326,7 +355,9 @@ export async function detectAuthChallenge(
|
|
|
326
355
|
|
|
327
356
|
return null;
|
|
328
357
|
} catch {
|
|
329
|
-
// If
|
|
358
|
+
// If Runtime.evaluate throws (e.g. page closed, navigation,
|
|
359
|
+
// aborted, disposed) — or any other CDP/transport failure — treat
|
|
360
|
+
// as no challenge. Matches the pre-CDP best-effort semantics.
|
|
330
361
|
return null;
|
|
331
362
|
}
|
|
332
363
|
}
|