@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/dist/index.cjs CHANGED
@@ -3036,6 +3036,17 @@ function createToolsNode(initialTools, opts) {
3036
3036
  }
3037
3037
  const durationMs = Date.now() - start;
3038
3038
  const executionId = nanoid.nanoid();
3039
+ if (output && typeof output === "object" && Array.isArray(output.__runtimeToolsDelta)) {
3040
+ const delta = output.__runtimeToolsDelta;
3041
+ delete output.__runtimeToolsDelta;
3042
+ const currentRuntime = state.agent || runtime;
3043
+ const currentTools = currentRuntime?.tools ?? [];
3044
+ const present = new Set(currentTools.map((tool2) => tool2?.name));
3045
+ const additions = delta.filter((tool2) => tool2 && tool2.name && !present.has(tool2.name));
3046
+ if (additions.length > 0 && currentRuntime) {
3047
+ state.agent = { ...currentRuntime, tools: [...currentTools, ...additions] };
3048
+ }
3049
+ }
3039
3050
  if (output && typeof output === "object" && output.__handoff && output.__handoff.runtime) {
3040
3051
  toolHistory.push({ executionId, toolName, args, output: "handoff:ok", rawOutput: output, timestamp: (/* @__PURE__ */ new Date()).toISOString(), tool_call_id: tc.id, status: "handoff" });
3041
3052
  push({ role: "tool", content: "ok", tool_call_id: tc.id || `${tc.name}_${toolCount}`, name: tc.name });
@@ -3345,15 +3356,40 @@ function countToolCallsInLastTurn(state) {
3345
3356
  function stripReflectionAskMessages(messages) {
3346
3357
  return messages.filter((m) => !(m?.role === "user" && m?.name === REFLECTION_ASK_NAME));
3347
3358
  }
3359
+ function lastTwoToolTurns(state) {
3360
+ const groups = [];
3361
+ let cur = [];
3362
+ let sawTool = false;
3363
+ for (let i = state.messages.length - 1; i >= 0; i--) {
3364
+ const m = state.messages[i];
3365
+ if (m?.role === "tool") {
3366
+ if (m.name) cur.push(m.name);
3367
+ sawTool = true;
3368
+ } else if (m?.role === "assistant") {
3369
+ if (sawTool) {
3370
+ groups.push(cur);
3371
+ cur = [];
3372
+ sawTool = false;
3373
+ if (groups.length >= 2) break;
3374
+ }
3375
+ }
3376
+ }
3377
+ if (sawTool && cur.length) groups.push(cur);
3378
+ return { current: groups[0] ?? [], previous: groups[1] ?? [] };
3379
+ }
3348
3380
  function shouldRunReflection(cadence, state, ranToolsThisTurn) {
3349
3381
  if (cadence === "off") return false;
3350
3382
  if (cadence === "every_turn") return true;
3351
3383
  if (cadence === "after_tool") return ranToolsThisTurn;
3384
+ if (cadence === "initial_then_after_tool") return ranToolsThisTurn;
3352
3385
  if (cadence === "on_branch") {
3353
- const reflections = state.reflections || [];
3354
- const lastReflectionTurn = reflections[reflections.length - 1]?.turn ?? -1;
3355
- const currentTurnId = state.toolCallCount ?? 0;
3356
- return currentTurnId - lastReflectionTurn >= 2;
3386
+ const { current, previous } = lastTwoToolTurns(state);
3387
+ if (previous.length === 0) return true;
3388
+ const a = new Set(current);
3389
+ const b = new Set(previous);
3390
+ for (const n of a) if (!b.has(n)) return true;
3391
+ for (const n of b) if (!a.has(n)) return true;
3392
+ return false;
3357
3393
  }
3358
3394
  return false;
3359
3395
  }
@@ -3370,7 +3406,10 @@ function createReflectionNode(opts, resolved) {
3370
3406
  const onEvent = state.ctx?.__onEvent;
3371
3407
  const traceSession = state.ctx?.__traceSession;
3372
3408
  const maxChars = resolved.maxChars;
3373
- const promptBody = (resolved.promptTemplate || DEFAULT_REFLECT_PROMPT).replace(/\$\{maxChars\}/g, String(maxChars));
3409
+ const turnNow = state.toolCallCount ?? 0;
3410
+ const hookCtx = { state, turn: turnNow, trigger, ranToolsThisTurn: true };
3411
+ const defaultPrompt = (resolved.promptTemplate || DEFAULT_REFLECT_PROMPT).replace(/\$\{maxChars\}/g, String(maxChars));
3412
+ const promptBody = resolved.buildPrompt ? String(resolved.buildPrompt({ ...hookCtx, defaultPrompt, maxChars }) ?? defaultPrompt) : defaultPrompt;
3374
3413
  const baseMessages = stripReflectionAskMessages([...state.messages]);
3375
3414
  const askMessage = {
3376
3415
  role: "user",
@@ -3404,6 +3443,8 @@ function createReflectionNode(opts, resolved) {
3404
3443
  const rawText = extractText(response);
3405
3444
  const text = trimToChars(String(rawText ?? "").trim(), maxChars);
3406
3445
  if (!text) return {};
3446
+ const prevText = (state.reflections?.[state.reflections.length - 1]?.text || "").trim();
3447
+ if (prevText && isNearDuplicate(prevText, text)) return {};
3407
3448
  const rawUsage = response?.usage_metadata || response?.response_metadata?.usage || response?.usage || response?.additional_kwargs?.usage;
3408
3449
  const usage = normalizeUsage(rawUsage);
3409
3450
  const { ids, names } = countToolCallsInLastTurn(state);
@@ -3452,6 +3493,12 @@ function createReflectionNode(opts, resolved) {
3452
3493
  } catch (e) {
3453
3494
  }
3454
3495
  }
3496
+ if (resolved.onReflection) {
3497
+ try {
3498
+ resolved.onReflection(record, hookCtx);
3499
+ } catch {
3500
+ }
3501
+ }
3455
3502
  const nextMessages = stripReflectionAskMessages([...state.messages]);
3456
3503
  const reflections = [...state.reflections || [], record];
3457
3504
  const kept = reflections.slice(-Math.max(1, resolved.keepLast));
@@ -3468,7 +3515,20 @@ ${r.text}
3468
3515
  metadata: { reflectionId: r.id, reflectionTurn: r.turn, reflectionTrigger: r.trigger }
3469
3516
  });
3470
3517
  }
3471
- return { messages: prunedMessages, reflections };
3518
+ const patch = { messages: prunedMessages, reflections };
3519
+ if (resolved.feedTo === "memory") {
3520
+ const fact = {
3521
+ key: `reflection_turn_${turn}`,
3522
+ value: text,
3523
+ sourceTurn: turn,
3524
+ confidence: 0.3,
3525
+ tags: ["reflection"]
3526
+ };
3527
+ patch.memoryFacts = [...state.memoryFacts || [], fact];
3528
+ } else if (resolved.feedTo === "plan" && state.plan) {
3529
+ patch.plan = { ...state.plan, lastReflection: text };
3530
+ }
3531
+ return patch;
3472
3532
  };
3473
3533
  }
3474
3534
  function extractText(chunk) {
@@ -3497,24 +3557,75 @@ function safeRandomId() {
3497
3557
  return `r_${Math.random().toString(36).slice(2, 10)}_${Date.now().toString(36)}`;
3498
3558
  }
3499
3559
  }
3560
+ function isNearDuplicate(a, b) {
3561
+ const norm = (s) => s.toLowerCase().replace(/\s+/g, " ").trim();
3562
+ const na = norm(a);
3563
+ const nb = norm(b);
3564
+ if (na === nb) return true;
3565
+ const tokensA = new Set(na.split(" ").filter(Boolean));
3566
+ const tokensB = new Set(nb.split(" ").filter(Boolean));
3567
+ if (tokensA.size === 0 || tokensB.size === 0) return false;
3568
+ let inter = 0;
3569
+ for (const t of tokensA) if (tokensB.has(t)) inter++;
3570
+ const union = tokensA.size + tokensB.size - inter;
3571
+ return union > 0 && inter / union >= 0.9;
3572
+ }
3500
3573
 
3501
3574
  // src/smart/reasoning.ts
3502
3575
  var LEVEL_DEFAULTS = {
3576
+ minimal: {
3577
+ native: { effort: "minimal" },
3578
+ reflection: { maxTokens: 150, maxChars: 400, cadence: "off" }
3579
+ },
3503
3580
  low: {
3504
3581
  native: { effort: "low" },
3505
3582
  reflection: { maxTokens: 200, maxChars: 600, cadence: "on_branch" }
3506
3583
  },
3507
3584
  medium: {
3508
3585
  native: { effort: "medium" },
3509
- reflection: { maxTokens: 350, maxChars: 1200, cadence: "after_tool" }
3586
+ reflection: { maxTokens: 350, maxChars: 1200, cadence: "initial_then_after_tool" }
3510
3587
  },
3511
3588
  high: {
3512
3589
  native: { effort: "high" },
3513
- reflection: { maxTokens: 600, maxChars: 2e3, cadence: "after_tool" }
3590
+ reflection: { maxTokens: 600, maxChars: 2e3, cadence: "initial_then_after_tool" }
3514
3591
  }
3515
3592
  };
