@cognipeer/agent-sdk 0.7.3 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs 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) {
@@ -9405,6 +10191,8 @@ exports.BaseProvider = BaseProvider;
9405
10191
  exports.BedrockProvider = BedrockProvider;
9406
10192
  exports.DEFAULT_PROFILE_CONFIGS = DEFAULT_PROFILE_CONFIGS;
9407
10193
  exports.DEFAULT_SKILL_POLICY = DEFAULT_SKILL_POLICY;
10194
+ exports.DEFAULT_SUBAGENT_POLICY = DEFAULT_SUBAGENT_POLICY;
10195
+ exports.DEFAULT_SUBAGENT_TOOL_NAMES = DEFAULT_SUBAGENT_TOOL_NAMES;
9408
10196
  exports.GuardrailPhase = GuardrailPhase;
9409
10197
  exports.InMemoryMemoryStore = InMemoryMemoryStore;
9410
10198
  exports.NativeJsonSchemaStrategy = NativeJsonSchemaStrategy;
@@ -9418,8 +10206,10 @@ exports.VertexProvider = VertexProvider;
9418
10206
  exports.agentVerdictRule = agentVerdictRule;
9419
10207
  exports.appendBoundTools = appendBoundTools;
9420
10208
  exports.buildSkillHeaderBlock = buildSkillHeaderBlock;
10209
+ exports.buildSubagentCatalogBlock = buildSubagentCatalogBlock;
9421
10210
  exports.buildSystemPrompt = buildSystemPrompt;
9422
10211
  exports.canOpenSkill = canOpenSkill;
10212
+ exports.canSpawn = canSpawn;
9423
10213
  exports.captureSnapshot = captureSnapshot;
9424
10214
  exports.codePresenceRule = codePresenceRule;
9425
10215
  exports.cognipeerSink = cognipeerSink;
@@ -9433,17 +10223,22 @@ exports.createBindSkillToolsTool = createBindSkillToolsTool;
9433
10223
  exports.createCodeGuardrail = createCodeGuardrail;
9434
10224
  exports.createContextSummarizeNode = createContextSummarizeNode;
9435
10225
  exports.createContextTools = createContextTools;
10226
+ exports.createDelegateTool = createDelegateTool;
9436
10227
  exports.createGetToolResponseTool = createGetToolResponseTool;
9437
10228
  exports.createGuardrail = createGuardrail;
9438
10229
  exports.createJsonGuardrail = createJsonGuardrail;
9439
10230
  exports.createManageTodoTool = createManageTodoTool;
9440
10231
  exports.createOpenSkillTool = createOpenSkillTool;
10232
+ exports.createParallelTool = createParallelTool;
9441
10233
  exports.createProvider = createProvider;
9442
10234
  exports.createRegexGuardrail = createRegexGuardrail;
9443
10235
  exports.createResolverNode = createResolverNode;
9444
10236
  exports.createSkillRegistryRef = createSkillRegistryRef;
9445
10237
  exports.createSkillTools = createSkillTools;
9446
10238
  exports.createSmartAgent = createSmartAgent;
10239
+ exports.createSpawnTool = createSpawnTool;
10240
+ exports.createSubagentRegistryRef = createSubagentRegistryRef;
10241
+ exports.createSubagentTools = createSubagentTools;
9447
10242
  exports.createTool = createTool;
9448
10243
  exports.createToolLimitFinalizeNode = createToolLimitFinalizeNode;
9449
10244
  exports.createToolsNode = createToolsNode;
@@ -9454,6 +10249,7 @@ exports.defaultTokenCounter = defaultTokenCounter;
9454
10249
  exports.emptyUsage = emptyUsage;
9455
10250
  exports.evaluateGuardrails = evaluateGuardrails;
9456
10251
  exports.fileSink = fileSink;
10252
+ exports.findSubagent = findSubagent;
9457
10253
  exports.formatZodError = formatZodError;
9458
10254
  exports.fromLangchainModel = fromLangchainModel;
9459
10255
  exports.fromLangchainTools = fromLangchainTools;
@@ -9468,23 +10264,29 @@ exports.hasToolResponseRecoveryReference = hasToolResponseRecoveryReference;
9468
10264
  exports.httpSink = httpSink;
9469
10265
  exports.isSmartModel = isSmartModel;
9470
10266
  exports.jsonSchemaRule = jsonSchemaRule;
10267
+ exports.loadSkillsFromDisk = loadSkillsFromDisk;
9471
10268
  exports.normalizeSmartAgentOptions = normalizeSmartAgentOptions;
9472
10269
  exports.otlpSink = otlpSink;
10270
+ exports.parseSkillFrontmatter = parseSkillFrontmatter;
9473
10271
  exports.readMemoryFacts = readMemoryFacts;
9474
10272
  exports.regexRule = regexRule;
9475
10273
  exports.resolveAvailableSkills = resolveAvailableSkills;
10274
+ exports.resolveAvailableSubagents = resolveAvailableSubagents;
9476
10275
  exports.resolveMemoryStore = resolveMemoryStore;
9477
10276
  exports.resolveReasoning = resolveReasoning;
9478
10277
  exports.resolveStrategy = resolveStrategy;
10278
+ exports.resolveSubagentTools = resolveSubagentTools;
9479
10279
  exports.resolveToolApprovalState = resolveToolApprovalState;
9480
10280
  exports.resolveUserQuestionState = resolveUserQuestionState;
9481
10281
  exports.restoreSnapshot = restoreSnapshot;
9482
10282
  exports.runSmartAgentEvalHarness = runSmartAgentEvalHarness;
10283
+ exports.seedChildMessages = seedChildMessages;
9483
10284
  exports.setTokenCounter = setTokenCounter;
9484
10285
  exports.startStreamingSession = startStreamingSession;
9485
10286
  exports.traceSessionToOtlp = traceSessionToOtlp;
9486
10287
  exports.validateReasoningConfig = validateReasoningConfig;
9487
10288
  exports.withTools = withTools;
10289
+ exports.withinDepth = withinDepth;
9488
10290
  exports.writeSummaryFactsToMemory = writeSummaryFactsToMemory;
9489
10291
  //# sourceMappingURL=index.cjs.map
9490
10292
  //# sourceMappingURL=index.cjs.map