@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,602 @@
1
+ import {
2
+ Tool
3
+ } from "./chunk-Q742PSH3.js";
4
+ import {
5
+ buildEntryPath,
6
+ deserializeMessage
7
+ } from "./chunk-ICZ66572.js";
8
+
9
+ // src/agent/session.ts
10
+ async function ensureSessionLoaded(options) {
11
+ const { sessionId, sessions, cwd } = options;
12
+ if (sessions.getSessionId() === sessionId) {
13
+ return;
14
+ }
15
+ const exists = await sessions.sessionExists(sessionId);
16
+ if (exists) {
17
+ await sessions.load(sessionId);
18
+ } else {
19
+ await sessions.create({ id: sessionId, cwd });
20
+ }
21
+ }
22
+ async function repairOrphanedToolCalls(sessions) {
23
+ const messages = sessions.getMessages();
24
+ const pendingCallIds = /* @__PURE__ */ new Map();
25
+ for (const message of messages) {
26
+ if (message.role === "assistant" && message.toolCalls) {
27
+ for (const toolCall of message.toolCalls) {
28
+ pendingCallIds.set(toolCall.toolCallId, { toolName: toolCall.toolName });
29
+ }
30
+ }
31
+ if (message.role === "tool" && message.toolCallId) {
32
+ pendingCallIds.delete(message.toolCallId);
33
+ }
34
+ }
35
+ for (const [toolCallId, { toolName }] of pendingCallIds) {
36
+ const toolMessage = {
37
+ id: crypto.randomUUID(),
38
+ role: "tool",
39
+ content: "Error: tool execution failed (result was not recorded)",
40
+ toolCallId,
41
+ toolName,
42
+ result: "Error: tool execution failed (result was not recorded)",
43
+ createdAt: /* @__PURE__ */ new Date()
44
+ };
45
+ await sessions.addMessage(toolMessage);
46
+ }
47
+ }
48
+ async function createSubAgentRunSession(options) {
49
+ const sessionId = options.parentSessionId ? `${options.parentSessionId}:sub:${crypto.randomUUID().slice(0, 8)}` : `sub:${crypto.randomUUID().slice(0, 8)}`;
50
+ await options.sessions.create({
51
+ id: sessionId,
52
+ cwd: options.cwd,
53
+ title: options.title ?? "Sub-agent task",
54
+ parentSessionId: options.parentSessionId
55
+ });
56
+ return sessionId;
57
+ }
58
+ function getVisibleSessionMessages(sessions) {
59
+ const leafId = sessions.getLeafId();
60
+ if (!leafId) {
61
+ return [];
62
+ }
63
+ const path = buildEntryPath(
64
+ sessions.getEntries(),
65
+ leafId
66
+ );
67
+ const visible = [];
68
+ let skipUntilId;
69
+ for (const entry of path) {
70
+ if (entry.type === "compaction") {
71
+ visible.push({
72
+ id: entry.id,
73
+ role: "system",
74
+ content: `## Previous Conversation Summary
75
+
76
+ ${entry.summary}`,
77
+ createdAt: new Date(entry.timestamp)
78
+ });
79
+ skipUntilId = entry.firstKeptEntryId !== entry.id ? entry.firstKeptEntryId : void 0;
80
+ continue;
81
+ }
82
+ if (skipUntilId && entry.id !== skipUntilId) {
83
+ continue;
84
+ }
85
+ if (entry.id === skipUntilId) {
86
+ skipUntilId = void 0;
87
+ }
88
+ if (entry.type === "message") {
89
+ visible.push(deserializeMessage(entry.message));
90
+ }
91
+ }
92
+ return visible;
93
+ }
94
+
95
+ // src/dispatch/types.ts
96
+ var DISPATCH_STATES = [
97
+ "running",
98
+ "completed",
99
+ "failed",
100
+ "cancelled"
101
+ ];
102
+ var DEFAULT_DISPATCH_TOOL_IDS = [
103
+ "start_dispatch",
104
+ "check_dispatch",
105
+ "redirect_dispatch",
106
+ "cancel_dispatch",
107
+ "list_dispatches"
108
+ ];
109
+ var DEFAULT_LOCAL_DISPATCH_CONCURRENCY = 6;
110
+ var DEFAULT_LOCAL_DISPATCH_DEPTH = 2;
111
+ var DEFAULT_LOCAL_DISPATCH_TITLE_PREFIX = "Dispatch";
112
+
113
+ // src/dispatch/tool-factories.ts
114
+ import { z } from "zod";
115
+
116
+ // src/dispatch/results.ts
117
+ function formatStatus(record) {
118
+ const parts = [
119
+ `ID: ${record.id}`,
120
+ `Target: ${record.targetType}`,
121
+ `Status: ${record.status}`
122
+ ];
123
+ if (record.title) {
124
+ parts.push(`Title: ${record.title}`);
125
+ }
126
+ if (record.sessionId) {
127
+ parts.push(`Session: ${record.sessionId}`);
128
+ }
129
+ if (record.redirectCount > 0) {
130
+ parts.push(`Redirects: ${record.redirectCount}`);
131
+ }
132
+ if (record.result) {
133
+ parts.push(`Response: ${record.result.response}`);
134
+ }
135
+ if (record.error) {
136
+ parts.push(`Error: ${record.error}`);
137
+ }
138
+ return parts.join("\n");
139
+ }
140
+ function formatDispatchStarted(record) {
141
+ return {
142
+ title: `Dispatch started: ${record.targetType}`,
143
+ output: `Dispatch started successfully.
144
+
145
+ ` + formatStatus(record) + `
146
+
147
+ Use \`check_dispatch\` with ID "${record.id}" to monitor progress.`,
148
+ metadata: {
149
+ dispatchId: record.id,
150
+ targetType: record.targetType,
151
+ sessionId: record.sessionId
152
+ }
153
+ };
154
+ }
155
+ function formatDispatchChecked(record) {
156
+ return {
157
+ title: `Dispatch ${record.status}: ${record.targetType}`,
158
+ output: formatStatus(record),
159
+ metadata: {
160
+ dispatchId: record.id,
161
+ targetType: record.targetType,
162
+ status: record.status
163
+ }
164
+ };
165
+ }
166
+ function formatDispatchRedirected(record) {
167
+ return {
168
+ title: `Dispatch redirected: ${record.targetType}`,
169
+ output: `Dispatch "${record.id}" has been redirected.
170
+
171
+ ` + formatStatus(record),
172
+ metadata: {
173
+ dispatchId: record.id,
174
+ targetType: record.targetType,
175
+ redirectCount: record.redirectCount
176
+ }
177
+ };
178
+ }
179
+ function formatDispatchCancelled(record) {
180
+ return {
181
+ title: `Dispatch cancelled: ${record.targetType}`,
182
+ output: `Dispatch "${record.id}" has been cancelled.
183
+
184
+ ` + formatStatus(record),
185
+ metadata: {
186
+ dispatchId: record.id,
187
+ targetType: record.targetType
188
+ }
189
+ };
190
+ }
191
+ function formatDispatchList(records) {
192
+ if (records.length === 0) {
193
+ return {
194
+ title: "No dispatches",
195
+ output: "No dispatches match the given criteria.",
196
+ metadata: { count: 0 }
197
+ };
198
+ }
199
+ const lines = records.map(
200
+ (record) => `- ${record.id} [${record.status}] ${record.targetType}: ${record.title || record.brief}`
201
+ );
202
+ return {
203
+ title: `${records.length} dispatch(es)`,
204
+ output: lines.join("\n"),
205
+ metadata: { count: records.length }
206
+ };
207
+ }
208
+ function formatDispatchError(label, error) {
209
+ return {
210
+ title: "Dispatch error",
211
+ output: `${label}: ` + (error instanceof Error ? error.message : String(error)),
212
+ metadata: { error: true }
213
+ };
214
+ }
215
+
216
+ // src/dispatch/tool-factories.ts
217
+ function buildTargetDescription(targets) {
218
+ const list = targets.map((target) => ` - "${target.name}": ${target.description}`).join("\n");
219
+ return `Available targets:
220
+ ${list}`;
221
+ }
222
+ function createDispatchStartTool(runtime) {
223
+ const targets = runtime.describeTargets();
224
+ const targetNames = targets.map((target) => target.name);
225
+ return Tool.define("start_dispatch", {
226
+ description: `Start a new background dispatch.
227
+
228
+ ` + buildTargetDescription(targets) + `
229
+
230
+ Use \`check_dispatch\` to monitor progress after starting.`,
231
+ parameters: z.object({
232
+ targetType: z.string().describe(
233
+ `The target to dispatch to. Must be one of: ${targetNames.join(", ")}`
234
+ ),
235
+ brief: z.string().describe("Detailed instructions for the dispatch target."),
236
+ title: z.string().optional().describe("Short title for tracking."),
237
+ parentSessionId: z.string().optional().describe("Parent session ID for context linking.")
238
+ }),
239
+ execute: async (params) => {
240
+ try {
241
+ const record = await runtime.start({
242
+ targetType: params.targetType,
243
+ brief: params.brief,
244
+ title: params.title,
245
+ parentSessionId: params.parentSessionId
246
+ });
247
+ return formatDispatchStarted(record);
248
+ } catch (error) {
249
+ return formatDispatchError("Failed to start dispatch", error);
250
+ }
251
+ }
252
+ });
253
+ }
254
+ function createDispatchCheckTool(runtime) {
255
+ return Tool.define("check_dispatch", {
256
+ description: "Check the status of a running dispatch. Returns current status, and result or error if completed or failed.",
257
+ parameters: z.object({
258
+ id: z.string().describe("The dispatch ID to check."),
259
+ waitMs: z.number().optional().describe("Optional time to wait for completion (milliseconds).")
260
+ }),
261
+ execute: async (params) => {
262
+ try {
263
+ const record = await runtime.check(params.id, {
264
+ waitMs: params.waitMs
265
+ });
266
+ if (!record) {
267
+ return formatDispatchError(
268
+ "Dispatch not found",
269
+ new Error(`No dispatch with ID "${params.id}".`)
270
+ );
271
+ }
272
+ return formatDispatchChecked(record);
273
+ } catch (error) {
274
+ return formatDispatchError("Failed to inspect dispatch", error);
275
+ }
276
+ }
277
+ });
278
+ }
279
+ function createDispatchRedirectTool(runtime) {
280
+ return Tool.define("redirect_dispatch", {
281
+ description: "Send a steering message to a running dispatch. Use this to narrow scope, add context, or change direction mid-run.",
282
+ parameters: z.object({
283
+ id: z.string().describe("The dispatch ID to redirect."),
284
+ message: z.string().describe("The steering message.")
285
+ }),
286
+ execute: async (params) => {
287
+ try {
288
+ const record = await runtime.redirect(params.id, params.message);
289
+ return formatDispatchRedirected(record);
290
+ } catch (error) {
291
+ return formatDispatchError("Failed to redirect dispatch", error);
292
+ }
293
+ }
294
+ });
295
+ }
296
+ function createDispatchCancelTool(runtime) {
297
+ return Tool.define("cancel_dispatch", {
298
+ description: "Cancel a running dispatch. Use when the result is no longer needed.",
299
+ parameters: z.object({
300
+ id: z.string().describe("The dispatch ID to cancel."),
301
+ reason: z.string().optional().describe("Reason for cancellation.")
302
+ }),
303
+ execute: async (params) => {
304
+ try {
305
+ const record = await runtime.cancel(params.id, params.reason);
306
+ return formatDispatchCancelled(record);
307
+ } catch (error) {
308
+ return formatDispatchError("Failed to cancel dispatch", error);
309
+ }
310
+ }
311
+ });
312
+ }
313
+ function createDispatchListTool(runtime) {
314
+ return Tool.define("list_dispatches", {
315
+ description: "List dispatches, optionally filtered by status, target type, or parent session.",
316
+ parameters: z.object({
317
+ status: z.string().optional().describe(
318
+ 'Filter by status: "running", "completed", "failed", "cancelled".'
319
+ ),
320
+ targetType: z.string().optional().describe("Filter by target type."),
321
+ parentSessionId: z.string().optional().describe("Filter by parent session.")
322
+ }),
323
+ execute: async (params) => {
324
+ try {
325
+ const records = await runtime.list({
326
+ status: params.status,
327
+ targetType: params.targetType,
328
+ parentSessionId: params.parentSessionId
329
+ });
330
+ return formatDispatchList(records);
331
+ } catch (error) {
332
+ return formatDispatchError("Failed to list dispatches", error);
333
+ }
334
+ }
335
+ });
336
+ }
337
+
338
+ // src/dispatch/tools.ts
339
+ function createDispatchTools(runtime) {
340
+ return [
341
+ createDispatchStartTool(runtime),
342
+ createDispatchCheckTool(runtime),
343
+ createDispatchRedirectTool(runtime),
344
+ createDispatchCancelTool(runtime),
345
+ createDispatchListTool(runtime)
346
+ ];
347
+ }
348
+
349
+ // src/dispatch/runtime.ts
350
+ import { randomUUID } from "crypto";
351
+ function allowsFurtherDispatch(role) {
352
+ return role.allowFurtherDispatch ?? false;
353
+ }
354
+ function buildRoleChild(parent, role) {
355
+ const forkOptions = {};
356
+ if (role.profile) {
357
+ forkOptions.profile = role.profile;
358
+ }
359
+ if (role.systemPrompt) {
360
+ forkOptions.systemPrompt = role.systemPrompt;
361
+ }
362
+ if (role.model) {
363
+ forkOptions.model = role.model;
364
+ }
365
+ if (role.maxSteps) {
366
+ forkOptions.maxSteps = role.maxSteps;
367
+ }
368
+ if (role.additionalMiddleware) {
369
+ forkOptions.additionalMiddleware = role.additionalMiddleware;
370
+ }
371
+ if (role.additionalTools && role.additionalTools.length > 0) {
372
+ const profileChild = parent.fork(forkOptions);
373
+ forkOptions.tools = [...profileChild.getTools(), ...role.additionalTools];
374
+ return parent.fork(forkOptions);
375
+ }
376
+ return parent.fork(forkOptions);
377
+ }
378
+ function createLocalDispatchRuntime(options) {
379
+ const {
380
+ parent,
381
+ roles,
382
+ maxConcurrent = DEFAULT_LOCAL_DISPATCH_CONCURRENCY,
383
+ maxDepth = DEFAULT_LOCAL_DISPATCH_DEPTH,
384
+ currentDepth = 0,
385
+ sessionTitlePrefix = DEFAULT_LOCAL_DISPATCH_TITLE_PREFIX,
386
+ now = () => (/* @__PURE__ */ new Date()).toISOString(),
387
+ createId = () => randomUUID(),
388
+ childToolIds = DEFAULT_DISPATCH_TOOL_IDS,
389
+ createChildTools = createDispatchTools,
390
+ buildChild: customBuildChild
391
+ } = options;
392
+ const dispatches = /* @__PURE__ */ new Map();
393
+ const roleIndex = new Map(roles.map((role) => [role.name, role]));
394
+ function buildChild(role) {
395
+ const child = customBuildChild ? customBuildChild(parent, role) : buildRoleChild(parent, role);
396
+ for (const toolId of childToolIds) {
397
+ child.removeTool?.(toolId);
398
+ }
399
+ if (allowsFurtherDispatch(role) && currentDepth + 1 < maxDepth) {
400
+ const childRuntime = createLocalDispatchRuntime({
401
+ parent: child,
402
+ roles,
403
+ maxConcurrent,
404
+ maxDepth,
405
+ currentDepth: currentDepth + 1,
406
+ sessionTitlePrefix,
407
+ now,
408
+ createId,
409
+ childToolIds,
410
+ createChildTools,
411
+ buildChild: customBuildChild
412
+ });
413
+ for (const tool of createChildTools(childRuntime)) {
414
+ child.addTool(tool);
415
+ }
416
+ }
417
+ return child;
418
+ }
419
+ function describeTargets() {
420
+ return roles.map((role) => ({
421
+ name: role.name,
422
+ description: role.description
423
+ }));
424
+ }
425
+ async function start(input) {
426
+ const role = roleIndex.get(input.targetType);
427
+ if (!role) {
428
+ throw new Error(
429
+ `Unknown dispatch target "${input.targetType}". Available: ${[...roleIndex.keys()].join(", ")}`
430
+ );
431
+ }
432
+ if (currentDepth >= maxDepth) {
433
+ throw new Error(
434
+ `Dispatch depth limit reached (${currentDepth}/${maxDepth}). Cannot create further child dispatches.`
435
+ );
436
+ }
437
+ const runningCount = [...dispatches.values()].filter(
438
+ (d) => d.record.status === "running"
439
+ ).length;
440
+ if (runningCount >= maxConcurrent) {
441
+ throw new Error(
442
+ `Concurrency limit reached (${runningCount}/${maxConcurrent}). Cancel or wait for running dispatches.`
443
+ );
444
+ }
445
+ const id = createId();
446
+ const child = buildChild(role);
447
+ const abort = new AbortController();
448
+ const timestamp = now();
449
+ const title = input.title ?? `${sessionTitlePrefix}: ${role.name}`;
450
+ if (input.abort) {
451
+ if (input.abort.aborted) {
452
+ abort.abort(input.abort.reason);
453
+ } else {
454
+ input.abort.addEventListener(
455
+ "abort",
456
+ () => abort.abort(input.abort?.reason),
457
+ { once: true }
458
+ );
459
+ }
460
+ }
461
+ const sessionId = await createSubAgentRunSession({
462
+ sessions: child.getSessionManager(),
463
+ cwd: child.cwd,
464
+ parentSessionId: input.parentSessionId,
465
+ title
466
+ });
467
+ const record = {
468
+ id,
469
+ targetType: input.targetType,
470
+ title,
471
+ brief: input.brief,
472
+ status: "running",
473
+ createdAt: timestamp,
474
+ updatedAt: timestamp,
475
+ parentSessionId: input.parentSessionId,
476
+ sessionId,
477
+ executionId: id,
478
+ redirectCount: 0
479
+ };
480
+ const promise = (async () => {
481
+ try {
482
+ const result = await child.send(sessionId, input.brief, {
483
+ abort: abort.signal
484
+ });
485
+ const active = dispatches.get(id);
486
+ if (active && active.record.status === "running") {
487
+ active.record.status = "completed";
488
+ active.record.updatedAt = now();
489
+ active.record.result = {
490
+ response: result.response,
491
+ usage: {
492
+ inputTokens: result.usage?.inputTokens ?? 0,
493
+ outputTokens: result.usage?.outputTokens ?? 0,
494
+ totalTokens: result.usage?.totalTokens ?? 0
495
+ },
496
+ toolCalls: result.toolCalls ?? []
497
+ };
498
+ }
499
+ } catch (error) {
500
+ const active = dispatches.get(id);
501
+ if (active && active.record.status === "running") {
502
+ if (abort.signal.aborted) {
503
+ active.record.status = "cancelled";
504
+ } else {
505
+ active.record.status = "failed";
506
+ active.record.error = error instanceof Error ? error.message : String(error);
507
+ }
508
+ active.record.updatedAt = now();
509
+ }
510
+ }
511
+ })();
512
+ dispatches.set(id, { record, child, abort, promise });
513
+ return { ...record };
514
+ }
515
+ async function check(id, options2) {
516
+ const active = dispatches.get(id);
517
+ if (!active) {
518
+ return void 0;
519
+ }
520
+ if (active.record.status === "running" && options2?.waitMs) {
521
+ await Promise.race([
522
+ active.promise,
523
+ new Promise(
524
+ (resolve) => setTimeout(resolve, options2.waitMs)
525
+ )
526
+ ]);
527
+ }
528
+ return { ...active.record };
529
+ }
530
+ async function redirect(id, message) {
531
+ const active = dispatches.get(id);
532
+ if (!active) {
533
+ throw new Error(`No dispatch with ID "${id}".`);
534
+ }
535
+ if (active.record.status !== "running") {
536
+ throw new Error(
537
+ `Cannot redirect dispatch "${id}" \u2014 status is "${active.record.status}".`
538
+ );
539
+ }
540
+ active.child.intervene(message);
541
+ active.record.redirectCount += 1;
542
+ active.record.lastRedirect = message;
543
+ active.record.updatedAt = now();
544
+ return { ...active.record };
545
+ }
546
+ async function cancel(id, reason) {
547
+ const active = dispatches.get(id);
548
+ if (!active) {
549
+ throw new Error(`No dispatch with ID "${id}".`);
550
+ }
551
+ if (active.record.status !== "running") {
552
+ return { ...active.record };
553
+ }
554
+ active.abort.abort(reason ?? "Cancelled");
555
+ active.record.status = "cancelled";
556
+ active.record.updatedAt = now();
557
+ if (reason) {
558
+ active.record.error = reason;
559
+ }
560
+ return { ...active.record };
561
+ }
562
+ async function list(options2) {
563
+ let records = [...dispatches.values()].map((d) => ({ ...d.record }));
564
+ if (options2?.status) {
565
+ const statuses = Array.isArray(options2.status) ? options2.status : [options2.status];
566
+ records = records.filter(
567
+ (r) => statuses.includes(r.status)
568
+ );
569
+ }
570
+ if (options2?.targetType) {
571
+ records = records.filter((r) => r.targetType === options2.targetType);
572
+ }
573
+ if (options2?.parentSessionId) {
574
+ records = records.filter(
575
+ (r) => r.parentSessionId === options2.parentSessionId
576
+ );
577
+ }
578
+ return records;
579
+ }
580
+ return {
581
+ describeTargets,
582
+ start,
583
+ check,
584
+ redirect,
585
+ cancel,
586
+ list
587
+ };
588
+ }
589
+
590
+ export {
591
+ ensureSessionLoaded,
592
+ repairOrphanedToolCalls,
593
+ createSubAgentRunSession,
594
+ getVisibleSessionMessages,
595
+ DISPATCH_STATES,
596
+ DEFAULT_DISPATCH_TOOL_IDS,
597
+ DEFAULT_LOCAL_DISPATCH_CONCURRENCY,
598
+ DEFAULT_LOCAL_DISPATCH_DEPTH,
599
+ DEFAULT_LOCAL_DISPATCH_TITLE_PREFIX,
600
+ createDispatchTools,
601
+ createLocalDispatchRuntime
602
+ };
@@ -0,0 +1,8 @@
1
+ // src/utils/sleep.ts
2
+ function sleep(ms) {
3
+ return new Promise((resolve) => setTimeout(resolve, ms));
4
+ }
5
+
6
+ export {
7
+ sleep
8
+ };