@cuylabs/agent-core 5.4.0 → 5.6.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 (39) hide show
  1. package/dist/agent/chat-loop/loop.d.ts.map +1 -1
  2. package/dist/agent/chat-loop/model-step-runner.d.ts +2 -0
  3. package/dist/agent/chat-loop/model-step-runner.d.ts.map +1 -1
  4. package/dist/{chunk-JZRLCTSD.js → chunk-2BRLPF3Z.js} +73 -2
  5. package/dist/{chunk-VT5FSYA2.js → chunk-NICU5N2S.js} +105 -14
  6. package/dist/{chunk-35A3XLI4.js → chunk-SJCAIWLZ.js} +23 -4
  7. package/dist/{chunk-MO7V4H4A.js → chunk-ZETYNQ35.js} +296 -16
  8. package/dist/dispatch/event-store.d.ts +15 -0
  9. package/dist/dispatch/event-store.d.ts.map +1 -0
  10. package/dist/dispatch/executor.d.ts.map +1 -1
  11. package/dist/dispatch/index.d.ts +2 -1
  12. package/dist/dispatch/index.d.ts.map +1 -1
  13. package/dist/dispatch/index.js +4 -2
  14. package/dist/dispatch/runtime.d.ts.map +1 -1
  15. package/dist/dispatch/tool-factories.d.ts.map +1 -1
  16. package/dist/dispatch/types.d.ts +68 -0
  17. package/dist/dispatch/types.d.ts.map +1 -1
  18. package/dist/execution/index.js +1 -1
  19. package/dist/execution/turn/index.d.ts +2 -2
  20. package/dist/execution/turn/index.d.ts.map +1 -1
  21. package/dist/execution/turn/index.js +3 -1
  22. package/dist/execution/turn/runner/index.d.ts +2 -0
  23. package/dist/execution/turn/runner/index.d.ts.map +1 -1
  24. package/dist/execution/turn/runner/live-events.d.ts +11 -0
  25. package/dist/execution/turn/runner/live-events.d.ts.map +1 -0
  26. package/dist/execution/turn/runner/stream-step.d.ts.map +1 -1
  27. package/dist/execution/turn/runner/tool-batch.d.ts.map +1 -1
  28. package/dist/execution/turn/runner/types.d.ts +4 -0
  29. package/dist/execution/turn/runner/types.d.ts.map +1 -1
  30. package/dist/index.js +57 -8
  31. package/dist/subagents/index.js +2 -2
  32. package/dist/subagents/results.d.ts.map +1 -1
  33. package/dist/subagents/roles/markdown-profile.d.ts.map +1 -1
  34. package/dist/subagents/tool-factories.d.ts.map +1 -1
  35. package/dist/team/coordinator/types.d.ts +2 -0
  36. package/dist/team/coordinator/types.d.ts.map +1 -1
  37. package/dist/types/events.d.ts +32 -1
  38. package/dist/types/events.d.ts.map +1 -1
  39. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"loop.d.ts","sourceRoot":"","sources":["../../../src/agent/chat-loop/loop.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAiBxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAQ/C;;;GAGG;AACH,wBAAuB,WAAW,CAChC,IAAI,EAAE,YAAY,GACjB,cAAc,CAAC,UAAU,CAAC,CA6V5B"}
