@cognipeer/agent-sdk 0.7.0 → 0.7.1
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.cjs +544 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +109 -3
- package/dist/index.d.ts +109 -3
- package/dist/index.mjs +543 -23
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -3345,15 +3345,40 @@ function countToolCallsInLastTurn(state) {
|
|
|
3345
3345
|
function stripReflectionAskMessages(messages) {
|
|
3346
3346
|
return messages.filter((m) => !(m?.role === "user" && m?.name === REFLECTION_ASK_NAME));
|
|
3347
3347
|
}
|
|
3348
|
+
function lastTwoToolTurns(state) {
|
|
3349
|
+
const groups = [];
|
|
3350
|
+
let cur = [];
|
|
3351
|
+
let sawTool = false;
|
|
3352
|
+
for (let i = state.messages.length - 1; i >= 0; i--) {
|
|
3353
|
+
const m = state.messages[i];
|
|
3354
|
+
if (m?.role === "tool") {
|
|
3355
|
+
if (m.name) cur.push(m.name);
|
|
3356
|
+
sawTool = true;
|
|
3357
|
+
} else if (m?.role === "assistant") {
|
|
3358
|
+
if (sawTool) {
|
|
3359
|
+
groups.push(cur);
|
|
3360
|
+
cur = [];
|
|
3361
|
+
sawTool = false;
|
|
3362
|
+
if (groups.length >= 2) break;
|
|
3363
|
+
}
|
|
3364
|
+
}
|
|
3365
|
+
}
|
|
3366
|
+
if (sawTool && cur.length) groups.push(cur);
|
|
3367
|
+
return { current: groups[0] ?? [], previous: groups[1] ?? [] };
|
|
3368
|
+
}
|
|
3348
3369
|
function shouldRunReflection(cadence, state, ranToolsThisTurn) {
|
|
3349
3370
|
if (cadence === "off") return false;
|
|
3350
3371
|
if (cadence === "every_turn") return true;
|
|
3351
3372
|
if (cadence === "after_tool") return ranToolsThisTurn;
|
|
3373
|
+
if (cadence === "initial_then_after_tool") return ranToolsThisTurn;
|
|
3352
3374
|
if (cadence === "on_branch") {
|
|
3353
|
-
const
|
|
3354
|
-
|
|
3355
|
-
const
|
|
3356
|
-
|
|
3375
|
+
const { current, previous } = lastTwoToolTurns(state);
|
|
3376
|
+
if (previous.length === 0) return true;
|
|
3377
|
+
const a = new Set(current);
|
|
3378
|
+
const b = new Set(previous);
|
|
3379
|
+
for (const n of a) if (!b.has(n)) return true;
|
|
3380
|
+
for (const n of b) if (!a.has(n)) return true;
|
|
3381
|
+
return false;
|
|
3357
3382
|
}
|
|
3358
3383
|
return false;
|
|
3359
3384
|
}
|
|
@@ -3370,7 +3395,10 @@ function createReflectionNode(opts, resolved) {
|
|
|
3370
3395
|
const onEvent = state.ctx?.__onEvent;
|
|
3371
3396
|
const traceSession = state.ctx?.__traceSession;
|
|
3372
3397
|
const maxChars = resolved.maxChars;
|
|
3373
|
-
const
|
|
3398
|
+
const turnNow = state.toolCallCount ?? 0;
|
|
3399
|
+
const hookCtx = { state, turn: turnNow, trigger, ranToolsThisTurn: true };
|
|
3400
|
+
const defaultPrompt = (resolved.promptTemplate || DEFAULT_REFLECT_PROMPT).replace(/\$\{maxChars\}/g, String(maxChars));
|
|
3401
|
+
const promptBody = resolved.buildPrompt ? String(resolved.buildPrompt({ ...hookCtx, defaultPrompt, maxChars }) ?? defaultPrompt) : defaultPrompt;
|
|
3374
3402
|
const baseMessages = stripReflectionAskMessages([...state.messages]);
|
|
3375
3403
|
const askMessage = {
|
|
3376
3404
|
role: "user",
|
|
@@ -3404,6 +3432,8 @@ function createReflectionNode(opts, resolved) {
|
|
|
3404
3432
|
const rawText = extractText(response);
|
|
3405
3433
|
const text = trimToChars(String(rawText ?? "").trim(), maxChars);
|
|
3406
3434
|
if (!text) return {};
|
|
3435
|
+
const prevText = (state.reflections?.[state.reflections.length - 1]?.text || "").trim();
|
|
3436
|
+
if (prevText && isNearDuplicate(prevText, text)) return {};
|
|
3407
3437
|
const rawUsage = response?.usage_metadata || response?.response_metadata?.usage || response?.usage || response?.additional_kwargs?.usage;
|
|
3408
3438
|
const usage = normalizeUsage(rawUsage);
|
|
3409
3439
|
const { ids, names } = countToolCallsInLastTurn(state);
|
|
@@ -3452,6 +3482,12 @@ function createReflectionNode(opts, resolved) {
|
|
|
3452
3482
|
} catch (e) {
|
|
3453
3483
|
}
|
|
3454
3484
|
}
|
|
3485
|
+
if (resolved.onReflection) {
|
|
3486
|
+
try {
|
|
3487
|
+
resolved.onReflection(record, hookCtx);
|
|
3488
|
+
} catch {
|
|
3489
|
+
}
|
|
3490
|
+
}
|
|
3455
3491
|
const nextMessages = stripReflectionAskMessages([...state.messages]);
|
|
3456
3492
|
const reflections = [...state.reflections || [], record];
|
|
3457
3493
|
const kept = reflections.slice(-Math.max(1, resolved.keepLast));
|
|
@@ -3468,7 +3504,20 @@ ${r.text}
|
|
|
3468
3504
|
metadata: { reflectionId: r.id, reflectionTurn: r.turn, reflectionTrigger: r.trigger }
|
|
3469
3505
|
});
|
|
3470
3506
|
}
|
|
3471
|
-
|
|
3507
|
+
const patch = { messages: prunedMessages, reflections };
|
|
3508
|
+
if (resolved.feedTo === "memory") {
|
|
3509
|
+
const fact = {
|
|
3510
|
+
key: `reflection_turn_${turn}`,
|
|
3511
|
+
value: text,
|
|
3512
|
+
sourceTurn: turn,
|
|
3513
|
+
confidence: 0.3,
|
|
3514
|
+
tags: ["reflection"]
|
|
3515
|
+
};
|
|
3516
|
+
patch.memoryFacts = [...state.memoryFacts || [], fact];
|
|
3517
|
+
} else if (resolved.feedTo === "plan" && state.plan) {
|
|
3518
|
+
patch.plan = { ...state.plan, lastReflection: text };
|
|
3519
|
+
}
|
|
3520
|
+
return patch;
|
|
3472
3521
|
};
|
|
3473
3522
|
}
|
|
3474
3523
|
function extractText(chunk) {
|
|
@@ -3497,24 +3546,75 @@ function safeRandomId() {
|
|
|
3497
3546
|
return `r_${Math.random().toString(36).slice(2, 10)}_${Date.now().toString(36)}`;
|
|
3498
3547
|
}
|
|
3499
3548
|
}
|
|
3549
|
+
function isNearDuplicate(a, b) {
|
|
3550
|
+
const norm = (s) => s.toLowerCase().replace(/\s+/g, " ").trim();
|
|
3551
|
+
const na = norm(a);
|
|
3552
|
+
const nb = norm(b);
|
|
3553
|
+
if (na === nb) return true;
|
|
3554
|
+
const tokensA = new Set(na.split(" ").filter(Boolean));
|
|
3555
|
+
const tokensB = new Set(nb.split(" ").filter(Boolean));
|
|
3556
|
+
if (tokensA.size === 0 || tokensB.size === 0) return false;
|
|
3557
|
+
let inter = 0;
|
|
3558
|
+
for (const t of tokensA) if (tokensB.has(t)) inter++;
|
|
3559
|
+
const union = tokensA.size + tokensB.size - inter;
|
|
3560
|
+
return union > 0 && inter / union >= 0.9;
|
|
3561
|
+
}
|
|
3500
3562
|
|
|
3501
3563
|
// src/smart/reasoning.ts
|
|
3502
3564
|
var LEVEL_DEFAULTS = {
|
|
3565
|
+
minimal: {
|
|
3566
|
+
native: { effort: "minimal" },
|
|
3567
|
+
reflection: { maxTokens: 150, maxChars: 400, cadence: "off" }
|
|
3568
|
+
},
|
|
3503
3569
|
low: {
|
|
3504
3570
|
native: { effort: "low" },
|
|
3505
3571
|
reflection: { maxTokens: 200, maxChars: 600, cadence: "on_branch" }
|
|
3506
3572
|
},
|
|
3507
3573
|
medium: {
|
|
3508
3574
|
native: { effort: "medium" },
|
|
3509
|
-
reflection: { maxTokens: 350, maxChars: 1200, cadence: "
|
|
3575
|
+
reflection: { maxTokens: 350, maxChars: 1200, cadence: "initial_then_after_tool" }
|
|
3510
3576
|
},
|
|
3511
3577
|
high: {
|
|
3512
3578
|
native: { effort: "high" },
|
|
3513
|
-
reflection: { maxTokens: 600, maxChars: 2e3, cadence: "
|
|
3579
|
+
reflection: { maxTokens: 600, maxChars: 2e3, cadence: "initial_then_after_tool" }
|
|
3514
3580
|
}
|
|
3515
3581
|
};
|
|
3582
|
+
var VALID_LEVELS = ["minimal", "low", "medium", "high"];
|
|
3583
|
+
var VALID_CADENCES = ["off", "every_turn", "after_tool", "on_branch", "initial_then_after_tool"];
|
|
3584
|
+
var VALID_EFFORTS = ["minimal", "low", "medium", "high"];
|
|
3585
|
+
function validateReasoningConfig(input) {
|
|
3586
|
+
if (!input) return;
|
|
3587
|
+
if (input.level !== void 0 && !VALID_LEVELS.includes(input.level)) {
|
|
3588
|
+
throw new Error(`reasoning.level must be one of ${VALID_LEVELS.join(", ")} (got "${input.level}")`);
|
|
3589
|
+
}
|
|
3590
|
+
if (input.native) {
|
|
3591
|
+
const n = input.native;
|
|
3592
|
+
if (n.effort !== void 0 && !VALID_EFFORTS.includes(n.effort)) {
|
|
3593
|
+
throw new Error(`reasoning.native.effort must be one of ${VALID_EFFORTS.join(", ")} (got "${n.effort}")`);
|
|
3594
|
+
}
|
|
3595
|
+
if (n.budgetTokens !== void 0 && (!Number.isFinite(n.budgetTokens) || n.budgetTokens < 0)) {
|
|
3596
|
+
throw new Error(`reasoning.native.budgetTokens must be a non-negative number (got ${n.budgetTokens})`);
|
|
3597
|
+
}
|
|
3598
|
+
}
|
|
3599
|
+
if (input.reflection) {
|
|
3600
|
+
const r = input.reflection;
|
|
3601
|
+
if (r.cadence !== void 0 && !VALID_CADENCES.includes(r.cadence)) {
|
|
3602
|
+
throw new Error(`reasoning.reflection.cadence must be one of ${VALID_CADENCES.join(", ")} (got "${r.cadence}")`);
|
|
3603
|
+
}
|
|
3604
|
+
if (r.maxPerRun !== void 0 && (!Number.isFinite(r.maxPerRun) || r.maxPerRun < 0)) {
|
|
3605
|
+
throw new Error(`reasoning.reflection.maxPerRun must be a non-negative number (got ${r.maxPerRun})`);
|
|
3606
|
+
}
|
|
3607
|
+
if (r.everyNTurns !== void 0 && (!Number.isFinite(r.everyNTurns) || r.everyNTurns < 1)) {
|
|
3608
|
+
throw new Error(`reasoning.reflection.everyNTurns must be >= 1 (got ${r.everyNTurns})`);
|
|
3609
|
+
}
|
|
3610
|
+
if (r.feedTo !== void 0 && !["memory", "plan", "none"].includes(r.feedTo)) {
|
|
3611
|
+
throw new Error(`reasoning.reflection.feedTo must be "memory", "plan", or "none" (got "${r.feedTo}")`);
|
|
3612
|
+
}
|
|
3613
|
+
}
|
|
3614
|
+
}
|
|
3516
3615
|
function resolveReasoning(input) {
|
|
3517
3616
|
if (!input || input.enabled === false) return void 0;
|
|
3617
|
+
validateReasoningConfig(input);
|
|
3518
3618
|
const enabled = input.enabled ?? (input.native !== void 0 || input.reflection !== void 0 || input.level !== void 0);
|
|
3519
3619
|
if (!enabled) return void 0;
|
|
3520
3620
|
const level = input.level ?? "medium";
|
|
@@ -3539,7 +3639,8 @@ function resolveReflection(input, preset) {
|
|
|
3539
3639
|
keepLast: 3,
|
|
3540
3640
|
summarize: false,
|
|
3541
3641
|
emitEvents: true,
|
|
3542
|
-
everyNTurns: 1
|
|
3642
|
+
everyNTurns: 1,
|
|
3643
|
+
feedTo: "none"
|
|
3543
3644
|
};
|
|
3544
3645
|
}
|
|
3545
3646
|
const cfg = input ?? {};
|
|
@@ -3556,7 +3657,11 @@ function resolveReflection(input, preset) {
|
|
|
3556
3657
|
promptTemplate: cfg.promptTemplate,
|
|
3557
3658
|
emitEvents: cfg.emitEvents ?? true,
|
|
3558
3659
|
maxPerRun: typeof cfg.maxPerRun === "number" && cfg.maxPerRun >= 0 ? cfg.maxPerRun : void 0,
|
|
3559
|
-
everyNTurns: Math.max(1, Math.trunc(cfg.everyNTurns ?? 1))
|
|
3660
|
+
everyNTurns: Math.max(1, Math.trunc(cfg.everyNTurns ?? 1)),
|
|
3661
|
+
feedTo: cfg.feedTo ?? "none",
|
|
3662
|
+
shouldReflect: cfg.shouldReflect,
|
|
3663
|
+
buildPrompt: cfg.buildPrompt,
|
|
3664
|
+
onReflection: cfg.onReflection
|
|
3560
3665
|
};
|
|
3561
3666
|
}
|
|
3562
3667
|
function ensureArray(value) {
|
|
@@ -4282,12 +4387,14 @@ function createAgent(opts) {
|
|
|
4282
4387
|
if (summarizationThreshold === void 0) {
|
|
4283
4388
|
state = clearNeedsSummarization(state);
|
|
4284
4389
|
}
|
|
4285
|
-
if (resolvedReasoning
|
|
4390
|
+
if (resolvedReasoning) {
|
|
4286
4391
|
const ctx = { ...state.ctx || {} };
|
|
4287
|
-
if (
|
|
4392
|
+
if (resolvedReasoning.native) {
|
|
4288
4393
|
ctx.__reasoning = resolvedReasoning.native;
|
|
4289
|
-
|
|
4394
|
+
} else {
|
|
4395
|
+
delete ctx.__reasoning;
|
|
4290
4396
|
}
|
|
4397
|
+
state = { ...state, ctx: Object.keys(ctx).length > 0 ? ctx : void 0 };
|
|
4291
4398
|
}
|
|
4292
4399
|
const mergedLimits = {
|
|
4293
4400
|
...opts.limits || {},
|
|
@@ -4335,6 +4442,7 @@ function createAgent(opts) {
|
|
|
4335
4442
|
return { breached: false };
|
|
4336
4443
|
};
|
|
4337
4444
|
let iterations = 0;
|
|
4445
|
+
let reflectionsThisRun = 0;
|
|
4338
4446
|
const onStateChange = config?.onStateChange;
|
|
4339
4447
|
const checkpointReason = config?.checkpointReason;
|
|
4340
4448
|
let pausedStage = null;
|
|
@@ -4380,6 +4488,16 @@ function createAgent(opts) {
|
|
|
4380
4488
|
pausedStage = stage;
|
|
4381
4489
|
return true;
|
|
4382
4490
|
};
|
|
4491
|
+
if (reflectNode && resolvedReasoning?.reflection.enabled && resolvedReasoning.reflection.cadence === "initial_then_after_tool" && resumeStage === null && !state.ctx?.__awaitingApproval && !state.ctx?.__awaitingUserQuestion && !state.messages.some((m) => m?.role === "assistant")) {
|
|
4492
|
+
try {
|
|
4493
|
+
const patch = await reflectNode(state, "initial_then_after_tool");
|
|
4494
|
+
if (patch && Object.keys(patch).length > 0) {
|
|
4495
|
+
state = { ...state, ...patch };
|
|
4496
|
+
reflectionsThisRun++;
|
|
4497
|
+
}
|
|
4498
|
+
} catch {
|
|
4499
|
+
}
|
|
4500
|
+
}
|
|
4383
4501
|
while (iterations < iterationLimit) {
|
|
4384
4502
|
iterations++;
|
|
4385
4503
|
const budget = checkBudgetBreached();
|
|
@@ -4556,16 +4674,18 @@ function createAgent(opts) {
|
|
|
4556
4674
|
if (reflectNode && resolvedReasoning?.reflection.enabled) {
|
|
4557
4675
|
const cadence = resolvedReasoning.reflection.cadence;
|
|
4558
4676
|
const refl = resolvedReasoning.reflection;
|
|
4559
|
-
const reflectionsSoFar = state.reflections?.length ?? 0;
|
|
4560
4677
|
const lastTurn = state.reflections?.at(-1)?.turn ?? -Infinity;
|
|
4561
4678
|
const currentTurn = state.toolCallCount || 0;
|
|
4562
|
-
const budgetExceeded = typeof refl.maxPerRun === "number" &&
|
|
4563
|
-
const
|
|
4564
|
-
|
|
4679
|
+
const budgetExceeded = typeof refl.maxPerRun === "number" && reflectionsThisRun >= refl.maxPerRun;
|
|
4680
|
+
const sinceLast = currentTurn - (Number.isFinite(lastTurn) ? lastTurn : -refl.everyNTurns);
|
|
4681
|
+
const cadenceGap = sinceLast < refl.everyNTurns;
|
|
4682
|
+
const cadenceWantsIt = refl.shouldReflect ? !!refl.shouldReflect({ state, turn: currentTurn, trigger: cadence, ranToolsThisTurn: true }) : shouldRunReflection(cadence, state, true);
|
|
4683
|
+
if (!budgetExceeded && !cadenceGap && cadenceWantsIt) {
|
|
4565
4684
|
try {
|
|
4566
4685
|
const patch = await reflectNode(state, cadence);
|
|
4567
4686
|
if (patch && Object.keys(patch).length > 0) {
|
|
4568
4687
|
state = { ...state, ...patch };
|
|
4688
|
+
reflectionsThisRun++;
|
|
4569
4689
|
}
|
|
4570
4690
|
} catch {
|
|
4571
4691
|
}
|
|
@@ -6828,6 +6948,20 @@ function parseSSEBlock(block) {
|
|
|
6828
6948
|
}
|
|
6829
6949
|
|
|
6830
6950
|
// src/providers/utils/reasoning.ts
|
|
6951
|
+
var ANTHROPIC_EFFORT_BUDGET = {
|
|
6952
|
+
minimal: 1024,
|
|
6953
|
+
low: 2048,
|
|
6954
|
+
medium: 8192,
|
|
6955
|
+
high: 16384
|
|
6956
|
+
};
|
|
6957
|
+
var GEMINI_EFFORT_BUDGET = {
|
|
6958
|
+
minimal: 512,
|
|
6959
|
+
low: 1024,
|
|
6960
|
+
medium: 4096,
|
|
6961
|
+
high: 12e3
|
|
6962
|
+
};
|
|
6963
|
+
var THINKING_OUTPUT_RESERVE = 1024;
|
|
6964
|
+
var THINKING_MIN_MAX_TOKENS = 4096;
|
|
6831
6965
|
function applyOpenAIReasoning(body, reasoning, mode = "legacy_effort") {
|
|
6832
6966
|
if (!reasoning) return;
|
|
6833
6967
|
const effort = normalizeEffort(reasoning.effort);
|
|
@@ -6844,21 +6978,56 @@ function applyOpenAIReasoning(body, reasoning, mode = "legacy_effort") {
|
|
|
6844
6978
|
}
|
|
6845
6979
|
function applyAnthropicReasoning(body, reasoning) {
|
|
6846
6980
|
if (!reasoning) return;
|
|
6847
|
-
|
|
6981
|
+
let budget = resolveBudget(reasoning, ANTHROPIC_EFFORT_BUDGET);
|
|
6848
6982
|
if (!budget) return;
|
|
6983
|
+
const currentMax = typeof body.max_tokens === "number" ? body.max_tokens : 0;
|
|
6984
|
+
const requiredMax = Math.max(THINKING_MIN_MAX_TOKENS, budget + THINKING_OUTPUT_RESERVE);
|
|
6985
|
+
if (currentMax < requiredMax) {
|
|
6986
|
+
body.max_tokens = requiredMax;
|
|
6987
|
+
}
|
|
6988
|
+
budget = clampBudget(budget, body.max_tokens);
|
|
6849
6989
|
const thinking = { type: "enabled", budget_tokens: budget };
|
|
6850
6990
|
if (reasoning.providerExtras) Object.assign(thinking, reasoning.providerExtras);
|
|
6851
6991
|
body.thinking = thinking;
|
|
6992
|
+
stripSamplingParams(body, ["temperature", "top_p", "top_k"]);
|
|
6993
|
+
}
|
|
6994
|
+
function applyBedrockReasoning(body, reasoning) {
|
|
6995
|
+
if (!reasoning) return;
|
|
6996
|
+
let budget = resolveBudget(reasoning, ANTHROPIC_EFFORT_BUDGET);
|
|
6997
|
+
if (!budget) return;
|
|
6998
|
+
const inference = body.inferenceConfig ?? (body.inferenceConfig = {});
|
|
6999
|
+
const currentMax = typeof inference.maxTokens === "number" ? inference.maxTokens : 0;
|
|
7000
|
+
const requiredMax = Math.max(THINKING_MIN_MAX_TOKENS, budget + THINKING_OUTPUT_RESERVE);
|
|
7001
|
+
if (currentMax < requiredMax) {
|
|
7002
|
+
inference.maxTokens = requiredMax;
|
|
7003
|
+
}
|
|
7004
|
+
budget = clampBudget(budget, inference.maxTokens);
|
|
7005
|
+
const extra = body.additionalModelRequestFields ?? (body.additionalModelRequestFields = {});
|
|
7006
|
+
const thinking = { type: "enabled", budget_tokens: budget };
|
|
7007
|
+
if (reasoning.providerExtras) Object.assign(thinking, reasoning.providerExtras);
|
|
7008
|
+
extra.thinking = thinking;
|
|
7009
|
+
stripSamplingParams(inference, ["temperature", "topP"]);
|
|
6852
7010
|
}
|
|
6853
7011
|
function applyGeminiReasoning(generationConfig, reasoning) {
|
|
6854
7012
|
if (!reasoning) return;
|
|
6855
|
-
const budget = resolveBudget(reasoning,
|
|
7013
|
+
const budget = resolveBudget(reasoning, GEMINI_EFFORT_BUDGET);
|
|
6856
7014
|
if (budget == null) return;
|
|
6857
7015
|
const thinkingConfig = { thinkingBudget: budget };
|
|
6858
7016
|
if (reasoning.includeThoughts) thinkingConfig.includeThoughts = true;
|
|
6859
7017
|
if (reasoning.providerExtras) Object.assign(thinkingConfig, reasoning.providerExtras);
|
|
6860
7018
|
generationConfig.thinkingConfig = thinkingConfig;
|
|
6861
7019
|
}
|
|
7020
|
+
function stripSamplingParams(target, keys) {
|
|
7021
|
+
for (const k of keys) {
|
|
7022
|
+
if (k in target) delete target[k];
|
|
7023
|
+
}
|
|
7024
|
+
}
|
|
7025
|
+
function clampBudget(budget, maxTokens) {
|
|
7026
|
+
if (typeof maxTokens !== "number" || maxTokens <= 0) return budget;
|
|
7027
|
+
const ceiling = maxTokens - THINKING_OUTPUT_RESERVE;
|
|
7028
|
+
if (ceiling < 1024) return Math.max(1024, Math.floor(maxTokens / 2));
|
|
7029
|
+
return Math.min(budget, ceiling);
|
|
7030
|
+
}
|
|
6862
7031
|
function normalizeEffort(effort) {
|
|
6863
7032
|
if (!effort) return void 0;
|
|
6864
7033
|
const allowed = ["minimal", "low", "medium", "high"];
|
|
@@ -6887,13 +7056,38 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
6887
7056
|
};
|
|
6888
7057
|
if (config.retry) this.retryPolicy = { ...this.retryPolicy, ...config.retry };
|
|
6889
7058
|
}
|
|
7059
|
+
/** True when the request targets a reasoning model (o-series / gpt-5) so we
|
|
7060
|
+
* should route through the Responses API, which exposes `reasoning.effort`
|
|
7061
|
+
* and reasoning summaries. Chat Completions silently drops these. */
|
|
7062
|
+
useResponsesApi(request) {
|
|
7063
|
+
if (!request.reasoning) return false;
|
|
7064
|
+
return isReasoningModel(request.model || this.defaultModel);
|
|
7065
|
+
}
|
|
6890
7066
|
async complete(request) {
|
|
7067
|
+
if (this.useResponsesApi(request)) {
|
|
7068
|
+
return this.completeResponses(request);
|
|
7069
|
+
}
|
|
6891
7070
|
const body = this.buildRequestBody(request, false);
|
|
6892
7071
|
const res = await this.doFetch(body);
|
|
6893
7072
|
const json = await res.json();
|
|
6894
7073
|
return this.parseResponse(json);
|
|
6895
7074
|
}
|
|
6896
7075
|
async *completeStream(request) {
|
|
7076
|
+
if (this.useResponsesApi(request)) {
|
|
7077
|
+
const response = await this.completeResponses(request);
|
|
7078
|
+
yield {
|
|
7079
|
+
id: response.id,
|
|
7080
|
+
model: response.model,
|
|
7081
|
+
delta: {
|
|
7082
|
+
content: response.content ?? void 0,
|
|
7083
|
+
toolCalls: response.toolCalls.length > 0 ? response.toolCalls : void 0,
|
|
7084
|
+
reasoning: response.reasoning
|
|
7085
|
+
},
|
|
7086
|
+
usage: response.usage,
|
|
7087
|
+
finishReason: response.finishReason
|
|
7088
|
+
};
|
|
7089
|
+
return;
|
|
7090
|
+
}
|
|
6897
7091
|
const body = this.buildRequestBody(request, true);
|
|
6898
7092
|
const res = await this.doFetch(body);
|
|
6899
7093
|
if (!res.body) throw new ProviderError("No response body for stream", this.providerName);
|
|
@@ -6992,6 +7186,156 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
6992
7186
|
applyOpenAIReasoning(body, request.reasoning, "legacy_effort");
|
|
6993
7187
|
return body;
|
|
6994
7188
|
}
|
|
7189
|
+
// ─── Responses API (reasoning models) ──────────────────────────────────────
|
|
7190
|
+
async completeResponses(request) {
|
|
7191
|
+
const body = this.buildResponsesBody(request);
|
|
7192
|
+
const res = await this.responsesFetch(body);
|
|
7193
|
+
const json = await res.json();
|
|
7194
|
+
return this.parseResponsesResponse(json, request.model || this.defaultModel);
|
|
7195
|
+
}
|
|
7196
|
+
buildResponsesBody(request) {
|
|
7197
|
+
const body = {
|
|
7198
|
+
model: request.model || this.defaultModel,
|
|
7199
|
+
input: request.messages.map((m) => this.toResponsesInput(m))
|
|
7200
|
+
};
|
|
7201
|
+
if (request.maxTokens != null) body.max_output_tokens = request.maxTokens;
|
|
7202
|
+
if (request.topP != null) body.top_p = request.topP;
|
|
7203
|
+
if (request.tools?.length) {
|
|
7204
|
+
body.tools = request.tools.map((t) => ({
|
|
7205
|
+
type: "function",
|
|
7206
|
+
name: t.name,
|
|
7207
|
+
description: t.description,
|
|
7208
|
+
parameters: t.parameters,
|
|
7209
|
+
...t.strict ? { strict: true } : {}
|
|
7210
|
+
}));
|
|
7211
|
+
}
|
|
7212
|
+
if (request.toolChoice != null && request.tools?.length) {
|
|
7213
|
+
if (typeof request.toolChoice === "string") {
|
|
7214
|
+
body.tool_choice = request.toolChoice;
|
|
7215
|
+
} else {
|
|
7216
|
+
body.tool_choice = { type: "function", name: request.toolChoice.name };
|
|
7217
|
+
}
|
|
7218
|
+
}
|
|
7219
|
+
if (request.responseFormat) {
|
|
7220
|
+
if (request.responseFormat.type === "json_schema") {
|
|
7221
|
+
body.text = {
|
|
7222
|
+
format: {
|
|
7223
|
+
type: "json_schema",
|
|
7224
|
+
name: request.responseFormat.name ?? "response",
|
|
7225
|
+
schema: request.responseFormat.schema,
|
|
7226
|
+
strict: true
|
|
7227
|
+
}
|
|
7228
|
+
};
|
|
7229
|
+
} else if (request.responseFormat.type === "json_object") {
|
|
7230
|
+
body.text = { format: { type: "json_object" } };
|
|
7231
|
+
}
|
|
7232
|
+
}
|
|
7233
|
+
if (request.extra) Object.assign(body, request.extra);
|
|
7234
|
+
applyOpenAIReasoning(body, request.reasoning, "responses");
|
|
7235
|
+
return body;
|
|
7236
|
+
}
|
|
7237
|
+
/** Maps a unified message to a Responses API `input` item. */
|
|
7238
|
+
toResponsesInput(m) {
|
|
7239
|
+
if (m.role === "tool" && m.toolCallId) {
|
|
7240
|
+
const output = typeof m.content === "string" ? m.content : JSON.stringify(m.content);
|
|
7241
|
+
return { type: "function_call_output", call_id: m.toolCallId, output };
|
|
7242
|
+
}
|
|
7243
|
+
if (m.role === "assistant" && m.toolCalls?.length) {
|
|
7244
|
+
return {
|
|
7245
|
+
__assistantWithCalls: true,
|
|
7246
|
+
text: typeof m.content === "string" ? m.content : "",
|
|
7247
|
+
calls: m.toolCalls.map((tc) => ({
|
|
7248
|
+
type: "function_call",
|
|
7249
|
+
call_id: tc.id,
|
|
7250
|
+
name: tc.name,
|
|
7251
|
+
arguments: tc.arguments
|
|
7252
|
+
}))
|
|
7253
|
+
};
|
|
7254
|
+
}
|
|
7255
|
+
const role = m.role === "system" ? "system" : m.role === "assistant" ? "assistant" : "user";
|
|
7256
|
+
const textType = role === "assistant" ? "output_text" : "input_text";
|
|
7257
|
+
if (typeof m.content === "string") {
|
|
7258
|
+
return { role, content: [{ type: textType, text: m.content }] };
|
|
7259
|
+
}
|
|
7260
|
+
const content = m.content.map((part) => {
|
|
7261
|
+
if (part.type === "text") return { type: textType, text: part.text };
|
|
7262
|
+
if (part.type === "image") {
|
|
7263
|
+
const src = part.source;
|
|
7264
|
+
const url = src.type === "url" ? src.url : `data:${src.mediaType};base64,${src.data}`;
|
|
7265
|
+
return { type: "input_image", image_url: url };
|
|
7266
|
+
}
|
|
7267
|
+
return { type: textType, text: "" };
|
|
7268
|
+
});
|
|
7269
|
+
return { role, content };
|
|
7270
|
+
}
|
|
7271
|
+
async responsesFetch(body) {
|
|
7272
|
+
body.input = expandResponsesInput(body.input);
|
|
7273
|
+
const url = `${this.baseURL}/responses`;
|
|
7274
|
+
const headers = {
|
|
7275
|
+
"Content-Type": "application/json",
|
|
7276
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
7277
|
+
...this.defaultHeaders
|
|
7278
|
+
};
|
|
7279
|
+
const payload = JSON.stringify(body);
|
|
7280
|
+
const res = await this.doFetchWithRetry(() => fetch(url, { method: "POST", headers, body: payload }));
|
|
7281
|
+
if (!res.ok) {
|
|
7282
|
+
const text = await res.text().catch(() => "");
|
|
7283
|
+
throw new ProviderError(
|
|
7284
|
+
`OpenAI Responses API error ${res.status}: ${text}`,
|
|
7285
|
+
this.providerName,
|
|
7286
|
+
res.status,
|
|
7287
|
+
text
|
|
7288
|
+
);
|
|
7289
|
+
}
|
|
7290
|
+
return res;
|
|
7291
|
+
}
|
|
7292
|
+
parseResponsesResponse(json, modelId) {
|
|
7293
|
+
const textParts = [];
|
|
7294
|
+
const toolCalls = [];
|
|
7295
|
+
const summaryParts = [];
|
|
7296
|
+
for (const item of json.output ?? []) {
|
|
7297
|
+
if (item.type === "message") {
|
|
7298
|
+
for (const c of item.content ?? []) {
|
|
7299
|
+
if (c.type === "output_text" && typeof c.text === "string") textParts.push(c.text);
|
|
7300
|
+
}
|
|
7301
|
+
} else if (item.type === "function_call") {
|
|
7302
|
+
toolCalls.push({
|
|
7303
|
+
id: item.call_id ?? item.id ?? "",
|
|
7304
|
+
name: item.name ?? "",
|
|
7305
|
+
arguments: typeof item.arguments === "string" ? item.arguments : JSON.stringify(item.arguments ?? {})
|
|
7306
|
+
});
|
|
7307
|
+
} else if (item.type === "reasoning") {
|
|
7308
|
+
for (const s of item.summary ?? []) {
|
|
7309
|
+
if (typeof s.text === "string") summaryParts.push(s.text);
|
|
7310
|
+
}
|
|
7311
|
+
}
|
|
7312
|
+
}
|
|
7313
|
+
if (textParts.length === 0 && typeof json.output_text === "string") {
|
|
7314
|
+
textParts.push(json.output_text);
|
|
7315
|
+
}
|
|
7316
|
+
const usage = json.usage ?? {};
|
|
7317
|
+
const reasoningTokens = usage.output_tokens_details?.reasoning_tokens ?? 0;
|
|
7318
|
+
const tokenUsage = {
|
|
7319
|
+
inputTokens: usage.input_tokens ?? 0,
|
|
7320
|
+
outputTokens: usage.output_tokens ?? 0,
|
|
7321
|
+
totalTokens: usage.total_tokens ?? (usage.input_tokens ?? 0) + (usage.output_tokens ?? 0),
|
|
7322
|
+
cachedInputTokens: usage.input_tokens_details?.cached_tokens ?? 0,
|
|
7323
|
+
cachedWriteTokens: 0,
|
|
7324
|
+
cachedOutputTokens: 0,
|
|
7325
|
+
reasoningTokens
|
|
7326
|
+
};
|
|
7327
|
+
const finishReason = toolCalls.length > 0 ? "tool_calls" : json.status === "incomplete" ? "length" : "stop";
|
|
7328
|
+
return {
|
|
7329
|
+
id: json.id ?? "",
|
|
7330
|
+
model: json.model ?? modelId,
|
|
7331
|
+
content: textParts.join("") || null,
|
|
7332
|
+
toolCalls,
|
|
7333
|
+
usage: tokenUsage,
|
|
7334
|
+
finishReason,
|
|
7335
|
+
reasoning: summaryParts.length > 0 ? { summary: summaryParts.join("\n").trim() || void 0 } : void 0,
|
|
7336
|
+
raw: json
|
|
7337
|
+
};
|
|
7338
|
+
}
|
|
6995
7339
|
toOpenAIMessage(m) {
|
|
6996
7340
|
const msg = { role: m.role };
|
|
6997
7341
|
if (typeof m.content === "string") {
|
|
@@ -7084,6 +7428,25 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
7084
7428
|
};
|
|
7085
7429
|
}
|
|
7086
7430
|
};
|
|
7431
|
+
function isReasoningModel(model) {
|
|
7432
|
+
if (!model) return false;
|
|
7433
|
+
const m = model.toLowerCase();
|
|
7434
|
+
return /(^|[/_-])o[0-9]/.test(m) || m.startsWith("o1") || m.startsWith("o3") || m.startsWith("o4") || m.includes("gpt-5") || m.includes("gpt5");
|
|
7435
|
+
}
|
|
7436
|
+
function expandResponsesInput(input) {
|
|
7437
|
+
const out = [];
|
|
7438
|
+
for (const item of input) {
|
|
7439
|
+
if (item && item.__assistantWithCalls) {
|
|
7440
|
+
if (item.text) {
|
|
7441
|
+
out.push({ role: "assistant", content: [{ type: "output_text", text: item.text }] });
|
|
7442
|
+
}
|
|
7443
|
+
for (const call of item.calls) out.push(call);
|
|
7444
|
+
} else {
|
|
7445
|
+
out.push(item);
|
|
7446
|
+
}
|
|
7447
|
+
}
|
|
7448
|
+
return out;
|
|
7449
|
+
}
|
|
7087
7450
|
function mapFinishReason(reason) {
|
|
7088
7451
|
switch (reason) {
|
|
7089
7452
|
case "stop":
|
|
@@ -7129,6 +7492,7 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
7129
7492
|
let cacheReadInputTokens = 0;
|
|
7130
7493
|
let cacheCreationInputTokens = 0;
|
|
7131
7494
|
const currentToolCalls = /* @__PURE__ */ new Map();
|
|
7495
|
+
const reasoningBlocks = /* @__PURE__ */ new Map();
|
|
7132
7496
|
for await (const event of parseSSEStream(res.body)) {
|
|
7133
7497
|
let data;
|
|
7134
7498
|
try {
|
|
@@ -7158,6 +7522,10 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
7158
7522
|
name: block.name ?? "",
|
|
7159
7523
|
arguments: ""
|
|
7160
7524
|
});
|
|
7525
|
+
} else if (block?.type === "thinking") {
|
|
7526
|
+
reasoningBlocks.set(idx, { type: "thinking", text: block.thinking ?? "", signature: block.signature });
|
|
7527
|
+
} else if (block?.type === "redacted_thinking") {
|
|
7528
|
+
reasoningBlocks.set(idx, { type: "redacted_thinking", data: block.data });
|
|
7161
7529
|
}
|
|
7162
7530
|
break;
|
|
7163
7531
|
}
|
|
@@ -7170,6 +7538,19 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
7170
7538
|
model,
|
|
7171
7539
|
delta: { content: delta.text }
|
|
7172
7540
|
};
|
|
7541
|
+
} else if (delta?.type === "thinking_delta" && delta.thinking) {
|
|
7542
|
+
const blk = reasoningBlocks.get(idx) ?? { type: "thinking", text: "" };
|
|
7543
|
+
blk.text = (blk.text ?? "") + delta.thinking;
|
|
7544
|
+
reasoningBlocks.set(idx, blk);
|
|
7545
|
+
yield {
|
|
7546
|
+
id,
|
|
7547
|
+
model,
|
|
7548
|
+
delta: { reasoning: { summary: delta.thinking } }
|
|
7549
|
+
};
|
|
7550
|
+
} else if (delta?.type === "signature_delta" && delta.signature) {
|
|
7551
|
+
const blk = reasoningBlocks.get(idx) ?? { type: "thinking", text: "" };
|
|
7552
|
+
blk.signature = (blk.signature ?? "") + delta.signature;
|
|
7553
|
+
reasoningBlocks.set(idx, blk);
|
|
7173
7554
|
} else if (delta?.type === "input_json_delta" && delta.partial_json) {
|
|
7174
7555
|
const tc = currentToolCalls.get(idx);
|
|
7175
7556
|
if (tc) {
|
|
@@ -7202,10 +7583,13 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
7202
7583
|
cachedOutputTokens: 0,
|
|
7203
7584
|
reasoningTokens: 0
|
|
7204
7585
|
};
|
|
7586
|
+
const blocks = [...reasoningBlocks.values()].filter(
|
|
7587
|
+
(b) => b.type === "thinking" && b.signature || b.type === "redacted_thinking" && b.data
|
|
7588
|
+
);
|
|
7205
7589
|
yield {
|
|
7206
7590
|
id,
|
|
7207
7591
|
model,
|
|
7208
|
-
delta: {},
|
|
7592
|
+
delta: blocks.length > 0 ? { reasoning: { blocks } } : {},
|
|
7209
7593
|
finishReason,
|
|
7210
7594
|
usage
|
|
7211
7595
|
};
|
|
@@ -7297,6 +7681,7 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
7297
7681
|
}
|
|
7298
7682
|
if (m.role === "assistant" && m.toolCalls?.length) {
|
|
7299
7683
|
const content = [];
|
|
7684
|
+
appendReasoningBlocks(content, m.reasoning?.blocks);
|
|
7300
7685
|
if (typeof m.content === "string" && m.content) {
|
|
7301
7686
|
content.push({ type: "text", text: m.content });
|
|
7302
7687
|
}
|
|
@@ -7310,6 +7695,13 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
7310
7695
|
}
|
|
7311
7696
|
return { role: "assistant", content };
|
|
7312
7697
|
}
|
|
7698
|
+
if (m.role === "assistant" && m.reasoning?.blocks?.length) {
|
|
7699
|
+
const content = [];
|
|
7700
|
+
appendReasoningBlocks(content, m.reasoning.blocks);
|
|
7701
|
+
const text = typeof m.content === "string" ? m.content : "";
|
|
7702
|
+
if (text) content.push({ type: "text", text });
|
|
7703
|
+
return { role: "assistant", content };
|
|
7704
|
+
}
|
|
7313
7705
|
const msg = { role: m.role };
|
|
7314
7706
|
if (typeof m.content === "string") {
|
|
7315
7707
|
msg.content = m.content;
|
|
@@ -7365,9 +7757,20 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
7365
7757
|
parseResponse(json) {
|
|
7366
7758
|
const textParts = [];
|
|
7367
7759
|
const toolCalls = [];
|
|
7760
|
+
const reasoningBlocks = [];
|
|
7761
|
+
const summaryParts = [];
|
|
7368
7762
|
for (const block of json.content ?? []) {
|
|
7369
7763
|
if (block.type === "text") {
|
|
7370
7764
|
textParts.push(block.text);
|
|
7765
|
+
} else if (block.type === "thinking") {
|
|
7766
|
+
reasoningBlocks.push({
|
|
7767
|
+
type: "thinking",
|
|
7768
|
+
text: block.thinking ?? "",
|
|
7769
|
+
signature: block.signature
|
|
7770
|
+
});
|
|
7771
|
+
if (block.thinking) summaryParts.push(block.thinking);
|
|
7772
|
+
} else if (block.type === "redacted_thinking") {
|
|
7773
|
+
reasoningBlocks.push({ type: "redacted_thinking", data: block.data });
|
|
7371
7774
|
} else if (block.type === "tool_use") {
|
|
7372
7775
|
toolCalls.push({
|
|
7373
7776
|
id: block.id,
|
|
@@ -7384,6 +7787,9 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
7384
7787
|
cachedInputTokens: usage.cache_read_input_tokens ?? 0,
|
|
7385
7788
|
cachedWriteTokens: usage.cache_creation_input_tokens ?? 0,
|
|
7386
7789
|
cachedOutputTokens: 0,
|
|
7790
|
+
// Anthropic bills thinking tokens inside `output_tokens` and does not
|
|
7791
|
+
// expose a separate count, so reasoningTokens stays 0 here (cost is still
|
|
7792
|
+
// captured via outputTokens). See docs for the limitation.
|
|
7387
7793
|
reasoningTokens: 0
|
|
7388
7794
|
};
|
|
7389
7795
|
return {
|
|
@@ -7393,6 +7799,7 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
7393
7799
|
toolCalls,
|
|
7394
7800
|
usage: tokenUsage,
|
|
7395
7801
|
finishReason: mapAnthropicStopReason(json.stop_reason),
|
|
7802
|
+
reasoning: reasoningBlocks.length > 0 ? { blocks: reasoningBlocks, summary: summaryParts.join("\n").trim() || void 0 } : void 0,
|
|
7396
7803
|
raw: json
|
|
7397
7804
|
};
|
|
7398
7805
|
}
|
|
@@ -7417,6 +7824,18 @@ function safeJsonParse(str) {
|
|
|
7417
7824
|
return {};
|
|
7418
7825
|
}
|
|
7419
7826
|
}
|
|
7827
|
+
function appendReasoningBlocks(content, blocks) {
|
|
7828
|
+
if (!blocks?.length) return;
|
|
7829
|
+
for (const b of blocks) {
|
|
7830
|
+
if (b.type === "redacted_thinking") {
|
|
7831
|
+
if (b.data) content.push({ type: "redacted_thinking", data: b.data });
|
|
7832
|
+
} else if (b.type === "thinking") {
|
|
7833
|
+
if (b.signature) {
|
|
7834
|
+
content.push({ type: "thinking", thinking: b.text ?? "", signature: b.signature });
|
|
7835
|
+
}
|
|
7836
|
+
}
|
|
7837
|
+
}
|
|
7838
|
+
}
|
|
7420
7839
|
|
|
7421
7840
|
// src/providers/azure.ts
|
|
7422
7841
|
var AzureProvider = class extends OpenAIProvider {
|
|
@@ -7460,7 +7879,52 @@ var AzureProvider = class extends OpenAIProvider {
|
|
|
7460
7879
|
}
|
|
7461
7880
|
return res;
|
|
7462
7881
|
}
|
|
7882
|
+
/** Azure exposes the Responses API at /openai/responses with api-key auth.
|
|
7883
|
+
* Reasoning summaries require a preview api-version; callers can override via
|
|
7884
|
+
* the `apiVersion` config. */
|
|
7885
|
+
async responsesFetch(body) {
|
|
7886
|
+
body.input = expandAzureResponsesInput(body.input);
|
|
7887
|
+
const deployment = this.deploymentName ?? body.model;
|
|
7888
|
+
if (!deployment) {
|
|
7889
|
+
throw new ProviderError("Azure requires a deploymentName or model", this.providerName);
|
|
7890
|
+
}
|
|
7891
|
+
const url = `${this.endpoint}/openai/responses?api-version=${this.apiVersion}`;
|
|
7892
|
+
const payload = JSON.stringify({ ...body, model: deployment });
|
|
7893
|
+
const res = await fetch(url, {
|
|
7894
|
+
method: "POST",
|
|
7895
|
+
headers: {
|
|
7896
|
+
"Content-Type": "application/json",
|
|
7897
|
+
"api-key": this.azureApiKey,
|
|
7898
|
+
...this.defaultHeaders
|
|
7899
|
+
},
|
|
7900
|
+
body: payload
|
|
7901
|
+
});
|
|
7902
|
+
if (!res.ok) {
|
|
7903
|
+
const text = await res.text().catch(() => "");
|
|
7904
|
+
throw new ProviderError(
|
|
7905
|
+
`Azure OpenAI Responses API error ${res.status}: ${text}`,
|
|
7906
|
+
this.providerName,
|
|
7907
|
+
res.status,
|
|
7908
|
+
text
|
|
7909
|
+
);
|
|
7910
|
+
}
|
|
7911
|
+
return res;
|
|
7912
|
+
}
|
|
7463
7913
|
};
|
|
7914
|
+
function expandAzureResponsesInput(input) {
|
|
7915
|
+
const out = [];
|
|
7916
|
+
for (const item of input) {
|
|
7917
|
+
if (item && item.__assistantWithCalls) {
|
|
7918
|
+
if (item.text) {
|
|
7919
|
+
out.push({ role: "assistant", content: [{ type: "output_text", text: item.text }] });
|
|
7920
|
+
}
|
|
7921
|
+
for (const call of item.calls) out.push(call);
|
|
7922
|
+
} else {
|
|
7923
|
+
out.push(item);
|
|
7924
|
+
}
|
|
7925
|
+
}
|
|
7926
|
+
return out;
|
|
7927
|
+
}
|
|
7464
7928
|
|
|
7465
7929
|
// src/providers/openaiCompatible.ts
|
|
7466
7930
|
var OpenAICompatibleProvider = class extends OpenAIProvider {
|
|
@@ -7633,6 +8097,7 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
7633
8097
|
if (request.extra) {
|
|
7634
8098
|
Object.assign(body, request.extra);
|
|
7635
8099
|
}
|
|
8100
|
+
applyBedrockReasoning(body, request.reasoning);
|
|
7636
8101
|
return body;
|
|
7637
8102
|
}
|
|
7638
8103
|
splitSystemMessages(messages) {
|
|
@@ -7666,6 +8131,7 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
7666
8131
|
}
|
|
7667
8132
|
if (m.role === "assistant" && m.toolCalls?.length) {
|
|
7668
8133
|
const content2 = [];
|
|
8134
|
+
appendBedrockReasoning(content2, m.reasoning?.blocks);
|
|
7669
8135
|
if (typeof m.content === "string" && m.content) {
|
|
7670
8136
|
content2.push({ text: m.content });
|
|
7671
8137
|
}
|
|
@@ -7746,9 +8212,23 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
7746
8212
|
const output = json.output?.message;
|
|
7747
8213
|
const textParts = [];
|
|
7748
8214
|
const toolCalls = [];
|
|
8215
|
+
const reasoningBlocks = [];
|
|
8216
|
+
const summaryParts = [];
|
|
7749
8217
|
for (const block of output?.content ?? []) {
|
|
7750
8218
|
if (block.text) {
|
|
7751
8219
|
textParts.push(block.text);
|
|
8220
|
+
} else if (block.reasoningContent) {
|
|
8221
|
+
const rc = block.reasoningContent;
|
|
8222
|
+
if (rc.reasoningText) {
|
|
8223
|
+
reasoningBlocks.push({
|
|
8224
|
+
type: "thinking",
|
|
8225
|
+
text: rc.reasoningText.text ?? "",
|
|
8226
|
+
signature: rc.reasoningText.signature
|
|
8227
|
+
});
|
|
8228
|
+
if (rc.reasoningText.text) summaryParts.push(rc.reasoningText.text);
|
|
8229
|
+
} else if (rc.redactedContent) {
|
|
8230
|
+
reasoningBlocks.push({ type: "redacted_thinking", data: rc.redactedContent });
|
|
8231
|
+
}
|
|
7752
8232
|
} else if (block.toolUse) {
|
|
7753
8233
|
toolCalls.push({
|
|
7754
8234
|
id: block.toolUse.toolUseId,
|
|
@@ -7765,6 +8245,7 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
7765
8245
|
cachedInputTokens: usage.cacheReadInputTokenCount ?? 0,
|
|
7766
8246
|
cachedWriteTokens: usage.cacheWriteInputTokenCount ?? 0,
|
|
7767
8247
|
cachedOutputTokens: 0,
|
|
8248
|
+
// Bedrock bills thinking tokens inside outputTokens; no separate count.
|
|
7768
8249
|
reasoningTokens: 0
|
|
7769
8250
|
};
|
|
7770
8251
|
return {
|
|
@@ -7774,10 +8255,25 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
7774
8255
|
toolCalls,
|
|
7775
8256
|
usage: tokenUsage,
|
|
7776
8257
|
finishReason: mapBedrockStopReason(json.stopReason),
|
|
8258
|
+
reasoning: reasoningBlocks.length > 0 ? { blocks: reasoningBlocks, summary: summaryParts.join("\n").trim() || void 0 } : void 0,
|
|
7777
8259
|
raw: json
|
|
7778
8260
|
};
|
|
7779
8261
|
}
|
|
7780
8262
|
};
|
|
8263
|
+
function appendBedrockReasoning(content, blocks) {
|
|
8264
|
+
if (!blocks?.length) return;
|
|
8265
|
+
for (const b of blocks) {
|
|
8266
|
+
if (b.type === "redacted_thinking") {
|
|
8267
|
+
if (b.data) content.push({ reasoningContent: { redactedContent: b.data } });
|
|
8268
|
+
} else if (b.type === "thinking") {
|
|
8269
|
+
if (b.signature) {
|
|
8270
|
+
content.push({
|
|
8271
|
+
reasoningContent: { reasoningText: { text: b.text ?? "", signature: b.signature } }
|
|
8272
|
+
});
|
|
8273
|
+
}
|
|
8274
|
+
}
|
|
8275
|
+
}
|
|
8276
|
+
}
|
|
7781
8277
|
function mapBedrockStopReason(reason) {
|
|
7782
8278
|
switch (reason) {
|
|
7783
8279
|
case "end_turn":
|
|
@@ -8100,10 +8596,15 @@ var VertexProvider = class extends BaseProvider {
|
|
|
8100
8596
|
const parts = candidate?.content?.parts ?? [];
|
|
8101
8597
|
const textParts = [];
|
|
8102
8598
|
const toolCalls = [];
|
|
8599
|
+
const thoughtParts = [];
|
|
8103
8600
|
let toolCallIdx = 0;
|
|
8104
8601
|
for (const part of parts) {
|
|
8105
8602
|
if (part.text) {
|
|
8106
|
-
|
|
8603
|
+
if (part.thought === true) {
|
|
8604
|
+
thoughtParts.push(part.text);
|
|
8605
|
+
} else {
|
|
8606
|
+
textParts.push(part.text);
|
|
8607
|
+
}
|
|
8107
8608
|
} else if (part.functionCall) {
|
|
8108
8609
|
toolCalls.push({
|
|
8109
8610
|
id: `call_${toolCallIdx++}`,
|
|
@@ -8129,6 +8630,7 @@ var VertexProvider = class extends BaseProvider {
|
|
|
8129
8630
|
toolCalls,
|
|
8130
8631
|
usage: tokenUsage,
|
|
8131
8632
|
finishReason: mapGeminiFinishReason(candidate?.finishReason),
|
|
8633
|
+
reasoning: thoughtParts.length > 0 ? { summary: thoughtParts.join("\n").trim() || void 0 } : void 0,
|
|
8132
8634
|
raw: json
|
|
8133
8635
|
};
|
|
8134
8636
|
}
|
|
@@ -8138,7 +8640,11 @@ var VertexProvider = class extends BaseProvider {
|
|
|
8138
8640
|
const delta = {};
|
|
8139
8641
|
for (const part of parts) {
|
|
8140
8642
|
if (part.text) {
|
|
8141
|
-
|
|
8643
|
+
if (part.thought === true) {
|
|
8644
|
+
delta.reasoning = { summary: (delta.reasoning?.summary ?? "") + part.text };
|
|
8645
|
+
} else {
|
|
8646
|
+
delta.content = (delta.content ?? "") + part.text;
|
|
8647
|
+
}
|
|
8142
8648
|
} else if (part.functionCall) {
|
|
8143
8649
|
if (!delta.toolCalls) delta.toolCalls = [];
|
|
8144
8650
|
delta.toolCalls.push({
|
|
@@ -8212,12 +8718,16 @@ function fromNativeProvider(provider, options) {
|
|
|
8212
8718
|
let fullContent = "";
|
|
8213
8719
|
let allToolCalls = [];
|
|
8214
8720
|
let lastUsage;
|
|
8721
|
+
let reasoningBlocks;
|
|
8215
8722
|
const toolCallBuffers = /* @__PURE__ */ new Map();
|
|
8216
8723
|
for await (const chunk of provider.completeStream(request)) {
|
|
8217
8724
|
if (chunk.delta.content) {
|
|
8218
8725
|
fullContent += chunk.delta.content;
|
|
8219
8726
|
yield chunk.delta.content;
|
|
8220
8727
|
}
|
|
8728
|
+
if (chunk.delta.reasoning?.blocks?.length) {
|
|
8729
|
+
reasoningBlocks = chunk.delta.reasoning.blocks;
|
|
8730
|
+
}
|
|
8221
8731
|
if (chunk.delta.toolCalls) {
|
|
8222
8732
|
for (const tc of chunk.delta.toolCalls) {
|
|
8223
8733
|
if (tc.id) {
|
|
@@ -8238,6 +8748,9 @@ function fromNativeProvider(provider, options) {
|
|
|
8238
8748
|
}
|
|
8239
8749
|
allToolCalls = [...toolCallBuffers.values()];
|
|
8240
8750
|
const finalMessage = assembleMessage(fullContent, allToolCalls, lastUsage);
|
|
8751
|
+
if (reasoningBlocks?.length) {
|
|
8752
|
+
finalMessage.reasoning = { blocks: reasoningBlocks };
|
|
8753
|
+
}
|
|
8241
8754
|
yield finalMessage;
|
|
8242
8755
|
},
|
|
8243
8756
|
bindTools: (tools, _bindOptions) => {
|
|
@@ -8300,6 +8813,10 @@ function toUnifiedMessage(msg) {
|
|
|
8300
8813
|
arguments: tc.function?.arguments ?? tc.arguments ?? "{}"
|
|
8301
8814
|
}));
|
|
8302
8815
|
}
|
|
8816
|
+
const reasoning = msg.reasoning;
|
|
8817
|
+
if (reasoning && (reasoning.blocks?.length || reasoning.summary)) {
|
|
8818
|
+
unified.reasoning = reasoning;
|
|
8819
|
+
}
|
|
8303
8820
|
return unified;
|
|
8304
8821
|
}
|
|
8305
8822
|
function convertContent(content) {
|
|
@@ -8508,6 +9025,9 @@ function toBaseChatMessage(response) {
|
|
|
8508
9025
|
function: { name: tc.name, arguments: tc.arguments }
|
|
8509
9026
|
}));
|
|
8510
9027
|
}
|
|
9028
|
+
if (response.reasoning && (response.reasoning.blocks?.length || response.reasoning.summary)) {
|
|
9029
|
+
msg.reasoning = response.reasoning;
|
|
9030
|
+
}
|
|
8511
9031
|
return msg;
|
|
8512
9032
|
}
|
|
8513
9033
|
function assembleMessage(content, toolCalls, usage) {
|
|
@@ -8667,6 +9187,7 @@ exports.otlpSink = otlpSink;
|
|
|
8667
9187
|
exports.readMemoryFacts = readMemoryFacts;
|
|
8668
9188
|
exports.regexRule = regexRule;
|
|
8669
9189
|
exports.resolveMemoryStore = resolveMemoryStore;
|
|
9190
|
+
exports.resolveReasoning = resolveReasoning;
|
|
8670
9191
|
exports.resolveStrategy = resolveStrategy;
|
|
8671
9192
|
exports.resolveToolApprovalState = resolveToolApprovalState;
|
|
8672
9193
|
exports.resolveUserQuestionState = resolveUserQuestionState;
|
|
@@ -8675,6 +9196,7 @@ exports.runSmartAgentEvalHarness = runSmartAgentEvalHarness;
|
|
|
8675
9196
|
exports.setTokenCounter = setTokenCounter;
|
|
8676
9197
|
exports.startStreamingSession = startStreamingSession;
|
|
8677
9198
|
exports.traceSessionToOtlp = traceSessionToOtlp;
|
|
9199
|
+
exports.validateReasoningConfig = validateReasoningConfig;
|
|
8678
9200
|
exports.withTools = withTools;
|
|
8679
9201
|
exports.writeSummaryFactsToMemory = writeSummaryFactsToMemory;
|
|
8680
9202
|
//# sourceMappingURL=index.cjs.map
|