eve 0.58.0 → 0.59.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 (196) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/README.md +1 -0
  3. package/dist/src/channel/session.d.ts +2 -0
  4. package/dist/src/channel/session.js +1 -1
  5. package/dist/src/channel/types.d.ts +8 -1
  6. package/dist/src/chunks/{use-eve-agent-X0asmJg-.js → use-eve-agent-Dmc6sX4d.js} +558 -233
  7. package/dist/src/chunks/{use-eve-agent-CxWcZCsU.js → use-eve-agent-jSR8P4nK.js} +565 -235
  8. package/dist/src/cli/dev/tui/runner.d.ts +4 -0
  9. package/dist/src/cli/dev/tui/runner.js +1 -1
  10. package/dist/src/cli/dev/tui/setup-issues.js +1 -1
  11. package/dist/src/cli/dev/tui/terminal-renderer.js +12 -12
  12. package/dist/src/client/eve-agent-projection.d.ts +10 -0
  13. package/dist/src/client/eve-agent-projection.js +1 -0
  14. package/dist/src/client/eve-agent-store-helpers.d.ts +6 -2
  15. package/dist/src/client/eve-agent-store-helpers.js +2 -2
  16. package/dist/src/client/eve-agent-store-state.d.ts +54 -1
  17. package/dist/src/client/eve-agent-store.d.ts +12 -82
  18. package/dist/src/client/eve-agent-store.js +1 -1
  19. package/dist/src/client/index.d.ts +2 -2
  20. package/dist/src/client/index.js +1 -1
  21. package/dist/src/client/message-response.d.ts +5 -1
  22. package/dist/src/client/message-response.js +1 -1
  23. package/dist/src/client/ndjson.d.ts +1 -0
  24. package/dist/src/client/ndjson.js +2 -2
  25. package/dist/src/client/open-stream.d.ts +4 -1
  26. package/dist/src/client/open-stream.js +1 -1
  27. package/dist/src/client/session-event-stream.d.ts +30 -0
  28. package/dist/src/client/session-event-stream.js +1 -0
  29. package/dist/src/client/session-utils.d.ts +2 -1
  30. package/dist/src/client/session-utils.js +1 -1
  31. package/dist/src/client/session.d.ts +14 -1
  32. package/dist/src/client/session.js +1 -1
  33. package/dist/src/client/sessions.d.ts +8 -2
  34. package/dist/src/client/sessions.js +1 -1
  35. package/dist/src/client/types.d.ts +7 -0
  36. package/dist/src/compiled/.vendor-stamp.json +2 -3
  37. package/dist/src/compiled/@vercel/sandbox/api-client/api-client.d.ts +88 -1
  38. package/dist/src/compiled/@vercel/sandbox/api-client/index.d.ts +1 -1
  39. package/dist/src/compiled/@vercel/sandbox/api-client/validators.d.ts +41 -1
  40. package/dist/src/compiled/@vercel/sandbox/constants.d.ts +3 -3
  41. package/dist/src/compiled/@vercel/{sandbox-drives → sandbox}/drive.d.ts +13 -2
  42. package/dist/src/compiled/@vercel/sandbox/index.d.ts +3 -2
  43. package/dist/src/compiled/@vercel/sandbox/index.js +15 -9
  44. package/dist/src/compiled/@vercel/sandbox/sandbox.d.ts +40 -5
  45. package/dist/src/compiled/_chunks/node/auth-DDrvYko5.js +2 -0
  46. package/dist/src/compiled/_chunks/node/version-C__MqbLM.js +1 -0
  47. package/dist/src/compiler/extension-compatibility.d.ts +14 -14
  48. package/dist/src/compiler/extension-compatibility.js +1 -1
  49. package/dist/src/context/build-dynamic-tools.js +1 -1
  50. package/dist/src/context/dynamic-tool-lifecycle.js +1 -1
  51. package/dist/src/context/memory-tools.js +1 -1
  52. package/dist/src/evals/context.d.ts +1 -1
  53. package/dist/src/evals/context.js +1 -1
  54. package/dist/src/evals/define-eval.d.ts +1 -1
  55. package/dist/src/evals/define-eval.js +1 -1
  56. package/dist/src/evals/index.js +1 -1
  57. package/dist/src/evals/judge.d.ts +1 -1
  58. package/dist/src/evals/runner/execute-task.d.ts +1 -1
  59. package/dist/src/evals/runner/execute-task.js +1 -1
  60. package/dist/src/evals/session-manager.d.ts +27 -0
  61. package/dist/src/evals/session-manager.js +1 -0
  62. package/dist/src/evals/session.d.ts +8 -28
  63. package/dist/src/evals/session.js +2 -1
  64. package/dist/src/evals/target.d.ts +1 -1
  65. package/dist/src/evals/target.js +1 -1
  66. package/dist/src/evals/types.d.ts +19 -15
  67. package/dist/src/eve-channel/create-request.d.ts +24 -0
  68. package/dist/src/eve-channel/create-request.js +1 -0
  69. package/dist/src/eve-channel/index.js +1 -1
  70. package/dist/src/eve-channel/request.d.ts +3 -12
  71. package/dist/src/eve-channel/request.js +2 -2
  72. package/dist/src/eve-channel/types.d.ts +4 -2
  73. package/dist/src/execution/dynamic-workflow/tool.js +1 -1
  74. package/dist/src/execution/legacy-session/turn-workflow.js +1 -1
  75. package/dist/src/execution/runtime-context.js +1 -1
  76. package/dist/src/execution/sandbox/bindings/vercel-lifecycle.d.ts +3 -3
  77. package/dist/src/execution/sandbox/bindings/vercel-lifecycle.js +1 -1
  78. package/dist/src/execution/sandbox/bindings/vercel-sdk-types.d.ts +1 -4
  79. package/dist/src/execution/sandbox/bindings/vercel.d.ts +1 -2
  80. package/dist/src/execution/sandbox/bindings/vercel.js +1 -1
  81. package/dist/src/execution/session/entry.js +1 -1
  82. package/dist/src/execution/session/handoff-steps.js +1 -1
  83. package/dist/src/execution/session/program.d.ts +2 -0
  84. package/dist/src/execution/session/program.js +1 -1
  85. package/dist/src/execution/session/turn-step.js +1 -1
  86. package/dist/src/execution/session/turn.js +1 -1
  87. package/dist/src/execution/session-inbox/protocol.js +1 -1
  88. package/dist/src/execution/tools/connection-search.js +1 -1
  89. package/dist/src/execution/tools/sleep-workflow.js +1 -1
  90. package/dist/src/execution/workflow-runtime.js +1 -1
  91. package/dist/src/experimental/evaluate/auto-model.js +2 -2
  92. package/dist/src/experimental/evaluate/evaluate.d.ts +7 -0
  93. package/dist/src/experimental/evaluate/evaluate.js +1 -0
  94. package/dist/src/harness/compaction.d.ts +3 -3
  95. package/dist/src/harness/compaction.js +1 -1
  96. package/dist/src/harness/request-envelope.d.ts +11 -0
  97. package/dist/src/harness/request-envelope.js +1 -0
  98. package/dist/src/harness/tool-loop.js +2 -2
  99. package/dist/src/instrumentation/prepare-trace-context.d.ts +2 -1
  100. package/dist/src/instrumentation/prepare-trace-context.js +1 -1
  101. package/dist/src/internal/application/package.js +1 -1
  102. package/dist/src/internal/authored-module-loader.d.ts +4 -1
  103. package/dist/src/internal/authored-module-loader.js +1 -1
  104. package/dist/src/internal/bundler/nitro-rolldown.d.ts +2 -0
  105. package/dist/src/internal/model-auth/transport.d.ts +3 -1
  106. package/dist/src/internal/model-auth/transport.js +1 -1
  107. package/dist/src/internal/nitro/host/build-extension.js +1 -1
  108. package/dist/src/internal/nitro/host/extension-capability-requirements.d.ts +1 -0
  109. package/dist/src/internal/nitro/host/extension-capability-requirements.js +1 -1
  110. package/dist/src/internal/nitro/host/extension-distribution.d.ts +1 -1
  111. package/dist/src/internal/nitro/host/extension-distribution.js +1 -1
  112. package/dist/src/internal/workflow-bundle/dynamic-tool-transform.js +1 -1
  113. package/dist/src/public/experimental/evaluate/index.d.ts +1 -0
  114. package/dist/src/public/experimental/evaluate/index.js +1 -1
  115. package/dist/src/public/models/anthropic/index.js +1 -1
  116. package/dist/src/public/sandbox/vercel-sandbox.d.ts +1 -1
  117. package/dist/src/public/sandbox/vercel.d.ts +1 -1
  118. package/dist/src/public/sandbox/vercel.js +1 -1
  119. package/dist/src/public/tools/index.d.ts +1 -0
  120. package/dist/src/public/tools/index.js +1 -1
  121. package/dist/src/react/use-eve-agent.d.ts +4 -0
  122. package/dist/src/react/use-eve-agent.js +1 -1
  123. package/dist/src/runtime/agent/resolve-model.js +1 -1
  124. package/dist/src/setup/flows/model-login-connection.js +1 -1
  125. package/dist/src/setup/scaffold/create/project.js +1 -1
  126. package/dist/src/subagents/handle-dispatch.js +1 -1
  127. package/dist/src/svelte/index.js +1 -1
  128. package/dist/src/svelte/use-eve-agent.d.ts +4 -0
  129. package/dist/src/svelte/use-eve-agent.js +1 -1
  130. package/dist/src/tools/definition.d.ts +2 -0
  131. package/dist/src/tools/definition.js +1 -1
  132. package/dist/src/tools/durable-callbacks.d.ts +8 -2
  133. package/dist/src/tools/durable-callbacks.js +1 -1
  134. package/dist/src/tools/durable-schema.d.ts +16 -0
  135. package/dist/src/tools/durable-schema.js +1 -0
  136. package/dist/src/vue/index.js +1 -1
  137. package/dist/src/vue/use-eve-agent.d.ts +4 -0
  138. package/dist/src/vue/use-eve-agent.js +1 -1
  139. package/docs/README.md +1 -0
  140. package/docs/channels/eve.mdx +20 -10
  141. package/docs/concepts/context-control.md +4 -0
  142. package/docs/concepts/sessions-runs-and-streaming.md +18 -3
  143. package/docs/evals/assertions.mdx +6 -6
  144. package/docs/evals/cases.mdx +59 -23
  145. package/docs/evals/judge.mdx +10 -8
  146. package/docs/evals/overview.mdx +6 -6
  147. package/docs/evals/reporters.mdx +1 -1
  148. package/docs/evals/targets.mdx +5 -0
  149. package/docs/guides/client/messages.mdx +5 -5
  150. package/docs/guides/client/overview.mdx +15 -1
  151. package/docs/guides/dynamic-capabilities.md +22 -0
  152. package/docs/guides/evaluate.md +58 -4
  153. package/docs/guides/frontend/overview.mdx +54 -5
  154. package/docs/guides/frontend/use-eve-agent-svelte.mdx +13 -8
  155. package/docs/guides/frontend/use-eve-agent-vue.mdx +13 -8
  156. package/docs/reference/typescript-api.md +38 -36
  157. package/package.json +2 -3
  158. package/dist/src/compiled/@vercel/sandbox-drives/LICENSE +0 -201
  159. package/dist/src/compiled/@vercel/sandbox-drives/_async-retry.d.ts +0 -8
  160. package/dist/src/compiled/@vercel/sandbox-drives/_workflow-serde.d.ts +0 -5
  161. package/dist/src/compiled/@vercel/sandbox-drives/api-client/api-client.d.ts +0 -1815
  162. package/dist/src/compiled/@vercel/sandbox-drives/api-client/api-error.d.ts +0 -29
  163. package/dist/src/compiled/@vercel/sandbox-drives/api-client/base-client.d.ts +0 -39
  164. package/dist/src/compiled/@vercel/sandbox-drives/api-client/file-writer.d.ts +0 -66
  165. package/dist/src/compiled/@vercel/sandbox-drives/api-client/index.d.ts +0 -2
  166. package/dist/src/compiled/@vercel/sandbox-drives/api-client/validators.d.ts +0 -932
  167. package/dist/src/compiled/@vercel/sandbox-drives/api-client/with-retry.d.ts +0 -10
  168. package/dist/src/compiled/@vercel/sandbox-drives/auth/error.d.ts +0 -15
  169. package/dist/src/compiled/@vercel/sandbox-drives/auth/file.d.ts +0 -18
  170. package/dist/src/compiled/@vercel/sandbox-drives/auth/index.d.ts +0 -6
  171. package/dist/src/compiled/@vercel/sandbox-drives/auth/oauth.d.ts +0 -111
  172. package/dist/src/compiled/@vercel/sandbox-drives/auth/poll-for-token.d.ts +0 -28
  173. package/dist/src/compiled/@vercel/sandbox-drives/auth/project.d.ts +0 -40
  174. package/dist/src/compiled/@vercel/sandbox-drives/command.d.ts +0 -292
  175. package/dist/src/compiled/@vercel/sandbox-drives/constants.d.ts +0 -15
  176. package/dist/src/compiled/@vercel/sandbox-drives/execution-context.d.ts +0 -116
  177. package/dist/src/compiled/@vercel/sandbox-drives/filesystem.d.ts +0 -258
  178. package/dist/src/compiled/@vercel/sandbox-drives/index.d.ts +0 -14
  179. package/dist/src/compiled/@vercel/sandbox-drives/index.js +0 -9
  180. package/dist/src/compiled/@vercel/sandbox-drives/network-policy.d.ts +0 -169
  181. package/dist/src/compiled/@vercel/sandbox-drives/proxy.d.ts +0 -55
  182. package/dist/src/compiled/@vercel/sandbox-drives/sandbox-user.d.ts +0 -211
  183. package/dist/src/compiled/@vercel/sandbox-drives/sandbox.d.ts +0 -1287
  184. package/dist/src/compiled/@vercel/sandbox-drives/session.d.ts +0 -435
  185. package/dist/src/compiled/@vercel/sandbox-drives/snapshot.d.ts +0 -238
  186. package/dist/src/compiled/@vercel/sandbox-drives/utils/get-credentials.d.ts +0 -21
  187. package/dist/src/compiled/@vercel/sandbox-drives/utils/paginator.d.ts +0 -16
  188. package/dist/src/compiled/@vercel/sandbox-drives/utils/resolveSignal.d.ts +0 -15
  189. package/dist/src/compiled/@vercel/sandbox-drives/utils/sandbox-snapshot.d.ts +0 -11
  190. package/dist/src/compiled/@vercel/sandbox-drives/utils/types.d.ts +0 -11
  191. package/dist/src/compiled/_chunks/node/auth-8aQozzfi.js +0 -2
  192. package/dist/src/compiled/_chunks/node/auth-Bvv0xGTY.js +0 -2
  193. package/dist/src/compiled/_chunks/node/esm-Fqlolk7e.js +0 -7
  194. package/dist/src/compiled/_chunks/node/version-BC6t2Txc.js +0 -1
  195. package/dist/src/compiled/_chunks/node/version-DSQqVZ5T.js +0 -1
  196. package/dist/src/compiled/_chunks/node/xdg-app-paths-F-QHrdza.js +0 -1
