eve 0.30.8 → 0.31.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (231) hide show
  1. package/CHANGELOG.md +38 -0
  2. package/README.md +5 -6
  3. package/dist/src/acp/adapter.d.ts +10 -4
  4. package/dist/src/acp/adapter.js +1 -1
  5. package/dist/src/channel/adapter-context.d.ts +1 -1
  6. package/dist/src/channel/adapter.d.ts +2 -4
  7. package/dist/src/channel/adapter.js +1 -1
  8. package/dist/src/channel/channel-address.d.ts +58 -0
  9. package/dist/src/channel/channel-address.js +1 -0
  10. package/dist/src/channel/channel-operations.d.ts +72 -0
  11. package/dist/src/channel/channel-operations.js +1 -0
  12. package/dist/src/channel/compiled-channel.d.ts +10 -6
  13. package/dist/src/channel/cross-channel-receive.d.ts +13 -25
  14. package/dist/src/channel/cross-channel-receive.js +2 -2
  15. package/dist/src/channel/receive-target.d.ts +1 -2
  16. package/dist/src/channel/routes.d.ts +21 -149
  17. package/dist/src/channel/schedule.d.ts +1 -1
  18. package/dist/src/channel/schedule.js +1 -1
  19. package/dist/src/channel/send-input.d.ts +6 -0
  20. package/dist/src/channel/send-input.js +1 -0
  21. package/dist/src/channel/session.d.ts +44 -30
  22. package/dist/src/channel/session.js +1 -1
  23. package/dist/src/channel/types.d.ts +8 -35
  24. package/dist/src/chunks/{use-eve-agent-DDoDDmJ2.js → use-eve-agent-CF5D6jSV.js} +339 -367
  25. package/dist/src/chunks/{use-eve-agent-Bx-ONuyb.js → use-eve-agent-DbYZLG0h.js} +342 -368
  26. package/dist/src/cli/commands/agent-prompt/build-and-verify.md +1 -2
  27. package/dist/src/cli/commands/channel-add-conflicts.js +1 -1
  28. package/dist/src/cli/commands/info.d.ts +1 -1
  29. package/dist/src/cli/commands/info.js +1 -1
  30. package/dist/src/cli/dev/tui/runner.d.ts +1 -1
  31. package/dist/src/cli/dev/tui/runner.js +1 -1
  32. package/dist/src/cli/dev/tui/subagent-pump.js +1 -1
  33. package/dist/src/cli/dev/tui/tui.js +1 -1
  34. package/dist/src/cli/invoke/invoke.d.ts +1 -1
  35. package/dist/src/cli/invoke/invoke.js +1 -1
  36. package/dist/src/cli/invoke/result.d.ts +0 -11
  37. package/dist/src/cli/invoke/result.js +1 -1
  38. package/dist/src/client/client-error.d.ts +2 -0
  39. package/dist/src/client/client-error.js +1 -1
  40. package/dist/src/client/client.d.ts +7 -14
  41. package/dist/src/client/client.js +1 -1
  42. package/dist/src/client/eve-agent-store.d.ts +4 -4
  43. package/dist/src/client/eve-agent-store.js +1 -1
  44. package/dist/src/client/index.d.ts +2 -1
  45. package/dist/src/client/index.js +1 -1
  46. package/dist/src/client/message-response.d.ts +2 -7
  47. package/dist/src/client/message-response.js +1 -1
  48. package/dist/src/client/open-stream.js +1 -1
  49. package/dist/src/client/session-controls.d.ts +29 -0
  50. package/dist/src/client/session-controls.js +1 -0
  51. package/dist/src/client/session-utils.d.ts +0 -20
  52. package/dist/src/client/session-utils.js +1 -1
  53. package/dist/src/client/session.d.ts +26 -90
  54. package/dist/src/client/session.js +1 -1
  55. package/dist/src/client/sessions.d.ts +20 -0
  56. package/dist/src/client/sessions.js +1 -0
  57. package/dist/src/client/types.d.ts +26 -47
  58. package/dist/src/compiler/extension-compatibility.d.ts +2 -2
  59. package/dist/src/compiler/extension-compatibility.js +1 -1
  60. package/dist/src/compiler/normalize-subagent.js +1 -1
  61. package/dist/src/context/container.d.ts +3 -0
  62. package/dist/src/context/container.js +1 -1
  63. package/dist/src/discover/filesystem.js +1 -1
  64. package/dist/src/evals/cli/eval-client.js +1 -1
  65. package/dist/src/evals/context.js +1 -1
  66. package/dist/src/evals/session.d.ts +7 -6
  67. package/dist/src/evals/session.js +1 -1
  68. package/dist/src/evals/types.d.ts +9 -9
  69. package/dist/src/execution/agent-handle-dispatch.js +1 -1
  70. package/dist/src/execution/cancel-descendant-turns-step.js +1 -1
  71. package/dist/src/execution/dispatch-runtime-actions-step.js +1 -1
  72. package/dist/src/execution/parked-delivery-wait.js +1 -1
  73. package/dist/src/execution/remote-agent-dispatch.d.ts +1 -3
  74. package/dist/src/execution/remote-agent-dispatch.js +1 -1
  75. package/dist/src/execution/runtime-context.js +1 -1
  76. package/dist/src/execution/runtime-errors.d.ts +1 -1
  77. package/dist/src/execution/session-command-inbox.d.ts +11 -3
  78. package/dist/src/execution/session-command-token.d.ts +2 -0
  79. package/dist/src/execution/session-command-token.js +1 -1
  80. package/dist/src/execution/session-command-wire.d.ts +24 -0
  81. package/dist/src/execution/session-command-wire.js +1 -0
  82. package/dist/src/execution/settle-cancelled-turn-step.js +1 -1
  83. package/dist/src/execution/subagent-hitl-proxy.js +1 -1
  84. package/dist/src/execution/turn-control-receiver.d.ts +2 -2
  85. package/dist/src/execution/turn-control-receiver.js +1 -1
  86. package/dist/src/execution/turn-workflow.js +1 -1
  87. package/dist/src/execution/workflow-entry.js +1 -1
  88. package/dist/src/execution/workflow-runtime.js +1 -1
  89. package/dist/src/execution/workflow-steps.js +1 -1
  90. package/dist/src/harness/authorization.d.ts +8 -0
  91. package/dist/src/harness/authorization.js +1 -1
  92. package/dist/src/harness/cancelled-turn-emission.d.ts +1 -1
  93. package/dist/src/harness/cancelled-turn-emission.js +1 -1
  94. package/dist/src/harness/emission.d.ts +1 -1
  95. package/dist/src/harness/emission.js +1 -1
  96. package/dist/src/harness/handles/prompt.d.ts +22 -3
  97. package/dist/src/harness/handles/prompt.js +1 -1
  98. package/dist/src/harness/handles/store.d.ts +0 -5
  99. package/dist/src/harness/handles/store.js +1 -1
  100. package/dist/src/harness/runtime-actions.js +1 -1
  101. package/dist/src/harness/session-limit-enforcement.js +1 -1
  102. package/dist/src/harness/tool-loop.js +1 -1
  103. package/dist/src/internal/application/package.js +1 -1
  104. package/dist/src/internal/nitro/dev-runtime-artifacts.js +1 -1
  105. package/dist/src/internal/nitro/dev-runtime-source-snapshot-copy.js +1 -1
  106. package/dist/src/internal/nitro/dev-runtime-source-snapshot-local-roots.d.ts +15 -0
  107. package/dist/src/internal/nitro/dev-runtime-source-snapshot-local-roots.js +1 -0
  108. package/dist/src/internal/nitro/dev-runtime-source-snapshot.d.ts +14 -2
  109. package/dist/src/internal/nitro/dev-runtime-source-snapshot.js +1 -1
  110. package/dist/src/internal/nitro/host/dev-authored-source-watcher.js +1 -1
  111. package/dist/src/internal/nitro/host/dev-server-http.js +1 -1
  112. package/dist/src/internal/nitro/routes/channel-dispatch.d.ts +2 -5
  113. package/dist/src/internal/nitro/routes/channel-dispatch.js +1 -1
  114. package/dist/src/internal/nitro/routes/channel-route-context.d.ts +4 -3
  115. package/dist/src/internal/nitro/routes/channel-route-context.js +1 -1
  116. package/dist/src/packages/eve-catalog/src/index.js +1 -1
  117. package/dist/src/protocol/cancel-turn.d.ts +9 -4
  118. package/dist/src/protocol/cancel-turn.js +1 -1
  119. package/dist/src/protocol/message.d.ts +4 -14
  120. package/dist/src/protocol/message.js +2 -2
  121. package/dist/src/protocol/reset-session.d.ts +1 -1
  122. package/dist/src/protocol/routes.d.ts +27 -47
  123. package/dist/src/protocol/routes.js +1 -1
  124. package/dist/src/public/channels/chat-sdk/chatSdkChannel.d.ts +19 -21
  125. package/dist/src/public/channels/chat-sdk/chatSdkChannel.js +2 -2
  126. package/dist/src/public/channels/discord/discordChannel.d.ts +4 -4
  127. package/dist/src/public/channels/discord/discordChannel.js +1 -1
  128. package/dist/src/public/channels/eve.d.ts +11 -10
  129. package/dist/src/public/channels/eve.js +1 -1
  130. package/dist/src/public/channels/github/dispatch.d.ts +8 -8
  131. package/dist/src/public/channels/github/dispatch.js +1 -1
  132. package/dist/src/public/channels/github/githubChannel.d.ts +3 -3
  133. package/dist/src/public/channels/github/githubChannel.js +1 -1
  134. package/dist/src/public/channels/github/pr-context.d.ts +1 -1
  135. package/dist/src/public/channels/index.d.ts +1 -1
  136. package/dist/src/public/channels/linear/linearChannel.d.ts +3 -3
  137. package/dist/src/public/channels/linear/linearChannel.js +1 -1
  138. package/dist/src/public/channels/slack/index.d.ts +1 -1
  139. package/dist/src/public/channels/slack/interactions.d.ts +3 -4
  140. package/dist/src/public/channels/slack/interactions.js +1 -1
  141. package/dist/src/public/channels/slack/session-operations.d.ts +37 -0
  142. package/dist/src/public/channels/slack/session-operations.js +1 -0
  143. package/dist/src/public/channels/slack/slackChannel.d.ts +55 -74
  144. package/dist/src/public/channels/slack/slackChannel.js +1 -1
  145. package/dist/src/public/channels/teams/teamsChannel.d.ts +3 -3
  146. package/dist/src/public/channels/teams/teamsChannel.js +1 -1
  147. package/dist/src/public/channels/telegram/telegramChannel.d.ts +4 -4
  148. package/dist/src/public/channels/telegram/telegramChannel.js +1 -1
  149. package/dist/src/public/channels/twilio/twilioChannel.d.ts +3 -3
  150. package/dist/src/public/channels/twilio/twilioChannel.js +1 -1
  151. package/dist/src/public/definitions/callback-context.d.ts +1 -2
  152. package/dist/src/public/definitions/channel.d.ts +21 -86
  153. package/dist/src/public/definitions/channel.js +1 -1
  154. package/dist/src/public/definitions/remote-agent.js +1 -1
  155. package/dist/src/public/definitions/schedule.d.ts +16 -16
  156. package/dist/src/public/definitions/tool.d.ts +18 -14
  157. package/dist/src/public/schedules/index.d.ts +1 -1
  158. package/dist/src/react/use-eve-agent.d.ts +7 -4
  159. package/dist/src/react/use-eve-agent.js +1 -1
  160. package/dist/src/runtime/agent/bootstrap-model-utils.d.ts +11 -0
  161. package/dist/src/runtime/agent/bootstrap-model-utils.js +1 -1
  162. package/dist/src/runtime/agent/mock-model-adapter.js +1 -1
  163. package/dist/src/runtime/agent/mock-model-fixtures.js +2 -2
  164. package/dist/src/runtime/connections/scoped-authorization.js +1 -1
  165. package/dist/src/runtime/framework-tools/connection-search-dynamic.js +2 -2
  166. package/dist/src/runtime/prompt/compose.js +1 -1
  167. package/dist/src/runtime/subagents/dynamic-remote-agent-config.js +1 -1
  168. package/dist/src/runtime/types.d.ts +2 -2
  169. package/dist/src/services/inspect-application.d.ts +1 -1
  170. package/dist/src/services/inspect-application.js +1 -1
  171. package/dist/src/setup/channel-add-conflicts.js +1 -1
  172. package/dist/src/setup/scaffold/create/project.js +1 -1
  173. package/dist/src/setup/scaffold/create/web-template.d.ts +1 -1
  174. package/dist/src/setup/scaffold/create/web-template.js +29 -17
  175. package/dist/src/shared/channel-definition.d.ts +7 -7
  176. package/dist/src/shared/schedule-definition.d.ts +2 -2
  177. package/dist/src/svelte/index.js +1 -1
  178. package/dist/src/svelte/use-eve-agent.d.ts +8 -5
  179. package/dist/src/svelte/use-eve-agent.js +1 -1
  180. package/dist/src/vue/index.js +1 -1
  181. package/dist/src/vue/use-eve-agent.d.ts +8 -5
  182. package/dist/src/vue/use-eve-agent.js +1 -1
  183. package/docs/README.md +6 -6
  184. package/docs/channels/chat-sdk.mdx +5 -6
  185. package/docs/channels/custom.mdx +116 -144
  186. package/docs/channels/discord.mdx +1 -1
  187. package/docs/channels/eve.mdx +76 -30
  188. package/docs/channels/github.mdx +1 -1
  189. package/docs/channels/linear.mdx +6 -8
  190. package/docs/channels/overview.mdx +2 -2
  191. package/docs/channels/slack.mdx +46 -15
  192. package/docs/channels/telegram.mdx +1 -1
  193. package/docs/channels/twilio.mdx +1 -1
  194. package/docs/concepts/default-harness.md +11 -3
  195. package/docs/concepts/execution-model-and-durability.mdx +17 -5
  196. package/docs/concepts/sessions-runs-and-streaming.md +42 -16
  197. package/docs/evals/cases.mdx +3 -3
  198. package/docs/evals/targets.mdx +1 -1
  199. package/docs/guides/auth-and-route-protection.md +2 -1
  200. package/docs/guides/client/continuations.mdx +50 -77
  201. package/docs/guides/client/messages.mdx +29 -33
  202. package/docs/guides/client/output-schema.mdx +7 -14
  203. package/docs/guides/client/overview.mdx +40 -11
  204. package/docs/guides/client/streaming.mdx +17 -23
  205. package/docs/guides/frontend/nuxt.mdx +1 -1
  206. package/docs/guides/frontend/overview.mdx +40 -36
  207. package/docs/guides/frontend/sveltekit.mdx +1 -1
  208. package/docs/guides/frontend/use-eve-agent-svelte.mdx +19 -23
  209. package/docs/guides/frontend/use-eve-agent-vue.mdx +21 -25
  210. package/docs/guides/instrumentation.md +1 -1
  211. package/docs/guides/meta.json +2 -1
  212. package/docs/guides/remote-agents.md +6 -4
  213. package/docs/guides/ucp.mdx +181 -0
  214. package/docs/patterns/dynamic-scheduling.md +16 -15
  215. package/docs/schedules.mdx +10 -11
  216. package/docs/subagents.mdx +1 -1
  217. package/docs/tools/human-in-the-loop.md +1 -1
  218. package/docs/tutorial/ship-it.mdx +1 -1
  219. package/package.json +1 -1
  220. package/dist/src/channel/cancel.d.ts +0 -6
  221. package/dist/src/channel/cancel.js +0 -1
  222. package/dist/src/channel/clear-session.d.ts +0 -4
  223. package/dist/src/channel/clear-session.js +0 -1
  224. package/dist/src/channel/compact-session.d.ts +0 -4
  225. package/dist/src/channel/compact-session.js +0 -1
  226. package/dist/src/channel/reset-session.d.ts +0 -6
  227. package/dist/src/channel/reset-session.js +0 -1
  228. package/dist/src/channel/resolve-active-session.d.ts +0 -4
  229. package/dist/src/channel/resolve-active-session.js +0 -1
  230. package/dist/src/channel/send.d.ts +0 -6
  231. package/dist/src/channel/send.js +0 -1
