@vellumai/assistant 0.10.9 → 0.10.10-dev.202607162206.d08e98e
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 +1 -1
- package/Dockerfile +8 -0
- package/docs/activation-funnel-telemetry.md +13 -7
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/__tests__/redacted-credential.test.ts +200 -0
- package/node_modules/@vellumai/ces-client/node_modules/@vellumai/service-contracts/src/redacted-credential.ts +226 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/__tests__/redacted-credential.test.ts +200 -0
- package/node_modules/@vellumai/gateway-client/node_modules/@vellumai/service-contracts/src/redacted-credential.ts +226 -0
- package/node_modules/@vellumai/service-contracts/package.json +1 -0
- package/node_modules/@vellumai/service-contracts/src/__tests__/redacted-credential.test.ts +200 -0
- package/node_modules/@vellumai/service-contracts/src/redacted-credential.ts +226 -0
- package/openapi.yaml +530 -107
- package/package.json +1 -1
- package/scripts/generate-openapi.ts +8 -0
- package/src/__tests__/activation-early-marking.test.ts +6 -5
- package/src/__tests__/agent-loop-override-profile.test.ts +22 -25
- package/src/__tests__/agent-wake-override-profile.test.ts +21 -48
- package/src/__tests__/app-builder-tool-scripts.test.ts +0 -1
- package/src/__tests__/app-bundler.test.ts +4 -12
- package/src/__tests__/app-executors.test.ts +2 -49
- package/src/__tests__/app-routes-csp.test.ts +114 -146
- package/src/__tests__/auth-fallback-events-store.test.ts +8 -1
- package/src/__tests__/build-persisted-content.test.ts +96 -0
- package/src/__tests__/bundle-scanner.test.ts +27 -1
- package/src/__tests__/call-controller.test.ts +291 -0
- package/src/__tests__/call-site-routing-connection-auto-resolve.test.ts +165 -0
- package/src/__tests__/chat-credential-redaction.test.ts +1395 -0
- package/src/__tests__/chat-reveal-guard-priming.test.ts +791 -0
- package/src/__tests__/compaction.benchmark.test.ts +2 -1
- package/src/__tests__/compactor-image-manifest-trust.test.ts +50 -0
- package/src/__tests__/config-loader-backfill.test.ts +9 -4
- package/src/__tests__/config-schema-cmd.test.ts +10 -11
- package/src/__tests__/config-schema.test.ts +190 -257
- package/src/__tests__/conversation-agent-loop-fatal-cleanup.test.ts +208 -0
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +5 -19
- package/src/__tests__/conversation-agent-loop.test.ts +22 -9
- package/src/__tests__/conversation-error.test.ts +31 -0
- package/src/__tests__/conversation-load-history-repair.test.ts +110 -0
- package/src/__tests__/conversation-process-callsite.test.ts +12 -19
- package/src/__tests__/conversation-routes-slash-commands.test.ts +7 -21
- package/src/__tests__/conversation-summarize-route.test.ts +36 -44
- package/src/__tests__/conversation-surfaces-action-delivery.test.ts +1 -0
- package/src/__tests__/conversation-surfaces-activation-emit.test.ts +7 -7
- package/src/__tests__/conversation-tool-setup-app-refresh.test.ts +0 -1
- package/src/__tests__/conversation-tool-setup-attribution.test.ts +0 -1
- package/src/__tests__/conversation-usage.test.ts +4 -12
- package/src/__tests__/credential-routes.test.ts +250 -0
- package/src/__tests__/credential-security-invariants.test.ts +3 -0
- package/src/__tests__/db-migration-rollback.test.ts +22 -0
- package/src/__tests__/empty-response-hook.test.ts +186 -1
- package/src/__tests__/external-plugin-loader.test.ts +11 -5
- package/src/__tests__/heartbeat-service.test.ts +0 -28
- package/src/__tests__/host-shell-tool.test.ts +2 -0
- package/src/__tests__/inactive-tool-error-messages.test.ts +2 -2
- package/src/__tests__/inference-no-mode-boot-e2e.test.ts +52 -8
- package/src/__tests__/internal-telemetry-routes.test.ts +23 -4
- package/src/__tests__/invite-routes-http.test.ts +12 -16
- package/src/__tests__/list-all-apps.test.ts +0 -4
- package/src/__tests__/llm-context-resolution.test.ts +32 -56
- package/src/__tests__/llm-request-log-turn-query.test.ts +109 -0
- package/src/__tests__/llm-resolver-override-or-default.test.ts +3 -52
- package/src/__tests__/llm-resolver.test.ts +342 -602
- package/src/__tests__/llm-schema.test.ts +79 -37
- package/src/__tests__/max-tokens-continue-hook.test.ts +19 -0
- package/src/__tests__/media-stream-output.test.ts +259 -3
- package/src/__tests__/media-stream-server-integration.test.ts +22 -1
- package/src/__tests__/media-stream-stt-session.test.ts +47 -0
- package/src/__tests__/memory-jobs-worker-cleanup-cadence.test.ts +33 -0
- package/src/__tests__/memory-recall-log-store.test.ts +47 -13
- package/src/__tests__/mock-gateway-ipc.ts +46 -1
- package/src/__tests__/mtime-cache.test.ts +61 -0
- package/src/__tests__/navigate-settings-tab.test.ts +2 -0
- package/src/__tests__/normalize-onboarding.test.ts +33 -0
- package/src/__tests__/onboarding-persona-write.test.ts +26 -0
- package/src/__tests__/plugin-api-resolve-credential.test.ts +140 -0
- package/src/__tests__/plugin-app-serve-routes.test.ts +166 -14
- package/src/__tests__/plugin-import-boundary-reverse-guard.test.ts +2 -0
- package/src/__tests__/post-turn-tool-result-truncation.test.ts +38 -0
- package/src/__tests__/provider-commit-message-generator.test.ts +27 -20
- package/src/__tests__/provider-connections-backfill.test.ts +138 -0
- package/src/__tests__/provider-platform-proxy-integration.test.ts +10 -31
- package/src/__tests__/provider-registry-ollama.test.ts +8 -18
- package/src/__tests__/provider-send-message-override-profile.test.ts +23 -23
- package/src/__tests__/provider-usage-tracking.test.ts +9 -19
- package/src/__tests__/prune-old-conversations-job.test.ts +12 -0
- package/src/__tests__/published-app-updater.test.ts +22 -16
- package/src/__tests__/registry.test.ts +5 -16
- package/src/__tests__/retry-openrouter-only-normalization.test.ts +22 -23
- package/src/__tests__/retry-thinking-adaptive-only.test.ts +43 -48
- package/src/__tests__/retry-thinking-tool-choice.test.ts +57 -66
- package/src/__tests__/retry-verbosity-normalization.test.ts +24 -23
- package/src/__tests__/reveal-success-registry.test.ts +123 -0
- package/src/__tests__/run-conversation-turn-persistence.test.ts +130 -0
- package/src/__tests__/secret-fixtures.ts +9 -0
- package/src/__tests__/server-history-render.test.ts +28 -0
- package/src/__tests__/skills.test.ts +9 -4
- package/src/__tests__/slack-share-routes.test.ts +0 -1
- package/src/__tests__/stt-stream-session.test.ts +6 -5
- package/src/__tests__/subagent-call-site-routing.test.ts +69 -95
- package/src/__tests__/subagent-disposal.test.ts +2 -0
- package/src/__tests__/subagent-fork-notifications.test.ts +2 -0
- package/src/__tests__/subagent-fork-spawn.test.ts +2 -0
- package/src/__tests__/subagent-manager-notify.test.ts +2 -0
- package/src/__tests__/subagent-role-registry.test.ts +37 -0
- package/src/__tests__/subagent-spawn-and-await.test.ts +1 -0
- package/src/__tests__/subagent-terminal-message.test.ts +50 -0
- package/src/__tests__/subagent-tool-gate-mode.test.ts +78 -5
- package/src/__tests__/surface-completion-nudge-hook.test.ts +19 -0
- package/src/__tests__/telemetry-routes.test.ts +99 -19
- package/src/__tests__/tool-audit.test.ts +34 -4
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +1 -1
- package/src/__tests__/tool-profiler.test.ts +72 -1
- package/src/__tests__/tool-result-spool.test.ts +49 -4
- package/src/__tests__/tool-side-effects-slack-dm.test.ts +0 -1
- package/src/__tests__/ui-channel-variants.test.ts +108 -0
- package/src/__tests__/ui-shape-teaching.test.ts +255 -0
- package/src/__tests__/usage-attribution.test.ts +18 -41
- package/src/__tests__/user-plugin-loader.test.ts +4 -4
- package/src/__tests__/voice-config-update.test.ts +46 -0
- package/src/__tests__/voice-session-bridge.test.ts +216 -84
- package/src/__tests__/workspace-migration-131-drop-web-fetch-mode.test.ts +120 -0
- package/src/agent/loop.ts +4 -3
- package/src/api/events/open-conversation.test.ts +64 -0
- package/src/api/events/open-conversation.ts +33 -0
- package/src/api/index.ts +6 -0
- package/src/api/responses/conversation-message.ts +5 -0
- package/src/apps/app-store.ts +25 -35
- package/src/bundler/app-bundler.ts +34 -48
- package/src/bundler/app-compiler.ts +39 -4
- package/src/bundler/bundle-scanner.ts +13 -0
- package/src/bundler/manifest.ts +1 -1
- package/src/calls/__tests__/voice-session-bridge.test.ts +47 -0
- package/src/calls/call-constants.ts +5 -0
- package/src/calls/call-controller.ts +100 -32
- package/src/calls/call-transport.ts +9 -0
- package/src/calls/media-stream-output.ts +107 -4
- package/src/calls/media-stream-server.ts +29 -9
- package/src/calls/media-stream-stt-session.ts +7 -1
- package/src/calls/media-turn-detector.ts +11 -1
- package/src/calls/voice-session-bridge.ts +84 -63
- package/src/cli/commands/__tests__/inference-providers.test.ts +270 -33
- package/src/cli/commands/__tests__/notifications.test.ts +24 -3
- package/src/cli/commands/config.help.ts +6 -6
- package/src/cli/commands/credentials.help.ts +13 -0
- package/src/cli/commands/credentials.ts +6 -1
- package/src/cli/commands/email.help.ts +7 -0
- package/src/cli/commands/email.ts +35 -1
- package/src/cli/commands/inference-providers.ts +168 -107
- package/src/cli/commands/inference.help.ts +118 -46
- package/src/cli/commands/memory/index.help.ts +23 -0
- package/src/cli/commands/memory/nodes.ts +146 -0
- package/src/cli/commands/notifications.help.ts +10 -10
- package/src/cli/commands/oauth/connect-surface-guidance.test.ts +40 -0
- package/src/cli/commands/oauth/connect-surface-guidance.ts +54 -0
- package/src/cli/commands/oauth/connect.test.ts +126 -0
- package/src/cli/commands/oauth/connect.ts +29 -6
- package/src/cli/commands/oauth/index.help.ts +7 -1
- package/src/cli/commands/oauth/status.test.ts +69 -3
- package/src/cli/commands/oauth/status.ts +50 -12
- package/src/cli/commands/plugins.help.ts +13 -2
- package/src/cli/commands/plugins.ts +61 -7
- package/src/cli/commands/telemetry.help.ts +13 -0
- package/src/cli/commands/telemetry.ts +45 -5
- package/src/cli/lib/__tests__/plugin-catalog-local.test.ts +8 -2
- package/src/cli/lib/__tests__/upgrade-plugin.test.ts +213 -9
- package/src/cli/lib/bundled-marketplace.json +93 -36
- package/src/cli/lib/inspect-plugin.ts +5 -1
- package/src/cli/lib/install-from-github.ts +68 -4
- package/src/cli/lib/plugin-catalog-local.ts +6 -2
- package/src/cli/lib/plugin-fingerprint.ts +3 -3
- package/src/cli/lib/upgrade-plugin.ts +236 -35
- package/src/config/__tests__/default-profile-catalog.test.ts +8 -12
- package/src/config/__tests__/plugin-resident-skill-discovery.test.ts +137 -0
- package/src/config/__tests__/profile-materialization.test.ts +1 -88
- package/src/config/bundled-skills/AGENTS.md +3 -30
- package/src/config/bundled-skills/app-builder/SKILL.md +5 -3
- package/src/config/bundled-skills/app-builder/TOOLS.json +23 -0
- package/src/config/bundled-skills/app-builder/tools/app-open.ts +32 -0
- package/src/config/bundled-skills/messaging/tools/messaging-send.ts +1 -1
- package/src/config/bundled-skills/phone-calls/references/CONFIG.md +7 -7
- package/src/config/bundled-skills/schedule/SKILL.md +1 -1
- package/src/config/bundled-skills/schedule/TOOLS.json +1 -1
- package/src/config/bundled-skills/settings/TOOLS.json +3 -1
- package/src/config/bundled-skills/settings/tools/navigate-settings-tab.ts +2 -0
- package/src/config/bundled-skills/settings/tools/voice-config-update.ts +18 -10
- package/src/config/bundled-skills/subagent/SKILL.md +2 -0
- package/src/config/bundled-skills/subagent/TOOLS.json +1 -1
- package/src/config/call-site-defaults.ts +3 -3
- package/src/config/feature-flag-registry.json +24 -39
- package/src/config/llm-resolver.ts +88 -475
- package/src/config/profile-materialization.ts +11 -11
- package/src/config/schema.ts +93 -127
- package/src/config/schemas/__tests__/live-voice.test.ts +24 -6
- package/src/config/schemas/__tests__/stt.test.ts +31 -3
- package/src/config/schemas/live-voice.ts +10 -4
- package/src/config/schemas/llm.ts +52 -15
- package/src/config/schemas/memory-lifecycle.ts +1 -1
- package/src/config/schemas/memory-retrospective.ts +8 -0
- package/src/config/schemas/memory-v2.ts +2 -2
- package/src/config/schemas/memory-v3.ts +1 -1
- package/src/config/schemas/services.ts +6 -3
- package/src/config/schemas/stt.ts +38 -21
- package/src/config/schemas/tts.ts +13 -18
- package/src/config/skills.ts +31 -21
- package/src/context/compactor.ts +44 -7
- package/src/context/post-turn-tool-result-truncation.ts +4 -2
- package/src/context/tool-result-spool.ts +26 -5
- package/src/conversations/__tests__/message-consolidation.test.ts +48 -0
- package/src/conversations/message-consolidation.ts +22 -2
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +5 -12
- package/src/daemon/app-source-watcher.ts +17 -23
- package/src/daemon/chat-credential-redaction.ts +1365 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +627 -34
- package/src/daemon/conversation-agent-loop.ts +71 -31
- package/src/daemon/conversation-error.ts +36 -14
- package/src/daemon/conversation-process.ts +22 -0
- package/src/daemon/conversation-store.ts +35 -0
- package/src/daemon/conversation-surfaces.ts +25 -25
- package/src/daemon/conversation-tool-setup.ts +33 -7
- package/src/daemon/conversation.ts +55 -5
- package/src/daemon/handlers/shared.ts +33 -2
- package/src/daemon/lifecycle.ts +4 -4
- package/src/daemon/message-types/conversations.ts +6 -17
- package/src/daemon/providers-setup.ts +8 -0
- package/src/daemon/tool-setup-types.ts +7 -1
- package/src/daemon/wake-conversation-ops.ts +10 -1
- package/src/hooks/types.ts +9 -0
- package/src/ipc/__tests__/email-ipc.test.ts +90 -0
- package/src/ipc/gateway-client.test.ts +59 -0
- package/src/ipc/gateway-client.ts +70 -27
- package/src/live-voice/__tests__/live-voice-events.test.ts +14 -2
- package/src/live-voice/__tests__/live-voice-integration.test.ts +116 -2
- package/src/live-voice/__tests__/live-voice-vad.test.ts +804 -13
- package/src/live-voice/__tests__/protocol.test.ts +122 -0
- package/src/live-voice/live-voice-session.ts +443 -40
- package/src/live-voice/protocol.ts +143 -1
- package/src/monitoring/__tests__/plugin-source-watch.test.ts +3 -1
- package/src/monitoring/plugin-source-watch.ts +3 -62
- package/src/notifications/README.md +1 -1
- package/src/permissions/checker.ts +8 -4
- package/src/persistence/__tests__/db-init-migrations-ok.test.ts +26 -0
- package/src/persistence/conversation-crud.ts +104 -2
- package/src/persistence/db-init.ts +14 -3
- package/src/persistence/job-handlers/cleanup.ts +15 -7
- package/src/persistence/llm-request-log-store.ts +88 -52
- package/src/persistence/migrations/298-move-memory-jobs-to-memory-db.ts +7 -31
- package/src/persistence/migrations/305-drop-contact-acl-columns.ts +3 -2
- package/src/persistence/migrations/326-move-injection-events-to-memory-db.ts +8 -34
- package/src/persistence/migrations/336-move-memory-v2-activation-logs-to-memory-db.ts +90 -0
- package/src/persistence/migrations/337-move-memory-recall-logs-to-memory-db.ts +114 -0
- package/src/persistence/migrations/338-move-memory-v3-selections-to-memory-db.ts +84 -0
- package/src/persistence/migrations/339-move-activation-sessions-to-memory-db.ts +52 -0
- package/src/persistence/migrations/__tests__/run-migrations.test.ts +155 -0
- package/src/persistence/migrations/helpers/relocation.ts +44 -1
- package/src/persistence/migrations/run-migrations.ts +25 -1
- package/src/persistence/schema/infrastructure.ts +9 -0
- package/src/persistence/schema/memory-core.ts +3 -0
- package/src/persistence/schema/memory-injection.ts +2 -0
- package/src/persistence/steps.ts +36 -0
- package/src/platform/client.test.ts +1 -44
- package/src/platform/client.ts +10 -20
- package/src/platform/consent-cache.test.ts +89 -23
- package/src/platform/consent-cache.ts +71 -33
- package/src/plugin-api/constants.ts +12 -0
- package/src/plugin-api/conversation-turn.ts +37 -14
- package/src/plugin-api/index.ts +11 -1
- package/src/plugin-api/resolve-credential.ts +75 -0
- package/src/plugin-api/vision-support.test.ts +8 -19
- package/src/plugin-api/vision-support.ts +26 -17
- package/src/plugins/collect-source-versions.ts +77 -0
- package/src/plugins/defaults/compaction/compact.ts +6 -0
- package/src/plugins/defaults/compaction/window-manager.ts +9 -0
- package/src/plugins/defaults/empty-response/hooks/post-model-call.ts +18 -24
- package/src/plugins/defaults/empty-response/hooks/user-prompt-submit.ts +38 -0
- package/src/plugins/defaults/empty-response/refusal-quarantine.ts +99 -0
- package/src/plugins/defaults/image-fallback/__tests__/caption-cache-persistence.test.ts +7 -3
- package/src/plugins/defaults/index.ts +8 -1
- package/src/plugins/defaults/max-tokens-continue/hooks/post-model-call.ts +4 -1
- package/src/plugins/defaults/memory/__tests__/activation-session-store.test.ts +48 -6
- package/src/plugins/defaults/memory/__tests__/db-memory-attach.test.ts +28 -22
- package/src/plugins/defaults/memory/__tests__/memory-log-stores-degraded.test.ts +148 -0
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-job.test.ts +80 -8
- package/src/plugins/defaults/memory/__tests__/memory-retrospective-prompt.test.ts +202 -0
- package/src/plugins/defaults/memory/__tests__/memory-v2-activation-log-store.test.ts +64 -25
- package/src/plugins/defaults/memory/__tests__/memory-v2-concept-frequency.test.ts +24 -11
- package/src/plugins/defaults/memory/__tests__/prompt-override.test.ts +70 -6
- package/src/plugins/defaults/memory/__tests__/table-relocation.test.ts +278 -0
- package/src/plugins/defaults/memory/activation-session-store.ts +27 -20
- package/src/plugins/defaults/memory/context-search/sources/memory-v2.ts +2 -9
- package/src/plugins/defaults/memory/context-search/sources/workspace.ts +1 -8
- package/src/plugins/defaults/memory/graph/retriever.test.ts +6 -6
- package/src/plugins/defaults/memory/graph/store.ts +114 -0
- package/src/plugins/defaults/memory/graph/tool-handlers.ts +36 -1
- package/src/plugins/defaults/memory/graph/tools.ts +47 -13
- package/src/plugins/defaults/memory/graph-topology/build-memory-graph.ts +16 -35
- package/src/plugins/defaults/memory/jobs-worker.ts +10 -1
- package/src/plugins/defaults/memory/memory-db.ts +3 -2
- package/src/plugins/defaults/memory/memory-recall-log-store.ts +129 -66
- package/src/plugins/defaults/memory/memory-retrospective-constants.ts +8 -0
- package/src/plugins/defaults/memory/memory-retrospective-job.ts +11 -122
- package/src/plugins/defaults/memory/memory-retrospective-prompt.ts +216 -0
- package/src/plugins/defaults/memory/memory-v2-activation-log-store.ts +84 -46
- package/src/plugins/defaults/memory/memory-v2-concept-frequency.ts +42 -32
- package/src/plugins/defaults/memory/path-containment.ts +21 -0
- package/src/plugins/defaults/memory/prompt-override.ts +51 -13
- package/src/plugins/defaults/memory/tools.test.ts +34 -0
- package/src/plugins/defaults/memory/tools.ts +12 -2
- package/src/plugins/defaults/memory/v2/__tests__/harness-compare.test.ts +19 -15
- package/src/plugins/defaults/memory/v2/__tests__/harness-oracle.test.ts +24 -19
- package/src/plugins/defaults/memory/v2/__tests__/harness-replay-input.test.ts +19 -15
- package/src/plugins/defaults/memory/v2/__tests__/injection.test.ts +22 -2
- package/src/plugins/defaults/memory/v2/__tests__/prompts-consolidation.test.ts +5 -3
- package/src/plugins/defaults/memory/v2/harness/oracle.ts +59 -41
- package/src/plugins/defaults/memory/v2/harness/replay-input.ts +29 -25
- package/src/plugins/defaults/memory/v2/migration.ts +46 -16
- package/src/plugins/defaults/memory/v2/prompts/consolidation.ts +4 -0
- package/src/plugins/defaults/memory/v3/__tests__/carry-integration.test.ts +17 -15
- package/src/plugins/defaults/memory/v3/__tests__/gate.test.ts +24 -22
- package/src/plugins/defaults/memory/v3/__tests__/injection.test.ts +9 -5
- package/src/plugins/defaults/memory/v3/__tests__/orchestrate.test.ts +277 -10
- package/src/plugins/defaults/memory/v3/__tests__/selection-log-store.test.ts +57 -5
- package/src/plugins/defaults/memory/v3/__tests__/shadow-integration.test.ts +9 -7
- package/src/plugins/defaults/memory/v3/__tests__/shadow-plugin.test.ts +38 -7
- package/src/plugins/defaults/memory/v3/hot-set.test.ts +36 -18
- package/src/plugins/defaults/memory/v3/hot-set.ts +12 -14
- package/src/plugins/defaults/memory/v3/learned-edges.test.ts +47 -27
- package/src/plugins/defaults/memory/v3/learned-edges.ts +12 -14
- package/src/plugins/defaults/memory/v3/orchestrate.ts +139 -22
- package/src/plugins/defaults/memory/v3/prune.test.ts +10 -3
- package/src/plugins/defaults/memory/v3/prune.ts +17 -11
- package/src/plugins/defaults/memory/v3/selection-log-store.ts +23 -11
- package/src/plugins/defaults/memory/v3/shadow-plugin.ts +70 -53
- package/src/plugins/defaults/surface-completion-nudge/hooks/post-model-call.ts +9 -6
- package/src/plugins/external-plugin-loader.ts +15 -15
- package/src/plugins/mtime-cache.ts +47 -0
- package/src/plugins/pipeline.ts +9 -1
- package/src/plugins/plugin-execution-context.ts +44 -0
- package/src/plugins/plugin-tree-walk.ts +31 -24
- package/src/plugins/source-fingerprint.ts +3 -4
- package/src/prompts/normalize-onboarding.ts +12 -0
- package/src/prompts/persona-resolver.ts +8 -0
- package/src/prompts/templates/BOOTSTRAP-ACTIVATION-RAIL.md +1 -1
- package/src/providers/__tests__/dispatch-connection-routing.test.ts +6 -9
- package/src/providers/__tests__/registry-native-web-search.test.ts +4 -10
- package/src/providers/__tests__/retry-callsite.test.ts +235 -215
- package/src/providers/__tests__/satellite-connection-routing.test.ts +8 -16
- package/src/providers/atlascloud/client.ts +10 -49
- package/src/providers/baseten/client.ts +43 -0
- package/src/providers/call-site-routing.ts +26 -13
- package/src/providers/connection-resolution.ts +9 -11
- package/src/providers/fetch-provider-catalog.ts +4 -2
- package/src/providers/inference/__tests__/adapter-factory-openai-compatible.test.ts +29 -4
- package/src/providers/inference/__tests__/connection-availability-keyless.test.ts +78 -0
- package/src/providers/inference/adapter-factory.ts +27 -6
- package/src/providers/inference/auth.ts +29 -1
- package/src/providers/inference/backfill.ts +61 -10
- package/src/providers/inference/connection-availability.ts +3 -2
- package/src/providers/inference/resolve-auth.ts +9 -1
- package/src/providers/model-catalog.ts +37 -0
- package/src/providers/openai/__tests__/api-error-normalization.test.ts +24 -2
- package/src/providers/openai/api-key-validation.ts +70 -0
- package/src/providers/retry.ts +2 -0
- package/src/providers/types.ts +11 -4
- package/src/providers/vellum-model-routing.test.ts +26 -0
- package/src/providers/vellum-model-routing.ts +30 -0
- package/src/providers/voice-error-copy.ts +47 -0
- package/src/runtime/agent-wake.ts +40 -24
- package/src/runtime/for-chat-mint-registry.ts +118 -0
- package/src/runtime/reveal-nonce.ts +49 -0
- package/src/runtime/reveal-success-registry.ts +306 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +88 -3
- package/src/runtime/routes/__tests__/inference-provider-connection-routes.test.ts +161 -30
- package/src/runtime/routes/__tests__/migration-vellum-metadata-reconcile.test.ts +7 -0
- package/src/runtime/routes/__tests__/schedule-worker-routes.test.ts +15 -0
- package/src/runtime/routes/app-management-routes.ts +152 -45
- package/src/runtime/routes/app-routes.ts +16 -77
- package/src/runtime/routes/canned-message-complete.ts +16 -16
- package/src/runtime/routes/conversation-management-routes.ts +17 -14
- package/src/runtime/routes/conversation-query-routes.ts +54 -6
- package/src/runtime/routes/conversation-routes.ts +48 -2
- package/src/runtime/routes/credential-routes.ts +116 -3
- package/src/runtime/routes/email-routes.ts +17 -1
- package/src/runtime/routes/inbound-stages/transcribe-audio.test.ts +33 -5
- package/src/runtime/routes/inbound-stages/transcribe-audio.ts +6 -5
- package/src/runtime/routes/inference-provider-connection-routes.ts +77 -28
- package/src/runtime/routes/inference-send-routes.ts +1 -1
- package/src/runtime/routes/internal-telemetry-routes.ts +7 -6
- package/src/runtime/routes/plugins-routes.ts +37 -6
- package/src/runtime/routes/publish-routes.ts +15 -18
- package/src/runtime/routes/schedule-worker-routes.ts +9 -0
- package/src/runtime/routes/secret-routes.ts +10 -0
- package/src/runtime/routes/telemetry-routes.ts +149 -45
- package/src/schedule/__tests__/schedule-timezone.test.ts +101 -0
- package/src/schedule/__tests__/worker-watchdog.test.ts +209 -0
- package/src/schedule/schedule-store.ts +12 -1
- package/src/schedule/schedule-timezone.ts +63 -0
- package/src/schedule/scheduler.ts +100 -6
- package/src/schedule/worker-control.ts +19 -0
- package/src/security/auth-fallback-events-store.ts +7 -6
- package/src/security/secret-scanner.ts +26 -1
- package/src/services/published-app-updater.ts +6 -11
- package/src/stt/stt-stream-session.ts +36 -16
- package/src/subagent/manager.ts +34 -8
- package/src/telemetry/AGENTS.md +30 -1
- package/src/telemetry/__tests__/config-setting-snapshot.test.ts +18 -0
- package/src/telemetry/__tests__/outbox-test-harness.ts +5 -3
- package/src/telemetry/config-setting-snapshot.ts +44 -10
- package/src/telemetry/telemetry-event-sources.test.ts +124 -30
- package/src/telemetry/telemetry-event-sources.ts +137 -83
- package/src/telemetry/telemetry-events-outbox.test.ts +46 -1
- package/src/telemetry/telemetry-events-outbox.ts +60 -9
- package/src/telemetry/telemetry-wire-source.json +1 -1
- package/src/telemetry/telemetry-wire-validation.ts +39 -2
- package/src/telemetry/telemetry-wire.generated.ts +8 -0
- package/src/telemetry/tool-audit.ts +15 -9
- package/src/telemetry/tool-executed-events-store.test.ts +1 -1
- package/src/telemetry/turn-events-store.ts +20 -0
- package/src/telemetry/types.ts +45 -12
- package/src/telemetry/usage-telemetry-reporter.test.ts +294 -25
- package/src/telemetry/usage-telemetry-reporter.ts +117 -18
- package/src/telemetry/watchdog-direct-emit.test.ts +11 -3
- package/src/telemetry/watchdog-direct-emit.ts +11 -6
- package/src/tools/apps/executors.ts +11 -36
- package/src/tools/executor.ts +14 -1
- package/src/tools/host-terminal/host-shell.ts +6 -2
- package/src/tools/network/__tests__/web-fetch-firecrawl.test.ts +1 -1
- package/src/tools/network/__tests__/web-fetch-metadata.test.ts +25 -0
- package/src/tools/network/web-fetch.ts +6 -2
- package/src/tools/skills/sandbox-runner.ts +5 -2
- package/src/tools/subagent/spawn.ts +7 -11
- package/src/tools/terminal/shell.ts +5 -2
- package/src/tools/tool-manifest.ts +0 -2
- package/src/tools/tool-profiler.ts +37 -6
- package/src/tools/ui-surface/channel-variants.ts +101 -0
- package/src/tools/ui-surface/definitions.ts +23 -67
- package/src/tools/ui-surface/surface-shape-docs.ts +229 -0
- package/src/tts/__tests__/provider-adapters.test.ts +18 -0
- package/src/tts/provider-catalog.ts +2 -4
- package/src/tts/providers/deepgram-provider.ts +10 -1
- package/src/types/onboarding-context.ts +8 -0
- package/src/usage/attribution.ts +18 -112
- package/src/{config/bundled-skills/messaging/tools/gmail-mime-helpers.ts → util/mime-type.ts} +4 -1
- package/src/util/provider-error-patterns.ts +7 -1
- package/src/util/worker-process.ts +105 -0
- package/src/watcher/__tests__/telemetry.test.ts +17 -4
- package/src/watcher/telemetry.ts +5 -5
- package/src/workspace/migrations/131-drop-web-fetch-mode.ts +61 -0
- package/src/workspace/migrations/registry.ts +2 -0
- package/src/workspace/provider-commit-message-generator.ts +6 -4
- package/src/__tests__/app-open-proxy.test.ts +0 -67
- package/src/onboarding/onboarding-research-events-store.test.ts +0 -230
- package/src/onboarding/onboarding-research-events-store.ts +0 -104
- package/src/runtime/routes/assets/vellum-design-system.css +0 -2236
- package/src/tools/apps/definitions.ts +0 -73
- package/src/tools/apps/open-proxy.ts +0 -43
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
} from "./__tests__/outbox-test-harness.js";
|
|
11
11
|
import {
|
|
12
12
|
deleteTelemetryOutboxEvents,
|
|
13
|
+
deleteTelemetryOutboxEventsBefore,
|
|
13
14
|
discardPendingTelemetryOutboxEvents,
|
|
14
15
|
insertTelemetryOutboxEvent,
|
|
15
16
|
insertTelemetryOutboxEvents,
|
|
@@ -290,7 +291,7 @@ describe("telemetry-events-outbox", () => {
|
|
|
290
291
|
);
|
|
291
292
|
});
|
|
292
293
|
|
|
293
|
-
test("recordTelemetryEvent honors
|
|
294
|
+
test("recordTelemetryEvent honors a confirmed share_analytics opt-out", () => {
|
|
294
295
|
setShareAnalytics(false);
|
|
295
296
|
expect(
|
|
296
297
|
recordTelemetryEvent("watchdog", {
|
|
@@ -302,6 +303,19 @@ describe("telemetry-events-outbox", () => {
|
|
|
302
303
|
expect(queryTelemetryOutboxBatch("watchdog", 10)).toEqual([]);
|
|
303
304
|
});
|
|
304
305
|
|
|
306
|
+
test("recordTelemetryEvent records while consent is unknown (cold cache)", () => {
|
|
307
|
+
setShareAnalytics("unknown");
|
|
308
|
+
const recorded = recordTelemetryEvent("watchdog", {
|
|
309
|
+
check_name: "c",
|
|
310
|
+
value: null,
|
|
311
|
+
detail: null,
|
|
312
|
+
});
|
|
313
|
+
expect(recorded).not.toBeNull();
|
|
314
|
+
expect(queryTelemetryOutboxBatch("watchdog", 10).map((r) => r.id)).toEqual([
|
|
315
|
+
recorded!.id,
|
|
316
|
+
]);
|
|
317
|
+
});
|
|
318
|
+
|
|
305
319
|
test("recordTelemetryEvent returns null when the telemetry DB is unavailable", () => {
|
|
306
320
|
withTelemetryDbUnavailable(() => {
|
|
307
321
|
expect(
|
|
@@ -315,6 +329,37 @@ describe("telemetry-events-outbox", () => {
|
|
|
315
329
|
expect(queryTelemetryOutboxBatch("watchdog", 10)).toEqual([]);
|
|
316
330
|
});
|
|
317
331
|
|
|
332
|
+
test("prune deletes rows strictly older than the cutoff across every name and returns the count", () => {
|
|
333
|
+
insert("evt-old-life", 1000, "lifecycle");
|
|
334
|
+
insert("evt-old-watch", 1500, "watchdog");
|
|
335
|
+
insert("evt-at-cutoff", 2000, "lifecycle");
|
|
336
|
+
insert("evt-fresh", 3000, "lifecycle");
|
|
337
|
+
|
|
338
|
+
expect(deleteTelemetryOutboxEventsBefore(2000)).toBe(2);
|
|
339
|
+
|
|
340
|
+
// Strictly-before semantics: the row AT the cutoff is retained.
|
|
341
|
+
expect(allIds()).toEqual(["evt-at-cutoff", "evt-fresh"]);
|
|
342
|
+
expect(queryTelemetryOutboxBatch("watchdog", 10)).toEqual([]);
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
test("prune with nothing expired deletes nothing and returns 0", () => {
|
|
346
|
+
insert("evt-1", 5000);
|
|
347
|
+
|
|
348
|
+
expect(deleteTelemetryOutboxEventsBefore(5000)).toBe(0);
|
|
349
|
+
|
|
350
|
+
expect(allIds()).toEqual(["evt-1"]);
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
test("prune returns 0 when the telemetry DB is unavailable", () => {
|
|
354
|
+
insert("evt-1", 1000);
|
|
355
|
+
|
|
356
|
+
withTelemetryDbUnavailable(() => {
|
|
357
|
+
expect(deleteTelemetryOutboxEventsBefore(2000)).toBe(0);
|
|
358
|
+
});
|
|
359
|
+
|
|
360
|
+
expect(allIds()).toEqual(["evt-1"]);
|
|
361
|
+
});
|
|
362
|
+
|
|
318
363
|
test("discards all pending rows for one name only", () => {
|
|
319
364
|
insert("evt-1", 1000, "lifecycle");
|
|
320
365
|
insert("evt-2", 2000, "lifecycle");
|
|
@@ -9,9 +9,9 @@
|
|
|
9
9
|
import { asc, eq, inArray } from "drizzle-orm";
|
|
10
10
|
import { v4 as uuid } from "uuid";
|
|
11
11
|
|
|
12
|
-
import { getTelemetryDb } from "../persistence/db-connection.js";
|
|
12
|
+
import { getSqliteFrom, getTelemetryDb } from "../persistence/db-connection.js";
|
|
13
13
|
import { telemetryEvents } from "../persistence/schema/index.js";
|
|
14
|
-
import {
|
|
14
|
+
import { getRawShareAnalytics } from "../platform/consent-cache.js";
|
|
15
15
|
import { APP_VERSION } from "../version.js";
|
|
16
16
|
import type {
|
|
17
17
|
OutboxTelemetryEventName,
|
|
@@ -23,6 +23,14 @@ import type {
|
|
|
23
23
|
/** Ids per DELETE chunk — stays under SQLite's bound-variable limit. */
|
|
24
24
|
const DELETE_CHUNK_SIZE = 500;
|
|
25
25
|
|
|
26
|
+
/**
|
|
27
|
+
* Max age of a pending outbox row. The reporter prunes older rows at the
|
|
28
|
+
* start of every flush cycle, in every consent state — this is what bounds
|
|
29
|
+
* the unknown-consent buffering (a permanently-unknown state never resolves,
|
|
30
|
+
* and a row this stale is worthless telemetry anyway).
|
|
31
|
+
*/
|
|
32
|
+
export const OUTBOX_MAX_ROW_AGE_MS = 30 * 24 * 60 * 60 * 1000;
|
|
33
|
+
|
|
26
34
|
/** One pending outbox row; `payload` is the wire `TelemetryEvent` JSON. */
|
|
27
35
|
export interface TelemetryOutboxRow {
|
|
28
36
|
id: string;
|
|
@@ -82,19 +90,25 @@ export function insertTelemetryOutboxEvent(
|
|
|
82
90
|
/**
|
|
83
91
|
* Lower-level record escape hatch: for payloads that need the record-time
|
|
84
92
|
* `(id, createdAt)` inside type-specific fields (onboarding's activation
|
|
85
|
-
* `daemon_event_id` override and `completed_at`).
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
*
|
|
93
|
+
* `daemon_event_id` override and `completed_at`). Drops only on a confirmed
|
|
94
|
+
* `share_analytics` opt-out — the record-time drop is a privacy courtesy for
|
|
95
|
+
* known opt-outs. While consent is unknown (cold cache, no platform session)
|
|
96
|
+
* the event is recorded: dropping on an unresolved state would permanently
|
|
97
|
+
* destroy data, and consent is enforced again at flush time. Unknown-state
|
|
98
|
+
* buffering is bounded — the reporter prunes rows older than
|
|
99
|
+
* {@link OUTBOX_MAX_ROW_AGE_MS} each flush cycle. Generates the
|
|
100
|
+
* outbox row identity, builds the wire payload via `buildEvent` (which owns
|
|
101
|
+
* all stamping), and inserts. Returns the generated row identity, or null
|
|
102
|
+
* when dropped for the opt-out or when the telemetry DB is unavailable
|
|
103
|
+
* (degraded mode). Prefer `recordTelemetryEvent` when the payload doesn't
|
|
104
|
+
* need them.
|
|
91
105
|
*/
|
|
92
106
|
export function recordTelemetryOutboxEvent(
|
|
93
107
|
name: string,
|
|
94
108
|
buildEvent: (id: string, createdAt: number) => TelemetryEvent,
|
|
95
109
|
opts?: { conversationId?: string | null },
|
|
96
110
|
): { id: string; createdAt: number } | null {
|
|
97
|
-
if (
|
|
111
|
+
if (getRawShareAnalytics() === false) {
|
|
98
112
|
return null;
|
|
99
113
|
}
|
|
100
114
|
const id = uuid();
|
|
@@ -176,6 +190,25 @@ export function deleteTelemetryOutboxEvents(ids: string[]): void {
|
|
|
176
190
|
}
|
|
177
191
|
}
|
|
178
192
|
|
|
193
|
+
/**
|
|
194
|
+
* Delete rows recorded before `cutoffCreatedAt`, across every event name
|
|
195
|
+
* (age-bound prune). Returns the deleted row count; 0 when the telemetry DB
|
|
196
|
+
* is unavailable.
|
|
197
|
+
*/
|
|
198
|
+
export function deleteTelemetryOutboxEventsBefore(
|
|
199
|
+
cutoffCreatedAt: number,
|
|
200
|
+
): number {
|
|
201
|
+
const db = getTelemetryDb();
|
|
202
|
+
if (!db) {
|
|
203
|
+
return 0;
|
|
204
|
+
}
|
|
205
|
+
// Raw statement: drizzle's bun-sqlite `.run()` is typed void, and the
|
|
206
|
+
// prune's only output is the changed-row count.
|
|
207
|
+
return getSqliteFrom(db)
|
|
208
|
+
.prepare("DELETE FROM telemetry_events WHERE created_at < ?")
|
|
209
|
+
.run(cutoffCreatedAt).changes;
|
|
210
|
+
}
|
|
211
|
+
|
|
179
212
|
/** Drop all pending rows for one event name (telemetry opt-out). */
|
|
180
213
|
export function discardPendingTelemetryOutboxEvents(name: string): void {
|
|
181
214
|
const db = getTelemetryDb();
|
|
@@ -184,3 +217,21 @@ export function discardPendingTelemetryOutboxEvents(name: string): void {
|
|
|
184
217
|
}
|
|
185
218
|
db.delete(telemetryEvents).where(eq(telemetryEvents.name, name)).run();
|
|
186
219
|
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Distinct event names with at least one pending row in the outbox. Used by the
|
|
223
|
+
* orphan-drain source to find rows whose type is no longer in the wire contract
|
|
224
|
+
* (e.g. recorded before the platform removed/renamed a type) so they can be
|
|
225
|
+
* flushed instead of stranded. Empty when the telemetry DB is unavailable.
|
|
226
|
+
*/
|
|
227
|
+
export function queryDistinctOutboxEventNames(): string[] {
|
|
228
|
+
const db = getTelemetryDb();
|
|
229
|
+
if (!db) {
|
|
230
|
+
return [];
|
|
231
|
+
}
|
|
232
|
+
return db
|
|
233
|
+
.selectDistinct({ name: telemetryEvents.name })
|
|
234
|
+
.from(telemetryEvents)
|
|
235
|
+
.all()
|
|
236
|
+
.map((row) => row.name);
|
|
237
|
+
}
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* events.
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
|
-
import
|
|
17
|
+
import { z } from "zod";
|
|
18
18
|
|
|
19
19
|
import type { getLogger } from "../util/logger.js";
|
|
20
20
|
import { telemetryEventSchema } from "./telemetry-wire.generated.js";
|
|
@@ -26,13 +26,24 @@ type Logger = ReturnType<typeof getLogger>;
|
|
|
26
26
|
* discriminated union (`.options` + each member's `type` literal), so a new
|
|
27
27
|
* generated event type is validated with zero hand edits here.
|
|
28
28
|
*/
|
|
29
|
-
const wireSchemaByType: ReadonlyMap<string, z.
|
|
29
|
+
const wireSchemaByType: ReadonlyMap<string, z.ZodObject> = new Map(
|
|
30
30
|
telemetryEventSchema.options.map((option) => [
|
|
31
31
|
option.shape.type.value,
|
|
32
32
|
option,
|
|
33
33
|
]),
|
|
34
34
|
);
|
|
35
35
|
|
|
36
|
+
/**
|
|
37
|
+
* Base fields stamped by the daemon at record time, never supplied by a client.
|
|
38
|
+
* Stripped when deriving the client-facing `fields` schema for a wire type.
|
|
39
|
+
*/
|
|
40
|
+
const TELEMETRY_BASE_FIELD_KEYS = {
|
|
41
|
+
type: true,
|
|
42
|
+
daemon_event_id: true,
|
|
43
|
+
recorded_at: true,
|
|
44
|
+
assistant_version: true,
|
|
45
|
+
} as const;
|
|
46
|
+
|
|
36
47
|
/**
|
|
37
48
|
* Event types already warned about as absent from the wire contract.
|
|
38
49
|
* Unknown-type warnings are rate-limited to once per process per type —
|
|
@@ -46,6 +57,32 @@ export function resetUnknownTypeWarningsForTests(): void {
|
|
|
46
57
|
warnedUnknownTypes.clear();
|
|
47
58
|
}
|
|
48
59
|
|
|
60
|
+
/**
|
|
61
|
+
* Per-event-type wire schema for one `type` discriminant, or undefined when the
|
|
62
|
+
* platform contract has no serializer for it. Lets the client-ingest boundary
|
|
63
|
+
* (`POST /v1/telemetry/ingest`) reject a malformed payload up front with the
|
|
64
|
+
* same schema pre-flush validation would have logged a silent drop for.
|
|
65
|
+
*/
|
|
66
|
+
export function getWireSchemaForType(type: string): z.ZodObject | undefined {
|
|
67
|
+
return wireSchemaByType.get(type);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Client-facing `fields` schema for a wire type: the wire object minus the
|
|
72
|
+
* daemon-stamped base fields. Rebuilt from `.shape` because `.omit()` rejects
|
|
73
|
+
* the refined wire schemas; this drops the claims/suggestions byte-bound
|
|
74
|
+
* superRefines, which aren't expressible in the request type anyway — the
|
|
75
|
+
* handler still validates the assembled event against the full wire schema
|
|
76
|
+
* ({@link getWireSchemaForType}) for those bounds. Undefined when the platform
|
|
77
|
+
* contract has no serializer for `type`.
|
|
78
|
+
*/
|
|
79
|
+
export function getWireFieldsSchema(type: string): z.ZodObject | undefined {
|
|
80
|
+
const schema = wireSchemaByType.get(type);
|
|
81
|
+
return schema
|
|
82
|
+
? z.object(schema.shape).omit(TELEMETRY_BASE_FIELD_KEYS)
|
|
83
|
+
: undefined;
|
|
84
|
+
}
|
|
85
|
+
|
|
49
86
|
/**
|
|
50
87
|
* Render a zod issue path for logging without leaking dynamic record keys.
|
|
51
88
|
*
|
|
@@ -332,6 +332,12 @@ export const onboardingResearchTelemetryEventSchema = z
|
|
|
332
332
|
assistant_version: z.string().trim().min(1).max(64).nullable().optional(),
|
|
333
333
|
conversation_id: z.string().trim().min(1).max(64).nullable().optional(),
|
|
334
334
|
status: z.string().trim().min(1).max(32),
|
|
335
|
+
self_reported_occupation: z.string().max(256).nullable().optional(),
|
|
336
|
+
self_reported_hobbies: z
|
|
337
|
+
.array(z.string().trim().min(1).max(128))
|
|
338
|
+
.max(32)
|
|
339
|
+
.optional(),
|
|
340
|
+
self_reported_timezone: z.string().max(64).nullable().optional(),
|
|
335
341
|
claims: z.array(jsonValueSchema).max(20),
|
|
336
342
|
claim_count: z.number().int().min(0),
|
|
337
343
|
claims_confident: z.number().int().min(0),
|
|
@@ -427,6 +433,8 @@ export type TelemetryIngestRequest = z.infer<
|
|
|
427
433
|
|
|
428
434
|
export const telemetryIngestResponseSchema = z.object({
|
|
429
435
|
accepted: z.number().int(),
|
|
436
|
+
persisted: z.number().int(),
|
|
437
|
+
dropped: z.record(z.string(), jsonValueSchema),
|
|
430
438
|
});
|
|
431
439
|
export type TelemetryIngestResponse = z.infer<
|
|
432
440
|
typeof telemetryIngestResponseSchema
|
|
@@ -14,16 +14,19 @@
|
|
|
14
14
|
* - `logToolFailure` emits the operator-facing failure log.
|
|
15
15
|
*
|
|
16
16
|
* The telemetry-only columns (payload sizes + model attribution) are the
|
|
17
|
-
* single write-time privacy gate for `tool_executed` telemetry:
|
|
18
|
-
*
|
|
19
|
-
* `arg_bytes IS NOT NULL` filter excludes permanently.
|
|
17
|
+
* single write-time privacy gate for `tool_executed` telemetry: on a confirmed
|
|
18
|
+
* `share_analytics` opt-out they persist as NULL, which the projection's
|
|
19
|
+
* `arg_bytes IS NOT NULL` filter excludes permanently. An unknown consent
|
|
20
|
+
* state (cold cache) populates the columns — NULLing them would destroy the
|
|
21
|
+
* data irreversibly, and consent is enforced again at flush time and platform
|
|
22
|
+
* ingest, so opted-out rows never leave the device. The audit fields
|
|
20
23
|
* themselves (tool name, decision, redacted input/result previews, duration)
|
|
21
24
|
* are unaffected — `tool_invocations` is a local always-on audit log.
|
|
22
25
|
*/
|
|
23
26
|
|
|
24
27
|
import { isAllowDecision, type UserDecision } from "../permissions/types.js";
|
|
25
28
|
import { recordLifecycleEvent } from "../persistence/lifecycle-events-store.js";
|
|
26
|
-
import {
|
|
29
|
+
import { getRawShareAnalytics } from "../platform/consent-cache.js";
|
|
27
30
|
import { redactJsonStringLeaves } from "../security/redact-json.js";
|
|
28
31
|
import { redactSensitiveFields } from "../security/redaction.js";
|
|
29
32
|
import { redactSecrets } from "../security/secret-scanner.js";
|
|
@@ -257,17 +260,20 @@ const NULL_TELEMETRY_COLUMNS: TelemetryColumns = {
|
|
|
257
260
|
};
|
|
258
261
|
|
|
259
262
|
/**
|
|
260
|
-
* Telemetry-only columns (payload sizes + model attribution).
|
|
261
|
-
*
|
|
262
|
-
* `
|
|
263
|
-
*
|
|
263
|
+
* Telemetry-only columns (payload sizes + model attribution). NULLed only on a
|
|
264
|
+
* confirmed `share_analytics` opt-out — the projection's `arg_bytes IS NOT
|
|
265
|
+
* NULL` filter excludes NULL rows permanently (the same mechanism that
|
|
266
|
+
* excludes legacy pre-migration rows, see tool-executed-events-store.ts), so
|
|
267
|
+
* an unknown consent state (cold cache) must populate the columns rather than
|
|
268
|
+
* destroy them. Consent is enforced again at flush time and platform ingest,
|
|
269
|
+
* so opted-out rows never ship.
|
|
264
270
|
*/
|
|
265
271
|
function telemetryColumns(
|
|
266
272
|
attribution: UsageAttributionSnapshot | null,
|
|
267
273
|
rawInput: string,
|
|
268
274
|
resultBytes: number,
|
|
269
275
|
): TelemetryColumns {
|
|
270
|
-
if (
|
|
276
|
+
if (getRawShareAnalytics() === false) {
|
|
271
277
|
return NULL_TELEMETRY_COLUMNS;
|
|
272
278
|
}
|
|
273
279
|
return {
|
|
@@ -5,7 +5,7 @@ import { beforeEach, describe, expect, mock, test } from "bun:test";
|
|
|
5
5
|
let shareAnalytics = true;
|
|
6
6
|
|
|
7
7
|
mock.module("../platform/consent-cache.js", () => ({
|
|
8
|
-
|
|
8
|
+
getRawShareAnalytics: () => shareAnalytics,
|
|
9
9
|
}));
|
|
10
10
|
|
|
11
11
|
import {
|
|
@@ -55,6 +55,21 @@ export interface TurnEvent {
|
|
|
55
55
|
* and should never appear on a user-message row.
|
|
56
56
|
*/
|
|
57
57
|
channelId: string | null;
|
|
58
|
+
/**
|
|
59
|
+
* Send-source tag for messages the UI sent on the user's behalf
|
|
60
|
+
* (`"nav_redirect"` — a navigation shortcut redirected the user into
|
|
61
|
+
* chat with a pre-filled message). Sourced from
|
|
62
|
+
* `messages.metadata.userMessageSource`, stamped by `handleSendMessage`
|
|
63
|
+
* when the request body carries `source`. Null for hand-typed messages
|
|
64
|
+
* and rows predating the field. Lets activation-funnel analytics
|
|
65
|
+
* separate UI-initiated turns from organic ones.
|
|
66
|
+
*
|
|
67
|
+
* Daemon-side projection only for now: the platform's turn serializer
|
|
68
|
+
* does not yet accept a `source` wire field, so `turnSource` must not
|
|
69
|
+
* emit it until the platform serializer lands and the wire sync PR
|
|
70
|
+
* updates `telemetry-wire.generated.ts` (see `src/telemetry/AGENTS.md`).
|
|
71
|
+
*/
|
|
72
|
+
source: string | null;
|
|
58
73
|
/**
|
|
59
74
|
* Flexible client metadata stashed under `messages.metadata.client` by
|
|
60
75
|
* the HTTP header middleware. Carries optional `browserFamily`,
|
|
@@ -160,6 +175,11 @@ export function queryUnreportedTurnEvents(
|
|
|
160
175
|
>`json_extract(${messages.metadata}, '$.userMessageChannel')`.as(
|
|
161
176
|
"channel_id",
|
|
162
177
|
),
|
|
178
|
+
source: sql<
|
|
179
|
+
string | null
|
|
180
|
+
>`json_extract(${messages.metadata}, '$.userMessageSource')`.as(
|
|
181
|
+
"source",
|
|
182
|
+
),
|
|
163
183
|
clientMetadata: sql<
|
|
164
184
|
string | null
|
|
165
185
|
>`json_extract(${messages.metadata}, '$.client')`.as("client_metadata"),
|
package/src/telemetry/types.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { LLMCallSite } from "../config/schemas/llm.js";
|
|
2
2
|
import type { UsageAttributionProfileSource } from "../usage/types.js";
|
|
3
3
|
import type * as wire from "./telemetry-wire.generated.js";
|
|
4
|
+
import { telemetryEventSchema } from "./telemetry-wire.generated.js";
|
|
4
5
|
import type { TurnOutcome } from "./turn-outcome.js";
|
|
5
6
|
|
|
6
7
|
/** Base fields present on every telemetry event. */
|
|
@@ -464,8 +465,8 @@ export interface OnboardingResearchSuggestion {
|
|
|
464
465
|
* settled result during onboarding. Client-orchestrated: the web client
|
|
465
466
|
* knows exactly when the turn completes and what it produced (claims,
|
|
466
467
|
* suggestions, plugin picks), and reports it once via
|
|
467
|
-
* `POST /v1/telemetry/
|
|
468
|
-
* turn on its own.
|
|
468
|
+
* `POST /v1/telemetry/ingest` (as a client-reportable type) — the daemon
|
|
469
|
+
* never detects this turn on its own.
|
|
469
470
|
*
|
|
470
471
|
* Carries both the raw claim/suggestion text (+ source URLs) and structural
|
|
471
472
|
* counts by confidence tier, so downstream consumers can aggregate cheaply
|
|
@@ -475,6 +476,14 @@ export interface OnboardingResearchTelemetryEvent extends TelemetryEventBase {
|
|
|
475
476
|
type: "onboarding_research";
|
|
476
477
|
conversation_id: string | null;
|
|
477
478
|
status: "done" | "error";
|
|
479
|
+
/**
|
|
480
|
+
* The onboarding-form values the turn was run ON (its INPUT), as distinct
|
|
481
|
+
* from the inferred `claims` below (its OUTPUT). Excludes the user's name by
|
|
482
|
+
* design. Optional — an older web client omits them.
|
|
483
|
+
*/
|
|
484
|
+
self_reported_occupation?: string;
|
|
485
|
+
self_reported_hobbies?: string[];
|
|
486
|
+
self_reported_timezone?: string;
|
|
478
487
|
claims: OnboardingResearchClaim[];
|
|
479
488
|
claim_count: number;
|
|
480
489
|
claims_confident: number;
|
|
@@ -664,18 +673,42 @@ type _extensionsDontCollide = AssertNoWireCollision<
|
|
|
664
673
|
* change once shipped. The watermark-flushed types (`llm_usage`, `turn`,
|
|
665
674
|
* `tool_executed`) live on their own tables and are deliberately excluded.
|
|
666
675
|
*/
|
|
667
|
-
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
676
|
+
/**
|
|
677
|
+
* Types NOT on the generic `telemetry_events` outbox — the high-volume events
|
|
678
|
+
* flushed from their own SQLite tables by a watermark source
|
|
679
|
+
* (`telemetry-event-sources.ts`). This is the ONLY hand-maintained partition
|
|
680
|
+
* fact; every other wire event type is outbox-backed by default. Add a name
|
|
681
|
+
* here only when a new type gets its own dedicated table.
|
|
682
|
+
*/
|
|
683
|
+
export const WATERMARK_TELEMETRY_EVENT_NAMES = [
|
|
684
|
+
"llm_usage",
|
|
685
|
+
"turn",
|
|
686
|
+
"tool_executed",
|
|
675
687
|
] as const;
|
|
676
688
|
|
|
677
|
-
export type
|
|
678
|
-
(typeof
|
|
689
|
+
export type WatermarkTelemetryEventName =
|
|
690
|
+
(typeof WATERMARK_TELEMETRY_EVENT_NAMES)[number];
|
|
691
|
+
|
|
692
|
+
/**
|
|
693
|
+
* Event names backed by the `telemetry_events` outbox: every wire event type
|
|
694
|
+
* that is not watermark-flushed. Derived from the generated wire contract, so a
|
|
695
|
+
* new event type added on the platform side flows onto the outbox — and gets a
|
|
696
|
+
* flush source (`telemetry-event-sources.ts`) and a fully-typed
|
|
697
|
+
* `recordTelemetryEvent` call — with NO edit here. Each name doubles as the
|
|
698
|
+
* wire `type` discriminant and the flush-group key.
|
|
699
|
+
*/
|
|
700
|
+
export type OutboxTelemetryEventName = Exclude<
|
|
701
|
+
keyof wire.WireEventMap,
|
|
702
|
+
WatermarkTelemetryEventName
|
|
703
|
+
>;
|
|
704
|
+
|
|
705
|
+
export const OUTBOX_TELEMETRY_EVENT_NAMES: readonly OutboxTelemetryEventName[] =
|
|
706
|
+
telemetryEventSchema.options
|
|
707
|
+
.map((option) => option.shape.type.value)
|
|
708
|
+
.filter(
|
|
709
|
+
(name): name is OutboxTelemetryEventName =>
|
|
710
|
+
!(WATERMARK_TELEMETRY_EVENT_NAMES as readonly string[]).includes(name),
|
|
711
|
+
);
|
|
679
712
|
|
|
680
713
|
/** Wire event type for one outbox event name. */
|
|
681
714
|
export type OutboxTelemetryEventOf<N extends OutboxTelemetryEventName> =
|