@cognipeer/agent-sdk 0.7.2 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -2583,6 +2583,27 @@ function validateToolArgs(tool, args) {
2583
2583
  }
2584
2584
  }
2585
2585
 
2586
+ // src/utils/pendingToolCalls.ts
2587
+ function selectPendingToolCalls(messages) {
2588
+ if (!Array.isArray(messages) || messages.length === 0) return [];
2589
+ const last = messages[messages.length - 1];
2590
+ if (last?.role === "assistant") {
2591
+ return Array.isArray(last.tool_calls) ? last.tool_calls : [];
2592
+ }
2593
+ const resolvedIds = /* @__PURE__ */ new Set();
2594
+ for (const m of messages) {
2595
+ if (m?.role === "tool" && m.tool_call_id != null) resolvedIds.add(String(m.tool_call_id));
2596
+ }
2597
+ for (let i = messages.length - 1; i >= 0; i -= 1) {
2598
+ const m = messages[i];
2599
+ if (m?.role !== "assistant") continue;
2600
+ const calls = Array.isArray(m.tool_calls) ? m.tool_calls : [];
2601
+ if (calls.length === 0) return [];
2602
+ return calls.filter((c) => c?.id == null || !resolvedIds.has(String(c.id)));
2603
+ }
2604
+ return [];
2605
+ }
2606
+
2586
2607
  // src/nodes/tools.ts
2587
2608
  function normalizeMaxExecutionsPerRun(value) {
2588
2609
  if (value === null || value === void 0 || value === "") return null;
@@ -2740,9 +2761,8 @@ function createToolsNode(initialTools, opts) {
2740
2761
  anyTool._stateRef.parentRuntime = runtime;
2741
2762
  }
2742
2763
  }
2743
- const last = state.messages[state.messages.length - 1];
2744
2764
  let toolCount = state.toolCallCount || 0;
2745
- const toolCalls = Array.isArray(last?.tool_calls) ? last.tool_calls.map((toolCall) => normalizeToolCall(toolCall)).filter((toolCall) => toolCall !== null) : [];
2765
+ const toolCalls = selectPendingToolCalls(state.messages).map((toolCall) => normalizeToolCall(toolCall)).filter((toolCall) => toolCall !== null);
2746
2766
  const toolHistory = state.toolHistory || [];
2747
2767
  const toolHistoryArchived = state.toolHistoryArchived || [];
2748
2768
  const remaining = Math.max(0, limits.maxToolCalls - toolCount);
