@vellumai/assistant 0.8.3 → 0.8.5
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 +2 -2
- package/docker-entrypoint.sh +0 -1
- package/docs/browser-use-architecture-phase2.md +1 -1
- package/knip.json +2 -1
- package/node_modules/@vellumai/gateway-client/src/types.ts +2 -0
- package/openapi.yaml +1492 -100
- package/package.json +1 -1
- package/src/__tests__/agent-loop-exit-reason.test.ts +4 -5
- package/src/__tests__/agent-loop-override-profile.test.ts +1 -1
- package/src/__tests__/agent-loop.test.ts +88 -3
- package/src/__tests__/anthropic-provider.test.ts +302 -33
- package/src/__tests__/approval-cascade.test.ts +1 -1
- package/src/__tests__/assistant-event-hub-self-exclusion.test.ts +293 -0
- package/src/__tests__/assistant-feature-flags-integration.test.ts +3 -3
- package/src/__tests__/audit-log-rotation.test.ts +70 -16
- package/src/__tests__/background-workers-disk-pressure.test.ts +4 -3
- package/src/__tests__/btw-routes.test.ts +2 -3
- package/src/__tests__/call-controller.test.ts +0 -1
- package/src/__tests__/cancel-resolves-conversation-key.test.ts +1 -1
- package/src/__tests__/channel-delivery-store.test.ts +193 -0
- package/src/__tests__/channel-guardian.test.ts +3 -3
- package/src/__tests__/channel-reply-delivery.test.ts +284 -5
- package/src/__tests__/channel-retry-sweep.test.ts +274 -1
- package/src/__tests__/checker.test.ts +6 -15
- package/src/__tests__/compaction-events.test.ts +2 -1
- package/src/__tests__/compactor-call-site-logging.test.ts +214 -0
- package/src/__tests__/compactor-preserved-tail-count.test.ts +110 -0
- package/src/__tests__/computer-use-skill-manifest-regression.test.ts +5 -11
- package/src/__tests__/computer-use-tools.test.ts +2 -4
- package/src/__tests__/config-watcher.test.ts +1 -1
- package/src/__tests__/confirmation-request-guardian-bridge.test.ts +0 -1
- package/src/__tests__/context-token-estimator.test.ts +91 -1
- package/src/__tests__/conversation-abort-tool-results.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop-disk-pressure.test.ts +1 -1
- package/src/__tests__/conversation-agent-loop-inference-profile.test.ts +55 -4
- package/src/__tests__/conversation-agent-loop-overflow.test.ts +228 -8
- package/src/__tests__/conversation-agent-loop.test.ts +188 -129
- package/src/__tests__/conversation-app-control-instantiation.test.ts +2 -5
- package/src/__tests__/conversation-app-control-lifecycle.test.ts +1 -1
- package/src/__tests__/conversation-clean-command.test.ts +137 -0
- package/src/__tests__/conversation-clear-safety.test.ts +25 -25
- package/src/__tests__/conversation-confirmation-signals.test.ts +1 -1
- package/src/__tests__/conversation-delete-schedule-cleanup.test.ts +1 -1
- package/src/__tests__/conversation-disk-view-integration.test.ts +2 -2
- package/src/__tests__/conversation-error.test.ts +31 -0
- package/src/__tests__/conversation-fork-crud.test.ts +324 -0
- package/src/__tests__/conversation-lifecycle.test.ts +53 -12
- package/src/__tests__/conversation-load-history-repair.test.ts +1 -1
- package/src/__tests__/conversation-load-history-stripped.test.ts +279 -0
- package/src/__tests__/conversation-pairing.test.ts +2 -2
- package/src/__tests__/conversation-process-callsite.test.ts +1 -1
- package/src/__tests__/conversation-provider-retry-repair.test.ts +2 -1
- package/src/__tests__/conversation-queue.test.ts +1 -1
- package/src/__tests__/conversation-routes-disk-view.test.ts +109 -0
- package/src/__tests__/conversation-routes-slash-commands.test.ts +35 -0
- package/src/__tests__/conversation-runtime-assembly.test.ts +264 -81
- package/src/__tests__/conversation-seed-composer.test.ts +66 -4
- package/src/__tests__/conversation-skill-tools.test.ts +2 -5
- package/src/__tests__/conversation-slash-commands.test.ts +36 -8
- package/src/__tests__/conversation-slash-queue.test.ts +1 -1
- package/src/__tests__/conversation-slash-unknown.test.ts +1 -1
- package/src/__tests__/conversation-speed-override.test.ts +1 -1
- package/src/__tests__/conversation-store.test.ts +1 -1
- package/src/__tests__/conversation-surfaces-task-progress.test.ts +220 -0
- package/src/__tests__/conversation-sync-tags.test.ts +99 -32
- package/src/__tests__/conversation-workspace-cache-state.test.ts +2 -1
- package/src/__tests__/conversation-workspace-injection.test.ts +5 -1
- package/src/__tests__/conversation-workspace-tool-tracking.test.ts +5 -1
- package/src/__tests__/credential-execution-feature-gates.test.ts +9 -7
- package/src/__tests__/credential-execution-tools.test.ts +6 -6
- package/src/__tests__/credential-security-invariants.test.ts +7 -0
- package/src/__tests__/credential-vault-unit.test.ts +2 -2
- package/src/__tests__/cu-unified-flow.test.ts +10 -1
- package/src/__tests__/dm-backfill.test.ts +64 -0
- package/src/__tests__/dm-persistence.test.ts +33 -0
- package/src/__tests__/document-find-replace.test.ts +501 -0
- package/src/__tests__/dynamic-page-surface.test.ts +2 -2
- package/src/__tests__/email-html-renderer.test.ts +12 -0
- package/src/__tests__/first-greeting.test.ts +23 -2
- package/src/__tests__/gateway-flag-listener.test.ts +237 -0
- package/src/__tests__/gemini-provider.test.ts +78 -0
- package/src/__tests__/guardian-dispatch.test.ts +0 -1
- package/src/__tests__/guardian-outbound-http.test.ts +7 -5
- package/src/__tests__/handlers-user-message-approval-consumption.test.ts +1 -1
- package/src/__tests__/headless-browser-navigate.test.ts +172 -0
- package/src/__tests__/heartbeat-disk-pressure.test.ts +4 -0
- package/src/__tests__/heartbeat-service.test.ts +4 -0
- package/src/__tests__/host-bash-proxy.test.ts +6 -0
- package/src/__tests__/host-browser-proxy.test.ts +10 -0
- package/src/__tests__/host-cu-proxy.test.ts +8 -1
- package/src/__tests__/host-file-proxy.test.ts +8 -1
- package/src/__tests__/host-shell-tool.test.ts +1 -1
- package/src/__tests__/host-transfer-proxy.test.ts +8 -1
- package/src/__tests__/identity-routes.test.ts +57 -0
- package/src/__tests__/inbound-slack-persistence.test.ts +3 -0
- package/src/__tests__/init-feature-flag-overrides.test.ts +5 -6
- package/src/__tests__/injector-chain.test.ts +2 -0
- package/src/__tests__/injector-document-comments.test.ts +378 -0
- package/src/__tests__/injector-pkb-v2-silenced.test.ts +4 -25
- package/src/__tests__/list-messages-attachments.test.ts +21 -17
- package/src/__tests__/list-messages-hidden-metadata.test.ts +217 -0
- package/src/__tests__/list-messages-page-latest.test.ts +130 -14
- package/src/__tests__/list-messages-tool-merge.test.ts +77 -17
- package/src/__tests__/llm-context-normalization.test.ts +0 -2
- package/src/__tests__/llm-request-log-call-site.test.ts +136 -0
- package/src/__tests__/llm-request-log-source-clickhouse.test.ts +26 -0
- package/src/__tests__/llm-resolver.test.ts +161 -9
- package/src/__tests__/llm-usage-store.test.ts +66 -0
- package/src/__tests__/log-export-routes.test.ts +99 -2
- package/src/__tests__/logger.test.ts +89 -0
- package/src/__tests__/mcp-abort-signal.test.ts +2 -2
- package/src/__tests__/media-generate-image.test.ts +31 -0
- package/src/__tests__/memory-v2-static-injector.test.ts +7 -7
- package/src/__tests__/message-queue-steer.test.ts +114 -0
- package/src/__tests__/model-intents.test.ts +2 -4
- package/src/__tests__/notification-guardian-path.test.ts +0 -1
- package/src/__tests__/onboarding-template-contract.test.ts +1 -1
- package/src/__tests__/openai-provider.test.ts +151 -0
- package/src/__tests__/openai-responses-provider.test.ts +118 -16
- package/src/__tests__/outbound-slack-persistence.test.ts +187 -20
- package/src/__tests__/pending-interactions-resolved-event.test.ts +189 -0
- package/src/__tests__/platform-bash-auto-approve.test.ts +2 -2
- package/src/__tests__/platform.test.ts +2 -5
- package/src/__tests__/plugin-api-tool-definition.test.ts +92 -0
- package/src/__tests__/plugin-bootstrap.test.ts +2 -2
- package/src/__tests__/plugin-source-watcher.test.ts +302 -0
- package/src/__tests__/plugin-tool-contribution.test.ts +13 -6
- package/src/__tests__/plugin-types.test.ts +3 -2
- package/src/__tests__/prechat-onboarding-contract.test.ts +131 -98
- package/src/__tests__/pricing.test.ts +12 -0
- package/src/__tests__/process-message-background-slack.test.ts +1 -51
- package/src/__tests__/process-message-display-content.test.ts +21 -16
- package/src/__tests__/prune-jobs-changes-parser.test.ts +61 -0
- package/src/__tests__/registry.test.ts +2 -8
- package/src/__tests__/require-fresh-approval.test.ts +2 -2
- package/src/__tests__/runtime-events-sse-bilingual.test.ts +154 -0
- package/src/__tests__/server-history-render.test.ts +83 -4
- package/src/__tests__/shell-tool-proxy-mode.test.ts +1 -1
- package/src/__tests__/skill-feature-flags.test.ts +2 -2
- package/src/__tests__/skill-projection-feature-flag.test.ts +4 -7
- package/src/__tests__/skill-projection.benchmark.test.ts +2 -6
- package/src/__tests__/skill-tool-factory.test.ts +1 -1
- package/src/__tests__/steer-tool-repair.test.ts +249 -0
- package/src/__tests__/subagent-notify-parent.test.ts +1 -1
- package/src/__tests__/suggestion-routes.test.ts +1 -0
- package/src/__tests__/sync-message-contract.test.ts +59 -0
- package/src/__tests__/system-prompt.test.ts +161 -124
- package/src/__tests__/terminal-tools.test.ts +12 -2
- package/src/__tests__/thinking-block-replay.test.ts +113 -0
- package/src/__tests__/thread-backfill.test.ts +370 -22
- package/src/__tests__/tool-approval-handler.test.ts +1 -5
- package/src/__tests__/tool-execute-pipeline.test.ts +2 -2
- package/src/__tests__/tool-execution-pipeline.benchmark.test.ts +2 -5
- package/src/__tests__/tool-executor-lifecycle-events.test.ts +15 -5
- package/src/__tests__/tool-executor.test.ts +89 -53
- package/src/__tests__/tool-grant-request-escalation.test.ts +1 -6
- package/src/__tests__/tool-result-metadata-plumbing.test.ts +167 -0
- package/src/__tests__/trusted-contact-approval-notifier.test.ts +0 -1
- package/src/__tests__/trusted-contact-inline-approval-integration.test.ts +1 -6
- package/src/__tests__/trusted-contact-multichannel.test.ts +0 -1
- package/src/__tests__/twilio-routes.test.ts +1 -1
- package/src/__tests__/ui-file-upload-surface.test.ts +2 -2
- package/src/__tests__/usage-routes.test.ts +3 -0
- package/src/__tests__/verification-control-plane-policy.test.ts +2 -2
- package/src/__tests__/web-fetch.test.ts +2 -2
- package/src/__tests__/workspace-git-service.test.ts +94 -10
- package/src/__tests__/workspace-migration-088-deprecate-background-conversation-override.test.ts +158 -0
- package/src/__tests__/workspace-migration-089-move-memory-tree-out-of-v3.test.ts +86 -0
- package/src/acp/__tests__/prepare-agent-env.test.ts +146 -0
- package/src/acp/prepare-agent-env.ts +78 -0
- package/src/acp/session-manager.ts +1 -1
- package/src/agent/attachments.ts +1 -0
- package/src/agent/loop.ts +65 -20
- package/src/api/README.md +5 -0
- package/src/api/index.ts +4 -0
- package/src/api/package.json +10 -0
- package/src/background-wake/background-wake-routes.test.ts +233 -0
- package/src/background-wake/next-wake.test.ts +289 -0
- package/src/background-wake/next-wake.ts +172 -0
- package/src/background-wake/runtime-registry.ts +24 -0
- package/src/browser/operations.ts +15 -0
- package/src/cli/commands/__tests__/browser.test.ts +23 -5
- package/src/cli/commands/__tests__/conversations-slack.test.ts +572 -0
- package/src/cli/commands/__tests__/domain-register.test.ts +110 -0
- package/src/cli/commands/__tests__/domain-status.test.ts +33 -33
- package/src/cli/commands/__tests__/inference-send.test.ts +108 -5
- package/src/cli/commands/__tests__/memory-v2-compare-render.test.ts +98 -0
- package/src/cli/commands/__tests__/memory-v2.test.ts +10 -12
- package/src/cli/commands/__tests__/memory-v3-render.test.ts +340 -0
- package/src/cli/commands/browser.ts +247 -0
- package/src/cli/commands/conversations.ts +128 -1
- package/src/cli/commands/domain.ts +91 -41
- package/src/cli/commands/inference-providers.ts +147 -1
- package/src/cli/commands/inference.ts +93 -40
- package/src/cli/commands/memory-v2-compare-render.ts +115 -0
- package/src/cli/commands/memory-v2.ts +483 -0
- package/src/cli/commands/memory-v3-render.ts +344 -0
- package/src/cli/commands/memory-v3.ts +316 -0
- package/src/cli/commands/notifications.ts +24 -2
- package/src/cli/program.ts +2 -0
- package/src/cli/utils/conversation-id.ts +17 -5
- package/src/config/assistant-feature-flags.ts +21 -9
- package/src/config/bundled-skills/app-builder/SKILL.md +2 -2
- package/src/config/bundled-skills/document-editor/SKILL.md +124 -0
- package/src/config/bundled-skills/document-editor/TOOLS.json +258 -0
- package/src/config/bundled-skills/document-editor/tools/comment-list.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/comment-reply.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/comment-resolve.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/document-find.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/document-open.ts +12 -0
- package/src/config/bundled-skills/document-editor/tools/document-replace-text.ts +12 -0
- package/src/config/bundled-skills/image-studio/SKILL.md +4 -0
- package/src/config/bundled-skills/image-studio/tools/media-generate-image.ts +2 -2
- package/src/config/bundled-skills/media-processing/SKILL.md +8 -0
- package/src/config/bundled-skills/media-processing/tools/ingest-media.ts +13 -8
- package/src/config/bundled-skills/messaging/tools/messaging-analyze-style.ts +10 -3
- package/src/config/bundled-skills/phone-calls/references/TRANSCRIPTS.md +16 -14
- package/src/config/bundled-skills/playbooks/tools/playbook-create.ts +7 -2
- package/src/config/bundled-skills/playbooks/tools/playbook-update.ts +7 -2
- package/src/config/bundled-skills/schedule/SKILL.md +8 -0
- package/src/config/bundled-tool-registry.ts +24 -12
- package/src/config/call-site-defaults.ts +20 -0
- package/src/config/feature-flag-registry.json +115 -3
- package/src/config/llm-resolver.ts +16 -2
- package/src/config/schemas/__tests__/memory-v2.test.ts +217 -1
- package/src/config/schemas/call-site-catalog.ts +35 -0
- package/src/config/schemas/llm.ts +14 -0
- package/src/config/schemas/memory-v2.ts +294 -1
- package/src/config/schemas/memory.ts +2 -1
- package/src/context/compactor.ts +60 -1
- package/src/context/token-estimator.ts +47 -4
- package/src/context/window-manager.ts +25 -0
- package/src/conversations/__tests__/message-consolidation.test.ts +350 -0
- package/src/conversations/message-consolidation.ts +404 -0
- package/src/credential-health/credential-health-service.ts +34 -19
- package/src/daemon/__tests__/conversation-tool-setup-exclude.test.ts +1 -1
- package/src/daemon/__tests__/conversation-tool-setup.test.ts +66 -6
- package/src/daemon/__tests__/meet-manifest-loader.test.ts +1 -1
- package/src/daemon/__tests__/native-web-search-metadata.test.ts +357 -0
- package/src/daemon/__tests__/web-search-status-text.test.ts +287 -0
- package/src/daemon/conversation-agent-loop-handlers.ts +155 -36
- package/src/daemon/conversation-agent-loop.ts +307 -88
- package/src/daemon/conversation-error.ts +31 -1
- package/src/daemon/conversation-lifecycle.ts +149 -118
- package/src/daemon/conversation-messaging.ts +3 -0
- package/src/daemon/conversation-process.ts +273 -0
- package/src/daemon/conversation-queue-manager.ts +14 -0
- package/src/daemon/conversation-runtime-assembly.ts +145 -84
- package/src/daemon/conversation-slash.ts +37 -5
- package/src/daemon/conversation-surfaces.ts +45 -2
- package/src/daemon/conversation-tool-setup.ts +70 -3
- package/src/daemon/conversation-usage.ts +2 -0
- package/src/daemon/conversation.ts +54 -32
- package/src/daemon/disk-pressure-guard.ts +14 -2
- package/src/daemon/first-greeting.ts +10 -0
- package/src/daemon/handlers/__tests__/config-a2a-accept.test.ts +498 -0
- package/src/daemon/handlers/config-a2a.ts +160 -0
- package/src/daemon/handlers/config-model.test.ts +2 -0
- package/src/daemon/handlers/conversations.ts +90 -3
- package/src/daemon/handlers/shared.ts +92 -29
- package/src/daemon/host-bash-proxy.ts +1 -1
- package/src/daemon/host-browser-proxy.ts +5 -5
- package/src/daemon/host-cu-proxy.ts +5 -5
- package/src/daemon/host-file-proxy.ts +5 -5
- package/src/daemon/host-proxy-base.ts +4 -4
- package/src/daemon/host-transfer-proxy.ts +11 -11
- package/src/daemon/lifecycle.ts +40 -23
- package/src/daemon/meet-manifest-loader.ts +1 -7
- package/src/daemon/message-protocol.ts +4 -0
- package/src/daemon/message-types/conversations.ts +14 -9
- package/src/daemon/message-types/document-comments.ts +50 -0
- package/src/daemon/message-types/home.ts +1 -13
- package/src/daemon/message-types/messages.ts +66 -7
- package/src/daemon/message-types/surfaces.ts +3 -1
- package/src/daemon/message-types/sync.ts +14 -0
- package/src/daemon/message-types/web-activity.ts +57 -0
- package/src/daemon/plugin-source-watcher.ts +135 -3
- package/src/daemon/process-message.ts +69 -12
- package/src/daemon/shutdown-handlers.ts +24 -5
- package/src/daemon/switch-inference-profile-tool.ts +52 -0
- package/src/daemon/tool-setup-types.ts +13 -0
- package/src/daemon/trust-context.ts +6 -0
- package/src/documents/document-comments-store.test.ts +338 -0
- package/src/documents/document-comments-store.ts +237 -0
- package/src/documents/document-store.ts +202 -0
- package/src/events/relationship-state-updated.ts +25 -0
- package/src/heartbeat/__tests__/heartbeat-service.test.ts +1 -2
- package/src/heartbeat/heartbeat-service.ts +1 -0
- package/src/home/__tests__/suggested-prompts.test.ts +33 -2
- package/src/home/feed-types.ts +6 -1
- package/src/home/home-content-refresh.ts +52 -0
- package/src/home/home-greeting-cache.ts +69 -0
- package/src/home/home-greeting.ts +85 -0
- package/src/home/suggested-prompts.ts +168 -9
- package/src/ipc/gateway-flag-listener.ts +123 -0
- package/src/ipc/skill-routes/registries.ts +8 -12
- package/src/memory/__tests__/db-async-query.test.ts +165 -0
- package/src/memory/__tests__/db-maintenance.test.ts +115 -0
- package/src/memory/__tests__/jobs-store-enqueue-gate.test.ts +241 -0
- package/src/memory/__tests__/jobs-store-job-classes.test.ts +28 -1
- package/src/memory/__tests__/jobs-worker-v2-schedule.test.ts +135 -2
- package/src/memory/__tests__/memory-retrospective-job.test.ts +327 -6
- package/src/memory/auto-analysis-enqueue.ts +5 -1
- package/src/memory/conversation-crud.ts +191 -100
- package/src/memory/conversation-starters-cadence.ts +3 -1
- package/src/memory/conversation-title-service.ts +19 -3
- package/src/memory/db-async-query.ts +214 -0
- package/src/memory/db-init.ts +26 -0
- package/src/memory/db-maintenance.ts +30 -21
- package/src/memory/delivery-crud.ts +41 -0
- package/src/memory/delivery-status.ts +141 -15
- package/src/memory/external-conversation-store.ts +32 -1
- package/src/memory/graph/bootstrap.ts +8 -1
- package/src/memory/graph/capability-seed.ts +7 -3
- package/src/memory/graph/conversation-graph-memory.ts +100 -17
- package/src/memory/graph/extraction.ts +1 -5
- package/src/memory/graph/graph-search.ts +7 -1
- package/src/memory/indexer.ts +28 -18
- package/src/memory/job-handlers/cleanup.ts +76 -18
- package/src/memory/job-handlers/conversation-starters.ts +1 -4
- package/src/memory/jobs/embed-pkb-file.ts +6 -1
- package/src/memory/jobs-store.ts +14 -0
- package/src/memory/jobs-worker.ts +68 -15
- package/src/memory/llm-request-log-source-clickhouse.ts +42 -2
- package/src/memory/llm-request-log-source-local.ts +7 -0
- package/src/memory/llm-request-log-source.ts +9 -2
- package/src/memory/llm-request-log-store.ts +43 -1
- package/src/memory/llm-usage-store.ts +24 -0
- package/src/memory/memory-retrospective-constants.ts +28 -0
- package/src/memory/memory-retrospective-enqueue.ts +11 -3
- package/src/memory/memory-retrospective-job.ts +413 -18
- package/src/memory/memory-retrospective-startup-cleanup.ts +3 -3
- package/src/memory/memory-v2-activation-log-store.ts +41 -14
- package/src/memory/migrations/100-core-tables.ts +1 -0
- package/src/memory/migrations/109-external-conversation-bindings.ts +1 -0
- package/src/memory/migrations/253-conversation-last-notified-profile.ts +15 -0
- package/src/memory/migrations/253-document-comments.ts +47 -0
- package/src/memory/migrations/254-external-conversation-binding-chat-name.ts +43 -0
- package/src/memory/migrations/255-channel-inbound-delivery-attempts.ts +24 -0
- package/src/memory/migrations/256-memory-v2-injection-events.ts +113 -0
- package/src/memory/migrations/257-strip-base-url-non-openai-compatible.ts +22 -0
- package/src/memory/migrations/258-onboarding-events-prior-assistants.ts +13 -0
- package/src/memory/migrations/259-conversation-cleaned-at.ts +33 -0
- package/src/memory/migrations/260-rename-cleaned-at.ts +44 -0
- package/src/memory/migrations/261-llm-usage-add-raw-usage.ts +36 -0
- package/src/memory/migrations/262-memory-v3-coactivation.ts +57 -0
- package/src/memory/migrations/263-memory-v3-auto-edges.ts +50 -0
- package/src/memory/migrations/264-llm-request-log-call-site.ts +29 -0
- package/src/memory/migrations/index.ts +34 -0
- package/src/memory/migrations/registry.ts +58 -0
- package/src/memory/onboarding-events-store.ts +7 -0
- package/src/memory/schema/calls.ts +1 -0
- package/src/memory/schema/conversations.ts +3 -0
- package/src/memory/schema/infrastructure.ts +22 -0
- package/src/memory/tool-usage-store.ts +36 -8
- package/src/memory/v2/__tests__/consolidation-job.test.ts +1 -0
- package/src/memory/v2/__tests__/harness-compare.test.ts +186 -0
- package/src/memory/v2/__tests__/harness-metrics.test.ts +74 -0
- package/src/memory/v2/__tests__/harness-oracle.test.ts +257 -0
- package/src/memory/v2/__tests__/harness-replay-input.test.ts +225 -0
- package/src/memory/v2/__tests__/harness-runner.test.ts +109 -0
- package/src/memory/v2/__tests__/injection-events.test.ts +318 -0
- package/src/memory/v2/__tests__/injection.test.ts +158 -112
- package/src/memory/v2/__tests__/page-index.test.ts +365 -1
- package/src/memory/v2/__tests__/qdrant.test.ts +36 -0
- package/src/memory/v2/__tests__/router.test.ts +660 -4
- package/src/memory/v2/consolidation-job.ts +14 -0
- package/src/memory/v2/harness/compare.ts +57 -0
- package/src/memory/v2/harness/metrics.ts +124 -0
- package/src/memory/v2/harness/oracle.ts +145 -0
- package/src/memory/v2/harness/replay-input.ts +224 -0
- package/src/memory/v2/harness/retriever.ts +74 -0
- package/src/memory/v2/harness/router-retriever.ts +43 -0
- package/src/memory/v2/harness/runner.ts +106 -0
- package/src/memory/v2/harness/trace.ts +58 -0
- package/src/memory/v2/injection-events.ts +101 -0
- package/src/memory/v2/injection.ts +42 -25
- package/src/memory/v2/page-index.ts +209 -7
- package/src/memory/v2/page-store.ts +18 -0
- package/src/memory/v2/prompts/router.ts +26 -1
- package/src/memory/v2/qdrant.ts +14 -2
- package/src/memory/v2/router.ts +369 -62
- package/src/memory/v3/__tests__/coactivation-store.test.ts +422 -0
- package/src/memory/v3/__tests__/consolidation-job.test.ts +468 -0
- package/src/memory/v3/__tests__/edge-learning-job.test.ts +324 -0
- package/src/memory/v3/__tests__/edges.test.ts +563 -0
- package/src/memory/v3/__tests__/filter.test.ts +512 -0
- package/src/memory/v3/__tests__/gate.test.ts +574 -0
- package/src/memory/v3/__tests__/index-composition.test.ts +233 -0
- package/src/memory/v3/__tests__/loop.test.ts +530 -0
- package/src/memory/v3/__tests__/retriever.test.ts +226 -0
- package/src/memory/v3/__tests__/scouts.test.ts +440 -0
- package/src/memory/v3/__tests__/shadow-middleware.test.ts +312 -0
- package/src/memory/v3/__tests__/system-prompts.test.ts +154 -0
- package/src/memory/v3/__tests__/traversal.test.ts +469 -0
- package/src/memory/v3/__tests__/tree-index.test.ts +280 -0
- package/src/memory/v3/__tests__/tree-store.test.ts +529 -0
- package/src/memory/v3/__tests__/tree-walk.test.ts +707 -0
- package/src/memory/v3/__tests__/validate.test.ts +245 -0
- package/src/memory/v3/auto-edges.ts +223 -0
- package/src/memory/v3/coactivation-store.ts +124 -0
- package/src/memory/v3/consolidation-job.ts +323 -0
- package/src/memory/v3/edge-learning-job.ts +160 -0
- package/src/memory/v3/edges.ts +249 -0
- package/src/memory/v3/filter.ts +281 -0
- package/src/memory/v3/gate.ts +334 -0
- package/src/memory/v3/index-composition.ts +113 -0
- package/src/memory/v3/llm-capture.ts +46 -0
- package/src/memory/v3/loop.ts +382 -0
- package/src/memory/v3/maintenance.ts +144 -0
- package/src/memory/v3/prompt-context.ts +33 -0
- package/src/memory/v3/prompts/consolidation.ts +458 -0
- package/src/memory/v3/prompts/system-prompts.ts +196 -0
- package/src/memory/v3/retriever.ts +33 -0
- package/src/memory/v3/scouts.ts +420 -0
- package/src/memory/v3/shadow-middleware.ts +305 -0
- package/src/memory/v3/traversal.ts +206 -0
- package/src/memory/v3/tree-index.ts +237 -0
- package/src/memory/v3/tree-store.ts +394 -0
- package/src/memory/v3/tree-walk.ts +351 -0
- package/src/memory/v3/types.ts +65 -0
- package/src/memory/v3/validate.ts +300 -0
- package/src/messaging/providers/index.ts +7 -1
- package/src/messaging/providers/slack/__tests__/adapter-mention-rendering.test.ts +329 -3
- package/src/messaging/providers/slack/__tests__/adapter-token-routing.test.ts +34 -1
- package/src/messaging/providers/slack/adapter.ts +178 -25
- package/src/messaging/providers/slack/api.test.ts +54 -0
- package/src/messaging/providers/slack/api.ts +119 -3
- package/src/messaging/providers/slack/client.ts +12 -0
- package/src/messaging/providers/slack/deep-link.ts +20 -1
- package/src/messaging/providers/slack/message-metadata.test.ts +48 -0
- package/src/messaging/providers/slack/message-metadata.ts +156 -0
- package/src/messaging/providers/slack/render-transcript.test.ts +107 -75
- package/src/messaging/providers/slack/render-transcript.ts +176 -49
- package/src/messaging/providers/slack/send.test.ts +77 -0
- package/src/messaging/providers/slack/send.ts +8 -2
- package/src/messaging/providers/slack/types.ts +14 -0
- package/src/notifications/__tests__/emit-signal-home-feed.test.ts +4 -1
- package/src/notifications/__tests__/home-feed-side-effect.test.ts +116 -54
- package/src/notifications/adapters/macos.ts +18 -1
- package/src/notifications/adapters/platform.ts +1 -1
- package/src/notifications/conversation-seed-composer.ts +14 -2
- package/src/notifications/decision-engine.ts +1 -4
- package/src/notifications/deferred-emit.ts +135 -0
- package/src/notifications/emit-signal.ts +38 -50
- package/src/notifications/home-feed-side-effect.ts +60 -30
- package/src/oauth/connect-orchestrator.ts +3 -0
- package/src/oauth/credential-token-resolver.ts +2 -0
- package/src/oauth/manual-token-connection.ts +19 -0
- package/src/oauth/oauth-store.ts +12 -0
- package/src/oauth/seed-providers.ts +22 -0
- package/src/permissions/prompter.ts +8 -5
- package/src/permissions/question-prompter.ts +5 -2
- package/src/permissions/secret-prompter.ts +6 -3
- package/src/plugin-api/index.ts +4 -0
- package/src/plugin-api/types.ts +7 -33
- package/src/plugins/defaults/index.ts +6 -0
- package/src/plugins/defaults/injectors.ts +100 -20
- package/src/plugins/external-plugin-loader.ts +5 -68
- package/src/plugins/types.ts +11 -16
- package/src/proactive-artifact/aux-message-injector.ts +17 -4
- package/src/prompts/__tests__/system-prompt.test.ts +46 -2
- package/src/prompts/__tests__/task-progress-hint-section.test.ts +3 -9
- package/src/prompts/normalize-onboarding.ts +40 -0
- package/src/prompts/persona-resolver.ts +36 -21
- package/src/prompts/sections.ts +69 -19
- package/src/prompts/system-prompt.ts +118 -216
- package/src/prompts/template-detection.ts +37 -0
- package/src/prompts/templates/BOOTSTRAP-CONTENT-AUTOMATION.md +141 -0
- package/src/prompts/templates/BOOTSTRAP.md +10 -2
- package/src/prompts/templates/VOICE.md +3 -0
- package/src/prompts/templates/system-sections.ts +281 -9
- package/src/providers/__tests__/connection-model-compat.test.ts +234 -0
- package/src/providers/__tests__/retry-callsite.test.ts +85 -5
- package/src/providers/anthropic/client.ts +159 -66
- package/src/providers/call-site-routing.ts +14 -2
- package/src/providers/connection-model-compat.ts +38 -0
- package/src/providers/connection-resolution.ts +16 -2
- package/src/providers/fireworks/client.ts +20 -2
- package/src/providers/gemini/client.ts +49 -6
- package/src/providers/inference/__tests__/base-url-route-validation.test.ts +342 -0
- package/src/providers/inference/__tests__/base-url-security.test.ts +189 -0
- package/src/providers/inference/__tests__/codex-token-refresh.test.ts +254 -0
- package/src/providers/inference/adapter-factory.ts +18 -1
- package/src/providers/inference/auth.ts +3 -3
- package/src/providers/inference/codex-token-refresh.ts +128 -0
- package/src/providers/inference/resolve-auth.ts +49 -6
- package/src/providers/minimax/client.ts +106 -0
- package/src/providers/model-catalog.ts +91 -1
- package/src/providers/model-intents.ts +1 -1
- package/src/providers/openai/chat-completions-provider.ts +63 -23
- package/src/providers/openai/codex-models.ts +18 -0
- package/src/providers/openai/responses-provider.ts +86 -23
- package/src/providers/openrouter/client.ts +5 -1
- package/src/providers/provider-send-message.ts +7 -1
- package/src/providers/retry.ts +34 -3
- package/src/providers/thinking-config.ts +26 -1
- package/src/providers/types.ts +25 -0
- package/src/providers/usage-tracking.ts +2 -0
- package/src/runtime/AGENTS.md +2 -2
- package/src/runtime/__tests__/agent-wake.test.ts +214 -0
- package/src/runtime/__tests__/background-job-runner.test.ts +128 -0
- package/src/runtime/agent-wake.ts +152 -56
- package/src/runtime/assistant-event-hub.ts +76 -6
- package/src/runtime/auth/route-policy.ts +43 -3
- package/src/runtime/background-job-runner.ts +26 -0
- package/src/runtime/btw-sidechain.ts +0 -6
- package/src/runtime/channel-reply-delivery.ts +182 -47
- package/src/runtime/channel-retry-sweep.ts +141 -16
- package/src/runtime/http-types.ts +7 -6
- package/src/runtime/migrations/vbundle-builder.ts +10 -3
- package/src/runtime/pending-interactions.ts +50 -8
- package/src/runtime/routes/__tests__/content-source-routes.test.ts +162 -0
- package/src/runtime/routes/__tests__/conversation-query-routes.test.ts +161 -1
- package/src/runtime/routes/__tests__/memory-v2-routes.test.ts +14 -0
- package/src/runtime/routes/__tests__/memory-v2-simulate-route.test.ts +290 -0
- package/src/runtime/routes/__tests__/plugins-routes.test.ts +512 -0
- package/src/runtime/routes/__tests__/sanity-routes.test.ts +280 -0
- package/src/runtime/routes/__tests__/slack-channel-routes.test.ts +266 -0
- package/src/runtime/routes/acp-routes.test.ts +255 -6
- package/src/runtime/routes/acp-routes.ts +8 -1
- package/src/runtime/routes/approval-routes.ts +4 -1
- package/src/runtime/routes/avatar-routes.ts +10 -10
- package/src/runtime/routes/background-wake-routes.ts +188 -0
- package/src/runtime/routes/browser-tabs-routes.ts +200 -0
- package/src/runtime/routes/btw-routes.ts +0 -6
- package/src/runtime/routes/chatgpt-subscription-auth-routes.ts +246 -0
- package/src/runtime/routes/content-source-routes.ts +78 -0
- package/src/runtime/routes/conversation-cli-routes.ts +147 -2
- package/src/runtime/routes/conversation-list-routes.ts +12 -4
- package/src/runtime/routes/conversation-management-routes.ts +77 -20
- package/src/runtime/routes/conversation-query-routes.ts +196 -31
- package/src/runtime/routes/conversation-routes.ts +472 -425
- package/src/runtime/routes/conversation-starter-routes.ts +6 -3
- package/src/runtime/routes/disk-pressure-routes.ts +1 -1
- package/src/runtime/routes/document-comments-routes.ts +287 -0
- package/src/runtime/routes/documents-routes.ts +33 -0
- package/src/runtime/routes/domain-routes.ts +60 -10
- package/src/runtime/routes/email-routes.ts +5 -2
- package/src/runtime/routes/events-routes.ts +54 -10
- package/src/runtime/routes/group-routes.ts +24 -8
- package/src/runtime/routes/home-feed-routes.ts +6 -3
- package/src/runtime/routes/host-app-control-routes.ts +1 -1
- package/src/runtime/routes/host-browser-routes.ts +17 -2
- package/src/runtime/routes/host-cu-routes.ts +2 -2
- package/src/runtime/routes/identity-routes.ts +21 -0
- package/src/runtime/routes/inbound-message-handler.ts +288 -58
- package/src/runtime/routes/inbound-stages/acl-enforcement.ts +96 -3
- package/src/runtime/routes/inbound-stages/background-dispatch.test.ts +365 -6
- package/src/runtime/routes/inbound-stages/background-dispatch.ts +283 -82
- package/src/runtime/routes/index.ts +20 -4
- package/src/runtime/routes/inference-profile-session-handler.ts +22 -12
- package/src/runtime/routes/inference-profile-session-routes.ts +7 -1
- package/src/runtime/routes/inference-provider-connection-routes.ts +63 -7
- package/src/runtime/routes/integrations/a2a.ts +60 -1
- package/src/runtime/routes/llm-call-sites-routes.ts +32 -5
- package/src/runtime/routes/log-export-routes.ts +39 -0
- package/src/runtime/routes/memory-item-routes.ts +8 -3
- package/src/runtime/routes/memory-v2-routes.ts +427 -0
- package/src/runtime/routes/memory-v3-routes.ts +316 -0
- package/src/runtime/routes/migration-routes.ts +21 -24
- package/src/runtime/routes/notification-routes.ts +19 -2
- package/src/runtime/routes/plugins-routes.ts +337 -0
- package/src/runtime/routes/question-routes.ts +4 -1
- package/src/runtime/routes/rename-conversation-routes.ts +6 -2
- package/src/runtime/routes/sanity-routes.ts +159 -0
- package/src/runtime/routes/secret-routes.ts +25 -5
- package/src/runtime/routes/settings-routes.ts +12 -11
- package/src/runtime/routes/slack-channel-routes.ts +188 -0
- package/src/runtime/routes/workspace-routes.ts +25 -10
- package/src/runtime/services/conversation-serializer.ts +30 -4
- package/src/runtime/sync/resource-sync-events.ts +106 -38
- package/src/runtime/sync/sync-publisher.test.ts +49 -0
- package/src/runtime/sync/sync-publisher.ts +2 -1
- package/src/runtime/verification-outbound-actions.ts +73 -1
- package/src/schedule/integration-status.ts +3 -1
- package/src/security/__tests__/oauth2-device-code.test.ts +479 -0
- package/src/security/oauth2-device-code.ts +307 -0
- package/src/security/oauth2.ts +26 -9
- package/src/security/secure-keys.ts +5 -0
- package/src/skills/catalog-install.ts +6 -2
- package/src/telemetry/types.ts +12 -0
- package/src/telemetry/usage-telemetry-reporter.test.ts +48 -0
- package/src/telemetry/usage-telemetry-reporter.ts +1 -0
- package/src/tools/acp/spawn.test.ts +119 -0
- package/src/tools/acp/spawn.ts +15 -2
- package/src/tools/apps/definitions.ts +2 -8
- package/src/tools/ask-question/ask-question-tool.test.ts +3 -3
- package/src/tools/ask-question/ask-question-tool.ts +38 -45
- package/src/tools/browser/__tests__/pinned-tabs.test.ts +150 -0
- package/src/tools/browser/browser-execution.ts +106 -0
- package/src/tools/browser/cdp-client/__tests__/browser-tabs-factory.test.ts +402 -0
- package/src/tools/browser/cdp-client/__tests__/factory.test.ts +28 -0
- package/src/tools/browser/cdp-client/__tests__/types.test.ts +4 -0
- package/src/tools/browser/cdp-client/cdp-inspect-client.ts +22 -0
- package/src/tools/browser/cdp-client/extension-cdp-client.ts +42 -2
- package/src/tools/browser/cdp-client/factory.ts +171 -4
- package/src/tools/browser/cdp-client/local-cdp-client.ts +21 -0
- package/src/tools/browser/cdp-client/types.ts +101 -0
- package/src/tools/browser/pinned-tabs.ts +146 -0
- package/src/tools/computer-use/definitions.ts +22 -78
- package/src/tools/credential-execution/make-authenticated-request.ts +3 -9
- package/src/tools/credential-execution/manage-secure-command-tool.ts +3 -9
- package/src/tools/credential-execution/run-authenticated-command.ts +3 -9
- package/src/tools/credentials/vault.ts +3 -9
- package/src/tools/document/document-comment-tool.test.ts +379 -0
- package/src/tools/document/document-comment-tool.ts +156 -0
- package/src/tools/document/document-tool.ts +187 -2
- package/src/tools/execution-target.ts +21 -23
- package/src/tools/executor.ts +6 -1
- package/src/tools/filesystem/edit.ts +3 -9
- package/src/tools/filesystem/list.ts +3 -9
- package/src/tools/filesystem/read.ts +3 -9
- package/src/tools/filesystem/write.ts +3 -9
- package/src/tools/host-filesystem/edit.ts +3 -9
- package/src/tools/host-filesystem/read.ts +3 -9
- package/src/tools/host-filesystem/transfer.ts +3 -9
- package/src/tools/host-filesystem/write.ts +3 -9
- package/src/tools/host-terminal/host-shell.ts +3 -9
- package/src/tools/mcp/mcp-tool-factory.ts +1 -8
- package/src/tools/memory/register.test.ts +1 -1
- package/src/tools/memory/register.ts +4 -9
- package/src/tools/network/__tests__/web-fetch-metadata.test.ts +229 -0
- package/src/tools/network/__tests__/web-search-metadata.test.ts +346 -0
- package/src/tools/network/domain-normalize.ts +17 -0
- package/src/tools/network/web-fetch.ts +216 -73
- package/src/tools/network/web-search.ts +216 -98
- package/src/tools/registry.ts +7 -23
- package/src/tools/schema-transforms.ts +1 -1
- package/src/tools/skills/execute.ts +3 -9
- package/src/tools/skills/load.ts +3 -9
- package/src/tools/skills/skill-tool-factory.ts +1 -8
- package/src/tools/subagent/notify-parent.ts +3 -9
- package/src/tools/system/request-permission.ts +3 -9
- package/src/tools/terminal/safe-env.ts +3 -2
- package/src/tools/terminal/shell.ts +3 -9
- package/src/tools/tool-approval-handler.ts +19 -12
- package/src/tools/tool-defaults.ts +94 -0
- package/src/tools/types.ts +31 -98
- package/src/tools/ui-surface/definitions.ts +9 -23
- package/src/types/onboarding-context.ts +4 -0
- package/src/usage/pricing.ts +23 -0
- package/src/usage/types.ts +12 -0
- package/src/util/__tests__/favicon.test.ts +84 -0
- package/src/util/favicon.ts +40 -0
- package/src/util/logger.ts +16 -7
- package/src/util/platform.ts +7 -7
- package/src/util/sqlite3-runtime.ts +65 -0
- package/src/workspace/git-service.ts +75 -4
- package/src/workspace/migrations/086-revert-stale-gemini-mis-rewrites.ts +1 -0
- package/src/workspace/migrations/088-deprecate-background-conversation-override.ts +103 -0
- package/src/workspace/migrations/089-move-memory-tree-out-of-v3.ts +86 -0
- package/src/workspace/migrations/registry.ts +4 -0
- package/src/__tests__/compaction-strip-metadata-clear.test.ts +0 -206
- package/src/__tests__/message-complete-display-id.test.ts +0 -175
- package/src/config/bundled-skills/document/SKILL.md +0 -54
- package/src/config/bundled-skills/document/TOOLS.json +0 -106
- package/src/daemon/seed-files.ts +0 -18
- package/src/prompts/cache-boundary.ts +0 -8
- package/src/runtime/routes/interface-routes.ts +0 -43
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-create.ts +0 -0
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-delete.ts +0 -0
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-list.ts +0 -0
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-read.ts +0 -0
- /package/src/config/bundled-skills/{document → document-editor}/tools/document-update.ts +0 -0
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OAuth2 Device Authorization Grant (RFC 8628).
|
|
3
|
+
*
|
|
4
|
+
* Implements the device-code flow for environments where a browser redirect
|
|
5
|
+
* is impractical (CLI, headless). The user visits a verification URI and
|
|
6
|
+
* enters a short code; meanwhile, the client polls the token endpoint until
|
|
7
|
+
* authorization completes.
|
|
8
|
+
*
|
|
9
|
+
* This is intentionally separate from the PKCE authorization code flow in
|
|
10
|
+
* oauth2.ts — different grant type, different UX (no localhost server), and
|
|
11
|
+
* different polling lifecycle.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { getLogger } from "../util/logger.js";
|
|
15
|
+
|
|
16
|
+
const log = getLogger("oauth2-device-code");
|
|
17
|
+
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
// Types
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
|
|
22
|
+
export interface DeviceCodeConfig {
|
|
23
|
+
deviceCodeUrl: string;
|
|
24
|
+
tokenUrl: string;
|
|
25
|
+
clientId: string;
|
|
26
|
+
scopes: string[];
|
|
27
|
+
audience?: string;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface DeviceCodeInitResult {
|
|
31
|
+
deviceCode: string;
|
|
32
|
+
userCode: string;
|
|
33
|
+
verificationUri: string;
|
|
34
|
+
verificationUriComplete?: string;
|
|
35
|
+
expiresIn: number;
|
|
36
|
+
interval: number;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface DeviceCodeTokenResult {
|
|
40
|
+
accessToken: string;
|
|
41
|
+
refreshToken?: string;
|
|
42
|
+
expiresIn?: number;
|
|
43
|
+
tokenType?: string;
|
|
44
|
+
scope?: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export class DeviceCodeError extends Error {
|
|
48
|
+
constructor(
|
|
49
|
+
message: string,
|
|
50
|
+
public readonly code:
|
|
51
|
+
| "expired_token"
|
|
52
|
+
| "access_denied"
|
|
53
|
+
| "request_failed"
|
|
54
|
+
| "aborted",
|
|
55
|
+
) {
|
|
56
|
+
super(message);
|
|
57
|
+
this.name = "DeviceCodeError";
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// ---------------------------------------------------------------------------
|
|
62
|
+
// Well-known provider configs
|
|
63
|
+
// ---------------------------------------------------------------------------
|
|
64
|
+
|
|
65
|
+
export const OPENAI_DEVICE_CODE_CONFIG: DeviceCodeConfig = {
|
|
66
|
+
deviceCodeUrl: "https://auth.openai.com/oauth/device/code",
|
|
67
|
+
tokenUrl: "https://auth.openai.com/oauth/token",
|
|
68
|
+
clientId: "app_EMoamEEZ73f0CkXaXp7hrann",
|
|
69
|
+
scopes: ["openid", "profile", "email", "offline_access"],
|
|
70
|
+
audience: "https://chatgpt.com",
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
// ---------------------------------------------------------------------------
|
|
74
|
+
// Device code request
|
|
75
|
+
// ---------------------------------------------------------------------------
|
|
76
|
+
|
|
77
|
+
export async function requestDeviceCode(
|
|
78
|
+
config: DeviceCodeConfig,
|
|
79
|
+
): Promise<DeviceCodeInitResult> {
|
|
80
|
+
const body: Record<string, string> = {
|
|
81
|
+
client_id: config.clientId,
|
|
82
|
+
scope: config.scopes.join(" "),
|
|
83
|
+
};
|
|
84
|
+
if (config.audience) {
|
|
85
|
+
body.audience = config.audience;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const resp = await fetch(config.deviceCodeUrl, {
|
|
89
|
+
method: "POST",
|
|
90
|
+
headers: {
|
|
91
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
92
|
+
Accept: "application/json",
|
|
93
|
+
},
|
|
94
|
+
body: new URLSearchParams(body),
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
if (!resp.ok) {
|
|
98
|
+
const rawBody = await resp.text().catch(() => "");
|
|
99
|
+
log.error(
|
|
100
|
+
{ status: resp.status, body: rawBody },
|
|
101
|
+
"Device code request failed",
|
|
102
|
+
);
|
|
103
|
+
throw new DeviceCodeError(
|
|
104
|
+
`Device code request failed (HTTP ${resp.status})`,
|
|
105
|
+
"request_failed",
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const data = (await resp.json()) as Record<string, unknown>;
|
|
110
|
+
|
|
111
|
+
return {
|
|
112
|
+
deviceCode: data.device_code as string,
|
|
113
|
+
userCode: data.user_code as string,
|
|
114
|
+
verificationUri: data.verification_uri as string,
|
|
115
|
+
verificationUriComplete: data.verification_uri_complete as
|
|
116
|
+
| string
|
|
117
|
+
| undefined,
|
|
118
|
+
expiresIn: data.expires_in as number,
|
|
119
|
+
interval: (data.interval as number | undefined) ?? 5,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// ---------------------------------------------------------------------------
|
|
124
|
+
// Token polling
|
|
125
|
+
// ---------------------------------------------------------------------------
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Poll the token endpoint until the user completes authorization or the
|
|
129
|
+
* device code expires.
|
|
130
|
+
*
|
|
131
|
+
* Handles RFC 8628 error codes:
|
|
132
|
+
* - `authorization_pending` — keep polling
|
|
133
|
+
* - `slow_down` — increase interval by 5 seconds (per spec)
|
|
134
|
+
* - `expired_token` — abort with error
|
|
135
|
+
* - `access_denied` — abort with error
|
|
136
|
+
*/
|
|
137
|
+
export async function pollForToken(
|
|
138
|
+
config: DeviceCodeConfig,
|
|
139
|
+
deviceCode: string,
|
|
140
|
+
intervalSeconds: number,
|
|
141
|
+
expiresIn: number,
|
|
142
|
+
signal?: AbortSignal,
|
|
143
|
+
/** @internal Test-only: override the sleep function to avoid real delays. */
|
|
144
|
+
_sleepFn?: (ms: number, signal?: AbortSignal) => Promise<void>,
|
|
145
|
+
): Promise<DeviceCodeTokenResult> {
|
|
146
|
+
const doSleep = _sleepFn ?? sleep;
|
|
147
|
+
let interval = intervalSeconds;
|
|
148
|
+
const deadline = Date.now() + expiresIn * 1000;
|
|
149
|
+
|
|
150
|
+
while (Date.now() < deadline) {
|
|
151
|
+
if (signal?.aborted) {
|
|
152
|
+
throw new DeviceCodeError("Device code flow aborted", "aborted");
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
await doSleep(interval * 1000, signal);
|
|
156
|
+
|
|
157
|
+
if (signal?.aborted) {
|
|
158
|
+
throw new DeviceCodeError("Device code flow aborted", "aborted");
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const body = new URLSearchParams({
|
|
162
|
+
grant_type: "urn:ietf:params:oauth:grant-type:device_code",
|
|
163
|
+
device_code: deviceCode,
|
|
164
|
+
client_id: config.clientId,
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
let resp: Response;
|
|
168
|
+
try {
|
|
169
|
+
resp = await fetch(config.tokenUrl, {
|
|
170
|
+
method: "POST",
|
|
171
|
+
headers: {
|
|
172
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
173
|
+
Accept: "application/json",
|
|
174
|
+
},
|
|
175
|
+
body,
|
|
176
|
+
signal,
|
|
177
|
+
});
|
|
178
|
+
} catch (err) {
|
|
179
|
+
if (signal?.aborted) {
|
|
180
|
+
throw new DeviceCodeError("Device code flow aborted", "aborted");
|
|
181
|
+
}
|
|
182
|
+
log.warn({ err }, "Token poll request failed, will retry");
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
const data = (await resp.json()) as Record<string, unknown>;
|
|
187
|
+
|
|
188
|
+
if (resp.ok) {
|
|
189
|
+
log.info("Device code authorization completed");
|
|
190
|
+
return {
|
|
191
|
+
accessToken: data.access_token as string,
|
|
192
|
+
refreshToken: data.refresh_token as string | undefined,
|
|
193
|
+
expiresIn: data.expires_in as number | undefined,
|
|
194
|
+
tokenType: data.token_type as string | undefined,
|
|
195
|
+
scope: data.scope as string | undefined,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
const errorCode = data.error as string | undefined;
|
|
200
|
+
|
|
201
|
+
if (errorCode === "authorization_pending") {
|
|
202
|
+
log.debug("Authorization pending, continuing to poll");
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
if (errorCode === "slow_down") {
|
|
207
|
+
interval += 5;
|
|
208
|
+
log.info({ newInterval: interval }, "Received slow_down, increasing poll interval");
|
|
209
|
+
continue;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (errorCode === "expired_token") {
|
|
213
|
+
throw new DeviceCodeError(
|
|
214
|
+
"Device code expired before user completed authorization",
|
|
215
|
+
"expired_token",
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
if (errorCode === "access_denied") {
|
|
220
|
+
throw new DeviceCodeError(
|
|
221
|
+
"User denied the authorization request",
|
|
222
|
+
"access_denied",
|
|
223
|
+
);
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
log.error(
|
|
227
|
+
{ status: resp.status, error: errorCode },
|
|
228
|
+
"Unexpected token poll error",
|
|
229
|
+
);
|
|
230
|
+
throw new DeviceCodeError(
|
|
231
|
+
`Token poll failed: ${errorCode ?? `HTTP ${resp.status}`}`,
|
|
232
|
+
"request_failed",
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
throw new DeviceCodeError(
|
|
237
|
+
"Device code expired before user completed authorization",
|
|
238
|
+
"expired_token",
|
|
239
|
+
);
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
// ---------------------------------------------------------------------------
|
|
243
|
+
// Combined flow
|
|
244
|
+
// ---------------------------------------------------------------------------
|
|
245
|
+
|
|
246
|
+
export interface DeviceCodeFlowResult {
|
|
247
|
+
tokens: DeviceCodeTokenResult;
|
|
248
|
+
init: DeviceCodeInitResult;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Run the full device-code flow:
|
|
253
|
+
* 1. Request a device code + user code
|
|
254
|
+
* 2. Return the user code and verification URI (caller shows these to the user)
|
|
255
|
+
* 3. Poll for the token
|
|
256
|
+
*
|
|
257
|
+
* The returned `init` contains the user code and verification URI that the
|
|
258
|
+
* caller should present to the user before awaiting `tokens`.
|
|
259
|
+
*/
|
|
260
|
+
export async function startDeviceCodeFlow(
|
|
261
|
+
config: DeviceCodeConfig,
|
|
262
|
+
signal?: AbortSignal,
|
|
263
|
+
): Promise<DeviceCodeFlowResult> {
|
|
264
|
+
const init = await requestDeviceCode(config);
|
|
265
|
+
|
|
266
|
+
log.info(
|
|
267
|
+
{
|
|
268
|
+
verificationUri: init.verificationUri,
|
|
269
|
+
expiresIn: init.expiresIn,
|
|
270
|
+
interval: init.interval,
|
|
271
|
+
},
|
|
272
|
+
"Device code flow started",
|
|
273
|
+
);
|
|
274
|
+
|
|
275
|
+
const tokens = await pollForToken(
|
|
276
|
+
config,
|
|
277
|
+
init.deviceCode,
|
|
278
|
+
init.interval,
|
|
279
|
+
init.expiresIn,
|
|
280
|
+
signal,
|
|
281
|
+
);
|
|
282
|
+
|
|
283
|
+
return { tokens, init };
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// ---------------------------------------------------------------------------
|
|
287
|
+
// Helpers
|
|
288
|
+
// ---------------------------------------------------------------------------
|
|
289
|
+
|
|
290
|
+
function sleep(ms: number, signal?: AbortSignal): Promise<void> {
|
|
291
|
+
return new Promise((resolve, reject) => {
|
|
292
|
+
if (signal?.aborted) {
|
|
293
|
+
reject(new DeviceCodeError("Device code flow aborted", "aborted"));
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
const timer = setTimeout(resolve, ms);
|
|
297
|
+
if (typeof timer === "object" && "unref" in timer) timer.unref();
|
|
298
|
+
signal?.addEventListener(
|
|
299
|
+
"abort",
|
|
300
|
+
() => {
|
|
301
|
+
clearTimeout(timer);
|
|
302
|
+
reject(new DeviceCodeError("Device code flow aborted", "aborted"));
|
|
303
|
+
},
|
|
304
|
+
{ once: true },
|
|
305
|
+
);
|
|
306
|
+
});
|
|
307
|
+
}
|
package/src/security/oauth2.ts
CHANGED
|
@@ -86,6 +86,10 @@ export interface OAuth2FlowOptions {
|
|
|
86
86
|
* instead of an OS-assigned random port. Required for providers like Slack that
|
|
87
87
|
* need pre-registered redirect URIs. */
|
|
88
88
|
loopbackPort?: number;
|
|
89
|
+
/** Override the loopback callback path. Defaults to `/oauth/callback`.
|
|
90
|
+
* Required for providers with pre-registered redirect URIs that use a
|
|
91
|
+
* different path (e.g. OpenAI Codex uses `/auth/callback`). */
|
|
92
|
+
loopbackCallbackPath?: string;
|
|
89
93
|
}
|
|
90
94
|
|
|
91
95
|
export interface OAuth2FlowResult {
|
|
@@ -98,15 +102,15 @@ export interface OAuth2FlowResult {
|
|
|
98
102
|
// PKCE helpers
|
|
99
103
|
// ---------------------------------------------------------------------------
|
|
100
104
|
|
|
101
|
-
function generateCodeVerifier(): string {
|
|
105
|
+
export function generateCodeVerifier(): string {
|
|
102
106
|
return randomBytes(32).toString("base64url");
|
|
103
107
|
}
|
|
104
108
|
|
|
105
|
-
function generateCodeChallenge(verifier: string): string {
|
|
109
|
+
export function generateCodeChallenge(verifier: string): string {
|
|
106
110
|
return createHash("sha256").update(verifier).digest("base64url");
|
|
107
111
|
}
|
|
108
112
|
|
|
109
|
-
function generateState(): string {
|
|
113
|
+
export function generateState(): string {
|
|
110
114
|
return randomBytes(16).toString("hex");
|
|
111
115
|
}
|
|
112
116
|
|
|
@@ -114,7 +118,7 @@ function generateState(): string {
|
|
|
114
118
|
// Token exchange (shared between transports)
|
|
115
119
|
// ---------------------------------------------------------------------------
|
|
116
120
|
|
|
117
|
-
async function exchangeCodeForTokens(
|
|
121
|
+
export async function exchangeCodeForTokens(
|
|
118
122
|
config: OAuth2Config,
|
|
119
123
|
code: string,
|
|
120
124
|
redirectUri: string,
|
|
@@ -293,6 +297,7 @@ async function runLoopbackFlow(
|
|
|
293
297
|
codeChallenge: string,
|
|
294
298
|
state: string,
|
|
295
299
|
loopbackPort?: number,
|
|
300
|
+
callbackPath?: string,
|
|
296
301
|
): Promise<OAuth2FlowResult> {
|
|
297
302
|
const { code, redirectUri } = await startLoopbackServerAndWaitForCode(
|
|
298
303
|
config,
|
|
@@ -300,6 +305,7 @@ async function runLoopbackFlow(
|
|
|
300
305
|
codeChallenge,
|
|
301
306
|
state,
|
|
302
307
|
loopbackPort,
|
|
308
|
+
callbackPath,
|
|
303
309
|
);
|
|
304
310
|
|
|
305
311
|
return await exchangeCodeForTokens(config, code, redirectUri, codeVerifier);
|
|
@@ -317,7 +323,9 @@ function startLoopbackServerAndWaitForCode(
|
|
|
317
323
|
codeChallenge: string,
|
|
318
324
|
state: string,
|
|
319
325
|
loopbackPort?: number,
|
|
326
|
+
callbackPath?: string,
|
|
320
327
|
): Promise<{ code: string; redirectUri: string }> {
|
|
328
|
+
const effectiveCallbackPath = callbackPath ?? LOOPBACK_CALLBACK_PATH;
|
|
321
329
|
return new Promise((resolve, reject) => {
|
|
322
330
|
let settled = false;
|
|
323
331
|
let boundRedirectUri = "";
|
|
@@ -340,7 +348,7 @@ function startLoopbackServerAndWaitForCode(
|
|
|
340
348
|
|
|
341
349
|
const url = new URL(req.url ?? "/", `http://127.0.0.1`);
|
|
342
350
|
|
|
343
|
-
if (url.pathname !==
|
|
351
|
+
if (url.pathname !== effectiveCallbackPath) {
|
|
344
352
|
log.info(
|
|
345
353
|
{ pathname: url.pathname },
|
|
346
354
|
"oauth2 loopback: non-callback path, returning 404",
|
|
@@ -426,7 +434,7 @@ function startLoopbackServerAndWaitForCode(
|
|
|
426
434
|
|
|
427
435
|
server.listen(loopbackPort ?? 0, "localhost", () => {
|
|
428
436
|
const addr = server.address() as { port: number };
|
|
429
|
-
boundRedirectUri = `http://localhost:${addr.port}${
|
|
437
|
+
boundRedirectUri = `http://localhost:${addr.port}${effectiveCallbackPath}`;
|
|
430
438
|
|
|
431
439
|
log.info(
|
|
432
440
|
{ port: addr.port, redirectUri: boundRedirectUri },
|
|
@@ -497,7 +505,11 @@ export async function prepareOAuth2Flow(
|
|
|
497
505
|
const transport = options?.callbackTransport ?? "loopback";
|
|
498
506
|
|
|
499
507
|
if (transport === "loopback") {
|
|
500
|
-
return prepareLoopbackFlow(
|
|
508
|
+
return prepareLoopbackFlow(
|
|
509
|
+
config,
|
|
510
|
+
options?.loopbackPort,
|
|
511
|
+
options?.loopbackCallbackPath,
|
|
512
|
+
);
|
|
501
513
|
}
|
|
502
514
|
|
|
503
515
|
// Dynamic imports required here to avoid circular dependencies with
|
|
@@ -555,6 +567,7 @@ export async function prepareOAuth2Flow(
|
|
|
555
567
|
async function prepareLoopbackFlow(
|
|
556
568
|
config: OAuth2Config,
|
|
557
569
|
loopbackPort?: number,
|
|
570
|
+
callbackPath?: string,
|
|
558
571
|
): Promise<OAuth2PreparedFlow> {
|
|
559
572
|
const codeVerifier = generateCodeVerifier();
|
|
560
573
|
const codeChallenge = generateCodeChallenge(codeVerifier);
|
|
@@ -563,6 +576,7 @@ async function prepareLoopbackFlow(
|
|
|
563
576
|
const { redirectUri, codePromise } = await startLoopbackServerForPreparedFlow(
|
|
564
577
|
state,
|
|
565
578
|
loopbackPort,
|
|
579
|
+
callbackPath,
|
|
566
580
|
);
|
|
567
581
|
|
|
568
582
|
const authParams = new URLSearchParams({
|
|
@@ -599,7 +613,9 @@ async function prepareLoopbackFlow(
|
|
|
599
613
|
function startLoopbackServerForPreparedFlow(
|
|
600
614
|
state: string,
|
|
601
615
|
loopbackPort?: number,
|
|
616
|
+
callbackPath?: string,
|
|
602
617
|
): Promise<{ redirectUri: string; codePromise: Promise<string> }> {
|
|
618
|
+
const effectiveCallbackPath = callbackPath ?? LOOPBACK_CALLBACK_PATH;
|
|
603
619
|
return new Promise((resolveSetup, rejectSetup) => {
|
|
604
620
|
let settled = false;
|
|
605
621
|
let listening = false;
|
|
@@ -619,7 +635,7 @@ function startLoopbackServerForPreparedFlow(
|
|
|
619
635
|
|
|
620
636
|
const url = new URL(req.url ?? "/", `http://127.0.0.1`);
|
|
621
637
|
|
|
622
|
-
if (url.pathname !==
|
|
638
|
+
if (url.pathname !== effectiveCallbackPath) {
|
|
623
639
|
res.writeHead(404, { "Content-Type": "text/plain" });
|
|
624
640
|
res.end("Not found");
|
|
625
641
|
return;
|
|
@@ -683,7 +699,7 @@ function startLoopbackServerForPreparedFlow(
|
|
|
683
699
|
|
|
684
700
|
server.listen(loopbackPort ?? 0, "localhost", () => {
|
|
685
701
|
const addr = server.address() as { port: number };
|
|
686
|
-
const redirectUri = `http://localhost:${addr.port}${
|
|
702
|
+
const redirectUri = `http://localhost:${addr.port}${effectiveCallbackPath}`;
|
|
687
703
|
listening = true;
|
|
688
704
|
resolveSetup({ redirectUri, codePromise });
|
|
689
705
|
});
|
|
@@ -784,6 +800,7 @@ export async function startOAuth2Flow(
|
|
|
784
800
|
codeChallenge,
|
|
785
801
|
state,
|
|
786
802
|
options?.loopbackPort,
|
|
803
|
+
options?.loopbackCallbackPath,
|
|
787
804
|
);
|
|
788
805
|
}
|
|
789
806
|
|
|
@@ -113,6 +113,11 @@ const RECONNECT_COOLDOWN_MS = 3_000;
|
|
|
113
113
|
*/
|
|
114
114
|
const CREDENTIAL_OP_TIMEOUT_MS = 45_000;
|
|
115
115
|
|
|
116
|
+
/** Returns the current CES RPC client if one has been injected. */
|
|
117
|
+
export function getCesClient(): CesClient | undefined {
|
|
118
|
+
return _cesClient;
|
|
119
|
+
}
|
|
120
|
+
|
|
116
121
|
/** Inject a CES RPC client for credential routing. Resets the resolved backend. */
|
|
117
122
|
export function setCesClient(client: CesClient | undefined): void {
|
|
118
123
|
_cesClient = client;
|
|
@@ -111,7 +111,9 @@ export async function fetchCatalog(): Promise<CatalogSkill[]> {
|
|
|
111
111
|
if (!Array.isArray(manifest.skills)) {
|
|
112
112
|
throw new Error("Platform catalog has invalid skills array");
|
|
113
113
|
}
|
|
114
|
-
return manifest.skills
|
|
114
|
+
return manifest.skills.filter(
|
|
115
|
+
(s): s is CatalogSkill => !!s && typeof s.id === "string",
|
|
116
|
+
);
|
|
115
117
|
}
|
|
116
118
|
|
|
117
119
|
export function readLocalCatalog(repoSkillsDir: string): CatalogSkill[] {
|
|
@@ -119,7 +121,9 @@ export function readLocalCatalog(repoSkillsDir: string): CatalogSkill[] {
|
|
|
119
121
|
const raw = readFileSync(join(repoSkillsDir, "catalog.json"), "utf-8");
|
|
120
122
|
const manifest = JSON.parse(raw) as CatalogManifest;
|
|
121
123
|
if (!Array.isArray(manifest.skills)) return [];
|
|
122
|
-
return manifest.skills
|
|
124
|
+
return manifest.skills.filter(
|
|
125
|
+
(s): s is CatalogSkill => !!s && typeof s.id === "string",
|
|
126
|
+
);
|
|
123
127
|
} catch {
|
|
124
128
|
return [];
|
|
125
129
|
}
|
package/src/telemetry/types.ts
CHANGED
|
@@ -38,6 +38,18 @@ export interface LlmUsageTelemetryEvent extends TelemetryEventBase {
|
|
|
38
38
|
output_tokens: number;
|
|
39
39
|
cache_creation_input_tokens: number | null;
|
|
40
40
|
cache_read_input_tokens: number | null;
|
|
41
|
+
/**
|
|
42
|
+
* The provider's untouched `usage` block. Anthropic surfaces a TTL
|
|
43
|
+
* breakdown under `cache_creation.ephemeral_{5m,1h}_input_tokens`;
|
|
44
|
+
* OpenAI surfaces cached-read counts under
|
|
45
|
+
* `prompt_tokens_details.cached_tokens` (and reasoning tokens under
|
|
46
|
+
* `completion_tokens_details`). Both shapes are forwarded verbatim so
|
|
47
|
+
* downstream consumers (admin charts, dbt models) can extract any
|
|
48
|
+
* provider-specific detail without requiring a schema change here.
|
|
49
|
+
* Null when the provider did not return a usage payload, and for
|
|
50
|
+
* daemons that predate `260-llm-usage-add-raw-usage`.
|
|
51
|
+
*/
|
|
52
|
+
raw_usage: Record<string, unknown> | null;
|
|
41
53
|
actor: string;
|
|
42
54
|
llm_call_site: LLMCallSite | null;
|
|
43
55
|
inference_profile: string | null;
|
|
@@ -159,6 +159,7 @@ function makeUsageEvent(
|
|
|
159
159
|
outputTokens: 50,
|
|
160
160
|
cacheCreationInputTokens: 10,
|
|
161
161
|
cacheReadInputTokens: 5,
|
|
162
|
+
rawUsage: null,
|
|
162
163
|
actor: "main_agent",
|
|
163
164
|
callSite: null,
|
|
164
165
|
inferenceProfile: null,
|
|
@@ -435,6 +436,53 @@ describe("UsageTelemetryReporter", () => {
|
|
|
435
436
|
expect(e.inference_profile_source).toBe("conversation");
|
|
436
437
|
expect(e.cost).toBe(0.001);
|
|
437
438
|
expect(e.recorded_at).toBe(1700000099000);
|
|
439
|
+
// raw_usage defaults to null on this fixture (the makeUsageEvent default),
|
|
440
|
+
// confirming the wire shape carries the key as `null` rather than
|
|
441
|
+
// dropping it for legacy rows or providers that did not return a
|
|
442
|
+
// usage block.
|
|
443
|
+
expect(e.raw_usage).toBeNull();
|
|
444
|
+
});
|
|
445
|
+
|
|
446
|
+
test("payload forwards the provider's raw_usage block verbatim", async () => {
|
|
447
|
+
// The reporter must surface the literal usage object the provider
|
|
448
|
+
// returned (Anthropic nests TTL breakdown under `cache_creation`,
|
|
449
|
+
// OpenAI nests cached-read counts under `prompt_tokens_details`,
|
|
450
|
+
// etc.) so downstream consumers can extract any provider-specific
|
|
451
|
+
// detail without a wire-level schema change. Anything that
|
|
452
|
+
// transforms, summarises, or strips fields here destroys data the
|
|
453
|
+
// admin charts and dbt models depend on.
|
|
454
|
+
const rawUsage = {
|
|
455
|
+
input_tokens: 200,
|
|
456
|
+
output_tokens: 100,
|
|
457
|
+
cache_creation_input_tokens: 750,
|
|
458
|
+
cache_creation: {
|
|
459
|
+
ephemeral_5m_input_tokens: 250,
|
|
460
|
+
ephemeral_1h_input_tokens: 500,
|
|
461
|
+
},
|
|
462
|
+
cache_read_input_tokens: 15,
|
|
463
|
+
service_tier: "standard",
|
|
464
|
+
};
|
|
465
|
+
const event = makeUsageEvent({
|
|
466
|
+
id: "evt-raw-usage",
|
|
467
|
+
provider: "anthropic",
|
|
468
|
+
model: "claude-sonnet-4-20250514",
|
|
469
|
+
cacheCreationInputTokens: 750,
|
|
470
|
+
rawUsage,
|
|
471
|
+
});
|
|
472
|
+
mockQueryUnreportedUsageEvents.mockReturnValue([event]);
|
|
473
|
+
mockFetch.mockImplementation(() =>
|
|
474
|
+
Promise.resolve(new Response('{"accepted":1}', { status: 200 })),
|
|
475
|
+
);
|
|
476
|
+
|
|
477
|
+
const reporter = new UsageTelemetryReporter();
|
|
478
|
+
await reporter.flush();
|
|
479
|
+
|
|
480
|
+
const body = JSON.parse(
|
|
481
|
+
(mockFetch.mock.calls[0] as [string, RequestInit])[1].body as string,
|
|
482
|
+
);
|
|
483
|
+
const e = body.events[0];
|
|
484
|
+
expect(e.cache_creation_input_tokens).toBe(750);
|
|
485
|
+
expect(e.raw_usage).toEqual(rawUsage);
|
|
438
486
|
});
|
|
439
487
|
|
|
440
488
|
test("payload preserves null attribution for historical usage rows", async () => {
|
|
@@ -234,6 +234,7 @@ export class UsageTelemetryReporter {
|
|
|
234
234
|
output_tokens: e.outputTokens,
|
|
235
235
|
cache_creation_input_tokens: e.cacheCreationInputTokens ?? null,
|
|
236
236
|
cache_read_input_tokens: e.cacheReadInputTokens ?? null,
|
|
237
|
+
raw_usage: e.rawUsage,
|
|
237
238
|
actor: e.actor,
|
|
238
239
|
llm_call_site: e.callSite,
|
|
239
240
|
inference_profile: e.inferenceProfile,
|