@cuylabs/agent-core 0.9.0 → 0.10.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.
Files changed (116) hide show
  1. package/README.md +33 -17
  2. package/dist/chunk-2O4MCSQS.js +780 -0
  3. package/dist/chunk-2TTOLHBT.js +198 -0
  4. package/dist/chunk-5FMSGQVX.js +281 -0
  5. package/dist/chunk-5NVVNXPQ.js +288 -0
  6. package/dist/{chunk-EKR6PKXU.js → chunk-6HZBHFOL.js} +3 -3
  7. package/dist/chunk-CJI7PVS2.js +58 -0
  8. package/dist/{chunk-WKHDSSXG.js → chunk-CMYN2RCB.js} +146 -46
  9. package/dist/chunk-FII65CN7.js +117 -0
  10. package/dist/{chunk-UHCJEM2E.js → chunk-ICZ66572.js} +13 -6
  11. package/dist/chunk-KYLPMBHD.js +316 -0
  12. package/dist/chunk-MXAP4UG6.js +2956 -0
  13. package/dist/{chunk-4QFNWPIF.js → chunk-N3VX7FEE.js} +35 -2
  14. package/dist/{chunk-MAZ5DY5B.js → chunk-NDZWXCBZ.js} +213 -78
  15. package/dist/{chunk-MHKK374K.js → chunk-Q742PSH3.js} +11 -27
  16. package/dist/{chunk-WGZAPU6N.js → chunk-QAL3OMI3.js} +15 -1
  17. package/dist/{chunk-UDCZ673N.js → chunk-RN6WZEUF.js} +27 -23
  18. package/dist/{chunk-ZXAKHMWH.js → chunk-ROTGCYDW.js} +22 -84
  19. package/dist/chunk-SPBFQXOT.js +0 -0
  20. package/dist/chunk-SSFBF3US.js +602 -0
  21. package/dist/chunk-SZ2XBPTW.js +8 -0
  22. package/dist/chunk-T4UIX5D7.js +115 -0
  23. package/dist/{chunk-IYWQOJMQ.js → chunk-TIHPYVAJ.js} +34 -34
  24. package/dist/{chunk-RKEW5WXI.js → chunk-TOTDGK3P.js} +1 -1
  25. package/dist/chunk-V4RFNEET.js +563 -0
  26. package/dist/chunk-VOUEJSW6.js +0 -0
  27. package/dist/{chunk-J4QDGZIA.js → chunk-WBPOZ7CL.js} +659 -275
  28. package/dist/chunk-X4VN4GIJ.js +185 -0
  29. package/dist/dispatch/index.d.ts +93 -0
  30. package/dist/dispatch/index.js +37 -0
  31. package/dist/events/index.d.ts +93 -0
  32. package/dist/events/index.js +6 -0
  33. package/dist/{runtime → execution}/index.d.ts +120 -35
  34. package/dist/{runtime → execution}/index.js +17 -11
  35. package/dist/index.d.ts +489 -115
  36. package/dist/index.js +1665 -462
  37. package/dist/inference/errors/index.js +1 -1
  38. package/dist/inference/index.d.ts +13 -21
  39. package/dist/inference/index.js +15 -12
  40. package/dist/instance-BqV2D5pc.d.ts +5723 -0
  41. package/dist/logger/index.d.ts +50 -0
  42. package/dist/logger/index.js +11 -0
  43. package/dist/mcp/index.d.ts +5 -9
  44. package/dist/mcp/index.js +2 -3
  45. package/dist/middleware/index.d.ts +10 -150
  46. package/dist/middleware/index.js +10 -2
  47. package/dist/model-messages-B4nK9D1-.d.ts +13 -0
  48. package/dist/models/index.d.ts +5 -2
  49. package/dist/models/index.js +2 -1
  50. package/dist/models/reasoning/index.js +2 -1
  51. package/dist/plugin/index.d.ts +55 -11
  52. package/dist/plugin/index.js +1 -1
  53. package/dist/profiles/index.d.ts +55 -0
  54. package/dist/{presets → profiles}/index.js +10 -10
  55. package/dist/prompt/index.d.ts +8 -13
  56. package/dist/safety/index.d.ts +109 -14
  57. package/dist/safety/index.js +59 -3
  58. package/dist/sandbox/index.d.ts +81 -0
  59. package/dist/sandbox/index.js +1 -0
  60. package/dist/skill/index.d.ts +10 -8
  61. package/dist/skill/index.js +2 -2
  62. package/dist/storage/index.d.ts +12 -4
  63. package/dist/storage/index.js +1 -1
  64. package/dist/subagents/index.d.ts +177 -0
  65. package/dist/subagents/index.js +78 -0
  66. package/dist/team/index.d.ts +544 -0
  67. package/dist/team/index.js +41 -0
  68. package/dist/tool/host/index.d.ts +41 -0
  69. package/dist/tool/host/index.js +10 -0
  70. package/dist/tool/index.d.ts +111 -21
  71. package/dist/tool/index.js +20 -13
  72. package/dist/{types-VQgymC1N.d.ts → types-Bj_J8u_W.d.ts} +44 -64
  73. package/dist/{types-CHiPh8U2.d.ts → types-C_LCeYNg.d.ts} +7 -7
  74. package/dist/types-RSCv7nQ4.d.ts +59 -0
  75. package/package.json +46 -47
  76. package/dist/builder-BgZ_j4Vs.d.ts +0 -35
  77. package/dist/chunk-5ARZJWD2.js +0 -259
  78. package/dist/chunk-DXFBQMXP.js +0 -53
  79. package/dist/chunk-H3FUYU52.js +0 -81
  80. package/dist/chunk-JLXG2SH7.js +0 -905
  81. package/dist/chunk-N7P4PN3O.js +0 -84
  82. package/dist/chunk-OFDKHNCX.js +0 -727
  83. package/dist/chunk-SDSBEQXG.js +0 -157
  84. package/dist/chunk-VEKUXUVF.js +0 -41
  85. package/dist/chunk-VNQBHPCT.js +0 -398
  86. package/dist/chunk-WWYYNWEW.js +0 -259
  87. package/dist/context/index.d.ts +0 -259
  88. package/dist/context/index.js +0 -26
  89. package/dist/events-CE72w8W4.d.ts +0 -149
  90. package/dist/host/index.d.ts +0 -45
  91. package/dist/host/index.js +0 -8
  92. package/dist/index-DQuTZ8xL.d.ts +0 -1335
  93. package/dist/messages-BYWGn8TY.d.ts +0 -110
  94. package/dist/presets/index.d.ts +0 -53
  95. package/dist/registry-DwYqsQkX.d.ts +0 -164
  96. package/dist/runner-CI-XeR16.d.ts +0 -91
  97. package/dist/scope/index.d.ts +0 -10
  98. package/dist/scope/index.js +0 -14
  99. package/dist/session-manager-KbYt2WUh.d.ts +0 -282
  100. package/dist/signal/index.d.ts +0 -28
  101. package/dist/signal/index.js +0 -6
  102. package/dist/sub-agent/index.d.ts +0 -24
  103. package/dist/sub-agent/index.js +0 -32
  104. package/dist/tool-CZWN3KbO.d.ts +0 -141
  105. package/dist/tool-DkhSCV2Y.d.ts +0 -145
  106. package/dist/tracker-DClqYqTj.d.ts +0 -96
  107. package/dist/tracking/index.d.ts +0 -111
  108. package/dist/tracking/index.js +0 -20
  109. package/dist/types-BfNpU8NS.d.ts +0 -270
  110. package/dist/types-BlOKk-Bb.d.ts +0 -330
  111. package/dist/types-BlZwmnuW.d.ts +0 -50
  112. package/dist/types-CQL-SvTn.d.ts +0 -29
  113. package/dist/types-CWm-7rvB.d.ts +0 -55
  114. package/dist/types-DTSkxakL.d.ts +0 -651
  115. package/dist/types-DmDwi2zI.d.ts +0 -339
  116. package/dist/types-YuWV4ag7.d.ts +0 -72
