@theokit/sdk-budget 0.3.1 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # Changelog — @theokit/sdk-budget
2
2
 
3
+ ## 0.3.2
4
+
5
+ ### Patch Changes
6
+
7
+ - 8790f70: Refuse a `workspace:` range before it can reach npm.
8
+
9
+ Five of this repo's twelve publishable packages declare internal dependencies as `workspace:^`, which
10
+ is correct on disk and becomes an unrecoverable defect if the publish goes out through a tool that
11
+ does not rewrite it: `pnpm` resolves the protocol while packing, `npm` ships the manifest verbatim.
12
+ A version published that way fails to install for everyone and cannot be corrected — only
13
+ deprecated.
14
+
15
+ Every publishable package now runs the guard in `prepublishOnly`, so it fires whichever way the
16
+ publish is invoked, and `pnpm release` runs it once across the repo before `changeset publish`.
17
+
18
+ Note for anyone reading a published manifest: the `prepublishOnly` entry points at a path inside
19
+ this repository. It never runs for a consumer — the hook only fires when the package itself is
20
+ published — and guarding the entry point that a hand-run `npm publish` actually uses was worth the
21
+ cosmetic wart of shipping the line.
22
+
3
23
  ## 0.3.1
4
24
 
5
25
  ### Patch Changes
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/format-cost.ts","../src/internal/calendar-window.ts","../src/internal/ledger.ts","../src/internal/registry.ts","../src/internal/enforcement.ts","../src/internal/normalize-usage.ts","../src/usd-pricing.ts","../src/usd-budget-tracker.ts"],"names":["withCwdMutex","ConfigurationError","BudgetExceededError"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * M7-6 — honest-null cost render helper. Turns the `number | undefined` cost\n * (from `computeUsdCost` / `getTotalUsd`, M1-6) into a display string: an\n * unknown cost renders as `\"—\"` (NEVER a dishonest `\"$0\"`), a real number\n * renders as `\"$X.XX\"`. Composes the cost-honesty contract — a known-zero cost\n * (`0`) is distinct from an unknown one (`undefined`).\n *\n * @public\n */\n\n/** Options for {@link formatCostUsd}. */\nexport interface FormatCostUsdOptions {\n /** Marker for an unknown cost (`undefined`). Default `\"—\"`. */\n readonly unknown?: string;\n /** Currency prefix for a known cost. Default `\"$\"`. */\n readonly currency?: string;\n}\n\n/**\n * Render a USD cost for display. `undefined` -> the unknown marker (`\"—\"` by\n * default); a number -> `\"$X.XX\"` (2 decimal places). `0` is a real known-zero\n * and renders `\"$0.00\"`, NOT the unknown marker.\n */\nexport function formatCostUsd(cost: number | undefined, opts: FormatCostUsdOptions = {}): string {\n if (cost === undefined) return opts.unknown ?? \"—\";\n return `${opts.currency ?? \"$\"}${cost.toFixed(2)}`;\n}\n","/**\n * UTC-aligned calendar window helpers (ADR D382).\n *\n * - `1h` — relative (now - 1 hour).\n * - `1d` — UTC midnight (current UTC day).\n * - `1w` — UTC monday 00:00:00 (current UTC week, Monday is week start).\n * - `30d` — relative 30 days.\n * - `365d` — relative 365 days.\n *\n * `1d` and `1w` are calendar-aligned because users expect \"1 USD per day\"\n * = \"since midnight UTC\", not a rolling 24h.\n * `30d`/`365d` are relative because nobody expects \"since the 1st\".\n *\n * @internal\n */\n\nimport type { BudgetWindow } from \"@theokit/sdk\";\n\nexport function startOfDayUtc(now: Date = new Date()): Date {\n return new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()));\n}\n\nexport function startOfWeekUtc(now: Date = new Date()): Date {\n // ISO 8601 week starts on Monday. getUTCDay() returns 0 (Sun) .. 6 (Sat).\n const dayOfWeek = now.getUTCDay();\n const daysSinceMonday = (dayOfWeek + 6) % 7; // Mon=0, Sun=6\n const start = startOfDayUtc(now);\n start.setUTCDate(start.getUTCDate() - daysSinceMonday);\n return start;\n}\n\nconst MS_PER_HOUR = 60 * 60 * 1000;\nconst MS_PER_DAY = 24 * MS_PER_HOUR;\n\n/** Returns the inclusive start timestamp (ms) for the given window relative to `now`. */\nexport function windowStartMs(window: BudgetWindow, now: Date = new Date()): number {\n switch (window) {\n case \"1h\":\n return now.getTime() - MS_PER_HOUR;\n case \"1d\":\n return startOfDayUtc(now).getTime();\n case \"1w\":\n return startOfWeekUtc(now).getTime();\n case \"30d\":\n return now.getTime() - 30 * MS_PER_DAY;\n case \"365d\":\n return now.getTime() - 365 * MS_PER_DAY;\n default: {\n const _exhaustive: never = window;\n throw new Error(`unreachable window: ${_exhaustive as string}`);\n }\n }\n}\n","/**\n * In-process Budget ledger (ADR D385).\n *\n * Singleton mutex-protected. Stores per-budget ChargeLog[] arrays;\n * `spentIn(window)` filters by timestamp.\n *\n * EC-6: GC eviction runs DENTRO do mesmo mutex que charge — sem race.\n * EC-9: charge() é called inside same critical section as preflight\n * check by Budget enforcement.\n *\n * Persistence cross-restart: deferred to v0.2 (JsonFile pattern).\n *\n * @internal\n */\n\nimport { type BudgetWindow, withCwdMutex } from \"@theokit/sdk\";\nimport { windowStartMs } from \"./calendar-window.js\";\n\ninterface ChargeLog {\n timestamp: number;\n amountUsd: number;\n}\n\nconst MS_PER_YEAR = 365 * 24 * 60 * 60 * 1000;\nconst GC_INTERVAL_MS = 5 * 60 * 1000; // 5 minutes\nconst GC_LOGS_THRESHOLD = 10_000;\n\ninterface LedgerState {\n readonly logs: Map<string, ChargeLog[]>;\n lastGcAt: number;\n}\n\nlet state: LedgerState = {\n logs: new Map(),\n lastGcAt: Date.now(),\n};\n\nconst MUTEX_KEY = \"budget-ledger\";\n\nfunction shouldGc(now: number): boolean {\n if (now - state.lastGcAt < GC_INTERVAL_MS) return false;\n let totalLogs = 0;\n for (const arr of state.logs.values()) totalLogs += arr.length;\n return totalLogs > GC_LOGS_THRESHOLD;\n}\n\nfunction gcOlderThanOneYear(now: number): void {\n const cutoff = now - MS_PER_YEAR;\n for (const [name, arr] of state.logs.entries()) {\n const kept = arr.filter((l) => l.timestamp >= cutoff);\n if (kept.length === 0) state.logs.delete(name);\n else state.logs.set(name, kept);\n }\n state.lastGcAt = now;\n}\n\n/** Charge a budget. Idempotent across concurrent calls via withCwdMutex. */\nexport async function charge(name: string, amountUsd: number): Promise<void> {\n if (amountUsd <= 0) return;\n await withCwdMutex(MUTEX_KEY, async () => {\n const now = Date.now();\n const list = state.logs.get(name) ?? [];\n list.push({ timestamp: now, amountUsd });\n state.logs.set(name, list);\n if (shouldGc(now)) gcOlderThanOneYear(now);\n });\n}\n\n/** Return total spend in the given window for `name`. Snapshot read (no mutex needed). */\nexport function spentIn(name: string, window: BudgetWindow, now: Date = new Date()): number {\n const arr = state.logs.get(name);\n if (arr === undefined) return 0;\n const sinceMs = windowStartMs(window, now);\n let total = 0;\n for (const log of arr) {\n if (log.timestamp >= sinceMs) total += log.amountUsd;\n }\n return total;\n}\n\n/** Diagnostic — total logs across all budgets. */\nfunction __getLogCountForTests(name?: string): number {\n if (name !== undefined) return state.logs.get(name)?.length ?? 0;\n let total = 0;\n for (const arr of state.logs.values()) total += arr.length;\n return total;\n}\n\nfunction __resetLedgerForTests(): void {\n state = { logs: new Map(), lastGcAt: Date.now() };\n}\n\n/** Force GC manually (tests only). */\nasync function __evictNowForTests(): Promise<void> {\n await withCwdMutex(MUTEX_KEY, async () => {\n gcOlderThanOneYear(Date.now());\n });\n}\n\n/** Force-insert a log at a specific timestamp (tests only). */\nfunction __injectLogForTests(name: string, timestamp: number, amountUsd: number): void {\n const list = state.logs.get(name) ?? [];\n list.push({ timestamp, amountUsd });\n state.logs.set(name, list);\n}\n","/**\n * Internal Budget registry — keeps live `BudgetOptions` per name.\n * Singleton; no persistence (D385).\n *\n * @internal\n */\n\nimport {\n type BudgetHandle,\n type BudgetMode,\n type BudgetOptions,\n type BudgetSnapshot,\n type BudgetWindow,\n ConfigurationError,\n} from \"@theokit/sdk\";\nimport { spentIn } from \"./ledger.js\";\n\nconst NAME_GRAMMAR = /^[a-z0-9][a-z0-9_-]*$/;\n\nconst registry = new Map<string, BudgetOptions>();\n\nfunction __resetRegistryForTests(): void {\n registry.clear();\n}\n\nfunction validateBudgetName(name: string): void {\n if (typeof name !== \"string\" || name.length === 0) {\n throw new ConfigurationError(\"Budget name must be a non-empty string\", {\n code: \"invalid_budget_name\",\n });\n }\n if (!NAME_GRAMMAR.test(name)) {\n throw new ConfigurationError(\n `Budget name \"${name}\" must match ^[a-z0-9][a-z0-9_-]*$ (lowercase + dash/underscore, start alphanumeric)`,\n { code: \"invalid_budget_name\" },\n );\n }\n}\n\nexport function createBudget(opts: BudgetOptions): BudgetHandle {\n // EC-7: name validation\n validateBudgetName(opts.name);\n if (registry.has(opts.name)) {\n // EC-16: duplicate throws (vs Task.submit idempotent return)\n throw new ConfigurationError(`Budget \"${opts.name}\" already exists`, {\n code: \"invalid_budget_name\",\n });\n }\n registry.set(opts.name, opts);\n return buildHandle(opts);\n}\n\nexport function getBudget(name: string): BudgetHandle | undefined {\n const opts = registry.get(name);\n if (opts === undefined) return undefined;\n return buildHandle(opts);\n}\n\nexport function listBudgets(): readonly BudgetHandle[] {\n return [...registry.values()].map(buildHandle);\n}\n\nexport function deleteBudget(name: string): boolean {\n return registry.delete(name);\n}\n\nexport function snapshotAll(): readonly BudgetSnapshot[] {\n const result: BudgetSnapshot[] = [];\n for (const opts of registry.values()) {\n for (const lim of opts.limits) {\n const spent = spentIn(opts.name, lim.window);\n result.push({\n name: opts.name,\n window: lim.window,\n spentUsd: spent,\n limitUsd: lim.limitUsd,\n ratio: lim.limitUsd > 0 ? spent / lim.limitUsd : 0,\n });\n }\n }\n return result;\n}\n\nexport function getBudgetOptionsRaw(name: string): BudgetOptions | undefined {\n return registry.get(name);\n}\n\nexport function defaultMode(opts: BudgetOptions): BudgetMode {\n return opts.mode ?? \"warn\";\n}\n\nfunction buildHandle(opts: BudgetOptions): BudgetHandle {\n return {\n name: opts.name,\n mode: defaultMode(opts),\n scope: opts.scope,\n limits: opts.limits,\n spentIn: (window: BudgetWindow) => spentIn(opts.name, window),\n remainingIn: (window: BudgetWindow) => {\n const lim = opts.limits.find((l) => l.window === window);\n if (lim === undefined) return Number.POSITIVE_INFINITY;\n return Math.max(0, lim.limitUsd - spentIn(opts.name, window));\n },\n };\n}\n","/**\n * Budget enforcement (ADRs D383, D386, EC-7/8/9).\n *\n * - `preflightCheck(name, estimatedUsd)` — em `block` mode, throw\n * `BudgetExceededError` antes da LLM call se qualquer limit seria\n * excedido (EC-9 — caller chama dentro do mutex section).\n * - `chargeAndCheckThresholds(name, actualUsd)` — apply charge ao\n * ledger + invoca onThreshold/onExceed callbacks isolated em\n * try/catch (EC-8).\n *\n * @internal\n */\n\nimport { BudgetExceededError, type BudgetMode, type BudgetOptions } from \"@theokit/sdk\";\nimport { charge, spentIn } from \"./ledger.js\";\nimport { defaultMode, getBudgetOptionsRaw } from \"./registry.js\";\n\nconst THRESHOLDS = [0.8, 0.95] as const;\ntype Threshold = (typeof THRESHOLDS)[number];\n\n/**\n * Throws BudgetExceededError if `mode === \"block\"` and any limit\n * would be exceeded. No-op for audit/warn modes (post-charge checks\n * handle those).\n *\n * Caller invokes this BEFORE the LLM call.\n */\nexport function preflightCheck(name: string, estimatedUsd: number): void {\n const opts = getBudgetOptionsRaw(name);\n if (opts === undefined) return; // EC-20: budget deleted; charge becomes no-op\n if (defaultMode(opts) !== \"block\") return;\n for (const lim of opts.limits) {\n const currentSpent = spentIn(opts.name, lim.window);\n if (currentSpent + estimatedUsd > lim.limitUsd) {\n throw new BudgetExceededError({\n budgetName: opts.name,\n window: lim.window,\n spentUsd: currentSpent + estimatedUsd,\n limitUsd: lim.limitUsd,\n mode: \"block\",\n });\n }\n }\n}\n\n/**\n * Charge the budget + dispatch threshold/exceed callbacks (EC-8 isolated).\n *\n * - In `audit` mode: charge only, no callbacks.\n * - In `warn` mode: charge + onThreshold (80/95) + onExceed (100). No throw.\n * - In `block` mode: charge + onThreshold + onExceed. No throw post-call\n * (preflightCheck already prevented exceed for the upcoming call;\n * this protects against simultaneous-call races where multiple sends\n * each pass preflight independently — last one to charge may still\n * tip a limit. We document the case rather than retroactively throw).\n */\nexport async function chargeAndCheckThresholds(name: string, actualUsd: number): Promise<void> {\n const opts = getBudgetOptionsRaw(name);\n if (opts === undefined) {\n // EC-20: budget deleted during in-flight call. Charge is silent no-op.\n process.stderr.write(\n `[budget] charge for deleted budget \"${name}\" is a no-op (was the budget removed during in-flight send?)\\n`,\n );\n return;\n }\n const mode = defaultMode(opts);\n\n await charge(opts.name, actualUsd);\n\n if (mode === \"audit\") return;\n await dispatchCallbacksFor(opts, mode);\n}\n\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: 3-mode × 3-threshold dispatch table inherently branchy; pulling out helpers loses local context.\nasync function dispatchCallbacksFor(opts: BudgetOptions, mode: BudgetMode): Promise<void> {\n for (const lim of opts.limits) {\n const spent = spentIn(opts.name, lim.window);\n if (lim.limitUsd <= 0) {\n if (spent > 0) await dispatchExceed(opts, lim.window, spent, lim.limitUsd, mode);\n continue;\n }\n const ratio = spent / lim.limitUsd;\n if (ratio >= 1) {\n await dispatchExceed(opts, lim.window, spent, lim.limitUsd, mode);\n } else {\n // Iterate descending so the HIGHEST matched threshold fires (0.95 not 0.8)\n for (const t of [...THRESHOLDS].reverse() as Threshold[]) {\n if (ratio >= t) {\n await dispatchThreshold(opts, lim.window, spent, lim.limitUsd, t);\n break;\n }\n }\n }\n }\n}\n\nasync function dispatchThreshold(\n opts: BudgetOptions,\n window: BudgetOptions[\"limits\"][number][\"window\"],\n spentUsd: number,\n limitUsd: number,\n threshold: Threshold,\n): Promise<void> {\n if (opts.onThreshold === undefined) return;\n try {\n await opts.onThreshold({\n budgetName: opts.name,\n window,\n threshold,\n spentUsd,\n limitUsd,\n });\n } catch (err) {\n // EC-8: callback throw isolated\n const msg = err instanceof Error ? err.message : String(err);\n process.stderr.write(`[budget] onThreshold callback threw: ${msg}\\n`);\n }\n}\n\nasync function dispatchExceed(\n opts: BudgetOptions,\n window: BudgetOptions[\"limits\"][number][\"window\"],\n spentUsd: number,\n limitUsd: number,\n mode: BudgetMode,\n): Promise<void> {\n if (opts.onExceed === undefined) {\n if (mode === \"warn\") {\n process.stderr.write(\n `[budget] \"${opts.name}\" exceeded ${window} limit: $${spentUsd.toFixed(4)} > $${limitUsd.toFixed(4)}\\n`,\n );\n }\n return;\n }\n try {\n await opts.onExceed({\n budgetName: opts.name,\n window,\n spentUsd,\n limitUsd,\n mode,\n });\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n process.stderr.write(`[budget] onExceed callback threw: ${msg}\\n`);\n }\n}\n","/**\n * normalizeUsage — convert provider-shaped raw `usage` object to\n * canonical `TokenUsage`. Ports Hermes Agent's `normalize_usage`\n * (referencia/hermes-agent/agent/usage_pricing.py:672-742).\n *\n * Handles 3 API shapes:\n * - Anthropic Messages: 4 explicit buckets (input/output/cache_read/cache_creation).\n * - OpenAI Chat Completions: prompt_tokens INCLUDES cache; subtract cached_tokens.\n * - OpenAI Responses (Codex): input_tokens INCLUDES cache; same subtraction.\n *\n * Edge cases:\n * - cline#10266 — OpenAI-compat proxies (OpenRouter, Vercel AI Gateway,\n * Cline) routing Claude expose Anthropic-style top-level fields\n * (cache_read_input_tokens / cache_creation_input_tokens). Both\n * locations are checked with top-level fallback.\n * - Null/undefined fields → 0 via `int()` coerce.\n * - String token counts → parsed via int.\n * - Negative values → clamped to 0 (defensive against proxy bugs).\n *\n * @internal\n */\n\nimport type { TokenUsage } from \"@theokit/sdk\";\n\ntype ApiMode = \"anthropic_messages\" | \"openai_chat_completions\" | \"openai_responses\";\n\nfunction int(v: unknown): number {\n if (typeof v === \"number\") return Number.isFinite(v) ? Math.max(0, Math.trunc(v)) : 0;\n if (typeof v === \"string\") {\n const n = Number.parseInt(v, 10);\n return Number.isFinite(n) ? Math.max(0, n) : 0;\n }\n return 0;\n}\n\nfunction buildTotal(buckets: {\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n}): number {\n // total = visible input + cache buckets + output (reasoning counted via output)\n return (\n buckets.inputTokens + buckets.outputTokens + buckets.cacheReadTokens + buckets.cacheWriteTokens\n );\n}\n\nfunction omitUndefined(usage: {\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n reasoningTokens: number;\n totalTokens: number;\n}): TokenUsage {\n return {\n inputTokens: usage.inputTokens,\n outputTokens: usage.outputTokens,\n ...(usage.cacheReadTokens > 0 ? { cacheReadTokens: usage.cacheReadTokens } : {}),\n ...(usage.cacheWriteTokens > 0 ? { cacheWriteTokens: usage.cacheWriteTokens } : {}),\n ...(usage.reasoningTokens > 0 ? { reasoningTokens: usage.reasoningTokens } : {}),\n totalTokens: usage.totalTokens,\n };\n}\n\nexport function inferApiMode(provider: string): ApiMode {\n const p = provider.toLowerCase();\n if (p === \"anthropic\" || p === \"claude\" || p === \"bedrock_anthropic\") {\n return \"anthropic_messages\";\n }\n if (p === \"openai-codex\" || p === \"codex\") return \"openai_responses\";\n // openai, openrouter, deepseek, google (compat), ollama (compat), lmstudio (compat), etc\n return \"openai_chat_completions\";\n}\n\ninterface RawRecord {\n [k: string]: unknown;\n}\n\nexport function normalizeUsage(\n rawUsage: unknown,\n opts: { provider: string; apiMode?: ApiMode },\n): TokenUsage {\n if (rawUsage === null || rawUsage === undefined) {\n return { inputTokens: 0, outputTokens: 0, totalTokens: 0 };\n }\n if (typeof rawUsage !== \"object\") {\n return { inputTokens: 0, outputTokens: 0, totalTokens: 0 };\n }\n const raw = rawUsage as RawRecord;\n const mode = opts.apiMode ?? inferApiMode(opts.provider);\n\n if (mode === \"anthropic_messages\") return normalizeAnthropic(raw);\n if (mode === \"openai_responses\") return normalizeOpenAIResponses(raw);\n return normalizeOpenAIChat(raw);\n}\n\nfunction normalizeAnthropic(raw: RawRecord): TokenUsage {\n const inputTokens = int(raw.input_tokens);\n const outputTokens = int(raw.output_tokens);\n const cacheReadTokens = int(raw.cache_read_input_tokens);\n const cacheWriteTokens = int(raw.cache_creation_input_tokens);\n const usage = {\n inputTokens,\n outputTokens,\n cacheReadTokens,\n cacheWriteTokens,\n reasoningTokens: 0,\n totalTokens: buildTotal({ inputTokens, outputTokens, cacheReadTokens, cacheWriteTokens }),\n };\n return omitUndefined(usage);\n}\n\nfunction normalizeOpenAIResponses(raw: RawRecord): TokenUsage {\n const inputTotal = int(raw.input_tokens);\n const outputTokens = int(raw.output_tokens);\n const inputDetails = (raw.input_tokens_details as RawRecord | undefined) ?? {};\n const outputDetails = (raw.output_tokens_details as RawRecord | undefined) ?? {};\n const cacheReadTokens = int(inputDetails.cached_tokens);\n const cacheWriteTokens = int(inputDetails.cache_creation_tokens);\n const reasoningTokens = int(outputDetails.reasoning_tokens);\n const inputTokens = Math.max(0, inputTotal - cacheReadTokens - cacheWriteTokens);\n const usage = {\n inputTokens,\n outputTokens,\n cacheReadTokens,\n cacheWriteTokens,\n reasoningTokens,\n totalTokens: buildTotal({ inputTokens, outputTokens, cacheReadTokens, cacheWriteTokens }),\n };\n return omitUndefined(usage);\n}\n\nfunction normalizeOpenAIChat(raw: RawRecord): TokenUsage {\n const promptTotal = int(raw.prompt_tokens);\n const outputTokens = int(raw.completion_tokens);\n const promptDetails = (raw.prompt_tokens_details as RawRecord | undefined) ?? {};\n const completionDetails = (raw.completion_tokens_details as RawRecord | undefined) ?? {};\n\n // cline#10266 fallback — proxies expose Anthropic-style top-level fields when routing Claude\n const cacheReadTokens = int(promptDetails.cached_tokens) || int(raw.cache_read_input_tokens);\n const cacheWriteTokens =\n int(promptDetails.cache_write_tokens) || int(raw.cache_creation_input_tokens);\n\n const reasoningTokens = int(completionDetails.reasoning_tokens);\n const inputTokens = Math.max(0, promptTotal - cacheReadTokens - cacheWriteTokens);\n const usage = {\n inputTokens,\n outputTokens,\n cacheReadTokens,\n cacheWriteTokens,\n reasoningTokens,\n totalTokens: buildTotal({ inputTokens, outputTokens, cacheReadTokens, cacheWriteTokens }),\n };\n return omitUndefined(usage);\n}\n","/**\n * Built-in per-model USD pricing table (SDK 2.0 Phase 2 / sdk-budget T2.X).\n *\n * Prices are in USD per 1M tokens (input / output). Sources: each\n * provider's public pricing page; values verified 2026-06 against\n * the same tier used in sdk-core's `internal/budget/pricing-data.json`.\n *\n * The table is intentionally CONSERVATIVE — only the most-used models\n * land here. Consumers needing exhaustive coverage can supply an\n * override via `createUsdBudgetTracker({ pricing })`.\n *\n * @public\n */\n\nexport interface ModelPricing {\n /** USD per 1,000,000 input tokens. */\n readonly inputPerMillionUsd: number;\n /** USD per 1,000,000 output tokens. */\n readonly outputPerMillionUsd: number;\n}\n\n/** Built-in pricing table — exhaustive enough for v0.1; users supply overrides for niche models. */\nexport const BUILTIN_PRICING: Readonly<Record<string, ModelPricing>> = Object.freeze({\n // OpenAI / OpenRouter aliases\n \"openai/gpt-4o\": { inputPerMillionUsd: 2.5, outputPerMillionUsd: 10 },\n \"openai/gpt-4o-mini\": { inputPerMillionUsd: 0.15, outputPerMillionUsd: 0.6 },\n \"openai/gpt-4-turbo\": { inputPerMillionUsd: 10, outputPerMillionUsd: 30 },\n \"openai/gpt-3.5-turbo\": { inputPerMillionUsd: 0.5, outputPerMillionUsd: 1.5 },\n // Anthropic / Claude\n \"anthropic/claude-3-5-sonnet-latest\": { inputPerMillionUsd: 3, outputPerMillionUsd: 15 },\n \"anthropic/claude-3-5-haiku-latest\": { inputPerMillionUsd: 0.8, outputPerMillionUsd: 4 },\n \"anthropic/claude-3-opus-latest\": { inputPerMillionUsd: 15, outputPerMillionUsd: 75 },\n // Google\n \"google/gemini-1.5-pro\": { inputPerMillionUsd: 1.25, outputPerMillionUsd: 5 },\n \"google/gemini-1.5-flash\": { inputPerMillionUsd: 0.075, outputPerMillionUsd: 0.3 },\n});\n\n/**\n * Compute USD cost for a single token event.\n *\n * Returns `undefined` (NOT `0`, NOT throws) when the model is UNKNOWN — its\n * cost is genuinely unknown, and coercing it to `$0` would be dishonest (cost\n * contract `D377-cost-status-closed-enum.md`: amount-unknown ≠ `$0`). Consumers\n * who want a price for a niche model supply an override via\n * `createUsdBudgetTracker({ pricing })`. A KNOWN model with zero/invalid tokens\n * returns `0` — that is a real, known `$0`.\n */\nexport function computeUsdCost(\n pricing: Readonly<Record<string, ModelPricing>>,\n model: string,\n type: \"input\" | \"output\",\n tokens: number,\n): number | undefined {\n const entry = pricing[model];\n if (entry === undefined) return undefined;\n const ratePerMillion = type === \"input\" ? entry.inputPerMillionUsd : entry.outputPerMillionUsd;\n if (!Number.isFinite(tokens) || tokens <= 0) return 0;\n return (tokens / 1_000_000) * ratePerMillion;\n}\n","/**\n * `createUsdBudgetTracker` — USD-cost-aware `BudgetTracker` impl shipped\n * in `@theokit/sdk-budget` (SDK 2.0 Phase 2 / T2.X).\n *\n * Extends the counter pattern from `createCounterBudgetTracker`\n * (sdk-core reference impl) with per-model USD cost computation via\n * the `BUILTIN_PRICING` table.\n *\n * Use cases:\n * - Cap total spend per agent run (`maxUsd`).\n * - Cap total tokens (`maxTokens`) AND USD ceiling simultaneously.\n * - Observe cumulative USD from outside (`getTotalUsd()`).\n *\n * Tracker.check() returns `allowed: false` when ANY of the configured\n * caps is exceeded. `reason` is one of:\n * - `\"token_limit\"` — `maxTokens` reached\n * - `\"cost_limit\"` — `maxUsd` reached\n *\n * Layered design (mirrors counter impl):\n * - `track()` is sync + non-throwing (clamps invalid values).\n * - `check()` is sync (allowed: true unless a cap is exceeded).\n * - `getTotal()` returns the SDK-required token + iteration totals\n * ONLY (USD is exposed via the bonus `getTotalUsd()` method).\n *\n * @public\n */\n\nimport type { BudgetCheck, BudgetTotal, BudgetTracker, BudgetUsageEvent } from \"@theokit/sdk\";\nimport { BUILTIN_PRICING, computeUsdCost, type ModelPricing } from \"./usd-pricing.js\";\n\n/** Options for `createUsdBudgetTracker`. */\nexport interface UsdBudgetTrackerOptions {\n /** Hard ceiling on total tokens (input + output combined). */\n readonly maxTokens?: number;\n /** Hard ceiling on cumulative USD spend. */\n readonly maxUsd?: number;\n /** Optional override map — model id → pricing entry. Merged onto BUILTIN_PRICING. */\n readonly pricing?: Readonly<Record<string, ModelPricing>>;\n}\n\n/** The cost-cap denial for the current state, or `null` if the cost cap is satisfied. */\nfunction evaluateCostCap(\n maxUsd: number | undefined,\n costKnown: boolean,\n totalUsd: number,\n): BudgetCheck | null {\n if (maxUsd === undefined) return null;\n if (!costKnown) {\n // Fail closed: a spend cap is set but cost is unknown — we cannot prove the\n // run is under budget, so deny rather than allow unbounded spend.\n return {\n allowed: false,\n reason: \"cost_limit\",\n detail: `cost unknown — cannot verify maxUsd ${maxUsd}`,\n };\n }\n if (totalUsd >= maxUsd) {\n return {\n allowed: false,\n reason: \"cost_limit\",\n detail: `USD ${totalUsd.toFixed(6)} >= maxUsd ${maxUsd}`,\n };\n }\n return null;\n}\n\n/** The token-cap denial for the current state, or `null` if the token cap is satisfied. */\nfunction evaluateTokenCap(maxTokens: number | undefined, totalTokens: number): BudgetCheck | null {\n if (maxTokens !== undefined && totalTokens >= maxTokens) {\n return {\n allowed: false,\n reason: \"token_limit\",\n detail: `${totalTokens} >= maxTokens ${maxTokens}`,\n };\n }\n return null;\n}\n\n/**\n * Build a fresh USD-aware tracker. The returned object exposes the\n * `BudgetTracker` contract PLUS `getTotalUsd()` + `nextIteration()`\n * helpers for explicit iteration counting.\n */\nexport function createUsdBudgetTracker(\n options: UsdBudgetTrackerOptions = {},\n): BudgetTracker & { nextIteration(): void; getTotalUsd(): number | undefined } {\n let totalTokens = 0;\n let iterations = 0;\n let totalUsd = 0;\n // Honest-null (D377): once any round's cost is UNKNOWN, the aggregate becomes\n // unknown and STAYS unknown — a later known round does not resurrect it.\n let costKnown = true;\n const maxTokens = options.maxTokens;\n const maxUsd = options.maxUsd;\n const pricing: Readonly<Record<string, ModelPricing>> =\n options.pricing !== undefined ? { ...BUILTIN_PRICING, ...options.pricing } : BUILTIN_PRICING;\n\n return {\n track(event: BudgetUsageEvent): void {\n // Sync + non-throwing per contract. Invalid events silently clamped.\n const t = Number.isFinite(event.tokens) && event.tokens > 0 ? event.tokens : 0;\n if (t === 0) return;\n totalTokens += t;\n const cost = computeUsdCost(pricing, event.model, event.type, t);\n if (cost === undefined) {\n costKnown = false; // poison — do NOT add 0 (that would be a dishonest $0)\n return;\n }\n if (costKnown) totalUsd += cost;\n },\n\n check(): BudgetCheck {\n // Cost cap is evaluated first (USD is the higher-signal denial for a human).\n return (\n evaluateCostCap(maxUsd, costKnown, totalUsd) ??\n evaluateTokenCap(maxTokens, totalTokens) ?? { allowed: true }\n );\n },\n\n getTotal(): BudgetTotal {\n return { tokens: totalTokens, iterations };\n },\n\n getTotalUsd(): number | undefined {\n return costKnown ? totalUsd : undefined;\n },\n\n nextIteration(): void {\n iterations += 1;\n },\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/format-cost.ts","../src/internal/calendar-window.ts","../src/internal/ledger.ts","../src/internal/registry.ts","../src/internal/enforcement.ts","../src/internal/normalize-usage.ts","../src/usd-pricing.ts","../src/usd-budget-tracker.ts"],"names":["withCwdMutex","ConfigurationError","BudgetExceededError"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * M7-6 — honest-null cost render helper. Turns the `number | undefined` cost\n * (from `computeUsdCost` / `getTotalUsd`, M1-6) into a display string: an\n * unknown cost renders as `\"—\"` (NEVER a dishonest `\"$0\"`), a real number\n * renders as `\"$X.XX\"`. Composes the cost-honesty contract — a known-zero cost\n * (`0`) is distinct from an unknown one (`undefined`).\n *\n * @public\n */\n\n/** Options for {@link formatCostUsd}. */\nexport interface FormatCostUsdOptions {\n /** Marker for an unknown cost (`undefined`). Default `\"—\"`. */\n readonly unknown?: string;\n /** Currency prefix for a known cost. Default `\"$\"`. */\n readonly currency?: string;\n}\n\n/**\n * Render a USD cost for display. `undefined` -> the unknown marker (`\"—\"` by\n * default); a number -> `\"$X.XX\"` (2 decimal places). `0` is a real known-zero\n * and renders `\"$0.00\"`, NOT the unknown marker.\n */\nexport function formatCostUsd(cost: number | undefined, opts: FormatCostUsdOptions = {}): string {\n if (cost === undefined) return opts.unknown ?? \"—\";\n return `${opts.currency ?? \"$\"}${cost.toFixed(2)}`;\n}\n","/**\n * UTC-aligned calendar window helpers (ADR D382).\n *\n * - `1h` — relative (now - 1 hour).\n * - `1d` — UTC midnight (current UTC day).\n * - `1w` — UTC monday 00:00:00 (current UTC week, Monday is week start).\n * - `30d` — relative 30 days.\n * - `365d` — relative 365 days.\n *\n * `1d` and `1w` are calendar-aligned because users expect \"1 USD per day\"\n * = \"since midnight UTC\", not a rolling 24h.\n * `30d`/`365d` are relative because nobody expects \"since the 1st\".\n *\n * @internal\n */\n\nimport type { BudgetWindow } from \"@theokit/sdk\";\n\nexport function startOfDayUtc(now: Date = new Date()): Date {\n return new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()));\n}\n\nexport function startOfWeekUtc(now: Date = new Date()): Date {\n // ISO 8601 week starts on Monday. getUTCDay() returns 0 (Sun) .. 6 (Sat).\n const dayOfWeek = now.getUTCDay();\n const daysSinceMonday = (dayOfWeek + 6) % 7; // Mon=0, Sun=6\n const start = startOfDayUtc(now);\n start.setUTCDate(start.getUTCDate() - daysSinceMonday);\n return start;\n}\n\nconst MS_PER_HOUR = 60 * 60 * 1000;\nconst MS_PER_DAY = 24 * MS_PER_HOUR;\n\n/** Returns the inclusive start timestamp (ms) for the given window relative to `now`. */\nexport function windowStartMs(window: BudgetWindow, now: Date = new Date()): number {\n switch (window) {\n case \"1h\":\n return now.getTime() - MS_PER_HOUR;\n case \"1d\":\n return startOfDayUtc(now).getTime();\n case \"1w\":\n return startOfWeekUtc(now).getTime();\n case \"30d\":\n return now.getTime() - 30 * MS_PER_DAY;\n case \"365d\":\n return now.getTime() - 365 * MS_PER_DAY;\n default: {\n const _exhaustive: never = window;\n throw new Error(`unreachable window: ${_exhaustive as string}`);\n }\n }\n}\n","/**\n * In-process Budget ledger (ADR D385).\n *\n * Singleton mutex-protected. Stores per-budget ChargeLog[] arrays;\n * `spentIn(window)` filters by timestamp.\n *\n * EC-6: GC eviction runs INSIDE the same mutex as charge — no race.\n * EC-9: charge() is called inside the same critical section as preflight\n * check by Budget enforcement.\n *\n * Persistence cross-restart: deferred to v0.2 (JsonFile pattern).\n *\n * @internal\n */\n\nimport { type BudgetWindow, withCwdMutex } from \"@theokit/sdk\";\nimport { windowStartMs } from \"./calendar-window.js\";\n\ninterface ChargeLog {\n timestamp: number;\n amountUsd: number;\n}\n\nconst MS_PER_YEAR = 365 * 24 * 60 * 60 * 1000;\nconst GC_INTERVAL_MS = 5 * 60 * 1000; // 5 minutes\nconst GC_LOGS_THRESHOLD = 10_000;\n\ninterface LedgerState {\n readonly logs: Map<string, ChargeLog[]>;\n lastGcAt: number;\n}\n\nconst state: LedgerState = {\n logs: new Map(),\n lastGcAt: Date.now(),\n};\n\nconst MUTEX_KEY = \"budget-ledger\";\n\nfunction shouldGc(now: number): boolean {\n if (now - state.lastGcAt < GC_INTERVAL_MS) return false;\n let totalLogs = 0;\n for (const arr of state.logs.values()) totalLogs += arr.length;\n return totalLogs > GC_LOGS_THRESHOLD;\n}\n\nfunction gcOlderThanOneYear(now: number): void {\n const cutoff = now - MS_PER_YEAR;\n for (const [name, arr] of state.logs.entries()) {\n const kept = arr.filter((l) => l.timestamp >= cutoff);\n if (kept.length === 0) state.logs.delete(name);\n else state.logs.set(name, kept);\n }\n state.lastGcAt = now;\n}\n\n/** Charge a budget. Idempotent across concurrent calls via withCwdMutex. */\nexport async function charge(name: string, amountUsd: number): Promise<void> {\n if (amountUsd <= 0) return;\n await withCwdMutex(MUTEX_KEY, async () => {\n const now = Date.now();\n const list = state.logs.get(name) ?? [];\n list.push({ timestamp: now, amountUsd });\n state.logs.set(name, list);\n if (shouldGc(now)) gcOlderThanOneYear(now);\n });\n}\n\n/** Return total spend in the given window for `name`. Snapshot read (no mutex needed). */\nexport function spentIn(name: string, window: BudgetWindow, now: Date = new Date()): number {\n const arr = state.logs.get(name);\n if (arr === undefined) return 0;\n const sinceMs = windowStartMs(window, now);\n let total = 0;\n for (const log of arr) {\n if (log.timestamp >= sinceMs) total += log.amountUsd;\n }\n return total;\n}\n","/**\n * Internal Budget registry — keeps live `BudgetOptions` per name.\n * Singleton; no persistence (D385).\n *\n * @internal\n */\n\nimport {\n type BudgetHandle,\n type BudgetMode,\n type BudgetOptions,\n type BudgetSnapshot,\n type BudgetWindow,\n ConfigurationError,\n} from \"@theokit/sdk\";\nimport { spentIn } from \"./ledger.js\";\n\nconst NAME_GRAMMAR = /^[a-z0-9][a-z0-9_-]*$/;\n\nconst registry = new Map<string, BudgetOptions>();\n\nfunction validateBudgetName(name: string): void {\n if (typeof name !== \"string\" || name.length === 0) {\n throw new ConfigurationError(\"Budget name must be a non-empty string\", {\n code: \"invalid_budget_name\",\n });\n }\n if (!NAME_GRAMMAR.test(name)) {\n throw new ConfigurationError(\n `Budget name \"${name}\" must match ^[a-z0-9][a-z0-9_-]*$ (lowercase + dash/underscore, start alphanumeric)`,\n { code: \"invalid_budget_name\" },\n );\n }\n}\n\nexport function createBudget(opts: BudgetOptions): BudgetHandle {\n // EC-7: name validation\n validateBudgetName(opts.name);\n if (registry.has(opts.name)) {\n // EC-16: duplicate throws (vs Task.submit idempotent return)\n throw new ConfigurationError(`Budget \"${opts.name}\" already exists`, {\n code: \"invalid_budget_name\",\n });\n }\n registry.set(opts.name, opts);\n return buildHandle(opts);\n}\n\nexport function getBudget(name: string): BudgetHandle | undefined {\n const opts = registry.get(name);\n if (opts === undefined) return undefined;\n return buildHandle(opts);\n}\n\nexport function listBudgets(): readonly BudgetHandle[] {\n return [...registry.values()].map(buildHandle);\n}\n\nexport function deleteBudget(name: string): boolean {\n return registry.delete(name);\n}\n\nexport function snapshotAll(): readonly BudgetSnapshot[] {\n const result: BudgetSnapshot[] = [];\n for (const opts of registry.values()) {\n for (const lim of opts.limits) {\n const spent = spentIn(opts.name, lim.window);\n result.push({\n name: opts.name,\n window: lim.window,\n spentUsd: spent,\n limitUsd: lim.limitUsd,\n ratio: lim.limitUsd > 0 ? spent / lim.limitUsd : 0,\n });\n }\n }\n return result;\n}\n\nexport function getBudgetOptionsRaw(name: string): BudgetOptions | undefined {\n return registry.get(name);\n}\n\nexport function defaultMode(opts: BudgetOptions): BudgetMode {\n return opts.mode ?? \"warn\";\n}\n\nfunction buildHandle(opts: BudgetOptions): BudgetHandle {\n return {\n name: opts.name,\n mode: defaultMode(opts),\n scope: opts.scope,\n limits: opts.limits,\n spentIn: (window: BudgetWindow) => spentIn(opts.name, window),\n remainingIn: (window: BudgetWindow) => {\n const lim = opts.limits.find((l) => l.window === window);\n if (lim === undefined) return Number.POSITIVE_INFINITY;\n return Math.max(0, lim.limitUsd - spentIn(opts.name, window));\n },\n };\n}\n","/**\n * Budget enforcement (ADRs D383, D386, EC-7/8/9).\n *\n * - `preflightCheck(name, estimatedUsd)` — em `block` mode, throw\n * `BudgetExceededError` before the LLM call if any limit would be\n * exceeded (EC-9 — the caller invokes it inside the mutex section).\n * - `chargeAndCheckThresholds(name, actualUsd)` — apply charge ao\n * ledger + invokes onThreshold/onExceed callbacks isolated in\n * try/catch (EC-8).\n *\n * @internal\n */\n\nimport { BudgetExceededError, type BudgetMode, type BudgetOptions } from \"@theokit/sdk\";\nimport { charge, spentIn } from \"./ledger.js\";\nimport { defaultMode, getBudgetOptionsRaw } from \"./registry.js\";\n\nconst THRESHOLDS = [0.8, 0.95] as const;\ntype Threshold = (typeof THRESHOLDS)[number];\n\n/**\n * Throws BudgetExceededError if `mode === \"block\"` and any limit\n * would be exceeded. No-op for audit/warn modes (post-charge checks\n * handle those).\n *\n * Caller invokes this BEFORE the LLM call.\n */\nexport function preflightCheck(name: string, estimatedUsd: number): void {\n const opts = getBudgetOptionsRaw(name);\n if (opts === undefined) return; // EC-20: budget deleted; charge becomes no-op\n if (defaultMode(opts) !== \"block\") return;\n for (const lim of opts.limits) {\n const currentSpent = spentIn(opts.name, lim.window);\n if (currentSpent + estimatedUsd > lim.limitUsd) {\n throw new BudgetExceededError({\n budgetName: opts.name,\n window: lim.window,\n spentUsd: currentSpent + estimatedUsd,\n limitUsd: lim.limitUsd,\n mode: \"block\",\n });\n }\n }\n}\n\n/**\n * Charge the budget + dispatch threshold/exceed callbacks (EC-8 isolated).\n *\n * - In `audit` mode: charge only, no callbacks.\n * - In `warn` mode: charge + onThreshold (80/95) + onExceed (100). No throw.\n * - In `block` mode: charge + onThreshold + onExceed. No throw post-call\n * (preflightCheck already prevented exceed for the upcoming call;\n * this protects against simultaneous-call races where multiple sends\n * each pass preflight independently — last one to charge may still\n * tip a limit. We document the case rather than retroactively throw).\n */\nexport async function chargeAndCheckThresholds(name: string, actualUsd: number): Promise<void> {\n const opts = getBudgetOptionsRaw(name);\n if (opts === undefined) {\n // EC-20: budget deleted during in-flight call. Charge is silent no-op.\n process.stderr.write(\n `[budget] charge for deleted budget \"${name}\" is a no-op (was the budget removed during in-flight send?)\\n`,\n );\n return;\n }\n const mode = defaultMode(opts);\n\n await charge(opts.name, actualUsd);\n\n if (mode === \"audit\") return;\n await dispatchCallbacksFor(opts, mode);\n}\n\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: 3-mode × 3-threshold dispatch table inherently branchy; pulling out helpers loses local context.\nasync function dispatchCallbacksFor(opts: BudgetOptions, mode: BudgetMode): Promise<void> {\n for (const lim of opts.limits) {\n const spent = spentIn(opts.name, lim.window);\n if (lim.limitUsd <= 0) {\n if (spent > 0) await dispatchExceed(opts, lim.window, spent, lim.limitUsd, mode);\n continue;\n }\n const ratio = spent / lim.limitUsd;\n if (ratio >= 1) {\n await dispatchExceed(opts, lim.window, spent, lim.limitUsd, mode);\n } else {\n // Iterate descending so the HIGHEST matched threshold fires (0.95 not 0.8)\n for (const t of [...THRESHOLDS].reverse() as Threshold[]) {\n if (ratio >= t) {\n await dispatchThreshold(opts, lim.window, spent, lim.limitUsd, t);\n break;\n }\n }\n }\n }\n}\n\nasync function dispatchThreshold(\n opts: BudgetOptions,\n window: BudgetOptions[\"limits\"][number][\"window\"],\n spentUsd: number,\n limitUsd: number,\n threshold: Threshold,\n): Promise<void> {\n if (opts.onThreshold === undefined) return;\n try {\n await opts.onThreshold({\n budgetName: opts.name,\n window,\n threshold,\n spentUsd,\n limitUsd,\n });\n } catch (err) {\n // EC-8: callback throw isolated\n const msg = err instanceof Error ? err.message : String(err);\n process.stderr.write(`[budget] onThreshold callback threw: ${msg}\\n`);\n }\n}\n\nasync function dispatchExceed(\n opts: BudgetOptions,\n window: BudgetOptions[\"limits\"][number][\"window\"],\n spentUsd: number,\n limitUsd: number,\n mode: BudgetMode,\n): Promise<void> {\n if (opts.onExceed === undefined) {\n if (mode === \"warn\") {\n process.stderr.write(\n `[budget] \"${opts.name}\" exceeded ${window} limit: $${spentUsd.toFixed(4)} > $${limitUsd.toFixed(4)}\\n`,\n );\n }\n return;\n }\n try {\n await opts.onExceed({\n budgetName: opts.name,\n window,\n spentUsd,\n limitUsd,\n mode,\n });\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n process.stderr.write(`[budget] onExceed callback threw: ${msg}\\n`);\n }\n}\n","/**\n * normalizeUsage — convert provider-shaped raw `usage` object to\n * canonical `TokenUsage`. Ports Hermes Agent's `normalize_usage`\n * (reference/peer-agent/agent/usage_pricing.py:672-742).\n *\n * Handles 3 API shapes:\n * - Anthropic Messages: 4 explicit buckets (input/output/cache_read/cache_creation).\n * - OpenAI Chat Completions: prompt_tokens INCLUDES cache; subtract cached_tokens.\n * - OpenAI Responses (Codex): input_tokens INCLUDES cache; same subtraction.\n *\n * Edge cases:\n * - a peer#10266 — OpenAI-compat proxies (OpenRouter, a peer vendor AI Gateway,\n * a peer) routing Claude expose Anthropic-style top-level fields\n * (cache_read_input_tokens / cache_creation_input_tokens). Both\n * locations are checked with top-level fallback.\n * - Null/undefined fields → 0 via `int()` coerce.\n * - String token counts → parsed via int.\n * - Negative values → clamped to 0 (defensive against proxy bugs).\n *\n * @internal\n */\n\nimport type { TokenUsage } from \"@theokit/sdk\";\n\ntype ApiMode = \"anthropic_messages\" | \"openai_chat_completions\" | \"openai_responses\";\n\nfunction int(v: unknown): number {\n if (typeof v === \"number\") return Number.isFinite(v) ? Math.max(0, Math.trunc(v)) : 0;\n if (typeof v === \"string\") {\n const n = Number.parseInt(v, 10);\n return Number.isFinite(n) ? Math.max(0, n) : 0;\n }\n return 0;\n}\n\nfunction buildTotal(buckets: {\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n}): number {\n // total = visible input + cache buckets + output (reasoning counted via output)\n return (\n buckets.inputTokens + buckets.outputTokens + buckets.cacheReadTokens + buckets.cacheWriteTokens\n );\n}\n\nfunction omitUndefined(usage: {\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n reasoningTokens: number;\n totalTokens: number;\n}): TokenUsage {\n return {\n inputTokens: usage.inputTokens,\n outputTokens: usage.outputTokens,\n ...(usage.cacheReadTokens > 0 ? { cacheReadTokens: usage.cacheReadTokens } : {}),\n ...(usage.cacheWriteTokens > 0 ? { cacheWriteTokens: usage.cacheWriteTokens } : {}),\n ...(usage.reasoningTokens > 0 ? { reasoningTokens: usage.reasoningTokens } : {}),\n totalTokens: usage.totalTokens,\n };\n}\n\nexport function inferApiMode(provider: string): ApiMode {\n const p = provider.toLowerCase();\n if (p === \"anthropic\" || p === \"claude\" || p === \"bedrock_anthropic\") {\n return \"anthropic_messages\";\n }\n if (p === \"openai-codex\" || p === \"codex\") return \"openai_responses\";\n // openai, openrouter, deepseek, google (compat), ollama (compat), lmstudio (compat), etc\n return \"openai_chat_completions\";\n}\n\ninterface RawRecord {\n [k: string]: unknown;\n}\n\nexport function normalizeUsage(\n rawUsage: unknown,\n opts: { provider: string; apiMode?: ApiMode },\n): TokenUsage {\n if (rawUsage === null || rawUsage === undefined) {\n return { inputTokens: 0, outputTokens: 0, totalTokens: 0 };\n }\n if (typeof rawUsage !== \"object\") {\n return { inputTokens: 0, outputTokens: 0, totalTokens: 0 };\n }\n const raw = rawUsage as RawRecord;\n const mode = opts.apiMode ?? inferApiMode(opts.provider);\n\n if (mode === \"anthropic_messages\") return normalizeAnthropic(raw);\n if (mode === \"openai_responses\") return normalizeOpenAIResponses(raw);\n return normalizeOpenAIChat(raw);\n}\n\nfunction normalizeAnthropic(raw: RawRecord): TokenUsage {\n const inputTokens = int(raw.input_tokens);\n const outputTokens = int(raw.output_tokens);\n const cacheReadTokens = int(raw.cache_read_input_tokens);\n const cacheWriteTokens = int(raw.cache_creation_input_tokens);\n const usage = {\n inputTokens,\n outputTokens,\n cacheReadTokens,\n cacheWriteTokens,\n reasoningTokens: 0,\n totalTokens: buildTotal({ inputTokens, outputTokens, cacheReadTokens, cacheWriteTokens }),\n };\n return omitUndefined(usage);\n}\n\nfunction normalizeOpenAIResponses(raw: RawRecord): TokenUsage {\n const inputTotal = int(raw.input_tokens);\n const outputTokens = int(raw.output_tokens);\n const inputDetails = (raw.input_tokens_details as RawRecord | undefined) ?? {};\n const outputDetails = (raw.output_tokens_details as RawRecord | undefined) ?? {};\n const cacheReadTokens = int(inputDetails.cached_tokens);\n const cacheWriteTokens = int(inputDetails.cache_creation_tokens);\n const reasoningTokens = int(outputDetails.reasoning_tokens);\n const inputTokens = Math.max(0, inputTotal - cacheReadTokens - cacheWriteTokens);\n const usage = {\n inputTokens,\n outputTokens,\n cacheReadTokens,\n cacheWriteTokens,\n reasoningTokens,\n totalTokens: buildTotal({ inputTokens, outputTokens, cacheReadTokens, cacheWriteTokens }),\n };\n return omitUndefined(usage);\n}\n\nfunction normalizeOpenAIChat(raw: RawRecord): TokenUsage {\n const promptTotal = int(raw.prompt_tokens);\n const outputTokens = int(raw.completion_tokens);\n const promptDetails = (raw.prompt_tokens_details as RawRecord | undefined) ?? {};\n const completionDetails = (raw.completion_tokens_details as RawRecord | undefined) ?? {};\n\n // a peer#10266 fallback — proxies expose Anthropic-style top-level fields when routing Claude\n const cacheReadTokens = int(promptDetails.cached_tokens) || int(raw.cache_read_input_tokens);\n const cacheWriteTokens =\n int(promptDetails.cache_write_tokens) || int(raw.cache_creation_input_tokens);\n\n const reasoningTokens = int(completionDetails.reasoning_tokens);\n const inputTokens = Math.max(0, promptTotal - cacheReadTokens - cacheWriteTokens);\n const usage = {\n inputTokens,\n outputTokens,\n cacheReadTokens,\n cacheWriteTokens,\n reasoningTokens,\n totalTokens: buildTotal({ inputTokens, outputTokens, cacheReadTokens, cacheWriteTokens }),\n };\n return omitUndefined(usage);\n}\n","/**\n * Built-in per-model USD pricing table (SDK 2.0 Phase 2 / sdk-budget T2.X).\n *\n * Prices are in USD per 1M tokens (input / output). Sources: each\n * provider's public pricing page; values verified 2026-06 against\n * the same tier used in sdk-core's `internal/budget/pricing-data.json`.\n *\n * The table is intentionally CONSERVATIVE — only the most-used models\n * land here. Consumers needing exhaustive coverage can supply an\n * override via `createUsdBudgetTracker({ pricing })`.\n *\n * @public\n */\n\nexport interface ModelPricing {\n /** USD per 1,000,000 input tokens. */\n readonly inputPerMillionUsd: number;\n /** USD per 1,000,000 output tokens. */\n readonly outputPerMillionUsd: number;\n}\n\n/** Built-in pricing table — exhaustive enough for v0.1; users supply overrides for niche models. */\nexport const BUILTIN_PRICING: Readonly<Record<string, ModelPricing>> = Object.freeze({\n // OpenAI / OpenRouter aliases\n \"openai/gpt-4o\": { inputPerMillionUsd: 2.5, outputPerMillionUsd: 10 },\n \"openai/gpt-4o-mini\": { inputPerMillionUsd: 0.15, outputPerMillionUsd: 0.6 },\n \"openai/gpt-4-turbo\": { inputPerMillionUsd: 10, outputPerMillionUsd: 30 },\n \"openai/gpt-3.5-turbo\": { inputPerMillionUsd: 0.5, outputPerMillionUsd: 1.5 },\n // Anthropic / Claude\n \"anthropic/claude-3-5-sonnet-latest\": { inputPerMillionUsd: 3, outputPerMillionUsd: 15 },\n \"anthropic/claude-3-5-haiku-latest\": { inputPerMillionUsd: 0.8, outputPerMillionUsd: 4 },\n \"anthropic/claude-3-opus-latest\": { inputPerMillionUsd: 15, outputPerMillionUsd: 75 },\n // Google\n \"google/gemini-1.5-pro\": { inputPerMillionUsd: 1.25, outputPerMillionUsd: 5 },\n \"google/gemini-1.5-flash\": { inputPerMillionUsd: 0.075, outputPerMillionUsd: 0.3 },\n});\n\n/**\n * Compute USD cost for a single token event.\n *\n * Returns `undefined` (NOT `0`, NOT throws) when the model is UNKNOWN — its\n * cost is genuinely unknown, and coercing it to `$0` would be dishonest (cost\n * contract `D377-cost-status-closed-enum.md`: amount-unknown ≠ `$0`). Consumers\n * who want a price for a niche model supply an override via\n * `createUsdBudgetTracker({ pricing })`. A KNOWN model with zero/invalid tokens\n * returns `0` — that is a real, known `$0`.\n */\nexport function computeUsdCost(\n pricing: Readonly<Record<string, ModelPricing>>,\n model: string,\n type: \"input\" | \"output\",\n tokens: number,\n): number | undefined {\n const entry = pricing[model];\n if (entry === undefined) return undefined;\n const ratePerMillion = type === \"input\" ? entry.inputPerMillionUsd : entry.outputPerMillionUsd;\n if (!Number.isFinite(tokens) || tokens <= 0) return 0;\n return (tokens / 1_000_000) * ratePerMillion;\n}\n","/**\n * `createUsdBudgetTracker` — USD-cost-aware `BudgetTracker` impl shipped\n * in `@theokit/sdk-budget` (SDK 2.0 Phase 2 / T2.X).\n *\n * Extends the counter pattern from `createCounterBudgetTracker`\n * (sdk-core reference impl) with per-model USD cost computation via\n * the `BUILTIN_PRICING` table.\n *\n * Use cases:\n * - Cap total spend per agent run (`maxUsd`).\n * - Cap total tokens (`maxTokens`) AND USD ceiling simultaneously.\n * - Observe cumulative USD from outside (`getTotalUsd()`).\n *\n * Tracker.check() returns `allowed: false` when ANY of the configured\n * caps is exceeded. `reason` is one of:\n * - `\"token_limit\"` — `maxTokens` reached\n * - `\"cost_limit\"` — `maxUsd` reached\n *\n * Layered design (mirrors counter impl):\n * - `track()` is sync + non-throwing (clamps invalid values).\n * - `check()` is sync (allowed: true unless a cap is exceeded).\n * - `getTotal()` returns the SDK-required token + iteration totals\n * ONLY (USD is exposed via the bonus `getTotalUsd()` method).\n *\n * @public\n */\n\nimport type { BudgetCheck, BudgetTotal, BudgetTracker, BudgetUsageEvent } from \"@theokit/sdk\";\nimport { BUILTIN_PRICING, computeUsdCost, type ModelPricing } from \"./usd-pricing.js\";\n\n/** Options for `createUsdBudgetTracker`. */\nexport interface UsdBudgetTrackerOptions {\n /** Hard ceiling on total tokens (input + output combined). */\n readonly maxTokens?: number;\n /** Hard ceiling on cumulative USD spend. */\n readonly maxUsd?: number;\n /** Optional override map — model id → pricing entry. Merged onto BUILTIN_PRICING. */\n readonly pricing?: Readonly<Record<string, ModelPricing>>;\n}\n\n/** The cost-cap denial for the current state, or `null` if the cost cap is satisfied. */\nfunction evaluateCostCap(\n maxUsd: number | undefined,\n costKnown: boolean,\n totalUsd: number,\n): BudgetCheck | null {\n if (maxUsd === undefined) return null;\n if (!costKnown) {\n // Fail closed: a spend cap is set but cost is unknown — we cannot prove the\n // run is under budget, so deny rather than allow unbounded spend.\n return {\n allowed: false,\n reason: \"cost_limit\",\n detail: `cost unknown — cannot verify maxUsd ${maxUsd}`,\n };\n }\n if (totalUsd >= maxUsd) {\n return {\n allowed: false,\n reason: \"cost_limit\",\n detail: `USD ${totalUsd.toFixed(6)} >= maxUsd ${maxUsd}`,\n };\n }\n return null;\n}\n\n/** The token-cap denial for the current state, or `null` if the token cap is satisfied. */\nfunction evaluateTokenCap(maxTokens: number | undefined, totalTokens: number): BudgetCheck | null {\n if (maxTokens !== undefined && totalTokens >= maxTokens) {\n return {\n allowed: false,\n reason: \"token_limit\",\n detail: `${totalTokens} >= maxTokens ${maxTokens}`,\n };\n }\n return null;\n}\n\n/**\n * Build a fresh USD-aware tracker. The returned object exposes the\n * `BudgetTracker` contract PLUS `getTotalUsd()` + `nextIteration()`\n * helpers for explicit iteration counting.\n */\nexport function createUsdBudgetTracker(\n options: UsdBudgetTrackerOptions = {},\n): BudgetTracker & { nextIteration(): void; getTotalUsd(): number | undefined } {\n let totalTokens = 0;\n let iterations = 0;\n let totalUsd = 0;\n // Honest-null (D377): once any round's cost is UNKNOWN, the aggregate becomes\n // unknown and STAYS unknown — a later known round does not resurrect it.\n let costKnown = true;\n const maxTokens = options.maxTokens;\n const maxUsd = options.maxUsd;\n const pricing: Readonly<Record<string, ModelPricing>> =\n options.pricing !== undefined ? { ...BUILTIN_PRICING, ...options.pricing } : BUILTIN_PRICING;\n\n return {\n track(event: BudgetUsageEvent): void {\n // Sync + non-throwing per contract. Invalid events silently clamped.\n const t = Number.isFinite(event.tokens) && event.tokens > 0 ? event.tokens : 0;\n if (t === 0) return;\n totalTokens += t;\n const cost = computeUsdCost(pricing, event.model, event.type, t);\n if (cost === undefined) {\n costKnown = false; // poison — do NOT add 0 (that would be a dishonest $0)\n return;\n }\n if (costKnown) totalUsd += cost;\n },\n\n check(): BudgetCheck {\n // Cost cap is evaluated first (USD is the higher-signal denial for a human).\n return (\n evaluateCostCap(maxUsd, costKnown, totalUsd) ??\n evaluateTokenCap(maxTokens, totalTokens) ?? { allowed: true }\n );\n },\n\n getTotal(): BudgetTotal {\n return { tokens: totalTokens, iterations };\n },\n\n getTotalUsd(): number | undefined {\n return costKnown ? totalUsd : undefined;\n },\n\n nextIteration(): void {\n iterations += 1;\n },\n };\n}\n"]}
package/dist/index.d.cts CHANGED
@@ -47,10 +47,10 @@ declare function windowStartMs(window: BudgetWindow, now?: Date): number;
47
47
  * Budget enforcement (ADRs D383, D386, EC-7/8/9).
