eve 0.79.0 → 0.79.2

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 (201) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/dist/src/channel/pending-authorization.d.ts +10 -0
  3. package/dist/src/channel/pending-authorization.js +1 -0
  4. package/dist/src/chunks/{use-eve-agent-BSYe_Re7.js → use-eve-agent-Ch-Q-s12.js} +43 -13
  5. package/dist/src/chunks/{use-eve-agent-B8brxCk-.js → use-eve-agent-Vsl-S0yI.js} +43 -13
  6. package/dist/src/client/abort-signal.d.ts +2 -0
  7. package/dist/src/client/abort-signal.js +1 -0
  8. package/dist/src/client/conversation-client.d.ts +2 -0
  9. package/dist/src/client/conversation-client.js +1 -1
  10. package/dist/src/client/eve-agent-store-state.d.ts +9 -0
  11. package/dist/src/client/eve-agent-store.js +1 -1
  12. package/dist/src/client/ndjson.js +1 -1
  13. package/dist/src/client/open-stream.js +1 -1
  14. package/dist/src/client/session-turn-dispatch.js +1 -1
  15. package/dist/src/client/session-utils.js +1 -1
  16. package/dist/src/client/session.js +1 -1
  17. package/dist/src/compiled/.vendor-stamp.json +2 -2
  18. package/dist/src/compiled/@eve/tracing/adapters/serialization.d.ts +2 -2
  19. package/dist/src/compiled/@eve/tracing/core/types.d.ts +6 -1
  20. package/dist/src/compiled/@eve/tracing/index.js +1 -1
  21. package/dist/src/compiled/@eve/tracing/otel.js +1 -1
  22. package/dist/src/compiled/_chunks/workflow/mcp-Bwx_LQ4q.js +5 -0
  23. package/dist/src/compiler/extension-compatibility.d.ts +18 -18
  24. package/dist/src/compiler/extension-compatibility.js +1 -1
  25. package/dist/src/compiler/project-sources.js +1 -1
  26. package/dist/src/context/memory-tools.js +1 -1
  27. package/dist/src/evals/runner/reporters/assertion-scores.d.ts +6 -4
  28. package/dist/src/evals/runner/reporters/assertion-scores.js +1 -1
  29. package/dist/src/evals/runner/reporters/braintrust.js +1 -1
  30. package/dist/src/eve-channel/request.js +1 -1
  31. package/dist/src/execution/authorization-callback-match.d.ts +2 -2
  32. package/dist/src/execution/authorization-callback-match.js +1 -1
  33. package/dist/src/execution/durable-session-store.js +1 -1
  34. package/dist/src/execution/dynamic-workflow/tool.js +1 -1
  35. package/dist/src/execution/forward-session-input.js +1 -1
  36. package/dist/src/execution/proxied-deliver-step.js +1 -1
  37. package/dist/src/execution/publish-session-events.d.ts +26 -5
  38. package/dist/src/execution/publish-session-events.js +1 -1
  39. package/dist/src/execution/sandbox/bindings/microsandbox-runtime.js +1 -1
  40. package/dist/src/execution/sandbox/bindings/vercel-create-sdk.js +1 -1
  41. package/dist/src/execution/sandbox/bindings/vercel-credentials.d.ts +2 -0
  42. package/dist/src/execution/sandbox/bindings/vercel-credentials.js +1 -1
  43. package/dist/src/execution/sandbox/bindings/vercel-lifecycle.js +1 -1
  44. package/dist/src/execution/sandbox/bindings/vercel-lookup.js +1 -1
  45. package/dist/src/execution/sandbox/bindings/vercel.d.ts +3 -6
  46. package/dist/src/execution/sandbox/bindings/vercel.js +1 -1
  47. package/dist/src/execution/session/active-turn.d.ts +2 -1
  48. package/dist/src/execution/session/active-turn.js +1 -1
  49. package/dist/src/execution/session/checkpoint-migrations.js +1 -1
  50. package/dist/src/execution/session/handoff-steps.js +1 -1
  51. package/dist/src/execution/session/handoff.d.ts +1 -1
  52. package/dist/src/execution/session/handoff.js +1 -1
  53. package/dist/src/execution/session/input-queue.d.ts +13 -6
  54. package/dist/src/execution/session/input-queue.js +1 -1
  55. package/dist/src/execution/session/pending-turn-state.js +1 -1
  56. package/dist/src/execution/session/turn-step.js +1 -1
  57. package/dist/src/execution/session/turn.d.ts +5 -1
  58. package/dist/src/execution/session/turn.js +1 -1
  59. package/dist/src/execution/tasks/steps.d.ts +1 -1
  60. package/dist/src/execution/tasks/steps.js +1 -1
  61. package/dist/src/execution/tasks/task-id-input.js +1 -1
  62. package/dist/src/execution/tool-auth.js +1 -1
  63. package/dist/src/execution/tools/agent-router-workflow.js +1 -1
  64. package/dist/src/execution/tools/workflow/answer.d.ts +1 -1
  65. package/dist/src/execution/tools/workflow/apply-run-messages-step.d.ts +6 -2
  66. package/dist/src/execution/tools/workflow/apply-run-messages-step.js +1 -1
  67. package/dist/src/execution/tools/workflow/body.d.ts +10 -1
  68. package/dist/src/execution/tools/workflow/body.js +1 -1
  69. package/dist/src/execution/tools/workflow/owner-inbox.js +1 -1
  70. package/dist/src/execution/tools/workflow/serve.js +1 -1
  71. package/dist/src/execution/tools/workflow/withdraw-step.d.ts +2 -2
  72. package/dist/src/execution/tools/workflow/withdraw-step.js +1 -1
  73. package/dist/src/execution/workflow-callback-url.d.ts +10 -1
  74. package/dist/src/execution/workflow-callback-url.js +1 -1
  75. package/dist/src/harness/action-result-helpers.js +1 -1
  76. package/dist/src/harness/attachment-staging.js +1 -1
  77. package/dist/src/harness/authorization.d.ts +3 -13
  78. package/dist/src/harness/authorization.js +1 -1
  79. package/dist/src/harness/compaction/engine.js +3 -1
  80. package/dist/src/harness/compaction/prompt.d.ts +7 -0
  81. package/dist/src/harness/compaction/prompt.js +1 -1
  82. package/dist/src/harness/compaction/step.d.ts +1 -0
  83. package/dist/src/harness/compaction/step.js +1 -1
  84. package/dist/src/harness/coordination.js +1 -1
  85. package/dist/src/harness/hitl/approvals.d.ts +1 -1
  86. package/dist/src/harness/hitl/approvals.js +1 -1
  87. package/dist/src/harness/hitl/approved-calls.d.ts +3 -0
  88. package/dist/src/harness/hitl/approved-calls.js +1 -1
  89. package/dist/src/harness/hitl/candidates.d.ts +13 -0
  90. package/dist/src/harness/hitl/candidates.js +1 -1
  91. package/dist/src/harness/hitl/coordinator.js +1 -1
  92. package/dist/src/harness/hitl/index.d.ts +2 -5
  93. package/dist/src/harness/hitl/index.js +1 -1
  94. package/dist/src/harness/hitl/intake.js +1 -1
  95. package/dist/src/harness/{proxy-input-requests.d.ts → hitl/relays.d.ts} +3 -39
  96. package/dist/src/harness/hitl/relays.js +1 -0
  97. package/dist/src/harness/hitl/requests.d.ts +64 -0
  98. package/dist/src/harness/hitl/requests.js +1 -0
  99. package/dist/src/harness/hitl/sign-ins.d.ts +9 -0
  100. package/dist/src/harness/hitl/sign-ins.js +1 -0
  101. package/dist/src/harness/inline-tool-authorization.js +1 -1
  102. package/dist/src/harness/input-request-resolution.d.ts +2 -1
  103. package/dist/src/harness/input-request-resolution.js +1 -1
  104. package/dist/src/harness/model-call/call.js +1 -1
  105. package/dist/src/harness/model-call/model.d.ts +3 -1
  106. package/dist/src/harness/model-call/model.js +1 -1
  107. package/dist/src/harness/session-machine/commit.d.ts +14 -3
  108. package/dist/src/harness/session-machine/commit.js +1 -1
  109. package/dist/src/harness/session-machine/transitions.d.ts +16 -0
  110. package/dist/src/harness/session-machine/transitions.js +1 -1
  111. package/dist/src/instrumentation/native-events.js +1 -1
  112. package/dist/src/instrumentation/runtime.d.ts +1 -0
  113. package/dist/src/instrumentation/runtime.js +1 -1
  114. package/dist/src/internal/application/optional-package-import.d.ts +5 -0
  115. package/dist/src/internal/application/optional-package-import.js +1 -1
  116. package/dist/src/internal/application/stamped-package-version.js +1 -1
  117. package/dist/src/internal/authored-definition/source-identity.d.ts +6 -0
  118. package/dist/src/internal/authored-definition/source-identity.js +1 -1
  119. package/dist/src/internal/authored-module-map-loader.js +1 -1
  120. package/dist/src/internal/helpers/markdown.js +1 -1
  121. package/dist/src/internal/nitro/host/start-production-server.js +2 -2
  122. package/dist/src/internal/workflow/is-inactive-workflow-run-error.d.ts +2 -0
  123. package/dist/src/internal/workflow/is-inactive-workflow-run-error.js +1 -1
  124. package/dist/src/protocol/baggage.d.ts +1 -0
  125. package/dist/src/protocol/baggage.js +1 -1
  126. package/dist/src/protocol/message.d.ts +2 -0
  127. package/dist/src/protocol/message.js +1 -1
  128. package/dist/src/public/channels/teams/authorization.d.ts +53 -0
  129. package/dist/src/public/channels/teams/authorization.js +1 -0
  130. package/dist/src/public/channels/teams/defaults.js +2 -2
  131. package/dist/src/public/channels/teams/hitl.d.ts +2 -1
  132. package/dist/src/public/channels/teams/teamsChannel.js +1 -1
  133. package/dist/src/public/channels/telegram/authorization-callback.js +1 -1
  134. package/dist/src/public/definitions/connections/mcp.js +1 -1
  135. package/dist/src/public/definitions/connections/openapi.js +1 -1
  136. package/dist/src/public/next/index.js +1 -1
  137. package/dist/src/public/next/server.d.ts +11 -2
  138. package/dist/src/public/next/server.js +1 -1
  139. package/dist/src/public/sandbox/vercel.d.ts +2 -0
  140. package/dist/src/public/tools/index.d.ts +1 -1
  141. package/dist/src/public/tools/result.d.ts +10 -7
  142. package/dist/src/react/use-eve-agent.d.ts +6 -0
  143. package/dist/src/react/use-eve-agent.js +1 -1
  144. package/dist/src/runtime/authorization-context.d.ts +5 -0
  145. package/dist/src/runtime/authorization-context.js +1 -1
  146. package/dist/src/runtime/connections/mcp-tracing.js +1 -1
  147. package/dist/src/runtime/connections/openapi-operations.js +1 -1
  148. package/dist/src/runtime/connections/scoped-authorization.d.ts +6 -0
  149. package/dist/src/runtime/connections/scoped-authorization.js +1 -1
  150. package/dist/src/runtime/resolve-connection.js +1 -1
  151. package/dist/src/setup/scaffold/create/project.js +1 -1
  152. package/dist/src/setup/scaffold/create/web-template.d.ts +1 -1
  153. package/dist/src/setup/scaffold/create/web-template.js +18 -10
  154. package/dist/src/shared/action-types.d.ts +1 -0
  155. package/dist/src/shared/action-types.js +1 -1
  156. package/dist/src/shared/git.js +1 -1
  157. package/dist/src/shared/instrumentation-content.d.ts +1 -1
  158. package/dist/src/shared/instrumentation-content.js +1 -1
  159. package/dist/src/shared/instrumentation-decision.d.ts +3 -0
  160. package/dist/src/shared/instrumentation-decision.js +1 -1
  161. package/dist/src/shared/skill-package.js +1 -1
  162. package/dist/src/shared/trace-policy.js +1 -1
  163. package/dist/src/subagents/adapter.js +1 -1
  164. package/dist/src/subagents/event-proxy-step.d.ts +1 -1
  165. package/dist/src/subagents/event-proxy-step.js +1 -1
  166. package/dist/src/subagents/hitl-proxy.d.ts +1 -1
  167. package/dist/src/subagents/hitl-proxy.js +1 -1
  168. package/dist/src/svelte/index.js +1 -1
  169. package/dist/src/svelte/use-eve-agent.d.ts +6 -0
  170. package/dist/src/svelte/use-eve-agent.js +1 -1
  171. package/dist/src/tools/definition.d.ts +38 -1
  172. package/dist/src/tools/provided/ask-question-workflow.js +1 -1
  173. package/dist/src/tools/provided/sleep-workflow.js +1 -1
  174. package/dist/src/tools/signature.d.ts +4 -2
  175. package/dist/src/tools/signature.js +1 -1
  176. package/dist/src/tracing/eve/agent-otel-provider.js +1 -1
  177. package/dist/src/tracing/eve/gateway.d.ts +2 -1
  178. package/dist/src/tracing/eve/gateway.js +1 -1
  179. package/dist/src/tracing/eve/invoke-tool-span.js +1 -1
  180. package/dist/src/tracing/eve/otel-declaration.d.ts +9 -8
  181. package/dist/src/tracing/eve/policy.js +1 -1
  182. package/dist/src/vue/index.js +1 -1
  183. package/dist/src/vue/use-eve-agent.d.ts +6 -0
  184. package/dist/src/vue/use-eve-agent.js +1 -1
  185. package/docs/agent-config.md +48 -0
  186. package/docs/channels/eve.mdx +2 -0
  187. package/docs/channels/teams.mdx +6 -0
  188. package/docs/concepts/built-in-tools.md +1 -1
  189. package/docs/connections/overview.mdx +9 -6
  190. package/docs/guides/frontend/overview.mdx +10 -1
  191. package/docs/guides/hooks.md +6 -2
  192. package/docs/guides/instrumentation/instrumentation.mdx +2 -0
  193. package/docs/guides/instrumentation/otel.mdx +3 -0
  194. package/docs/reference/cli.md +1 -1
  195. package/docs/reference/typescript-api.md +7 -6
  196. package/docs/sandbox/vercel.mdx +9 -0
  197. package/docs/skills.mdx +1 -1
  198. package/docs/tools/human-in-the-loop.md +21 -0
  199. package/package.json +1 -1
  200. package/dist/src/compiled/_chunks/workflow/mcp-CrGp4EC8.js +0 -5
  201. package/dist/src/harness/proxy-input-requests.js +0 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,52 @@
1
1
  # eve
2
2
 