@@ -5,13 +5,13 @@ import { z } from "#compiled/zod/index.js";
5
5
  const EVE_ROUTE_PREFIX = "/eve/v1";
6
6
  const EVE_HEALTH_ROUTE_PATH = `${EVE_ROUTE_PREFIX}/health`;
7
7
  const EVE_INFO_ROUTE_PATH = `${EVE_ROUTE_PREFIX}/info`;
8
- const EVE_CREATE_SESSION_ROUTE_PATH = `${EVE_ROUTE_PREFIX}/session`;
9
- const EVE_RESET_SESSION_ROUTE_PATH = `${EVE_ROUTE_PREFIX}/session/reset`;
10
- const EVE_COMPACT_SESSION_ROUTE_PATH = `${EVE_ROUTE_PREFIX}/session/compact`;
11
- const EVE_CLEAR_SESSION_ROUTE_PATH = `${EVE_ROUTE_PREFIX}/session/clear`;
12
- const EVE_CONTINUE_SESSION_ROUTE_PATTERN = `${EVE_ROUTE_PREFIX}/session/:sessionId`;
13
- const EVE_MESSAGE_STREAM_ROUTE_PATTERN = `${EVE_ROUTE_PREFIX}/session/:sessionId/stream`;
14
- const EVE_CANCEL_TURN_ROUTE_PATTERN = `${EVE_ROUTE_PREFIX}/session/:sessionId/cancel`;
8
+ const EVE_SESSION_ROUTE_PATH = `${EVE_ROUTE_PREFIX}/session`;
9
+ const EVE_SESSION_ROUTE_PATTERN = `${EVE_SESSION_ROUTE_PATH}/:sessionId`;
10
+ const EVE_SESSION_CANCEL_ROUTE_PATTERN = `${EVE_SESSION_ROUTE_PATH}/:sessionId/cancel`;
11
+ const EVE_SESSION_COMPACT_ROUTE_PATTERN = `${EVE_SESSION_ROUTE_PATH}/:sessionId/compact`;
12
+ const EVE_SESSION_CLEAR_ROUTE_PATTERN = `${EVE_SESSION_ROUTE_PATH}/:sessionId/clear`;
13
+ const EVE_SESSION_RESET_ROUTE_PATTERN = `${EVE_SESSION_ROUTE_PATH}/:sessionId/reset`;
14
+ const EVE_SESSION_STREAM_ROUTE_PATTERN = `${EVE_SESSION_ROUTE_PATH}/:sessionId/stream`;
15
15
  const EVE_DEV_DISPATCH_SCHEDULE_ROUTE_PATTERN = `${EVE_ROUTE_PREFIX}/dev/schedules/:scheduleId`;
