@hiper2d/ai-agents 0.2.0 → 0.3.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/README.md +22 -0
- package/dist/index.d.mts +154 -1
- package/dist/index.d.ts +154 -1
- package/dist/index.js +198 -18
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +188 -18
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -35,6 +35,8 @@ __export(index_exports, {
|
|
|
35
35
|
AbstractAgent: () => AbstractAgent,
|
|
36
36
|
AgentFactory: () => AgentFactory,
|
|
37
37
|
BotResponseError: () => BotResponseError,
|
|
38
|
+
BudgetController: () => BudgetController,
|
|
39
|
+
BudgetExceededError: () => BudgetExceededError,
|
|
38
40
|
CACHE_TIER_MARKER: () => CACHE_TIER_MARKER,
|
|
39
41
|
ClaudeAgent: () => ClaudeAgent,
|
|
40
42
|
DEEPSEEK_PEAK_SCHEDULE: () => DEEPSEEK_PEAK_SCHEDULE,
|
|
@@ -52,6 +54,7 @@ __export(index_exports, {
|
|
|
52
54
|
GoogleVoiceAgent: () => GoogleVoiceAgent,
|
|
53
55
|
Gpt5Agent: () => Gpt5Agent,
|
|
54
56
|
GrokAgent: () => GrokAgent,
|
|
57
|
+
InMemorySpendStore: () => InMemorySpendStore,
|
|
55
58
|
KimiAgent: () => KimiAgent,
|
|
56
59
|
LLM_CONSTANTS: () => LLM_CONSTANTS,
|
|
57
60
|
MESSAGE_ROLE: () => MESSAGE_ROLE,
|
|
@@ -78,6 +81,7 @@ __export(index_exports, {
|
|
|
78
81
|
VOICE_PROVIDER_API_KEY: () => VOICE_PROVIDER_API_KEY,
|
|
79
82
|
VoiceAgentFactory: () => VoiceAgentFactory,
|
|
80
83
|
ZodSchemaConverter: () => ZodSchemaConverter,
|
|
84
|
+
applySpend: () => applySpend,
|
|
81
85
|
buildGoogleTtsPrompt: () => buildGoogleTtsPrompt,
|
|
82
86
|
calculateAnthropicCost: () => calculateAnthropicCost,
|
|
83
87
|
calculateCost: () => calculateCost,
|
|
@@ -96,6 +100,7 @@ __export(index_exports, {
|
|
|
96
100
|
cleanResponse: () => cleanResponse,
|
|
97
101
|
createCatalog: () => createCatalog,
|
|
98
102
|
createVoiceAgent: () => createVoiceAgent,
|
|
103
|
+
evaluateBudget: () => evaluateBudget,
|
|
99
104
|
extractAnthropicTokenUsage: () => extractAnthropicTokenUsage,
|
|
100
105
|
extractAnthropicTokenUsageFromResponse: () => extractTokenUsageFromResponse5,
|
|
101
106
|
extractDeepSeekTokenUsage: () => extractDeepSeekTokenUsage,
|
|
@@ -113,6 +118,7 @@ __export(index_exports, {
|
|
|
113
118
|
extractOpenAITokenUsageFromResponse: () => extractTokenUsageFromResponse,
|
|
114
119
|
extractTokenUsage: () => extractTokenUsage,
|
|
115
120
|
extractUsageAndCalculateCost: () => extractUsageAndCalculateCost,
|
|
121
|
+
firstRefusal: () => firstRefusal,
|
|
116
122
|
generateGoogleTtsAudio: () => generateGoogleTtsAudio,
|
|
117
123
|
generateOpenAiTtsAudio: () => generateOpenAiTtsAudio,
|
|
118
124
|
generateSchemaInstructions: () => generateSchemaInstructions,
|
|
@@ -121,10 +127,12 @@ __export(index_exports, {
|
|
|
121
127
|
getModelProviderName: () => getModelProviderName,
|
|
122
128
|
getModelTags: () => getModelTags,
|
|
123
129
|
getProviderSignatureFields: () => getProviderSignatureFields,
|
|
130
|
+
isBudgetExceededError: () => isBudgetExceededError,
|
|
124
131
|
isHybridThinkingModel: () => isHybridThinkingModel,
|
|
125
132
|
isInPeakWindow: () => isInPeakWindow,
|
|
126
133
|
isPeakBilling: () => isPeakBilling,
|
|
127
134
|
isWeekendAt: () => isWeekendAt,
|
|
135
|
+
ledgerSpend: () => ledgerSpend,
|
|
128
136
|
logger: () => logger,
|
|
129
137
|
mergeThinking: () => mergeThinking,
|
|
130
138
|
modelHasTag: () => modelHasTag,
|
|
@@ -132,6 +140,8 @@ __export(index_exports, {
|
|
|
132
140
|
needsPromptBasedSchema: () => needsPromptBasedSchema,
|
|
133
141
|
parseAndValidateLlmJson: () => parseAndValidateLlmJson,
|
|
134
142
|
pcmToWav: () => pcmToWav,
|
|
143
|
+
periodEnd: () => periodEnd,
|
|
144
|
+
periodKey: () => periodKey,
|
|
135
145
|
safeValidateResponse: () => safeValidateResponse,
|
|
136
146
|
setLlmLogger: () => setLlmLogger,
|
|
137
147
|
stableHashHex: () => stableHashHex,
|
|
@@ -2026,6 +2036,152 @@ function createVoiceAgent(provider, apiKey) {
|
|
|
2026
2036
|
return VoiceAgentFactory.createAgent(provider, apiKey);
|
|
2027
2037
|
}
|
|
2028
2038
|
|
|
2039
|
+
// src/budget/index.ts
|
|
2040
|
+
function round6(n) {
|
|
2041
|
+
return parseFloat((Number(n) || 0).toFixed(6));
|
|
2042
|
+
}
|
|
2043
|
+
function periodKey(timestamp, window) {
|
|
2044
|
+
const d = new Date(timestamp);
|
|
2045
|
+
const y = d.getUTCFullYear();
|
|
2046
|
+
const m = String(d.getUTCMonth() + 1).padStart(2, "0");
|
|
2047
|
+
if (window === "month") {
|
|
2048
|
+
return `${y}-${m}`;
|
|
2049
|
+
}
|
|
2050
|
+
const day = String(d.getUTCDate()).padStart(2, "0");
|
|
2051
|
+
return `${y}-${m}-${day}`;
|
|
2052
|
+
}
|
|
2053
|
+
function periodEnd(timestamp, window) {
|
|
2054
|
+
const d = new Date(timestamp);
|
|
2055
|
+
if (window === "month") {
|
|
2056
|
+
return Date.UTC(d.getUTCFullYear(), d.getUTCMonth() + 1, 1);
|
|
2057
|
+
}
|
|
2058
|
+
return Date.UTC(d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate() + 1);
|
|
2059
|
+
}
|
|
2060
|
+
function normalizeLedger(ledger, period) {
|
|
2061
|
+
if (!ledger || ledger.period !== period) {
|
|
2062
|
+
return { period, totalUSD: 0, buckets: {} };
|
|
2063
|
+
}
|
|
2064
|
+
const buckets = {};
|
|
2065
|
+
for (const [k, v] of Object.entries(ledger.buckets ?? {})) {
|
|
2066
|
+
buckets[k] = round6(v);
|
|
2067
|
+
}
|
|
2068
|
+
return { period, totalUSD: round6(ledger.totalUSD ?? 0), buckets };
|
|
2069
|
+
}
|
|
2070
|
+
function applySpend(ledger, input) {
|
|
2071
|
+
const timestamp = input.timestamp ?? Date.now();
|
|
2072
|
+
const period = periodKey(timestamp, input.window);
|
|
2073
|
+
const current2 = normalizeLedger(ledger, period);
|
|
2074
|
+
const amount = round6(input.amountUSD);
|
|
2075
|
+
if (!(amount > 0)) {
|
|
2076
|
+
return current2;
|
|
2077
|
+
}
|
|
2078
|
+
const buckets = { ...current2.buckets };
|
|
2079
|
+
if (input.bucket) {
|
|
2080
|
+
buckets[input.bucket] = round6((buckets[input.bucket] ?? 0) + amount);
|
|
2081
|
+
}
|
|
2082
|
+
return { period, totalUSD: round6(current2.totalUSD + amount), buckets };
|
|
2083
|
+
}
|
|
2084
|
+
function ledgerSpend(ledger, window, timestamp = Date.now(), bucket) {
|
|
2085
|
+
const current2 = normalizeLedger(ledger, periodKey(timestamp, window));
|
|
2086
|
+
return bucket ? current2.buckets[bucket] ?? 0 : current2.totalUSD;
|
|
2087
|
+
}
|
|
2088
|
+
function evaluateBudget(spentUSD, limit, timestamp = Date.now()) {
|
|
2089
|
+
const spent = round6(spentUSD);
|
|
2090
|
+
const unlimited = !Number.isFinite(limit.limitUSD);
|
|
2091
|
+
const remaining = unlimited ? Number.POSITIVE_INFINITY : Math.max(0, round6(limit.limitUSD - spent));
|
|
2092
|
+
return {
|
|
2093
|
+
allowed: unlimited || spent < limit.limitUSD,
|
|
2094
|
+
window: limit.window,
|
|
2095
|
+
...limit.bucket ? { bucket: limit.bucket } : {},
|
|
2096
|
+
limitUSD: limit.limitUSD,
|
|
2097
|
+
spentUSD: spent,
|
|
2098
|
+
remainingUSD: remaining,
|
|
2099
|
+
resetsAt: periodEnd(timestamp, limit.window)
|
|
2100
|
+
};
|
|
2101
|
+
}
|
|
2102
|
+
function firstRefusal(verdicts) {
|
|
2103
|
+
return verdicts.find((v) => !v.allowed);
|
|
2104
|
+
}
|
|
2105
|
+
var BudgetExceededError = class _BudgetExceededError extends Error {
|
|
2106
|
+
verdict;
|
|
2107
|
+
subject;
|
|
2108
|
+
constructor(verdict, subject, message) {
|
|
2109
|
+
super(message ?? _BudgetExceededError.describe(verdict));
|
|
2110
|
+
this.name = "BudgetExceededError";
|
|
2111
|
+
this.verdict = verdict;
|
|
2112
|
+
this.subject = subject;
|
|
2113
|
+
}
|
|
2114
|
+
static describe(v) {
|
|
2115
|
+
const when = v.window === "day" ? "daily" : "monthly";
|
|
2116
|
+
return `${when} budget of $${v.limitUSD} exhausted ($${v.spentUSD} spent); resets at ${new Date(v.resetsAt).toISOString()}`;
|
|
2117
|
+
}
|
|
2118
|
+
};
|
|
2119
|
+
function isBudgetExceededError(err) {
|
|
2120
|
+
return err instanceof BudgetExceededError || typeof err === "object" && err !== null && err.name === "BudgetExceededError" && !!err.verdict;
|
|
2121
|
+
}
|
|
2122
|
+
var InMemorySpendStore = class {
|
|
2123
|
+
ledgers = /* @__PURE__ */ new Map();
|
|
2124
|
+
async read(subject) {
|
|
2125
|
+
return { ...this.ledgers.get(subject) ?? {} };
|
|
2126
|
+
}
|
|
2127
|
+
async update(subject, fn) {
|
|
2128
|
+
const next = fn({ ...this.ledgers.get(subject) ?? {} });
|
|
2129
|
+
this.ledgers.set(subject, next);
|
|
2130
|
+
return { ...next };
|
|
2131
|
+
}
|
|
2132
|
+
};
|
|
2133
|
+
var BudgetController = class {
|
|
2134
|
+
constructor(store, options) {
|
|
2135
|
+
this.store = store;
|
|
2136
|
+
this.limits = options.limits;
|
|
2137
|
+
this.bucket = options.bucket;
|
|
2138
|
+
this.clock = options.clock ?? (() => Date.now());
|
|
2139
|
+
}
|
|
2140
|
+
store;
|
|
2141
|
+
limits;
|
|
2142
|
+
bucket;
|
|
2143
|
+
clock;
|
|
2144
|
+
verdicts(ledgers, now) {
|
|
2145
|
+
return this.limits.map((limit) => {
|
|
2146
|
+
const spent = ledgerSpend(ledgers[limit.window], limit.window, now, limit.bucket ?? this.bucket);
|
|
2147
|
+
return evaluateBudget(spent, limit, now);
|
|
2148
|
+
});
|
|
2149
|
+
}
|
|
2150
|
+
async check(subject) {
|
|
2151
|
+
return this.verdicts(await this.store.read(subject), this.clock());
|
|
2152
|
+
}
|
|
2153
|
+
async assertWithinBudget(subject) {
|
|
2154
|
+
const refused = firstRefusal(await this.check(subject));
|
|
2155
|
+
if (refused) {
|
|
2156
|
+
throw new BudgetExceededError(refused, subject);
|
|
2157
|
+
}
|
|
2158
|
+
}
|
|
2159
|
+
/**
|
|
2160
|
+
* Record `amountUSD` against every limited window. Re-checks the limits on the
|
|
2161
|
+
* ledgers as they are at write time and throws `BudgetExceededError` (writing
|
|
2162
|
+
* nothing) if any window is already exhausted.
|
|
2163
|
+
*/
|
|
2164
|
+
async record(subject, amountUSD) {
|
|
2165
|
+
const now = this.clock();
|
|
2166
|
+
return this.store.update(subject, (current2) => {
|
|
2167
|
+
const refused = firstRefusal(this.verdicts(current2, now));
|
|
2168
|
+
if (refused) {
|
|
2169
|
+
throw new BudgetExceededError(refused, subject);
|
|
2170
|
+
}
|
|
2171
|
+
const next = { ...current2 };
|
|
2172
|
+
for (const limit of this.limits) {
|
|
2173
|
+
next[limit.window] = applySpend(current2[limit.window], {
|
|
2174
|
+
window: limit.window,
|
|
2175
|
+
amountUSD,
|
|
2176
|
+
bucket: limit.bucket ?? this.bucket,
|
|
2177
|
+
timestamp: now
|
|
2178
|
+
});
|
|
2179
|
+
}
|
|
2180
|
+
return next;
|
|
2181
|
+
});
|
|
2182
|
+
}
|
|
2183
|
+
};
|
|
2184
|
+
|
|
2029
2185
|
// src/agents/abstract-agent.ts
|
|
2030
2186
|
var AbstractAgent = class {
|
|
2031
2187
|
name;
|
|
@@ -2176,6 +2332,11 @@ var import_openai3 = __toESM(require("openai"));
|
|
|
2176
2332
|
var import_zod2 = require("openai/helpers/zod");
|
|
2177
2333
|
var Gpt5Agent = class extends AbstractAgent {
|
|
2178
2334
|
client;
|
|
2335
|
+
// Routing hint for OpenAI's prefix cache (same scheme as the Mistral/Grok agents): one
|
|
2336
|
+
// key per agent+instruction, so an agent's own calls group together instead of every
|
|
2337
|
+
// agent that shares a static prefix hashing to the same route. Keys influence routing
|
|
2338
|
+
// only; they do not guarantee a hit.
|
|
2339
|
+
promptCacheKey;
|
|
2179
2340
|
// Log message templates
|
|
2180
2341
|
logTemplates = {
|
|
2181
2342
|
error: (name, error) => `Error in ${name} agent: ${error}`
|
|
@@ -2188,6 +2349,8 @@ var Gpt5Agent = class extends AbstractAgent {
|
|
|
2188
2349
|
};
|
|
2189
2350
|
constructor(name, instruction, model, apiKey, temperature, enableThinking = false, agentLoggingConfig = DEFAULT_LOGGING_CONFIG.agents) {
|
|
2190
2351
|
super(name, instruction, model, temperature, enableThinking, agentLoggingConfig);
|
|
2352
|
+
this.promptCacheKey = stableHashHex(`${name}
|
|
2353
|
+
${instruction}`);
|
|
2191
2354
|
this.client = new import_openai3.default({
|
|
2192
2355
|
apiKey
|
|
2193
2356
|
});
|
|
@@ -2202,10 +2365,7 @@ var Gpt5Agent = class extends AbstractAgent {
|
|
|
2202
2365
|
try {
|
|
2203
2366
|
this.logAsking(messages);
|
|
2204
2367
|
this.logMessages(messages);
|
|
2205
|
-
const input =
|
|
2206
|
-
`System: ${this.instruction}`,
|
|
2207
|
-
...this.prepareMessages(messages).map((msg) => `${msg.role === "user" ? "User" : "Assistant"}: ${msg.content}`)
|
|
2208
|
-
].join("\n\n");
|
|
2368
|
+
const input = this.prepareMessages(messages).map((msg) => `${msg.role === "user" ? "User" : "Assistant"}: ${msg.content}`).join("\n\n");
|
|
2209
2369
|
const schemaToSend = zodSchema;
|
|
2210
2370
|
let response;
|
|
2211
2371
|
try {
|
|
@@ -2214,6 +2374,7 @@ var Gpt5Agent = class extends AbstractAgent {
|
|
|
2214
2374
|
instructions: this.instruction,
|
|
2215
2375
|
input,
|
|
2216
2376
|
max_output_tokens: this.maxOutputTokens,
|
|
2377
|
+
prompt_cache_key: this.promptCacheKey,
|
|
2217
2378
|
text: {
|
|
2218
2379
|
format: (0, import_zod2.zodTextFormat)(schemaToSend, "response_schema")
|
|
2219
2380
|
}
|
|
@@ -2292,15 +2453,13 @@ var Gpt5Agent = class extends AbstractAgent {
|
|
|
2292
2453
|
try {
|
|
2293
2454
|
this.logAsking(messages);
|
|
2294
2455
|
this.logMessages(messages);
|
|
2295
|
-
const input =
|
|
2296
|
-
`System: ${this.instruction}`,
|
|
2297
|
-
...this.prepareMessages(messages).map((msg) => `${msg.role === "user" ? "User" : "Assistant"}: ${msg.content}`)
|
|
2298
|
-
].join("\n\n");
|
|
2456
|
+
const input = this.prepareMessages(messages).map((msg) => `${msg.role === "user" ? "User" : "Assistant"}: ${msg.content}`).join("\n\n");
|
|
2299
2457
|
const response = await this.client.responses.create({
|
|
2300
2458
|
model: this.model,
|
|
2301
2459
|
instructions: this.instruction,
|
|
2302
2460
|
input,
|
|
2303
|
-
max_output_tokens: this.maxOutputTokens
|
|
2461
|
+
max_output_tokens: this.maxOutputTokens,
|
|
2462
|
+
prompt_cache_key: this.promptCacheKey
|
|
2304
2463
|
});
|
|
2305
2464
|
const content = response.output_text;
|
|
2306
2465
|
if (!content) {
|
|
@@ -2356,13 +2515,24 @@ var Gpt5Agent = class extends AbstractAgent {
|
|
|
2356
2515
|
var import_sdk = require("@anthropic-ai/sdk");
|
|
2357
2516
|
var ClaudeAgent = class extends AbstractAgent {
|
|
2358
2517
|
client;
|
|
2518
|
+
/**
|
|
2519
|
+
* TTL for every breakpoint this agent places (system tiers and the message anchor).
|
|
2520
|
+
* Anthropic bills a 5m write at 1.25x input, a 1h write at 2x, reads at 0.1x, and a read
|
|
2521
|
+
* refreshes the timer on either TTL. Default '1h' because the main consumer runs at human
|
|
2522
|
+
* pace: consecutive calls for one agent measured 12-78 minutes apart, so 5m entries
|
|
2523
|
+
* expired before they were ever read (0-16% hit rate over 30 days, hits only on gaps
|
|
2524
|
+
* under five minutes). Set '5m' for continuous traffic where every call lands inside the
|
|
2525
|
+
* window; there the cheaper write wins. One knob for all breakpoints on purpose: Anthropic
|
|
2526
|
+
* requires 1h entries to precede 5m ones, and a single TTL keeps that trivially true.
|
|
2527
|
+
*/
|
|
2528
|
+
cacheTtl = "1h";
|
|
2359
2529
|
// System-prompt breakpoints, one per cache tier (see CACHE_TIER_MARKER):
|
|
2360
|
-
// block 1
|
|
2361
|
-
// same rule set, so one
|
|
2362
|
-
// refreshes
|
|
2363
|
-
// block 2
|
|
2364
|
-
//
|
|
2365
|
-
//
|
|
2530
|
+
// block 1 - shared static rules, byte-identical across all bots and games with the
|
|
2531
|
+
// same rule set. Caches are scoped per model, so one entry serves every bot
|
|
2532
|
+
// ON THAT MODEL (not the whole lobby), and any of their calls refreshes it;
|
|
2533
|
+
// block 2 - per-bot identity + game state + summaries, byte-stable between the game's
|
|
2534
|
+
// state writes (a lynch, the night resolution, the summary rewrite, the new
|
|
2535
|
+
// day), so every call inside one of those windows reads it.
|
|
2366
2536
|
// GM prompts have no marker → single block, same behavior as before. Haiku 4.5 needs a
|
|
2367
2537
|
// 4096-token cacheable prefix, so tiers below that silently no-op on Haiku — expected.
|
|
2368
2538
|
// A getter, not a field: `maxOutputTokens` can be raised after construction, and a field
|
|
@@ -2370,7 +2540,7 @@ var ClaudeAgent = class extends AbstractAgent {
|
|
|
2370
2540
|
get defaultParams() {
|
|
2371
2541
|
return {
|
|
2372
2542
|
max_tokens: this.maxOutputTokens,
|
|
2373
|
-
system: this.instructionParts.map((part) => ({ type: "text", text: part, cache_control: { type: "ephemeral" } })),
|
|
2543
|
+
system: this.instructionParts.map((part) => ({ type: "text", text: part, cache_control: { type: "ephemeral", ttl: this.cacheTtl } })),
|
|
2374
2544
|
model: this.model
|
|
2375
2545
|
};
|
|
2376
2546
|
}
|
|
@@ -2475,14 +2645,14 @@ var ClaudeAgent = class extends AbstractAgent {
|
|
|
2475
2645
|
const anchor = messages[messages.length - 2];
|
|
2476
2646
|
if (typeof anchor.content === "string") {
|
|
2477
2647
|
if (anchor.content.length > 0) {
|
|
2478
|
-
anchor.content = [{ type: "text", text: anchor.content, cache_control: { type: "ephemeral" } }];
|
|
2648
|
+
anchor.content = [{ type: "text", text: anchor.content, cache_control: { type: "ephemeral", ttl: this.cacheTtl } }];
|
|
2479
2649
|
}
|
|
2480
2650
|
return;
|
|
2481
2651
|
}
|
|
2482
2652
|
for (let i = anchor.content.length - 1; i >= 0; i--) {
|
|
2483
2653
|
const block = anchor.content[i];
|
|
2484
2654
|
if (block.type === "text" && block.text.length > 0) {
|
|
2485
|
-
block.cache_control = { type: "ephemeral" };
|
|
2655
|
+
block.cache_control = { type: "ephemeral", ttl: this.cacheTtl };
|
|
2486
2656
|
return;
|
|
2487
2657
|
}
|
|
2488
2658
|
}
|
|
@@ -4741,6 +4911,8 @@ var AgentFactory = class {
|
|
|
4741
4911
|
AbstractAgent,
|
|
4742
4912
|
AgentFactory,
|
|
4743
4913
|
BotResponseError,
|
|
4914
|
+
BudgetController,
|
|
4915
|
+
BudgetExceededError,
|
|
4744
4916
|
CACHE_TIER_MARKER,
|
|
4745
4917
|
ClaudeAgent,
|
|
4746
4918
|
DEEPSEEK_PEAK_SCHEDULE,
|
|
@@ -4758,6 +4930,7 @@ var AgentFactory = class {
|
|
|
4758
4930
|
GoogleVoiceAgent,
|
|
4759
4931
|
Gpt5Agent,
|
|
4760
4932
|
GrokAgent,
|
|
4933
|
+
InMemorySpendStore,
|
|
4761
4934
|
KimiAgent,
|
|
4762
4935
|
LLM_CONSTANTS,
|
|
4763
4936
|
MESSAGE_ROLE,
|
|
@@ -4784,6 +4957,7 @@ var AgentFactory = class {
|
|
|
4784
4957
|
VOICE_PROVIDER_API_KEY,
|
|
4785
4958
|
VoiceAgentFactory,
|
|
4786
4959
|
ZodSchemaConverter,
|
|
4960
|
+
applySpend,
|
|
4787
4961
|
buildGoogleTtsPrompt,
|
|
4788
4962
|
calculateAnthropicCost,
|
|
4789
4963
|
calculateCost,
|
|
@@ -4802,6 +4976,7 @@ var AgentFactory = class {
|
|
|
4802
4976
|
cleanResponse,
|
|
4803
4977
|
createCatalog,
|
|
4804
4978
|
createVoiceAgent,
|
|
4979
|
+
evaluateBudget,
|
|
4805
4980
|
extractAnthropicTokenUsage,
|
|
4806
4981
|
extractAnthropicTokenUsageFromResponse,
|
|
4807
4982
|
extractDeepSeekTokenUsage,
|
|
@@ -4819,6 +4994,7 @@ var AgentFactory = class {
|
|
|
4819
4994
|
extractOpenAITokenUsageFromResponse,
|
|
4820
4995
|
extractTokenUsage,
|
|
4821
4996
|
extractUsageAndCalculateCost,
|
|
4997
|
+
firstRefusal,
|
|
4822
4998
|
generateGoogleTtsAudio,
|
|
4823
4999
|
generateOpenAiTtsAudio,
|
|
4824
5000
|
generateSchemaInstructions,
|
|
@@ -4827,10 +5003,12 @@ var AgentFactory = class {
|
|
|
4827
5003
|
getModelProviderName,
|
|
4828
5004
|
getModelTags,
|
|
4829
5005
|
getProviderSignatureFields,
|
|
5006
|
+
isBudgetExceededError,
|
|
4830
5007
|
isHybridThinkingModel,
|
|
4831
5008
|
isInPeakWindow,
|
|
4832
5009
|
isPeakBilling,
|
|
4833
5010
|
isWeekendAt,
|
|
5011
|
+
ledgerSpend,
|
|
4834
5012
|
logger,
|
|
4835
5013
|
mergeThinking,
|
|
4836
5014
|
modelHasTag,
|
|
@@ -4838,6 +5016,8 @@ var AgentFactory = class {
|
|
|
4838
5016
|
needsPromptBasedSchema,
|
|
4839
5017
|
parseAndValidateLlmJson,
|
|
4840
5018
|
pcmToWav,
|
|
5019
|
+
periodEnd,
|
|
5020
|
+
periodKey,
|
|
4841
5021
|
safeValidateResponse,
|
|
4842
5022
|
setLlmLogger,
|
|
4843
5023
|
stableHashHex,
|