UNPKG

@sema-agent/core

Version:

Stateless, task-oriented AI agent core

62 lines (61 loc) • 3.09 kB
import { readDegradation } from "../../brain/degrading.js"; import { isModelPriced, modelCostToPricing } from "../pricing.js"; import { emitTrace } from "../trace.js"; import { cacheFamilyOf, usageCostMicroUsd } from "./usage-accounting.js"; export const SIDE_CALL_LANE_TOTAL = { compaction: "compactionMicroUsd", classifier: "sideCallMicroUsd", mod: "sideCallMicroUsd", }; function catalogModel(id, catalog) { if (catalog === undefined) return undefined; for (const m of Object.values(catalog)) if (m.id === id) return m; return Object.hasOwn(catalog, id) ? catalog[id] : undefined; } export function recordSideCallUsage(stats, usage, lane, call) { if (usage === undefined || call.usageMissing === true) stats.usageMissing = true; if (usage === undefined) return; const { model: requested, account } = call; const pricing = account.pricing(); const served = call.servedBy === undefined ? requested : catalogModel(call.servedBy, account.catalog); const modelId = served?.id ?? call.servedBy ?? requested.id; const price = pricing?.[modelId] ?? modelCostToPricing(served?.cost); const priced = served !== undefined ? isModelPriced(served, pricing) : pricing?.[modelId] !== undefined; if (!priced) account.telemetry.unpricedSpend = true; account.noteUnevaluablePriceTable(price); const family = served !== undefined ? cacheFamilyOf(served) : "input-excludes-cached"; const { totalInputTokens, uncachedInputTokens, costMicroUsd } = usageCostMicroUsd(family, usage, price); stats.tokens += usage.totalTokens || 0; stats.promptTokens += uncachedInputTokens; stats.totalInputTokens += totalInputTokens; stats.cachedTokens += usage.cacheRead || 0; stats.cacheWriteTokens += usage.cacheWrite || 0; stats.outputTokens += usage.output || 0; stats.costMicroUsd += costMicroUsd; const total = SIDE_CALL_LANE_TOTAL[lane]; stats[total] = (stats[total] ?? 0) + costMicroUsd; emitTrace(account.telemetry.tracer, () => ({ kind: "brain.call", version: 1, taskId: account.telemetry.taskId, model: modelId, ...(served !== undefined ? { provider: served.provider } : {}), promptTokens: uncachedInputTokens, totalInputTokens, completionTokens: usage.output || 0, cacheRead: usage.cacheRead || 0, cacheWrite: usage.cacheWrite || 0, latencyMs: 0, ...(priced ? { costMicroUsd } : {}), ...(call.stopReason !== undefined ? { stopReason: call.stopReason } : {}), ts: Date.now(), })); } export function sideCallBookOf(stats, account) { return (lane, model, reply) => { const degradedTo = readDegradation(reply)?.to; recordSideCallUsage(stats, reply?.usage, lane, { model, account, ...(reply?.usageMissing === true ? { usageMissing: true } : {}), ...(typeof reply?.stopReason === "string" ? { stopReason: reply.stopReason } : {}), ...(degradedTo !== undefined && degradedTo !== model.id ? { servedBy: degradedTo } : {}), }); }; }