3
+ ## 0.79.2
4
+
5
+ ### Patch Changes
6
+
7
+ - 910705c: An agent or `serve` tool call with an empty `taskId` now starts a new task instead of failing with `UNKNOWN_TASK`. Some models send `""` for the optional `taskId` rather than omitting it.
8
+ - 3ac1bd0: `eve start` no longer keeps the server's stdout and stderr in memory after startup. Output is still forwarded, and an unexpected exit no longer repeats the full log history in its error.
9
+ - 4c8ffa6: Keep successful tool calls completed when their output includes `code` and `message` fields.
10
+ - ee0c6c0: `ctx.cancel()` in a `message.received` hook now cancels the turn when the message is a plain-text answer to a pending `ask_question` or `ctx.ask()` question. The question resolves as `cancelled` and the tool call never receives the text. Before, eve logged a warning and delivered the answer. `ctx.cancel()` in an `action.partial` hook for a workflow tool's report now cancels the turn waiting on that tool too.
11
+ - bc4edd9: Attachments no longer fail a step when the session's sandbox cannot be resumed, for example when a follow-up lands on another replica. Earlier attachments and tool-result files in history reach the model as a "FileNotFound" note, and new inbound attachments and tool-returned files become a "could not be stored" note. Tools that use the sandbox still report the resume error.
12
+ - 2de4011: Fail fast with an actionable error when the project has an unsupported `microsandbox` version (such as 0.7), instead of every sandbox operation throwing `isInstalled is not a function`.
13
+ - 394ed22: Start built, managed eve agents when a local production Next.js server loads its configuration, so `next start` can serve eve routes.
14
+ - f6bf73e: Keep every property name in `eve__search` tool signatures that run past the length cap. A long signature now drops its property descriptions before any property name, so the model no longer misses fields a large MCP tool such as Linear's `save_issue` supports.
15
+ - b382594: Compaction no longer re-caps a tool result it already capped. A capped result now fits the size limit it was measured against, so later compactions leave it as it is instead of nesting another truncation notice and keeping less of the original content. A summary written after a cap also sees the whole content the capped result kept.
16
+ - a1c18f5: Teams group chats and channels no longer show connection sign-in links or confirmation codes in the shared thread. The card now has a **Sign in** button, and Teams shows the link only to the person who has to sign in, so another member can't connect their own account under the requester's identity.
17
+ - 9f3a634: Snapshot retained tracing arguments and errors so later mutations cannot introduce private content into telemetry or checkpoints. Apply accepted delegation capture ceilings when re-entering durable turns, including through `resume()`.
18
+ - ec2862e: When a tool throws, the error on its `tool.call.failed` instrumentation event now keeps the thrown error's `name`, such as `QuotaError`, instead of always reading `Error`. The `action.result` stream event reports the same name as `error.name`.
19
+ - c1880f4: Parse a workflow tool's result as JSON when its run completes, the way a local tool's result already is. A tool that returns `ctx.ask()`'s answer directly, after the person picked an option, no longer fails the turn with `Cannot convert undefined or null to object`: undefined properties are omitted, a tool that returns nothing reports `null`, and the same applies to `ctx.reply()` in `serve` tools. A result JSON can't carry, such as a `Date` or `Map`, now fails the call with a serialization error instead of reaching the model as `{}`.
20
+
21
+ ## 0.79.1
22
+
23
+ ### Patch Changes
24
+
25
+ - 68b9d58: Approved `defineTool` calls can read who approved them: `ctx.approval.responder` is the approver and `ctx.approval.responder.getToken(provider)` resolves their token, while the call still runs as the requester.
26
+ - 620022b: The Braintrust eval reporter no longer aborts the run when an eval produces no agent output. Those evals are now logged with an empty output.
27
+ - 2e45423: Allow `eve/client` to use an `AbortSignal` that does not implement `throwIfAborted`, including the signal provided by React Native.
28
+ - afa7741: Sync dynamic skill files to the sandbox about 7× faster by writing them concurrently.
29
+ - 70f75ed: Connection sign-in callback URLs no longer include `VERCEL_AUTOMATION_BYPASS_SECRET`, so the secret stays out of the links shown to users and the `redirect_uri` sent to providers. On a deployment behind Deployment Protection, the person signing in now passes protection on their own, for example through Vercel Authentication or a Deployment Protection Exception.
30
+ - 4c6fc60: Record `agent.input.messages.omitted` on model spans when the oldest prompt messages are dropped to fit the 32 KB content cap, so a long conversation no longer looks like it starts partway through.
31
+ - 7f5a5e6: Reading a session stream whose history passed the World's retention now returns `410` with `code: "session_expired"` instead of a retryable `503` or `404`. The TypeScript client fails on the first response instead of retrying for about 38 seconds.
32
+ - 624be47: Pass `followIdle: false` to `useEveAgent()` (React, Vue, and Svelte) or `EveAgentStore` to close the session stream while the session is idle instead of reconnecting it indefinitely. The stream reopens from its cursor on the next send, answer, or resume, and a prewarmed session opens no stream until its first message.
33
+ - 4bf1efa: Propagate configured trace context at each AI Gateway model request.
34
+ - 7921fb0: Self-modification now rejects target branch names Git rejects: path components starting with `.` (such as `.hidden` or `feature/.hidden`) and names containing the DEL character.
35
+ - 71479ce: Let a message sent with `turnPolicy: "queue"` right after a tool approval or sign-in appears steer the held turn again. A message that arrived while the step raising the request was still finishing was treated as sent before the request, so it stayed queued behind a turn that could not end until the person acted.
36
+ - 0fd4240: Honor explicit OpenTelemetry trace policies that enable inputs or outputs for DMs, private channels, and unknown audiences. Default capture remains audience-aware, and inherited capture limits and destination redaction still apply.
37
+ - 3aa9a3a: Expose the live Vercel Sandbox name on `VercelSandboxSession` so tools can create Vercel git-credential-broker grants scoped to their session sandbox.
38
+ - 9d046f8: Memory provider tools are now offered on a turn whose message carries a file attachment. Before, the agent lost its memory tools on exactly that turn.
39
+ - 8d5b75f: `eve build` now works for apps with mounted extensions on filesystems without hard-link support, such as some NFS and FUSE mounts. It no longer fails with `Unknown system error -524` while writing the authored module map.
40
+ - d8414ad: OpenAPI connections whose operation names collide at 64 characters now keep the suffixed tool names within the 64-character provider limit.
41
+ - 8f336b8: Prewarm new Web Chat sessions when the user starts typing, so durable session startup overlaps with composing the first message.
42
+ - 0dea0de: Keep a message sent with `turnPolicy: "queue"` before a tool approval or sign-in was requested in the queue, so it can no longer answer a prompt the person had not seen. Messages sent after the prompt still steer the held turn.
43
+ - d7fef87: Import skills with structured or non-string metadata without failing, treating metadata outside eve's modeled shape like other unmodeled frontmatter.
44
+ - f2e0f67: Vercel sandbox creation now reads `VERCEL_TOKEN`, `VERCEL_TEAM_ID`/`VERCEL_ORG_ID`, and `VERCEL_PROJECT_ID` from the environment, like sandbox lookup and deletion already do. A CI runner without a linked project can now create sandboxes.
45
+ - a4af301: Labeled assertions now report to Braintrust and Datadog under their label, so `t.score(x).label("grounding")` logs as `grounding` instead of `score [grounding]` or `score_grounding`. Display names in the console and run artifacts are unchanged, and labeled metrics start a new series under the bare label.
46
+ - d91d27c: Keep the answer a turn already wrote when it waits on tasks and resumes without new text, so `MessageResponse` results, `eve invoke`, and eval turns no longer report an empty message.
47
+ - 57d4272: Connections that share a host, such as Jira and Confluence on one Atlassian domain, no longer trigger the "could not assign a unique toolResultFrom identity" warning, and `toolResultFrom` now accepts OpenAPI connections, including ones without a `baseUrl`.
48
+ - 0e6bc96: `eve build` now reports why an extension mount failed to resolve, for example an extension that requires an unsupported tool contract or a package that isn't installed. Before, the build stopped with `Selected module binding "extensions/<name>.ts" has no compile or runtime usage.` and hid the cause.
49
+
3
50
  ## 0.79.0
4
51
 
5
52
  ### Minor Changes
@@ -0,0 +1,10 @@
1
+ import type { Session } from "#channel/session.js";
2
+ import type { AuthorizationRequiredStreamEvent } from "#protocol/message.js";
3
+ type AuthorizationRequired = AuthorizationRequiredStreamEvent["data"];
4
+ /**
5
+ * The newest sign-in that `matches` and hasn't completed yet, from the
6
+ * session's recent events. Attempts are keyed by connection name and
7
+ * `attemptId`, so one attempt completing never hides another still pending.
8
+ */
9
+ export declare function findPendingAuthorization(session: Pick<Session, "getEventStream">, matches: (event: AuthorizationRequired) => boolean): Promise<AuthorizationRequired | undefined>;
10
+ export {};
@@ -0,0 +1 @@
1
+ async function findPendingAuthorization(e,t){let n=new Map,r=(await e.getEventStream({follow:!1,startIndex:-500})).getReader();try{for(;;){let e=await r.read();if(e.done)break;let i=e.value;if(i.type===`authorization.required`&&t(i.data)){let e=attemptKey(i.data);n.delete(e),n.set(e,i.data)}else i.type===`authorization.completed`&&n.delete(attemptKey(i.data))}}finally{await r.cancel().catch(()=>{})}return[...n.values()].at(-1)}function attemptKey(e){return JSON.stringify([e.name,e.attemptId??null])}export{findPendingAuthorization};
@@ -4,6 +4,22 @@ import { z } from "#compiled/zod/index.js";
4
4
  import "ai";
5
5
  import { Validator } from "#compiled/@cfworker/json-schema/index.js";
6
6
 
7
+ //#region src/client/abort-signal.ts
8
+ function throwIfAborted(signal) {
9
+ if (signal === void 0) return;
10
+ const nativeThrowIfAborted = signal.throwIfAborted;
11
+ if (typeof nativeThrowIfAborted === "function") {
12
+ nativeThrowIfAborted.call(signal);
13
+ return;
14
+ }
15
+ if (!signal.aborted) return;
16
+ if (signal.reason !== void 0) throw signal.reason;
17
+ const error = /* @__PURE__ */ new Error("The operation was aborted.");
18
+ error.name = "AbortError";
19
+ throw error;
20
+ }
21
+
22
+ //#endregion
7
23
  //#region src/protocol/routes.ts
8
24
  const EVE_ROUTE_PREFIX = "/eve/v1";
9
25
  const EVE_PRODUCTION_CRON_ROUTE_PATTERN = `${EVE_ROUTE_PREFIX}/cron/:token`;
@@ -1152,7 +1168,6 @@ function summarizeTurnEvents(events) {
1152
1168
  if (segment.observe(event)) boundary = event;
1153
1169
  if (isTurnFailureEvent(event)) failure = event;
1154
1170
  if (isFinalMessageCompleted(event)) message = event.data.message ?? void 0;
1155
- if (event.type === "turn.waiting") message = void 0;
1156
1171
  }