48
48
  *
49
49
  * - `preflightCheck(name, estimatedUsd)` — em `block` mode, throw
50
- * `BudgetExceededError` antes da LLM call se qualquer limit seria
51
- * excedido (EC-9 — caller chama dentro do mutex section).
50
+ * `BudgetExceededError` before the LLM call if any limit would be
51
+ * exceeded (EC-9 — the caller invokes it inside the mutex section).
52
52
  * - `chargeAndCheckThresholds(name, actualUsd)` — apply charge ao
53
- * ledger + invoca onThreshold/onExceed callbacks isolated em
53
+ * ledger + invokes onThreshold/onExceed callbacks isolated in
54
54
  * try/catch (EC-8).
55
55
  *
56
56
  * @internal
@@ -82,8 +82,8 @@ declare function chargeAndCheckThresholds(name: string, actualUsd: number): Prom
82
82
  * Singleton mutex-protected. Stores per-budget ChargeLog[] arrays;
83
83
  * `spentIn(window)` filters by timestamp.
84
84
  *
85
- * EC-6: GC eviction runs DENTRO do mesmo mutex que charge — sem race.
86
- * EC-9: charge() é called inside same critical section as preflight
85
+ * EC-6: GC eviction runs INSIDE the same mutex as charge — no race.
86
+ * EC-9: charge() is called inside the same critical section as preflight
87
87
  * check by Budget enforcement.
