@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.mjs CHANGED
@@ -2573,6 +2573,27 @@ function validateToolArgs(tool, args) {
2573
2573
  }
2574
2574
  }
2575
2575
 
2576
+ // src/utils/pendingToolCalls.ts
2577
+ function selectPendingToolCalls(messages) {
2578
+ if (!Array.isArray(messages) || messages.length === 0) return [];
2579
+ const last = messages[messages.length - 1];
2580
+ if (last?.role === "assistant") {
2581
+ return Array.isArray(last.tool_calls) ? last.tool_calls : [];
2582
+ }
2583
+ const resolvedIds = /* @__PURE__ */ new Set();
2584
+ for (const m of messages) {
2585
+ if (m?.role === "tool" && m.tool_call_id != null) resolvedIds.add(String(m.tool_call_id));
2586
+ }
2587
+ for (let i = messages.length - 1; i >= 0; i -= 1) {
2588
+ const m = messages[i];
2589
+ if (m?.role !== "assistant") continue;
2590
+ const calls = Array.isArray(m.tool_calls) ? m.tool_calls : [];
2591
+ if (calls.length === 0) return [];
2592
+ return calls.filter((c) => c?.id == null || !resolvedIds.has(String(c.id)));
2593
+ }
2594
+ return [];
2595
+ }
2596
+
2576
2597
  // src/nodes/tools.ts
2577
2598
  function normalizeMaxExecutionsPerRun(value) {
2578
2599
  if (value === null || value === void 0 || value === "") return null;
@@ -2730,9 +2751,8 @@ function createToolsNode(initialTools, opts) {
2730
2751
  anyTool._stateRef.parentRuntime = runtime;
2731
2752
  }
2732
2753
  }
2733
- const last = state.messages[state.messages.length - 1];
2734
2754
  let toolCount = state.toolCallCount || 0;
2735
- const toolCalls = Array.isArray(last?.tool_calls) ? last.tool_calls.map((toolCall) => normalizeToolCall(toolCall)).filter((toolCall) => toolCall !== null) : [];
2755
+ const toolCalls = selectPendingToolCalls(state.messages).map((toolCall) => normalizeToolCall(toolCall)).filter((toolCall) => toolCall !== null);
2736
2756
  const toolHistory = state.toolHistory || [];
2737
2757
  const toolHistoryArchived = state.toolHistoryArchived || [];
2738
2758
  const remaining = Math.max(0, limits.maxToolCalls - toolCount);
