@vellumai/assistant 0.9.0 → 0.10.0-staging.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +18 -34
- package/bun.lock +7 -8
- package/docs/activation-funnel-telemetry.md +28 -22
- package/docs/architecture/security.md +29 -28
- package/docs/stt-provider-onboarding.md +3 -5
- package/docs/workflows-testing.md +13 -44
- package/docs/workflows.md +3 -5
- package/node_modules/@vellumai/ces-client/src/__tests__/ces-client.test.ts +47 -0
- package/node_modules/@vellumai/ces-client/src/rpc-client.ts +28 -5
- package/node_modules/@vellumai/environments/src/seeds.ts +2 -5
- package/node_modules/@vellumai/gateway-client/src/admission-policy-contract.ts +97 -0
- package/node_modules/@vellumai/gateway-client/src/inbound-contract.ts +10 -0
- package/node_modules/@vellumai/gateway-client/src/index.ts +32 -6
- package/node_modules/@vellumai/gateway-client/src/outbound-contract.ts +119 -0
- package/node_modules/@vellumai/gateway-client/src/types.ts +15 -84
- package/openapi.yaml +976 -63
- package/package.json +2 -1
- package/scripts/sync-llm-catalog.ts +6 -15
- package/scripts/sync-web-search-catalog.ts +3 -11
- package/src/__tests__/access-request-card-view.test.ts +98 -0
- package/src/__tests__/access-request-seed-content-blocks.test.ts +2 -4
- package/src/__tests__/actor-trust-resolver-address-fallback.test.ts +72 -32
- package/src/__tests__/agent-loop-compaction-strip.test.ts +241 -0
- package/src/__tests__/agent-loop-mutable-latest-user-message.test.ts +16 -13
- package/src/__tests__/agent-loop-output-hooks.test.ts +69 -0
- package/src/__tests__/agent-loop-override-profile.test.ts +25 -0
- package/src/__tests__/always-loaded-tools-guard.test.ts +2 -3
- package/src/__tests__/app-compiler.test.ts +15 -1
- package/src/__tests__/app-dir-path-guard.test.ts +0 -1
- package/src/__tests__/assistant-feature-flag-guard.test.ts +1 -4
- package/src/__tests__/assistant-feature-flag-guardrails.test.ts +0 -2
- package/src/__tests__/auth-fallback-events-store.test.ts +6 -14
- package/src/__tests__/avatar-identity-sync.test.ts +2 -27
- package/src/__tests__/btw-routes.test.ts +6 -8
- package/src/__tests__/call-pointer-messages.test.ts +28 -0
- package/src/__tests__/cancel-clears-processing.test.ts +89 -0
- package/src/__tests__/channel-approval-routes.test.ts +0 -4
- package/src/__tests__/channel-inbound-disk-pressure.test.ts +5 -15
- package/src/__tests__/checker.test.ts +0 -3
- package/src/__tests__/cli-memory-v2-reembed-skills.test.ts +3 -4
- package/src/__tests__/compactor-image-manifest-trust.test.ts +21 -1
- package/src/__tests__/compactor-summary-call-truncation.test.ts +223 -0
- package/src/__tests__/config-loader-backfill.test.ts +268 -27
- package/src/__tests__/config-schema.test.ts +35 -0
- package/src/__tests__/config-watcher.test.ts +0 -18
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +2 -2
- package/src/__tests__/contact-store-user-file.test.ts +0 -6
- package/src/__tests__/contacts-tools.test.ts +29 -0
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +22 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +1 -0
- package/src/__tests__/conversation-agent-loop.test.ts +58 -0
- package/src/__tests__/conversation-attention-telegram.test.ts +0 -1
- package/src/__tests__/conversation-lifecycle.test.ts +7 -9
- package/src/__tests__/conversation-load-history-repair.test.ts +101 -0
- package/src/__tests__/conversation-routes-guardian-reply.test.ts +15 -12
- package/src/__tests__/conversation-surfaces-activation-emit.test.ts +6 -3
- package/src/__tests__/conversation-title-service.test.ts +62 -0
- package/src/__tests__/credential-broker.test.ts +449 -1
- package/src/__tests__/credential-execution-shell-lockdown.test.ts +18 -11
- package/src/__tests__/credential-execution-tools.test.ts +0 -1
- package/src/__tests__/credential-prompt-route.test.ts +4 -4
- package/src/__tests__/credential-routes.test.ts +360 -0
- package/src/__tests__/credential-security-invariants.test.ts +4 -13
- package/src/__tests__/disk-pressure-policy.test.ts +12 -0
- package/src/__tests__/disk-usage.test.ts +65 -0
- package/src/__tests__/dynamic-page-surface.test.ts +152 -1
- package/src/__tests__/fixtures/credential-security-fixtures.ts +2 -33
- package/src/__tests__/gateway-flag-listener.test.ts +110 -1
- package/src/__tests__/gateway-only-guard.test.ts +3 -7
- package/src/__tests__/guardian-binding-drift-heal.test.ts +1 -1
- package/src/__tests__/guardian-card-withdrawal.test.ts +403 -0
- package/src/__tests__/guardian-decision-primitive-canonical.test.ts +5 -3
- package/src/__tests__/guardian-grant-minting.test.ts +3 -35
- package/src/__tests__/guardian-routing-invariants.test.ts +64 -26
- package/src/__tests__/guardian-routing-state.test.ts +0 -1
- package/src/__tests__/headless-browser-mode.test.ts +10 -0
- package/src/__tests__/headless-browser-navigate.test.ts +8 -3
- package/src/__tests__/helpers/create-guardian-binding.ts +0 -1
- package/src/__tests__/host-browser-proxy.test.ts +87 -0
- package/src/__tests__/identity-routes.test.ts +0 -189
- package/src/__tests__/inbound-invite-redemption.test.ts +4 -4
- package/src/__tests__/injector-v3-suppression.test.ts +27 -20
- package/src/__tests__/internal-telemetry-routes.test.ts +6 -14
- package/src/__tests__/invite-redemption-service.test.ts +4 -7
- package/src/__tests__/llm-callsite-catalog.test.ts +5 -6
- package/src/__tests__/llm-catalog-parity.test.ts +30 -23
- package/src/__tests__/llm-resolver.test.ts +70 -24
- package/src/__tests__/llm-schema.test.ts +1 -0
- package/src/__tests__/managed-profile-guard.test.ts +163 -4
- package/src/__tests__/mcp-health-check.test.ts +6 -7
- package/src/__tests__/media-stream-server-integration.test.ts +317 -13
- package/src/__tests__/oauth-provider-seed-logos.test.ts +4 -6
- package/src/__tests__/onboarding-persona-write.test.ts +1 -1
- package/src/__tests__/path-policy.test.ts +34 -0
- package/src/__tests__/persona-resolver.test.ts +49 -14
- package/src/__tests__/plugin-api-model-profiles.test.ts +178 -0
- package/src/__tests__/plugin-api-provider.test.ts +24 -0
- package/src/__tests__/plugin-tool-contribution.test.ts +6 -3
- package/src/__tests__/post-compaction-reinjection-idempotency.test.ts +214 -0
- package/src/__tests__/provider-send-message-override-profile.test.ts +76 -0
- package/src/__tests__/reaction-persistence.test.ts +150 -29
- package/src/__tests__/registry.test.ts +2 -7
- package/src/__tests__/relay-server.test.ts +285 -0
- package/src/__tests__/runtime-attachment-metadata.test.ts +0 -1
- package/src/__tests__/schedule-routes-workflow-validation.test.ts +1 -10
- package/src/__tests__/schedule-routes.test.ts +0 -30
- package/src/__tests__/schedule-tools.test.ts +2 -18
- package/src/__tests__/scheduler-reuse-conversation.test.ts +8 -5
- package/src/__tests__/skill-execute-input.test.ts +51 -1
- package/src/__tests__/skill-runtime-path.test.ts +2 -3
- package/src/__tests__/skills.test.ts +51 -0
- package/src/__tests__/slack-notification-approval-card.test.ts +176 -0
- package/src/__tests__/slack-reaction-canonical-approval.test.ts +285 -0
- package/src/__tests__/subagent-tools.test.ts +266 -0
- package/src/__tests__/surface-completion-nudge-hook.test.ts +367 -0
- package/src/__tests__/task-progress-nudge-hook.test.ts +1 -1
- package/src/__tests__/title-generate-hook.test.ts +100 -3
- package/src/__tests__/token-estimator-accuracy.benchmark.test.ts +1 -29
- package/src/__tests__/token-manager.test.ts +519 -0
- package/src/__tests__/tool-approval-seed-content-blocks.test.ts +1 -1
- package/src/__tests__/tool-audit-listener.test.ts +7 -7
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +6 -3
- package/src/__tests__/tool-executor.test.ts +0 -79
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +4 -2
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +220 -3
- package/src/__tests__/trusted-contact-multichannel.test.ts +3 -3
- package/src/__tests__/trusted-contact-verification.test.ts +8 -10
- package/src/__tests__/twilio-routes.test.ts +81 -1
- package/src/__tests__/voice-invite-redemption.test.ts +2 -3
- package/src/__tests__/weak-open-model.test.ts +30 -0
- package/src/__tests__/web-search-catalog-parity.test.ts +6 -25
- package/src/__tests__/workspace-greetings.test.ts +152 -0
- package/src/__tests__/workspace-migration-105-enable-memory-v3-live-for-new-workspaces.test.ts +149 -0
- package/src/__tests__/workspace-migration-108-drop-balanced-economy-profile.test.ts +285 -0
- package/src/__tests__/workspace-migration-add-send-diagnostics.test.ts +1 -1
- package/src/__tests__/workspace-migration-drop-collect-usage-data.test.ts +118 -0
- package/src/__tests__/workspace-migration-drop-send-diagnostics.test.ts +118 -0
- package/src/a2a/__tests__/e2e-a2a-channel.test.ts +0 -4
- package/src/agent/loop.ts +49 -29
- package/src/api/README.md +6 -6
- package/src/api/events/tool-result.ts +6 -0
- package/src/api/events/workflow-completed.ts +53 -0
- package/src/api/events/workflow-leaf-finished.ts +38 -0
- package/src/api/events/workflow-leaf-started.ts +35 -0
- package/src/api/events/workflow-progress.ts +32 -0
- package/src/api/events/workflow-started.ts +31 -0
- package/src/api/index.ts +40 -0
- package/src/api/responses/conversation-message.ts +28 -4
- package/src/api/responses/home.ts +26 -4
- package/src/api/responses/workflow-journal.ts +53 -0
- package/src/approvals/guardian-card-withdrawal.ts +145 -0
- package/src/approvals/guardian-decision-primitive.ts +26 -3
- package/src/approvals/guardian-request-resolvers.ts +183 -80
- package/src/calls/__tests__/channel-admission-reader.test.ts +132 -0
- package/src/calls/__tests__/relay-setup-router.test.ts +350 -0
- package/src/calls/call-pointer-messages.ts +10 -4
- package/src/calls/channel-admission-reader.ts +104 -0
- package/src/calls/guardian-dispatch.ts +17 -45
- package/src/calls/media-stream-server.ts +84 -2
- package/src/calls/relay-access-wait.ts +1 -1
- package/src/calls/relay-server.ts +66 -0
- package/src/calls/relay-setup-router.ts +82 -1
- package/src/calls/twilio-routes.ts +17 -8
- package/src/calls/voice-session-bridge.ts +2 -2
- package/src/cli/commands/clients.ts +3 -0
- package/src/cli/commands/{__tests__ → memory/__tests__}/memory-v2-compare-render.test.ts +1 -1
- package/src/cli/commands/{__tests__ → memory/__tests__}/memory-v2.test.ts +8 -7
- package/src/cli/commands/{__tests__ → memory/__tests__}/memory-v3.test.ts +5 -4
- package/src/cli/commands/memory/index.ts +30 -0
- package/src/cli/commands/{memory-v2-compare-render.ts → memory/memory-v2-compare-render.ts} +1 -1
- package/src/cli/commands/{memory-v2.ts → memory/memory-v2.ts} +6 -15
- package/src/cli/commands/{memory-v3.ts → memory/memory-v3.ts} +97 -11
- package/src/cli/commands/oauth/status.test.ts +36 -0
- package/src/cli/commands/oauth/status.ts +23 -3
- package/src/cli/commands/plugins.ts +197 -4
- package/src/cli/lib/__tests__/diff-plugin.test.ts +443 -0
- package/src/cli/lib/__tests__/inspect-plugin.test.ts +54 -0
- package/src/cli/lib/__tests__/merge-plugin-tree.test.ts +443 -0
- package/src/cli/lib/__tests__/plugin-surfaces.test.ts +111 -0
- package/src/cli/lib/__tests__/upgrade-plugin.test.ts +295 -2
- package/src/cli/lib/diff-plugin.ts +346 -0
- package/src/cli/lib/inspect-plugin.ts +12 -1
- package/src/cli/lib/install-from-github.ts +105 -17
- package/src/cli/lib/merge-plugin-tree.ts +328 -0
- package/src/cli/lib/plugin-fingerprint.ts +14 -0
- package/src/cli/lib/plugin-surfaces.ts +104 -0
- package/src/cli/lib/upgrade-plugin.ts +298 -10
- package/src/cli/program.ts +2 -6
- package/src/config/__tests__/sync-gated-profiles.test.ts +368 -0
- package/src/config/assistant-feature-flags.ts +22 -7
- package/src/config/bundled-skills/contacts/tools/contact-search.ts +0 -1
- package/src/config/bundled-skills/messaging/SKILL.md +6 -4
- package/src/config/bundled-skills/messaging/tools/messaging-archive-by-sender.ts +9 -8
- package/src/config/bundled-skills/subagent/SKILL.md +4 -0
- package/src/config/bundled-skills/subagent/TOOLS.json +4 -0
- package/src/config/bundled-skills/workflows/SKILL.md +14 -8
- package/src/config/bundled-tool-registry.ts +2 -7
- package/src/config/call-site-defaults.ts +15 -2
- package/src/config/feature-flag-registry.json +46 -31
- package/src/config/inference-profile-validation.ts +26 -0
- package/src/config/llm-resolver.ts +3 -0
- package/src/config/loader.ts +4 -0
- package/src/config/memory-v3-gate.ts +11 -0
- package/src/config/profile-order.ts +28 -0
- package/src/config/schema.ts +8 -6
- package/src/config/schemas/__tests__/memory-v3.test.ts +1 -0
- package/src/config/schemas/call-site-catalog.ts +7 -0
- package/src/config/schemas/channels.ts +11 -0
- package/src/config/schemas/elevenlabs.ts +0 -1
- package/src/config/schemas/llm.ts +31 -0
- package/src/config/schemas/memory-lifecycle.ts +3 -7
- package/src/config/schemas/memory-v3.ts +6 -0
- package/src/config/schemas/platform.ts +0 -8
- package/src/config/schemas/services.ts +18 -0
- package/src/config/seed-inference-profiles.ts +109 -44
- package/src/config/skills.ts +21 -0
- package/src/config/sync-gated-profiles.ts +220 -0
- package/src/contacts/contact-store.ts +89 -106
- package/src/contacts/contacts-write.ts +5 -22
- package/src/contacts/types.ts +0 -1
- package/src/context/compactor.ts +88 -54
- package/src/context/strip-injections.ts +58 -10
- package/src/context/token-estimator.ts +1 -1
- package/src/credential-execution/process-manager.ts +55 -14
- package/src/credential-execution/prompted-credential.ts +2 -3
- package/src/daemon/__tests__/conversation-lifecycle-auto-analyze.test.ts +3 -2
- package/src/daemon/config-watcher.ts +0 -4
- package/src/daemon/conversation-agent-loop-handlers.ts +2 -0
- package/src/daemon/conversation-agent-loop.ts +114 -22
- package/src/daemon/conversation-history.ts +1 -1
- package/src/daemon/conversation-lifecycle.ts +3 -5
- package/src/daemon/conversation-process.ts +13 -5
- package/src/daemon/conversation-runtime-assembly.ts +13 -15
- package/src/daemon/conversation-slash.ts +2 -23
- package/src/daemon/conversation-surfaces.ts +26 -0
- package/src/daemon/conversation-tool-setup.ts +27 -14
- package/src/daemon/conversation.ts +66 -14
- package/src/daemon/disk-pressure-policy.ts +5 -3
- package/src/daemon/handlers/__tests__/config-a2a-complete.test.ts +0 -1
- package/src/daemon/handlers/__tests__/config-a2a-redeem.test.ts +0 -1
- package/src/daemon/handlers/config-a2a.ts +0 -2
- package/src/daemon/handlers/config-channels.ts +15 -16
- package/src/daemon/handlers/config-slack-channel.ts +22 -3
- package/src/daemon/handlers/conversations.ts +107 -0
- package/src/daemon/host-browser-proxy.ts +41 -0
- package/src/daemon/lifecycle.ts +55 -27
- package/src/daemon/message-provenance.ts +2 -0
- package/src/daemon/message-types/contacts.ts +0 -1
- package/src/daemon/message-types/conversations.ts +3 -3
- package/src/daemon/message-types/sync.ts +0 -1
- package/src/daemon/message-types/web-activity.ts +7 -1
- package/src/daemon/message-types/workflows.ts +83 -1
- package/src/daemon/orphan-reaper.test.ts +0 -19
- package/src/daemon/orphan-reaper.ts +2 -24
- package/src/daemon/server.ts +0 -10
- package/src/daemon/tool-setup-types.ts +4 -0
- package/src/daemon/trust-context.ts +1 -1
- package/src/events/tool-audit-listener.ts +2 -2
- package/src/home/feed-source-enrichment.test.ts +151 -0
- package/src/home/feed-source-enrichment.ts +176 -0
- package/src/home/relationship-state.ts +2 -4
- package/src/instrument.ts +18 -6
- package/src/ipc/__tests__/binary-result-ipc.test.ts +81 -0
- package/src/ipc/__tests__/clients-list-ipc.test.ts +20 -0
- package/src/ipc/assistant-server.ts +37 -4
- package/src/ipc/gateway-flag-listener.ts +18 -2
- package/src/memory/__tests__/auto-analysis-enqueue.test.ts +5 -16
- package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +7 -11
- package/src/memory/__tests__/memory-retrospective-enqueue.test.ts +37 -7
- package/src/memory/__tests__/memory-retrospective-job.test.ts +229 -401
- package/src/memory/__tests__/onboarding-events-store.test.ts +7 -7
- package/src/memory/auth-fallback-events-store.ts +2 -2
- package/src/memory/auto-analysis-enqueue.ts +3 -5
- package/src/memory/bookmark-crud.ts +1 -2
- package/src/memory/canonical-guardian-store.ts +39 -1
- package/src/memory/conversation-crud.ts +9 -4
- package/src/memory/conversation-key-store.ts +17 -2
- package/src/memory/conversation-title-service.ts +64 -7
- package/src/memory/db-init.ts +17 -17
- package/src/memory/embedding-backend.ts +38 -1
- package/src/memory/embedding-billing-breaker.ts +96 -0
- package/src/memory/jobs-store.ts +25 -13
- package/src/memory/jobs-worker.ts +54 -1
- package/src/memory/lifecycle-events-store.ts +2 -2
- package/src/memory/memory-retrospective-constants.ts +4 -4
- package/src/memory/memory-retrospective-enqueue.ts +31 -6
- package/src/memory/memory-retrospective-job.ts +28 -227
- package/src/memory/migrations/129-contact-channels-access-fields.ts +18 -9
- package/src/memory/migrations/131-drop-legacy-member-guardian-tables.ts +14 -2
- package/src/memory/migrations/289-contact-channels-unique-ext-user.ts +10 -0
- package/src/memory/migrations/291-contact-channels-renormalize-addresses.ts +72 -0
- package/src/memory/migrations/292-schedule-default-no-reuse-conversation.test.ts +67 -0
- package/src/memory/migrations/292-schedule-default-no-reuse-conversation.ts +25 -0
- package/src/memory/migrations/293-workflow-journal-leaf-tokens.ts +32 -0
- package/src/memory/migrations/294-drop-external-user-id.ts +31 -0
- package/src/memory/migrations/295-drop-approval-prompt-ts-tracker.ts +20 -0
- package/src/memory/migrations/296-rewrite-balanced-economy-profile-pins.test.ts +110 -0
- package/src/memory/migrations/296-rewrite-balanced-economy-profile-pins.ts +68 -0
- package/src/memory/migrations/__tests__/131-drop-legacy-member-guardian-tables.test.ts +154 -0
- package/src/memory/migrations/__tests__/289-contact-channels-unique-ext-user.test.ts +31 -0
- package/src/memory/migrations/__tests__/291-contact-channels-renormalize-addresses.test.ts +341 -0
- package/src/memory/migrations/__tests__/run-migrations.test.ts +52 -0
- package/src/memory/migrations/index.ts +6 -0
- package/src/memory/migrations/run-migrations.ts +41 -0
- package/src/memory/migrations/validate-migration-state.ts +1 -1
- package/src/memory/onboarding-events-store.ts +3 -3
- package/src/memory/schema/contacts.ts +0 -5
- package/src/memory/skill-loaded-events-store.test.ts +7 -15
- package/src/memory/skill-loaded-events-store.ts +2 -2
- package/src/memory/tool-executed-events-store.test.ts +7 -7
- package/src/memory/turn-trace-store.test.ts +736 -0
- package/src/memory/turn-trace-store.ts +364 -0
- package/src/memory/v2/__tests__/consolidation-job.test.ts +8 -0
- package/src/memory/v2/__tests__/skill-content.test.ts +30 -0
- package/src/memory/v2/consolidation-job.ts +2 -2
- package/src/memory/v2/skill-content.ts +25 -7
- package/src/memory/v2/skill-store.ts +7 -1
- package/src/memory/v3-eval/__tests__/eval-packets.test.ts +248 -0
- package/src/memory/v3-eval/eval-packets.ts +546 -0
- package/src/messaging/providers/slack/adapter.ts +1 -1
- package/src/messaging/providers/slack/api.ts +31 -0
- package/src/messaging/providers/slack/send.test.ts +114 -2
- package/src/messaging/providers/slack/send.ts +30 -7
- package/src/messaging/providers/slack/withdraw.test.ts +200 -0
- package/src/messaging/providers/slack/withdraw.ts +161 -0
- package/src/notifications/AGENTS.md +2 -0
- package/src/notifications/access-request-copy.ts +72 -59
- package/src/notifications/adapters/shared.ts +29 -0
- package/src/notifications/adapters/slack.ts +58 -103
- package/src/notifications/adapters/telegram.ts +2 -20
- package/src/notifications/approval-card-data.ts +333 -0
- package/src/notifications/broadcaster.ts +16 -3
- package/src/notifications/canonical-delivery-recorder.ts +139 -0
- package/src/notifications/copy-composer.ts +3 -3
- package/src/notifications/decision-engine.ts +4 -2
- package/src/notifications/destination-resolver.ts +4 -6
- package/src/notifications/guardian-question-mode.ts +10 -0
- package/src/notifications/home-feed-side-effect.ts +7 -16
- package/src/notifications/notification-utils.ts +19 -20
- package/src/notifications/signal.ts +79 -43
- package/src/notifications/types.ts +98 -121
- package/src/oauth/AGENTS.md +5 -24
- package/src/permissions/checker.test.ts +51 -0
- package/src/permissions/checker.ts +185 -26
- package/src/permissions/ipc-risk-types.ts +24 -0
- package/src/permissions/question-prompter.test.ts +27 -0
- package/src/permissions/question-prompter.ts +4 -0
- package/src/platform/client.test.ts +119 -0
- package/src/platform/client.ts +66 -0
- package/src/platform/consent-cache.test.ts +267 -0
- package/src/platform/consent-cache.ts +174 -0
- package/src/plugin-api/constants.ts +1 -1
- package/src/plugin-api/index.ts +33 -1
- package/src/plugin-api/model-profiles.ts +33 -0
- package/src/plugin-api/types.ts +50 -2
- package/src/plugins/defaults/advisor/__tests__/advisor-gate.test.ts +56 -0
- package/src/plugins/defaults/advisor/__tests__/advisor-state-store.test.ts +43 -0
- package/src/plugins/defaults/advisor/__tests__/agent-loop-integration.test.ts +137 -0
- package/src/plugins/defaults/advisor/__tests__/consult.test.ts +153 -0
- package/src/plugins/defaults/advisor/__tests__/hooks.test.ts +138 -0
- package/src/plugins/defaults/advisor/__tests__/transcript.test.ts +147 -0
- package/src/plugins/defaults/advisor/advisor-gate.ts +29 -0
- package/src/plugins/defaults/advisor/advisor-state-store.ts +94 -0
- package/src/plugins/defaults/advisor/config.ts +21 -0
- package/src/plugins/defaults/advisor/consult.ts +93 -0
- package/src/plugins/defaults/advisor/hooks/post-model-call.ts +34 -0
- package/src/plugins/defaults/advisor/hooks/pre-model-call.ts +30 -0
- package/src/plugins/defaults/advisor/hooks/user-prompt-submit.ts +19 -0
- package/src/plugins/defaults/advisor/package.json +14 -0
- package/src/plugins/defaults/advisor/steering.ts +67 -0
- package/src/plugins/defaults/advisor/tools/advisor.ts +65 -0
- package/src/plugins/defaults/advisor/transcript.ts +76 -0
- package/src/plugins/defaults/index.ts +60 -0
- package/src/plugins/defaults/memory-retrieval/hooks/post-compact.ts +22 -9
- package/src/plugins/defaults/memory-retrieval/hooks/user-prompt-submit.ts +2 -2
- package/src/plugins/defaults/memory-retrieval/tail-reinjection-strip.ts +64 -0
- package/src/plugins/defaults/memory-retrieval/unified-turn-context.ts +29 -21
- package/src/plugins/defaults/memory-v3-shadow/__tests__/carry-integration.test.ts +1 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/injection.test.ts +1 -0
- package/src/plugins/defaults/memory-v3-shadow/__tests__/maintain-job.test.ts +129 -9
- package/src/plugins/defaults/memory-v3-shadow/__tests__/orchestrate.test.ts +31 -4
- package/src/plugins/defaults/memory-v3-shadow/__tests__/selection-log-store.test.ts +77 -2
- package/src/plugins/defaults/memory-v3-shadow/__tests__/shadow-plugin.test.ts +1 -0
- package/src/plugins/defaults/memory-v3-shadow/injector.ts +7 -10
- package/src/plugins/defaults/memory-v3-shadow/maintain-job.ts +144 -11
- package/src/plugins/defaults/memory-v3-shadow/orchestrate.ts +32 -20
- package/src/plugins/defaults/memory-v3-shadow/selection-log-store.ts +56 -3
- package/src/plugins/defaults/memory-v3-shadow/shadow-plugin.ts +23 -2
- package/src/plugins/defaults/surface-completion-nudge/hooks/post-model-call.ts +276 -0
- package/src/plugins/defaults/surface-completion-nudge/hooks/stop.ts +22 -0
- package/src/plugins/defaults/surface-completion-nudge/nudge-state-store.ts +46 -0
- package/src/plugins/defaults/surface-completion-nudge/package.json +14 -0
- package/src/plugins/defaults/task-progress-nudge/hooks/post-tool-use.ts +3 -13
- package/src/plugins/defaults/title-generate/hooks/stop.ts +56 -21
- package/src/prompts/persona-resolver.ts +14 -4
- package/src/prompts/templates/system-sections.ts +7 -2
- package/src/providers/__tests__/provider-env-vars.test.ts +6 -0
- package/src/providers/__tests__/provider-secret-catalog.test.ts +1 -0
- package/src/providers/__tests__/retry-callsite.test.ts +176 -0
- package/src/providers/atlascloud/client.ts +85 -0
- package/src/providers/fetch-provider-catalog.ts +85 -0
- package/src/providers/inference/adapter-factory.ts +3 -0
- package/src/providers/model-catalog.ts +58 -0
- package/src/providers/openai/__tests__/chat-completions-provider-reasoning.test.ts +33 -0
- package/src/providers/openai/chat-completions-provider.ts +7 -0
- package/src/providers/openai/responses-provider.ts +10 -0
- package/src/providers/provider-send-message.ts +11 -3
- package/src/providers/retry.ts +53 -12
- package/src/providers/search-provider-catalog.ts +10 -0
- package/src/providers/weak-open-model.ts +22 -0
- package/src/runtime/AGENTS.md +0 -1
- package/src/runtime/__tests__/agent-wake.test.ts +181 -0
- package/src/runtime/__tests__/client-health.test.ts +44 -0
- package/src/runtime/access-request-helper.ts +21 -53
- package/src/runtime/actor-trust-resolver.ts +59 -63
- package/src/runtime/agent-wake.ts +52 -0
- package/src/runtime/assistant-event-hub.ts +18 -4
- package/src/runtime/auth/__tests__/route-policy.test.ts +12 -0
- package/src/runtime/auth/require-bound-guardian.ts +1 -4
- package/src/runtime/btw-sidechain.ts +3 -6
- package/src/runtime/capabilities.test.ts +120 -0
- package/src/runtime/capabilities.ts +197 -0
- package/src/runtime/channel-approval-types.ts +22 -45
- package/src/runtime/channel-invite-transports/telegram.ts +4 -4
- package/src/runtime/channel-retry-sweep.ts +1 -0
- package/src/runtime/channel-verification-service.ts +3 -3
- package/src/runtime/client-health.ts +26 -0
- package/src/runtime/confirmation-request-guardian-bridge.ts +38 -29
- package/src/runtime/effective-capabilities.test.ts +128 -0
- package/src/runtime/effective-capabilities.ts +84 -0
- package/src/runtime/guardian-reply-router.ts +106 -21
- package/src/runtime/invite-redemption-service.ts +9 -25
- package/src/runtime/migrations/__tests__/vbundle-builder-fd-leak.test.ts +123 -0
- package/src/runtime/migrations/vbundle-builder.ts +49 -20
- package/src/runtime/pending-interactions.ts +15 -0
- package/src/runtime/routes/__tests__/client-routes.test.ts +13 -0
- package/src/runtime/routes/__tests__/conversation-management-routes.test.ts +67 -0
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +240 -1
- package/src/runtime/routes/app-routes.ts +1 -1
- package/src/runtime/routes/approval-strategies/guardian-callback-strategy.ts +2 -2
- package/src/runtime/routes/assets/vellum-design-system.css +1959 -0
- package/src/runtime/routes/browser-tabs-routes.ts +9 -0
- package/src/runtime/routes/btw-routes.ts +1 -27
- package/src/runtime/routes/canonical-guardian-expiry-sweep.ts +17 -8
- package/src/runtime/routes/client-routes.ts +10 -0
- package/src/runtime/routes/contact-routes.ts +31 -8
- package/src/runtime/routes/conversation-compaction-routes.ts +1 -1
- package/src/runtime/routes/conversation-management-routes.ts +80 -1
- package/src/runtime/routes/conversation-query-routes.ts +68 -22
- package/src/runtime/routes/conversation-routes.ts +39 -14
- package/src/runtime/routes/credential-routes.ts +40 -16
- package/src/runtime/routes/empty-state-greeting-cache.ts +1 -2
- package/src/runtime/routes/events-routes.ts +1 -3
- package/src/runtime/routes/guardian-approval-interception.ts +14 -73
- package/src/runtime/routes/guardian-approval-prompt.ts +22 -4
- package/src/runtime/routes/home-feed-routes.ts +8 -3
- package/src/runtime/routes/identity-routes.ts +1 -296
- package/src/runtime/routes/inbound-message-handler.ts +214 -228
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +89 -7
- package/src/runtime/routes/inbound-stages/admission-policy.test.ts +154 -0
- package/src/runtime/routes/inbound-stages/admission-policy.ts +140 -0
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +3 -3
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +11 -6
- package/src/runtime/routes/inbound-stages/escalation-intercept.ts +1 -2
- package/src/runtime/routes/inbound-stages/guardian-activation-intercept.ts +1 -2
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.test.ts +7 -7
- package/src/runtime/routes/inbound-stages/guardian-reply-intercept.ts +47 -28
- package/src/runtime/routes/inbound-stages/reaction-intercept.ts +358 -0
- package/src/runtime/routes/index.ts +2 -0
- package/src/runtime/routes/integrations/slack/__tests__/channel.test.ts +8 -0
- package/src/runtime/routes/integrations/slack/channel.ts +36 -0
- package/src/runtime/routes/internal-telemetry-routes.ts +1 -1
- package/src/runtime/routes/mcp-auth-routes.ts +233 -41
- package/src/runtime/routes/memory-eval-routes.ts +87 -0
- package/src/runtime/routes/notification-routes.ts +122 -133
- package/src/runtime/routes/platform-routes.ts +2 -2
- package/src/runtime/routes/plugins-routes.ts +202 -3
- package/src/runtime/routes/schedule-routes.ts +0 -22
- package/src/runtime/routes/secret-routes.ts +10 -0
- package/src/runtime/routes/surface-action-routes.ts +2 -1
- package/src/runtime/routes/tool-call-question-enrichment.test.ts +146 -0
- package/src/runtime/routes/tool-call-question-enrichment.ts +66 -0
- package/src/runtime/routes/workflow-routes.test.ts +229 -44
- package/src/runtime/routes/workflow-routes.ts +131 -29
- package/src/runtime/routes/workspace-greetings.ts +55 -0
- package/src/runtime/sync/resource-sync-events.ts +1 -11
- package/src/runtime/tool-grant-request-helper.ts +18 -16
- package/src/runtime/trust-context-resolver.ts +8 -5
- package/src/schedule/inference-profile.ts +2 -14
- package/src/schedule/schedule-store.ts +1 -1
- package/src/schedule/scheduler-types.ts +5 -1
- package/src/security/__tests__/provider-key-env-fallback.test.ts +6 -0
- package/src/security/secret-patterns.ts +3 -0
- package/src/subagent/manager.ts +17 -4
- package/src/subagent/types.ts +6 -0
- package/src/telemetry/trace-collection-policy.test.ts +28 -0
- package/src/telemetry/trace-collection-policy.ts +30 -0
- package/src/telemetry/types.ts +89 -0
- package/src/telemetry/usage-telemetry-reporter.test.ts +586 -36
- package/src/telemetry/usage-telemetry-reporter.ts +148 -41
- package/src/tools/AGENTS.md +3 -3
- package/src/tools/browser/__tests__/browser-execution-acquire.test.ts +31 -0
- package/src/tools/browser/browser-execution.ts +30 -19
- package/src/tools/document/document-tool.ts +2 -3
- package/src/tools/executor.ts +5 -3
- package/src/tools/host-terminal/host-shell.ts +5 -4
- package/src/tools/memory/register.ts +2 -2
- package/src/tools/network/__tests__/web-fetch-firecrawl.test.ts +360 -0
- package/src/tools/network/__tests__/web-search.test.ts +143 -0
- package/src/tools/network/web-fetch.ts +372 -1
- package/src/tools/network/web-search-error.ts +1 -1
- package/src/tools/network/web-search.ts +213 -10
- package/src/tools/permission-checker.ts +4 -3
- package/src/tools/registry.ts +20 -0
- package/src/tools/schedule/create.ts +7 -12
- package/src/tools/schedule/update.ts +4 -11
- package/src/tools/shared/filesystem/path-policy.ts +39 -13
- package/src/tools/side-effects.ts +2 -17
- package/src/tools/skills/execute.ts +33 -0
- package/src/tools/subagent/spawn.ts +61 -12
- package/src/tools/terminal/shell.ts +10 -4
- package/src/tools/tool-approval-handler.ts +18 -13
- package/src/tools/tool-manifest.ts +0 -2
- package/src/tools/types.ts +9 -0
- package/src/tools/ui-surface/definitions.ts +64 -3
- package/src/tools/verification-control-plane-policy.ts +3 -1
- package/src/tools/workflows/run-workflow.test.ts +8 -18
- package/src/tools/workflows/run-workflow.ts +1 -0
- package/src/util/disk-usage.ts +78 -23
- package/src/util/platform.ts +10 -3
- package/src/watcher/telemetry.ts +2 -2
- package/src/workflows/capabilities.ts +2 -3
- package/src/workflows/engine.test.ts +175 -1
- package/src/workflows/engine.ts +82 -0
- package/src/workflows/journal-store.test.ts +70 -0
- package/src/workflows/journal-store.ts +18 -3
- package/src/workflows/run-manager.test.ts +171 -28
- package/src/workflows/run-manager.ts +66 -24
- package/src/workspace/migrations/105-enable-memory-v3-live-for-new-workspaces.ts +63 -0
- package/src/workspace/migrations/106-drop-collect-usage-data.ts +47 -0
- package/src/workspace/migrations/107-drop-send-diagnostics.ts +47 -0
- package/src/workspace/migrations/108-drop-balanced-economy-profile.ts +129 -0
- package/src/workspace/migrations/registry.ts +8 -0
- package/src/__tests__/app-control-no-global-cgevent.test.ts +0 -98
- package/src/__tests__/credential-security-e2e.test.ts +0 -362
- package/src/__tests__/credential-vault-unit.test.ts +0 -1528
- package/src/__tests__/credential-vault.test.ts +0 -1706
- package/src/__tests__/identity-intro-cache.test.ts +0 -315
- package/src/__tests__/secret-onetime-send.test.ts +0 -182
- package/src/cli/commands/__tests__/task.test.ts +0 -914
- package/src/cli/commands/task.ts +0 -771
- package/src/config/bundled-skills/personal-page/SKILL.md +0 -57
- package/src/config/bundled-skills/personal-page/TOOLS.json +0 -27
- package/src/config/bundled-skills/personal-page/tools/app-refresh.ts +0 -17
- package/src/config/preloaded-apps/personal-page/src/components/About.tsx +0 -22
- package/src/config/preloaded-apps/personal-page/src/components/App.tsx +0 -16
- package/src/config/preloaded-apps/personal-page/src/components/Features.tsx +0 -77
- package/src/config/preloaded-apps/personal-page/src/components/Hero.tsx +0 -57
- package/src/config/preloaded-apps/personal-page/src/components/Pending.tsx +0 -28
- package/src/config/preloaded-apps/personal-page/src/components/animations.tsx +0 -234
- package/src/config/preloaded-apps/personal-page/src/components/icons.tsx +0 -48
- package/src/config/preloaded-apps/personal-page/src/components/media.ts +0 -16
- package/src/config/preloaded-apps/personal-page/src/index.html +0 -20
- package/src/config/preloaded-apps/personal-page/src/main.tsx +0 -7
- package/src/config/preloaded-apps/personal-page/src/profile-data.ts +0 -82
- package/src/config/preloaded-apps/personal-page/src/styles.css +0 -759
- package/src/memory/__tests__/preloaded-apps.test.ts +0 -85
- package/src/memory/preloaded-apps.ts +0 -116
- package/src/notifications/tool-approval-copy.ts +0 -142
- package/src/runtime/routes/approval-prompt-ts-tracker.ts +0 -78
- package/src/runtime/routes/identity-intro-cache.ts +0 -172
- package/src/tools/credentials/vault.ts +0 -712
|
@@ -4,16 +4,14 @@
|
|
|
4
4
|
* Periodically flushes LLM usage events and turn events (user messages) from
|
|
5
5
|
* the local SQLite database and POSTs them to the platform telemetry endpoint.
|
|
6
6
|
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
7
|
+
* Authenticated-only: events are sent via the managed proxy context
|
|
8
|
+
* (Api-Key header). When no platform credentials are available, or when
|
|
9
|
+
* platform features are disabled (VELLUM_DISABLE_PLATFORM in local mode), the
|
|
10
|
+
* flush is skipped and retried next cycle.
|
|
10
11
|
*/
|
|
11
12
|
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
getPlatformOrganizationId,
|
|
15
|
-
getPlatformUserId,
|
|
16
|
-
} from "../config/env.js";
|
|
13
|
+
import { isAssistantFeatureFlagEnabled } from "../config/assistant-feature-flags.js";
|
|
14
|
+
import { getPlatformOrganizationId, getPlatformUserId } from "../config/env.js";
|
|
17
15
|
import { getConfig } from "../config/loader.js";
|
|
18
16
|
import { queryUnreportedAuthFallbackEvents } from "../memory/auth-fallback-events-store.js";
|
|
19
17
|
import {
|
|
@@ -26,7 +24,17 @@ import { queryUnreportedOnboardingEvents } from "../memory/onboarding-events-sto
|
|
|
26
24
|
import { queryUnreportedSkillLoadedEvents } from "../memory/skill-loaded-events-store.js";
|
|
27
25
|
import { queryUnreportedToolExecutedEvents } from "../memory/tool-executed-events-store.js";
|
|
28
26
|
import { queryUnreportedTurnEvents } from "../memory/turn-events-store.js";
|
|
27
|
+
import {
|
|
28
|
+
assembleBoundedTurnTrace,
|
|
29
|
+
isTurnSettled,
|
|
30
|
+
} from "../memory/turn-trace-store.js";
|
|
29
31
|
import { VellumPlatformClient } from "../platform/client.js";
|
|
32
|
+
import {
|
|
33
|
+
getCachedShareAnalytics,
|
|
34
|
+
getCachedShareDiagnostics,
|
|
35
|
+
getCachedShareDiagnosticsVersion,
|
|
36
|
+
} from "../platform/consent-cache.js";
|
|
37
|
+
import { arePlatformFeaturesEnabled } from "../platform/feature-gate.js";
|
|
30
38
|
import type { UsageAttributionProfileSource } from "../usage/types.js";
|
|
31
39
|
import { getDeviceId } from "../util/device-id.js";
|
|
32
40
|
import { getLogger } from "../util/logger.js";
|
|
@@ -35,6 +43,7 @@ import {
|
|
|
35
43
|
type ActivationStepName,
|
|
36
44
|
buildActivationDaemonEventId,
|
|
37
45
|
} from "./activation-funnel.js";
|
|
46
|
+
import { isDiagnosticsConsentVersionEligible } from "./trace-collection-policy.js";
|
|
38
47
|
import type { TelemetryEvent, TurnTelemetryClientInfo } from "./types.js";
|
|
39
48
|
|
|
40
49
|
const log = getLogger("usage-telemetry");
|
|
@@ -128,7 +137,7 @@ export class UsageTelemetryReporter {
|
|
|
128
137
|
// reporter shipping its rows: an absent watermark means no flush (opted
|
|
129
138
|
// in or out) has ever advanced it, so rows recorded before this build —
|
|
130
139
|
// including any opted-out period under older builds that gated the
|
|
131
|
-
// reporter on
|
|
140
|
+
// reporter on the usage-data opt-out — would otherwise ship retroactively.
|
|
132
141
|
// Initialize an absent watermark to "now" at construction. Construction
|
|
133
142
|
// happens during daemon startup before any tool runs, so no legitimate
|
|
134
143
|
// row falls behind the watermark — initializing at first FLUSH instead
|
|
@@ -137,8 +146,8 @@ export class UsageTelemetryReporter {
|
|
|
137
146
|
// absent and re-initialize later. An EXISTING watermark is never touched:
|
|
138
147
|
// opted-out sessions keep it advancing via the opt-out flush branch, and
|
|
139
148
|
// overwriting it here would drop a legitimate unshipped backlog.
|
|
140
|
-
// `skill_loaded` needs no init: recording is gated on
|
|
141
|
-
// so opt-out rows never exist and its standard 0 default is safe.
|
|
149
|
+
// `skill_loaded` needs no init: recording is gated on share_analytics
|
|
150
|
+
// consent, so opt-out rows never exist and its standard 0 default is safe.
|
|
142
151
|
//
|
|
143
152
|
// Best-effort: DB init failures are tolerated at daemon startup (degraded
|
|
144
153
|
// mode), so this must never throw out of the constructor — matching
|
|
@@ -162,7 +171,8 @@ export class UsageTelemetryReporter {
|
|
|
162
171
|
// Delay the first flush to allow the credential infrastructure (CES
|
|
163
172
|
// handshake) to complete. Without this delay, VellumPlatformClient.create()
|
|
164
173
|
// returns null because the credential backend hasn't resolved yet, causing
|
|
165
|
-
//
|
|
174
|
+
// the initial flush to be skipped (we send authenticated-only); the
|
|
175
|
+
// delay lets credentials resolve so the first flush can actually ship.
|
|
166
176
|
this.initialFlushTimer = setTimeout(() => {
|
|
167
177
|
this.initialFlushTimer = null;
|
|
168
178
|
this.flush().catch((err) => {
|
|
@@ -205,22 +215,32 @@ export class UsageTelemetryReporter {
|
|
|
205
215
|
try {
|
|
206
216
|
if (batchCount >= MAX_CONSECUTIVE_BATCHES) return;
|
|
207
217
|
|
|
208
|
-
//
|
|
209
|
-
// the
|
|
210
|
-
//
|
|
211
|
-
//
|
|
212
|
-
//
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
218
|
+
// Skip when platform features are disabled (VELLUM_DISABLE_PLATFORM in
|
|
219
|
+
// local mode; the flag is ignored when IS_PLATFORM is set, matching
|
|
220
|
+
// VellumPlatformClient.create()). Watermarks are NOT advanced here: this
|
|
221
|
+
// is a deployment/local-mode toggle, not a privacy opt-out, so the unsent
|
|
222
|
+
// backlog ships once the flag is cleared.
|
|
223
|
+
if (!arePlatformFeaturesEnabled()) {
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Respect opt-out: if the platform owner has not granted
|
|
228
|
+
// `share_analytics` consent, skip the flush and advance watermarks so
|
|
229
|
+
// events recorded during the opt-out window are never sent
|
|
230
|
+
// retroactively. The daemon runs the reporter even when opted out
|
|
231
|
+
// specifically so this branch keeps executing — every cycle plus the
|
|
232
|
+
// final flush in stop() — which is what lets a later opt-in (runtime or
|
|
233
|
+
// via restart) resume from a watermark that already covers the opt-out
|
|
234
|
+
// window. One caveat: a RUNTIME false→true flip can still ship up to one
|
|
235
|
+
// flush interval (≤5 min) of pre-toggle rows recorded since the last
|
|
236
|
+
// opted-out flush;
|
|
217
237
|
// the restart path is fully covered by the final flush in stop(). The
|
|
218
238
|
// caveat applies to the always-on tables without a write-time opt-out
|
|
219
239
|
// gate (llm_usage, turn events) and to tool_invocations rows recorded
|
|
220
240
|
// under builds predating the audit listener's write-time gate — new
|
|
221
241
|
// opted-out tool_invocations rows persist NULL telemetry columns and
|
|
222
242
|
// are unreportable by construction regardless of watermark timing.
|
|
223
|
-
if (!
|
|
243
|
+
if (!getCachedShareAnalytics()) {
|
|
224
244
|
// Advance the timestamp watermarks and pin the ID watermarks to a
|
|
225
245
|
// sentinel that sorts above any real UUID. The sentinel (rather than
|
|
226
246
|
// "") keeps the compound-cursor branch active — a falsy ID would
|
|
@@ -332,9 +352,68 @@ export class UsageTelemetryReporter {
|
|
|
332
352
|
BATCH_SIZE,
|
|
333
353
|
);
|
|
334
354
|
|
|
355
|
+
// Trace completeness barrier (trace-eligible owners only).
|
|
356
|
+
//
|
|
357
|
+
// When trace collection is on, a turn's trace must only be sent once that
|
|
358
|
+
// turn is COMPLETE — otherwise a flush that races an in-progress reply
|
|
359
|
+
// would capture a partial transcript and the watermark would advance past
|
|
360
|
+
// the turn, leaving it permanently partial. So we report only the leading
|
|
361
|
+
// run of complete turns and STOP at the first incomplete (in-flight) one:
|
|
362
|
+
// the turn watermark is a single monotonic `(createdAt, id)` cursor, so a
|
|
363
|
+
// later complete turn cannot be reported past an earlier deferred one
|
|
364
|
+
// without skipping it. The deferred turn (and everything after it) is
|
|
365
|
+
// picked up on a later flush once its response settles.
|
|
366
|
+
//
|
|
367
|
+
// When trace collection is OFF, no turn is deferred and reporting timing
|
|
368
|
+
// is unchanged for everyone else — `turn_raw` behavior is untouched.
|
|
369
|
+
//
|
|
370
|
+
// Trace eligibility is composed daemon-side to mirror the platform's
|
|
371
|
+
// authoritative owner-based ingest gate, so traces for ineligible owners
|
|
372
|
+
// never leave the device. Three parts, fail-closed (all must be true):
|
|
373
|
+
// 1. the `trace-collection` LaunchDarkly flag (delivered via the
|
|
374
|
+
// assistant-tagged flag sync, already evaluated server-side for this
|
|
375
|
+
// assistant's owner),
|
|
376
|
+
// 2. the owner's cached `share_diagnostics` consent, and
|
|
377
|
+
// 3. the owner's cached `share_diagnostics_accepted_version` being at or
|
|
378
|
+
// past the disclosing version — the platform applies the identical
|
|
379
|
+
// check, so an old consent never yields a trace here or there.
|
|
380
|
+
const traceEligible =
|
|
381
|
+
isAssistantFeatureFlagEnabled("trace-collection", getConfig()) &&
|
|
382
|
+
getCachedShareDiagnostics() &&
|
|
383
|
+
isDiagnosticsConsentVersionEligible(getCachedShareDiagnosticsVersion());
|
|
384
|
+
let reportableTurnEvents = turnEvents;
|
|
385
|
+
if (traceEligible && turnEvents.length > 0) {
|
|
386
|
+
let barrier = turnEvents.length;
|
|
387
|
+
for (let i = 0; i < turnEvents.length; i++) {
|
|
388
|
+
const t = turnEvents[i];
|
|
389
|
+
if (
|
|
390
|
+
!isTurnSettled({
|
|
391
|
+
conversationId: t.conversationId,
|
|
392
|
+
userMessageId: t.id,
|
|
393
|
+
userMessageCreatedAt: t.createdAt,
|
|
394
|
+
})
|
|
395
|
+
) {
|
|
396
|
+
barrier = i;
|
|
397
|
+
break;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
if (barrier < turnEvents.length) {
|
|
401
|
+
reportableTurnEvents = turnEvents.slice(0, barrier);
|
|
402
|
+
log.debug(
|
|
403
|
+
{
|
|
404
|
+
deferredTurnId: turnEvents[barrier].id,
|
|
405
|
+
deferredConversationId: turnEvents[barrier].conversationId,
|
|
406
|
+
reportedTurns: barrier,
|
|
407
|
+
deferredTurns: turnEvents.length - barrier,
|
|
408
|
+
},
|
|
409
|
+
"Deferring in-progress turn(s) from telemetry until complete",
|
|
410
|
+
);
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
|
|
335
414
|
if (
|
|
336
415
|
events.length === 0 &&
|
|
337
|
-
|
|
416
|
+
reportableTurnEvents.length === 0 &&
|
|
338
417
|
lifecycleEvents.length === 0 &&
|
|
339
418
|
onboardingEvents.length === 0 &&
|
|
340
419
|
authFallbackEvents.length === 0 &&
|
|
@@ -343,14 +422,21 @@ export class UsageTelemetryReporter {
|
|
|
343
422
|
)
|
|
344
423
|
return;
|
|
345
424
|
|
|
346
|
-
// Resolve auth context
|
|
347
|
-
//
|
|
425
|
+
// Resolve auth context. We send authenticated-only: if no platform
|
|
426
|
+
// credentials are available yet, skip without advancing watermarks so the
|
|
427
|
+
// backlog ships on a later cycle once credentials resolve.
|
|
348
428
|
const client = await VellumPlatformClient.create();
|
|
429
|
+
if (!client) {
|
|
430
|
+
log.debug(
|
|
431
|
+
{ pendingEventCount: events.length + turnEvents.length },
|
|
432
|
+
"Telemetry flush: no platform credentials — skipping, will retry next cycle",
|
|
433
|
+
);
|
|
434
|
+
return;
|
|
435
|
+
}
|
|
349
436
|
log.debug(
|
|
350
437
|
{
|
|
351
|
-
authenticated: !!client,
|
|
352
438
|
usageCount: events.length,
|
|
353
|
-
turnCount:
|
|
439
|
+
turnCount: reportableTurnEvents.length,
|
|
354
440
|
lifecycleCount: lifecycleEvents.length,
|
|
355
441
|
onboardingCount: onboardingEvents.length,
|
|
356
442
|
authFallbackCount: authFallbackEvents.length,
|
|
@@ -396,7 +482,23 @@ export class UsageTelemetryReporter {
|
|
|
396
482
|
assistant_version: e.assistantVersion ?? APP_VERSION,
|
|
397
483
|
}),
|
|
398
484
|
),
|
|
399
|
-
...
|
|
485
|
+
...reportableTurnEvents.map((e): TelemetryEvent => {
|
|
486
|
+
// Per-turn trace collection gate. `traceEligible` (computed above)
|
|
487
|
+
// requires the `trace-collection` flag AND the owner's cached
|
|
488
|
+
// `share_diagnostics` consent AND an eligible accepted consent
|
|
489
|
+
// version. Fail-closed: when any is off the trace is omitted and the
|
|
490
|
+
// trace-free turn row flushes as before. The
|
|
491
|
+
// `share_analytics` gate above already passed, so this is an
|
|
492
|
+
// additional, independent gate specific to trace PII. Every turn
|
|
493
|
+
// reaching here is settled (the completeness barrier dropped any
|
|
494
|
+
// in-flight turns), so the trace is never a partial mid-turn snapshot.
|
|
495
|
+
const trace = traceEligible
|
|
496
|
+
? assembleBoundedTurnTrace({
|
|
497
|
+
conversationId: e.conversationId,
|
|
498
|
+
userMessageId: e.id,
|
|
499
|
+
userMessageCreatedAt: e.createdAt,
|
|
500
|
+
})
|
|
501
|
+
: null;
|
|
400
502
|
// `messages.metadata.client` is a nested JSON object extracted
|
|
401
503
|
// via `json_extract`; sqlite returns it as a text representation.
|
|
402
504
|
// Parse defensively — a corrupted blob in the JSON column should
|
|
@@ -431,6 +533,11 @@ export class UsageTelemetryReporter {
|
|
|
431
533
|
interface_id: e.interfaceId,
|
|
432
534
|
channel_id: e.channelId,
|
|
433
535
|
client,
|
|
536
|
+
// Only attach `trace` when consent is on AND a bounded trace was
|
|
537
|
+
// assembled. Omitting the key entirely when there's no trace keeps
|
|
538
|
+
// the wire shape byte-identical to pre-trace turn events for the
|
|
539
|
+
// common (no-consent) path.
|
|
540
|
+
...(trace ? { trace } : {}),
|
|
434
541
|
// Turn events derive from `messages` + `conversations`
|
|
435
542
|
// rather than a dedicated table. Adding `assistant_version`
|
|
436
543
|
// to `messages` is a separate (larger) migration; until
|
|
@@ -588,18 +695,12 @@ export class UsageTelemetryReporter {
|
|
|
588
695
|
body: JSON.stringify(payload),
|
|
589
696
|
};
|
|
590
697
|
|
|
591
|
-
|
|
592
|
-
if (client) {
|
|
593
|
-
resp = await client.fetch(TELEMETRY_PATH, fetchInit);
|
|
594
|
-
} else {
|
|
595
|
-
const url = `${getPlatformBaseUrl()}${TELEMETRY_PATH}`;
|
|
596
|
-
resp = await fetch(url, fetchInit);
|
|
597
|
-
}
|
|
698
|
+
const resp = await client.fetch(TELEMETRY_PATH, fetchInit);
|
|
598
699
|
|
|
599
700
|
if (!resp.ok) {
|
|
600
701
|
const body = await resp.text();
|
|
601
702
|
log.warn(
|
|
602
|
-
{ status: resp.status,
|
|
703
|
+
{ status: resp.status, body },
|
|
603
704
|
"Usage telemetry POST failed — will retry next cycle",
|
|
604
705
|
);
|
|
605
706
|
return;
|
|
@@ -616,9 +717,11 @@ export class UsageTelemetryReporter {
|
|
|
616
717
|
setMemoryCheckpoint(CHECKPOINT_KEY_WATERMARK_ID, lastEvent.id);
|
|
617
718
|
}
|
|
618
719
|
|
|
619
|
-
// Advance turn watermark (compound cursor)
|
|
620
|
-
|
|
621
|
-
|
|
720
|
+
// Advance turn watermark (compound cursor) — only to the last REPORTED
|
|
721
|
+
// turn. Deferred (in-flight) turns sit beyond this cursor and are
|
|
722
|
+
// re-evaluated on a later flush, so the watermark never skips them.
|
|
723
|
+
if (reportableTurnEvents.length > 0) {
|
|
724
|
+
const lastTurn = reportableTurnEvents[reportableTurnEvents.length - 1];
|
|
622
725
|
setMemoryCheckpoint(
|
|
623
726
|
CHECKPOINT_KEY_TURN_WATERMARK,
|
|
624
727
|
String(lastTurn.createdAt),
|
|
@@ -693,10 +796,14 @@ export class UsageTelemetryReporter {
|
|
|
693
796
|
);
|
|
694
797
|
}
|
|
695
798
|
|
|
696
|
-
// If we got a full batch of any type, there may be more — recurse
|
|
799
|
+
// If we got a full batch of any type, there may be more — recurse.
|
|
800
|
+
// Turns use the REPORTED count: when the completeness barrier truncates
|
|
801
|
+
// the batch, the deferred turns must wait for a later flush (by which
|
|
802
|
+
// point they've settled) rather than being re-queried and re-deferred in
|
|
803
|
+
// a tight recursion.
|
|
697
804
|
if (
|
|
698
805
|
events.length === BATCH_SIZE ||
|
|
699
|
-
|
|
806
|
+
reportableTurnEvents.length === BATCH_SIZE ||
|
|
700
807
|
lifecycleEvents.length === BATCH_SIZE ||
|
|
701
808
|
onboardingEvents.length === BATCH_SIZE ||
|
|
702
809
|
authFallbackEvents.length === BATCH_SIZE ||
|
package/src/tools/AGENTS.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## New Non-Skill Tools Are Strongly Discouraged
|
|
4
4
|
|
|
5
|
-
**Prefer skills over new non-skill tool registrations.** Non-skill tools require approval from
|
|
5
|
+
**Prefer skills over new non-skill tool registrations.** Non-skill tools require approval from the core team.
|
|
6
6
|
|
|
7
7
|
Skills are the preferred approach for adding new capabilities — they are progressively disclosed into context, more portable, and can be iterated on independently. New non-skill tool registrations (`class ... implements Tool` + `registerTool()`) carry additional costs:
|
|
8
8
|
|
|
@@ -48,7 +48,7 @@ See [`assistant/docs/credential-execution-service.md`](../../docs/credential-exe
|
|
|
48
48
|
|
|
49
49
|
## If You Have Approval
|
|
50
50
|
|
|
51
|
-
If
|
|
51
|
+
If the core team has approved your new tool:
|
|
52
52
|
|
|
53
53
|
1. The pre-commit hook will block your commit by default
|
|
54
54
|
2. Use `git commit --no-verify` to bypass the hook
|
|
@@ -56,4 +56,4 @@ If Team Jarvis has approved your new tool:
|
|
|
56
56
|
|
|
57
57
|
## Questions?
|
|
58
58
|
|
|
59
|
-
Contact
|
|
59
|
+
Contact the core team before shipping a new tool.
|
|
@@ -54,6 +54,9 @@ const setPreferredBackendKindMock = mock(
|
|
|
54
54
|
(_conversationId: string, _kind: CdpClientKind) => {},
|
|
55
55
|
);
|
|
56
56
|
const clearPreferredBackendKindMock = mock((_conversationId: string) => {});
|
|
57
|
+
const waitForExtensionClientMock = mock(
|
|
58
|
+
async (_actor?: string, _targetClientId?: string) => true,
|
|
59
|
+
);
|
|
57
60
|
|
|
58
61
|
// ---------------------------------------------------------------------------
|
|
59
62
|
// Module mocks (must be declared before dynamic import)
|
|
@@ -98,6 +101,7 @@ mock.module("../../../daemon/host-browser-proxy.js", () => ({
|
|
|
98
101
|
return {
|
|
99
102
|
isAvailable: () => false,
|
|
100
103
|
hasExtensionClient: () => false,
|
|
104
|
+
waitForExtensionClient: waitForExtensionClientMock,
|
|
101
105
|
request: () => Promise.reject(new Error("no extension")),
|
|
102
106
|
};
|
|
103
107
|
},
|
|
@@ -141,9 +145,36 @@ describe("acquireCdpClientWithMode: target_client_id overrides sticky backend mo
|
|
|
141
145
|
getCdpClientMock.mockClear();
|
|
142
146
|
setPreferredBackendKindMock.mockClear();
|
|
143
147
|
clearPreferredBackendKindMock.mockClear();
|
|
148
|
+
waitForExtensionClientMock.mockClear();
|
|
144
149
|
stickyKind = null;
|
|
145
150
|
});
|
|
146
151
|
|
|
152
|
+
test("extension-pinned acquisition awaits the reconnect grace window", async () => {
|
|
153
|
+
await executeBrowserAttach(
|
|
154
|
+
{ target_client_id: "host-client-grace" },
|
|
155
|
+
makeContext("grace-window"),
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
// The grace wait runs before backend selection so a flapping extension
|
|
159
|
+
// SSE reconnect doesn't hard-fail the dispatch, and it targets the exact
|
|
160
|
+
// requested client.
|
|
161
|
+
expect(waitForExtensionClientMock).toHaveBeenCalledTimes(1);
|
|
162
|
+
expect(waitForExtensionClientMock).toHaveBeenCalledWith(
|
|
163
|
+
undefined,
|
|
164
|
+
"host-client-grace",
|
|
165
|
+
);
|
|
166
|
+
expect(getCdpClientCalls[0].mode).toBe("extension");
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
test("non-extension (sticky local, no target) does not wait on the extension", async () => {
|
|
170
|
+
stickyKind = "local";
|
|
171
|
+
|
|
172
|
+
await executeBrowserAttach({}, makeContext("no-grace-for-local"));
|
|
173
|
+
|
|
174
|
+
expect(waitForExtensionClientMock).not.toHaveBeenCalled();
|
|
175
|
+
expect(getCdpClientCalls[0].mode).toBe("local");
|
|
176
|
+
});
|
|
177
|
+
|
|
147
178
|
test("sticky local + target_client_id → getCdpClient receives mode:extension, not local", async () => {
|
|
148
179
|
// Simulate a prior turn that pinned the conversation to the local backend.
|
|
149
180
|
stickyKind = "local";
|
|
@@ -375,16 +375,17 @@ function isRestrictedChromePageProbeError(error: CdpError): boolean {
|
|
|
375
375
|
* The returned client is wrapped so its first successful `send()`
|
|
376
376
|
* writes the resolved kind back to the conversation memo.
|
|
377
377
|
*/
|
|
378
|
-
function acquireCdpClientWithMode(
|
|
378
|
+
async function acquireCdpClientWithMode(
|
|
379
379
|
input: Record<string, unknown>,
|
|
380
380
|
context: ToolContext,
|
|
381
|
-
):
|
|
381
|
+
): Promise<
|
|
382
382
|
| {
|
|
383
383
|
cdp: ReturnType<typeof getCdpClient>;
|
|
384
384
|
browserMode: BrowserMode;
|
|
385
385
|
errorResult?: never;
|
|
386
386
|
}
|
|
387
|
-
| { cdp?: never; browserMode?: never; errorResult: ToolExecutionResult }
|
|
387
|
+
| { cdp?: never; browserMode?: never; errorResult: ToolExecutionResult }
|
|
388
|
+
> {
|
|
388
389
|
const modeResult = parseBrowserMode(input);
|
|
389
390
|
if (!modeResult.ok) {
|
|
390
391
|
return {
|
|
@@ -412,6 +413,16 @@ function acquireCdpClientWithMode(
|
|
|
412
413
|
? rememberedKind
|
|
413
414
|
: browserMode;
|
|
414
415
|
|
|
416
|
+
// Extension-pinned dispatch (explicit `--browser-mode extension` or a
|
|
417
|
+
// `target_client_id`) hard-fails when the extension is momentarily
|
|
418
|
+
// absent. Absorb a brief reconnect blip before selecting the backend.
|
|
419
|
+
if (effectiveMode === "extension") {
|
|
420
|
+
await HostBrowserProxy.instance.waitForExtensionClient(
|
|
421
|
+
context.sourceActorPrincipalId,
|
|
422
|
+
targetClientId,
|
|
423
|
+
);
|
|
424
|
+
}
|
|
425
|
+
|
|
415
426
|
try {
|
|
416
427
|
const raw = getCdpClient(context, { mode: effectiveMode, targetClientId });
|
|
417
428
|
const cdp = wrapWithKindMemo(raw, context.conversationId);
|
|
@@ -655,7 +666,7 @@ export async function executeBrowserNavigate(
|
|
|
655
666
|
}
|
|
656
667
|
|
|
657
668
|
// URL validation passed — acquire the CDP client.
|
|
658
|
-
const acquired = acquireCdpClientWithMode(input, context);
|
|
669
|
+
const acquired = await acquireCdpClientWithMode(input, context);
|
|
659
670
|
if (acquired.errorResult) return acquired.errorResult;
|
|
660
671
|
const { cdp, browserMode } = acquired;
|
|
661
672
|
|
|
@@ -1093,7 +1104,7 @@ export async function executeBrowserNavigate(
|
|
|
1093
1104
|
}
|
|
1094
1105
|
} else {
|
|
1095
1106
|
// Login / 2FA / OAuth - the agent should handle these itself
|
|
1096
|
-
// using browser operations +
|
|
1107
|
+
// using browser operations + stored credentials. Don't hand off.
|
|
1097
1108
|
lines.push("");
|
|
1098
1109
|
lines.push(formatAuthChallenge(challenge));
|
|
1099
1110
|
lines.push("");
|
|
@@ -1157,7 +1168,7 @@ export async function executeBrowserSnapshot(
|
|
|
1157
1168
|
_input: Record<string, unknown>,
|
|
1158
1169
|
context: ToolContext,
|
|
1159
1170
|
): Promise<ToolExecutionResult> {
|
|
1160
|
-
const acquired = acquireCdpClientWithMode(_input, context);
|
|
1171
|
+
const acquired = await acquireCdpClientWithMode(_input, context);
|
|
1161
1172
|
if (acquired.errorResult) return acquired.errorResult;
|
|
1162
1173
|
const { cdp, browserMode } = acquired;
|
|
1163
1174
|
|
|
@@ -1209,7 +1220,7 @@ export async function executeBrowserScreenshot(
|
|
|
1209
1220
|
input: Record<string, unknown>,
|
|
1210
1221
|
context: ToolContext,
|
|
1211
1222
|
): Promise<ToolExecutionResult> {
|
|
1212
|
-
const acquired = acquireCdpClientWithMode(input, context);
|
|
1223
|
+
const acquired = await acquireCdpClientWithMode(input, context);
|
|
1213
1224
|
if (acquired.errorResult) return acquired.errorResult;
|
|
1214
1225
|
const { cdp, browserMode } = acquired;
|
|
1215
1226
|
const fullPage = input.full_page === true;
|
|
@@ -1266,7 +1277,7 @@ export async function executeBrowserAttach(
|
|
|
1266
1277
|
_input: Record<string, unknown>,
|
|
1267
1278
|
context: ToolContext,
|
|
1268
1279
|
): Promise<ToolExecutionResult> {
|
|
1269
|
-
const acquired = acquireCdpClientWithMode(_input, context);
|
|
1280
|
+
const acquired = await acquireCdpClientWithMode(_input, context);
|
|
1270
1281
|
if (acquired.errorResult) return acquired.errorResult;
|
|
1271
1282
|
const cdp = acquired.cdp;
|
|
1272
1283
|
try {
|
|
@@ -1319,7 +1330,7 @@ export async function executeBrowserDetach(
|
|
|
1319
1330
|
_input: Record<string, unknown>,
|
|
1320
1331
|
context: ToolContext,
|
|
1321
1332
|
): Promise<ToolExecutionResult> {
|
|
1322
|
-
const acquired = acquireCdpClientWithMode(_input, context);
|
|
1333
|
+
const acquired = await acquireCdpClientWithMode(_input, context);
|
|
1323
1334
|
if (acquired.errorResult) return acquired.errorResult;
|
|
1324
1335
|
const cdp = acquired.cdp;
|
|
1325
1336
|
try {
|
|
@@ -1369,7 +1380,7 @@ export async function executeBrowserClose(
|
|
|
1369
1380
|
input: Record<string, unknown>,
|
|
1370
1381
|
context: ToolContext,
|
|
1371
1382
|
): Promise<ToolExecutionResult> {
|
|
1372
|
-
const acquired = acquireCdpClientWithMode(input, context);
|
|
1383
|
+
const acquired = await acquireCdpClientWithMode(input, context);
|
|
1373
1384
|
if (acquired.errorResult) return acquired.errorResult;
|
|
1374
1385
|
const cdp = acquired.cdp;
|
|
1375
1386
|
try {
|
|
@@ -1440,7 +1451,7 @@ export async function executeBrowserClick(
|
|
|
1440
1451
|
const { resolved, error } = resolveElement(context.conversationId, input);
|
|
1441
1452
|
if (error) return { content: error, isError: true };
|
|
1442
1453
|
|
|
1443
|
-
const acquired = acquireCdpClientWithMode(input, context);
|
|
1454
|
+
const acquired = await acquireCdpClientWithMode(input, context);
|
|
1444
1455
|
if (acquired.errorResult) return acquired.errorResult;
|
|
1445
1456
|
const cdp = acquired.cdp;
|
|
1446
1457
|
try {
|
|
@@ -1561,7 +1572,7 @@ export async function executeBrowserType(
|
|
|
1561
1572
|
? `element_id "${resolved!.eid}"`
|
|
1562
1573
|
: resolved!.selector;
|
|
1563
1574
|
|
|
1564
|
-
const acquired = acquireCdpClientWithMode(input, context);
|
|
1575
|
+
const acquired = await acquireCdpClientWithMode(input, context);
|
|
1565
1576
|
if (acquired.errorResult) return acquired.errorResult;
|
|
1566
1577
|
const cdp = acquired.cdp;
|
|
1567
1578
|
try {
|
|
@@ -1638,7 +1649,7 @@ export async function executeBrowserPressKey(
|
|
|
1638
1649
|
: resolved!.selector;
|
|
1639
1650
|
}
|
|
1640
1651
|
|
|
1641
|
-
const acquired = acquireCdpClientWithMode(input, context);
|
|
1652
|
+
const acquired = await acquireCdpClientWithMode(input, context);
|
|
1642
1653
|
if (acquired.errorResult) return acquired.errorResult;
|
|
1643
1654
|
const cdp = acquired.cdp;
|
|
1644
1655
|
try {
|
|
@@ -1715,7 +1726,7 @@ export async function executeBrowserScroll(
|
|
|
1715
1726
|
break;
|
|
1716
1727
|
}
|
|
1717
1728
|
|
|
1718
|
-
const acquired = acquireCdpClientWithMode(input, context);
|
|
1729
|
+
const acquired = await acquireCdpClientWithMode(input, context);
|
|
1719
1730
|
if (acquired.errorResult) return acquired.errorResult;
|
|
1720
1731
|
const cdp = acquired.cdp;
|
|
1721
1732
|
try {
|
|
@@ -1778,7 +1789,7 @@ export async function executeBrowserSelectOption(
|
|
|
1778
1789
|
? `element_id "${resolved!.eid}"`
|
|
1779
1790
|
: resolved!.selector;
|
|
1780
1791
|
|
|
1781
|
-
const acquired = acquireCdpClientWithMode(input, context);
|
|
1792
|
+
const acquired = await acquireCdpClientWithMode(input, context);
|
|
1782
1793
|
if (acquired.errorResult) return acquired.errorResult;
|
|
1783
1794
|
const cdp = acquired.cdp;
|
|
1784
1795
|
try {
|
|
@@ -1894,7 +1905,7 @@ export async function executeBrowserHover(
|
|
|
1894
1905
|
const { resolved, error } = resolveElement(context.conversationId, input);
|
|
1895
1906
|
if (error) return { content: error, isError: true };
|
|
1896
1907
|
|
|
1897
|
-
const acquired = acquireCdpClientWithMode(input, context);
|
|
1908
|
+
const acquired = await acquireCdpClientWithMode(input, context);
|
|
1898
1909
|
if (acquired.errorResult) return acquired.errorResult;
|
|
1899
1910
|
const cdp = acquired.cdp;
|
|
1900
1911
|
try {
|
|
@@ -1988,7 +1999,7 @@ export async function executeBrowserWaitFor(
|
|
|
1988
1999
|
return { content: `Waited ${waitMs}ms.`, isError: false };
|
|
1989
2000
|
}
|
|
1990
2001
|
|
|
1991
|
-
const acquired = acquireCdpClientWithMode(input, context);
|
|
2002
|
+
const acquired = await acquireCdpClientWithMode(input, context);
|
|
1992
2003
|
if (acquired.errorResult) return acquired.errorResult;
|
|
1993
2004
|
const cdp = acquired.cdp;
|
|
1994
2005
|
try {
|
|
@@ -2037,7 +2048,7 @@ export async function executeBrowserExtract(
|
|
|
2037
2048
|
): Promise<ToolExecutionResult> {
|
|
2038
2049
|
const includeLinks = input.include_links === true;
|
|
2039
2050
|
|
|
2040
|
-
const acquired = acquireCdpClientWithMode(input, context);
|
|
2051
|
+
const acquired = await acquireCdpClientWithMode(input, context);
|
|
2041
2052
|
if (acquired.errorResult) return acquired.errorResult;
|
|
2042
2053
|
const cdp = acquired.cdp;
|
|
2043
2054
|
try {
|
|
@@ -2120,7 +2131,7 @@ export async function executeBrowserFillCredential(
|
|
|
2120
2131
|
? `element_id "${resolved!.eid}"`
|
|
2121
2132
|
: resolved!.selector;
|
|
2122
2133
|
|
|
2123
|
-
const acquired = acquireCdpClientWithMode(input, context);
|
|
2134
|
+
const acquired = await acquireCdpClientWithMode(input, context);
|
|
2124
2135
|
if (acquired.errorResult) return acquired.errorResult;
|
|
2125
2136
|
const cdp = acquired.cdp;
|
|
2126
2137
|
try {
|
|
@@ -13,12 +13,11 @@ import {
|
|
|
13
13
|
searchDocumentsByTitle,
|
|
14
14
|
updateDocumentContent,
|
|
15
15
|
} from "../../documents/document-store.js";
|
|
16
|
+
import { canActOnPrivilegedDocuments } from "../../runtime/effective-capabilities.js";
|
|
16
17
|
import type { ToolContext, ToolExecutionResult } from "../types.js";
|
|
17
18
|
|
|
18
19
|
function isPrivilegedDocumentActor(context: ToolContext): boolean {
|
|
19
|
-
return (
|
|
20
|
-
context.trustClass === "guardian" || context.executionChannel === "vellum"
|
|
21
|
-
);
|
|
20
|
+
return canActOnPrivilegedDocuments(context);
|
|
22
21
|
}
|
|
23
22
|
|
|
24
23
|
export function documentNotFound(surfaceId: string): ToolExecutionResult {
|
package/src/tools/executor.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { bridgeCesApproval } from "../credential-execution/approval-bridge.js";
|
|
|
5
5
|
import { isCesShellLockdownEnabled } from "../credential-execution/feature-gates.js";
|
|
6
6
|
import { PermissionPrompter } from "../permissions/prompter.js";
|
|
7
7
|
import { RiskLevel } from "../permissions/types.js";
|
|
8
|
-
import {
|
|
8
|
+
import { isUntrustedShellLockdownActive } from "../runtime/effective-capabilities.js";
|
|
9
9
|
import { redactSensitiveFields } from "../security/redaction.js";
|
|
10
10
|
import { getCesClient } from "../security/secure-keys.js";
|
|
11
11
|
import { TokenExpiredError } from "../security/token-manager.js";
|
|
@@ -128,8 +128,10 @@ export class ToolExecutor {
|
|
|
128
128
|
// skip this assignment entirely - defeating the lockdown.
|
|
129
129
|
if (
|
|
130
130
|
name === "host_bash" &&
|
|
131
|
-
|
|
132
|
-
|
|
131
|
+
isUntrustedShellLockdownActive({
|
|
132
|
+
trustClass: context.trustClass,
|
|
133
|
+
lockdownEnabled: isCesShellLockdownEnabled(getConfig()),
|
|
134
|
+
})
|
|
133
135
|
) {
|
|
134
136
|
context.forcePromptSideEffects = true;
|
|
135
137
|
}
|
|
@@ -23,9 +23,9 @@ import { getConfig } from "../../config/loader.js";
|
|
|
23
23
|
import { isCesShellLockdownEnabled } from "../../credential-execution/feature-gates.js";
|
|
24
24
|
import { HostBashProxy } from "../../daemon/host-bash-proxy.js";
|
|
25
25
|
import { RiskLevel } from "../../permissions/types.js";
|
|
26
|
-
import { isUntrustedTrustClass } from "../../runtime/actor-trust-resolver.js";
|
|
27
26
|
import { wakeAgentForOpportunity } from "../../runtime/agent-wake.js";
|
|
28
27
|
import { assistantEventHub } from "../../runtime/assistant-event-hub.js";
|
|
28
|
+
import { isUntrustedShellLockdownActive } from "../../runtime/effective-capabilities.js";
|
|
29
29
|
import { redactSecrets } from "../../security/secret-scanner.js";
|
|
30
30
|
import { getLogger } from "../../util/logger.js";
|
|
31
31
|
import {
|
|
@@ -204,9 +204,10 @@ export const hostShellTool = {
|
|
|
204
204
|
// NOTE: forcePromptSideEffects is set in executor.ts BEFORE the
|
|
205
205
|
// permission check runs, not here. Setting it here would be too late
|
|
206
206
|
// because execute() is called after permissions have already been evaluated.
|
|
207
|
-
const hostLockdownActive =
|
|
208
|
-
|
|
209
|
-
|
|
207
|
+
const hostLockdownActive = isUntrustedShellLockdownActive({
|
|
208
|
+
trustClass: context.trustClass,
|
|
209
|
+
lockdownEnabled: isCesShellLockdownEnabled(config),
|
|
210
|
+
});
|
|
210
211
|
|
|
211
212
|
// Guard: non-host-proxy interfaces need an explicit target when multiple
|
|
212
213
|
// capable clients are connected to avoid ambiguous untargeted broadcasts.
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
graphRememberDefinition,
|
|
11
11
|
} from "../../memory/graph/tools.js";
|
|
12
12
|
import { RiskLevel } from "../../permissions/types.js";
|
|
13
|
-
import {
|
|
13
|
+
import { resolveCapabilities } from "../../runtime/capabilities.js";
|
|
14
14
|
import type {
|
|
15
15
|
ToolContext,
|
|
16
16
|
ToolDefinition,
|
|
@@ -60,7 +60,7 @@ export const recallTool = {
|
|
|
60
60
|
input: Record<string, unknown>,
|
|
61
61
|
context: ToolContext,
|
|
62
62
|
): Promise<ToolExecutionResult> {
|
|
63
|
-
if (
|
|
63
|
+
if (!resolveCapabilities(context.trustClass).canAccessMemory) {
|
|
64
64
|
return {
|
|
65
65
|
content:
|
|
66
66
|
"Recall is only available to the guardian because it can read sensitive local context.",
|