1
+ {"version":3,"file":"loop.d.ts","sourceRoot":"","sources":["../../../src/agent/chat-loop/loop.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAkBxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAQ/C;;;GAGG;AACH,wBAAuB,WAAW,CAChC,IAAI,EAAE,YAAY,GACjB,cAAc,CAAC,UAAU,CAAC,CA+Y5B"}
@@ -2,6 +2,7 @@ import type { ModelContextCompactionReport } from "../../context/assembly/index.
2
2
  import type { AgentTurnEngine } from "../../execution/turn/index.js";
3
3
  import { type AgentTurnCommitApplier } from "../../execution/turn/index.js";
4
4
  import type { StepProcessingOutput } from "../../execution/turn/index.js";
5
+ import type { AgentTurnLiveEventQueue } from "../../execution/turn/index.js";
5
6
  import type { AgentEvent } from "../../types/events.js";
6
7
  import { type ResolvedContextRecoveryConfig } from "./context-recovery.js";
7
8
  import { type ChatModelStepToolRecord } from "./model-step-snapshot.js";
@@ -22,5 +23,6 @@ export declare function runChatModelStepWithRecovery(options: {
22
23
  toolRecord: ChatModelStepToolRecord;
23
24
  contextRecovery: ResolvedContextRecoveryConfig;
24
25
  compactionReport?: ModelContextCompactionReport;
26
+ liveEvents?: AgentTurnLiveEventQueue;
25
27
  }): AsyncGenerator<AgentEvent, ChatModelStepRunResult>;
26
28
  //# sourceMappingURL=model-step-runner.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"model-step-runner.d.ts","sourceRoot":"","sources":["../../../src/agent/chat-loop/model-step-runner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,iCAAiC,CAAC;AACpF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAGL,KAAK,sBAAsB,EAC5B,MAAM,+BAA+B,CAAC;AACvC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAC1E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAEL,KAAK,6BAA6B,EAEnC,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAEL,KAAK,uBAAuB,EAC7B,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEzD,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,oBAAoB,CAAC;IACjC,UAAU,EAAE,uBAAuB,CAAC;IACpC,gBAAgB,CAAC,EAAE,4BAA4B,CAAC;CACjD;AAED,wBAAuB,4BAA4B,CAAC,OAAO,EAAE;IAC3D,IAAI,EAAE,YAAY,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,eAAe,CAAC;IAC5B,gBAAgB,EAAE,sBAAsB,CAAC;IACzC,iBAAiB,EAAE,iBAAiB,CAAC;IACrC,YAAY,EAAE,YAAY,CAAC,UAAU,CAAC,CAAC;IACvC,UAAU,EAAE,uBAAuB,CAAC;IACpC,eAAe,EAAE,6BAA6B,CAAC;IAC/C,gBAAgB,CAAC,EAAE,4BAA4B,CAAC;CACjD,GAAG,cAAc,CAAC,UAAU,EAAE,sBAAsB,CAAC,CAmIrD"}
1
+ {"version":3,"file":"model-step-runner.d.ts","sourceRoot":"","sources":["../../../src/agent/chat-loop/model-step-runner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,iCAAiC,CAAC;AACpF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AACrE,OAAO,EAGL,KAAK,sBAAsB,EAC5B,MAAM,+BAA+B,CAAC;AACvC,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAC;AAC1E,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,+BAA+B,CAAC;AAC7E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAEL,KAAK,6BAA6B,EAEnC,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAEL,KAAK,uBAAuB,EAC7B,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEzD,MAAM,WAAW,sBAAsB;IACrC,UAAU,EAAE,oBAAoB,CAAC;IACjC,UAAU,EAAE,uBAAuB,CAAC;IACpC,gBAAgB,CAAC,EAAE,4BAA4B,CAAC;CACjD;AAED,wBAAuB,4BAA4B,CAAC,OAAO,EAAE;IAC3D,IAAI,EAAE,YAAY,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,eAAe,CAAC;IAC5B,gBAAgB,EAAE,sBAAsB,CAAC;IACzC,iBAAiB,EAAE,iBAAiB,CAAC;IACrC,YAAY,EAAE,YAAY,CAAC,UAAU,CAAC,CAAC;IACvC,UAAU,EAAE,uBAAuB,CAAC;IACpC,eAAe,EAAE,6BAA6B,CAAC;IAC/C,gBAAgB,CAAC,EAAE,4BAA4B,CAAC;IAChD,UAAU,CAAC,EAAE,uBAAuB,CAAC;CACtC,GAAG,cAAc,CAAC,UAAU,EAAE,sBAAsB,CAAC,CAoIrD"}
@@ -2,6 +2,68 @@ import {
2
2
  sleep
3
3
  } from "./chunk-SZ2XBPTW.js";
4
4
 
5
+ // src/dispatch/event-store.ts
6
+ function cloneEventRecord(record) {
7
+ try {
8
+ return structuredClone(record);
9
+ } catch {
10
+ return { ...record };
11
+ }
12
+ }
13
+ function matchesFilter(record, filter) {
14
+ if (!filter) {
15
+ return true;
16
+ }
17
+ if (filter.dispatchId && record.dispatchId !== filter.dispatchId) {
18
+ return false;
19
+ }
20
+ if (filter.parentSessionId && record.parentSessionId !== filter.parentSessionId) {
21
+ return false;
22
+ }
23
+ if (filter.parentTurnId && record.parentTurnId !== filter.parentTurnId) {
24
+ return false;
25
+ }
26
+ if (filter.parentDispatchId && record.parentDispatchId !== filter.parentDispatchId) {
27
+ return false;
28
+ }
29
+ if (filter.agentPath && record.agentPath !== filter.agentPath) {
30
+ return false;
31
+ }
32
+ if (filter.childSessionId && record.childSessionId !== filter.childSessionId) {
33
+ return false;
34
+ }
35
+ if (filter.targetType && record.targetType !== filter.targetType) {
36
+ return false;
37
+ }
38
+ if (filter.afterSequence !== void 0 && record.sequence <= filter.afterSequence) {
39
+ return false;
40
+ }
41
+ if (filter.type) {
42
+ const types = Array.isArray(filter.type) ? filter.type : [filter.type];
43
+ if (!types.includes(record.event.type)) {
44
+ return false;
45
+ }
46
+ }
47
+ return true;
48
+ }
49
+ var InMemoryDispatchEventStore = class {
50
+ events = [];
51
+ sequence = 0;
52
+ async append(event) {
53
+ const record = {
54
+ ...event,
55
+ id: `${event.dispatchId}:event:${this.sequence + 1}`,
56
+ sequence: this.sequence + 1
57
+ };
58
+ this.sequence = record.sequence;
59
+ this.events.push(cloneEventRecord(record));
60
+ return cloneEventRecord(record);
61
+ }
62
+ async list(filter) {
63
+ return this.events.filter((event) => matchesFilter(event, filter)).map((event) => cloneEventRecord(event));
64
+ }
65
+ };
66
+
5
67
  // src/dispatch/executor.ts
6
68
  function ensureNonEmpty(input, label) {
7
69
  const trimmed = input.trim();
@@ -32,6 +94,7 @@ function defaultTaskRecord(input, targetName, startedAt, dispatchId, startResult
32
94
  createdAt: startedAt,
33
95
  updatedAt: startedAt,
34
96
  parentSessionId: input.parentSessionId,
97
+ parentTurnId: input.parentTurnId,
35
98
  sessionId: startResult.sessionId ?? input.runtime.member.sessionId,
36
99
  executionId: startResult.executionId ?? input.task.runId ?? dispatchId,
37
100
  redirectCount: 0
@@ -102,7 +165,12 @@ function createRuntimeDispatchTargets(options) {
102
165
  targetType: target.name,
103
166
  brief: input.brief,
104
167
  title: input.title,
105
- parentSessionId: input.parentSessionId
168
+ parentSessionId: input.parentSessionId,
169
+ parentTurnId: input.parentTurnId,
170
+ parentDispatchId: input.parentDispatchId,
171
+ depth: input.depth,
172
+ agentPath: input.agentPath,
173
+ abort: input.abort
106
174
  });
107
175
  return {
108
176
  sessionId: record.sessionId,
@@ -148,7 +216,9 @@ function createDispatchTaskExecutor(options) {
148
216
  brief: input.prompt,
149
217
  title: input.task.title,
150
218
  parentSessionId: input.parentSessionId,
151
- sessionId: input.runtime.member.sessionId
219
+ parentTurnId: input.parentTurnId,
220
+ sessionId: input.runtime.member.sessionId,
221
+ abort: input.abort
152
222
  });
153
223
  let record = options.createRecord?.({
154
224
  taskInput: input,
@@ -277,6 +347,7 @@ function createDispatchExternalTaskControl(options) {
277
347
  }
278
348
 
279
349
  export {
350
+ InMemoryDispatchEventStore,
280
351
  ensureNonEmpty,
281
352
  mergeInspection,
282
353
  createRuntimeDispatchTargets,
@@ -242,6 +242,51 @@ function createAgentTurnEngine(options) {
242
242
  return new AgentTurnEngine(options);
243
243
  }
244
244
 
245
+ // src/execution/turn/runner/live-events.ts
246
+ function createAgentTurnLiveEventQueue() {
247
+ const events = [];
248
+ let waiters = [];
249
+ let closed = false;
250
+ function wakeWaiters() {
251
+ const current = waiters;
252
+ waiters = [];
253
+ for (const resolve of current) {
254
+ resolve();
255
+ }
256
+ }
257
+ return {
258
+ emit(event) {
259
+ if (closed) {
260
+ return;
261
+ }
262
+ events.push(event);
263
+ wakeWaiters();
264
+ },
265
+ drain() {
266
+ return events.splice(0, events.length);
267
+ },
268
+ size() {
269
+ return events.length;
270
+ },
271
+ wait() {
272
+ if (closed || events.length > 0) {
273
+ return Promise.resolve();
274
+ }
275
+ return new Promise((resolve) => {
276
+ waiters.push(resolve);
277
+ });
278
+ },
279
+ wake() {
280
+ wakeWaiters();
281
+ },
282
+ close() {
283
+ closed = true;
284
+ events.length = 0;
285
+ wakeWaiters();
286
+ }
287
+ };
288
+ }
289
+
245
290
  // src/execution/turn/runner/prepare.ts
246
291
  function prepareModelStep(options) {
247
292
  const modelMessages = Array.from(options.toModelMessages(options.messages));
@@ -622,6 +667,40 @@ async function* runModelStep(options) {
622
667
  resolveNext = null;
623
668
  }
624
669
  };
670
+ const emitToolEvent = async (event) => {
671
+ if (options.liveEvents) {
672
+ options.liveEvents.emit(event);
673
+ return;
674
+ }
675
+ await emitQueuedEvent(event);
676
+ };
677
+ async function* drainLiveEvents() {
678
+ if (!options.liveEvents) {
679
+ return;
680
+ }
681
+ for (const event of options.liveEvents.drain()) {
682
+ middleware?.emitEvent(event);
683
+ turnEngine.recordEvent(event, (/* @__PURE__ */ new Date()).toISOString());
684
+ yield event;
685
+ }
686
+ }
687
+ async function waitForQueuedOrLiveEvent() {
688
+ let streamResolved = false;
689
+ const streamWait = new Promise((resolve) => {
690
+ resolveNext = () => {
691
+ streamResolved = true;
692
+ resolve();
693
+ };
694
+ });
695
+ if (!options.liveEvents) {
696
+ await streamWait;
697
+ return;
698
+ }
699
+ await Promise.race([streamWait, options.liveEvents.wait()]);
700
+ if (!streamResolved) {
701
+ resolveNext = null;
702
+ }
703
+ }
625
704
  if (intervention) {
626
705
  intervention.onApplied = (item) => {
627
706
  eventQueue.push({
@@ -648,7 +727,7 @@ async function* runModelStep(options) {
648
727
  }
649
728
  const stream = await Inference.streamStep({
650
729
  ...preparedStep.inferenceInput,
651
- onEvent: emitQueuedEvent
730
+ onEvent: emitToolEvent
652
731
  });
653
732
  const processPromise = processStepStream(stream, {
654
733
  sessionID: preparedStep.inferenceInput.sessionID,
@@ -681,7 +760,7 @@ async function* runModelStep(options) {
681
760
  }
682
761
  return null;
683
762
  });
684
- while (!streamDone || eventQueue.length > 0) {
763
+ while (!streamDone || eventQueue.length > 0 || (options.liveEvents?.size() ?? 0) > 0) {
685
764
  while (eventQueue.length > 0) {
686
765
  const event = eventQueue.shift();
687
766
  turnEngine.recordEvent(event, (/* @__PURE__ */ new Date()).toISOString());
@@ -695,10 +774,9 @@ async function* runModelStep(options) {
695
774
  );
696
775
  }
697
776
  }
698
- if (!streamDone) {
699
- await new Promise((resolve) => {
700
- resolveNext = resolve;
701
- });
777
+ yield* drainLiveEvents();
778
+ if (!streamDone && eventQueue.length === 0) {
779
+ await waitForQueuedOrLiveEvent();
702
780
  }
703
781
  }
704
782
  if (streamError) {
@@ -729,6 +807,13 @@ async function* runModelStep(options) {
729
807
  }
730
808
 
731
809
  // src/execution/turn/runner/tool-batch.ts
810
+ async function emitBatchEvent(event, accumulators) {
811
+ if (accumulators.onEvent) {
812
+ await accumulators.onEvent(event);
813
+ return;
814
+ }
815
+ accumulators.events.push(event);
816
+ }
732
817
  function cloneToolResultRecord(options) {
733
818
  return new Map(
734
819
  options.snapshot.toolResults.map((toolResult) => [
@@ -737,8 +822,8 @@ function cloneToolResultRecord(options) {
737
822
  ])
738
823
  );
739
824
  }
740
- function recordToolResult(toolCall, event, result, accumulators, metadata) {
741
- accumulators.events.push(event);
825
+ async function recordToolResult(toolCall, event, result, accumulators, metadata) {
826
+ await emitBatchEvent(event, accumulators);
742
827
  accumulators.toolResultsByCallId.set(toolCall.toolCallId, {
743
828
  toolCallId: toolCall.toolCallId,
744
829
  toolName: toolCall.toolName,
@@ -772,7 +857,7 @@ async function executeBatchEntry(toolCall, options, accumulators, preInitialized
772
857
  const tool = options.tools[toolCall.toolName];
773
858
  if (!tool) {
774
859
  const errorMessage = `Tool '${toolCall.toolName}' is not registered`;
775
- recordToolResult(
860
+ await recordToolResult(
776
861
  toolCall,
777
862
  {
778
863
  type: "tool-error",
@@ -801,11 +886,11 @@ async function executeBatchEntry(toolCall, options, accumulators, preInitialized
801
886
  ...options.turnTracker ? { turnTracker: options.turnTracker } : {},
802
887
  ...options.middleware ? { middleware: options.middleware } : {},
803
888
  onEvent: async (event) => {
804
- accumulators.events.push(event);
889
+ await emitBatchEvent(event, accumulators);
805
890
  },
806
891
  ...preInitialized ? { initialized: preInitialized } : {}
807
892
  });
808
- recordToolResult(
893
+ await recordToolResult(
809
894
  toolCall,
810
895
  {
811
896
  type: "tool-result",
@@ -820,7 +905,7 @@ async function executeBatchEntry(toolCall, options, accumulators, preInitialized
820
905
  );
821
906
  } catch (error) {
822
907
  const errorMessage = error instanceof Error ? error.message : String(error);
823
- recordToolResult(
908
+ await recordToolResult(
824
909
  toolCall,
825
910
  {
826
911
  type: "tool-error",
@@ -839,7 +924,12 @@ async function runToolBatch(options) {
839
924
  const turnState = {
840
925
  value: options.turnState ? structuredClone(options.turnState) : void 0
841
926
  };
842
- const accumulators = { events, toolResultsByCallId, turnState };
927
+ const accumulators = {
928
+ events,
929
+ toolResultsByCallId,
930
+ turnState,
931
+ ...options.onEvent ? { onEvent: options.onEvent } : {}
932
+ };
843
933
  const pending = options.snapshot.toolCalls.filter(
844
934
  (tc) => !toolResultsByCallId.has(tc.toolCallId)
845
935
  );
@@ -876,7 +966,7 @@ async function runToolBatch(options) {
876
966
  if (options.intervention?.hasPending && initialized) {
877
967
  const interruptPolicy = initialized.capabilities?.onInterrupt ?? "finish";
878
968
  if (interruptPolicy === "cancel") {
879
- recordToolResult(
969
+ await recordToolResult(
880
970
  toolCall,
881
971
  {
882
972
  type: "tool-error",
@@ -949,6 +1039,7 @@ export {
949
1039
  createAgentTurnStepCommitBatch,
950
1040
  AgentTurnEngine,
951
1041
  createAgentTurnEngine,
1042
+ createAgentTurnLiveEventQueue,
952
1043
  prepareModelStep,
953
1044
  DoomLoopError,
954
1045
  ContextOverflowError,
@@ -3,7 +3,7 @@ import {
3
3
  } from "./chunk-TPZ37IWI.js";
4
4
  import {
5
5
  createLocalDispatchRuntime
6
- } from "./chunk-MO7V4H4A.js";
6
+ } from "./chunk-ZETYNQ35.js";
7
7
  import {
8
8
  Tool
9
9
  } from "./chunk-MJML3A2F.js";
@@ -96,7 +96,9 @@ function formatWaitTimeoutResult(timeoutMs, runningIds) {
96
96
  title: "Wait timed out",
97
97
  output: `Timed out waiting after ${timeoutMs}ms.
98
98
 
99
- ` + (runningIds.length > 0 ? `Still running: ${runningIds.join(", ")}` : "No requested subagents are still running."),
99
+ ` + (runningIds.length > 0 ? `Still running: ${runningIds.join(", ")}
100
+
101
+ Use wait_agent again to keep waiting, close_agent if the result is no longer needed, or continue with any completed results you already have.` : "No requested subagents are still running. Check their status again or continue with any completed results you already have."),
100
102
  metadata: { timeoutMs, runningIds }
101
103
  };
102
104
  }
@@ -142,6 +144,8 @@ var SUBAGENT_TOOL_IDS = [
142
144
  "wait_agent",
143
145
  "close_agent"
144
146
  ];
147
+ var DEFAULT_WAIT_AGENT_TIMEOUT_MS = 6e4;
148
+ var MAX_WAIT_AGENT_TIMEOUT_MS = 6e5;
145
149
  function getRoleNames(roles) {
146
150
  return roles.map((role) => role.name);
147
151
  }
@@ -179,6 +183,15 @@ function toCompletedResult(record) {
179
183
  toolCalls: record.result.toolCalls
180
184
  };
181
185
  }
186
+ function normalizeWaitAgentTimeoutMs(timeoutMs) {
187
+ if (timeoutMs === void 0) {
188
+ return DEFAULT_WAIT_AGENT_TIMEOUT_MS;
189
+ }
190
+ if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
191
+ return DEFAULT_WAIT_AGENT_TIMEOUT_MS;
192
+ }
193
+ return Math.min(Math.floor(timeoutMs), MAX_WAIT_AGENT_TIMEOUT_MS);
194
+ }
182
195
  async function waitForTerminalDispatch(runtime, id) {
183
196
  for (; ; ) {
184
197
  const record = await runtime.check(id, { waitMs: 1e3 });
@@ -234,7 +247,9 @@ function createInvokeAgentTool(runtime, roles, options) {
234
247
  brief: params.task,
235
248
  title: params.title ?? `${titlePrefix}: ${role.name}`,
236
249
  parentSessionId: ctx.sessionID,
237
- abort: ctx.abort
250
+ parentTurnId: ctx.turnID,
251
+ abort: ctx.abort,
252
+ emitEvent: ctx.emitEvent
238
253
  });
239
254
  } catch (error) {
240
255
  return formatSpawnBlockedResult(
@@ -274,7 +289,7 @@ function createWaitAgentTool(runtime) {
274
289
  timeout_ms: z.number().optional().describe("Timeout in milliseconds (default: 60000, max: 600000)")
275
290
  }),
276
291
  execute: async (params) => {
277
- const timeoutMs = Math.min(params.timeout_ms ?? 6e4, 6e5);
292
+ const timeoutMs = normalizeWaitAgentTimeoutMs(params.timeout_ms);
278
293
  const existing = await Promise.all(
279
294
  params.ids.map(async (id) => [id, await runtime.check(id)])
280
295
  );
@@ -318,6 +333,7 @@ function createCloseAgentTool(runtime) {
318
333
  return formatCloseMissingAgentResult(params.id);
319
334
  }
320
335
  if (record.status !== "running") {
336
+ await runtime.cancel(params.id, "Parent subagent closed");
321
337
  return formatCloseAlreadyResolvedResult(params.id, record.status);
322
338
  }
323
339
  const cancelled = await runtime.cancel(params.id);
@@ -661,6 +677,9 @@ function toSubAgentRole(parsed, resolvers = {}) {
661
677
  };
662
678
  if (systemPrompt) role.systemPrompt = systemPrompt;
663
679
  if (maxSteps !== void 0 && !isNaN(maxSteps)) role.maxSteps = maxSteps;
680
+ if (reasoning !== void 0 && VALID_REASONING_LEVELS.has(reasoning)) {
681
+ role.reasoningLevel = reasoning;
682
+ }
664
683
  if (allowFurtherDispatch !== void 0) {
665
684
  role.allowFurtherDispatch = allowFurtherDispatch;
666
685
  }