@@ -3974,12 +3994,20 @@ function resolveUserQuestionState(state, resolution) {
3974
3994
  entry.notes = resolution.notes;
3975
3995
  entry.answeredAt = (/* @__PURE__ */ new Date()).toISOString();
3976
3996
  pending[matchIndex] = entry;
3997
+ const isSubagentQuestion = Boolean(entry.metadata?.__subagent);
3977
3998
  const ctx = { ...state.ctx || {} };
3978
3999
  delete ctx.__awaitingUserQuestion;
3979
- if (ctx.__resumeStage === "tools") {
4000
+ if (ctx.__resumeStage === "tools" && !isSubagentQuestion) {
3980
4001
  delete ctx.__resumeStage;
3981
4002
  }
3982
4003
  ctx.__userQuestionResolved = { id: entry.id, status: entry.status };
4004
+ if (isSubagentQuestion) {
4005
+ return {
4006
+ ...state,
4007
+ pendingUserQuestions: pending,
4008
+ ctx
4009
+ };
4010
+ }
3983
4011
  const toolMessage = {
3984
4012
  role: "tool",
3985
4013
  name: "ask_user_question",
@@ -4260,6 +4288,88 @@ var StructuredOutputManager = class {
4260
4288
  }
4261
4289
  };
4262
4290
 
4291
+ // src/smart/subagents/registry.ts
4292
+ function findSubagent(subagents, name) {
4293
+ return subagents.find((entry) => entry.name === name);
4294
+ }
4295
+ async function resolveAvailableSubagents(subagents) {
4296
+ const out = [];
4297
+ for (const entry of subagents) {
4298
+ const available = entry.isAvailable ? await entry.isAvailable() : true;
4299
+ if (available) out.push(entry);
4300
+ }
4301
+ return out;
4302
+ }
4303
+ function canSpawn(ref, policy, count = 1) {
4304
+ if (policy.mode === "off") {
4305
+ return { ok: false, reason: "sub-agents are disabled by runtime policy" };
4306
+ }
4307
+ if (ref.spawnedCount + count > policy.maxChildCalls) {
4308
+ return {
4309
+ ok: false,
4310
+ reason: `child-call budget exhausted (${policy.maxChildCalls}); ${ref.spawnedCount} already spawned`
4311
+ };
4312
+ }
4313
+ return { ok: true };
4314
+ }
4315
+ function withinDepth(currentDepth, policy) {
4316
+ if (currentDepth >= policy.maxDepth) {
4317
+ return { ok: false, reason: `delegation depth limit reached (${policy.maxDepth})` };
4318
+ }
4319
+ return { ok: true };
4320
+ }
4321
+ function seedChildMessages(policy, parentMessages, input) {
4322
+ const messages = (Array.isArray(parentMessages) ? parentMessages : []).filter((m) => m?.role !== "system");
4323
+ switch (policy) {
4324
+ case "full":
4325
+ return [...messages, { role: "user", content: input }];
4326
+ case "scoped": {
4327
+ const lastUser = [...messages].reverse().find((m) => m?.role === "user");
4328
+ return [
4329
+ ...lastUser ? [lastUser] : [],
4330
+ { role: "user", content: input }
4331
+ ];
4332
+ }
4333
+ case "minimal":
4334
+ default:
4335
+ return [{ role: "user", content: input }];
4336
+ }
4337
+ }
4338
+ async function resolveSubagentTools(declared, parentTools) {
4339
+ if (!declared) return [];
4340
+ if (typeof declared === "function") {
4341
+ return await declared();
4342
+ }
4343
+ if (Array.isArray(declared) && declared.length > 0 && typeof declared[0] === "string") {
4344
+ const wanted = new Set(declared);
4345
+ return parentTools.filter((tool) => wanted.has(tool?.name));
4346
+ }
4347
+ return declared;
4348
+ }
4349
+ function buildSubagentCatalogBlock(subagents, policy, toolNames) {
4350
+ const lines = ["<available_subagents>"];
4351
+ const adhoc = policy.mode === "registry_and_adhoc";
4352
+ lines.push(
4353
+ "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."
4354
+ );
4355
+ if (subagents.length > 0) {
4356
+ lines.push(`Call ${toolNames.delegate}(subagent, input) for a named sub-agent:`);
4357
+ for (const entry of subagents) {
4358
+ lines.push(`- ${entry.name}: ${entry.header}`);
4359
+ }
4360
+ }
4361
+ if (adhoc) {
4362
+ lines.push(
4363
+ `Call ${toolNames.spawn}({ role, prompt, input, tools? }) to create a sub-agent on the fly.`
4364
+ );
4365
+ }
4366
+ lines.push(
4367
+ `Call ${toolNames.parallel}({ tasks: [...] }) to run up to ${policy.maxParallel} independent subtasks concurrently (no human-input tools inside parallel children).`
4368
+ );
4369
+ lines.push("</available_subagents>");
4370
+ return lines.join("\n");
4371
+ }
4372
+
4263
4373
  // src/agent.ts
4264
4374
  function getLastAssistantMessage(messages) {
4265
4375
  for (let index = messages.length - 1; index >= 0; index -= 1) {
@@ -4631,7 +4741,7 @@ function createAgent(opts) {
4631
4741
  resumeStage = null;
4632
4742
  }
4633
4743
  const lastMsg = state.messages[state.messages.length - 1];
4634
- const toolCalls = Array.isArray(lastMsg?.tool_calls) ? lastMsg.tool_calls : [];
4744
+ const toolCalls = selectPendingToolCalls(state.messages);
4635
4745
  const toolCallCount = state.toolCallCount || 0;
4636
4746
  if (state.ctx?.__finalizedDueToToolLimit) {
4637
4747
  break;
@@ -4931,27 +5041,28 @@ function createAgent(opts) {
4931
5041
  error: `Child-call budget exhausted (${delegationPolicy.maxChildCalls}).`
4932
5042
  };
4933
5043
  }
4934
- let childMessages;
4935
- switch (delegationPolicy.childContextPolicy) {
4936
- case "full":
4937
- childMessages = [...parentMessages, { role: "user", content: input }];
4938
- break;
4939
- case "scoped": {
4940
- const systemPrefix = parentMessages[0]?.role === "system" ? [parentMessages[0]] : [];
4941
- const lastUser = [...parentMessages].reverse().find((m) => m?.role === "user");
4942
- childMessages = [
4943
- ...systemPrefix,
4944
- ...lastUser ? [lastUser] : [],
4945
- { role: "user", content: input }
4946
- ];
4947
- break;
4948
- }
4949
- case "minimal":
4950
- default:
4951
- childMessages = [{ role: "user", content: input }];
4952
- }
5044
+ const childMessages = seedChildMessages(
5045
+ delegationPolicy.childContextPolicy,
5046
+ parentMessages,
5047
+ input
5048
+ );
4953
5049
  const childCtx = { __delegationDepth: currentDepth + 1 };
4954
- const res = await instance.invoke({ messages: childMessages, ctx: childCtx });
5050
+ const childConfig = {
5051
+ onEvent: parentCtx.__onEvent ? (e) => {
5052
+ if (e?.type === "finalAnswer" || e?.type === "metadata") return;
5053
+ try {
5054
+ parentCtx.__onEvent({ ...e, delegatedTo: opts.name });
5055
+ } catch {
5056
+ }
5057
+ } : void 0,
5058
+ onProgress: parentCtx.__onProgress,
5059
+ onStream: parentCtx.__streaming && parentCtx.__onStream ? (chunk) => {
5060
+ if (!chunk?.isFinal) parentCtx.__onStream(chunk);
5061
+ } : void 0,
5062
+ stream: Boolean(parentCtx.__streaming),
5063
+ cancellationToken: parentCtx.__cancellationToken ?? parentCtx.__abortSignal
5064
+ };
5065
+ const res = await instance.invoke({ messages: childMessages, ctx: childCtx }, childConfig);
4955
5066
  return {
4956
5067
  content: res.content,
4957
5068
  output: res.output,
@@ -6378,6 +6489,421 @@ function createSkillTools(deps) {
6378
6489
  return [createOpenSkillTool(deps), createBindSkillToolsTool(deps)];
6379
6490
  }
6380
6491
 
6492
+ // src/smart/subagents/types.ts
6493
+ var DEFAULT_SUBAGENT_POLICY = {
6494
+ mode: "registry_and_adhoc",
6495
+ maxDepth: 2,
6496
+ maxChildCalls: 8,
6497
+ maxParallel: 4,
6498
+ childContextPolicy: "scoped",
6499
+ allowAdhocTools: true
6500
+ };
6501
+ function createSubagentRegistryRef() {
6502
+ return { spawnedCount: 0, results: [] };
6503
+ }
6504
+ var DEFAULT_SUBAGENT_TOOL_NAMES = {
6505
+ delegate: "delegate_to",
6506
+ spawn: "spawn_subagent",
6507
+ parallel: "spawn_subagents_parallel"
6508
+ };
6509
+ 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.";
6510
+ 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.";
6511
+ 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).";
6512
+ var CTX_CALLBACK_KEYS = /* @__PURE__ */ new Set([
6513
+ "__onEvent",
6514
+ "__onProgress",
6515
+ "__onStream",
6516
+ "__traceSession",
6517
+ "__paused",
6518
+ "__cancellationToken",
6519
+ "__abortSignal",
6520
+ "__deadline"
6521
+ ]);
6522
+ function cleanChildState(state) {
6523
+ const { agent: _agent, ctx, ...rest } = state;
6524
+ let cleanCtx2;
6525
+ if (ctx && typeof ctx === "object") {
6526
+ cleanCtx2 = {};
6527
+ for (const [k, v] of Object.entries(ctx)) {
6528
+ if (CTX_CALLBACK_KEYS.has(k)) continue;
6529
+ cleanCtx2[k] = v;
6530
+ }
6531
+ }
6532
+ return { ...rest, ctx: cleanCtx2 };
6533
+ }
6534
+ function makeChildEventForwarder(parentOnEvent, spawnId, name) {
6535
+ return (event) => {
6536
+ if (!parentOnEvent) return;
6537
+ if (event?.type === "finalAnswer" || event?.type === "metadata") return;
6538
+ try {
6539
+ parentOnEvent({ ...event, subagentId: spawnId, subagentName: name });
6540
+ } catch {
6541
+ }
6542
+ };
6543
+ }
6544
+ function buildChildConfig(parentCtx, spawnId, name) {
6545
+ const streaming = Boolean(parentCtx.__streaming);
6546
+ const parentOnStream = parentCtx.__onStream;
6547
+ return {
6548
+ onEvent: makeChildEventForwarder(parentCtx.__onEvent, spawnId, name),
6549
+ onProgress: parentCtx.__onProgress,
6550
+ // Forward streaming deltas but swallow the child's `isFinal` chunk so the
6551
+ // host does not mistake a child completion for the parent's final answer.
6552
+ onStream: streaming && parentOnStream ? (chunk) => {
6553
+ if (!chunk.isFinal) parentOnStream(chunk);
6554
+ } : void 0,
6555
+ stream: streaming,
6556
+ cancellationToken: parentCtx.__cancellationToken ?? parentCtx.__abortSignal
6557
+ };
6558
+ }
6559
+ function summaryOf(state) {
6560
+ const summaries = state?.summaries;
6561
+ return Array.isArray(summaries) && summaries.length > 0 ? summaries[summaries.length - 1] : void 0;
6562
+ }
6563
+ async function runChild(spec, input, deps, ref, opts) {
6564
+ const parentCtx = ref.ctx || {};
6565
+ const parentOnEvent = parentCtx.__onEvent;
6566
+ const spawnId = `sa_${nanoid(6)}`;
6567
+ const start = Date.now();
6568
+ const child = deps.buildChild({
6569
+ name: spec.name,
6570
+ model: spec.model,
6571
+ systemPrompt: spec.systemPrompt,
6572
+ tools: spec.tools,
6573
+ outputSchema: spec.outputSchema,
6574
+ limits: spec.limits
6575
+ });
6576
+ const childConfig = buildChildConfig(parentCtx, spawnId, spec.name);
6577
+ let childInput;
6578
+ if (opts.isResume && opts.record) {
6579
+ const restored = { ...opts.record.childState };
6580
+ if (opts.record.pendingKind === "approval") {
6581
+ const entry = (ref.pendingApprovals || []).find((e) => e.id === opts.record.pendingId);
6582
+ if (!entry) {
6583
+ return { kind: "result", result: { name: spec.name, mode: spec.mode, input, error: "Pending approval resolution missing on resume." } };
6584
+ }
6585
+ if (entry.status === "pending") {
6586
+ if (!parentCtx.__awaitingApproval) {
6587
+ parentCtx.__awaitingApproval = { approvalId: entry.id, toolCallId: entry.toolCallId, toolName: entry.toolName, requestedAt: entry.requestedAt };
6588
+ }
6589
+ parentCtx.__resumeStage = "tools";
6590
+ return { kind: "approval", toolCallId: entry.toolCallId, approvalId: entry.id };
6591
+ }
6592
+ childInput = resolveToolApprovalState(restored, {
6593
+ id: opts.record.pendingId,
6594
+ approved: entry.status === "approved",
6595
+ approvedArgs: entry.approvedArgs,
6596
+ decidedBy: entry.decidedBy,
6597
+ comment: entry.comment
6598
+ });
6599
+ } else {
6600
+ const entry = (ref.pendingUserQuestions || []).find((e) => e.id === opts.record.pendingId);
6601
+ if (!entry) {
6602
+ return { kind: "result", result: { name: spec.name, mode: spec.mode, input, error: "Pending question resolution missing on resume." } };
6603
+ }
6604
+ if (entry.status === "pending") {
6605
+ if (!parentCtx.__awaitingUserQuestion) {
6606
+ parentCtx.__awaitingUserQuestion = { id: entry.id, toolCallId: entry.toolCallId, requestedAt: entry.requestedAt };
6607
+ }
6608
+ parentCtx.__resumeStage = "tools";
6609
+ return { kind: "user_question", toolCallId: entry.toolCallId, id: entry.id };
6610
+ }
6611
+ childInput = resolveUserQuestionState(restored, {
6612
+ id: opts.record.pendingId,
6613
+ answers: entry.answers,
6614
+ answeredBy: entry.answeredBy,
6615
+ notes: entry.notes,
6616
+ cancelled: entry.cancelled === true
6617
+ });
6618
+ }
6619
+ } else {
6620
+ parentOnEvent?.({ type: "subagent", phase: "start", name: spec.name, id: spawnId, mode: spec.mode, parallel: opts.parallel, parentToolCallId: opts.parentToolCallId, input });
6621
+ const currentDepth = Number(parentCtx.__delegationDepth) || 0;
6622
+ childInput = {
6623
+ messages: seedChildMessages(spec.childContextPolicy, ref.messages || [], input),
6624
+ ctx: { __delegationDepth: currentDepth + 1 }
6625
+ };
6626
+ }
6627
+ let res;
6628
+ try {
6629
+ res = await child.invoke(childInput, childConfig);
6630
+ } catch (err) {
6631
+ const result2 = { name: spec.name, mode: spec.mode, input, error: err?.message || String(err), durationMs: Date.now() - start };
6632
+ deps.registryRef.results.push(result2);
6633
+ parentOnEvent?.({ type: "subagent", phase: "error", name: spec.name, id: spawnId, mode: spec.mode, error: { message: result2.error }, parentToolCallId: opts.parentToolCallId });
6634
+ return { kind: "result", result: result2 };
6635
+ }
6636
+ const childState = res.state;
6637
+ const awaitingApproval = childState?.ctx?.__awaitingApproval;
6638
+ const awaitingQuestion = childState?.ctx?.__awaitingUserQuestion;
6639
+ if (childState && (awaitingApproval || awaitingQuestion)) {
6640
+ if (!opts.allowHITL) {
6641
+ const result2 = {
6642
+ name: spec.name,
6643
+ mode: spec.mode,
6644
+ input,
6645
+ error: "Sub-agent requested human input, which is not supported inside parallel fan-out. Run it via delegate_to / spawn_subagent instead.",
6646
+ durationMs: Date.now() - start
6647
+ };
6648
+ deps.registryRef.results.push(result2);
6649
+ return { kind: "result", result: result2 };
6650
+ }
6651
+ const pendingStore = parentCtx.__subagentPending || (parentCtx.__subagentPending = {});
6652
+ if (awaitingApproval) {
6653
+ const childEntry = (childState.pendingApprovals || []).find((e) => e.status === "pending");
6654
+ if (childEntry) {
6655
+ const surfaced = { ...childEntry, metadata: { ...childEntry.metadata || {}, __subagent: { parentToolCallId: opts.parentToolCallId, name: spec.name } } };
6656
+ (ref.pendingApprovals || (ref.pendingApprovals = [])).push(surfaced);
6657
+ if (!parentCtx.__awaitingApproval && !parentCtx.__awaitingUserQuestion) {
6658
+ parentCtx.__awaitingApproval = { approvalId: surfaced.id, toolCallId: surfaced.toolCallId, toolName: surfaced.toolName, requestedAt: surfaced.requestedAt };
6659
+ }
6660
+ parentCtx.__resumeStage = "tools";
6661
+ pendingStore[opts.parentToolCallId] = {
6662
+ parentToolCallId: opts.parentToolCallId,
6663
+ name: spec.name,
6664
+ mode: spec.mode,
6665
+ adhoc: spec.adhoc,
6666
+ input,
6667
+ childState: cleanChildState(childState),
6668
+ pendingKind: "approval",
6669
+ pendingId: childEntry.id
6670
+ };
6671
+ parentOnEvent?.({ type: "subagent", phase: "paused", name: spec.name, id: spawnId, mode: spec.mode, parentToolCallId: opts.parentToolCallId });
6672
+ return { kind: "approval", toolCallId: surfaced.toolCallId, approvalId: surfaced.id };
6673
+ }
6674
+ }
6675
+ if (awaitingQuestion) {
6676
+ const childEntry = (childState.pendingUserQuestions || []).find((e) => e.status === "pending");
6677
+ if (childEntry) {
6678
+ const surfaced = { ...childEntry, metadata: { ...childEntry.metadata || {}, __subagent: { parentToolCallId: opts.parentToolCallId, name: spec.name } } };
6679
+ (ref.pendingUserQuestions || (ref.pendingUserQuestions = [])).push(surfaced);
6680
+ if (!parentCtx.__awaitingUserQuestion && !parentCtx.__awaitingApproval) {
6681
+ parentCtx.__awaitingUserQuestion = { id: surfaced.id, toolCallId: surfaced.toolCallId, requestedAt: surfaced.requestedAt };
6682
+ }
6683
+ parentCtx.__resumeStage = "tools";
6684
+ pendingStore[opts.parentToolCallId] = {
6685
+ parentToolCallId: opts.parentToolCallId,
6686
+ name: spec.name,
6687
+ mode: spec.mode,
6688
+ adhoc: spec.adhoc,
6689
+ input,
6690
+ childState: cleanChildState(childState),
6691
+ pendingKind: "user_question",
6692
+ pendingId: childEntry.id
6693
+ };
6694
+ parentOnEvent?.({ type: "subagent", phase: "paused", name: spec.name, id: spawnId, mode: spec.mode, parentToolCallId: opts.parentToolCallId });
6695
+ return { kind: "user_question", toolCallId: surfaced.toolCallId, id: surfaced.id };
6696
+ }
6697
+ }
6698
+ }
6699
+ if (parentCtx.__subagentPending?.[opts.parentToolCallId]) {
6700
+ delete parentCtx.__subagentPending[opts.parentToolCallId];
6701
+ }
6702
+ const result = {
6703
+ name: spec.name,
6704
+ mode: spec.mode,
6705
+ input,
6706
+ content: res.content,
6707
+ output: res.output,
6708
+ summary: summaryOf(childState),
6709
+ durationMs: Date.now() - start
6710
+ };
6711
+ deps.registryRef.results.push(result);
6712
+ parentOnEvent?.({ type: "subagent", phase: "result", name: spec.name, id: spawnId, mode: spec.mode, content: res.content, durationMs: result.durationMs, parentToolCallId: opts.parentToolCallId });
6713
+ return { kind: "result", result };
6714
+ }
6715
+ async function specFromRegistry(def, deps, parentRuntime) {
6716
+ const tools = await resolveSubagentTools(def.tools, parentRuntime?.tools || []);
6717
+ return {
6718
+ name: def.name,
6719
+ mode: "registry",
6720
+ systemPrompt: def.systemPrompt,
6721
+ model: def.model ?? parentRuntime?.model,
6722
+ tools,
6723
+ outputSchema: def.outputSchema,
6724
+ limits: def.limits,
6725
+ childContextPolicy: def.childContextPolicy ?? deps.policy.childContextPolicy,
6726
+ metadata: def.metadata
6727
+ };
6728
+ }
6729
+ async function specFromAdhoc(args, deps, parentRuntime) {
6730
+ const toolNames = deps.policy.allowAdhocTools ? args.tools ?? args.toolNames ?? [] : [];
6731
+ const tools = await resolveSubagentTools(toolNames, parentRuntime?.tools || []);
6732
+ const systemPrompt = [args.prompt, args.outputContract ? `Output contract: ${args.outputContract}` : ""].filter(Boolean).join("\n\n");
6733
+ return {
6734
+ name: args.role,
6735
+ mode: "adhoc",
6736
+ systemPrompt: systemPrompt || void 0,
6737
+ model: parentRuntime?.model,
6738
+ tools,
6739
+ childContextPolicy: deps.policy.childContextPolicy,
6740
+ adhoc: { role: args.role, prompt: args.prompt, toolNames, outputContract: args.outputContract }
6741
+ };
6742
+ }
6743
+ function toToolReturn(outcome) {
6744
+ if (outcome.kind === "approval") {
6745
+ return { __awaitingToolApproval: true, toolCallId: outcome.toolCallId, approvalId: outcome.approvalId };
6746
+ }
6747
+ if (outcome.kind === "user_question") {
6748
+ return { __awaitingUserQuestion: true, toolCallId: outcome.toolCallId, id: outcome.id };
6749
+ }
6750
+ return outcome.result;
6751
+ }
6752
+ function createDelegateTool(deps) {
6753
+ const names = deps.subagents.map((s) => s.name);
6754
+ const tool = createTool({
6755
+ name: "delegate_to",
6756
+ description: deps.descriptions?.delegate ?? DEFAULT_DELEGATE_DESCRIPTION,
6757
+ schema: z.object({
6758
+ subagent: (names.length > 0 ? z.enum(names) : z.string().min(1)).describe("Name of a sub-agent from <available_subagents>."),
6759
+ input: z.string().min(1).describe("Complete, standalone task for the sub-agent.")
6760
+ }).strict(),
6761
+ func: async ({ subagent, input }) => {
6762
+ const ref = tool._stateRef || {};
6763
+ const d = tool._deps;
6764
+ const parentRuntime = ref.parentRuntime;
6765
+ const parentToolCallId = ref.__currentToolCallId || `delegate_${nanoid(6)}`;
6766
+ const parentCtx = ref.ctx || (ref.ctx = {});
6767
+ const def = findSubagent(d.subagents, subagent);
6768
+ if (!def) return { error: `Unknown sub-agent: ${subagent}. Choose one from <available_subagents>.` };
6769
+ if (def.isAvailable && !await def.isAvailable()) return { error: `Sub-agent ${subagent} is not available right now.` };
6770
+ const record = parentCtx.__subagentPending?.[parentToolCallId];
6771
+ const spec = await specFromRegistry(def, d, parentRuntime);
6772
+ if (!record) {
6773
+ const depth = withinDepth(Number(parentCtx.__delegationDepth) || 0, d.policy);
6774
+ if (!depth.ok) return { error: depth.reason };
6775
+ const budget = canSpawn(d.registryRef, d.policy, 1);
6776
+ if (!budget.ok) return { error: budget.reason };
6777
+ d.registryRef.spawnedCount += 1;
6778
+ }
6779
+ return toToolReturn(await runChild(spec, record?.input ?? input, d, ref, { allowHITL: true, parentToolCallId, isResume: !!record, record }));
6780
+ }
6781
+ });
6782
+ tool._deps = deps;
6783
+ tool._stateRef = {};
6784
+ tool.__source = "smart-subagents";
6785
+ return tool;
6786
+ }
6787
+ function createSpawnTool(deps) {
6788
+ const tool = createTool({
6789
+ name: "spawn_subagent",
6790
+ description: deps.descriptions?.spawn ?? DEFAULT_SPAWN_DESCRIPTION,
6791
+ schema: z.object({
6792
+ role: z.string().min(1).describe("Short role name, e.g. 'db-analyst'."),
6793
+ prompt: z.string().optional().describe("System prompt defining how the sub-agent behaves."),
6794
+ input: z.string().min(1).describe("Complete, standalone task for the sub-agent."),
6795
+ tools: z.array(z.string().min(1)).optional().describe("Names of the parent's tools the sub-agent may use."),
6796
+ outputContract: z.string().optional().describe("Optional description of the expected output shape.")
6797
+ }).strict(),
6798
+ func: async (args) => {
6799
+ const ref = tool._stateRef || {};
6800
+ const d = tool._deps;
6801
+ if (d.policy.mode !== "registry_and_adhoc") {
6802
+ return { error: "Ad-hoc sub-agents are disabled (subagentPolicy.mode is not 'registry_and_adhoc'). Use delegate_to." };
6803
+ }
6804
+ const parentRuntime = ref.parentRuntime;
6805
+ const parentToolCallId = ref.__currentToolCallId || `spawn_${nanoid(6)}`;
6806
+ const parentCtx = ref.ctx || (ref.ctx = {});
6807
+ const record = parentCtx.__subagentPending?.[parentToolCallId];
6808
+ const spec = record?.adhoc ? await specFromAdhoc(record.adhoc, d, parentRuntime) : await specFromAdhoc(args, d, parentRuntime);
6809
+ if (!record) {
6810
+ const depth = withinDepth(Number(parentCtx.__delegationDepth) || 0, d.policy);
6811
+ if (!depth.ok) return { error: depth.reason };
6812
+ const budget = canSpawn(d.registryRef, d.policy, 1);
6813
+ if (!budget.ok) return { error: budget.reason };
6814
+ d.registryRef.spawnedCount += 1;
6815
+ }
6816
+ return toToolReturn(await runChild(spec, record?.input ?? args.input, d, ref, { allowHITL: true, parentToolCallId, isResume: !!record, record }));
6817
+ }
6818
+ });
6819
+ tool._deps = deps;
6820
+ tool._stateRef = {};
6821
+ tool.__source = "smart-subagents";
6822
+ return tool;
6823
+ }
6824
+ function createParallelTool(deps) {
6825
+ const tool = createTool({
6826
+ name: "spawn_subagents_parallel",
6827
+ description: deps.descriptions?.parallel ?? DEFAULT_PARALLEL_DESCRIPTION,
6828
+ schema: z.object({
6829
+ tasks: z.array(
6830
+ z.object({
6831
+ subagent: z.string().optional().describe("Registry sub-agent name."),
6832
+ role: z.string().optional().describe("Ad-hoc role (when not using `subagent`)."),
6833
+ prompt: z.string().optional(),
6834
+ tools: z.array(z.string().min(1)).optional(),
6835
+ input: z.string().min(1)
6836
+ }).strict()
6837
+ ).min(1).max(16).describe("Independent subtasks to run concurrently.")
6838
+ }).strict(),
6839
+ func: async ({ tasks }) => {
6840
+ const ref = tool._stateRef || {};
6841
+ const d = tool._deps;
6842
+ const parentRuntime = ref.parentRuntime;
6843
+ const parentToolCallId = ref.__currentToolCallId || `parallel_${nanoid(6)}`;
6844
+ const parentCtx = ref.ctx || (ref.ctx = {});
6845
+ const depth = withinDepth(Number(parentCtx.__delegationDepth) || 0, d.policy);
6846
+ if (!depth.ok) return { error: depth.reason };
6847
+ const specs = [];
6848
+ for (const task of tasks) {
6849
+ if (task.subagent) {
6850
+ const def = findSubagent(d.subagents, task.subagent);
6851
+ if (!def) {
6852
+ specs.push({ error: `Unknown sub-agent: ${task.subagent}`, input: task.input });
6853
+ continue;
6854
+ }
6855
+ specs.push({ spec: await specFromRegistry(def, d, parentRuntime), input: task.input });
6856
+ } else if (task.role) {
6857
+ if (d.policy.mode !== "registry_and_adhoc") {
6858
+ specs.push({ error: "Ad-hoc sub-agents are disabled.", input: task.input });
6859
+ continue;
6860
+ }
6861
+ specs.push({ spec: await specFromAdhoc({ role: task.role, prompt: task.prompt, tools: task.tools }, d, parentRuntime), input: task.input });
6862
+ } else {
6863
+ specs.push({ error: "Each task needs either `subagent` or `role`.", input: task.input });
6864
+ }
6865
+ }
6866
+ const spawnCount = specs.filter((entry) => !("error" in entry)).length;
6867
+ const budget = canSpawn(d.registryRef, d.policy, spawnCount);
6868
+ if (!budget.ok) return { error: budget.reason };
6869
+ d.registryRef.spawnedCount += spawnCount;
6870
+ const results = new Array(specs.length);
6871
+ const concurrency = Math.max(1, Math.min(d.policy.maxParallel, specs.length));
6872
+ let cursor = 0;
6873
+ const worker = async () => {
6874
+ while (true) {
6875
+ const i = cursor++;
6876
+ if (i >= specs.length) return;
6877
+ const entry = specs[i];
6878
+ if ("error" in entry) {
6879
+ results[i] = { name: "?", mode: "adhoc", input: entry.input, error: entry.error };
6880
+ continue;
6881
+ }
6882
+ const outcome = await runChild(entry.spec, entry.input, d, ref, {
6883
+ allowHITL: false,
6884
+ parentToolCallId: `${parentToolCallId}#${i}`,
6885
+ parallel: true
6886
+ });
6887
+ results[i] = outcome.kind === "result" ? outcome.result : { name: entry.spec.name, mode: entry.spec.mode, input: entry.input, error: "Unexpected pause in parallel child." };
6888
+ }
6889
+ };
6890
+ await Promise.all(Array.from({ length: concurrency }, () => worker()));
6891
+ return { results };
6892
+ }
6893
+ });
6894
+ tool._deps = deps;
6895
+ tool._stateRef = {};
6896
+ tool.__source = "smart-subagents";
6897
+ return tool;
6898
+ }
6899
+ function createSubagentTools(deps) {
6900
+ const tools = [];
6901
+ if (deps.subagents.length > 0) tools.push(createDelegateTool(deps));
6902
+ if (deps.policy.mode === "registry_and_adhoc") tools.push(createSpawnTool(deps));
6903
+ tools.push(createParallelTool(deps));
6904
+ return tools;
6905
+ }
6906
+
6381
6907
  // src/smart/index.ts
6382
6908
  function createSmartAgent(opts) {
6383
6909
  const resolved = normalizeSmartAgentOptions(opts);
@@ -6415,6 +6941,42 @@ function createSmartAgent(opts) {
6415
6941
  const skills = opts.skills ?? [];
6416
6942
  const skillPolicy = opts.skillPolicy ?? DEFAULT_SKILL_POLICY;
6417
6943
  const skillsEnabled = skills.length > 0;
6944
+ const subagentsProvided = opts.subagents !== void 0 || opts.subagentPolicy !== void 0;
6945
+ const subagents = opts.subagents ?? [];
6946
+ const subagentPolicy = opts.subagentPolicy ?? DEFAULT_SUBAGENT_POLICY;
6947
+ const subagentsEnabled = subagentsProvided && subagentPolicy.mode !== "off" && (subagents.length > 0 || subagentPolicy.mode === "registry_and_adhoc");
6948
+ const promptHooks = opts.promptHooks;
6949
+ const buildChild = (cfg) => createSmartAgent({
6950
+ name: cfg.name,
6951
+ model: cfg.model,
6952
+ tools: cfg.tools,
6953
+ systemPrompt: cfg.systemPrompt,
6954
+ outputSchema: cfg.outputSchema,
6955
+ limits: cfg.limits,
6956
+ runtimeProfile: resolved.runtimeProfile,
6957
+ humanInTheLoop: opts.humanInTheLoop,
6958
+ reasoning: opts.reasoning,
6959
+ tokenCounter: opts.tokenCounter,
6960
+ costEstimator: opts.costEstimator,
6961
+ promptHooks,
6962
+ // Sub-agents are single-level by design: a child never gets its own spawn
6963
+ // tools, so it cannot delegate further. This keeps decomposition bounded and
6964
+ // is why the depth guard mainly governs `asTool`-composed nesting (which seeds
6965
+ // __delegationDepth externally) rather than sub-agent-of-sub-agent recursion.
6966
+ subagents: [],
6967
+ subagentPolicy: { ...subagentPolicy, mode: "off" }
6968
+ });
6969
+ const decorateToolDescriptions = (tools) => {
6970
+ const overrides = promptHooks?.toolDescriptions;
6971
+ if (!overrides) return tools;
6972
+ return tools.map((tool) => {
6973
+ const override = overrides[tool?.name];
6974
+ if (override === void 0) return tool;
6975
+ const next = typeof override === "function" ? override(tool.description || "") : override;
6976
+ if (next === tool.description) return tool;
6977
+ return { ...tool, description: next };
6978
+ });
6979
+ };
6418
6980
  const soManagerFactory = opts.outputSchema ? new StructuredOutputManager(opts.outputSchema, resolveStrategy(opts.model)) : void 0;
6419
6981
  const modelCapabilities = opts.outputSchema ? getModelCapabilities(opts.model) : void 0;
6420
6982
  const responseFinalizeTool = soManagerFactory && modelCapabilities?.structuredOutput !== "native" ? soManagerFactory.getResponseTool() : void 0;
@@ -6425,12 +6987,27 @@ function createSmartAgent(opts) {
6425
6987
  const coreBase = [...userTools, ...ctxTools];
6426
6988
  if (responseFinalizeTool) coreBase.push(responseFinalizeTool);
6427
6989
  if (askUserConfig) coreBase.push(createAskUserQuestionTool(ref, askUserConfig));
6990
+ let subagentRegistryRef;
6991
+ if (subagentsEnabled) {
6992
+ subagentRegistryRef = createSubagentRegistryRef();
6993
+ const deps = {
6994
+ registryRef: subagentRegistryRef,
6995
+ subagents,
6996
+ policy: subagentPolicy,
6997
+ buildChild
6998
+ // NOTE: promptHooks.toolDescriptions overrides for the sub-agent tools are
6999
+ // applied uniformly (and only) by decorateToolDescriptions below, so the
7000
+ // function form of an override receives the real DEFAULT_* string. Baking
7001
+ // them in here as well would double-apply and stringify the function.
7002
+ };
7003
+ coreBase.push(...createSubagentTools(deps));
7004
+ }
6428
7005
  if (!skillsEnabled) {
6429
- const without = coreBase;
6430
- const withRec = [...without, recoveryTool];
6431
- return { stateRef: ref, toolsWithoutRecovery: without, toolsWithRecovery: withRec };
7006
+ const without = decorateToolDescriptions(coreBase);
7007
+ const withRec = decorateToolDescriptions([...coreBase, recoveryTool]);
7008
+ return { stateRef: ref, toolsWithoutRecovery: without, toolsWithRecovery: withRec, subagentRegistryRef };
6432
7009
  }
6433
- const toolSet = { stateRef: ref, toolsWithoutRecovery: [], toolsWithRecovery: [] };
7010
+ const toolSet = { stateRef: ref, toolsWithoutRecovery: [], toolsWithRecovery: [], subagentRegistryRef };
6434
7011
  const skillRegistryRef = createSkillRegistryRef();
6435
7012
  const skillMetaTools = createSkillTools({ registryRef: skillRegistryRef, skills, policy: skillPolicy });
6436
7013
  const baseWithMeta = [...coreBase, ...skillMetaTools];
@@ -6440,14 +7017,43 @@ function createSmartAgent(opts) {
6440
7017
  boundSkillTools: skillRegistryRef.boundSkillTools,
6441
7018
  recoveryTool
6442
7019
  });
6443
- toolSet.toolsWithoutRecovery = composed.toolsWithoutRecovery;
6444
- toolSet.toolsWithRecovery = composed.toolsWithRecovery;
7020
+ toolSet.toolsWithoutRecovery = decorateToolDescriptions(composed.toolsWithoutRecovery);
7021
+ toolSet.toolsWithRecovery = decorateToolDescriptions(composed.toolsWithRecovery);
6445
7022
  };
6446
7023
  skillRegistryRef.__onToolsChanged = rebuild;
6447
7024
  toolSet.skillRegistryRef = skillRegistryRef;
6448
7025
  rebuild();
6449
7026
  return toolSet;
6450
7027
  };
7028
+ async function rehydrateSkillRegistry(ref, persisted) {
7029
+ if (!persisted) return false;
7030
+ const opened = Array.isArray(persisted.openedSkillKeys) ? persisted.openedSkillKeys : [];
7031
+ const boundNames = new Set(Array.isArray(persisted.boundToolNames) ? persisted.boundToolNames : []);
7032
+ if (opened.length === 0) return false;
7033
+ let changed = false;
7034
+ for (const key of opened) {
7035
+ if (!ref.openedSkillKeys.includes(key)) ref.openedSkillKeys.push(key);
7036
+ const skill = skills.find((s) => s.key === key);
7037
+ if (!skill) continue;
7038
+ let bound;
7039
+ try {
7040
+ bound = await skill.bindTools();
7041
+ } catch {
7042
+ continue;
7043
+ }
7044
+ const wanted = bound.filter((t) => boundNames.has(t.name));
7045
+ const added = appendBoundTools(ref, wanted, skillPolicy);
7046
+ if (added.length > 0) changed = true;
7047
+ }
7048
+ return changed;
7049
+ }
7050
+ function skillStateFromRegistry(ref) {
7051
+ if (!ref || !Array.isArray(ref.openedSkillKeys) || ref.openedSkillKeys.length === 0) return void 0;
7052
+ return {
7053
+ openedSkillKeys: [...ref.openedSkillKeys],
7054
+ boundToolNames: (ref.boundSkillTools || []).map((t) => t.name)
7055
+ };
7056
+ }
6451
7057
  const base = createAgent({ ...runtimeOpts, tools: factoryToolsWithoutRecovery });
6452
7058
  base.__runtime.runtimeProfile = resolved.runtimeProfile;
6453
7059
  base.__runtime.smart = resolved;
@@ -6498,12 +7104,19 @@ function createSmartAgent(opts) {
6498
7104
  };
6499
7105
  }
6500
7106
  function systemMessage2(extraBlock) {
6501
- const sys = buildSystemPrompt(
7107
+ let sys = buildSystemPrompt(
6502
7108
  [opts.systemPrompt, runtimeHint, structuredOutputHint, extraBlock].filter(Boolean).join("\n"),
6503
7109
  planningEnabled,
6504
7110
  opts.name || "Agent",
6505
7111
  opts.todoListPrompt
6506
7112
  );
7113
+ if (promptHooks?.transformSystemPrompt) {
7114
+ try {
7115
+ sys = promptHooks.transformSystemPrompt(sys, { agentName: opts.name || "Agent" });
7116
+ } catch (err) {
7117
+ console.warn("[agent-sdk] promptHooks.transformSystemPrompt error:", err);
7118
+ }
7119
+ }
6507
7120
  return { role: "system", content: sys };
6508
7121
  }
6509
7122
  function syncRuntimeTools(currentState, currentMessages, toolSet) {
@@ -6548,11 +7161,33 @@ function createSmartAgent(opts) {
6548
7161
  stateRef.todoList = input.plan?.steps;
6549
7162
  stateRef.planVersion = input.planVersion || input.plan?.version || 0;
6550
7163
  stateRef.adherenceScore = input.plan?.adherenceScore || 0;
7164
+ if (skillsEnabled && toolSet.skillRegistryRef) {
7165
+ const changed = await rehydrateSkillRegistry(toolSet.skillRegistryRef, input.ctx?.__skillState);
7166
+ if (changed) toolSet.skillRegistryRef.__onToolsChanged?.();
7167
+ }
6551
7168
  const syncPlanFromRef = (state2) => syncPlanStateWith(stateRef, state2);
6552
7169
  const availableSkills = skillsEnabled ? await resolveAvailableSkills(skills, { modelTier: skillPolicy.modelTier }) : [];
6553
7170
  const skillBlock = availableSkills.length > 0 ? buildSkillHeaderBlock(availableSkills) : void 0;
7171
+ let subagentBlock;
7172
+ if (subagentsEnabled) {
7173
+ const availableSubagents = await resolveAvailableSubagents(subagents);
7174
+ let block = buildSubagentCatalogBlock(availableSubagents, subagentPolicy, {
7175
+ delegate: "delegate_to",
7176
+ spawn: "spawn_subagent",
7177
+ parallel: "spawn_subagents_parallel"
7178
+ });
7179
+ if (promptHooks?.subagentCatalog) {
7180
+ try {
7181
+ block = promptHooks.subagentCatalog(block, availableSubagents);
7182
+ } catch (err) {
7183
+ console.warn("[agent-sdk] promptHooks.subagentCatalog error:", err);
7184
+ }
7185
+ }
7186
+ subagentBlock = block;
7187
+ }
7188
+ const disclosureBlock = [skillBlock, subagentBlock].filter(Boolean).join("\n\n") || void 0;
6554
7189
  const alreadyHasSystem = Array.isArray(input.messages) && input.messages[0]?.role === "system";
6555
- const seedMessages = alreadyHasSystem ? [...input.messages || []] : [systemMessage2(skillBlock), ...input.messages || []];
7190
+ const seedMessages = alreadyHasSystem ? [...input.messages || []] : [systemMessage2(disclosureBlock), ...input.messages || []];
6556
7191
  let state = syncRuntimeTools(await syncMemory({ ...input, messages: seedMessages }), seedMessages, toolSet);
6557
7192
  let lastResult = null;
6558
7193
  let rawMessages = [...seedMessages];
@@ -6625,6 +7260,13 @@ function createSmartAgent(opts) {
6625
7260
  } else if (lastResult.state) {
6626
7261
  lastResult = { ...lastResult, state: { ...lastResult.state, memoryFacts: state.memoryFacts, plan: state.plan, planVersion: state.planVersion, messages: rawMessages } };
6627
7262
  }
7263
+ if (skillsEnabled && lastResult.state) {
7264
+ const persisted = skillStateFromRegistry(toolSet.skillRegistryRef);
7265
+ if (persisted) {
7266
+ const prevCtx = lastResult.state.ctx || {};
7267
+ lastResult = { ...lastResult, state: { ...lastResult.state, ctx: { ...prevCtx, __skillState: persisted } } };
7268
+ }
7269
+ }
6628
7270
  return lastResult;
6629
7271
  },
6630
7272
  snapshot: base.snapshot,
@@ -6637,6 +7279,150 @@ function createSmartAgent(opts) {
6637
7279
  };
6638
7280
  return instance;
6639
7281
  }
7282
+ var FRONTMATTER_RE = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?/;
7283
+ function parseSkillFrontmatter(md) {
7284
+ const match = FRONTMATTER_RE.exec(md);
7285
+ if (!match) return { metadata: {}, body: md.trim() };
7286
+ return { metadata: parseFrontmatterBlock(match[1] ?? ""), body: md.slice(match[0].length).trim() };
7287
+ }
7288
+ var LIST_KEYS = /* @__PURE__ */ new Set([
7289
+ "scripts",
7290
+ "keywords",
7291
+ "tags",
7292
+ "allowed-tools",
7293
+ "allowed_tools",
7294
+ "compatible-models",
7295
+ "compatible_models"
7296
+ ]);
7297
+ function parseFrontmatterBlock(raw) {
7298
+ const out = {};
7299
+ let listKey = null;
7300
+ let listAcc = [];
7301
+ const flush = () => {
7302
+ if (listKey) {
7303
+ out[listKey] = listAcc;
7304
+ listAcc = [];
7305
+ listKey = null;
7306
+ }
7307
+ };
7308
+ const splitList = (value) => value.split(",").map((v) => unquote(v.trim())).filter(Boolean);
7309
+ for (const line of raw.split(/\r?\n/)) {
7310
+ if (line.trim() === "") continue;
7311
+ const item = /^\s*-\s+(.*)$/.exec(line);
7312
+ if (item && listKey) {
7313
+ listAcc.push(unquote(item[1].trim()));
7314
+ continue;
7315
+ }
7316
+ flush();
7317
+ const kv = /^([A-Za-z0-9_-]+):\s*(.*)$/.exec(line);
7318
+ if (!kv) continue;
7319
+ const [, key, rawValue] = kv;
7320
+ const value = rawValue.trim();
7321
+ if (value === "") {
7322
+ listKey = key;
7323
+ } else if (value.startsWith("[") && value.endsWith("]")) {
7324
+ out[key] = splitList(value.slice(1, -1));
7325
+ } else if (LIST_KEYS.has(key.toLowerCase())) {
7326
+ out[key] = splitList(value);
7327
+ } else {
7328
+ out[key] = unquote(value);
7329
+ }
7330
+ }
7331
+ flush();
7332
+ return out;
7333
+ }
7334
+ function unquote(s) {
7335
+ if (s.startsWith('"') && s.endsWith('"') || s.startsWith("'") && s.endsWith("'")) {
7336
+ return s.slice(1, -1);
7337
+ }
7338
+ return s;
7339
+ }
7340
+ function asArray(v) {
7341
+ if (v === void 0) return [];
7342
+ return Array.isArray(v) ? v : [v];
7343
+ }
7344
+ function sanitize(s) {
7345
+ return s.replace(/[^A-Za-z0-9_]+/g, "_").replace(/^_+|_+$/g, "");
7346
+ }
7347
+ function scriptToolName(skillName, scriptFile) {
7348
+ const base = scriptFile.replace(/\.[^.]+$/, "");
7349
+ return `${sanitize(skillName)}__${sanitize(base)}`;
7350
+ }
7351
+ var join = (...parts) => parts.join("/").replace(/\/{2,}/g, "/");
7352
+ function buildScriptTools(skillName, skillDir, scripts, execution) {
7353
+ const tools = scripts.map(
7354
+ (file) => createTool({
7355
+ name: scriptToolName(skillName, file),
7356
+ description: `Run the bundled "${file}" script from the "${skillName}" skill.`,
7357
+ schema: z.object({
7358
+ args: z.record(z.any()).optional().describe("Arguments passed to the script.")
7359
+ }),
7360
+ needsApproval: true,
7361
+ approvalPrompt: `Run script ${file} from skill ${skillName}?`,
7362
+ func: (input) => execution.executeScript(join(skillDir, "scripts", file), input?.args ?? {})
7363
+ })
7364
+ );
7365
+ const headers = tools.map((t) => ({ name: t.name, description: t.description }));
7366
+ return { headers, tools };
7367
+ }
7368
+ async function loadOneSkill(fs2, skillDir, fallbackName, execution, minModelTier) {
7369
+ let md;
7370
+ try {
7371
+ md = await fs2.readFile(join(skillDir, "SKILL.md"));
7372
+ } catch {
7373
+ return null;
7374
+ }
7375
+ const { metadata, body } = parseSkillFrontmatter(md);
7376
+ const name = metadata.name ?? fallbackName;
7377
+ const description = metadata.description ?? "";
7378
+ const tier = metadata["min-model-tier"] ?? minModelTier;
7379
+ let scripts = asArray(metadata.scripts);
7380
+ if (scripts.length === 0) {
7381
+ try {
7382
+ scripts = await fs2.listDir(join(skillDir, "scripts"));
7383
+ } catch {
7384
+ scripts = [];
7385
+ }
7386
+ }
7387
+ const built = execution && scripts.length > 0 ? buildScriptTools(name, skillDir, scripts, execution) : { headers: [], tools: [] };
7388
+ const skill = {
7389
+ key: `skillmd:${name}`,
7390
+ title: name,
7391
+ header: description,
7392
+ prompt: body,
7393
+ needsSandbox: scripts.length > 0,
7394
+ listToolIndex: () => built.headers,
7395
+ bindTools: (names) => names ? built.tools.filter((t) => names.includes(t.name)) : built.tools
7396
+ };
7397
+ if (tier) skill.minModelTier = tier;
7398
+ return skill;
7399
+ }
7400
+ async function loadSkillsFromDisk(opts) {
7401
+ const skills = [];
7402
+ const seen = /* @__PURE__ */ new Set();
7403
+ for (const root of opts.roots) {
7404
+ let entries;
7405
+ try {
7406
+ entries = await opts.fs.listDir(root);
7407
+ } catch {
7408
+ continue;
7409
+ }
7410
+ for (const entry of entries) {
7411
+ const skill = await loadOneSkill(
7412
+ opts.fs,
7413
+ join(root, entry),
7414
+ entry,
7415
+ opts.execution,
7416
+ opts.minModelTier
7417
+ );
7418
+ if (skill && !seen.has(skill.key)) {
7419
+ seen.add(skill.key);
7420
+ skills.push(skill);
7421
+ }
7422
+ }
7423
+ }
7424
+ return skills;
7425
+ }
6640
7426
 
6641
7427
  // src/smart/eval.ts
6642
7428
  function normalizeProfileTarget(target) {
@@ -9333,6 +10119,6 @@ function createProvider(config) {
9333
10119
  }
9334
10120
  }
9335
10121
 
9336
- export { AnthropicProvider, AzureProvider, BaseProvider, BedrockProvider, DEFAULT_PROFILE_CONFIGS, DEFAULT_SKILL_POLICY, GuardrailPhase, InMemoryMemoryStore, NativeJsonSchemaStrategy, OpenAICompatibleProvider, OpenAIProvider, ProviderError, SMALL_TIER_SKILL_POLICY, StructuredOutputManager, ToolBasedStrategy, VertexProvider, agentVerdictRule, appendBoundTools, buildSkillHeaderBlock, buildSystemPrompt, canOpenSkill, captureSnapshot, codePresenceRule, cognipeerSink, composeToolSets, countApproxTokens, countMessagesTokens, createAgent, createAgentNode, createAskUserQuestionTool, createBindSkillToolsTool, createCodeGuardrail, createContextSummarizeNode, createContextTools, createGetToolResponseTool, createGuardrail, createJsonGuardrail, createManageTodoTool, createOpenSkillTool, createProvider, createRegexGuardrail, createResolverNode, createSkillRegistryRef, createSkillTools, createSmartAgent, createTool, createToolLimitFinalizeNode, createToolsNode, customCallbackRule, customSink, dedupeToolsByName, defaultTokenCounter, emptyUsage, evaluateGuardrails, fileSink, formatZodError, fromLangchainModel, fromLangchainTools, fromNativeProvider, generateSpanId, generateTraceId, getModelCapabilities, getNestedValue, getResolvedSmartConfig, getTokenCounter, hasToolResponseRecoveryReference, httpSink, isSmartModel, jsonSchemaRule, normalizeSmartAgentOptions, otlpSink, readMemoryFacts, regexRule, resolveAvailableSkills, resolveMemoryStore, resolveReasoning, resolveStrategy, resolveToolApprovalState, resolveUserQuestionState, restoreSnapshot, runSmartAgentEvalHarness, setTokenCounter, startStreamingSession, traceSessionToOtlp, validateReasoningConfig, withTools, writeSummaryFactsToMemory };
10122
+ export { AnthropicProvider, AzureProvider, BaseProvider, BedrockProvider, DEFAULT_PROFILE_CONFIGS, DEFAULT_SKILL_POLICY, DEFAULT_SUBAGENT_POLICY, DEFAULT_SUBAGENT_TOOL_NAMES, GuardrailPhase, InMemoryMemoryStore, NativeJsonSchemaStrategy, OpenAICompatibleProvider, OpenAIProvider, ProviderError, SMALL_TIER_SKILL_POLICY, StructuredOutputManager, ToolBasedStrategy, VertexProvider, agentVerdictRule, appendBoundTools, buildSkillHeaderBlock, buildSubagentCatalogBlock, buildSystemPrompt, canOpenSkill, canSpawn, captureSnapshot, codePresenceRule, cognipeerSink, composeToolSets, countApproxTokens, countMessagesTokens, createAgent, createAgentNode, createAskUserQuestionTool, createBindSkillToolsTool, createCodeGuardrail, createContextSummarizeNode, createContextTools, createDelegateTool, createGetToolResponseTool, createGuardrail, createJsonGuardrail, createManageTodoTool, createOpenSkillTool, createParallelTool, createProvider, createRegexGuardrail, createResolverNode, createSkillRegistryRef, createSkillTools, createSmartAgent, createSpawnTool, createSubagentRegistryRef, createSubagentTools, createTool, createToolLimitFinalizeNode, createToolsNode, customCallbackRule, customSink, dedupeToolsByName, defaultTokenCounter, emptyUsage, evaluateGuardrails, fileSink, findSubagent, formatZodError, fromLangchainModel, fromLangchainTools, fromNativeProvider, generateSpanId, generateTraceId, getModelCapabilities, getNestedValue, getResolvedSmartConfig, getTokenCounter, hasToolResponseRecoveryReference, httpSink, isSmartModel, jsonSchemaRule, loadSkillsFromDisk, normalizeSmartAgentOptions, otlpSink, parseSkillFrontmatter, readMemoryFacts, regexRule, resolveAvailableSkills, resolveAvailableSubagents, resolveMemoryStore, resolveReasoning, resolveStrategy, resolveSubagentTools, resolveToolApprovalState, resolveUserQuestionState, restoreSnapshot, runSmartAgentEvalHarness, seedChildMessages, setTokenCounter, startStreamingSession, traceSessionToOtlp, validateReasoningConfig, withTools, withinDepth, writeSummaryFactsToMemory };
9337
10123
  //# sourceMappingURL=index.mjs.map
9338
10124
  //# sourceMappingURL=index.mjs.map