@@ -686,17 +686,6 @@ function isTurnFailureEvent(event) {
686
686
  return event.type === "session.failed" || event.type === "step.failed" || event.type === "turn.failed";
687
687
  }
688
688
 
689
- //#endregion
690
- //#region src/client/output-schema.ts
691
- function extractCompletedResult(events) {
692
- let result;
693
- for (const event of events) if (isResultCompletedEvent(event)) result = event.data.result;
694
- return result;
695
- }
696
- function isResultCompletedEvent(event) {
697
- return event.type === "result.completed";
698
- }
699
-
700
689
  //#endregion
701
690
  //#region src/client/session-utils.ts
702
691
  function summarizeTurnEvents(events) {
@@ -725,9 +714,25 @@ function summarizeTurnEvents(events) {
725
714
  function isFinalMessageCompleted(event) {
726
715
  return event.type === "message.completed" && event.data.finishReason !== "tool-calls";
727
716
  }
717
+ function updatePendingAuthorizations(pending, event) {
718
+ if (event.type === "authorization.required" && event.data.webhookUrl !== void 0) pending.add(event.data.name);
719
+ else if (event.type === "authorization.completed") pending.delete(event.data.name);
720
+ }
721
+
722
+ //#endregion
723
+ //#region src/client/output-schema.ts
724
+ function extractCompletedResult(events) {
725
+ let result;
726
+ for (const event of events) if (isResultCompletedEvent(event)) result = event.data.result;
727
+ return result;
728
+ }
729
+ function isResultCompletedEvent(event) {
730
+ return event.type === "result.completed";
731
+ }
728
732
 
729
733
  //#endregion
730
734
  //#region src/client/message-response.ts
735
+ const consumeResponse = Symbol("consumeMessageResponse");
731
736
  var MessageResponse = class {
732
737
  sessionId;
733
738
  #cancelTurn;
@@ -765,13 +770,16 @@ var MessageResponse = class {
765
770
  };
766
771
  }
767
772
  [Symbol.asyncIterator]() {
773
+ return this[consumeResponse]();
774
+ }
775
+ [consumeResponse](source) {
768
776
  if (this.#consumed) throw new Error("MessageResponse has already been consumed.");
769
777
  this.#consumed = true;
770
- return this.#observeStream();
778
+ return this.#observeStream(source);
771
779
  }
772
- async *#observeStream() {
780
+ async *#observeStream(source) {
773
781
  try {
774
- for await (const event of this.#createStream()) {
782
+ for await (const event of this.#createStream(source)) {
775
783
  if (event.type === "turn.started") this.#turnId.resolve(event.data.turnId);
776
784
  else if (isCurrentTurnBoundaryEvent(event)) {
777
785
  this.#settled = true;
@@ -784,6 +792,9 @@ var MessageResponse = class {
784
792
  }
785
793
  }
786
794
  };
795
+ function consumeMessageResponse(response, source) {
796
+ return response[consumeResponse](source);
797
+ }
787
798
 
788
799
  //#endregion
789
800
  //#region src/protocol/message-version.ts
@@ -893,9 +904,15 @@ async function* readNdjsonStream(body, options) {
893
904
  const decoder = new TextDecoder();
894
905
  let buffer = "";
895
906
  let reachedEof = false;
907
+ const abort = () => {
908
+ reader.cancel().catch(() => {});
909
+ };
910
+ options.signal?.addEventListener("abort", abort, { once: true });
896
911
  try {
897
912
  while (true) {
913
+ options.signal?.throwIfAborted();
898
914
  const result = await readWithIdleTimeout(reader, options?.idleTimeoutMs);
915
+ options.signal?.throwIfAborted();
899
916
  if (result.done) {
900
917
  reachedEof = true;
901
918
  buffer += decoder.decode();
@@ -921,6 +938,7 @@ async function* readNdjsonStream(body, options) {
921
938
  else yield parseMessageStreamEvent(value, options.streamVersion);
922
939
  }
923
940
  } finally {
941
+ options.signal?.removeEventListener("abort", abort);
924
942
  if (!reachedEof) reader.cancel().catch(() => {});
925
943
  reader.releaseLock();
926
944
  }
@@ -1065,45 +1083,56 @@ function resolveRetryPolicy(policy, defaults) {
1065
1083
  ...policy
1066
1084
  };
1067
1085
  }
1068
- function resolveStreamReconnectPolicy(policy) {
1086
+ function resolveStreamReconnectPolicy(policy, keepAlive = false) {
1069
1087
  if (policy && "reconnect" in policy && policy.reconnect === false) return NO_STREAM_RECONNECT_POLICY;
1070
1088
  const configured = policy;
1071
1089
  return {
1072
1090
  retryableErrorStatuses: configured?.retryableErrorStatuses ? new Set(configured.retryableErrorStatuses) : DEFAULT_STREAM_RECONNECT_POLICY.retryableErrorStatuses,
1073
- streamIdleReconnectPolicy: resolveRetryPolicy(configured?.streamIdleReconnectPolicy, DEFAULT_STREAM_RECONNECT_POLICY.streamIdleReconnectPolicy),
1091
+ streamIdleReconnectPolicy: resolveRetryPolicy(configured?.streamIdleReconnectPolicy, {
1092
+ ...DEFAULT_STREAM_RECONNECT_POLICY.streamIdleReconnectPolicy,
1093
+ maxAttempts: keepAlive ? Infinity : DEFAULT_STREAM_RECONNECT_POLICY.streamIdleReconnectPolicy.maxAttempts
1094
+ }),
1074
1095
  streamOpenReconnectPolicy: resolveRetryPolicy(configured?.streamOpenReconnectPolicy, DEFAULT_STREAM_RECONNECT_POLICY.streamOpenReconnectPolicy)
1075
1096
  };
1076
1097
  }
1077
1098
  async function* followStreamIterable(input) {
1078
1099
  if (input.follow === false && input.startIndex < 0) throw new Error("stream({ follow: false }) requires a nonnegative startIndex; a tail-relative cursor cannot be bounded.");
1079
- const retryPolicy = resolveStreamReconnectPolicy(input.streamReconnectPolicy);
1080
- const idleRetryPolicy = retryPolicy.streamIdleReconnectPolicy;
1100
+ const resolvePolicy = () => resolveStreamReconnectPolicy(input.resolveReconnectPolicy === void 0 ? input.streamReconnectPolicy : input.resolveReconnectPolicy(), input.keepAlive);
1101
+ let retryPolicy = resolvePolicy();
1102
+ let idleRetryPolicy = retryPolicy.streamIdleReconnectPolicy;
1081
1103
  let startIndex = input.startIndex;
1082
1104
  let reconnectDelayMs = idleRetryPolicy.baseDelayMs;
1083
1105
  let idleReconnects = 0;
1084
1106
  let initialConnection = true;
1085
1107
  let tailIndex;
1108
+ let caughtUp = false;
1086
1109
  while (true) {
1110
+ retryPolicy = resolvePolicy();
1111
+ idleRetryPolicy = retryPolicy.streamIdleReconnectPolicy;
1087
1112
  let connection;
1088
1113
  try {
1089
1114
  connection = await openStreamBody({
1090
1115
  ...input,
1091
1116
  retryPolicy,
1092
1117
  startIndex,
1093
- requestTailIndex: input.follow === false && tailIndex === void 0
1118
+ requestTailIndex: (input.follow === false || input.onCaughtUp !== void 0) && tailIndex === void 0
1094
1119
  });
1095
1120
  } catch (error) {
1096
1121
  if (input.signal?.aborted) return;
1097
1122
  throw error;
1098
1123
  }
1099
- if (input.follow === false && tailIndex === void 0) {
1124
+ if ((input.follow === false || input.onCaughtUp !== void 0) && tailIndex === void 0) {
1100
1125
  tailIndex = connection.tailIndex;
1101
1126
  if (tailIndex === void 0) {
1102
1127
  connection.close();
1103
1128
  throw new Error(`stream({ follow: false }) requires the server to report the ${EVE_STREAM_TAIL_INDEX_HEADER} header. The agent may be running an older eve version.`);
1104
1129
  }
1105
1130
  }
1106
- if (tailIndex !== void 0 && startIndex > tailIndex) {
1131
+ if (!caughtUp && tailIndex !== void 0 && startIndex > tailIndex) {
1132
+ caughtUp = true;
1133
+ input.onCaughtUp?.();
1134
+ }
1135
+ if (input.follow === false && tailIndex !== void 0 && startIndex > tailIndex) {
1107
1136
  connection.close();
1108
1137
  return;
1109
1138
  }
@@ -1111,6 +1140,7 @@ async function* followStreamIterable(input) {
1111
1140
  let leaseEnded = false;
1112
1141
  try {
1113
1142
  for await (const event of readNdjsonStream(connection.body, {
1143
+ signal: input.signal,
1114
1144
  controlVersion: connection.controlVersion,
1115
1145
  idleTimeoutMs: input.streamReadIdleTimeoutMs ?? DEFAULT_STREAM_READ_IDLE_TIMEOUT_MS,
1116
1146
  onLeaseEnded: () => {
@@ -1123,16 +1153,21 @@ async function* followStreamIterable(input) {
1123
1153
  reconnectDelayMs = idleRetryPolicy.baseDelayMs;
1124
1154
  idleReconnects = 0;
1125
1155
  yield event;
1126
- if (tailIndex !== void 0 && startIndex > tailIndex) return;
1156
+ if (!caughtUp && tailIndex !== void 0 && startIndex > tailIndex) {
1157
+ caughtUp = true;
1158
+ input.onCaughtUp?.();
1159
+ }
1160
+ if (input.follow === false && tailIndex !== void 0 && startIndex > tailIndex) return;
1127
1161
  }
1128
1162
  } catch (error) {
1129
1163
  if (!isStreamDisconnectError(error)) throw error;
1130
1164
  } finally {
1131
1165
  connection.close();
1132
1166
  }
1167
+ idleRetryPolicy = resolvePolicy().streamIdleReconnectPolicy;
1133
1168
  if (input.signal?.aborted || input.startIndex < 0 || idleRetryPolicy.maxAttempts === 0) return;
1134
1169
  if (leaseEnded) continue;
1135
- if (input.keepAlive !== true && !deliveredEvent && !initialConnection && (idleReconnects += 1) >= idleRetryPolicy.maxAttempts) return;
1170
+ if (!deliveredEvent && !initialConnection && (idleReconnects += 1) >= idleRetryPolicy.maxAttempts) return;
1136
1171
  initialConnection = false;
1137
1172
  await sleep(reconnectDelayMs, input.signal);
1138
1173
  if (input.signal?.aborted) return;
@@ -1140,7 +1175,7 @@ async function* followStreamIterable(input) {
1140
1175
  }
1141
1176
  }
1142
1177
  async function openStreamBody(input) {
1143
- const retryPolicy = input.retryPolicy ?? resolveStreamReconnectPolicy(input.streamReconnectPolicy);
1178
+ const retryPolicy = input.retryPolicy ?? resolveStreamReconnectPolicy(input.streamReconnectPolicy, input.keepAlive);
1144
1179
  const openRetryPolicy = retryPolicy.streamOpenReconnectPolicy;
1145
1180
  let lastStatus;
1146
1181
  let lastBody;
@@ -1152,8 +1187,10 @@ async function openStreamBody(input) {
1152
1187
  if (input.startIndex !== 0) searchParams.startIndex = String(input.startIndex);
1153
1188
  if (input.requestTailIndex === true) searchParams.includeTailIndex = "1";
1154
1189
  for (let attempt = 0; attempt < openRetryPolicy.maxAttempts; attempt += 1) {
1190
+ input.signal?.throwIfAborted();
1155
1191
  const url = createClientUrl(input.host, createEveSessionStreamRoutePath(input.sessionId), Object.keys(searchParams).length > 0 ? searchParams : void 0);
1156
1192
  const headers = await input.resolveHeaders();
1193
+ input.signal?.throwIfAborted();
1157
1194
  const connectionController = new AbortController();
1158
1195
  const signal = input.signal ? AbortSignal.any([input.signal, connectionController.signal]) : connectionController.signal;
1159
1196
  let response;
@@ -1434,8 +1471,10 @@ function getStandardSchemaProperties(value) {
1434
1471
 
1435
1472
  //#endregion
1436
1473
  //#region src/client/session.ts
1437
- const SESSION_SEND_RETRY_COUNT = 3;
1438
1474
  const SESSION_SEND_RETRY_BASE_DELAY_MS = 250;
1475
+ const SESSION_SEND_RETRY_MAX_DELAY_MS = 2e3;
1476
+ const SESSION_SEND_READY_TIMEOUT_MS = 2e4;
1477
+ const followSession = Symbol("followClientSession");
1439
1478
  var ClientSession = class ClientSession {
1440
1479
  #context;
1441
1480
  #state;
@@ -1455,6 +1494,13 @@ var ClientSession = class ClientSession {
1455
1494
  session
1456
1495
  };
1457
1496
  }
1497
+ static async prewarm(context, options = {}) {
1498
+ const { sessionId } = await readAcceptedMessage(await postCreateSession(context, options));
1499
+ return new ClientSession(context, {
1500
+ sessionId,
1501
+ streamIndex: 0
1502
+ });
1503
+ }
1458
1504
  get state() {
1459
1505
  return this.#state;
1460
1506
  }
@@ -1488,10 +1534,10 @@ var ClientSession = class ClientSession {
1488
1534
  inputResponses
1489
1535
  }, false);
1490
1536
  }
1491
- async #send(input, retrySessionNotActive) {
1537
+ async #send(input, retrySessionNotReady) {
1492
1538
  const initialStreamIndex = this.#state.streamIndex;
1493
1539
  const path = createEveSessionRoutePath(this.#state.sessionId);
1494
- const response = retrySessionNotActive ? await postSessionSend(this.#context, path, input) : await postTurn(this.#context, path, input, false);
1540
+ const response = retrySessionNotReady ? await postSessionSend(this.#context, path, input) : await postTurn(this.#context, path, input, false);
1495
1541
  const { sessionId: responseSessionId, deliveryId } = await readAcceptedMessage(response, this.#state.sessionId);
1496
1542
  if (responseSessionId !== this.#state.sessionId) throw new Error("Message route returned a different session id.");
1497
1543
  if (input.message !== void 0 && deliveryId === void 0) throw new Error("Message route did not return a delivery id. Update the server before sending with this client.");
@@ -1527,23 +1573,29 @@ var ClientSession = class ClientSession {
1527
1573
  if (options?.follow === false && (options.startIndex ?? this.#state.streamIndex) < 0) throw new Error("stream({ follow: false }) requires a nonnegative startIndex; a tail-relative cursor cannot be bounded.");
1528
1574
  return this.#streamAndAdvance(options);
1529
1575
  }
1576
+ [followSession](options) {
1577
+ return this.#streamAndAdvance({
1578
+ ...options,
1579
+ keepAlive: true
1580
+ });
1581
+ }
1530
1582
  #messageResponse(response, input, initialStreamIndex, deliveryId) {
1531
1583
  response.body?.cancel().catch(() => {});
1532
1584
  return new MessageResponse({
1533
1585
  cancelTurn: async (turnId) => await this.cancel({ turnId }),
1534
- createStream: () => this.#createEventStream(initialStreamIndex, input, deliveryId),
1586
+ createStream: (source) => this.#createEventStream(initialStreamIndex, input, deliveryId, source),
1535
1587
  sessionId: this.#state.sessionId
1536
1588
  });
1537
1589
  }
1538
- async *#createEventStream(initialStreamIndex, input, deliveryId) {
1590
+ async *#createEventStream(initialStreamIndex, input, deliveryId, source) {
1539
1591
  let eventCount = 0;
1540
1592
  let started = deliveryId === void 0;
1541
1593
  let reachedBoundary = false;
1542
1594
  const pendingAuthorizations = /* @__PURE__ */ new Set();
1543
1595
  try {
1544
- for await (const event of this.#readStream({
1596
+ for await (const event of source ?? this.#readStream({
1545
1597
  headers: input.headers,
1546
- keepAlive: shouldKeepActiveTurnAlive(input.streamReconnectPolicy),
1598
+ keepAlive: true,
1547
1599
  signal: input.signal,
1548
1600
  startIndex: initialStreamIndex,
1549
1601
  streamReconnectPolicy: input.streamReconnectPolicy
@@ -1557,73 +1609,92 @@ var ClientSession = class ClientSession {
1557
1609
  if (!terminal && event.meta?.deliveryIds !== void 0 && !matches) continue;
1558
1610
  started = true;
1559
1611
  }
1560
- if (event.type === "authorization.required" && event.data.webhookUrl !== void 0) pendingAuthorizations.add(event.data.name);
1561
- else if (event.type === "authorization.completed") pendingAuthorizations.delete(event.data.name);
1612
+ updatePendingAuthorizations(pendingAuthorizations, event);
1562
1613
  reachedBoundary = isCurrentTurnBoundaryEvent(event) && (event.type !== "session.waiting" || pendingAuthorizations.size === 0);
1563
1614
  yield event;
1564
1615
  if (reachedBoundary) break;
1565
1616
  }
1566
1617
  if (deliveryId !== void 0 && !reachedBoundary && !input.signal?.aborted) throw new Error("The response stream ended before the accepted message reached its turn boundary.");
1567
1618
  } finally {
1568
- this.#state = {
1569
- sessionId: this.#state.sessionId,
1570
- streamIndex: Math.max(this.#state.streamIndex, initialStreamIndex + eventCount)
1571
- };
1619
+ this.#advanceStreamIndex(initialStreamIndex + eventCount);
1572
1620
  }
1573
1621
  }
1574
1622
  async *#streamAndAdvance(options) {
1575
1623
  const startIndex = options?.startIndex ?? this.#state.streamIndex;
1576
1624
  let eventCount = 0;
1577
- try {
1578
- for await (const event of this.#readStream({
1579
- follow: options?.follow,
1580
- signal: options?.signal,
1581
- startIndex,
1582
- streamReconnectPolicy: options?.streamReconnectPolicy
1583
- })) {
1584
- eventCount += 1;
1585
- yield event;
1586
- }
1587
- } finally {
1588
- if (startIndex >= 0) this.#state = {
1589
- sessionId: this.#state.sessionId,
1590
- streamIndex: startIndex + eventCount
1591
- };
1625
+ for await (const event of this.#readStream({
1626
+ follow: options?.follow,
1627
+ headers: options?.headers,
1628
+ keepAlive: options?.keepAlive,
1629
+ onCaughtUp: options?.onCaughtUp,
1630
+ resolveHeaders: options?.resolveHeaders,
1631
+ resolveReconnectPolicy: options?.resolveReconnectPolicy,
1632
+ signal: options?.signal,
1633
+ startIndex,
1634
+ streamReconnectPolicy: options?.streamReconnectPolicy
1635
+ })) {
1636
+ eventCount += 1;
1637
+ if (startIndex >= 0) this.#advanceStreamIndex(startIndex + eventCount);
1638
+ yield event;
1592
1639
  }
1593
1640
  }
1641
+ #advanceStreamIndex(streamIndex) {
1642
+ this.#state = {
1643
+ sessionId: this.#state.sessionId,
1644
+ streamIndex: Math.max(this.#state.streamIndex, streamIndex)
1645
+ };
1646
+ }
1594
1647
  #readStream(input) {
1595
1648
  return followStreamIterable({
1649
+ onCaughtUp: input.onCaughtUp,
1596
1650
  follow: input.follow,
1597
1651
  host: this.#context.host,
1598
1652
  keepAlive: input.keepAlive,
1599
- resolveHeaders: () => this.#context.resolveHeaders(input.headers),
1653
+ resolveHeaders: () => this.#context.resolveHeaders(input.resolveHeaders?.() ?? input.headers),
1600
1654
  redirect: this.#context.redirect,
1601
1655
  sessionId: this.#state.sessionId,
1602
1656
  signal: input.signal,
1603
1657
  startIndex: input.startIndex,
1604
- streamReconnectPolicy: input.streamReconnectPolicy
1658
+ streamReconnectPolicy: input.streamReconnectPolicy,
1659
+ resolveReconnectPolicy: input.resolveReconnectPolicy
1605
1660
  });
1606
1661
  }
1607
1662
  };
1663
+ function followClientSession(session, options) {
1664
+ return session[followSession](options);
1665
+ }
1608
1666
  async function postSessionSend(context, path, input) {
1667
+ const readyDeadline = Date.now() + SESSION_SEND_READY_TIMEOUT_MS;
1609
1668
  let retryDelayMs = SESSION_SEND_RETRY_BASE_DELAY_MS;
1610
- for (let retry = 0;; retry += 1) {
1669
+ for (;;) {
1611
1670
  try {
1612
1671
  return await postTurn(context, path, input, false);
1613
1672
  } catch (error) {
1614
- if (!isSessionNotActive(error) || retry >= SESSION_SEND_RETRY_COUNT) throw error;
1673
+ if (!isSessionNotReady(error)) throw error;
1674
+ const remainingMs = readyDeadline - Date.now();
1675
+ if (remainingMs <= 0) throw error;
1676
+ await sleep(Math.min(retryDelayMs, remainingMs), input.signal);
1615
1677
  }
1616
- await sleep(retryDelayMs, input.signal);
1617
1678
  input.signal?.throwIfAborted();
1618
- retryDelayMs *= 2;
1679
+ retryDelayMs = Math.min(retryDelayMs * 2, SESSION_SEND_RETRY_MAX_DELAY_MS);
1619
1680
  }
1620
1681
  }
1621
- function isSessionNotActive(error) {
1622
- return error instanceof ClientError && error.status === 409 && error.code === "session_not_active";
1682
+ async function postCreateSession(context, options) {
1683
+ const headers = await context.resolveHeaders(options.headers);
1684
+ const response = await fetch(createClientUrl(context.host, EVE_SESSION_ROUTE_PATH), {
1685
+ headers,
1686
+ method: "POST",
1687
+ redirect: context.redirect,
1688
+ signal: options.signal ?? null
1689
+ });
1690
+ if (!response.ok) {
1691
+ const responseBody = await response.text();
1692
+ throw new ClientError(response.status, responseBody, response.headers);
1693
+ }
1694
+ return response;
1623
1695
  }
1624
- function shouldKeepActiveTurnAlive(policy) {
1625
- if (policy && "reconnect" in policy) return false;
1626
- return policy?.streamIdleReconnectPolicy?.maxAttempts === void 0;
1696
+ function isSessionNotReady(error) {
1697
+ return error instanceof ClientError && error.status === 409 && error.code === "session_not_ready";
1627
1698
  }
1628
1699
  async function postTurn(context, path, input, requireMessage) {
1629
1700
  const body = createMessageBody(input, requireMessage);
@@ -1672,8 +1743,9 @@ var ClientSessions = class {
1672
1743
  constructor(context) {
1673
1744
  this.#context = context;
1674
1745
  }
1675
- async create(input) {
1676
- return await ClientSession.create(this.#context, input);
1746
+ async create(input = {}) {
1747
+ if ("message" in input) return await ClientSession.create(this.#context, input);
1748
+ return { session: await ClientSession.prewarm(this.#context, input) };
1677
1749
  }
1678
1750
  attach(sessionId, options) {
1679
1751
  if (sessionId.length === 0) throw new Error("sessionId must be a non-empty string.");
@@ -1803,6 +1875,151 @@ function withRedirectPolicy(init, redirect) {
1803
1875
  };
1804
1876
  }
1805
1877
 
1878
+ //#endregion
1879
+ //#region src/client/session-event-stream.ts
1880
+ var SessionEventStream = class {
1881
+ #controller = new AbortController();
1882
+ #readers = /* @__PURE__ */ new Set();
1883
+ #caughtUp = Promise.withResolvers();
1884
+ caughtUp = this.#caughtUp.promise;
1885
+ #ended = false;
1886
+ #error;
1887
+ #headers;
1888
+ #reconnectPolicy;
1889
+ constructor(session, options) {
1890
+ this.setOptions(options);
1891
+ this.caughtUp.catch(() => {});
1892
+ if (!options.catchUp) this.#caughtUp.resolve();
1893
+ (async () => {
1894
+ try {
1895
+ for await (const event of followClientSession(session, {
1896
+ signal: this.#controller.signal,
1897
+ resolveHeaders: () => this.#headers,
1898
+ resolveReconnectPolicy: () => this.#reconnectPolicy,
1899
+ startIndex: options.startIndex,
1900
+ onCaughtUp: options.catchUp ? () => this.#caughtUp.resolve() : void 0
1901
+ })) {
1902
+ if (this.#controller.signal.aborted) return;
1903
+ options.onEvent(event);
1904
+ for (const reader of this.#readers) reader.push(event);
1905
+ if (event.type === "session.completed" || event.type === "session.failed") break;
1906
+ }
1907
+ this.#caughtUp.resolve();
1908
+ this.#finish();
1909
+ } catch (error) {
1910
+ this.#caughtUp.reject(error);
1911
+ this.#finish(error);
1912
+ if (!this.#controller.signal.aborted) options.onError(error);
1913
+ }
1914
+ })();
1915
+ }
1916
+ subscribe(signal) {
1917
+ const reader = new SessionEventReader(() => this.#readers.delete(reader), signal);
1918
+ if (this.#ended) reader.end(this.#error);
1919
+ else this.#readers.add(reader);
1920
+ return reader;
1921
+ }
1922
+ get ended() {
1923
+ return this.#ended;
1924
+ }
1925
+ setOptions(options) {
1926
+ if ("headers" in options) this.#headers = options.headers;
1927
+ if ("streamReconnectPolicy" in options) this.#reconnectPolicy = options.streamReconnectPolicy;
1928
+ }
1929
+ close() {
1930
+ const error = new DOMException("Session stream was detached.", "AbortError");
1931
+ this.#controller.abort(error);
1932
+ this.#caughtUp.reject(error);
1933
+ this.#finish(error);
1934
+ }
1935
+ #finish(error) {
1936
+ if (this.#ended) return;
1937
+ this.#ended = true;
1938
+ this.#error = error;
1939
+ for (const reader of this.#readers) reader.end(error);
1940
+ }
1941
+ };
1942
+ var SessionEventReader = class {
1943
+ #events = [];
1944
+ #wake = Promise.withResolvers();
1945
+ #ended = false;
1946
+ #error;
1947
+ #dispose;
1948
+ constructor(unsubscribe, signal) {
1949
+ const abort = () => this.end(signal?.reason);
1950
+ signal?.addEventListener("abort", abort, { once: true });
1951
+ this.#dispose = () => {
1952
+ signal?.removeEventListener("abort", abort);
1953
+ unsubscribe();
1954
+ };
1955
+ if (signal?.aborted) abort();
1956
+ }
1957
+ push(event) {
1958
+ if (this.#ended) return;
1959
+ this.#events.push(event);
1960
+ this.#wake.resolve();
1961
+ }
1962
+ end(error) {
1963
+ if (this.#ended) return;
1964
+ this.#ended = true;
1965
+ this.#error = error;
1966
+ this.#wake.resolve();
1967
+ }
1968
+ [Symbol.dispose]() {
1969
+ this.end();
1970
+ this.#events = [];
1971
+ this.#dispose();
1972
+ }
1973
+ discard() {
1974
+ this.#events = [];
1975
+ }
1976
+ async *[Symbol.asyncIterator]() {
1977
+ for (;;) {
1978
+ while (this.#events.length > 0) yield this.#events.shift();
1979
+ if (this.#ended) {
1980
+ if (this.#error !== void 0) throw this.#error;
1981
+ return;
1982
+ }
1983
+ this.#wake = Promise.withResolvers();
1984
+ await this.#wake.promise;
1985
+ }
1986
+ }
1987
+ };
1988
+
1989
+ //#endregion
1990
+ //#region src/client/eve-agent-projection.ts
1991
+ var EveAgentProjection = class {
1992
+ #reducer;
1993
+ #events;
1994
+ #data;
1995
+ constructor(reducer, events) {
1996
+ this.#reducer = reducer;
1997
+ this.#events = events;
1998
+ this.#data = this.#reduce();
1999
+ }
2000
+ get data() {
2001
+ return this.#data;
2002
+ }
2003
+ reset() {
2004
+ this.#events = [];
2005
+ this.#data = this.#reducer.initial();
2006
+ }
2007
+ append(event) {
2008
+ this.#events = [...this.#events, event];
2009
+ this.#data = this.#reducer.reduce(this.#data, event);
2010
+ }
2011
+ replace(predicate, replacement) {
2012
+ const index = this.#events.findIndex(predicate);
2013
+ this.#events = index === -1 ? [...this.#events, replacement] : this.#events.map((event, i) => i === index ? replacement : event);
2014
+ this.#data = this.#reduce();
2015
+ }
2016
+ #reduce() {
2017
+ let data = this.#reducer.initial();
2018
+ for (const event of this.#events) data = this.#reducer.reduce(data, event);
2019
+ return data;
2020
+ }
2021
+ };
2022
+
1806
2023
  //#endregion
1807
2024
  //#region src/protocol/event-dedupe.ts
1808
2025
  function createEventDeduper() {
@@ -1832,10 +2049,6 @@ function collectPendingAuthorizations(events) {
1832
2049
  for (const event of events) updatePendingAuthorizations(pending, event);
1833
2050
  return pending;
1834
2051
  }
1835
- function updatePendingAuthorizations(pending, event) {
1836
- if (event.type === "authorization.required" && event.data.webhookUrl !== void 0) pending.add(event.data.name);
1837
- else if (event.type === "authorization.completed") pending.delete(event.data.name);
1838
- }
1839
2052
  function assertExclusiveTurnInput(input) {
1840
2053
  if (input.message !== void 0 === (input.inputResponses !== void 0)) throw new Error("A turn requires exactly one of message or inputResponses.");
1841
2054
  }
@@ -1865,29 +2078,78 @@ function toTerminalStreamFailureError(event) {
1865
2078
  error.name = event.data.code;
1866
2079
  return error;
1867
2080
  }
2081
+ function createActiveTurn(cancel) {
2082
+ const response = Promise.withResolvers();
2083
+ const completion = Promise.withResolvers();
2084
+ const turn = {
2085
+ abortController: new AbortController(),
2086
+ acceptedFollowUps: 0,
2087
+ cancel: () => cancel(turn),
2088
+ completion: completion.promise,
2089
+ followUpDispatches: /* @__PURE__ */ new Set(),
2090
+ receivedFollowUps: 0,
2091
+ receivedFollowUpEvents: /* @__PURE__ */ new Set(),
2092
+ followUpSubmissionIds: /* @__PURE__ */ new Set(),
2093
+ resolveCompletion: completion.resolve,
2094
+ response: response.promise,
2095
+ resolveResponse: response.resolve
2096
+ };
2097
+ return turn;
2098
+ }
2099
+ async function followSteeredTurns(turn, events, isActive) {
2100
+ while (turn.followUpDispatches.size > 0) await Promise.allSettled(turn.followUpDispatches);
2101
+ if (turn.receivedFollowUps >= turn.acceptedFollowUps) return;
2102
+ for await (const event of events) {
2103
+ if (!isActive()) return;
2104
+ if (turn.receivedFollowUpEvents.delete(event)) turn.receivedFollowUps += 1;
2105
+ if (isCurrentTurnBoundaryEvent(event)) {
2106
+ while (turn.followUpDispatches.size > 0) await Promise.allSettled(turn.followUpDispatches);
2107
+ if (turn.receivedFollowUps >= turn.acceptedFollowUps) return;
2108
+ }
2109
+ }
2110
+ }
2111
+ async function waitWithSignal(promise, signal) {
2112
+ if (signal === void 0) return await promise;
2113
+ const aborted = Promise.withResolvers();
2114
+ const onAbort = () => aborted.reject(signal.reason);
2115
+ signal.addEventListener("abort", onAbort, { once: true });
2116
+ if (signal.aborted) onAbort();
2117
+ try {
2118
+ return await Promise.race([aborted.promise, promise]);
2119
+ } finally {
2120
+ signal.removeEventListener("abort", onAbort);
2121
+ }
2122
+ }
1868
2123
 
1869
2124
  //#endregion
1870
2125
  //#region src/client/eve-agent-store.ts
1871
2126
  const detachStore = Symbol("detachEveAgentStore");
2127
+ const attachStore = Symbol("attachEveAgentStore");
1872
2128
  var EveAgentStore = class {
1873
2129
  #client;
2130
+ #autoPrewarm;
2131
+ #attached = false;
2132
+ #stream;
2133
+ #pendingAuthorizations = /* @__PURE__ */ new Set();
1874
2134
  #externalSession;
1875
2135
  #optimistic;
1876
- #reducer;
2136
+ #projection;
1877
2137
  #subscribers = /* @__PURE__ */ new Set();
1878
2138
  #seenEvents = createEventDeduper();
1879
2139
  #activeTurn;
1880
2140
  #callbacks = {};
1881
- #data;
1882
2141
  #error;
1883
2142
  #events;
1884
2143
  #pendingMessageSubmissions = [];
1885
- #projectionEvents;
2144
+ #prewarmGeneration = 0;
2145
+ #prewarmPromise;
2146
+ #prewarmController;
1886
2147
  #resumePromise;
1887
2148
  #session;
1888
2149
  #snapshot;
1889
2150
  #status = "ready";
1890
2151
  constructor(init) {
2152
+ this.#autoPrewarm = init.prewarm ?? false;
1891
2153
  this.#externalSession = init.session !== void 0;
1892
2154
  this.#client = this.#externalSession ? void 0 : new Client({
1893
2155
  auth: init.auth,
@@ -1895,13 +2157,14 @@ var EveAgentStore = class {
1895
2157
  host: init.host ?? ""
1896
2158
  });
1897
2159
  const initialEvents = [];
1898
- for (const event of init.initialEvents ?? []) if (this.#seenEvents.admit(event)) initialEvents.push(event);
2160
+ for (const event of init.initialEvents ?? []) {
2161
+ if (this.#seenEvents.admit(event)) initialEvents.push(event);
2162
+ updatePendingAuthorizations(this.#pendingAuthorizations, event);
2163
+ }
1899
2164
  this.#events = initialEvents;
1900
- this.#projectionEvents = [...this.#events];
2165
+ this.#projection = new EveAgentProjection(init.reducer, this.#events);
1901
2166
  this.#optimistic = init.optimistic ?? true;
1902
- this.#reducer = init.reducer;
1903
2167
  this.#session = init.session ?? (init.initialSession === void 0 ? void 0 : this.#client?.sessions.attach(init.initialSession.sessionId, { streamIndex: init.initialSession.streamIndex }));
1904
- this.#data = this.#reduceProjectionEvents(this.#projectionEvents);
1905
2168
  this.#snapshot = this.#createSnapshot();
1906
2169
  }
1907
2170
  get snapshot() {
@@ -1916,31 +2179,63 @@ var EveAgentStore = class {
1916
2179
  this.#subscribers.delete(callback);
1917
2180
  };
1918
2181
  }
2182
+ prewarm() {
2183
+ if (this.#prewarmPromise !== void 0) return this.#prewarmPromise;
2184
+ if (this.#session !== void 0 || this.#externalSession) return Promise.resolve();
2185
+ if (this.#activeTurn !== void 0) return this.#activeTurn.response.then((response) => {
2186
+ if (response === void 0) throw this.#error ?? new DOMException("Session creation was aborted.", "AbortError");
2187
+ });
2188
+ const client = this.#client;
2189
+ if (client === void 0) return Promise.reject(/* @__PURE__ */ new Error("This eve agent store does not own a session client."));
2190
+ const generation = this.#prewarmGeneration;
2191
+ const controller = new AbortController();
2192
+ this.#prewarmController = controller;
2193
+ const promise = (async () => {
2194
+ try {
2195
+ const created = await client.sessions.create({ signal: controller.signal });
2196
+ if (generation !== this.#prewarmGeneration) return;
2197
+ this.#session = created.session;
2198
+ this.#error = void 0;
2199
+ if (this.#status === "error") this.#status = "ready";
2200
+ this.#callbacks.onSessionChange?.(created.session.state);
2201
+ this.#publish();
2202
+ this.#ensureStream();
2203
+ } catch (error) {
2204
+ if (generation === this.#prewarmGeneration && this.#activeTurn === void 0 && this.#error === void 0) {
2205
+ this.#error = toError(error);
2206
+ this.#status = "error";
2207
+ this.#callbacks.onError?.(this.#error);
2208
+ this.#publish();
2209
+ }
2210
+ throw error;
2211
+ }
2212
+ })();
2213
+ this.#prewarmPromise = promise;
2214
+ const clear = () => {
2215
+ if (this.#prewarmPromise === promise) {
2216
+ this.#prewarmPromise = void 0;
2217
+ this.#prewarmController = void 0;
2218
+ }
2219
+ };
2220
+ promise.then(clear, clear);
2221
+ return promise;
2222
+ }
1919
2223
  async send(input) {
2224
+ return await this.#submit(input, this.#callbacks.prepareSend);
2225
+ }
2226
+ async #submit(input, prepareSend) {
1920
2227
  if (this.#activeTurn !== void 0) {
1921
2228
  if (this.#status === "resuming") throw new Error("eve session is resuming.");
1922
- return await this.#sendFollowUp(this.#activeTurn, input);
2229
+ return await this.#sendFollowUp(this.#activeTurn, input, prepareSend);
1923
2230
  }
1924
- const response = Promise.withResolvers();
1925
- const completion = Promise.withResolvers();
1926
- const turn = {
1927
- abortController: new AbortController(),
1928
- acceptedFollowUps: 0,
1929
- cancel: () => turn.acceptedFollowUps > 0 && this.#session !== void 0 ? this.#session.cancel() : response.promise.then((messageResponse) => messageResponse === void 0 ? { status: "no_active_turn" } : messageResponse.cancel()),
1930
- completion: completion.promise,
1931
- followUpDispatches: /* @__PURE__ */ new Set(),
1932
- receivedFollowUps: 0,
1933
- followUpSubmissionIds: /* @__PURE__ */ new Set(),
1934
- resolveCompletion: completion.resolve,
1935
- response: response.promise,
1936
- resolveResponse: response.resolve
1937
- };
2231
+ const turn = createActiveTurn((turn) => turn.acceptedFollowUps > 0 && this.#session !== void 0 ? this.#session.cancel() : turn.response.then((response) => response === void 0 ? { status: "no_active_turn" } : response.cancel()));
1938
2232
  this.#activeTurn = turn;
1939
2233
  this.#error = void 0;
1940
2234
  this.#status = "submitted";
1941
2235
  this.#publish();
2236
+ let reader;
1942
2237
  try {
1943
- const preparedInput = await this.#callbacks.prepareSend?.(input) ?? input;
2238
+ const preparedInput = await (prepareSend === void 0 ? input : waitWithSignal(Promise.resolve(prepareSend(input)), createAbortSignal(input.signal, turn.abortController.signal)));
1944
2239
  assertExclusiveTurnInput(preparedInput);
1945
2240
  if (!this.#isActiveTurn(turn)) return;
1946
2241
  this.#projectOptimisticMessage(preparedInput);
@@ -1950,15 +2245,17 @@ var EveAgentStore = class {
1950
2245
  ...preparedInput,
1951
2246
  signal: createAbortSignal(preparedInput.signal, turn.abortController.signal)
1952
2247
  };
1953
- const response = await this.#dispatchTurn(turnInput);
2248
+ const dispatched = await this.#dispatchTurn(turnInput);
2249
+ const response = dispatched.response;
2250
+ reader = dispatched.reader;
1954
2251
  if (!this.#isActiveTurn(turn)) return;
1955
2252
  turn.resolveResponse(response);
1956
- for await (const event of response) {
2253
+ for await (const event of consumeMessageResponse(response, reader)) {
1957
2254
  if (!this.#isActiveTurn(turn)) return;
1958
- this.#acceptServerEvent(event);
2255
+ if (turn.receivedFollowUpEvents.delete(event)) turn.receivedFollowUps += 1;
1959
2256
  }
1960
2257
  if (!this.#isActiveTurn(turn)) return;
1961
- await this.#followSteeredTurns(turn);
2258
+ await followSteeredTurns(turn, reader, () => this.#isActiveTurn(turn));
1962
2259
  if (!this.#isActiveTurn(turn)) return;
1963
2260
  this.#status = this.#error === void 0 ? "ready" : "error";
1964
2261
  } catch (error) {
@@ -1967,20 +2264,15 @@ var EveAgentStore = class {
1967
2264
  this.#status = "ready";
1968
2265
  this.#failPendingMessageSubmission(toError(error));
1969
2266
  } else {
1970
- this.#error = toError(error);
2267
+ const reported = this.#error !== void 0;
2268
+ this.#error ??= toError(error);
1971
2269
  this.#status = "error";
1972
2270
  this.#failPendingMessageSubmission(this.#error);
1973
- this.#callbacks.onError?.(this.#error);
2271
+ if (!reported) this.#callbacks.onError?.(this.#error);
1974
2272
  }
1975
2273
  } finally {
1976
- if (this.#isActiveTurn(turn)) {
1977
- turn.resolveResponse(void 0);
1978
- this.#activeTurn = void 0;
1979
- this.#callbacks.onSessionChange?.(this.#session?.state);
1980
- this.#publish();
1981
- this.#callbacks.onFinish?.(this.#snapshot);
1982
- turn.resolveCompletion();
1983
- }
2274
+ reader?.[Symbol.dispose]();
2275
+ this.#finishTurn(turn);
1984
2276
  }
1985
2277
  }
1986
2278
  resume() {
@@ -1996,70 +2288,34 @@ var EveAgentStore = class {
1996
2288
  async #resume() {
1997
2289
  if (this.#status === "resuming" || this.#status === "streaming" || this.#status === "submitted") throw new Error("eve session is already processing a turn.");
1998
2290
  if (this.#session === void 0) throw new Error("An eve session is required before resuming.");
1999
- const response = Promise.withResolvers();
2000
- const completion = Promise.withResolvers();
2001
2291
  const session = this.#session;
2002
- const turn = {
2003
- abortController: new AbortController(),
2004
- acceptedFollowUps: 0,
2005
- cancel: () => session.cancel(),
2006
- completion: completion.promise,
2007
- followUpDispatches: /* @__PURE__ */ new Set(),
2008
- receivedFollowUps: 0,
2009
- followUpSubmissionIds: /* @__PURE__ */ new Set(),
2010
- resolveCompletion: completion.resolve,
2011
- response: response.promise,
2012
- resolveResponse: response.resolve
2013
- };
2292
+ const turn = createActiveTurn(() => session.cancel());
2014
2293
  this.#activeTurn = turn;
2015
2294
  turn.resolveResponse(void 0);
2016
2295
  this.#error = void 0;
2017
2296
  this.#status = "resuming";
2018
2297
  this.#publish();
2019
2298
  try {
2020
- const hasCompleteInitialPrefix = this.#events.length === session.state.streamIndex;
2021
- const replayed = hasCompleteInitialPrefix ? [...this.#events] : [];
2022
- for await (const event of session.stream({
2023
- follow: false,
2024
- signal: turn.abortController.signal,
2025
- startIndex: hasCompleteInitialPrefix ? session.state.streamIndex : 0
2026
- })) {
2027
- if (!this.#isActiveTurn(turn)) return;
2028
- replayed.push(event);
2029
- this.#acceptServerEvent(event, {
2030
- publish: false,
2031
- transitionToStreaming: false
2032
- });
2033
- }
2299
+ const stream = this.#ensureStream({
2300
+ catchUp: true,
2301
+ startIndex: this.#events.length === session.state.streamIndex ? session.state.streamIndex : 0
2302
+ });
2303
+ using reader = stream.subscribe(turn.abortController.signal);
2304
+ await stream.caughtUp;
2034
2305
  if (!this.#isActiveTurn(turn)) return;
2035
- const replayTail = replayed.at(-1);
2036
- if (replayTail !== void 0) this.#applyTerminalStreamFailure(replayTail);
2037
- const replaySettled = isSettledSessionTail(replayed);
2038
- if (this.#error === void 0 && (!replaySettled || replayTail?.type === "session.waiting")) {
2039
- const pendingAuthorizations = collectPendingAuthorizations(replayed);
2040
- if (!replaySettled) this.#status = "streaming";
2306
+ reader.discard();
2307
+ const tail = this.#events.at(-1);
2308
+ if (tail !== void 0) this.#applyTerminalStreamFailure(tail);
2309
+ if (tail !== void 0 && this.#error === void 0 && !isSettledSessionTail(this.#events)) {
2310
+ this.#status = "streaming";
2041
2311
  this.#publish();
2042
- let followLive = !replaySettled;
2043
- for (;;) {
2044
- for await (const event of session.stream({
2045
- follow: followLive ? void 0 : false,
2046
- signal: turn.abortController.signal
2047
- })) {
2048
- if (!this.#isActiveTurn(turn)) return;
2049
- replayed.push(event);
2050
- this.#acceptServerEvent(event);
2051
- updatePendingAuthorizations(pendingAuthorizations, event);
2052
- if (followLive && isCurrentTurnBoundaryEvent(event) && (event.type !== "session.waiting" || pendingAuthorizations.size === 0)) break;
2053
- }
2312
+ for await (const event of reader) {
2054
2313
  if (!this.#isActiveTurn(turn)) return;
2055
- if (followLive || isSettledSessionTail(replayed)) break;
2056
- followLive = true;
2314
+ if (turn.receivedFollowUpEvents.delete(event)) turn.receivedFollowUps += 1;
2315
+ if (isCurrentTurnBoundaryEvent(event) && this.#pendingAuthorizations.size === 0) break;
2057
2316
  }
2058
- } else {
2059
- this.#status = this.#error === void 0 ? "ready" : "error";
2060
- this.#publish();
2061
2317
  }
2062
- await this.#followSteeredTurns(turn);
2318
+ await followSteeredTurns(turn, reader, () => this.#isActiveTurn(turn));
2063
2319
  if (this.#isActiveTurn(turn)) this.#status = this.#error === void 0 ? "ready" : "error";
2064
2320
  } catch (error) {
2065
2321
  if (!this.#isActiveTurn(turn)) return;
@@ -2070,61 +2326,81 @@ var EveAgentStore = class {
2070
2326
  this.#callbacks.onError?.(this.#error);
2071
2327
  }
2072
2328
  } finally {
2073
- if (this.#isActiveTurn(turn)) {
2074
- turn.resolveResponse(void 0);
2075
- this.#activeTurn = void 0;
2076
- this.#callbacks.onSessionChange?.(session.state);
2077
- this.#publish();
2078
- this.#callbacks.onFinish?.(this.#snapshot);
2079
- turn.resolveCompletion();
2080
- }
2329
+ this.#finishTurn(turn);
2081
2330
  }
2082
2331
  }
2083
2332
  cancel() {
2084
2333
  const turn = this.#activeTurn;
2085
- if (turn === void 0) return Promise.resolve({ status: "no_active_turn" });
2334
+ if (turn === void 0) return this.#status === "streaming" && this.#session !== void 0 ? this.#session.cancel() : Promise.resolve({ status: "no_active_turn" });
2086
2335
  return turn.cancel();
2087
2336
  }
2337
+ [attachStore]() {
2338
+ this.#attached = true;
2339
+ if (this.#autoPrewarm && this.#session === void 0) this.prewarm().catch(() => {});
2340
+ }
2088
2341
  [detachStore]() {
2342
+ this.#attached = false;
2343
+ this.#stream?.close();
2344
+ this.#stream = void 0;
2089
2345
  this.#activeTurn?.abortController.abort();
2346
+ this.#resetPrewarm();
2347
+ this.#resumePromise = void 0;
2090
2348
  }
2091
2349
  reset() {
2350
+ this.#stream?.close();
2351
+ this.#stream = void 0;
2352
+ this.#pendingAuthorizations.clear();
2092
2353
  const turn = this.#activeTurn;
2093
2354
  this.#activeTurn = void 0;
2094
2355
  turn?.resolveResponse(void 0);
2095
2356
  turn?.resolveCompletion();
2096
2357
  turn?.abortController.abort();
2358
+ this.#resetPrewarm();
2359
+ this.#resumePromise = void 0;
2097
2360
  if (!this.#externalSession) this.#session = void 0;
2098
2361
  this.#events = [];
2099
2362
  this.#seenEvents = createEventDeduper();
2100
2363
  this.#pendingMessageSubmissions = [];
2101
- this.#projectionEvents = [];
2102
- this.#data = this.#reducer.initial();
2364
+ this.#projection.reset();
2103
2365
  this.#error = void 0;
2104
2366
  this.#status = "ready";
2105
2367
  this.#callbacks.onSessionChange?.(this.#session?.state);
2106
2368
  this.#publish();
2369
+ if (this.#autoPrewarm && this.#attached) this.prewarm().catch(() => {});
2107
2370
  }
2108
- async #sendFollowUp(turn, input) {
2371
+ async #sendFollowUp(turn, input, prepareSend) {
2109
2372
  if (input.message === void 0 || input.turnPolicy !== "steer") throw new Error("eve session is already processing a turn. Send a message with turnPolicy: \"steer\" to guide it at the next boundary.");
2110
- const preparedInput = await this.#callbacks.prepareSend?.(input) ?? input;
2373
+ const generation = this.#prewarmGeneration;
2374
+ const signal = createAbortSignal(input.signal, turn.abortController.signal);
2375
+ const preparedInput = await waitWithSignal(Promise.resolve(prepareSend?.(input)), signal) ?? input;
2376
+ if (generation !== this.#prewarmGeneration) return;
2111
2377
  assertExclusiveTurnInput(preparedInput);
2112
2378
  if (preparedInput.message === void 0 || preparedInput.turnPolicy !== "steer") throw new Error("An in-flight follow-up requires a message with turnPolicy: \"steer\".");
2113
- if (!this.#isActiveTurn(turn)) return await this.send(preparedInput);
2379
+ if (!this.#isActiveTurn(turn)) return await this.#submit(preparedInput);
2114
2380
  const submissionId = this.#projectOptimisticMessage(preparedInput);
2115
2381
  if (submissionId !== void 0) turn.followUpSubmissionIds.add(submissionId);
2116
2382
  this.#publish();
2383
+ this.#ensureStream({
2384
+ headers: preparedInput.headers,
2385
+ streamReconnectPolicy: preparedInput.streamReconnectPolicy
2386
+ });
2117
2387
  let dispatch;
2118
2388
  dispatch = (async () => {
2119
2389
  try {
2120
- await turn.response;
2390
+ const signal = createAbortSignal(preparedInput.signal, turn.abortController.signal);
2391
+ await waitWithSignal(turn.response, signal);
2121
2392
  if (!this.#isActiveTurn(turn) || this.#session === void 0) throw new Error("The active eve turn ended before the follow-up could be sent.");
2122
2393
  const { message, ...options } = preparedInput;
2123
- await this.#session.send(message, options);
2394
+ await this.#session.send(message, {
2395
+ ...options,
2396
+ signal
2397
+ });
2124
2398
  turn.acceptedFollowUps += 1;
2125
2399
  } catch (error) {
2126
- this.#failPendingMessageSubmission(toError(error), submissionId);
2127
- this.#publish();
2400
+ if (this.#isActiveTurn(turn)) {
2401
+ this.#failPendingMessageSubmission(toError(error), submissionId);
2402
+ this.#publish();
2403
+ }
2128
2404
  throw error;
2129
2405
  } finally {
2130
2406
  turn.followUpDispatches.delete(dispatch);
@@ -2134,38 +2410,94 @@ var EveAgentStore = class {
2134
2410
  await dispatch;
2135
2411
  await turn.completion;
2136
2412
  }
2137
- async #followSteeredTurns(turn) {
2138
- while (turn.followUpDispatches.size > 0) await Promise.allSettled(turn.followUpDispatches);
2139
- if (turn.receivedFollowUps >= turn.acceptedFollowUps || this.#session === void 0) return;
2140
- for await (const event of this.#session.stream({ signal: turn.abortController.signal })) {
2141
- if (!this.#isActiveTurn(turn)) return;
2142
- this.#acceptServerEvent(event);
2143
- if (isCurrentTurnBoundaryEvent(event)) {
2144
- while (turn.followUpDispatches.size > 0) await Promise.allSettled(turn.followUpDispatches);
2145
- if (turn.receivedFollowUps >= turn.acceptedFollowUps) return;
2413
+ async #dispatchTurn(input) {
2414
+ const streamOptions = {
2415
+ headers: input.headers,
2416
+ streamReconnectPolicy: input.streamReconnectPolicy
2417
+ };
2418
+ if (this.#prewarmPromise !== void 0) {
2419
+ await waitWithSignal(this.#prewarmPromise.catch((error) => {
2420
+ if (this.#session !== void 0) throw error;
2421
+ }), input.signal);
2422
+ input.signal?.throwIfAborted();
2423
+ }
2424
+ if (this.#session === void 0) {
2425
+ if (this.#client === void 0) throw new Error("An external eve session is required before sending.");
2426
+ if (input.message === void 0) throw new Error("Cannot answer an input request before the session starts.");
2427
+ const created = await this.#client.sessions.create({
2428
+ ...input,
2429
+ message: input.message
2430
+ });
2431
+ input.signal?.throwIfAborted();
2432
+ this.#session = created.session;
2433
+ this.#callbacks.onSessionChange?.(created.session.state);
2434
+ this.#publish();
2435
+ return {
2436
+ response: created.response,
2437
+ reader: this.#ensureStream(streamOptions).subscribe(input.signal)
2438
+ };
2439
+ }
2440
+ const reader = this.#ensureStream(streamOptions).subscribe(input.signal);
2441
+ try {
2442
+ if (input.inputResponses === void 0) {
2443
+ const { message, ...options } = input;
2444
+ return {
2445
+ response: await this.#session.send(message, options),
2446
+ reader
2447
+ };
2146
2448
  }
2449
+ const { inputResponses, ...options } = input;
2450
+ return {
2451
+ response: await this.#session.respond(inputResponses, options),
2452
+ reader
2453
+ };
2454
+ } catch (error) {
2455
+ reader[Symbol.dispose]();
2456
+ throw error;
2147
2457
  }
2148
2458
  }
2149
- async #createFirstTurn(input) {
2150
- if (this.#client === void 0) throw new Error("An external eve session is required before sending.");
2151
- if (input.message === void 0) throw new Error("Cannot answer an input request before the session starts.");
2152
- const created = await this.#client.sessions.create({
2153
- ...input,
2154
- message: input.message
2459
+ #ensureStream(options = {}) {
2460
+ if (this.#stream !== void 0 && !this.#stream.ended) {
2461
+ this.#stream.setOptions(options);
2462
+ return this.#stream;
2463
+ }
2464
+ if (this.#session === void 0) throw new Error("A session is required before opening its stream.");
2465
+ const session = this.#session;
2466
+ const generation = this.#prewarmGeneration;
2467
+ this.#stream = new SessionEventStream(session, {
2468
+ ...options,
2469
+ onEvent: (event) => {
2470
+ if (generation === this.#prewarmGeneration) this.#acceptServerEvent(event);
2471
+ },
2472
+ onError: (error) => {
2473
+ if (generation !== this.#prewarmGeneration) return;
2474
+ this.#stream = void 0;
2475
+ if (this.#activeTurn !== void 0) return;
2476
+ this.#error = toError(error);
2477
+ this.#status = "error";
2478
+ this.#callbacks.onError?.(this.#error);
2479
+ this.#publish();
2480
+ }
2155
2481
  });
2156
- this.#session = created.session;
2157
- this.#callbacks.onSessionChange?.(created.session.state);
2158
- this.#publish();
2159
- return created.response;
2482
+ return this.#stream;
2160
2483
  }
2161
- async #dispatchTurn(input) {
2162
- if (this.#session === void 0) return await this.#createFirstTurn(input);
2163
- if (input.inputResponses === void 0) {
2164
- const { message, ...options } = input;
2165
- return await this.#session.send(message, options);
2484
+ #resetPrewarm() {
2485
+ this.#prewarmGeneration += 1;
2486
+ this.#prewarmController?.abort();
2487
+ this.#prewarmController = void 0;
2488
+ this.#prewarmPromise = void 0;
2489
+ }
2490
+ #finishTurn(turn) {
2491
+ if (!this.#isActiveTurn(turn)) return;
2492
+ turn.resolveResponse(void 0);
2493
+ this.#activeTurn = void 0;
2494
+ try {
2495
+ this.#callbacks.onSessionChange?.(this.#session?.state);
2496
+ this.#publish();
2497
+ this.#callbacks.onFinish?.(this.#snapshot);
2498
+ } finally {
2499
+ turn.resolveCompletion();
2166
2500
  }
2167
- const { inputResponses, ...options } = input;
2168
- return await this.#session.respond(inputResponses, options);
2169
2501
  }
2170
2502
  #isActiveTurn(turn) {
2171
2503
  return this.#activeTurn === turn;
@@ -2179,7 +2511,7 @@ var EveAgentStore = class {
2179
2511
  message: summarizeUserContent(input.message)
2180
2512
  };
2181
2513
  this.#pendingMessageSubmissions = [...this.#pendingMessageSubmissions, pending];
2182
- if (this.#optimistic) this.#appendProjectionEvent({
2514
+ if (this.#optimistic) this.#projection.append({
2183
2515
  data: {
2184
2516
  createdAt: pending.createdAt,
2185
2517
  message: pending.message,
@@ -2191,7 +2523,7 @@ var EveAgentStore = class {
2191
2523
  }
2192
2524
  #projectInputResponses(input) {
2193
2525
  if (input.inputResponses === void 0 || input.inputResponses.length === 0) return;
2194
- this.#appendProjectionEvent({
2526
+ this.#projection.append({
2195
2527
  data: {
2196
2528
  createdAt: Date.now(),
2197
2529
  responses: input.inputResponses
@@ -2199,25 +2531,33 @@ var EveAgentStore = class {
2199
2531
  type: "client.input.responded"
2200
2532
  });
2201
2533
  }
2202
- #acceptServerEvent(event, options = {}) {
2534
+ #acceptServerEvent(event) {
2203
2535
  if (!this.#seenEvents.admit(event)) return;
2536
+ const wasStreaming = this.#status === "streaming";
2537
+ updatePendingAuthorizations(this.#pendingAuthorizations, event);
2204
2538
  this.#events = [...this.#events, event];
2205
2539
  this.#applyServerEvent(event);
2206
2540
  this.#callbacks.onEvent?.(event);
2207
- if (options.transitionToStreaming ?? true) this.#status = "streaming";
2208
2541
  this.#applyTerminalStreamFailure(event);
2209
- if (options.publish ?? true) this.#publish();
2542
+ const settled = isCurrentTurnBoundaryEvent(event) && this.#pendingAuthorizations.size === 0;
2543
+ if (this.#status !== "resuming" && this.#error === void 0) {
2544
+ if ("data" in event && "turnId" in event.data) this.#status = "streaming";
2545
+ if (this.#activeTurn === void 0 && settled) this.#status = "ready";
2546
+ }
2547
+ this.#callbacks.onSessionChange?.(this.#session?.state);
2548
+ this.#publish();
2549
+ if (this.#activeTurn === void 0 && wasStreaming && settled) this.#callbacks.onFinish?.(this.#snapshot);
2210
2550
  }
2211
2551
  #applyServerEvent(event) {
2212
2552
  const pendingSubmission = this.#pendingMessageSubmissions[0];
2213
2553
  if (event.type === "message.received" && pendingSubmission !== void 0) {
2214
2554
  const submissionId = pendingSubmission.id;
2215
- if (this.#activeTurn?.followUpSubmissionIds.delete(submissionId)) this.#activeTurn.receivedFollowUps += 1;
2555
+ if (this.#activeTurn?.followUpSubmissionIds.delete(submissionId)) this.#activeTurn.receivedFollowUpEvents.add(event);
2216
2556
  this.#pendingMessageSubmissions = this.#pendingMessageSubmissions.slice(1);
2217
- this.#replaceProjectionEvent((candidate) => candidate.type === "client.message.submitted" && candidate.data.submissionId === submissionId, event);
2557
+ this.#projection.replace((candidate) => candidate.type === "client.message.submitted" && candidate.data.submissionId === submissionId, event);
2218
2558
  return;
2219
2559
  }
2220
- this.#appendProjectionEvent(event);
2560
+ this.#projection.append(event);
2221
2561
  }
2222
2562
  #applyTerminalStreamFailure(event) {
2223
2563
  const error = toTerminalStreamFailureError(event);
@@ -2233,7 +2573,7 @@ var EveAgentStore = class {
2233
2573
  const pending = submissionId === void 0 ? this.#pendingMessageSubmissions[0] : this.#pendingMessageSubmissions.find((candidate) => candidate.id === submissionId);
2234
2574
  if (pending === void 0) return;
2235
2575
  this.#pendingMessageSubmissions = this.#pendingMessageSubmissions.filter((candidate) => candidate.id !== pending.id);
2236
- this.#replaceProjectionEvent((event) => event.type === "client.message.submitted" && event.data.submissionId === pending.id, {
2576
+ this.#projection.replace((event) => event.type === "client.message.submitted" && event.data.submissionId === pending.id, {
2237
2577
  data: {
2238
2578
  createdAt: pending.createdAt,
2239
2579
  error: { message: error.message },
@@ -2243,30 +2583,9 @@ var EveAgentStore = class {
2243
2583
  type: "client.message.failed"
2244
2584
  });
2245
2585
  }
2246
- #appendProjectionEvent(event) {
2247
- this.#projectionEvents = [...this.#projectionEvents, event];
2248
- this.#data = this.#reducer.reduce(this.#data, event);
2249
- }
2250
- #replaceProjectionEvent(predicate, replacement) {
2251
- let replaced = false;
2252
- this.#projectionEvents = this.#projectionEvents.map((event) => {
2253
- if (!replaced && predicate(event)) {
2254
- replaced = true;
2255
- return replacement;
2256
- }
2257
- return event;
2258
- });
2259
- if (!replaced) this.#projectionEvents = [...this.#projectionEvents, replacement];
2260
- this.#data = this.#reduceProjectionEvents(this.#projectionEvents);
2261
- }
2262
- #reduceProjectionEvents(events) {
2263
- let data = this.#reducer.initial();
2264
- for (const event of events) data = this.#reducer.reduce(data, event);
2265
- return data;
2266
- }
2267
2586
  #createSnapshot() {
2268
2587
  return {
2269
- data: this.#data,
2588
+ data: this.#projection.data,
2270
2589
  error: this.#error,
2271
2590
  events: this.#events,
2272
2591
  session: this.#session?.state,
@@ -2281,6 +2600,9 @@ var EveAgentStore = class {
2281
2600
  function detachEveAgentStore(store) {
2282
2601
  store[detachStore]();
2283
2602
  }
2603
+ function attachEveAgentStore(store) {
2604
+ store[attachStore]();
2605
+ }
2284
2606
 
2285
2607
  //#endregion
2286
2608
  //#region src/client/agent-host.ts
@@ -2935,6 +3257,7 @@ function useEveAgent(options = {}) {
2935
3257
  initialEvents: options.initialEvents,
2936
3258
  initialSession: options.initialSession,
2937
3259
  optimistic: options.optimistic,
3260
+ prewarm: options.prewarm,
2938
3261
  reducer,
2939
3262
  session: options.session
2940
3263
  });
@@ -2950,6 +3273,7 @@ function useEveAgent(options = {}) {
2950
3273
  const unsubscribe = store.subscribe(() => {
2951
3274
  snapshot.value = store.snapshot;
2952
3275
  });
3276
+ attachEveAgentStore(store);
2953
3277
  if (options.resume) store.resume();
2954
3278
  onScopeDispose(() => {
2955
3279
  unsubscribe();
@@ -2961,6 +3285,7 @@ function useEveAgent(options = {}) {
2961
3285
  data: computed(() => snapshot.value.data),
2962
3286
  error: computed(() => snapshot.value.error),
2963
3287
  events: computed(() => snapshot.value.events),
3288
+ prewarm: () => store.prewarm(),
2964
3289
  reset: () => store.reset(),
2965
3290
  respond: (inputResponses, options) => store.send({
2966
3291
  ...options,