88
88
  *
89
89
  * Persistence cross-restart: deferred to v0.2 (JsonFile pattern).
@@ -98,7 +98,7 @@ declare function spentIn(name: string, window: BudgetWindow, now?: Date): number
98
98
  /**
99
99
  * normalizeUsage — convert provider-shaped raw `usage` object to
100
100
  * canonical `TokenUsage`. Ports Hermes Agent's `normalize_usage`
101
- * (referencia/hermes-agent/agent/usage_pricing.py:672-742).
101
+ * (reference/peer-agent/agent/usage_pricing.py:672-742).
102
102
  *
103
103
  * Handles 3 API shapes:
104
104
  * - Anthropic Messages: 4 explicit buckets (input/output/cache_read/cache_creation).
@@ -106,8 +106,8 @@ declare function spentIn(name: string, window: BudgetWindow, now?: Date): number
106
106
  * - OpenAI Responses (Codex): input_tokens INCLUDES cache; same subtraction.
107
107
  *
108
108
  * Edge cases:
109
- * - cline#10266 — OpenAI-compat proxies (OpenRouter, Vercel AI Gateway,
110
- * Cline) routing Claude expose Anthropic-style top-level fields
109
+ * - a peer#10266 — OpenAI-compat proxies (OpenRouter, a peer vendor AI Gateway,
110
+ * a peer) routing Claude expose Anthropic-style top-level fields
111
111
  * (cache_read_input_tokens / cache_creation_input_tokens). Both
112
112
  * locations are checked with top-level fallback.
113
113
  * - Null/undefined fields → 0 via `int()` coerce.
package/dist/index.d.ts CHANGED
@@ -47,10 +47,10 @@ declare function windowStartMs(window: BudgetWindow, now?: Date): number;
47
47
  * Budget enforcement (ADRs D383, D386, EC-7/8/9).
48
48
  *
49
49
  * - `preflightCheck(name, estimatedUsd)` — em `block` mode, throw
50
- * `BudgetExceededError` antes da LLM call se qualquer limit seria
51
- * excedido (EC-9 — caller chama dentro do mutex section).
50
+ * `BudgetExceededError` before the LLM call if any limit would be
51
+ * exceeded (EC-9 — the caller invokes it inside the mutex section).
52
52
  * - `chargeAndCheckThresholds(name, actualUsd)` — apply charge ao
53
- * ledger + invoca onThreshold/onExceed callbacks isolated em
53
+ * ledger + invokes onThreshold/onExceed callbacks isolated in
54
54
  * try/catch (EC-8).
55
55
  *
56
56
  * @internal
@@ -82,8 +82,8 @@ declare function chargeAndCheckThresholds(name: string, actualUsd: number): Prom
82
82
  * Singleton mutex-protected. Stores per-budget ChargeLog[] arrays;
83
83
  * `spentIn(window)` filters by timestamp.
84
84
  *
85
- * EC-6: GC eviction runs DENTRO do mesmo mutex que charge — sem race.
86
- * EC-9: charge() é called inside same critical section as preflight
85
+ * EC-6: GC eviction runs INSIDE the same mutex as charge — no race.
86
+ * EC-9: charge() is called inside the same critical section as preflight
87
87
  * check by Budget enforcement.
88
88
  *
89
89
  * Persistence cross-restart: deferred to v0.2 (JsonFile pattern).
@@ -98,7 +98,7 @@ declare function spentIn(name: string, window: BudgetWindow, now?: Date): number
98
98
  /**
99
99
  * normalizeUsage — convert provider-shaped raw `usage` object to
100
100
  * canonical `TokenUsage`. Ports Hermes Agent's `normalize_usage`
101
- * (referencia/hermes-agent/agent/usage_pricing.py:672-742).
101
+ * (reference/peer-agent/agent/usage_pricing.py:672-742).
102
102
  *
103
103
  * Handles 3 API shapes:
104
104
  * - Anthropic Messages: 4 explicit buckets (input/output/cache_read/cache_creation).
@@ -106,8 +106,8 @@ declare function spentIn(name: string, window: BudgetWindow, now?: Date): number
106
106
  * - OpenAI Responses (Codex): input_tokens INCLUDES cache; same subtraction.
107
107
  *
108
108
  * Edge cases:
109
- * - cline#10266 — OpenAI-compat proxies (OpenRouter, Vercel AI Gateway,
110
- * Cline) routing Claude expose Anthropic-style top-level fields
109
+ * - a peer#10266 — OpenAI-compat proxies (OpenRouter, a peer vendor AI Gateway,
110
+ * a peer) routing Claude expose Anthropic-style top-level fields
111
111
  * (cache_read_input_tokens / cache_creation_input_tokens). Both
112
112
  * locations are checked with top-level fallback.
113
113
  * - Null/undefined fields → 0 via `int()` coerce.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/format-cost.ts","../src/internal/calendar-window.ts","../src/internal/ledger.ts","../src/internal/registry.ts","../src/internal/enforcement.ts","../src/internal/normalize-usage.ts","../src/usd-pricing.ts","../src/usd-budget-tracker.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * M7-6 — honest-null cost render helper. Turns the `number | undefined` cost\n * (from `computeUsdCost` / `getTotalUsd`, M1-6) into a display string: an\n * unknown cost renders as `\"—\"` (NEVER a dishonest `\"$0\"`), a real number\n * renders as `\"$X.XX\"`. Composes the cost-honesty contract — a known-zero cost\n * (`0`) is distinct from an unknown one (`undefined`).\n *\n * @public\n */\n\n/** Options for {@link formatCostUsd}. */\nexport interface FormatCostUsdOptions {\n /** Marker for an unknown cost (`undefined`). Default `\"—\"`. */\n readonly unknown?: string;\n /** Currency prefix for a known cost. Default `\"$\"`. */\n readonly currency?: string;\n}\n\n/**\n * Render a USD cost for display. `undefined` -> the unknown marker (`\"—\"` by\n * default); a number -> `\"$X.XX\"` (2 decimal places). `0` is a real known-zero\n * and renders `\"$0.00\"`, NOT the unknown marker.\n */\nexport function formatCostUsd(cost: number | undefined, opts: FormatCostUsdOptions = {}): string {\n if (cost === undefined) return opts.unknown ?? \"—\";\n return `${opts.currency ?? \"$\"}${cost.toFixed(2)}`;\n}\n","/**\n * UTC-aligned calendar window helpers (ADR D382).\n *\n * - `1h` — relative (now - 1 hour).\n * - `1d` — UTC midnight (current UTC day).\n * - `1w` — UTC monday 00:00:00 (current UTC week, Monday is week start).\n * - `30d` — relative 30 days.\n * - `365d` — relative 365 days.\n *\n * `1d` and `1w` are calendar-aligned because users expect \"1 USD per day\"\n * = \"since midnight UTC\", not a rolling 24h.\n * `30d`/`365d` are relative because nobody expects \"since the 1st\".\n *\n * @internal\n */\n\nimport type { BudgetWindow } from \"@theokit/sdk\";\n\nexport function startOfDayUtc(now: Date = new Date()): Date {\n return new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()));\n}\n\nexport function startOfWeekUtc(now: Date = new Date()): Date {\n // ISO 8601 week starts on Monday. getUTCDay() returns 0 (Sun) .. 6 (Sat).\n const dayOfWeek = now.getUTCDay();\n const daysSinceMonday = (dayOfWeek + 6) % 7; // Mon=0, Sun=6\n const start = startOfDayUtc(now);\n start.setUTCDate(start.getUTCDate() - daysSinceMonday);\n return start;\n}\n\nconst MS_PER_HOUR = 60 * 60 * 1000;\nconst MS_PER_DAY = 24 * MS_PER_HOUR;\n\n/** Returns the inclusive start timestamp (ms) for the given window relative to `now`. */\nexport function windowStartMs(window: BudgetWindow, now: Date = new Date()): number {\n switch (window) {\n case \"1h\":\n return now.getTime() - MS_PER_HOUR;\n case \"1d\":\n return startOfDayUtc(now).getTime();\n case \"1w\":\n return startOfWeekUtc(now).getTime();\n case \"30d\":\n return now.getTime() - 30 * MS_PER_DAY;\n case \"365d\":\n return now.getTime() - 365 * MS_PER_DAY;\n default: {\n const _exhaustive: never = window;\n throw new Error(`unreachable window: ${_exhaustive as string}`);\n }\n }\n}\n","/**\n * In-process Budget ledger (ADR D385).\n *\n * Singleton mutex-protected. Stores per-budget ChargeLog[] arrays;\n * `spentIn(window)` filters by timestamp.\n *\n * EC-6: GC eviction runs DENTRO do mesmo mutex que charge — sem race.\n * EC-9: charge() é called inside same critical section as preflight\n * check by Budget enforcement.\n *\n * Persistence cross-restart: deferred to v0.2 (JsonFile pattern).\n *\n * @internal\n */\n\nimport { type BudgetWindow, withCwdMutex } from \"@theokit/sdk\";\nimport { windowStartMs } from \"./calendar-window.js\";\n\ninterface ChargeLog {\n timestamp: number;\n amountUsd: number;\n}\n\nconst MS_PER_YEAR = 365 * 24 * 60 * 60 * 1000;\nconst GC_INTERVAL_MS = 5 * 60 * 1000; // 5 minutes\nconst GC_LOGS_THRESHOLD = 10_000;\n\ninterface LedgerState {\n readonly logs: Map<string, ChargeLog[]>;\n lastGcAt: number;\n}\n\nlet state: LedgerState = {\n logs: new Map(),\n lastGcAt: Date.now(),\n};\n\nconst MUTEX_KEY = \"budget-ledger\";\n\nfunction shouldGc(now: number): boolean {\n if (now - state.lastGcAt < GC_INTERVAL_MS) return false;\n let totalLogs = 0;\n for (const arr of state.logs.values()) totalLogs += arr.length;\n return totalLogs > GC_LOGS_THRESHOLD;\n}\n\nfunction gcOlderThanOneYear(now: number): void {\n const cutoff = now - MS_PER_YEAR;\n for (const [name, arr] of state.logs.entries()) {\n const kept = arr.filter((l) => l.timestamp >= cutoff);\n if (kept.length === 0) state.logs.delete(name);\n else state.logs.set(name, kept);\n }\n state.lastGcAt = now;\n}\n\n/** Charge a budget. Idempotent across concurrent calls via withCwdMutex. */\nexport async function charge(name: string, amountUsd: number): Promise<void> {\n if (amountUsd <= 0) return;\n await withCwdMutex(MUTEX_KEY, async () => {\n const now = Date.now();\n const list = state.logs.get(name) ?? [];\n list.push({ timestamp: now, amountUsd });\n state.logs.set(name, list);\n if (shouldGc(now)) gcOlderThanOneYear(now);\n });\n}\n\n/** Return total spend in the given window for `name`. Snapshot read (no mutex needed). */\nexport function spentIn(name: string, window: BudgetWindow, now: Date = new Date()): number {\n const arr = state.logs.get(name);\n if (arr === undefined) return 0;\n const sinceMs = windowStartMs(window, now);\n let total = 0;\n for (const log of arr) {\n if (log.timestamp >= sinceMs) total += log.amountUsd;\n }\n return total;\n}\n\n/** Diagnostic — total logs across all budgets. */\nfunction __getLogCountForTests(name?: string): number {\n if (name !== undefined) return state.logs.get(name)?.length ?? 0;\n let total = 0;\n for (const arr of state.logs.values()) total += arr.length;\n return total;\n}\n\nfunction __resetLedgerForTests(): void {\n state = { logs: new Map(), lastGcAt: Date.now() };\n}\n\n/** Force GC manually (tests only). */\nasync function __evictNowForTests(): Promise<void> {\n await withCwdMutex(MUTEX_KEY, async () => {\n gcOlderThanOneYear(Date.now());\n });\n}\n\n/** Force-insert a log at a specific timestamp (tests only). */\nfunction __injectLogForTests(name: string, timestamp: number, amountUsd: number): void {\n const list = state.logs.get(name) ?? [];\n list.push({ timestamp, amountUsd });\n state.logs.set(name, list);\n}\n","/**\n * Internal Budget registry — keeps live `BudgetOptions` per name.\n * Singleton; no persistence (D385).\n *\n * @internal\n */\n\nimport {\n type BudgetHandle,\n type BudgetMode,\n type BudgetOptions,\n type BudgetSnapshot,\n type BudgetWindow,\n ConfigurationError,\n} from \"@theokit/sdk\";\nimport { spentIn } from \"./ledger.js\";\n\nconst NAME_GRAMMAR = /^[a-z0-9][a-z0-9_-]*$/;\n\nconst registry = new Map<string, BudgetOptions>();\n\nfunction __resetRegistryForTests(): void {\n registry.clear();\n}\n\nfunction validateBudgetName(name: string): void {\n if (typeof name !== \"string\" || name.length === 0) {\n throw new ConfigurationError(\"Budget name must be a non-empty string\", {\n code: \"invalid_budget_name\",\n });\n }\n if (!NAME_GRAMMAR.test(name)) {\n throw new ConfigurationError(\n `Budget name \"${name}\" must match ^[a-z0-9][a-z0-9_-]*$ (lowercase + dash/underscore, start alphanumeric)`,\n { code: \"invalid_budget_name\" },\n );\n }\n}\n\nexport function createBudget(opts: BudgetOptions): BudgetHandle {\n // EC-7: name validation\n validateBudgetName(opts.name);\n if (registry.has(opts.name)) {\n // EC-16: duplicate throws (vs Task.submit idempotent return)\n throw new ConfigurationError(`Budget \"${opts.name}\" already exists`, {\n code: \"invalid_budget_name\",\n });\n }\n registry.set(opts.name, opts);\n return buildHandle(opts);\n}\n\nexport function getBudget(name: string): BudgetHandle | undefined {\n const opts = registry.get(name);\n if (opts === undefined) return undefined;\n return buildHandle(opts);\n}\n\nexport function listBudgets(): readonly BudgetHandle[] {\n return [...registry.values()].map(buildHandle);\n}\n\nexport function deleteBudget(name: string): boolean {\n return registry.delete(name);\n}\n\nexport function snapshotAll(): readonly BudgetSnapshot[] {\n const result: BudgetSnapshot[] = [];\n for (const opts of registry.values()) {\n for (const lim of opts.limits) {\n const spent = spentIn(opts.name, lim.window);\n result.push({\n name: opts.name,\n window: lim.window,\n spentUsd: spent,\n limitUsd: lim.limitUsd,\n ratio: lim.limitUsd > 0 ? spent / lim.limitUsd : 0,\n });\n }\n }\n return result;\n}\n\nexport function getBudgetOptionsRaw(name: string): BudgetOptions | undefined {\n return registry.get(name);\n}\n\nexport function defaultMode(opts: BudgetOptions): BudgetMode {\n return opts.mode ?? \"warn\";\n}\n\nfunction buildHandle(opts: BudgetOptions): BudgetHandle {\n return {\n name: opts.name,\n mode: defaultMode(opts),\n scope: opts.scope,\n limits: opts.limits,\n spentIn: (window: BudgetWindow) => spentIn(opts.name, window),\n remainingIn: (window: BudgetWindow) => {\n const lim = opts.limits.find((l) => l.window === window);\n if (lim === undefined) return Number.POSITIVE_INFINITY;\n return Math.max(0, lim.limitUsd - spentIn(opts.name, window));\n },\n };\n}\n","/**\n * Budget enforcement (ADRs D383, D386, EC-7/8/9).\n *\n * - `preflightCheck(name, estimatedUsd)` — em `block` mode, throw\n * `BudgetExceededError` antes da LLM call se qualquer limit seria\n * excedido (EC-9 — caller chama dentro do mutex section).\n * - `chargeAndCheckThresholds(name, actualUsd)` — apply charge ao\n * ledger + invoca onThreshold/onExceed callbacks isolated em\n * try/catch (EC-8).\n *\n * @internal\n */\n\nimport { BudgetExceededError, type BudgetMode, type BudgetOptions } from \"@theokit/sdk\";\nimport { charge, spentIn } from \"./ledger.js\";\nimport { defaultMode, getBudgetOptionsRaw } from \"./registry.js\";\n\nconst THRESHOLDS = [0.8, 0.95] as const;\ntype Threshold = (typeof THRESHOLDS)[number];\n\n/**\n * Throws BudgetExceededError if `mode === \"block\"` and any limit\n * would be exceeded. No-op for audit/warn modes (post-charge checks\n * handle those).\n *\n * Caller invokes this BEFORE the LLM call.\n */\nexport function preflightCheck(name: string, estimatedUsd: number): void {\n const opts = getBudgetOptionsRaw(name);\n if (opts === undefined) return; // EC-20: budget deleted; charge becomes no-op\n if (defaultMode(opts) !== \"block\") return;\n for (const lim of opts.limits) {\n const currentSpent = spentIn(opts.name, lim.window);\n if (currentSpent + estimatedUsd > lim.limitUsd) {\n throw new BudgetExceededError({\n budgetName: opts.name,\n window: lim.window,\n spentUsd: currentSpent + estimatedUsd,\n limitUsd: lim.limitUsd,\n mode: \"block\",\n });\n }\n }\n}\n\n/**\n * Charge the budget + dispatch threshold/exceed callbacks (EC-8 isolated).\n *\n * - In `audit` mode: charge only, no callbacks.\n * - In `warn` mode: charge + onThreshold (80/95) + onExceed (100). No throw.\n * - In `block` mode: charge + onThreshold + onExceed. No throw post-call\n * (preflightCheck already prevented exceed for the upcoming call;\n * this protects against simultaneous-call races where multiple sends\n * each pass preflight independently — last one to charge may still\n * tip a limit. We document the case rather than retroactively throw).\n */\nexport async function chargeAndCheckThresholds(name: string, actualUsd: number): Promise<void> {\n const opts = getBudgetOptionsRaw(name);\n if (opts === undefined) {\n // EC-20: budget deleted during in-flight call. Charge is silent no-op.\n process.stderr.write(\n `[budget] charge for deleted budget \"${name}\" is a no-op (was the budget removed during in-flight send?)\\n`,\n );\n return;\n }\n const mode = defaultMode(opts);\n\n await charge(opts.name, actualUsd);\n\n if (mode === \"audit\") return;\n await dispatchCallbacksFor(opts, mode);\n}\n\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: 3-mode × 3-threshold dispatch table inherently branchy; pulling out helpers loses local context.\nasync function dispatchCallbacksFor(opts: BudgetOptions, mode: BudgetMode): Promise<void> {\n for (const lim of opts.limits) {\n const spent = spentIn(opts.name, lim.window);\n if (lim.limitUsd <= 0) {\n if (spent > 0) await dispatchExceed(opts, lim.window, spent, lim.limitUsd, mode);\n continue;\n }\n const ratio = spent / lim.limitUsd;\n if (ratio >= 1) {\n await dispatchExceed(opts, lim.window, spent, lim.limitUsd, mode);\n } else {\n // Iterate descending so the HIGHEST matched threshold fires (0.95 not 0.8)\n for (const t of [...THRESHOLDS].reverse() as Threshold[]) {\n if (ratio >= t) {\n await dispatchThreshold(opts, lim.window, spent, lim.limitUsd, t);\n break;\n }\n }\n }\n }\n}\n\nasync function dispatchThreshold(\n opts: BudgetOptions,\n window: BudgetOptions[\"limits\"][number][\"window\"],\n spentUsd: number,\n limitUsd: number,\n threshold: Threshold,\n): Promise<void> {\n if (opts.onThreshold === undefined) return;\n try {\n await opts.onThreshold({\n budgetName: opts.name,\n window,\n threshold,\n spentUsd,\n limitUsd,\n });\n } catch (err) {\n // EC-8: callback throw isolated\n const msg = err instanceof Error ? err.message : String(err);\n process.stderr.write(`[budget] onThreshold callback threw: ${msg}\\n`);\n }\n}\n\nasync function dispatchExceed(\n opts: BudgetOptions,\n window: BudgetOptions[\"limits\"][number][\"window\"],\n spentUsd: number,\n limitUsd: number,\n mode: BudgetMode,\n): Promise<void> {\n if (opts.onExceed === undefined) {\n if (mode === \"warn\") {\n process.stderr.write(\n `[budget] \"${opts.name}\" exceeded ${window} limit: $${spentUsd.toFixed(4)} > $${limitUsd.toFixed(4)}\\n`,\n );\n }\n return;\n }\n try {\n await opts.onExceed({\n budgetName: opts.name,\n window,\n spentUsd,\n limitUsd,\n mode,\n });\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n process.stderr.write(`[budget] onExceed callback threw: ${msg}\\n`);\n }\n}\n","/**\n * normalizeUsage — convert provider-shaped raw `usage` object to\n * canonical `TokenUsage`. Ports Hermes Agent's `normalize_usage`\n * (referencia/hermes-agent/agent/usage_pricing.py:672-742).\n *\n * Handles 3 API shapes:\n * - Anthropic Messages: 4 explicit buckets (input/output/cache_read/cache_creation).\n * - OpenAI Chat Completions: prompt_tokens INCLUDES cache; subtract cached_tokens.\n * - OpenAI Responses (Codex): input_tokens INCLUDES cache; same subtraction.\n *\n * Edge cases:\n * - cline#10266 — OpenAI-compat proxies (OpenRouter, Vercel AI Gateway,\n * Cline) routing Claude expose Anthropic-style top-level fields\n * (cache_read_input_tokens / cache_creation_input_tokens). Both\n * locations are checked with top-level fallback.\n * - Null/undefined fields → 0 via `int()` coerce.\n * - String token counts → parsed via int.\n * - Negative values → clamped to 0 (defensive against proxy bugs).\n *\n * @internal\n */\n\nimport type { TokenUsage } from \"@theokit/sdk\";\n\ntype ApiMode = \"anthropic_messages\" | \"openai_chat_completions\" | \"openai_responses\";\n\nfunction int(v: unknown): number {\n if (typeof v === \"number\") return Number.isFinite(v) ? Math.max(0, Math.trunc(v)) : 0;\n if (typeof v === \"string\") {\n const n = Number.parseInt(v, 10);\n return Number.isFinite(n) ? Math.max(0, n) : 0;\n }\n return 0;\n}\n\nfunction buildTotal(buckets: {\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n}): number {\n // total = visible input + cache buckets + output (reasoning counted via output)\n return (\n buckets.inputTokens + buckets.outputTokens + buckets.cacheReadTokens + buckets.cacheWriteTokens\n );\n}\n\nfunction omitUndefined(usage: {\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n reasoningTokens: number;\n totalTokens: number;\n}): TokenUsage {\n return {\n inputTokens: usage.inputTokens,\n outputTokens: usage.outputTokens,\n ...(usage.cacheReadTokens > 0 ? { cacheReadTokens: usage.cacheReadTokens } : {}),\n ...(usage.cacheWriteTokens > 0 ? { cacheWriteTokens: usage.cacheWriteTokens } : {}),\n ...(usage.reasoningTokens > 0 ? { reasoningTokens: usage.reasoningTokens } : {}),\n totalTokens: usage.totalTokens,\n };\n}\n\nexport function inferApiMode(provider: string): ApiMode {\n const p = provider.toLowerCase();\n if (p === \"anthropic\" || p === \"claude\" || p === \"bedrock_anthropic\") {\n return \"anthropic_messages\";\n }\n if (p === \"openai-codex\" || p === \"codex\") return \"openai_responses\";\n // openai, openrouter, deepseek, google (compat), ollama (compat), lmstudio (compat), etc\n return \"openai_chat_completions\";\n}\n\ninterface RawRecord {\n [k: string]: unknown;\n}\n\nexport function normalizeUsage(\n rawUsage: unknown,\n opts: { provider: string; apiMode?: ApiMode },\n): TokenUsage {\n if (rawUsage === null || rawUsage === undefined) {\n return { inputTokens: 0, outputTokens: 0, totalTokens: 0 };\n }\n if (typeof rawUsage !== \"object\") {\n return { inputTokens: 0, outputTokens: 0, totalTokens: 0 };\n }\n const raw = rawUsage as RawRecord;\n const mode = opts.apiMode ?? inferApiMode(opts.provider);\n\n if (mode === \"anthropic_messages\") return normalizeAnthropic(raw);\n if (mode === \"openai_responses\") return normalizeOpenAIResponses(raw);\n return normalizeOpenAIChat(raw);\n}\n\nfunction normalizeAnthropic(raw: RawRecord): TokenUsage {\n const inputTokens = int(raw.input_tokens);\n const outputTokens = int(raw.output_tokens);\n const cacheReadTokens = int(raw.cache_read_input_tokens);\n const cacheWriteTokens = int(raw.cache_creation_input_tokens);\n const usage = {\n inputTokens,\n outputTokens,\n cacheReadTokens,\n cacheWriteTokens,\n reasoningTokens: 0,\n totalTokens: buildTotal({ inputTokens, outputTokens, cacheReadTokens, cacheWriteTokens }),\n };\n return omitUndefined(usage);\n}\n\nfunction normalizeOpenAIResponses(raw: RawRecord): TokenUsage {\n const inputTotal = int(raw.input_tokens);\n const outputTokens = int(raw.output_tokens);\n const inputDetails = (raw.input_tokens_details as RawRecord | undefined) ?? {};\n const outputDetails = (raw.output_tokens_details as RawRecord | undefined) ?? {};\n const cacheReadTokens = int(inputDetails.cached_tokens);\n const cacheWriteTokens = int(inputDetails.cache_creation_tokens);\n const reasoningTokens = int(outputDetails.reasoning_tokens);\n const inputTokens = Math.max(0, inputTotal - cacheReadTokens - cacheWriteTokens);\n const usage = {\n inputTokens,\n outputTokens,\n cacheReadTokens,\n cacheWriteTokens,\n reasoningTokens,\n totalTokens: buildTotal({ inputTokens, outputTokens, cacheReadTokens, cacheWriteTokens }),\n };\n return omitUndefined(usage);\n}\n\nfunction normalizeOpenAIChat(raw: RawRecord): TokenUsage {\n const promptTotal = int(raw.prompt_tokens);\n const outputTokens = int(raw.completion_tokens);\n const promptDetails = (raw.prompt_tokens_details as RawRecord | undefined) ?? {};\n const completionDetails = (raw.completion_tokens_details as RawRecord | undefined) ?? {};\n\n // cline#10266 fallback — proxies expose Anthropic-style top-level fields when routing Claude\n const cacheReadTokens = int(promptDetails.cached_tokens) || int(raw.cache_read_input_tokens);\n const cacheWriteTokens =\n int(promptDetails.cache_write_tokens) || int(raw.cache_creation_input_tokens);\n\n const reasoningTokens = int(completionDetails.reasoning_tokens);\n const inputTokens = Math.max(0, promptTotal - cacheReadTokens - cacheWriteTokens);\n const usage = {\n inputTokens,\n outputTokens,\n cacheReadTokens,\n cacheWriteTokens,\n reasoningTokens,\n totalTokens: buildTotal({ inputTokens, outputTokens, cacheReadTokens, cacheWriteTokens }),\n };\n return omitUndefined(usage);\n}\n","/**\n * Built-in per-model USD pricing table (SDK 2.0 Phase 2 / sdk-budget T2.X).\n *\n * Prices are in USD per 1M tokens (input / output). Sources: each\n * provider's public pricing page; values verified 2026-06 against\n * the same tier used in sdk-core's `internal/budget/pricing-data.json`.\n *\n * The table is intentionally CONSERVATIVE — only the most-used models\n * land here. Consumers needing exhaustive coverage can supply an\n * override via `createUsdBudgetTracker({ pricing })`.\n *\n * @public\n */\n\nexport interface ModelPricing {\n /** USD per 1,000,000 input tokens. */\n readonly inputPerMillionUsd: number;\n /** USD per 1,000,000 output tokens. */\n readonly outputPerMillionUsd: number;\n}\n\n/** Built-in pricing table — exhaustive enough for v0.1; users supply overrides for niche models. */\nexport const BUILTIN_PRICING: Readonly<Record<string, ModelPricing>> = Object.freeze({\n // OpenAI / OpenRouter aliases\n \"openai/gpt-4o\": { inputPerMillionUsd: 2.5, outputPerMillionUsd: 10 },\n \"openai/gpt-4o-mini\": { inputPerMillionUsd: 0.15, outputPerMillionUsd: 0.6 },\n \"openai/gpt-4-turbo\": { inputPerMillionUsd: 10, outputPerMillionUsd: 30 },\n \"openai/gpt-3.5-turbo\": { inputPerMillionUsd: 0.5, outputPerMillionUsd: 1.5 },\n // Anthropic / Claude\n \"anthropic/claude-3-5-sonnet-latest\": { inputPerMillionUsd: 3, outputPerMillionUsd: 15 },\n \"anthropic/claude-3-5-haiku-latest\": { inputPerMillionUsd: 0.8, outputPerMillionUsd: 4 },\n \"anthropic/claude-3-opus-latest\": { inputPerMillionUsd: 15, outputPerMillionUsd: 75 },\n // Google\n \"google/gemini-1.5-pro\": { inputPerMillionUsd: 1.25, outputPerMillionUsd: 5 },\n \"google/gemini-1.5-flash\": { inputPerMillionUsd: 0.075, outputPerMillionUsd: 0.3 },\n});\n\n/**\n * Compute USD cost for a single token event.\n *\n * Returns `undefined` (NOT `0`, NOT throws) when the model is UNKNOWN — its\n * cost is genuinely unknown, and coercing it to `$0` would be dishonest (cost\n * contract `D377-cost-status-closed-enum.md`: amount-unknown ≠ `$0`). Consumers\n * who want a price for a niche model supply an override via\n * `createUsdBudgetTracker({ pricing })`. A KNOWN model with zero/invalid tokens\n * returns `0` — that is a real, known `$0`.\n */\nexport function computeUsdCost(\n pricing: Readonly<Record<string, ModelPricing>>,\n model: string,\n type: \"input\" | \"output\",\n tokens: number,\n): number | undefined {\n const entry = pricing[model];\n if (entry === undefined) return undefined;\n const ratePerMillion = type === \"input\" ? entry.inputPerMillionUsd : entry.outputPerMillionUsd;\n if (!Number.isFinite(tokens) || tokens <= 0) return 0;\n return (tokens / 1_000_000) * ratePerMillion;\n}\n","/**\n * `createUsdBudgetTracker` — USD-cost-aware `BudgetTracker` impl shipped\n * in `@theokit/sdk-budget` (SDK 2.0 Phase 2 / T2.X).\n *\n * Extends the counter pattern from `createCounterBudgetTracker`\n * (sdk-core reference impl) with per-model USD cost computation via\n * the `BUILTIN_PRICING` table.\n *\n * Use cases:\n * - Cap total spend per agent run (`maxUsd`).\n * - Cap total tokens (`maxTokens`) AND USD ceiling simultaneously.\n * - Observe cumulative USD from outside (`getTotalUsd()`).\n *\n * Tracker.check() returns `allowed: false` when ANY of the configured\n * caps is exceeded. `reason` is one of:\n * - `\"token_limit\"` — `maxTokens` reached\n * - `\"cost_limit\"` — `maxUsd` reached\n *\n * Layered design (mirrors counter impl):\n * - `track()` is sync + non-throwing (clamps invalid values).\n * - `check()` is sync (allowed: true unless a cap is exceeded).\n * - `getTotal()` returns the SDK-required token + iteration totals\n * ONLY (USD is exposed via the bonus `getTotalUsd()` method).\n *\n * @public\n */\n\nimport type { BudgetCheck, BudgetTotal, BudgetTracker, BudgetUsageEvent } from \"@theokit/sdk\";\nimport { BUILTIN_PRICING, computeUsdCost, type ModelPricing } from \"./usd-pricing.js\";\n\n/** Options for `createUsdBudgetTracker`. */\nexport interface UsdBudgetTrackerOptions {\n /** Hard ceiling on total tokens (input + output combined). */\n readonly maxTokens?: number;\n /** Hard ceiling on cumulative USD spend. */\n readonly maxUsd?: number;\n /** Optional override map — model id → pricing entry. Merged onto BUILTIN_PRICING. */\n readonly pricing?: Readonly<Record<string, ModelPricing>>;\n}\n\n/** The cost-cap denial for the current state, or `null` if the cost cap is satisfied. */\nfunction evaluateCostCap(\n maxUsd: number | undefined,\n costKnown: boolean,\n totalUsd: number,\n): BudgetCheck | null {\n if (maxUsd === undefined) return null;\n if (!costKnown) {\n // Fail closed: a spend cap is set but cost is unknown — we cannot prove the\n // run is under budget, so deny rather than allow unbounded spend.\n return {\n allowed: false,\n reason: \"cost_limit\",\n detail: `cost unknown — cannot verify maxUsd ${maxUsd}`,\n };\n }\n if (totalUsd >= maxUsd) {\n return {\n allowed: false,\n reason: \"cost_limit\",\n detail: `USD ${totalUsd.toFixed(6)} >= maxUsd ${maxUsd}`,\n };\n }\n return null;\n}\n\n/** The token-cap denial for the current state, or `null` if the token cap is satisfied. */\nfunction evaluateTokenCap(maxTokens: number | undefined, totalTokens: number): BudgetCheck | null {\n if (maxTokens !== undefined && totalTokens >= maxTokens) {\n return {\n allowed: false,\n reason: \"token_limit\",\n detail: `${totalTokens} >= maxTokens ${maxTokens}`,\n };\n }\n return null;\n}\n\n/**\n * Build a fresh USD-aware tracker. The returned object exposes the\n * `BudgetTracker` contract PLUS `getTotalUsd()` + `nextIteration()`\n * helpers for explicit iteration counting.\n */\nexport function createUsdBudgetTracker(\n options: UsdBudgetTrackerOptions = {},\n): BudgetTracker & { nextIteration(): void; getTotalUsd(): number | undefined } {\n let totalTokens = 0;\n let iterations = 0;\n let totalUsd = 0;\n // Honest-null (D377): once any round's cost is UNKNOWN, the aggregate becomes\n // unknown and STAYS unknown — a later known round does not resurrect it.\n let costKnown = true;\n const maxTokens = options.maxTokens;\n const maxUsd = options.maxUsd;\n const pricing: Readonly<Record<string, ModelPricing>> =\n options.pricing !== undefined ? { ...BUILTIN_PRICING, ...options.pricing } : BUILTIN_PRICING;\n\n return {\n track(event: BudgetUsageEvent): void {\n // Sync + non-throwing per contract. Invalid events silently clamped.\n const t = Number.isFinite(event.tokens) && event.tokens > 0 ? event.tokens : 0;\n if (t === 0) return;\n totalTokens += t;\n const cost = computeUsdCost(pricing, event.model, event.type, t);\n if (cost === undefined) {\n costKnown = false; // poison — do NOT add 0 (that would be a dishonest $0)\n return;\n }\n if (costKnown) totalUsd += cost;\n },\n\n check(): BudgetCheck {\n // Cost cap is evaluated first (USD is the higher-signal denial for a human).\n return (\n evaluateCostCap(maxUsd, costKnown, totalUsd) ??\n evaluateTokenCap(maxTokens, totalTokens) ?? { allowed: true }\n );\n },\n\n getTotal(): BudgetTotal {\n return { tokens: totalTokens, iterations };\n },\n\n getTotalUsd(): number | undefined {\n return costKnown ? totalUsd : undefined;\n },\n\n nextIteration(): void {\n iterations += 1;\n },\n };\n}\n"]}