@@ -0,0 +1,780 @@
1
+ import {
2
+ Profiles
3
+ } from "./chunk-6HZBHFOL.js";
4
+ import {
5
+ createLocalDispatchRuntime
6
+ } from "./chunk-SSFBF3US.js";
7
+ import {
8
+ Tool
9
+ } from "./chunk-Q742PSH3.js";
10
+
11
+ // src/subagents/types.ts
12
+ var DEFAULT_SUBAGENT_CONCURRENCY = 6;
13
+ var DEFAULT_SUBAGENT_DEPTH = 2;
14
+ var DEFAULT_SUBAGENT_SESSION_PREFIX = "Subagent";
15
+
16
+ // src/subagents/tool-factories.ts
17
+ import { z } from "zod";
18
+
19
+ // src/subagents/results.ts
20
+ function formatUsageLine(result) {
21
+ return result.usage ? `
22
+ Tokens: ${result.usage.inputTokens} in / ${result.usage.outputTokens} out` : "";
23
+ }
24
+ function formatToolCallsLine(result) {
25
+ return result.toolCalls.length > 0 ? `
26
+ Tool calls: ${result.toolCalls.map((tool) => tool.name).join(", ")}` : "";
27
+ }
28
+ function formatInvalidAgentTypeResult(roleName, validNames) {
29
+ return {
30
+ title: "Invalid role",
31
+ output: `Unknown role "${roleName}".
32
+
33
+ Available roles: ${validNames.join(", ")}`,
34
+ metadata: {}
35
+ };
36
+ }
37
+ function formatSpawnBlockedResult(message) {
38
+ return {
39
+ title: "Cannot start subagent dispatch",
40
+ output: message,
41
+ metadata: {}
42
+ };
43
+ }
44
+ function formatSyncSubAgentResult(roleName, result) {
45
+ return {
46
+ title: `${roleName} completed`,
47
+ output: `<agent_result role="${roleName}" session="${result.sessionId}">
48
+ ` + result.response + `
49
+ </agent_result>` + formatUsageLine(result) + formatToolCallsLine(result),
50
+ metadata: {
51
+ sessionId: result.sessionId,
52
+ role: roleName,
53
+ toolCalls: result.toolCalls.length
54
+ }
55
+ };
56
+ }
57
+ function formatSyncSubAgentErrorResult(roleName, error) {
58
+ return {
59
+ title: `${roleName} failed`,
60
+ output: `Subagent "${roleName}" encountered an error:
61
+ ` + (error instanceof Error ? error.message : String(error)) + `
62
+
63
+ Consider handling the task directly.`,
64
+ metadata: { role: roleName, error: true }
65
+ };
66
+ }
67
+ function formatAsyncSpawnedResult(agentId, roleName, sessionId) {
68
+ return {
69
+ title: `Spawned ${roleName}`,
70
+ output: `Subagent started successfully.
71
+
72
+ ID: ${agentId}
73
+ Role: ${roleName}
74
+ ` + (sessionId ? `Session: ${sessionId}
75
+
76
+ ` : "\n") + `Use wait_agent with this ID to collect the result later.`,
77
+ metadata: { agentId, role: roleName, sessionId }
78
+ };
79
+ }
80
+ function formatWaitResult(agentId, roleName, result) {
81
+ return {
82
+ title: `${roleName} finished`,
83
+ output: `<agent_result id="${agentId}" role="${roleName}" session="${result.sessionId}">
84
+ ` + result.response + `
85
+ </agent_result>` + formatUsageLine(result) + formatToolCallsLine(result),
86
+ metadata: {
87
+ agentId,
88
+ role: roleName,
89
+ sessionId: result.sessionId,
90
+ toolCalls: result.toolCalls.length
91
+ }
92
+ };
93
+ }
94
+ function formatWaitTimeoutResult(timeoutMs, runningIds) {
95
+ return {
96
+ title: "Wait timed out",
97
+ output: `Timed out waiting after ${timeoutMs}ms.
98
+
99
+ ` + (runningIds.length > 0 ? `Still running: ${runningIds.join(", ")}` : "No requested subagents are still running."),
100
+ metadata: { timeoutMs, runningIds }
101
+ };
102
+ }
103
+ function formatWaitErrorResult(error) {
104
+ return {
105
+ title: "Wait failed",
106
+ output: error instanceof Error ? error.message : String(error),
107
+ metadata: { error: true }
108
+ };
109
+ }
110
+ function formatMissingAgentsResult(ids) {
111
+ return {
112
+ title: "Unknown subagent IDs",
113
+ output: `No tracked subagents found for: ${ids.join(", ")}`,
114
+ metadata: { missing: ids }
115
+ };
116
+ }
117
+ function formatCloseMissingAgentResult(id) {
118
+ return {
119
+ title: "Unknown subagent ID",
120
+ output: `No tracked subagent found for "${id}".`,
121
+ metadata: { id, missing: true }
122
+ };
123
+ }
124
+ function formatCloseAlreadyResolvedResult(id, state) {
125
+ return {
126
+ title: "Subagent already resolved",
127
+ output: `Subagent "${id}" is already ${state}.`,
128
+ metadata: { id, state }
129
+ };
130
+ }
131
+ function formatCancelledAgentResult(id, roleName) {
132
+ return {
133
+ title: `Cancelled ${roleName}`,
134
+ output: `Subagent "${id}" was cancelled.`,
135
+ metadata: { id, role: roleName, cancelled: true }
136
+ };
137
+ }
138
+
139
+ // src/subagents/tool-factories.ts
140
+ var SUBAGENT_TOOL_IDS = [
141
+ "invoke_agent",
142
+ "wait_agent",
143
+ "close_agent"
144
+ ];
145
+ function getRoleNames(roles) {
146
+ return roles.map((role) => role.name);
147
+ }
148
+ function findRole(roles, roleName) {
149
+ return roles.find((role) => role.name === roleName);
150
+ }
151
+ function buildInvokeDescription(roles, isAsync) {
152
+ const roleList = roles.map((role) => ` - "${role.name}": ${role.description}`).join("\n");
153
+ const modeNote = isAsync ? "Returns an agent ID immediately. For parallel work, launch all needed subagents first, then use `wait_agent` to collect the results." : "Blocks until the subagent completes and returns the result directly.";
154
+ return `Delegate a focused task to a specialized subagent.
155
+
156
+ Available roles:
157
+ ${roleList}
158
+
159
+ ${modeNote}
160
+
161
+ Guidelines:
162
+ - Use subagents for well-scoped, independent tasks
163
+ - Provide clear, self-contained instructions \u2014 the subagent has a fresh context
164
+ - Include any relevant file paths, function names, or context the subagent needs
165
+ - Mention the working directory structure if known (for example, "code is in packages/agent-core/src")
166
+ - For parallel work, invoke multiple subagents before waiting for results
167
+ - Subagents will retry on errors and explore alternatives`;
168
+ }
169
+ function toCompletedResult(record) {
170
+ if (!record.result || !record.sessionId) {
171
+ throw new Error(`Dispatch "${record.id}" did not produce a completed result.`);
172
+ }
173
+ return {
174
+ response: record.result.response,
175
+ sessionId: record.sessionId,
176
+ usage: record.result.usage,
177
+ toolCalls: record.result.toolCalls
178
+ };
179
+ }
180
+ async function waitForTerminalDispatch(runtime, id) {
181
+ for (; ; ) {
182
+ const record = await runtime.check(id, { waitMs: 1e3 });
183
+ if (!record) {
184
+ throw new Error(`Subagent dispatch "${id}" was not found.`);
185
+ }
186
+ if (record.status !== "running") {
187
+ return record;
188
+ }
189
+ }
190
+ }
191
+ function formatTerminalFailure(record) {
192
+ if (record.status === "failed") {
193
+ return formatWaitErrorResult(
194
+ new Error(record.error ?? `Subagent "${record.id}" failed.`)
195
+ );
196
+ }
197
+ if (record.status === "cancelled") {
198
+ return formatWaitErrorResult(
199
+ new Error(record.error ?? `Subagent "${record.id}" was cancelled.`)
200
+ );
201
+ }
202
+ return formatWaitErrorResult(
203
+ new Error(`Subagent "${record.id}" is in unexpected state "${record.status}".`)
204
+ );
205
+ }
206
+ function createInvokeAgentTool(runtime, roles, options) {
207
+ const isAsync = options?.async ?? false;
208
+ const titlePrefix = options?.sessionTitlePrefix ?? DEFAULT_SUBAGENT_SESSION_PREFIX;
209
+ const validNames = getRoleNames(roles);
210
+ return Tool.define("invoke_agent", () => ({
211
+ description: buildInvokeDescription(roles, isAsync),
212
+ parameters: z.object({
213
+ role: z.string().describe(
214
+ `The specialized role to use. Must be one of: ${validNames.join(", ")}`
215
+ ),
216
+ task: z.string().describe(
217
+ "A detailed, self-contained description of the task. Include all context the subagent needs."
218
+ ),
219
+ title: z.string().optional().describe("Short title for tracking (3-5 words)")
220
+ }),
221
+ execute: async (params, ctx) => {
222
+ const role = findRole(roles, params.role);
223
+ if (!role) {
224
+ return formatInvalidAgentTypeResult(params.role, validNames);
225
+ }
226
+ let started;
227
+ try {
228
+ started = await runtime.start({
229
+ targetType: role.name,
230
+ brief: params.task,
231
+ title: params.title ?? `${titlePrefix}: ${role.name}`,
232
+ parentSessionId: ctx.sessionID,
233
+ abort: ctx.abort
234
+ });
235
+ } catch (error) {
236
+ return formatSpawnBlockedResult(
237
+ error instanceof Error ? error.message : String(error)
238
+ );
239
+ }
240
+ if (isAsync) {
241
+ return formatAsyncSpawnedResult(started.id, role.name, started.sessionId);
242
+ }
243
+ try {
244
+ const finished = await waitForTerminalDispatch(runtime, started.id);
245
+ if (finished.status === "completed") {
246
+ return formatSyncSubAgentResult(
247
+ role.name,
248
+ toCompletedResult(finished)
249
+ );
250
+ }
251
+ return formatSyncSubAgentErrorResult(
252
+ role.name,
253
+ finished.error ?? `Subagent finished with status "${finished.status}".`
254
+ );
255
+ } catch (error) {
256
+ return formatSyncSubAgentErrorResult(role.name, error);
257
+ }
258
+ }
259
+ }));
260
+ }
261
+ function createWaitAgentTool(runtime) {
262
+ return Tool.define("wait_agent", {
263
+ description: "Wait for one or more subagents to complete and return their results. When multiple IDs are provided, returns whichever finishes first. Use a timeout to avoid blocking indefinitely.",
264
+ parameters: z.object({
265
+ ids: z.array(z.string()).min(1).describe("Subagent IDs to wait on (from invoke_agent)"),
266
+ timeout_ms: z.number().optional().describe("Timeout in milliseconds (default: 60000, max: 600000)")
267
+ }),
268
+ execute: async (params) => {
269
+ const timeoutMs = Math.min(params.timeout_ms ?? 6e4, 6e5);
270
+ const existing = await Promise.all(
271
+ params.ids.map(async (id) => [id, await runtime.check(id)])
272
+ );
273
+ const missing = existing.filter(([, record]) => !record).map(([id]) => id);
274
+ if (missing.length > 0) {
275
+ return formatMissingAgentsResult(missing);
276
+ }
277
+ const checks = params.ids.map(async (id) => {
278
+ const record = await runtime.check(id, { waitMs: timeoutMs });
279
+ return [id, record];
280
+ });
281
+ try {
282
+ const [id, record] = await Promise.race(checks);
283
+ if (record.status === "running") {
284
+ const runningIds = existing.filter(([, current]) => current?.status === "running").map(([currentId]) => currentId);
285
+ return formatWaitTimeoutResult(timeoutMs, runningIds);
286
+ }
287
+ if (record.status === "completed") {
288
+ return formatWaitResult(
289
+ id,
290
+ record.targetType,
291
+ toCompletedResult(record)
292
+ );
293
+ }
294
+ return formatTerminalFailure(record);
295
+ } catch (error) {
296
+ return formatWaitErrorResult(error);
297
+ }
298
+ }
299
+ });
300
+ }
301
+ function createCloseAgentTool(runtime) {
302
+ return Tool.define("close_agent", {
303
+ description: "Cancel a running subagent. Use when the result is no longer needed or the subagent is taking too long.",
304
+ parameters: z.object({
305
+ id: z.string().describe("Subagent ID to cancel (from invoke_agent)")
306
+ }),
307
+ execute: async (params) => {
308
+ const record = await runtime.check(params.id);
309
+ if (!record) {
310
+ return formatCloseMissingAgentResult(params.id);
311
+ }
312
+ if (record.status !== "running") {
313
+ return formatCloseAlreadyResolvedResult(params.id, record.status);
314
+ }
315
+ const cancelled = await runtime.cancel(params.id);
316
+ return formatCancelledAgentResult(params.id, cancelled.targetType);
317
+ }
318
+ });
319
+ }
320
+
321
+ // src/subagents/tools.ts
322
+ function createSubAgentTools(parent, options) {
323
+ if (options.roles.length === 0) {
324
+ return [];
325
+ }
326
+ const currentDepth = options.currentDepth ?? 0;
327
+ const maxDepth = options.maxDepth ?? DEFAULT_SUBAGENT_DEPTH;
328
+ if (currentDepth >= maxDepth) {
329
+ return [];
330
+ }
331
+ const runtime = createLocalDispatchRuntime({
332
+ ...options,
333
+ parent,
334
+ childToolIds: SUBAGENT_TOOL_IDS,
335
+ createChildTools: (childRuntime) => {
336
+ const tools2 = [
337
+ createInvokeAgentTool(childRuntime, options.roles, options)
338
+ ];
339
+ if (options.async) {
340
+ tools2.push(
341
+ createWaitAgentTool(childRuntime),
342
+ createCloseAgentTool(childRuntime)
343
+ );
344
+ }
345
+ return tools2;
346
+ }
347
+ });
348
+ const tools = [
349
+ createInvokeAgentTool(runtime, options.roles, options)
350
+ ];
351
+ if (options.async) {
352
+ tools.push(createWaitAgentTool(runtime), createCloseAgentTool(runtime));
353
+ }
354
+ return tools;
355
+ }
356
+
357
+ // src/subagents/installation.ts
358
+ var LOCAL_SUBAGENT_BACKEND = "@cuylabs/agent-core/local";
359
+ var installedSubAgents = /* @__PURE__ */ new WeakMap();
360
+ function cloneConfig(config) {
361
+ return {
362
+ ...config,
363
+ roles: [...config.roles]
364
+ };
365
+ }
366
+ function configureSubAgents(agent, config) {
367
+ const next = cloneConfig(config);
368
+ const target = agent;
369
+ const current = installedSubAgents.get(target);
370
+ installedSubAgents.set(target, {
371
+ config: next,
372
+ backend: current?.backend ?? "uninstalled"
373
+ });
374
+ return next;
375
+ }
376
+ function getConfiguredSubAgents(agent) {
377
+ return installedSubAgents.get(agent)?.config;
378
+ }
379
+ function getInstalledSubAgentBackend(agent) {
380
+ const backend = installedSubAgents.get(agent)?.backend;
381
+ return backend && backend !== "uninstalled" ? backend : void 0;
382
+ }
383
+ function clearInstalledSubAgents(agent) {
384
+ installedSubAgents.delete(agent);
385
+ for (const toolId of SUBAGENT_TOOL_IDS) {
386
+ agent.removeTool(toolId);
387
+ }
388
+ }
389
+ function installSubAgentTools(options) {
390
+ const target = options.agent;
391
+ const config = configureSubAgents(target, options.config);
392
+ for (const toolId of SUBAGENT_TOOL_IDS) {
393
+ target.removeTool(toolId);
394
+ }
395
+ for (const tool of options.tools) {
396
+ target.addTool(tool);
397
+ }
398
+ installedSubAgents.set(target, {
399
+ config,
400
+ backend: options.backend
401
+ });
402
+ return options.tools;
403
+ }
404
+ function installLocalSubAgents(agent, config) {
405
+ const resolved = config ?? getConfiguredSubAgents(agent);
406
+ if (!resolved) {
407
+ return [];
408
+ }
409
+ const tools = createSubAgentTools(agent, resolved);
410
+ return installSubAgentTools({
411
+ agent,
412
+ config: resolved,
413
+ backend: LOCAL_SUBAGENT_BACKEND,
414
+ tools
415
+ });
416
+ }
417
+
418
+ // src/subagents/roles/discovery.ts
419
+ import { existsSync, readdirSync, readFileSync, statSync } from "fs";
420
+ import { homedir } from "os";
421
+ import { isAbsolute, join, resolve } from "path";
422
+
423
+ // src/subagents/roles/markdown-profile.ts
424
+ var FRONTMATTER_REGEX = /^---\s*\n([\s\S]*?)\n---\s*\n?([\s\S]*)$/;
425
+ var VALID_REASONING_LEVELS = /* @__PURE__ */ new Set([
426
+ "off",
427
+ "minimal",
428
+ "low",
429
+ "medium",
430
+ "high",
431
+ "xhigh"
432
+ ]);
433
+ function parseSubAgentRoleFrontmatter(raw) {
434
+ const result = {};
435
+ const lines = raw.split("\n");
436
+ let i = 0;
437
+ while (i < lines.length) {
438
+ const line = lines[i];
439
+ if (line.trim() === "" || line.trim().startsWith("#")) {
440
+ i++;
441
+ continue;
442
+ }
443
+ const colonIndex = line.indexOf(":");
444
+ if (colonIndex === -1) {
445
+ i++;
446
+ continue;
447
+ }
448
+ const key = line.slice(0, colonIndex).trim();
449
+ let value = line.slice(colonIndex + 1).trim();
450
+ if (value === "|") {
451
+ const blockLines = [];
452
+ i++;
453
+ while (i < lines.length) {
454
+ const blockLine = lines[i];
455
+ if (blockLine.length > 0 && !blockLine.startsWith(" ") && !blockLine.startsWith(" ")) {
456
+ break;
457
+ }
458
+ blockLines.push(blockLine);
459
+ i++;
460
+ }
461
+ const minIndent = blockLines.filter((l) => l.trim().length > 0).reduce((min, l) => {
462
+ const indent = l.match(/^(\s*)/)?.[1].length ?? 0;
463
+ return Math.min(min, indent);
464
+ }, Infinity);
465
+ result[key] = blockLines.map((l) => l.trim().length === 0 ? "" : l.slice(minIndent)).join("\n").trim();
466
+ continue;
467
+ }
468
+ if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
469
+ value = value.slice(1, -1);
470
+ }
471
+ if (key.length > 0) {
472
+ result[key] = value;
473
+ }
474
+ i++;
475
+ }
476
+ return result;
477
+ }
478
+ function parseMarkdownSubAgentRole(content, filePath) {
479
+ const match = content.match(FRONTMATTER_REGEX);
480
+ if (!match) {
481
+ return null;
482
+ }
483
+ const [, rawFrontmatter, body] = match;
484
+ const fields = parseSubAgentRoleFrontmatter(rawFrontmatter);
485
+ if (!fields.name || !fields.description) {
486
+ return null;
487
+ }
488
+ const frontmatter = {
489
+ name: fields.name,
490
+ description: fields.description
491
+ };
492
+ if (fields.profile) frontmatter.profile = fields.profile;
493
+ if (fields.extends) frontmatter.extends = fields.extends;
494
+ if (fields.model) frontmatter.model = fields.model;
495
+ if (fields.maxSteps) frontmatter.maxSteps = fields.maxSteps;
496
+ if (fields.temperature) frontmatter.temperature = fields.temperature;
497
+ if (fields.reasoning) frontmatter.reasoning = fields.reasoning;
498
+ if (fields.tools) frontmatter.tools = fields.tools;
499
+ if (fields.skills) frontmatter.skills = fields.skills;
500
+ if (fields.allowFurtherDispatch) {
501
+ frontmatter.allowFurtherDispatch = fields.allowFurtherDispatch;
502
+ }
503
+ return {
504
+ frontmatter,
505
+ body: body.trim(),
506
+ filePath
507
+ };
508
+ }
509
+ function normalizeToolPattern(pattern) {
510
+ return pattern.trim();
511
+ }
512
+ function parseSubAgentToolSpec(raw) {
513
+ if (!raw || raw.trim().length === 0) {
514
+ return { mode: "inherit" };
515
+ }
516
+ const parts = raw.split(",").map((part) => part.trim()).filter(Boolean);
517
+ if (parts.length === 0) {
518
+ return { mode: "inherit" };
519
+ }
520
+ const hasModified = parts.some((part) => part.startsWith("+") || part.startsWith("-"));
521
+ if (hasModified) {
522
+ return {
523
+ mode: "modifiers",
524
+ modifiers: parts.map((part) => ({
525
+ kind: part.startsWith("-") ? "remove" : "add",
526
+ pattern: normalizeToolPattern(
527
+ part.startsWith("+") || part.startsWith("-") ? part.slice(1) : part
528
+ )
529
+ }))
530
+ };
531
+ }
532
+ return {
533
+ mode: "explicit",
534
+ patterns: parts.map(normalizeToolPattern)
535
+ };
536
+ }
537
+ function toSubAgentRole(parsed, resolvers = {}) {
538
+ const { frontmatter } = parsed;
539
+ const parent = frontmatter.extends ? resolvers.resolveParent?.(frontmatter.extends) : void 0;
540
+ const profile = frontmatter.profile ? resolvers.resolveProfile?.(frontmatter.profile) : parent?.profile;
541
+ const systemPrompt = parsed.body.length > 0 ? parent?.systemPrompt ? parsed.body.replaceAll("{basePrompt}", parent.systemPrompt) : parsed.body : parent?.systemPrompt;
542
+ const maxSteps = frontmatter.maxSteps ? parseInt(frontmatter.maxSteps, 10) : parent?.maxSteps;
543
+ let resolvedProfile = profile;
544
+ const temperature = frontmatter.temperature ? parseFloat(frontmatter.temperature) : void 0;
545
+ const reasoning = frontmatter.reasoning;
546
+ if (temperature !== void 0 || reasoning !== void 0) {
547
+ resolvedProfile = {
548
+ ...profile ?? { name: "custom", description: "Markdown-defined role" },
549
+ ...temperature !== void 0 ? { temperature } : {},
550
+ ...reasoning !== void 0 && VALID_REASONING_LEVELS.has(reasoning) ? { reasoningLevel: reasoning } : {}
551
+ };
552
+ }
553
+ const toolSpec = parseSubAgentToolSpec(frontmatter.tools);
554
+ if (toolSpec.mode === "explicit" || toolSpec.mode === "modifiers") {
555
+ resolvedProfile = {
556
+ ...resolvedProfile ?? { name: "custom", description: "Markdown-defined role" }
557
+ };
558
+ if (toolSpec.mode === "explicit") {
559
+ resolvedProfile.allowTools = toolSpec.patterns;
560
+ resolvedProfile.denyTools = void 0;
561
+ } else {
562
+ const baseAllow = [...resolvedProfile.allowTools ?? []];
563
+ const baseDeny = [...resolvedProfile.denyTools ?? []];
564
+ for (const mod of toolSpec.modifiers) {
565
+ if (mod.kind === "add") {
566
+ baseAllow.push(mod.pattern);
567
+ const denyIdx = baseDeny.indexOf(mod.pattern);
568
+ if (denyIdx !== -1) baseDeny.splice(denyIdx, 1);
569
+ } else {
570
+ baseDeny.push(mod.pattern);
571
+ const allowIdx = baseAllow.indexOf(mod.pattern);
572
+ if (allowIdx !== -1) baseAllow.splice(allowIdx, 1);
573
+ }
574
+ }
575
+ if (baseAllow.length > 0) resolvedProfile.allowTools = baseAllow;
576
+ if (baseDeny.length > 0) resolvedProfile.denyTools = baseDeny;
577
+ }
578
+ }
579
+ const allowFurtherDispatch = frontmatter.allowFurtherDispatch ? frontmatter.allowFurtherDispatch === "true" : parent?.allowFurtherDispatch;
580
+ const role = {
581
+ name: frontmatter.name,
582
+ description: frontmatter.description
583
+ };
584
+ if (resolvedProfile) role.profile = resolvedProfile;
585
+ if (systemPrompt) role.systemPrompt = systemPrompt;
586
+ if (maxSteps !== void 0 && !isNaN(maxSteps)) role.maxSteps = maxSteps;
587
+ if (allowFurtherDispatch !== void 0) {
588
+ role.allowFurtherDispatch = allowFurtherDispatch;
589
+ }
590
+ if (frontmatter.model) {
591
+ role._modelId = frontmatter.model;
592
+ }
593
+ if (frontmatter.skills) {
594
+ role._skillNames = frontmatter.skills.split(",").map((s) => s.trim()).filter(Boolean);
595
+ }
596
+ role._source = parsed.filePath;
597
+ return role;
598
+ }
599
+ function isMarkdownSubAgentRole(role) {
600
+ return "_source" in role;
601
+ }
602
+
603
+ // src/subagents/roles/discovery.ts
604
+ var DEFAULT_USER_DIR = join(homedir(), ".cuylabs", "agents");
605
+ var DEFAULT_PROJECT_DIR = ".cuylabs/agents";
606
+ var PRESET_MAP = {
607
+ explore: Profiles.explore,
608
+ plan: Profiles.plan,
609
+ review: Profiles.review,
610
+ quick: Profiles.quick,
611
+ careful: Profiles.careful,
612
+ code: Profiles.code,
613
+ watch: Profiles.watch
614
+ };
615
+ function defaultResolveProfile(name) {
616
+ return PRESET_MAP[name.toLowerCase()];
617
+ }
618
+ function isLoadableMarkdown(filename) {
619
+ return filename.endsWith(".md") && !filename.startsWith("_") && !filename.startsWith(".");
620
+ }
621
+ function loadRoleDir(dir, source, resolvers, errors, onRole) {
622
+ if (!existsSync(dir)) return [];
623
+ let stat;
624
+ try {
625
+ stat = statSync(dir);
626
+ } catch {
627
+ return [];
628
+ }
629
+ if (!stat.isDirectory()) return [];
630
+ const results = [];
631
+ let entries;
632
+ try {
633
+ entries = readdirSync(dir, { withFileTypes: true });
634
+ } catch {
635
+ return [];
636
+ }
637
+ entries.sort((left, right) => left.name.localeCompare(right.name));
638
+ for (const entry of entries) {
639
+ if (!entry.isFile() && !entry.isSymbolicLink()) continue;
640
+ if (!isLoadableMarkdown(entry.name)) continue;
641
+ const filePath = join(dir, entry.name);
642
+ try {
643
+ const content = readFileSync(filePath, "utf-8");
644
+ const parsed = parseMarkdownSubAgentRole(content, filePath);
645
+ if (!parsed) {
646
+ errors.push({ path: filePath, error: "Missing required frontmatter (name, description)" });
647
+ continue;
648
+ }
649
+ const role = toSubAgentRole(parsed, resolvers);
650
+ const discovered = { role, source, filePath };
651
+ results.push(discovered);
652
+ onRole?.(discovered);
653
+ } catch (err) {
654
+ errors.push({
655
+ path: filePath,
656
+ error: err instanceof Error ? err.message : String(err)
657
+ });
658
+ }
659
+ }
660
+ return results;
661
+ }
662
+ function loadRoleFile(filePath, source, resolvers, errors, onRole) {
663
+ if (!existsSync(filePath)) {
664
+ errors.push({ path: filePath, error: "File not found" });
665
+ return null;
666
+ }
667
+ try {
668
+ const content = readFileSync(filePath, "utf-8");
669
+ const parsed = parseMarkdownSubAgentRole(content, filePath);
670
+ if (!parsed) {
671
+ errors.push({ path: filePath, error: "Missing required frontmatter (name, description)" });
672
+ return null;
673
+ }
674
+ const role = toSubAgentRole(parsed, resolvers);
675
+ const discovered = { role, source, filePath };
676
+ onRole?.(discovered);
677
+ return discovered;
678
+ } catch (err) {
679
+ errors.push({
680
+ path: filePath,
681
+ error: err instanceof Error ? err.message : String(err)
682
+ });
683
+ return null;
684
+ }
685
+ }
686
+ function getUserSubAgentRolesDir(userDir = DEFAULT_USER_DIR) {
687
+ return userDir;
688
+ }
689
+ function getProjectSubAgentRolesDir(cwd, projectDir = DEFAULT_PROJECT_DIR) {
690
+ return resolve(cwd, projectDir);
691
+ }
692
+ function discoverSubAgentRoles(options) {
693
+ const errors = [];
694
+ const discovered = [];
695
+ const merged = /* @__PURE__ */ new Map();
696
+ const builtInRoles = options.builtInRoles ?? [];
697
+ for (const role of builtInRoles) {
698
+ discovered.push({ role, source: "builtin" });
699
+ merged.set(role.name, role);
700
+ }
701
+ const roleIndex = new Map(
702
+ builtInRoles.map((role) => [role.name, role])
703
+ );
704
+ const resolveProfile = options.resolveProfile ?? defaultResolveProfile;
705
+ const resolvers = {
706
+ resolveProfile,
707
+ resolveParent: (name) => roleIndex.get(name)
708
+ };
709
+ const register = (entry) => {
710
+ discovered.push(entry);
711
+ merged.set(entry.role.name, entry.role);
712
+ roleIndex.set(entry.role.name, entry.role);
713
+ };
714
+ loadRoleDir(
715
+ getUserSubAgentRolesDir(options.userDir),
716
+ "user",
717
+ resolvers,
718
+ errors,
719
+ register
720
+ );
721
+ loadRoleDir(
722
+ getProjectSubAgentRolesDir(options.cwd, options.projectDir),
723
+ "project",
724
+ resolvers,
725
+ errors,
726
+ register
727
+ );
728
+ for (const configPath of options.configPaths ?? []) {
729
+ const fullPath = isAbsolute(configPath) ? configPath : resolve(options.cwd, configPath);
730
+ const stat = existsSync(fullPath) ? statSync(fullPath) : void 0;
731
+ if (stat?.isDirectory()) {
732
+ loadRoleDir(fullPath, "config", resolvers, errors, register);
733
+ } else {
734
+ loadRoleFile(fullPath, "config", resolvers, errors, register);
735
+ }
736
+ }
737
+ return {
738
+ roles: [...merged.values()],
739
+ discovered,
740
+ errors
741
+ };
742
+ }
743
+
744
+ export {
745
+ DEFAULT_SUBAGENT_CONCURRENCY,
746
+ DEFAULT_SUBAGENT_DEPTH,
747
+ DEFAULT_SUBAGENT_SESSION_PREFIX,
748
+ formatInvalidAgentTypeResult,
749
+ formatSpawnBlockedResult,
750
+ formatSyncSubAgentResult,
751
+ formatSyncSubAgentErrorResult,
752
+ formatAsyncSpawnedResult,
753
+ formatWaitResult,
754
+ formatWaitTimeoutResult,
755
+ formatWaitErrorResult,
756
+ formatMissingAgentsResult,
757
+ formatCloseMissingAgentResult,
758
+ formatCloseAlreadyResolvedResult,
759
+ formatCancelledAgentResult,
760
+ SUBAGENT_TOOL_IDS,
761
+ createInvokeAgentTool,
762
+ createWaitAgentTool,
763
+ createCloseAgentTool,
764
+ createSubAgentTools,
765
+ LOCAL_SUBAGENT_BACKEND,
766
+ configureSubAgents,
767
+ getConfiguredSubAgents,
768
+ getInstalledSubAgentBackend,
769
+ clearInstalledSubAgents,
770
+ installSubAgentTools,
771
+ installLocalSubAgents,
772
+ parseSubAgentRoleFrontmatter,
773
+ parseMarkdownSubAgentRole,
774
+ parseSubAgentToolSpec,
775
+ toSubAgentRole,
776
+ isMarkdownSubAgentRole,
777
+ getUserSubAgentRolesDir,
778
+ getProjectSubAgentRolesDir,
779
+ discoverSubAgentRoles
780
+ };