@hiper2d/ai-agents 0.6.0 → 0.8.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/index.d.mts +4 -3
- package/dist/index.d.ts +4 -3
- package/dist/index.js +96 -57
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +96 -57
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -370,6 +370,7 @@ declare const LLM_CONSTANTS: {
|
|
|
370
370
|
GLM: string;
|
|
371
371
|
GLM_FLASH: string;
|
|
372
372
|
FUGU_ULTRA: string;
|
|
373
|
+
FUGU_MAX: string;
|
|
373
374
|
QWEN_MAX: string;
|
|
374
375
|
QWEN_FLASH: string;
|
|
375
376
|
MINIMAX: string;
|
|
@@ -527,7 +528,8 @@ declare function getProviderSignatureFields(aiType: string, signature?: string):
|
|
|
527
528
|
* - Gemini 3.x thinkingLevel: minimal|low|medium|high (3.1 Pro and 3.7 Flash reject minimal)
|
|
528
529
|
* - Z.AI GLM-5.3 / 5.3-Flash: low|high|max only
|
|
529
530
|
* - DeepSeek V4: low|high|max (the API itself aliases medium → high)
|
|
530
|
-
* - Sakana Fugu: high|xhigh
|
|
531
|
+
* - Sakana Fugu (verified live 2026-09-20): high|xhigh|max on every model ("low" → 400 naming
|
|
532
|
+
* exactly that enum). The server default is xhigh for fugu-ultra and high for the rest.
|
|
531
533
|
* - Meta Muse Spark (verified 2026-09-12): minimal|low|medium|high|xhigh|max ("none" → 400; max is
|
|
532
534
|
* Standard tier only)
|
|
533
535
|
* - Mistral Small 4 / Medium 3.5 (verified 2026-09-18): the API enum is
|
|
@@ -543,7 +545,7 @@ type AnthropicReasoningEffort = 'low' | 'medium' | 'high' | 'xhigh' | 'max';
|
|
|
543
545
|
type GeminiReasoningEffort = 'minimal' | 'low' | 'medium' | 'high';
|
|
544
546
|
type GlmReasoningEffort = 'low' | 'high' | 'max';
|
|
545
547
|
type DeepSeekReasoningEffort = 'low' | 'high' | 'max';
|
|
546
|
-
type FuguReasoningEffort = 'high' | 'xhigh';
|
|
548
|
+
type FuguReasoningEffort = 'high' | 'xhigh' | 'max';
|
|
547
549
|
type MetaReasoningEffort = 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max';
|
|
548
550
|
type MistralReasoningEffort = 'minimal' | 'low' | 'medium' | 'high' | 'xhigh';
|
|
549
551
|
/** The shared scale, lowest first. */
|
|
@@ -1651,7 +1653,6 @@ declare class FuguAgent extends AbstractAgent {
|
|
|
1651
1653
|
private readonly errorMessages;
|
|
1652
1654
|
constructor(name: string, instruction: string, model: string, apiKey: string, enableThinking?: boolean, agentLoggingConfig?: AgentLoggingConfig);
|
|
1653
1655
|
private convertToOpenAIMessages;
|
|
1654
|
-
private logRawUsageForCalibration;
|
|
1655
1656
|
private extractThinkingAndUsage;
|
|
1656
1657
|
private prependSystemInstruction;
|
|
1657
1658
|
doAskWithZodSchema<T>(zodSchema: z.ZodSchema<T>, messages: AIMessage[]): Promise<[T, string, TokenUsage$1?, string?]>;
|
package/dist/index.d.ts
CHANGED
|
@@ -370,6 +370,7 @@ declare const LLM_CONSTANTS: {
|
|
|
370
370
|
GLM: string;
|
|
371
371
|
GLM_FLASH: string;
|
|
372
372
|
FUGU_ULTRA: string;
|
|
373
|
+
FUGU_MAX: string;
|
|
373
374
|
QWEN_MAX: string;
|
|
374
375
|
QWEN_FLASH: string;
|
|
375
376
|
MINIMAX: string;
|
|
@@ -527,7 +528,8 @@ declare function getProviderSignatureFields(aiType: string, signature?: string):
|
|
|
527
528
|
* - Gemini 3.x thinkingLevel: minimal|low|medium|high (3.1 Pro and 3.7 Flash reject minimal)
|
|
528
529
|
* - Z.AI GLM-5.3 / 5.3-Flash: low|high|max only
|
|
529
530
|
* - DeepSeek V4: low|high|max (the API itself aliases medium → high)
|
|
530
|
-
* - Sakana Fugu: high|xhigh
|
|
531
|
+
* - Sakana Fugu (verified live 2026-09-20): high|xhigh|max on every model ("low" → 400 naming
|
|
532
|
+
* exactly that enum). The server default is xhigh for fugu-ultra and high for the rest.
|
|
531
533
|
* - Meta Muse Spark (verified 2026-09-12): minimal|low|medium|high|xhigh|max ("none" → 400; max is
|
|
532
534
|
* Standard tier only)
|
|
533
535
|
* - Mistral Small 4 / Medium 3.5 (verified 2026-09-18): the API enum is
|
|
@@ -543,7 +545,7 @@ type AnthropicReasoningEffort = 'low' | 'medium' | 'high' | 'xhigh' | 'max';
|
|
|
543
545
|
type GeminiReasoningEffort = 'minimal' | 'low' | 'medium' | 'high';
|
|
544
546
|
type GlmReasoningEffort = 'low' | 'high' | 'max';
|
|
545
547
|
type DeepSeekReasoningEffort = 'low' | 'high' | 'max';
|
|
546
|
-
type FuguReasoningEffort = 'high' | 'xhigh';
|
|
548
|
+
type FuguReasoningEffort = 'high' | 'xhigh' | 'max';
|
|
547
549
|
type MetaReasoningEffort = 'minimal' | 'low' | 'medium' | 'high' | 'xhigh' | 'max';
|
|
548
550
|
type MistralReasoningEffort = 'minimal' | 'low' | 'medium' | 'high' | 'xhigh';
|
|
549
551
|
/** The shared scale, lowest first. */
|
|
@@ -1651,7 +1653,6 @@ declare class FuguAgent extends AbstractAgent {
|
|
|
1651
1653
|
private readonly errorMessages;
|
|
1652
1654
|
constructor(name: string, instruction: string, model: string, apiKey: string, enableThinking?: boolean, agentLoggingConfig?: AgentLoggingConfig);
|
|
1653
1655
|
private convertToOpenAIMessages;
|
|
1654
|
-
private logRawUsageForCalibration;
|
|
1655
1656
|
private extractThinkingAndUsage;
|
|
1656
1657
|
private prependSystemInstruction;
|
|
1657
1658
|
doAskWithZodSchema<T>(zodSchema: z.ZodSchema<T>, messages: AIMessage[]): Promise<[T, string, TokenUsage$1?, string?]>;
|
package/dist/index.js
CHANGED
|
@@ -976,6 +976,7 @@ var LLM_CONSTANTS = {
|
|
|
976
976
|
GLM: "glm",
|
|
977
977
|
GLM_FLASH: "glm-flash",
|
|
978
978
|
FUGU_ULTRA: "fugu-ultra",
|
|
979
|
+
FUGU_MAX: "fugu-max",
|
|
979
980
|
// Qwen (QwenCloud/DashScope). Stable picker ids without the version, matching the gpt/gemini
|
|
980
981
|
// pattern, so future repoints don't orphan persisted ids.
|
|
981
982
|
QWEN_MAX: "qwen-max",
|
|
@@ -997,9 +998,13 @@ var SupportedAiModels = {
|
|
|
997
998
|
tags: ["expensive"]
|
|
998
999
|
},
|
|
999
1000
|
// Claude models — thinking-only entries (non-thinking variants retired 2026-08-05)
|
|
1001
|
+
// Opus moved 5 → 5.5 on 2026-09-22 (`claude-opus-5-5`, verified against GET /v1/models).
|
|
1002
|
+
// Cheaper than Opus 5 ($4/$20 vs $5/$25) and the same 1M context / 128K output. Thinking is
|
|
1003
|
+
// always on, as on Opus 5. Its API default effort is `medium`, but we keep the catalog-wide
|
|
1004
|
+
// `high` pin so bot answers don't get shallower than every other model in the lobby.
|
|
1000
1005
|
[LLM_CONSTANTS.CLAUDE_OPUS]: {
|
|
1001
|
-
displayName: "Claude 5 Opus",
|
|
1002
|
-
modelApiName: "claude-opus-5",
|
|
1006
|
+
displayName: "Claude 5.5 Opus",
|
|
1007
|
+
modelApiName: "claude-opus-5-5",
|
|
1003
1008
|
apiKeyName: API_KEY_CONSTANTS.ANTHROPIC,
|
|
1004
1009
|
hasThinking: true,
|
|
1005
1010
|
reasoningEffort: "high",
|
|
@@ -1221,13 +1226,37 @@ var SupportedAiModels = {
|
|
|
1221
1226
|
// so the rate is not even guaranteed stable, and its cache hit rate was 9.3% — effectively
|
|
1222
1227
|
// zero, since every hit came from a duplicate call seconds apart rather than turn-to-turn
|
|
1223
1228
|
// prefix reuse. Ultra costs the same and is predictable.
|
|
1229
|
+
//
|
|
1230
|
+
// reasoningEffort is PINNED on both entries because the server default differs per model:
|
|
1231
|
+
// fugu-ultra defaults to `xhigh` (console.sakana.ai/models), fugu-max to `high`. Until
|
|
1232
|
+
// 2026-09-20 the agent sent no effort at all, so every Ultra turn ran at xhigh. Measured that
|
|
1233
|
+
// day on a 2k-token three-day game prompt (two samples each, chat completions, json mode):
|
|
1234
|
+
// ultra xhigh 148s / 265s $0.34 / $0.50 a turn (orchestration tokens included)
|
|
1235
|
+
// ultra high 65s / 78s $0.16 / $0.17
|
|
1236
|
+
// max high 6s / 10s $0.006 / $0.008
|
|
1237
|
+
// max xhigh 41s / 47s $0.02
|
|
1238
|
+
// `max_tokens` is not a latency lever for Ultra: Sakana applies it to the final response only,
|
|
1239
|
+
// the orchestrator "still uses maximum token limit". Effort is the only knob.
|
|
1224
1240
|
[LLM_CONSTANTS.FUGU_ULTRA]: {
|
|
1225
1241
|
displayName: "Sakana Fugu Ultra",
|
|
1226
1242
|
modelApiName: "fugu-ultra",
|
|
1227
1243
|
apiKeyName: API_KEY_CONSTANTS.FUGU,
|
|
1228
1244
|
hasThinking: false,
|
|
1245
|
+
reasoningEffort: "high",
|
|
1229
1246
|
tags: ["extremely-slow", "expensive"]
|
|
1230
1247
|
},
|
|
1248
|
+
// Fugu Max (2026-09-20, fugu-max → fugu-max-v1.0): Sakana's "largest pool of models on the
|
|
1249
|
+
// cost–performance Pareto frontier" — the everyday Fugu at 5x less than Ultra's output rate
|
|
1250
|
+
// and a fraction of its latency. It reasons (reasoning_tokens 80-500 a turn) but, like
|
|
1251
|
+
// Ultra, never returns reasoning_content, hence hasThinking: false. No orchestration
|
|
1252
|
+
// tokens observed on any call.
|
|
1253
|
+
[LLM_CONSTANTS.FUGU_MAX]: {
|
|
1254
|
+
displayName: "Sakana Fugu Max",
|
|
1255
|
+
modelApiName: "fugu-max",
|
|
1256
|
+
apiKeyName: API_KEY_CONSTANTS.FUGU,
|
|
1257
|
+
hasThinking: false,
|
|
1258
|
+
reasoningEffort: "high"
|
|
1259
|
+
},
|
|
1231
1260
|
// Qwen models (QwenCloud, OpenAI-compatible endpoint). Added 2026-08-05 straight into the
|
|
1232
1261
|
// thinking-only catalog: their API has an `enable_thinking` toggle, we always send true, and
|
|
1233
1262
|
// thinking arrives in `reasoning_content` (verified live against all three, non-streaming).
|
|
@@ -1448,9 +1477,13 @@ var MODEL_PRICING = {
|
|
|
1448
1477
|
cacheHitPrice: 0.25
|
|
1449
1478
|
},
|
|
1450
1479
|
[SupportedAiModels[LLM_CONSTANTS.CLAUDE_OPUS].modelApiName]: {
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1480
|
+
// Opus 5.5 (2026-09-22): $4/$20, down from Opus 5's $5/$25. Cache reads are 5% of input
|
|
1481
|
+
// here, not the usual 10% — $0.20, not $0.40. Cache WRITES ($5 at 5m, $8 at 1h) are not
|
|
1482
|
+
// modelled: calculateCost bills every uncached prompt token at inputPrice, so a write is
|
|
1483
|
+
// under-billed by the 1.25x/2x premium. Pre-existing for every Anthropic model.
|
|
1484
|
+
inputPrice: 4,
|
|
1485
|
+
outputPrice: 20,
|
|
1486
|
+
cacheHitPrice: 0.2
|
|
1454
1487
|
},
|
|
1455
1488
|
[SupportedAiModels[LLM_CONSTANTS.CLAUDE_SONNET].modelApiName]: {
|
|
1456
1489
|
inputPrice: 2,
|
|
@@ -1515,9 +1548,12 @@ var MODEL_PRICING = {
|
|
|
1515
1548
|
extendedContextCacheHitPrice: 1,
|
|
1516
1549
|
extendedContextThresholdTokens: 2e5
|
|
1517
1550
|
},
|
|
1518
|
-
// Sakana Fugu models. Base `fugu` was retired
|
|
1519
|
-
// measured out at these same ultra rates, so it
|
|
1520
|
-
//
|
|
1551
|
+
// Sakana Fugu models (console.sakana.ai/pricing, read 2026-09-20). Base `fugu` was retired
|
|
1552
|
+
// 2026-08-04 — it had no published price and measured out at these same ultra rates, so it
|
|
1553
|
+
// has no pricing entry. fugu-ultra: above 272K context the rates roughly double. Ultra also
|
|
1554
|
+
// reports "orchestration" tokens (its internal expert calls) in prompt_tokens_details /
|
|
1555
|
+
// completion_tokens_details, billed at these same input/output rates — FuguAgent folds them
|
|
1556
|
+
// into the token counts before pricing.
|
|
1521
1557
|
[SupportedAiModels[LLM_CONSTANTS.FUGU_ULTRA].modelApiName]: {
|
|
1522
1558
|
inputPrice: 5,
|
|
1523
1559
|
outputPrice: 30,
|
|
@@ -1527,6 +1563,12 @@ var MODEL_PRICING = {
|
|
|
1527
1563
|
extendedContextCacheHitPrice: 1,
|
|
1528
1564
|
extendedContextThresholdTokens: 272e3
|
|
1529
1565
|
},
|
|
1566
|
+
// fugu-max: flat rates, no context tiers.
|
|
1567
|
+
[SupportedAiModels[LLM_CONSTANTS.FUGU_MAX].modelApiName]: {
|
|
1568
|
+
inputPrice: 2,
|
|
1569
|
+
outputPrice: 6,
|
|
1570
|
+
cacheHitPrice: 0.25
|
|
1571
|
+
},
|
|
1530
1572
|
// Qwen models. Rates from the official pricing page (qwencloud.com/pricing/api, read
|
|
1531
1573
|
// 2026-08-30 — the page is client-rendered, so it was read by eye, not WebFetch):
|
|
1532
1574
|
// qwen3.8-max $2/$6 with implicit-cache hits at $0.25; qwen3.8-flash $0.15/$0.47, hits
|
|
@@ -1643,7 +1685,7 @@ var ANTHROPIC_REASONING_EFFORTS = ["low", "medium", "high", "xhigh", "max"];
|
|
|
1643
1685
|
var GEMINI_REASONING_EFFORTS = ["minimal", "low", "medium", "high"];
|
|
1644
1686
|
var GLM_REASONING_EFFORTS = ["low", "high", "max"];
|
|
1645
1687
|
var DEEPSEEK_REASONING_EFFORTS = ["low", "high", "max"];
|
|
1646
|
-
var FUGU_REASONING_EFFORTS = ["high", "xhigh"];
|
|
1688
|
+
var FUGU_REASONING_EFFORTS = ["high", "xhigh", "max"];
|
|
1647
1689
|
var META_REASONING_EFFORTS = ["minimal", "low", "medium", "high", "xhigh", "max"];
|
|
1648
1690
|
var MISTRAL_REASONING_EFFORTS = ["minimal", "low", "medium", "high", "xhigh"];
|
|
1649
1691
|
function clampReasoningEffort(effort, allowed) {
|
|
@@ -2599,6 +2641,7 @@ ${instruction}`);
|
|
|
2599
2641
|
|
|
2600
2642
|
// src/agents/anthropic-agent.ts
|
|
2601
2643
|
var import_sdk = require("@anthropic-ai/sdk");
|
|
2644
|
+
var rejectsDisabledThinking = (model) => model.includes("fable") || model.includes("opus-5-5");
|
|
2602
2645
|
var ClaudeAgent = class extends AbstractAgent {
|
|
2603
2646
|
client;
|
|
2604
2647
|
/**
|
|
@@ -2815,7 +2858,9 @@ ${schemaDescription}`;
|
|
|
2815
2858
|
params.temperature = 1;
|
|
2816
2859
|
}
|
|
2817
2860
|
} else if (usesAdaptiveThinking) {
|
|
2818
|
-
|
|
2861
|
+
if (!rejectsDisabledThinking(this.model)) {
|
|
2862
|
+
params.thinking = { type: "disabled" };
|
|
2863
|
+
}
|
|
2819
2864
|
} else {
|
|
2820
2865
|
params.temperature = this.temperature;
|
|
2821
2866
|
}
|
|
@@ -2909,7 +2954,9 @@ ${schemaDescription}`;
|
|
|
2909
2954
|
params.temperature = 1;
|
|
2910
2955
|
}
|
|
2911
2956
|
} else if (usesAdaptiveThinking) {
|
|
2912
|
-
|
|
2957
|
+
if (!rejectsDisabledThinking(this.model)) {
|
|
2958
|
+
params.thinking = { type: "disabled" };
|
|
2959
|
+
}
|
|
2913
2960
|
} else {
|
|
2914
2961
|
params.temperature = this.temperature;
|
|
2915
2962
|
}
|
|
@@ -4411,13 +4458,15 @@ var FuguAgent = class extends AbstractAgent {
|
|
|
4411
4458
|
client;
|
|
4412
4459
|
// A getter, not a field: `maxOutputTokens` can be raised after construction, and a field
|
|
4413
4460
|
// initializer would snapshot the default and silently ignore the override.
|
|
4461
|
+
// `reasoning_effort` is re-declared as string: the OpenAI SDK's union lacks Sakana's 'max'.
|
|
4414
4462
|
get defaultParams() {
|
|
4415
4463
|
return {
|
|
4416
4464
|
model: this.model,
|
|
4417
4465
|
stream: false,
|
|
4418
|
-
// Caps
|
|
4419
|
-
//
|
|
4420
|
-
max_tokens: this.maxOutputTokens
|
|
4466
|
+
// Caps the final reply only. Per Sakana's docs the orchestrator "still uses maximum
|
|
4467
|
+
// token limit", so this bounds neither Ultra's latency nor its orchestration spend.
|
|
4468
|
+
max_tokens: this.maxOutputTokens,
|
|
4469
|
+
reasoning_effort: toFuguEffort(this.reasoningEffort ?? "high")
|
|
4421
4470
|
};
|
|
4422
4471
|
}
|
|
4423
4472
|
logTemplates = {
|
|
@@ -4442,33 +4491,6 @@ var FuguAgent = class extends AbstractAgent {
|
|
|
4442
4491
|
content: msg.content
|
|
4443
4492
|
}));
|
|
4444
4493
|
}
|
|
4445
|
-
// ───────────────────────────────────────────────────────────────────────────────────────
|
|
4446
|
-
// TEMPORARY (cost calibration). Base `fugu` is a dynamic router with no published per-token
|
|
4447
|
-
// price and Sakana returns NO cost field in the response — only token counts. Crucially the
|
|
4448
|
-
// response also reports "orchestration tokens" (billed at input/output rates per Sakana's
|
|
4449
|
-
// pricing page) that our standard TokenUsage drops. This logs the full raw breakdown to
|
|
4450
|
-
// BetterStack under a distinctive tag so we can sum real tokens per game and, combined with
|
|
4451
|
-
// the Sakana billing dashboard total, derive the true per-token rate. REMOVE AFTER CALIBRATION.
|
|
4452
|
-
logRawUsageForCalibration(completion) {
|
|
4453
|
-
const usage = completion?.usage;
|
|
4454
|
-
if (!usage) return;
|
|
4455
|
-
logger.info("FUGU_COST_CALIBRATION", {
|
|
4456
|
-
tag: "FUGU_COST_CALIBRATION",
|
|
4457
|
-
model: this.model,
|
|
4458
|
-
agentName: this.name,
|
|
4459
|
-
gameId: this.gameId,
|
|
4460
|
-
userId: this.userId,
|
|
4461
|
-
promptTokens: usage.prompt_tokens ?? 0,
|
|
4462
|
-
completionTokens: usage.completion_tokens ?? 0,
|
|
4463
|
-
totalTokens: usage.total_tokens ?? 0,
|
|
4464
|
-
cachedTokens: usage.prompt_tokens_details?.cached_tokens ?? 0,
|
|
4465
|
-
orchestrationInputTokens: usage.prompt_tokens_details?.orchestration_input_tokens ?? 0,
|
|
4466
|
-
orchestrationInputCachedTokens: usage.prompt_tokens_details?.orchestration_input_cached_tokens ?? 0,
|
|
4467
|
-
reasoningTokens: usage.completion_tokens_details?.reasoning_tokens ?? 0,
|
|
4468
|
-
orchestrationOutputTokens: usage.completion_tokens_details?.orchestration_output_tokens ?? 0,
|
|
4469
|
-
rawUsage: usage
|
|
4470
|
-
});
|
|
4471
|
-
}
|
|
4472
4494
|
extractThinkingAndUsage(completion) {
|
|
4473
4495
|
let thinkingContent = "";
|
|
4474
4496
|
const message = completion.choices[0]?.message;
|
|
@@ -4476,21 +4498,14 @@ var FuguAgent = class extends AbstractAgent {
|
|
|
4476
4498
|
thinkingContent = message.reasoning_content;
|
|
4477
4499
|
this.logger(`Captured reasoning_content (${thinkingContent.length} characters)`);
|
|
4478
4500
|
}
|
|
4479
|
-
|
|
4480
|
-
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
|
|
4485
|
-
totalTokens: usageResult.usage.totalTokens,
|
|
4486
|
-
costUSD: usageResult.cost,
|
|
4487
|
-
...usageResult.usage.cacheHitTokens !== void 0 ? { cachedInputTokens: usageResult.usage.cacheHitTokens } : {}
|
|
4488
|
-
};
|
|
4489
|
-
if (usageResult.usage.reasoningTokens) {
|
|
4490
|
-
const reasoningTokens = usageResult.usage.reasoningTokens;
|
|
4491
|
-
const finalAnswerTokens = Math.max(0, tokenUsage.outputTokens - reasoningTokens);
|
|
4501
|
+
const tokenUsage = extractFuguTokenUsage(this.model, completion);
|
|
4502
|
+
if (tokenUsage) {
|
|
4503
|
+
const details = completion.usage ?? {};
|
|
4504
|
+
const orchestrationIn = details.prompt_tokens_details?.orchestration_input_tokens ?? 0;
|
|
4505
|
+
const orchestrationOut = details.completion_tokens_details?.orchestration_output_tokens ?? 0;
|
|
4506
|
+
if (tokenUsage.reasoningTokens || orchestrationIn || orchestrationOut) {
|
|
4492
4507
|
this.logger(
|
|
4493
|
-
`
|
|
4508
|
+
`Usage breakdown: ${tokenUsage.reasoningTokens ?? 0} reasoning tokens; orchestration ${orchestrationIn} in / ${orchestrationOut} out (billed, folded into the totals)`
|
|
4494
4509
|
);
|
|
4495
4510
|
}
|
|
4496
4511
|
}
|
|
@@ -4532,7 +4547,6 @@ ${schemaDescription}`;
|
|
|
4532
4547
|
this.logger(this.logTemplates.error(this.name, apiError));
|
|
4533
4548
|
throw new Error(this.errorMessages.apiError(apiError));
|
|
4534
4549
|
}
|
|
4535
|
-
this.logRawUsageForCalibration(completion);
|
|
4536
4550
|
const rawReply = completion.choices[0]?.message?.content;
|
|
4537
4551
|
if (!rawReply) {
|
|
4538
4552
|
throw new Error(this.errorMessages.emptyResponse);
|
|
@@ -4576,7 +4590,6 @@ ${schemaDescription}`;
|
|
|
4576
4590
|
this.logger(this.logTemplates.error(this.name, apiError));
|
|
4577
4591
|
throw new Error(this.errorMessages.apiError(apiError));
|
|
4578
4592
|
}
|
|
4579
|
-
this.logRawUsageForCalibration(completion);
|
|
4580
4593
|
const rawReply = completion.choices[0]?.message?.content;
|
|
4581
4594
|
if (!rawReply) {
|
|
4582
4595
|
throw new Error(this.errorMessages.emptyResponse);
|
|
@@ -4595,6 +4608,31 @@ ${schemaDescription}`;
|
|
|
4595
4608
|
}
|
|
4596
4609
|
}
|
|
4597
4610
|
};
|
|
4611
|
+
function extractFuguTokenUsage(modelApiName, completion) {
|
|
4612
|
+
const usage = completion?.usage;
|
|
4613
|
+
if (!usage) {
|
|
4614
|
+
return void 0;
|
|
4615
|
+
}
|
|
4616
|
+
const promptDetails = usage.prompt_tokens_details ?? {};
|
|
4617
|
+
const completionDetails = usage.completion_tokens_details ?? {};
|
|
4618
|
+
const inputTokens = (usage.prompt_tokens ?? 0) + (promptDetails.orchestration_input_tokens ?? 0);
|
|
4619
|
+
const outputTokens = (usage.completion_tokens ?? 0) + (completionDetails.orchestration_output_tokens ?? 0);
|
|
4620
|
+
const cachedInputTokens = (promptDetails.cached_tokens ?? 0) + (promptDetails.orchestration_input_cached_tokens ?? 0);
|
|
4621
|
+
const reasoningTokens = completionDetails.reasoning_tokens ?? 0;
|
|
4622
|
+
return {
|
|
4623
|
+
inputTokens,
|
|
4624
|
+
outputTokens,
|
|
4625
|
+
totalTokens: inputTokens + outputTokens,
|
|
4626
|
+
cachedInputTokens,
|
|
4627
|
+
// Omitted rather than 0: consumers persist the object as-is (see TokenUsage).
|
|
4628
|
+
...reasoningTokens > 0 ? { reasoningTokens } : {},
|
|
4629
|
+
costUSD: calculateModelCost(modelApiName, inputTokens, outputTokens, {
|
|
4630
|
+
cacheHitTokens: cachedInputTokens,
|
|
4631
|
+
// Context-tier selection: the request's own size, not the orchestrator's traffic.
|
|
4632
|
+
contextTokens: usage.total_tokens ?? inputTokens
|
|
4633
|
+
})
|
|
4634
|
+
};
|
|
4635
|
+
}
|
|
4598
4636
|
|
|
4599
4637
|
// src/agents/qwen-agent.ts
|
|
4600
4638
|
var import_openai9 = require("openai");
|
|
@@ -5255,6 +5293,7 @@ var AgentFactory = class {
|
|
|
5255
5293
|
return new GlmAgent(name, instruction, model.modelApiName, key, model.temperature, shouldEnableThinking);
|
|
5256
5294
|
// Sakana Fugu models — always-on reasoning, no temperature (ignored by the model)
|
|
5257
5295
|
case LLM_CONSTANTS.FUGU_ULTRA:
|
|
5296
|
+
case LLM_CONSTANTS.FUGU_MAX:
|
|
5258
5297
|
return new FuguAgent(name, instruction, model.modelApiName, key, shouldEnableThinking);
|
|
5259
5298
|
// Qwen models — thinking-only (enable_thinking always sent)
|
|
5260
5299
|
case LLM_CONSTANTS.QWEN_MAX:
|