1
+ {"version":3,"sources":["../src/format-cost.ts","../src/internal/calendar-window.ts","../src/internal/ledger.ts","../src/internal/registry.ts","../src/internal/enforcement.ts","../src/internal/normalize-usage.ts","../src/usd-pricing.ts","../src/usd-budget-tracker.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["/**\n * M7-6 — honest-null cost render helper. Turns the `number | undefined` cost\n * (from `computeUsdCost` / `getTotalUsd`, M1-6) into a display string: an\n * unknown cost renders as `\"—\"` (NEVER a dishonest `\"$0\"`), a real number\n * renders as `\"$X.XX\"`. Composes the cost-honesty contract — a known-zero cost\n * (`0`) is distinct from an unknown one (`undefined`).\n *\n * @public\n */\n\n/** Options for {@link formatCostUsd}. */\nexport interface FormatCostUsdOptions {\n /** Marker for an unknown cost (`undefined`). Default `\"—\"`. */\n readonly unknown?: string;\n /** Currency prefix for a known cost. Default `\"$\"`. */\n readonly currency?: string;\n}\n\n/**\n * Render a USD cost for display. `undefined` -> the unknown marker (`\"—\"` by\n * default); a number -> `\"$X.XX\"` (2 decimal places). `0` is a real known-zero\n * and renders `\"$0.00\"`, NOT the unknown marker.\n */\nexport function formatCostUsd(cost: number | undefined, opts: FormatCostUsdOptions = {}): string {\n if (cost === undefined) return opts.unknown ?? \"—\";\n return `${opts.currency ?? \"$\"}${cost.toFixed(2)}`;\n}\n","/**\n * UTC-aligned calendar window helpers (ADR D382).\n *\n * - `1h` — relative (now - 1 hour).\n * - `1d` — UTC midnight (current UTC day).\n * - `1w` — UTC monday 00:00:00 (current UTC week, Monday is week start).\n * - `30d` — relative 30 days.\n * - `365d` — relative 365 days.\n *\n * `1d` and `1w` are calendar-aligned because users expect \"1 USD per day\"\n * = \"since midnight UTC\", not a rolling 24h.\n * `30d`/`365d` are relative because nobody expects \"since the 1st\".\n *\n * @internal\n */\n\nimport type { BudgetWindow } from \"@theokit/sdk\";\n\nexport function startOfDayUtc(now: Date = new Date()): Date {\n return new Date(Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate()));\n}\n\nexport function startOfWeekUtc(now: Date = new Date()): Date {\n // ISO 8601 week starts on Monday. getUTCDay() returns 0 (Sun) .. 6 (Sat).\n const dayOfWeek = now.getUTCDay();\n const daysSinceMonday = (dayOfWeek + 6) % 7; // Mon=0, Sun=6\n const start = startOfDayUtc(now);\n start.setUTCDate(start.getUTCDate() - daysSinceMonday);\n return start;\n}\n\nconst MS_PER_HOUR = 60 * 60 * 1000;\nconst MS_PER_DAY = 24 * MS_PER_HOUR;\n\n/** Returns the inclusive start timestamp (ms) for the given window relative to `now`. */\nexport function windowStartMs(window: BudgetWindow, now: Date = new Date()): number {\n switch (window) {\n case \"1h\":\n return now.getTime() - MS_PER_HOUR;\n case \"1d\":\n return startOfDayUtc(now).getTime();\n case \"1w\":\n return startOfWeekUtc(now).getTime();\n case \"30d\":\n return now.getTime() - 30 * MS_PER_DAY;\n case \"365d\":\n return now.getTime() - 365 * MS_PER_DAY;\n default: {\n const _exhaustive: never = window;\n throw new Error(`unreachable window: ${_exhaustive as string}`);\n }\n }\n}\n","/**\n * In-process Budget ledger (ADR D385).\n *\n * Singleton mutex-protected. Stores per-budget ChargeLog[] arrays;\n * `spentIn(window)` filters by timestamp.\n *\n * EC-6: GC eviction runs INSIDE the same mutex as charge — no race.\n * EC-9: charge() is called inside the same critical section as preflight\n * check by Budget enforcement.\n *\n * Persistence cross-restart: deferred to v0.2 (JsonFile pattern).\n *\n * @internal\n */\n\nimport { type BudgetWindow, withCwdMutex } from \"@theokit/sdk\";\nimport { windowStartMs } from \"./calendar-window.js\";\n\ninterface ChargeLog {\n timestamp: number;\n amountUsd: number;\n}\n\nconst MS_PER_YEAR = 365 * 24 * 60 * 60 * 1000;\nconst GC_INTERVAL_MS = 5 * 60 * 1000; // 5 minutes\nconst GC_LOGS_THRESHOLD = 10_000;\n\ninterface LedgerState {\n readonly logs: Map<string, ChargeLog[]>;\n lastGcAt: number;\n}\n\nconst state: LedgerState = {\n logs: new Map(),\n lastGcAt: Date.now(),\n};\n\nconst MUTEX_KEY = \"budget-ledger\";\n\nfunction shouldGc(now: number): boolean {\n if (now - state.lastGcAt < GC_INTERVAL_MS) return false;\n let totalLogs = 0;\n for (const arr of state.logs.values()) totalLogs += arr.length;\n return totalLogs > GC_LOGS_THRESHOLD;\n}\n\nfunction gcOlderThanOneYear(now: number): void {\n const cutoff = now - MS_PER_YEAR;\n for (const [name, arr] of state.logs.entries()) {\n const kept = arr.filter((l) => l.timestamp >= cutoff);\n if (kept.length === 0) state.logs.delete(name);\n else state.logs.set(name, kept);\n }\n state.lastGcAt = now;\n}\n\n/** Charge a budget. Idempotent across concurrent calls via withCwdMutex. */\nexport async function charge(name: string, amountUsd: number): Promise<void> {\n if (amountUsd <= 0) return;\n await withCwdMutex(MUTEX_KEY, async () => {\n const now = Date.now();\n const list = state.logs.get(name) ?? [];\n list.push({ timestamp: now, amountUsd });\n state.logs.set(name, list);\n if (shouldGc(now)) gcOlderThanOneYear(now);\n });\n}\n\n/** Return total spend in the given window for `name`. Snapshot read (no mutex needed). */\nexport function spentIn(name: string, window: BudgetWindow, now: Date = new Date()): number {\n const arr = state.logs.get(name);\n if (arr === undefined) return 0;\n const sinceMs = windowStartMs(window, now);\n let total = 0;\n for (const log of arr) {\n if (log.timestamp >= sinceMs) total += log.amountUsd;\n }\n return total;\n}\n","/**\n * Internal Budget registry — keeps live `BudgetOptions` per name.\n * Singleton; no persistence (D385).\n *\n * @internal\n */\n\nimport {\n type BudgetHandle,\n type BudgetMode,\n type BudgetOptions,\n type BudgetSnapshot,\n type BudgetWindow,\n ConfigurationError,\n} from \"@theokit/sdk\";\nimport { spentIn } from \"./ledger.js\";\n\nconst NAME_GRAMMAR = /^[a-z0-9][a-z0-9_-]*$/;\n\nconst registry = new Map<string, BudgetOptions>();\n\nfunction validateBudgetName(name: string): void {\n if (typeof name !== \"string\" || name.length === 0) {\n throw new ConfigurationError(\"Budget name must be a non-empty string\", {\n code: \"invalid_budget_name\",\n });\n }\n if (!NAME_GRAMMAR.test(name)) {\n throw new ConfigurationError(\n `Budget name \"${name}\" must match ^[a-z0-9][a-z0-9_-]*$ (lowercase + dash/underscore, start alphanumeric)`,\n { code: \"invalid_budget_name\" },\n );\n }\n}\n\nexport function createBudget(opts: BudgetOptions): BudgetHandle {\n // EC-7: name validation\n validateBudgetName(opts.name);\n if (registry.has(opts.name)) {\n // EC-16: duplicate throws (vs Task.submit idempotent return)\n throw new ConfigurationError(`Budget \"${opts.name}\" already exists`, {\n code: \"invalid_budget_name\",\n });\n }\n registry.set(opts.name, opts);\n return buildHandle(opts);\n}\n\nexport function getBudget(name: string): BudgetHandle | undefined {\n const opts = registry.get(name);\n if (opts === undefined) return undefined;\n return buildHandle(opts);\n}\n\nexport function listBudgets(): readonly BudgetHandle[] {\n return [...registry.values()].map(buildHandle);\n}\n\nexport function deleteBudget(name: string): boolean {\n return registry.delete(name);\n}\n\nexport function snapshotAll(): readonly BudgetSnapshot[] {\n const result: BudgetSnapshot[] = [];\n for (const opts of registry.values()) {\n for (const lim of opts.limits) {\n const spent = spentIn(opts.name, lim.window);\n result.push({\n name: opts.name,\n window: lim.window,\n spentUsd: spent,\n limitUsd: lim.limitUsd,\n ratio: lim.limitUsd > 0 ? spent / lim.limitUsd : 0,\n });\n }\n }\n return result;\n}\n\nexport function getBudgetOptionsRaw(name: string): BudgetOptions | undefined {\n return registry.get(name);\n}\n\nexport function defaultMode(opts: BudgetOptions): BudgetMode {\n return opts.mode ?? \"warn\";\n}\n\nfunction buildHandle(opts: BudgetOptions): BudgetHandle {\n return {\n name: opts.name,\n mode: defaultMode(opts),\n scope: opts.scope,\n limits: opts.limits,\n spentIn: (window: BudgetWindow) => spentIn(opts.name, window),\n remainingIn: (window: BudgetWindow) => {\n const lim = opts.limits.find((l) => l.window === window);\n if (lim === undefined) return Number.POSITIVE_INFINITY;\n return Math.max(0, lim.limitUsd - spentIn(opts.name, window));\n },\n };\n}\n","/**\n * Budget enforcement (ADRs D383, D386, EC-7/8/9).\n *\n * - `preflightCheck(name, estimatedUsd)` — em `block` mode, throw\n * `BudgetExceededError` before the LLM call if any limit would be\n * exceeded (EC-9 — the caller invokes it inside the mutex section).\n * - `chargeAndCheckThresholds(name, actualUsd)` — apply charge ao\n * ledger + invokes onThreshold/onExceed callbacks isolated in\n * try/catch (EC-8).\n *\n * @internal\n */\n\nimport { BudgetExceededError, type BudgetMode, type BudgetOptions } from \"@theokit/sdk\";\nimport { charge, spentIn } from \"./ledger.js\";\nimport { defaultMode, getBudgetOptionsRaw } from \"./registry.js\";\n\nconst THRESHOLDS = [0.8, 0.95] as const;\ntype Threshold = (typeof THRESHOLDS)[number];\n\n/**\n * Throws BudgetExceededError if `mode === \"block\"` and any limit\n * would be exceeded. No-op for audit/warn modes (post-charge checks\n * handle those).\n *\n * Caller invokes this BEFORE the LLM call.\n */\nexport function preflightCheck(name: string, estimatedUsd: number): void {\n const opts = getBudgetOptionsRaw(name);\n if (opts === undefined) return; // EC-20: budget deleted; charge becomes no-op\n if (defaultMode(opts) !== \"block\") return;\n for (const lim of opts.limits) {\n const currentSpent = spentIn(opts.name, lim.window);\n if (currentSpent + estimatedUsd > lim.limitUsd) {\n throw new BudgetExceededError({\n budgetName: opts.name,\n window: lim.window,\n spentUsd: currentSpent + estimatedUsd,\n limitUsd: lim.limitUsd,\n mode: \"block\",\n });\n }\n }\n}\n\n/**\n * Charge the budget + dispatch threshold/exceed callbacks (EC-8 isolated).\n *\n * - In `audit` mode: charge only, no callbacks.\n * - In `warn` mode: charge + onThreshold (80/95) + onExceed (100). No throw.\n * - In `block` mode: charge + onThreshold + onExceed. No throw post-call\n * (preflightCheck already prevented exceed for the upcoming call;\n * this protects against simultaneous-call races where multiple sends\n * each pass preflight independently — last one to charge may still\n * tip a limit. We document the case rather than retroactively throw).\n */\nexport async function chargeAndCheckThresholds(name: string, actualUsd: number): Promise<void> {\n const opts = getBudgetOptionsRaw(name);\n if (opts === undefined) {\n // EC-20: budget deleted during in-flight call. Charge is silent no-op.\n process.stderr.write(\n `[budget] charge for deleted budget \"${name}\" is a no-op (was the budget removed during in-flight send?)\\n`,\n );\n return;\n }\n const mode = defaultMode(opts);\n\n await charge(opts.name, actualUsd);\n\n if (mode === \"audit\") return;\n await dispatchCallbacksFor(opts, mode);\n}\n\n// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: 3-mode × 3-threshold dispatch table inherently branchy; pulling out helpers loses local context.\nasync function dispatchCallbacksFor(opts: BudgetOptions, mode: BudgetMode): Promise<void> {\n for (const lim of opts.limits) {\n const spent = spentIn(opts.name, lim.window);\n if (lim.limitUsd <= 0) {\n if (spent > 0) await dispatchExceed(opts, lim.window, spent, lim.limitUsd, mode);\n continue;\n }\n const ratio = spent / lim.limitUsd;\n if (ratio >= 1) {\n await dispatchExceed(opts, lim.window, spent, lim.limitUsd, mode);\n } else {\n // Iterate descending so the HIGHEST matched threshold fires (0.95 not 0.8)\n for (const t of [...THRESHOLDS].reverse() as Threshold[]) {\n if (ratio >= t) {\n await dispatchThreshold(opts, lim.window, spent, lim.limitUsd, t);\n break;\n }\n }\n }\n }\n}\n\nasync function dispatchThreshold(\n opts: BudgetOptions,\n window: BudgetOptions[\"limits\"][number][\"window\"],\n spentUsd: number,\n limitUsd: number,\n threshold: Threshold,\n): Promise<void> {\n if (opts.onThreshold === undefined) return;\n try {\n await opts.onThreshold({\n budgetName: opts.name,\n window,\n threshold,\n spentUsd,\n limitUsd,\n });\n } catch (err) {\n // EC-8: callback throw isolated\n const msg = err instanceof Error ? err.message : String(err);\n process.stderr.write(`[budget] onThreshold callback threw: ${msg}\\n`);\n }\n}\n\nasync function dispatchExceed(\n opts: BudgetOptions,\n window: BudgetOptions[\"limits\"][number][\"window\"],\n spentUsd: number,\n limitUsd: number,\n mode: BudgetMode,\n): Promise<void> {\n if (opts.onExceed === undefined) {\n if (mode === \"warn\") {\n process.stderr.write(\n `[budget] \"${opts.name}\" exceeded ${window} limit: $${spentUsd.toFixed(4)} > $${limitUsd.toFixed(4)}\\n`,\n );\n }\n return;\n }\n try {\n await opts.onExceed({\n budgetName: opts.name,\n window,\n spentUsd,\n limitUsd,\n mode,\n });\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n process.stderr.write(`[budget] onExceed callback threw: ${msg}\\n`);\n }\n}\n","/**\n * normalizeUsage — convert provider-shaped raw `usage` object to\n * canonical `TokenUsage`. Ports Hermes Agent's `normalize_usage`\n * (reference/peer-agent/agent/usage_pricing.py:672-742).\n *\n * Handles 3 API shapes:\n * - Anthropic Messages: 4 explicit buckets (input/output/cache_read/cache_creation).\n * - OpenAI Chat Completions: prompt_tokens INCLUDES cache; subtract cached_tokens.\n * - OpenAI Responses (Codex): input_tokens INCLUDES cache; same subtraction.\n *\n * Edge cases:\n * - a peer#10266 — OpenAI-compat proxies (OpenRouter, a peer vendor AI Gateway,\n * a peer) routing Claude expose Anthropic-style top-level fields\n * (cache_read_input_tokens / cache_creation_input_tokens). Both\n * locations are checked with top-level fallback.\n * - Null/undefined fields → 0 via `int()` coerce.\n * - String token counts → parsed via int.\n * - Negative values → clamped to 0 (defensive against proxy bugs).\n *\n * @internal\n */\n\nimport type { TokenUsage } from \"@theokit/sdk\";\n\ntype ApiMode = \"anthropic_messages\" | \"openai_chat_completions\" | \"openai_responses\";\n\nfunction int(v: unknown): number {\n if (typeof v === \"number\") return Number.isFinite(v) ? Math.max(0, Math.trunc(v)) : 0;\n if (typeof v === \"string\") {\n const n = Number.parseInt(v, 10);\n return Number.isFinite(n) ? Math.max(0, n) : 0;\n }\n return 0;\n}\n\nfunction buildTotal(buckets: {\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n}): number {\n // total = visible input + cache buckets + output (reasoning counted via output)\n return (\n buckets.inputTokens + buckets.outputTokens + buckets.cacheReadTokens + buckets.cacheWriteTokens\n );\n}\n\nfunction omitUndefined(usage: {\n inputTokens: number;\n outputTokens: number;\n cacheReadTokens: number;\n cacheWriteTokens: number;\n reasoningTokens: number;\n totalTokens: number;\n}): TokenUsage {\n return {\n inputTokens: usage.inputTokens,\n outputTokens: usage.outputTokens,\n ...(usage.cacheReadTokens > 0 ? { cacheReadTokens: usage.cacheReadTokens } : {}),\n ...(usage.cacheWriteTokens > 0 ? { cacheWriteTokens: usage.cacheWriteTokens } : {}),\n ...(usage.reasoningTokens > 0 ? { reasoningTokens: usage.reasoningTokens } : {}),\n totalTokens: usage.totalTokens,\n };\n}\n\nexport function inferApiMode(provider: string): ApiMode {\n const p = provider.toLowerCase();\n if (p === \"anthropic\" || p === \"claude\" || p === \"bedrock_anthropic\") {\n return \"anthropic_messages\";\n }\n if (p === \"openai-codex\" || p === \"codex\") return \"openai_responses\";\n // openai, openrouter, deepseek, google (compat), ollama (compat), lmstudio (compat), etc\n return \"openai_chat_completions\";\n}\n\ninterface RawRecord {\n [k: string]: unknown;\n}\n\nexport function normalizeUsage(\n rawUsage: unknown,\n opts: { provider: string; apiMode?: ApiMode },\n): TokenUsage {\n if (rawUsage === null || rawUsage === undefined) {\n return { inputTokens: 0, outputTokens: 0, totalTokens: 0 };\n }\n if (typeof rawUsage !== \"object\") {\n return { inputTokens: 0, outputTokens: 0, totalTokens: 0 };\n }\n const raw = rawUsage as RawRecord;\n const mode = opts.apiMode ?? inferApiMode(opts.provider);\n\n if (mode === \"anthropic_messages\") return normalizeAnthropic(raw);\n if (mode === \"openai_responses\") return normalizeOpenAIResponses(raw);\n return normalizeOpenAIChat(raw);\n}\n\nfunction normalizeAnthropic(raw: RawRecord): TokenUsage {\n const inputTokens = int(raw.input_tokens);\n const outputTokens = int(raw.output_tokens);\n const cacheReadTokens = int(raw.cache_read_input_tokens);\n const cacheWriteTokens = int(raw.cache_creation_input_tokens);\n const usage = {\n inputTokens,\n outputTokens,\n cacheReadTokens,\n cacheWriteTokens,\n reasoningTokens: 0,\n totalTokens: buildTotal({ inputTokens, outputTokens, cacheReadTokens, cacheWriteTokens }),\n };\n return omitUndefined(usage);\n}\n\nfunction normalizeOpenAIResponses(raw: RawRecord): TokenUsage {\n const inputTotal = int(raw.input_tokens);\n const outputTokens = int(raw.output_tokens);\n const inputDetails = (raw.input_tokens_details as RawRecord | undefined) ?? {};\n const outputDetails = (raw.output_tokens_details as RawRecord | undefined) ?? {};\n const cacheReadTokens = int(inputDetails.cached_tokens);\n const cacheWriteTokens = int(inputDetails.cache_creation_tokens);\n const reasoningTokens = int(outputDetails.reasoning_tokens);\n const inputTokens = Math.max(0, inputTotal - cacheReadTokens - cacheWriteTokens);\n const usage = {\n inputTokens,\n outputTokens,\n cacheReadTokens,\n cacheWriteTokens,\n reasoningTokens,\n totalTokens: buildTotal({ inputTokens, outputTokens, cacheReadTokens, cacheWriteTokens }),\n };\n return omitUndefined(usage);\n}\n\nfunction normalizeOpenAIChat(raw: RawRecord): TokenUsage {\n const promptTotal = int(raw.prompt_tokens);\n const outputTokens = int(raw.completion_tokens);\n const promptDetails = (raw.prompt_tokens_details as RawRecord | undefined) ?? {};\n const completionDetails = (raw.completion_tokens_details as RawRecord | undefined) ?? {};\n\n // a peer#10266 fallback — proxies expose Anthropic-style top-level fields when routing Claude\n const cacheReadTokens = int(promptDetails.cached_tokens) || int(raw.cache_read_input_tokens);\n const cacheWriteTokens =\n int(promptDetails.cache_write_tokens) || int(raw.cache_creation_input_tokens);\n\n const reasoningTokens = int(completionDetails.reasoning_tokens);\n const inputTokens = Math.max(0, promptTotal - cacheReadTokens - cacheWriteTokens);\n const usage = {\n inputTokens,\n outputTokens,\n cacheReadTokens,\n cacheWriteTokens,\n reasoningTokens,\n totalTokens: buildTotal({ inputTokens, outputTokens, cacheReadTokens, cacheWriteTokens }),\n };\n return omitUndefined(usage);\n}\n","/**\n * Built-in per-model USD pricing table (SDK 2.0 Phase 2 / sdk-budget T2.X).\n *\n * Prices are in USD per 1M tokens (input / output). Sources: each\n * provider's public pricing page; values verified 2026-06 against\n * the same tier used in sdk-core's `internal/budget/pricing-data.json`.\n *\n * The table is intentionally CONSERVATIVE — only the most-used models\n * land here. Consumers needing exhaustive coverage can supply an\n * override via `createUsdBudgetTracker({ pricing })`.\n *\n * @public\n */\n\nexport interface ModelPricing {\n /** USD per 1,000,000 input tokens. */\n readonly inputPerMillionUsd: number;\n /** USD per 1,000,000 output tokens. */\n readonly outputPerMillionUsd: number;\n}\n\n/** Built-in pricing table — exhaustive enough for v0.1; users supply overrides for niche models. */\nexport const BUILTIN_PRICING: Readonly<Record<string, ModelPricing>> = Object.freeze({\n // OpenAI / OpenRouter aliases\n \"openai/gpt-4o\": { inputPerMillionUsd: 2.5, outputPerMillionUsd: 10 },\n \"openai/gpt-4o-mini\": { inputPerMillionUsd: 0.15, outputPerMillionUsd: 0.6 },\n \"openai/gpt-4-turbo\": { inputPerMillionUsd: 10, outputPerMillionUsd: 30 },\n \"openai/gpt-3.5-turbo\": { inputPerMillionUsd: 0.5, outputPerMillionUsd: 1.5 },\n // Anthropic / Claude\n \"anthropic/claude-3-5-sonnet-latest\": { inputPerMillionUsd: 3, outputPerMillionUsd: 15 },\n \"anthropic/claude-3-5-haiku-latest\": { inputPerMillionUsd: 0.8, outputPerMillionUsd: 4 },\n \"anthropic/claude-3-opus-latest\": { inputPerMillionUsd: 15, outputPerMillionUsd: 75 },\n // Google\n \"google/gemini-1.5-pro\": { inputPerMillionUsd: 1.25, outputPerMillionUsd: 5 },\n \"google/gemini-1.5-flash\": { inputPerMillionUsd: 0.075, outputPerMillionUsd: 0.3 },\n});\n\n/**\n * Compute USD cost for a single token event.\n *\n * Returns `undefined` (NOT `0`, NOT throws) when the model is UNKNOWN — its\n * cost is genuinely unknown, and coercing it to `$0` would be dishonest (cost\n * contract `D377-cost-status-closed-enum.md`: amount-unknown ≠ `$0`). Consumers\n * who want a price for a niche model supply an override via\n * `createUsdBudgetTracker({ pricing })`. A KNOWN model with zero/invalid tokens\n * returns `0` — that is a real, known `$0`.\n */\nexport function computeUsdCost(\n pricing: Readonly<Record<string, ModelPricing>>,\n model: string,\n type: \"input\" | \"output\",\n tokens: number,\n): number | undefined {\n const entry = pricing[model];\n if (entry === undefined) return undefined;\n const ratePerMillion = type === \"input\" ? entry.inputPerMillionUsd : entry.outputPerMillionUsd;\n if (!Number.isFinite(tokens) || tokens <= 0) return 0;\n return (tokens / 1_000_000) * ratePerMillion;\n}\n","/**\n * `createUsdBudgetTracker` — USD-cost-aware `BudgetTracker` impl shipped\n * in `@theokit/sdk-budget` (SDK 2.0 Phase 2 / T2.X).\n *\n * Extends the counter pattern from `createCounterBudgetTracker`\n * (sdk-core reference impl) with per-model USD cost computation via\n * the `BUILTIN_PRICING` table.\n *\n * Use cases:\n * - Cap total spend per agent run (`maxUsd`).\n * - Cap total tokens (`maxTokens`) AND USD ceiling simultaneously.\n * - Observe cumulative USD from outside (`getTotalUsd()`).\n *\n * Tracker.check() returns `allowed: false` when ANY of the configured\n * caps is exceeded. `reason` is one of:\n * - `\"token_limit\"` — `maxTokens` reached\n * - `\"cost_limit\"` — `maxUsd` reached\n *\n * Layered design (mirrors counter impl):\n * - `track()` is sync + non-throwing (clamps invalid values).\n * - `check()` is sync (allowed: true unless a cap is exceeded).\n * - `getTotal()` returns the SDK-required token + iteration totals\n * ONLY (USD is exposed via the bonus `getTotalUsd()` method).\n *\n * @public\n */\n\nimport type { BudgetCheck, BudgetTotal, BudgetTracker, BudgetUsageEvent } from \"@theokit/sdk\";\nimport { BUILTIN_PRICING, computeUsdCost, type ModelPricing } from \"./usd-pricing.js\";\n\n/** Options for `createUsdBudgetTracker`. */\nexport interface UsdBudgetTrackerOptions {\n /** Hard ceiling on total tokens (input + output combined). */\n readonly maxTokens?: number;\n /** Hard ceiling on cumulative USD spend. */\n readonly maxUsd?: number;\n /** Optional override map — model id → pricing entry. Merged onto BUILTIN_PRICING. */\n readonly pricing?: Readonly<Record<string, ModelPricing>>;\n}\n\n/** The cost-cap denial for the current state, or `null` if the cost cap is satisfied. */\nfunction evaluateCostCap(\n maxUsd: number | undefined,\n costKnown: boolean,\n totalUsd: number,\n): BudgetCheck | null {\n if (maxUsd === undefined) return null;\n if (!costKnown) {\n // Fail closed: a spend cap is set but cost is unknown — we cannot prove the\n // run is under budget, so deny rather than allow unbounded spend.\n return {\n allowed: false,\n reason: \"cost_limit\",\n detail: `cost unknown — cannot verify maxUsd ${maxUsd}`,\n };\n }\n if (totalUsd >= maxUsd) {\n return {\n allowed: false,\n reason: \"cost_limit\",\n detail: `USD ${totalUsd.toFixed(6)} >= maxUsd ${maxUsd}`,\n };\n }\n return null;\n}\n\n/** The token-cap denial for the current state, or `null` if the token cap is satisfied. */\nfunction evaluateTokenCap(maxTokens: number | undefined, totalTokens: number): BudgetCheck | null {\n if (maxTokens !== undefined && totalTokens >= maxTokens) {\n return {\n allowed: false,\n reason: \"token_limit\",\n detail: `${totalTokens} >= maxTokens ${maxTokens}`,\n };\n }\n return null;\n}\n\n/**\n * Build a fresh USD-aware tracker. The returned object exposes the\n * `BudgetTracker` contract PLUS `getTotalUsd()` + `nextIteration()`\n * helpers for explicit iteration counting.\n */\nexport function createUsdBudgetTracker(\n options: UsdBudgetTrackerOptions = {},\n): BudgetTracker & { nextIteration(): void; getTotalUsd(): number | undefined } {\n let totalTokens = 0;\n let iterations = 0;\n let totalUsd = 0;\n // Honest-null (D377): once any round's cost is UNKNOWN, the aggregate becomes\n // unknown and STAYS unknown — a later known round does not resurrect it.\n let costKnown = true;\n const maxTokens = options.maxTokens;\n const maxUsd = options.maxUsd;\n const pricing: Readonly<Record<string, ModelPricing>> =\n options.pricing !== undefined ? { ...BUILTIN_PRICING, ...options.pricing } : BUILTIN_PRICING;\n\n return {\n track(event: BudgetUsageEvent): void {\n // Sync + non-throwing per contract. Invalid events silently clamped.\n const t = Number.isFinite(event.tokens) && event.tokens > 0 ? event.tokens : 0;\n if (t === 0) return;\n totalTokens += t;\n const cost = computeUsdCost(pricing, event.model, event.type, t);\n if (cost === undefined) {\n costKnown = false; // poison — do NOT add 0 (that would be a dishonest $0)\n return;\n }\n if (costKnown) totalUsd += cost;\n },\n\n check(): BudgetCheck {\n // Cost cap is evaluated first (USD is the higher-signal denial for a human).\n return (\n evaluateCostCap(maxUsd, costKnown, totalUsd) ??\n evaluateTokenCap(maxTokens, totalTokens) ?? { allowed: true }\n );\n },\n\n getTotal(): BudgetTotal {\n return { tokens: totalTokens, iterations };\n },\n\n getTotalUsd(): number | undefined {\n return costKnown ? totalUsd : undefined;\n },\n\n nextIteration(): void {\n iterations += 1;\n },\n };\n}\n"]}
package/package.json CHANGED
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "name": "@theokit/sdk-budget",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "description": "USD-cost-aware BudgetTracker impls for @theokit/sdk — extends the counter-based reference with per-model pricing. Consumes the kernel-facing BudgetTracker port from sdk-core.",
5
5
  "license": "Apache-2.0",
6
- "homepage": "https://github.com/usetheo/theokit-sdk#readme",
7
- "bugs": "https://github.com/usetheo/theokit-sdk/issues",
6
+ "homepage": "https://github.com/usetheodev/theokit-sdk#readme",
7
+ "bugs": "https://github.com/usetheodev/theokit-sdk/issues",
8
8
  "repository": {
9
9
  "type": "git",
10
- "url": "git+https://github.com/usetheo/theokit-sdk.git",
10
+ "url": "git+https://github.com/usetheodev/theokit-sdk.git",
11
11
  "directory": "packages/sdk-budget"
12
12
  },
13
13
  "type": "module",
@@ -44,7 +44,7 @@
44
44
  "tsup": "^8.3.5",
45
45
  "typescript": "^5.7.2",
46
46
  "vitest": "^4.1.8",
47
- "@theokit/sdk": "4.2.0"
47
+ "@theokit/sdk": "4.43.0"
48
48
  },
49
49
  "publishConfig": {
50
50
  "access": "public"