3593
+ var VALID_LEVELS = ["minimal", "low", "medium", "high"];
3594
+ var VALID_CADENCES = ["off", "every_turn", "after_tool", "on_branch", "initial_then_after_tool"];
3595
+ var VALID_EFFORTS = ["minimal", "low", "medium", "high"];
3596
+ function validateReasoningConfig(input) {
3597
+ if (!input) return;
3598
+ if (input.level !== void 0 && !VALID_LEVELS.includes(input.level)) {
3599
+ throw new Error(`reasoning.level must be one of ${VALID_LEVELS.join(", ")} (got "${input.level}")`);
3600
+ }
3601
+ if (input.native) {
3602
+ const n = input.native;
3603
+ if (n.effort !== void 0 && !VALID_EFFORTS.includes(n.effort)) {
3604
+ throw new Error(`reasoning.native.effort must be one of ${VALID_EFFORTS.join(", ")} (got "${n.effort}")`);
3605
+ }
3606
+ if (n.budgetTokens !== void 0 && (!Number.isFinite(n.budgetTokens) || n.budgetTokens < 0)) {
3607
+ throw new Error(`reasoning.native.budgetTokens must be a non-negative number (got ${n.budgetTokens})`);
3608
+ }
3609
+ }
3610
+ if (input.reflection) {
3611
+ const r = input.reflection;
3612
+ if (r.cadence !== void 0 && !VALID_CADENCES.includes(r.cadence)) {
3613
+ throw new Error(`reasoning.reflection.cadence must be one of ${VALID_CADENCES.join(", ")} (got "${r.cadence}")`);
3614
+ }
3615
+ if (r.maxPerRun !== void 0 && (!Number.isFinite(r.maxPerRun) || r.maxPerRun < 0)) {
3616
+ throw new Error(`reasoning.reflection.maxPerRun must be a non-negative number (got ${r.maxPerRun})`);
3617
+ }
3618
+ if (r.everyNTurns !== void 0 && (!Number.isFinite(r.everyNTurns) || r.everyNTurns < 1)) {
3619
+ throw new Error(`reasoning.reflection.everyNTurns must be >= 1 (got ${r.everyNTurns})`);
3620
+ }
3621
+ if (r.feedTo !== void 0 && !["memory", "plan", "none"].includes(r.feedTo)) {
3622
+ throw new Error(`reasoning.reflection.feedTo must be "memory", "plan", or "none" (got "${r.feedTo}")`);
3623
+ }
3624
+ }
3625
+ }
3516
3626
  function resolveReasoning(input) {
3517
3627
  if (!input || input.enabled === false) return void 0;
3628
+ validateReasoningConfig(input);
3518
3629
  const enabled = input.enabled ?? (input.native !== void 0 || input.reflection !== void 0 || input.level !== void 0);
3519
3630
  if (!enabled) return void 0;
3520
3631
  const level = input.level ?? "medium";
@@ -3539,7 +3650,8 @@ function resolveReflection(input, preset) {
3539
3650
  keepLast: 3,
3540
3651
  summarize: false,
3541
3652
  emitEvents: true,
3542
- everyNTurns: 1
3653
+ everyNTurns: 1,
3654
+ feedTo: "none"
3543
3655
  };
3544
3656
  }
3545
3657
  const cfg = input ?? {};
@@ -3556,7 +3668,11 @@ function resolveReflection(input, preset) {
3556
3668
  promptTemplate: cfg.promptTemplate,
3557
3669
  emitEvents: cfg.emitEvents ?? true,
3558
3670
  maxPerRun: typeof cfg.maxPerRun === "number" && cfg.maxPerRun >= 0 ? cfg.maxPerRun : void 0,
3559
- everyNTurns: Math.max(1, Math.trunc(cfg.everyNTurns ?? 1))
3671
+ everyNTurns: Math.max(1, Math.trunc(cfg.everyNTurns ?? 1)),
3672
+ feedTo: cfg.feedTo ?? "none",
3673
+ shouldReflect: cfg.shouldReflect,
3674
+ buildPrompt: cfg.buildPrompt,
3675
+ onReflection: cfg.onReflection
3560
3676
  };
3561
3677
  }
