@genesislcap/ai-assistant 15.9.1 → 15.10.0-GENC-1480.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.
@@ -31,21 +31,36 @@ __export(chat_driver_node_exports, {
31
31
  REQUEST_CONTINUATION_TOOL: () => REQUEST_CONTINUATION_TOOL,
32
32
  SUPPORTED_ANTHROPIC_MODEL_IDS: () => SUPPORTED_ANTHROPIC_MODEL_IDS,
33
33
  SUPPORTED_GEMINI_MODEL_IDS: () => SUPPORTED_GEMINI_MODEL_IDS,
34
+ addUsage: () => addUsage,
34
35
  agenticActivityBus: () => agenticActivityBus,
35
36
  assembleDebugLog: () => assembleDebugLog,
36
37
  buildTimelineEntries: () => buildTimelineEntries,
37
38
  clearSession: () => clearSession,
38
39
  defineAgent: () => defineAgent,
39
40
  defineStatefulAgent: () => defineStatefulAgent,
41
+ emptyUsage: () => emptyUsage,
40
42
  friendlyFallbackAgent: () => friendlyFallbackAgent,
41
43
  getMetaEvents: () => getMetaEvents,
42
44
  isObservableAIProviderRegistry: () => isObservableAIProviderRegistry,
43
45
  restoreMachine: () => restoreMachine,
44
- strictFallbackAgent: () => strictFallbackAgent
46
+ strictFallbackAgent: () => strictFallbackAgent,
47
+ sumUsage: () => sumUsage,
48
+ totalTokens: () => totalTokens
45
49
  });
46
50
  module.exports = __toCommonJS(chat_driver_node_exports);
47
51
 
48
52
  // ../../../../node_modules/tslib/tslib.es6.mjs