@@ -3984,12 +4004,20 @@ function resolveUserQuestionState(state, resolution) {
3984
4004
  entry.notes = resolution.notes;
3985
4005
  entry.answeredAt = (/* @__PURE__ */ new Date()).toISOString();
3986
4006
  pending[matchIndex] = entry;
4007
+ const isSubagentQuestion = Boolean(entry.metadata?.__subagent);
3987
4008
  const ctx = { ...state.ctx || {} };
3988
4009
  delete ctx.__awaitingUserQuestion;
3989
- if (ctx.__resumeStage === "tools") {
4010
+ if (ctx.__resumeStage === "tools" && !isSubagentQuestion) {
3990
4011
  delete ctx.__resumeStage;
3991
4012
  }
3992
4013
  ctx.__userQuestionResolved = { id: entry.id, status: entry.status };
4014
+ if (isSubagentQuestion) {
4015
+ return {
4016
+ ...state,
4017
+ pendingUserQuestions: pending,
4018
+ ctx
4019
+ };
4020
+ }
3993
4021
  const toolMessage = {
3994
4022
  role: "tool",
3995
4023
  name: "ask_user_question",
@@ -4270,6 +4298,88 @@ var StructuredOutputManager = class {
4270
4298
  }
4271
4299
  };
4272
4300
 
4301
+ // src/smart/subagents/registry.ts
4302
+ function findSubagent(subagents, name) {
4303
+ return subagents.find((entry) => entry.name === name);
4304
+ }
4305
+ async function resolveAvailableSubagents(subagents) {
4306
+ const out = [];
4307
+ for (const entry of subagents) {
4308
+ const available = entry.isAvailable ? await entry.isAvailable() : true;
4309
+ if (available) out.push(entry);
4310
+ }
4311
+ return out;
4312
+ }
4313
+ function canSpawn(ref, policy, count = 1) {
4314
+ if (policy.mode === "off") {
4315
+ return { ok: false, reason: "sub-agents are disabled by runtime policy" };
4316
+ }
4317
+ if (ref.spawnedCount + count > policy.maxChildCalls) {
4318
+ return {
4319
+ ok: false,
4320
+ reason: `child-call budget exhausted (${policy.maxChildCalls}); ${ref.spawnedCount} already spawned`
4321
+ };
4322
+ }
4323
+ return { ok: true };
4324
+ }
4325
+ function withinDepth(currentDepth, policy) {
4326
+ if (currentDepth >= policy.maxDepth) {
4327
+ return { ok: false, reason: `delegation depth limit reached (${policy.maxDepth})` };
4328
+ }
4329
+ return { ok: true };
4330
+ }
4331
+ function seedChildMessages(policy, parentMessages, input) {
4332
+ const messages = (Array.isArray(parentMessages) ? parentMessages : []).filter((m) => m?.role !== "system");
4333
+ switch (policy) {
4334
+ case "full":
4335
+ return [...messages, { role: "user", content: input }];
4336
+ case "scoped": {
4337
+ const lastUser = [...messages].reverse().find((m) => m?.role === "user");
4338
+ return [
4339
+ ...lastUser ? [lastUser] : [],
4340
+ { role: "user", content: input }
4341
+ ];
4342
+ }
4343
+ case "minimal":
4344
+ default:
4345
+ return [{ role: "user", content: input }];
4346
+ }
4347
+ }
4348
+ async function resolveSubagentTools(declared, parentTools) {
4349
+ if (!declared) return [];
4350
+ if (typeof declared === "function") {
4351
+ return await declared();
4352
+ }
4353
+ if (Array.isArray(declared) && declared.length > 0 && typeof declared[0] === "string") {
4354
+ const wanted = new Set(declared);
4355
+ return parentTools.filter((tool) => wanted.has(tool?.name));
4356
+ }
4357
+ return declared;
4358
+ }
4359
+ function buildSubagentCatalogBlock(subagents, policy, toolNames) {
4360
+ const lines = ["<available_subagents>"];
4361
+ const adhoc = policy.mode === "registry_and_adhoc";
4362
+ lines.push(
4363
+ "Delegate self-contained subtasks to focused sub-agents. Each runs with an isolated context and returns a concise result. Use them to decompose hard problems; do NOT delegate trivial steps you can do directly."
4364
+ );
4365
+ if (subagents.length > 0) {
4366
+ lines.push(`Call ${toolNames.delegate}(subagent, input) for a named sub-agent:`);
4367
+ for (const entry of subagents) {
4368
+ lines.push(`- ${entry.name}: ${entry.header}`);
4369
+ }
4370
+ }
4371
+ if (adhoc) {
4372
+ lines.push(
4373
+ `Call ${toolNames.spawn}({ role, prompt, input, tools? }) to create a sub-agent on the fly.`
4374
+ );
4375
+ }
4376
+ lines.push(
4377
+ `Call ${toolNames.parallel}({ tasks: [...] }) to run up to ${policy.maxParallel} independent subtasks concurrently (no human-input tools inside parallel children).`
4378
+ );
4379
+ lines.push("</available_subagents>");
4380
+ return lines.join("\n");
4381
+ }
4382
+
4273
4383
  // src/agent.ts
4274
4384
  function getLastAssistantMessage(messages) {
4275
4385
  for (let index = messages.length - 1; index >= 0; index -= 1) {
@@ -4641,7 +4751,7 @@ function createAgent(opts) {
4641
4751
  resumeStage = null;
4642
4752
  }
4643
4753
  const lastMsg = state.messages[state.messages.length - 1];
4644
- const toolCalls = Array.isArray(lastMsg?.tool_calls) ? lastMsg.tool_calls : [];
4754
+ const toolCalls = selectPendingToolCalls(state.messages);
4645
4755
  const toolCallCount = state.toolCallCount || 0;
4646
4756
  if (state.ctx?.__finalizedDueToToolLimit) {
4647
4757
  break;
@@ -4941,27 +5051,28 @@ function createAgent(opts) {
4941
5051
  error: `Child-call budget exhausted (${delegationPolicy.maxChildCalls}).`
4942
5052
  };
4943
5053
  }
4944
- let childMessages;
4945
- switch (delegationPolicy.childContextPolicy) {
4946
- case "full":
4947
- childMessages = [...parentMessages, { role: "user", content: input }];
4948
- break;
4949
- case "scoped": {
4950
- const systemPrefix = parentMessages[0]?.role === "system" ? [parentMessages[0]] : [];
4951
- const lastUser = [...parentMessages].reverse().find((m) => m?.role === "user");
4952
- childMessages = [
4953
- ...systemPrefix,
4954
- ...lastUser ? [lastUser] : [],
4955
- { role: "user", content: input }
4956
- ];
4957
- break;
4958
- }
4959
- case "minimal":
4960
- default:
4961
- childMessages = [{ role: "user", content: input }];
4962
- }
5054
+ const childMessages = seedChildMessages(
5055
+ delegationPolicy.childContextPolicy,
5056
+ parentMessages,
5057
+ input
5058
+ );
4963
5059
  const childCtx = { __delegationDepth: currentDepth + 1 };
4964
- const res = await instance.invoke({ messages: childMessages, ctx: childCtx });
5060
+ const childConfig = {
5061
+ onEvent: parentCtx.__onEvent ? (e) => {
5062
+ if (e?.type === "finalAnswer" || e?.type === "metadata") return;
5063
+ try {
5064
+ parentCtx.__onEvent({ ...e, delegatedTo: opts.name });
5065
+ } catch {
5066
+ }
5067
+ } : void 0,
5068
+ onProgress: parentCtx.__onProgress,
5069
+ onStream: parentCtx.__streaming && parentCtx.__onStream ? (chunk) => {
5070
+ if (!chunk?.isFinal) parentCtx.__onStream(chunk);
5071
+ } : void 0,
5072
+ stream: Boolean(parentCtx.__streaming),
5073
+ cancellationToken: parentCtx.__cancellationToken ?? parentCtx.__abortSignal
5074
+ };
5075
+ const res = await instance.invoke({ messages: childMessages, ctx: childCtx }, childConfig);
4965
5076
  return {
4966
5077
  content: res.content,
4967
5078
  output: res.output,
@@ -6388,6 +6499,421 @@ function createSkillTools(deps) {
6388
6499
  return [createOpenSkillTool(deps), createBindSkillToolsTool(deps)];
6389
6500
  }
6390
6501
 
6502
+ // src/smart/subagents/types.ts
6503
+ var DEFAULT_SUBAGENT_POLICY = {
6504
+ mode: "registry_and_adhoc",
6505
+ maxDepth: 2,
6506
+ maxChildCalls: 8,
6507
+ maxParallel: 4,
6508
+ childContextPolicy: "scoped",
6509
+ allowAdhocTools: true
6510
+ };
6511
+ function createSubagentRegistryRef() {
6512
+ return { spawnedCount: 0, results: [] };
6513
+ }
6514
+ var DEFAULT_SUBAGENT_TOOL_NAMES = {
6515
+ delegate: "delegate_to",
6516
+ spawn: "spawn_subagent",
6517
+ parallel: "spawn_subagents_parallel"
6518
+ };
6519
+ var DEFAULT_DELEGATE_DESCRIPTION = "Delegate a self-contained subtask to a predefined sub-agent. Pass the sub-agent name (from <available_subagents>) and a complete, standalone `input` describing the task and the expected result. The sub-agent runs in isolation and returns a concise result.";
6520
+ var DEFAULT_SPAWN_DESCRIPTION = "Create a sub-agent on the fly. Provide a short `role`, a `prompt` defining how it should behave, and a complete `input` task. Optionally pass `tools` (names of the parent's tools the sub-agent may use). Use for one-off specialist subtasks.";
6521
+ var DEFAULT_PARALLEL_DESCRIPTION = "Run several independent subtasks concurrently. Each task is either a registry `subagent` + `input`, or an ad-hoc `role` + `prompt` + `input`. Returns one result per task in order. Do NOT use for tasks that require human input (approval / questions).";
6522
+ var CTX_CALLBACK_KEYS = /* @__PURE__ */ new Set([
6523
+ "__onEvent",
6524
+ "__onProgress",
6525
+ "__onStream",
6526
+ "__traceSession",
6527
+ "__paused",
6528
+ "__cancellationToken",
6529
+ "__abortSignal",
6530
+ "__deadline"
6531
+ ]);
6532
+ function cleanChildState(state) {
6533
+ const { agent: _agent, ctx, ...rest } = state;
6534
+ let cleanCtx2;
6535
+ if (ctx && typeof ctx === "object") {
6536
+ cleanCtx2 = {};
6537
+ for (const [k, v] of Object.entries(ctx)) {
6538
+ if (CTX_CALLBACK_KEYS.has(k)) continue;
6539
+ cleanCtx2[k] = v;
6540
+ }
6541
+ }
6542
+ return { ...rest, ctx: cleanCtx2 };
6543
+ }
6544
+ function makeChildEventForwarder(parentOnEvent, spawnId, name) {
6545
+ return (event) => {
6546
+ if (!parentOnEvent) return;
6547
+ if (event?.type === "finalAnswer" || event?.type === "metadata") return;
6548
+ try {
6549
+ parentOnEvent({ ...event, subagentId: spawnId, subagentName: name });
6550
+ } catch {
6551
+ }
6552
+ };
6553
+ }
6554
+ function buildChildConfig(parentCtx, spawnId, name) {
6555
+ const streaming = Boolean(parentCtx.__streaming);
6556
+ const parentOnStream = parentCtx.__onStream;
6557
+ return {
6558
+ onEvent: makeChildEventForwarder(parentCtx.__onEvent, spawnId, name),
6559
+ onProgress: parentCtx.__onProgress,
6560
+ // Forward streaming deltas but swallow the child's `isFinal` chunk so the
6561
+ // host does not mistake a child completion for the parent's final answer.
6562
+ onStream: streaming && parentOnStream ? (chunk) => {
6563
+ if (!chunk.isFinal) parentOnStream(chunk);
6564
+ } : void 0,
6565
+ stream: streaming,
6566
+ cancellationToken: parentCtx.__cancellationToken ?? parentCtx.__abortSignal
6567
+ };
6568
+ }
6569
+ function summaryOf(state) {
6570
+ const summaries = state?.summaries;
6571
+ return Array.isArray(summaries) && summaries.length > 0 ? summaries[summaries.length - 1] : void 0;
6572
+ }
6573
+ async function runChild(spec, input, deps, ref, opts) {
6574
+ const parentCtx = ref.ctx || {};
6575
+ const parentOnEvent = parentCtx.__onEvent;
6576
+ const spawnId = `sa_${nanoid.nanoid(6)}`;
6577
+ const start = Date.now();
6578
+ const child = deps.buildChild({
6579
+ name: spec.name,
6580
+ model: spec.model,
6581
+ systemPrompt: spec.systemPrompt,
6582
+ tools: spec.tools,
6583
+ outputSchema: spec.outputSchema,
6584
+ limits: spec.limits
6585
+ });
6586
+ const childConfig = buildChildConfig(parentCtx, spawnId, spec.name);
6587
+ let childInput;
6588
+ if (opts.isResume && opts.record) {
6589
+ const restored = { ...opts.record.childState };
6590
+ if (opts.record.pendingKind === "approval") {
6591
+ const entry = (ref.pendingApprovals || []).find((e) => e.id === opts.record.pendingId);
6592
+ if (!entry) {
6593
+ return { kind: "result", result: { name: spec.name, mode: spec.mode, input, error: "Pending approval resolution missing on resume." } };
6594
+ }
6595
+ if (entry.status === "pending") {
6596
+ if (!parentCtx.__awaitingApproval) {
6597
+ parentCtx.__awaitingApproval = { approvalId: entry.id, toolCallId: entry.toolCallId, toolName: entry.toolName, requestedAt: entry.requestedAt };
6598
+ }
6599
+ parentCtx.__resumeStage = "tools";
6600
+ return { kind: "approval", toolCallId: entry.toolCallId, approvalId: entry.id };
6601
+ }
6602
+ childInput = resolveToolApprovalState(restored, {
6603
+ id: opts.record.pendingId,
6604
+ approved: entry.status === "approved",
6605
+ approvedArgs: entry.approvedArgs,
6606
+ decidedBy: entry.decidedBy,
6607
+ comment: entry.comment
6608
+ });
6609
+ } else {
6610
+ const entry = (ref.pendingUserQuestions || []).find((e) => e.id === opts.record.pendingId);
6611
+ if (!entry) {
6612
+ return { kind: "result", result: { name: spec.name, mode: spec.mode, input, error: "Pending question resolution missing on resume." } };
6613
+ }
6614
+ if (entry.status === "pending") {
6615
+ if (!parentCtx.__awaitingUserQuestion) {
6616
+ parentCtx.__awaitingUserQuestion = { id: entry.id, toolCallId: entry.toolCallId, requestedAt: entry.requestedAt };
6617
+ }
6618
+ parentCtx.__resumeStage = "tools";
6619
+ return { kind: "user_question", toolCallId: entry.toolCallId, id: entry.id };
6620
+ }
6621
+ childInput = resolveUserQuestionState(restored, {
6622
+ id: opts.record.pendingId,
6623
+ answers: entry.answers,
6624
+ answeredBy: entry.answeredBy,
6625
+ notes: entry.notes,
6626
+ cancelled: entry.cancelled === true
6627
+ });
6628
+ }
6629
+ } else {
6630
+ parentOnEvent?.({ type: "subagent", phase: "start", name: spec.name, id: spawnId, mode: spec.mode, parallel: opts.parallel, parentToolCallId: opts.parentToolCallId, input });
6631
+ const currentDepth = Number(parentCtx.__delegationDepth) || 0;
6632
+ childInput = {
6633
+ messages: seedChildMessages(spec.childContextPolicy, ref.messages || [], input),
6634
+ ctx: { __delegationDepth: currentDepth + 1 }
6635
+ };
6636
+ }
6637
+ let res;
6638
+ try {
6639
+ res = await child.invoke(childInput, childConfig);
6640
+ } catch (err) {
6641
+ const result2 = { name: spec.name, mode: spec.mode, input, error: err?.message || String(err), durationMs: Date.now() - start };
6642
+ deps.registryRef.results.push(result2);
6643
+ parentOnEvent?.({ type: "subagent", phase: "error", name: spec.name, id: spawnId, mode: spec.mode, error: { message: result2.error }, parentToolCallId: opts.parentToolCallId });
6644
+ return { kind: "result", result: result2 };
6645
+ }
6646
+ const childState = res.state;
6647
+ const awaitingApproval = childState?.ctx?.__awaitingApproval;
6648
+ const awaitingQuestion = childState?.ctx?.__awaitingUserQuestion;
6649
+ if (childState && (awaitingApproval || awaitingQuestion)) {
6650
+ if (!opts.allowHITL) {
6651
+ const result2 = {
6652
+ name: spec.name,
6653
+ mode: spec.mode,
6654
+ input,
6655
+ error: "Sub-agent requested human input, which is not supported inside parallel fan-out. Run it via delegate_to / spawn_subagent instead.",
6656
+ durationMs: Date.now() - start
6657
+ };
6658
+ deps.registryRef.results.push(result2);
6659
+ return { kind: "result", result: result2 };
6660
+ }
6661
+ const pendingStore = parentCtx.__subagentPending || (parentCtx.__subagentPending = {});
6662
+ if (awaitingApproval) {
6663
+ const childEntry = (childState.pendingApprovals || []).find((e) => e.status === "pending");
6664
+ if (childEntry) {
6665
+ const surfaced = { ...childEntry, metadata: { ...childEntry.metadata || {}, __subagent: { parentToolCallId: opts.parentToolCallId, name: spec.name } } };
6666
+ (ref.pendingApprovals || (ref.pendingApprovals = [])).push(surfaced);
6667
+ if (!parentCtx.__awaitingApproval && !parentCtx.__awaitingUserQuestion) {
6668
+ parentCtx.__awaitingApproval = { approvalId: surfaced.id, toolCallId: surfaced.toolCallId, toolName: surfaced.toolName, requestedAt: surfaced.requestedAt };
6669
+ }
6670
+ parentCtx.__resumeStage = "tools";
6671
+ pendingStore[opts.parentToolCallId] = {
6672
+ parentToolCallId: opts.parentToolCallId,
6673
+ name: spec.name,
6674
+ mode: spec.mode,
6675
+ adhoc: spec.adhoc,
6676
+ input,
6677
+ childState: cleanChildState(childState),
6678
+ pendingKind: "approval",
6679
+ pendingId: childEntry.id
6680
+ };
6681
+ parentOnEvent?.({ type: "subagent", phase: "paused", name: spec.name, id: spawnId, mode: spec.mode, parentToolCallId: opts.parentToolCallId });
6682
+ return { kind: "approval", toolCallId: surfaced.toolCallId, approvalId: surfaced.id };
6683
+ }
6684
+ }
6685
+ if (awaitingQuestion) {
6686
+ const childEntry = (childState.pendingUserQuestions || []).find((e) => e.status === "pending");
6687
+ if (childEntry) {
6688
+ const surfaced = { ...childEntry, metadata: { ...childEntry.metadata || {}, __subagent: { parentToolCallId: opts.parentToolCallId, name: spec.name } } };
6689
+ (ref.pendingUserQuestions || (ref.pendingUserQuestions = [])).push(surfaced);
6690
+ if (!parentCtx.__awaitingUserQuestion && !parentCtx.__awaitingApproval) {
6691
+ parentCtx.__awaitingUserQuestion = { id: surfaced.id, toolCallId: surfaced.toolCallId, requestedAt: surfaced.requestedAt };
6692
+ }
6693
+ parentCtx.__resumeStage = "tools";
6694
+ pendingStore[opts.parentToolCallId] = {
6695
+ parentToolCallId: opts.parentToolCallId,
6696
+ name: spec.name,
6697
+ mode: spec.mode,
6698
+ adhoc: spec.adhoc,
6699
+ input,
6700
+ childState: cleanChildState(childState),
6701
+ pendingKind: "user_question",
6702
+ pendingId: childEntry.id
6703
+ };
6704
+ parentOnEvent?.({ type: "subagent", phase: "paused", name: spec.name, id: spawnId, mode: spec.mode, parentToolCallId: opts.parentToolCallId });
6705
+ return { kind: "user_question", toolCallId: surfaced.toolCallId, id: surfaced.id };
6706
+ }
6707
+ }
6708
+ }
6709
+ if (parentCtx.__subagentPending?.[opts.parentToolCallId]) {
6710
+ delete parentCtx.__subagentPending[opts.parentToolCallId];
6711
+ }
6712
+ const result = {
6713
+ name: spec.name,
6714
+ mode: spec.mode,
6715
+ input,
6716
+ content: res.content,
6717
+ output: res.output,
6718
+ summary: summaryOf(childState),
6719
+ durationMs: Date.now() - start
6720
+ };
6721
+ deps.registryRef.results.push(result);
6722
+ parentOnEvent?.({ type: "subagent", phase: "result", name: spec.name, id: spawnId, mode: spec.mode, content: res.content, durationMs: result.durationMs, parentToolCallId: opts.parentToolCallId });
6723
+ return { kind: "result", result };
6724
+ }
6725
+ async function specFromRegistry(def, deps, parentRuntime) {
6726
+ const tools = await resolveSubagentTools(def.tools, parentRuntime?.tools || []);
6727
+ return {
6728
+ name: def.name,
6729
+ mode: "registry",
6730
+ systemPrompt: def.systemPrompt,
6731
+ model: def.model ?? parentRuntime?.model,
6732
+ tools,
6733
+ outputSchema: def.outputSchema,
6734
+ limits: def.limits,
6735
+ childContextPolicy: def.childContextPolicy ?? deps.policy.childContextPolicy,
6736
+ metadata: def.metadata
6737
+ };
6738
+ }
6739
+ async function specFromAdhoc(args, deps, parentRuntime) {
6740
+ const toolNames = deps.policy.allowAdhocTools ? args.tools ?? args.toolNames ?? [] : [];
6741
+ const tools = await resolveSubagentTools(toolNames, parentRuntime?.tools || []);
6742
+ const systemPrompt = [args.prompt, args.outputContract ? `Output contract: ${args.outputContract}` : ""].filter(Boolean).join("\n\n");
6743
+ return {
6744
+ name: args.role,
6745
+ mode: "adhoc",
6746
+ systemPrompt: systemPrompt || void 0,
6747
+ model: parentRuntime?.model,
6748
+ tools,
6749
+ childContextPolicy: deps.policy.childContextPolicy,
6750
+ adhoc: { role: args.role, prompt: args.prompt, toolNames, outputContract: args.outputContract }
6751
+ };
6752
+ }
6753
+ function toToolReturn(outcome) {
6754
+ if (outcome.kind === "approval") {
6755
+ return { __awaitingToolApproval: true, toolCallId: outcome.toolCallId, approvalId: outcome.approvalId };
6756
+ }
6757
+ if (outcome.kind === "user_question") {
6758
+ return { __awaitingUserQuestion: true, toolCallId: outcome.toolCallId, id: outcome.id };
6759
+ }
6760
+ return outcome.result;
6761
+ }
6762
+ function createDelegateTool(deps) {
6763
+ const names = deps.subagents.map((s) => s.name);
6764
+ const tool = createTool({
6765
+ name: "delegate_to",
6766
+ description: deps.descriptions?.delegate ?? DEFAULT_DELEGATE_DESCRIPTION,
6767
+ schema: zod.z.object({
6768
+ subagent: (names.length > 0 ? zod.z.enum(names) : zod.z.string().min(1)).describe("Name of a sub-agent from <available_subagents>."),
6769
+ input: zod.z.string().min(1).describe("Complete, standalone task for the sub-agent.")
6770
+ }).strict(),
6771
+ func: async ({ subagent, input }) => {
6772
+ const ref = tool._stateRef || {};
6773
+ const d = tool._deps;
6774
+ const parentRuntime = ref.parentRuntime;
6775
+ const parentToolCallId = ref.__currentToolCallId || `delegate_${nanoid.nanoid(6)}`;
6776
+ const parentCtx = ref.ctx || (ref.ctx = {});
6777
+ const def = findSubagent(d.subagents, subagent);
6778
+ if (!def) return { error: `Unknown sub-agent: ${subagent}. Choose one from <available_subagents>.` };
6779
+ if (def.isAvailable && !await def.isAvailable()) return { error: `Sub-agent ${subagent} is not available right now.` };
6780
+ const record = parentCtx.__subagentPending?.[parentToolCallId];
6781
+ const spec = await specFromRegistry(def, d, parentRuntime);
6782
+ if (!record) {
6783
+ const depth = withinDepth(Number(parentCtx.__delegationDepth) || 0, d.policy);
6784
+ if (!depth.ok) return { error: depth.reason };
6785
+ const budget = canSpawn(d.registryRef, d.policy, 1);
6786
+ if (!budget.ok) return { error: budget.reason };
6787
+ d.registryRef.spawnedCount += 1;
6788
+ }
6789
+ return toToolReturn(await runChild(spec, record?.input ?? input, d, ref, { allowHITL: true, parentToolCallId, isResume: !!record, record }));
6790
+ }
6791
+ });
6792
+ tool._deps = deps;
6793
+ tool._stateRef = {};
6794
+ tool.__source = "smart-subagents";
6795
+ return tool;
6796
+ }
6797
+ function createSpawnTool(deps) {
6798
+ const tool = createTool({
6799
+ name: "spawn_subagent",
6800
+ description: deps.descriptions?.spawn ?? DEFAULT_SPAWN_DESCRIPTION,
6801
+ schema: zod.z.object({
6802
+ role: zod.z.string().min(1).describe("Short role name, e.g. 'db-analyst'."),
6803
+ prompt: zod.z.string().optional().describe("System prompt defining how the sub-agent behaves."),
6804
+ input: zod.z.string().min(1).describe("Complete, standalone task for the sub-agent."),
6805
+ tools: zod.z.array(zod.z.string().min(1)).optional().describe("Names of the parent's tools the sub-agent may use."),
6806
+ outputContract: zod.z.string().optional().describe("Optional description of the expected output shape.")
6807
+ }).strict(),
6808
+ func: async (args) => {
6809
+ const ref = tool._stateRef || {};
6810
+ const d = tool._deps;
6811
+ if (d.policy.mode !== "registry_and_adhoc") {
6812
+ return { error: "Ad-hoc sub-agents are disabled (subagentPolicy.mode is not 'registry_and_adhoc'). Use delegate_to." };
6813
+ }
6814
+ const parentRuntime = ref.parentRuntime;
6815
+ const parentToolCallId = ref.__currentToolCallId || `spawn_${nanoid.nanoid(6)}`;
6816
+ const parentCtx = ref.ctx || (ref.ctx = {});
6817
+ const record = parentCtx.__subagentPending?.[parentToolCallId];
6818
+ const spec = record?.adhoc ? await specFromAdhoc(record.adhoc, d, parentRuntime) : await specFromAdhoc(args, d, parentRuntime);
6819
+ if (!record) {
6820
+ const depth = withinDepth(Number(parentCtx.__delegationDepth) || 0, d.policy);
6821
+ if (!depth.ok) return { error: depth.reason };
6822
+ const budget = canSpawn(d.registryRef, d.policy, 1);
6823
+ if (!budget.ok) return { error: budget.reason };
6824
+ d.registryRef.spawnedCount += 1;
6825
+ }
6826
+ return toToolReturn(await runChild(spec, record?.input ?? args.input, d, ref, { allowHITL: true, parentToolCallId, isResume: !!record, record }));
6827
+ }
6828
+ });
6829
+ tool._deps = deps;
6830
+ tool._stateRef = {};
6831
+ tool.__source = "smart-subagents";
6832
+ return tool;
6833
+ }
6834
+ function createParallelTool(deps) {
6835
+ const tool = createTool({
6836
+ name: "spawn_subagents_parallel",
6837
+ description: deps.descriptions?.parallel ?? DEFAULT_PARALLEL_DESCRIPTION,
6838
+ schema: zod.z.object({
6839
+ tasks: zod.z.array(
6840
+ zod.z.object({
6841
+ subagent: zod.z.string().optional().describe("Registry sub-agent name."),
6842
+ role: zod.z.string().optional().describe("Ad-hoc role (when not using `subagent`)."),
6843
+ prompt: zod.z.string().optional(),
6844
+ tools: zod.z.array(zod.z.string().min(1)).optional(),
6845
+ input: zod.z.string().min(1)
6846
+ }).strict()
6847
+ ).min(1).max(16).describe("Independent subtasks to run concurrently.")
6848
+ }).strict(),
6849
+ func: async ({ tasks }) => {
6850
+ const ref = tool._stateRef || {};
6851
+ const d = tool._deps;
6852
+ const parentRuntime = ref.parentRuntime;
6853
+ const parentToolCallId = ref.__currentToolCallId || `parallel_${nanoid.nanoid(6)}`;
6854
+ const parentCtx = ref.ctx || (ref.ctx = {});
6855
+ const depth = withinDepth(Number(parentCtx.__delegationDepth) || 0, d.policy);
6856
+ if (!depth.ok) return { error: depth.reason };
6857
+ const specs = [];
6858
+ for (const task of tasks) {
6859
+ if (task.subagent) {
6860
+ const def = findSubagent(d.subagents, task.subagent);
6861
+ if (!def) {
6862
+ specs.push({ error: `Unknown sub-agent: ${task.subagent}`, input: task.input });
6863
+ continue;
6864
+ }
6865
+ specs.push({ spec: await specFromRegistry(def, d, parentRuntime), input: task.input });
6866
+ } else if (task.role) {
6867
+ if (d.policy.mode !== "registry_and_adhoc") {
6868
+ specs.push({ error: "Ad-hoc sub-agents are disabled.", input: task.input });
6869
+ continue;
6870
+ }
6871
+ specs.push({ spec: await specFromAdhoc({ role: task.role, prompt: task.prompt, tools: task.tools }, d, parentRuntime), input: task.input });
6872
+ } else {
6873
+ specs.push({ error: "Each task needs either `subagent` or `role`.", input: task.input });
6874
+ }
6875
+ }
6876
+ const spawnCount = specs.filter((entry) => !("error" in entry)).length;
6877
+ const budget = canSpawn(d.registryRef, d.policy, spawnCount);
6878
+ if (!budget.ok) return { error: budget.reason };
6879
+ d.registryRef.spawnedCount += spawnCount;
6880
+ const results = new Array(specs.length);
6881
+ const concurrency = Math.max(1, Math.min(d.policy.maxParallel, specs.length));
6882
+ let cursor = 0;
6883
+ const worker = async () => {
6884
+ while (true) {
6885
+ const i = cursor++;
6886
+ if (i >= specs.length) return;
6887
+ const entry = specs[i];
6888
+ if ("error" in entry) {
6889
+ results[i] = { name: "?", mode: "adhoc", input: entry.input, error: entry.error };
6890
+ continue;
6891
+ }
6892
+ const outcome = await runChild(entry.spec, entry.input, d, ref, {
6893
+ allowHITL: false,
6894
+ parentToolCallId: `${parentToolCallId}#${i}`,
6895
+ parallel: true
6896
+ });
6897
+ results[i] = outcome.kind === "result" ? outcome.result : { name: entry.spec.name, mode: entry.spec.mode, input: entry.input, error: "Unexpected pause in parallel child." };
6898
+ }
6899
+ };
6900
+ await Promise.all(Array.from({ length: concurrency }, () => worker()));
6901
+ return { results };
6902
+ }
6903
+ });
6904
+ tool._deps = deps;
6905
+ tool._stateRef = {};
6906
+ tool.__source = "smart-subagents";
6907
+ return tool;
6908
+ }
6909
+ function createSubagentTools(deps) {
6910
+ const tools = [];
6911
+ if (deps.subagents.length > 0) tools.push(createDelegateTool(deps));
6912
+ if (deps.policy.mode === "registry_and_adhoc") tools.push(createSpawnTool(deps));
6913
+ tools.push(createParallelTool(deps));
6914
+ return tools;
6915
+ }
6916
+
6391
6917
  // src/smart/index.ts
6392
6918
  function createSmartAgent(opts) {
6393
6919
  const resolved = normalizeSmartAgentOptions(opts);
@@ -6425,6 +6951,42 @@ function createSmartAgent(opts) {
6425
6951
  const skills = opts.skills ?? [];
6426
6952
  const skillPolicy = opts.skillPolicy ?? DEFAULT_SKILL_POLICY;
6427
6953
  const skillsEnabled = skills.length > 0;
6954
+ const subagentsProvided = opts.subagents !== void 0 || opts.subagentPolicy !== void 0;
6955
+ const subagents = opts.subagents ?? [];
6956
+ const subagentPolicy = opts.subagentPolicy ?? DEFAULT_SUBAGENT_POLICY;
6957
+ const subagentsEnabled = subagentsProvided && subagentPolicy.mode !== "off" && (subagents.length > 0 || subagentPolicy.mode === "registry_and_adhoc");
6958
+ const promptHooks = opts.promptHooks;
6959
+ const buildChild = (cfg) => createSmartAgent({
6960
+ name: cfg.name,
6961
+ model: cfg.model,
6962
+ tools: cfg.tools,
6963
+ systemPrompt: cfg.systemPrompt,
6964
+ outputSchema: cfg.outputSchema,
6965
+ limits: cfg.limits,
6966
+ runtimeProfile: resolved.runtimeProfile,
6967
+ humanInTheLoop: opts.humanInTheLoop,
6968
+ reasoning: opts.reasoning,
6969
+ tokenCounter: opts.tokenCounter,
6970
+ costEstimator: opts.costEstimator,
6971
+ promptHooks,
6972
+ // Sub-agents are single-level by design: a child never gets its own spawn
6973
+ // tools, so it cannot delegate further. This keeps decomposition bounded and
6974
+ // is why the depth guard mainly governs `asTool`-composed nesting (which seeds
6975
+ // __delegationDepth externally) rather than sub-agent-of-sub-agent recursion.
6976
+ subagents: [],
6977
+ subagentPolicy: { ...subagentPolicy, mode: "off" }
6978
+ });
6979
+ const decorateToolDescriptions = (tools) => {
6980
+ const overrides = promptHooks?.toolDescriptions;
6981
+ if (!overrides) return tools;
6982
+ return tools.map((tool) => {
6983
+ const override = overrides[tool?.name];
6984
+ if (override === void 0) return tool;
6985
+ const next = typeof override === "function" ? override(tool.description || "") : override;
6986
+ if (next === tool.description) return tool;
6987
+ return { ...tool, description: next };
6988
+ });
6989
+ };
6428
6990
  const soManagerFactory = opts.outputSchema ? new StructuredOutputManager(opts.outputSchema, resolveStrategy(opts.model)) : void 0;
6429
6991
  const modelCapabilities = opts.outputSchema ? getModelCapabilities(opts.model) : void 0;
6430
6992
  const responseFinalizeTool = soManagerFactory && modelCapabilities?.structuredOutput !== "native" ? soManagerFactory.getResponseTool() : void 0;
@@ -6435,12 +6997,27 @@ function createSmartAgent(opts) {
6435
6997
  const coreBase = [...userTools, ...ctxTools];
6436
6998
  if (responseFinalizeTool) coreBase.push(responseFinalizeTool);
6437
6999
  if (askUserConfig) coreBase.push(createAskUserQuestionTool(ref, askUserConfig));
7000
+ let subagentRegistryRef;
7001
+ if (subagentsEnabled) {
7002
+ subagentRegistryRef = createSubagentRegistryRef();
7003
+ const deps = {
7004
+ registryRef: subagentRegistryRef,
7005
+ subagents,
7006
+ policy: subagentPolicy,
7007
+ buildChild
7008
+ // NOTE: promptHooks.toolDescriptions overrides for the sub-agent tools are
7009
+ // applied uniformly (and only) by decorateToolDescriptions below, so the
7010
+ // function form of an override receives the real DEFAULT_* string. Baking
7011
+ // them in here as well would double-apply and stringify the function.
7012
+ };
7013
+ coreBase.push(...createSubagentTools(deps));
7014
+ }
6438
7015
  if (!skillsEnabled) {
6439
- const without = coreBase;
6440
- const withRec = [...without, recoveryTool];
6441
- return { stateRef: ref, toolsWithoutRecovery: without, toolsWithRecovery: withRec };
7016
+ const without = decorateToolDescriptions(coreBase);
7017
+ const withRec = decorateToolDescriptions([...coreBase, recoveryTool]);
7018
+ return { stateRef: ref, toolsWithoutRecovery: without, toolsWithRecovery: withRec, subagentRegistryRef };
6442
7019
  }
6443
- const toolSet = { stateRef: ref, toolsWithoutRecovery: [], toolsWithRecovery: [] };
7020
+ const toolSet = { stateRef: ref, toolsWithoutRecovery: [], toolsWithRecovery: [], subagentRegistryRef };
6444
7021
  const skillRegistryRef = createSkillRegistryRef();
6445
7022
  const skillMetaTools = createSkillTools({ registryRef: skillRegistryRef, skills, policy: skillPolicy });
6446
7023
  const baseWithMeta = [...coreBase, ...skillMetaTools];
@@ -6450,14 +7027,43 @@ function createSmartAgent(opts) {
6450
7027
  boundSkillTools: skillRegistryRef.boundSkillTools,
6451
7028
  recoveryTool
6452
7029
  });
6453
- toolSet.toolsWithoutRecovery = composed.toolsWithoutRecovery;
6454
- toolSet.toolsWithRecovery = composed.toolsWithRecovery;
7030
+ toolSet.toolsWithoutRecovery = decorateToolDescriptions(composed.toolsWithoutRecovery);
7031
+ toolSet.toolsWithRecovery = decorateToolDescriptions(composed.toolsWithRecovery);
6455
7032
  };
6456
7033
  skillRegistryRef.__onToolsChanged = rebuild;
6457
7034
  toolSet.skillRegistryRef = skillRegistryRef;
6458
7035
  rebuild();
6459
7036
  return toolSet;
6460
7037
  };
7038
+ async function rehydrateSkillRegistry(ref, persisted) {
7039
+ if (!persisted) return false;
7040
+ const opened = Array.isArray(persisted.openedSkillKeys) ? persisted.openedSkillKeys : [];
7041
+ const boundNames = new Set(Array.isArray(persisted.boundToolNames) ? persisted.boundToolNames : []);
7042
+ if (opened.length === 0) return false;
7043
+ let changed = false;
7044
+ for (const key of opened) {
7045
+ if (!ref.openedSkillKeys.includes(key)) ref.openedSkillKeys.push(key);
7046
+ const skill = skills.find((s) => s.key === key);
7047
+ if (!skill) continue;
7048
+ let bound;
7049
+ try {
7050
+ bound = await skill.bindTools();
7051
+ } catch {
7052
+ continue;
7053
+ }
7054
+ const wanted = bound.filter((t) => boundNames.has(t.name));
7055
+ const added = appendBoundTools(ref, wanted, skillPolicy);
7056
+ if (added.length > 0) changed = true;
7057
+ }
7058
+ return changed;
7059
+ }
7060
+ function skillStateFromRegistry(ref) {
7061
+ if (!ref || !Array.isArray(ref.openedSkillKeys) || ref.openedSkillKeys.length === 0) return void 0;
7062
+ return {
7063
+ openedSkillKeys: [...ref.openedSkillKeys],
7064
+ boundToolNames: (ref.boundSkillTools || []).map((t) => t.name)
7065
+ };
7066
+ }
6461
7067
  const base = createAgent({ ...runtimeOpts, tools: factoryToolsWithoutRecovery });
6462
7068
  base.__runtime.runtimeProfile = resolved.runtimeProfile;
6463
7069
  base.__runtime.smart = resolved;
@@ -6508,12 +7114,19 @@ function createSmartAgent(opts) {
6508
7114
  };
6509
7115
  }
6510
7116
  function systemMessage2(extraBlock) {
6511
- const sys = buildSystemPrompt(
7117
+ let sys = buildSystemPrompt(
6512
7118
  [opts.systemPrompt, runtimeHint, structuredOutputHint, extraBlock].filter(Boolean).join("\n"),
6513
7119
  planningEnabled,
6514
7120
  opts.name || "Agent",
6515
7121
  opts.todoListPrompt
6516
7122
  );
7123
+ if (promptHooks?.transformSystemPrompt) {
7124
+ try {
7125
+ sys = promptHooks.transformSystemPrompt(sys, { agentName: opts.name || "Agent" });
7126
+ } catch (err) {
7127
+ console.warn("[agent-sdk] promptHooks.transformSystemPrompt error:", err);
7128
+ }
7129
+ }
6517
7130
  return { role: "system", content: sys };
6518
7131
  }
6519
7132
  function syncRuntimeTools(currentState, currentMessages, toolSet) {
@@ -6558,11 +7171,33 @@ function createSmartAgent(opts) {
6558
7171
  stateRef.todoList = input.plan?.steps;
6559
7172
  stateRef.planVersion = input.planVersion || input.plan?.version || 0;
6560
7173
  stateRef.adherenceScore = input.plan?.adherenceScore || 0;
7174
+ if (skillsEnabled && toolSet.skillRegistryRef) {
7175
+ const changed = await rehydrateSkillRegistry(toolSet.skillRegistryRef, input.ctx?.__skillState);
7176
+ if (changed) toolSet.skillRegistryRef.__onToolsChanged?.();
7177
+ }
6561
7178
  const syncPlanFromRef = (state2) => syncPlanStateWith(stateRef, state2);
6562
7179
  const availableSkills = skillsEnabled ? await resolveAvailableSkills(skills, { modelTier: skillPolicy.modelTier }) : [];
6563
7180
  const skillBlock = availableSkills.length > 0 ? buildSkillHeaderBlock(availableSkills) : void 0;
7181
+ let subagentBlock;
7182
+ if (subagentsEnabled) {
7183
+ const availableSubagents = await resolveAvailableSubagents(subagents);
7184
+ let block = buildSubagentCatalogBlock(availableSubagents, subagentPolicy, {
7185
+ delegate: "delegate_to",
7186
+ spawn: "spawn_subagent",
7187
+ parallel: "spawn_subagents_parallel"
7188
+ });
7189
+ if (promptHooks?.subagentCatalog) {
7190
+ try {
7191
+ block = promptHooks.subagentCatalog(block, availableSubagents);
7192
+ } catch (err) {
7193
+ console.warn("[agent-sdk] promptHooks.subagentCatalog error:", err);
7194
+ }
7195
+ }
7196
+ subagentBlock = block;
7197
+ }
7198
+ const disclosureBlock = [skillBlock, subagentBlock].filter(Boolean).join("\n\n") || void 0;
6564
7199
  const alreadyHasSystem = Array.isArray(input.messages) && input.messages[0]?.role === "system";
6565
- const seedMessages = alreadyHasSystem ? [...input.messages || []] : [systemMessage2(skillBlock), ...input.messages || []];
7200
+ const seedMessages = alreadyHasSystem ? [...input.messages || []] : [systemMessage2(disclosureBlock), ...input.messages || []];
6566
7201
  let state = syncRuntimeTools(await syncMemory({ ...input, messages: seedMessages }), seedMessages, toolSet);
6567
7202
  let lastResult = null;
6568
7203
  let rawMessages = [...seedMessages];
@@ -6635,6 +7270,13 @@ function createSmartAgent(opts) {
6635
7270
  } else if (lastResult.state) {
6636
7271
  lastResult = { ...lastResult, state: { ...lastResult.state, memoryFacts: state.memoryFacts, plan: state.plan, planVersion: state.planVersion, messages: rawMessages } };
6637
7272
  }
7273
+ if (skillsEnabled && lastResult.state) {
7274
+ const persisted = skillStateFromRegistry(toolSet.skillRegistryRef);
7275
+ if (persisted) {
7276
+ const prevCtx = lastResult.state.ctx || {};
7277
+ lastResult = { ...lastResult, state: { ...lastResult.state, ctx: { ...prevCtx, __skillState: persisted } } };
7278
+ }
7279
+ }
6638
7280
  return lastResult;
6639
7281
  },
6640
7282
  snapshot: base.snapshot,
@@ -6647,6 +7289,150 @@ function createSmartAgent(opts) {
6647
7289
  };
6648
7290
  return instance;
6649
7291
  }
7292
+ var FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/;
7293
+ function parseSkillFrontmatter(md) {
7294
+ const match = FRONTMATTER_RE.exec(md);
7295
+ if (!match) return { metadata: {}, body: md.trim() };
7296
+ return { metadata: parseFrontmatterBlock(match[1] ?? ""), body: md.slice(match[0].length).trim() };
7297
+ }
7298
+ var LIST_KEYS = /* @__PURE__ */ new Set([
7299
+ "scripts",
7300
+ "keywords",
7301
+ "tags",
7302
+ "allowed-tools",
7303
+ "allowed_tools",
7304
+ "compatible-models",
7305
+ "compatible_models"
7306
+ ]);
7307
+ function parseFrontmatterBlock(raw) {
7308
+ const out = {};
7309
+ let listKey = null;
7310
+ let listAcc = [];
7311
+ const flush = () => {
7312
+ if (listKey) {
7313
+ out[listKey] = listAcc;
7314
+ listAcc = [];
7315
+ listKey = null;
7316
+ }
7317
+ };
7318
+ const splitList = (value) => value.split(",").map((v) => unquote(v.trim())).filter(Boolean);
7319
+ for (const line of raw.split(/\r?\n/)) {
7320
+ if (line.trim() === "") continue;
7321
+ const item = /^\s*-\s+(.*)$/.exec(line);
7322
+ if (item && listKey) {
7323
+ listAcc.push(unquote(item[1].trim()));
7324
+ continue;
7325
+ }
7326
+ flush();
7327
+ const kv = /^([A-Za-z0-9_-]+):\s*(.*)$/.exec(line);
7328
+ if (!kv) continue;
7329
+ const [, key, rawValue] = kv;
7330
+ const value = rawValue.trim();
7331
+ if (value === "") {
7332
+ listKey = key;
7333
+ } else if (value.startsWith("[") && value.endsWith("]")) {
7334
+ out[key] = splitList(value.slice(1, -1));
7335
+ } else if (LIST_KEYS.has(key.toLowerCase())) {
7336
+ out[key] = splitList(value);
7337
+ } else {
7338
+ out[key] = unquote(value);
7339
+ }
7340
+ }
7341
+ flush();
7342
+ return out;
7343
+ }
7344
+ function unquote(s) {
7345
+ if (s.startsWith('"') && s.endsWith('"') || s.startsWith("'") && s.endsWith("'")) {
7346
+ return s.slice(1, -1);
7347
+ }
7348
+ return s;
7349
+ }
7350
+ function asArray(v) {
7351
+ if (v === void 0) return [];
7352
+ return Array.isArray(v) ? v : [v];
7353
+ }
7354
+ function sanitize(s) {
7355
+ return s.replace(/[^A-Za-z0-9_]+/g, "_").replace(/^_+|_+$/g, "");
7356
+ }
7357
+ function scriptToolName(skillName, scriptFile) {
7358
+ const base = scriptFile.replace(/\.[^.]+$/, "");
7359
+ return `${sanitize(skillName)}__${sanitize(base)}`;
7360
+ }
7361
+ var join = (...parts) => parts.join("/").replace(/\/{2,}/g, "/");
7362
+ function buildScriptTools(skillName, skillDir, scripts, execution) {
7363
+ const tools = scripts.map(
7364
+ (file) => createTool({
7365
+ name: scriptToolName(skillName, file),
7366
+ description: `Run the bundled "${file}" script from the "${skillName}" skill.`,
7367
+ schema: zod.z.object({
7368
+ args: zod.z.record(zod.z.any()).optional().describe("Arguments passed to the script.")
7369
+ }),
7370
+ needsApproval: true,
7371
+ approvalPrompt: `Run script ${file} from skill ${skillName}?`,
7372
+ func: (input) => execution.executeScript(join(skillDir, "scripts", file), input?.args ?? {})
7373
+ })
7374
+ );
7375
+ const headers = tools.map((t) => ({ name: t.name, description: t.description }));
7376
+ return { headers, tools };
7377
+ }
7378
+ async function loadOneSkill(fs2, skillDir, fallbackName, execution, minModelTier) {
7379
+ let md;
7380
+ try {
7381
+ md = await fs2.readFile(join(skillDir, "SKILL.md"));
7382
+ } catch {
7383
+ return null;
7384
+ }
7385
+ const { metadata, body } = parseSkillFrontmatter(md);
7386
+ const name = metadata.name ?? fallbackName;
7387
+ const description = metadata.description ?? "";
7388
+ const tier = metadata["min-model-tier"] ?? minModelTier;
7389
+ let scripts = asArray(metadata.scripts);
7390
+ if (scripts.length === 0) {
7391
+ try {
7392
+ scripts = await fs2.listDir(join(skillDir, "scripts"));
7393
+ } catch {
7394
+ scripts = [];
7395
+ }
7396
+ }
7397
+ const built = execution && scripts.length > 0 ? buildScriptTools(name, skillDir, scripts, execution) : { headers: [], tools: [] };
7398
+ const skill = {
7399
+ key: `skillmd:${name}`,
7400
+ title: name,
7401
+ header: description,
7402
+ prompt: body,
7403
+ needsSandbox: scripts.length > 0,
7404
+ listToolIndex: () => built.headers,
7405
+ bindTools: (names) => names ? built.tools.filter((t) => names.includes(t.name)) : built.tools
7406
+ };
7407
+ if (tier) skill.minModelTier = tier;
7408
+ return skill;
7409
+ }
7410
+ async function loadSkillsFromDisk(opts) {
7411
+ const skills = [];
7412
+ const seen = /* @__PURE__ */ new Set();
7413
+ for (const root of opts.roots) {
7414
+ let entries;
7415
+ try {
7416
+ entries = await opts.fs.listDir(root);
7417
+ } catch {
7418
+ continue;
7419
+ }
7420
+ for (const entry of entries) {
7421
+ const skill = await loadOneSkill(
7422
+ opts.fs,
7423
+ join(root, entry),
7424
+ entry,
7425
+ opts.execution,
7426
+ opts.minModelTier
7427
+ );
7428
+ if (skill && !seen.has(skill.key)) {
7429
+ seen.add(skill.key);
7430
+ skills.push(skill);
7431
+ }
7432
+ }
7433
+ }
7434
+ return skills;
7435
+ }
6650
7436
 
6651
7437
  // src/smart/eval.ts
6652
7438
  function normalizeProfileTarget(target) {
@@ -9349,6 +10135,8 @@ exports.BaseProvider = BaseProvider;
9349
10135
  exports.BedrockProvider = BedrockProvider;
9350
10136
  exports.DEFAULT_PROFILE_CONFIGS = DEFAULT_PROFILE_CONFIGS;
9351
10137
  exports.DEFAULT_SKILL_POLICY = DEFAULT_SKILL_POLICY;
10138
+ exports.DEFAULT_SUBAGENT_POLICY = DEFAULT_SUBAGENT_POLICY;
10139
+ exports.DEFAULT_SUBAGENT_TOOL_NAMES = DEFAULT_SUBAGENT_TOOL_NAMES;
9352
10140
  exports.GuardrailPhase = GuardrailPhase;
9353
10141
  exports.InMemoryMemoryStore = InMemoryMemoryStore;
9354
10142
  exports.NativeJsonSchemaStrategy = NativeJsonSchemaStrategy;
@@ -9362,8 +10150,10 @@ exports.VertexProvider = VertexProvider;
9362
10150
  exports.agentVerdictRule = agentVerdictRule;
9363
10151
  exports.appendBoundTools = appendBoundTools;
9364
10152
  exports.buildSkillHeaderBlock = buildSkillHeaderBlock;
10153
+ exports.buildSubagentCatalogBlock = buildSubagentCatalogBlock;
9365
10154
  exports.buildSystemPrompt = buildSystemPrompt;
9366
10155
  exports.canOpenSkill = canOpenSkill;
10156
+ exports.canSpawn = canSpawn;
9367
10157
  exports.captureSnapshot = captureSnapshot;
9368
10158
  exports.codePresenceRule = codePresenceRule;
9369
10159
  exports.cognipeerSink = cognipeerSink;
@@ -9377,17 +10167,22 @@ exports.createBindSkillToolsTool = createBindSkillToolsTool;
9377
10167
  exports.createCodeGuardrail = createCodeGuardrail;
9378
10168
  exports.createContextSummarizeNode = createContextSummarizeNode;
9379
10169
  exports.createContextTools = createContextTools;
10170
+ exports.createDelegateTool = createDelegateTool;
9380
10171
  exports.createGetToolResponseTool = createGetToolResponseTool;
9381
10172
  exports.createGuardrail = createGuardrail;
9382
10173
  exports.createJsonGuardrail = createJsonGuardrail;
9383
10174
  exports.createManageTodoTool = createManageTodoTool;
9384
10175
  exports.createOpenSkillTool = createOpenSkillTool;
10176
+ exports.createParallelTool = createParallelTool;
9385
10177
  exports.createProvider = createProvider;
9386
10178
  exports.createRegexGuardrail = createRegexGuardrail;
9387
10179
  exports.createResolverNode = createResolverNode;
9388
10180
  exports.createSkillRegistryRef = createSkillRegistryRef;
9389
10181
  exports.createSkillTools = createSkillTools;
9390
10182
  exports.createSmartAgent = createSmartAgent;
10183
+ exports.createSpawnTool = createSpawnTool;
10184
+ exports.createSubagentRegistryRef = createSubagentRegistryRef;
10185
+ exports.createSubagentTools = createSubagentTools;
9391
10186
  exports.createTool = createTool;
9392
10187
  exports.createToolLimitFinalizeNode = createToolLimitFinalizeNode;
9393
10188
  exports.createToolsNode = createToolsNode;
@@ -9398,6 +10193,7 @@ exports.defaultTokenCounter = defaultTokenCounter;
9398
10193
  exports.emptyUsage = emptyUsage;
9399
10194
  exports.evaluateGuardrails = evaluateGuardrails;
9400
10195
  exports.fileSink = fileSink;
10196
+ exports.findSubagent = findSubagent;
9401
10197
  exports.formatZodError = formatZodError;
9402
10198
  exports.fromLangchainModel = fromLangchainModel;
9403
10199
  exports.fromLangchainTools = fromLangchainTools;
@@ -9412,23 +10208,29 @@ exports.hasToolResponseRecoveryReference = hasToolResponseRecoveryReference;
9412
10208
  exports.httpSink = httpSink;
9413
10209
  exports.isSmartModel = isSmartModel;
9414
10210
  exports.jsonSchemaRule = jsonSchemaRule;
10211
+ exports.loadSkillsFromDisk = loadSkillsFromDisk;
9415
10212
  exports.normalizeSmartAgentOptions = normalizeSmartAgentOptions;
9416
10213
  exports.otlpSink = otlpSink;
10214
+ exports.parseSkillFrontmatter = parseSkillFrontmatter;
9417
10215
  exports.readMemoryFacts = readMemoryFacts;
9418
10216
  exports.regexRule = regexRule;
9419
10217
  exports.resolveAvailableSkills = resolveAvailableSkills;
10218
+ exports.resolveAvailableSubagents = resolveAvailableSubagents;
9420
10219
  exports.resolveMemoryStore = resolveMemoryStore;
9421
10220
  exports.resolveReasoning = resolveReasoning;
9422
10221
  exports.resolveStrategy = resolveStrategy;
10222
+ exports.resolveSubagentTools = resolveSubagentTools;
9423
10223
  exports.resolveToolApprovalState = resolveToolApprovalState;
9424
10224
  exports.resolveUserQuestionState = resolveUserQuestionState;
9425
10225
  exports.restoreSnapshot = restoreSnapshot;
9426
10226
  exports.runSmartAgentEvalHarness = runSmartAgentEvalHarness;
10227
+ exports.seedChildMessages = seedChildMessages;
9427
10228
  exports.setTokenCounter = setTokenCounter;
9428
10229
  exports.startStreamingSession = startStreamingSession;
9429
10230
  exports.traceSessionToOtlp = traceSessionToOtlp;
9430
10231
  exports.validateReasoningConfig = validateReasoningConfig;
9431
10232
  exports.withTools = withTools;
10233
+ exports.withinDepth = withinDepth;
9432
10234
  exports.writeSummaryFactsToMemory = writeSummaryFactsToMemory;
9433
10235
  //# sourceMappingURL=index.cjs.map
9434
10236
  //# sourceMappingURL=index.cjs.map