16
16
  const EVE_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH = `${EVE_ROUTE_PREFIX}/dev/runtime-artifacts`;
17
17
  const EVE_DEV_RUNTIME_ARTIFACTS_REBUILD_ROUTE_PATH = `${EVE_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH}/rebuild`;
@@ -19,14 +19,23 @@ const EVE_DEV_RUNTIME_ARTIFACTS_SUSPEND_ROUTE_PATH = `${EVE_DEV_RUNTIME_ARTIFACT
19
19
  const EVE_DEV_RUNTIME_ARTIFACTS_RESUME_ROUTE_PATH = `${EVE_DEV_RUNTIME_ARTIFACTS_ROUTE_PATH}/resume`;
20
20
  const EVE_CONNECTION_CALLBACK_ROUTE_PATTERN = `${EVE_ROUTE_PREFIX}/connections/:name/callback/:token`;
21
21
  const EVE_CALLBACK_ROUTE_PATTERN = `${EVE_ROUTE_PREFIX}/callback/:token`;
22
- function createEveMessageStreamRoutePath(sessionId) {
23
- return `${EVE_ROUTE_PREFIX}/session/${encodeURIComponent(sessionId)}/stream`;
22
+ function createEveSessionRoutePath(sessionId) {
23
+ return `${EVE_SESSION_ROUTE_PATH}/${encodeURIComponent(sessionId)}`;
24
24
  }
25
- function createEveContinueSessionRoutePath(sessionId) {
26
- return `${EVE_ROUTE_PREFIX}/session/${encodeURIComponent(sessionId)}`;
25
+ function createEveSessionCancelRoutePath(sessionId) {
26
+ return `${EVE_SESSION_ROUTE_PATH}/${encodeURIComponent(sessionId)}/cancel`;
27
27
  }
28
- function createEveCancelTurnRoutePath(sessionId) {
29
- return `${EVE_ROUTE_PREFIX}/session/${encodeURIComponent(sessionId)}/cancel`;
28
+ function createEveSessionCompactRoutePath(sessionId) {
29
+ return `${EVE_SESSION_ROUTE_PATH}/${encodeURIComponent(sessionId)}/compact`;
30
+ }
31
+ function createEveSessionClearRoutePath(sessionId) {
32
+ return `${EVE_SESSION_ROUTE_PATH}/${encodeURIComponent(sessionId)}/clear`;
33
+ }
34
+ function createEveSessionResetRoutePath(sessionId) {
35
+ return `${EVE_SESSION_ROUTE_PATH}/${encodeURIComponent(sessionId)}/reset`;
36
+ }
37
+ function createEveSessionStreamRoutePath(sessionId) {
38
+ return `${EVE_SESSION_ROUTE_PATH}/${encodeURIComponent(sessionId)}/stream`;
30
39
  }
31
40
 
32
41
  //#endregion
@@ -254,17 +263,23 @@ function isObject(value) {
254
263
  //#endregion
255
264
  //#region src/client/client-error.ts
256
265
  var ClientError = class extends Error {
266
+ code;
257
267
  status;
258
268
  body;
259
269
  headers;
260
270
  constructor(status, body, headers) {
261
271
  let message = body || `Server returned ${status}.`;
272
+ let code;
262
273
  try {
263
274
  const parsed = JSON.parse(body);
264
- if (isObject(parsed) && typeof parsed.error === "string") message = parsed.error;
275
+ if (isObject(parsed)) {
276
+ if (typeof parsed.error === "string") message = parsed.error;
277
+ if (typeof parsed.code === "string") code = parsed.code;
278
+ }
265
279
  } catch {}
266
280
  super(message);
267
281
  this.name = "ClientError";
282
+ this.code = code;
268
283
  this.status = status;
269
284
  this.body = body;
270
285
  this.headers = Object.freeze(Object.fromEntries(new Headers(headers).entries()));
@@ -377,47 +392,6 @@ function isTurnFailureEvent(event) {
377
392
  return event.type === "session.failed" || event.type === "step.failed" || event.type === "turn.failed";
378
393
  }
379
394
 
380
- //#endregion
381
- //#region src/protocol/cancel-turn.ts
382
- const CancelTurnResponseSchema = z.object({
383
- ok: z.literal(true),
384
- sessionId: z.string().min(1),
385
- status: z.enum(["accepted", "no_active_turn"])
386
- });
387
-
388
- //#endregion
389
- //#region src/protocol/clear-session.ts
390
- const ClearResponseSchema = z.discriminatedUnion("status", [z.object({
391
- ok: z.literal(true),
392
- sessionId: z.string().min(1),
393
- status: z.literal("accepted")
394
- }), z.object({
395
- ok: z.literal(true),
396
- status: z.literal("no_active_session")
397
- })]);
398
-
399
- //#endregion
400
- //#region src/protocol/compact-session.ts
401
- const CompactResponseSchema = z.discriminatedUnion("status", [z.object({
402
- ok: z.literal(true),
403
- sessionId: z.string().min(1),
404
- status: z.literal("accepted")
405
- }), z.object({
406
- ok: z.literal(true),
407
- status: z.literal("no_active_session")
408
- })]);
409
-
410
- //#endregion
411
- //#region src/protocol/reset-session.ts
412
- const ResetResponseSchema = z.discriminatedUnion("status", [z.object({
413
- ok: z.literal(true),
414
- previousSessionId: z.string().min(1),
415
- status: z.literal("reset")
416
- }), z.object({
417
- ok: z.literal(true),
418
- status: z.literal("no_active_session")
419
- })]);
420
-
421
395
  //#endregion
422
396
  //#region src/client/output-schema.ts
423
397
  function extractCompletedResult(events) {
@@ -431,24 +405,6 @@ function isResultCompletedEvent(event) {
431
405
 
432
406
  //#endregion
433
407
  //#region src/client/session-utils.ts
434
- function createInitialSessionState() {
435
- return { streamIndex: 0 };
436
- }
437
- function advanceSession(input) {
438
- const boundaryEvent = findBoundaryEvent(input.events);
439
- const streamIndex = input.session.streamIndex + input.events.length;
440
- if (boundaryEvent?.type === "session.waiting" || input.preserveCompletedSessions === true && boundaryEvent?.type === "session.completed") return {
441
- continuationToken: boundaryEvent?.type === "session.waiting" ? boundaryEvent.data.continuationToken : input.continuationToken ?? input.session.continuationToken,
442
- sessionId: input.sessionId,
443
- streamIndex
444
- };
445
- if (boundaryEvent === void 0) return {
446
- continuationToken: input.continuationToken ?? input.session.continuationToken,
447
- sessionId: input.sessionId,
448
- streamIndex
449
- };
450
- return createInitialSessionState();
451
- }
452
408
  function summarizeTurnEvents(events) {
453
409
  let boundary;
454
410
  let failure;
@@ -472,12 +428,6 @@ function summarizeTurnEvents(events) {
472
428
  status: boundary?.type === "session.waiting" ? "waiting" : boundary?.type === "session.failed" ? "failed" : "completed"
473
429
  };
474
430
  }
475
- function findBoundaryEvent(events) {
476
- for (let i = events.length - 1; i >= 0; i--) {
477
- const event = events[i];
478
- if (event !== void 0 && isCurrentTurnBoundaryEvent(event)) return event;
479
- }
480
- }
481
431
  function isFinalMessageCompleted(event) {
482
432
  return event.type === "message.completed" && event.data.finishReason !== "tool-calls";
483
433
  }
@@ -485,12 +435,10 @@ function isFinalMessageCompleted(event) {
485
435
  //#endregion
486
436
  //#region src/client/message-response.ts
487
437
  var MessageResponse = class {
488
- continuationToken;
489
438
  sessionId;
490
439
  #consumed = false;
491
440
  #createStream;
492
441
  constructor(input) {
493
- this.continuationToken = input.continuationToken;
494
442
  this.sessionId = input.sessionId;
495
443
  this.#createStream = input.createStream;
496
444
  }
@@ -682,7 +630,7 @@ async function* followStreamIterable(input) {
682
630
  if (input.signal?.aborted || input.startIndex < 0 || idleRetryPolicy.maxAttempts === 0) return;
683
631
  if (!deliveredEvent && !initialConnection && (idleReconnects += 1) >= idleRetryPolicy.maxAttempts) return;
684
632
  initialConnection = false;
685
- await sleep$1(reconnectDelayMs, input.signal);
633
+ await sleep(reconnectDelayMs, input.signal);
686
634
  if (input.signal?.aborted) return;
687
635
  reconnectDelayMs = Math.min(reconnectDelayMs * 2, idleRetryPolicy.maxDelayMs);
688
636
  }
@@ -698,7 +646,7 @@ async function openStreamBody(input) {
698
646
  if (input.startIndex !== 0) searchParams.startIndex = String(input.startIndex);
699
647
  if (input.requestTailIndex === true) searchParams.includeTailIndex = "1";
700
648
  for (let attempt = 0; attempt < openRetryPolicy.maxAttempts; attempt += 1) {
701
- const url = createClientUrl(input.host, createEveMessageStreamRoutePath(input.sessionId), Object.keys(searchParams).length > 0 ? searchParams : void 0);
649
+ const url = createClientUrl(input.host, createEveSessionStreamRoutePath(input.sessionId), Object.keys(searchParams).length > 0 ? searchParams : void 0);
702
650
  const headers = await input.resolveHeaders();
703
651
  let response;
704
652
  try {
@@ -710,7 +658,7 @@ async function openStreamBody(input) {
710
658
  });
711
659
  } catch (error) {
712
660
  if (input.signal?.aborted || !isStreamDisconnectError(error) || attempt === openRetryPolicy.maxAttempts - 1) throw error;
713
- await sleep$1(retryDelayMs, input.signal);
661
+ await sleep(retryDelayMs, input.signal);
714
662
  retryDelayMs = Math.min(retryDelayMs * 2, openRetryPolicy.maxDelayMs);
715
663
  continue;
716
664
  }
@@ -726,7 +674,7 @@ async function openStreamBody(input) {
726
674
  lastHeaders = response.headers;
727
675
  if (!retryPolicy.retryableErrorStatuses.has(response.status)) throw new ClientError(response.status, lastBody, response.headers);
728
676
  if (attempt < openRetryPolicy.maxAttempts - 1) {
729
- await sleep$1(retryDelayMs, input.signal);
677
+ await sleep(retryDelayMs, input.signal);
730
678
  retryDelayMs = Math.min(retryDelayMs * 2, openRetryPolicy.maxDelayMs);
731
679
  }
732
680
  }
@@ -738,7 +686,7 @@ function parseTailIndexHeader(headers) {
738
686
  const parsed = Number(raw);
739
687
  return Number.isSafeInteger(parsed) ? parsed : void 0;
740
688
  }
741
- async function sleep$1(ms, signal) {
689
+ async function sleep(ms, signal) {
742
690
  if (signal?.aborted) return;
743
691
  await new Promise((resolve) => {
744
692
  const onAbort = () => {
@@ -753,6 +701,132 @@ async function sleep$1(ms, signal) {
753
701
  });
754
702
  }
755
703
 
704
+ //#endregion
705
+ //#region src/protocol/cancel-turn.ts
706
+ const CancelTurnResponseSchema = z.discriminatedUnion("status", [z.strictObject({
707
+ ok: z.literal(true),
708
+ sessionId: z.string().min(1),
709
+ status: z.literal("accepted")
710
+ }), z.strictObject({
711
+ ok: z.literal(true),
712
+ status: z.literal("no_active_turn")
713
+ })]);
714
+
715
+ //#endregion
716
+ //#region src/protocol/clear-session.ts
717
+ const ClearResponseSchema = z.discriminatedUnion("status", [z.object({
718
+ ok: z.literal(true),
719
+ sessionId: z.string().min(1),
720
+ status: z.literal("accepted")
721
+ }), z.object({
722
+ ok: z.literal(true),
723
+ status: z.literal("no_active_session")
724
+ })]);
725
+
726
+ //#endregion
727
+ //#region src/protocol/compact-session.ts
728
+ const CompactResponseSchema = z.discriminatedUnion("status", [z.object({
729
+ ok: z.literal(true),
730
+ sessionId: z.string().min(1),
731
+ status: z.literal("accepted")
732
+ }), z.object({
733
+ ok: z.literal(true),
734
+ status: z.literal("no_active_session")
735
+ })]);
736
+
737
+ //#endregion
738
+ //#region src/protocol/reset-session.ts
739
+ const ResetResponseSchema = z.discriminatedUnion("status", [z.object({
740
+ ok: z.literal(true),
741
+ previousSessionId: z.string().min(1),
742
+ status: z.literal("reset")
743
+ }), z.object({
744
+ ok: z.literal(true),
745
+ status: z.literal("no_active_session")
746
+ })]);
747
+
748
+ //#endregion
749
+ //#region src/client/session-controls.ts
750
+ async function cancelClientSession(input) {
751
+ const { payload, response } = await postJson({
752
+ body: input.options,
753
+ context: input.context,
754
+ operation: "Cancel",
755
+ path: createEveSessionCancelRoutePath(input.sessionId)
756
+ });
757
+ const result = CancelTurnResponseSchema.safeParse(payload);
758
+ if (!result.success || result.data.status === "accepted" && result.data.sessionId !== input.sessionId) throw new Error(`Cancel route returned an invalid response (${response.status}).`);
759
+ return result.data.status === "accepted" ? {
760
+ sessionId: result.data.sessionId,
761
+ status: "accepted"
762
+ } : { status: "no_active_turn" };
763
+ }
764
+ async function clearClientSession(input) {
765
+ const { payload } = await postJson({
766
+ context: input.context,
767
+ operation: "Clear",
768
+ path: createEveSessionClearRoutePath(input.sessionId)
769
+ });
770
+ const result = ClearResponseSchema.safeParse(payload);
771
+ if (!result.success || result.data.status === "accepted" && result.data.sessionId !== input.sessionId) throw new Error("Clear route returned an invalid response.");
772
+ return result.data.status === "accepted" ? {
773
+ sessionId: result.data.sessionId,
774
+ status: "accepted"
775
+ } : { status: "no_active_session" };
776
+ }
777
+ async function compactClientSession(input) {
778
+ const { payload } = await postJson({
779
+ context: input.context,
780
+ operation: "Compact",
781
+ path: createEveSessionCompactRoutePath(input.sessionId)
782
+ });
783
+ const result = CompactResponseSchema.safeParse(payload);
784
+ if (!result.success || result.data.status === "accepted" && result.data.sessionId !== input.sessionId) throw new Error("Compact route returned an invalid response.");
785
+ return result.data.status === "accepted" ? {
786
+ sessionId: result.data.sessionId,
787
+ status: "accepted"
788
+ } : { status: "no_active_session" };
789
+ }
790
+ async function resetClientSession(input) {
791
+ const { payload } = await postJson({
792
+ body: input.options,
793
+ context: input.context,
794
+ operation: "Reset",
795
+ path: createEveSessionResetRoutePath(input.sessionId)
796
+ });
797
+ const result = ResetResponseSchema.safeParse(payload);
798
+ if (!result.success || result.data.status === "reset" && result.data.previousSessionId !== input.sessionId) throw new Error("Reset route returned an invalid response.");
799
+ return result.data.status === "reset" ? {
800
+ previousSessionId: result.data.previousSessionId,
801
+ status: "reset"
802
+ } : { status: "no_active_session" };
803
+ }
804
+ async function postJson(input) {
805
+ const headers = await input.context.resolveHeaders();
806
+ headers.set("content-type", "application/json");
807
+ const response = await fetch(createClientUrl(input.context.host, input.path), withRedirectPolicy$1({
808
+ body: input.body === void 0 ? void 0 : JSON.stringify(input.body),
809
+ headers,
810
+ method: "POST"
811
+ }, input.context.redirect));
812
+ const text = await response.text();
813
+ if (!response.ok) throw new ClientError(response.status, text, response.headers);
814
+ try {
815
+ return {
816
+ payload: JSON.parse(text),
817
+ response
818
+ };
819
+ } catch {
820
+ throw new Error(`${input.operation} route returned invalid JSON (${response.status}).`);
821
+ }
822
+ }
823
+ function withRedirectPolicy$1(init, redirect) {
824
+ return redirect === void 0 ? init : {
825
+ ...init,
826
+ redirect
827
+ };
828
+ }
829
+
756
830
  //#endregion
757
831
  //#region src/shared/json.ts
758
832
  const INVALID_JSON_VALUE_CANDIDATE = Symbol("invalid-json-value-candidate");
@@ -823,266 +897,139 @@ function isStandardJsonSchema(value) {
823
897
 
824
898
  //#endregion
825
899
  //#region src/client/session.ts
826
- const DELIVER_RETRY_ATTEMPTS = 10;
827
- const DELIVER_RETRY_DELAY_MS = 200;
828
- var ClientSession = class {
900
+ var ClientSession = class ClientSession {
829
901
  #context;
830
902
  #state;
831
903
  constructor(context, state) {
832
904
  this.#context = context;
833
905
  this.#state = state;
834
906
  }
907
+ static async create(context, input) {
908
+ const response = await postTurn(context, EVE_SESSION_ROUTE_PATH, input, true);
909
+ const sessionId = await readSessionId(response);
910
+ const session = new ClientSession(context, {
911
+ sessionId,
912
+ streamIndex: 0
913
+ });
914
+ return {
915
+ response: session.#messageResponse(response, input, 0),
916
+ session
917
+ };
918
+ }
835
919
  get state() {
836
920
  return this.#state;
837
921
  }
838
922
  async snapshot(options) {
839
923
  options?.signal?.throwIfAborted();
840
- const initialState = this.#state;
841
- const sessionId = initialState.sessionId;
842
- if (!sessionId) throw new Error("Session has no session ID. Send a message first.");
843
924
  const events = [];
844
925
  for await (const event of this.#readStream({
845
926
  follow: false,
846
- sessionId,
847
927
  signal: options?.signal,
848
928
  startIndex: 0
849
929
  })) events.push(event);
850
930
  options?.signal?.throwIfAborted();
851
- const lastEvent = events.at(-1);
852
- const continuationToken = lastEvent?.type === "session.waiting" ? lastEvent.data.continuationToken : lastEvent?.type === "session.completed" && this.#context.preserveCompletedSessions ? initialState.continuationToken : void 0;
853
931
  return {
854
932
  events,
855
- session: continuationToken === void 0 ? {
856
- sessionId,
857
- streamIndex: events.length
858
- } : {
859
- continuationToken,
860
- sessionId,
933
+ session: {
934
+ sessionId: this.#state.sessionId,
861
935
  streamIndex: events.length
862
936
  }
863
937
  };
864
938
  }
865
- async send(input) {
866
- const payload = normalizeSendTurnInput(input);
867
- const state = this.#state;
868
- const { continuationToken, sessionId } = await this.#postTurn(payload, state);
869
- if (this.#state === state) {
870
- const nextState = {
871
- ...state,
872
- sessionId
873
- };
874
- if (continuationToken !== void 0) nextState.continuationToken = continuationToken;
875
- this.#state = nextState;
876
- }
877
- return new MessageResponse({
878
- continuationToken,
879
- createStream: () => this.#createEventStream(sessionId, continuationToken, state, payload),
880
- sessionId
939
+ async send(message, options = {}) {
940
+ return await this.#send({
941
+ ...options,
942
+ message
881
943
  });
882
944
  }
945
+ async respond(inputResponses, options = {}) {
946
+ if (inputResponses.length === 0) throw new Error("ClientSession.respond() requires at least one input response.");
947
+ return await this.#send({
948
+ ...options,
949
+ inputResponses
950
+ });
951
+ }
952
+ async #send(input) {
953
+ const initialStreamIndex = this.#state.streamIndex;
954
+ const response = await postTurn(this.#context, createEveSessionRoutePath(this.#state.sessionId), input, false);
955
+ if (await readSessionId(response, this.#state.sessionId) !== this.#state.sessionId) throw new Error("Message route returned a different session id.");
956
+ return this.#messageResponse(response, input, initialStreamIndex);
957
+ }
883
958
  async cancel(options) {
884
- const sessionId = this.#state.sessionId;
885
- if (!sessionId) throw new Error("Session has no session ID. Send a message first.");
886
- const url = createClientUrl(this.#context.host, createEveCancelTurnRoutePath(sessionId));
887
- const headers = await this.#context.resolveHeaders();
888
- headers.set("content-type", "application/json");
889
- const response = await fetch(url, withRedirectPolicy$1({
890
- headers,
891
- method: "POST",
892
- body: options ? JSON.stringify(options) : void 0
893
- }, this.#context.redirect));
894
- const body = await response.text();
895
- if (!response.ok) throw new ClientError(response.status, body, response.headers);
896
- let payload;
897
- try {
898
- payload = JSON.parse(body);
899
- } catch {
900
- throw new Error(`Cancel route returned invalid JSON (${response.status}).`);
901
- }
902
- const result = CancelTurnResponseSchema.safeParse(payload);
903
- if (!result.success || result.data.sessionId !== sessionId) throw new Error(`Cancel route returned an invalid response (${response.status}).`);
904
- return {
905
- sessionId: result.data.sessionId,
906
- status: result.data.status
907
- };
959
+ return await cancelClientSession({
960
+ context: this.#context,
961
+ options,
962
+ sessionId: this.#state.sessionId
963
+ });
908
964
  }
909
965
  async clear() {
910
- const state = this.#state;
911
- const continuationToken = state.continuationToken;
912
- if (continuationToken === void 0) {
913
- if (state.sessionId !== void 0) throw new Error("Session has no continuation token. Consume its event stream before clearing.");
914
- return { status: "no_active_session" };
915
- }
916
- const url = createClientUrl(this.#context.host, EVE_CLEAR_SESSION_ROUTE_PATH);
917
- const headers = await this.#context.resolveHeaders();
918
- headers.set("content-type", "application/json");
919
- const response = await fetch(url, withRedirectPolicy$1({
920
- body: JSON.stringify({ continuationToken }),
921
- headers,
922
- method: "POST"
923
- }, this.#context.redirect));
924
- const body = await response.text();
925
- if (!response.ok) throw new ClientError(response.status, body, response.headers);
926
- let payload;
927
- try {
928
- payload = JSON.parse(body);
929
- } catch {
930
- throw new Error(`Clear route returned invalid JSON (${response.status}).`);
931
- }
932
- const result = ClearResponseSchema.safeParse(payload);
933
- if (!result.success || result.data.status === "accepted" && state.sessionId !== void 0 && result.data.sessionId !== state.sessionId) throw new Error(`Clear route returned an invalid response (${response.status}).`);
934
- return result.data.status === "accepted" ? {
935
- sessionId: result.data.sessionId,
936
- status: "accepted"
937
- } : { status: "no_active_session" };
966
+ return await clearClientSession({
967
+ context: this.#context,
968
+ sessionId: this.#state.sessionId
969
+ });
938
970
  }
939
971
  async compact() {
940
- const state = this.#state;
941
- const continuationToken = state.continuationToken;
942
- if (continuationToken === void 0) {
943
- if (state.sessionId !== void 0) throw new Error("Session has no continuation token. Consume its event stream before compacting.");
944
- return { status: "no_active_session" };
945
- }
946
- const url = createClientUrl(this.#context.host, EVE_COMPACT_SESSION_ROUTE_PATH);
947
- const headers = await this.#context.resolveHeaders();
948
- headers.set("content-type", "application/json");
949
- const response = await fetch(url, withRedirectPolicy$1({
950
- body: JSON.stringify({ continuationToken }),
951
- headers,
952
- method: "POST"
953
- }, this.#context.redirect));
954
- const body = await response.text();
955
- if (!response.ok) throw new ClientError(response.status, body, response.headers);
956
- let payload;
957
- try {
958
- payload = JSON.parse(body);
959
- } catch {
960
- throw new Error(`Compact route returned invalid JSON (${response.status}).`);
961
- }
962
- const result = CompactResponseSchema.safeParse(payload);
963
- if (!result.success || result.data.status === "accepted" && state.sessionId !== void 0 && result.data.sessionId !== state.sessionId) throw new Error(`Compact route returned an invalid response (${response.status}).`);
964
- return result.data.status === "accepted" ? {
965
- sessionId: result.data.sessionId,
966
- status: "accepted"
967
- } : { status: "no_active_session" };
968
- }
969
- async reset() {
970
- const state = this.#state;
971
- const continuationToken = state.continuationToken;
972
- if (continuationToken === void 0) {
973
- if (state.sessionId !== void 0) throw new Error("Session has no continuation token. Consume its event stream before resetting.");
974
- this.#state = createInitialSessionState();
975
- return { status: "no_active_session" };
976
- }
977
- const url = createClientUrl(this.#context.host, EVE_RESET_SESSION_ROUTE_PATH);
978
- const headers = await this.#context.resolveHeaders();
979
- headers.set("content-type", "application/json");
980
- const response = await fetch(url, withRedirectPolicy$1({
981
- body: JSON.stringify({ continuationToken }),
982
- headers,
983
- method: "POST"
984
- }, this.#context.redirect));
985
- const body = await response.text();
986
- if (!response.ok) throw new ClientError(response.status, body, response.headers);
987
- let payload;
988
- try {
989
- payload = JSON.parse(body);
990
- } catch {
991
- throw new Error(`Reset route returned invalid JSON (${response.status}).`);
992
- }
993
- const result = ResetResponseSchema.safeParse(payload);
994
- if (!result.success) throw new Error(`Reset route returned an invalid response (${response.status}).`);
995
- if (result.data.status === "reset" && state.sessionId !== void 0 && result.data.previousSessionId !== state.sessionId) throw new Error(`Reset route returned an invalid response (${response.status}).`);
996
- if (this.#state === state) this.#state = createInitialSessionState();
997
- return result.data.status === "reset" ? {
998
- previousSessionId: result.data.previousSessionId,
999
- status: "reset"
1000
- } : { status: "no_active_session" };
972
+ return await compactClientSession({
973
+ context: this.#context,
974
+ sessionId: this.#state.sessionId
975
+ });
976
+ }
977
+ async reset(options) {
978
+ return await resetClientSession({
979
+ context: this.#context,
980
+ options,
981
+ sessionId: this.#state.sessionId
982
+ });
1001
983
  }
1002
984
  stream(options) {
1003
- const sessionId = this.#state.sessionId;
1004
- if (!sessionId) throw new Error("Session has no session ID. Send a message first.");
1005
985
  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.");
1006
- return this.#streamAndAdvance(sessionId, options);
1007
- }
1008
- async #postTurn(input, session) {
1009
- const routePath = session.sessionId ? createEveContinueSessionRoutePath(session.sessionId) : EVE_CREATE_SESSION_ROUTE_PATH;
1010
- const url = createClientUrl(this.#context.host, routePath);
1011
- const headers = await this.#context.resolveHeaders(input.headers);
1012
- headers.set("content-type", "application/json");
1013
- const body = createHandleMessageBody({
1014
- input,
1015
- outputSchema: serializeOutputSchema(input.outputSchema),
1016
- session
1017
- });
1018
- if (body === null) throw new Error("Session.send requires a non-empty message, inputResponses, or both.");
1019
- const response = await postTurnWithRetry({
1020
- body: JSON.stringify(body),
1021
- headers,
1022
- mustDeliver: (input.inputResponses?.length ?? 0) > 0,
1023
- redirect: this.#context.redirect,
1024
- signal: input.signal,
1025
- url
986
+ return this.#streamAndAdvance(options);
987
+ }
988
+ #messageResponse(response, input, initialStreamIndex) {
989
+ response.body?.cancel().catch(() => {});
990
+ return new MessageResponse({
991
+ createStream: () => this.#createEventStream(initialStreamIndex, input),
992
+ sessionId: this.#state.sessionId
1026
993
  });
1027
- const payload = await response.json();
1028
- const sessionId = (typeof payload.sessionId === "string" ? payload.sessionId : void 0) ?? response.headers.get("x-eve-session-id")?.trim() ?? session.sessionId;
1029
- if (!sessionId) throw new Error("Message route did not return a session id.");
1030
- return {
1031
- continuationToken: typeof payload.continuationToken === "string" ? payload.continuationToken : void 0,
1032
- sessionId
1033
- };
1034
994
  }
1035
- async *#createEventStream(sessionId, continuationToken, initialState, input) {
1036
- const events = [];
995
+ async *#createEventStream(initialStreamIndex, input) {
996
+ let eventCount = 0;
1037
997
  try {
1038
998
  for await (const event of this.#readStream({
1039
999
  headers: input.headers,
1040
- streamReconnectPolicy: input.streamReconnectPolicy,
1041
- sessionId,
1042
1000
  signal: input.signal,
1043
- startIndex: initialState.sessionId === sessionId ? initialState.streamIndex : 0
1001
+ startIndex: initialStreamIndex,
1002
+ streamReconnectPolicy: input.streamReconnectPolicy
1044
1003
  })) {
1045
- events.push(event);
1004
+ eventCount += 1;
1046
1005
  yield event;
1047
1006
  if (isCurrentTurnBoundaryEvent(event)) break;
1048
1007
  }
1049
1008
  } finally {
1050
- this.#state = advanceSession({
1051
- continuationToken,
1052
- events,
1053
- preserveCompletedSessions: this.#context.preserveCompletedSessions,
1054
- sessionId,
1055
- session: initialState
1056
- });
1009
+ this.#state = {
1010
+ sessionId: this.#state.sessionId,
1011
+ streamIndex: initialStreamIndex + eventCount
1012
+ };
1057
1013
  }
1058
1014
  }
1059
- async *#streamAndAdvance(sessionId, options) {
1060
- const initialState = this.#state;
1061
- const streamIndex = options?.startIndex ?? initialState.streamIndex;
1062
- const events = [];
1015
+ async *#streamAndAdvance(options) {
1016
+ const startIndex = options?.startIndex ?? this.#state.streamIndex;
1017
+ let eventCount = 0;
1063
1018
  try {
1064
1019
  for await (const event of this.#readStream({
1065
1020
  follow: options?.follow,
1066
- sessionId,
1067
1021
  signal: options?.signal,
1068
- startIndex: streamIndex,
1022
+ startIndex,
1069
1023
  streamReconnectPolicy: options?.streamReconnectPolicy
1070
1024
  })) {
1071
- events.push(event);
1025
+ eventCount += 1;
1072
1026
  yield event;
1073
1027
  }
1074
1028
  } finally {
1075
- if (streamIndex >= 0) this.#state = advanceSession({
1076
- continuationToken: initialState.continuationToken,
1077
- events,
1078
- preserveCompletedSessions: this.#context.preserveCompletedSessions,
1079
- session: {
1080
- ...initialState,
1081
- sessionId,
1082
- streamIndex
1083
- },
1084
- sessionId
1085
- });
1029
+ if (startIndex >= 0) this.#state = {
1030
+ sessionId: this.#state.sessionId,
1031
+ streamIndex: startIndex + eventCount
1032
+ };
1086
1033
  }
1087
1034
  }
1088
1035
  #readStream(input) {
@@ -1091,62 +1038,67 @@ var ClientSession = class {
1091
1038
  host: this.#context.host,
1092
1039
  resolveHeaders: () => this.#context.resolveHeaders(input.headers),
1093
1040
  redirect: this.#context.redirect,
1094
- streamReconnectPolicy: input.streamReconnectPolicy,
1095
- sessionId: input.sessionId,
1041
+ sessionId: this.#state.sessionId,
1096
1042
  signal: input.signal,
1097
- startIndex: input.startIndex
1043
+ startIndex: input.startIndex,
1044
+ streamReconnectPolicy: input.streamReconnectPolicy
1098
1045
  });
1099
1046
  }
1100
1047
  };
1101
- async function postTurnWithRetry(input) {
1102
- const attempts = input.mustDeliver ? DELIVER_RETRY_ATTEMPTS : 1;
1103
- let lastStatus;
1104
- let lastBody;
1105
- let lastHeaders;
1106
- for (let attempt = 0; attempt < attempts; attempt += 1) {
1107
- const response = await fetch(input.url, {
1108
- body: input.body,
1109
- headers: input.headers,
1110
- method: "POST",
1111
- redirect: input.redirect,
1112
- signal: input.signal ?? null
1113
- });
1114
- if (response.ok) return response;
1115
- lastStatus = response.status;
1116
- lastBody = await response.text();
1117
- lastHeaders = response.headers;
1118
- if (!isRetryableDeliveryFailure(response.status, lastBody)) throw new ClientError(response.status, lastBody, response.headers);
1119
- if (attempt < attempts - 1) await sleep(DELIVER_RETRY_DELAY_MS);
1048
+ async function postTurn(context, path, input, requireMessage) {
1049
+ const body = createMessageBody(input, requireMessage);
1050
+ if (body === null) throw new Error(requireMessage ? "Creating a session requires a non-empty message." : "A session turn requires a non-empty message or inputResponses.");
1051
+ const headers = await context.resolveHeaders(input.headers);
1052
+ headers.set("content-type", "application/json");
1053
+ const response = await fetch(createClientUrl(context.host, path), {
1054
+ body: JSON.stringify(body),
1055
+ headers,
1056
+ method: "POST",
1057
+ redirect: context.redirect,
1058
+ signal: input.signal ?? null
1059
+ });
1060
+ if (!response.ok) {
1061
+ const responseBody = await response.text();
1062
+ throw new ClientError(response.status, responseBody, response.headers);
1120
1063
  }
1121
- throw new ClientError(lastStatus ?? 0, lastBody ?? "Failed to deliver session turn.", lastHeaders);
1122
- }
1123
- function isRetryableDeliveryFailure(status, body) {
1124
- return status === 500 && /target session was not found/i.test(body);
1064
+ return response;
1125
1065
  }
1126
- async function sleep(ms) {
1127
- await new Promise((resolve) => setTimeout(resolve, ms));
1066
+ async function readSessionId(response, expected) {
1067
+ const payload = await response.json();
1068
+ const sessionId = (typeof payload.sessionId === "string" ? payload.sessionId : void 0) ?? response.headers.get("x-eve-session-id")?.trim() ?? expected;
1069
+ if (!sessionId) throw new Error("Message route did not return a session id.");
1070
+ return sessionId;
1128
1071
  }
1129
- function normalizeSendTurnInput(input) {
1130
- return typeof input === "string" ? { message: input } : input;
1131
- }
1132
- function createHandleMessageBody(input) {
1072
+ function createMessageBody(input, requireMessage) {
1133
1073
  const body = {};
1134
- if (input.input.message !== void 0) body.message = input.input.message;
1135
- if (input.input.inputResponses !== void 0 && input.input.inputResponses.length > 0) body.inputResponses = input.input.inputResponses;
1136
- if (input.input.clientContext !== void 0) body.clientContext = input.input.clientContext;
1137
- if (input.outputSchema !== void 0) body.outputSchema = input.outputSchema;
1138
- if (input.session.continuationToken !== void 0) body.continuationToken = input.session.continuationToken;
1139
- if (Object.keys(body).length === 0) return null;
1140
- if (input.session.continuationToken === void 0 && body.message === void 0) return null;
1141
- if (input.session.continuationToken !== void 0 && body.message === void 0 && body.inputResponses === void 0) return null;
1074
+ if (input.message !== void 0) body.message = input.message;
1075
+ if (input.inputResponses !== void 0 && input.inputResponses.length > 0) body.inputResponses = input.inputResponses;
1076
+ if (input.clientContext !== void 0) body.clientContext = input.clientContext;
1077
+ const outputSchema = serializeOutputSchema(input.outputSchema);
1078
+ if (outputSchema !== void 0) body.outputSchema = outputSchema;
1079
+ if (requireMessage && body.message === void 0) return null;
1080
+ if (body.message === void 0 && body.inputResponses === void 0) return null;
1142
1081
  return body;
1143
1082
  }
1144
- function withRedirectPolicy$1(init, redirect) {
1145
- return redirect === void 0 ? init : {
1146
- ...init,
1147
- redirect
1148
- };
1149
- }
1083
+
1084
+ //#endregion
1085
+ //#region src/client/sessions.ts
1086
+ var ClientSessions = class {
1087
+ #context;
1088
+ constructor(context) {
1089
+ this.#context = context;
1090
+ }
1091
+ async create(input) {
1092
+ return await ClientSession.create(this.#context, input);
1093
+ }
1094
+ attach(sessionId, options) {
1095
+ if (sessionId.length === 0) throw new Error("sessionId must be a non-empty string.");
1096
+ return new ClientSession(this.#context, {
1097
+ sessionId,
1098
+ streamIndex: options?.streamIndex ?? 0
1099
+ });
1100
+ }
1101
+ };
1150
1102
 
1151
1103
  //#endregion
1152
1104
  //#region src/client/types.ts
@@ -1158,14 +1110,18 @@ var Client = class {
1158
1110
  #auth;
1159
1111
  #headers;
1160
1112
  #host;
1161
- #preserveCompletedSessions;
1162
1113
  #redirect;
1114
+ sessions;
1163
1115
  constructor(options) {
1164
1116
  this.#host = options.host;
1165
1117
  this.#auth = options.auth;
1166
1118
  this.#headers = options.headers;
1167
- this.#preserveCompletedSessions = options.preserveCompletedSessions ?? false;
1168
1119
  this.#redirect = options.redirect;
1120
+ this.sessions = new ClientSessions({
1121
+ host: this.#host,
1122
+ redirect: this.#redirect,
1123
+ resolveHeaders: (perRequest) => this.#resolveHeaders(perRequest)
1124
+ });
1169
1125
  }
1170
1126
  async health() {
1171
1127
  const url = createClientUrl(this.#host, EVE_HEALTH_ROUTE_PATH);
@@ -1204,21 +1160,6 @@ var Client = class {
1204
1160
  headers
1205
1161
  }, this.#redirect));
1206
1162
  }
1207
- session(state) {
1208
- let resolved;
1209
- if (typeof state === "string") resolved = {
1210
- continuationToken: state,
1211
- streamIndex: 0
1212
- };
1213
- else if (state) resolved = state;
1214
- else resolved = createInitialSessionState();
1215
- return new ClientSession({
1216
- host: this.#host,
1217
- preserveCompletedSessions: this.#preserveCompletedSessions,
1218
- redirect: this.#redirect,
1219
- resolveHeaders: (perRequest) => this.#resolveHeaders(perRequest)
1220
- }, resolved);
1221
- }
1222
1163
  async #resolveHeaders(perRequest) {
1223
1164
  const headers = new Headers();
1224
1165
  const [baseHeaders, authHeaders] = await Promise.all([resolveHeadersValue(this.#headers), this.#resolveAuthHeaders()]);
@@ -1288,7 +1229,8 @@ function createEventDeduper() {
1288
1229
  //#endregion
1289
1230
  //#region src/client/eve-agent-store.ts
1290
1231
  var EveAgentStore = class {
1291
- #createSession;
1232
+ #client;
1233
+ #externalSession;
1292
1234
  #optimistic;
1293
1235
  #reducer;
1294
1236
  #subscribers = /* @__PURE__ */ new Set();
@@ -1305,18 +1247,19 @@ var EveAgentStore = class {
1305
1247
  #snapshot;
1306
1248
  #status = "ready";
1307
1249
  constructor(init) {
1308
- this.#createSession = init.session ? void 0 : () => new Client({
1250
+ this.#externalSession = init.session !== void 0;
1251
+ this.#client = this.#externalSession ? void 0 : new Client({
1309
1252
  auth: init.auth,
1310
1253
  headers: init.headers,
1311
1254
  host: init.host ?? ""
1312
- }).session(init.initialSession);
1255
+ });
1313
1256
  const initialEvents = [];
1314
1257
  for (const event of init.initialEvents ?? []) if (this.#seenEvents.admit(event)) initialEvents.push(event);
1315
1258
  this.#events = initialEvents;
1316
1259
  this.#projectionEvents = [...this.#events];
1317
1260
  this.#optimistic = init.optimistic ?? true;
1318
1261
  this.#reducer = init.reducer;
1319
- this.#session = init.session ?? this.#createOwnedSession();
1262
+ this.#session = init.session ?? (init.initialSession === void 0 ? void 0 : this.#client?.sessions.attach(init.initialSession.sessionId, { streamIndex: init.initialSession.streamIndex }));
1320
1263
  this.#data = this.#reduceProjectionEvents(this.#projectionEvents);
1321
1264
  this.#snapshot = this.#createSnapshot();
1322
1265
  }
@@ -1342,14 +1285,16 @@ var EveAgentStore = class {
1342
1285
  this.#publish();
1343
1286
  try {
1344
1287
  const preparedInput = await this.#callbacks.prepareSend?.(input) ?? input;
1288
+ assertExclusiveTurnInput(preparedInput);
1345
1289
  if (!this.#isCurrentOperation(operationId)) return;
1346
1290
  this.#projectOptimisticMessage(preparedInput);
1347
1291
  this.#projectInputResponses(preparedInput);
1348
1292
  this.#publish();
1349
- const response = await this.#session.send({
1293
+ const turnInput = {
1350
1294
  ...preparedInput,
1351
1295
  signal: createAbortSignal(preparedInput.signal, abortController.signal)
1352
- });
1296
+ };
1297
+ const response = await this.#dispatchTurn(turnInput);
1353
1298
  let sawEvent = false;
1354
1299
  for await (const event of response) {
1355
1300
  if (!this.#isCurrentOperation(operationId)) return;
@@ -1380,7 +1325,7 @@ var EveAgentStore = class {
1380
1325
  } finally {
1381
1326
  if (this.#isCurrentOperation(operationId)) {
1382
1327
  this.#abortController = void 0;
1383
- this.#callbacks.onSessionChange?.(this.#session.state);
1328
+ this.#callbacks.onSessionChange?.(this.#session?.state);
1384
1329
  this.#publish();
1385
1330
  this.#callbacks.onFinish?.(this.#snapshot);
1386
1331
  }
@@ -1393,7 +1338,7 @@ var EveAgentStore = class {
1393
1338
  this.#invalidateOperation();
1394
1339
  this.stop();
1395
1340
  this.#abortController = void 0;
1396
- this.#session = this.#createSession?.() ?? this.#session;
1341
+ if (!this.#externalSession) this.#session = void 0;
1397
1342
  this.#events = [];
1398
1343
  this.#seenEvents = createEventDeduper();
1399
1344
  this.#pendingMessageSubmission = void 0;
@@ -1401,12 +1346,29 @@ var EveAgentStore = class {
1401
1346
  this.#data = this.#reducer.initial();
1402
1347
  this.#error = void 0;
1403
1348
  this.#status = "ready";
1404
- this.#callbacks.onSessionChange?.(this.#session.state);
1349
+ this.#callbacks.onSessionChange?.(this.#session?.state);
1405
1350
  this.#publish();
1406
1351
  }
1407
- #createOwnedSession() {
1408
- if (!this.#createSession) throw new Error("Cannot create an owned eve session from an external session.");
1409
- return this.#createSession();
1352
+ async #createFirstTurn(input) {
1353
+ if (this.#client === void 0) throw new Error("An external eve session is required before sending.");
1354
+ if (input.message === void 0) throw new Error("Cannot answer an input request before the session starts.");
1355
+ const created = await this.#client.sessions.create({
1356
+ ...input,
1357
+ message: input.message
1358
+ });
1359
+ this.#session = created.session;
1360
+ this.#callbacks.onSessionChange?.(created.session.state);
1361
+ this.#publish();
1362
+ return created.response;
1363
+ }
1364
+ async #dispatchTurn(input) {
1365
+ if (this.#session === void 0) return await this.#createFirstTurn(input);
1366
+ if (input.inputResponses === void 0) {
1367
+ const { message, ...options } = input;
1368
+ return await this.#session.send(message, options);
1369
+ }
1370
+ const { inputResponses, ...options } = input;
1371
+ return await this.#session.respond(inputResponses, options);
1410
1372
  }
1411
1373
  #startOperation() {
1412
1374
  this.#operationId += 1;
@@ -1505,7 +1467,7 @@ var EveAgentStore = class {
1505
1467
  data: this.#data,
1506
1468
  error: this.#error,
1507
1469
  events: this.#events,
1508
- session: this.#session.state,
1470
+ session: this.#session?.state,
1509
1471
  status: this.#status
1510
1472
  };
1511
1473
  }
@@ -1514,6 +1476,9 @@ var EveAgentStore = class {
1514
1476
  for (const subscriber of this.#subscribers) subscriber();
1515
1477
  }
1516
1478
  };
1479
+ function assertExclusiveTurnInput(input) {
1480
+ if (input.message !== void 0 === (input.inputResponses !== void 0)) throw new Error("A turn requires exactly one of message or inputResponses.");
1481
+ }
1517
1482
  let submissionSequence = 0;
1518
1483
  function createSubmissionId() {
1519
1484
  const randomUUID = globalThis.crypto?.randomUUID;
@@ -2107,7 +2072,14 @@ function useEveAgent(options = {}) {
2107
2072
  error: computed(() => snapshot.value.error),
2108
2073
  events: computed(() => snapshot.value.events),
2109
2074
  reset: () => store.reset(),
2110
- send: (input) => store.send(input),
2075
+ respond: (inputResponses, options) => store.send({
2076
+ ...options,
2077
+ inputResponses
2078
+ }),
2079
+ send: (message, options) => store.send({
2080
+ ...options,
2081
+ message
2082
+ }),
2111
2083
  session: computed(() => snapshot.value.session),
2112
2084
  status: computed(() => snapshot.value.status),
2113
2085
  stop: () => store.stop()