53
+ function __rest(s, e) {
54
+ var t = {};
55
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
56
+ t[p] = s[p];
57
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
58
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
59
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
60
+ t[p[i]] = s[p[i]];
61
+ }
62
+ return t;
63
+ }
49
64
  function __awaiter(thisArg, _arguments, P, generator) {
50
65
  function adopt(value) {
51
66
  return value instanceof P ? value : new P(function(resolve) {
@@ -1102,6 +1117,277 @@ function scaleTemperature(normalized, { defaultTemp, maxTemp }) {
1102
1117
  return t <= DEFAULT_ANCHOR ? t / DEFAULT_ANCHOR * defaultTemp : defaultTemp + (t - DEFAULT_ANCHOR) / (1 - DEFAULT_ANCHOR) * (maxTemp - defaultTemp);
1103
1118
  }
1104
1119
 
1120
+ // ../../foundation-ai/dist/esm/utils/token-cost.js
1121
+ var TOKENS_PER_MILLION = 1e6;
1122
+ function anthropicRatesFor(model) {
1123
+ if (model === "claude-haiku-4-5-20251001") {
1124
+ return { promptPerMillion: 1, candidatePerMillion: 5 };
1125
+ }
1126
+ if (model === "claude-fable-5") {
1127
+ return { promptPerMillion: 10, candidatePerMillion: 50 };
1128
+ }
1129
+ if (model === "claude-sonnet-5" || model === "claude-sonnet-4-6") {
1130
+ return { promptPerMillion: 3, candidatePerMillion: 15 };
1131
+ }
1132
+ return { promptPerMillion: 5, candidatePerMillion: 25 };
1133
+ }
1134
+ var ANTHROPIC_CACHE_READ_MULTIPLIER = 0.1;
1135
+ var ANTHROPIC_CACHE_WRITE_5M_MULTIPLIER = 1.25;
1136
+ var ANTHROPIC_CACHE_WRITE_1H_MULTIPLIER = 2;
1137
+ function anthropicTokenCost(model, usage) {
1138
+ const { promptPerMillion, candidatePerMillion } = anthropicRatesFor(model);
1139
+ const m = TOKENS_PER_MILLION;
1140
+ const cacheWrite5mTokens = Math.max(0, usage.cacheWriteTokens - usage.cacheWrite1hTokens);
1141
+ const promptCost = usage.uncachedInputTokens / m * promptPerMillion;
1142
+ const cacheReadCost = usage.cacheReadTokens / m * promptPerMillion * ANTHROPIC_CACHE_READ_MULTIPLIER;
1143
+ const cacheWriteCost = cacheWrite5mTokens / m * promptPerMillion * ANTHROPIC_CACHE_WRITE_5M_MULTIPLIER + usage.cacheWrite1hTokens / m * promptPerMillion * ANTHROPIC_CACHE_WRITE_1H_MULTIPLIER;
1144
+ const candidateCost = usage.outputTokens / m * candidatePerMillion;
1145
+ const cacheReadFull = usage.cacheReadTokens / m * promptPerMillion;
1146
+ const cacheWriteFull = usage.cacheWriteTokens / m * promptPerMillion;
1147
+ return {
1148
+ costUsd: promptCost + cacheReadCost + cacheWriteCost + candidateCost,
1149
+ savedUsd: cacheReadFull - cacheReadCost + (cacheWriteFull - cacheWriteCost),
1150
+ breakdown: {
1151
+ promptUsd: promptCost,
1152
+ cacheReadUsd: cacheReadCost,
1153
+ cacheWriteUsd: cacheWriteCost,
1154
+ candidateUsd: candidateCost
1155
+ }
1156
+ };
1157
+ }
1158
+ var GEMINI_LONG_CONTEXT_THRESHOLD = 2e5;
1159
+ var GEMINI_CACHED_INPUT_MULTIPLIER = 0.1;
1160
+ var GEMINI_PRICING = {
1161
+ "gemini-2.5-flash-lite": {
1162
+ kind: "flat",
1163
+ rate: { promptPerMillion: 0.1, candidatePerMillion: 0.4 }
1164
+ },
1165
+ "gemini-2.5-flash": { kind: "flat", rate: { promptPerMillion: 0.3, candidatePerMillion: 2.5 } },
1166
+ "gemini-2.5-pro": {
1167
+ kind: "tiered",
1168
+ standard: { promptPerMillion: 1.25, candidatePerMillion: 10 },
1169
+ longContext: { promptPerMillion: 2.5, candidatePerMillion: 15 }
1170
+ },
1171
+ "gemini-3.1-flash-lite": {
1172
+ kind: "flat",
1173
+ rate: { promptPerMillion: 0.25, candidatePerMillion: 1.5 }
1174
+ },
1175
+ "gemini-3.5-flash": { kind: "flat", rate: { promptPerMillion: 1.5, candidatePerMillion: 9 } },
1176
+ "gemini-3.1-pro-preview": {
1177
+ kind: "tiered",
1178
+ standard: { promptPerMillion: 2, candidatePerMillion: 12 },
1179
+ longContext: { promptPerMillion: 4, candidatePerMillion: 18 }
1180
+ }
1181
+ };
1182
+ function geminiRatesFor(model, promptTokens) {
1183
+ const pricing = GEMINI_PRICING[model];
1184
+ if (pricing.kind === "flat") {
1185
+ return pricing.rate;
1186
+ }
1187
+ return promptTokens > GEMINI_LONG_CONTEXT_THRESHOLD ? pricing.longContext : pricing.standard;
1188
+ }
1189
+ function geminiTokenCost(model, usage) {
1190
+ const { promptPerMillion, candidatePerMillion } = geminiRatesFor(model, usage.promptTokens);
1191
+ const m = TOKENS_PER_MILLION;
1192
+ const uncachedPromptTokens = Math.max(0, usage.promptTokens - usage.cachedTokens);
1193
+ const promptCost = uncachedPromptTokens / m * promptPerMillion;
1194
+ const cacheReadCost = usage.cachedTokens / m * promptPerMillion * GEMINI_CACHED_INPUT_MULTIPLIER;
1195
+ const candidateCost = (usage.candidateTokens + usage.thoughtTokens) / m * candidatePerMillion;
1196
+ return {
1197
+ costUsd: promptCost + cacheReadCost + candidateCost,
1198
+ // Implicit caching has no write premium, so this is always >= 0.
1199
+ savedUsd: usage.cachedTokens / m * promptPerMillion - cacheReadCost,
1200
+ breakdown: {
1201
+ promptUsd: promptCost,
1202
+ cacheReadUsd: cacheReadCost,
1203
+ cacheWriteUsd: 0,
1204
+ candidateUsd: candidateCost
1205
+ }
1206
+ };
1207
+ }
1208
+
1209
+ // ../../foundation-ai/dist/esm/utils/tool-schema.js
1210
+ var SCHEMA_MAP_KEYS = ["properties", "patternProperties", "$defs", "definitions"];
1211
+ var SCHEMA_LIST_KEYS = ["anyOf", "oneOf", "allOf", "prefixItems"];
1212
+ var SCHEMA_VALUE_KEYS = [
1213
+ "items",
1214
+ "not",
1215
+ "additionalProperties",
1216
+ "propertyNames",
1217
+ "contains"
1218
+ ];
1219
+ var isPlainObject2 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
1220
+ function cloneValue(value) {
1221
+ if (Array.isArray(value))
1222
+ return value.map(cloneValue);
1223
+ if (isPlainObject2(value)) {
1224
+ const out = {};
1225
+ for (const [k, v] of Object.entries(value))
1226
+ out[k] = cloneValue(v);
1227
+ return out;
1228
+ }
1229
+ return value;
1230
+ }
1231
+ function mapChildSchemas(node, visit, path) {
1232
+ const out = {};
1233
+ for (const [key, value] of Object.entries(node)) {
1234
+ const here = `${path}/${key}`;
1235
+ if (SCHEMA_MAP_KEYS.includes(key) && isPlainObject2(value)) {
1236
+ out[key] = Object.fromEntries(Object.entries(value).map(([name, child]) => [
1237
+ name,
1238
+ isPlainObject2(child) ? visit(child, `${here}/${name}`) : cloneValue(child)
1239
+ ]));
1240
+ } else if (SCHEMA_LIST_KEYS.includes(key) && Array.isArray(value)) {
1241
+ out[key] = value.map((child, i) => isPlainObject2(child) ? visit(child, `${here}/${i}`) : cloneValue(child));
1242
+ } else if (SCHEMA_VALUE_KEYS.includes(key)) {
1243
+ if (isPlainObject2(value))
1244
+ out[key] = visit(value, here);
1245
+ else if (Array.isArray(value))
1246
+ out[key] = value.map((child, i) => isPlainObject2(child) ? visit(child, `${here}/${i}`) : cloneValue(child));
1247
+ else
1248
+ out[key] = cloneValue(value);
1249
+ } else {
1250
+ out[key] = cloneValue(value);
1251
+ }
1252
+ }
1253
+ return out;
1254
+ }
1255
+ function mapSchema(node, transform, path = "") {
1256
+ return transform(mapChildSchemas(node, (child, childPath) => mapSchema(child, transform, childPath), path), path);
1257
+ }
1258
+ var UNENFORCEABLE_KEYWORDS = [
1259
+ "minimum",
1260
+ "maximum",
1261
+ "exclusiveMinimum",
1262
+ "exclusiveMaximum",
1263
+ "multipleOf",
1264
+ "maxItems",
1265
+ "uniqueItems",
1266
+ "minProperties",
1267
+ "maxProperties"
1268
+ ];
1269
+ var UNDROPPABLE_KEYWORDS = ["oneOf", "not"];
1270
+ function toEnforcedAnthropicSchema(parameters) {
1271
+ const stripped = [];
1272
+ const overridden = [];
1273
+ const undroppable = [];
1274
+ const schema = mapSchema(parameters, (node, path) => {
1275
+ for (const keyword of UNENFORCEABLE_KEYWORDS) {
1276
+ if (keyword in node) {
1277
+ delete node[keyword];
1278
+ stripped.push(`${path}/${keyword}`);
1279
+ }
1280
+ }
1281
+ if (typeof node.minItems === "number" && node.minItems > 1) {
1282
+ delete node.minItems;
1283
+ stripped.push(`${path}/minItems`);
1284
+ }
1285
+ for (const keyword of UNDROPPABLE_KEYWORDS) {
1286
+ if (keyword in node)
1287
+ undroppable.push(`${path}/${keyword}`);
1288
+ }
1289
+ const isObjectNode = node.type === "object" || Array.isArray(node.type) && node.type.includes("object") || isPlainObject2(node.properties);
1290
+ if (isObjectNode) {
1291
+ if (node.additionalProperties !== false) {
1292
+ if (node.additionalProperties !== void 0) {
1293
+ overridden.push(`${path}/additionalProperties`);
1294
+ }
1295
+ node.additionalProperties = false;
1296
+ }
1297
+ }
1298
+ return node;
1299
+ });
1300
+ return { schema, stripped, overridden, undroppable };
1301
+ }
1302
+ function enforceAnthropicToolSchema(parameters, toolName) {
1303
+ const { schema, stripped, overridden, undroppable } = toEnforcedAnthropicSchema(parameters);
1304
+ if (stripped.length) {
1305
+ logger.warn(`AnthropicTransport: tool "${toolName}" requested schema enforcement; these keywords cannot be enforced and were removed \u2014 validate them yourself: ${stripped.join(", ")}`);
1306
+ }
1307
+ if (overridden.length) {
1308
+ logger.warn(`AnthropicTransport: tool "${toolName}" requested schema enforcement, which requires closed objects; \`additionalProperties\` was set to false at: ${overridden.join(", ")}. The tool now accepts fewer inputs than its schema declared.`);
1309
+ }
1310
+ if (undroppable.length) {
1311
+ logger.warn(`AnthropicTransport: tool "${toolName}" uses schema keywords enforcement cannot express (${undroppable.join(", ")}). They cannot be removed without changing the schema's meaning, so the request will be rejected. Rewrite them or drop enforceSchema for this tool.`);
1312
+ }
1313
+ return schema;
1314
+ }
1315
+ var GEMINI_UNSUPPORTED_KEYWORDS = [
1316
+ "additionalProperties",
1317
+ "examples",
1318
+ "multipleOf",
1319
+ "patternProperties",
1320
+ // Both spellings of the definitions block. `$defs` would also fall to the
1321
+ // `$`-prefix sweep below, but the draft-07 spelling has no `$` and would
1322
+ // otherwise survive inlining and 400 the request — so list the pair together.
1323
+ "$defs",
1324
+ "definitions"
1325
+ ];
1326
+ function resolvePointer(root, ref) {
1327
+ if (!ref.startsWith("#/"))
1328
+ return void 0;
1329
+ let current = root;
1330
+ for (const segment of ref.slice(2).split("/")) {
1331
+ if (!isPlainObject2(current))
1332
+ return void 0;
1333
+ current = current[segment.replace(/~1/g, "/").replace(/~0/g, "~")];
1334
+ }
1335
+ return isPlainObject2(current) ? current : void 0;
1336
+ }
1337
+ function inlineRefs(root, node, seen, unresolved) {
1338
+ let current = node;
1339
+ let visited = seen;
1340
+ let ref = typeof current.$ref === "string" ? current.$ref : void 0;
1341
+ while (ref && !visited.has(ref)) {
1342
+ const target = resolvePointer(root, ref);
1343
+ if (!target)
1344
+ break;
1345
+ const { $ref: _dropped } = current, siblings = __rest(current, ["$ref"]);
1346
+ current = Object.assign(Object.assign({}, cloneValue(target)), siblings);
1347
+ visited = /* @__PURE__ */ new Set([...visited, ref]);
1348
+ ref = typeof current.$ref === "string" ? current.$ref : void 0;
1349
+ }
1350
+ if (typeof current.$ref === "string")
1351
+ unresolved.push(current.$ref);
1352
+ return mapChildSchemas(current, (child) => inlineRefs(root, child, visited, unresolved), "");
1353
+ }
1354
+ function toGeminiSchema(parameters) {
1355
+ const unresolved = [];
1356
+ const inlined = inlineRefs(parameters, parameters, /* @__PURE__ */ new Set(), unresolved);
1357
+ if (unresolved.length) {
1358
+ logger.warn(`GeminiTransport: these \`$ref\` pointers could not be inlined \u2014 a cycle, a typo, or an external ref: ${[...new Set(unresolved)].join(", ")}. They are left in the schema, so Gemini will reject this declaration; that is deliberate, because dropping them would send a node that constrains nothing.`);
1359
+ }
1360
+ const translated = mapSchema(inlined, (node) => {
1361
+ if (Array.isArray(node.type)) {
1362
+ const types = node.type.filter((t) => t !== "null");
1363
+ if (types.length === 1 && node.type.length !== types.length) {
1364
+ node.type = types[0];
1365
+ node.nullable = true;
1366
+ }
1367
+ }
1368
+ if (Array.isArray(node.anyOf)) {
1369
+ const branches = node.anyOf.filter(isPlainObject2);
1370
+ const nonNull = branches.filter((b) => b.type !== "null");
1371
+ if (branches.length === 2 && nonNull.length === 1) {
1372
+ const { anyOf: _dropped } = node, siblings = __rest(node, ["anyOf"]);
1373
+ return Object.assign(Object.assign(Object.assign({}, nonNull[0]), siblings), { nullable: true });
1374
+ }
1375
+ }
1376
+ if ("const" in node) {
1377
+ node.enum = [node.const];
1378
+ delete node.const;
1379
+ }
1380
+ for (const keyword of GEMINI_UNSUPPORTED_KEYWORDS)
1381
+ delete node[keyword];
1382
+ for (const key of Object.keys(node)) {
1383
+ if (key.startsWith("$") && key !== "$ref")
1384
+ delete node[key];
1385
+ }
1386
+ return node;
1387
+ });
1388
+ return translated;
1389
+ }
1390
+
1105
1391
  // ../../foundation-ai/dist/esm/utils/abort-reason.js
1106
1392
  function authoritativeAbortReason(error, timeoutSignal, callerSignal) {
1107
1393
  const abortShaped = (error instanceof DOMException || error instanceof Error) && (error.name === "AbortError" || error.name === "TimeoutError");
@@ -1321,18 +1607,6 @@ function assertSupportedAnthropicModel(model) {
1321
1607
  throw new Error(`AnthropicTransport: unsupported model "${model}". Use one of: ${SUPPORTED_ANTHROPIC_MODEL_IDS.join(", ")}.`);
1322
1608
  }
1323
1609
  }
1324
- function estimatedAnthropicRatesUsdPerMillion(model) {
1325
- if (model === "claude-haiku-4-5-20251001") {
1326
- return { promptPerMillion: 1, candidatePerMillion: 5 };
1327
- }
1328
- if (model === "claude-fable-5") {
1329
- return { promptPerMillion: 10, candidatePerMillion: 50 };
1330
- }
1331
- if (model === "claude-sonnet-5" || model === "claude-sonnet-4-6") {
1332
- return { promptPerMillion: 3, candidatePerMillion: 15 };
1333
- }
1334
- return { promptPerMillion: 5, candidatePerMillion: 25 };
1335
- }
1336
1610
  function rejectsSamplingParams(model) {
1337
1611
  return model === "claude-fable-5" || model === "claude-opus-4-8" || model === "claude-opus-4-7" || model === "claude-sonnet-5";
1338
1612
  }
@@ -1344,9 +1618,6 @@ function anthropicThinking(model) {
1344
1618
  return void 0;
1345
1619
  return { type: "adaptive", display: "summarized" };
1346
1620
  }
1347
- var ANTHROPIC_CACHE_READ_MULTIPLIER = 0.1;
1348
- var ANTHROPIC_CACHE_WRITE_5M_MULTIPLIER = 1.25;
1349
- var ANTHROPIC_CACHE_WRITE_1H_MULTIPLIER = 2;
1350
1621
  var ResponseTruncatedError = class extends Error {
1351
1622
  constructor(model, maxTokens, outputTokens, toolNames) {
1352
1623
  super(`Response truncated at ${maxTokens != null ? `the max_tokens cap (${maxTokens})` : "the model's output-token limit"} for model ${model}` + (toolNames.length > 0 ? ` while emitting tool call(s): ${toolNames.join(", ")}` : "") + ". The output exceeds the per-response limit \u2014 raise the provider maxTokens (where configurable) or split the work into smaller outputs.");
@@ -1452,11 +1723,7 @@ var AnthropicTransport = class _AnthropicTransport {
1452
1723
  if (options === null || options === void 0 ? void 0 : options.systemPrompt)
1453
1724
  body.system = options.systemPrompt;
1454
1725
  if ((_a = options === null || options === void 0 ? void 0 : options.tools) === null || _a === void 0 ? void 0 : _a.length) {
1455
- body.tools = options.tools.map((t) => ({
1456
- name: t.name,
1457
- description: t.description,
1458
- input_schema: t.parameters
1459
- }));
1726
+ body.tools = options.tools.map((t) => Object.assign({ name: t.name, description: t.description, input_schema: t.enforceSchema ? enforceAnthropicToolSchema(t.parameters, t.name) : t.parameters }, t.enforceSchema ? { strict: true } : {}));
1460
1727
  }
1461
1728
  if ((_b = body.tools) === null || _b === void 0 ? void 0 : _b.length) {
1462
1729
  const toolChoice = toAnthropicToolChoice(options === null || options === void 0 ? void 0 : options.toolChoice);
@@ -1549,30 +1816,26 @@ var AnthropicTransport = class _AnthropicTransport {
1549
1816
  * message.
1550
1817
  */
1551
1818
  logTokenUsage(promptTokens, candidateTokens, cacheReadTokens, cacheCreationTokens, cacheCreation1hTokens) {
1552
- const { promptPerMillion, candidatePerMillion } = estimatedAnthropicRatesUsdPerMillion(this.model);
1553
- const m = _AnthropicTransport.TOKENS_PER_MILLION;
1554
- const cacheCreation5mTokens = Math.max(0, cacheCreationTokens - cacheCreation1hTokens);
1555
- const promptCost = promptTokens / m * promptPerMillion;
1556
- const cacheReadCost = cacheReadTokens / m * promptPerMillion * ANTHROPIC_CACHE_READ_MULTIPLIER;
1557
- const cacheWriteCost = cacheCreation5mTokens / m * promptPerMillion * ANTHROPIC_CACHE_WRITE_5M_MULTIPLIER + cacheCreation1hTokens / m * promptPerMillion * ANTHROPIC_CACHE_WRITE_1H_MULTIPLIER;
1558
- const candidateCost = candidateTokens / m * candidatePerMillion;
1559
- const totalCost = promptCost + cacheReadCost + cacheWriteCost + candidateCost;
1560
- this.lifetimeCostUsd += totalCost;
1561
- const cacheReadFull = cacheReadTokens / m * promptPerMillion;
1562
- const cacheWriteFull = cacheCreationTokens / m * promptPerMillion;
1563
- const saved = cacheReadFull - cacheReadCost + (cacheWriteFull - cacheWriteCost);
1564
- this.lifetimeSavingsUsd += saved;
1819
+ const { costUsd, savedUsd, breakdown } = anthropicTokenCost(this.model, {
1820
+ uncachedInputTokens: promptTokens,
1821
+ outputTokens: candidateTokens,
1822
+ cacheReadTokens,
1823
+ cacheWriteTokens: cacheCreationTokens,
1824
+ cacheWrite1hTokens: cacheCreation1hTokens
1825
+ });
1826
+ this.lifetimeCostUsd += costUsd;
1827
+ this.lifetimeSavingsUsd += savedUsd;
1565
1828
  const dp = _AnthropicTransport.COST_DECIMAL_PLACES;
1566
1829
  console.log(`--- Anthropic Token Usage (${this.model}) ---`);
1567
- console.log(`Prompt Tokens: ${promptTokens} ($${promptCost.toFixed(dp)})`);
1568
- console.log(`Cache Read: ${cacheReadTokens} ($${cacheReadCost.toFixed(dp)})`);
1569
- console.log(`Cache Write: ${cacheCreationTokens} ($${cacheWriteCost.toFixed(dp)})`);
1570
- console.log(`Candidate Tokens: ${candidateTokens} ($${candidateCost.toFixed(dp)})`);
1571
- console.log(`Total Cost: $${totalCost.toFixed(dp)}`);
1572
- console.log(`Cache Saved: $${saved.toFixed(dp)} (lifetime $${this.lifetimeSavingsUsd.toFixed(dp)})`);
1830
+ console.log(`Prompt Tokens: ${promptTokens} ($${breakdown.promptUsd.toFixed(dp)})`);
1831
+ console.log(`Cache Read: ${cacheReadTokens} ($${breakdown.cacheReadUsd.toFixed(dp)})`);
1832
+ console.log(`Cache Write: ${cacheCreationTokens} ($${breakdown.cacheWriteUsd.toFixed(dp)})`);
1833
+ console.log(`Candidate Tokens: ${candidateTokens} ($${breakdown.candidateUsd.toFixed(dp)})`);
1834
+ console.log(`Total Cost: $${costUsd.toFixed(dp)}`);
1835
+ console.log(`Cache Saved: $${savedUsd.toFixed(dp)} (lifetime $${this.lifetimeSavingsUsd.toFixed(dp)})`);
1573
1836
  console.log(`Lifetime Cost: $${this.lifetimeCostUsd.toFixed(dp)}`);
1574
1837
  console.log("--------------------------");
1575
- return totalCost;
1838
+ return costUsd;
1576
1839
  }
1577
1840
  /**
1578
1841
  * Convert the internal `ChatMessage[]` history into Anthropic's message format.
@@ -1995,37 +2258,6 @@ function assertSupportedGeminiModel(model) {
1995
2258
  throw new Error(`GeminiTransport: unsupported model "${model}". Use one of: ${SUPPORTED_GEMINI_MODEL_IDS.join(", ")}.`);
1996
2259
  }
1997
2260
  }
1998
- var GEMINI_LONG_CONTEXT_THRESHOLD = 2e5;
1999
- var GEMINI_CACHED_INPUT_MULTIPLIER = 0.1;
2000
- var GEMINI_PRICING = {
2001
- "gemini-2.5-flash-lite": {
2002
- kind: "flat",
2003
- rate: { promptPerMillion: 0.1, candidatePerMillion: 0.4 }
2004
- },
2005
- "gemini-2.5-flash": { kind: "flat", rate: { promptPerMillion: 0.3, candidatePerMillion: 2.5 } },
2006
- "gemini-2.5-pro": {
2007
- kind: "tiered",
2008
- standard: { promptPerMillion: 1.25, candidatePerMillion: 10 },
2009
- longContext: { promptPerMillion: 2.5, candidatePerMillion: 15 }
2010
- },
2011
- "gemini-3.1-flash-lite": {
2012
- kind: "flat",
2013
- rate: { promptPerMillion: 0.25, candidatePerMillion: 1.5 }
2014
- },
2015
- "gemini-3.5-flash": { kind: "flat", rate: { promptPerMillion: 1.5, candidatePerMillion: 9 } },
2016
- "gemini-3.1-pro-preview": {
2017
- kind: "tiered",
2018
- standard: { promptPerMillion: 2, candidatePerMillion: 12 },
2019
- longContext: { promptPerMillion: 4, candidatePerMillion: 18 }
2020
- }
2021
- };
2022
- function estimatedGeminiPaidRatesUsdPerMillion(model, promptTokens) {
2023
- const pricing = GEMINI_PRICING[model];
2024
- if (pricing.kind === "flat") {
2025
- return pricing.rate;
2026
- }
2027
- return promptTokens > GEMINI_LONG_CONTEXT_THRESHOLD ? pricing.longContext : pricing.standard;
2028
- }
2029
2261
  var GEMINI_MODEL_WARNINGS = {
2030
2262
  "gemini-2.5-flash": "GeminiTransport: using gemini-2.5-flash \u2014 higher cost than flash-lite; use for harder reasoning or agent tasks.",
2031
2263
  "gemini-2.5-pro": "GeminiTransport: using gemini-2.5-pro \u2014 significantly higher, prompt-size-tiered cost; reserve for tasks where flash reliability is insufficient.",
@@ -2106,7 +2338,7 @@ var GeminiTransport = class _GeminiTransport {
2106
2338
  functionDeclarations: options.tools.map((t) => ({
2107
2339
  name: t.name,
2108
2340
  description: t.description,
2109
- parameters: t.parameters
2341
+ parameters: toGeminiSchema(t.parameters)
2110
2342
  }))
2111
2343
  }
2112
2344
  ] : void 0;
@@ -2129,7 +2361,7 @@ var GeminiTransport = class _GeminiTransport {
2129
2361
  systemInstruction,
2130
2362
  toolConfig,
2131
2363
  generationConfig
2132
- }, applyResponseSchema ? { responseSchema: options.responseSchema } : {}), options === null || options === void 0 ? void 0 : options.signal);
2364
+ }, applyResponseSchema ? { responseSchema: toGeminiSchema(options.responseSchema) } : {}), options === null || options === void 0 ? void 0 : options.signal);
2133
2365
  return this.fromGeminiResponse(response, offeredToolNames);
2134
2366
  });
2135
2367
  }
@@ -2139,25 +2371,23 @@ var GeminiTransport = class _GeminiTransport {
2139
2371
  * message.
2140
2372
  */
2141
2373
  logTokenUsage(promptTokens, candidateTokens, thoughtTokens, cachedTokens) {
2142
- const { promptPerMillion, candidatePerMillion } = estimatedGeminiPaidRatesUsdPerMillion(this.model, promptTokens);
2143
- const m = _GeminiTransport.TOKENS_PER_MILLION;
2144
- const uncachedPromptTokens = Math.max(0, promptTokens - cachedTokens);
2145
- const promptCost = uncachedPromptTokens / m * promptPerMillion;
2146
- const cacheReadCost = cachedTokens / m * promptPerMillion * GEMINI_CACHED_INPUT_MULTIPLIER;
2147
- const candidateCost = (candidateTokens + thoughtTokens) / m * candidatePerMillion;
2148
- const totalCost = promptCost + cacheReadCost + candidateCost;
2149
- this.lifetimeCostUsd += totalCost;
2150
- const saved = cachedTokens / m * promptPerMillion - cacheReadCost;
2151
- this.lifetimeSavingsUsd += saved;
2374
+ const { costUsd, savedUsd, breakdown } = geminiTokenCost(this.model, {
2375
+ promptTokens,
2376
+ candidateTokens,
2377
+ thoughtTokens,
2378
+ cachedTokens
2379
+ });
2380
+ this.lifetimeCostUsd += costUsd;
2381
+ this.lifetimeSavingsUsd += savedUsd;
2152
2382
  const dp = _GeminiTransport.COST_DECIMAL_PLACES;
2153
2383
  console.log(`--- Gemini Token Usage (${this.model}) ---`);
2154
- console.log(`Prompt Tokens: ${promptTokens} (${cachedTokens} cached) ($${promptCost.toFixed(dp)} + $${cacheReadCost.toFixed(dp)})`);
2155
- console.log(`Candidate Tokens: ${candidateTokens} (+${thoughtTokens} thinking) ($${candidateCost.toFixed(dp)})`);
2156
- console.log(`Total Cost: $${totalCost.toFixed(dp)}`);
2157
- console.log(`Cache Saved: $${saved.toFixed(dp)} (lifetime $${this.lifetimeSavingsUsd.toFixed(dp)})`);
2384
+ console.log(`Prompt Tokens: ${promptTokens} (${cachedTokens} cached) ($${breakdown.promptUsd.toFixed(dp)} + $${breakdown.cacheReadUsd.toFixed(dp)})`);
2385
+ console.log(`Candidate Tokens: ${candidateTokens} (+${thoughtTokens} thinking) ($${breakdown.candidateUsd.toFixed(dp)})`);
2386
+ console.log(`Total Cost: $${costUsd.toFixed(dp)}`);
2387
+ console.log(`Cache Saved: $${savedUsd.toFixed(dp)} (lifetime $${this.lifetimeSavingsUsd.toFixed(dp)})`);
2158
2388
  console.log(`Lifetime Cost: $${this.lifetimeCostUsd.toFixed(dp)}`);
2159
2389
  console.log("--------------------------");
2160
- return totalCost;
2390
+ return costUsd;
2161
2391
  }
2162
2392
  toGeminiContents(history, userMessage, attachments) {
2163
2393
  var _a, _b, _c;
@@ -3122,6 +3352,18 @@ function emptyUsage() {
3122
3352
  outputTokens: 0
3123
3353
  };
3124
3354
  }
3355
+ function totalTokens(usage) {
3356
+ return usage.uncachedInputTokens + usage.cacheReadTokens + usage.cacheWriteTokens + usage.outputTokens;
3357
+ }
3358
+ function addUsage(a, b) {
3359
+ return {
3360
+ costUsd: a.costUsd + b.costUsd,
3361
+ uncachedInputTokens: a.uncachedInputTokens + b.uncachedInputTokens,
3362
+ cacheReadTokens: a.cacheReadTokens + b.cacheReadTokens,
3363
+ cacheWriteTokens: a.cacheWriteTokens + b.cacheWriteTokens,
3364
+ outputTokens: a.outputTokens + b.outputTokens
3365
+ };
3366
+ }
3125
3367
  function sumUsage(messages) {
3126
3368
  const total = emptyUsage();
3127
3369
  accumulate(messages, total);
@@ -6108,16 +6350,20 @@ function assembleDebugLog(entries, readme) {
6108
6350
  REQUEST_CONTINUATION_TOOL,
6109
6351
  SUPPORTED_ANTHROPIC_MODEL_IDS,
6110
6352
  SUPPORTED_GEMINI_MODEL_IDS,
6353
+ addUsage,
6111
6354
  agenticActivityBus,
6112
6355
  assembleDebugLog,
6113
6356
  buildTimelineEntries,
6114
6357
  clearSession,
6115
6358
  defineAgent,
6116
6359
  defineStatefulAgent,
6360
+ emptyUsage,
6117
6361
  friendlyFallbackAgent,
6118
6362
  getMetaEvents,
6119
6363
  isObservableAIProviderRegistry,
6120
6364
  restoreMachine,
6121
- strictFallbackAgent
6365
+ strictFallbackAgent,
6366
+ sumUsage,
6367
+ totalTokens
6122
6368
  });
6123
6369
  //# sourceMappingURL=chat-driver.cjs.map