@genesislcap/ai-assistant 15.11.0 → 15.12.0
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/dist/ai-assistant.api.json +135 -0
- package/dist/ai-assistant.d.ts +75 -3
- package/dist/chat-driver.cjs +540 -117
- package/dist/chat-driver.cjs.map +4 -4
- package/dist/chat-driver.mjs +524 -116
- package/dist/chat-driver.mjs.map +4 -4
- package/dist/custom-elements.json +1822 -1483
- package/dist/dts/chat-driver-node.d.ts +5 -2
- package/dist/dts/chat-driver-node.d.ts.map +1 -1
- package/dist/dts/components/chat-driver/chat-driver.d.ts +20 -3
- package/dist/dts/components/chat-driver/chat-driver.d.ts.map +1 -1
- package/dist/dts/components/chat-driver/chat-driver.thinking-policy.test.d.ts +2 -0
- package/dist/dts/components/chat-driver/chat-driver.thinking-policy.test.d.ts.map +1 -0
- package/dist/dts/components/chat-driver/chat-driver.trace-capture.test.d.ts +2 -0
- package/dist/dts/components/chat-driver/chat-driver.trace-capture.test.d.ts.map +1 -0
- package/dist/dts/config/config.d.ts +39 -2
- package/dist/dts/config/config.d.ts.map +1 -1
- package/dist/dts/config/define-stateful-agent.d.ts +15 -1
- package/dist/dts/config/define-stateful-agent.d.ts.map +1 -1
- package/dist/dts/main/main.template.d.ts.map +1 -1
- package/dist/dts/utils/strip-agent-handlers.d.ts +1 -1
- package/dist/dts/utils/sum-usage.d.ts +37 -4
- package/dist/dts/utils/sum-usage.d.ts.map +1 -1
- package/dist/dts/utils/usage-rows.d.ts +102 -0
- package/dist/dts/utils/usage-rows.d.ts.map +1 -0
- package/dist/dts/utils/usage-rows.test.d.ts +2 -0
- package/dist/dts/utils/usage-rows.test.d.ts.map +1 -0
- package/dist/esm/chat-driver-node.js +36 -1
- package/dist/esm/components/chat-driver/chat-driver.js +73 -10
- package/dist/esm/components/chat-driver/chat-driver.thinking-policy.test.js +137 -0
- package/dist/esm/components/chat-driver/chat-driver.trace-capture.test.js +200 -0
- package/dist/esm/config/define-stateful-agent.js +11 -0
- package/dist/esm/main/main.template.js +20 -1
- package/dist/esm/utils/strip-agent-handlers.js +1 -1
- package/dist/esm/utils/sum-usage.js +37 -4
- package/dist/esm/utils/usage-rows.js +90 -0
- package/dist/esm/utils/usage-rows.test.js +189 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +17 -17
- package/src/chat-driver-node.ts +58 -0
- package/src/components/chat-driver/chat-driver.thinking-policy.test.ts +185 -0
- package/src/components/chat-driver/chat-driver.trace-capture.test.ts +251 -0
- package/src/components/chat-driver/chat-driver.ts +90 -10
- package/src/config/config.ts +50 -1
- package/src/config/define-stateful-agent.ts +37 -0
- package/src/main/main.template.ts +19 -1
- package/src/utils/strip-agent-handlers.ts +1 -1
- package/src/utils/sum-usage.ts +37 -4
- package/src/utils/usage-rows.test.ts +237 -0
- package/src/utils/usage-rows.ts +187 -0
package/dist/chat-driver.mjs
CHANGED
|
@@ -1058,6 +1058,13 @@ var SUPPORTED_ANTHROPIC_MODEL_IDS = [
|
|
|
1058
1058
|
"claude-sonnet-4-6",
|
|
1059
1059
|
"claude-haiku-4-5-20251001"
|
|
1060
1060
|
];
|
|
1061
|
+
function vendorOfModel(modelId) {
|
|
1062
|
+
if (SUPPORTED_ANTHROPIC_MODEL_IDS.includes(modelId))
|
|
1063
|
+
return "anthropic";
|
|
1064
|
+
if (SUPPORTED_GEMINI_MODEL_IDS.includes(modelId))
|
|
1065
|
+
return "gemini";
|
|
1066
|
+
return void 0;
|
|
1067
|
+
}
|
|
1061
1068
|
|
|
1062
1069
|
// ../../foundation-ai/dist/esm/utils/temperature.js
|
|
1063
1070
|
var DEFAULT_ANCHOR = 0.5;
|
|
@@ -1066,6 +1073,106 @@ function scaleTemperature(normalized, { defaultTemp, maxTemp }) {
|
|
|
1066
1073
|
return t <= DEFAULT_ANCHOR ? t / DEFAULT_ANCHOR * defaultTemp : defaultTemp + (t - DEFAULT_ANCHOR) / (1 - DEFAULT_ANCHOR) * (maxTemp - defaultTemp);
|
|
1067
1074
|
}
|
|
1068
1075
|
|
|
1076
|
+
// ../../foundation-ai/dist/esm/utils/token-cost.js
|
|
1077
|
+
var TOKENS_PER_MILLION = 1e6;
|
|
1078
|
+
var ANTHROPIC_PRICING = {
|
|
1079
|
+
"claude-haiku-4-5-20251001": { promptPerMillion: 1, candidatePerMillion: 5 },
|
|
1080
|
+
// Fable 5 — Anthropic's most capable widely-released model; priced above Opus tier.
|
|
1081
|
+
"claude-fable-5": { promptPerMillion: 10, candidatePerMillion: 50 },
|
|
1082
|
+
// Opus 4.7 / 4.8 — same $5 / $25 per MTok. Stated per model rather than shared through a
|
|
1083
|
+
// fall-through, so neither is ever "whatever was left over".
|
|
1084
|
+
"claude-opus-4-8": { promptPerMillion: 5, candidatePerMillion: 25 },
|
|
1085
|
+
"claude-opus-4-7": { promptPerMillion: 5, candidatePerMillion: 25 },
|
|
1086
|
+
// Sonnet 5 is $2 / $10 — its OWN tier, and CHEAPER than the older Sonnet 4.6 below.
|
|
1087
|
+
//
|
|
1088
|
+
// This launched as an introductory rate through 2026-08-31, and an earlier version of this
|
|
1089
|
+
// table deliberately charged the $3 / $15 standard rate instead, on the reasoning that the
|
|
1090
|
+
// introductory period would lapse. Anthropic has since confirmed $2 / $10 as the permanent
|
|
1091
|
+
// standard price and cancelled the scheduled increase, so that reasoning is dead and the old
|
|
1092
|
+
// figure over-charged every Sonnet 5 request by 50%.
|
|
1093
|
+
// https://platform.claude.com/docs/en/about-claude/pricing#model-pricing
|
|
1094
|
+
"claude-sonnet-5": { promptPerMillion: 2, candidatePerMillion: 10 },
|
|
1095
|
+
// Sonnet 4.6 remains on the older $3 / $15 Sonnet tier — the newer model is the cheaper one.
|
|
1096
|
+
"claude-sonnet-4-6": { promptPerMillion: 3, candidatePerMillion: 15 }
|
|
1097
|
+
};
|
|
1098
|
+
function anthropicRatesFor(model) {
|
|
1099
|
+
return ANTHROPIC_PRICING[model];
|
|
1100
|
+
}
|
|
1101
|
+
var ANTHROPIC_CACHE_READ_MULTIPLIER = 0.1;
|
|
1102
|
+
var ANTHROPIC_CACHE_WRITE_5M_MULTIPLIER = 1.25;
|
|
1103
|
+
var ANTHROPIC_CACHE_WRITE_1H_MULTIPLIER = 2;
|
|
1104
|
+
function anthropicTokenCost(model, usage) {
|
|
1105
|
+
const { promptPerMillion, candidatePerMillion } = anthropicRatesFor(model);
|
|
1106
|
+
const m = TOKENS_PER_MILLION;
|
|
1107
|
+
const cacheWrite5mTokens = Math.max(0, usage.cacheWriteTokens - usage.cacheWrite1hTokens);
|
|
1108
|
+
const promptCost = usage.uncachedInputTokens / m * promptPerMillion;
|
|
1109
|
+
const cacheReadCost = usage.cacheReadTokens / m * promptPerMillion * ANTHROPIC_CACHE_READ_MULTIPLIER;
|
|
1110
|
+
const cacheWriteCost = cacheWrite5mTokens / m * promptPerMillion * ANTHROPIC_CACHE_WRITE_5M_MULTIPLIER + usage.cacheWrite1hTokens / m * promptPerMillion * ANTHROPIC_CACHE_WRITE_1H_MULTIPLIER;
|
|
1111
|
+
const candidateCost = usage.outputTokens / m * candidatePerMillion;
|
|
1112
|
+
const cacheReadFull = usage.cacheReadTokens / m * promptPerMillion;
|
|
1113
|
+
const cacheWriteFull = usage.cacheWriteTokens / m * promptPerMillion;
|
|
1114
|
+
return {
|
|
1115
|
+
costUsd: promptCost + cacheReadCost + cacheWriteCost + candidateCost,
|
|
1116
|
+
savedUsd: cacheReadFull - cacheReadCost + (cacheWriteFull - cacheWriteCost),
|
|
1117
|
+
breakdown: {
|
|
1118
|
+
promptUsd: promptCost,
|
|
1119
|
+
cacheReadUsd: cacheReadCost,
|
|
1120
|
+
cacheWriteUsd: cacheWriteCost,
|
|
1121
|
+
candidateUsd: candidateCost
|
|
1122
|
+
}
|
|
1123
|
+
};
|
|
1124
|
+
}
|
|
1125
|
+
var GEMINI_LONG_CONTEXT_THRESHOLD = 2e5;
|
|
1126
|
+
var GEMINI_CACHED_INPUT_MULTIPLIER = 0.1;
|
|
1127
|
+
var GEMINI_PRICING = {
|
|
1128
|
+
"gemini-2.5-flash-lite": {
|
|
1129
|
+
kind: "flat",
|
|
1130
|
+
rate: { promptPerMillion: 0.1, candidatePerMillion: 0.4 }
|
|
1131
|
+
},
|
|
1132
|
+
"gemini-2.5-flash": { kind: "flat", rate: { promptPerMillion: 0.3, candidatePerMillion: 2.5 } },
|
|
1133
|
+
"gemini-2.5-pro": {
|
|
1134
|
+
kind: "tiered",
|
|
1135
|
+
standard: { promptPerMillion: 1.25, candidatePerMillion: 10 },
|
|
1136
|
+
longContext: { promptPerMillion: 2.5, candidatePerMillion: 15 }
|
|
1137
|
+
},
|
|
1138
|
+
"gemini-3.1-flash-lite": {
|
|
1139
|
+
kind: "flat",
|
|
1140
|
+
rate: { promptPerMillion: 0.25, candidatePerMillion: 1.5 }
|
|
1141
|
+
},
|
|
1142
|
+
"gemini-3.5-flash": { kind: "flat", rate: { promptPerMillion: 1.5, candidatePerMillion: 9 } },
|
|
1143
|
+
"gemini-3.1-pro-preview": {
|
|
1144
|
+
kind: "tiered",
|
|
1145
|
+
standard: { promptPerMillion: 2, candidatePerMillion: 12 },
|
|
1146
|
+
longContext: { promptPerMillion: 4, candidatePerMillion: 18 }
|
|
1147
|
+
}
|
|
1148
|
+
};
|
|
1149
|
+
function geminiRatesFor(model, promptTokens) {
|
|
1150
|
+
const pricing = GEMINI_PRICING[model];
|
|
1151
|
+
if (pricing.kind === "flat") {
|
|
1152
|
+
return pricing.rate;
|
|
1153
|
+
}
|
|
1154
|
+
return promptTokens > GEMINI_LONG_CONTEXT_THRESHOLD ? pricing.longContext : pricing.standard;
|
|
1155
|
+
}
|
|
1156
|
+
function geminiTokenCost(model, usage) {
|
|
1157
|
+
const { promptPerMillion, candidatePerMillion } = geminiRatesFor(model, usage.promptTokens);
|
|
1158
|
+
const m = TOKENS_PER_MILLION;
|
|
1159
|
+
const uncachedPromptTokens = Math.max(0, usage.promptTokens - usage.cachedTokens);
|
|
1160
|
+
const promptCost = uncachedPromptTokens / m * promptPerMillion;
|
|
1161
|
+
const cacheReadCost = usage.cachedTokens / m * promptPerMillion * GEMINI_CACHED_INPUT_MULTIPLIER;
|
|
1162
|
+
const candidateCost = (usage.candidateTokens + usage.thoughtTokens) / m * candidatePerMillion;
|
|
1163
|
+
return {
|
|
1164
|
+
costUsd: promptCost + cacheReadCost + candidateCost,
|
|
1165
|
+
// Implicit caching has no write premium, so this is always >= 0.
|
|
1166
|
+
savedUsd: usage.cachedTokens / m * promptPerMillion - cacheReadCost,
|
|
1167
|
+
breakdown: {
|
|
1168
|
+
promptUsd: promptCost,
|
|
1169
|
+
cacheReadUsd: cacheReadCost,
|
|
1170
|
+
cacheWriteUsd: 0,
|
|
1171
|
+
candidateUsd: candidateCost
|
|
1172
|
+
}
|
|
1173
|
+
};
|
|
1174
|
+
}
|
|
1175
|
+
|
|
1069
1176
|
// ../../foundation-ai/dist/esm/utils/tool-schema.js
|
|
1070
1177
|
var SCHEMA_MAP_KEYS = ["properties", "patternProperties", "$defs", "definitions"];
|
|
1071
1178
|
var SCHEMA_LIST_KEYS = ["anyOf", "oneOf", "allOf", "prefixItems"];
|
|
@@ -1467,32 +1574,32 @@ function assertSupportedAnthropicModel(model) {
|
|
|
1467
1574
|
throw new Error(`AnthropicTransport: unsupported model "${model}". Use one of: ${SUPPORTED_ANTHROPIC_MODEL_IDS.join(", ")}.`);
|
|
1468
1575
|
}
|
|
1469
1576
|
}
|
|
1470
|
-
function estimatedAnthropicRatesUsdPerMillion(model) {
|
|
1471
|
-
if (model === "claude-haiku-4-5-20251001") {
|
|
1472
|
-
return { promptPerMillion: 1, candidatePerMillion: 5 };
|
|
1473
|
-
}
|
|
1474
|
-
if (model === "claude-fable-5") {
|
|
1475
|
-
return { promptPerMillion: 10, candidatePerMillion: 50 };
|
|
1476
|
-
}
|
|
1477
|
-
if (model === "claude-sonnet-5" || model === "claude-sonnet-4-6") {
|
|
1478
|
-
return { promptPerMillion: 3, candidatePerMillion: 15 };
|
|
1479
|
-
}
|
|
1480
|
-
return { promptPerMillion: 5, candidatePerMillion: 25 };
|
|
1481
|
-
}
|
|
1482
1577
|
function rejectsSamplingParams(model) {
|
|
1483
1578
|
return model === "claude-fable-5" || model === "claude-opus-4-8" || model === "claude-opus-4-7" || model === "claude-sonnet-5";
|
|
1484
1579
|
}
|
|
1485
1580
|
function supportsNativeStructuredOutput(model) {
|
|
1486
1581
|
return model === "claude-fable-5" || model === "claude-opus-4-8" || model === "claude-sonnet-5" || model === "claude-haiku-4-5-20251001";
|
|
1487
1582
|
}
|
|
1488
|
-
function
|
|
1489
|
-
|
|
1490
|
-
return void 0;
|
|
1491
|
-
return { type: "adaptive", display: "summarized" };
|
|
1583
|
+
function supportsAdaptiveThinking(model) {
|
|
1584
|
+
return model !== "claude-haiku-4-5-20251001";
|
|
1492
1585
|
}
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1586
|
+
function thinkingIsMandatory(model) {
|
|
1587
|
+
return model === "claude-fable-5";
|
|
1588
|
+
}
|
|
1589
|
+
function anthropicThinking(model, policy) {
|
|
1590
|
+
const defaultsToThinking = model === "claude-sonnet-5" || thinkingIsMandatory(model);
|
|
1591
|
+
const adaptive = { type: "adaptive", display: "summarized" };
|
|
1592
|
+
if (policy === "off") {
|
|
1593
|
+
if (thinkingIsMandatory(model))
|
|
1594
|
+
return adaptive;
|
|
1595
|
+
return defaultsToThinking ? { type: "disabled" } : void 0;
|
|
1596
|
+
}
|
|
1597
|
+
if (policy === "auto") {
|
|
1598
|
+
return supportsAdaptiveThinking(model) ? adaptive : void 0;
|
|
1599
|
+
}
|
|
1600
|
+
return defaultsToThinking ? adaptive : void 0;
|
|
1601
|
+
}
|
|
1602
|
+
var ANTHROPIC_PROVIDER_KEY = "anthropic";
|
|
1496
1603
|
var ResponseTruncatedError = class extends Error {
|
|
1497
1604
|
constructor(model, maxTokens, outputTokens, toolNames) {
|
|
1498
1605
|
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.");
|
|
@@ -1504,10 +1611,30 @@ var ResponseTruncatedError = class extends Error {
|
|
|
1504
1611
|
}
|
|
1505
1612
|
};
|
|
1506
1613
|
var AnthropicTransport = class _AnthropicTransport {
|
|
1614
|
+
/**
|
|
1615
|
+
* Warn once when a requested policy is silently clamped, in EITHER direction — which is what
|
|
1616
|
+
* `ChatThinkingPolicy` promises callers. Both directions cost the caller something they asked
|
|
1617
|
+
* for and would otherwise get no signal about: `'off'` on a model that always thinks keeps
|
|
1618
|
+
* billing reasoning as output, and `'auto'` on a model without adaptive support means an agent
|
|
1619
|
+
* that asked to reason quietly does not. (Gemini's twin deliberately stays silent on `'auto'`,
|
|
1620
|
+
* but only because dynamic thinking is already the default there; Haiku defaults to none, so
|
|
1621
|
+
* the same silence would hide a real difference.)
|
|
1622
|
+
*/
|
|
1623
|
+
warnIfThinkingUnclampable(policy) {
|
|
1624
|
+
if (this.warnedThinkingClamped)
|
|
1625
|
+
return;
|
|
1626
|
+
const clamped = policy === "off" && thinkingIsMandatory(this.model) || policy === "auto" && !supportsAdaptiveThinking(this.model);
|
|
1627
|
+
if (!clamped)
|
|
1628
|
+
return;
|
|
1629
|
+
this.warnedThinkingClamped = true;
|
|
1630
|
+
logger.warn(policy === "off" ? `AnthropicTransport: thinkingPolicy 'off' ignored \u2014 ${this.model} always thinks and rejects an explicit disable. Reasoning tokens are still billed as output; switch model if you need them gone.` : `AnthropicTransport: thinkingPolicy 'auto' ignored \u2014 ${this.model} does not support adaptive thinking, so this turn runs without reasoning. Use a Sonnet or Opus tier if the agent needs it.`);
|
|
1631
|
+
}
|
|
1507
1632
|
constructor(config = {}) {
|
|
1508
1633
|
var _a, _b, _c, _d;
|
|
1509
1634
|
this.lifetimeCostUsd = 0;
|
|
1510
1635
|
this.lifetimeSavingsUsd = 0;
|
|
1636
|
+
this.warnedThinkingClamped = false;
|
|
1637
|
+
this.warnedUnknownServingModels = /* @__PURE__ */ new Set();
|
|
1511
1638
|
const model = (_a = config.model) !== null && _a !== void 0 ? _a : DEFAULT_MODEL;
|
|
1512
1639
|
assertSupportedAnthropicModel(model);
|
|
1513
1640
|
this.model = model;
|
|
@@ -1588,8 +1715,12 @@ var AnthropicTransport = class _AnthropicTransport {
|
|
|
1588
1715
|
// ── ChatTransport (multi-turn chat) ────────────────────────────────────
|
|
1589
1716
|
sendChatMessage(history, userMessage, options) {
|
|
1590
1717
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1591
|
-
var _a, _b, _c;
|
|
1592
|
-
const
|
|
1718
|
+
var _a, _b, _c, _d;
|
|
1719
|
+
const reachableModels = /* @__PURE__ */ new Set([
|
|
1720
|
+
this.model,
|
|
1721
|
+
...((_a = options === null || options === void 0 ? void 0 : options.fallbacks) !== null && _a !== void 0 ? _a : []).map((f) => f.model)
|
|
1722
|
+
]);
|
|
1723
|
+
const messages = this.toAnthropicMessages(history, userMessage, options === null || options === void 0 ? void 0 : options.attachments, reachableModels);
|
|
1593
1724
|
const body = {
|
|
1594
1725
|
model: this.model,
|
|
1595
1726
|
max_tokens: this.maxTokens,
|
|
@@ -1597,18 +1728,20 @@ var AnthropicTransport = class _AnthropicTransport {
|
|
|
1597
1728
|
};
|
|
1598
1729
|
if (options === null || options === void 0 ? void 0 : options.systemPrompt)
|
|
1599
1730
|
body.system = options.systemPrompt;
|
|
1600
|
-
if ((
|
|
1731
|
+
if ((_b = options === null || options === void 0 ? void 0 : options.tools) === null || _b === void 0 ? void 0 : _b.length) {
|
|
1601
1732
|
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 } : {}));
|
|
1602
1733
|
}
|
|
1603
|
-
if ((
|
|
1734
|
+
if ((_c = body.tools) === null || _c === void 0 ? void 0 : _c.length) {
|
|
1604
1735
|
const toolChoice = toAnthropicToolChoice(options === null || options === void 0 ? void 0 : options.toolChoice);
|
|
1605
1736
|
if (toolChoice)
|
|
1606
1737
|
body.tool_choice = toolChoice;
|
|
1607
1738
|
}
|
|
1608
|
-
|
|
1739
|
+
this.warnIfThinkingUnclampable(options === null || options === void 0 ? void 0 : options.thinkingPolicy);
|
|
1740
|
+
const thinking = anthropicThinking(this.model, options === null || options === void 0 ? void 0 : options.thinkingPolicy);
|
|
1609
1741
|
if (thinking)
|
|
1610
1742
|
body.thinking = thinking;
|
|
1611
|
-
|
|
1743
|
+
const thinkingEnabled = (thinking === null || thinking === void 0 ? void 0 : thinking.type) === "adaptive";
|
|
1744
|
+
if ((options === null || options === void 0 ? void 0 : options.temperature) != null && !rejectsSamplingParams(this.model) && !thinkingEnabled) {
|
|
1612
1745
|
body.temperature = scaleTemperature(options.temperature, {
|
|
1613
1746
|
defaultTemp: ANTHROPIC_DEFAULT_TEMPERATURE,
|
|
1614
1747
|
maxTemp: ANTHROPIC_MAX_TEMPERATURE
|
|
@@ -1619,7 +1752,7 @@ var AnthropicTransport = class _AnthropicTransport {
|
|
|
1619
1752
|
format: { type: "json_schema", schema: options.responseSchema }
|
|
1620
1753
|
};
|
|
1621
1754
|
}
|
|
1622
|
-
if ((
|
|
1755
|
+
if ((_d = options === null || options === void 0 ? void 0 : options.fallbacks) === null || _d === void 0 ? void 0 : _d.length) {
|
|
1623
1756
|
body.fallbacks = options.fallbacks.map((f) => f.maxTokens != null ? { model: f.model, max_tokens: f.maxTokens } : { model: f.model });
|
|
1624
1757
|
}
|
|
1625
1758
|
if (options === null || options === void 0 ? void 0 : options.cachePolicy) {
|
|
@@ -1690,31 +1823,27 @@ var AnthropicTransport = class _AnthropicTransport {
|
|
|
1690
1823
|
* and returns the per-call total so the caller can attach it to the response
|
|
1691
1824
|
* message.
|
|
1692
1825
|
*/
|
|
1693
|
-
logTokenUsage(promptTokens, candidateTokens, cacheReadTokens, cacheCreationTokens, cacheCreation1hTokens) {
|
|
1694
|
-
const {
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
this.
|
|
1703
|
-
const cacheReadFull = cacheReadTokens / m * promptPerMillion;
|
|
1704
|
-
const cacheWriteFull = cacheCreationTokens / m * promptPerMillion;
|
|
1705
|
-
const saved = cacheReadFull - cacheReadCost + (cacheWriteFull - cacheWriteCost);
|
|
1706
|
-
this.lifetimeSavingsUsd += saved;
|
|
1826
|
+
logTokenUsage(model, promptTokens, candidateTokens, cacheReadTokens, cacheCreationTokens, cacheCreation1hTokens) {
|
|
1827
|
+
const { costUsd, savedUsd, breakdown } = anthropicTokenCost(model, {
|
|
1828
|
+
uncachedInputTokens: promptTokens,
|
|
1829
|
+
outputTokens: candidateTokens,
|
|
1830
|
+
cacheReadTokens,
|
|
1831
|
+
cacheWriteTokens: cacheCreationTokens,
|
|
1832
|
+
cacheWrite1hTokens: cacheCreation1hTokens
|
|
1833
|
+
});
|
|
1834
|
+
this.lifetimeCostUsd += costUsd;
|
|
1835
|
+
this.lifetimeSavingsUsd += savedUsd;
|
|
1707
1836
|
const dp = _AnthropicTransport.COST_DECIMAL_PLACES;
|
|
1708
|
-
console.log(`--- Anthropic Token Usage (${
|
|
1709
|
-
console.log(`Prompt Tokens: ${promptTokens} ($${
|
|
1710
|
-
console.log(`Cache Read: ${cacheReadTokens} ($${
|
|
1711
|
-
console.log(`Cache Write: ${cacheCreationTokens} ($${
|
|
1712
|
-
console.log(`Candidate Tokens: ${candidateTokens} ($${
|
|
1713
|
-
console.log(`Total Cost: $${
|
|
1714
|
-
console.log(`Cache Saved: $${
|
|
1837
|
+
console.log(`--- Anthropic Token Usage (${model}) ---`);
|
|
1838
|
+
console.log(`Prompt Tokens: ${promptTokens} ($${breakdown.promptUsd.toFixed(dp)})`);
|
|
1839
|
+
console.log(`Cache Read: ${cacheReadTokens} ($${breakdown.cacheReadUsd.toFixed(dp)})`);
|
|
1840
|
+
console.log(`Cache Write: ${cacheCreationTokens} ($${breakdown.cacheWriteUsd.toFixed(dp)})`);
|
|
1841
|
+
console.log(`Candidate Tokens: ${candidateTokens} ($${breakdown.candidateUsd.toFixed(dp)})`);
|
|
1842
|
+
console.log(`Total Cost: $${costUsd.toFixed(dp)}`);
|
|
1843
|
+
console.log(`Cache Saved: $${savedUsd.toFixed(dp)} (lifetime $${this.lifetimeSavingsUsd.toFixed(dp)})`);
|
|
1715
1844
|
console.log(`Lifetime Cost: $${this.lifetimeCostUsd.toFixed(dp)}`);
|
|
1716
1845
|
console.log("--------------------------");
|
|
1717
|
-
return
|
|
1846
|
+
return costUsd;
|
|
1718
1847
|
}
|
|
1719
1848
|
/**
|
|
1720
1849
|
* Convert the internal `ChatMessage[]` history into Anthropic's message format.
|
|
@@ -1725,7 +1854,7 @@ var AnthropicTransport = class _AnthropicTransport {
|
|
|
1725
1854
|
* Consecutive same-role turns are merged by the API but we merge here to keep
|
|
1726
1855
|
* the payload tidy.
|
|
1727
1856
|
*/
|
|
1728
|
-
toAnthropicMessages(history, userMessage, attachments) {
|
|
1857
|
+
toAnthropicMessages(history, userMessage, attachments, reachableModels = /* @__PURE__ */ new Set([this.model])) {
|
|
1729
1858
|
var _a, _b, _c;
|
|
1730
1859
|
const messages = [];
|
|
1731
1860
|
const pushBlock = (role, block) => {
|
|
@@ -1748,6 +1877,9 @@ var AnthropicTransport = class _AnthropicTransport {
|
|
|
1748
1877
|
continue;
|
|
1749
1878
|
}
|
|
1750
1879
|
if ((_a = msg.toolCalls) === null || _a === void 0 ? void 0 : _a.length) {
|
|
1880
|
+
for (const block of this.reasoningToReplay(msg.toolCalls[0], reachableModels)) {
|
|
1881
|
+
pushBlock("assistant", block);
|
|
1882
|
+
}
|
|
1751
1883
|
if (msg.content) {
|
|
1752
1884
|
pushBlock("assistant", { type: "text", text: msg.content });
|
|
1753
1885
|
}
|
|
@@ -1783,20 +1915,140 @@ ${att.content}` });
|
|
|
1783
1915
|
}
|
|
1784
1916
|
return messages;
|
|
1785
1917
|
}
|
|
1918
|
+
/**
|
|
1919
|
+
* The blocks to replay ahead of a tool call — fallback boundaries then reasoning, or none.
|
|
1920
|
+
*
|
|
1921
|
+
* A `signature` is only valid for the model that produced it, so reasoning captured under a
|
|
1922
|
+
* *different* model is normally dropped: an agent that varies `provider` by state can switch
|
|
1923
|
+
* models mid-loop, and replaying the old model's signatures would send blocks the new one
|
|
1924
|
+
* cannot verify.
|
|
1925
|
+
*
|
|
1926
|
+
* Two ways the producer can be the model that will validate:
|
|
1927
|
+
*
|
|
1928
|
+
* 1. **It is the model we are asking for.** `state.model === this.model` — the ordinary case.
|
|
1929
|
+
* 2. **Sticky routing will send this conversation back to it.** After a conversation falls
|
|
1930
|
+
* back, later requests carrying `fallbacks` go straight to the model that served, without
|
|
1931
|
+
* re-running the one that declined. That is what makes a fallback producer's reasoning
|
|
1932
|
+
* replayable at all (Fable 5 configured, Opus 4.8 serving — the pairing this transport's
|
|
1933
|
+
* own constructor warning recommends). But it holds only while the conversation continues
|
|
1934
|
+
* under the SAME request configuration, which is why `requestedModel` is compared rather
|
|
1935
|
+
* than just checking the chain for the producer.
|
|
1936
|
+
*
|
|
1937
|
+
* That second condition is deliberately narrow. Chain membership alone is too weak: a
|
|
1938
|
+
* fallback target is only *contingently* the server, so an agent that switches `provider` to
|
|
1939
|
+
* a model whose own chain happens to contain the old producer would replay foreign
|
|
1940
|
+
* signatures to whichever model actually answers. Requiring the requested model to be
|
|
1941
|
+
* unchanged separates "this conversation is still going" from "we are somewhere else now".
|
|
1942
|
+
*
|
|
1943
|
+
* State captured before `requestedModel` existed falls back to condition 1 alone, which is
|
|
1944
|
+
* the conservative branch — it can drop reasoning, never misdirect it.
|
|
1945
|
+
*
|
|
1946
|
+
* Boundaries themselves are always echoed: keeping them in place is the documented rule, and
|
|
1947
|
+
* with no thinking blocks around them they are inert rather than harmful.
|
|
1948
|
+
*/
|
|
1949
|
+
reasoningToReplay(firstCall, reachableModels) {
|
|
1950
|
+
var _a, _b, _c;
|
|
1951
|
+
const state = (_a = firstCall.providerMetadata) === null || _a === void 0 ? void 0 : _a[ANTHROPIC_PROVIDER_KEY];
|
|
1952
|
+
if (!state)
|
|
1953
|
+
return [];
|
|
1954
|
+
const boundaries = (_b = state.fallbacks) !== null && _b !== void 0 ? _b : [];
|
|
1955
|
+
const stickyToProducer = state.requestedModel === this.model && reachableModels.has(state.model);
|
|
1956
|
+
const vouched = state.model === this.model || stickyToProducer;
|
|
1957
|
+
return [...boundaries, ...vouched ? (_c = state.reasoning) !== null && _c !== void 0 ? _c : [] : []];
|
|
1958
|
+
}
|
|
1959
|
+
/**
|
|
1960
|
+
* The model that actually served this response.
|
|
1961
|
+
*
|
|
1962
|
+
* A server-side `fallbacks` chain re-runs a declined request on another model and
|
|
1963
|
+
* names it in the response's top-level `model`. Pricing must follow that, not the
|
|
1964
|
+
* model we asked for: a Fable 5 request served by Opus 4.8 costed at Fable's
|
|
1965
|
+
* $10/$50 instead of $5/$25 doubles that part of the bill.
|
|
1966
|
+
*
|
|
1967
|
+
* An unrecognised model id is NOT priced at a guessed rate — that is precisely how
|
|
1968
|
+
* a consumer ended up billing Haiku at Sonnet rates. It warns and falls back to the
|
|
1969
|
+
* configured model, which is at least a figure someone chose.
|
|
1970
|
+
*/
|
|
1971
|
+
servingModel(response) {
|
|
1972
|
+
const served = response.model;
|
|
1973
|
+
if (!served || served === this.model)
|
|
1974
|
+
return this.model;
|
|
1975
|
+
if (SUPPORTED_ANTHROPIC_MODEL_IDS.includes(served)) {
|
|
1976
|
+
return served;
|
|
1977
|
+
}
|
|
1978
|
+
if (!this.warnedUnknownServingModels.has(served)) {
|
|
1979
|
+
this.warnedUnknownServingModels.add(served);
|
|
1980
|
+
logger.warn(`AnthropicTransport: response was served by "${served}", which is not a known model \u2014 pricing it at the configured "${this.model}" rate instead of guessing. The reported cost for this request may be wrong; add the model to SUPPORTED_ANTHROPIC_MODEL_IDS.`);
|
|
1981
|
+
}
|
|
1982
|
+
return this.model;
|
|
1983
|
+
}
|
|
1984
|
+
/**
|
|
1985
|
+
* Whether a fallback-chain attempt is a refusal that was **not billed**.
|
|
1986
|
+
*
|
|
1987
|
+
* Anthropic does not charge for a refusal that arrives before any output: the token counts
|
|
1988
|
+
* still appear in `usage`, but they are not on the bill. Pricing them anyway turns the
|
|
1989
|
+
* fallback undercount this reducer was written to fix into an overcount — the documented
|
|
1990
|
+
* example declines with `input_tokens: 535, output_tokens: 0`, which is real money at
|
|
1991
|
+
* Fable 5's prompt rate.
|
|
1992
|
+
*
|
|
1993
|
+
* A **mid-output** refusal *is* billed for the input and whatever it streamed, so output
|
|
1994
|
+
* tokens are the discriminator rather than the refusal itself.
|
|
1995
|
+
*
|
|
1996
|
+
* Declined attempts appear as `type: 'message'`; the attempt that served the turn is
|
|
1997
|
+
* `type: 'fallback_message'`. The serving entry is normally billable — except when every
|
|
1998
|
+
* model in the chain declined, where the last entry is both the serving one and a refusal,
|
|
1999
|
+
* which `lastAndRefused` covers.
|
|
2000
|
+
*
|
|
2001
|
+
* Also called for a response with no chain at all, as `isUnbilledRefusal({}, usage, refused)`:
|
|
2002
|
+
* a direct request that was declined has no `iterations` array, and the same rule applies to
|
|
2003
|
+
* it. That is in fact the common case — `iterations` only appears when `fallbacks` was
|
|
2004
|
+
* configured.
|
|
2005
|
+
*/
|
|
2006
|
+
isUnbilledRefusal(attempt, usage, lastAndRefused) {
|
|
2007
|
+
var _a;
|
|
2008
|
+
if (((_a = usage.output_tokens) !== null && _a !== void 0 ? _a : 0) > 0)
|
|
2009
|
+
return false;
|
|
2010
|
+
return attempt.type === "message" || lastAndRefused;
|
|
2011
|
+
}
|
|
2012
|
+
/** Cost one attempt's usage block at `model`'s rates, logging and banking it. */
|
|
2013
|
+
costAttempt(model, usage) {
|
|
2014
|
+
var _a, _b, _c, _d, _e, _f;
|
|
2015
|
+
const cacheRead = (_a = usage.cache_read_input_tokens) !== null && _a !== void 0 ? _a : 0;
|
|
2016
|
+
const breakdown = usage.cache_creation;
|
|
2017
|
+
const cacheCreation1h = (_b = breakdown === null || breakdown === void 0 ? void 0 : breakdown.ephemeral_1h_input_tokens) !== null && _b !== void 0 ? _b : 0;
|
|
2018
|
+
const cacheCreation = (_c = usage.cache_creation_input_tokens) !== null && _c !== void 0 ? _c : breakdown ? ((_d = breakdown.ephemeral_5m_input_tokens) !== null && _d !== void 0 ? _d : 0) + cacheCreation1h : 0;
|
|
2019
|
+
return this.logTokenUsage(model, (_e = usage.input_tokens) !== null && _e !== void 0 ? _e : 0, (_f = usage.output_tokens) !== null && _f !== void 0 ? _f : 0, cacheRead, cacheCreation, cacheCreation1h);
|
|
2020
|
+
}
|
|
1786
2021
|
fromAnthropicResponse(response) {
|
|
1787
|
-
var _a, _b, _c, _d, _e, _f, _g
|
|
2022
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
1788
2023
|
let inputTokens;
|
|
1789
2024
|
let outputTokens;
|
|
1790
2025
|
let cacheReadTokens;
|
|
1791
2026
|
let cacheWriteTokens;
|
|
1792
2027
|
let cost;
|
|
2028
|
+
const servingModel = this.servingModel(response);
|
|
1793
2029
|
if (response.usage) {
|
|
1794
2030
|
const uncachedInput = (_a = response.usage.input_tokens) !== null && _a !== void 0 ? _a : 0;
|
|
1795
2031
|
const cacheRead = (_b = response.usage.cache_read_input_tokens) !== null && _b !== void 0 ? _b : 0;
|
|
1796
2032
|
const breakdown = response.usage.cache_creation;
|
|
1797
2033
|
const cacheCreation1h = (_c = breakdown === null || breakdown === void 0 ? void 0 : breakdown.ephemeral_1h_input_tokens) !== null && _c !== void 0 ? _c : 0;
|
|
1798
2034
|
const cacheCreation = (_d = response.usage.cache_creation_input_tokens) !== null && _d !== void 0 ? _d : breakdown ? ((_e = breakdown.ephemeral_5m_input_tokens) !== null && _e !== void 0 ? _e : 0) + cacheCreation1h : 0;
|
|
1799
|
-
|
|
2035
|
+
const attempts = response.usage.iterations;
|
|
2036
|
+
if (attempts === null || attempts === void 0 ? void 0 : attempts.length) {
|
|
2037
|
+
const refused = response.stop_reason === "refusal";
|
|
2038
|
+
cost = attempts.reduce((total, attempt, index) => {
|
|
2039
|
+
var _a2;
|
|
2040
|
+
const usage = (_a2 = attempt.usage) !== null && _a2 !== void 0 ? _a2 : attempt;
|
|
2041
|
+
if (this.isUnbilledRefusal(attempt, usage, index === attempts.length - 1 && refused)) {
|
|
2042
|
+
return total;
|
|
2043
|
+
}
|
|
2044
|
+
const model = attempt.model ? this.servingModel({ model: attempt.model }) : this.model;
|
|
2045
|
+
return total + this.costAttempt(model, usage);
|
|
2046
|
+
}, 0);
|
|
2047
|
+
} else if (this.isUnbilledRefusal({}, response.usage, response.stop_reason === "refusal")) {
|
|
2048
|
+
cost = 0;
|
|
2049
|
+
} else {
|
|
2050
|
+
cost = this.costAttempt(servingModel, response.usage);
|
|
2051
|
+
}
|
|
1800
2052
|
inputTokens = uncachedInput + cacheRead + cacheCreation;
|
|
1801
2053
|
cacheReadTokens = cacheRead;
|
|
1802
2054
|
cacheWriteTokens = cacheCreation;
|
|
@@ -1804,23 +2056,44 @@ ${att.content}` });
|
|
|
1804
2056
|
outputTokens = response.usage.output_tokens;
|
|
1805
2057
|
}
|
|
1806
2058
|
}
|
|
1807
|
-
const blocks = (
|
|
2059
|
+
const blocks = (_f = response.content) !== null && _f !== void 0 ? _f : [];
|
|
1808
2060
|
const toolCalls = [];
|
|
1809
2061
|
const thoughtParts = [];
|
|
1810
2062
|
const textParts = [];
|
|
1811
|
-
|
|
2063
|
+
const reasoningBlocks = [];
|
|
2064
|
+
const fallbackIndex = blocks.map((b) => b.type).lastIndexOf("fallback");
|
|
2065
|
+
const fallbackBlocks = blocks.filter((b) => b.type === "fallback");
|
|
2066
|
+
for (const [index, block] of blocks.entries()) {
|
|
2067
|
+
const postBoundary = index > fallbackIndex;
|
|
1812
2068
|
if (block.type === "tool_use") {
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
2069
|
+
if (postBoundary) {
|
|
2070
|
+
toolCalls.push({
|
|
2071
|
+
id: block.id,
|
|
2072
|
+
name: block.name,
|
|
2073
|
+
args: (_g = block.input) !== null && _g !== void 0 ? _g : {}
|
|
2074
|
+
});
|
|
2075
|
+
}
|
|
1818
2076
|
} else if (block.type === "thinking") {
|
|
2077
|
+
if (postBoundary)
|
|
2078
|
+
reasoningBlocks.push(block);
|
|
1819
2079
|
thoughtParts.push(block.thinking);
|
|
2080
|
+
} else if (block.type === "redacted_thinking") {
|
|
2081
|
+
if (postBoundary)
|
|
2082
|
+
reasoningBlocks.push(block);
|
|
1820
2083
|
} else if (block.type === "text") {
|
|
1821
2084
|
textParts.push(block.text);
|
|
1822
2085
|
}
|
|
1823
2086
|
}
|
|
2087
|
+
if (toolCalls.length > 0 && (reasoningBlocks.length > 0 || fallbackBlocks.length > 0)) {
|
|
2088
|
+
const state = {
|
|
2089
|
+
reasoning: reasoningBlocks,
|
|
2090
|
+
model: servingModel,
|
|
2091
|
+
requestedModel: this.model
|
|
2092
|
+
};
|
|
2093
|
+
if (fallbackBlocks.length > 0)
|
|
2094
|
+
state.fallbacks = fallbackBlocks;
|
|
2095
|
+
toolCalls[0].providerMetadata = Object.assign(Object.assign({}, toolCalls[0].providerMetadata), { [ANTHROPIC_PROVIDER_KEY]: state });
|
|
2096
|
+
}
|
|
1824
2097
|
if (response.stop_reason === "max_tokens" && toolCalls.length > 0) {
|
|
1825
2098
|
throw new ResponseTruncatedError(this.model, this.maxTokens, outputTokens, toolCalls.map((tc) => tc.name));
|
|
1826
2099
|
}
|
|
@@ -1836,6 +2109,7 @@ ${att.content}` });
|
|
|
1836
2109
|
base.cacheWriteTokens = cacheWriteTokens;
|
|
1837
2110
|
if (cost != null)
|
|
1838
2111
|
base.cost = cost;
|
|
2112
|
+
base.model = servingModel;
|
|
1839
2113
|
if (response.stop_reason === "max_tokens") {
|
|
1840
2114
|
base.responseMeta = { finishReason: "max_tokens" };
|
|
1841
2115
|
}
|
|
@@ -2137,43 +2411,25 @@ function assertSupportedGeminiModel(model) {
|
|
|
2137
2411
|
throw new Error(`GeminiTransport: unsupported model "${model}". Use one of: ${SUPPORTED_GEMINI_MODEL_IDS.join(", ")}.`);
|
|
2138
2412
|
}
|
|
2139
2413
|
}
|
|
2140
|
-
var GEMINI_LONG_CONTEXT_THRESHOLD = 2e5;
|
|
2141
|
-
var GEMINI_CACHED_INPUT_MULTIPLIER = 0.1;
|
|
2142
|
-
var GEMINI_PRICING = {
|
|
2143
|
-
"gemini-2.5-flash-lite": {
|
|
2144
|
-
kind: "flat",
|
|
2145
|
-
rate: { promptPerMillion: 0.1, candidatePerMillion: 0.4 }
|
|
2146
|
-
},
|
|
2147
|
-
"gemini-2.5-flash": { kind: "flat", rate: { promptPerMillion: 0.3, candidatePerMillion: 2.5 } },
|
|
2148
|
-
"gemini-2.5-pro": {
|
|
2149
|
-
kind: "tiered",
|
|
2150
|
-
standard: { promptPerMillion: 1.25, candidatePerMillion: 10 },
|
|
2151
|
-
longContext: { promptPerMillion: 2.5, candidatePerMillion: 15 }
|
|
2152
|
-
},
|
|
2153
|
-
"gemini-3.1-flash-lite": {
|
|
2154
|
-
kind: "flat",
|
|
2155
|
-
rate: { promptPerMillion: 0.25, candidatePerMillion: 1.5 }
|
|
2156
|
-
},
|
|
2157
|
-
"gemini-3.5-flash": { kind: "flat", rate: { promptPerMillion: 1.5, candidatePerMillion: 9 } },
|
|
2158
|
-
"gemini-3.1-pro-preview": {
|
|
2159
|
-
kind: "tiered",
|
|
2160
|
-
standard: { promptPerMillion: 2, candidatePerMillion: 12 },
|
|
2161
|
-
longContext: { promptPerMillion: 4, candidatePerMillion: 18 }
|
|
2162
|
-
}
|
|
2163
|
-
};
|
|
2164
|
-
function estimatedGeminiPaidRatesUsdPerMillion(model, promptTokens) {
|
|
2165
|
-
const pricing = GEMINI_PRICING[model];
|
|
2166
|
-
if (pricing.kind === "flat") {
|
|
2167
|
-
return pricing.rate;
|
|
2168
|
-
}
|
|
2169
|
-
return promptTokens > GEMINI_LONG_CONTEXT_THRESHOLD ? pricing.longContext : pricing.standard;
|
|
2170
|
-
}
|
|
2171
2414
|
var GEMINI_MODEL_WARNINGS = {
|
|
2172
2415
|
"gemini-2.5-flash": "GeminiTransport: using gemini-2.5-flash \u2014 higher cost than flash-lite; use for harder reasoning or agent tasks.",
|
|
2173
2416
|
"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.",
|
|
2174
2417
|
"gemini-3.5-flash": "GeminiTransport: using gemini-3.5-flash \u2014 frontier model, materially higher cost than flash-lite; use for harder reasoning or agent tasks.",
|
|
2175
2418
|
"gemini-3.1-pro-preview": "GeminiTransport: using gemini-3.1-pro-preview \u2014 PREVIEW model (no stability guarantee, may be withdrawn) with significantly higher, prompt-size-tiered cost; reserve for tasks where flash reliability is insufficient."
|
|
2176
2419
|
};
|
|
2420
|
+
var GEMINI_THINKING_DISABLEABLE = [
|
|
2421
|
+
"gemini-2.5-flash",
|
|
2422
|
+
"gemini-2.5-flash-lite"
|
|
2423
|
+
];
|
|
2424
|
+
function geminiThinkingConfig(model, policy) {
|
|
2425
|
+
if (policy === "off" && GEMINI_THINKING_DISABLEABLE.includes(model)) {
|
|
2426
|
+
return { includeThoughts: false, thinkingBudget: 0 };
|
|
2427
|
+
}
|
|
2428
|
+
if (policy === "auto" && GEMINI_THINKING_DISABLEABLE.includes(model)) {
|
|
2429
|
+
return { includeThoughts: true, thinkingBudget: -1 };
|
|
2430
|
+
}
|
|
2431
|
+
return { includeThoughts: true };
|
|
2432
|
+
}
|
|
2177
2433
|
var SKIP_SIGNATURE = "skip_thought_signature_validator";
|
|
2178
2434
|
var GEMINI_PROVIDER_KEY = "gemini";
|
|
2179
2435
|
var MalformedFunctionCallError = class extends Error {
|
|
@@ -2184,10 +2440,28 @@ var MalformedFunctionCallError = class extends Error {
|
|
|
2184
2440
|
}
|
|
2185
2441
|
};
|
|
2186
2442
|
var GeminiTransport = class _GeminiTransport {
|
|
2443
|
+
/**
|
|
2444
|
+
* Warn once when a requested policy is silently clamped. Turning thinking off is a *cost*
|
|
2445
|
+
* decision, so a caller who asked for it and kept paying for reasoning tokens needs to hear
|
|
2446
|
+
* about it — but only once, not per turn.
|
|
2447
|
+
*
|
|
2448
|
+
* Only `'off'` can actually be denied. `'auto'` is already what an omitted budget produces on
|
|
2449
|
+
* every model here — dynamic thinking is the documented default — so warning that it was
|
|
2450
|
+
* "ignored" would be false, and latching on it would spend the one warning the genuinely
|
|
2451
|
+
* unhonourable `'off'` needs.
|
|
2452
|
+
*/
|
|
2453
|
+
warnIfThinkingUnclampable(policy) {
|
|
2454
|
+
if (policy !== "off" || GEMINI_THINKING_DISABLEABLE.includes(this.model) || this.warnedThinkingClamped) {
|
|
2455
|
+
return;
|
|
2456
|
+
}
|
|
2457
|
+
this.warnedThinkingClamped = true;
|
|
2458
|
+
logger.warn(`GeminiTransport: thinkingPolicy 'off' ignored \u2014 ${this.model} runs its default thinking posture and takes no budget we can safely set. Reasoning tokens are still billed at the candidate rate; use a flash tier if you need them gone.`);
|
|
2459
|
+
}
|
|
2187
2460
|
constructor(config = {}) {
|
|
2188
2461
|
var _a, _b, _c;
|
|
2189
2462
|
this.lifetimeCostUsd = 0;
|
|
2190
2463
|
this.lifetimeSavingsUsd = 0;
|
|
2464
|
+
this.warnedThinkingClamped = false;
|
|
2191
2465
|
const model = (_a = config.model) !== null && _a !== void 0 ? _a : DEFAULT_MODEL2;
|
|
2192
2466
|
assertSupportedGeminiModel(model);
|
|
2193
2467
|
this.model = model;
|
|
@@ -2254,7 +2528,8 @@ var GeminiTransport = class _GeminiTransport {
|
|
|
2254
2528
|
] : void 0;
|
|
2255
2529
|
const systemInstruction = (options === null || options === void 0 ? void 0 : options.systemPrompt) ? { role: "system", parts: [{ text: options.systemPrompt }] } : void 0;
|
|
2256
2530
|
const toolConfig = tools ? toGeminiToolConfig(options === null || options === void 0 ? void 0 : options.toolChoice) : void 0;
|
|
2257
|
-
|
|
2531
|
+
this.warnIfThinkingUnclampable(options === null || options === void 0 ? void 0 : options.thinkingPolicy);
|
|
2532
|
+
const generationConfig = { thinkingConfig: geminiThinkingConfig(this.model, options === null || options === void 0 ? void 0 : options.thinkingPolicy) };
|
|
2258
2533
|
if ((options === null || options === void 0 ? void 0 : options.temperature) != null) {
|
|
2259
2534
|
generationConfig.temperature = scaleTemperature(options.temperature, {
|
|
2260
2535
|
defaultTemp: GEMINI_DEFAULT_TEMPERATURE,
|
|
@@ -2281,25 +2556,23 @@ var GeminiTransport = class _GeminiTransport {
|
|
|
2281
2556
|
* message.
|
|
2282
2557
|
*/
|
|
2283
2558
|
logTokenUsage(promptTokens, candidateTokens, thoughtTokens, cachedTokens) {
|
|
2284
|
-
const {
|
|
2285
|
-
|
|
2286
|
-
|
|
2287
|
-
|
|
2288
|
-
|
|
2289
|
-
|
|
2290
|
-
|
|
2291
|
-
this.
|
|
2292
|
-
const saved = cachedTokens / m * promptPerMillion - cacheReadCost;
|
|
2293
|
-
this.lifetimeSavingsUsd += saved;
|
|
2559
|
+
const { costUsd, savedUsd, breakdown } = geminiTokenCost(this.model, {
|
|
2560
|
+
promptTokens,
|
|
2561
|
+
candidateTokens,
|
|
2562
|
+
thoughtTokens,
|
|
2563
|
+
cachedTokens
|
|
2564
|
+
});
|
|
2565
|
+
this.lifetimeCostUsd += costUsd;
|
|
2566
|
+
this.lifetimeSavingsUsd += savedUsd;
|
|
2294
2567
|
const dp = _GeminiTransport.COST_DECIMAL_PLACES;
|
|
2295
2568
|
console.log(`--- Gemini Token Usage (${this.model}) ---`);
|
|
2296
|
-
console.log(`Prompt Tokens: ${promptTokens} (${cachedTokens} cached) ($${
|
|
2297
|
-
console.log(`Candidate Tokens: ${candidateTokens} (+${thoughtTokens} thinking) ($${
|
|
2298
|
-
console.log(`Total Cost: $${
|
|
2299
|
-
console.log(`Cache Saved: $${
|
|
2569
|
+
console.log(`Prompt Tokens: ${promptTokens} (${cachedTokens} cached) ($${breakdown.promptUsd.toFixed(dp)} + $${breakdown.cacheReadUsd.toFixed(dp)})`);
|
|
2570
|
+
console.log(`Candidate Tokens: ${candidateTokens} (+${thoughtTokens} thinking) ($${breakdown.candidateUsd.toFixed(dp)})`);
|
|
2571
|
+
console.log(`Total Cost: $${costUsd.toFixed(dp)}`);
|
|
2572
|
+
console.log(`Cache Saved: $${savedUsd.toFixed(dp)} (lifetime $${this.lifetimeSavingsUsd.toFixed(dp)})`);
|
|
2300
2573
|
console.log(`Lifetime Cost: $${this.lifetimeCostUsd.toFixed(dp)}`);
|
|
2301
2574
|
console.log("--------------------------");
|
|
2302
|
-
return
|
|
2575
|
+
return costUsd;
|
|
2303
2576
|
}
|
|
2304
2577
|
toGeminiContents(history, userMessage, attachments) {
|
|
2305
2578
|
var _a, _b, _c;
|
|
@@ -3270,6 +3543,18 @@ function emptyUsage() {
|
|
|
3270
3543
|
outputTokens: 0
|
|
3271
3544
|
};
|
|
3272
3545
|
}
|
|
3546
|
+
function totalTokens(usage) {
|
|
3547
|
+
return usage.uncachedInputTokens + usage.cacheReadTokens + usage.cacheWriteTokens + usage.outputTokens;
|
|
3548
|
+
}
|
|
3549
|
+
function addUsage(a, b) {
|
|
3550
|
+
return {
|
|
3551
|
+
costUsd: a.costUsd + b.costUsd,
|
|
3552
|
+
uncachedInputTokens: a.uncachedInputTokens + b.uncachedInputTokens,
|
|
3553
|
+
cacheReadTokens: a.cacheReadTokens + b.cacheReadTokens,
|
|
3554
|
+
cacheWriteTokens: a.cacheWriteTokens + b.cacheWriteTokens,
|
|
3555
|
+
outputTokens: a.outputTokens + b.outputTokens
|
|
3556
|
+
};
|
|
3557
|
+
}
|
|
3273
3558
|
function sumUsage(messages) {
|
|
3274
3559
|
const total = emptyUsage();
|
|
3275
3560
|
accumulate(messages, total);
|
|
@@ -3758,6 +4043,7 @@ var ChatDriver = class _ChatDriver extends EventTarget {
|
|
|
3758
4043
|
this.activeTemperatureInput = config.temperature;
|
|
3759
4044
|
this.activeToolChoiceInput = config.toolChoice;
|
|
3760
4045
|
this.activeCachePolicyInput = config.cachePolicy;
|
|
4046
|
+
this.activeThinkingPolicyInput = config.thinkingPolicy;
|
|
3761
4047
|
this.activeTailContextInput = config.tailContext;
|
|
3762
4048
|
this.activeResponseSchemaInput = config.responseSchema;
|
|
3763
4049
|
this.activeFallbacks = config.fallbacks;
|
|
@@ -4412,16 +4698,27 @@ Output format (strict):
|
|
|
4412
4698
|
* `condenseWhen` can register against the right call (it stamps the clocks
|
|
4413
4699
|
* straight off the driver). Absent for dispatch paths with no addressable tool
|
|
4414
4700
|
* call (e.g. the fold-close handler), where `condenseWhen` is a no-op.
|
|
4415
|
-
* @param traceCapture - Optional per-
|
|
4416
|
-
*
|
|
4417
|
-
* so parallel tool calls each capture their own
|
|
4701
|
+
* @param traceCapture - Optional per-tool-call accumulator. When provided, every
|
|
4702
|
+
* sub-agent call's trace is **appended** here rather than written to shared
|
|
4703
|
+
* instance state, so parallel tool calls each capture their own traces
|
|
4704
|
+
* independently.
|
|
4705
|
+
*
|
|
4706
|
+
* Deliberately a list of traces, not one slot. A single handler may call
|
|
4707
|
+
* `requestSubAgent` more than once — a code-driven scheduler dispatching a
|
|
4708
|
+
* dependency graph, a retry of a timed-out child, any fan-out helper — and a
|
|
4709
|
+
* single slot kept only the last, so every other child ran, was billed by the
|
|
4710
|
+
* provider, and then vanished from history. The loss was silent in the worst
|
|
4711
|
+
* way: `sumUsage` and `usageRows` both recurse into the trace, so they summed a
|
|
4712
|
+
* truncated input and still agreed with each other. Measured at 1 of 7 traces
|
|
4713
|
+
* kept on a seven-way fan-out, reporting ~2.3x under the real cost, with the
|
|
4714
|
+
* error growing as the fan-out widens.
|
|
4418
4715
|
*/
|
|
4419
4716
|
buildHandlerContext(activeToolCallId, traceCapture) {
|
|
4420
4717
|
return {
|
|
4421
4718
|
requestInteraction: (componentName, data, options) => this.requestInteraction(componentName, data, options),
|
|
4422
4719
|
...this.subAgentsMap.size > 0 && {
|
|
4423
4720
|
requestSubAgent: (name, options) => this.invokeSubAgent(name, options).then(({ outcome, trace }) => {
|
|
4424
|
-
if (traceCapture) traceCapture.trace
|
|
4721
|
+
if (traceCapture && trace) traceCapture.traces.push(trace);
|
|
4425
4722
|
return outcome;
|
|
4426
4723
|
})
|
|
4427
4724
|
},
|
|
@@ -4795,6 +5092,8 @@ Output format (strict):
|
|
|
4795
5092
|
let emptyResponseAttempts = 0;
|
|
4796
5093
|
let setupTransportAttempts = 0;
|
|
4797
5094
|
let firstLlmCall = !!currentInput;
|
|
5095
|
+
let pinnedThinkingPolicy;
|
|
5096
|
+
let thinkingPolicyPinned = false;
|
|
4798
5097
|
while (iterations < this.maxToolIterations) {
|
|
4799
5098
|
iterations += 1;
|
|
4800
5099
|
this.modelCallSeq += 1;
|
|
@@ -4894,7 +5193,8 @@ Output format (strict):
|
|
|
4894
5193
|
resolvedToolChoice,
|
|
4895
5194
|
resolvedCachePolicy,
|
|
4896
5195
|
resolvedTailContext,
|
|
4897
|
-
resolvedResponseSchema
|
|
5196
|
+
resolvedResponseSchema,
|
|
5197
|
+
firstResolvedThinkingPolicy
|
|
4898
5198
|
] = (
|
|
4899
5199
|
// oxlint-disable-next-line no-await-in-loop
|
|
4900
5200
|
await Promise.all([
|
|
@@ -4902,9 +5202,19 @@ Output format (strict):
|
|
|
4902
5202
|
this.resolveTurnInput(this.activeToolChoiceInput, promptCtx),
|
|
4903
5203
|
this.resolveTurnInput(this.activeCachePolicyInput, promptCtx),
|
|
4904
5204
|
this.resolveTurnInput(this.activeTailContextInput, promptCtx),
|
|
4905
|
-
this.resolveTurnInput(this.activeResponseSchemaInput, promptCtx)
|
|
5205
|
+
this.resolveTurnInput(this.activeResponseSchemaInput, promptCtx),
|
|
5206
|
+
// Only consulted on the first iteration (see `pinnedThinkingPolicy`); resolved
|
|
5207
|
+
// alongside the others so a resolver still sees the same turn context.
|
|
5208
|
+
thinkingPolicyPinned ? Promise.resolve(void 0) : this.resolveTurnInput(
|
|
5209
|
+
this.activeThinkingPolicyInput,
|
|
5210
|
+
promptCtx
|
|
5211
|
+
)
|
|
4906
5212
|
])
|
|
4907
5213
|
);
|
|
5214
|
+
if (!thinkingPolicyPinned) {
|
|
5215
|
+
pinnedThinkingPolicy = firstResolvedThinkingPolicy;
|
|
5216
|
+
thinkingPolicyPinned = true;
|
|
5217
|
+
}
|
|
4908
5218
|
const systemPrompt = resolvedSystemPrompt || void 0;
|
|
4909
5219
|
const tailBody = [resolvedTailContext, frameworkSystemSuffix].map((part) => (part ?? "").trim()).filter((part) => part.length > 0).join("\n\n");
|
|
4910
5220
|
const tailContext = tailBody ? `<system-reminder>
|
|
@@ -4931,6 +5241,12 @@ ${tailBody}
|
|
|
4931
5241
|
// Prompt-cache policy for this turn (Anthropic places breakpoints per scope; Gemini
|
|
4932
5242
|
// caches implicitly regardless). Undefined → no caching requested.
|
|
4933
5243
|
cachePolicy: resolvedCachePolicy,
|
|
5244
|
+
// Extended-thinking posture, pinned for the whole tool loop (one assistant turn) rather
|
|
5245
|
+
// than re-resolved per iteration — see `pinnedThinkingPolicy`. Undefined — unset, or the
|
|
5246
|
+
// resolver's answer for this turn — is NOT "off": it leaves the model on its own default,
|
|
5247
|
+
// so agents that never set this are priced exactly as before. Transports clamp models
|
|
5248
|
+
// that can't honour it.
|
|
5249
|
+
thinkingPolicy: pinnedThinkingPolicy,
|
|
4934
5250
|
// Framed volatile context injected at the message tail (never stored). Undefined → none.
|
|
4935
5251
|
tailContext,
|
|
4936
5252
|
// Structured-output schema for this turn (agent/state-resolved). When set, the transport
|
|
@@ -5051,7 +5367,9 @@ ${tailBody}
|
|
|
5051
5367
|
}
|
|
5052
5368
|
throw e;
|
|
5053
5369
|
}
|
|
5054
|
-
if (this.lastResolvedModel !== void 0)
|
|
5370
|
+
if (response.model === void 0 && this.lastResolvedModel !== void 0) {
|
|
5371
|
+
response.model = this.lastResolvedModel;
|
|
5372
|
+
}
|
|
5055
5373
|
if (this.lastResolvedProvider !== void 0) response.provider = this.lastResolvedProvider;
|
|
5056
5374
|
if (this.lastResolvedProviderName !== void 0) {
|
|
5057
5375
|
response.providerName = this.lastResolvedProviderName;
|
|
@@ -5259,14 +5577,18 @@ ${tailBody}
|
|
|
5259
5577
|
}
|
|
5260
5578
|
return;
|
|
5261
5579
|
}
|
|
5580
|
+
const traceCapture = { traces: [] };
|
|
5581
|
+
const capturedTrace = () => traceCapture.traces.length ? traceCapture.traces.flat() : void 0;
|
|
5262
5582
|
try {
|
|
5263
|
-
const traceCapture = {};
|
|
5264
5583
|
const result = await handler(tc.args, this.buildHandlerContext(tc.id, traceCapture));
|
|
5265
5584
|
const content = typeof result === "string" ? result : JSON.stringify(result);
|
|
5266
5585
|
executedById.set(tc.id, {
|
|
5267
5586
|
toolCallId: tc.id,
|
|
5268
5587
|
content,
|
|
5269
|
-
|
|
5588
|
+
// Concatenated when a handler invoked several children, so none is lost.
|
|
5589
|
+
// Stays `undefined` when nothing was captured — readers key off presence,
|
|
5590
|
+
// and an empty array is a different claim from "no sub-agent ran".
|
|
5591
|
+
subAgentTrace: capturedTrace()
|
|
5270
5592
|
});
|
|
5271
5593
|
anyRealToolExecuted = true;
|
|
5272
5594
|
} catch (e) {
|
|
@@ -5281,7 +5603,10 @@ ${tailBody}
|
|
|
5281
5603
|
// Structured recovery hint so the model retries or routes around a tool
|
|
5282
5604
|
// failure instead of apologising and giving up.
|
|
5283
5605
|
content: `Tool error: ${e.message}
|
|
5284
|
-
RECOVERY: this tool failed once \u2014 you may retry it, or take a different valid action to make progress. Do NOT abandon the task, ask the user to rephrase, or claim you cannot make changes. If a planning tool failed, retry it or proceed with the information you already have
|
|
5606
|
+
RECOVERY: this tool failed once \u2014 you may retry it, or take a different valid action to make progress. Do NOT abandon the task, ask the user to rephrase, or claim you cannot make changes. If a planning tool failed, retry it or proceed with the information you already have.`,
|
|
5607
|
+
// Children that completed before the throw were still billed — keep
|
|
5608
|
+
// their traces so the run's cost stays whole.
|
|
5609
|
+
subAgentTrace: capturedTrace()
|
|
5285
5610
|
});
|
|
5286
5611
|
anyRealToolExecuted = true;
|
|
5287
5612
|
}
|
|
@@ -6073,6 +6398,10 @@ function defineStatefulAgent(opts) {
|
|
|
6073
6398
|
}
|
|
6074
6399
|
return opts.cachePolicy({ ...ctx, state });
|
|
6075
6400
|
} : opts.cachePolicy;
|
|
6401
|
+
const wrappedThinkingPolicy = typeof opts.thinkingPolicy === "function" ? async (ctx) => {
|
|
6402
|
+
if (!state) return void 0;
|
|
6403
|
+
return opts.thinkingPolicy({ ...ctx, state });
|
|
6404
|
+
} : opts.thinkingPolicy;
|
|
6076
6405
|
const wrappedTailContext = typeof opts.tailContext === "function" ? async (ctx) => {
|
|
6077
6406
|
if (!state) {
|
|
6078
6407
|
throw new Error(`Stateful agent "${opts.name}" tailContext called before init`);
|
|
@@ -6111,6 +6440,7 @@ function defineStatefulAgent(opts) {
|
|
|
6111
6440
|
temperature: wrappedTemperature,
|
|
6112
6441
|
toolChoice: wrappedToolChoice,
|
|
6113
6442
|
cachePolicy: wrappedCachePolicy,
|
|
6443
|
+
thinkingPolicy: wrappedThinkingPolicy,
|
|
6114
6444
|
tailContext: wrappedTailContext,
|
|
6115
6445
|
onUnresolvedTool: wrappedOnUnresolvedTool,
|
|
6116
6446
|
resumable: wrappedResumable,
|
|
@@ -6172,6 +6502,69 @@ var strictFallbackAgent = {
|
|
|
6172
6502
|
systemPrompt: `You are a concise assistant. The user's request is outside your scope. Respond with a single short sentence stating what you can assist with. Do not elaborate. The available specialists are: {{agents}}.`
|
|
6173
6503
|
};
|
|
6174
6504
|
|
|
6505
|
+
// src/utils/usage-rows.ts
|
|
6506
|
+
function hasUsage(m) {
|
|
6507
|
+
return m.cost != null || m.externalCostUsd != null || m.inputTokens != null || m.outputTokens != null || m.cacheReadTokens != null || m.cacheWriteTokens != null;
|
|
6508
|
+
}
|
|
6509
|
+
function usageRows(messages) {
|
|
6510
|
+
return collectRows(messages, 0, void 0);
|
|
6511
|
+
}
|
|
6512
|
+
function bucketsOf(usage) {
|
|
6513
|
+
return {
|
|
6514
|
+
uncachedInputTokens: usage.uncachedInputTokens,
|
|
6515
|
+
cacheReadTokens: usage.cacheReadTokens,
|
|
6516
|
+
cacheWriteTokens: usage.cacheWriteTokens,
|
|
6517
|
+
outputTokens: usage.outputTokens
|
|
6518
|
+
};
|
|
6519
|
+
}
|
|
6520
|
+
function collectRows(messages, depth, subAgentOf) {
|
|
6521
|
+
const rows = [];
|
|
6522
|
+
for (const m of messages) {
|
|
6523
|
+
if (hasUsage(m)) {
|
|
6524
|
+
const cacheReadTokens = m.cacheReadTokens ?? 0;
|
|
6525
|
+
const cacheWriteTokens = m.cacheWriteTokens ?? 0;
|
|
6526
|
+
rows.push({
|
|
6527
|
+
source: "request",
|
|
6528
|
+
model: m.model,
|
|
6529
|
+
// The driver stamps `ChatMessage.provider` from the resolved provider's own
|
|
6530
|
+
// status, so it is AUTHORITATIVE and covers vendors the model allowlists do
|
|
6531
|
+
// not — a server-proxied `gpt-5` turn is `provider: 'openai'` on the message
|
|
6532
|
+
// and unknown to `vendorOfModel`. Prefer it; fall back to resolving the model
|
|
6533
|
+
// id only for messages persisted before the field existed. Still left
|
|
6534
|
+
// undefined when neither knows, rather than guessed at.
|
|
6535
|
+
provider: m.provider ?? (m.model ? vendorOfModel(m.model) : void 0),
|
|
6536
|
+
...m.cost != null && { costUsd: m.cost },
|
|
6537
|
+
...m.externalCostUsd != null && { externalCostUsd: m.externalCostUsd },
|
|
6538
|
+
// Uncached input is the REMAINDER, matching `sumUsage`: `inputTokens` is the
|
|
6539
|
+
// whole prompt and the cache fields break it down. Clamped for the same
|
|
6540
|
+
// reason — hand-edited history must not drive a total negative.
|
|
6541
|
+
uncachedInputTokens: Math.max(0, (m.inputTokens ?? 0) - cacheReadTokens - cacheWriteTokens),
|
|
6542
|
+
cacheReadTokens,
|
|
6543
|
+
cacheWriteTokens,
|
|
6544
|
+
outputTokens: m.outputTokens ?? 0,
|
|
6545
|
+
...m.agentName != null && { agentName: m.agentName },
|
|
6546
|
+
subAgentDepth: depth,
|
|
6547
|
+
...subAgentOf != null && { subAgentOf }
|
|
6548
|
+
});
|
|
6549
|
+
}
|
|
6550
|
+
const rolled = m.compaction?.rolledUpUsage;
|
|
6551
|
+
if (rolled) {
|
|
6552
|
+
rows.push({
|
|
6553
|
+
source: "compaction",
|
|
6554
|
+
...rolled.costUsd != null && { costUsd: rolled.costUsd },
|
|
6555
|
+
...bucketsOf(rolled),
|
|
6556
|
+
...m.agentName != null && { agentName: m.agentName },
|
|
6557
|
+
subAgentDepth: depth,
|
|
6558
|
+
...subAgentOf != null && { subAgentOf }
|
|
6559
|
+
});
|
|
6560
|
+
}
|
|
6561
|
+
for (const tc of m.toolCalls ?? []) {
|
|
6562
|
+
if (tc.subAgentTrace) rows.push(...collectRows(tc.subAgentTrace, depth + 1, tc.id));
|
|
6563
|
+
}
|
|
6564
|
+
}
|
|
6565
|
+
return rows;
|
|
6566
|
+
}
|
|
6567
|
+
|
|
6175
6568
|
// src/utils/flatten-sub-agent-messages.ts
|
|
6176
6569
|
function flattenSubAgentMessages(messages, prefix = "", depth = 0, subAgentOf) {
|
|
6177
6570
|
return messages.flatMap((m) => {
|
|
@@ -6252,10 +6645,15 @@ function assembleDebugLog(entries, readme) {
|
|
|
6252
6645
|
return { readme, timeline, meta: latestMeta?.meta };
|
|
6253
6646
|
}
|
|
6254
6647
|
export {
|
|
6648
|
+
ANTHROPIC_CACHE_READ_MULTIPLIER,
|
|
6649
|
+
ANTHROPIC_CACHE_WRITE_1H_MULTIPLIER,
|
|
6650
|
+
ANTHROPIC_CACHE_WRITE_5M_MULTIPLIER,
|
|
6255
6651
|
AgenticActivityBus,
|
|
6256
6652
|
AnthropicProvider,
|
|
6257
6653
|
AnthropicTransport,
|
|
6258
6654
|
ChatDriver,
|
|
6655
|
+
GEMINI_CACHED_INPUT_MULTIPLIER,
|
|
6656
|
+
GEMINI_LONG_CONTEXT_THRESHOLD,
|
|
6259
6657
|
GeminiProvider,
|
|
6260
6658
|
GeminiTransport,
|
|
6261
6659
|
MutableAIProviderRegistry,
|
|
@@ -6264,16 +6662,26 @@ export {
|
|
|
6264
6662
|
REQUEST_CONTINUATION_TOOL,
|
|
6265
6663
|
SUPPORTED_ANTHROPIC_MODEL_IDS,
|
|
6266
6664
|
SUPPORTED_GEMINI_MODEL_IDS,
|
|
6665
|
+
addUsage,
|
|
6267
6666
|
agenticActivityBus,
|
|
6667
|
+
anthropicRatesFor,
|
|
6668
|
+
anthropicTokenCost,
|
|
6268
6669
|
assembleDebugLog,
|
|
6269
6670
|
buildTimelineEntries,
|
|
6270
6671
|
clearSession,
|
|
6271
6672
|
defineAgent,
|
|
6272
6673
|
defineStatefulAgent,
|
|
6674
|
+
emptyUsage,
|
|
6273
6675
|
friendlyFallbackAgent,
|
|
6676
|
+
geminiRatesFor,
|
|
6677
|
+
geminiTokenCost,
|
|
6274
6678
|
getMetaEvents,
|
|
6275
6679
|
isObservableAIProviderRegistry,
|
|
6276
6680
|
restoreMachine,
|
|
6277
|
-
strictFallbackAgent
|
|
6681
|
+
strictFallbackAgent,
|
|
6682
|
+
sumUsage,
|
|
6683
|
+
totalTokens,
|
|
6684
|
+
usageRows,
|
|
6685
|
+
vendorOfModel
|
|
6278
6686
|
};
|
|
6279
6687
|
//# sourceMappingURL=chat-driver.mjs.map
|