3562
3678
  function ensureArray(value) {
@@ -4282,12 +4398,14 @@ function createAgent(opts) {
4282
4398
  if (summarizationThreshold === void 0) {
4283
4399
  state = clearNeedsSummarization(state);
4284
4400
  }
4285
- if (resolvedReasoning?.native) {
4401
+ if (resolvedReasoning) {
4286
4402
  const ctx = { ...state.ctx || {} };
4287
- if (!ctx.__reasoning) {
4403
+ if (resolvedReasoning.native) {
4288
4404
  ctx.__reasoning = resolvedReasoning.native;
4289
- state = { ...state, ctx };
4405
+ } else {
4406
+ delete ctx.__reasoning;
4290
4407
  }
4408
+ state = { ...state, ctx: Object.keys(ctx).length > 0 ? ctx : void 0 };
4291
4409
  }
4292
4410
  const mergedLimits = {
4293
4411
  ...opts.limits || {},
@@ -4335,6 +4453,7 @@ function createAgent(opts) {
4335
4453
  return { breached: false };
4336
4454
  };
4337
4455
  let iterations = 0;
4456
+ let reflectionsThisRun = 0;
4338
4457
  const onStateChange = config?.onStateChange;
4339
4458
  const checkpointReason = config?.checkpointReason;
4340
4459
  let pausedStage = null;
@@ -4380,6 +4499,16 @@ function createAgent(opts) {
4380
4499
  pausedStage = stage;
4381
4500
  return true;
4382
4501
  };
4502
+ 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")) {
4503
+ try {
4504
+ const patch = await reflectNode(state, "initial_then_after_tool");
4505
+ if (patch && Object.keys(patch).length > 0) {
4506
+ state = { ...state, ...patch };
4507
+ reflectionsThisRun++;
4508
+ }
4509
+ } catch {
4510
+ }
4511
+ }
4383
4512
  while (iterations < iterationLimit) {
4384
4513
  iterations++;
4385
4514
  const budget = checkBudgetBreached();
@@ -4556,16 +4685,18 @@ function createAgent(opts) {
4556
4685
  if (reflectNode && resolvedReasoning?.reflection.enabled) {
4557
4686
  const cadence = resolvedReasoning.reflection.cadence;
4558
4687
  const refl = resolvedReasoning.reflection;
4559
- const reflectionsSoFar = state.reflections?.length ?? 0;
4560
4688
  const lastTurn = state.reflections?.at(-1)?.turn ?? -Infinity;
4561
4689
  const currentTurn = state.toolCallCount || 0;
4562
- const budgetExceeded = typeof refl.maxPerRun === "number" && reflectionsSoFar >= refl.maxPerRun;
4563
- const cadenceGap = currentTurn - (Number.isFinite(lastTurn) ? lastTurn : -refl.everyNTurns) < refl.everyNTurns;
4564
- if (!budgetExceeded && !cadenceGap && shouldRunReflection(cadence, state, true)) {
4690
+ const budgetExceeded = typeof refl.maxPerRun === "number" && reflectionsThisRun >= refl.maxPerRun;
4691
+ const sinceLast = currentTurn - (Number.isFinite(lastTurn) ? lastTurn : -refl.everyNTurns);
4692
+ const cadenceGap = sinceLast < refl.everyNTurns;
4693
+ const cadenceWantsIt = refl.shouldReflect ? !!refl.shouldReflect({ state, turn: currentTurn, trigger: cadence, ranToolsThisTurn: true }) : shouldRunReflection(cadence, state, true);
4694
+ if (!budgetExceeded && !cadenceGap && cadenceWantsIt) {
4565
4695
  try {
4566
4696
  const patch = await reflectNode(state, cadence);
4567
4697
  if (patch && Object.keys(patch).length > 0) {
4568
4698
  state = { ...state, ...patch };
4699
+ reflectionsThisRun++;
4569
4700
  }
4570
4701
  } catch {
4571
4702
  }
@@ -6073,6 +6204,190 @@ async function writeSummaryFactsToMemory(store, config, summary, sourceTurn) {
6073
6204
  return store.get(config.memory.scope, { limit: config.context.lastTurnsToKeep + summary.stable_facts.length });
6074
6205
  }
6075
6206
 
6207
+ // src/smart/skills/types.ts
6208
+ var DEFAULT_SKILL_POLICY = {
6209
+ maxOpenSkills: 4,
6210
+ maxBoundToolsPerSkill: 12,
6211
+ maxBoundToolsTotal: 40
6212
+ };
6213
+ var SMALL_TIER_SKILL_POLICY = {
6214
+ maxOpenSkills: 1,
6215
+ maxBoundToolsPerSkill: 6,
6216
+ maxBoundToolsTotal: 18,
6217
+ modelTier: "small"
6218
+ };
6219
+ function createSkillRegistryRef() {
6220
+ return { openedSkillKeys: [], boundSkillTools: [] };
6221
+ }
6222
+
6223
+ // src/smart/skills/registry.ts
6224
+ function composeToolSets(input) {
6225
+ const without = [...input.base, ...input.boundSkillTools];
6226
+ const withRec = input.recoveryTool ? [...without, input.recoveryTool] : [...without];
6227
+ return { toolsWithoutRecovery: without, toolsWithRecovery: withRec };
6228
+ }
6229
+ function appendBoundTools(ref, newTools, policy) {
6230
+ const present = new Set(ref.boundSkillTools.map((tool) => tool.name));
6231
+ const added = [];
6232
+ for (const tool of newTools) {
6233
+ if (ref.boundSkillTools.length >= policy.maxBoundToolsTotal) break;
6234
+ if (present.has(tool.name)) continue;
6235
+ present.add(tool.name);
6236
+ ref.boundSkillTools.push(tool);
6237
+ added.push(tool);
6238
+ }
6239
+ return added;
6240
+ }
6241
+ function canOpenSkill(ref, policy) {
6242
+ if (ref.openedSkillKeys.length >= policy.maxOpenSkills) {
6243
+ return { ok: false, reason: `max ${policy.maxOpenSkills} skill(s) already open` };
6244
+ }
6245
+ if (ref.boundSkillTools.length >= policy.maxBoundToolsTotal) {
6246
+ return { ok: false, reason: "skill tool budget exhausted" };
6247
+ }
6248
+ return { ok: true };
6249
+ }
6250
+ async function resolveAvailableSkills(skills, opts = {}) {
6251
+ const out = [];
6252
+ for (const skill of skills) {
6253
+ if (skill.minModelTier === "large" && opts.modelTier === "small") continue;
6254
+ const available = skill.isAvailable ? await skill.isAvailable() : true;
6255
+ if (available) out.push(skill);
6256
+ }
6257
+ return out;
6258
+ }
6259
+ function buildSkillHeaderBlock(skills) {
6260
+ if (skills.length === 0) return "";
6261
+ const lines = skills.map((skill) => `- ${skill.key}: ${skill.header}`);
6262
+ return [
6263
+ "<available_skills>",
6264
+ "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.",
6265
+ ...lines,
6266
+ "</available_skills>"
6267
+ ].join("\n");
6268
+ }
6269
+ function dedupeToolsByName(tools) {
6270
+ const seen = /* @__PURE__ */ new Set();
6271
+ const out = [];
6272
+ for (const tool of tools) {
6273
+ if (seen.has(tool.name)) continue;
6274
+ seen.add(tool.name);
6275
+ out.push(tool);
6276
+ }
6277
+ return out;
6278
+ }
6279
+
6280
+ // src/smart/skills/skillTools.ts
6281
+ var MAX_RETURNED_INDEX = 40;
6282
+ 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.";
6283
+ 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.";
6284
+ function findSkill(deps, key) {
6285
+ return deps.skills.find((skill) => skill.key === key);
6286
+ }
6287
+ function createOpenSkillTool(deps) {
6288
+ const tool = createTool({
6289
+ name: "open_skill",
6290
+ description: OPEN_SKILL_DESCRIPTION,
6291
+ schema: zod.z.object({
6292
+ skillKey: zod.z.string().min(1).describe("A key from <available_skills>."),
6293
+ query: zod.z.string().optional().describe("What you need from the skill \u2014 used to rank a large skill's tools.")
6294
+ }).strict(),
6295
+ func: async ({ skillKey, query }) => {
6296
+ const { registryRef: ref, policy } = tool._deps;
6297
+ const skill = findSkill(tool._deps, skillKey);
6298
+ if (!skill) {
6299
+ return { error: `Unknown skill: ${skillKey}. Choose a key listed in <available_skills>.` };
6300
+ }
6301
+ if (skill.isAvailable && !await skill.isAvailable()) {
6302
+ return { error: `Skill ${skillKey} is not available in this workspace.` };
6303
+ }
6304
+ const alreadyOpen = ref.openedSkillKeys.includes(skillKey);
6305
+ if (!alreadyOpen) {
6306
+ const guard = canOpenSkill(ref, policy);
6307
+ if (!guard.ok) {
6308
+ return {
6309
+ error: `Cannot open ${skillKey}: ${guard.reason}. Work with the skills already open.`
6310
+ };
6311
+ }
6312
+ ref.openedSkillKeys.push(skillKey);
6313
+ }
6314
+ const prompt = typeof skill.prompt === "function" ? await skill.prompt() : skill.prompt;
6315
+ const index = await skill.listToolIndex();
6316
+ if (index.length <= policy.maxBoundToolsPerSkill) {
6317
+ const bound = await skill.bindTools();
6318
+ const added = appendBoundTools(ref, bound, policy);
6319
+ if (added.length > 0) ref.__onToolsChanged?.();
6320
+ return {
6321
+ skillKey,
6322
+ prompt,
6323
+ needsSandbox: Boolean(skill.needsSandbox),
6324
+ boundTools: added.map((t) => t.name),
6325
+ // Inject the bound tools into the live runtime for this loop.
6326
+ __runtimeToolsDelta: added
6327
+ };
6328
+ }
6329
+ let defaultBound = [];
6330
+ let defaultAdded = [];
6331
+ if ((!query || query.trim().length < 3) && skill.defaultBindNames?.length) {
6332
+ const bound = await skill.bindTools(skill.defaultBindNames.slice(0, policy.maxBoundToolsPerSkill));
6333
+ defaultAdded = appendBoundTools(ref, bound, policy);
6334
+ if (defaultAdded.length > 0) ref.__onToolsChanged?.();
6335
+ defaultBound = defaultAdded.map((t) => t.name);
6336
+ }
6337
+ const headers = query && query.trim().length >= 3 && skill.rankToolHeaders ? await skill.rankToolHeaders(query, index) : index;
6338
+ return {
6339
+ skillKey,
6340
+ prompt,
6341
+ needsSandbox: Boolean(skill.needsSandbox),
6342
+ boundTools: defaultBound,
6343
+ toolIndex: headers.slice(0, MAX_RETURNED_INDEX).map((h) => ({ name: h.name, description: h.description })),
6344
+ hint: "Call bind_skill_tools(skillKey, toolNames) with only the tools you need.",
6345
+ ...defaultAdded.length > 0 ? { __runtimeToolsDelta: defaultAdded } : {}
6346
+ };
6347
+ }
6348
+ });
6349
+ tool._deps = deps;
6350
+ tool.__source = "smart-skills";
6351
+ return tool;
6352
+ }
6353
+ function createBindSkillToolsTool(deps) {
6354
+ const tool = createTool({
6355
+ name: "bind_skill_tools",
6356
+ description: BIND_SKILL_TOOLS_DESCRIPTION,
6357
+ schema: zod.z.object({
6358
+ skillKey: zod.z.string().min(1),
6359
+ toolNames: zod.z.array(zod.z.string().min(1)).min(1).describe("Tool names from the skill's index.")
6360
+ }).strict(),
6361
+ func: async ({ skillKey, toolNames }) => {
6362
+ const { registryRef: ref, policy } = tool._deps;
6363
+ const skill = findSkill(tool._deps, skillKey);
6364
+ if (!skill) {
6365
+ return { error: `Unknown skill: ${skillKey}.` };
6366
+ }
6367
+ if (!ref.openedSkillKeys.includes(skillKey)) {
6368
+ return { error: `Call open_skill("${skillKey}") before binding its tools.` };
6369
+ }
6370
+ const capped = toolNames.slice(0, policy.maxBoundToolsPerSkill);
6371
+ const bound = await skill.bindTools(capped);
6372
+ const added = appendBoundTools(ref, bound, policy);
6373
+ if (added.length > 0) ref.__onToolsChanged?.();
6374
+ return {
6375
+ skillKey,
6376
+ boundTools: added.map((t) => t.name),
6377
+ requested: capped.length,
6378
+ truncated: toolNames.length > capped.length,
6379
+ ...added.length > 0 ? { __runtimeToolsDelta: added } : {}
6380
+ };
6381
+ }
6382
+ });
6383
+ tool._deps = deps;
6384
+ tool.__source = "smart-skills";
6385
+ return tool;
6386
+ }
6387
+ function createSkillTools(deps) {
6388
+ return [createOpenSkillTool(deps), createBindSkillToolsTool(deps)];
6389
+ }
6390
+
6076
6391
  // src/smart/index.ts
6077
6392
  function createSmartAgent(opts) {
6078
6393
  const resolved = normalizeSmartAgentOptions(opts);
@@ -6107,6 +6422,9 @@ function createSmartAgent(opts) {
6107
6422
  if (askUserConfig) {
6108
6423
  factoryToolsWithoutRecovery.push(createAskUserQuestionTool(factoryStateRef, askUserConfig));
6109
6424
  }
6425
+ const skills = opts.skills ?? [];
6426
+ const skillPolicy = opts.skillPolicy ?? DEFAULT_SKILL_POLICY;
6427
+ const skillsEnabled = skills.length > 0;
6110
6428
  const soManagerFactory = opts.outputSchema ? new StructuredOutputManager(opts.outputSchema, resolveStrategy(opts.model)) : void 0;
6111
6429
  const modelCapabilities = opts.outputSchema ? getModelCapabilities(opts.model) : void 0;
6112
6430
  const responseFinalizeTool = soManagerFactory && modelCapabilities?.structuredOutput !== "native" ? soManagerFactory.getResponseTool() : void 0;
@@ -6114,12 +6432,31 @@ function createSmartAgent(opts) {
6114
6432
  const ref = { toolHistory: void 0, toolHistoryArchived: void 0, todoList: void 0, planVersion: 0, adherenceScore: 0 };
6115
6433
  const ctxTools = createContextTools(ref, { planningEnabled, includeGetToolResponse: false });
6116
6434
  const recoveryTool = createGetToolResponseTool(ref);
6117
- const base2 = [...userTools, ...ctxTools];
6118
- if (responseFinalizeTool) base2.push(responseFinalizeTool);
6119
- if (askUserConfig) base2.push(createAskUserQuestionTool(ref, askUserConfig));
6120
- const without = base2;
6121
- const withRec = [...without, recoveryTool];
6122
- return { stateRef: ref, toolsWithoutRecovery: without, toolsWithRecovery: withRec };
6435
+ const coreBase = [...userTools, ...ctxTools];
6436
+ if (responseFinalizeTool) coreBase.push(responseFinalizeTool);
6437
+ if (askUserConfig) coreBase.push(createAskUserQuestionTool(ref, askUserConfig));
6438
+ if (!skillsEnabled) {
6439
+ const without = coreBase;
6440
+ const withRec = [...without, recoveryTool];
6441
+ return { stateRef: ref, toolsWithoutRecovery: without, toolsWithRecovery: withRec };
6442
+ }
6443
+ const toolSet = { stateRef: ref, toolsWithoutRecovery: [], toolsWithRecovery: [] };
6444
+ const skillRegistryRef = createSkillRegistryRef();
6445
+ const skillMetaTools = createSkillTools({ registryRef: skillRegistryRef, skills, policy: skillPolicy });
6446
+ const baseWithMeta = [...coreBase, ...skillMetaTools];
6447
+ const rebuild = () => {
6448
+ const composed = composeToolSets({
6449
+ base: baseWithMeta,
6450
+ boundSkillTools: skillRegistryRef.boundSkillTools,
6451
+ recoveryTool
6452
+ });
6453
+ toolSet.toolsWithoutRecovery = composed.toolsWithoutRecovery;
6454
+ toolSet.toolsWithRecovery = composed.toolsWithRecovery;
6455
+ };
6456
+ skillRegistryRef.__onToolsChanged = rebuild;
6457
+ toolSet.skillRegistryRef = skillRegistryRef;
6458
+ rebuild();
6459
+ return toolSet;
6123
6460
  };
6124
6461
  const base = createAgent({ ...runtimeOpts, tools: factoryToolsWithoutRecovery });
6125
6462
  base.__runtime.runtimeProfile = resolved.runtimeProfile;
@@ -6170,9 +6507,9 @@ function createSmartAgent(opts) {
6170
6507
  planVersion: ref.planVersion || state.planVersion || 1
6171
6508
  };
6172
6509
  }
6173
- function systemMessage2() {
6510
+ function systemMessage2(extraBlock) {
6174
6511
  const sys = buildSystemPrompt(
6175
- [opts.systemPrompt, runtimeHint, structuredOutputHint].filter(Boolean).join("\n"),
6512
+ [opts.systemPrompt, runtimeHint, structuredOutputHint, extraBlock].filter(Boolean).join("\n"),
6176
6513
  planningEnabled,
6177
6514
  opts.name || "Agent",
6178
6515
  opts.todoListPrompt
@@ -6222,8 +6559,10 @@ function createSmartAgent(opts) {
6222
6559
  stateRef.planVersion = input.planVersion || input.plan?.version || 0;
6223
6560
  stateRef.adherenceScore = input.plan?.adherenceScore || 0;
6224
6561
  const syncPlanFromRef = (state2) => syncPlanStateWith(stateRef, state2);
6562
+ const availableSkills = skillsEnabled ? await resolveAvailableSkills(skills, { modelTier: skillPolicy.modelTier }) : [];
6563
+ const skillBlock = availableSkills.length > 0 ? buildSkillHeaderBlock(availableSkills) : void 0;
6225
6564
  const alreadyHasSystem = Array.isArray(input.messages) && input.messages[0]?.role === "system";
6226
- const seedMessages = alreadyHasSystem ? [...input.messages || []] : [systemMessage2(), ...input.messages || []];
6565
+ const seedMessages = alreadyHasSystem ? [...input.messages || []] : [systemMessage2(skillBlock), ...input.messages || []];
6227
6566
  let state = syncRuntimeTools(await syncMemory({ ...input, messages: seedMessages }), seedMessages, toolSet);
6228
6567
  let lastResult = null;
6229
6568
  let rawMessages = [...seedMessages];
@@ -6828,6 +7167,20 @@ function parseSSEBlock(block) {
6828
7167
  }
6829
7168
 
6830
7169
  // src/providers/utils/reasoning.ts
7170
+ var ANTHROPIC_EFFORT_BUDGET = {
7171
+ minimal: 1024,
7172
+ low: 2048,
7173
+ medium: 8192,
7174
+ high: 16384
7175
+ };
7176
+ var GEMINI_EFFORT_BUDGET = {
7177
+ minimal: 512,
7178
+ low: 1024,
7179
+ medium: 4096,
7180
+ high: 12e3
7181
+ };
7182
+ var THINKING_OUTPUT_RESERVE = 1024;
7183
+ var THINKING_MIN_MAX_TOKENS = 4096;
6831
7184
  function applyOpenAIReasoning(body, reasoning, mode = "legacy_effort") {
6832
7185
  if (!reasoning) return;
6833
7186
  const effort = normalizeEffort(reasoning.effort);
@@ -6844,21 +7197,56 @@ function applyOpenAIReasoning(body, reasoning, mode = "legacy_effort") {
6844
7197
  }
6845
7198
  function applyAnthropicReasoning(body, reasoning) {
6846
7199
  if (!reasoning) return;
6847
- const budget = resolveBudget(reasoning, { low: 2048, medium: 8192, high: 16384, minimal: 1024 });
7200
+ let budget = resolveBudget(reasoning, ANTHROPIC_EFFORT_BUDGET);
6848
7201
  if (!budget) return;
7202
+ const currentMax = typeof body.max_tokens === "number" ? body.max_tokens : 0;
7203
+ const requiredMax = Math.max(THINKING_MIN_MAX_TOKENS, budget + THINKING_OUTPUT_RESERVE);
7204
+ if (currentMax < requiredMax) {
7205
+ body.max_tokens = requiredMax;
7206
+ }
7207
+ budget = clampBudget(budget, body.max_tokens);
6849
7208
  const thinking = { type: "enabled", budget_tokens: budget };
6850
7209
  if (reasoning.providerExtras) Object.assign(thinking, reasoning.providerExtras);
6851
7210
  body.thinking = thinking;
7211
+ stripSamplingParams(body, ["temperature", "top_p", "top_k"]);
7212
+ }
7213
+ function applyBedrockReasoning(body, reasoning) {
7214
+ if (!reasoning) return;
7215
+ let budget = resolveBudget(reasoning, ANTHROPIC_EFFORT_BUDGET);
7216
+ if (!budget) return;
7217
+ const inference = body.inferenceConfig ?? (body.inferenceConfig = {});
7218
+ const currentMax = typeof inference.maxTokens === "number" ? inference.maxTokens : 0;
7219
+ const requiredMax = Math.max(THINKING_MIN_MAX_TOKENS, budget + THINKING_OUTPUT_RESERVE);
7220
+ if (currentMax < requiredMax) {
7221
+ inference.maxTokens = requiredMax;
7222
+ }
7223
+ budget = clampBudget(budget, inference.maxTokens);
7224
+ const extra = body.additionalModelRequestFields ?? (body.additionalModelRequestFields = {});
7225
+ const thinking = { type: "enabled", budget_tokens: budget };
7226
+ if (reasoning.providerExtras) Object.assign(thinking, reasoning.providerExtras);
7227
+ extra.thinking = thinking;
7228
+ stripSamplingParams(inference, ["temperature", "topP"]);
6852
7229
  }
6853
7230
  function applyGeminiReasoning(generationConfig, reasoning) {
6854
7231
  if (!reasoning) return;
6855
- const budget = resolveBudget(reasoning, { low: 1024, medium: 4096, high: 12e3, minimal: 512 });
7232
+ const budget = resolveBudget(reasoning, GEMINI_EFFORT_BUDGET);
6856
7233
  if (budget == null) return;
6857
7234
  const thinkingConfig = { thinkingBudget: budget };
6858
7235
  if (reasoning.includeThoughts) thinkingConfig.includeThoughts = true;
6859
7236
  if (reasoning.providerExtras) Object.assign(thinkingConfig, reasoning.providerExtras);
6860
7237
  generationConfig.thinkingConfig = thinkingConfig;
6861
7238
  }
7239
+ function stripSamplingParams(target, keys) {
7240
+ for (const k of keys) {
7241
+ if (k in target) delete target[k];
7242
+ }
7243
+ }
7244
+ function clampBudget(budget, maxTokens) {
7245
+ if (typeof maxTokens !== "number" || maxTokens <= 0) return budget;
7246
+ const ceiling = maxTokens - THINKING_OUTPUT_RESERVE;
7247
+ if (ceiling < 1024) return Math.max(1024, Math.floor(maxTokens / 2));
7248
+ return Math.min(budget, ceiling);
7249
+ }
6862
7250
  function normalizeEffort(effort) {
6863
7251
  if (!effort) return void 0;
6864
7252
  const allowed = ["minimal", "low", "medium", "high"];
@@ -6887,13 +7275,38 @@ var OpenAIProvider = class extends BaseProvider {
6887
7275
  };
6888
7276
  if (config.retry) this.retryPolicy = { ...this.retryPolicy, ...config.retry };
6889
7277
  }
7278
+ /** True when the request targets a reasoning model (o-series / gpt-5) so we
7279
+ * should route through the Responses API, which exposes `reasoning.effort`
7280
+ * and reasoning summaries. Chat Completions silently drops these. */
7281
+ useResponsesApi(request) {
7282
+ if (!request.reasoning) return false;
7283
+ return isReasoningModel(request.model || this.defaultModel);
7284
+ }
6890
7285
  async complete(request) {
7286
+ if (this.useResponsesApi(request)) {
7287
+ return this.completeResponses(request);
7288
+ }
6891
7289
  const body = this.buildRequestBody(request, false);
6892
7290
  const res = await this.doFetch(body);
6893
7291
  const json = await res.json();
6894
7292
  return this.parseResponse(json);
6895
7293
  }
6896
7294
  async *completeStream(request) {
7295
+ if (this.useResponsesApi(request)) {
7296
+ const response = await this.completeResponses(request);
7297
+ yield {
7298
+ id: response.id,
7299
+ model: response.model,
7300
+ delta: {
7301
+ content: response.content ?? void 0,
7302
+ toolCalls: response.toolCalls.length > 0 ? response.toolCalls : void 0,
7303
+ reasoning: response.reasoning
7304
+ },
7305
+ usage: response.usage,
7306
+ finishReason: response.finishReason
7307
+ };
7308
+ return;
7309
+ }
6897
7310
  const body = this.buildRequestBody(request, true);
6898
7311
  const res = await this.doFetch(body);
6899
7312
  if (!res.body) throw new ProviderError("No response body for stream", this.providerName);
@@ -6992,6 +7405,156 @@ var OpenAIProvider = class extends BaseProvider {
6992
7405
  applyOpenAIReasoning(body, request.reasoning, "legacy_effort");
6993
7406
  return body;
6994
7407
  }
7408
+ // ─── Responses API (reasoning models) ──────────────────────────────────────
7409
+ async completeResponses(request) {
7410
+ const body = this.buildResponsesBody(request);
7411
+ const res = await this.responsesFetch(body);
7412
+ const json = await res.json();
7413
+ return this.parseResponsesResponse(json, request.model || this.defaultModel);
7414
+ }
7415
+ buildResponsesBody(request) {
7416
+ const body = {
7417
+ model: request.model || this.defaultModel,
7418
+ input: request.messages.map((m) => this.toResponsesInput(m))
7419
+ };
7420
+ if (request.maxTokens != null) body.max_output_tokens = request.maxTokens;
7421
+ if (request.topP != null) body.top_p = request.topP;
7422
+ if (request.tools?.length) {
7423
+ body.tools = request.tools.map((t) => ({
7424
+ type: "function",
7425
+ name: t.name,
7426
+ description: t.description,
7427
+ parameters: t.parameters,
7428
+ ...t.strict ? { strict: true } : {}
7429
+ }));
7430
+ }
7431
+ if (request.toolChoice != null && request.tools?.length) {
7432
+ if (typeof request.toolChoice === "string") {
7433
+ body.tool_choice = request.toolChoice;
7434
+ } else {
7435
+ body.tool_choice = { type: "function", name: request.toolChoice.name };
7436
+ }
7437
+ }
7438
+ if (request.responseFormat) {
7439
+ if (request.responseFormat.type === "json_schema") {
7440
+ body.text = {
7441
+ format: {
7442
+ type: "json_schema",
7443
+ name: request.responseFormat.name ?? "response",
7444
+ schema: request.responseFormat.schema,
7445
+ strict: true
7446
+ }
7447
+ };
7448
+ } else if (request.responseFormat.type === "json_object") {
7449
+ body.text = { format: { type: "json_object" } };
7450
+ }
7451
+ }
7452
+ if (request.extra) Object.assign(body, request.extra);
7453
+ applyOpenAIReasoning(body, request.reasoning, "responses");
7454
+ return body;
7455
+ }
7456
+ /** Maps a unified message to a Responses API `input` item. */
7457
+ toResponsesInput(m) {
7458
+ if (m.role === "tool" && m.toolCallId) {
7459
+ const output = typeof m.content === "string" ? m.content : JSON.stringify(m.content);
7460
+ return { type: "function_call_output", call_id: m.toolCallId, output };
7461
+ }
7462
+ if (m.role === "assistant" && m.toolCalls?.length) {
7463
+ return {
7464
+ __assistantWithCalls: true,
7465
+ text: typeof m.content === "string" ? m.content : "",
7466
+ calls: m.toolCalls.map((tc) => ({
7467
+ type: "function_call",
7468
+ call_id: tc.id,
7469
+ name: tc.name,
7470
+ arguments: tc.arguments
7471
+ }))
7472
+ };
7473
+ }
7474
+ const role = m.role === "system" ? "system" : m.role === "assistant" ? "assistant" : "user";
7475
+ const textType = role === "assistant" ? "output_text" : "input_text";
7476
+ if (typeof m.content === "string") {
7477
+ return { role, content: [{ type: textType, text: m.content }] };
7478
+ }
7479
+ const content = m.content.map((part) => {
7480
+ if (part.type === "text") return { type: textType, text: part.text };
7481
+ if (part.type === "image") {
7482
+ const src = part.source;
7483
+ const url = src.type === "url" ? src.url : `data:${src.mediaType};base64,${src.data}`;
7484
+ return { type: "input_image", image_url: url };
7485
+ }
7486
+ return { type: textType, text: "" };
7487
+ });
7488
+ return { role, content };
7489
+ }
7490
+ async responsesFetch(body) {
7491
+ body.input = expandResponsesInput(body.input);
7492
+ const url = `${this.baseURL}/responses`;
7493
+ const headers = {
7494
+ "Content-Type": "application/json",
7495
+ Authorization: `Bearer ${this.apiKey}`,
7496
+ ...this.defaultHeaders
7497
+ };
7498
+ const payload = JSON.stringify(body);
7499
+ const res = await this.doFetchWithRetry(() => fetch(url, { method: "POST", headers, body: payload }));
7500
+ if (!res.ok) {
7501
+ const text = await res.text().catch(() => "");
7502
+ throw new ProviderError(
7503
+ `OpenAI Responses API error ${res.status}: ${text}`,
7504
+ this.providerName,
7505
+ res.status,
7506
+ text
7507
+ );
7508
+ }
7509
+ return res;
7510
+ }
7511
+ parseResponsesResponse(json, modelId) {
7512
+ const textParts = [];
7513
+ const toolCalls = [];
7514
+ const summaryParts = [];
7515
+ for (const item of json.output ?? []) {
7516
+ if (item.type === "message") {
7517
+ for (const c of item.content ?? []) {
7518
+ if (c.type === "output_text" && typeof c.text === "string") textParts.push(c.text);
7519
+ }
7520
+ } else if (item.type === "function_call") {
7521
+ toolCalls.push({
7522
+ id: item.call_id ?? item.id ?? "",
7523
+ name: item.name ?? "",
7524
+ arguments: typeof item.arguments === "string" ? item.arguments : JSON.stringify(item.arguments ?? {})
7525
+ });
7526
+ } else if (item.type === "reasoning") {
7527
+ for (const s of item.summary ?? []) {
7528
+ if (typeof s.text === "string") summaryParts.push(s.text);
7529
+ }
7530
+ }
7531
+ }
7532
+ if (textParts.length === 0 && typeof json.output_text === "string") {
7533
+ textParts.push(json.output_text);
7534
+ }
7535
+ const usage = json.usage ?? {};
7536
+ const reasoningTokens = usage.output_tokens_details?.reasoning_tokens ?? 0;
7537
+ const tokenUsage = {
7538
+ inputTokens: usage.input_tokens ?? 0,
7539
+ outputTokens: usage.output_tokens ?? 0,
7540
+ totalTokens: usage.total_tokens ?? (usage.input_tokens ?? 0) + (usage.output_tokens ?? 0),
7541
+ cachedInputTokens: usage.input_tokens_details?.cached_tokens ?? 0,
7542
+ cachedWriteTokens: 0,
7543
+ cachedOutputTokens: 0,
7544
+ reasoningTokens
7545
+ };
7546
+ const finishReason = toolCalls.length > 0 ? "tool_calls" : json.status === "incomplete" ? "length" : "stop";
7547
+ return {
7548
+ id: json.id ?? "",
7549
+ model: json.model ?? modelId,
7550
+ content: textParts.join("") || null,
7551
+ toolCalls,
7552
+ usage: tokenUsage,
7553
+ finishReason,
7554
+ reasoning: summaryParts.length > 0 ? { summary: summaryParts.join("\n").trim() || void 0 } : void 0,
7555
+ raw: json
7556
+ };
7557
+ }
6995
7558
  toOpenAIMessage(m) {
6996
7559
  const msg = { role: m.role };
6997
7560
  if (typeof m.content === "string") {
@@ -7084,6 +7647,25 @@ var OpenAIProvider = class extends BaseProvider {
7084
7647
  };
7085
7648
  }
7086
7649
  };
7650
+ function isReasoningModel(model) {
7651
+ if (!model) return false;
7652
+ const m = model.toLowerCase();
7653
+ return /(^|[/_-])o[0-9]/.test(m) || m.startsWith("o1") || m.startsWith("o3") || m.startsWith("o4") || m.includes("gpt-5") || m.includes("gpt5");
7654
+ }
7655
+ function expandResponsesInput(input) {
7656
+ const out = [];
7657
+ for (const item of input) {
7658
+ if (item && item.__assistantWithCalls) {
7659
+ if (item.text) {
7660
+ out.push({ role: "assistant", content: [{ type: "output_text", text: item.text }] });
7661
+ }
7662
+ for (const call of item.calls) out.push(call);
7663
+ } else {
7664
+ out.push(item);
7665
+ }
7666
+ }
7667
+ return out;
7668
+ }
7087
7669
  function mapFinishReason(reason) {
7088
7670
  switch (reason) {
7089
7671
  case "stop":
@@ -7129,6 +7711,7 @@ var AnthropicProvider = class extends BaseProvider {
7129
7711
  let cacheReadInputTokens = 0;
7130
7712
  let cacheCreationInputTokens = 0;
7131
7713
  const currentToolCalls = /* @__PURE__ */ new Map();
7714
+ const reasoningBlocks = /* @__PURE__ */ new Map();
7132
7715
  for await (const event of parseSSEStream(res.body)) {
7133
7716
  let data;
7134
7717
  try {
@@ -7158,6 +7741,10 @@ var AnthropicProvider = class extends BaseProvider {
7158
7741
  name: block.name ?? "",
7159
7742
  arguments: ""
7160
7743
  });
7744
+ } else if (block?.type === "thinking") {
7745
+ reasoningBlocks.set(idx, { type: "thinking", text: block.thinking ?? "", signature: block.signature });
7746
+ } else if (block?.type === "redacted_thinking") {
7747
+ reasoningBlocks.set(idx, { type: "redacted_thinking", data: block.data });
7161
7748
  }
7162
7749
  break;
7163
7750
  }
@@ -7170,6 +7757,19 @@ var AnthropicProvider = class extends BaseProvider {
7170
7757
  model,
7171
7758
  delta: { content: delta.text }
7172
7759
  };
7760
+ } else if (delta?.type === "thinking_delta" && delta.thinking) {
7761
+ const blk = reasoningBlocks.get(idx) ?? { type: "thinking", text: "" };
7762
+ blk.text = (blk.text ?? "") + delta.thinking;
7763
+ reasoningBlocks.set(idx, blk);
7764
+ yield {
7765
+ id,
7766
+ model,
7767
+ delta: { reasoning: { summary: delta.thinking } }
7768
+ };
7769
+ } else if (delta?.type === "signature_delta" && delta.signature) {
7770
+ const blk = reasoningBlocks.get(idx) ?? { type: "thinking", text: "" };
7771
+ blk.signature = (blk.signature ?? "") + delta.signature;
7772
+ reasoningBlocks.set(idx, blk);
7173
7773
  } else if (delta?.type === "input_json_delta" && delta.partial_json) {
7174
7774
  const tc = currentToolCalls.get(idx);
7175
7775
  if (tc) {
@@ -7202,10 +7802,13 @@ var AnthropicProvider = class extends BaseProvider {
7202
7802
  cachedOutputTokens: 0,
7203
7803
  reasoningTokens: 0
7204
7804
  };
7805
+ const blocks = [...reasoningBlocks.values()].filter(
7806
+ (b) => b.type === "thinking" && b.signature || b.type === "redacted_thinking" && b.data
7807
+ );
7205
7808
  yield {
7206
7809
  id,
7207
7810
  model,
7208
- delta: {},
7811
+ delta: blocks.length > 0 ? { reasoning: { blocks } } : {},
7209
7812
  finishReason,
7210
7813
  usage
7211
7814
  };
@@ -7297,6 +7900,7 @@ var AnthropicProvider = class extends BaseProvider {
7297
7900
  }
7298
7901
  if (m.role === "assistant" && m.toolCalls?.length) {
7299
7902
  const content = [];
7903
+ appendReasoningBlocks(content, m.reasoning?.blocks);
7300
7904
  if (typeof m.content === "string" && m.content) {
7301
7905
  content.push({ type: "text", text: m.content });
7302
7906
  }
@@ -7310,6 +7914,13 @@ var AnthropicProvider = class extends BaseProvider {
7310
7914
  }
7311
7915
  return { role: "assistant", content };
7312
7916
  }
7917
+ if (m.role === "assistant" && m.reasoning?.blocks?.length) {
7918
+ const content = [];
7919
+ appendReasoningBlocks(content, m.reasoning.blocks);
7920
+ const text = typeof m.content === "string" ? m.content : "";
7921
+ if (text) content.push({ type: "text", text });
7922
+ return { role: "assistant", content };
7923
+ }
7313
7924
  const msg = { role: m.role };
7314
7925
  if (typeof m.content === "string") {
7315
7926
  msg.content = m.content;
@@ -7365,9 +7976,20 @@ var AnthropicProvider = class extends BaseProvider {
7365
7976
  parseResponse(json) {
7366
7977
  const textParts = [];
7367
7978
  const toolCalls = [];
7979
+ const reasoningBlocks = [];
7980
+ const summaryParts = [];
7368
7981
  for (const block of json.content ?? []) {
7369
7982
  if (block.type === "text") {
7370
7983
  textParts.push(block.text);
7984
+ } else if (block.type === "thinking") {
7985
+ reasoningBlocks.push({
7986
+ type: "thinking",
7987
+ text: block.thinking ?? "",
7988
+ signature: block.signature
7989
+ });
7990
+ if (block.thinking) summaryParts.push(block.thinking);
7991
+ } else if (block.type === "redacted_thinking") {
7992
+ reasoningBlocks.push({ type: "redacted_thinking", data: block.data });
7371
7993
  } else if (block.type === "tool_use") {
7372
7994
  toolCalls.push({
7373
7995
  id: block.id,
@@ -7384,6 +8006,9 @@ var AnthropicProvider = class extends BaseProvider {
7384
8006
  cachedInputTokens: usage.cache_read_input_tokens ?? 0,
7385
8007
  cachedWriteTokens: usage.cache_creation_input_tokens ?? 0,
7386
8008
  cachedOutputTokens: 0,
8009
+ // Anthropic bills thinking tokens inside `output_tokens` and does not
8010
+ // expose a separate count, so reasoningTokens stays 0 here (cost is still
8011
+ // captured via outputTokens). See docs for the limitation.
7387
8012
  reasoningTokens: 0
7388
8013
  };
7389
8014
  return {
@@ -7393,6 +8018,7 @@ var AnthropicProvider = class extends BaseProvider {
7393
8018
  toolCalls,
7394
8019
  usage: tokenUsage,
7395
8020
  finishReason: mapAnthropicStopReason(json.stop_reason),
8021
+ reasoning: reasoningBlocks.length > 0 ? { blocks: reasoningBlocks, summary: summaryParts.join("\n").trim() || void 0 } : void 0,
7396
8022
  raw: json
7397
8023
  };
7398
8024
  }
@@ -7417,6 +8043,18 @@ function safeJsonParse(str) {
7417
8043
  return {};
7418
8044
  }
7419
8045
  }
8046
+ function appendReasoningBlocks(content, blocks) {
8047
+ if (!blocks?.length) return;
8048
+ for (const b of blocks) {
8049
+ if (b.type === "redacted_thinking") {
8050
+ if (b.data) content.push({ type: "redacted_thinking", data: b.data });
8051
+ } else if (b.type === "thinking") {
8052
+ if (b.signature) {
8053
+ content.push({ type: "thinking", thinking: b.text ?? "", signature: b.signature });
8054
+ }
8055
+ }
8056
+ }
8057
+ }
7420
8058
 
7421
8059
  // src/providers/azure.ts
7422
8060
  var AzureProvider = class extends OpenAIProvider {
@@ -7460,7 +8098,52 @@ var AzureProvider = class extends OpenAIProvider {
7460
8098
  }
7461
8099
  return res;
7462
8100
  }
8101
+ /** Azure exposes the Responses API at /openai/responses with api-key auth.
8102
+ * Reasoning summaries require a preview api-version; callers can override via
8103
+ * the `apiVersion` config. */
8104
+ async responsesFetch(body) {
8105
+ body.input = expandAzureResponsesInput(body.input);
8106
+ const deployment = this.deploymentName ?? body.model;
8107
+ if (!deployment) {
8108
+ throw new ProviderError("Azure requires a deploymentName or model", this.providerName);
8109
+ }
8110
+ const url = `${this.endpoint}/openai/responses?api-version=${this.apiVersion}`;
8111
+ const payload = JSON.stringify({ ...body, model: deployment });
8112
+ const res = await fetch(url, {
8113
+ method: "POST",
8114
+ headers: {
8115
+ "Content-Type": "application/json",
8116
+ "api-key": this.azureApiKey,
8117
+ ...this.defaultHeaders
8118
+ },
8119
+ body: payload
8120
+ });
8121
+ if (!res.ok) {
8122
+ const text = await res.text().catch(() => "");
8123
+ throw new ProviderError(
8124
+ `Azure OpenAI Responses API error ${res.status}: ${text}`,
8125
+ this.providerName,
8126
+ res.status,
8127
+ text
8128
+ );
8129
+ }
8130
+ return res;
8131
+ }
7463
8132
  };
8133
+ function expandAzureResponsesInput(input) {
8134
+ const out = [];
8135
+ for (const item of input) {
8136
+ if (item && item.__assistantWithCalls) {
8137
+ if (item.text) {
8138
+ out.push({ role: "assistant", content: [{ type: "output_text", text: item.text }] });
8139
+ }
8140
+ for (const call of item.calls) out.push(call);
8141
+ } else {
8142
+ out.push(item);
8143
+ }
8144
+ }
8145
+ return out;
8146
+ }
7464
8147
 
7465
8148
  // src/providers/openaiCompatible.ts
7466
8149
  var OpenAICompatibleProvider = class extends OpenAIProvider {
@@ -7633,6 +8316,7 @@ var BedrockProvider = class extends BaseProvider {
7633
8316
  if (request.extra) {
7634
8317
  Object.assign(body, request.extra);
7635
8318
  }
8319
+ applyBedrockReasoning(body, request.reasoning);
7636
8320
  return body;
7637
8321
  }
7638
8322
  splitSystemMessages(messages) {
@@ -7666,6 +8350,7 @@ var BedrockProvider = class extends BaseProvider {
7666
8350
  }
7667
8351
  if (m.role === "assistant" && m.toolCalls?.length) {
7668
8352
  const content2 = [];
8353
+ appendBedrockReasoning(content2, m.reasoning?.blocks);
7669
8354
  if (typeof m.content === "string" && m.content) {
7670
8355
  content2.push({ text: m.content });
7671
8356
  }
@@ -7746,9 +8431,23 @@ var BedrockProvider = class extends BaseProvider {
7746
8431
  const output = json.output?.message;
7747
8432
  const textParts = [];
7748
8433
  const toolCalls = [];
8434
+ const reasoningBlocks = [];
8435
+ const summaryParts = [];
7749
8436
  for (const block of output?.content ?? []) {
7750
8437
  if (block.text) {
7751
8438
  textParts.push(block.text);
8439
+ } else if (block.reasoningContent) {
8440
+ const rc = block.reasoningContent;
8441
+ if (rc.reasoningText) {
8442
+ reasoningBlocks.push({
8443
+ type: "thinking",
8444
+ text: rc.reasoningText.text ?? "",
8445
+ signature: rc.reasoningText.signature
8446
+ });
8447
+ if (rc.reasoningText.text) summaryParts.push(rc.reasoningText.text);
8448
+ } else if (rc.redactedContent) {
8449
+ reasoningBlocks.push({ type: "redacted_thinking", data: rc.redactedContent });
8450
+ }
7752
8451
  } else if (block.toolUse) {
7753
8452
  toolCalls.push({
7754
8453
  id: block.toolUse.toolUseId,
@@ -7765,6 +8464,7 @@ var BedrockProvider = class extends BaseProvider {
7765
8464
  cachedInputTokens: usage.cacheReadInputTokenCount ?? 0,
7766
8465
  cachedWriteTokens: usage.cacheWriteInputTokenCount ?? 0,
7767
8466
  cachedOutputTokens: 0,
8467
+ // Bedrock bills thinking tokens inside outputTokens; no separate count.
7768
8468
  reasoningTokens: 0
7769
8469
  };
7770
8470
  return {
@@ -7774,10 +8474,25 @@ var BedrockProvider = class extends BaseProvider {
7774
8474
  toolCalls,
7775
8475
  usage: tokenUsage,
7776
8476
  finishReason: mapBedrockStopReason(json.stopReason),
8477
+ reasoning: reasoningBlocks.length > 0 ? { blocks: reasoningBlocks, summary: summaryParts.join("\n").trim() || void 0 } : void 0,
7777
8478
  raw: json
7778
8479
  };
7779
8480
  }
7780
8481
  };
8482
+ function appendBedrockReasoning(content, blocks) {
8483
+ if (!blocks?.length) return;
8484
+ for (const b of blocks) {
8485
+ if (b.type === "redacted_thinking") {
8486
+ if (b.data) content.push({ reasoningContent: { redactedContent: b.data } });
8487
+ } else if (b.type === "thinking") {
8488
+ if (b.signature) {
8489
+ content.push({
8490
+ reasoningContent: { reasoningText: { text: b.text ?? "", signature: b.signature } }
8491
+ });
8492
+ }
8493
+ }
8494
+ }
8495
+ }
7781
8496
  function mapBedrockStopReason(reason) {
7782
8497
  switch (reason) {
7783
8498
  case "end_turn":
@@ -8100,10 +8815,15 @@ var VertexProvider = class extends BaseProvider {
8100
8815
  const parts = candidate?.content?.parts ?? [];
8101
8816
  const textParts = [];
8102
8817
  const toolCalls = [];
8818
+ const thoughtParts = [];
8103
8819
  let toolCallIdx = 0;
8104
8820
  for (const part of parts) {
8105
8821
  if (part.text) {
8106
- textParts.push(part.text);
8822
+ if (part.thought === true) {
8823
+ thoughtParts.push(part.text);
8824
+ } else {
8825
+ textParts.push(part.text);
8826
+ }
8107
8827
  } else if (part.functionCall) {
8108
8828
  toolCalls.push({
8109
8829
  id: `call_${toolCallIdx++}`,
@@ -8129,6 +8849,7 @@ var VertexProvider = class extends BaseProvider {
8129
8849
  toolCalls,
8130
8850
  usage: tokenUsage,
8131
8851
  finishReason: mapGeminiFinishReason(candidate?.finishReason),
8852
+ reasoning: thoughtParts.length > 0 ? { summary: thoughtParts.join("\n").trim() || void 0 } : void 0,
8132
8853
  raw: json
8133
8854
  };
8134
8855
  }
@@ -8138,7 +8859,11 @@ var VertexProvider = class extends BaseProvider {
8138
8859
  const delta = {};
8139
8860
  for (const part of parts) {
8140
8861
  if (part.text) {
8141
- delta.content = (delta.content ?? "") + part.text;
8862
+ if (part.thought === true) {
8863
+ delta.reasoning = { summary: (delta.reasoning?.summary ?? "") + part.text };
8864
+ } else {
8865
+ delta.content = (delta.content ?? "") + part.text;
8866
+ }
8142
8867
  } else if (part.functionCall) {
8143
8868
  if (!delta.toolCalls) delta.toolCalls = [];
8144
8869
  delta.toolCalls.push({
@@ -8212,12 +8937,16 @@ function fromNativeProvider(provider, options) {
8212
8937
  let fullContent = "";
8213
8938
  let allToolCalls = [];
8214
8939
  let lastUsage;
8940
+ let reasoningBlocks;
8215
8941
  const toolCallBuffers = /* @__PURE__ */ new Map();
8216
8942
  for await (const chunk of provider.completeStream(request)) {
8217
8943
  if (chunk.delta.content) {
8218
8944
  fullContent += chunk.delta.content;
8219
8945
  yield chunk.delta.content;
8220
8946
  }
8947
+ if (chunk.delta.reasoning?.blocks?.length) {
8948
+ reasoningBlocks = chunk.delta.reasoning.blocks;
8949
+ }
8221
8950
  if (chunk.delta.toolCalls) {
8222
8951
  for (const tc of chunk.delta.toolCalls) {
8223
8952
  if (tc.id) {
@@ -8238,6 +8967,9 @@ function fromNativeProvider(provider, options) {
8238
8967
  }
8239
8968
  allToolCalls = [...toolCallBuffers.values()];
8240
8969
  const finalMessage = assembleMessage(fullContent, allToolCalls, lastUsage);
8970
+ if (reasoningBlocks?.length) {
8971
+ finalMessage.reasoning = { blocks: reasoningBlocks };
8972
+ }
8241
8973
  yield finalMessage;
8242
8974
  },
8243
8975
  bindTools: (tools, _bindOptions) => {
@@ -8300,6 +9032,10 @@ function toUnifiedMessage(msg) {
8300
9032
  arguments: tc.function?.arguments ?? tc.arguments ?? "{}"
8301
9033
  }));
8302
9034
  }
9035
+ const reasoning = msg.reasoning;
9036
+ if (reasoning && (reasoning.blocks?.length || reasoning.summary)) {
9037
+ unified.reasoning = reasoning;
9038
+ }
8303
9039
  return unified;
8304
9040
  }
8305
9041
  function convertContent(content) {
@@ -8508,6 +9244,9 @@ function toBaseChatMessage(response) {
8508
9244
  function: { name: tc.name, arguments: tc.arguments }
8509
9245
  }));
8510
9246
  }
9247
+ if (response.reasoning && (response.reasoning.blocks?.length || response.reasoning.summary)) {
9248
+ msg.reasoning = response.reasoning;
9249
+ }
8511
9250
  return msg;
8512
9251
  }
8513
9252
  function assembleMessage(content, toolCalls, usage) {
@@ -8609,25 +9348,32 @@ exports.AzureProvider = AzureProvider;
8609
9348
  exports.BaseProvider = BaseProvider;
8610
9349
  exports.BedrockProvider = BedrockProvider;
8611
9350
  exports.DEFAULT_PROFILE_CONFIGS = DEFAULT_PROFILE_CONFIGS;
9351
+ exports.DEFAULT_SKILL_POLICY = DEFAULT_SKILL_POLICY;
8612
9352
  exports.GuardrailPhase = GuardrailPhase;
8613
9353
  exports.InMemoryMemoryStore = InMemoryMemoryStore;
8614
9354
  exports.NativeJsonSchemaStrategy = NativeJsonSchemaStrategy;
8615
9355
  exports.OpenAICompatibleProvider = OpenAICompatibleProvider;
8616
9356
  exports.OpenAIProvider = OpenAIProvider;
8617
9357
  exports.ProviderError = ProviderError;
9358
+ exports.SMALL_TIER_SKILL_POLICY = SMALL_TIER_SKILL_POLICY;
8618
9359
  exports.StructuredOutputManager = StructuredOutputManager;
8619
9360
  exports.ToolBasedStrategy = ToolBasedStrategy;
8620
9361
  exports.VertexProvider = VertexProvider;
8621
9362
  exports.agentVerdictRule = agentVerdictRule;
9363
+ exports.appendBoundTools = appendBoundTools;
9364
+ exports.buildSkillHeaderBlock = buildSkillHeaderBlock;
8622
9365
  exports.buildSystemPrompt = buildSystemPrompt;
9366
+ exports.canOpenSkill = canOpenSkill;
8623
9367
  exports.captureSnapshot = captureSnapshot;
8624
9368
  exports.codePresenceRule = codePresenceRule;
8625
9369
  exports.cognipeerSink = cognipeerSink;
9370
+ exports.composeToolSets = composeToolSets;
8626
9371
  exports.countApproxTokens = countApproxTokens;
8627
9372
  exports.countMessagesTokens = countMessagesTokens;
8628
9373
  exports.createAgent = createAgent;
8629
9374
  exports.createAgentNode = createAgentNode;
8630
9375
  exports.createAskUserQuestionTool = createAskUserQuestionTool;
9376
+ exports.createBindSkillToolsTool = createBindSkillToolsTool;
8631
9377
  exports.createCodeGuardrail = createCodeGuardrail;
8632
9378
  exports.createContextSummarizeNode = createContextSummarizeNode;
8633
9379
  exports.createContextTools = createContextTools;
@@ -8635,15 +9381,19 @@ exports.createGetToolResponseTool = createGetToolResponseTool;
8635
9381
  exports.createGuardrail = createGuardrail;
8636
9382
  exports.createJsonGuardrail = createJsonGuardrail;
8637
9383
  exports.createManageTodoTool = createManageTodoTool;
9384
+ exports.createOpenSkillTool = createOpenSkillTool;
8638
9385
  exports.createProvider = createProvider;
8639
9386
  exports.createRegexGuardrail = createRegexGuardrail;
8640
9387
  exports.createResolverNode = createResolverNode;
9388
+ exports.createSkillRegistryRef = createSkillRegistryRef;
9389
+ exports.createSkillTools = createSkillTools;
8641
9390
  exports.createSmartAgent = createSmartAgent;
8642
9391
  exports.createTool = createTool;
8643
9392
  exports.createToolLimitFinalizeNode = createToolLimitFinalizeNode;
8644
9393
  exports.createToolsNode = createToolsNode;
8645
9394
  exports.customCallbackRule = customCallbackRule;
8646
9395
  exports.customSink = customSink;
9396
+ exports.dedupeToolsByName = dedupeToolsByName;
8647
9397
  exports.defaultTokenCounter = defaultTokenCounter;
8648
9398
  exports.emptyUsage = emptyUsage;
8649
9399
  exports.evaluateGuardrails = evaluateGuardrails;
@@ -8666,7 +9416,9 @@ exports.normalizeSmartAgentOptions = normalizeSmartAgentOptions;
8666
9416
  exports.otlpSink = otlpSink;
8667
9417
  exports.readMemoryFacts = readMemoryFacts;
8668
9418
  exports.regexRule = regexRule;
9419
+ exports.resolveAvailableSkills = resolveAvailableSkills;
8669
9420
  exports.resolveMemoryStore = resolveMemoryStore;
9421
+ exports.resolveReasoning = resolveReasoning;
8670
9422
  exports.resolveStrategy = resolveStrategy;
8671
9423
  exports.resolveToolApprovalState = resolveToolApprovalState;
8672
9424
  exports.resolveUserQuestionState = resolveUserQuestionState;
@@ -8675,6 +9427,7 @@ exports.runSmartAgentEvalHarness = runSmartAgentEvalHarness;
8675
9427
  exports.setTokenCounter = setTokenCounter;
8676
9428
  exports.startStreamingSession = startStreamingSession;
8677
9429
  exports.traceSessionToOtlp = traceSessionToOtlp;
9430
+ exports.validateReasoningConfig = validateReasoningConfig;
8678
9431
  exports.withTools = withTools;
8679
9432
  exports.writeSummaryFactsToMemory = writeSummaryFactsToMemory;
8680
9433
  //# sourceMappingURL=index.cjs.map