@vellumai/assistant 0.4.56 → 0.4.57
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +10 -10
- package/Dockerfile +3 -0
- package/README.md +11 -11
- package/docs/architecture/integrations.md +2 -2
- package/docs/architecture/memory.md +3 -4
- package/docs/credential-execution-service.md +13 -20
- package/node_modules/@vellumai/ces-contracts/src/error.ts +5 -4
- package/package.json +1 -1
- package/src/__tests__/actor-token-service.test.ts +7 -7
- package/src/__tests__/anthropic-provider.test.ts +172 -0
- package/src/__tests__/app-builder-tool-scripts.test.ts +15 -1
- package/src/__tests__/approval-cascade.test.ts +2 -2
- package/src/__tests__/approval-routes-http.test.ts +3 -4
- package/src/__tests__/asset-materialize-tool.test.ts +5 -5
- package/src/__tests__/asset-search-tool.test.ts +1 -1
- package/src/__tests__/assistant-attachments.test.ts +5 -5
- package/src/__tests__/assistant-events-sse-hardening.test.ts +1 -1
- package/src/__tests__/assistant-feature-flags-integration.test.ts +50 -38
- package/src/__tests__/attachments-store.test.ts +2 -2
- package/src/__tests__/avatar-e2e.test.ts +5 -3
- package/src/__tests__/browser-skill-endstate.test.ts +0 -1
- package/src/__tests__/call-routes-http.test.ts +2 -2
- package/src/__tests__/callback-handoff-copy.test.ts +1 -1
- package/src/__tests__/cancel-resolves-conversation-key.test.ts +158 -0
- package/src/__tests__/channel-readiness-routes.test.ts +0 -1
- package/src/__tests__/channel-readiness-service.test.ts +0 -1
- package/src/__tests__/checker.test.ts +31 -32
- package/src/__tests__/chrome-cdp.test.ts +47 -18
- package/src/__tests__/claude-code-skill-regression.test.ts +2 -2
- package/src/__tests__/config-schema-cmd.test.ts +2 -2
- package/src/__tests__/config-schema.test.ts +9 -18
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +1 -1
- package/src/__tests__/conversation-abort-tool-results.test.ts +4 -4
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +2 -2
- package/src/__tests__/conversation-agent-loop.test.ts +11 -4
- package/src/__tests__/conversation-attachments.test.ts +1 -1
- package/src/__tests__/conversation-confirmation-signals.test.ts +2 -2
- package/src/__tests__/conversation-error.test.ts +33 -0
- package/src/__tests__/conversation-init.benchmark.test.ts +0 -1
- package/src/__tests__/conversation-load-history-repair.test.ts +1 -1
- package/src/__tests__/conversation-pairing.test.ts +1 -1
- package/src/__tests__/conversation-pre-run-repair.test.ts +4 -4
- package/src/__tests__/conversation-provider-retry-repair.test.ts +4 -4
- package/src/__tests__/conversation-queue.test.ts +23 -14
- package/src/__tests__/conversation-routes-slash-commands.test.ts +3 -3
- package/src/__tests__/conversation-runtime-assembly.test.ts +185 -173
- package/src/__tests__/conversation-seed-composer.test.ts +1 -1
- package/src/__tests__/conversation-slash-queue.test.ts +4 -4
- package/src/__tests__/conversation-slash-unknown.test.ts +4 -4
- package/src/__tests__/conversation-starter-routes.test.ts +291 -0
- package/src/__tests__/conversation-wipe.test.ts +438 -0
- package/src/__tests__/conversation-workspace-cache-state.test.ts +2 -3
- package/src/__tests__/conversation-workspace-injection.test.ts +4 -5
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +4 -5
- package/src/__tests__/credential-security-e2e.test.ts +20 -0
- package/src/__tests__/credential-security-invariants.test.ts +1 -0
- package/src/__tests__/credential-vault-unit.test.ts +227 -0
- package/src/__tests__/credentials-cli.test.ts +3 -0
- package/src/__tests__/date-context.test.ts +59 -377
- package/src/__tests__/drop-capability-card-state-migration.test.ts +169 -0
- package/src/__tests__/dynamic-skill-workflow-prompt.test.ts +11 -45
- package/src/__tests__/emit-signal-routing-intent.test.ts +3 -3
- package/src/__tests__/encrypted-store.test.ts +237 -15
- package/src/__tests__/ephemeral-permissions.test.ts +4 -5
- package/src/__tests__/event-bus.test.ts +3 -3
- package/src/__tests__/gateway-only-enforcement.test.ts +2 -2
- package/src/__tests__/gateway-only-guard.test.ts +1 -0
- package/src/__tests__/gemini-image-service.test.ts +4 -4
- package/src/__tests__/gemini-provider.test.ts +6 -9
- package/src/__tests__/guardian-binding-drift-heal.test.ts +128 -0
- package/src/__tests__/guardian-dispatch.test.ts +0 -1
- package/src/__tests__/host-shell-tool.test.ts +6 -6
- package/src/__tests__/http-user-message-parity.test.ts +2 -2
- package/src/__tests__/intent-routing.test.ts +51 -99
- package/src/__tests__/invite-routes-http.test.ts +5 -0
- package/src/__tests__/list-messages-attachments.test.ts +1 -1
- package/src/__tests__/managed-proxy-context.test.ts +2 -5
- package/src/__tests__/managed-skill-lifecycle.test.ts +8 -8
- package/src/__tests__/media-generate-image.test.ts +32 -15
- package/src/__tests__/media-reuse-story.e2e.test.ts +1 -1
- package/src/__tests__/memory-context-benchmark.benchmark.test.ts +1 -1
- package/src/__tests__/memory-lifecycle-e2e.test.ts +24 -18
- package/src/__tests__/memory-recall-quality.test.ts +4 -3
- package/src/__tests__/memory-regressions.test.ts +86 -90
- package/src/__tests__/migration-cross-version-compatibility.test.ts +32 -32
- package/src/__tests__/migration-export-http.test.ts +26 -27
- package/src/__tests__/migration-import-commit-http.test.ts +165 -37
- package/src/__tests__/migration-import-preflight-http.test.ts +81 -20
- package/src/__tests__/migration-validate-http.test.ts +16 -16
- package/src/__tests__/model-intents.test.ts +1 -1
- package/src/__tests__/no-domain-routing-in-prompt-guard.test.ts +1 -1
- package/src/__tests__/notification-broadcaster.test.ts +1 -1
- package/src/__tests__/notification-decision-fallback.test.ts +2 -2
- package/src/__tests__/notification-decision-identity.test.ts +8 -9
- package/src/__tests__/notification-decision-strategy.test.ts +1 -1
- package/src/__tests__/notification-deep-link.test.ts +1 -1
- package/src/__tests__/notification-guardian-path.test.ts +0 -1
- package/src/__tests__/notification-schedule-dedup.test.ts +7 -7
- package/src/__tests__/oauth-store.test.ts +1 -3
- package/src/__tests__/oauth2-gateway-transport.test.ts +6 -1
- package/src/__tests__/onboarding-template-contract.test.ts +23 -59
- package/src/__tests__/provider-error-scenarios.test.ts +154 -0
- package/src/__tests__/provider-fail-open-selection.test.ts +2 -2
- package/src/__tests__/provider-managed-proxy-integration.test.ts +8 -9
- package/src/__tests__/provider-registry-ollama.test.ts +5 -2
- package/src/__tests__/qdrant-manager.test.ts +7 -7
- package/src/__tests__/ratelimit.test.ts +0 -74
- package/src/__tests__/recording-handler.test.ts +0 -1
- package/src/__tests__/require-fresh-approval.test.ts +1 -1
- package/src/__tests__/runtime-attachment-metadata.test.ts +1 -1
- package/src/__tests__/runtime-events-sse-parity.test.ts +1 -1
- package/src/__tests__/runtime-events-sse.test.ts +1 -1
- package/src/__tests__/scheduler-recurrence.test.ts +46 -2
- package/src/__tests__/schema-transforms.test.ts +114 -54
- package/src/__tests__/secret-onetime-send.test.ts +20 -0
- package/src/__tests__/secret-routes-managed-proxy.test.ts +5 -2
- package/src/__tests__/secret-scanner-executor.test.ts +1 -2
- package/src/__tests__/send-endpoint-busy.test.ts +63 -4
- package/src/__tests__/send-notification-tool.test.ts +2 -2
- package/src/__tests__/shell-credential-ref.test.ts +0 -1
- package/src/__tests__/shell-tool-proxy-mode.test.ts +1 -2
- package/src/__tests__/skill-memory.test.ts +547 -0
- package/src/__tests__/skill-script-runner-sandbox.test.ts +1 -2
- package/src/__tests__/slack-app-setup-skill-regression.test.ts +37 -0
- package/src/__tests__/slack-channel-config.test.ts +109 -94
- package/src/__tests__/swarm-conversation-integration.test.ts +2 -2
- package/src/__tests__/swarm-recursion.test.ts +2 -2
- package/src/__tests__/swarm-tool.test.ts +2 -2
- package/src/__tests__/system-prompt.test.ts +19 -66
- package/src/__tests__/telegram-config.test.ts +121 -0
- package/src/__tests__/terminal-tools.test.ts +1 -1
- package/src/__tests__/tool-execution-abort-cleanup.test.ts +1 -2
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +1 -1
- package/src/__tests__/tool-executor-shell-integration.test.ts +1 -1
- package/src/__tests__/tool-executor.test.ts +1 -1
- package/src/__tests__/trace-emitter.test.ts +8 -1
- package/src/__tests__/trust-store.test.ts +7 -8
- package/src/__tests__/twilio-routes.test.ts +1 -18
- package/src/__tests__/user-reference.test.ts +82 -2
- package/src/__tests__/vbundle-pax-and-symlink.test.ts +196 -0
- package/src/__tests__/verification-control-plane-policy.test.ts +1 -1
- package/src/approvals/guardian-request-resolvers.ts +3 -3
- package/src/avatar/ascii-renderer.ts +2 -2
- package/src/avatar/png-renderer.ts +2 -2
- package/src/avatar/resvg-lazy.ts +21 -0
- package/src/calls/guardian-dispatch.ts +1 -1
- package/src/calls/relay-access-wait.ts +2 -2
- package/src/calls/twilio-rest.ts +0 -248
- package/src/cli/AGENTS.md +5 -8
- package/src/cli/__tests__/notifications.test.ts +5 -5
- package/src/cli/commands/avatar.ts +64 -2
- package/src/cli/commands/conversations.ts +131 -1
- package/src/cli/commands/credentials.ts +2 -0
- package/src/cli/commands/notifications.ts +3 -3
- package/src/cli.ts +10 -0
- package/src/config/bundled-skills/acp/SKILL.md +5 -5
- package/src/config/bundled-skills/acp/TOOLS.json +6 -6
- package/src/config/bundled-skills/app-builder/SKILL.md +42 -42
- package/src/config/bundled-skills/app-builder/TOOLS.json +10 -10
- package/src/config/bundled-skills/browser/SKILL.md +15 -15
- package/src/config/bundled-skills/browser/TOOLS.json +14 -14
- package/src/config/bundled-skills/chatgpt-import/SKILL.md +2 -2
- package/src/config/bundled-skills/chatgpt-import/TOOLS.json +1 -1
- package/src/config/bundled-skills/chatgpt-import/tools/chatgpt-import.ts +1 -1
- package/src/config/bundled-skills/claude-code/SKILL.md +5 -5
- package/src/config/bundled-skills/computer-use/SKILL.md +2 -2
- package/src/config/bundled-skills/computer-use/TOOLS.json +15 -15
- package/src/config/bundled-skills/contacts/SKILL.md +3 -3
- package/src/config/bundled-skills/contacts/TOOLS.json +4 -4
- package/src/config/bundled-skills/document/SKILL.md +4 -4
- package/src/config/bundled-skills/document/TOOLS.json +2 -2
- package/src/config/bundled-skills/followups/TOOLS.json +3 -3
- package/src/config/bundled-skills/gmail/SKILL.md +32 -32
- package/src/config/bundled-skills/gmail/TOOLS.json +16 -16
- package/src/config/bundled-skills/gmail/tools/gmail-archive.ts +1 -1
- package/src/config/bundled-skills/gmail/tools/gmail-sender-digest.ts +1 -1
- package/src/config/bundled-skills/google-calendar/SKILL.md +1 -1
- package/src/config/bundled-skills/google-calendar/TOOLS.json +5 -5
- package/src/config/bundled-skills/google-calendar/types.ts +1 -1
- package/src/config/bundled-skills/heartbeat/SKILL.md +43 -0
- package/src/config/bundled-skills/image-studio/SKILL.md +3 -3
- package/src/config/bundled-skills/image-studio/TOOLS.json +2 -3
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +16 -12
- package/src/config/bundled-skills/media-processing/SKILL.md +40 -40
- package/src/config/bundled-skills/media-processing/TOOLS.json +8 -8
- package/src/config/bundled-skills/media-processing/__tests__/concurrency-pool.test.ts +2 -2
- package/src/config/bundled-skills/media-processing/__tests__/preprocess.test.ts +1 -1
- package/src/config/bundled-skills/media-processing/services/gemini-map.ts +5 -5
- package/src/config/bundled-skills/media-processing/services/gemini-video.ts +2 -2
- package/src/config/bundled-skills/media-processing/services/preprocess.ts +2 -2
- package/src/config/bundled-skills/media-processing/services/processing-pipeline.ts +2 -2
- package/src/config/bundled-skills/media-processing/services/reduce.ts +3 -3
- package/src/config/bundled-skills/media-processing/tools/generate-clip.ts +2 -2
- package/src/config/bundled-skills/media-processing/tools/query-media-events.ts +1 -1
- package/src/config/bundled-skills/messaging/SKILL.md +29 -25
- package/src/config/bundled-skills/messaging/TOOLS.json +11 -11
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +1 -1
- package/src/config/bundled-skills/messaging/tools/shared.ts +1 -1
- package/src/config/bundled-skills/notifications/SKILL.md +3 -3
- package/src/config/bundled-skills/notifications/TOOLS.json +2 -2
- package/src/config/bundled-skills/notifications/tools/send-notification.ts +3 -3
- package/src/config/bundled-skills/orchestration/SKILL.md +1 -1
- package/src/config/bundled-skills/orchestration/TOOLS.json +1 -1
- package/src/config/bundled-skills/phone-calls/SKILL.md +18 -14
- package/src/config/bundled-skills/phone-calls/TOOLS.json +3 -3
- package/src/config/bundled-skills/phone-calls/references/CONFIG.md +2 -2
- package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +2 -2
- package/src/config/bundled-skills/phone-calls/references/TROUBLESHOOTING.md +1 -1
- package/src/config/bundled-skills/playbooks/TOOLS.json +4 -4
- package/src/config/bundled-skills/schedule/SKILL.md +26 -26
- package/src/config/bundled-skills/schedule/TOOLS.json +5 -5
- package/src/config/bundled-skills/screen-watch/SKILL.md +3 -3
- package/src/config/bundled-skills/screen-watch/TOOLS.json +1 -1
- package/src/config/bundled-skills/sequences/SKILL.md +2 -2
- package/src/config/bundled-skills/sequences/TOOLS.json +10 -10
- package/src/config/bundled-skills/sequences/tools/sequence-analytics.ts +2 -2
- package/src/config/bundled-skills/sequences/tools/sequence-enroll.ts +2 -2
- package/src/config/bundled-skills/sequences/tools/sequence-enrollment-list.ts +1 -1
- package/src/config/bundled-skills/sequences/tools/sequence-get.ts +1 -1
- package/src/config/bundled-skills/sequences/tools/sequence-import.ts +3 -3
- package/src/config/bundled-skills/sequences/tools/sequence-list.ts +1 -1
- package/src/config/bundled-skills/sequences/tools/sequence-update.ts +1 -1
- package/src/config/bundled-skills/settings/TOOLS.json +3 -3
- package/src/config/bundled-skills/settings/tools/open-system-settings.ts +1 -1
- package/src/config/bundled-skills/skill-management/TOOLS.json +5 -5
- package/src/config/bundled-skills/skills-catalog/SKILL.md +84 -0
- package/src/config/bundled-skills/slack/SKILL.md +2 -2
- package/src/config/bundled-skills/slack/TOOLS.json +8 -8
- package/src/config/bundled-skills/slack/tools/slack-scan-digest.ts +3 -3
- package/src/config/bundled-skills/subagent/TOOLS.json +5 -5
- package/src/config/bundled-skills/tasks/SKILL.md +1 -1
- package/src/config/bundled-skills/tasks/TOOLS.json +9 -9
- package/src/config/bundled-skills/transcribe/SKILL.md +5 -5
- package/src/config/bundled-skills/transcribe/TOOLS.json +1 -1
- package/src/config/bundled-skills/transcribe/tools/transcribe-media.ts +10 -10
- package/src/config/bundled-skills/watcher/SKILL.md +4 -4
- package/src/config/bundled-skills/watcher/TOOLS.json +5 -5
- package/src/config/feature-flag-registry.json +33 -17
- package/src/config/schemas/sandbox.ts +1 -1
- package/src/config/schemas/services.ts +13 -3
- package/src/config/schemas/timeouts.ts +0 -10
- package/src/contacts/contact-store.ts +63 -0
- package/src/contacts/contacts-write.ts +1 -1
- package/src/daemon/assistant-attachments.ts +2 -2
- package/src/daemon/conversation-agent-loop-handlers.ts +2 -2
- package/src/daemon/conversation-agent-loop.ts +7 -30
- package/src/daemon/conversation-error.ts +24 -0
- package/src/daemon/conversation-memory.ts +8 -7
- package/src/daemon/conversation-runtime-assembly.ts +139 -274
- package/src/daemon/conversation-slash.ts +7 -26
- package/src/daemon/conversation-surfaces.ts +14 -0
- package/src/daemon/conversation-tool-setup.ts +9 -8
- package/src/daemon/conversation.ts +2 -0
- package/src/daemon/daemon-control.ts +1 -1
- package/src/daemon/date-context.ts +10 -83
- package/src/daemon/handlers/config-channels.ts +12 -2
- package/src/daemon/handlers/config-slack-channel.ts +7 -1
- package/src/daemon/handlers/config-telegram.ts +6 -1
- package/src/daemon/handlers/conversations.ts +2 -2
- package/src/daemon/handlers/skills.ts +4 -0
- package/src/daemon/lifecycle.ts +28 -4
- package/src/daemon/providers-setup.ts +1 -1
- package/src/daemon/server.ts +1 -5
- package/src/daemon/shutdown-handlers.ts +9 -3
- package/src/daemon/tool-side-effects.ts +40 -0
- package/src/daemon/trace-emitter.ts +25 -2
- package/src/events/domain-events.ts +1 -1
- package/src/events/tool-permission-telemetry-listener.ts +46 -0
- package/src/inbound/platform-callback-registration.ts +0 -18
- package/src/media/app-icon-generator.ts +15 -8
- package/src/media/avatar-router.ts +15 -8
- package/src/media/gemini-image-service.ts +125 -21
- package/src/memory/attachments-store.ts +3 -3
- package/src/memory/channel-verification-sessions.ts +6 -6
- package/src/memory/conversation-crud.ts +196 -1
- package/src/memory/{thread-starters-cadence.ts → conversation-starters-cadence.ts} +9 -42
- package/src/memory/conversation-title-service.ts +2 -3
- package/src/memory/db-init.ts +25 -1
- package/src/memory/invite-store.ts +4 -4
- package/src/memory/items-extractor.ts +4 -4
- package/src/memory/job-handlers/{thread-starters.ts → conversation-starters.ts} +123 -38
- package/src/memory/jobs-store.ts +3 -2
- package/src/memory/jobs-worker.ts +7 -5
- package/src/memory/lifecycle-events-store.ts +63 -0
- package/src/memory/migrations/172-rename-created-by-session-id.ts +27 -0
- package/src/memory/migrations/173-rename-source-session-id.ts +16 -0
- package/src/memory/migrations/174-rename-thread-starters-table.ts +52 -0
- package/src/memory/migrations/175-create-lifecycle-events.ts +15 -0
- package/src/memory/migrations/176-drop-capability-card-state.ts +36 -0
- package/src/memory/migrations/177-create-trace-events-table.ts +40 -0
- package/src/memory/migrations/index.ts +6 -0
- package/src/memory/migrations/registry.ts +13 -0
- package/src/memory/retriever.test.ts +223 -96
- package/src/memory/retriever.ts +115 -138
- package/src/memory/schema/calls.ts +1 -1
- package/src/memory/schema/contacts.ts +1 -1
- package/src/memory/schema/infrastructure.ts +29 -0
- package/src/memory/schema/memory-core.ts +7 -17
- package/src/memory/schema/notifications.ts +1 -1
- package/src/memory/search/formatting.ts +23 -6
- package/src/memory/search/lexical.ts +2 -0
- package/src/memory/search/semantic.ts +2 -0
- package/src/memory/search/staleness.ts +1 -0
- package/src/memory/search/types.ts +4 -0
- package/src/memory/task-memory-cleanup.ts +96 -6
- package/src/memory/trace-event-store.ts +148 -0
- package/src/notifications/README.md +1 -1
- package/src/notifications/decision-engine.ts +2 -2
- package/src/notifications/emit-signal.ts +4 -4
- package/src/notifications/events-store.ts +4 -4
- package/src/notifications/signal.ts +1 -1
- package/src/oauth/manual-token-connection.ts +49 -25
- package/src/permissions/checker.ts +6 -5
- package/src/permissions/defaults.ts +4 -4
- package/src/prompts/__tests__/build-cli-reference-section.test.ts +9 -90
- package/src/prompts/cache-boundary.ts +8 -0
- package/src/prompts/system-prompt.ts +105 -634
- package/src/prompts/templates/BOOTSTRAP.md +166 -33
- package/src/prompts/templates/IDENTITY.md +8 -23
- package/src/prompts/templates/SOUL.md +20 -41
- package/src/prompts/templates/USER.md +3 -19
- package/src/prompts/user-reference.ts +14 -16
- package/src/providers/anthropic/client.ts +46 -2
- package/src/providers/gemini/client.ts +6 -9
- package/src/providers/managed-proxy/constants.ts +1 -7
- package/src/providers/managed-proxy/context.ts +0 -1
- package/src/providers/model-intents.ts +5 -5
- package/src/providers/openai/client.ts +10 -1
- package/src/providers/openrouter/client.ts +1 -0
- package/src/providers/ratelimit.ts +0 -35
- package/src/providers/registry.ts +3 -5
- package/src/providers/retry.ts +18 -1
- package/src/runtime/access-request-helper.ts +1 -1
- package/src/runtime/auth/route-policy.ts +7 -0
- package/src/runtime/channel-verification-service.ts +1 -1
- package/src/runtime/confirmation-request-guardian-bridge.ts +1 -1
- package/src/runtime/guardian-vellum-migration.ts +63 -1
- package/src/runtime/http-server.ts +8 -4
- package/src/runtime/migrations/vbundle-builder.ts +212 -32
- package/src/runtime/migrations/vbundle-import-analyzer.ts +74 -8
- package/src/runtime/migrations/vbundle-importer.ts +66 -1
- package/src/runtime/migrations/vbundle-validator.ts +17 -3
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +4 -4
- package/src/runtime/routes/attachment-routes.ts +2 -2
- package/src/runtime/routes/btw-routes.ts +9 -0
- package/src/runtime/routes/channel-verification-routes.ts +19 -2
- package/src/runtime/routes/conversation-management-routes.ts +55 -1
- package/src/runtime/routes/conversation-query-routes.ts +1 -1
- package/src/runtime/routes/conversation-routes.ts +49 -5
- package/src/runtime/routes/conversation-starter-routes.ts +207 -0
- package/src/runtime/routes/guardian-bootstrap-routes.ts +13 -9
- package/src/runtime/routes/inbound-stages/escalation-intercept.ts +1 -1
- package/src/runtime/routes/inbound-stages/verification-intercept.ts +1 -1
- package/src/runtime/routes/migration-routes.ts +25 -13
- package/src/runtime/routes/secret-routes.ts +18 -0
- package/src/runtime/routes/settings-routes.ts +8 -8
- package/src/runtime/routes/telemetry-routes.ts +53 -0
- package/src/runtime/routes/trace-event-routes.ts +62 -0
- package/src/runtime/tool-grant-request-helper.ts +1 -1
- package/src/runtime/verification-outbound-actions.ts +47 -31
- package/src/security/encrypted-store.ts +263 -78
- package/src/skills/catalog-install.ts +10 -0
- package/src/skills/managed-store.ts +2 -0
- package/src/skills/skill-memory.ts +220 -0
- package/src/subagent/manager.ts +1 -4
- package/src/telemetry/types.ts +10 -1
- package/src/telemetry/usage-telemetry-reporter.test.ts +1 -1
- package/src/telemetry/usage-telemetry-reporter.ts +51 -4
- package/src/tools/AGENTS.md +11 -11
- package/src/tools/acp/spawn.ts +1 -1
- package/src/tools/apps/executors.ts +8 -8
- package/src/tools/apps/registry.ts +1 -1
- package/src/tools/assets/materialize.ts +6 -6
- package/src/tools/assets/search.ts +10 -10
- package/src/tools/browser/__tests__/auth-cache.test.ts +2 -2
- package/src/tools/browser/__tests__/auth-detector.test.ts +4 -4
- package/src/tools/browser/auth-detector.ts +6 -6
- package/src/tools/browser/browser-execution.ts +13 -13
- package/src/tools/browser/browser-manager.ts +3 -3
- package/src/tools/browser/chrome-cdp.ts +5 -5
- package/src/tools/browser/jit-auth.ts +2 -2
- package/src/tools/browser/network-recorder.test.ts +2 -2
- package/src/tools/browser/network-recorder.ts +3 -3
- package/src/tools/browser/runtime-check.ts +3 -3
- package/src/tools/claude-code/claude-code.ts +2 -2
- package/src/tools/computer-use/definitions.ts +18 -18
- package/src/tools/credential-execution/make-authenticated-request.ts +4 -4
- package/src/tools/credential-execution/manage-secure-command-tool.ts +3 -3
- package/src/tools/credential-execution/run-authenticated-command.ts +4 -4
- package/src/tools/credentials/broker-types.ts +5 -5
- package/src/tools/credentials/broker.ts +15 -15
- package/src/tools/credentials/metadata-store.ts +2 -2
- package/src/tools/credentials/resolve.ts +1 -1
- package/src/tools/credentials/selection.ts +1 -1
- package/src/tools/credentials/tool-policy.ts +1 -1
- package/src/tools/credentials/vault.ts +115 -25
- package/src/tools/execution-target.ts +2 -2
- package/src/tools/executor.ts +7 -7
- package/src/tools/filesystem/edit.ts +2 -2
- package/src/tools/filesystem/read.ts +1 -1
- package/src/tools/filesystem/write.ts +1 -1
- package/src/tools/host-filesystem/edit.ts +2 -1
- package/src/tools/host-filesystem/read.ts +2 -1
- package/src/tools/host-filesystem/write.ts +1 -1
- package/src/tools/host-terminal/host-shell.ts +9 -8
- package/src/tools/mcp/mcp-tool-factory.ts +7 -6
- package/src/tools/memory/definitions.ts +6 -5
- package/src/tools/memory/handlers.test.ts +1 -1
- package/src/tools/network/__tests__/web-search.test.ts +3 -3
- package/src/tools/network/domain-normalize.ts +2 -2
- package/src/tools/network/script-proxy/session-manager.ts +10 -10
- package/src/tools/network/web-fetch.ts +1 -1
- package/src/tools/network/web-search.ts +3 -3
- package/src/tools/permission-checker.ts +8 -8
- package/src/tools/registry.ts +7 -7
- package/src/tools/schedule/list.ts +2 -2
- package/src/tools/schema-transforms.ts +31 -21
- package/src/tools/secret-detection-handler.ts +1 -1
- package/src/tools/sensitive-output-placeholders.ts +1 -1
- package/src/tools/shared/filesystem/edit-engine.ts +1 -1
- package/src/tools/shared/filesystem/file-ops-service.ts +3 -3
- package/src/tools/shared/filesystem/image-read.ts +25 -5
- package/src/tools/shared/filesystem/path-policy.ts +2 -2
- package/src/tools/shared/shell-output.ts +1 -1
- package/src/tools/side-effects.ts +1 -1
- package/src/tools/skills/execute.ts +1 -1
- package/src/tools/skills/load.ts +3 -3
- package/src/tools/skills/sandbox-runner.ts +3 -3
- package/src/tools/subagent/read.ts +1 -1
- package/src/tools/subagent/spawn.ts +2 -2
- package/src/tools/swarm/delegate.ts +3 -3
- package/src/tools/system/request-permission.ts +5 -4
- package/src/tools/terminal/backends/native.ts +4 -4
- package/src/tools/terminal/parser.ts +6 -6
- package/src/tools/terminal/sandbox-diagnostics.ts +1 -1
- package/src/tools/terminal/shell.ts +16 -16
- package/src/tools/tool-approval-handler.ts +21 -12
- package/src/tools/tool-manifest.ts +4 -4
- package/src/tools/types.ts +3 -3
- package/src/tools/ui-surface/definitions.ts +9 -37
- package/src/tools/watcher/list.ts +1 -1
- package/src/util/logger.ts +7 -2
- package/src/util/retry.ts +29 -1
- package/src/workspace/migrations/007-web-search-provider-rename.ts +37 -0
- package/src/workspace/migrations/registry.ts +2 -0
- package/src/__tests__/cli-help-reference-sync.test.ts +0 -26
- package/src/__tests__/onboarding-starter-tasks.test.ts +0 -190
- package/src/cli/reference.ts +0 -38
- package/src/memory/job-handlers/capability-cards.ts +0 -420
- package/src/runtime/routes/thread-starter-routes.ts +0 -294
|
@@ -185,7 +185,7 @@ describe("isAuthUrl", () => {
|
|
|
185
185
|
|
|
186
186
|
// ── DOM detection: login pages ───────────────────────────────────────
|
|
187
187
|
|
|
188
|
-
describe("detectAuthChallenge
|
|
188
|
+
describe("detectAuthChallenge - login pages", () => {
|
|
189
189
|
it("detects a generic login page with password input", async () => {
|
|
190
190
|
const page = mockPage("https://example.com/login", {
|
|
191
191
|
type: "login",
|
|
@@ -251,7 +251,7 @@ describe("detectAuthChallenge — login pages", () => {
|
|
|
251
251
|
|
|
252
252
|
// ── DOM detection: 2FA pages ─────────────────────────────────────────
|
|
253
253
|
|
|
254
|
-
describe("detectAuthChallenge
|
|
254
|
+
describe("detectAuthChallenge - 2FA pages", () => {
|
|
255
255
|
it("detects a 2FA page with code input", async () => {
|
|
256
256
|
const page = mockPage("https://accounts.google.com/signin/v2/challenge", {
|
|
257
257
|
type: "2fa",
|
|
@@ -290,7 +290,7 @@ describe("detectAuthChallenge — 2FA pages", () => {
|
|
|
290
290
|
|
|
291
291
|
// ── DOM detection: OAuth consent ─────────────────────────────────────
|
|
292
292
|
|
|
293
|
-
describe("detectAuthChallenge
|
|
293
|
+
describe("detectAuthChallenge - OAuth consent", () => {
|
|
294
294
|
it("detects an OAuth consent page with Allow button", async () => {
|
|
295
295
|
const page = mockPage("https://accounts.google.com/o/oauth2/v2/auth", {
|
|
296
296
|
type: "oauth_consent",
|
|
@@ -324,7 +324,7 @@ describe("detectAuthChallenge — OAuth consent", () => {
|
|
|
324
324
|
|
|
325
325
|
// ── Non-auth pages ───────────────────────────────────────────────────
|
|
326
326
|
|
|
327
|
-
describe("detectAuthChallenge
|
|
327
|
+
describe("detectAuthChallenge - non-auth pages", () => {
|
|
328
328
|
it("returns null for a regular page", async () => {
|
|
329
329
|
const page = mockPage("https://example.com/dashboard", null);
|
|
330
330
|
|
|
@@ -25,7 +25,7 @@ interface ServicePattern {
|
|
|
25
25
|
}
|
|
26
26
|
|
|
27
27
|
const SERVICE_PATTERNS: ServicePattern[] = [
|
|
28
|
-
// Auth-subdomain services
|
|
28
|
+
// Auth-subdomain services - hostname match is sufficient
|
|
29
29
|
{ pattern: /accounts\.google\.com/, service: "Google" },
|
|
30
30
|
{ pattern: /login\.microsoftonline\.com/, service: "Microsoft" },
|
|
31
31
|
{ pattern: /appleid\.apple\.com/, service: "Apple" },
|
|
@@ -33,7 +33,7 @@ const SERVICE_PATTERNS: ServicePattern[] = [
|
|
|
33
33
|
{ pattern: /id\.atlassian\.com/, service: "Atlassian" },
|
|
34
34
|
{ pattern: /auth0\.com/, service: "Auth0" },
|
|
35
35
|
{ pattern: /okta\.com/, service: "Okta" },
|
|
36
|
-
// General-domain services
|
|
36
|
+
// General-domain services - need both hostname AND path match
|
|
37
37
|
{
|
|
38
38
|
pattern: /github\.com/,
|
|
39
39
|
service: "GitHub",
|
|
@@ -89,7 +89,7 @@ export function isAuthUrl(url: string): boolean {
|
|
|
89
89
|
)
|
|
90
90
|
)
|
|
91
91
|
return true;
|
|
92
|
-
// Generic path patterns
|
|
92
|
+
// Generic path patterns - match against pathname only to avoid false positives
|
|
93
93
|
// from query parameters or fragments that happen to contain auth-related words.
|
|
94
94
|
return GENERIC_AUTH_PATTERNS.some((p) => p.test(parsedUrl.pathname));
|
|
95
95
|
}
|
|
@@ -228,7 +228,7 @@ const CAPTCHA_DETECT_EXPRESSION = `(() => {
|
|
|
228
228
|
if (document.querySelector(sel)) return true;
|
|
229
229
|
}
|
|
230
230
|
|
|
231
|
-
// reCAPTCHA
|
|
231
|
+
// reCAPTCHA - only flag visible challenges, not invisible v3 scoring widgets.
|
|
232
232
|
// The challenge iframe (api2/bframe) or a visible .g-recaptcha container indicates
|
|
233
233
|
// an interactive CAPTCHA the user must solve.
|
|
234
234
|
if (document.querySelector('iframe[src*="recaptcha/api2/bframe"]')) return true;
|
|
@@ -238,14 +238,14 @@ const CAPTCHA_DETECT_EXPRESSION = `(() => {
|
|
|
238
238
|
if (rect.width > 0 && rect.height > 0) return true;
|
|
239
239
|
}
|
|
240
240
|
|
|
241
|
-
// hCaptcha
|
|
241
|
+
// hCaptcha - only flag when a visible challenge container is present
|
|
242
242
|
const hcaptchaContainer = document.querySelector('#hcaptcha-container, .h-captcha');
|
|
243
243
|
if (hcaptchaContainer) {
|
|
244
244
|
const rect = hcaptchaContainer.getBoundingClientRect();
|
|
245
245
|
if (rect.width > 0 && rect.height > 0) return true;
|
|
246
246
|
}
|
|
247
247
|
|
|
248
|
-
// hCaptcha fallback
|
|
248
|
+
// hCaptcha fallback - catch custom-rendered hCaptcha in arbitrary host elements
|
|
249
249
|
// by looking for any visible hCaptcha iframe (check all, not just the first)
|
|
250
250
|
const hcaptchaIframes = document.querySelectorAll('iframe[src*="hcaptcha"]');
|
|
251
251
|
for (const iframe of hcaptchaIframes) {
|
|
@@ -245,7 +245,7 @@ export async function executeBrowserNavigate(
|
|
|
245
245
|
await page.route("**/*", routeHandler);
|
|
246
246
|
}
|
|
247
247
|
|
|
248
|
-
// Use domcontentloaded but with a shorter timeout
|
|
248
|
+
// Use domcontentloaded but with a shorter timeout - if it times out,
|
|
249
249
|
// the page is likely still usable (heavy SPAs like DoorDash keep loading
|
|
250
250
|
// scripts after DOMContentLoaded). Fall back gracefully instead of failing.
|
|
251
251
|
let response: PageResponse | null = null;
|
|
@@ -260,7 +260,7 @@ export async function executeBrowserNavigate(
|
|
|
260
260
|
const navMsg = navErr instanceof Error ? navErr.message : String(navErr);
|
|
261
261
|
if (navMsg.includes("Timeout") || navMsg.includes("timeout")) {
|
|
262
262
|
// If the page URL never changed from before navigation, the page
|
|
263
|
-
// never actually loaded
|
|
263
|
+
// never actually loaded - re-throw instead of reporting success.
|
|
264
264
|
if (page.url() === urlBeforeNav && urlBeforeNav !== parsedUrl.href) {
|
|
265
265
|
throw navErr;
|
|
266
266
|
}
|
|
@@ -300,7 +300,7 @@ export async function executeBrowserNavigate(
|
|
|
300
300
|
browserManager.clearSnapshotMap(context.conversationId);
|
|
301
301
|
|
|
302
302
|
// Auto-dismiss common blocker modals (regulatory notices, cookie banners)
|
|
303
|
-
// that aren't exposed in the accessibility tree. Runs silently
|
|
303
|
+
// that aren't exposed in the accessibility tree. Runs silently - if no
|
|
304
304
|
// modal is present the evaluate is a no-op.
|
|
305
305
|
try {
|
|
306
306
|
await page.evaluate(`(() => {
|
|
@@ -318,7 +318,7 @@ export async function executeBrowserNavigate(
|
|
|
318
318
|
}
|
|
319
319
|
})()`);
|
|
320
320
|
} catch {
|
|
321
|
-
// Page may have navigated during evaluate
|
|
321
|
+
// Page may have navigated during evaluate - safe to ignore
|
|
322
322
|
}
|
|
323
323
|
|
|
324
324
|
const finalUrl = page.url();
|
|
@@ -335,7 +335,7 @@ export async function executeBrowserNavigate(
|
|
|
335
335
|
|
|
336
336
|
if (navigationTimedOut) {
|
|
337
337
|
lines.push(
|
|
338
|
-
`Note: Page is still loading (domcontentloaded timed out). The page should still be interactive
|
|
338
|
+
`Note: Page is still loading (domcontentloaded timed out). The page should still be interactive - use browser_snapshot to check.`,
|
|
339
339
|
);
|
|
340
340
|
}
|
|
341
341
|
|
|
@@ -347,7 +347,7 @@ export async function executeBrowserNavigate(
|
|
|
347
347
|
try {
|
|
348
348
|
const authChallenge = await detectAuthChallenge(page);
|
|
349
349
|
const captchaChallenge = await detectCaptchaChallenge(page);
|
|
350
|
-
// CAPTCHA takes priority
|
|
350
|
+
// CAPTCHA takes priority - it blocks all interaction including login
|
|
351
351
|
let challenge = captchaChallenge ?? authChallenge;
|
|
352
352
|
|
|
353
353
|
// Many CAPTCHA interstitials (e.g. Cloudflare "Just a moment") auto-resolve
|
|
@@ -362,7 +362,7 @@ export async function executeBrowserNavigate(
|
|
|
362
362
|
const still = await detectCaptchaChallenge(page);
|
|
363
363
|
if (!still) {
|
|
364
364
|
log.info("CAPTCHA auto-resolved");
|
|
365
|
-
// Re-check for auth challenge now that CAPTCHA is gone
|
|
365
|
+
// Re-check for auth challenge now that CAPTCHA is gone -
|
|
366
366
|
// the page may have loaded a login form behind it.
|
|
367
367
|
challenge = await detectAuthChallenge(page);
|
|
368
368
|
break;
|
|
@@ -372,7 +372,7 @@ export async function executeBrowserNavigate(
|
|
|
372
372
|
|
|
373
373
|
if (challenge) {
|
|
374
374
|
if (challenge.type === "captcha") {
|
|
375
|
-
// CAPTCHA persisted after auto-resolve wait
|
|
375
|
+
// CAPTCHA persisted after auto-resolve wait - hand off to user
|
|
376
376
|
if (sender) {
|
|
377
377
|
const { startHandoff } = await import("./browser-handoff.js");
|
|
378
378
|
await startHandoff(context.conversationId, {
|
|
@@ -388,7 +388,7 @@ export async function executeBrowserNavigate(
|
|
|
388
388
|
`CAPTCHA solved by user. Current page: ${newTitle} (${newUrl})`,
|
|
389
389
|
);
|
|
390
390
|
|
|
391
|
-
// Re-check for auth challenges
|
|
391
|
+
// Re-check for auth challenges - the page behind the CAPTCHA may have a login form
|
|
392
392
|
const postCaptchaAuth = await detectAuthChallenge(page);
|
|
393
393
|
if (postCaptchaAuth) {
|
|
394
394
|
lines.push("");
|
|
@@ -407,7 +407,7 @@ export async function executeBrowserNavigate(
|
|
|
407
407
|
"3. For email verification codes, use ui_show with a form to ask the user for the code mid-turn",
|
|
408
408
|
);
|
|
409
409
|
lines.push(
|
|
410
|
-
"4. Do NOT give up or tell the user to sign in manually
|
|
410
|
+
"4. Do NOT give up or tell the user to sign in manually - handle the login flow yourself",
|
|
411
411
|
);
|
|
412
412
|
}
|
|
413
413
|
} else {
|
|
@@ -420,7 +420,7 @@ export async function executeBrowserNavigate(
|
|
|
420
420
|
);
|
|
421
421
|
}
|
|
422
422
|
} else {
|
|
423
|
-
// Login / 2FA / OAuth
|
|
423
|
+
// Login / 2FA / OAuth - the agent should handle these itself
|
|
424
424
|
// using browser tools + credential_store. Don't hand off.
|
|
425
425
|
lines.push("");
|
|
426
426
|
lines.push(formatAuthChallenge(challenge));
|
|
@@ -438,7 +438,7 @@ export async function executeBrowserNavigate(
|
|
|
438
438
|
"3. For email verification codes, use ui_show with a form to ask the user for the code mid-turn",
|
|
439
439
|
);
|
|
440
440
|
lines.push(
|
|
441
|
-
"4. Do NOT give up or tell the user to sign in manually
|
|
441
|
+
"4. Do NOT give up or tell the user to sign in manually - handle the login flow yourself",
|
|
442
442
|
);
|
|
443
443
|
}
|
|
444
444
|
}
|
|
@@ -1047,7 +1047,7 @@ export async function executeBrowserFillCredential(
|
|
|
1047
1047
|
pageDomain = parsed.hostname;
|
|
1048
1048
|
}
|
|
1049
1049
|
} catch {
|
|
1050
|
-
// Invalid URL
|
|
1050
|
+
// Invalid URL - pageDomain stays undefined, broker will deny if domain policy exists
|
|
1051
1051
|
}
|
|
1052
1052
|
|
|
1053
1053
|
const result = await credentialBroker.browserFill({
|
|
@@ -596,7 +596,7 @@ class BrowserManager {
|
|
|
596
596
|
log.debug("positionWindowSidebar: placed browser window in top-right");
|
|
597
597
|
} catch (err) {
|
|
598
598
|
log.warn({ err }, "positionWindowSidebar: failed to position window");
|
|
599
|
-
// CDP session may be stale (e.g. page closed)
|
|
599
|
+
// CDP session may be stale (e.g. page closed) - clear it so it gets recreated
|
|
600
600
|
this.browserCdpSession = null;
|
|
601
601
|
this.browserWindowId = null;
|
|
602
602
|
}
|
|
@@ -682,7 +682,7 @@ class BrowserManager {
|
|
|
682
682
|
|
|
683
683
|
this.handoffResolvers.set(conversationId, resolver);
|
|
684
684
|
|
|
685
|
-
// Poll for URL changes
|
|
685
|
+
// Poll for URL changes - auto-resolve when the page navigates
|
|
686
686
|
// (e.g., CAPTCHA solved, login redirect)
|
|
687
687
|
if (initialUrl && page) {
|
|
688
688
|
pollTimer = setInterval(() => {
|
|
@@ -702,7 +702,7 @@ class BrowserManager {
|
|
|
702
702
|
resolver();
|
|
703
703
|
}
|
|
704
704
|
} catch {
|
|
705
|
-
// Page may have been closed
|
|
705
|
+
// Page may have been closed - resolve gracefully
|
|
706
706
|
this.interactiveModeSessions.delete(conversationId);
|
|
707
707
|
resolver();
|
|
708
708
|
}
|
|
@@ -53,7 +53,7 @@ export interface EnsureChromeOptions {
|
|
|
53
53
|
/**
|
|
54
54
|
* Returns `true` when a CDP endpoint is responding at the given base URL
|
|
55
55
|
* and has at least one open page tab. A CDP endpoint with zero tabs is
|
|
56
|
-
* stale and unusable
|
|
56
|
+
* stale and unusable - callers should treat it as not ready.
|
|
57
57
|
*/
|
|
58
58
|
export async function isCdpReady(
|
|
59
59
|
cdpBase: string = DEFAULT_CDP_BASE,
|
|
@@ -62,7 +62,7 @@ export async function isCdpReady(
|
|
|
62
62
|
const res = await fetch(`${cdpBase}/json/version`);
|
|
63
63
|
if (!res.ok) return false;
|
|
64
64
|
|
|
65
|
-
// Verify there's at least one page tab
|
|
65
|
+
// Verify there's at least one page tab - a CDP endpoint with no tabs
|
|
66
66
|
// is a stale Chrome process that should be relaunched.
|
|
67
67
|
const listRes = await fetch(`${cdpBase}/json/list`);
|
|
68
68
|
if (!listRes.ok) return false;
|
|
@@ -99,19 +99,19 @@ export async function ensureChromeWithCdp(
|
|
|
99
99
|
try {
|
|
100
100
|
const versionRes = await fetch(`${baseUrl}/json/version`);
|
|
101
101
|
if (versionRes.ok) {
|
|
102
|
-
// Stale Chrome
|
|
102
|
+
// Stale Chrome - CDP up but no tabs. Kill it so we can relaunch.
|
|
103
103
|
try {
|
|
104
104
|
execSync(`lsof -ti :${port} | xargs kill -9 2>/dev/null`, {
|
|
105
105
|
stdio: "ignore",
|
|
106
106
|
});
|
|
107
107
|
} catch {
|
|
108
|
-
// Ignore
|
|
108
|
+
// Ignore - process may have already exited.
|
|
109
109
|
}
|
|
110
110
|
// Brief wait for port to clear.
|
|
111
111
|
await new Promise((r) => setTimeout(r, 500));
|
|
112
112
|
}
|
|
113
113
|
} catch {
|
|
114
|
-
// CDP not responding at all
|
|
114
|
+
// CDP not responding at all - port is free, proceed to launch.
|
|
115
115
|
}
|
|
116
116
|
|
|
117
117
|
const args = [
|
|
@@ -65,6 +65,6 @@ function mapAuthFieldType(authType: AuthField["type"]): FormField["type"] {
|
|
|
65
65
|
export function buildTimeoutMessage(challenge: AuthChallenge): string {
|
|
66
66
|
const serviceName = challenge.service ?? "the website";
|
|
67
67
|
return challenge.type === "2fa"
|
|
68
|
-
? `No rush
|
|
69
|
-
: `Take your time
|
|
68
|
+
? `No rush - just let me know when you've got the verification code from ${serviceName}.`
|
|
69
|
+
: `Take your time - I'll continue once you sign in to ${serviceName}.`;
|
|
70
70
|
}
|
|
@@ -57,7 +57,7 @@ describe("NetworkRecorder", () => {
|
|
|
57
57
|
try {
|
|
58
58
|
await recorder.startDirect();
|
|
59
59
|
} catch {
|
|
60
|
-
// Expected
|
|
60
|
+
// Expected - WebSocket connection will fail in test environment
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
expect(fetchCalls.length).toBeGreaterThanOrEqual(1);
|
|
@@ -73,7 +73,7 @@ describe("NetworkRecorder", () => {
|
|
|
73
73
|
try {
|
|
74
74
|
await recorder.startDirect(explicitBase);
|
|
75
75
|
} catch {
|
|
76
|
-
// Expected
|
|
76
|
+
// Expected - WebSocket connection will fail in test environment
|
|
77
77
|
}
|
|
78
78
|
|
|
79
79
|
expect(fetchCalls.length).toBeGreaterThanOrEqual(1);
|
|
@@ -18,11 +18,11 @@ const log = getLogger("network-recorder");
|
|
|
18
18
|
/** Max response body size to capture (64 KB). */
|
|
19
19
|
const MAX_BODY_SIZE = 64 * 1024;
|
|
20
20
|
|
|
21
|
-
/** Default CDP endpoint
|
|
21
|
+
/** Default CDP endpoint - used when no base URL is injected. */
|
|
22
22
|
const DEFAULT_CDP_BASE = "http://localhost:9222";
|
|
23
23
|
|
|
24
24
|
/**
|
|
25
|
-
* Minimal CDP client over WebSocket
|
|
25
|
+
* Minimal CDP client over WebSocket - talks the Chrome DevTools Protocol directly
|
|
26
26
|
* without needing Playwright, so it can attach to the user's real browsing session.
|
|
27
27
|
*/
|
|
28
28
|
class DirectCDPClient {
|
|
@@ -385,7 +385,7 @@ export class NetworkRecorder {
|
|
|
385
385
|
this.loginDetectedFired = true;
|
|
386
386
|
log.info(
|
|
387
387
|
{ url: truncate(entry.request.url, 120, "") },
|
|
388
|
-
"Login detected
|
|
388
|
+
"Login detected - will auto-stop in 5s",
|
|
389
389
|
);
|
|
390
390
|
// Delay to let remaining network requests (cookies, session data) settle
|
|
391
391
|
setTimeout(() => this.onLoginDetected?.(), 5000);
|
|
@@ -26,7 +26,7 @@ function resolveChromium(
|
|
|
26
26
|
/**
|
|
27
27
|
* Try importing playwright from the bundled binary. Returns the module
|
|
28
28
|
* if chromium is resolvable, otherwise undefined. This never installs
|
|
29
|
-
* anything
|
|
29
|
+
* anything - safe for diagnostic/read-only use.
|
|
30
30
|
*/
|
|
31
31
|
async function tryBundledPlaywright(): Promise<
|
|
32
32
|
typeof import("playwright") | undefined
|
|
@@ -95,7 +95,7 @@ export async function importPlaywright(): Promise<typeof import("playwright")> {
|
|
|
95
95
|
}
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
// Dynamic import with a runtime-computed path
|
|
98
|
+
// Dynamic import with a runtime-computed path - bun can't statically
|
|
99
99
|
// analyze this, so it resolves from the filesystem at runtime.
|
|
100
100
|
const entryPath = resolvePackageEntry(pwPkg);
|
|
101
101
|
const pw: Record<string, unknown> = await import(entryPath);
|
|
@@ -109,7 +109,7 @@ export async function importPlaywright(): Promise<typeof import("playwright")> {
|
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
export async function checkBrowserRuntime(): Promise<BrowserRuntimeStatus> {
|
|
112
|
-
// Diagnostic only
|
|
112
|
+
// Diagnostic only - no side effects (no playwright installation)
|
|
113
113
|
let chromium: { executablePath: () => string };
|
|
114
114
|
try {
|
|
115
115
|
const pw = await tryBundledPlaywright();
|
|
@@ -438,7 +438,7 @@ export const claudeCodeTool: Tool = {
|
|
|
438
438
|
}
|
|
439
439
|
|
|
440
440
|
if (!emittedToolUseIds.has(toolUseId)) {
|
|
441
|
-
// New tool
|
|
441
|
+
// New tool - mark previous as complete and emit tool_start.
|
|
442
442
|
if (lastSubToolName && activeToolUseId !== toolUseId) {
|
|
443
443
|
context.onOutput?.(
|
|
444
444
|
JSON.stringify({
|
|
@@ -523,7 +523,7 @@ export const claudeCodeTool: Tool = {
|
|
|
523
523
|
resultText = message.result;
|
|
524
524
|
}
|
|
525
525
|
} else {
|
|
526
|
-
// Error result
|
|
526
|
+
// Error result - surface the subtype and details
|
|
527
527
|
hasError = true;
|
|
528
528
|
const errors = message.errors ?? [];
|
|
529
529
|
const denials = message.permission_denials ?? [];
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* These tools mirror the macOS client's ToolDefinitions.swift schemas, prefixed
|
|
5
5
|
* with `computer_use_` to avoid collisions with existing daemon tools. They are all
|
|
6
|
-
* proxy tools
|
|
6
|
+
* proxy tools - execution is forwarded to a connected macOS client and never
|
|
7
7
|
* handled locally by the daemon.
|
|
8
8
|
*/
|
|
9
9
|
|
|
@@ -21,14 +21,14 @@ function proxyExecute(): Promise<ToolExecutionResult> {
|
|
|
21
21
|
);
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
const
|
|
24
|
+
const activityProperty = {
|
|
25
25
|
type: "string" as const,
|
|
26
26
|
description:
|
|
27
27
|
"Brief non-technical explanation of why this tool is being called",
|
|
28
28
|
};
|
|
29
29
|
|
|
30
30
|
// ---------------------------------------------------------------------------
|
|
31
|
-
// click (unified
|
|
31
|
+
// click (unified - click_type selects single / double / right)
|
|
32
32
|
// ---------------------------------------------------------------------------
|
|
33
33
|
|
|
34
34
|
export const computerUseClickTool: Tool = {
|
|
@@ -69,7 +69,7 @@ export const computerUseClickTool: Tool = {
|
|
|
69
69
|
description:
|
|
70
70
|
"Explanation of what you see and why you are clicking here",
|
|
71
71
|
},
|
|
72
|
-
|
|
72
|
+
activity: activityProperty,
|
|
73
73
|
},
|
|
74
74
|
required: ["reasoning"],
|
|
75
75
|
},
|
|
@@ -106,7 +106,7 @@ export const computerUseTypeTextTool: Tool = {
|
|
|
106
106
|
type: "string",
|
|
107
107
|
description: "Explanation of what you are typing and why",
|
|
108
108
|
},
|
|
109
|
-
|
|
109
|
+
activity: activityProperty,
|
|
110
110
|
},
|
|
111
111
|
required: ["text", "reasoning"],
|
|
112
112
|
},
|
|
@@ -144,7 +144,7 @@ export const computerUseKeyTool: Tool = {
|
|
|
144
144
|
type: "string",
|
|
145
145
|
description: "Explanation of why you are pressing this key",
|
|
146
146
|
},
|
|
147
|
-
|
|
147
|
+
activity: activityProperty,
|
|
148
148
|
},
|
|
149
149
|
required: ["key", "reasoning"],
|
|
150
150
|
},
|
|
@@ -199,7 +199,7 @@ export const computerUseScrollTool: Tool = {
|
|
|
199
199
|
type: "string",
|
|
200
200
|
description: "Explanation of why you are scrolling",
|
|
201
201
|
},
|
|
202
|
-
|
|
202
|
+
activity: activityProperty,
|
|
203
203
|
},
|
|
204
204
|
required: ["direction", "amount", "reasoning"],
|
|
205
205
|
},
|
|
@@ -260,7 +260,7 @@ export const computerUseDragTool: Tool = {
|
|
|
260
260
|
type: "string",
|
|
261
261
|
description: "Explanation of what you are dragging and why",
|
|
262
262
|
},
|
|
263
|
-
|
|
263
|
+
activity: activityProperty,
|
|
264
264
|
},
|
|
265
265
|
required: ["reasoning"],
|
|
266
266
|
},
|
|
@@ -296,7 +296,7 @@ export const computerUseWaitTool: Tool = {
|
|
|
296
296
|
type: "string",
|
|
297
297
|
description: "Explanation of what you are waiting for",
|
|
298
298
|
},
|
|
299
|
-
|
|
299
|
+
activity: activityProperty,
|
|
300
300
|
},
|
|
301
301
|
required: ["duration_ms", "reasoning"],
|
|
302
302
|
},
|
|
@@ -313,7 +313,7 @@ export const computerUseWaitTool: Tool = {
|
|
|
313
313
|
export const computerUseOpenAppTool: Tool = {
|
|
314
314
|
name: "computer_use_open_app",
|
|
315
315
|
description:
|
|
316
|
-
"Open or switch to a macOS application by name. Preferred over cmd+tab for switching apps
|
|
316
|
+
"Open or switch to a macOS application by name. Preferred over cmd+tab for switching apps - more reliable and explicit.",
|
|
317
317
|
category: "computer-use",
|
|
318
318
|
defaultRiskLevel: RiskLevel.Low,
|
|
319
319
|
executionMode: "proxy",
|
|
@@ -335,7 +335,7 @@ export const computerUseOpenAppTool: Tool = {
|
|
|
335
335
|
description:
|
|
336
336
|
"Explanation of why you need to open or switch to this app",
|
|
337
337
|
},
|
|
338
|
-
|
|
338
|
+
activity: activityProperty,
|
|
339
339
|
},
|
|
340
340
|
required: ["app_name", "reasoning"],
|
|
341
341
|
},
|
|
@@ -352,7 +352,7 @@ export const computerUseOpenAppTool: Tool = {
|
|
|
352
352
|
export const computerUseRunAppleScriptTool: Tool = {
|
|
353
353
|
name: "computer_use_run_applescript",
|
|
354
354
|
description:
|
|
355
|
-
"Run an AppleScript command. Prefer this over click/type when possible
|
|
355
|
+
"Run an AppleScript command. Prefer this over click/type when possible - it doesn't move the cursor or interrupt the user. Never use 'do shell script' inside AppleScript (blocked for security).",
|
|
356
356
|
category: "computer-use",
|
|
357
357
|
defaultRiskLevel: RiskLevel.Low,
|
|
358
358
|
executionMode: "proxy",
|
|
@@ -373,7 +373,7 @@ export const computerUseRunAppleScriptTool: Tool = {
|
|
|
373
373
|
description:
|
|
374
374
|
"Explanation of what this script does and why AppleScript is better than UI interaction for this step",
|
|
375
375
|
},
|
|
376
|
-
|
|
376
|
+
activity: activityProperty,
|
|
377
377
|
},
|
|
378
378
|
required: ["script", "reasoning"],
|
|
379
379
|
},
|
|
@@ -406,7 +406,7 @@ export const computerUseDoneTool: Tool = {
|
|
|
406
406
|
type: "string",
|
|
407
407
|
description: "Human-readable summary of what was accomplished",
|
|
408
408
|
},
|
|
409
|
-
|
|
409
|
+
activity: activityProperty,
|
|
410
410
|
},
|
|
411
411
|
required: ["summary"],
|
|
412
412
|
},
|
|
@@ -443,7 +443,7 @@ export const computerUseRespondTool: Tool = {
|
|
|
443
443
|
type: "string",
|
|
444
444
|
description: "Explanation of how you determined the answer",
|
|
445
445
|
},
|
|
446
|
-
|
|
446
|
+
activity: activityProperty,
|
|
447
447
|
},
|
|
448
448
|
required: ["answer", "reasoning"],
|
|
449
449
|
},
|
|
@@ -460,7 +460,7 @@ export const computerUseRespondTool: Tool = {
|
|
|
460
460
|
export const computerUseObserveTool: Tool = {
|
|
461
461
|
name: "computer_use_observe",
|
|
462
462
|
description:
|
|
463
|
-
"Capture the current screen state. Returns the accessibility tree with [ID] element references and optionally a screenshot.\n\nThe accessibility tree shows interactive elements like [3] AXButton 'Save' or [17] AXTextField 'Search'. Use element_id to target these elements in subsequent actions
|
|
463
|
+
"Capture the current screen state. Returns the accessibility tree with [ID] element references and optionally a screenshot.\n\nThe accessibility tree shows interactive elements like [3] AXButton 'Save' or [17] AXTextField 'Search'. Use element_id to target these elements in subsequent actions - this is much more reliable than pixel coordinates.\n\nCall this before your first computer use action, or to check screen state without acting.",
|
|
464
464
|
category: "computer-use",
|
|
465
465
|
defaultRiskLevel: RiskLevel.Low,
|
|
466
466
|
executionMode: "proxy",
|
|
@@ -472,9 +472,9 @@ export const computerUseObserveTool: Tool = {
|
|
|
472
472
|
input_schema: {
|
|
473
473
|
type: "object",
|
|
474
474
|
properties: {
|
|
475
|
-
|
|
475
|
+
activity: activityProperty,
|
|
476
476
|
},
|
|
477
|
-
required: ["
|
|
477
|
+
required: ["activity"],
|
|
478
478
|
},
|
|
479
479
|
};
|
|
480
480
|
},
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* CES tool: make_authenticated_request
|
|
3
3
|
*
|
|
4
4
|
* Delegates an authenticated HTTP request to the Credential Execution Service.
|
|
5
|
-
* The assistant never sees raw credentials
|
|
5
|
+
* The assistant never sees raw credentials - CES injects the credential into
|
|
6
6
|
* the outbound request internally and returns the sanitised response.
|
|
7
7
|
*
|
|
8
8
|
* The input schema matches the `MakeAuthenticatedRequestSchema` from
|
|
@@ -22,7 +22,7 @@ const log = getLogger("ces-tool:make-authenticated-request");
|
|
|
22
22
|
class MakeAuthenticatedRequestTool implements Tool {
|
|
23
23
|
name = "make_authenticated_request";
|
|
24
24
|
description =
|
|
25
|
-
"Execute an authenticated HTTP request through CES. CES injects the credential and returns the response
|
|
25
|
+
"Execute an authenticated HTTP request through CES. CES injects the credential and returns the response - the assistant never sees raw secrets.";
|
|
26
26
|
category = "credential-execution";
|
|
27
27
|
defaultRiskLevel = RiskLevel.High;
|
|
28
28
|
|
|
@@ -50,7 +50,7 @@ class MakeAuthenticatedRequestTool implements Tool {
|
|
|
50
50
|
type: "object",
|
|
51
51
|
additionalProperties: { type: "string" },
|
|
52
52
|
description:
|
|
53
|
-
"Optional request headers. Credential headers are injected by CES
|
|
53
|
+
"Optional request headers. Credential headers are injected by CES - do not include secrets here.",
|
|
54
54
|
},
|
|
55
55
|
body: {
|
|
56
56
|
description:
|
|
@@ -188,7 +188,7 @@ class MakeAuthenticatedRequestTool implements Tool {
|
|
|
188
188
|
"CES make_authenticated_request RPC error",
|
|
189
189
|
);
|
|
190
190
|
return {
|
|
191
|
-
content: `Error: CES RPC call failed
|
|
191
|
+
content: `Error: CES RPC call failed - ${msg}`,
|
|
192
192
|
isError: true,
|
|
193
193
|
};
|
|
194
194
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* The only assistant-facing way to request secure bundle installation or
|
|
5
5
|
* update. This tool deliberately accepts only user-reviewable bundle
|
|
6
|
-
* metadata (bundleId, version, sourceUrl, sha256, declared profiles)
|
|
6
|
+
* metadata (bundleId, version, sourceUrl, sha256, declared profiles) -
|
|
7
7
|
* never raw bytes, workspace file paths, or executable content.
|
|
8
8
|
*
|
|
9
9
|
* Every invocation forces a fresh approval prompt without creating
|
|
@@ -28,7 +28,7 @@ class ManageSecureCommandToolImpl implements Tool {
|
|
|
28
28
|
name = "manage_secure_command_tool";
|
|
29
29
|
description =
|
|
30
30
|
"Request installation, update, or removal of a secure command tool bundle. " +
|
|
31
|
-
"Accepts only bundle metadata for guardian review
|
|
31
|
+
"Accepts only bundle metadata for guardian review - never raw bytes or file paths. " +
|
|
32
32
|
"Each invocation requires fresh approval.";
|
|
33
33
|
category = "credential-execution";
|
|
34
34
|
defaultRiskLevel = RiskLevel.High;
|
|
@@ -362,7 +362,7 @@ class ManageSecureCommandToolImpl implements Tool {
|
|
|
362
362
|
"CES manage_secure_command_tool RPC error",
|
|
363
363
|
);
|
|
364
364
|
return {
|
|
365
|
-
content: `Error: CES RPC call failed
|
|
365
|
+
content: `Error: CES RPC call failed - ${msg}`,
|
|
366
366
|
isError: true,
|
|
367
367
|
};
|
|
368
368
|
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Delegates an authenticated command execution to the Credential Execution
|
|
5
5
|
* Service. CES injects credential values into the command's environment and
|
|
6
|
-
* runs it inside the CES sandbox
|
|
6
|
+
* runs it inside the CES sandbox - the assistant never sees raw secrets.
|
|
7
7
|
*
|
|
8
8
|
* The input schema matches the `RunAuthenticatedCommandSchema` from
|
|
9
9
|
* `@vellumai/ces-contracts` exactly so the LLM-produced parameters pass
|
|
@@ -22,7 +22,7 @@ const log = getLogger("ces-tool:run-authenticated-command");
|
|
|
22
22
|
class RunAuthenticatedCommandTool implements Tool {
|
|
23
23
|
name = "run_authenticated_command";
|
|
24
24
|
description =
|
|
25
|
-
"Execute a command with credential environment variables injected by CES. The command runs inside the CES sandbox
|
|
25
|
+
"Execute a command with credential environment variables injected by CES. The command runs inside the CES sandbox - the assistant never sees raw secrets.";
|
|
26
26
|
category = "credential-execution";
|
|
27
27
|
defaultRiskLevel = RiskLevel.High;
|
|
28
28
|
|
|
@@ -192,7 +192,7 @@ class RunAuthenticatedCommandTool implements Tool {
|
|
|
192
192
|
};
|
|
193
193
|
}
|
|
194
194
|
|
|
195
|
-
// Surface copyback errors
|
|
195
|
+
// Surface copyback errors - CES may report success (command exited
|
|
196
196
|
// normally) but populate response.error with copyback failures.
|
|
197
197
|
if (response.error) {
|
|
198
198
|
const copybackMsg = response.error.message ?? "Output copyback failed";
|
|
@@ -251,7 +251,7 @@ class RunAuthenticatedCommandTool implements Tool {
|
|
|
251
251
|
"CES run_authenticated_command RPC error",
|
|
252
252
|
);
|
|
253
253
|
return {
|
|
254
|
-
content: `Error: CES RPC call failed
|
|
254
|
+
content: `Error: CES RPC call failed - ${msg}`,
|
|
255
255
|
isError: true,
|
|
256
256
|
};
|
|
257
257
|
}
|