zidane 6.4.4 → 6.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. package/README.md +1 -0
  2. package/dist/acp-cli.js +7 -6
  3. package/dist/acp-cli.js.map +1 -1
  4. package/dist/{acp-BLO58K3F.js → acp-o-LQAjFw.js} +4 -5
  5. package/dist/{acp-BLO58K3F.js.map → acp-o-LQAjFw.js.map} +1 -1
  6. package/dist/acp.d.ts +1 -1
  7. package/dist/acp.js +1 -1
  8. package/dist/{agent-8sUadp5M.js → agent-BVNkC1h4.js} +886 -113
  9. package/dist/agent-BVNkC1h4.js.map +1 -0
  10. package/dist/agent.d.ts +1 -1
  11. package/dist/agent.js +1 -2
  12. package/dist/{anthropic-D3lkw5mv.js → anthropic-Dov2mC5e.js} +3 -3
  13. package/dist/{anthropic-D3lkw5mv.js.map → anthropic-Dov2mC5e.js.map} +1 -1
  14. package/dist/{auth-BzYbbdN_.js → auth-B8ZuBcKC.js} +5 -5
  15. package/dist/{auth-BzYbbdN_.js.map → auth-B8ZuBcKC.js.map} +1 -1
  16. package/dist/chat/pure.d.ts +3 -3
  17. package/dist/chat/pure.js +2 -2
  18. package/dist/chat.d.ts +13 -44
  19. package/dist/chat.d.ts.map +1 -1
  20. package/dist/chat.js +8 -7
  21. package/dist/chat.js.map +1 -1
  22. package/dist/{edit-utils-EGosADZq.js → context-breakdown-BLF10tOO.js} +154 -2
  23. package/dist/context-breakdown-BLF10tOO.js.map +1 -0
  24. package/dist/{context-transport-D29WvHcm.js → context-transport-D-daWOmp.js} +3 -3
  25. package/dist/{context-transport-D29WvHcm.js.map → context-transport-D-daWOmp.js.map} +1 -1
  26. package/dist/contexts/daytona.d.ts +1 -1
  27. package/dist/contexts/e2b.d.ts +1 -1
  28. package/dist/eval.d.ts +1 -1
  29. package/dist/eval.js +1 -1
  30. package/dist/extensions.d.ts +2 -2
  31. package/dist/extensions.js +2 -2
  32. package/dist/headless.d.ts +1 -1
  33. package/dist/headless.js +3 -3
  34. package/dist/{index-C-Nd2ZbV.d.ts → index-CWBSrqI6.d.ts} +676 -3
  35. package/dist/index-CWBSrqI6.d.ts.map +1 -0
  36. package/dist/index.d.ts +2 -2
  37. package/dist/index.js +13 -13
  38. package/dist/{login-CMVVnAHS.js → login-CR3fDHXh.js} +3 -3
  39. package/dist/{login-CMVVnAHS.js.map → login-CR3fDHXh.js.map} +1 -1
  40. package/dist/{mcp-3GXUBwur.js → mcp-C6IkXNOS.js} +87 -6
  41. package/dist/mcp-C6IkXNOS.js.map +1 -0
  42. package/dist/mcp.d.ts +2 -2
  43. package/dist/mcp.js +3 -2
  44. package/dist/{messages-C01kKGj0.js → messages-C_H9soi5.js} +2 -3
  45. package/dist/{messages-C01kKGj0.js.map → messages-C_H9soi5.js.map} +1 -1
  46. package/dist/{openai-compat-B3c_hzwf.js → openai-compat-CnHeo4Lz.js} +216 -3
  47. package/dist/openai-compat-CnHeo4Lz.js.map +1 -0
  48. package/dist/origin-pinned-fetch-CqG8VZIq.js +159 -0
  49. package/dist/origin-pinned-fetch-CqG8VZIq.js.map +1 -0
  50. package/dist/output/stream-json.d.ts +1 -1
  51. package/dist/output/terminal.d.ts +1 -1
  52. package/dist/plugins-2PMTVcp-.js +1174 -0
  53. package/dist/plugins-2PMTVcp-.js.map +1 -0
  54. package/dist/plugins.d.ts +2 -0
  55. package/dist/plugins.js +2 -0
  56. package/dist/presets.d.ts +1 -1
  57. package/dist/presets.js +1 -1
  58. package/dist/providers/anthropic.d.ts +1 -1
  59. package/dist/providers/anthropic.js +1 -1
  60. package/dist/providers/arcee.d.ts +1 -1
  61. package/dist/providers/arcee.js +1 -1
  62. package/dist/providers/baseten.d.ts +1 -1
  63. package/dist/providers/baseten.js +1 -1
  64. package/dist/providers/cerebras.d.ts +1 -1
  65. package/dist/providers/cerebras.js +1 -1
  66. package/dist/providers/local.d.ts +1 -1
  67. package/dist/providers/local.js +1 -1
  68. package/dist/providers/openai-compat.d.ts +1 -1
  69. package/dist/providers/openai-compat.js +1 -1
  70. package/dist/providers/openai.d.ts +1 -1
  71. package/dist/providers/openai.js +2 -2
  72. package/dist/providers/openrouter.d.ts +1 -1
  73. package/dist/providers/openrouter.js +1 -1
  74. package/dist/providers/xai.d.ts +1 -1
  75. package/dist/providers/xai.js +1 -1
  76. package/dist/{providers-z1vU0b2Q.js → providers-B6mFe7OD.js} +3 -3
  77. package/dist/{providers-z1vU0b2Q.js.map → providers-B6mFe7OD.js.map} +1 -1
  78. package/dist/providers.d.ts +1 -1
  79. package/dist/providers.js +4 -4
  80. package/dist/restate.d.ts +178 -2
  81. package/dist/restate.d.ts.map +1 -1
  82. package/dist/restate.js +463 -7
  83. package/dist/restate.js.map +1 -1
  84. package/dist/session/sqlite.d.ts +1 -1
  85. package/dist/{session-cr9VdoEO.js → session-VpLrNaFQ.js} +2 -2
  86. package/dist/{session-cr9VdoEO.js.map → session-VpLrNaFQ.js.map} +1 -1
  87. package/dist/session.d.ts +1 -1
  88. package/dist/session.js +2 -2
  89. package/dist/{resolve-CZJxds85.js → skills-Cp9vnBwd.js} +1430 -1006
  90. package/dist/skills-Cp9vnBwd.js.map +1 -0
  91. package/dist/skills.d.ts +1 -1
  92. package/dist/skills.js +1 -2
  93. package/dist/{stdio-BvL8HGYW.js → stdio-DzUUkkhS.js} +2 -2
  94. package/dist/{stdio-BvL8HGYW.js.map → stdio-DzUUkkhS.js.map} +1 -1
  95. package/dist/{stdio-loader-CjfoqBle.js → stdio-loader-BILyUGmi.js} +2 -2
  96. package/dist/{stdio-loader-CjfoqBle.js.map → stdio-loader-BILyUGmi.js.map} +1 -1
  97. package/dist/{tool-formatters-DPQjso_C.d.ts → tool-formatters-gFqQbzPY.d.ts} +2 -2
  98. package/dist/{tool-formatters-DPQjso_C.d.ts.map → tool-formatters-gFqQbzPY.d.ts.map} +1 -1
  99. package/dist/tools/fetch-url.d.ts +1 -1
  100. package/dist/tools/web-search.d.ts +1 -1
  101. package/dist/tools.d.ts +1 -1
  102. package/dist/tools.js +1 -2
  103. package/dist/{transcript-anchors-CgDzYin1.js → transcript-anchors-DEIr0tJC.js} +44 -7
  104. package/dist/transcript-anchors-DEIr0tJC.js.map +1 -0
  105. package/dist/{transcript-anchors-BCUpbNxc.d.ts → transcript-anchors-qCs3wZpu.d.ts} +98 -92
  106. package/dist/transcript-anchors-qCs3wZpu.d.ts.map +1 -0
  107. package/dist/tui.d.ts +38 -4
  108. package/dist/tui.d.ts.map +1 -1
  109. package/dist/tui.js +843 -109
  110. package/dist/tui.js.map +1 -1
  111. package/dist/{turn-operations-CAvi8NYt.js → turn-operations-C3IijXMW.js} +2 -2
  112. package/dist/{turn-operations-CAvi8NYt.js.map → turn-operations-C3IijXMW.js.map} +1 -1
  113. package/dist/{turn-operations-Bu2Hkinw.d.ts → turn-operations-M9-jUyDd.d.ts} +3 -3
  114. package/dist/{turn-operations-Bu2Hkinw.d.ts.map → turn-operations-M9-jUyDd.d.ts.map} +1 -1
  115. package/dist/types-BIarq1qE.js.map +1 -1
  116. package/dist/types.d.ts +1 -1
  117. package/dist/{xai-BPwMQSuF.js → xai-Du6Wfnlb.js} +2 -2
  118. package/dist/{xai-BPwMQSuF.js.map → xai-Du6Wfnlb.js.map} +1 -1
  119. package/docs/PLUGINS.md +340 -0
  120. package/docs/RESTATE.md +168 -3
  121. package/docs/SKILL.md +24 -8
  122. package/package.json +6 -1
  123. package/dist/agent-8sUadp5M.js.map +0 -1
  124. package/dist/aliasing-lVFbm81n.js +0 -217
  125. package/dist/aliasing-lVFbm81n.js.map +0 -1
  126. package/dist/context-breakdown-Dzo25N45.js +0 -155
  127. package/dist/context-breakdown-Dzo25N45.js.map +0 -1
  128. package/dist/edit-utils-EGosADZq.js.map +0 -1
  129. package/dist/index-C-Nd2ZbV.d.ts.map +0 -1
  130. package/dist/mcp-3GXUBwur.js.map +0 -1
  131. package/dist/openai-compat-B3c_hzwf.js.map +0 -1
  132. package/dist/resolve-CZJxds85.js.map +0 -1
  133. package/dist/skills-Dd6XCi4s.js +0 -420
  134. package/dist/skills-Dd6XCi4s.js.map +0 -1
  135. package/dist/tool-state-DTs-3ZHH.js +0 -653
  136. package/dist/tool-state-DTs-3ZHH.js.map +0 -1
  137. package/dist/transcript-anchors-BCUpbNxc.d.ts.map +0 -1
  138. package/dist/transcript-anchors-CgDzYin1.js.map +0 -1