1157
1172
  return {
1158
1173
  boundary,
@@ -1336,9 +1351,9 @@ async function* readNdjsonStream(body, options) {
1336
1351
  options.signal?.addEventListener("abort", abort, { once: true });
1337
1352
  try {
1338
1353
  while (true) {
1339
- options.signal?.throwIfAborted();
1354
+ throwIfAborted(options.signal);
1340
1355
  const result = await readWithIdleTimeout(reader, options?.idleTimeoutMs);
1341
- options.signal?.throwIfAborted();
1356
+ throwIfAborted(options.signal);
1342
1357
  if (result.done) {
1343
1358
  reachedEof = true;
1344
1359
  buffer += decoder.decode();
@@ -1616,10 +1631,10 @@ async function openStreamBody(input) {
1616
1631
  if (input.requestTailIndex === true) searchParams.includeTailIndex = "1";
1617
1632
  if (input.follow === false) searchParams.follow = "false";
1618
1633
  for (let attempt = 0; attempt < openRetryPolicy.maxAttempts; attempt += 1) {
1619
- input.signal?.throwIfAborted();
1634
+ throwIfAborted(input.signal);
1620
1635
  const url = createClientUrl(input.host, input.path, Object.keys(searchParams).length > 0 ? searchParams : void 0);
1621
1636
  const headers = await input.resolveHeaders();
1622
- input.signal?.throwIfAborted();
1637
+ throwIfAborted(input.signal);
1623
1638
  const connectionController = new AbortController();
1624
1639
  const signal = input.signal ? AbortSignal.any([input.signal, connectionController.signal]) : connectionController.signal;
1625
1640
  let response;
@@ -2325,14 +2340,14 @@ var ClientSession = class ClientSession {
2325
2340
  return this.#state;
2326
2341
  }
2327
2342
  async snapshot(options) {
2328
- options?.signal?.throwIfAborted();
2343
+ throwIfAborted(options?.signal);
2329
2344
  const events = [];
2330
2345
  for await (const event of this.#readStream({
2331
2346
  follow: false,
2332
2347
  signal: options?.signal,
2333
2348
  startIndex: 0
2334
2349
  })) events.push(event);
2335
- options?.signal?.throwIfAborted();
2350
+ throwIfAborted(options?.signal);
2336
2351
  return {
2337
2352
  events,
2338
2353
  session: {
@@ -2500,7 +2515,7 @@ async function postSessionSend(context, path, input) {
2500
2515
  if (remainingMs <= 0) throw error;
2501
2516
  await sleep(Math.min(retryDelayMs, remainingMs), input.signal);
2502
2517
  }
2503
- input.signal?.throwIfAborted();
2518
+ throwIfAborted(input.signal);
2504
2519
  retryDelayMs = Math.min(retryDelayMs * 2, SESSION_SEND_RETRY_MAX_DELAY_MS);
2505
2520
  }
2506
2521
  }
@@ -4198,11 +4213,14 @@ var ConversationClient = class {
4198
4213
  this.#stream = new SessionEventStream(session, options);
4199
4214
  return this.#stream;
4200
4215
  }
4216
+ closeStream() {
4217
+ this.#stream?.close();
4218
+ this.#stream = void 0;
4219
+ }
4201
4220
  stop() {
4202
4221
  this.#follower?.abortAll();
4203
4222
  this.#follower = void 0;
4204
- this.#stream?.close();
4205
- this.#stream = void 0;
4223
+ this.closeStream();
4206
4224
  }
4207
4225
  reset() {
4208
4226
  this.stop();
@@ -4223,7 +4241,7 @@ async function dispatchSessionTurn(input) {
4223
4241
  ...turn,
4224
4242
  message: turn.message
4225
4243
  });
4226
- turn.signal?.throwIfAborted();
4244
+ throwIfAborted(turn.signal);
4227
4245
  return {
4228
4246
  ...created,
4229
4247
  created: true
@@ -4256,6 +4274,7 @@ var EveAgentStore = class {
4256
4274
  #attached = false;
4257
4275
  #conversationClient;
4258
4276
  #followChildStreams;
4277
+ #followIdle;
4259
4278
  #externalSession;
4260
4279
  #subscribers = /* @__PURE__ */ new Set();
4261
4280
  #activeTurn;
@@ -4273,6 +4292,7 @@ var EveAgentStore = class {
4273
4292
  constructor(init) {
4274
4293
  this.#autoPrewarm = init.prewarm ?? false;
4275
4294
  this.#followChildStreams = init.followSubagents ?? false;
4295
+ this.#followIdle = init.followIdle ?? true;
4276
4296
  this.#externalSession = init.session !== void 0;
4277
4297
  this.#client = this.#externalSession ? void 0 : init.client ?? new Client({
4278
4298
  auth: init.auth,
@@ -4313,7 +4333,7 @@ var EveAgentStore = class {
4313
4333
  this.#error = void 0;
4314
4334
  if (this.#status === "error") this.#status = "ready";
4315
4335
  this.#adoptSession(created.session);
4316
- this.#ensureStream();
4336
+ if (this.#followIdle) this.#ensureStream();
4317
4337
  } catch (error) {
4318
4338
  if (generation === this.#prewarmGeneration && this.#activeTurn === void 0 && this.#error === void 0) this.#fail(error);
4319
4339
  throw error;
@@ -4569,7 +4589,7 @@ var EveAgentStore = class {
4569
4589
  await waitWithSignal(this.#prewarmPromise.catch((error) => {
4570
4590
  if (this.#session !== void 0) throw error;
4571
4591
  }), input.signal);
4572
- input.signal?.throwIfAborted();
4592
+ throwIfAborted(input.signal);
4573
4593
  }
4574
4594
  const session = this.#session;
4575
4595
  let reader;
@@ -4635,6 +4655,7 @@ var EveAgentStore = class {
4635
4655
  if (!this.#isActiveTurn(turn)) return;
4636
4656
  turn.resolveResponse(void 0);
4637
4657
  this.#activeTurn = void 0;
4658
+ this.#closeStreamWhenIdle();
4638
4659
  try {
4639
4660
  this.#callbacks.onSessionChange?.(this.#session?.state);
4640
4661
  this.#publish();
@@ -4668,8 +4689,16 @@ var EveAgentStore = class {
4668
4689
  this.#callbacks.onSessionChange?.(this.#session?.state);
4669
4690
  if (this.#status !== "resuming") this.#publish();
4670
4691
  if (this.#activeTurn === void 0 && wasStreaming && settled) this.#callbacks.onFinish?.(this.#snapshot);
4692
+ if (this.#activeTurn === void 0) this.#closeStreamWhenIdle();
4671
4693
  return true;
4672
4694
  }
4695
+ #closeStreamWhenIdle() {
4696
+ if (this.#followIdle) return;
4697
+ const { conversation } = this.#conversationClient;
4698
+ if (conversation.activeTurnId !== void 0) return;
4699
+ if (this.#events.length > 0 && !isSettledSessionTail(this.#events, conversation)) return;
4700
+ if (!Object.values(conversation.tasks).some((task) => Object.values(task.calls).some((call) => call.status === "working"))) this.#conversationClient.closeStream();
4701
+ }
4673
4702
  #correlate(submissionId, response) {
4674
4703
  const deliveryId = getMessageResponseDeliveryId(response);
4675
4704
  const reconciled = this.#messageSubmissions.correlate(submissionId, deliveryId, this.#events);
@@ -4809,6 +4838,7 @@ function useEveAgent(options = {}) {
4809
4838
  initialSession: options.initialSession,
4810
4839
  optimistic: options.optimistic,
4811
4840
  followSubagents: options.followSubagents,
4841
+ followIdle: options.followIdle,
4812
4842
  prewarm: options.prewarm,
4813
4843
  reducer,
4814
4844
  session: options.session
@@ -3,6 +3,22 @@ import { z } from "#compiled/zod/index.js";
3
3
  import "ai";
4
4
  import { Validator } from "#compiled/@cfworker/json-schema/index.js";
5
5
 
6
+ //#region src/client/abort-signal.ts
7
+ function throwIfAborted(signal) {
8
+ if (signal === void 0) return;
9
+ const nativeThrowIfAborted = signal.throwIfAborted;
10
+ if (typeof nativeThrowIfAborted === "function") {
11
+ nativeThrowIfAborted.call(signal);
12
+ return;
13
+ }
14
+ if (!signal.aborted) return;
15
+ if (signal.reason !== void 0) throw signal.reason;
16
+ const error = /* @__PURE__ */ new Error("The operation was aborted.");
17
+ error.name = "AbortError";
18
+ throw error;
19
+ }
20
+
21
+ //#endregion
6
22
  //#region src/protocol/routes.ts
7
23
  const EVE_ROUTE_PREFIX = "/eve/v1";
8
24
  const EVE_PRODUCTION_CRON_ROUTE_PATTERN = `${EVE_ROUTE_PREFIX}/cron/:token`;
@@ -1151,7 +1167,6 @@ function summarizeTurnEvents(events) {
1151
1167
  if (segment.observe(event)) boundary = event;
1152
1168
  if (isTurnFailureEvent(event)) failure = event;
1153
1169
  if (isFinalMessageCompleted(event)) message = event.data.message ?? void 0;
1154
- if (event.type === "turn.waiting") message = void 0;
1155
1170
  }
1156
1171
  return {
1157
1172
  boundary,
@@ -1335,9 +1350,9 @@ async function* readNdjsonStream(body, options) {
1335
1350
  options.signal?.addEventListener("abort", abort, { once: true });
1336
1351
  try {
1337
1352
  while (true) {
1338
- options.signal?.throwIfAborted();
1353
+ throwIfAborted(options.signal);
1339
1354
  const result = await readWithIdleTimeout(reader, options?.idleTimeoutMs);
1340
- options.signal?.throwIfAborted();
1355
+ throwIfAborted(options.signal);
1341
1356
  if (result.done) {
1342
1357
  reachedEof = true;
1343
1358
  buffer += decoder.decode();
@@ -1615,10 +1630,10 @@ async function openStreamBody(input) {
1615
1630
  if (input.requestTailIndex === true) searchParams.includeTailIndex = "1";
1616
1631
  if (input.follow === false) searchParams.follow = "false";
1617
1632
  for (let attempt = 0; attempt < openRetryPolicy.maxAttempts; attempt += 1) {
1618
- input.signal?.throwIfAborted();
1633
+ throwIfAborted(input.signal);
1619
1634
  const url = createClientUrl(input.host, input.path, Object.keys(searchParams).length > 0 ? searchParams : void 0);
1620
1635
  const headers = await input.resolveHeaders();
1621
- input.signal?.throwIfAborted();
1636
+ throwIfAborted(input.signal);
1622
1637
  const connectionController = new AbortController();
1623
1638
  const signal = input.signal ? AbortSignal.any([input.signal, connectionController.signal]) : connectionController.signal;
1624
1639
  let response;
@@ -2324,14 +2339,14 @@ var ClientSession = class ClientSession {
2324
2339
  return this.#state;
2325
2340
  }
2326
2341
  async snapshot(options) {
2327
- options?.signal?.throwIfAborted();
2342
+ throwIfAborted(options?.signal);
2328
2343
  const events = [];
2329
2344
  for await (const event of this.#readStream({
2330
2345
  follow: false,
2331
2346
  signal: options?.signal,
2332
2347
  startIndex: 0
2333
2348
  })) events.push(event);
2334
- options?.signal?.throwIfAborted();
2349
+ throwIfAborted(options?.signal);
2335
2350
  return {
2336
2351
  events,
2337
2352
  session: {
@@ -2499,7 +2514,7 @@ async function postSessionSend(context, path, input) {
2499
2514
  if (remainingMs <= 0) throw error;
2500
2515
  await sleep(Math.min(retryDelayMs, remainingMs), input.signal);
2501
2516
  }
2502
- input.signal?.throwIfAborted();
2517
+ throwIfAborted(input.signal);
2503
2518
  retryDelayMs = Math.min(retryDelayMs * 2, SESSION_SEND_RETRY_MAX_DELAY_MS);
2504
2519
  }
2505
2520
  }
@@ -4197,11 +4212,14 @@ var ConversationClient = class {
4197
4212
  this.#stream = new SessionEventStream(session, options);
4198
4213
  return this.#stream;
4199
4214
  }
4215
+ closeStream() {
4216
+ this.#stream?.close();
4217
+ this.#stream = void 0;
4218
+ }
4200
4219
  stop() {
4201
4220
  this.#follower?.abortAll();
4202
4221
  this.#follower = void 0;
4203
- this.#stream?.close();
4204
- this.#stream = void 0;
4222
+ this.closeStream();
4205
4223
  }
4206
4224
  reset() {
4207
4225
  this.stop();
@@ -4222,7 +4240,7 @@ async function dispatchSessionTurn(input) {
4222
4240
  ...turn,
4223
4241
  message: turn.message
4224
4242
  });
4225
- turn.signal?.throwIfAborted();
4243
+ throwIfAborted(turn.signal);
4226
4244
  return {
4227
4245
  ...created,
4228
4246
  created: true
@@ -4255,6 +4273,7 @@ var EveAgentStore = class {
4255
4273
  #attached = false;
4256
4274
  #conversationClient;
4257
4275
  #followChildStreams;
4276
+ #followIdle;
4258
4277
  #externalSession;
4259
4278
  #subscribers = /* @__PURE__ */ new Set();
4260
4279
  #activeTurn;
@@ -4272,6 +4291,7 @@ var EveAgentStore = class {
4272
4291
  constructor(init) {
4273
4292
  this.#autoPrewarm = init.prewarm ?? false;
4274
4293
  this.#followChildStreams = init.followSubagents ?? false;
4294
+ this.#followIdle = init.followIdle ?? true;
4275
4295
  this.#externalSession = init.session !== void 0;
4276
4296
  this.#client = this.#externalSession ? void 0 : init.client ?? new Client({
4277
4297
  auth: init.auth,
@@ -4312,7 +4332,7 @@ var EveAgentStore = class {
4312
4332
  this.#error = void 0;
4313
4333
  if (this.#status === "error") this.#status = "ready";
4314
4334
  this.#adoptSession(created.session);
4315
- this.#ensureStream();
4335
+ if (this.#followIdle) this.#ensureStream();
4316
4336
  } catch (error) {
4317
4337
  if (generation === this.#prewarmGeneration && this.#activeTurn === void 0 && this.#error === void 0) this.#fail(error);
4318
4338
  throw error;
@@ -4568,7 +4588,7 @@ var EveAgentStore = class {
4568
4588
  await waitWithSignal(this.#prewarmPromise.catch((error) => {
4569
4589
  if (this.#session !== void 0) throw error;
4570
4590
  }), input.signal);
4571
- input.signal?.throwIfAborted();
4591
+ throwIfAborted(input.signal);
4572
4592
  }
4573
4593
  const session = this.#session;
4574
4594
  let reader;
@@ -4634,6 +4654,7 @@ var EveAgentStore = class {
4634
4654
  if (!this.#isActiveTurn(turn)) return;
4635
4655
  turn.resolveResponse(void 0);
4636
4656
  this.#activeTurn = void 0;
4657
+ this.#closeStreamWhenIdle();
4637
4658
  try {
4638
4659
  this.#callbacks.onSessionChange?.(this.#session?.state);
4639
4660
  this.#publish();
@@ -4667,8 +4688,16 @@ var EveAgentStore = class {
4667
4688
  this.#callbacks.onSessionChange?.(this.#session?.state);
4668
4689
  if (this.#status !== "resuming") this.#publish();
4669
4690
  if (this.#activeTurn === void 0 && wasStreaming && settled) this.#callbacks.onFinish?.(this.#snapshot);
4691
+ if (this.#activeTurn === void 0) this.#closeStreamWhenIdle();
4670
4692
  return true;
4671
4693
  }
4694
+ #closeStreamWhenIdle() {
4695
+ if (this.#followIdle) return;
4696
+ const { conversation } = this.#conversationClient;
4697
+ if (conversation.activeTurnId !== void 0) return;
4698
+ if (this.#events.length > 0 && !isSettledSessionTail(this.#events, conversation)) return;
4699
+ if (!Object.values(conversation.tasks).some((task) => Object.values(task.calls).some((call) => call.status === "working"))) this.#conversationClient.closeStream();
4700
+ }
4672
4701
  #correlate(submissionId, response) {
4673
4702
  const deliveryId = getMessageResponseDeliveryId(response);
4674
4703
  const reconciled = this.#messageSubmissions.correlate(submissionId, deliveryId, this.#events);
@@ -4741,6 +4770,7 @@ function useEveAgent(options = {}) {
4741
4770
  initialSession: options.initialSession,
4742
4771
  optimistic: options.optimistic,
4743
4772
  followSubagents: options.followSubagents,
4773
+ followIdle: options.followIdle,
4744
4774
  prewarm: options.prewarm,
4745
4775
  reducer,
4746
4776
  session: options.session
@@ -0,0 +1,2 @@
1
+ /** Throws the signal's abort reason without requiring AbortSignal#throwIfAborted support. */
2
+ export declare function throwIfAborted(signal: AbortSignal | undefined): void;
@@ -0,0 +1 @@
1
+ function throwIfAborted(e){if(e===void 0)return;let t=e.throwIfAborted;if(typeof t==`function`){t.call(e);return}if(!e.aborted)return;if(e.reason!==void 0)throw e.reason;let n=Error(`The operation was aborted.`);throw n.name=`AbortError`,n}export{throwIfAborted};
@@ -35,6 +35,8 @@ export declare class ConversationClient<TData = ConversationState> {
35
35
  follow(session: ClientSession, events?: readonly MessageStreamEvent[]): void;
36
36
  /** Follows the root session continuously; operation readers subscribe to this one stream. */
37
37
  stream(session: ClientSession, options: SessionEventStreamOptions): SessionEventStream;
38
+ /** Closes the root stream; the next `stream()` call reopens it from the session cursor. */
39
+ closeStream(): void;
38
40
  stop(): void;
39
41
  reset(): void;
40
42
  }
@@ -1 +1 @@
1
- import{assertAnswerable}from"#client/eve-agent-store-helpers.js";import{AgentStreamFollower}from"#client/agent-stream-follower.js";import{canonicalConversationReducer,conversationReducer}from"#client/conversation-reducer.js";import{EveAgentProjection}from"#client/eve-agent-projection.js";import{createEventDeduper}from"#protocol/event-dedupe.js";import{SessionEventStream}from"#client/session-event-stream.js";var ConversationClient=class{projection;#e;#t=new Map;#n=createEventDeduper();#r;#i;#a;#o;constructor(e,t,n){this.projection=e,this.#e=e.reducer===conversationReducer?e:new EveAgentProjection(canonicalConversationReducer,[]),this.#a=t,this.#o=n}get data(){return this.projection.data}get conversation(){return this.#e.data}get projections(){return this.#e===this.projection?[this.projection]:[this.#e,this.projection]}get following(){return this.#r!==void 0}append(e){let t=this.data,n=this.conversation;this.#c(e),t===this.data?n!==this.conversation&&this.#o?.(this.conversation,n):this.#a(this.data,t)}projectResponses(e){if(!e?.length)return;let t={data:{createdAt:Date.now(),responses:e},type:`client.input.responded`};return this.append(t),()=>this.#s(t)}replaceResponses(e,t){return e?.(),assertAnswerable(t,this.conversation),this.projectResponses(t.inputResponses)}#s(e){let t=this.data,n=this.conversation;for(let t of this.projections)t.remove(t=>t===e);t===this.data?n!==this.conversation&&this.#o?.(this.conversation,n):this.#a(this.data,t)}observe(e,t={}){if(!this.#n.admit(e))return!1;t.onAccepted?.(e);let n=this.data,r=this.conversation;return t.project?t.project(e):this.#c(e),t.notify!==!1&&(n===this.data?r!==this.conversation&&this.#o?.(this.conversation,r):this.#a(this.data,n)),this.#r?.acceptParentEvent(e),this.#r?.reconcile(),!0}hydrate(e){return this.#n.admit(e)?(this.#c(e),!0):!1}follow(e,t=[]){this.#r?.abortAll();let n=new AgentStreamFollower({session:e,cursors:this.#t,getState:()=>this.conversation,onFollowing:e=>this.#l({type:`client.agent.following`,data:{sessionId:e}}),onEvent:(e,t)=>this.#l({type:`client.agent.observed`,data:{sessionId:e,event:t}}),onIdle:e=>this.#l({type:`client.agent.idle`,data:{sessionId:e}}),onUnavailable:e=>this.#l({type:`client.agent.unavailable`,data:{sessionId:e}})});this.#r=n;for(let e of t)n.acceptParentEvent(e);n.reconcile()}#c(e){for(let t of this.projections)t.append(e)}#l(e){let t=this.data,n=this.conversation;this.#e.append(e),t===this.data?n!==this.conversation&&this.#o?.(this.conversation,n):this.#a(this.data,t)}stream(e,t){return this.#i!==void 0&&!this.#i.ended?(this.#i.setOptions(t),this.#i):(this.#i=new SessionEventStream(e,t),this.#i)}stop(){this.#r?.abortAll(),this.#r=void 0,this.#i?.close(),this.#i=void 0}reset(){this.stop(),this.#t.clear(),this.#n=createEventDeduper();for(let e of this.projections)e.reset()}};export{ConversationClient};
1
+ import{assertAnswerable}from"#client/eve-agent-store-helpers.js";import{AgentStreamFollower}from"#client/agent-stream-follower.js";import{canonicalConversationReducer,conversationReducer}from"#client/conversation-reducer.js";import{EveAgentProjection}from"#client/eve-agent-projection.js";import{createEventDeduper}from"#protocol/event-dedupe.js";import{SessionEventStream}from"#client/session-event-stream.js";var ConversationClient=class{projection;#e;#t=new Map;#n=createEventDeduper();#r;#i;#a;#o;constructor(e,t,n){this.projection=e,this.#e=e.reducer===conversationReducer?e:new EveAgentProjection(canonicalConversationReducer,[]),this.#a=t,this.#o=n}get data(){return this.projection.data}get conversation(){return this.#e.data}get projections(){return this.#e===this.projection?[this.projection]:[this.#e,this.projection]}get following(){return this.#r!==void 0}append(e){let t=this.data,n=this.conversation;this.#c(e),t===this.data?n!==this.conversation&&this.#o?.(this.conversation,n):this.#a(this.data,t)}projectResponses(e){if(!e?.length)return;let t={data:{createdAt:Date.now(),responses:e},type:`client.input.responded`};return this.append(t),()=>this.#s(t)}replaceResponses(e,t){return e?.(),assertAnswerable(t,this.conversation),this.projectResponses(t.inputResponses)}#s(e){let t=this.data,n=this.conversation;for(let t of this.projections)t.remove(t=>t===e);t===this.data?n!==this.conversation&&this.#o?.(this.conversation,n):this.#a(this.data,t)}observe(e,t={}){if(!this.#n.admit(e))return!1;t.onAccepted?.(e);let n=this.data,r=this.conversation;return t.project?t.project(e):this.#c(e),t.notify!==!1&&(n===this.data?r!==this.conversation&&this.#o?.(this.conversation,r):this.#a(this.data,n)),this.#r?.acceptParentEvent(e),this.#r?.reconcile(),!0}hydrate(e){return this.#n.admit(e)?(this.#c(e),!0):!1}follow(e,t=[]){this.#r?.abortAll();let n=new AgentStreamFollower({session:e,cursors:this.#t,getState:()=>this.conversation,onFollowing:e=>this.#l({type:`client.agent.following`,data:{sessionId:e}}),onEvent:(e,t)=>this.#l({type:`client.agent.observed`,data:{sessionId:e,event:t}}),onIdle:e=>this.#l({type:`client.agent.idle`,data:{sessionId:e}}),onUnavailable:e=>this.#l({type:`client.agent.unavailable`,data:{sessionId:e}})});this.#r=n;for(let e of t)n.acceptParentEvent(e);n.reconcile()}#c(e){for(let t of this.projections)t.append(e)}#l(e){let t=this.data,n=this.conversation;this.#e.append(e),t===this.data?n!==this.conversation&&this.#o?.(this.conversation,n):this.#a(this.data,t)}stream(e,t){return this.#i!==void 0&&!this.#i.ended?(this.#i.setOptions(t),this.#i):(this.#i=new SessionEventStream(e,t),this.#i)}closeStream(){this.#i?.close(),this.#i=void 0}stop(){this.#r?.abortAll(),this.#r=void 0,this.closeStream()}reset(){this.stop(),this.#t.clear(),this.#n=createEventDeduper();for(let e of this.projections)e.reset()}};export{ConversationClient};
@@ -60,6 +60,15 @@ export interface EveAgentStoreInit<TData> {
60
60
  * while the store streams its session or a framework binding has it mounted.
61
61
  */
62
62
  readonly followSubagents?: boolean;
63
+ /**
64
+ * Keep the session stream open while the session is idle, so the store sees events that arrive
65
+ * between turns from schedules, channels, or other clients. When false, the store closes the
66
+ * stream once no turn, task, or sign-in is pending, and reopens it from the session cursor on
67
+ * the next send, answer, or resume.
68
+ *
69
+ * @default true
70
+ */
71
+ readonly followIdle?: boolean;
63
72
  readonly reducer: EveAgentReducer<TData>;
64
73
  readonly session?: ClientSession;
65
74
  }
@@ -1 +1 @@
1
- import{toError}from"#shared/errors.js";import{activeTurnForOptimisticFollowUp,assertAnswerable,assertExclusiveTurnInput,assertInFlightFollowUp,countFollowUpDeliveries,createAbortSignal,createActiveTurn,followSteeredTurns,isAbortError,isResponseBoundary,isSettledSessionTail,settledStatus,toTerminalStreamFailureError,validateFollowUp,waitWithSignal}from"#client/eve-agent-store-helpers.js";import{EveAgentProjection}from"#client/eve-agent-projection.js";import{Client}from"#client/client.js";import{consumeMessageResponse,getMessageResponseDeliveryId}from"#client/message-response.js";import{OptimisticMessageSubmissions}from"#client/optimistic-message-submissions.js";import{ConversationClient}from"#client/conversation-client.js";import{dispatchSessionTurn}from"#client/session-turn-dispatch.js";const detachStore=Symbol(`detachEveAgentStore`),attachStore=Symbol(`attachEveAgentStore`);var EveAgentStore=class{#e;#t;#n=!1;#r;#i;#a;#o=new Set;#s;#c={};#l;#u;#d;#f=0;#p;#m;#h;#g;#_;#v=`ready`;constructor(e){this.#t=e.prewarm??!1,this.#i=e.followSubagents??!1,this.#a=e.session!==void 0,this.#e=this.#a?void 0:e.client??new Client({auth:e.auth,headers:e.headers,host:e.host??``}),this.#r=new ConversationClient(new EveAgentProjection(e.reducer,[]),()=>this.#F(),()=>this.#F()),this.#u=(e.initialEvents??[]).filter(e=>this.#r.hydrate(e)),this.#d=new OptimisticMessageSubmissions(this.#r.projections,e.optimistic??!0),this.#g=e.session??(e.initialSession===void 0?void 0:this.#e?.sessions.attach(e.initialSession.sessionId,{streamIndex:e.initialSession.streamIndex})),this.#_=this.#P()}get snapshot(){return this.#_}setCallbacks(e){this.#c=e}subscribe(e){return this.#o.add(e),()=>void this.#o.delete(e)}prewarm(){if(this.#p!==void 0)return this.#p;if(this.#g!==void 0||this.#a)return Promise.resolve();if(this.#s!==void 0)return this.#s.response.then(e=>{if(e===void 0)throw this.#l??new DOMException(`Session creation was aborted.`,`AbortError`)});let e=this.#e;if(e===void 0)return Promise.reject(Error(`This eve agent store does not own a session client.`));let t=this.#f,n=new AbortController;this.#m=n;let r=(async()=>{try{let r=await e.sessions.create({signal:n.signal});if(t!==this.#f)return;this.#l=void 0,this.#v===`error`&&(this.#v=`ready`),this.#w(r.session),this.#C()}catch(e){throw t===this.#f&&this.#s===void 0&&this.#l===void 0&&this.#T(e),e}})();this.#p=r;let clear=()=>{this.#p===r&&(this.#p=void 0,this.#m=void 0)};return r.then(clear,clear),r}async send(e){return await this.#y(e,this.#c.prepareSend)}async#y(e,t){if(assertAnswerable(e,this.#r.conversation),this.#s!==void 0){if(this.#v===`resuming`)throw Error(`eve session is resuming.`);return await this.#x(this.#s,e,t)}let n=createActiveTurn(e=>e.acceptedFollowUps>0&&this.#g!==void 0?this.#g.cancel():e.response.then(e=>e===void 0?{status:`no_active_turn`}:e.cancel()));this.#s=n,this.#l=void 0,this.#v=`submitted`;let r,i,a;try{assertExclusiveTurnInput(e),i=this.#d.submit(e,this.#u.length),a=this.#r.projectResponses(e.inputResponses),this.#F();let o=await(t===void 0?e:waitWithSignal(Promise.resolve(t(e)),createAbortSignal(e.signal,n.abortController.signal)));if(assertExclusiveTurnInput(o),!this.#k(n))return;o!==e&&(i=this.#d.resubmit(i,o),a=this.#r.replaceResponses(a,o),this.#F());let s={...o,signal:createAbortSignal(o.signal,n.abortController.signal)},c=await this.#S(s);a=void 0;let l=c.response;if(r=c.reader,!this.#k(n))return;n.resolveResponse(l),this.#j(i,l);for await(let e of consumeMessageResponse(l,r)){if(!this.#k(n))return;n.receivedFollowUps+=n.receivedFollowUpEvents.get(e)??0,n.receivedFollowUpEvents.delete(e)}if(!this.#k(n)||(await followSteeredTurns(n,r,()=>this.#k(n)),!this.#k(n)))return;this.#v=settledStatus(this.#l,this.#r.conversation)}catch(e){if(!this.#k(n))return;if(a?.(),isAbortError(e))this.#v=`ready`,this.#d.fail(toError(e),i);else{let t=this.#l!==void 0;this.#l??=toError(e),this.#v=`error`,this.#d.fail(this.#l,i),t||this.#c.onError?.(this.#l)}}finally{r?.[Symbol.dispose](),this.#O(n)}}resume(){if(this.#h!==void 0)return this.#h;let e=this.#b();this.#h=e;let clear=()=>{this.#h===e&&(this.#h=void 0)};return e.then(clear,clear),e}async#b(){if(this.#v!==`ready`&&this.#v!==`error`)throw Error(`eve session is already processing a turn.`);if(this.#g===void 0)throw Error(`An eve session is required before resuming.`);let e=this.#g,t=createActiveTurn(()=>e.cancel());this.#s=t,t.resolveResponse(void 0),this.#l=void 0,this.#v=`resuming`,this.#F();let n;try{let r=this.#C({catchUp:!0,startIndex:this.#u.length===e.state.streamIndex?e.state.streamIndex:0});if(n=r.subscribe(t.abortController.signal),await r.caughtUp,!this.#k(t))return;n.discard();let i=this.#u.at(-1);if(i!==void 0&&this.#N(i),i&&!this.#l&&!isSettledSessionTail(this.#u,this.#r.conversation)){this.#v=`streaming`,this.#F();for await(let e of n){if(!this.#k(t))return;if(t.receivedFollowUps+=t.receivedFollowUpEvents.get(e)??0,t.receivedFollowUpEvents.delete(e),isResponseBoundary(e,this.#r.conversation))break}}await followSteeredTurns(t,n,()=>this.#k(t)),this.#k(t)&&(this.#v=settledStatus(this.#l,this.#r.conversation))}catch(e){if(!this.#k(t))return;isAbortError(e)?this.#v=`ready`:(this.#l=toError(e),this.#v=`error`,this.#c.onError?.(this.#l))}finally{n?.[Symbol.dispose](),this.#O(t)}}cancel(){let e=this.#s;return e===void 0?this.#v===`streaming`&&this.#g!==void 0?this.#g.cancel():Promise.resolve({status:`no_active_turn`}):e.cancel()}async compact(){return await this.#g?.compact()??{status:`no_active_session`}}async clear(){return await this.#g?.clear()??{status:`no_active_session`}}async retire(){if(this.#a)throw Error(`retire() needs a store-owned session. Call reset() on the session you supplied, then create a new store for the next session.`);let e=await this.#g?.reset()??{status:`no_active_session`};return this.reset(),e}[attachStore](){this.#n=!0,this.#i&&!this.#r.following&&this.#E(),this.#t&&this.#g===void 0&&this.prewarm().catch(()=>{})}[detachStore](){this.#n=!1,this.#r.stop(),this.#s?.abortController.abort(),this.#D(),this.#h=void 0}reset(){this.#r.stop();let e=this.#s;this.#s=void 0,e?.resolveResponse(void 0),e?.resolveCompletion(),e?.abortController.abort(),this.#D(),this.#h=void 0,this.#a||(this.#g=void 0),this.#u=[],this.#r.reset(),this.#d.reset(),this.#i&&this.#n&&this.#E(),this.#l=void 0,this.#v=`ready`,this.#c.onSessionChange?.(this.#g?.state),this.#F(),this.#t&&this.#n&&this.prewarm().catch(()=>{})}async#x(e,t,n){assertInFlightFollowUp(t);let r=this.#f,i=createAbortSignal(t.signal,e.abortController.signal),a=this.#r.projectResponses(t.inputResponses),o=await waitWithSignal(Promise.resolve(n?.(t)),i).then(e=>{let n=validateFollowUp(e??t);return n===t||(a=this.#r.replaceResponses(a,n)),n}).catch(e=>{throw a?.(),e});if(r!==this.#f)return;if(!this.#k(e))return a?.(),await this.#y(o);let s=this.#d.submit(o,this.#u.length,activeTurnForOptimisticFollowUp(this.#u));s!==void 0&&e.followUpSubmissionIds.add(s),this.#F();let c;c=(async()=>{try{let t=createAbortSignal(o.signal,e.abortController.signal);if(await waitWithSignal(e.response,t),!this.#k(e)||this.#g===void 0)throw Error(`The active eve turn ended before the follow-up could be sent.`);this.#C({headers:o.headers,streamReconnectPolicy:o.streamReconnectPolicy});let n=(await dispatchSessionTurn({session:this.#g,turn:{...o,signal:t}})).response;if(a=void 0,o.message===void 0)return;e.acceptedFollowUps+=1,this.#j(s,n)}catch(t){throw this.#k(e)&&(this.#d.fail(toError(t),s),a?.(),this.#F()),t}finally{e.followUpDispatches.delete(c)}})(),e.followUpDispatches.add(c),await c,await e.completion}async#S(e){let t={headers:e.headers,streamReconnectPolicy:e.streamReconnectPolicy};this.#p!==void 0&&(await waitWithSignal(this.#p.catch(e=>{if(this.#g!==void 0)throw e}),e.signal),e.signal?.throwIfAborted());let n=this.#g,r;try{let i=await dispatchSessionTurn({client:this.#e,session:n,turn:e,beforeSend:()=>{r=this.#C(t).subscribe(e.signal)}});return i.created&&(this.#w(i.session),r=this.#C(t).subscribe(e.signal)),{response:i.response,reader:r}}catch(e){throw r?.[Symbol.dispose](),e}}#C(e={}){if(this.#g===void 0)throw Error(`A session is required before opening its stream.`);let t=this.#f;return this.#i&&!this.#r.following&&this.#E(),this.#r.stream(this.#g,{...e,onEvent:e=>{t===this.#f&&this.#A(e)},onError:e=>{t===this.#f&&this.#s===void 0&&this.#T(e)}})}#w(e){this.#g=e,this.#i&&this.#n&&this.#E(),this.#c.onSessionChange?.(e.state),this.#F()}#T(e){this.#l=toError(e),this.#v=`error`,this.#c.onError?.(this.#l),this.#F()}#E(){this.#g&&this.#r.follow(this.#g,this.#u)}#D(){this.#f+=1,this.#m?.abort(),this.#m=void 0,this.#p=void 0}#O(e){if(this.#k(e)){e.resolveResponse(void 0),this.#s=void 0;try{this.#c.onSessionChange?.(this.#g?.state),this.#F(),this.#c.onFinish?.(this.#_)}finally{e.resolveCompletion()}}}#k(e){return this.#s===e}#A(e){let t=this.#v===`streaming`;if(!this.#r.observe(e,{onAccepted:()=>{this.#u=[...this.#u,e]},project:e=>{this.#M(this.#d.apply(e))},notify:!1}))return!1;this.#c.onEvent?.(e),this.#N(e);let{conversation:n}=this.#r,r=isSettledSessionTail(this.#u,n)&&n.activeTurnId===void 0;return this.#v!==`resuming`&&this.#l===void 0&&(`data`in e&&e.data!==void 0&&`turnId`in e.data&&(this.#v=`streaming`),this.#s===void 0&&r&&(this.#v=`ready`)),this.#c.onSessionChange?.(this.#g?.state),this.#v!==`resuming`&&this.#F(),this.#s===void 0&&t&&r&&this.#c.onFinish?.(this.#_),!0}#j(e,t){let n=getMessageResponseDeliveryId(t),r=this.#d.correlate(e,n,this.#u);this.#M(r)&&this.#F()}#M(e){return e!==void 0&&(this.#s!==void 0&&countFollowUpDeliveries(this.#s,e),!0)}#N(e){let t=toTerminalStreamFailureError(e);t!==void 0&&(this.#v=`error`,this.#d.failAll(t),this.#l===void 0&&(this.#l=t,this.#c.onError?.(t)))}#P(){return{data:this.#r.data,conversation:this.#r.conversation,error:this.#l,events:this.#u,session:this.#g?.state,status:this.#v}}#F(){this.#_=this.#P();for(let e of this.#o)e()}};function detachEveAgentStore(e){e[detachStore]()}function attachEveAgentStore(e){e[attachStore]()}export{EveAgentStore,attachEveAgentStore,detachEveAgentStore};
1
+ import{toError}from"#shared/errors.js";import{activeTurnForOptimisticFollowUp,assertAnswerable,assertExclusiveTurnInput,assertInFlightFollowUp,countFollowUpDeliveries,createAbortSignal,createActiveTurn,followSteeredTurns,isAbortError,isResponseBoundary,isSettledSessionTail,settledStatus,toTerminalStreamFailureError,validateFollowUp,waitWithSignal}from"#client/eve-agent-store-helpers.js";import{EveAgentProjection}from"#client/eve-agent-projection.js";import{throwIfAborted}from"#client/abort-signal.js";import{Client}from"#client/client.js";import{consumeMessageResponse,getMessageResponseDeliveryId}from"#client/message-response.js";import{OptimisticMessageSubmissions}from"#client/optimistic-message-submissions.js";import{ConversationClient}from"#client/conversation-client.js";import{dispatchSessionTurn}from"#client/session-turn-dispatch.js";const detachStore=Symbol(`detachEveAgentStore`),attachStore=Symbol(`attachEveAgentStore`);var EveAgentStore=class{#e;#t;#n=!1;#r;#i;#a;#o;#s=new Set;#c;#l={};#u;#d;#f;#p=0;#m;#h;#g;#_;#v;#y=`ready`;constructor(e){this.#t=e.prewarm??!1,this.#i=e.followSubagents??!1,this.#a=e.followIdle??!0,this.#o=e.session!==void 0,this.#e=this.#o?void 0:e.client??new Client({auth:e.auth,headers:e.headers,host:e.host??``}),this.#r=new ConversationClient(new EveAgentProjection(e.reducer,[]),()=>this.#L(),()=>this.#L()),this.#d=(e.initialEvents??[]).filter(e=>this.#r.hydrate(e)),this.#f=new OptimisticMessageSubmissions(this.#r.projections,e.optimistic??!0),this.#_=e.session??(e.initialSession===void 0?void 0:this.#e?.sessions.attach(e.initialSession.sessionId,{streamIndex:e.initialSession.streamIndex})),this.#v=this.#I()}get snapshot(){return this.#v}setCallbacks(e){this.#l=e}subscribe(e){return this.#s.add(e),()=>void this.#s.delete(e)}prewarm(){if(this.#m!==void 0)return this.#m;if(this.#_!==void 0||this.#o)return Promise.resolve();if(this.#c!==void 0)return this.#c.response.then(e=>{if(e===void 0)throw this.#u??new DOMException(`Session creation was aborted.`,`AbortError`)});let e=this.#e;if(e===void 0)return Promise.reject(Error(`This eve agent store does not own a session client.`));let t=this.#p,n=new AbortController;this.#h=n;let r=(async()=>{try{let r=await e.sessions.create({signal:n.signal});if(t!==this.#p)return;this.#u=void 0,this.#y===`error`&&(this.#y=`ready`),this.#T(r.session),this.#a&&this.#w()}catch(e){throw t===this.#p&&this.#c===void 0&&this.#u===void 0&&this.#E(e),e}})();this.#m=r;let clear=()=>{this.#m===r&&(this.#m=void 0,this.#h=void 0)};return r.then(clear,clear),r}async send(e){return await this.#b(e,this.#l.prepareSend)}async#b(e,t){if(assertAnswerable(e,this.#r.conversation),this.#c!==void 0){if(this.#y===`resuming`)throw Error(`eve session is resuming.`);return await this.#S(this.#c,e,t)}let n=createActiveTurn(e=>e.acceptedFollowUps>0&&this.#_!==void 0?this.#_.cancel():e.response.then(e=>e===void 0?{status:`no_active_turn`}:e.cancel()));this.#c=n,this.#u=void 0,this.#y=`submitted`;let r,i,a;try{assertExclusiveTurnInput(e),i=this.#f.submit(e,this.#d.length),a=this.#r.projectResponses(e.inputResponses),this.#L();let o=await(t===void 0?e:waitWithSignal(Promise.resolve(t(e)),createAbortSignal(e.signal,n.abortController.signal)));if(assertExclusiveTurnInput(o),!this.#A(n))return;o!==e&&(i=this.#f.resubmit(i,o),a=this.#r.replaceResponses(a,o),this.#L());let s={...o,signal:createAbortSignal(o.signal,n.abortController.signal)},c=await this.#C(s);a=void 0;let l=c.response;if(r=c.reader,!this.#A(n))return;n.resolveResponse(l),this.#N(i,l);for await(let e of consumeMessageResponse(l,r)){if(!this.#A(n))return;n.receivedFollowUps+=n.receivedFollowUpEvents.get(e)??0,n.receivedFollowUpEvents.delete(e)}if(!this.#A(n)||(await followSteeredTurns(n,r,()=>this.#A(n)),!this.#A(n)))return;this.#y=settledStatus(this.#u,this.#r.conversation)}catch(e){if(!this.#A(n))return;if(a?.(),isAbortError(e))this.#y=`ready`,this.#f.fail(toError(e),i);else{let t=this.#u!==void 0;this.#u??=toError(e),this.#y=`error`,this.#f.fail(this.#u,i),t||this.#l.onError?.(this.#u)}}finally{r?.[Symbol.dispose](),this.#k(n)}}resume(){if(this.#g!==void 0)return this.#g;let e=this.#x();this.#g=e;let clear=()=>{this.#g===e&&(this.#g=void 0)};return e.then(clear,clear),e}async#x(){if(this.#y!==`ready`&&this.#y!==`error`)throw Error(`eve session is already processing a turn.`);if(this.#_===void 0)throw Error(`An eve session is required before resuming.`);let e=this.#_,t=createActiveTurn(()=>e.cancel());this.#c=t,t.resolveResponse(void 0),this.#u=void 0,this.#y=`resuming`,this.#L();let n;try{let r=this.#w({catchUp:!0,startIndex:this.#d.length===e.state.streamIndex?e.state.streamIndex:0});if(n=r.subscribe(t.abortController.signal),await r.caughtUp,!this.#A(t))return;n.discard();let i=this.#d.at(-1);if(i!==void 0&&this.#F(i),i&&!this.#u&&!isSettledSessionTail(this.#d,this.#r.conversation)){this.#y=`streaming`,this.#L();for await(let e of n){if(!this.#A(t))return;if(t.receivedFollowUps+=t.receivedFollowUpEvents.get(e)??0,t.receivedFollowUpEvents.delete(e),isResponseBoundary(e,this.#r.conversation))break}}await followSteeredTurns(t,n,()=>this.#A(t)),this.#A(t)&&(this.#y=settledStatus(this.#u,this.#r.conversation))}catch(e){if(!this.#A(t))return;isAbortError(e)?this.#y=`ready`:(this.#u=toError(e),this.#y=`error`,this.#l.onError?.(this.#u))}finally{n?.[Symbol.dispose](),this.#k(t)}}cancel(){let e=this.#c;return e===void 0?this.#y===`streaming`&&this.#_!==void 0?this.#_.cancel():Promise.resolve({status:`no_active_turn`}):e.cancel()}async compact(){return await this.#_?.compact()??{status:`no_active_session`}}async clear(){return await this.#_?.clear()??{status:`no_active_session`}}async retire(){if(this.#o)throw Error(`retire() needs a store-owned session. Call reset() on the session you supplied, then create a new store for the next session.`);let e=await this.#_?.reset()??{status:`no_active_session`};return this.reset(),e}[attachStore](){this.#n=!0,this.#i&&!this.#r.following&&this.#D(),this.#t&&this.#_===void 0&&this.prewarm().catch(()=>{})}[detachStore](){this.#n=!1,this.#r.stop(),this.#c?.abortController.abort(),this.#O(),this.#g=void 0}reset(){this.#r.stop();let e=this.#c;this.#c=void 0,e?.resolveResponse(void 0),e?.resolveCompletion(),e?.abortController.abort(),this.#O(),this.#g=void 0,this.#o||(this.#_=void 0),this.#d=[],this.#r.reset(),this.#f.reset(),this.#i&&this.#n&&this.#D(),this.#u=void 0,this.#y=`ready`,this.#l.onSessionChange?.(this.#_?.state),this.#L(),this.#t&&this.#n&&this.prewarm().catch(()=>{})}async#S(e,t,n){assertInFlightFollowUp(t);let r=this.#p,i=createAbortSignal(t.signal,e.abortController.signal),a=this.#r.projectResponses(t.inputResponses),o=await waitWithSignal(Promise.resolve(n?.(t)),i).then(e=>{let n=validateFollowUp(e??t);return n===t||(a=this.#r.replaceResponses(a,n)),n}).catch(e=>{throw a?.(),e});if(r!==this.#p)return;if(!this.#A(e))return a?.(),await this.#b(o);let s=this.#f.submit(o,this.#d.length,activeTurnForOptimisticFollowUp(this.#d));s!==void 0&&e.followUpSubmissionIds.add(s),this.#L();let c;c=(async()=>{try{let t=createAbortSignal(o.signal,e.abortController.signal);if(await waitWithSignal(e.response,t),!this.#A(e)||this.#_===void 0)throw Error(`The active eve turn ended before the follow-up could be sent.`);this.#w({headers:o.headers,streamReconnectPolicy:o.streamReconnectPolicy});let n=(await dispatchSessionTurn({session:this.#_,turn:{...o,signal:t}})).response;if(a=void 0,o.message===void 0)return;e.acceptedFollowUps+=1,this.#N(s,n)}catch(t){throw this.#A(e)&&(this.#f.fail(toError(t),s),a?.(),this.#L()),t}finally{e.followUpDispatches.delete(c)}})(),e.followUpDispatches.add(c),await c,await e.completion}async#C(e){let t={headers:e.headers,streamReconnectPolicy:e.streamReconnectPolicy};this.#m!==void 0&&(await waitWithSignal(this.#m.catch(e=>{if(this.#_!==void 0)throw e}),e.signal),throwIfAborted(e.signal));let n=this.#_,r;try{let i=await dispatchSessionTurn({client:this.#e,session:n,turn:e,beforeSend:()=>{r=this.#w(t).subscribe(e.signal)}});return i.created&&(this.#T(i.session),r=this.#w(t).subscribe(e.signal)),{response:i.response,reader:r}}catch(e){throw r?.[Symbol.dispose](),e}}#w(e={}){if(this.#_===void 0)throw Error(`A session is required before opening its stream.`);let t=this.#p;return this.#i&&!this.#r.following&&this.#D(),this.#r.stream(this.#_,{...e,onEvent:e=>{t===this.#p&&this.#j(e)},onError:e=>{t===this.#p&&this.#c===void 0&&this.#E(e)}})}#T(e){this.#_=e,this.#i&&this.#n&&this.#D(),this.#l.onSessionChange?.(e.state),this.#L()}#E(e){this.#u=toError(e),this.#y=`error`,this.#l.onError?.(this.#u),this.#L()}#D(){this.#_&&this.#r.follow(this.#_,this.#d)}#O(){this.#p+=1,this.#h?.abort(),this.#h=void 0,this.#m=void 0}#k(e){if(this.#A(e)){e.resolveResponse(void 0),this.#c=void 0,this.#M();try{this.#l.onSessionChange?.(this.#_?.state),this.#L(),this.#l.onFinish?.(this.#v)}finally{e.resolveCompletion()}}}#A(e){return this.#c===e}#j(e){let t=this.#y===`streaming`;if(!this.#r.observe(e,{onAccepted:()=>{this.#d=[...this.#d,e]},project:e=>{this.#P(this.#f.apply(e))},notify:!1}))return!1;this.#l.onEvent?.(e),this.#F(e);let{conversation:n}=this.#r,r=isSettledSessionTail(this.#d,n)&&n.activeTurnId===void 0;return this.#y!==`resuming`&&this.#u===void 0&&(`data`in e&&e.data!==void 0&&`turnId`in e.data&&(this.#y=`streaming`),this.#c===void 0&&r&&(this.#y=`ready`)),this.#l.onSessionChange?.(this.#_?.state),this.#y!==`resuming`&&this.#L(),this.#c===void 0&&t&&r&&this.#l.onFinish?.(this.#v),this.#c===void 0&&this.#M(),!0}#M(){if(this.#a)return;let{conversation:e}=this.#r;e.activeTurnId!==void 0||this.#d.length>0&&!isSettledSessionTail(this.#d,e)||Object.values(e.tasks).some(e=>Object.values(e.calls).some(e=>e.status===`working`))||this.#r.closeStream()}#N(e,t){let n=getMessageResponseDeliveryId(t),r=this.#f.correlate(e,n,this.#d);this.#P(r)&&this.#L()}#P(e){return e!==void 0&&(this.#c!==void 0&&countFollowUpDeliveries(this.#c,e),!0)}#F(e){let t=toTerminalStreamFailureError(e);t!==void 0&&(this.#y=`error`,this.#f.failAll(t),this.#u===void 0&&(this.#u=t,this.#l.onError?.(t)))}#I(){return{data:this.#r.data,conversation:this.#r.conversation,error:this.#u,events:this.#d,session:this.#_?.state,status:this.#y}}#L(){this.#v=this.#I();for(let e of this.#s)e()}};function detachEveAgentStore(e){e[detachStore]()}function attachEveAgentStore(e){e[attachStore]()}export{EveAgentStore,attachEveAgentStore,detachEveAgentStore};
@@ -1,3 +1,3 @@
1
- import{EVE_STREAM_LEASE_ENDED_CONTROL}from"#protocol/message.js";import{normalizeMessageStreamEvent}from"#protocol/message-version.js";function isStreamDisconnectError(e){if(e instanceof DOMException)return e.name===`AbortError`;if(!(e instanceof Error))return!1;let t=`code`in e&&typeof e.code==`string`?e.code:void 0;return e.name===`AbortError`||e.message===`terminated`||t===`UND_ERR_SOCKET`||e instanceof TypeError&&/^(?:failed to fetch|fetch failed|load failed|networkerror when attempting to fetch resource\.)$/i.test(e.message)||/abort|cancel|disconnect|premature close|socket|terminated/i.test(e.message)}async function*readNdjsonStream(e,t){let n=e.getReader(),r=new TextDecoder,i=``,a=!1,abort=()=>{n.cancel().catch(()=>{})};t.signal?.addEventListener(`abort`,abort,{once:!0});try{for(;;){t.signal?.throwIfAborted();let e=await readWithIdleTimeout(n,t?.idleTimeoutMs);if(t.signal?.throwIfAborted(),e.done){a=!0,i+=r.decode();break}e.value&&(i+=r.decode(e.value,{stream:!0}));let o=i.indexOf(`
1
+ import{EVE_STREAM_LEASE_ENDED_CONTROL}from"#protocol/message.js";import{throwIfAborted}from"#client/abort-signal.js";import{normalizeMessageStreamEvent}from"#protocol/message-version.js";function isStreamDisconnectError(e){if(e instanceof DOMException)return e.name===`AbortError`;if(!(e instanceof Error))return!1;let t=`code`in e&&typeof e.code==`string`?e.code:void 0;return e.name===`AbortError`||e.message===`terminated`||t===`UND_ERR_SOCKET`||e instanceof TypeError&&/^(?:failed to fetch|fetch failed|load failed|networkerror when attempting to fetch resource\.)$/i.test(e.message)||/abort|cancel|disconnect|premature close|socket|terminated/i.test(e.message)}async function*readNdjsonStream(e,t){let n=e.getReader(),r=new TextDecoder,i=``,a=!1,abort=()=>{n.cancel().catch(()=>{})};t.signal?.addEventListener(`abort`,abort,{once:!0});try{for(;;){throwIfAborted(t.signal);let e=await readWithIdleTimeout(n,t?.idleTimeoutMs);if(throwIfAborted(t.signal),e.done){a=!0,i+=r.decode();break}e.value&&(i+=r.decode(e.value,{stream:!0}));let o=i.indexOf(`
2
2
  `);for(;o!==-1;){let e=i.slice(0,o).trim();if(i=i.slice(o+1),e.length>0){let n=JSON.parse(e);t.controlVersion===`1`&&isLeaseEndedControl(n)?t.onLeaseEnded?.():yield parseMessageStreamEvent(n,t.streamVersion)}o=i.indexOf(`
3
3
  `)}}let e=i.trim();if(e.length>0){let n=JSON.parse(e);t.controlVersion===`1`&&isLeaseEndedControl(n)?t.onLeaseEnded?.():yield parseMessageStreamEvent(n,t.streamVersion)}}finally{t.signal?.removeEventListener(`abort`,abort),a||n.cancel().catch(()=>{}),n.releaseLock()}}function isLeaseEndedControl(e){if(typeof e!=`object`||!e)return!1;let t=e;return t.$eve===EVE_STREAM_LEASE_ENDED_CONTROL.$eve&&t.version===EVE_STREAM_LEASE_ENDED_CONTROL.version}function parseMessageStreamEvent(e,t){return normalizeMessageStreamEvent(t,e)}async function readWithIdleTimeout(e,t){let n;try{return t===void 0?await e.read():await Promise.race([e.read(),new Promise((e,r)=>{n=setTimeout(()=>r(new DOMException(`Session stream was idle.`,`AbortError`)),t)})])}catch(e){throw e instanceof TypeError?Error(`Session stream disconnected.`,{cause:e}):e}finally{n!==void 0&&clearTimeout(n)}}export{isStreamDisconnectError,readNdjsonStream};
@@ -1 +1 @@
1
- import{ClientError,ClientSessionStrandedError,createClientError}from"#client/client-error.js";import{EVE_STREAM_CONTROL_VERSION,EVE_STREAM_CONTROL_VERSION_QUERY,EVE_STREAM_TAIL_INDEX_HEADER}from"#protocol/message.js";import{createClientUrl}from"#client/url.js";import{isStreamDisconnectError,readNdjsonStream}from"#client/ndjson.js";import{readMessageStreamVersion}from"#client/stream-version.js";const DEFAULT_STREAM_RECONNECT_POLICY={retryableErrorStatuses:new Set([404,409,425,500,502,503,504]),streamIdleReconnectPolicy:{baseDelayMs:250,maxAttempts:5,maxDelayMs:4e3},streamOpenReconnectPolicy:{baseDelayMs:250,maxAttempts:12,maxDelayMs:5e3}},NO_STREAM_RECONNECT_POLICY={...DEFAULT_STREAM_RECONNECT_POLICY,streamIdleReconnectPolicy:{...DEFAULT_STREAM_RECONNECT_POLICY.streamIdleReconnectPolicy,maxAttempts:0},streamOpenReconnectPolicy:{...DEFAULT_STREAM_RECONNECT_POLICY.streamOpenReconnectPolicy,maxAttempts:1}};function resolveRetryPolicy(e,t){return{...t,...e}}function resolveStreamReconnectPolicy(e,t=!1){if(e&&`reconnect`in e&&e.reconnect===!1)return NO_STREAM_RECONNECT_POLICY;let n=e;return{retryableErrorStatuses:n?.retryableErrorStatuses?new Set(n.retryableErrorStatuses):DEFAULT_STREAM_RECONNECT_POLICY.retryableErrorStatuses,streamIdleReconnectPolicy:resolveRetryPolicy(n?.streamIdleReconnectPolicy,{...DEFAULT_STREAM_RECONNECT_POLICY.streamIdleReconnectPolicy,maxAttempts:t?1/0:DEFAULT_STREAM_RECONNECT_POLICY.streamIdleReconnectPolicy.maxAttempts}),streamOpenReconnectPolicy:resolveRetryPolicy(n?.streamOpenReconnectPolicy,DEFAULT_STREAM_RECONNECT_POLICY.streamOpenReconnectPolicy)}}async function*followStreamIterable(e){if(e.follow===!1&&e.startIndex<0)throw Error(`stream({ follow: false }) requires a nonnegative startIndex; a tail-relative cursor cannot be bounded.`);let resolvePolicy=()=>resolveStreamReconnectPolicy(e.resolveReconnectPolicy===void 0?e.streamReconnectPolicy:e.resolveReconnectPolicy(),e.keepAlive),t=resolvePolicy(),n=t.streamIdleReconnectPolicy,r=e.startIndex,i=n.baseDelayMs,a=0,o=!0,s,c=!1;for(;;){t=resolvePolicy(),n=t.streamIdleReconnectPolicy;let l;try{l=await openStreamBody({...e,retryPolicy:t,startIndex:r,requestTailIndex:(e.follow===!1||e.onCaughtUp!==void 0)&&s===void 0})}catch(t){if(e.signal?.aborted)return;throw t}if((e.follow===!1||e.onCaughtUp!==void 0)&&s===void 0&&(s=l.tailIndex,s===void 0))throw l.close(),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.`);if(!c&&s!==void 0&&r>s&&(c=!0,e.onCaughtUp?.()),e.follow===!1&&s!==void 0&&r>s){l.close();return}let u=!1,d=!1;try{for await(let t of readNdjsonStream(l.body,{signal:e.signal,controlVersion:l.controlVersion,idleTimeoutMs:e.streamReadIdleTimeoutMs??15e3,onLeaseEnded:()=>{d=!0},streamVersion:l.streamVersion}))if(r+=1,u=!0,i=n.baseDelayMs,a=0,yield t,!c&&s!==void 0&&r>s&&(c=!0,e.onCaughtUp?.()),t.type===`session.failed`||t.type===`session.completed`||e.follow===!1&&s!==void 0&&r>s)return}catch(e){if(!isStreamDisconnectError(e))throw e}finally{l.close()}if(n=resolvePolicy().streamIdleReconnectPolicy,e.signal?.aborted||e.startIndex<0||n.maxAttempts===0)return;if(!d){if(!u&&!o&&(a+=1)>=n.maxAttempts||(o=!1,await sleep(i,e.signal),e.signal?.aborted))return;i=Math.min(i*2,n.maxDelayMs)}}}async function openStreamBody(e){let t=e.retryPolicy??resolveStreamReconnectPolicy(e.streamReconnectPolicy,e.keepAlive),n=t.streamOpenReconnectPolicy,r,i,a,o=n.baseDelayMs,s=e.startIndex>=0&&t.streamIdleReconnectPolicy.maxAttempts>0?EVE_STREAM_CONTROL_VERSION:void 0,c={};s!==void 0&&(c[EVE_STREAM_CONTROL_VERSION_QUERY]=s),e.startIndex!==0&&(c.startIndex=String(e.startIndex)),e.requestTailIndex===!0&&(c.includeTailIndex=`1`),e.follow===!1&&(c.follow=`false`);for(let l=0;l<n.maxAttempts;l+=1){e.signal?.throwIfAborted();let u=createClientUrl(e.host,e.path,Object.keys(c).length>0?c:void 0),d=await e.resolveHeaders();e.signal?.throwIfAborted();let f=new AbortController,p=e.signal?AbortSignal.any([e.signal,f.signal]):f.signal,m;try{m=await fetch(u,{cache:`no-store`,headers:d,redirect:e.redirect,signal:p})}catch(t){if(e.signal?.aborted||!isStreamDisconnectError(t)||l===n.maxAttempts-1)throw t;await sleep(o,e.signal),o=Math.min(o*2,n.maxDelayMs);continue}if(m.ok){if(!m.body)throw new ClientError(m.status,`Response body is null.`,m.headers);let e=!1;return{body:m.body,close:()=>{e||(e=!0,m.body?.cancel().catch(()=>{}),f.abort())},controlVersion:s,streamVersion:readMessageStreamVersion(m.headers),tailIndex:parseTailIndexHeader(m.headers)}}r=m.status,i=await m.text(),a=m.headers;let h=createClientError(m.status,i,m.headers);if(h instanceof ClientSessionStrandedError||!t.retryableErrorStatuses.has(m.status))throw h;l<n.maxAttempts-1&&(await sleep(o,e.signal),o=Math.min(o*2,n.maxDelayMs))}throw new ClientError(r??0,i??`Failed to open message stream.`,a)}function parseTailIndexHeader(e){let t=e.get(EVE_STREAM_TAIL_INDEX_HEADER);if(t===null||!/^-?\d+$/.test(t))return;let n=Number(t);return Number.isSafeInteger(n)?n:void 0}async function sleep(e,t){t?.aborted||await new Promise(n=>{let onAbort=()=>{clearTimeout(r),n()},r=setTimeout(()=>{t?.removeEventListener(`abort`,onAbort),n()},e);t?.addEventListener(`abort`,onAbort,{once:!0})})}export{followStreamIterable,openStreamBody,sleep};
1
+ import{ClientError,ClientSessionStrandedError,createClientError}from"#client/client-error.js";import{EVE_STREAM_CONTROL_VERSION,EVE_STREAM_CONTROL_VERSION_QUERY,EVE_STREAM_TAIL_INDEX_HEADER}from"#protocol/message.js";import{createClientUrl}from"#client/url.js";import{throwIfAborted}from"#client/abort-signal.js";import{isStreamDisconnectError,readNdjsonStream}from"#client/ndjson.js";import{readMessageStreamVersion}from"#client/stream-version.js";const DEFAULT_STREAM_RECONNECT_POLICY={retryableErrorStatuses:new Set([404,409,425,500,502,503,504]),streamIdleReconnectPolicy:{baseDelayMs:250,maxAttempts:5,maxDelayMs:4e3},streamOpenReconnectPolicy:{baseDelayMs:250,maxAttempts:12,maxDelayMs:5e3}},NO_STREAM_RECONNECT_POLICY={...DEFAULT_STREAM_RECONNECT_POLICY,streamIdleReconnectPolicy:{...DEFAULT_STREAM_RECONNECT_POLICY.streamIdleReconnectPolicy,maxAttempts:0},streamOpenReconnectPolicy:{...DEFAULT_STREAM_RECONNECT_POLICY.streamOpenReconnectPolicy,maxAttempts:1}};function resolveRetryPolicy(e,t){return{...t,...e}}function resolveStreamReconnectPolicy(e,t=!1){if(e&&`reconnect`in e&&e.reconnect===!1)return NO_STREAM_RECONNECT_POLICY;let n=e;return{retryableErrorStatuses:n?.retryableErrorStatuses?new Set(n.retryableErrorStatuses):DEFAULT_STREAM_RECONNECT_POLICY.retryableErrorStatuses,streamIdleReconnectPolicy:resolveRetryPolicy(n?.streamIdleReconnectPolicy,{...DEFAULT_STREAM_RECONNECT_POLICY.streamIdleReconnectPolicy,maxAttempts:t?1/0:DEFAULT_STREAM_RECONNECT_POLICY.streamIdleReconnectPolicy.maxAttempts}),streamOpenReconnectPolicy:resolveRetryPolicy(n?.streamOpenReconnectPolicy,DEFAULT_STREAM_RECONNECT_POLICY.streamOpenReconnectPolicy)}}async function*followStreamIterable(e){if(e.follow===!1&&e.startIndex<0)throw Error(`stream({ follow: false }) requires a nonnegative startIndex; a tail-relative cursor cannot be bounded.`);let resolvePolicy=()=>resolveStreamReconnectPolicy(e.resolveReconnectPolicy===void 0?e.streamReconnectPolicy:e.resolveReconnectPolicy(),e.keepAlive),t=resolvePolicy(),n=t.streamIdleReconnectPolicy,r=e.startIndex,i=n.baseDelayMs,a=0,o=!0,s,c=!1;for(;;){t=resolvePolicy(),n=t.streamIdleReconnectPolicy;let l;try{l=await openStreamBody({...e,retryPolicy:t,startIndex:r,requestTailIndex:(e.follow===!1||e.onCaughtUp!==void 0)&&s===void 0})}catch(t){if(e.signal?.aborted)return;throw t}if((e.follow===!1||e.onCaughtUp!==void 0)&&s===void 0&&(s=l.tailIndex,s===void 0))throw l.close(),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.`);if(!c&&s!==void 0&&r>s&&(c=!0,e.onCaughtUp?.()),e.follow===!1&&s!==void 0&&r>s){l.close();return}let u=!1,d=!1;try{for await(let t of readNdjsonStream(l.body,{signal:e.signal,controlVersion:l.controlVersion,idleTimeoutMs:e.streamReadIdleTimeoutMs??15e3,onLeaseEnded:()=>{d=!0},streamVersion:l.streamVersion}))if(r+=1,u=!0,i=n.baseDelayMs,a=0,yield t,!c&&s!==void 0&&r>s&&(c=!0,e.onCaughtUp?.()),t.type===`session.failed`||t.type===`session.completed`||e.follow===!1&&s!==void 0&&r>s)return}catch(e){if(!isStreamDisconnectError(e))throw e}finally{l.close()}if(n=resolvePolicy().streamIdleReconnectPolicy,e.signal?.aborted||e.startIndex<0||n.maxAttempts===0)return;if(!d){if(!u&&!o&&(a+=1)>=n.maxAttempts||(o=!1,await sleep(i,e.signal),e.signal?.aborted))return;i=Math.min(i*2,n.maxDelayMs)}}}async function openStreamBody(e){let t=e.retryPolicy??resolveStreamReconnectPolicy(e.streamReconnectPolicy,e.keepAlive),n=t.streamOpenReconnectPolicy,r,i,a,o=n.baseDelayMs,s=e.startIndex>=0&&t.streamIdleReconnectPolicy.maxAttempts>0?EVE_STREAM_CONTROL_VERSION:void 0,c={};s!==void 0&&(c[EVE_STREAM_CONTROL_VERSION_QUERY]=s),e.startIndex!==0&&(c.startIndex=String(e.startIndex)),e.requestTailIndex===!0&&(c.includeTailIndex=`1`),e.follow===!1&&(c.follow=`false`);for(let l=0;l<n.maxAttempts;l+=1){throwIfAborted(e.signal);let u=createClientUrl(e.host,e.path,Object.keys(c).length>0?c:void 0),d=await e.resolveHeaders();throwIfAborted(e.signal);let f=new AbortController,p=e.signal?AbortSignal.any([e.signal,f.signal]):f.signal,m;try{m=await fetch(u,{cache:`no-store`,headers:d,redirect:e.redirect,signal:p})}catch(t){if(e.signal?.aborted||!isStreamDisconnectError(t)||l===n.maxAttempts-1)throw t;await sleep(o,e.signal),o=Math.min(o*2,n.maxDelayMs);continue}if(m.ok){if(!m.body)throw new ClientError(m.status,`Response body is null.`,m.headers);let e=!1;return{body:m.body,close:()=>{e||(e=!0,m.body?.cancel().catch(()=>{}),f.abort())},controlVersion:s,streamVersion:readMessageStreamVersion(m.headers),tailIndex:parseTailIndexHeader(m.headers)}}r=m.status,i=await m.text(),a=m.headers;let h=createClientError(m.status,i,m.headers);if(h instanceof ClientSessionStrandedError||!t.retryableErrorStatuses.has(m.status))throw h;l<n.maxAttempts-1&&(await sleep(o,e.signal),o=Math.min(o*2,n.maxDelayMs))}throw new ClientError(r??0,i??`Failed to open message stream.`,a)}function parseTailIndexHeader(e){let t=e.get(EVE_STREAM_TAIL_INDEX_HEADER);if(t===null||!/^-?\d+$/.test(t))return;let n=Number(t);return Number.isSafeInteger(n)?n:void 0}async function sleep(e,t){t?.aborted||await new Promise(n=>{let onAbort=()=>{clearTimeout(r),n()},r=setTimeout(()=>{t?.removeEventListener(`abort`,onAbort),n()},e);t?.addEventListener(`abort`,onAbort,{once:!0})})}export{followStreamIterable,openStreamBody,sleep};
@@ -1 +1 @@
1
- async function dispatchSessionTurn(e){let{client:t,session:n,turn:r,beforeSend:i}=e;if(n===void 0){if(t===void 0)throw Error(`An external eve session is required before sending.`);if(r.message===void 0)throw Error(`Cannot answer an input request before the session starts.`);let e=await t.sessions.create({...r,message:r.message});return r.signal?.throwIfAborted(),{...e,created:!0}}if(i?.(),r.inputResponses===void 0){let{message:e,...t}=r;return{session:n,response:await n.send(e,t),created:!1}}let{inputResponses:a,...o}=r;return{session:n,response:await n.respond(a,o),created:!1}}export{dispatchSessionTurn};
1
+ import{throwIfAborted}from"#client/abort-signal.js";async function dispatchSessionTurn(e){let{client:t,session:n,turn:r,beforeSend:i}=e;if(n===void 0){if(t===void 0)throw Error(`An external eve session is required before sending.`);if(r.message===void 0)throw Error(`Cannot answer an input request before the session starts.`);let e=await t.sessions.create({...r,message:r.message});return throwIfAborted(r.signal),{...e,created:!0}}if(i?.(),r.inputResponses===void 0){let{message:e,...t}=r;return{session:n,response:await n.send(e,t),created:!1}}let{inputResponses:a,...o}=r;return{session:n,response:await n.respond(a,o),created:!1}}export{dispatchSessionTurn};
@@ -1 +1 @@
1
- import{foldSession,initialSessionProjection,openInputs,openSignIns}from"#protocol/session-projection.js";import{isCurrentTurnBoundaryEvent,isTurnFailureEvent}from"#protocol/message.js";function summarizeTurnEvents(e){let t=new TurnSegment,n,r,i;for(let a of e)t.observe(a)&&(n=a),isTurnFailureEvent(a)&&(r=a),isFinalMessageCompleted(a)&&(i=a.data.message??void 0),a.type===`turn.waiting`&&(i=void 0);return{boundary:n,failure:r,inputRequests:t.inputRequests,message:i,pendingAuthorizations:t.pendingAuthorizations,status:summarizeBoundaryStatus(n)}}function summarizeBoundaryStatus(e){return e?.type===`session.waiting`||e?.type===`turn.waiting`?`waiting`:e?.type===`session.failed`?`failed`:`completed`}async function collectTurnEvents(e){let t=[],n=new TurnSegment;for await(let r of e)if(t.push(r),n.observe(r))break;return t}function endsTurnSegment(e,t){return e.type===`turn.waiting`?t.requests||e.data.on===`input`&&!t.callbacks:isCurrentTurnBoundaryEvent(e)&&(e.type!==`session.waiting`||!t.callbacks)}var TurnSegment=class{#e=initialSessionProjection();#t=new Map;#n;constructor(e={}){this.#n=e.followCallbacks===!0}get inputRequests(){return openInputs(this.#e).map(e=>e.request)}get pendingAuthorizations(){return openSignIns(this.#e).flatMap(e=>this.#t.get(e.attemptId)??[])}observe(e){return this.#e=foldSession(this.#e,e),e.type===`authorization.required`&&this.#t.set(e.data.attemptId??e.data.name,e.data),endsTurnSegment(e,{callbacks:this.#n&&openSignIns(this.#e).some(e=>e.awaitsCallback===!0),requests:openInputs(this.#e).length>0})}};function isFinalMessageCompleted(e){return e.type===`message.completed`&&e.data.finishReason!==`tool-calls`}function authorizationKey(e){return e.attemptId===void 0?`name:${e.name}`:`attempt:${e.attemptId}`}export{TurnSegment,authorizationKey,collectTurnEvents,endsTurnSegment,summarizeTurnEvents};
1
+ import{foldSession,initialSessionProjection,openInputs,openSignIns}from"#protocol/session-projection.js";import{isCurrentTurnBoundaryEvent,isTurnFailureEvent}from"#protocol/message.js";function summarizeTurnEvents(e){let t=new TurnSegment,n,r,i;for(let a of e)t.observe(a)&&(n=a),isTurnFailureEvent(a)&&(r=a),isFinalMessageCompleted(a)&&(i=a.data.message??void 0);return{boundary:n,failure:r,inputRequests:t.inputRequests,message:i,pendingAuthorizations:t.pendingAuthorizations,status:summarizeBoundaryStatus(n)}}function summarizeBoundaryStatus(e){return e?.type===`session.waiting`||e?.type===`turn.waiting`?`waiting`:e?.type===`session.failed`?`failed`:`completed`}async function collectTurnEvents(e){let t=[],n=new TurnSegment;for await(let r of e)if(t.push(r),n.observe(r))break;return t}function endsTurnSegment(e,t){return e.type===`turn.waiting`?t.requests||e.data.on===`input`&&!t.callbacks:isCurrentTurnBoundaryEvent(e)&&(e.type!==`session.waiting`||!t.callbacks)}var TurnSegment=class{#e=initialSessionProjection();#t=new Map;#n;constructor(e={}){this.#n=e.followCallbacks===!0}get inputRequests(){return openInputs(this.#e).map(e=>e.request)}get pendingAuthorizations(){return openSignIns(this.#e).flatMap(e=>this.#t.get(e.attemptId)??[])}observe(e){return this.#e=foldSession(this.#e,e),e.type===`authorization.required`&&this.#t.set(e.data.attemptId??e.data.name,e.data),endsTurnSegment(e,{callbacks:this.#n&&openSignIns(this.#e).some(e=>e.awaitsCallback===!0),requests:openInputs(this.#e).length>0})}};function isFinalMessageCompleted(e){return e.type===`message.completed`&&e.data.finishReason!==`tool-calls`}function authorizationKey(e){return e.attemptId===void 0?`name:${e.name}`:`attempt:${e.attemptId}`}export{TurnSegment,authorizationKey,collectTurnEvents,endsTurnSegment,summarizeTurnEvents};
@@ -1 +1 @@
1
- import{EVE_SESSION_ROUTE_PATH,createEveSessionRoutePath,createEveSessionStreamRoutePath}from"#protocol/routes.js";import{ClientError,createClientError}from"#client/client-error.js";import{TurnSegment}from"#client/session-utils.js";import{EVE_SESSION_ID_HEADER}from"#protocol/message.js";import{followStreamIterable,sleep}from"#client/open-stream.js";import{createClientUrl}from"#client/url.js";import{MessageResponse}from"#client/message-response.js";import{ClientAgentSession}from"#client/agent-session.js";import{cancelClientSession,clearClientSession,compactClientSession,resetClientSession}from"#client/session-controls.js";import{serializeOutputSchema}from"#tools/schema.js";const followSession=Symbol(`followClientSession`);var ClientSession=class ClientSession{#e;#t;constructor(e,t){this.#e=e,this.#t=t}static async create(e,t){let n=await postTurn(e,EVE_SESSION_ROUTE_PATH,t,!0,t.stubs),{sessionId:r}=await readAcceptedMessage(n),i=new ClientSession(e,{sessionId:r,streamIndex:0});return{response:i.#r(n,t,0),session:i}}static async prewarm(e,t={}){let{sessionId:n}=await readAcceptedMessage(await postCreateSession(e,t));return new ClientSession(e,{sessionId:n,streamIndex:0})}get state(){return this.#t}async snapshot(e){e?.signal?.throwIfAborted();let t=[];for await(let n of this.#s({follow:!1,signal:e?.signal,startIndex:0}))t.push(n);return e?.signal?.throwIfAborted(),{events:t,session:{sessionId:this.#t.sessionId,streamIndex:t.length}}}async send(e,t={}){return await this.#n({...t,message:e},!0)}async respond(e,t={}){if(e.length===0)throw Error(`ClientSession.respond() requires at least one input response.`);return await this.#n({...t,inputResponses:e},!1)}async#n(e,t){let n=this.#t.streamIndex,r=createEveSessionRoutePath(this.#t.sessionId),i=t?await postSessionSend(this.#e,r,e):await postTurn(this.#e,r,e,!1),{sessionId:a,deliveryId:o}=await readAcceptedMessage(i,this.#t.sessionId);if(a!==this.#t.sessionId)throw Error(`Message route returned a different session id.`);if(e.message!==void 0&&o===void 0)throw Error(`Message route did not return a delivery id. Update the server before sending with this client.`);return this.#r(i,e,n,e.message===void 0?void 0:o)}async cancel(e){return await cancelClientSession({context:this.#e,options:e,sessionId:this.#t.sessionId})}async clear(){return await clearClientSession({context:this.#e,sessionId:this.#t.sessionId})}async compact(){return await compactClientSession({context:this.#e,sessionId:this.#t.sessionId})}async reset(e){return await resetClientSession({context:this.#e,options:e,sessionId:this.#t.sessionId})}stream(e){if(e?.follow===!1&&(e.startIndex??this.#t.streamIndex)<0)throw Error(`stream({ follow: false }) requires a nonnegative startIndex; a tail-relative cursor cannot be bounded.`);return this.#a(e)}agent(e){return new ClientAgentSession(this.#e,e)}[followSession](e){return this.#a({...e,keepAlive:!0})}#r(e,t,n,r){return e.body?.cancel().catch(()=>{}),new MessageResponse({cancelTurn:async e=>await this.cancel({turnId:e}),createStream:e=>this.#i(n,t,r,e),deliveryId:r,resumesTurn:t.inputResponses!==void 0,sessionId:this.#t.sessionId})}async*#i(e,t,n,r){let i=0,a=n===void 0,o=!1,s=new TurnSegment({followCallbacks:!0});try{for await(let c of r??this.#s({headers:t.headers,keepAlive:!0,signal:t.signal,startIndex:e,streamReconnectPolicy:t.streamReconnectPolicy})){if(i+=1,n!==void 0){let e=c.meta?.deliveryIds?.includes(n)===!0,t=c.type===`session.failed`||c.type===`session.completed`;if(!e&&t&&(!a||c.type===`session.completed`))throw Error(`The session ended before the accepted message reached its turn boundary.`);if(!a&&!e)continue;let r=c.meta?.deliveryIds!==void 0;if(!t&&r&&!e)continue;a=!0}if(o=s.observe(c),yield c,o)break}if(n!==void 0&&!o&&!t.signal?.aborted)throw Error(`The response stream ended before the accepted message reached its turn boundary.`)}finally{this.#o(e+i)}}async*#a(e){let t=e?.startIndex??this.#t.streamIndex,n=0;for await(let r of this.#s({follow:e?.follow,headers:e?.headers,keepAlive:e?.keepAlive,onCaughtUp:e?.onCaughtUp,resolveHeaders:e?.resolveHeaders,resolveReconnectPolicy:e?.resolveReconnectPolicy,signal:e?.signal,startIndex:t,streamReconnectPolicy:e?.streamReconnectPolicy}))n+=1,t>=0&&this.#o(t+n),yield r}#o(e){this.#t={sessionId:this.#t.sessionId,streamIndex:Math.max(this.#t.streamIndex,e)}}#s(e){return followStreamIterable({onCaughtUp:e.onCaughtUp,follow:e.follow,host:this.#e.host,keepAlive:e.keepAlive,resolveHeaders:()=>this.#e.resolveHeaders(e.resolveHeaders?.()??e.headers),path:createEveSessionStreamRoutePath(this.#t.sessionId),redirect:this.#e.redirect,signal:e.signal,startIndex:e.startIndex,streamReconnectPolicy:e.streamReconnectPolicy,resolveReconnectPolicy:e.resolveReconnectPolicy})}};function followClientSession(e,t){return e[followSession](t)}async function postSessionSend(e,t,n){let r=Date.now()+2e4,i=250;for(;;){try{return await postTurn(e,t,n,!1)}catch(e){if(!isSessionNotReady(e))throw e;let t=r-Date.now();if(t<=0)throw e;await sleep(Math.min(i,t),n.signal)}n.signal?.throwIfAborted(),i=Math.min(i*2,2e3)}}async function postCreateSession(e,t){let n=await e.resolveHeaders(t.headers),r=t.stubs===void 0?void 0:JSON.stringify({stubs:t.stubs});r!==void 0&&n.set(`content-type`,`application/json`);let i=await fetch(createClientUrl(e.host,EVE_SESSION_ROUTE_PATH),{body:r,headers:n,method:`POST`,redirect:e.redirect,signal:t.signal??null});if(!i.ok){let e=await i.text();throw new ClientError(i.status,e,i.headers)}return i}function isSessionNotReady(e){return e instanceof ClientError&&e.status===409&&e.code===`session_not_ready`}async function postTurn(e,t,n,r,i){let a=createMessageBody(n,r);if(a===null)throw Error(r?`Creating a session requires a non-empty message.`:`A session turn requires a non-empty message or inputResponses.`);i!==void 0&&(a.stubs=i);let o=await e.resolveHeaders(n.headers);o.set(`content-type`,`application/json`);let s=await fetch(createClientUrl(e.host,t),{body:JSON.stringify(a),headers:o,method:`POST`,redirect:e.redirect,signal:n.signal??null});if(!s.ok){let e=await s.text();throw createClientError(s.status,e,s.headers)}return s}async function readAcceptedMessage(e,t){let n=await e.json(),r=(typeof n.sessionId==`string`?n.sessionId:void 0)??e.headers.get(EVE_SESSION_ID_HEADER)?.trim()??t;if(!r)throw Error(`Message route did not return a session id.`);return{sessionId:r,deliveryId:typeof n.deliveryId==`string`&&n.deliveryId.length>0?n.deliveryId:void 0}}function createMessageBody(e,t){let n={};e.message!==void 0&&(n.message=e.message),e.inputResponses!==void 0&&e.inputResponses.length>0&&(n.inputResponses=e.inputResponses),!t&&e.message!==void 0&&e.turnPolicy!==void 0&&(n.turnPolicy=e.turnPolicy),e.clientContext!==void 0&&(n.clientContext=e.clientContext);let r=serializeOutputSchema(e.outputSchema);return r!==void 0&&(n.outputSchema=r),t&&n.message===void 0||n.message===void 0&&n.inputResponses===void 0?null:n}export{ClientSession,followClientSession};
1
+ import{EVE_SESSION_ROUTE_PATH,createEveSessionRoutePath,createEveSessionStreamRoutePath}from"#protocol/routes.js";import{ClientError,createClientError}from"#client/client-error.js";import{TurnSegment}from"#client/session-utils.js";import{EVE_SESSION_ID_HEADER}from"#protocol/message.js";import{followStreamIterable,sleep}from"#client/open-stream.js";import{createClientUrl}from"#client/url.js";import{throwIfAborted}from"#client/abort-signal.js";import{MessageResponse}from"#client/message-response.js";import{ClientAgentSession}from"#client/agent-session.js";import{cancelClientSession,clearClientSession,compactClientSession,resetClientSession}from"#client/session-controls.js";import{serializeOutputSchema}from"#tools/schema.js";const followSession=Symbol(`followClientSession`);var ClientSession=class ClientSession{#e;#t;constructor(e,t){this.#e=e,this.#t=t}static async create(e,t){let n=await postTurn(e,EVE_SESSION_ROUTE_PATH,t,!0,t.stubs),{sessionId:r}=await readAcceptedMessage(n),i=new ClientSession(e,{sessionId:r,streamIndex:0});return{response:i.#r(n,t,0),session:i}}static async prewarm(e,t={}){let{sessionId:n}=await readAcceptedMessage(await postCreateSession(e,t));return new ClientSession(e,{sessionId:n,streamIndex:0})}get state(){return this.#t}async snapshot(e){throwIfAborted(e?.signal);let t=[];for await(let n of this.#s({follow:!1,signal:e?.signal,startIndex:0}))t.push(n);return throwIfAborted(e?.signal),{events:t,session:{sessionId:this.#t.sessionId,streamIndex:t.length}}}async send(e,t={}){return await this.#n({...t,message:e},!0)}async respond(e,t={}){if(e.length===0)throw Error(`ClientSession.respond() requires at least one input response.`);return await this.#n({...t,inputResponses:e},!1)}async#n(e,t){let n=this.#t.streamIndex,r=createEveSessionRoutePath(this.#t.sessionId),i=t?await postSessionSend(this.#e,r,e):await postTurn(this.#e,r,e,!1),{sessionId:a,deliveryId:o}=await readAcceptedMessage(i,this.#t.sessionId);if(a!==this.#t.sessionId)throw Error(`Message route returned a different session id.`);if(e.message!==void 0&&o===void 0)throw Error(`Message route did not return a delivery id. Update the server before sending with this client.`);return this.#r(i,e,n,e.message===void 0?void 0:o)}async cancel(e){return await cancelClientSession({context:this.#e,options:e,sessionId:this.#t.sessionId})}async clear(){return await clearClientSession({context:this.#e,sessionId:this.#t.sessionId})}async compact(){return await compactClientSession({context:this.#e,sessionId:this.#t.sessionId})}async reset(e){return await resetClientSession({context:this.#e,options:e,sessionId:this.#t.sessionId})}stream(e){if(e?.follow===!1&&(e.startIndex??this.#t.streamIndex)<0)throw Error(`stream({ follow: false }) requires a nonnegative startIndex; a tail-relative cursor cannot be bounded.`);return this.#a(e)}agent(e){return new ClientAgentSession(this.#e,e)}[followSession](e){return this.#a({...e,keepAlive:!0})}#r(e,t,n,r){return e.body?.cancel().catch(()=>{}),new MessageResponse({cancelTurn:async e=>await this.cancel({turnId:e}),createStream:e=>this.#i(n,t,r,e),deliveryId:r,resumesTurn:t.inputResponses!==void 0,sessionId:this.#t.sessionId})}async*#i(e,t,n,r){let i=0,a=n===void 0,o=!1,s=new TurnSegment({followCallbacks:!0});try{for await(let c of r??this.#s({headers:t.headers,keepAlive:!0,signal:t.signal,startIndex:e,streamReconnectPolicy:t.streamReconnectPolicy})){if(i+=1,n!==void 0){let e=c.meta?.deliveryIds?.includes(n)===!0,t=c.type===`session.failed`||c.type===`session.completed`;if(!e&&t&&(!a||c.type===`session.completed`))throw Error(`The session ended before the accepted message reached its turn boundary.`);if(!a&&!e)continue;let r=c.meta?.deliveryIds!==void 0;if(!t&&r&&!e)continue;a=!0}if(o=s.observe(c),yield c,o)break}if(n!==void 0&&!o&&!t.signal?.aborted)throw Error(`The response stream ended before the accepted message reached its turn boundary.`)}finally{this.#o(e+i)}}async*#a(e){let t=e?.startIndex??this.#t.streamIndex,n=0;for await(let r of this.#s({follow:e?.follow,headers:e?.headers,keepAlive:e?.keepAlive,onCaughtUp:e?.onCaughtUp,resolveHeaders:e?.resolveHeaders,resolveReconnectPolicy:e?.resolveReconnectPolicy,signal:e?.signal,startIndex:t,streamReconnectPolicy:e?.streamReconnectPolicy}))n+=1,t>=0&&this.#o(t+n),yield r}#o(e){this.#t={sessionId:this.#t.sessionId,streamIndex:Math.max(this.#t.streamIndex,e)}}#s(e){return followStreamIterable({onCaughtUp:e.onCaughtUp,follow:e.follow,host:this.#e.host,keepAlive:e.keepAlive,resolveHeaders:()=>this.#e.resolveHeaders(e.resolveHeaders?.()??e.headers),path:createEveSessionStreamRoutePath(this.#t.sessionId),redirect:this.#e.redirect,signal:e.signal,startIndex:e.startIndex,streamReconnectPolicy:e.streamReconnectPolicy,resolveReconnectPolicy:e.resolveReconnectPolicy})}};function followClientSession(e,t){return e[followSession](t)}async function postSessionSend(e,t,n){let r=Date.now()+2e4,i=250;for(;;){try{return await postTurn(e,t,n,!1)}catch(e){if(!isSessionNotReady(e))throw e;let t=r-Date.now();if(t<=0)throw e;await sleep(Math.min(i,t),n.signal)}throwIfAborted(n.signal),i=Math.min(i*2,2e3)}}async function postCreateSession(e,t){let n=await e.resolveHeaders(t.headers),r=t.stubs===void 0?void 0:JSON.stringify({stubs:t.stubs});r!==void 0&&n.set(`content-type`,`application/json`);let i=await fetch(createClientUrl(e.host,EVE_SESSION_ROUTE_PATH),{body:r,headers:n,method:`POST`,redirect:e.redirect,signal:t.signal??null});if(!i.ok){let e=await i.text();throw new ClientError(i.status,e,i.headers)}return i}function isSessionNotReady(e){return e instanceof ClientError&&e.status===409&&e.code===`session_not_ready`}async function postTurn(e,t,n,r,i){let a=createMessageBody(n,r);if(a===null)throw Error(r?`Creating a session requires a non-empty message.`:`A session turn requires a non-empty message or inputResponses.`);i!==void 0&&(a.stubs=i);let o=await e.resolveHeaders(n.headers);o.set(`content-type`,`application/json`);let s=await fetch(createClientUrl(e.host,t),{body:JSON.stringify(a),headers:o,method:`POST`,redirect:e.redirect,signal:n.signal??null});if(!s.ok){let e=await s.text();throw createClientError(s.status,e,s.headers)}return s}async function readAcceptedMessage(e,t){let n=await e.json(),r=(typeof n.sessionId==`string`?n.sessionId:void 0)??e.headers.get(EVE_SESSION_ID_HEADER)?.trim()??t;if(!r)throw Error(`Message route did not return a session id.`);return{sessionId:r,deliveryId:typeof n.deliveryId==`string`&&n.deliveryId.length>0?n.deliveryId:void 0}}function createMessageBody(e,t){let n={};e.message!==void 0&&(n.message=e.message),e.inputResponses!==void 0&&e.inputResponses.length>0&&(n.inputResponses=e.inputResponses),!t&&e.message!==void 0&&e.turnPolicy!==void 0&&(n.turnPolicy=e.turnPolicy),e.clientContext!==void 0&&(n.clientContext=e.clientContext);let r=serializeOutputSchema(e.outputSchema);return r!==void 0&&(n.outputSchema=r),t&&n.message===void 0||n.message===void 0&&n.inputResponses===void 0?null:n}export{ClientSession,followClientSession};