@rudderjs/ai 1.17.3 → 1.18.0
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/README.md +19 -1274
- package/dist/budget-orm/index.d.ts +1 -95
- package/dist/budget-orm/index.d.ts.map +1 -1
- package/dist/budget-orm/index.js +4 -176
- package/dist/budget-orm/index.js.map +1 -1
- package/dist/chat-mentions.d.ts +1 -58
- package/dist/chat-mentions.d.ts.map +1 -1
- package/dist/chat-mentions.js +4 -80
- package/dist/chat-mentions.js.map +1 -1
- package/dist/commands/ai-eval.d.ts +1 -92
- package/dist/commands/ai-eval.d.ts.map +1 -1
- package/dist/commands/ai-eval.js +4 -377
- package/dist/commands/ai-eval.js.map +1 -1
- package/dist/commands/make-agent.d.ts +1 -2
- package/dist/commands/make-agent.d.ts.map +1 -1
- package/dist/commands/make-agent.js +4 -22
- package/dist/commands/make-agent.js.map +1 -1
- package/dist/computer-use/index.d.ts +1 -52
- package/dist/computer-use/index.d.ts.map +1 -1
- package/dist/computer-use/index.js +4 -50
- package/dist/computer-use/index.js.map +1 -1
- package/dist/conversation-orm/index.d.ts +1 -108
- package/dist/conversation-orm/index.d.ts.map +1 -1
- package/dist/conversation-orm/index.js +4 -214
- package/dist/conversation-orm/index.js.map +1 -1
- package/dist/doctor.d.ts +1 -1
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +4 -65
- package/dist/doctor.js.map +1 -1
- package/dist/eval/index.d.ts +1 -270
- package/dist/eval/index.d.ts.map +1 -1
- package/dist/eval/index.js +4 -509
- package/dist/eval/index.js.map +1 -1
- package/dist/gateway/index.d.ts +1 -10
- package/dist/gateway/index.d.ts.map +1 -1
- package/dist/gateway/index.js +4 -10
- package/dist/gateway/index.js.map +1 -1
- package/dist/index.d.ts +1 -66
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -78
- package/dist/index.js.map +1 -1
- package/dist/mcp/index.d.ts +1 -15
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +4 -14
- package/dist/mcp/index.js.map +1 -1
- package/dist/memory-embedding/index.d.ts +1 -120
- package/dist/memory-embedding/index.d.ts.map +1 -1
- package/dist/memory-embedding/index.js +4 -228
- package/dist/memory-embedding/index.js.map +1 -1
- package/dist/memory-orm/index.d.ts +1 -117
- package/dist/memory-orm/index.d.ts.map +1 -1
- package/dist/memory-orm/index.js +4 -186
- package/dist/memory-orm/index.js.map +1 -1
- package/dist/node/index.d.ts +1 -2
- package/dist/node/index.d.ts.map +1 -1
- package/dist/node/index.js +4 -2
- package/dist/node/index.js.map +1 -1
- package/dist/observers.d.ts +1 -129
- package/dist/observers.d.ts.map +1 -1
- package/dist/observers.js +4 -39
- package/dist/observers.js.map +1 -1
- package/dist/react/index.d.ts +1 -15
- package/dist/react/index.d.ts.map +1 -1
- package/dist/react/index.js +4 -15
- package/dist/react/index.js.map +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.d.ts.map +1 -1
- package/dist/server/index.js +4 -1
- package/dist/server/index.js.map +1 -1
- package/package.json +9 -13
- package/boost/guidelines.md +0 -260
- package/boost/skills/ai-agents/SKILL.md +0 -240
- package/boost/skills/ai-tools/SKILL.md +0 -260
- package/dist/agent-run-store.d.ts +0 -161
- package/dist/agent-run-store.d.ts.map +0 -1
- package/dist/agent-run-store.js +0 -98
- package/dist/agent-run-store.js.map +0 -1
- package/dist/agent-sse.d.ts +0 -153
- package/dist/agent-sse.d.ts.map +0 -1
- package/dist/agent-sse.js +0 -282
- package/dist/agent-sse.js.map +0 -1
- package/dist/agent.d.ts +0 -508
- package/dist/agent.d.ts.map +0 -1
- package/dist/agent.js +0 -1538
- package/dist/agent.js.map +0 -1
- package/dist/attachment.d.ts +0 -31
- package/dist/attachment.d.ts.map +0 -1
- package/dist/attachment.js +0 -89
- package/dist/attachment.js.map +0 -1
- package/dist/audio.d.ts +0 -45
- package/dist/audio.d.ts.map +0 -1
- package/dist/audio.js +0 -93
- package/dist/audio.js.map +0 -1
- package/dist/base64.d.ts +0 -7
- package/dist/base64.d.ts.map +0 -1
- package/dist/base64.js +0 -39
- package/dist/base64.js.map +0 -1
- package/dist/budget/pricing.d.ts +0 -124
- package/dist/budget/pricing.d.ts.map +0 -1
- package/dist/budget/pricing.js +0 -175
- package/dist/budget/pricing.js.map +0 -1
- package/dist/budget/storage.d.ts +0 -104
- package/dist/budget/storage.d.ts.map +0 -1
- package/dist/budget/storage.js +0 -0
- package/dist/budget/storage.js.map +0 -1
- package/dist/budget/with-budget.d.ts +0 -119
- package/dist/budget/with-budget.d.ts.map +0 -1
- package/dist/budget/with-budget.js +0 -175
- package/dist/budget/with-budget.js.map +0 -1
- package/dist/cached-embedding.d.ts +0 -14
- package/dist/cached-embedding.d.ts.map +0 -1
- package/dist/cached-embedding.js +0 -44
- package/dist/cached-embedding.js.map +0 -1
- package/dist/computer-use/actions.d.ts +0 -214
- package/dist/computer-use/actions.d.ts.map +0 -1
- package/dist/computer-use/actions.js +0 -48
- package/dist/computer-use/actions.js.map +0 -1
- package/dist/computer-use/errors.d.ts +0 -57
- package/dist/computer-use/errors.d.ts.map +0 -1
- package/dist/computer-use/errors.js +0 -76
- package/dist/computer-use/errors.js.map +0 -1
- package/dist/computer-use/playwright.d.ts +0 -76
- package/dist/computer-use/playwright.d.ts.map +0 -1
- package/dist/computer-use/playwright.js +0 -270
- package/dist/computer-use/playwright.js.map +0 -1
- package/dist/computer-use/tool.d.ts +0 -154
- package/dist/computer-use/tool.d.ts.map +0 -1
- package/dist/computer-use/tool.js +0 -210
- package/dist/computer-use/tool.js.map +0 -1
- package/dist/continuation-validation.d.ts +0 -85
- package/dist/continuation-validation.d.ts.map +0 -1
- package/dist/continuation-validation.js +0 -166
- package/dist/continuation-validation.js.map +0 -1
- package/dist/conversation-persistence.d.ts +0 -46
- package/dist/conversation-persistence.d.ts.map +0 -1
- package/dist/conversation-persistence.js +0 -176
- package/dist/conversation-persistence.js.map +0 -1
- package/dist/conversation.d.ts +0 -11
- package/dist/conversation.d.ts.map +0 -1
- package/dist/conversation.js +0 -55
- package/dist/conversation.js.map +0 -1
- package/dist/eval/fixtures.d.ts +0 -65
- package/dist/eval/fixtures.d.ts.map +0 -1
- package/dist/eval/fixtures.js +0 -110
- package/dist/eval/fixtures.js.map +0 -1
- package/dist/eval/html-reporter.d.ts +0 -25
- package/dist/eval/html-reporter.d.ts.map +0 -1
- package/dist/eval/html-reporter.js +0 -209
- package/dist/eval/html-reporter.js.map +0 -1
- package/dist/eval/json-reporter.d.ts +0 -43
- package/dist/eval/json-reporter.d.ts.map +0 -1
- package/dist/eval/json-reporter.js +0 -40
- package/dist/eval/json-reporter.js.map +0 -1
- package/dist/facade.d.ts +0 -96
- package/dist/facade.d.ts.map +0 -1
- package/dist/facade.js +0 -146
- package/dist/facade.js.map +0 -1
- package/dist/fake.d.ts +0 -201
- package/dist/fake.d.ts.map +0 -1
- package/dist/fake.js +0 -428
- package/dist/fake.js.map +0 -1
- package/dist/file-search.d.ts +0 -168
- package/dist/file-search.d.ts.map +0 -1
- package/dist/file-search.js +0 -158
- package/dist/file-search.js.map +0 -1
- package/dist/files.d.ts +0 -27
- package/dist/files.d.ts.map +0 -1
- package/dist/files.js +0 -44
- package/dist/files.js.map +0 -1
- package/dist/gateway/http-gateway-adapter.d.ts +0 -94
- package/dist/gateway/http-gateway-adapter.d.ts.map +0 -1
- package/dist/gateway/http-gateway-adapter.js +0 -106
- package/dist/gateway/http-gateway-adapter.js.map +0 -1
- package/dist/gateway/sse.d.ts +0 -28
- package/dist/gateway/sse.d.ts.map +0 -1
- package/dist/gateway/sse.js +0 -78
- package/dist/gateway/sse.js.map +0 -1
- package/dist/handoff.d.ts +0 -95
- package/dist/handoff.d.ts.map +0 -1
- package/dist/handoff.js +0 -78
- package/dist/handoff.js.map +0 -1
- package/dist/handoffs-driver.d.ts +0 -58
- package/dist/handoffs-driver.d.ts.map +0 -1
- package/dist/handoffs-driver.js +0 -103
- package/dist/handoffs-driver.js.map +0 -1
- package/dist/image.d.ts +0 -40
- package/dist/image.d.ts.map +0 -1
- package/dist/image.js +0 -109
- package/dist/image.js.map +0 -1
- package/dist/mcp/client-tools.d.ts +0 -39
- package/dist/mcp/client-tools.d.ts.map +0 -1
- package/dist/mcp/client-tools.js +0 -147
- package/dist/mcp/client-tools.js.map +0 -1
- package/dist/mcp/server-from-agent.d.ts +0 -24
- package/dist/mcp/server-from-agent.d.ts.map +0 -1
- package/dist/mcp/server-from-agent.js +0 -113
- package/dist/mcp/server-from-agent.js.map +0 -1
- package/dist/mcp/types.d.ts +0 -64
- package/dist/mcp/types.d.ts.map +0 -1
- package/dist/mcp/types.js +0 -6
- package/dist/mcp/types.js.map +0 -1
- package/dist/memory-extract.d.ts +0 -60
- package/dist/memory-extract.d.ts.map +0 -1
- package/dist/memory-extract.js +0 -163
- package/dist/memory-extract.js.map +0 -1
- package/dist/memory-inject.d.ts +0 -39
- package/dist/memory-inject.d.ts.map +0 -1
- package/dist/memory-inject.js +0 -135
- package/dist/memory-inject.js.map +0 -1
- package/dist/memory.d.ts +0 -55
- package/dist/memory.d.ts.map +0 -1
- package/dist/memory.js +0 -132
- package/dist/memory.js.map +0 -1
- package/dist/middleware.d.ts +0 -18
- package/dist/middleware.d.ts.map +0 -1
- package/dist/middleware.js +0 -72
- package/dist/middleware.js.map +0 -1
- package/dist/node/attachment.d.ts +0 -6
- package/dist/node/attachment.d.ts.map +0 -1
- package/dist/node/attachment.js +0 -35
- package/dist/node/attachment.js.map +0 -1
- package/dist/node/transcription.d.ts +0 -4
- package/dist/node/transcription.d.ts.map +0 -1
- package/dist/node/transcription.js +0 -8
- package/dist/node/transcription.js.map +0 -1
- package/dist/output.d.ts +0 -22
- package/dist/output.d.ts.map +0 -1
- package/dist/output.js +0 -60
- package/dist/output.js.map +0 -1
- package/dist/provider-tools.d.ts +0 -87
- package/dist/provider-tools.d.ts.map +0 -1
- package/dist/provider-tools.js +0 -189
- package/dist/provider-tools.js.map +0 -1
- package/dist/providers/anthropic.d.ts +0 -24
- package/dist/providers/anthropic.d.ts.map +0 -1
- package/dist/providers/anthropic.js +0 -405
- package/dist/providers/anthropic.js.map +0 -1
- package/dist/providers/azure.d.ts +0 -13
- package/dist/providers/azure.d.ts.map +0 -1
- package/dist/providers/azure.js +0 -15
- package/dist/providers/azure.js.map +0 -1
- package/dist/providers/bedrock.d.ts +0 -75
- package/dist/providers/bedrock.d.ts.map +0 -1
- package/dist/providers/bedrock.js +0 -181
- package/dist/providers/bedrock.js.map +0 -1
- package/dist/providers/cohere.d.ts +0 -13
- package/dist/providers/cohere.d.ts.map +0 -1
- package/dist/providers/cohere.js +0 -87
- package/dist/providers/cohere.js.map +0 -1
- package/dist/providers/deepseek.d.ts +0 -12
- package/dist/providers/deepseek.d.ts.map +0 -1
- package/dist/providers/deepseek.js +0 -15
- package/dist/providers/deepseek.js.map +0 -1
- package/dist/providers/elevenlabs.d.ts +0 -98
- package/dist/providers/elevenlabs.d.ts.map +0 -1
- package/dist/providers/elevenlabs.js +0 -229
- package/dist/providers/elevenlabs.js.map +0 -1
- package/dist/providers/google-cache-registry.d.ts +0 -132
- package/dist/providers/google-cache-registry.d.ts.map +0 -1
- package/dist/providers/google-cache-registry.js +0 -209
- package/dist/providers/google-cache-registry.js.map +0 -1
- package/dist/providers/google.d.ts +0 -38
- package/dist/providers/google.d.ts.map +0 -1
- package/dist/providers/google.js +0 -903
- package/dist/providers/google.js.map +0 -1
- package/dist/providers/groq.d.ts +0 -12
- package/dist/providers/groq.d.ts.map +0 -1
- package/dist/providers/groq.js +0 -15
- package/dist/providers/groq.js.map +0 -1
- package/dist/providers/jina.d.ts +0 -13
- package/dist/providers/jina.d.ts.map +0 -1
- package/dist/providers/jina.js +0 -90
- package/dist/providers/jina.js.map +0 -1
- package/dist/providers/mistral.d.ts +0 -13
- package/dist/providers/mistral.d.ts.map +0 -1
- package/dist/providers/mistral.js +0 -46
- package/dist/providers/mistral.js.map +0 -1
- package/dist/providers/ollama.d.ts +0 -11
- package/dist/providers/ollama.d.ts.map +0 -1
- package/dist/providers/ollama.js +0 -15
- package/dist/providers/ollama.js.map +0 -1
- package/dist/providers/openai.d.ts +0 -79
- package/dist/providers/openai.d.ts.map +0 -1
- package/dist/providers/openai.js +0 -792
- package/dist/providers/openai.js.map +0 -1
- package/dist/providers/openrouter.d.ts +0 -43
- package/dist/providers/openrouter.d.ts.map +0 -1
- package/dist/providers/openrouter.js +0 -21
- package/dist/providers/openrouter.js.map +0 -1
- package/dist/providers/voyage.d.ts +0 -91
- package/dist/providers/voyage.d.ts.map +0 -1
- package/dist/providers/voyage.js +0 -166
- package/dist/providers/voyage.js.map +0 -1
- package/dist/providers/xai.d.ts +0 -12
- package/dist/providers/xai.d.ts.map +0 -1
- package/dist/providers/xai.js +0 -15
- package/dist/providers/xai.js.map +0 -1
- package/dist/queue-job.d.ts +0 -100
- package/dist/queue-job.d.ts.map +0 -1
- package/dist/queue-job.js +0 -185
- package/dist/queue-job.js.map +0 -1
- package/dist/react/agent-run.d.ts +0 -111
- package/dist/react/agent-run.d.ts.map +0 -1
- package/dist/react/agent-run.js +0 -107
- package/dist/react/agent-run.js.map +0 -1
- package/dist/react/useAgentRun.d.ts +0 -68
- package/dist/react/useAgentRun.d.ts.map +0 -1
- package/dist/react/useAgentRun.js +0 -125
- package/dist/react/useAgentRun.js.map +0 -1
- package/dist/registry.d.ts +0 -45
- package/dist/registry.d.ts.map +0 -1
- package/dist/registry.js +0 -131
- package/dist/registry.js.map +0 -1
- package/dist/rerank.d.ts +0 -20
- package/dist/rerank.d.ts.map +0 -1
- package/dist/rerank.js +0 -40
- package/dist/rerank.js.map +0 -1
- package/dist/resume-approval.d.ts +0 -30
- package/dist/resume-approval.d.ts.map +0 -1
- package/dist/resume-approval.js +0 -147
- package/dist/resume-approval.js.map +0 -1
- package/dist/sanitize-conversation.d.ts +0 -43
- package/dist/sanitize-conversation.d.ts.map +0 -1
- package/dist/sanitize-conversation.js +0 -85
- package/dist/sanitize-conversation.js.map +0 -1
- package/dist/scoped-tool.d.ts +0 -98
- package/dist/scoped-tool.d.ts.map +0 -1
- package/dist/scoped-tool.js +0 -174
- package/dist/scoped-tool.js.map +0 -1
- package/dist/server/provider.d.ts +0 -22
- package/dist/server/provider.d.ts.map +0 -1
- package/dist/server/provider.js +0 -194
- package/dist/server/provider.js.map +0 -1
- package/dist/similarity-search.d.ts +0 -163
- package/dist/similarity-search.d.ts.map +0 -1
- package/dist/similarity-search.js +0 -147
- package/dist/similarity-search.js.map +0 -1
- package/dist/sub-agent-run-store.d.ts +0 -157
- package/dist/sub-agent-run-store.d.ts.map +0 -1
- package/dist/sub-agent-run-store.js +0 -87
- package/dist/sub-agent-run-store.js.map +0 -1
- package/dist/tool-execution.d.ts +0 -16
- package/dist/tool-execution.d.ts.map +0 -1
- package/dist/tool-execution.js +0 -498
- package/dist/tool-execution.js.map +0 -1
- package/dist/tool-helpers.d.ts +0 -77
- package/dist/tool-helpers.d.ts.map +0 -1
- package/dist/tool-helpers.js +0 -117
- package/dist/tool-helpers.js.map +0 -1
- package/dist/tool.d.ts +0 -216
- package/dist/tool.d.ts.map +0 -1
- package/dist/tool.js +0 -175
- package/dist/tool.js.map +0 -1
- package/dist/transcription.d.ts +0 -42
- package/dist/transcription.d.ts.map +0 -1
- package/dist/transcription.js +0 -77
- package/dist/transcription.js.map +0 -1
- package/dist/types.d.ts +0 -1020
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -2
- package/dist/types.js.map +0 -1
- package/dist/util/hash.d.ts +0 -11
- package/dist/util/hash.d.ts.map +0 -1
- package/dist/util/hash.js +0 -23
- package/dist/util/hash.js.map +0 -1
- package/dist/vector-stores/index.d.ts +0 -96
- package/dist/vector-stores/index.d.ts.map +0 -1
- package/dist/vector-stores/index.js +0 -153
- package/dist/vector-stores/index.js.map +0 -1
- package/dist/vercel-protocol.d.ts +0 -18
- package/dist/vercel-protocol.d.ts.map +0 -1
- package/dist/vercel-protocol.js +0 -75
- package/dist/vercel-protocol.js.map +0 -1
- package/dist/zod-to-json-schema.d.ts +0 -16
- package/dist/zod-to-json-schema.d.ts.map +0 -1
- package/dist/zod-to-json-schema.js +0 -17
- package/dist/zod-to-json-schema.js.map +0 -1
package/dist/budget/pricing.js
DELETED
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Model pricing catalog — USD per 1k tokens, snapshot-dated per entry.
|
|
3
|
-
*
|
|
4
|
-
* Used by:
|
|
5
|
-
* - `@rudderjs/ai/eval` to populate the cost column on eval reports
|
|
6
|
-
* - `@rudderjs/ai`'s budget enforcement middleware (A6 phase 3) to debit
|
|
7
|
-
* per-user spend against caps
|
|
8
|
-
*
|
|
9
|
-
* # Pricing drift
|
|
10
|
-
*
|
|
11
|
-
* Provider list pricing changes monthly. Each entry carries `_snapshotDate`
|
|
12
|
-
* indicating when the rate was captured. Apps with negotiated rates should
|
|
13
|
-
* pass an override map:
|
|
14
|
-
*
|
|
15
|
-
* ```ts
|
|
16
|
-
* import { ModelPricing, withBudget } from '@rudderjs/ai'
|
|
17
|
-
*
|
|
18
|
-
* withBudget({
|
|
19
|
-
* pricing: {
|
|
20
|
-
* ...ModelPricing,
|
|
21
|
-
* 'anthropic/claude-opus-4-7': {
|
|
22
|
-
* inputPer1k: 0.012,
|
|
23
|
-
* outputPer1k: 0.060,
|
|
24
|
-
* _snapshotDate: '2026-01-15',
|
|
25
|
-
* },
|
|
26
|
-
* },
|
|
27
|
-
* // ...
|
|
28
|
-
* })
|
|
29
|
-
* ```
|
|
30
|
-
*
|
|
31
|
-
* # Cache rates
|
|
32
|
-
*
|
|
33
|
-
* Anthropic, OpenAI, and Google all offer reduced rates for cache reads
|
|
34
|
-
* (and Anthropic charges a small premium for cache writes). The optional
|
|
35
|
-
* `cacheReadPer1k` / `cacheWritePer1k` fields capture those. The budget
|
|
36
|
-
* middleware uses them when `TokenUsage` carries cache deltas; when absent
|
|
37
|
-
* (today's `TokenUsage` shape), input rate applies to all input tokens.
|
|
38
|
-
*/
|
|
39
|
-
/**
|
|
40
|
-
* `<provider>/<model>` → {@link ModelPriceEntry}. Override entries by
|
|
41
|
-
* spreading: `{ ...ModelPricing, 'anthropic/claude-opus-4-7': {...} }`.
|
|
42
|
-
*
|
|
43
|
-
* Snapshot date: 2026-05-11.
|
|
44
|
-
*/
|
|
45
|
-
export const ModelPricing = {
|
|
46
|
-
// ─── Anthropic ──────────────────────────────────────────
|
|
47
|
-
// Cache write = 1.25× input, cache read = 0.1× input (Anthropic ephemeral)
|
|
48
|
-
'anthropic/claude-opus-4-7': { inputPer1k: 0.015, outputPer1k: 0.075, cacheWritePer1k: 0.01875, cacheReadPer1k: 0.0015, _snapshotDate: '2026-05-11' },
|
|
49
|
-
'anthropic/claude-opus-4-6': { inputPer1k: 0.015, outputPer1k: 0.075, cacheWritePer1k: 0.01875, cacheReadPer1k: 0.0015, _snapshotDate: '2026-05-11' },
|
|
50
|
-
'anthropic/claude-sonnet-4-6': { inputPer1k: 0.003, outputPer1k: 0.015, cacheWritePer1k: 0.00375, cacheReadPer1k: 0.0003, _snapshotDate: '2026-05-11' },
|
|
51
|
-
'anthropic/claude-sonnet-4-5': { inputPer1k: 0.003, outputPer1k: 0.015, cacheWritePer1k: 0.00375, cacheReadPer1k: 0.0003, _snapshotDate: '2026-05-11' },
|
|
52
|
-
'anthropic/claude-haiku-4-5': { inputPer1k: 0.0008, outputPer1k: 0.004, cacheWritePer1k: 0.001, cacheReadPer1k: 0.00008, _snapshotDate: '2026-05-11' },
|
|
53
|
-
'anthropic/claude-3-7-sonnet': { inputPer1k: 0.003, outputPer1k: 0.015, cacheWritePer1k: 0.00375, cacheReadPer1k: 0.0003, _snapshotDate: '2026-05-11' },
|
|
54
|
-
'anthropic/claude-3-5-sonnet': { inputPer1k: 0.003, outputPer1k: 0.015, cacheWritePer1k: 0.00375, cacheReadPer1k: 0.0003, _snapshotDate: '2026-05-11' },
|
|
55
|
-
'anthropic/claude-3-5-haiku': { inputPer1k: 0.0008, outputPer1k: 0.004, cacheWritePer1k: 0.001, cacheReadPer1k: 0.00008, _snapshotDate: '2026-05-11' },
|
|
56
|
-
// ─── OpenAI ─────────────────────────────────────────────
|
|
57
|
-
// Cache read = 0.5× input (OpenAI prefix cache); no cache write surcharge
|
|
58
|
-
'openai/gpt-4-1': { inputPer1k: 0.002, outputPer1k: 0.008, cacheReadPer1k: 0.0005, _snapshotDate: '2026-05-11' },
|
|
59
|
-
'openai/gpt-4-1-mini': { inputPer1k: 0.0004, outputPer1k: 0.0016, cacheReadPer1k: 0.0001, _snapshotDate: '2026-05-11' },
|
|
60
|
-
'openai/gpt-4-1-nano': { inputPer1k: 0.0001, outputPer1k: 0.0004, cacheReadPer1k: 0.000025, _snapshotDate: '2026-05-11' },
|
|
61
|
-
'openai/gpt-4o': { inputPer1k: 0.0025, outputPer1k: 0.01, cacheReadPer1k: 0.00125, _snapshotDate: '2026-05-11' },
|
|
62
|
-
'openai/gpt-4o-mini': { inputPer1k: 0.00015, outputPer1k: 0.0006, cacheReadPer1k: 0.000075, _snapshotDate: '2026-05-11' },
|
|
63
|
-
'openai/o1': { inputPer1k: 0.015, outputPer1k: 0.06, cacheReadPer1k: 0.0075, _snapshotDate: '2026-05-11' },
|
|
64
|
-
'openai/o1-mini': { inputPer1k: 0.0011, outputPer1k: 0.0044, cacheReadPer1k: 0.00055, _snapshotDate: '2026-05-11' },
|
|
65
|
-
'openai/o3': { inputPer1k: 0.002, outputPer1k: 0.008, cacheReadPer1k: 0.0005, _snapshotDate: '2026-05-11' },
|
|
66
|
-
'openai/o3-mini': { inputPer1k: 0.0011, outputPer1k: 0.0044, cacheReadPer1k: 0.00055, _snapshotDate: '2026-05-11' },
|
|
67
|
-
'openai/o4-mini': { inputPer1k: 0.0011, outputPer1k: 0.0044, cacheReadPer1k: 0.000275, _snapshotDate: '2026-05-11' },
|
|
68
|
-
// ─── Google (Gemini) ────────────────────────────────────
|
|
69
|
-
// Cache read = 0.25× input (Google cachedContent); no cache write surcharge
|
|
70
|
-
'google/gemini-2.5-pro': { inputPer1k: 0.00125, outputPer1k: 0.005, cacheReadPer1k: 0.0003125, _snapshotDate: '2026-05-11' },
|
|
71
|
-
'google/gemini-2.5-flash': { inputPer1k: 0.000075, outputPer1k: 0.0003, cacheReadPer1k: 0.00001875, _snapshotDate: '2026-05-11' },
|
|
72
|
-
'google/gemini-2.5-flash-lite': { inputPer1k: 0.00004, outputPer1k: 0.00015, cacheReadPer1k: 0.00001, _snapshotDate: '2026-05-11' },
|
|
73
|
-
'google/gemini-2.0-flash': { inputPer1k: 0.0001, outputPer1k: 0.0004, cacheReadPer1k: 0.000025, _snapshotDate: '2026-05-11' },
|
|
74
|
-
'google/gemini-2.0-flash-lite': { inputPer1k: 0.000075, outputPer1k: 0.0003, cacheReadPer1k: 0.00001875, _snapshotDate: '2026-05-11' },
|
|
75
|
-
// ─── Bedrock (Anthropic models on AWS Bedrock) ──────────
|
|
76
|
-
// Bedrock matches Anthropic list pricing for Claude family.
|
|
77
|
-
'bedrock/anthropic.claude-opus-4-7': { inputPer1k: 0.015, outputPer1k: 0.075, cacheWritePer1k: 0.01875, cacheReadPer1k: 0.0015, _snapshotDate: '2026-05-11' },
|
|
78
|
-
'bedrock/anthropic.claude-sonnet-4-6': { inputPer1k: 0.003, outputPer1k: 0.015, cacheWritePer1k: 0.00375, cacheReadPer1k: 0.0003, _snapshotDate: '2026-05-11' },
|
|
79
|
-
'bedrock/anthropic.claude-haiku-4-5': { inputPer1k: 0.0008, outputPer1k: 0.004, cacheWritePer1k: 0.001, cacheReadPer1k: 0.00008, _snapshotDate: '2026-05-11' },
|
|
80
|
-
'bedrock/anthropic.claude-3-5-sonnet': { inputPer1k: 0.003, outputPer1k: 0.015, cacheWritePer1k: 0.00375, cacheReadPer1k: 0.0003, _snapshotDate: '2026-05-11' },
|
|
81
|
-
'bedrock/anthropic.claude-3-5-haiku': { inputPer1k: 0.0008, outputPer1k: 0.004, cacheWritePer1k: 0.001, cacheReadPer1k: 0.00008, _snapshotDate: '2026-05-11' },
|
|
82
|
-
// ─── xAI (Grok) ─────────────────────────────────────────
|
|
83
|
-
'xai/grok-4': { inputPer1k: 0.003, outputPer1k: 0.015, _snapshotDate: '2026-05-11' },
|
|
84
|
-
'xai/grok-3': { inputPer1k: 0.003, outputPer1k: 0.015, _snapshotDate: '2026-05-11' },
|
|
85
|
-
'xai/grok-3-mini': { inputPer1k: 0.0003, outputPer1k: 0.0005, _snapshotDate: '2026-05-11' },
|
|
86
|
-
// ─── DeepSeek ───────────────────────────────────────────
|
|
87
|
-
'deepseek/deepseek-chat': { inputPer1k: 0.00027, outputPer1k: 0.0011, cacheReadPer1k: 0.00007, _snapshotDate: '2026-05-11' },
|
|
88
|
-
'deepseek/deepseek-reasoner': { inputPer1k: 0.00055, outputPer1k: 0.00219, cacheReadPer1k: 0.00014, _snapshotDate: '2026-05-11' },
|
|
89
|
-
// ─── Mistral ────────────────────────────────────────────
|
|
90
|
-
'mistral/mistral-large': { inputPer1k: 0.002, outputPer1k: 0.006, _snapshotDate: '2026-05-11' },
|
|
91
|
-
'mistral/mistral-medium': { inputPer1k: 0.0004, outputPer1k: 0.002, _snapshotDate: '2026-05-11' },
|
|
92
|
-
'mistral/mistral-small': { inputPer1k: 0.0001, outputPer1k: 0.0003, _snapshotDate: '2026-05-11' },
|
|
93
|
-
// ─── Groq ───────────────────────────────────────────────
|
|
94
|
-
'groq/llama-3.3-70b-versatile': { inputPer1k: 0.00059, outputPer1k: 0.00079, _snapshotDate: '2026-05-11' },
|
|
95
|
-
'groq/llama-3.1-8b-instant': { inputPer1k: 0.00005, outputPer1k: 0.00008, _snapshotDate: '2026-05-11' },
|
|
96
|
-
// ─── Cohere ─────────────────────────────────────────────
|
|
97
|
-
'cohere/command-a': { inputPer1k: 0.0025, outputPer1k: 0.01, _snapshotDate: '2026-05-11' },
|
|
98
|
-
'cohere/command-r-plus': { inputPer1k: 0.0025, outputPer1k: 0.01, _snapshotDate: '2026-05-11' },
|
|
99
|
-
'cohere/command-r': { inputPer1k: 0.00015, outputPer1k: 0.0006, _snapshotDate: '2026-05-11' },
|
|
100
|
-
};
|
|
101
|
-
/**
|
|
102
|
-
* Compute USD cost for an agent call given prompt + completion token
|
|
103
|
-
* counts and a pricing catalog.
|
|
104
|
-
*
|
|
105
|
-
* Returns `0` when the model id isn't in `pricing` — eval cost columns
|
|
106
|
-
* shouldn't crash on a fresh model. The budget middleware (A6 phase 3)
|
|
107
|
-
* uses {@link assertKnownModelPricing} to fail loud at config time
|
|
108
|
-
* instead.
|
|
109
|
-
*
|
|
110
|
-
* @param model `<provider>/<model>` id
|
|
111
|
-
* @param promptTokens Input tokens charged at `inputPer1k`
|
|
112
|
-
* @param completionTokens Output tokens charged at `outputPer1k`
|
|
113
|
-
* @param pricing Catalog override (defaults to {@link ModelPricing})
|
|
114
|
-
*/
|
|
115
|
-
export function estimateCost(model, promptTokens, completionTokens, pricing = ModelPricing) {
|
|
116
|
-
const rate = pricing[model];
|
|
117
|
-
if (!rate)
|
|
118
|
-
return 0;
|
|
119
|
-
return (promptTokens * rate.inputPer1k + completionTokens * rate.outputPer1k) / 1000;
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
|
-
* Budget enforcement uses this — fail loud at agent-construction time
|
|
123
|
-
* if the configured model isn't priced. Call from `withBudget(...)` in
|
|
124
|
-
* phase 3.
|
|
125
|
-
*
|
|
126
|
-
* @throws {UnknownModelPricingError} when `pricing[model]` is missing
|
|
127
|
-
*/
|
|
128
|
-
export function assertKnownModelPricing(model, pricing = ModelPricing) {
|
|
129
|
-
const rate = pricing[model];
|
|
130
|
-
if (!rate)
|
|
131
|
-
throw new UnknownModelPricingError(model, pricing);
|
|
132
|
-
return rate;
|
|
133
|
-
}
|
|
134
|
-
/**
|
|
135
|
-
* Thrown by `assertKnownModelPricing` when a model id has no pricing
|
|
136
|
-
* entry. The budget middleware throws this at construction so apps
|
|
137
|
-
* fail at boot, not on first prompt.
|
|
138
|
-
*/
|
|
139
|
-
export class UnknownModelPricingError extends Error {
|
|
140
|
-
model;
|
|
141
|
-
snapshotDate;
|
|
142
|
-
constructor(model, pricing) {
|
|
143
|
-
const sample = Object.keys(pricing)[0];
|
|
144
|
-
const snapshotDate = sample ? (pricing[sample]?._snapshotDate ?? null) : null;
|
|
145
|
-
const sampleSuffix = snapshotDate ? ` (catalog snapshot ${snapshotDate})` : '';
|
|
146
|
-
super(`[Rudder AI] No pricing entry for model "${model}"${sampleSuffix}. ` +
|
|
147
|
-
`Either the model id is misspelled, or the catalog is stale — ` +
|
|
148
|
-
`add an override entry: \`pricing: { ...ModelPricing, "${model}": { inputPer1k, outputPer1k, _snapshotDate } }\`.`);
|
|
149
|
-
this.name = 'UnknownModelPricingError';
|
|
150
|
-
this.model = model;
|
|
151
|
-
this.snapshotDate = snapshotDate;
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
/**
|
|
155
|
-
* Thrown by the budget middleware (A6 phase 3) when a request would
|
|
156
|
-
* exceed a user's daily or monthly cap. Apps that want a different
|
|
157
|
-
* error type can intercept via `withBudget({ onExceeded })` and throw
|
|
158
|
-
* their own.
|
|
159
|
-
*/
|
|
160
|
-
export class BudgetExceededError extends Error {
|
|
161
|
-
userId;
|
|
162
|
-
period;
|
|
163
|
-
spent;
|
|
164
|
-
cap;
|
|
165
|
-
constructor(opts) {
|
|
166
|
-
super(`[Rudder AI] ${opts.period} budget of $${opts.cap.toFixed(2)} exceeded for user ${opts.userId} ` +
|
|
167
|
-
`(spent $${opts.spent.toFixed(4)}).`);
|
|
168
|
-
this.name = 'BudgetExceededError';
|
|
169
|
-
this.userId = opts.userId;
|
|
170
|
-
this.period = opts.period;
|
|
171
|
-
this.spent = opts.spent;
|
|
172
|
-
this.cap = opts.cap;
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
//# sourceMappingURL=pricing.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"pricing.js","sourceRoot":"","sources":["../../src/budget/pricing.ts"],"names":[],"mappings":"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"}
|
package/dist/budget/storage.d.ts
DELETED
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Persistence contract for `withBudget(...)` middleware (#A6 Phase 3).
|
|
3
|
-
*
|
|
4
|
-
* Apps configure a `BudgetStorage` instance — the middleware calls
|
|
5
|
-
* `checkAndDebit()` once before each request (estimated input cost) and
|
|
6
|
-
* once per `usage` chunk (actual output cost). The storage is responsible
|
|
7
|
-
* for atomic increment + cap enforcement.
|
|
8
|
-
*
|
|
9
|
-
* # Atomicity
|
|
10
|
-
*
|
|
11
|
-
* `checkAndDebit` MUST be atomic: a concurrent caller cannot observe a
|
|
12
|
-
* stale `spent` value between the read and the write. Otherwise two
|
|
13
|
-
* requests both pass the check before either debits, and a user can
|
|
14
|
-
* exceed their cap by `costUsd × concurrency`.
|
|
15
|
-
*
|
|
16
|
-
* Implementations:
|
|
17
|
-
* - `memoryBudgetStorage()` — single-process Map; atomic because we never
|
|
18
|
-
* `await` between the read and the write.
|
|
19
|
-
* - `ormBudgetStorage()` (Phase 4) — uses `UPDATE … RETURNING` (Postgres)
|
|
20
|
-
* or row-level `SELECT … FOR UPDATE` (MySQL/SQLite) to keep the read +
|
|
21
|
-
* write in a single transaction.
|
|
22
|
-
* - Redis / Cache impls — would use `INCRBY` + a `EXPIRE`, treating the
|
|
23
|
-
* counter as authoritative.
|
|
24
|
-
*
|
|
25
|
-
* # Period semantics
|
|
26
|
-
*
|
|
27
|
-
* `daily` rolls at the user's local midnight when `timezone` is provided
|
|
28
|
-
* (IANA name, e.g. `'America/New_York'`); UTC otherwise. `monthly` rolls
|
|
29
|
-
* on the calendar-month boundary in the same TZ. Phase 2 does not
|
|
30
|
-
* implement rolling-30-days windows — adds storage complexity for marginal
|
|
31
|
-
* value.
|
|
32
|
-
*/
|
|
33
|
-
export type BudgetPeriod = 'daily' | 'monthly';
|
|
34
|
-
export interface BudgetCheckOptions {
|
|
35
|
-
/** Identifier for the budget owner (typically a user id). */
|
|
36
|
-
userId: string;
|
|
37
|
-
/** Which cap to check against. */
|
|
38
|
-
period: BudgetPeriod;
|
|
39
|
-
/** Cap in USD. Caller resolves `budget()` once per request. */
|
|
40
|
-
cap: number;
|
|
41
|
-
/** Cost to debit in USD. Pass `0` to read the current spent value without mutating. */
|
|
42
|
-
costUsd: number;
|
|
43
|
-
/** Override the clock — useful for tests + period-rollover assertions. */
|
|
44
|
-
now?: Date;
|
|
45
|
-
/** IANA timezone for period boundaries. Defaults to UTC. */
|
|
46
|
-
timezone?: string;
|
|
47
|
-
}
|
|
48
|
-
export interface BudgetCheckResult {
|
|
49
|
-
/** True when the debit was applied; false when it would have exceeded `cap`. */
|
|
50
|
-
allowed: boolean;
|
|
51
|
-
/**
|
|
52
|
-
* Current spend for the period.
|
|
53
|
-
*
|
|
54
|
-
* - When `allowed: true`, this is the value AFTER the debit (i.e.
|
|
55
|
-
* includes `costUsd`).
|
|
56
|
-
* - When `allowed: false`, this is the value BEFORE the rejected debit
|
|
57
|
-
* (i.e. the prior `spent`). This matches the value `BudgetExceededError`
|
|
58
|
-
* should report — the user spent `spent`, the cap was `cap`, the
|
|
59
|
-
* request would have pushed past.
|
|
60
|
-
*/
|
|
61
|
-
spent: number;
|
|
62
|
-
/** The cap passed in `BudgetCheckOptions.cap`, echoed for caller convenience. */
|
|
63
|
-
cap: number;
|
|
64
|
-
}
|
|
65
|
-
export interface BudgetStorage {
|
|
66
|
-
/**
|
|
67
|
-
* Atomically read the current `spent` value, add `costUsd` if the result
|
|
68
|
-
* stays within `cap`, and return the outcome.
|
|
69
|
-
*
|
|
70
|
-
* Pass `costUsd: 0` for a pure read (e.g. for a "you've spent $X today"
|
|
71
|
-
* status display) — the result reflects current spend without mutating.
|
|
72
|
-
*/
|
|
73
|
-
checkAndDebit(opts: BudgetCheckOptions): Promise<BudgetCheckResult>;
|
|
74
|
-
/**
|
|
75
|
-
* Reset the budget counter for `(userId, period)` at the period
|
|
76
|
-
* containing `now` (or "now" by clock). Useful for tests and admin
|
|
77
|
-
* overrides; not required by the middleware.
|
|
78
|
-
*/
|
|
79
|
-
reset?(userId: string, period: BudgetPeriod, now?: Date, timezone?: string): Promise<void>;
|
|
80
|
-
}
|
|
81
|
-
/**
|
|
82
|
-
* Format a `Date` as the bucket key for a billing period.
|
|
83
|
-
*
|
|
84
|
-
* - `daily` → `YYYY-MM-DD` in the given timezone (or UTC)
|
|
85
|
-
* - `monthly` → `YYYY-MM` in the given timezone (or UTC)
|
|
86
|
-
*
|
|
87
|
-
* Used by `memoryBudgetStorage` and `ormBudgetStorage` (Phase 4) to
|
|
88
|
-
* partition the counter by billing window. Exposed publicly so apps
|
|
89
|
-
* computing per-period totals outside the middleware (admin dashboards,
|
|
90
|
-
* tests) get the same bucketing.
|
|
91
|
-
*/
|
|
92
|
-
export declare function periodKey(period: BudgetPeriod, now: Date, timezone?: string): string;
|
|
93
|
-
/**
|
|
94
|
-
* In-process `BudgetStorage` backed by a `Map`. Suitable for tests and
|
|
95
|
-
* single-process dev servers.
|
|
96
|
-
*
|
|
97
|
-
* **Cross-process caveat:** counters live in process-local memory, so
|
|
98
|
-
* queue workers (or any second process) see their own copy. For any app
|
|
99
|
-
* with workers or horizontal scaling, use `ormBudgetStorage()` (Phase 4)
|
|
100
|
-
* or a Redis-backed storage. Use `memoryBudgetStorage()` only when you're
|
|
101
|
-
* sure all budget-relevant code paths run in the same Node process.
|
|
102
|
-
*/
|
|
103
|
-
export declare function memoryBudgetStorage(): BudgetStorage;
|
|
104
|
-
//# sourceMappingURL=storage.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/budget/storage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,SAAS,CAAA;AAE9C,MAAM,WAAW,kBAAkB;IACjC,6DAA6D;IAC7D,MAAM,EAAK,MAAM,CAAA;IACjB,kCAAkC;IAClC,MAAM,EAAK,YAAY,CAAA;IACvB,+DAA+D;IAC/D,GAAG,EAAQ,MAAM,CAAA;IACjB,uFAAuF;IACvF,OAAO,EAAI,MAAM,CAAA;IACjB,0EAA0E;IAC1E,GAAG,CAAC,EAAO,IAAI,CAAA;IACf,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,iBAAiB;IAChC,gFAAgF;IAChF,OAAO,EAAE,OAAO,CAAA;IAChB;;;;;;;;;OASG;IACH,KAAK,EAAE,MAAM,CAAA;IACb,iFAAiF;IACjF,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,MAAM,WAAW,aAAa;IAC5B;;;;;;OAMG;IACH,aAAa,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAA;IAEnE;;;;OAIG;IACH,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,YAAY,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC3F;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,EAAE,IAAI,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAUpF;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,IAAI,aAAa,CAgCnD"}
|
package/dist/budget/storage.js
DELETED
|
Binary file
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"storage.js","sourceRoot":"","sources":["../../src/budget/storage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAuDH;;;;;;;;;;GAUG;AACH,MAAM,UAAU,SAAS,CAAC,MAAoB,EAAE,GAAS,EAAE,QAAiB;IAC1E,kEAAkE;IAClE,MAAM,GAAG,GAAG,IAAI,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE;QAC3C,QAAQ,EAAE,QAAQ,IAAI,KAAK;QAC3B,IAAI,EAAG,SAAS;QAChB,KAAK,EAAE,SAAS;QAChB,GAAG,EAAI,SAAS;KACjB,CAAC,CAAA;IACF,MAAM,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA,CAAC,eAAe;IAC3C,OAAO,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA,CAAC,YAAY;AAChE,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,mBAAmB;IACjC,kEAAkE;IAClE,8DAA8D;IAC9D,MAAM,IAAI,GAAG,IAAI,GAAG,EAAkB,CAAA;IACtC,MAAM,GAAG,GAAG,CAAC,MAAc,EAAE,MAAoB,EAAE,GAAS,EAAE,EAAW,EAAU,EAAE,CACnF,GAAG,MAAM,IAAI,MAAM,IAAI,SAAS,CAAC,MAAM,EAAE,GAAG,EAAE,EAAE,CAAC,EAAE,CAAA;IAErD,OAAO;QACL,sEAAsE;QACtE,sEAAsE;QACtE,yEAAyE;QACzE,sEAAsE;QACtE,gEAAgE;QAChE,aAAa;QACb,KAAK,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,GAAG,IAAI,IAAI,EAAE,EAAE,QAAQ,EAAE;YAC9E,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC;gBAAU,MAAM,IAAI,KAAK,CAAC,8EAA8E,GAAG,EAAE,CAAC,CAAA;YAClJ,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,OAAO,GAAG,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,kFAAkF,OAAO,EAAE,CAAC,CAAA;YAE1J,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAA;YAC5C,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;YAChC,MAAM,SAAS,GAAG,OAAO,GAAG,OAAO,CAAA;YACnC,IAAI,SAAS,GAAG,GAAG,EAAE,CAAC;gBACpB,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,CAAA;YAChD,CAAC;YACD,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,CAAC,CAAA;YACtB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,CAAA;QACjD,CAAC;QAED,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,GAAG,IAAI,IAAI,EAAE,EAAE,QAAQ;YACpD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAA;QACjD,CAAC;KACF,CAAA;AACH,CAAC"}
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
import type { AiMiddleware, MiddlewareContext } from '../types.js';
|
|
2
|
-
import { type ModelPriceEntry } from './pricing.js';
|
|
3
|
-
import type { BudgetPeriod, BudgetStorage } from './storage.js';
|
|
4
|
-
/**
|
|
5
|
-
* Per-period caps in USD. Either or both can be set; periods with `null`
|
|
6
|
-
* / `undefined` are not enforced.
|
|
7
|
-
*/
|
|
8
|
-
export interface BudgetCaps {
|
|
9
|
-
daily?: number | null;
|
|
10
|
-
monthly?: number | null;
|
|
11
|
-
}
|
|
12
|
-
export interface BudgetExceededArgs {
|
|
13
|
-
userId: string;
|
|
14
|
-
period: BudgetPeriod;
|
|
15
|
-
/** Spend recorded BEFORE the rejected debit. */
|
|
16
|
-
spent: number;
|
|
17
|
-
cap: number;
|
|
18
|
-
ctx: MiddlewareContext;
|
|
19
|
-
}
|
|
20
|
-
export interface WithBudgetOptions {
|
|
21
|
-
/**
|
|
22
|
-
* Resolves the user identifier for a given request. Return `null` (or
|
|
23
|
-
* `undefined`) to bypass budget enforcement entirely — useful for
|
|
24
|
-
* unauthenticated paths or admin tooling.
|
|
25
|
-
*
|
|
26
|
-
* Async return supported.
|
|
27
|
-
*/
|
|
28
|
-
user(ctx: MiddlewareContext): string | null | undefined | Promise<string | null | undefined>;
|
|
29
|
-
/**
|
|
30
|
-
* USD caps for the resolved user. Called once per request (per agent
|
|
31
|
-
* step, more precisely). Caps may be set per-tier / per-plan by reading
|
|
32
|
-
* the user from your DB inside the callback.
|
|
33
|
-
*/
|
|
34
|
-
budget(args: {
|
|
35
|
-
userId: string;
|
|
36
|
-
ctx: MiddlewareContext;
|
|
37
|
-
}): BudgetCaps | Promise<BudgetCaps>;
|
|
38
|
-
/**
|
|
39
|
-
* Where counters persist. Use {@link memoryBudgetStorage} for tests +
|
|
40
|
-
* single-process dev; `ormBudgetStorage` (#A6 Phase 4) for production.
|
|
41
|
-
*/
|
|
42
|
-
storage: BudgetStorage;
|
|
43
|
-
/**
|
|
44
|
-
* Pricing catalog. Defaults to the shipped {@link ModelPricing}; spread
|
|
45
|
-
* to override entries for negotiated rates:
|
|
46
|
-
*
|
|
47
|
-
* ```ts
|
|
48
|
-
* pricing: { ...ModelPricing, 'anthropic/claude-opus-4-7': { ... } }
|
|
49
|
-
* ```
|
|
50
|
-
*/
|
|
51
|
-
pricing?: Record<string, ModelPriceEntry>;
|
|
52
|
-
/**
|
|
53
|
-
* Called when a debit would exceed a cap. Default throws
|
|
54
|
-
* {@link BudgetExceededError}; supply your own to log/alert before
|
|
55
|
-
* throwing, or to throw a different error class. Must throw — return
|
|
56
|
-
* value is ignored. The throw aborts the agent run before the model
|
|
57
|
-
* call.
|
|
58
|
-
*/
|
|
59
|
-
onExceeded?(args: BudgetExceededArgs): never | Promise<never>;
|
|
60
|
-
/**
|
|
61
|
-
* IANA timezone for daily / monthly period rollover. Defaults to UTC.
|
|
62
|
-
* Use the user's tz to roll caps at user-local midnight (matches
|
|
63
|
-
* billing dashboards).
|
|
64
|
-
*/
|
|
65
|
-
timezone?: string;
|
|
66
|
-
/**
|
|
67
|
-
* Approximate-tokens estimator used for the pre-debit. Defaults to
|
|
68
|
-
* `Math.ceil(text.length / 4)` — fine for English-heavy prompts. Pass
|
|
69
|
-
* a tiktoken-backed estimator for accuracy.
|
|
70
|
-
*/
|
|
71
|
-
estimateTokens?: (text: string) => number;
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Per-user spend cap middleware (#A6 Phase 3).
|
|
75
|
-
*
|
|
76
|
-
* Pre-debits an input-cost estimate before each provider call (refusing
|
|
77
|
-
* with {@link BudgetExceededError} if the user would exceed any
|
|
78
|
-
* configured cap), then debits the actual cost difference once the
|
|
79
|
-
* `usage` chunk arrives.
|
|
80
|
-
*
|
|
81
|
-
* The pre-debit reserves budget so two concurrent requests can't both
|
|
82
|
-
* pass the check before either is billed — the `BudgetStorage` contract
|
|
83
|
-
* (#A6 Phase 2) requires `checkAndDebit` to be atomic.
|
|
84
|
-
*
|
|
85
|
-
* # Example
|
|
86
|
-
*
|
|
87
|
-
* ```ts
|
|
88
|
-
* import { withBudget, memoryBudgetStorage, ModelPricing } from '@rudderjs/ai'
|
|
89
|
-
*
|
|
90
|
-
* const budgeted = withBudget({
|
|
91
|
-
* user: (ctx) => ctx.context as string, // your app's user-id source
|
|
92
|
-
* budget: () => ({ daily: 0.50, monthly: 10 }), // USD
|
|
93
|
-
* storage: memoryBudgetStorage(),
|
|
94
|
-
* pricing: ModelPricing,
|
|
95
|
-
* })
|
|
96
|
-
*
|
|
97
|
-
* class MyAgent extends Agent {
|
|
98
|
-
* middleware() { return [budgeted] }
|
|
99
|
-
* }
|
|
100
|
-
* ```
|
|
101
|
-
*
|
|
102
|
-
* # Caveats
|
|
103
|
-
*
|
|
104
|
-
* - **Refunds on errors are not issued.** If the provider call fails
|
|
105
|
-
* after the pre-debit, the estimate stays debited. This avoids the
|
|
106
|
-
* complexity of distinguishing partial-credit cases (the model may
|
|
107
|
-
* have produced output before erroring). Apps that need refund-on-error
|
|
108
|
-
* should subscribe via `onError` and call `storage` directly.
|
|
109
|
-
* - **Cache token deltas not counted.** `TokenUsage` does not yet expose
|
|
110
|
-
* `cacheReadInputTokens` / `cacheWriteInputTokens`; cached requests are
|
|
111
|
-
* billed at the full `inputPer1k` rate today. Refining this is a phase
|
|
112
|
-
* 3.x follow-up that needs a `TokenUsage` widening.
|
|
113
|
-
* - **Tokenizer differences.** The default token estimator is
|
|
114
|
-
* `text.length / 4`. Provider-reported `usage.promptTokens` may differ
|
|
115
|
-
* by a few percent. Pass `estimateTokens: …` for a tiktoken-accurate
|
|
116
|
-
* pre-debit if your caps are tight.
|
|
117
|
-
*/
|
|
118
|
-
export declare function withBudget(opts: WithBudgetOptions): AiMiddleware;
|
|
119
|
-
//# sourceMappingURL=with-budget.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"with-budget.d.ts","sourceRoot":"","sources":["../../src/budget/with-budget.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,YAAY,EAEZ,iBAAiB,EAClB,MAAM,aAAa,CAAA;AACpB,OAAO,EAIL,KAAK,eAAe,EACrB,MAAM,cAAc,CAAA;AACrB,OAAO,KAAK,EACV,YAAY,EACZ,aAAa,EACd,MAAM,cAAc,CAAA;AAErB;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,EAAI,MAAM,GAAG,IAAI,CAAA;IACvB,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACxB;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,YAAY,CAAA;IACpB,gDAAgD;IAChD,KAAK,EAAG,MAAM,CAAA;IACd,GAAG,EAAK,MAAM,CAAA;IACd,GAAG,EAAK,iBAAiB,CAAA;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAChC;;;;;;OAMG;IACH,IAAI,CAAC,GAAG,EAAE,iBAAiB,GAAG,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAA;IAE5F;;;;OAIG;IACH,MAAM,CAAC,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,iBAAiB,CAAA;KAAE,GAAG,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,CAAA;IAE1F;;;OAGG;IACH,OAAO,EAAE,aAAa,CAAA;IAEtB;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAA;IAEzC;;;;;;OAMG;IACH,UAAU,CAAC,CAAC,IAAI,EAAE,kBAAkB,GAAG,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,CAAA;IAE7D;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IAEjB;;;;OAIG;IACH,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAA;CAC1C;AAgBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,iBAAiB,GAAG,YAAY,CAmGhE"}
|
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
import { BudgetExceededError, ModelPricing, assertKnownModelPricing, } from './pricing.js';
|
|
2
|
-
const BudgetState = Symbol.for('rudderjs.ai.budget.state');
|
|
3
|
-
/**
|
|
4
|
-
* Per-user spend cap middleware (#A6 Phase 3).
|
|
5
|
-
*
|
|
6
|
-
* Pre-debits an input-cost estimate before each provider call (refusing
|
|
7
|
-
* with {@link BudgetExceededError} if the user would exceed any
|
|
8
|
-
* configured cap), then debits the actual cost difference once the
|
|
9
|
-
* `usage` chunk arrives.
|
|
10
|
-
*
|
|
11
|
-
* The pre-debit reserves budget so two concurrent requests can't both
|
|
12
|
-
* pass the check before either is billed — the `BudgetStorage` contract
|
|
13
|
-
* (#A6 Phase 2) requires `checkAndDebit` to be atomic.
|
|
14
|
-
*
|
|
15
|
-
* # Example
|
|
16
|
-
*
|
|
17
|
-
* ```ts
|
|
18
|
-
* import { withBudget, memoryBudgetStorage, ModelPricing } from '@rudderjs/ai'
|
|
19
|
-
*
|
|
20
|
-
* const budgeted = withBudget({
|
|
21
|
-
* user: (ctx) => ctx.context as string, // your app's user-id source
|
|
22
|
-
* budget: () => ({ daily: 0.50, monthly: 10 }), // USD
|
|
23
|
-
* storage: memoryBudgetStorage(),
|
|
24
|
-
* pricing: ModelPricing,
|
|
25
|
-
* })
|
|
26
|
-
*
|
|
27
|
-
* class MyAgent extends Agent {
|
|
28
|
-
* middleware() { return [budgeted] }
|
|
29
|
-
* }
|
|
30
|
-
* ```
|
|
31
|
-
*
|
|
32
|
-
* # Caveats
|
|
33
|
-
*
|
|
34
|
-
* - **Refunds on errors are not issued.** If the provider call fails
|
|
35
|
-
* after the pre-debit, the estimate stays debited. This avoids the
|
|
36
|
-
* complexity of distinguishing partial-credit cases (the model may
|
|
37
|
-
* have produced output before erroring). Apps that need refund-on-error
|
|
38
|
-
* should subscribe via `onError` and call `storage` directly.
|
|
39
|
-
* - **Cache token deltas not counted.** `TokenUsage` does not yet expose
|
|
40
|
-
* `cacheReadInputTokens` / `cacheWriteInputTokens`; cached requests are
|
|
41
|
-
* billed at the full `inputPer1k` rate today. Refining this is a phase
|
|
42
|
-
* 3.x follow-up that needs a `TokenUsage` widening.
|
|
43
|
-
* - **Tokenizer differences.** The default token estimator is
|
|
44
|
-
* `text.length / 4`. Provider-reported `usage.promptTokens` may differ
|
|
45
|
-
* by a few percent. Pass `estimateTokens: …` for a tiktoken-accurate
|
|
46
|
-
* pre-debit if your caps are tight.
|
|
47
|
-
*/
|
|
48
|
-
export function withBudget(opts) {
|
|
49
|
-
const pricing = opts.pricing ?? ModelPricing;
|
|
50
|
-
const tz = opts.timezone;
|
|
51
|
-
const estimateTokens = opts.estimateTokens ?? defaultEstimateTokens;
|
|
52
|
-
const onExceeded = opts.onExceeded ?? defaultOnExceeded;
|
|
53
|
-
return {
|
|
54
|
-
name: 'budget',
|
|
55
|
-
async onIteration(ctx) {
|
|
56
|
-
// Pre-debit fires before each model call (every step), including
|
|
57
|
-
// step 1. `onIteration` runs after `onStart` but before
|
|
58
|
-
// `prepareStep`/`onConfig('beforeModel')` — so transforms applied by
|
|
59
|
-
// those later hooks (e.g. a `prepareStep` model swap) aren't
|
|
60
|
-
// reflected in this estimate. For v1 that's acceptable; tighten
|
|
61
|
-
// later if it bites.
|
|
62
|
-
const userId = await opts.user(ctx);
|
|
63
|
-
if (userId == null)
|
|
64
|
-
return; // bypass — unauthenticated path or admin
|
|
65
|
-
const modelKey = ctx.model;
|
|
66
|
-
// Fail loud if the model isn't priced — silently zero-costing through
|
|
67
|
-
// a typo'd model is the worst-of-both for budget enforcement.
|
|
68
|
-
const rate = assertKnownModelPricing(modelKey, pricing);
|
|
69
|
-
const caps = await opts.budget({ userId, ctx });
|
|
70
|
-
const definedCaps = [];
|
|
71
|
-
if (caps.daily != null)
|
|
72
|
-
definedCaps.push({ period: 'daily', cap: caps.daily });
|
|
73
|
-
if (caps.monthly != null)
|
|
74
|
-
definedCaps.push({ period: 'monthly', cap: caps.monthly });
|
|
75
|
-
if (definedCaps.length === 0)
|
|
76
|
-
return; // nothing to enforce
|
|
77
|
-
// Estimate input cost for THIS step from the live messages array.
|
|
78
|
-
const estimate = estimateInputCostUsd(ctx.messages, [], rate, estimateTokens);
|
|
79
|
-
// Pre-debit each defined period; throw on first denial.
|
|
80
|
-
for (const { period, cap } of definedCaps) {
|
|
81
|
-
const r = await opts.storage.checkAndDebit({
|
|
82
|
-
userId,
|
|
83
|
-
period,
|
|
84
|
-
cap,
|
|
85
|
-
costUsd: estimate,
|
|
86
|
-
...(tz != null ? { timezone: tz } : {}),
|
|
87
|
-
});
|
|
88
|
-
if (!r.allowed) {
|
|
89
|
-
await onExceeded({ userId, period, spent: r.spent, cap: r.cap, ctx });
|
|
90
|
-
// If onExceeded didn't throw, fall back to the default error so
|
|
91
|
-
// the run is always aborted on a denied debit.
|
|
92
|
-
throw new BudgetExceededError({ userId, period, spent: r.spent, cap: r.cap });
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
// Stash for onUsage true-up. If estimate was high vs actual we just
|
|
96
|
-
// accept the small over-charge; if low, onUsage debits the delta.
|
|
97
|
-
;
|
|
98
|
-
ctx[BudgetState] = {
|
|
99
|
-
userId,
|
|
100
|
-
caps: definedCaps,
|
|
101
|
-
pendingEstimate: estimate,
|
|
102
|
-
};
|
|
103
|
-
},
|
|
104
|
-
async onUsage(ctx, usage) {
|
|
105
|
-
const state = ctx[BudgetState];
|
|
106
|
-
if (!state)
|
|
107
|
-
return; // no user, was bypassed
|
|
108
|
-
const modelKey = ctx.model;
|
|
109
|
-
const rate = pricing[modelKey];
|
|
110
|
-
// If pricing was found at onConfig time it's still found here; this is
|
|
111
|
-
// belt-and-suspenders for the rare case where the agent loop swapped
|
|
112
|
-
// models mid-run (failover). Skip silently — the pre-debit covered
|
|
113
|
-
// estimate, so we under-charge actual on a missing-rate model.
|
|
114
|
-
if (!rate) {
|
|
115
|
-
state.pendingEstimate = 0;
|
|
116
|
-
return;
|
|
117
|
-
}
|
|
118
|
-
const actualCost = (usage.promptTokens * rate.inputPer1k +
|
|
119
|
-
usage.completionTokens * rate.outputPer1k) / 1000;
|
|
120
|
-
const delta = actualCost - state.pendingEstimate;
|
|
121
|
-
state.pendingEstimate = 0; // clear so a tool round-trip's next onConfig starts fresh
|
|
122
|
-
if (delta <= 0)
|
|
123
|
-
return; // overestimated; accept the small over-charge
|
|
124
|
-
// Always-apply true-up — the response already streamed, we can't
|
|
125
|
-
// unspend. Pass MAX_SAFE_INTEGER as cap so the storage just records
|
|
126
|
-
// the delta. Pre-debit enforcement already happened at onConfig.
|
|
127
|
-
for (const { period } of state.caps) {
|
|
128
|
-
await opts.storage.checkAndDebit({
|
|
129
|
-
userId: state.userId,
|
|
130
|
-
period,
|
|
131
|
-
cap: Number.MAX_SAFE_INTEGER,
|
|
132
|
-
costUsd: delta,
|
|
133
|
-
...(tz != null ? { timezone: tz } : {}),
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
},
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
// ─── Helpers ──────────────────────────────────────────────
|
|
140
|
-
function defaultEstimateTokens(text) {
|
|
141
|
-
return Math.ceil(text.length / 4);
|
|
142
|
-
}
|
|
143
|
-
function defaultOnExceeded(args) {
|
|
144
|
-
throw new BudgetExceededError({
|
|
145
|
-
userId: args.userId,
|
|
146
|
-
period: args.period,
|
|
147
|
-
spent: args.spent,
|
|
148
|
-
cap: args.cap,
|
|
149
|
-
});
|
|
150
|
-
}
|
|
151
|
-
function estimateInputCostUsd(messages, systemPrompts, rate, estimateTokens) {
|
|
152
|
-
// Concatenating all input into one string for the estimator means a
|
|
153
|
-
// single tokenizer pass for tiktoken-backed estimators (cheaper than
|
|
154
|
-
// tokenizing each message separately and summing).
|
|
155
|
-
const parts = [...systemPrompts];
|
|
156
|
-
for (const m of messages)
|
|
157
|
-
parts.push(messageText(m));
|
|
158
|
-
const tokens = estimateTokens(parts.join('\n'));
|
|
159
|
-
return (tokens * rate.inputPer1k) / 1000;
|
|
160
|
-
}
|
|
161
|
-
function messageText(m) {
|
|
162
|
-
if (typeof m.content === 'string')
|
|
163
|
-
return m.content;
|
|
164
|
-
if (Array.isArray(m.content)) {
|
|
165
|
-
let s = '';
|
|
166
|
-
for (const part of m.content)
|
|
167
|
-
s += contentPartText(part);
|
|
168
|
-
return s;
|
|
169
|
-
}
|
|
170
|
-
return '';
|
|
171
|
-
}
|
|
172
|
-
function contentPartText(p) {
|
|
173
|
-
return p.type === 'text' ? p.text : '';
|
|
174
|
-
}
|
|
175
|
-
//# sourceMappingURL=with-budget.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"with-budget.js","sourceRoot":"","sources":["../../src/budget/with-budget.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type { EmbeddingAdapter, EmbeddingResult } from './types.js';
|
|
2
|
-
/**
|
|
3
|
-
* In-memory caching wrapper for any EmbeddingAdapter.
|
|
4
|
-
*
|
|
5
|
-
* Caches embeddings by `model:text` key so repeated inputs skip the provider call.
|
|
6
|
-
* Cache hits report zero token usage since no API call is made.
|
|
7
|
-
*/
|
|
8
|
-
export declare class CachedEmbeddingAdapter implements EmbeddingAdapter {
|
|
9
|
-
private inner;
|
|
10
|
-
private cache;
|
|
11
|
-
constructor(inner: EmbeddingAdapter);
|
|
12
|
-
embed(input: string | string[], model: string): Promise<EmbeddingResult>;
|
|
13
|
-
}
|
|
14
|
-
//# sourceMappingURL=cached-embedding.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cached-embedding.d.ts","sourceRoot":"","sources":["../src/cached-embedding.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAEnE;;;;;GAKG;AACH,qBAAa,sBAAuB,YAAW,gBAAgB;IAGjD,OAAO,CAAC,KAAK;IAFzB,OAAO,CAAC,KAAK,CAA8B;gBAEvB,KAAK,EAAE,gBAAgB;IAErC,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;CAgC/E"}
|