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
@@ -1,3 +1,4 @@
1
+ import { onMount } from "svelte";
1
2
  import { createSubscriber } from "svelte/reactivity";
2
3
  import { z } from "#compiled/zod/index.js";
3
4
  import { asSchema } from "ai";
@@ -686,17 +687,6 @@ function isTurnFailureEvent(event) {
686
687
  return event.type === "session.failed" || event.type === "step.failed" || event.type === "turn.failed";
687
688
  }
688
689
 
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
690
  //#endregion
701
691
  //#region src/client/session-utils.ts
702
692
  function summarizeTurnEvents(events) {
@@ -725,9 +715,25 @@ function summarizeTurnEvents(events) {
725
715
  function isFinalMessageCompleted(event) {
726
716
  return event.type === "message.completed" && event.data.finishReason !== "tool-calls";
727
717
  }
718
+ function updatePendingAuthorizations(pending, event) {
719
+ if (event.type === "authorization.required" && event.data.webhookUrl !== void 0) pending.add(event.data.name);
720
+ else if (event.type === "authorization.completed") pending.delete(event.data.name);
721
+ }
722
+
723
+ //#endregion
724
+ //#region src/client/output-schema.ts
725
+ function extractCompletedResult(events) {
726
+ let result;
727
+ for (const event of events) if (isResultCompletedEvent(event)) result = event.data.result;
728
+ return result;
729
+ }
730
+ function isResultCompletedEvent(event) {
731
+ return event.type === "result.completed";
732
+ }
728
733
 
729
734
  //#endregion
730
735
  //#region src/client/message-response.ts
736
+ const consumeResponse = Symbol("consumeMessageResponse");
731
737
  var MessageResponse = class {
732
738
  sessionId;
733
739
  #cancelTurn;
@@ -765,13 +771,16 @@ var MessageResponse = class {
765
771
  };
766
772
  }
767
773
  [Symbol.asyncIterator]() {
774
+ return this[consumeResponse]();
775
+ }
776
+ [consumeResponse](source) {
768
777
  if (this.#consumed) throw new Error("MessageResponse has already been consumed.");
769
778
  this.#consumed = true;
770
- return this.#observeStream();
779
+ return this.#observeStream(source);
771
780
  }
772
- async *#observeStream() {
781
+ async *#observeStream(source) {
773
782
  try {
774
- for await (const event of this.#createStream()) {
783
+ for await (const event of this.#createStream(source)) {
775
784
  if (event.type === "turn.started") this.#turnId.resolve(event.data.turnId);
776
785
  else if (isCurrentTurnBoundaryEvent(event)) {
777
786
  this.#settled = true;
@@ -784,6 +793,9 @@ var MessageResponse = class {
784
793
  }
785
794
  }
786
795
  };
796
+ function consumeMessageResponse(response, source) {
797
+ return response[consumeResponse](source);
798
+ }
787
799
 
788
800
  //#endregion
789
801
  //#region src/protocol/message-version.ts
@@ -893,9 +905,15 @@ async function* readNdjsonStream(body, options) {
893
905
  const decoder = new TextDecoder();
894
906
  let buffer = "";
895
907
  let reachedEof = false;
908
+ const abort = () => {
909
+ reader.cancel().catch(() => {});
910
+ };
911
+ options.signal?.addEventListener("abort", abort, { once: true });
896
912
  try {
897
913
  while (true) {
914
+ options.signal?.throwIfAborted();
898
915
  const result = await readWithIdleTimeout(reader, options?.idleTimeoutMs);
916
+ options.signal?.throwIfAborted();
899
917
  if (result.done) {
900
918
  reachedEof = true;
901
919
  buffer += decoder.decode();
@@ -921,6 +939,7 @@ async function* readNdjsonStream(body, options) {
921
939
  else yield parseMessageStreamEvent(value, options.streamVersion);
922
940
  }
923
941
  } finally {
942
+ options.signal?.removeEventListener("abort", abort);
924
943
  if (!reachedEof) reader.cancel().catch(() => {});
925
944
  reader.releaseLock();
926
945
  }
@@ -1065,45 +1084,56 @@ function resolveRetryPolicy(policy, defaults) {
1065
1084
  ...policy
1066
1085
  };
1067
1086
  }
1068
- function resolveStreamReconnectPolicy(policy) {
1087
+ function resolveStreamReconnectPolicy(policy, keepAlive = false) {
1069
1088
  if (policy && "reconnect" in policy && policy.reconnect === false) return NO_STREAM_RECONNECT_POLICY;
1070
1089
  const configured = policy;
1071
1090
  return {
1072
1091
  retryableErrorStatuses: configured?.retryableErrorStatuses ? new Set(configured.retryableErrorStatuses) : DEFAULT_STREAM_RECONNECT_POLICY.retryableErrorStatuses,
1073
- streamIdleReconnectPolicy: resolveRetryPolicy(configured?.streamIdleReconnectPolicy, DEFAULT_STREAM_RECONNECT_POLICY.streamIdleReconnectPolicy),
1092
+ streamIdleReconnectPolicy: resolveRetryPolicy(configured?.streamIdleReconnectPolicy, {
1093
+ ...DEFAULT_STREAM_RECONNECT_POLICY.streamIdleReconnectPolicy,
1094
+ maxAttempts: keepAlive ? Infinity : DEFAULT_STREAM_RECONNECT_POLICY.streamIdleReconnectPolicy.maxAttempts
1095
+ }),
1074
1096
  streamOpenReconnectPolicy: resolveRetryPolicy(configured?.streamOpenReconnectPolicy, DEFAULT_STREAM_RECONNECT_POLICY.streamOpenReconnectPolicy)
1075
1097
  };
1076
1098
  }
1077
1099
  async function* followStreamIterable(input) {
1078
1100
  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;
1101
+ const resolvePolicy = () => resolveStreamReconnectPolicy(input.resolveReconnectPolicy === void 0 ? input.streamReconnectPolicy : input.resolveReconnectPolicy(), input.keepAlive);
1102
+ let retryPolicy = resolvePolicy();
1103
+ let idleRetryPolicy = retryPolicy.streamIdleReconnectPolicy;
1081
1104
  let startIndex = input.startIndex;
1082
1105
  let reconnectDelayMs = idleRetryPolicy.baseDelayMs;
1083
1106
  let idleReconnects = 0;
1084
1107
  let initialConnection = true;
1085
1108
  let tailIndex;
1109
+ let caughtUp = false;
1086
1110
  while (true) {
1111
+ retryPolicy = resolvePolicy();
1112
+ idleRetryPolicy = retryPolicy.streamIdleReconnectPolicy;
1087
1113
  let connection;
1088
1114
  try {
1089
1115
  connection = await openStreamBody({
1090
1116
  ...input,
1091
1117
  retryPolicy,
1092
1118
  startIndex,
1093
- requestTailIndex: input.follow === false && tailIndex === void 0
1119
+ requestTailIndex: (input.follow === false || input.onCaughtUp !== void 0) && tailIndex === void 0
1094
1120
  });
1095
1121
  } catch (error) {
1096
1122
  if (input.signal?.aborted) return;
1097
1123
  throw error;
1098
1124
  }
1099
- if (input.follow === false && tailIndex === void 0) {
1125
+ if ((input.follow === false || input.onCaughtUp !== void 0) && tailIndex === void 0) {
1100
1126
  tailIndex = connection.tailIndex;
1101
1127
  if (tailIndex === void 0) {
1102
1128
  connection.close();
1103
1129
  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
1130
  }
1105
1131
  }
1106
- if (tailIndex !== void 0 && startIndex > tailIndex) {
1132
+ if (!caughtUp && tailIndex !== void 0 && startIndex > tailIndex) {
1133
+ caughtUp = true;
1134
+ input.onCaughtUp?.();
1135
+ }
1136
+ if (input.follow === false && tailIndex !== void 0 && startIndex > tailIndex) {
1107
1137
  connection.close();
1108
1138
  return;
1109
1139
  }
@@ -1111,6 +1141,7 @@ async function* followStreamIterable(input) {
1111
1141
  let leaseEnded = false;
1112
1142
  try {
1113
1143
  for await (const event of readNdjsonStream(connection.body, {
1144
+ signal: input.signal,
1114
1145
  controlVersion: connection.controlVersion,
1115
1146
  idleTimeoutMs: input.streamReadIdleTimeoutMs ?? DEFAULT_STREAM_READ_IDLE_TIMEOUT_MS,
1116
1147
  onLeaseEnded: () => {
@@ -1123,16 +1154,21 @@ async function* followStreamIterable(input) {
1123
1154
  reconnectDelayMs = idleRetryPolicy.baseDelayMs;
1124
1155
  idleReconnects = 0;
1125
1156
  yield event;
1126
- if (tailIndex !== void 0 && startIndex > tailIndex) return;
1157
+ if (!caughtUp && tailIndex !== void 0 && startIndex > tailIndex) {
1158
+ caughtUp = true;
1159
+ input.onCaughtUp?.();
1160
+ }
1161
+ if (input.follow === false && tailIndex !== void 0 && startIndex > tailIndex) return;
1127
1162
  }
1128
1163
  } catch (error) {
1129
1164
  if (!isStreamDisconnectError(error)) throw error;
1130
1165
  } finally {
1131
1166
  connection.close();
1132
1167
  }
1168
+ idleRetryPolicy = resolvePolicy().streamIdleReconnectPolicy;
1133
1169
  if (input.signal?.aborted || input.startIndex < 0 || idleRetryPolicy.maxAttempts === 0) return;
1134
1170
  if (leaseEnded) continue;
1135
- if (input.keepAlive !== true && !deliveredEvent && !initialConnection && (idleReconnects += 1) >= idleRetryPolicy.maxAttempts) return;
1171
+ if (!deliveredEvent && !initialConnection && (idleReconnects += 1) >= idleRetryPolicy.maxAttempts) return;
1136
1172
  initialConnection = false;
1137
1173
  await sleep(reconnectDelayMs, input.signal);
1138
1174
  if (input.signal?.aborted) return;
@@ -1140,7 +1176,7 @@ async function* followStreamIterable(input) {
1140
1176
  }
1141
1177
  }
1142
1178
  async function openStreamBody(input) {
1143
- const retryPolicy = input.retryPolicy ?? resolveStreamReconnectPolicy(input.streamReconnectPolicy);
1179
+ const retryPolicy = input.retryPolicy ?? resolveStreamReconnectPolicy(input.streamReconnectPolicy, input.keepAlive);
1144
1180
  const openRetryPolicy = retryPolicy.streamOpenReconnectPolicy;
1145
1181
  let lastStatus;
1146
1182
  let lastBody;
@@ -1152,8 +1188,10 @@ async function openStreamBody(input) {
1152
1188
  if (input.startIndex !== 0) searchParams.startIndex = String(input.startIndex);
1153
1189
  if (input.requestTailIndex === true) searchParams.includeTailIndex = "1";
1154
1190
  for (let attempt = 0; attempt < openRetryPolicy.maxAttempts; attempt += 1) {
1191
+ input.signal?.throwIfAborted();
1155
1192
  const url = createClientUrl(input.host, createEveSessionStreamRoutePath(input.sessionId), Object.keys(searchParams).length > 0 ? searchParams : void 0);
1156
1193
  const headers = await input.resolveHeaders();
1194
+ input.signal?.throwIfAborted();
1157
1195
  const connectionController = new AbortController();
1158
1196
  const signal = input.signal ? AbortSignal.any([input.signal, connectionController.signal]) : connectionController.signal;
1159
1197
  let response;
@@ -1434,8 +1472,10 @@ function getStandardSchemaProperties(value) {
1434
1472
 
1435
1473
  //#endregion
1436
1474
  //#region src/client/session.ts
1437
- const SESSION_SEND_RETRY_COUNT = 3;
1438
1475
  const SESSION_SEND_RETRY_BASE_DELAY_MS = 250;
1476
+ const SESSION_SEND_RETRY_MAX_DELAY_MS = 2e3;
1477
+ const SESSION_SEND_READY_TIMEOUT_MS = 2e4;
1478
+ const followSession = Symbol("followClientSession");
1439
1479
  var ClientSession = class ClientSession {
1440
1480
  #context;
1441
1481
  #state;
@@ -1455,6 +1495,13 @@ var ClientSession = class ClientSession {
1455
1495
  session
1456
1496
  };
1457
1497
  }
1498
+ static async prewarm(context, options = {}) {
1499
+ const { sessionId } = await readAcceptedMessage(await postCreateSession(context, options));
1500
+ return new ClientSession(context, {
1501
+ sessionId,
1502
+ streamIndex: 0
1503
+ });
1504
+ }
1458
1505
  get state() {
1459
1506
  return this.#state;
1460
1507
  }
@@ -1488,10 +1535,10 @@ var ClientSession = class ClientSession {
1488
1535
  inputResponses
1489
1536
  }, false);
1490
1537
  }
1491
- async #send(input, retrySessionNotActive) {
1538
+ async #send(input, retrySessionNotReady) {
1492
1539
  const initialStreamIndex = this.#state.streamIndex;
1493
1540
  const path = createEveSessionRoutePath(this.#state.sessionId);
1494
- const response = retrySessionNotActive ? await postSessionSend(this.#context, path, input) : await postTurn(this.#context, path, input, false);
1541
+ const response = retrySessionNotReady ? await postSessionSend(this.#context, path, input) : await postTurn(this.#context, path, input, false);
1495
1542
  const { sessionId: responseSessionId, deliveryId } = await readAcceptedMessage(response, this.#state.sessionId);
1496
1543
  if (responseSessionId !== this.#state.sessionId) throw new Error("Message route returned a different session id.");
1497
1544
  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 +1574,29 @@ var ClientSession = class ClientSession {
1527
1574
  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
1575
  return this.#streamAndAdvance(options);
1529
1576
  }
1577
+ [followSession](options) {
1578
+ return this.#streamAndAdvance({
1579
+ ...options,
1580
+ keepAlive: true
1581
+ });
1582
+ }
1530
1583
  #messageResponse(response, input, initialStreamIndex, deliveryId) {
1531
1584
  response.body?.cancel().catch(() => {});
1532
1585
  return new MessageResponse({
1533
1586
  cancelTurn: async (turnId) => await this.cancel({ turnId }),
1534
- createStream: () => this.#createEventStream(initialStreamIndex, input, deliveryId),
1587
+ createStream: (source) => this.#createEventStream(initialStreamIndex, input, deliveryId, source),
1535
1588
  sessionId: this.#state.sessionId
1536
1589
  });
1537
1590
  }
1538
- async *#createEventStream(initialStreamIndex, input, deliveryId) {
1591
+ async *#createEventStream(initialStreamIndex, input, deliveryId, source) {
1539
1592
  let eventCount = 0;
1540
1593
  let started = deliveryId === void 0;
1541
1594
  let reachedBoundary = false;
1542
1595
  const pendingAuthorizations = /* @__PURE__ */ new Set();
1543
1596
  try {
1544
- for await (const event of this.#readStream({
1597
+ for await (const event of source ?? this.#readStream({
1545
1598
  headers: input.headers,
1546
- keepAlive: shouldKeepActiveTurnAlive(input.streamReconnectPolicy),
1599
+ keepAlive: true,
1547
1600
  signal: input.signal,
1548
1601
  startIndex: initialStreamIndex,
1549
1602
  streamReconnectPolicy: input.streamReconnectPolicy
@@ -1557,73 +1610,92 @@ var ClientSession = class ClientSession {
1557
1610
  if (!terminal && event.meta?.deliveryIds !== void 0 && !matches) continue;
1558
1611
  started = true;
1559
1612
  }
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);
1613
+ updatePendingAuthorizations(pendingAuthorizations, event);
1562
1614
  reachedBoundary = isCurrentTurnBoundaryEvent(event) && (event.type !== "session.waiting" || pendingAuthorizations.size === 0);
1563
1615
  yield event;
1564
1616
  if (reachedBoundary) break;
1565
1617
  }
1566
1618
  if (deliveryId !== void 0 && !reachedBoundary && !input.signal?.aborted) throw new Error("The response stream ended before the accepted message reached its turn boundary.");
1567
1619
  } finally {
1568
- this.#state = {
1569
- sessionId: this.#state.sessionId,
1570
- streamIndex: Math.max(this.#state.streamIndex, initialStreamIndex + eventCount)
1571
- };
1620
+ this.#advanceStreamIndex(initialStreamIndex + eventCount);
1572
1621
  }
1573
1622
  }
1574
1623
  async *#streamAndAdvance(options) {
1575
1624
  const startIndex = options?.startIndex ?? this.#state.streamIndex;
1576
1625
  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
- };
1626
+ for await (const event of this.#readStream({
1627
+ follow: options?.follow,
1628
+ headers: options?.headers,
1629
+ keepAlive: options?.keepAlive,
1630
+ onCaughtUp: options?.onCaughtUp,
1631
+ resolveHeaders: options?.resolveHeaders,
1632
+ resolveReconnectPolicy: options?.resolveReconnectPolicy,
1633
+ signal: options?.signal,
1634
+ startIndex,
1635
+ streamReconnectPolicy: options?.streamReconnectPolicy
1636
+ })) {
1637
+ eventCount += 1;
1638
+ if (startIndex >= 0) this.#advanceStreamIndex(startIndex + eventCount);
1639
+ yield event;
1592
1640
  }
1593
1641
  }
1642
+ #advanceStreamIndex(streamIndex) {
1643
+ this.#state = {
1644
+ sessionId: this.#state.sessionId,
1645
+ streamIndex: Math.max(this.#state.streamIndex, streamIndex)
1646
+ };
1647
+ }
1594
1648
  #readStream(input) {
1595
1649
  return followStreamIterable({
1650
+ onCaughtUp: input.onCaughtUp,
1596
1651
  follow: input.follow,
1597
1652
  host: this.#context.host,
1598
1653
  keepAlive: input.keepAlive,
1599
- resolveHeaders: () => this.#context.resolveHeaders(input.headers),
1654
+ resolveHeaders: () => this.#context.resolveHeaders(input.resolveHeaders?.() ?? input.headers),
1600
1655
  redirect: this.#context.redirect,
1601
1656
  sessionId: this.#state.sessionId,
1602
1657
  signal: input.signal,
1603
1658
  startIndex: input.startIndex,
1604
- streamReconnectPolicy: input.streamReconnectPolicy
1659
+ streamReconnectPolicy: input.streamReconnectPolicy,
1660
+ resolveReconnectPolicy: input.resolveReconnectPolicy
1605
1661
  });
1606
1662
  }
1607
1663
  };
1664
+ function followClientSession(session, options) {
1665
+ return session[followSession](options);
1666
+ }
1608
1667
  async function postSessionSend(context, path, input) {
1668
+ const readyDeadline = Date.now() + SESSION_SEND_READY_TIMEOUT_MS;
1609
1669
  let retryDelayMs = SESSION_SEND_RETRY_BASE_DELAY_MS;
1610
- for (let retry = 0;; retry += 1) {
1670
+ for (;;) {
1611
1671
  try {
1612
1672
  return await postTurn(context, path, input, false);
1613
1673
  } catch (error) {
1614
- if (!isSessionNotActive(error) || retry >= SESSION_SEND_RETRY_COUNT) throw error;
1674
+ if (!isSessionNotReady(error)) throw error;
1675
+ const remainingMs = readyDeadline - Date.now();
1676
+ if (remainingMs <= 0) throw error;
1677
+ await sleep(Math.min(retryDelayMs, remainingMs), input.signal);
1615
1678
  }
1616
- await sleep(retryDelayMs, input.signal);
1617
1679
  input.signal?.throwIfAborted();
1618
- retryDelayMs *= 2;
1680
+ retryDelayMs = Math.min(retryDelayMs * 2, SESSION_SEND_RETRY_MAX_DELAY_MS);
1619
1681
  }
1620
1682
  }
1621
- function isSessionNotActive(error) {
1622
- return error instanceof ClientError && error.status === 409 && error.code === "session_not_active";
1683
+ async function postCreateSession(context, options) {
1684
+ const headers = await context.resolveHeaders(options.headers);
1685
+ const response = await fetch(createClientUrl(context.host, EVE_SESSION_ROUTE_PATH), {
1686
+ headers,
1687
+ method: "POST",
1688
+ redirect: context.redirect,
1689
+ signal: options.signal ?? null
1690
+ });
1691
+ if (!response.ok) {
1692
+ const responseBody = await response.text();
1693
+ throw new ClientError(response.status, responseBody, response.headers);
1694
+ }
1695
+ return response;
1623
1696
  }
1624
- function shouldKeepActiveTurnAlive(policy) {
1625
- if (policy && "reconnect" in policy) return false;
1626
- return policy?.streamIdleReconnectPolicy?.maxAttempts === void 0;
1697
+ function isSessionNotReady(error) {
1698
+ return error instanceof ClientError && error.status === 409 && error.code === "session_not_ready";
1627
1699
  }
1628
1700
  async function postTurn(context, path, input, requireMessage) {
1629
1701
  const body = createMessageBody(input, requireMessage);
@@ -1672,8 +1744,9 @@ var ClientSessions = class {
1672
1744
  constructor(context) {
1673
1745
  this.#context = context;
1674
1746
  }
1675
- async create(input) {
1676
- return await ClientSession.create(this.#context, input);
1747
+ async create(input = {}) {
1748
+ if ("message" in input) return await ClientSession.create(this.#context, input);
1749
+ return { session: await ClientSession.prewarm(this.#context, input) };
1677
1750
  }
1678
1751
  attach(sessionId, options) {
1679
1752
  if (sessionId.length === 0) throw new Error("sessionId must be a non-empty string.");
@@ -1803,6 +1876,151 @@ function withRedirectPolicy(init, redirect) {
1803
1876
  };
1804
1877
  }
1805
1878
 
1879
+ //#endregion
1880
+ //#region src/client/session-event-stream.ts
1881
+ var SessionEventStream = class {
1882
+ #controller = new AbortController();
1883
+ #readers = /* @__PURE__ */ new Set();
1884
+ #caughtUp = Promise.withResolvers();
1885
+ caughtUp = this.#caughtUp.promise;
1886
+ #ended = false;
1887
+ #error;
1888
+ #headers;
1889
+ #reconnectPolicy;
1890
+ constructor(session, options) {
1891
+ this.setOptions(options);
1892
+ this.caughtUp.catch(() => {});
1893
+ if (!options.catchUp) this.#caughtUp.resolve();
1894
+ (async () => {
1895
+ try {
1896
+ for await (const event of followClientSession(session, {
1897
+ signal: this.#controller.signal,
1898
+ resolveHeaders: () => this.#headers,
1899
+ resolveReconnectPolicy: () => this.#reconnectPolicy,
1900
+ startIndex: options.startIndex,
1901
+ onCaughtUp: options.catchUp ? () => this.#caughtUp.resolve() : void 0
1902
+ })) {
1903
+ if (this.#controller.signal.aborted) return;
1904
+ options.onEvent(event);
1905
+ for (const reader of this.#readers) reader.push(event);
1906
+ if (event.type === "session.completed" || event.type === "session.failed") break;
1907
+ }
1908
+ this.#caughtUp.resolve();
1909
+ this.#finish();
1910
+ } catch (error) {
1911
+ this.#caughtUp.reject(error);
1912
+ this.#finish(error);
1913
+ if (!this.#controller.signal.aborted) options.onError(error);
1914
+ }
1915
+ })();
1916
+ }
1917
+ subscribe(signal) {
1918
+ const reader = new SessionEventReader(() => this.#readers.delete(reader), signal);
1919
+ if (this.#ended) reader.end(this.#error);
1920
+ else this.#readers.add(reader);
1921
+ return reader;
1922
+ }
1923
+ get ended() {
1924
+ return this.#ended;
1925
+ }
1926
+ setOptions(options) {
1927
+ if ("headers" in options) this.#headers = options.headers;
1928
+ if ("streamReconnectPolicy" in options) this.#reconnectPolicy = options.streamReconnectPolicy;
1929
+ }
1930
+ close() {
1931
+ const error = new DOMException("Session stream was detached.", "AbortError");
1932
+ this.#controller.abort(error);
1933
+ this.#caughtUp.reject(error);
1934
+ this.#finish(error);
1935
+ }
1936
+ #finish(error) {
1937
+ if (this.#ended) return;
1938
+ this.#ended = true;
1939
+ this.#error = error;
1940
+ for (const reader of this.#readers) reader.end(error);
1941
+ }
1942
+ };
1943
+ var SessionEventReader = class {
1944
+ #events = [];
1945
+ #wake = Promise.withResolvers();
1946
+ #ended = false;
1947
+ #error;
1948
+ #dispose;
1949
+ constructor(unsubscribe, signal) {
1950
+ const abort = () => this.end(signal?.reason);
1951
+ signal?.addEventListener("abort", abort, { once: true });
1952
+ this.#dispose = () => {
1953
+ signal?.removeEventListener("abort", abort);
1954
+ unsubscribe();
1955
+ };
1956
+ if (signal?.aborted) abort();
1957
+ }
1958
+ push(event) {
1959
+ if (this.#ended) return;
1960
+ this.#events.push(event);
1961
+ this.#wake.resolve();
1962
+ }
1963
+ end(error) {
1964
+ if (this.#ended) return;
1965
+ this.#ended = true;
1966
+ this.#error = error;
1967
+ this.#wake.resolve();
1968
+ }
1969
+ [Symbol.dispose]() {
1970
+ this.end();
1971
+ this.#events = [];
1972
+ this.#dispose();
1973
+ }
1974
+ discard() {
1975
+ this.#events = [];
1976
+ }
1977
+ async *[Symbol.asyncIterator]() {
1978
+ for (;;) {
1979
+ while (this.#events.length > 0) yield this.#events.shift();
1980
+ if (this.#ended) {
1981
+ if (this.#error !== void 0) throw this.#error;
1982
+ return;
1983
+ }
1984
+ this.#wake = Promise.withResolvers();
1985
+ await this.#wake.promise;
1986
+ }
1987
+ }
1988
+ };
1989
+
1990
+ //#endregion
1991
+ //#region src/client/eve-agent-projection.ts
1992
+ var EveAgentProjection = class {
1993
+ #reducer;
1994
+ #events;
1995
+ #data;
1996
+ constructor(reducer, events) {
1997
+ this.#reducer = reducer;
1998
+ this.#events = events;
1999
+ this.#data = this.#reduce();
2000
+ }
2001
+ get data() {
2002
+ return this.#data;
2003
+ }
2004
+ reset() {
2005
+ this.#events = [];
2006
+ this.#data = this.#reducer.initial();
2007
+ }
2008
+ append(event) {
2009
+ this.#events = [...this.#events, event];
2010
+ this.#data = this.#reducer.reduce(this.#data, event);
2011
+ }
2012
+ replace(predicate, replacement) {
2013
+ const index = this.#events.findIndex(predicate);
2014
+ this.#events = index === -1 ? [...this.#events, replacement] : this.#events.map((event, i) => i === index ? replacement : event);
2015
+ this.#data = this.#reduce();
2016
+ }
2017
+ #reduce() {
2018
+ let data = this.#reducer.initial();
2019
+ for (const event of this.#events) data = this.#reducer.reduce(data, event);
2020
+ return data;
2021
+ }
2022
+ };
2023
+
1806
2024
  //#endregion
1807
2025
  //#region src/protocol/event-dedupe.ts
1808
2026
  function createEventDeduper() {
@@ -1832,10 +2050,6 @@ function collectPendingAuthorizations(events) {
1832
2050
  for (const event of events) updatePendingAuthorizations(pending, event);
1833
2051
  return pending;
1834
2052
  }
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
2053
  function assertExclusiveTurnInput(input) {
1840
2054
  if (input.message !== void 0 === (input.inputResponses !== void 0)) throw new Error("A turn requires exactly one of message or inputResponses.");
1841
2055
  }
@@ -1865,29 +2079,78 @@ function toTerminalStreamFailureError(event) {
1865
2079
  error.name = event.data.code;
1866
2080
  return error;
1867
2081
  }
2082
+ function createActiveTurn(cancel) {
2083
+ const response = Promise.withResolvers();
2084
+ const completion = Promise.withResolvers();
2085
+ const turn = {
2086
+ abortController: new AbortController(),
2087
+ acceptedFollowUps: 0,
2088
+ cancel: () => cancel(turn),
2089
+ completion: completion.promise,
2090
+ followUpDispatches: /* @__PURE__ */ new Set(),
2091
+ receivedFollowUps: 0,
2092
+ receivedFollowUpEvents: /* @__PURE__ */ new Set(),
2093
+ followUpSubmissionIds: /* @__PURE__ */ new Set(),
2094
+ resolveCompletion: completion.resolve,
2095
+ response: response.promise,
2096
+ resolveResponse: response.resolve
2097
+ };
2098
+ return turn;
2099
+ }
2100
+ async function followSteeredTurns(turn, events, isActive) {
2101
+ while (turn.followUpDispatches.size > 0) await Promise.allSettled(turn.followUpDispatches);
2102
+ if (turn.receivedFollowUps >= turn.acceptedFollowUps) return;
2103
+ for await (const event of events) {
2104
+ if (!isActive()) return;
2105
+ if (turn.receivedFollowUpEvents.delete(event)) turn.receivedFollowUps += 1;
2106
+ if (isCurrentTurnBoundaryEvent(event)) {
2107
+ while (turn.followUpDispatches.size > 0) await Promise.allSettled(turn.followUpDispatches);
2108
+ if (turn.receivedFollowUps >= turn.acceptedFollowUps) return;
2109
+ }
2110
+ }
2111
+ }
2112
+ async function waitWithSignal(promise, signal) {
2113
+ if (signal === void 0) return await promise;
2114
+ const aborted = Promise.withResolvers();
2115
+ const onAbort = () => aborted.reject(signal.reason);
2116
+ signal.addEventListener("abort", onAbort, { once: true });
2117
+ if (signal.aborted) onAbort();
2118
+ try {
2119
+ return await Promise.race([aborted.promise, promise]);
2120
+ } finally {
2121
+ signal.removeEventListener("abort", onAbort);
2122
+ }
2123
+ }
1868
2124
 
1869
2125
  //#endregion
1870
2126
  //#region src/client/eve-agent-store.ts
1871
2127
  const detachStore = Symbol("detachEveAgentStore");
2128
+ const attachStore = Symbol("attachEveAgentStore");
1872
2129
  var EveAgentStore = class {
1873
2130
  #client;
2131
+ #autoPrewarm;
2132
+ #attached = false;
2133
+ #stream;
2134
+ #pendingAuthorizations = /* @__PURE__ */ new Set();
1874
2135
  #externalSession;
1875
2136
  #optimistic;
1876
- #reducer;
2137
+ #projection;
1877
2138
  #subscribers = /* @__PURE__ */ new Set();
1878
2139
  #seenEvents = createEventDeduper();
1879
2140
  #activeTurn;
1880
2141
  #callbacks = {};
1881
- #data;
1882
2142
  #error;
1883
2143
  #events;
1884
2144
  #pendingMessageSubmissions = [];
1885
- #projectionEvents;
2145
+ #prewarmGeneration = 0;
2146
+ #prewarmPromise;
2147
+ #prewarmController;
1886
2148
  #resumePromise;
1887
2149
  #session;
1888
2150
  #snapshot;
1889
2151
  #status = "ready";
1890
2152
  constructor(init) {
2153
+ this.#autoPrewarm = init.prewarm ?? false;
1891
2154
  this.#externalSession = init.session !== void 0;
1892
2155
  this.#client = this.#externalSession ? void 0 : new Client({
1893
2156
  auth: init.auth,
@@ -1895,13 +2158,14 @@ var EveAgentStore = class {
1895
2158
  host: init.host ?? ""
1896
2159
  });
1897
2160
  const initialEvents = [];
1898
- for (const event of init.initialEvents ?? []) if (this.#seenEvents.admit(event)) initialEvents.push(event);
2161
+ for (const event of init.initialEvents ?? []) {
2162
+ if (this.#seenEvents.admit(event)) initialEvents.push(event);
2163
+ updatePendingAuthorizations(this.#pendingAuthorizations, event);
2164
+ }
1899
2165
  this.#events = initialEvents;
1900
- this.#projectionEvents = [...this.#events];
2166
+ this.#projection = new EveAgentProjection(init.reducer, this.#events);
1901
2167
  this.#optimistic = init.optimistic ?? true;
1902
- this.#reducer = init.reducer;
1903
2168
  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
2169
  this.#snapshot = this.#createSnapshot();
1906
2170
  }
1907
2171
  get snapshot() {
@@ -1916,31 +2180,63 @@ var EveAgentStore = class {
1916
2180
  this.#subscribers.delete(callback);
1917
2181
  };
1918
2182
  }
2183
+ prewarm() {
2184
+ if (this.#prewarmPromise !== void 0) return this.#prewarmPromise;
2185
+ if (this.#session !== void 0 || this.#externalSession) return Promise.resolve();
2186
+ if (this.#activeTurn !== void 0) return this.#activeTurn.response.then((response) => {
2187
+ if (response === void 0) throw this.#error ?? new DOMException("Session creation was aborted.", "AbortError");
2188
+ });
2189
+ const client = this.#client;
2190
+ if (client === void 0) return Promise.reject(/* @__PURE__ */ new Error("This eve agent store does not own a session client."));
2191
+ const generation = this.#prewarmGeneration;
2192
+ const controller = new AbortController();
2193
+ this.#prewarmController = controller;
2194
+ const promise = (async () => {
2195
+ try {
2196
+ const created = await client.sessions.create({ signal: controller.signal });
2197
+ if (generation !== this.#prewarmGeneration) return;
2198
+ this.#session = created.session;
2199
+ this.#error = void 0;
2200
+ if (this.#status === "error") this.#status = "ready";
2201
+ this.#callbacks.onSessionChange?.(created.session.state);
2202
+ this.#publish();
2203
+ this.#ensureStream();
2204
+ } catch (error) {
2205
+ if (generation === this.#prewarmGeneration && this.#activeTurn === void 0 && this.#error === void 0) {
2206
+ this.#error = toError(error);
2207
+ this.#status = "error";
2208
+ this.#callbacks.onError?.(this.#error);
2209
+ this.#publish();
2210
+ }
2211
+ throw error;
2212
+ }
2213
+ })();
2214
+ this.#prewarmPromise = promise;
2215
+ const clear = () => {
2216
+ if (this.#prewarmPromise === promise) {
2217
+ this.#prewarmPromise = void 0;
2218
+ this.#prewarmController = void 0;
2219
+ }
2220
+ };
2221
+ promise.then(clear, clear);
2222
+ return promise;
2223
+ }
1919
2224
  async send(input) {
2225
+ return await this.#submit(input, this.#callbacks.prepareSend);
2226
+ }
2227
+ async #submit(input, prepareSend) {
1920
2228
  if (this.#activeTurn !== void 0) {
1921
2229
  if (this.#status === "resuming") throw new Error("eve session is resuming.");
1922
- return await this.#sendFollowUp(this.#activeTurn, input);
2230
+ return await this.#sendFollowUp(this.#activeTurn, input, prepareSend);
1923
2231
  }
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
- };
2232
+ 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
2233
  this.#activeTurn = turn;
1939
2234
  this.#error = void 0;
1940
2235
  this.#status = "submitted";
1941
2236
  this.#publish();
2237
+ let reader;
1942
2238
  try {
1943
- const preparedInput = await this.#callbacks.prepareSend?.(input) ?? input;
2239
+ const preparedInput = await (prepareSend === void 0 ? input : waitWithSignal(Promise.resolve(prepareSend(input)), createAbortSignal(input.signal, turn.abortController.signal)));
1944
2240
  assertExclusiveTurnInput(preparedInput);
1945
2241
  if (!this.#isActiveTurn(turn)) return;
1946
2242
  this.#projectOptimisticMessage(preparedInput);
@@ -1950,15 +2246,17 @@ var EveAgentStore = class {
1950
2246
  ...preparedInput,
1951
2247
  signal: createAbortSignal(preparedInput.signal, turn.abortController.signal)
1952
2248
  };
1953
- const response = await this.#dispatchTurn(turnInput);
2249
+ const dispatched = await this.#dispatchTurn(turnInput);
2250
+ const response = dispatched.response;
2251
+ reader = dispatched.reader;
1954
2252
  if (!this.#isActiveTurn(turn)) return;
1955
2253
  turn.resolveResponse(response);
1956
- for await (const event of response) {
2254
+ for await (const event of consumeMessageResponse(response, reader)) {
1957
2255
  if (!this.#isActiveTurn(turn)) return;
1958
- this.#acceptServerEvent(event);
2256
+ if (turn.receivedFollowUpEvents.delete(event)) turn.receivedFollowUps += 1;
1959
2257
  }
1960
2258
  if (!this.#isActiveTurn(turn)) return;
1961
- await this.#followSteeredTurns(turn);
2259
+ await followSteeredTurns(turn, reader, () => this.#isActiveTurn(turn));
1962
2260
  if (!this.#isActiveTurn(turn)) return;
1963
2261
  this.#status = this.#error === void 0 ? "ready" : "error";
1964
2262
  } catch (error) {
@@ -1967,20 +2265,15 @@ var EveAgentStore = class {
1967
2265
  this.#status = "ready";
1968
2266
  this.#failPendingMessageSubmission(toError(error));
1969
2267
  } else {
1970
- this.#error = toError(error);
2268
+ const reported = this.#error !== void 0;
2269
+ this.#error ??= toError(error);
1971
2270
  this.#status = "error";
1972
2271
  this.#failPendingMessageSubmission(this.#error);
1973
- this.#callbacks.onError?.(this.#error);
2272
+ if (!reported) this.#callbacks.onError?.(this.#error);
1974
2273
  }
1975
2274
  } 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
- }
2275
+ reader?.[Symbol.dispose]();
2276
+ this.#finishTurn(turn);
1984
2277
  }
1985
2278
  }
1986
2279
  resume() {
@@ -1996,70 +2289,34 @@ var EveAgentStore = class {
1996
2289
  async #resume() {
1997
2290
  if (this.#status === "resuming" || this.#status === "streaming" || this.#status === "submitted") throw new Error("eve session is already processing a turn.");
1998
2291
  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
2292
  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
- };
2293
+ const turn = createActiveTurn(() => session.cancel());
2014
2294
  this.#activeTurn = turn;
2015
2295
  turn.resolveResponse(void 0);
2016
2296
  this.#error = void 0;
2017
2297
  this.#status = "resuming";
2018
2298
  this.#publish();
2019
2299
  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
- }
2300
+ const stream = this.#ensureStream({
2301
+ catchUp: true,
2302
+ startIndex: this.#events.length === session.state.streamIndex ? session.state.streamIndex : 0
2303
+ });
2304
+ using reader = stream.subscribe(turn.abortController.signal);
2305
+ await stream.caughtUp;
2034
2306
  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";
2307
+ reader.discard();
2308
+ const tail = this.#events.at(-1);
2309
+ if (tail !== void 0) this.#applyTerminalStreamFailure(tail);
2310
+ if (tail !== void 0 && this.#error === void 0 && !isSettledSessionTail(this.#events)) {
2311
+ this.#status = "streaming";
2041
2312
  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
- }
2313
+ for await (const event of reader) {
2054
2314
  if (!this.#isActiveTurn(turn)) return;
2055
- if (followLive || isSettledSessionTail(replayed)) break;
2056
- followLive = true;
2315
+ if (turn.receivedFollowUpEvents.delete(event)) turn.receivedFollowUps += 1;
2316
+ if (isCurrentTurnBoundaryEvent(event) && this.#pendingAuthorizations.size === 0) break;
2057
2317
  }
2058
- } else {
2059
- this.#status = this.#error === void 0 ? "ready" : "error";
2060
- this.#publish();
2061
2318
  }
2062
- await this.#followSteeredTurns(turn);
2319
+ await followSteeredTurns(turn, reader, () => this.#isActiveTurn(turn));
2063
2320
  if (this.#isActiveTurn(turn)) this.#status = this.#error === void 0 ? "ready" : "error";
2064
2321
  } catch (error) {
2065
2322
  if (!this.#isActiveTurn(turn)) return;
@@ -2070,61 +2327,81 @@ var EveAgentStore = class {
2070
2327
  this.#callbacks.onError?.(this.#error);
2071
2328
  }
2072
2329
  } 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
- }
2330
+ this.#finishTurn(turn);
2081
2331
  }
2082
2332
  }
2083
2333
  cancel() {
2084
2334
  const turn = this.#activeTurn;
2085
- if (turn === void 0) return Promise.resolve({ status: "no_active_turn" });
2335
+ if (turn === void 0) return this.#status === "streaming" && this.#session !== void 0 ? this.#session.cancel() : Promise.resolve({ status: "no_active_turn" });
2086
2336
  return turn.cancel();
2087
2337
  }
2338
+ [attachStore]() {
2339
+ this.#attached = true;
2340
+ if (this.#autoPrewarm && this.#session === void 0) this.prewarm().catch(() => {});
2341
+ }
2088
2342
  [detachStore]() {
2343
+ this.#attached = false;
2344
+ this.#stream?.close();
2345
+ this.#stream = void 0;
2089
2346
  this.#activeTurn?.abortController.abort();
2347
+ this.#resetPrewarm();
2348
+ this.#resumePromise = void 0;
2090
2349
  }
2091
2350
  reset() {
2351
+ this.#stream?.close();
2352
+ this.#stream = void 0;
2353
+ this.#pendingAuthorizations.clear();
2092
2354
  const turn = this.#activeTurn;
2093
2355
  this.#activeTurn = void 0;
2094
2356
  turn?.resolveResponse(void 0);
2095
2357
  turn?.resolveCompletion();
2096
2358
  turn?.abortController.abort();
2359
+ this.#resetPrewarm();
2360
+ this.#resumePromise = void 0;
2097
2361
  if (!this.#externalSession) this.#session = void 0;
2098
2362
  this.#events = [];
2099
2363
  this.#seenEvents = createEventDeduper();
2100
2364
  this.#pendingMessageSubmissions = [];
2101
- this.#projectionEvents = [];
2102
- this.#data = this.#reducer.initial();
2365
+ this.#projection.reset();
2103
2366
  this.#error = void 0;
2104
2367
  this.#status = "ready";
2105
2368
  this.#callbacks.onSessionChange?.(this.#session?.state);
2106
2369
  this.#publish();
2370
+ if (this.#autoPrewarm && this.#attached) this.prewarm().catch(() => {});
2107
2371
  }
2108
- async #sendFollowUp(turn, input) {
2372
+ async #sendFollowUp(turn, input, prepareSend) {
2109
2373
  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;
2374
+ const generation = this.#prewarmGeneration;
2375
+ const signal = createAbortSignal(input.signal, turn.abortController.signal);
2376
+ const preparedInput = await waitWithSignal(Promise.resolve(prepareSend?.(input)), signal) ?? input;
2377
+ if (generation !== this.#prewarmGeneration) return;
2111
2378
  assertExclusiveTurnInput(preparedInput);
2112
2379
  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);
2380
+ if (!this.#isActiveTurn(turn)) return await this.#submit(preparedInput);
2114
2381
  const submissionId = this.#projectOptimisticMessage(preparedInput);
2115
2382
  if (submissionId !== void 0) turn.followUpSubmissionIds.add(submissionId);
2116
2383
  this.#publish();
2384
+ this.#ensureStream({
2385
+ headers: preparedInput.headers,
2386
+ streamReconnectPolicy: preparedInput.streamReconnectPolicy
2387
+ });
2117
2388
  let dispatch;
2118
2389
  dispatch = (async () => {
2119
2390
  try {
2120
- await turn.response;
2391
+ const signal = createAbortSignal(preparedInput.signal, turn.abortController.signal);
2392
+ await waitWithSignal(turn.response, signal);
2121
2393
  if (!this.#isActiveTurn(turn) || this.#session === void 0) throw new Error("The active eve turn ended before the follow-up could be sent.");
2122
2394
  const { message, ...options } = preparedInput;
2123
- await this.#session.send(message, options);
2395
+ await this.#session.send(message, {
2396
+ ...options,
2397
+ signal
2398
+ });
2124
2399
  turn.acceptedFollowUps += 1;
2125
2400
  } catch (error) {
2126
- this.#failPendingMessageSubmission(toError(error), submissionId);
2127
- this.#publish();
2401
+ if (this.#isActiveTurn(turn)) {
2402
+ this.#failPendingMessageSubmission(toError(error), submissionId);
2403
+ this.#publish();
2404
+ }
2128
2405
  throw error;
2129
2406
  } finally {
2130
2407
  turn.followUpDispatches.delete(dispatch);
@@ -2134,38 +2411,94 @@ var EveAgentStore = class {
2134
2411
  await dispatch;
2135
2412
  await turn.completion;
2136
2413
  }
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;
2414
+ async #dispatchTurn(input) {
2415
+ const streamOptions = {
2416
+ headers: input.headers,
2417
+ streamReconnectPolicy: input.streamReconnectPolicy
2418
+ };
2419
+ if (this.#prewarmPromise !== void 0) {
2420
+ await waitWithSignal(this.#prewarmPromise.catch((error) => {
2421
+ if (this.#session !== void 0) throw error;
2422
+ }), input.signal);
2423
+ input.signal?.throwIfAborted();
2424
+ }
2425
+ if (this.#session === void 0) {
2426
+ if (this.#client === void 0) throw new Error("An external eve session is required before sending.");
2427
+ if (input.message === void 0) throw new Error("Cannot answer an input request before the session starts.");
2428
+ const created = await this.#client.sessions.create({
2429
+ ...input,
2430
+ message: input.message
2431
+ });
2432
+ input.signal?.throwIfAborted();
2433
+ this.#session = created.session;
2434
+ this.#callbacks.onSessionChange?.(created.session.state);
2435
+ this.#publish();
2436
+ return {
2437
+ response: created.response,
2438
+ reader: this.#ensureStream(streamOptions).subscribe(input.signal)
2439
+ };
2440
+ }
2441
+ const reader = this.#ensureStream(streamOptions).subscribe(input.signal);
2442
+ try {
2443
+ if (input.inputResponses === void 0) {
2444
+ const { message, ...options } = input;
2445
+ return {
2446
+ response: await this.#session.send(message, options),
2447
+ reader
2448
+ };
2146
2449
  }
2450
+ const { inputResponses, ...options } = input;
2451
+ return {
2452
+ response: await this.#session.respond(inputResponses, options),
2453
+ reader
2454
+ };
2455
+ } catch (error) {
2456
+ reader[Symbol.dispose]();
2457
+ throw error;
2147
2458
  }
2148
2459
  }
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
2460
+ #ensureStream(options = {}) {
2461
+ if (this.#stream !== void 0 && !this.#stream.ended) {
2462
+ this.#stream.setOptions(options);
2463
+ return this.#stream;
2464
+ }
2465
+ if (this.#session === void 0) throw new Error("A session is required before opening its stream.");
2466
+ const session = this.#session;
2467
+ const generation = this.#prewarmGeneration;
2468
+ this.#stream = new SessionEventStream(session, {
2469
+ ...options,
2470
+ onEvent: (event) => {
2471
+ if (generation === this.#prewarmGeneration) this.#acceptServerEvent(event);
2472
+ },
2473
+ onError: (error) => {
2474
+ if (generation !== this.#prewarmGeneration) return;
2475
+ this.#stream = void 0;
2476
+ if (this.#activeTurn !== void 0) return;
2477
+ this.#error = toError(error);
2478
+ this.#status = "error";
2479
+ this.#callbacks.onError?.(this.#error);
2480
+ this.#publish();
2481
+ }
2155
2482
  });
2156
- this.#session = created.session;
2157
- this.#callbacks.onSessionChange?.(created.session.state);
2158
- this.#publish();
2159
- return created.response;
2483
+ return this.#stream;
2160
2484
  }
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);
2485
+ #resetPrewarm() {
2486
+ this.#prewarmGeneration += 1;
2487
+ this.#prewarmController?.abort();
2488
+ this.#prewarmController = void 0;
2489
+ this.#prewarmPromise = void 0;
2490
+ }
2491
+ #finishTurn(turn) {
2492
+ if (!this.#isActiveTurn(turn)) return;
2493
+ turn.resolveResponse(void 0);
2494
+ this.#activeTurn = void 0;
2495
+ try {
2496
+ this.#callbacks.onSessionChange?.(this.#session?.state);
2497
+ this.#publish();
2498
+ this.#callbacks.onFinish?.(this.#snapshot);
2499
+ } finally {
2500
+ turn.resolveCompletion();
2166
2501
  }
2167
- const { inputResponses, ...options } = input;
2168
- return await this.#session.respond(inputResponses, options);
2169
2502
  }
2170
2503
  #isActiveTurn(turn) {
2171
2504
  return this.#activeTurn === turn;
@@ -2179,7 +2512,7 @@ var EveAgentStore = class {
2179
2512
  message: summarizeUserContent(input.message)
2180
2513
  };
2181
2514
  this.#pendingMessageSubmissions = [...this.#pendingMessageSubmissions, pending];
2182
- if (this.#optimistic) this.#appendProjectionEvent({
2515
+ if (this.#optimistic) this.#projection.append({
2183
2516
  data: {
2184
2517
  createdAt: pending.createdAt,
2185
2518
  message: pending.message,
@@ -2191,7 +2524,7 @@ var EveAgentStore = class {
2191
2524
  }
2192
2525
  #projectInputResponses(input) {
2193
2526
  if (input.inputResponses === void 0 || input.inputResponses.length === 0) return;
2194
- this.#appendProjectionEvent({
2527
+ this.#projection.append({
2195
2528
  data: {
2196
2529
  createdAt: Date.now(),
2197
2530
  responses: input.inputResponses
@@ -2199,25 +2532,33 @@ var EveAgentStore = class {
2199
2532
  type: "client.input.responded"
2200
2533
  });
2201
2534
  }
2202
- #acceptServerEvent(event, options = {}) {
2535
+ #acceptServerEvent(event) {
2203
2536
  if (!this.#seenEvents.admit(event)) return;
2537
+ const wasStreaming = this.#status === "streaming";
2538
+ updatePendingAuthorizations(this.#pendingAuthorizations, event);
2204
2539
  this.#events = [...this.#events, event];
2205
2540
  this.#applyServerEvent(event);
2206
2541
  this.#callbacks.onEvent?.(event);
2207
- if (options.transitionToStreaming ?? true) this.#status = "streaming";
2208
2542
  this.#applyTerminalStreamFailure(event);
2209
- if (options.publish ?? true) this.#publish();
2543
+ const settled = isCurrentTurnBoundaryEvent(event) && this.#pendingAuthorizations.size === 0;
2544
+ if (this.#status !== "resuming" && this.#error === void 0) {
2545
+ if ("data" in event && "turnId" in event.data) this.#status = "streaming";
2546
+ if (this.#activeTurn === void 0 && settled) this.#status = "ready";
2547
+ }
2548
+ this.#callbacks.onSessionChange?.(this.#session?.state);
2549
+ this.#publish();
2550
+ if (this.#activeTurn === void 0 && wasStreaming && settled) this.#callbacks.onFinish?.(this.#snapshot);
2210
2551
  }
2211
2552
  #applyServerEvent(event) {
2212
2553
  const pendingSubmission = this.#pendingMessageSubmissions[0];
2213
2554
  if (event.type === "message.received" && pendingSubmission !== void 0) {
2214
2555
  const submissionId = pendingSubmission.id;
2215
- if (this.#activeTurn?.followUpSubmissionIds.delete(submissionId)) this.#activeTurn.receivedFollowUps += 1;
2556
+ if (this.#activeTurn?.followUpSubmissionIds.delete(submissionId)) this.#activeTurn.receivedFollowUpEvents.add(event);
2216
2557
  this.#pendingMessageSubmissions = this.#pendingMessageSubmissions.slice(1);
2217
- this.#replaceProjectionEvent((candidate) => candidate.type === "client.message.submitted" && candidate.data.submissionId === submissionId, event);
2558
+ this.#projection.replace((candidate) => candidate.type === "client.message.submitted" && candidate.data.submissionId === submissionId, event);
2218
2559
  return;
2219
2560
  }
2220
- this.#appendProjectionEvent(event);
2561
+ this.#projection.append(event);
2221
2562
  }
2222
2563
  #applyTerminalStreamFailure(event) {
2223
2564
  const error = toTerminalStreamFailureError(event);
@@ -2233,7 +2574,7 @@ var EveAgentStore = class {
2233
2574
  const pending = submissionId === void 0 ? this.#pendingMessageSubmissions[0] : this.#pendingMessageSubmissions.find((candidate) => candidate.id === submissionId);
2234
2575
  if (pending === void 0) return;
2235
2576
  this.#pendingMessageSubmissions = this.#pendingMessageSubmissions.filter((candidate) => candidate.id !== pending.id);
2236
- this.#replaceProjectionEvent((event) => event.type === "client.message.submitted" && event.data.submissionId === pending.id, {
2577
+ this.#projection.replace((event) => event.type === "client.message.submitted" && event.data.submissionId === pending.id, {
2237
2578
  data: {
2238
2579
  createdAt: pending.createdAt,
2239
2580
  error: { message: error.message },
@@ -2243,30 +2584,9 @@ var EveAgentStore = class {
2243
2584
  type: "client.message.failed"
2244
2585
  });
2245
2586
  }
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
2587
  #createSnapshot() {
2268
2588
  return {
2269
- data: this.#data,
2589
+ data: this.#projection.data,
2270
2590
  error: this.#error,
2271
2591
  events: this.#events,
2272
2592
  session: this.#session?.state,
@@ -2281,6 +2601,9 @@ var EveAgentStore = class {
2281
2601
  function detachEveAgentStore(store) {
2282
2602
  store[detachStore]();
2283
2603
  }
2604
+ function attachEveAgentStore(store) {
2605
+ store[attachStore]();
2606
+ }
2284
2607
 
2285
2608
  //#endregion
2286
2609
  //#region src/client/agent-host.ts
@@ -2937,7 +3260,6 @@ var SvelteEveAgent = class {
2937
3260
  });
2938
3261
  return () => {
2939
3262
  unsubscribe();
2940
- detachEveAgentStore(store);
2941
3263
  };
2942
3264
  });
2943
3265
  }
@@ -2967,6 +3289,9 @@ var SvelteEveAgent = class {
2967
3289
  reset = () => {
2968
3290
  this.#store.reset();
2969
3291
  };
3292
+ prewarm = () => {
3293
+ return this.#store.prewarm();
3294
+ };
2970
3295
  resume = () => {
2971
3296
  return this.#store.resume();
2972
3297
  };
@@ -2996,6 +3321,7 @@ function useEveAgent(options = {}) {
2996
3321
  initialEvents: options.initialEvents,
2997
3322
  initialSession: options.initialSession,
2998
3323
  optimistic: options.optimistic,
3324
+ prewarm: options.prewarm,
2999
3325
  reducer,
3000
3326
  session: options.session
3001
3327
  });
@@ -3006,7 +3332,11 @@ function useEveAgent(options = {}) {
3006
3332
  onSessionChange: options.onSessionChange,
3007
3333
  prepareSend: options.prepareSend
3008
3334
  });
3009
- if ("window" in globalThis && options.resume) store.resume();
3335
+ if ("window" in globalThis) onMount(() => {
3336
+ attachEveAgentStore(store);
3337
+ if (options.resume) store.resume();
3338
+ return () => detachEveAgentStore(store);
3339
+ });
3010
3340
  return new SvelteEveAgent(store);
3011
3341
  }
3012
3342