@sema-agent/core
Version:
Stateless, task-oriented AI agent core
62 lines (61 loc) • 3.09 kB
JavaScript
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 } : {}),
});
};
}