@cognipeer/agent-sdk 0.7.0 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +28 -1
- package/dist/index.cjs +784 -31
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +235 -3
- package/dist/index.d.ts +235 -3
- package/dist/index.mjs +771 -32
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -3026,6 +3026,17 @@ function createToolsNode(initialTools, opts) {
|
|
|
3026
3026
|
}
|
|
3027
3027
|
const durationMs = Date.now() - start;
|
|
3028
3028
|
const executionId = nanoid();
|
|
3029
|
+
if (output && typeof output === "object" && Array.isArray(output.__runtimeToolsDelta)) {
|
|
3030
|
+
const delta = output.__runtimeToolsDelta;
|
|
3031
|
+
delete output.__runtimeToolsDelta;
|
|
3032
|
+
const currentRuntime = state.agent || runtime;
|
|
3033
|
+
const currentTools = currentRuntime?.tools ?? [];
|
|
3034
|
+
const present = new Set(currentTools.map((tool2) => tool2?.name));
|
|
3035
|
+
const additions = delta.filter((tool2) => tool2 && tool2.name && !present.has(tool2.name));
|
|
3036
|
+
if (additions.length > 0 && currentRuntime) {
|
|
3037
|
+
state.agent = { ...currentRuntime, tools: [...currentTools, ...additions] };
|
|
3038
|
+
}
|
|
3039
|
+
}
|
|
3029
3040
|
if (output && typeof output === "object" && output.__handoff && output.__handoff.runtime) {
|
|
3030
3041
|
toolHistory.push({ executionId, toolName, args, output: "handoff:ok", rawOutput: output, timestamp: (/* @__PURE__ */ new Date()).toISOString(), tool_call_id: tc.id, status: "handoff" });
|
|
3031
3042
|
push({ role: "tool", content: "ok", tool_call_id: tc.id || `${tc.name}_${toolCount}`, name: tc.name });
|
|
@@ -3335,15 +3346,40 @@ function countToolCallsInLastTurn(state) {
|
|
|
3335
3346
|
function stripReflectionAskMessages(messages) {
|
|
3336
3347
|
return messages.filter((m) => !(m?.role === "user" && m?.name === REFLECTION_ASK_NAME));
|
|
3337
3348
|
}
|
|
3349
|
+
function lastTwoToolTurns(state) {
|
|
3350
|
+
const groups = [];
|
|
3351
|
+
let cur = [];
|
|
3352
|
+
let sawTool = false;
|
|
3353
|
+
for (let i = state.messages.length - 1; i >= 0; i--) {
|
|
3354
|
+
const m = state.messages[i];
|
|
3355
|
+
if (m?.role === "tool") {
|
|
3356
|
+
if (m.name) cur.push(m.name);
|
|
3357
|
+
sawTool = true;
|
|
3358
|
+
} else if (m?.role === "assistant") {
|
|
3359
|
+
if (sawTool) {
|
|
3360
|
+
groups.push(cur);
|
|
3361
|
+
cur = [];
|
|
3362
|
+
sawTool = false;
|
|
3363
|
+
if (groups.length >= 2) break;
|
|
3364
|
+
}
|
|
3365
|
+
}
|
|
3366
|
+
}
|
|
3367
|
+
if (sawTool && cur.length) groups.push(cur);
|
|
3368
|
+
return { current: groups[0] ?? [], previous: groups[1] ?? [] };
|
|
3369
|
+
}
|
|
3338
3370
|
function shouldRunReflection(cadence, state, ranToolsThisTurn) {
|
|
3339
3371
|
if (cadence === "off") return false;
|
|
3340
3372
|
if (cadence === "every_turn") return true;
|
|
3341
3373
|
if (cadence === "after_tool") return ranToolsThisTurn;
|
|
3374
|
+
if (cadence === "initial_then_after_tool") return ranToolsThisTurn;
|
|
3342
3375
|
if (cadence === "on_branch") {
|
|
3343
|
-
const
|
|
3344
|
-
|
|
3345
|
-
const
|
|
3346
|
-
|
|
3376
|
+
const { current, previous } = lastTwoToolTurns(state);
|
|
3377
|
+
if (previous.length === 0) return true;
|
|
3378
|
+
const a = new Set(current);
|
|
3379
|
+
const b = new Set(previous);
|
|
3380
|
+
for (const n of a) if (!b.has(n)) return true;
|
|
3381
|
+
for (const n of b) if (!a.has(n)) return true;
|
|
3382
|
+
return false;
|
|
3347
3383
|
}
|
|
3348
3384
|
return false;
|
|
3349
3385
|
}
|
|
@@ -3360,7 +3396,10 @@ function createReflectionNode(opts, resolved) {
|
|
|
3360
3396
|
const onEvent = state.ctx?.__onEvent;
|
|
3361
3397
|
const traceSession = state.ctx?.__traceSession;
|
|
3362
3398
|
const maxChars = resolved.maxChars;
|
|
3363
|
-
const
|
|
3399
|
+
const turnNow = state.toolCallCount ?? 0;
|
|
3400
|
+
const hookCtx = { state, turn: turnNow, trigger, ranToolsThisTurn: true };
|
|
3401
|
+
const defaultPrompt = (resolved.promptTemplate || DEFAULT_REFLECT_PROMPT).replace(/\$\{maxChars\}/g, String(maxChars));
|
|
3402
|
+
const promptBody = resolved.buildPrompt ? String(resolved.buildPrompt({ ...hookCtx, defaultPrompt, maxChars }) ?? defaultPrompt) : defaultPrompt;
|
|
3364
3403
|
const baseMessages = stripReflectionAskMessages([...state.messages]);
|
|
3365
3404
|
const askMessage = {
|
|
3366
3405
|
role: "user",
|
|
@@ -3394,6 +3433,8 @@ function createReflectionNode(opts, resolved) {
|
|
|
3394
3433
|
const rawText = extractText(response);
|
|
3395
3434
|
const text = trimToChars(String(rawText ?? "").trim(), maxChars);
|
|
3396
3435
|
if (!text) return {};
|
|
3436
|
+
const prevText = (state.reflections?.[state.reflections.length - 1]?.text || "").trim();
|
|
3437
|
+
if (prevText && isNearDuplicate(prevText, text)) return {};
|
|
3397
3438
|
const rawUsage = response?.usage_metadata || response?.response_metadata?.usage || response?.usage || response?.additional_kwargs?.usage;
|
|
3398
3439
|
const usage = normalizeUsage(rawUsage);
|
|
3399
3440
|
const { ids, names } = countToolCallsInLastTurn(state);
|
|
@@ -3442,6 +3483,12 @@ function createReflectionNode(opts, resolved) {
|
|
|
3442
3483
|
} catch (e) {
|
|
3443
3484
|
}
|
|
3444
3485
|
}
|
|
3486
|
+
if (resolved.onReflection) {
|
|
3487
|
+
try {
|
|
3488
|
+
resolved.onReflection(record, hookCtx);
|
|
3489
|
+
} catch {
|
|
3490
|
+
}
|
|
3491
|
+
}
|
|
3445
3492
|
const nextMessages = stripReflectionAskMessages([...state.messages]);
|
|
3446
3493
|
const reflections = [...state.reflections || [], record];
|
|
3447
3494
|
const kept = reflections.slice(-Math.max(1, resolved.keepLast));
|
|
@@ -3458,7 +3505,20 @@ ${r.text}
|
|
|
3458
3505
|
metadata: { reflectionId: r.id, reflectionTurn: r.turn, reflectionTrigger: r.trigger }
|
|
3459
3506
|
});
|
|
3460
3507
|
}
|
|
3461
|
-
|
|
3508
|
+
const patch = { messages: prunedMessages, reflections };
|
|
3509
|
+
if (resolved.feedTo === "memory") {
|
|
3510
|
+
const fact = {
|
|
3511
|
+
key: `reflection_turn_${turn}`,
|
|
3512
|
+
value: text,
|
|
3513
|
+
sourceTurn: turn,
|
|
3514
|
+
confidence: 0.3,
|
|
3515
|
+
tags: ["reflection"]
|
|
3516
|
+
};
|
|
3517
|
+
patch.memoryFacts = [...state.memoryFacts || [], fact];
|
|
3518
|
+
} else if (resolved.feedTo === "plan" && state.plan) {
|
|
3519
|
+
patch.plan = { ...state.plan, lastReflection: text };
|
|
3520
|
+
}
|
|
3521
|
+
return patch;
|
|
3462
3522
|
};
|
|
3463
3523
|
}
|
|
3464
3524
|
function extractText(chunk) {
|
|
@@ -3487,24 +3547,75 @@ function safeRandomId() {
|
|
|
3487
3547
|
return `r_${Math.random().toString(36).slice(2, 10)}_${Date.now().toString(36)}`;
|
|
3488
3548
|
}
|
|
3489
3549
|
}
|
|
3550
|
+
function isNearDuplicate(a, b) {
|
|
3551
|
+
const norm = (s) => s.toLowerCase().replace(/\s+/g, " ").trim();
|
|
3552
|
+
const na = norm(a);
|
|
3553
|
+
const nb = norm(b);
|
|
3554
|
+
if (na === nb) return true;
|
|
3555
|
+
const tokensA = new Set(na.split(" ").filter(Boolean));
|
|
3556
|
+
const tokensB = new Set(nb.split(" ").filter(Boolean));
|
|
3557
|
+
if (tokensA.size === 0 || tokensB.size === 0) return false;
|
|
3558
|
+
let inter = 0;
|
|
3559
|
+
for (const t of tokensA) if (tokensB.has(t)) inter++;
|
|
3560
|
+
const union = tokensA.size + tokensB.size - inter;
|
|
3561
|
+
return union > 0 && inter / union >= 0.9;
|
|
3562
|
+
}
|
|
3490
3563
|
|
|
3491
3564
|
// src/smart/reasoning.ts
|
|
3492
3565
|
var LEVEL_DEFAULTS = {
|
|
3566
|
+
minimal: {
|
|
3567
|
+
native: { effort: "minimal" },
|
|
3568
|
+
reflection: { maxTokens: 150, maxChars: 400, cadence: "off" }
|
|
3569
|
+
},
|
|
3493
3570
|
low: {
|
|
3494
3571
|
native: { effort: "low" },
|
|
3495
3572
|
reflection: { maxTokens: 200, maxChars: 600, cadence: "on_branch" }
|
|
3496
3573
|
},
|
|
3497
3574
|
medium: {
|
|
3498
3575
|
native: { effort: "medium" },
|
|
3499
|
-
reflection: { maxTokens: 350, maxChars: 1200, cadence: "
|
|
3576
|
+
reflection: { maxTokens: 350, maxChars: 1200, cadence: "initial_then_after_tool" }
|
|
3500
3577
|
},
|
|
3501
3578
|
high: {
|
|
3502
3579
|
native: { effort: "high" },
|
|
3503
|
-
reflection: { maxTokens: 600, maxChars: 2e3, cadence: "
|
|
3580
|
+
reflection: { maxTokens: 600, maxChars: 2e3, cadence: "initial_then_after_tool" }
|
|
3504
3581
|
}
|
|
3505
3582
|
};
|
|
3583
|
+
var VALID_LEVELS = ["minimal", "low", "medium", "high"];
|
|
3584
|
+
var VALID_CADENCES = ["off", "every_turn", "after_tool", "on_branch", "initial_then_after_tool"];
|
|
3585
|
+
var VALID_EFFORTS = ["minimal", "low", "medium", "high"];
|
|
3586
|
+
function validateReasoningConfig(input) {
|
|
3587
|
+
if (!input) return;
|
|
3588
|
+
if (input.level !== void 0 && !VALID_LEVELS.includes(input.level)) {
|
|
3589
|
+
throw new Error(`reasoning.level must be one of ${VALID_LEVELS.join(", ")} (got "${input.level}")`);
|
|
3590
|
+
}
|
|
3591
|
+
if (input.native) {
|
|
3592
|
+
const n = input.native;
|
|
3593
|
+
if (n.effort !== void 0 && !VALID_EFFORTS.includes(n.effort)) {
|
|
3594
|
+
throw new Error(`reasoning.native.effort must be one of ${VALID_EFFORTS.join(", ")} (got "${n.effort}")`);
|
|
3595
|
+
}
|
|
3596
|
+
if (n.budgetTokens !== void 0 && (!Number.isFinite(n.budgetTokens) || n.budgetTokens < 0)) {
|
|
3597
|
+
throw new Error(`reasoning.native.budgetTokens must be a non-negative number (got ${n.budgetTokens})`);
|
|
3598
|
+
}
|
|
3599
|
+
}
|
|
3600
|
+
if (input.reflection) {
|
|
3601
|
+
const r = input.reflection;
|
|
3602
|
+
if (r.cadence !== void 0 && !VALID_CADENCES.includes(r.cadence)) {
|
|
3603
|
+
throw new Error(`reasoning.reflection.cadence must be one of ${VALID_CADENCES.join(", ")} (got "${r.cadence}")`);
|
|
3604
|
+
}
|
|
3605
|
+
if (r.maxPerRun !== void 0 && (!Number.isFinite(r.maxPerRun) || r.maxPerRun < 0)) {
|
|
3606
|
+
throw new Error(`reasoning.reflection.maxPerRun must be a non-negative number (got ${r.maxPerRun})`);
|
|
3607
|
+
}
|
|
3608
|
+
if (r.everyNTurns !== void 0 && (!Number.isFinite(r.everyNTurns) || r.everyNTurns < 1)) {
|
|
3609
|
+
throw new Error(`reasoning.reflection.everyNTurns must be >= 1 (got ${r.everyNTurns})`);
|
|
3610
|
+
}
|
|
3611
|
+
if (r.feedTo !== void 0 && !["memory", "plan", "none"].includes(r.feedTo)) {
|
|
3612
|
+
throw new Error(`reasoning.reflection.feedTo must be "memory", "plan", or "none" (got "${r.feedTo}")`);
|
|
3613
|
+
}
|
|
3614
|
+
}
|
|
3615
|
+
}
|
|
3506
3616
|
function resolveReasoning(input) {
|
|
3507
3617
|
if (!input || input.enabled === false) return void 0;
|
|
3618
|
+
validateReasoningConfig(input);
|
|
3508
3619
|
const enabled = input.enabled ?? (input.native !== void 0 || input.reflection !== void 0 || input.level !== void 0);
|
|
3509
3620
|
if (!enabled) return void 0;
|
|
3510
3621
|
const level = input.level ?? "medium";
|
|
@@ -3529,7 +3640,8 @@ function resolveReflection(input, preset) {
|
|
|
3529
3640
|
keepLast: 3,
|
|
3530
3641
|
summarize: false,
|
|
3531
3642
|
emitEvents: true,
|
|
3532
|
-
everyNTurns: 1
|
|
3643
|
+
everyNTurns: 1,
|
|
3644
|
+
feedTo: "none"
|
|
3533
3645
|
};
|
|
3534
3646
|
}
|
|
3535
3647
|
const cfg = input ?? {};
|
|
@@ -3546,7 +3658,11 @@ function resolveReflection(input, preset) {
|
|
|
3546
3658
|
promptTemplate: cfg.promptTemplate,
|
|
3547
3659
|
emitEvents: cfg.emitEvents ?? true,
|
|
3548
3660
|
maxPerRun: typeof cfg.maxPerRun === "number" && cfg.maxPerRun >= 0 ? cfg.maxPerRun : void 0,
|
|
3549
|
-
everyNTurns: Math.max(1, Math.trunc(cfg.everyNTurns ?? 1))
|
|
3661
|
+
everyNTurns: Math.max(1, Math.trunc(cfg.everyNTurns ?? 1)),
|
|
3662
|
+
feedTo: cfg.feedTo ?? "none",
|
|
3663
|
+
shouldReflect: cfg.shouldReflect,
|
|
3664
|
+
buildPrompt: cfg.buildPrompt,
|
|
3665
|
+
onReflection: cfg.onReflection
|
|
3550
3666
|
};
|
|
3551
3667
|
}
|
|
3552
3668
|
function ensureArray(value) {
|
|
@@ -4272,12 +4388,14 @@ function createAgent(opts) {
|
|
|
4272
4388
|
if (summarizationThreshold === void 0) {
|
|
4273
4389
|
state = clearNeedsSummarization(state);
|
|
4274
4390
|
}
|
|
4275
|
-
if (resolvedReasoning
|
|
4391
|
+
if (resolvedReasoning) {
|
|
4276
4392
|
const ctx = { ...state.ctx || {} };
|
|
4277
|
-
if (
|
|
4393
|
+
if (resolvedReasoning.native) {
|
|
4278
4394
|
ctx.__reasoning = resolvedReasoning.native;
|
|
4279
|
-
|
|
4395
|
+
} else {
|
|
4396
|
+
delete ctx.__reasoning;
|
|
4280
4397
|
}
|
|
4398
|
+
state = { ...state, ctx: Object.keys(ctx).length > 0 ? ctx : void 0 };
|
|
4281
4399
|
}
|
|
4282
4400
|
const mergedLimits = {
|
|
4283
4401
|
...opts.limits || {},
|
|
@@ -4325,6 +4443,7 @@ function createAgent(opts) {
|
|
|
4325
4443
|
return { breached: false };
|
|
4326
4444
|
};
|
|
4327
4445
|
let iterations = 0;
|
|
4446
|
+
let reflectionsThisRun = 0;
|
|
4328
4447
|
const onStateChange = config?.onStateChange;
|
|
4329
4448
|
const checkpointReason = config?.checkpointReason;
|
|
4330
4449
|
let pausedStage = null;
|
|
@@ -4370,6 +4489,16 @@ function createAgent(opts) {
|
|
|
4370
4489
|
pausedStage = stage;
|
|
4371
4490
|
return true;
|
|
4372
4491
|
};
|
|
4492
|
+
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")) {
|
|
4493
|
+
try {
|
|
4494
|
+
const patch = await reflectNode(state, "initial_then_after_tool");
|
|
4495
|
+
if (patch && Object.keys(patch).length > 0) {
|
|
4496
|
+
state = { ...state, ...patch };
|
|
4497
|
+
reflectionsThisRun++;
|
|
4498
|
+
}
|
|
4499
|
+
} catch {
|
|
4500
|
+
}
|
|
4501
|
+
}
|
|
4373
4502
|
while (iterations < iterationLimit) {
|
|
4374
4503
|
iterations++;
|
|
4375
4504
|
const budget = checkBudgetBreached();
|
|
@@ -4546,16 +4675,18 @@ function createAgent(opts) {
|
|
|
4546
4675
|
if (reflectNode && resolvedReasoning?.reflection.enabled) {
|
|
4547
4676
|
const cadence = resolvedReasoning.reflection.cadence;
|
|
4548
4677
|
const refl = resolvedReasoning.reflection;
|
|
4549
|
-
const reflectionsSoFar = state.reflections?.length ?? 0;
|
|
4550
4678
|
const lastTurn = state.reflections?.at(-1)?.turn ?? -Infinity;
|
|
4551
4679
|
const currentTurn = state.toolCallCount || 0;
|
|
4552
|
-
const budgetExceeded = typeof refl.maxPerRun === "number" &&
|
|
4553
|
-
const
|
|
4554
|
-
|
|
4680
|
+
const budgetExceeded = typeof refl.maxPerRun === "number" && reflectionsThisRun >= refl.maxPerRun;
|
|
4681
|
+
const sinceLast = currentTurn - (Number.isFinite(lastTurn) ? lastTurn : -refl.everyNTurns);
|
|
4682
|
+
const cadenceGap = sinceLast < refl.everyNTurns;
|
|
4683
|
+
const cadenceWantsIt = refl.shouldReflect ? !!refl.shouldReflect({ state, turn: currentTurn, trigger: cadence, ranToolsThisTurn: true }) : shouldRunReflection(cadence, state, true);
|
|
4684
|
+
if (!budgetExceeded && !cadenceGap && cadenceWantsIt) {
|
|
4555
4685
|
try {
|
|
4556
4686
|
const patch = await reflectNode(state, cadence);
|
|
4557
4687
|
if (patch && Object.keys(patch).length > 0) {
|
|
4558
4688
|
state = { ...state, ...patch };
|
|
4689
|
+
reflectionsThisRun++;
|
|
4559
4690
|
}
|
|
4560
4691
|
} catch {
|
|
4561
4692
|
}
|
|
@@ -6063,6 +6194,190 @@ async function writeSummaryFactsToMemory(store, config, summary, sourceTurn) {
|
|
|
6063
6194
|
return store.get(config.memory.scope, { limit: config.context.lastTurnsToKeep + summary.stable_facts.length });
|
|
6064
6195
|
}
|
|
6065
6196
|
|
|
6197
|
+
// src/smart/skills/types.ts
|
|
6198
|
+
var DEFAULT_SKILL_POLICY = {
|
|
6199
|
+
maxOpenSkills: 4,
|
|
6200
|
+
maxBoundToolsPerSkill: 12,
|
|
6201
|
+
maxBoundToolsTotal: 40
|
|
6202
|
+
};
|
|
6203
|
+
var SMALL_TIER_SKILL_POLICY = {
|
|
6204
|
+
maxOpenSkills: 1,
|
|
6205
|
+
maxBoundToolsPerSkill: 6,
|
|
6206
|
+
maxBoundToolsTotal: 18,
|
|
6207
|
+
modelTier: "small"
|
|
6208
|
+
};
|
|
6209
|
+
function createSkillRegistryRef() {
|
|
6210
|
+
return { openedSkillKeys: [], boundSkillTools: [] };
|
|
6211
|
+
}
|
|
6212
|
+
|
|
6213
|
+
// src/smart/skills/registry.ts
|
|
6214
|
+
function composeToolSets(input) {
|
|
6215
|
+
const without = [...input.base, ...input.boundSkillTools];
|
|
6216
|
+
const withRec = input.recoveryTool ? [...without, input.recoveryTool] : [...without];
|
|
6217
|
+
return { toolsWithoutRecovery: without, toolsWithRecovery: withRec };
|
|
6218
|
+
}
|
|
6219
|
+
function appendBoundTools(ref, newTools, policy) {
|
|
6220
|
+
const present = new Set(ref.boundSkillTools.map((tool) => tool.name));
|
|
6221
|
+
const added = [];
|
|
6222
|
+
for (const tool of newTools) {
|
|
6223
|
+
if (ref.boundSkillTools.length >= policy.maxBoundToolsTotal) break;
|
|
6224
|
+
if (present.has(tool.name)) continue;
|
|
6225
|
+
present.add(tool.name);
|
|
6226
|
+
ref.boundSkillTools.push(tool);
|
|
6227
|
+
added.push(tool);
|
|
6228
|
+
}
|
|
6229
|
+
return added;
|
|
6230
|
+
}
|
|
6231
|
+
function canOpenSkill(ref, policy) {
|
|
6232
|
+
if (ref.openedSkillKeys.length >= policy.maxOpenSkills) {
|
|
6233
|
+
return { ok: false, reason: `max ${policy.maxOpenSkills} skill(s) already open` };
|
|
6234
|
+
}
|
|
6235
|
+
if (ref.boundSkillTools.length >= policy.maxBoundToolsTotal) {
|
|
6236
|
+
return { ok: false, reason: "skill tool budget exhausted" };
|
|
6237
|
+
}
|
|
6238
|
+
return { ok: true };
|
|
6239
|
+
}
|
|
6240
|
+
async function resolveAvailableSkills(skills, opts = {}) {
|
|
6241
|
+
const out = [];
|
|
6242
|
+
for (const skill of skills) {
|
|
6243
|
+
if (skill.minModelTier === "large" && opts.modelTier === "small") continue;
|
|
6244
|
+
const available = skill.isAvailable ? await skill.isAvailable() : true;
|
|
6245
|
+
if (available) out.push(skill);
|
|
6246
|
+
}
|
|
6247
|
+
return out;
|
|
6248
|
+
}
|
|
6249
|
+
function buildSkillHeaderBlock(skills) {
|
|
6250
|
+
if (skills.length === 0) return "";
|
|
6251
|
+
const lines = skills.map((skill) => `- ${skill.key}: ${skill.header}`);
|
|
6252
|
+
return [
|
|
6253
|
+
"<available_skills>",
|
|
6254
|
+
"Open a skill with open_skill(skillKey) to load its tools on demand. Only open what the task needs; close nothing \u2014 opened skills stay available for the rest of the run.",
|
|
6255
|
+
...lines,
|
|
6256
|
+
"</available_skills>"
|
|
6257
|
+
].join("\n");
|
|
6258
|
+
}
|
|
6259
|
+
function dedupeToolsByName(tools) {
|
|
6260
|
+
const seen = /* @__PURE__ */ new Set();
|
|
6261
|
+
const out = [];
|
|
6262
|
+
for (const tool of tools) {
|
|
6263
|
+
if (seen.has(tool.name)) continue;
|
|
6264
|
+
seen.add(tool.name);
|
|
6265
|
+
out.push(tool);
|
|
6266
|
+
}
|
|
6267
|
+
return out;
|
|
6268
|
+
}
|
|
6269
|
+
|
|
6270
|
+
// src/smart/skills/skillTools.ts
|
|
6271
|
+
var MAX_RETURNED_INDEX = 40;
|
|
6272
|
+
var OPEN_SKILL_DESCRIPTION = "Load a capability on demand. Pass a skillKey from <available_skills>. A small skill binds all its tools immediately; a large one returns a tool index \u2014 then call bind_skill_tools with only the tools you need. Open only what the task needs.";
|
|
6273
|
+
var BIND_SKILL_TOOLS_DESCRIPTION = "After open_skill on a large skill, bind a chosen subset of its tools by name. Pick the few tools the task actually needs.";
|
|
6274
|
+
function findSkill(deps, key) {
|
|
6275
|
+
return deps.skills.find((skill) => skill.key === key);
|
|
6276
|
+
}
|
|
6277
|
+
function createOpenSkillTool(deps) {
|
|
6278
|
+
const tool = createTool({
|
|
6279
|
+
name: "open_skill",
|
|
6280
|
+
description: OPEN_SKILL_DESCRIPTION,
|
|
6281
|
+
schema: z.object({
|
|
6282
|
+
skillKey: z.string().min(1).describe("A key from <available_skills>."),
|
|
6283
|
+
query: z.string().optional().describe("What you need from the skill \u2014 used to rank a large skill's tools.")
|
|
6284
|
+
}).strict(),
|
|
6285
|
+
func: async ({ skillKey, query }) => {
|
|
6286
|
+
const { registryRef: ref, policy } = tool._deps;
|
|
6287
|
+
const skill = findSkill(tool._deps, skillKey);
|
|
6288
|
+
if (!skill) {
|
|
6289
|
+
return { error: `Unknown skill: ${skillKey}. Choose a key listed in <available_skills>.` };
|
|
6290
|
+
}
|
|
6291
|
+
if (skill.isAvailable && !await skill.isAvailable()) {
|
|
6292
|
+
return { error: `Skill ${skillKey} is not available in this workspace.` };
|
|
6293
|
+
}
|
|
6294
|
+
const alreadyOpen = ref.openedSkillKeys.includes(skillKey);
|
|
6295
|
+
if (!alreadyOpen) {
|
|
6296
|
+
const guard = canOpenSkill(ref, policy);
|
|
6297
|
+
if (!guard.ok) {
|
|
6298
|
+
return {
|
|
6299
|
+
error: `Cannot open ${skillKey}: ${guard.reason}. Work with the skills already open.`
|
|
6300
|
+
};
|
|
6301
|
+
}
|
|
6302
|
+
ref.openedSkillKeys.push(skillKey);
|
|
6303
|
+
}
|
|
6304
|
+
const prompt = typeof skill.prompt === "function" ? await skill.prompt() : skill.prompt;
|
|
6305
|
+
const index = await skill.listToolIndex();
|
|
6306
|
+
if (index.length <= policy.maxBoundToolsPerSkill) {
|
|
6307
|
+
const bound = await skill.bindTools();
|
|
6308
|
+
const added = appendBoundTools(ref, bound, policy);
|
|
6309
|
+
if (added.length > 0) ref.__onToolsChanged?.();
|
|
6310
|
+
return {
|
|
6311
|
+
skillKey,
|
|
6312
|
+
prompt,
|
|
6313
|
+
needsSandbox: Boolean(skill.needsSandbox),
|
|
6314
|
+
boundTools: added.map((t) => t.name),
|
|
6315
|
+
// Inject the bound tools into the live runtime for this loop.
|
|
6316
|
+
__runtimeToolsDelta: added
|
|
6317
|
+
};
|
|
6318
|
+
}
|
|
6319
|
+
let defaultBound = [];
|
|
6320
|
+
let defaultAdded = [];
|
|
6321
|
+
if ((!query || query.trim().length < 3) && skill.defaultBindNames?.length) {
|
|
6322
|
+
const bound = await skill.bindTools(skill.defaultBindNames.slice(0, policy.maxBoundToolsPerSkill));
|
|
6323
|
+
defaultAdded = appendBoundTools(ref, bound, policy);
|
|
6324
|
+
if (defaultAdded.length > 0) ref.__onToolsChanged?.();
|
|
6325
|
+
defaultBound = defaultAdded.map((t) => t.name);
|
|
6326
|
+
}
|
|
6327
|
+
const headers = query && query.trim().length >= 3 && skill.rankToolHeaders ? await skill.rankToolHeaders(query, index) : index;
|
|
6328
|
+
return {
|
|
6329
|
+
skillKey,
|
|
6330
|
+
prompt,
|
|
6331
|
+
needsSandbox: Boolean(skill.needsSandbox),
|
|
6332
|
+
boundTools: defaultBound,
|
|
6333
|
+
toolIndex: headers.slice(0, MAX_RETURNED_INDEX).map((h) => ({ name: h.name, description: h.description })),
|
|
6334
|
+
hint: "Call bind_skill_tools(skillKey, toolNames) with only the tools you need.",
|
|
6335
|
+
...defaultAdded.length > 0 ? { __runtimeToolsDelta: defaultAdded } : {}
|
|
6336
|
+
};
|
|
6337
|
+
}
|
|
6338
|
+
});
|
|
6339
|
+
tool._deps = deps;
|
|
6340
|
+
tool.__source = "smart-skills";
|
|
6341
|
+
return tool;
|
|
6342
|
+
}
|
|
6343
|
+
function createBindSkillToolsTool(deps) {
|
|
6344
|
+
const tool = createTool({
|
|
6345
|
+
name: "bind_skill_tools",
|
|
6346
|
+
description: BIND_SKILL_TOOLS_DESCRIPTION,
|
|
6347
|
+
schema: z.object({
|
|
6348
|
+
skillKey: z.string().min(1),
|
|
6349
|
+
toolNames: z.array(z.string().min(1)).min(1).describe("Tool names from the skill's index.")
|
|
6350
|
+
}).strict(),
|
|
6351
|
+
func: async ({ skillKey, toolNames }) => {
|
|
6352
|
+
const { registryRef: ref, policy } = tool._deps;
|
|
6353
|
+
const skill = findSkill(tool._deps, skillKey);
|
|
6354
|
+
if (!skill) {
|
|
6355
|
+
return { error: `Unknown skill: ${skillKey}.` };
|
|
6356
|
+
}
|
|
6357
|
+
if (!ref.openedSkillKeys.includes(skillKey)) {
|
|
6358
|
+
return { error: `Call open_skill("${skillKey}") before binding its tools.` };
|
|
6359
|
+
}
|
|
6360
|
+
const capped = toolNames.slice(0, policy.maxBoundToolsPerSkill);
|
|
6361
|
+
const bound = await skill.bindTools(capped);
|
|
6362
|
+
const added = appendBoundTools(ref, bound, policy);
|
|
6363
|
+
if (added.length > 0) ref.__onToolsChanged?.();
|
|
6364
|
+
return {
|
|
6365
|
+
skillKey,
|
|
6366
|
+
boundTools: added.map((t) => t.name),
|
|
6367
|
+
requested: capped.length,
|
|
6368
|
+
truncated: toolNames.length > capped.length,
|
|
6369
|
+
...added.length > 0 ? { __runtimeToolsDelta: added } : {}
|
|
6370
|
+
};
|
|
6371
|
+
}
|
|
6372
|
+
});
|
|
6373
|
+
tool._deps = deps;
|
|
6374
|
+
tool.__source = "smart-skills";
|
|
6375
|
+
return tool;
|
|
6376
|
+
}
|
|
6377
|
+
function createSkillTools(deps) {
|
|
6378
|
+
return [createOpenSkillTool(deps), createBindSkillToolsTool(deps)];
|
|
6379
|
+
}
|
|
6380
|
+
|
|
6066
6381
|
// src/smart/index.ts
|
|
6067
6382
|
function createSmartAgent(opts) {
|
|
6068
6383
|
const resolved = normalizeSmartAgentOptions(opts);
|
|
@@ -6097,6 +6412,9 @@ function createSmartAgent(opts) {
|
|
|
6097
6412
|
if (askUserConfig) {
|
|
6098
6413
|
factoryToolsWithoutRecovery.push(createAskUserQuestionTool(factoryStateRef, askUserConfig));
|
|
6099
6414
|
}
|
|
6415
|
+
const skills = opts.skills ?? [];
|
|
6416
|
+
const skillPolicy = opts.skillPolicy ?? DEFAULT_SKILL_POLICY;
|
|
6417
|
+
const skillsEnabled = skills.length > 0;
|
|
6100
6418
|
const soManagerFactory = opts.outputSchema ? new StructuredOutputManager(opts.outputSchema, resolveStrategy(opts.model)) : void 0;
|
|
6101
6419
|
const modelCapabilities = opts.outputSchema ? getModelCapabilities(opts.model) : void 0;
|
|
6102
6420
|
const responseFinalizeTool = soManagerFactory && modelCapabilities?.structuredOutput !== "native" ? soManagerFactory.getResponseTool() : void 0;
|
|
@@ -6104,12 +6422,31 @@ function createSmartAgent(opts) {
|
|
|
6104
6422
|
const ref = { toolHistory: void 0, toolHistoryArchived: void 0, todoList: void 0, planVersion: 0, adherenceScore: 0 };
|
|
6105
6423
|
const ctxTools = createContextTools(ref, { planningEnabled, includeGetToolResponse: false });
|
|
6106
6424
|
const recoveryTool = createGetToolResponseTool(ref);
|
|
6107
|
-
const
|
|
6108
|
-
if (responseFinalizeTool)
|
|
6109
|
-
if (askUserConfig)
|
|
6110
|
-
|
|
6111
|
-
|
|
6112
|
-
|
|
6425
|
+
const coreBase = [...userTools, ...ctxTools];
|
|
6426
|
+
if (responseFinalizeTool) coreBase.push(responseFinalizeTool);
|
|
6427
|
+
if (askUserConfig) coreBase.push(createAskUserQuestionTool(ref, askUserConfig));
|
|
6428
|
+
if (!skillsEnabled) {
|
|
6429
|
+
const without = coreBase;
|
|
6430
|
+
const withRec = [...without, recoveryTool];
|
|
6431
|
+
return { stateRef: ref, toolsWithoutRecovery: without, toolsWithRecovery: withRec };
|
|
6432
|
+
}
|
|
6433
|
+
const toolSet = { stateRef: ref, toolsWithoutRecovery: [], toolsWithRecovery: [] };
|
|
6434
|
+
const skillRegistryRef = createSkillRegistryRef();
|
|
6435
|
+
const skillMetaTools = createSkillTools({ registryRef: skillRegistryRef, skills, policy: skillPolicy });
|
|
6436
|
+
const baseWithMeta = [...coreBase, ...skillMetaTools];
|
|
6437
|
+
const rebuild = () => {
|
|
6438
|
+
const composed = composeToolSets({
|
|
6439
|
+
base: baseWithMeta,
|
|
6440
|
+
boundSkillTools: skillRegistryRef.boundSkillTools,
|
|
6441
|
+
recoveryTool
|
|
6442
|
+
});
|
|
6443
|
+
toolSet.toolsWithoutRecovery = composed.toolsWithoutRecovery;
|
|
6444
|
+
toolSet.toolsWithRecovery = composed.toolsWithRecovery;
|
|
6445
|
+
};
|
|
6446
|
+
skillRegistryRef.__onToolsChanged = rebuild;
|
|
6447
|
+
toolSet.skillRegistryRef = skillRegistryRef;
|
|
6448
|
+
rebuild();
|
|
6449
|
+
return toolSet;
|
|
6113
6450
|
};
|
|
6114
6451
|
const base = createAgent({ ...runtimeOpts, tools: factoryToolsWithoutRecovery });
|
|
6115
6452
|
base.__runtime.runtimeProfile = resolved.runtimeProfile;
|
|
@@ -6160,9 +6497,9 @@ function createSmartAgent(opts) {
|
|
|
6160
6497
|
planVersion: ref.planVersion || state.planVersion || 1
|
|
6161
6498
|
};
|
|
6162
6499
|
}
|
|
6163
|
-
function systemMessage2() {
|
|
6500
|
+
function systemMessage2(extraBlock) {
|
|
6164
6501
|
const sys = buildSystemPrompt(
|
|
6165
|
-
[opts.systemPrompt, runtimeHint, structuredOutputHint].filter(Boolean).join("\n"),
|
|
6502
|
+
[opts.systemPrompt, runtimeHint, structuredOutputHint, extraBlock].filter(Boolean).join("\n"),
|
|
6166
6503
|
planningEnabled,
|
|
6167
6504
|
opts.name || "Agent",
|
|
6168
6505
|
opts.todoListPrompt
|
|
@@ -6212,8 +6549,10 @@ function createSmartAgent(opts) {
|
|
|
6212
6549
|
stateRef.planVersion = input.planVersion || input.plan?.version || 0;
|
|
6213
6550
|
stateRef.adherenceScore = input.plan?.adherenceScore || 0;
|
|
6214
6551
|
const syncPlanFromRef = (state2) => syncPlanStateWith(stateRef, state2);
|
|
6552
|
+
const availableSkills = skillsEnabled ? await resolveAvailableSkills(skills, { modelTier: skillPolicy.modelTier }) : [];
|
|
6553
|
+
const skillBlock = availableSkills.length > 0 ? buildSkillHeaderBlock(availableSkills) : void 0;
|
|
6215
6554
|
const alreadyHasSystem = Array.isArray(input.messages) && input.messages[0]?.role === "system";
|
|
6216
|
-
const seedMessages = alreadyHasSystem ? [...input.messages || []] : [systemMessage2(), ...input.messages || []];
|
|
6555
|
+
const seedMessages = alreadyHasSystem ? [...input.messages || []] : [systemMessage2(skillBlock), ...input.messages || []];
|
|
6217
6556
|
let state = syncRuntimeTools(await syncMemory({ ...input, messages: seedMessages }), seedMessages, toolSet);
|
|
6218
6557
|
let lastResult = null;
|
|
6219
6558
|
let rawMessages = [...seedMessages];
|
|
@@ -6818,6 +7157,20 @@ function parseSSEBlock(block) {
|
|
|
6818
7157
|
}
|
|
6819
7158
|
|
|
6820
7159
|
// src/providers/utils/reasoning.ts
|
|
7160
|
+
var ANTHROPIC_EFFORT_BUDGET = {
|
|
7161
|
+
minimal: 1024,
|
|
7162
|
+
low: 2048,
|
|
7163
|
+
medium: 8192,
|
|
7164
|
+
high: 16384
|
|
7165
|
+
};
|
|
7166
|
+
var GEMINI_EFFORT_BUDGET = {
|
|
7167
|
+
minimal: 512,
|
|
7168
|
+
low: 1024,
|
|
7169
|
+
medium: 4096,
|
|
7170
|
+
high: 12e3
|
|
7171
|
+
};
|
|
7172
|
+
var THINKING_OUTPUT_RESERVE = 1024;
|
|
7173
|
+
var THINKING_MIN_MAX_TOKENS = 4096;
|
|
6821
7174
|
function applyOpenAIReasoning(body, reasoning, mode = "legacy_effort") {
|
|
6822
7175
|
if (!reasoning) return;
|
|
6823
7176
|
const effort = normalizeEffort(reasoning.effort);
|
|
@@ -6834,21 +7187,56 @@ function applyOpenAIReasoning(body, reasoning, mode = "legacy_effort") {
|
|
|
6834
7187
|
}
|
|
6835
7188
|
function applyAnthropicReasoning(body, reasoning) {
|
|
6836
7189
|
if (!reasoning) return;
|
|
6837
|
-
|
|
7190
|
+
let budget = resolveBudget(reasoning, ANTHROPIC_EFFORT_BUDGET);
|
|
6838
7191
|
if (!budget) return;
|
|
7192
|
+
const currentMax = typeof body.max_tokens === "number" ? body.max_tokens : 0;
|
|
7193
|
+
const requiredMax = Math.max(THINKING_MIN_MAX_TOKENS, budget + THINKING_OUTPUT_RESERVE);
|
|
7194
|
+
if (currentMax < requiredMax) {
|
|
7195
|
+
body.max_tokens = requiredMax;
|
|
7196
|
+
}
|
|
7197
|
+
budget = clampBudget(budget, body.max_tokens);
|
|
6839
7198
|
const thinking = { type: "enabled", budget_tokens: budget };
|
|
6840
7199
|
if (reasoning.providerExtras) Object.assign(thinking, reasoning.providerExtras);
|
|
6841
7200
|
body.thinking = thinking;
|
|
7201
|
+
stripSamplingParams(body, ["temperature", "top_p", "top_k"]);
|
|
7202
|
+
}
|
|
7203
|
+
function applyBedrockReasoning(body, reasoning) {
|
|
7204
|
+
if (!reasoning) return;
|
|
7205
|
+
let budget = resolveBudget(reasoning, ANTHROPIC_EFFORT_BUDGET);
|
|
7206
|
+
if (!budget) return;
|
|
7207
|
+
const inference = body.inferenceConfig ?? (body.inferenceConfig = {});
|
|
7208
|
+
const currentMax = typeof inference.maxTokens === "number" ? inference.maxTokens : 0;
|
|
7209
|
+
const requiredMax = Math.max(THINKING_MIN_MAX_TOKENS, budget + THINKING_OUTPUT_RESERVE);
|
|
7210
|
+
if (currentMax < requiredMax) {
|
|
7211
|
+
inference.maxTokens = requiredMax;
|
|
7212
|
+
}
|
|
7213
|
+
budget = clampBudget(budget, inference.maxTokens);
|
|
7214
|
+
const extra = body.additionalModelRequestFields ?? (body.additionalModelRequestFields = {});
|
|
7215
|
+
const thinking = { type: "enabled", budget_tokens: budget };
|
|
7216
|
+
if (reasoning.providerExtras) Object.assign(thinking, reasoning.providerExtras);
|
|
7217
|
+
extra.thinking = thinking;
|
|
7218
|
+
stripSamplingParams(inference, ["temperature", "topP"]);
|
|
6842
7219
|
}
|
|
6843
7220
|
function applyGeminiReasoning(generationConfig, reasoning) {
|
|
6844
7221
|
if (!reasoning) return;
|
|
6845
|
-
const budget = resolveBudget(reasoning,
|
|
7222
|
+
const budget = resolveBudget(reasoning, GEMINI_EFFORT_BUDGET);
|
|
6846
7223
|
if (budget == null) return;
|
|
6847
7224
|
const thinkingConfig = { thinkingBudget: budget };
|
|
6848
7225
|
if (reasoning.includeThoughts) thinkingConfig.includeThoughts = true;
|
|
6849
7226
|
if (reasoning.providerExtras) Object.assign(thinkingConfig, reasoning.providerExtras);
|
|
6850
7227
|
generationConfig.thinkingConfig = thinkingConfig;
|
|
6851
7228
|
}
|
|
7229
|
+
function stripSamplingParams(target, keys) {
|
|
7230
|
+
for (const k of keys) {
|
|
7231
|
+
if (k in target) delete target[k];
|
|
7232
|
+
}
|
|
7233
|
+
}
|
|
7234
|
+
function clampBudget(budget, maxTokens) {
|
|
7235
|
+
if (typeof maxTokens !== "number" || maxTokens <= 0) return budget;
|
|
7236
|
+
const ceiling = maxTokens - THINKING_OUTPUT_RESERVE;
|
|
7237
|
+
if (ceiling < 1024) return Math.max(1024, Math.floor(maxTokens / 2));
|
|
7238
|
+
return Math.min(budget, ceiling);
|
|
7239
|
+
}
|
|
6852
7240
|
function normalizeEffort(effort) {
|
|
6853
7241
|
if (!effort) return void 0;
|
|
6854
7242
|
const allowed = ["minimal", "low", "medium", "high"];
|
|
@@ -6877,13 +7265,38 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
6877
7265
|
};
|
|
6878
7266
|
if (config.retry) this.retryPolicy = { ...this.retryPolicy, ...config.retry };
|
|
6879
7267
|
}
|
|
7268
|
+
/** True when the request targets a reasoning model (o-series / gpt-5) so we
|
|
7269
|
+
* should route through the Responses API, which exposes `reasoning.effort`
|
|
7270
|
+
* and reasoning summaries. Chat Completions silently drops these. */
|
|
7271
|
+
useResponsesApi(request) {
|
|
7272
|
+
if (!request.reasoning) return false;
|
|
7273
|
+
return isReasoningModel(request.model || this.defaultModel);
|
|
7274
|
+
}
|
|
6880
7275
|
async complete(request) {
|
|
7276
|
+
if (this.useResponsesApi(request)) {
|
|
7277
|
+
return this.completeResponses(request);
|
|
7278
|
+
}
|
|
6881
7279
|
const body = this.buildRequestBody(request, false);
|
|
6882
7280
|
const res = await this.doFetch(body);
|
|
6883
7281
|
const json = await res.json();
|
|
6884
7282
|
return this.parseResponse(json);
|
|
6885
7283
|
}
|
|
6886
7284
|
async *completeStream(request) {
|
|
7285
|
+
if (this.useResponsesApi(request)) {
|
|
7286
|
+
const response = await this.completeResponses(request);
|
|
7287
|
+
yield {
|
|
7288
|
+
id: response.id,
|
|
7289
|
+
model: response.model,
|
|
7290
|
+
delta: {
|
|
7291
|
+
content: response.content ?? void 0,
|
|
7292
|
+
toolCalls: response.toolCalls.length > 0 ? response.toolCalls : void 0,
|
|
7293
|
+
reasoning: response.reasoning
|
|
7294
|
+
},
|
|
7295
|
+
usage: response.usage,
|
|
7296
|
+
finishReason: response.finishReason
|
|
7297
|
+
};
|
|
7298
|
+
return;
|
|
7299
|
+
}
|
|
6887
7300
|
const body = this.buildRequestBody(request, true);
|
|
6888
7301
|
const res = await this.doFetch(body);
|
|
6889
7302
|
if (!res.body) throw new ProviderError("No response body for stream", this.providerName);
|
|
@@ -6982,6 +7395,156 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
6982
7395
|
applyOpenAIReasoning(body, request.reasoning, "legacy_effort");
|
|
6983
7396
|
return body;
|
|
6984
7397
|
}
|
|
7398
|
+
// ─── Responses API (reasoning models) ──────────────────────────────────────
|
|
7399
|
+
async completeResponses(request) {
|
|
7400
|
+
const body = this.buildResponsesBody(request);
|
|
7401
|
+
const res = await this.responsesFetch(body);
|
|
7402
|
+
const json = await res.json();
|
|
7403
|
+
return this.parseResponsesResponse(json, request.model || this.defaultModel);
|
|
7404
|
+
}
|
|
7405
|
+
buildResponsesBody(request) {
|
|
7406
|
+
const body = {
|
|
7407
|
+
model: request.model || this.defaultModel,
|
|
7408
|
+
input: request.messages.map((m) => this.toResponsesInput(m))
|
|
7409
|
+
};
|
|
7410
|
+
if (request.maxTokens != null) body.max_output_tokens = request.maxTokens;
|
|
7411
|
+
if (request.topP != null) body.top_p = request.topP;
|
|
7412
|
+
if (request.tools?.length) {
|
|
7413
|
+
body.tools = request.tools.map((t) => ({
|
|
7414
|
+
type: "function",
|
|
7415
|
+
name: t.name,
|
|
7416
|
+
description: t.description,
|
|
7417
|
+
parameters: t.parameters,
|
|
7418
|
+
...t.strict ? { strict: true } : {}
|
|
7419
|
+
}));
|
|
7420
|
+
}
|
|
7421
|
+
if (request.toolChoice != null && request.tools?.length) {
|
|
7422
|
+
if (typeof request.toolChoice === "string") {
|
|
7423
|
+
body.tool_choice = request.toolChoice;
|
|
7424
|
+
} else {
|
|
7425
|
+
body.tool_choice = { type: "function", name: request.toolChoice.name };
|
|
7426
|
+
}
|
|
7427
|
+
}
|
|
7428
|
+
if (request.responseFormat) {
|
|
7429
|
+
if (request.responseFormat.type === "json_schema") {
|
|
7430
|
+
body.text = {
|
|
7431
|
+
format: {
|
|
7432
|
+
type: "json_schema",
|
|
7433
|
+
name: request.responseFormat.name ?? "response",
|
|
7434
|
+
schema: request.responseFormat.schema,
|
|
7435
|
+
strict: true
|
|
7436
|
+
}
|
|
7437
|
+
};
|
|
7438
|
+
} else if (request.responseFormat.type === "json_object") {
|
|
7439
|
+
body.text = { format: { type: "json_object" } };
|
|
7440
|
+
}
|
|
7441
|
+
}
|
|
7442
|
+
if (request.extra) Object.assign(body, request.extra);
|
|
7443
|
+
applyOpenAIReasoning(body, request.reasoning, "responses");
|
|
7444
|
+
return body;
|
|
7445
|
+
}
|
|
7446
|
+
/** Maps a unified message to a Responses API `input` item. */
|
|
7447
|
+
toResponsesInput(m) {
|
|
7448
|
+
if (m.role === "tool" && m.toolCallId) {
|
|
7449
|
+
const output = typeof m.content === "string" ? m.content : JSON.stringify(m.content);
|
|
7450
|
+
return { type: "function_call_output", call_id: m.toolCallId, output };
|
|
7451
|
+
}
|
|
7452
|
+
if (m.role === "assistant" && m.toolCalls?.length) {
|
|
7453
|
+
return {
|
|
7454
|
+
__assistantWithCalls: true,
|
|
7455
|
+
text: typeof m.content === "string" ? m.content : "",
|
|
7456
|
+
calls: m.toolCalls.map((tc) => ({
|
|
7457
|
+
type: "function_call",
|
|
7458
|
+
call_id: tc.id,
|
|
7459
|
+
name: tc.name,
|
|
7460
|
+
arguments: tc.arguments
|
|
7461
|
+
}))
|
|
7462
|
+
};
|
|
7463
|
+
}
|
|
7464
|
+
const role = m.role === "system" ? "system" : m.role === "assistant" ? "assistant" : "user";
|
|
7465
|
+
const textType = role === "assistant" ? "output_text" : "input_text";
|
|
7466
|
+
if (typeof m.content === "string") {
|
|
7467
|
+
return { role, content: [{ type: textType, text: m.content }] };
|
|
7468
|
+
}
|
|
7469
|
+
const content = m.content.map((part) => {
|
|
7470
|
+
if (part.type === "text") return { type: textType, text: part.text };
|
|
7471
|
+
if (part.type === "image") {
|
|
7472
|
+
const src = part.source;
|
|
7473
|
+
const url = src.type === "url" ? src.url : `data:${src.mediaType};base64,${src.data}`;
|
|
7474
|
+
return { type: "input_image", image_url: url };
|
|
7475
|
+
}
|
|
7476
|
+
return { type: textType, text: "" };
|
|
7477
|
+
});
|
|
7478
|
+
return { role, content };
|
|
7479
|
+
}
|
|
7480
|
+
async responsesFetch(body) {
|
|
7481
|
+
body.input = expandResponsesInput(body.input);
|
|
7482
|
+
const url = `${this.baseURL}/responses`;
|
|
7483
|
+
const headers = {
|
|
7484
|
+
"Content-Type": "application/json",
|
|
7485
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
7486
|
+
...this.defaultHeaders
|
|
7487
|
+
};
|
|
7488
|
+
const payload = JSON.stringify(body);
|
|
7489
|
+
const res = await this.doFetchWithRetry(() => fetch(url, { method: "POST", headers, body: payload }));
|
|
7490
|
+
if (!res.ok) {
|
|
7491
|
+
const text = await res.text().catch(() => "");
|
|
7492
|
+
throw new ProviderError(
|
|
7493
|
+
`OpenAI Responses API error ${res.status}: ${text}`,
|
|
7494
|
+
this.providerName,
|
|
7495
|
+
res.status,
|
|
7496
|
+
text
|
|
7497
|
+
);
|
|
7498
|
+
}
|
|
7499
|
+
return res;
|
|
7500
|
+
}
|
|
7501
|
+
parseResponsesResponse(json, modelId) {
|
|
7502
|
+
const textParts = [];
|
|
7503
|
+
const toolCalls = [];
|
|
7504
|
+
const summaryParts = [];
|
|
7505
|
+
for (const item of json.output ?? []) {
|
|
7506
|
+
if (item.type === "message") {
|
|
7507
|
+
for (const c of item.content ?? []) {
|
|
7508
|
+
if (c.type === "output_text" && typeof c.text === "string") textParts.push(c.text);
|
|
7509
|
+
}
|
|
7510
|
+
} else if (item.type === "function_call") {
|
|
7511
|
+
toolCalls.push({
|
|
7512
|
+
id: item.call_id ?? item.id ?? "",
|
|
7513
|
+
name: item.name ?? "",
|
|
7514
|
+
arguments: typeof item.arguments === "string" ? item.arguments : JSON.stringify(item.arguments ?? {})
|
|
7515
|
+
});
|
|
7516
|
+
} else if (item.type === "reasoning") {
|
|
7517
|
+
for (const s of item.summary ?? []) {
|
|
7518
|
+
if (typeof s.text === "string") summaryParts.push(s.text);
|
|
7519
|
+
}
|
|
7520
|
+
}
|
|
7521
|
+
}
|
|
7522
|
+
if (textParts.length === 0 && typeof json.output_text === "string") {
|
|
7523
|
+
textParts.push(json.output_text);
|
|
7524
|
+
}
|
|
7525
|
+
const usage = json.usage ?? {};
|
|
7526
|
+
const reasoningTokens = usage.output_tokens_details?.reasoning_tokens ?? 0;
|
|
7527
|
+
const tokenUsage = {
|
|
7528
|
+
inputTokens: usage.input_tokens ?? 0,
|
|
7529
|
+
outputTokens: usage.output_tokens ?? 0,
|
|
7530
|
+
totalTokens: usage.total_tokens ?? (usage.input_tokens ?? 0) + (usage.output_tokens ?? 0),
|
|
7531
|
+
cachedInputTokens: usage.input_tokens_details?.cached_tokens ?? 0,
|
|
7532
|
+
cachedWriteTokens: 0,
|
|
7533
|
+
cachedOutputTokens: 0,
|
|
7534
|
+
reasoningTokens
|
|
7535
|
+
};
|
|
7536
|
+
const finishReason = toolCalls.length > 0 ? "tool_calls" : json.status === "incomplete" ? "length" : "stop";
|
|
7537
|
+
return {
|
|
7538
|
+
id: json.id ?? "",
|
|
7539
|
+
model: json.model ?? modelId,
|
|
7540
|
+
content: textParts.join("") || null,
|
|
7541
|
+
toolCalls,
|
|
7542
|
+
usage: tokenUsage,
|
|
7543
|
+
finishReason,
|
|
7544
|
+
reasoning: summaryParts.length > 0 ? { summary: summaryParts.join("\n").trim() || void 0 } : void 0,
|
|
7545
|
+
raw: json
|
|
7546
|
+
};
|
|
7547
|
+
}
|
|
6985
7548
|
toOpenAIMessage(m) {
|
|
6986
7549
|
const msg = { role: m.role };
|
|
6987
7550
|
if (typeof m.content === "string") {
|
|
@@ -7074,6 +7637,25 @@ var OpenAIProvider = class extends BaseProvider {
|
|
|
7074
7637
|
};
|
|
7075
7638
|
}
|
|
7076
7639
|
};
|
|
7640
|
+
function isReasoningModel(model) {
|
|
7641
|
+
if (!model) return false;
|
|
7642
|
+
const m = model.toLowerCase();
|
|
7643
|
+
return /(^|[/_-])o[0-9]/.test(m) || m.startsWith("o1") || m.startsWith("o3") || m.startsWith("o4") || m.includes("gpt-5") || m.includes("gpt5");
|
|
7644
|
+
}
|
|
7645
|
+
function expandResponsesInput(input) {
|
|
7646
|
+
const out = [];
|
|
7647
|
+
for (const item of input) {
|
|
7648
|
+
if (item && item.__assistantWithCalls) {
|
|
7649
|
+
if (item.text) {
|
|
7650
|
+
out.push({ role: "assistant", content: [{ type: "output_text", text: item.text }] });
|
|
7651
|
+
}
|
|
7652
|
+
for (const call of item.calls) out.push(call);
|
|
7653
|
+
} else {
|
|
7654
|
+
out.push(item);
|
|
7655
|
+
}
|
|
7656
|
+
}
|
|
7657
|
+
return out;
|
|
7658
|
+
}
|
|
7077
7659
|
function mapFinishReason(reason) {
|
|
7078
7660
|
switch (reason) {
|
|
7079
7661
|
case "stop":
|
|
@@ -7119,6 +7701,7 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
7119
7701
|
let cacheReadInputTokens = 0;
|
|
7120
7702
|
let cacheCreationInputTokens = 0;
|
|
7121
7703
|
const currentToolCalls = /* @__PURE__ */ new Map();
|
|
7704
|
+
const reasoningBlocks = /* @__PURE__ */ new Map();
|
|
7122
7705
|
for await (const event of parseSSEStream(res.body)) {
|
|
7123
7706
|
let data;
|
|
7124
7707
|
try {
|
|
@@ -7148,6 +7731,10 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
7148
7731
|
name: block.name ?? "",
|
|
7149
7732
|
arguments: ""
|
|
7150
7733
|
});
|
|
7734
|
+
} else if (block?.type === "thinking") {
|
|
7735
|
+
reasoningBlocks.set(idx, { type: "thinking", text: block.thinking ?? "", signature: block.signature });
|
|
7736
|
+
} else if (block?.type === "redacted_thinking") {
|
|
7737
|
+
reasoningBlocks.set(idx, { type: "redacted_thinking", data: block.data });
|
|
7151
7738
|
}
|
|
7152
7739
|
break;
|
|
7153
7740
|
}
|
|
@@ -7160,6 +7747,19 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
7160
7747
|
model,
|
|
7161
7748
|
delta: { content: delta.text }
|
|
7162
7749
|
};
|
|
7750
|
+
} else if (delta?.type === "thinking_delta" && delta.thinking) {
|
|
7751
|
+
const blk = reasoningBlocks.get(idx) ?? { type: "thinking", text: "" };
|
|
7752
|
+
blk.text = (blk.text ?? "") + delta.thinking;
|
|
7753
|
+
reasoningBlocks.set(idx, blk);
|
|
7754
|
+
yield {
|
|
7755
|
+
id,
|
|
7756
|
+
model,
|
|
7757
|
+
delta: { reasoning: { summary: delta.thinking } }
|
|
7758
|
+
};
|
|
7759
|
+
} else if (delta?.type === "signature_delta" && delta.signature) {
|
|
7760
|
+
const blk = reasoningBlocks.get(idx) ?? { type: "thinking", text: "" };
|
|
7761
|
+
blk.signature = (blk.signature ?? "") + delta.signature;
|
|
7762
|
+
reasoningBlocks.set(idx, blk);
|
|
7163
7763
|
} else if (delta?.type === "input_json_delta" && delta.partial_json) {
|
|
7164
7764
|
const tc = currentToolCalls.get(idx);
|
|
7165
7765
|
if (tc) {
|
|
@@ -7192,10 +7792,13 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
7192
7792
|
cachedOutputTokens: 0,
|
|
7193
7793
|
reasoningTokens: 0
|
|
7194
7794
|
};
|
|
7795
|
+
const blocks = [...reasoningBlocks.values()].filter(
|
|
7796
|
+
(b) => b.type === "thinking" && b.signature || b.type === "redacted_thinking" && b.data
|
|
7797
|
+
);
|
|
7195
7798
|
yield {
|
|
7196
7799
|
id,
|
|
7197
7800
|
model,
|
|
7198
|
-
delta: {},
|
|
7801
|
+
delta: blocks.length > 0 ? { reasoning: { blocks } } : {},
|
|
7199
7802
|
finishReason,
|
|
7200
7803
|
usage
|
|
7201
7804
|
};
|
|
@@ -7287,6 +7890,7 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
7287
7890
|
}
|
|
7288
7891
|
if (m.role === "assistant" && m.toolCalls?.length) {
|
|
7289
7892
|
const content = [];
|
|
7893
|
+
appendReasoningBlocks(content, m.reasoning?.blocks);
|
|
7290
7894
|
if (typeof m.content === "string" && m.content) {
|
|
7291
7895
|
content.push({ type: "text", text: m.content });
|
|
7292
7896
|
}
|
|
@@ -7300,6 +7904,13 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
7300
7904
|
}
|
|
7301
7905
|
return { role: "assistant", content };
|
|
7302
7906
|
}
|
|
7907
|
+
if (m.role === "assistant" && m.reasoning?.blocks?.length) {
|
|
7908
|
+
const content = [];
|
|
7909
|
+
appendReasoningBlocks(content, m.reasoning.blocks);
|
|
7910
|
+
const text = typeof m.content === "string" ? m.content : "";
|
|
7911
|
+
if (text) content.push({ type: "text", text });
|
|
7912
|
+
return { role: "assistant", content };
|
|
7913
|
+
}
|
|
7303
7914
|
const msg = { role: m.role };
|
|
7304
7915
|
if (typeof m.content === "string") {
|
|
7305
7916
|
msg.content = m.content;
|
|
@@ -7355,9 +7966,20 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
7355
7966
|
parseResponse(json) {
|
|
7356
7967
|
const textParts = [];
|
|
7357
7968
|
const toolCalls = [];
|
|
7969
|
+
const reasoningBlocks = [];
|
|
7970
|
+
const summaryParts = [];
|
|
7358
7971
|
for (const block of json.content ?? []) {
|
|
7359
7972
|
if (block.type === "text") {
|
|
7360
7973
|
textParts.push(block.text);
|
|
7974
|
+
} else if (block.type === "thinking") {
|
|
7975
|
+
reasoningBlocks.push({
|
|
7976
|
+
type: "thinking",
|
|
7977
|
+
text: block.thinking ?? "",
|
|
7978
|
+
signature: block.signature
|
|
7979
|
+
});
|
|
7980
|
+
if (block.thinking) summaryParts.push(block.thinking);
|
|
7981
|
+
} else if (block.type === "redacted_thinking") {
|
|
7982
|
+
reasoningBlocks.push({ type: "redacted_thinking", data: block.data });
|
|
7361
7983
|
} else if (block.type === "tool_use") {
|
|
7362
7984
|
toolCalls.push({
|
|
7363
7985
|
id: block.id,
|
|
@@ -7374,6 +7996,9 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
7374
7996
|
cachedInputTokens: usage.cache_read_input_tokens ?? 0,
|
|
7375
7997
|
cachedWriteTokens: usage.cache_creation_input_tokens ?? 0,
|
|
7376
7998
|
cachedOutputTokens: 0,
|
|
7999
|
+
// Anthropic bills thinking tokens inside `output_tokens` and does not
|
|
8000
|
+
// expose a separate count, so reasoningTokens stays 0 here (cost is still
|
|
8001
|
+
// captured via outputTokens). See docs for the limitation.
|
|
7377
8002
|
reasoningTokens: 0
|
|
7378
8003
|
};
|
|
7379
8004
|
return {
|
|
@@ -7383,6 +8008,7 @@ var AnthropicProvider = class extends BaseProvider {
|
|
|
7383
8008
|
toolCalls,
|
|
7384
8009
|
usage: tokenUsage,
|
|
7385
8010
|
finishReason: mapAnthropicStopReason(json.stop_reason),
|
|
8011
|
+
reasoning: reasoningBlocks.length > 0 ? { blocks: reasoningBlocks, summary: summaryParts.join("\n").trim() || void 0 } : void 0,
|
|
7386
8012
|
raw: json
|
|
7387
8013
|
};
|
|
7388
8014
|
}
|
|
@@ -7407,6 +8033,18 @@ function safeJsonParse(str) {
|
|
|
7407
8033
|
return {};
|
|
7408
8034
|
}
|
|
7409
8035
|
}
|
|
8036
|
+
function appendReasoningBlocks(content, blocks) {
|
|
8037
|
+
if (!blocks?.length) return;
|
|
8038
|
+
for (const b of blocks) {
|
|
8039
|
+
if (b.type === "redacted_thinking") {
|
|
8040
|
+
if (b.data) content.push({ type: "redacted_thinking", data: b.data });
|
|
8041
|
+
} else if (b.type === "thinking") {
|
|
8042
|
+
if (b.signature) {
|
|
8043
|
+
content.push({ type: "thinking", thinking: b.text ?? "", signature: b.signature });
|
|
8044
|
+
}
|
|
8045
|
+
}
|
|
8046
|
+
}
|
|
8047
|
+
}
|
|
7410
8048
|
|
|
7411
8049
|
// src/providers/azure.ts
|
|
7412
8050
|
var AzureProvider = class extends OpenAIProvider {
|
|
@@ -7450,7 +8088,52 @@ var AzureProvider = class extends OpenAIProvider {
|
|
|
7450
8088
|
}
|
|
7451
8089
|
return res;
|
|
7452
8090
|
}
|
|
8091
|
+
/** Azure exposes the Responses API at /openai/responses with api-key auth.
|
|
8092
|
+
* Reasoning summaries require a preview api-version; callers can override via
|
|
8093
|
+
* the `apiVersion` config. */
|
|
8094
|
+
async responsesFetch(body) {
|
|
8095
|
+
body.input = expandAzureResponsesInput(body.input);
|
|
8096
|
+
const deployment = this.deploymentName ?? body.model;
|
|
8097
|
+
if (!deployment) {
|
|
8098
|
+
throw new ProviderError("Azure requires a deploymentName or model", this.providerName);
|
|
8099
|
+
}
|
|
8100
|
+
const url = `${this.endpoint}/openai/responses?api-version=${this.apiVersion}`;
|
|
8101
|
+
const payload = JSON.stringify({ ...body, model: deployment });
|
|
8102
|
+
const res = await fetch(url, {
|
|
8103
|
+
method: "POST",
|
|
8104
|
+
headers: {
|
|
8105
|
+
"Content-Type": "application/json",
|
|
8106
|
+
"api-key": this.azureApiKey,
|
|
8107
|
+
...this.defaultHeaders
|
|
8108
|
+
},
|
|
8109
|
+
body: payload
|
|
8110
|
+
});
|
|
8111
|
+
if (!res.ok) {
|
|
8112
|
+
const text = await res.text().catch(() => "");
|
|
8113
|
+
throw new ProviderError(
|
|
8114
|
+
`Azure OpenAI Responses API error ${res.status}: ${text}`,
|
|
8115
|
+
this.providerName,
|
|
8116
|
+
res.status,
|
|
8117
|
+
text
|
|
8118
|
+
);
|
|
8119
|
+
}
|
|
8120
|
+
return res;
|
|
8121
|
+
}
|
|
7453
8122
|
};
|
|
8123
|
+
function expandAzureResponsesInput(input) {
|
|
8124
|
+
const out = [];
|
|
8125
|
+
for (const item of input) {
|
|
8126
|
+
if (item && item.__assistantWithCalls) {
|
|
8127
|
+
if (item.text) {
|
|
8128
|
+
out.push({ role: "assistant", content: [{ type: "output_text", text: item.text }] });
|
|
8129
|
+
}
|
|
8130
|
+
for (const call of item.calls) out.push(call);
|
|
8131
|
+
} else {
|
|
8132
|
+
out.push(item);
|
|
8133
|
+
}
|
|
8134
|
+
}
|
|
8135
|
+
return out;
|
|
8136
|
+
}
|
|
7454
8137
|
|
|
7455
8138
|
// src/providers/openaiCompatible.ts
|
|
7456
8139
|
var OpenAICompatibleProvider = class extends OpenAIProvider {
|
|
@@ -7623,6 +8306,7 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
7623
8306
|
if (request.extra) {
|
|
7624
8307
|
Object.assign(body, request.extra);
|
|
7625
8308
|
}
|
|
8309
|
+
applyBedrockReasoning(body, request.reasoning);
|
|
7626
8310
|
return body;
|
|
7627
8311
|
}
|
|
7628
8312
|
splitSystemMessages(messages) {
|
|
@@ -7656,6 +8340,7 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
7656
8340
|
}
|
|
7657
8341
|
if (m.role === "assistant" && m.toolCalls?.length) {
|
|
7658
8342
|
const content2 = [];
|
|
8343
|
+
appendBedrockReasoning(content2, m.reasoning?.blocks);
|
|
7659
8344
|
if (typeof m.content === "string" && m.content) {
|
|
7660
8345
|
content2.push({ text: m.content });
|
|
7661
8346
|
}
|
|
@@ -7736,9 +8421,23 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
7736
8421
|
const output = json.output?.message;
|
|
7737
8422
|
const textParts = [];
|
|
7738
8423
|
const toolCalls = [];
|
|
8424
|
+
const reasoningBlocks = [];
|
|
8425
|
+
const summaryParts = [];
|
|
7739
8426
|
for (const block of output?.content ?? []) {
|
|
7740
8427
|
if (block.text) {
|
|
7741
8428
|
textParts.push(block.text);
|
|
8429
|
+
} else if (block.reasoningContent) {
|
|
8430
|
+
const rc = block.reasoningContent;
|
|
8431
|
+
if (rc.reasoningText) {
|
|
8432
|
+
reasoningBlocks.push({
|
|
8433
|
+
type: "thinking",
|
|
8434
|
+
text: rc.reasoningText.text ?? "",
|
|
8435
|
+
signature: rc.reasoningText.signature
|
|
8436
|
+
});
|
|
8437
|
+
if (rc.reasoningText.text) summaryParts.push(rc.reasoningText.text);
|
|
8438
|
+
} else if (rc.redactedContent) {
|
|
8439
|
+
reasoningBlocks.push({ type: "redacted_thinking", data: rc.redactedContent });
|
|
8440
|
+
}
|
|
7742
8441
|
} else if (block.toolUse) {
|
|
7743
8442
|
toolCalls.push({
|
|
7744
8443
|
id: block.toolUse.toolUseId,
|
|
@@ -7755,6 +8454,7 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
7755
8454
|
cachedInputTokens: usage.cacheReadInputTokenCount ?? 0,
|
|
7756
8455
|
cachedWriteTokens: usage.cacheWriteInputTokenCount ?? 0,
|
|
7757
8456
|
cachedOutputTokens: 0,
|
|
8457
|
+
// Bedrock bills thinking tokens inside outputTokens; no separate count.
|
|
7758
8458
|
reasoningTokens: 0
|
|
7759
8459
|
};
|
|
7760
8460
|
return {
|
|
@@ -7764,10 +8464,25 @@ var BedrockProvider = class extends BaseProvider {
|
|
|
7764
8464
|
toolCalls,
|
|
7765
8465
|
usage: tokenUsage,
|
|
7766
8466
|
finishReason: mapBedrockStopReason(json.stopReason),
|
|
8467
|
+
reasoning: reasoningBlocks.length > 0 ? { blocks: reasoningBlocks, summary: summaryParts.join("\n").trim() || void 0 } : void 0,
|
|
7767
8468
|
raw: json
|
|
7768
8469
|
};
|
|
7769
8470
|
}
|
|
7770
8471
|
};
|
|
8472
|
+
function appendBedrockReasoning(content, blocks) {
|
|
8473
|
+
if (!blocks?.length) return;
|
|
8474
|
+
for (const b of blocks) {
|
|
8475
|
+
if (b.type === "redacted_thinking") {
|
|
8476
|
+
if (b.data) content.push({ reasoningContent: { redactedContent: b.data } });
|
|
8477
|
+
} else if (b.type === "thinking") {
|
|
8478
|
+
if (b.signature) {
|
|
8479
|
+
content.push({
|
|
8480
|
+
reasoningContent: { reasoningText: { text: b.text ?? "", signature: b.signature } }
|
|
8481
|
+
});
|
|
8482
|
+
}
|
|
8483
|
+
}
|
|
8484
|
+
}
|
|
8485
|
+
}
|
|
7771
8486
|
function mapBedrockStopReason(reason) {
|
|
7772
8487
|
switch (reason) {
|
|
7773
8488
|
case "end_turn":
|
|
@@ -8090,10 +8805,15 @@ var VertexProvider = class extends BaseProvider {
|
|
|
8090
8805
|
const parts = candidate?.content?.parts ?? [];
|
|
8091
8806
|
const textParts = [];
|
|
8092
8807
|
const toolCalls = [];
|
|
8808
|
+
const thoughtParts = [];
|
|
8093
8809
|
let toolCallIdx = 0;
|
|
8094
8810
|
for (const part of parts) {
|
|
8095
8811
|
if (part.text) {
|
|
8096
|
-
|
|
8812
|
+
if (part.thought === true) {
|
|
8813
|
+
thoughtParts.push(part.text);
|
|
8814
|
+
} else {
|
|
8815
|
+
textParts.push(part.text);
|
|
8816
|
+
}
|
|
8097
8817
|
} else if (part.functionCall) {
|
|
8098
8818
|
toolCalls.push({
|
|
8099
8819
|
id: `call_${toolCallIdx++}`,
|
|
@@ -8119,6 +8839,7 @@ var VertexProvider = class extends BaseProvider {
|
|
|
8119
8839
|
toolCalls,
|
|
8120
8840
|
usage: tokenUsage,
|
|
8121
8841
|
finishReason: mapGeminiFinishReason(candidate?.finishReason),
|
|
8842
|
+
reasoning: thoughtParts.length > 0 ? { summary: thoughtParts.join("\n").trim() || void 0 } : void 0,
|
|
8122
8843
|
raw: json
|
|
8123
8844
|
};
|
|
8124
8845
|
}
|
|
@@ -8128,7 +8849,11 @@ var VertexProvider = class extends BaseProvider {
|
|
|
8128
8849
|
const delta = {};
|
|
8129
8850
|
for (const part of parts) {
|
|
8130
8851
|
if (part.text) {
|
|
8131
|
-
|
|
8852
|
+
if (part.thought === true) {
|
|
8853
|
+
delta.reasoning = { summary: (delta.reasoning?.summary ?? "") + part.text };
|
|
8854
|
+
} else {
|
|
8855
|
+
delta.content = (delta.content ?? "") + part.text;
|
|
8856
|
+
}
|
|
8132
8857
|
} else if (part.functionCall) {
|
|
8133
8858
|
if (!delta.toolCalls) delta.toolCalls = [];
|
|
8134
8859
|
delta.toolCalls.push({
|
|
@@ -8202,12 +8927,16 @@ function fromNativeProvider(provider, options) {
|
|
|
8202
8927
|
let fullContent = "";
|
|
8203
8928
|
let allToolCalls = [];
|
|
8204
8929
|
let lastUsage;
|
|
8930
|
+
let reasoningBlocks;
|
|
8205
8931
|
const toolCallBuffers = /* @__PURE__ */ new Map();
|
|
8206
8932
|
for await (const chunk of provider.completeStream(request)) {
|
|
8207
8933
|
if (chunk.delta.content) {
|
|
8208
8934
|
fullContent += chunk.delta.content;
|
|
8209
8935
|
yield chunk.delta.content;
|
|
8210
8936
|
}
|
|
8937
|
+
if (chunk.delta.reasoning?.blocks?.length) {
|
|
8938
|
+
reasoningBlocks = chunk.delta.reasoning.blocks;
|
|
8939
|
+
}
|
|
8211
8940
|
if (chunk.delta.toolCalls) {
|
|
8212
8941
|
for (const tc of chunk.delta.toolCalls) {
|
|
8213
8942
|
if (tc.id) {
|
|
@@ -8228,6 +8957,9 @@ function fromNativeProvider(provider, options) {
|
|
|
8228
8957
|
}
|
|
8229
8958
|
allToolCalls = [...toolCallBuffers.values()];
|
|
8230
8959
|
const finalMessage = assembleMessage(fullContent, allToolCalls, lastUsage);
|
|
8960
|
+
if (reasoningBlocks?.length) {
|
|
8961
|
+
finalMessage.reasoning = { blocks: reasoningBlocks };
|
|
8962
|
+
}
|
|
8231
8963
|
yield finalMessage;
|
|
8232
8964
|
},
|
|
8233
8965
|
bindTools: (tools, _bindOptions) => {
|
|
@@ -8290,6 +9022,10 @@ function toUnifiedMessage(msg) {
|
|
|
8290
9022
|
arguments: tc.function?.arguments ?? tc.arguments ?? "{}"
|
|
8291
9023
|
}));
|
|
8292
9024
|
}
|
|
9025
|
+
const reasoning = msg.reasoning;
|
|
9026
|
+
if (reasoning && (reasoning.blocks?.length || reasoning.summary)) {
|
|
9027
|
+
unified.reasoning = reasoning;
|
|
9028
|
+
}
|
|
8293
9029
|
return unified;
|
|
8294
9030
|
}
|
|
8295
9031
|
function convertContent(content) {
|
|
@@ -8498,6 +9234,9 @@ function toBaseChatMessage(response) {
|
|
|
8498
9234
|
function: { name: tc.name, arguments: tc.arguments }
|
|
8499
9235
|
}));
|
|
8500
9236
|
}
|
|
9237
|
+
if (response.reasoning && (response.reasoning.blocks?.length || response.reasoning.summary)) {
|
|
9238
|
+
msg.reasoning = response.reasoning;
|
|
9239
|
+
}
|
|
8501
9240
|
return msg;
|
|
8502
9241
|
}
|
|
8503
9242
|
function assembleMessage(content, toolCalls, usage) {
|
|
@@ -8594,6 +9333,6 @@ function createProvider(config) {
|
|
|
8594
9333
|
}
|
|
8595
9334
|
}
|
|
8596
9335
|
|
|
8597
|
-
export { AnthropicProvider, AzureProvider, BaseProvider, BedrockProvider, DEFAULT_PROFILE_CONFIGS, GuardrailPhase, InMemoryMemoryStore, NativeJsonSchemaStrategy, OpenAICompatibleProvider, OpenAIProvider, ProviderError, StructuredOutputManager, ToolBasedStrategy, VertexProvider, agentVerdictRule, buildSystemPrompt, captureSnapshot, codePresenceRule, cognipeerSink, countApproxTokens, countMessagesTokens, createAgent, createAgentNode, createAskUserQuestionTool, createCodeGuardrail, createContextSummarizeNode, createContextTools, createGetToolResponseTool, createGuardrail, createJsonGuardrail, createManageTodoTool, createProvider, createRegexGuardrail, createResolverNode, createSmartAgent, createTool, createToolLimitFinalizeNode, createToolsNode, customCallbackRule, customSink, defaultTokenCounter, emptyUsage, evaluateGuardrails, fileSink, formatZodError, fromLangchainModel, fromLangchainTools, fromNativeProvider, generateSpanId, generateTraceId, getModelCapabilities, getNestedValue, getResolvedSmartConfig, getTokenCounter, hasToolResponseRecoveryReference, httpSink, isSmartModel, jsonSchemaRule, normalizeSmartAgentOptions, otlpSink, readMemoryFacts, regexRule, resolveMemoryStore, resolveStrategy, resolveToolApprovalState, resolveUserQuestionState, restoreSnapshot, runSmartAgentEvalHarness, setTokenCounter, startStreamingSession, traceSessionToOtlp, withTools, writeSummaryFactsToMemory };
|
|
9336
|
+
export { AnthropicProvider, AzureProvider, BaseProvider, BedrockProvider, DEFAULT_PROFILE_CONFIGS, DEFAULT_SKILL_POLICY, GuardrailPhase, InMemoryMemoryStore, NativeJsonSchemaStrategy, OpenAICompatibleProvider, OpenAIProvider, ProviderError, SMALL_TIER_SKILL_POLICY, StructuredOutputManager, ToolBasedStrategy, VertexProvider, agentVerdictRule, appendBoundTools, buildSkillHeaderBlock, buildSystemPrompt, canOpenSkill, captureSnapshot, codePresenceRule, cognipeerSink, composeToolSets, countApproxTokens, countMessagesTokens, createAgent, createAgentNode, createAskUserQuestionTool, createBindSkillToolsTool, createCodeGuardrail, createContextSummarizeNode, createContextTools, createGetToolResponseTool, createGuardrail, createJsonGuardrail, createManageTodoTool, createOpenSkillTool, createProvider, createRegexGuardrail, createResolverNode, createSkillRegistryRef, createSkillTools, createSmartAgent, createTool, createToolLimitFinalizeNode, createToolsNode, customCallbackRule, customSink, dedupeToolsByName, defaultTokenCounter, emptyUsage, evaluateGuardrails, fileSink, formatZodError, fromLangchainModel, fromLangchainTools, fromNativeProvider, generateSpanId, generateTraceId, getModelCapabilities, getNestedValue, getResolvedSmartConfig, getTokenCounter, hasToolResponseRecoveryReference, httpSink, isSmartModel, jsonSchemaRule, normalizeSmartAgentOptions, otlpSink, readMemoryFacts, regexRule, resolveAvailableSkills, resolveMemoryStore, resolveReasoning, resolveStrategy, resolveToolApprovalState, resolveUserQuestionState, restoreSnapshot, runSmartAgentEvalHarness, setTokenCounter, startStreamingSession, traceSessionToOtlp, validateReasoningConfig, withTools, writeSummaryFactsToMemory };
|
|
8598
9337
|
//# sourceMappingURL=index.mjs.map
|
|
8599
9338
|
//# sourceMappingURL=index.mjs.map
|