{"version":3,"file":"usage.mjs","names":[],"sources":["../../../src/agent/converters/usage.ts"],"sourcesContent":["export interface AgentRunUsage {\n  provider?: string;\n  model?: string;\n  inputTokens?: number;\n  outputTokens?: number;\n  totalTokens?: number;\n  reasoningTokens?: number;\n  cachedInputTokens?: number;\n}\n\nexport interface AgentRunFinishedDetails {\n  finishReason?: string;\n  usage?: AgentRunUsage[];\n}\n\nexport const tokenCountKeys = [\n  \"inputTokens\",\n  \"outputTokens\",\n  \"totalTokens\",\n  \"reasoningTokens\",\n  \"cachedInputTokens\",\n] as const;\n\n/** Returns a token count only when it is a safe, non-negative integer. */\nexport function getTokenCount(value: unknown): number | undefined {\n  return typeof value === \"number\" && Number.isSafeInteger(value) && value >= 0\n    ? value\n    : undefined;\n}\n\n/** Adds usage entries to a run, grouping and summing matching identities. */\nexport function aggregateRunUsage(\n  details: AgentRunFinishedDetails,\n  entries: AgentRunUsage[],\n): void {\n  for (const entry of entries) {\n    const hasCount = tokenCountKeys.some((key) => entry[key] !== undefined);\n    if (!hasCount) continue;\n\n    details.usage ??= [];\n    const existing = details.usage.find(\n      (candidate) =>\n        candidate.provider === entry.provider &&\n        candidate.model === entry.model,\n    );\n\n    if (!existing) {\n      details.usage.push({ ...entry });\n      continue;\n    }\n\n    for (const key of tokenCountKeys) {\n      const value = entry[key];\n      if (value === undefined) continue;\n\n      const sum = (existing[key] ?? 0) + value;\n      if (Number.isSafeInteger(sum)) {\n        existing[key] = sum;\n      }\n    }\n  }\n}\n\n/** Copies standard AG-UI terminal usage into a run-level accumulator. */\nexport function collectStandardRunFinishedDetails(\n  event: Record<string, unknown>,\n  details: AgentRunFinishedDetails,\n  fallbackIdentity: { provider?: string; model?: string } = {},\n): void {\n  if (typeof event.finishReason === \"string\") {\n    details.finishReason = event.finishReason;\n  }\n\n  if (!Array.isArray(event.usage)) return;\n\n  aggregateRunUsage(\n    details,\n    event.usage.flatMap((entry) => {\n      if (!isRecord(entry)) return [];\n\n      const normalized: AgentRunUsage = {\n        provider:\n          getNonEmptyString(entry.provider) ?? fallbackIdentity.provider,\n        model: getNonEmptyString(entry.model) ?? fallbackIdentity.model,\n      };\n      for (const key of tokenCountKeys) {\n        normalized[key] = getTokenCount(entry[key]);\n      }\n      return [normalized];\n    }),\n  );\n}\n\n/** Narrows an unknown value to a string-keyed object. */\nexport function isRecord(value: unknown): value is Record<string, unknown> {\n  return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\n/** Returns a non-empty string identity without changing its value. */\nexport function getNonEmptyString(value: unknown): string | undefined {\n  return typeof value === \"string\" && value.length > 0 ? value : undefined;\n}\n"],"mappings":";;AAeA,MAAa,iBAAiB;CAC5B;CACA;CACA;CACA;CACA;CACD;;AAGD,SAAgB,cAAc,OAAoC;AAChE,QAAO,OAAO,UAAU,YAAY,OAAO,cAAc,MAAM,IAAI,SAAS,IACxE,QACA;;;AAIN,SAAgB,kBACd,SACA,SACM;AACN,MAAK,MAAM,SAAS,SAAS;AAE3B,MAAI,CADa,eAAe,MAAM,QAAQ,MAAM,SAAS,OAAU,CACxD;AAEf,UAAQ,UAAU,EAAE;EACpB,MAAM,WAAW,QAAQ,MAAM,MAC5B,cACC,UAAU,aAAa,MAAM,YAC7B,UAAU,UAAU,MAAM,MAC7B;AAED,MAAI,CAAC,UAAU;AACb,WAAQ,MAAM,KAAK,EAAE,GAAG,OAAO,CAAC;AAChC;;AAGF,OAAK,MAAM,OAAO,gBAAgB;GAChC,MAAM,QAAQ,MAAM;AACpB,OAAI,UAAU,OAAW;GAEzB,MAAM,OAAO,SAAS,QAAQ,KAAK;AACnC,OAAI,OAAO,cAAc,IAAI,CAC3B,UAAS,OAAO;;;;;AAOxB,SAAgB,kCACd,OACA,SACA,mBAA0D,EAAE,EACtD;AACN,KAAI,OAAO,MAAM,iBAAiB,SAChC,SAAQ,eAAe,MAAM;AAG/B,KAAI,CAAC,MAAM,QAAQ,MAAM,MAAM,CAAE;AAEjC,mBACE,SACA,MAAM,MAAM,SAAS,UAAU;AAC7B,MAAI,CAAC,SAAS,MAAM,CAAE,QAAO,EAAE;EAE/B,MAAM,aAA4B;GAChC,UACE,kBAAkB,MAAM,SAAS,IAAI,iBAAiB;GACxD,OAAO,kBAAkB,MAAM,MAAM,IAAI,iBAAiB;GAC3D;AACD,OAAK,MAAM,OAAO,eAChB,YAAW,OAAO,cAAc,MAAM,KAAK;AAE7C,SAAO,CAAC,WAAW;GACnB,CACH;;;AAIH,SAAgB,SAAS,OAAkD;AACzE,QAAO,UAAU,QAAQ,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,MAAM;;;AAI7E,SAAgB,kBAAkB,OAAoC;AACpE,QAAO,OAAO,UAAU,YAAY,MAAM,SAAS,IAAI,QAAQ"}