package/dist/restate.js CHANGED
@@ -1,6 +1,7 @@
1
- import { n as buildAliasMaps } from "./aliasing-lVFbm81n.js";
2
- import { r as coerceToolResultContent } from "./types-BIarq1qE.js";
3
- import { i as stagedToolState, l as hydrateReadStateFromSessionAsync, r as isToolStateOps } from "./tool-state-DTs-3ZHH.js";
1
+ import { L as buildAliasMaps } from "./openai-compat-CnHeo4Lz.js";
2
+ import { c as toolOutputByteLength, l as toolResultToText, r as coerceToolResultContent } from "./types-BIarq1qE.js";
3
+ import { Dt as reserveChildLabel, Ln as hydrateReadStateFromSessionAsync, a as stagedToolState, i as isToolStateOps } from "./agent-BVNkC1h4.js";
4
+ import { r as formatTokenUsage } from "./stats-DAKBEKjc.js";
4
5
  import { createHash } from "node:crypto";
5
6
  //#region src/restate/awakeable.ts
6
7
  /**
@@ -182,7 +183,8 @@ function restateClock(ctx, options = {}) {
182
183
  const randomUUID = () => deterministicUuid(`${idSeed}:uuid:${idSeq++}`);
183
184
  if (!coalesce) return {
184
185
  now: () => ctx.date.now(),
185
- randomUUID
186
+ randomUUID,
187
+ journaled: true
186
188
  };
187
189
  const requested = typeof coalesce === "object" ? coalesce.reanchorEvery : void 0;
188
190
  const reanchorEvery = typeof requested === "number" && Number.isFinite(requested) && requested >= 1 ? Math.floor(requested) : DEFAULT_REANCHOR_EVERY;
@@ -201,7 +203,8 @@ function restateClock(ctx, options = {}) {
201
203
  lastReturned = value;
202
204
  return value;
203
205
  },
204
- randomUUID
206
+ randomUUID,
207
+ journaled: true
205
208
  };
206
209
  }
207
210
  //#endregion
@@ -567,7 +570,7 @@ function wrapAgentTools(tools, ctx, opts = {}) {
567
570
  const excludeSet = new Set(opts.exclude ?? []);
568
571
  const skipWaitTask = opts.detachedTasks === "durable";
569
572
  const wrapped = {};
570
- for (const [name, def] of Object.entries(tools)) wrapped[name] = excludeSet.has(name) || skipWaitTask && def.spec.name === "wait_task" ? def : restateTool(def, ctx, opts);
573
+ for (const [name, def] of Object.entries(tools)) wrapped[name] = excludeSet.has(name) || def.runsNestedAgent === true || skipWaitTask && def.spec.name === "wait_task" ? def : restateTool(def, ctx, opts);
571
574
  return wrapped;
572
575
  }
573
576
  //#endregion
@@ -965,6 +968,459 @@ function maxDefined(values) {
965
968
  return max;
966
969
  }
967
970
  //#endregion
971
+ //#region src/restate/spawn.ts
972
+ const ZERO_STATS = {
973
+ totalIn: 0,
974
+ totalOut: 0,
975
+ totalCacheRead: 0,
976
+ totalCacheCreation: 0,
977
+ turns: 0,
978
+ elapsed: 0
979
+ };
980
+ const DEFAULT_DESCRIPTION = "Delegate a self-contained task to a sub-agent that runs independently and returns only its final report. Several spawn calls in one turn run in parallel.";
981
+ function restateSpawnTool(options) {
982
+ const persist = options.persist ?? true;
983
+ const emitEvents = options.emitChildEvents ?? true;
984
+ let dispatchSeq = 0;
985
+ let sessionlessLabels = 0;
986
+ let cancelSignalled = false;
987
+ let nestedLabels = 0;
988
+ const pending = [];
989
+ const drainRegistered = /* @__PURE__ */ new WeakSet();
990
+ /**
991
+ * Build the request and the bookkeeping entry. Deliberately side-effect free
992
+ * apart from reserving the label: the fleet path has to be able to reject a
993
+ * misconfigured `dispatch` (below) without leaving a phantom child queued for
994
+ * the merge. `commit` is what actually enrols the child.
995
+ */
996
+ function prepare(input, ctx) {
997
+ const task = String(input.task ?? "");
998
+ const depth = (ctx.depth ?? 0) + 1;
999
+ const label = ctx.session ? reserveChildLabel(ctx.session) : `child-${++sessionlessLabels}`;
1000
+ return {
1001
+ entry: {
1002
+ order: ++dispatchSeq,
1003
+ label,
1004
+ task,
1005
+ depth,
1006
+ callId: ctx.callId,
1007
+ runId: `${ctx.runId ?? "run"}-${label}`,
1008
+ ...ctx.runId !== void 0 ? { parentRunId: ctx.runId } : {},
1009
+ ...ctx.session !== void 0 ? { session: ctx.session } : {}
1010
+ },
1011
+ req: {
1012
+ task,
1013
+ label,
1014
+ depth,
1015
+ ...ctx.runId !== void 0 ? { parentRunId: ctx.runId } : {},
1016
+ parentCallId: ctx.callId,
1017
+ ...ctx.session !== void 0 ? { sessionId: ctx.session.id } : {},
1018
+ ...typeof input.model === "string" ? { model: input.model } : {},
1019
+ ...typeof input.subagent_type === "string" ? { subagentType: input.subagent_type } : {}
1020
+ }
1021
+ };
1022
+ }
1023
+ /** Enrol a dispatched child for merging, and announce it. */
1024
+ function commit(entry, input, ctx) {
1025
+ pending.push(entry);
1026
+ registerDrain(ctx);
1027
+ watchAbort(entry, ctx);
1028
+ Promise.resolve(ctx.hooks.callHook("spawn:before", {
1029
+ id: entry.label,
1030
+ task: entry.task,
1031
+ callId: entry.callId,
1032
+ depth: entry.depth,
1033
+ ...typeof input.model === "string" ? { model: input.model } : {}
1034
+ })).catch(() => {});
1035
+ }
1036
+ function registerDrain(ctx) {
1037
+ if (drainRegistered.has(ctx.hooks)) return;
1038
+ drainRegistered.add(ctx.hooks);
1039
+ ctx.hooks.hook("tool-results:after", async () => {
1040
+ await drain(ctx);
1041
+ });
1042
+ ctx.hooks.hook("turn:after", async () => {
1043
+ await drain(ctx);
1044
+ });
1045
+ }
1046
+ /**
1047
+ * Persist finished children and announce them. Runs where awaiting is legal,
1048
+ * in submission order rather than settlement order, so two children that
1049
+ * complete out of order still land deterministically.
1050
+ */
1051
+ async function drain(ctx) {
1052
+ if (pending.length === 0) return;
1053
+ const batch = pending.splice(0, pending.length).sort((a, b) => a.order - b.order);
1054
+ let touchedSession;
1055
+ for (const entry of batch) {
1056
+ const result = entry.result;
1057
+ const stats = result?.stats ?? ZERO_STATS;
1058
+ const status = result?.status ?? (entry.cancelRequested ? "aborted" : "error");
1059
+ const session = entry.session;
1060
+ if (persist && session) {
1061
+ touchedSession = session;
1062
+ session.startRun(entry.runId, entry.task, {
1063
+ ...entry.parentRunId !== void 0 ? { parentRunId: entry.parentRunId } : {},
1064
+ depth: entry.depth,
1065
+ label: entry.label
1066
+ });
1067
+ if (result && result.turns.length > 0) await session.appendTurns(result.turns.map((turn) => ({
1068
+ ...turn,
1069
+ runId: entry.runId
1070
+ })));
1071
+ const rollup = {
1072
+ turns: stats.turns,
1073
+ tokensIn: stats.totalIn,
1074
+ tokensOut: stats.totalOut,
1075
+ ...stats.cost !== void 0 ? { cost: stats.cost } : {}
1076
+ };
1077
+ if (status === "completed") session.completeRun(entry.runId, rollup);
1078
+ else if (status === "error") session.errorRun(entry.runId, errorText(entry), rollup);
1079
+ else session.abortRun(entry.runId, rollup);
1080
+ stampJournaledRunTimes(session, entry, result);
1081
+ }
1082
+ if (emitEvents && result) await replayChildEvents(entry, result.turns, ctx);
1083
+ if (result?.children && result.children.length > 0) {
1084
+ const merged = await mergeDescendants(entry, result.children, ctx);
1085
+ if (merged) touchedSession = merged;
1086
+ }
1087
+ options.onChildMerged?.({
1088
+ label: entry.label,
1089
+ task: entry.task,
1090
+ depth: entry.depth,
1091
+ status,
1092
+ stats,
1093
+ turns: result?.turns ?? [],
1094
+ ...result?.startedAt !== void 0 ? { startedAt: result.startedAt } : {},
1095
+ ...result?.endedAt !== void 0 ? { endedAt: result.endedAt } : {},
1096
+ ...result?.children !== void 0 ? { children: result.children } : {}
1097
+ }, ctx);
1098
+ if (status === "error") await ctx.hooks.callHook("spawn:error", {
1099
+ id: entry.label,
1100
+ task: entry.task,
1101
+ error: new Error(errorText(entry)),
1102
+ depth: entry.depth
1103
+ });
1104
+ await ctx.hooks.callHook("spawn:complete", {
1105
+ id: entry.label,
1106
+ task: entry.task,
1107
+ callId: entry.callId,
1108
+ depth: entry.depth,
1109
+ status,
1110
+ stats,
1111
+ ...result?.text ? { text: result.text } : {}
1112
+ });
1113
+ }
1114
+ await touchedSession?.save();
1115
+ }
1116
+ /**
1117
+ * Merge a child's own descendants under it, depth-first and in the order the
1118
+ * child reported them.
1119
+ *
1120
+ * Each nested child is RE-LABELED from the merging session's counter: the
1121
+ * label it arrived with was minted by its own parent's counter and would
1122
+ * collide (every level starts at `child-1`). Re-labeling keeps the session's
1123
+ * labels unique and makes the synthesized events agree with the persisted
1124
+ * tree.
1125
+ */
1126
+ async function mergeDescendants(parent, nested, ctx) {
1127
+ let touched;
1128
+ const session = parent.session;
1129
+ for (const child of nested) {
1130
+ const depth = parent.depth + 1;
1131
+ const label = session ? reserveChildLabel(session) : `${parent.runId}-nested-${++nestedLabels}`;
1132
+ const runId = `${parent.runId}-${label}`;
1133
+ if (persist && session) {
1134
+ touched = session;
1135
+ session.startRun(runId, child.task, {
1136
+ parentRunId: parent.runId,
1137
+ depth,
1138
+ label
1139
+ });
1140
+ if (child.turns.length > 0) await session.appendTurns(child.turns.map((turn) => ({
1141
+ ...turn,
1142
+ runId
1143
+ })));
1144
+ const rollup = {
1145
+ turns: child.stats.turns,
1146
+ tokensIn: child.stats.totalIn,
1147
+ tokensOut: child.stats.totalOut,
1148
+ ...child.stats.cost !== void 0 ? { cost: child.stats.cost } : {}
1149
+ };
1150
+ if (child.status === "completed") session.completeRun(runId, rollup);
1151
+ else if (child.status === "error") session.errorRun(runId, "sub-agent failed", rollup);
1152
+ else session.abortRun(runId, rollup);
1153
+ const record = session.runs.find((run) => run.id === runId);
1154
+ if (record) {
1155
+ const startedAt = child.startedAt ?? child.turns[0]?.createdAt;
1156
+ const endedAt = child.endedAt ?? child.turns[child.turns.length - 1]?.createdAt ?? startedAt;
1157
+ if (startedAt !== void 0) record.startedAt = startedAt;
1158
+ if (endedAt !== void 0) record.endedAt = endedAt;
1159
+ }
1160
+ }
1161
+ if (emitEvents) await replayChildEvents({
1162
+ label,
1163
+ depth,
1164
+ runId,
1165
+ callId: parent.callId,
1166
+ ...parent.runId ? { parentRunId: parent.runId } : {}
1167
+ }, child.turns, ctx);
1168
+ if (child.children && child.children.length > 0) {
1169
+ const deeper = await mergeDescendants({
1170
+ runId,
1171
+ depth,
1172
+ callId: parent.callId,
1173
+ ...session ? { session } : {}
1174
+ }, child.children, ctx);
1175
+ touched = touched ?? deeper;
1176
+ }
1177
+ }
1178
+ return touched;
1179
+ }
1180
+ /**
1181
+ * Repair the run record's timestamps with journaled values.
1182
+ *
1183
+ * `startRun` / `completeRun` / `errorRun` / `abortRun` stamp `Date.now()`
1184
+ * internally, and these records reach `ctx.set` through `save()` below — so a
1185
+ * live value here changes the state payload on a replay and kills the
1186
+ * invocation with `RestateError 570`. The loop repairs its own runs exactly
1187
+ * this way (`agent.ts`: `sessionRun.startedAt = runStartedAt`, `run.endedAt =
1188
+ * await clock.now()`); the merge path has to do the same.
1189
+ *
1190
+ * Sampling the parent's clock here is not an option: the drain runs inside a
1191
+ * hook the loop may abandon (`settledHook`), and an awaited journal op left in
1192
+ * flight is its own failure mode. Everything below is already journaled by the
1193
+ * time it reaches us — either measured by the child on ITS clock and carried
1194
+ * inside the journaled call result, or read from state the parent's own run
1195
+ * already wrote.
1196
+ */
1197
+ function stampJournaledRunTimes(session, entry, result) {
1198
+ const merged = session.runs.find((run) => run.id === entry.runId);
1199
+ if (!merged) return;
1200
+ const turns = result?.turns ?? [];
1201
+ const parentStartedAt = entry.parentRunId !== void 0 ? session.runs.find((run) => run.id === entry.parentRunId)?.startedAt : void 0;
1202
+ const startedAt = result?.startedAt ?? turns[0]?.createdAt ?? parentStartedAt;
1203
+ const endedAt = result?.endedAt ?? turns[turns.length - 1]?.createdAt ?? startedAt;
1204
+ if (startedAt !== void 0) merged.startedAt = startedAt;
1205
+ if (endedAt !== void 0) merged.endedAt = endedAt;
1206
+ }
1207
+ /**
1208
+ * Replay a finished child's transcript onto the PARENT's hook bus as `child:*`
1209
+ * events, so hosts that already render subagent activity (`src/output/
1210
+ * terminal.ts`, the GUI engine, any `child:tool:*` listener) light up for
1211
+ * parallel children without a single change.
1212
+ *
1213
+ * Not live \u2014 hook bubbling cannot cross an invocation boundary, so these fire
1214
+ * when the child finishes, in submission order. Everything here is derived
1215
+ * from the journaled call result, so a parent replay produces the identical
1216
+ * sequence; like the in-process tool's `child:tool:*`, they DO re-fire on that
1217
+ * replay, so hosts dedupe by `callId` / `turnId` or gate on
1218
+ * `createReplayTracker`.
1219
+ *
1220
+ * Only events that describe things the child actually did are synthesized.
1221
+ * `tool:gate` / `tool:transform` / `tool:dispatched` / `tool:cancelled` /
1222
+ * `background:*` describe decisions taken inside another process; inventing
1223
+ * them would be fiction, so they stay absent.
1224
+ */
1225
+ async function replayChildEvents(child, turns, ctx) {
1226
+ if (turns.length === 0) return;
1227
+ const outputs = /* @__PURE__ */ new Map();
1228
+ for (const turn of turns) for (const block of turn.content) if (block.type === "tool_result") outputs.set(block.callId, {
1229
+ output: block.output,
1230
+ ...block.isError !== void 0 ? { isError: block.isError } : {}
1231
+ });
1232
+ const childIdentity = {
1233
+ childId: child.label,
1234
+ depth: child.depth
1235
+ };
1236
+ const identity = {
1237
+ ...childIdentity,
1238
+ runId: child.runId,
1239
+ ...child.parentRunId !== void 0 ? { parentRunId: child.parentRunId } : {},
1240
+ parentCallId: child.callId
1241
+ };
1242
+ const runToolCounts = {};
1243
+ let assistantTurns = 0;
1244
+ for (const turn of turns) {
1245
+ if (turn.role !== "assistant") continue;
1246
+ assistantTurns += 1;
1247
+ const text = turn.content.filter((block) => block.type === "text").map((block) => block.text).join("");
1248
+ if (text.length > 0) await ctx.hooks.callHook("child:stream:text", {
1249
+ ...childIdentity,
1250
+ turnId: turn.id,
1251
+ delta: text,
1252
+ text
1253
+ });
1254
+ const turnToolCounts = {};
1255
+ for (const block of turn.content) {
1256
+ if (block.type !== "tool_call") continue;
1257
+ runToolCounts[block.name] = (runToolCounts[block.name] ?? 0) + 1;
1258
+ turnToolCounts[block.name] = (turnToolCounts[block.name] ?? 0) + 1;
1259
+ const base = {
1260
+ ...identity,
1261
+ turnId: turn.id,
1262
+ callId: block.id,
1263
+ name: block.name,
1264
+ displayName: block.name,
1265
+ input: block.input,
1266
+ runToolCounts: { ...runToolCounts }
1267
+ };
1268
+ await ctx.hooks.callHook("child:tool:before", base);
1269
+ const settled = outputs.get(block.id);
1270
+ if (settled === void 0) continue;
1271
+ if (settled.isError === true) {
1272
+ await ctx.hooks.callHook("child:tool:error", {
1273
+ ...base,
1274
+ error: new Error(toolResultToText(settled.output))
1275
+ });
1276
+ continue;
1277
+ }
1278
+ await ctx.hooks.callHook("child:tool:after", {
1279
+ ...base,
1280
+ result: settled.output,
1281
+ outputBytes: toolOutputByteLength(settled.output)
1282
+ });
1283
+ }
1284
+ const usage = turn.usage ?? {
1285
+ input: 0,
1286
+ output: 0
1287
+ };
1288
+ await ctx.hooks.callHook("child:turn:after", {
1289
+ ...childIdentity,
1290
+ turn: assistantTurns,
1291
+ turnId: turn.id,
1292
+ usage,
1293
+ message: turn,
1294
+ toolCounts: {
1295
+ turn: { ...turnToolCounts },
1296
+ run: { ...runToolCounts }
1297
+ }
1298
+ });
1299
+ await ctx.hooks.callHook("child:stream:end", {
1300
+ ...childIdentity,
1301
+ turnId: turn.id,
1302
+ text
1303
+ });
1304
+ }
1305
+ }
1306
+ function errorText(entry) {
1307
+ if (entry.failure !== void 0) return entry.failure instanceof Error ? entry.failure.message : String(entry.failure);
1308
+ return entry.result?.error ?? "sub-agent failed";
1309
+ }
1310
+ /**
1311
+ * Shape the model-facing result. Mirrors the in-process tool's wording so a
1312
+ * host or model tuned on one reads the other.
1313
+ *
1314
+ * `stats.elapsed` is safe to print here even though it is a live measurement:
1315
+ * the child measured it inside ITS invocation and it arrives in the journaled
1316
+ * call result, so the parent replays the same bytes. (Sampling it on the
1317
+ * parent side is what corrupts a transcript — see `docs/RESTATE.md`.)
1318
+ */
1319
+ /**
1320
+ * Arm the abort path for one child. Nothing is read off the dispatch promise:
1321
+ * touching its `invocationId` mid-flight would register a second consumer on
1322
+ * the runtime's progress channel (see `onAbort`'s note), so the hook gets
1323
+ * labels and the host cancels the tree.
1324
+ */
1325
+ function watchAbort(entry, ctx) {
1326
+ if (!options.onAbort) return;
1327
+ if (ctx.signal.aborted) {
1328
+ requestCancel(ctx);
1329
+ return;
1330
+ }
1331
+ const onAbort = () => requestCancel(ctx);
1332
+ ctx.signal.addEventListener("abort", onAbort, { once: true });
1333
+ entry.release = () => ctx.signal.removeEventListener("abort", onAbort);
1334
+ }
1335
+ /**
1336
+ * Fire the host's abort hook once for the whole in-flight set. Called once per
1337
+ * abort, not once per child: cancelling the tree is a single operation, and a
1338
+ * second call would append a redundant journal command.
1339
+ */
1340
+ function requestCancel(ctx) {
1341
+ const onAbort = options.onAbort;
1342
+ if (!onAbort || cancelSignalled) return;
1343
+ const inFlight = pending.filter((entry) => !entry.settled);
1344
+ if (inFlight.length === 0) return;
1345
+ cancelSignalled = true;
1346
+ for (const entry of inFlight) entry.cancelRequested = true;
1347
+ onAbort(inFlight.map((entry) => ({
1348
+ label: entry.label,
1349
+ task: entry.task,
1350
+ depth: entry.depth
1351
+ })), ctx);
1352
+ }
1353
+ function settle(entry, value, failure) {
1354
+ entry.settled = true;
1355
+ entry.release?.();
1356
+ if (failure !== void 0) {
1357
+ entry.failure = failure;
1358
+ if (entry.cancelRequested) return `[sub-agent ${entry.label}] Aborted (cancelled)`;
1359
+ return `[sub-agent ${entry.label}] Error: ${errorText(entry)}`;
1360
+ }
1361
+ const result = value ?? {
1362
+ status: "error",
1363
+ text: "",
1364
+ turns: [],
1365
+ stats: ZERO_STATS
1366
+ };
1367
+ entry.result = result;
1368
+ const head = `[sub-agent ${entry.label}]`;
1369
+ const usage = `Tokens: ${formatTokenUsage(result.stats)}`;
1370
+ if (result.status === "completed") return [
1371
+ `${head} Completed in ${result.stats.turns} turns (${result.stats.elapsed}ms)`,
1372
+ usage,
1373
+ "",
1374
+ result.text || "(no text response)"
1375
+ ].join("\n");
1376
+ if (result.status === "error") return `${head} Error: ${errorText(entry)}`;
1377
+ return [`${head} ${result.status === "timeout" ? "Timed out" : "Aborted"} after ${result.stats.turns} turns (${result.stats.elapsed}ms)`, usage].join("\n");
1378
+ }
1379
+ return {
1380
+ spec: {
1381
+ name: "spawn",
1382
+ description: options.description ?? DEFAULT_DESCRIPTION,
1383
+ inputSchema: {
1384
+ type: "object",
1385
+ properties: {
1386
+ task: {
1387
+ type: "string",
1388
+ description: "The self-contained task for the sub-agent."
1389
+ },
1390
+ model: {
1391
+ type: "string",
1392
+ description: "Optional model id for the sub-agent."
1393
+ },
1394
+ subagent_type: {
1395
+ type: "string",
1396
+ description: "Optional named sub-agent type."
1397
+ }
1398
+ },
1399
+ required: ["task"]
1400
+ }
1401
+ },
1402
+ isConcurrencySafe: true,
1403
+ runsNestedAgent: true,
1404
+ durableExecute: (input, ctx) => {
1405
+ const { req, entry } = prepare(input, ctx);
1406
+ const promise = options.dispatch(req, ctx);
1407
+ if (typeof promise.map !== "function") throw new TypeError("restateSpawnTool: `dispatch` must return the runtime's durable promise (e.g. `ctx.serviceClient(svc).runChild(req)`), which exposes `map`.");
1408
+ commit(entry, input, ctx);
1409
+ return promise.map((value, failure) => settle(entry, value, failure));
1410
+ },
1411
+ execute: async (input, ctx) => {
1412
+ const { req, entry } = prepare(input, ctx);
1413
+ const promise = options.dispatch(req, ctx);
1414
+ commit(entry, input, ctx);
1415
+ try {
1416
+ return settle(entry, await promise);
1417
+ } catch (err) {
1418
+ return settle(entry, void 0, err);
1419
+ }
1420
+ }
1421
+ };
1422
+ }
1423
+ //#endregion
968
1424
  //#region src/restate/tool-state.ts
969
1425
  /** Default virtual-object state key holding the tool-state map. */
970
1426
  const DEFAULT_TOOL_STATE_KEY = "zidane_tool_state";
@@ -1099,6 +1555,6 @@ function restateWaitBackground(options) {
1099
1555
  };
1100
1556
  }
1101
1557
  //#endregion
1102
- export { DEFAULT_TOOL_STATE_KEY, awakeableWithTimeout, createReplayTracker, deterministicUuid, replayAwareAbort, restateAwakeableTool, restateBehavior, restateClock, restateMcpToolWrap, restateProvider, restateSessionStore, restateTool, restateToolBatchExecutor, restateToolStateStore, restateWaitBackground, shouldRethrowRestateControlError, wrapAgentTools };
1558
+ export { DEFAULT_TOOL_STATE_KEY, awakeableWithTimeout, createReplayTracker, deterministicUuid, replayAwareAbort, restateAwakeableTool, restateBehavior, restateClock, restateMcpToolWrap, restateProvider, restateSessionStore, restateSpawnTool, restateTool, restateToolBatchExecutor, restateToolStateStore, restateWaitBackground, shouldRethrowRestateControlError, wrapAgentTools };
1103
1559
 
1104
1560
  //# sourceMappingURL=restate.js.map