eve 0.58.0 → 0.59.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (196) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/README.md +1 -0
  3. package/dist/src/channel/session.d.ts +2 -0
  4. package/dist/src/channel/session.js +1 -1
  5. package/dist/src/channel/types.d.ts +8 -1
  6. package/dist/src/chunks/{use-eve-agent-X0asmJg-.js → use-eve-agent-Dmc6sX4d.js} +558 -233
  7. package/dist/src/chunks/{use-eve-agent-CxWcZCsU.js → use-eve-agent-jSR8P4nK.js} +565 -235
  8. package/dist/src/cli/dev/tui/runner.d.ts +4 -0
  9. package/dist/src/cli/dev/tui/runner.js +1 -1
  10. package/dist/src/cli/dev/tui/setup-issues.js +1 -1
  11. package/dist/src/cli/dev/tui/terminal-renderer.js +12 -12
  12. package/dist/src/client/eve-agent-projection.d.ts +10 -0
  13. package/dist/src/client/eve-agent-projection.js +1 -0
  14. package/dist/src/client/eve-agent-store-helpers.d.ts +6 -2
  15. package/dist/src/client/eve-agent-store-helpers.js +2 -2
  16. package/dist/src/client/eve-agent-store-state.d.ts +54 -1
  17. package/dist/src/client/eve-agent-store.d.ts +12 -82
  18. package/dist/src/client/eve-agent-store.js +1 -1
  19. package/dist/src/client/index.d.ts +2 -2
  20. package/dist/src/client/index.js +1 -1
  21. package/dist/src/client/message-response.d.ts +5 -1
  22. package/dist/src/client/message-response.js +1 -1
  23. package/dist/src/client/ndjson.d.ts +1 -0
  24. package/dist/src/client/ndjson.js +2 -2
  25. package/dist/src/client/open-stream.d.ts +4 -1
  26. package/dist/src/client/open-stream.js +1 -1
  27. package/dist/src/client/session-event-stream.d.ts +30 -0
  28. package/dist/src/client/session-event-stream.js +1 -0
  29. package/dist/src/client/session-utils.d.ts +2 -1
  30. package/dist/src/client/session-utils.js +1 -1
  31. package/dist/src/client/session.d.ts +14 -1
  32. package/dist/src/client/session.js +1 -1
  33. package/dist/src/client/sessions.d.ts +8 -2
  34. package/dist/src/client/sessions.js +1 -1
  35. package/dist/src/client/types.d.ts +7 -0
  36. package/dist/src/compiled/.vendor-stamp.json +2 -3
  37. package/dist/src/compiled/@vercel/sandbox/api-client/api-client.d.ts +88 -1
  38. package/dist/src/compiled/@vercel/sandbox/api-client/index.d.ts +1 -1
  39. package/dist/src/compiled/@vercel/sandbox/api-client/validators.d.ts +41 -1
  40. package/dist/src/compiled/@vercel/sandbox/constants.d.ts +3 -3
  41. package/dist/src/compiled/@vercel/{sandbox-drives → sandbox}/drive.d.ts +13 -2
  42. package/dist/src/compiled/@vercel/sandbox/index.d.ts +3 -2
  43. package/dist/src/compiled/@vercel/sandbox/index.js +15 -9
  44. package/dist/src/compiled/@vercel/sandbox/sandbox.d.ts +40 -5
  45. package/dist/src/compiled/_chunks/node/auth-DDrvYko5.js +2 -0
  46. package/dist/src/compiled/_chunks/node/version-C__MqbLM.js +1 -0
  47. package/dist/src/compiler/extension-compatibility.d.ts +14 -14
  48. package/dist/src/compiler/extension-compatibility.js +1 -1
  49. package/dist/src/context/build-dynamic-tools.js +1 -1
  50. package/dist/src/context/dynamic-tool-lifecycle.js +1 -1
  51. package/dist/src/context/memory-tools.js +1 -1
  52. package/dist/src/evals/context.d.ts +1 -1
  53. package/dist/src/evals/context.js +1 -1
  54. package/dist/src/evals/define-eval.d.ts +1 -1
  55. package/dist/src/evals/define-eval.js +1 -1
  56. package/dist/src/evals/index.js +1 -1
  57. package/dist/src/evals/judge.d.ts +1 -1
  58. package/dist/src/evals/runner/execute-task.d.ts +1 -1
  59. package/dist/src/evals/runner/execute-task.js +1 -1
  60. package/dist/src/evals/session-manager.d.ts +27 -0
  61. package/dist/src/evals/session-manager.js +1 -0
  62. package/dist/src/evals/session.d.ts +8 -28
  63. package/dist/src/evals/session.js +2 -1
  64. package/dist/src/evals/target.d.ts +1 -1
  65. package/dist/src/evals/target.js +1 -1
  66. package/dist/src/evals/types.d.ts +19 -15
  67. package/dist/src/eve-channel/create-request.d.ts +24 -0
  68. package/dist/src/eve-channel/create-request.js +1 -0
  69. package/dist/src/eve-channel/index.js +1 -1
  70. package/dist/src/eve-channel/request.d.ts +3 -12
  71. package/dist/src/eve-channel/request.js +2 -2
  72. package/dist/src/eve-channel/types.d.ts +4 -2
  73. package/dist/src/execution/dynamic-workflow/tool.js +1 -1
  74. package/dist/src/execution/legacy-session/turn-workflow.js +1 -1
  75. package/dist/src/execution/runtime-context.js +1 -1
  76. package/dist/src/execution/sandbox/bindings/vercel-lifecycle.d.ts +3 -3
  77. package/dist/src/execution/sandbox/bindings/vercel-lifecycle.js +1 -1
  78. package/dist/src/execution/sandbox/bindings/vercel-sdk-types.d.ts +1 -4
  79. package/dist/src/execution/sandbox/bindings/vercel.d.ts +1 -2
  80. package/dist/src/execution/sandbox/bindings/vercel.js +1 -1
  81. package/dist/src/execution/session/entry.js +1 -1
  82. package/dist/src/execution/session/handoff-steps.js +1 -1
  83. package/dist/src/execution/session/program.d.ts +2 -0
  84. package/dist/src/execution/session/program.js +1 -1
  85. package/dist/src/execution/session/turn-step.js +1 -1
  86. package/dist/src/execution/session/turn.js +1 -1
  87. package/dist/src/execution/session-inbox/protocol.js +1 -1
  88. package/dist/src/execution/tools/connection-search.js +1 -1
  89. package/dist/src/execution/tools/sleep-workflow.js +1 -1
  90. package/dist/src/execution/workflow-runtime.js +1 -1
  91. package/dist/src/experimental/evaluate/auto-model.js +2 -2
  92. package/dist/src/experimental/evaluate/evaluate.d.ts +7 -0
  93. package/dist/src/experimental/evaluate/evaluate.js +1 -0
  94. package/dist/src/harness/compaction.d.ts +3 -3
  95. package/dist/src/harness/compaction.js +1 -1
  96. package/dist/src/harness/request-envelope.d.ts +11 -0
  97. package/dist/src/harness/request-envelope.js +1 -0
  98. package/dist/src/harness/tool-loop.js +2 -2
  99. package/dist/src/instrumentation/prepare-trace-context.d.ts +2 -1
  100. package/dist/src/instrumentation/prepare-trace-context.js +1 -1
  101. package/dist/src/internal/application/package.js +1 -1
  102. package/dist/src/internal/authored-module-loader.d.ts +4 -1
  103. package/dist/src/internal/authored-module-loader.js +1 -1
  104. package/dist/src/internal/bundler/nitro-rolldown.d.ts +2 -0
  105. package/dist/src/internal/model-auth/transport.d.ts +3 -1
  106. package/dist/src/internal/model-auth/transport.js +1 -1
  107. package/dist/src/internal/nitro/host/build-extension.js +1 -1
  108. package/dist/src/internal/nitro/host/extension-capability-requirements.d.ts +1 -0
  109. package/dist/src/internal/nitro/host/extension-capability-requirements.js +1 -1
  110. package/dist/src/internal/nitro/host/extension-distribution.d.ts +1 -1
  111. package/dist/src/internal/nitro/host/extension-distribution.js +1 -1
  112. package/dist/src/internal/workflow-bundle/dynamic-tool-transform.js +1 -1
  113. package/dist/src/public/experimental/evaluate/index.d.ts +1 -0
  114. package/dist/src/public/experimental/evaluate/index.js +1 -1
  115. package/dist/src/public/models/anthropic/index.js +1 -1
  116. package/dist/src/public/sandbox/vercel-sandbox.d.ts +1 -1
  117. package/dist/src/public/sandbox/vercel.d.ts +1 -1
  118. package/dist/src/public/sandbox/vercel.js +1 -1
  119. package/dist/src/public/tools/index.d.ts +1 -0
  120. package/dist/src/public/tools/index.js +1 -1
  121. package/dist/src/react/use-eve-agent.d.ts +4 -0
  122. package/dist/src/react/use-eve-agent.js +1 -1
  123. package/dist/src/runtime/agent/resolve-model.js +1 -1
  124. package/dist/src/setup/flows/model-login-connection.js +1 -1
  125. package/dist/src/setup/scaffold/create/project.js +1 -1
  126. package/dist/src/subagents/handle-dispatch.js +1 -1
  127. package/dist/src/svelte/index.js +1 -1
  128. package/dist/src/svelte/use-eve-agent.d.ts +4 -0
  129. package/dist/src/svelte/use-eve-agent.js +1 -1
  130. package/dist/src/tools/definition.d.ts +2 -0
  131. package/dist/src/tools/definition.js +1 -1
  132. package/dist/src/tools/durable-callbacks.d.ts +8 -2
  133. package/dist/src/tools/durable-callbacks.js +1 -1
  134. package/dist/src/tools/durable-schema.d.ts +16 -0
  135. package/dist/src/tools/durable-schema.js +1 -0
  136. package/dist/src/vue/index.js +1 -1
  137. package/dist/src/vue/use-eve-agent.d.ts +4 -0
  138. package/dist/src/vue/use-eve-agent.js +1 -1
  139. package/docs/README.md +1 -0
  140. package/docs/channels/eve.mdx +20 -10
  141. package/docs/concepts/context-control.md +4 -0
  142. package/docs/concepts/sessions-runs-and-streaming.md +18 -3
  143. package/docs/evals/assertions.mdx +6 -6
  144. package/docs/evals/cases.mdx +59 -23
  145. package/docs/evals/judge.mdx +10 -8
  146. package/docs/evals/overview.mdx +6 -6
  147. package/docs/evals/reporters.mdx +1 -1
  148. package/docs/evals/targets.mdx +5 -0
  149. package/docs/guides/client/messages.mdx +5 -5
  150. package/docs/guides/client/overview.mdx +15 -1
  151. package/docs/guides/dynamic-capabilities.md +22 -0
  152. package/docs/guides/evaluate.md +58 -4
  153. package/docs/guides/frontend/overview.mdx +54 -5
  154. package/docs/guides/frontend/use-eve-agent-svelte.mdx +13 -8
  155. package/docs/guides/frontend/use-eve-agent-vue.mdx +13 -8
  156. package/docs/reference/typescript-api.md +38 -36
  157. package/package.json +2 -3
  158. package/dist/src/compiled/@vercel/sandbox-drives/LICENSE +0 -201
  159. package/dist/src/compiled/@vercel/sandbox-drives/_async-retry.d.ts +0 -8
  160. package/dist/src/compiled/@vercel/sandbox-drives/_workflow-serde.d.ts +0 -5
  161. package/dist/src/compiled/@vercel/sandbox-drives/api-client/api-client.d.ts +0 -1815
  162. package/dist/src/compiled/@vercel/sandbox-drives/api-client/api-error.d.ts +0 -29
  163. package/dist/src/compiled/@vercel/sandbox-drives/api-client/base-client.d.ts +0 -39
  164. package/dist/src/compiled/@vercel/sandbox-drives/api-client/file-writer.d.ts +0 -66
  165. package/dist/src/compiled/@vercel/sandbox-drives/api-client/index.d.ts +0 -2
  166. package/dist/src/compiled/@vercel/sandbox-drives/api-client/validators.d.ts +0 -932
  167. package/dist/src/compiled/@vercel/sandbox-drives/api-client/with-retry.d.ts +0 -10
  168. package/dist/src/compiled/@vercel/sandbox-drives/auth/error.d.ts +0 -15
  169. package/dist/src/compiled/@vercel/sandbox-drives/auth/file.d.ts +0 -18
  170. package/dist/src/compiled/@vercel/sandbox-drives/auth/index.d.ts +0 -6
  171. package/dist/src/compiled/@vercel/sandbox-drives/auth/oauth.d.ts +0 -111
  172. package/dist/src/compiled/@vercel/sandbox-drives/auth/poll-for-token.d.ts +0 -28
  173. package/dist/src/compiled/@vercel/sandbox-drives/auth/project.d.ts +0 -40
  174. package/dist/src/compiled/@vercel/sandbox-drives/command.d.ts +0 -292
  175. package/dist/src/compiled/@vercel/sandbox-drives/constants.d.ts +0 -15
  176. package/dist/src/compiled/@vercel/sandbox-drives/execution-context.d.ts +0 -116
  177. package/dist/src/compiled/@vercel/sandbox-drives/filesystem.d.ts +0 -258
  178. package/dist/src/compiled/@vercel/sandbox-drives/index.d.ts +0 -14
  179. package/dist/src/compiled/@vercel/sandbox-drives/index.js +0 -9
  180. package/dist/src/compiled/@vercel/sandbox-drives/network-policy.d.ts +0 -169
  181. package/dist/src/compiled/@vercel/sandbox-drives/proxy.d.ts +0 -55
  182. package/dist/src/compiled/@vercel/sandbox-drives/sandbox-user.d.ts +0 -211
  183. package/dist/src/compiled/@vercel/sandbox-drives/sandbox.d.ts +0 -1287
  184. package/dist/src/compiled/@vercel/sandbox-drives/session.d.ts +0 -435
  185. package/dist/src/compiled/@vercel/sandbox-drives/snapshot.d.ts +0 -238
  186. package/dist/src/compiled/@vercel/sandbox-drives/utils/get-credentials.d.ts +0 -21
  187. package/dist/src/compiled/@vercel/sandbox-drives/utils/paginator.d.ts +0 -16
  188. package/dist/src/compiled/@vercel/sandbox-drives/utils/resolveSignal.d.ts +0 -15
  189. package/dist/src/compiled/@vercel/sandbox-drives/utils/sandbox-snapshot.d.ts +0 -11
  190. package/dist/src/compiled/@vercel/sandbox-drives/utils/types.d.ts +0 -11
  191. package/dist/src/compiled/_chunks/node/auth-8aQozzfi.js +0 -2
  192. package/dist/src/compiled/_chunks/node/auth-Bvv0xGTY.js +0 -2
  193. package/dist/src/compiled/_chunks/node/esm-Fqlolk7e.js +0 -7
  194. package/dist/src/compiled/_chunks/node/version-BC6t2Txc.js +0 -1
  195. package/dist/src/compiled/_chunks/node/version-DSQqVZ5T.js +0 -1
  196. package/dist/src/compiled/_chunks/node/xdg-app-paths-F-QHrdza.js +0 -1
@@ -1,5 +1,57 @@
1
1
  import type { MessageResponse } from "#client/message-response.js";
2
- import type { CancelSessionResult } from "#client/types.js";
2
+ import type { EveAgentReducer } from "#client/reducer.js";
3
+ import type { ClientSession } from "#client/session.js";
4
+ import type { MessageStreamEvent } from "#protocol/message.js";
5
+ import type { CancelSessionResult, ClientAuth, ClientSessionState, HeadersValue, SendTurnPayload } from "#client/types.js";
6
+ /**
7
+ * Lifecycle state of an eve frontend session store: `ready` (idle),
8
+ * `resuming` (checking an attached session for continuation), `submitted`
9
+ * (turn sent, awaiting the first event), `streaming` (events arriving), and
10
+ * `error` (session creation, streaming, resume, or a turn failed).
11
+ */
12
+ export type EveAgentStoreStatus = "error" | "ready" | "resuming" | "streaming" | "submitted";
13
+ /**
14
+ * Prepares one outbound turn immediately before the client sends it, for
15
+ * example to attach fresh one-turn page state through `clientContext`.
16
+ */
17
+ export type PrepareSend = (input: SendTurnPayload) => SendTurnPayload | Promise<SendTurnPayload>;
18
+ /** Immutable projected state of an eve frontend session store. */
19
+ export interface EveAgentStoreSnapshot<TData> {
20
+ readonly data: TData;
21
+ /** The latest session creation, stream, resume, or turn failure. */
22
+ readonly error: Error | undefined;
23
+ readonly events: readonly MessageStreamEvent[];
24
+ readonly session: ClientSessionState | undefined;
25
+ readonly status: EveAgentStoreStatus;
26
+ }
27
+ /**
28
+ * Hooks invoked during session creation and turn processing. The observation callbacks
29
+ * do not alter execution; `prepareSend` may replace the outbound turn payload.
30
+ */
31
+ export interface EveAgentStoreCallbacks<TData> {
32
+ readonly onError?: (error: Error) => void;
33
+ readonly onEvent?: (event: MessageStreamEvent) => void;
34
+ readonly onFinish?: (snapshot: EveAgentStoreSnapshot<TData>) => void;
35
+ readonly onSessionChange?: (session: ClientSessionState | undefined) => void;
36
+ readonly prepareSend?: PrepareSend;
37
+ }
38
+ /**
39
+ * Configuration for constructing an eve frontend session store. Pass either
40
+ * connection options for a store-owned session or an existing `ClientSession`.
41
+ * Saved events must be an ordered prefix of the same session stream.
42
+ */
43
+ export interface EveAgentStoreInit<TData> {
44
+ readonly prewarm?: boolean;
45
+ readonly auth?: ClientAuth;
46
+ readonly headers?: HeadersValue;
47
+ readonly host?: string;
48
+ /** Ordered prefix of the session stream used to rehydrate projected state. */
49
+ readonly initialEvents?: readonly MessageStreamEvent[];
50
+ readonly initialSession?: ClientSessionState;
51
+ readonly optimistic?: boolean;
52
+ readonly reducer: EveAgentReducer<TData>;
53
+ readonly session?: ClientSession;
54
+ }
3
55
  export interface PendingMessageSubmission {
4
56
  readonly createdAt: number;
5
57
  readonly id: string;
@@ -12,6 +64,7 @@ export interface ActiveTurn {
12
64
  readonly completion: Promise<void>;
13
65
  readonly followUpDispatches: Set<Promise<void>>;
14
66
  receivedFollowUps: number;
67
+ readonly receivedFollowUpEvents: Set<MessageStreamEvent>;
15
68
  readonly followUpSubmissionIds: Set<string>;
16
69
  readonly resolveCompletion: () => void;
17
70
  readonly response: Promise<MessageResponse | undefined>;
@@ -1,86 +1,12 @@
1
- import type { EveAgentReducer } from "#client/reducer.js";
2
- import type { ClientSession } from "#client/session.js";
3
- import { type MessageStreamEvent } from "#protocol/message.js";
4
- import type { CancelSessionResult, ClientAuth, HeadersValue, SendTurnPayload, ClientSessionState } from "#client/types.js";
5
- /**
6
- * Lifecycle state of an {@link EveAgentStore}: `ready` (idle), `resuming`
7
- * (checking an attached session for continuation), `submitted` (turn sent,
8
- * awaiting the first event), `streaming` (events arriving), and `error` (the
9
- * turn failed). A new turn advances `ready` to `submitted` to `streaming` to
10
- * `ready` (or `error`).
11
- */
12
- export type EveAgentStoreStatus = "error" | "ready" | "resuming" | "streaming" | "submitted";
13
- /**
14
- * Prepares one outbound turn immediately before the client sends it, e.g. to
15
- * attach fresh one-turn client state such as page context via `clientContext`.
16
- */
17
- export type PrepareSend = (input: SendTurnPayload) => SendTurnPayload | Promise<SendTurnPayload>;
18
- /**
19
- * Immutable projected state of an {@link EveAgentStore}, read on every render.
20
- *
21
- * `data` is the reducer output, `events` is the raw server stream-event log for
22
- * this session, `session` is the current serializable cursor, `status` is the
23
- * turn lifecycle state, and `error` is the last failure (or `undefined`).
24
- */
25
- export interface EveAgentStoreSnapshot<TData> {
26
- readonly data: TData;
27
- readonly error: Error | undefined;
28
- readonly events: readonly MessageStreamEvent[];
29
- readonly session: ClientSessionState | undefined;
30
- readonly status: EveAgentStoreStatus;
31
- }
32
- /**
33
- * Hooks invoked while the store processes a turn.
34
- *
35
- * `onEvent`, `onError`, `onFinish`, and `onSessionChange` are observe-only.
36
- * `prepareSend` runs before each turn is sent and may return a modified
37
- * {@link SendTurnPayload} (for example to attach one-turn client context).
38
- */
39
- export interface EveAgentStoreCallbacks<TData> {
40
- readonly onError?: (error: Error) => void;
41
- readonly onEvent?: (event: MessageStreamEvent) => void;
42
- readonly onFinish?: (snapshot: EveAgentStoreSnapshot<TData>) => void;
43
- readonly onSessionChange?: (session: ClientSessionState | undefined) => void;
44
- readonly prepareSend?: PrepareSend;
45
- }
46
- /**
47
- * Configuration for constructing an {@link EveAgentStore}.
48
- *
49
- * Requires a {@link EveAgentReducer | reducer}, plus either connection options
50
- * (`host`, `auth`, `headers`, `initialSession`) for a
51
- * store-owned session or an existing {@link ClientSession} via `session`.
52
- *
53
- * `optimistic` (default `true`) projects submitted user messages before the
54
- * server confirms them. `host` defaults to `""`. `initialEvents` and
55
- * `initialSession` seed prior state on construction. Passing `session` makes
56
- * `reset()` reuse that external session rather than create a new one.
57
- * `initialEvents` must be an ordered prefix of the same session's stream; its
58
- * endpoint may overlap the cursor because repeated ids are applied once.
59
- */
60
- export interface EveAgentStoreInit<TData> {
61
- readonly auth?: ClientAuth;
62
- readonly headers?: HeadersValue;
63
- readonly host?: string;
64
- /** Ordered prefix of the session stream used to rehydrate projected state. */
65
- readonly initialEvents?: readonly MessageStreamEvent[];
66
- readonly initialSession?: ClientSessionState;
67
- readonly optimistic?: boolean;
68
- readonly reducer: EveAgentReducer<TData>;
69
- readonly session?: ClientSession;
70
- }
1
+ import type { EveAgentStoreCallbacks, EveAgentStoreInit, EveAgentStoreSnapshot } from "#client/eve-agent-store-state.js";
2
+ import type { CancelSessionResult, SendTurnPayload } from "#client/types.js";
3
+ export type { EveAgentStoreCallbacks, EveAgentStoreInit, EveAgentStoreSnapshot, EveAgentStoreStatus, PrepareSend, } from "#client/eve-agent-store-state.js";
71
4
  declare const detachStore: unique symbol;
5
+ declare const attachStore: unique symbol;
72
6
  /**
73
- * Framework-agnostic state machine for an eve agent session.
74
- *
75
- * Manages the send/stream lifecycle, optimistic projection, and subscriber
76
- * notification; framework integrations (React, Vue) wrap it with their own
77
- * reactivity primitives.
78
- *
79
- * Drives one turn at a time: `send` rejects while a turn is active, and
80
- * concurrent `resume` calls share one replay. Read the latest projection via
81
- * the `snapshot` getter, observe changes with `subscribe`, register lifecycle
82
- * hooks with `setCallbacks`, cancel the durable in-flight turn with `cancel`,
83
- * and discard all state with `reset`.
7
+ * Owns frontend session creation, continuous streaming, turn submission, and UI projection.
8
+ * Framework bindings subscribe to snapshots and attach or detach transport with their lifecycle.
9
+ * Reset clears local state; cancellation remains an explicit durable operation.
84
10
  */
85
11
  export declare class EveAgentStore<TData> {
86
12
  #private;
@@ -88,6 +14,8 @@ export declare class EveAgentStore<TData> {
88
14
  get snapshot(): EveAgentStoreSnapshot<TData>;
89
15
  setCallbacks(callbacks: EveAgentStoreCallbacks<TData>): void;
90
16
  subscribe(callback: () => void): () => void;
17
+ /** Creates this store's owned session without starting a turn. */
18
+ prewarm(): Promise<void>;
91
19
  send<TOutput = unknown>(input: SendTurnPayload<TOutput>): Promise<void>;
92
20
  /** Replays this store's attached durable session and follows an in-flight turn. */
93
21
  resume(): Promise<void>;
@@ -98,9 +26,11 @@ export declare class EveAgentStore<TData> {
98
26
  * that turn ID. The event stream stays attached until the turn settles.
99
27
  */
100
28
  cancel(): Promise<CancelSessionResult>;
29
+ [attachStore](): void;
101
30
  [detachStore](): void;
102
31
  reset(): void;
103
32
  }
104
33
  /** @internal Detaches local transport without cancelling durable server work. */
105
34
  export declare function detachEveAgentStore<TData>(store: EveAgentStore<TData>): void;
106
- export {};
35
+ /** @internal Starts mount-scoped session work after the framework commits. */
36
+ export declare function attachEveAgentStore<TData>(store: EveAgentStore<TData>): void;
@@ -1 +1 @@
1
- import{toError}from"#shared/errors.js";import{createEventDeduper}from"#protocol/event-dedupe.js";import{isCurrentTurnBoundaryEvent}from"#protocol/message.js";import{Client}from"#client/client.js";import{assertExclusiveTurnInput,collectPendingAuthorizations,createAbortSignal,createSubmissionId,isAbortError,isSettledSessionTail,summarizeUserContent,toTerminalStreamFailureError,updatePendingAuthorizations}from"#client/eve-agent-store-helpers.js";const detachStore=Symbol(`detachEveAgentStore`);var EveAgentStore=class{#e;#t;#n;#r;#i=new Set;#a=createEventDeduper();#o;#s={};#c;#l;#u;#d=[];#f;#p;#m;#h;#g=`ready`;constructor(e){this.#t=e.session!==void 0,this.#e=this.#t?void 0:new Client({auth:e.auth,headers:e.headers,host:e.host??``});let t=[];for(let n of e.initialEvents??[])this.#a.admit(n)&&t.push(n);this.#u=t,this.#f=[...this.#u],this.#n=e.optimistic??!0,this.#r=e.reducer,this.#m=e.session??(e.initialSession===void 0?void 0:this.#e?.sessions.attach(e.initialSession.sessionId,{streamIndex:e.initialSession.streamIndex})),this.#c=this.#j(this.#f),this.#h=this.#M()}get snapshot(){return this.#h}setCallbacks(e){this.#s=e}subscribe(e){return this.#i.add(e),()=>{this.#i.delete(e)}}async send(e){if(this.#o!==void 0){if(this.#g===`resuming`)throw Error(`eve session is resuming.`);return await this.#v(this.#o,e)}let t=Promise.withResolvers(),n=Promise.withResolvers(),r={abortController:new AbortController,acceptedFollowUps:0,cancel:()=>r.acceptedFollowUps>0&&this.#m!==void 0?this.#m.cancel():t.promise.then(e=>e===void 0?{status:`no_active_turn`}:e.cancel()),completion:n.promise,followUpDispatches:new Set,receivedFollowUps:0,followUpSubmissionIds:new Set,resolveCompletion:n.resolve,response:t.promise,resolveResponse:t.resolve};this.#o=r,this.#l=void 0,this.#g=`submitted`,this.#N();try{let t=await this.#s.prepareSend?.(e)??e;if(assertExclusiveTurnInput(t),!this.#S(r))return;this.#C(t),this.#w(t),this.#N();let n={...t,signal:createAbortSignal(t.signal,r.abortController.signal)},i=await this.#x(n);if(!this.#S(r))return;r.resolveResponse(i);for await(let e of i){if(!this.#S(r))return;this.#T(e)}if(!this.#S(r)||(await this.#y(r),!this.#S(r)))return;this.#g=this.#l===void 0?`ready`:`error`}catch(e){if(!this.#S(r))return;isAbortError(e)?(this.#g=`ready`,this.#O(toError(e))):(this.#l=toError(e),this.#g=`error`,this.#O(this.#l),this.#s.onError?.(this.#l))}finally{this.#S(r)&&(r.resolveResponse(void 0),this.#o=void 0,this.#s.onSessionChange?.(this.#m?.state),this.#N(),this.#s.onFinish?.(this.#h),r.resolveCompletion())}}resume(){if(this.#p!==void 0)return this.#p;let e=this.#_();this.#p=e;let clear=()=>{this.#p===e&&(this.#p=void 0)};return e.then(clear,clear),e}async#_(){if(this.#g===`resuming`||this.#g===`streaming`||this.#g===`submitted`)throw Error(`eve session is already processing a turn.`);if(this.#m===void 0)throw Error(`An eve session is required before resuming.`);let e=Promise.withResolvers(),t=Promise.withResolvers(),n=this.#m,r={abortController:new AbortController,acceptedFollowUps:0,cancel:()=>n.cancel(),completion:t.promise,followUpDispatches:new Set,receivedFollowUps:0,followUpSubmissionIds:new Set,resolveCompletion:t.resolve,response:e.promise,resolveResponse:e.resolve};this.#o=r,r.resolveResponse(void 0),this.#l=void 0,this.#g=`resuming`,this.#N();try{let e=this.#u.length===n.state.streamIndex,t=e?[...this.#u]:[];for await(let i of n.stream({follow:!1,signal:r.abortController.signal,startIndex:e?n.state.streamIndex:0})){if(!this.#S(r))return;t.push(i),this.#T(i,{publish:!1,transitionToStreaming:!1})}if(!this.#S(r))return;let i=t.at(-1);i!==void 0&&this.#D(i);let a=isSettledSessionTail(t);if(this.#l===void 0&&(!a||i?.type===`session.waiting`)){let e=collectPendingAuthorizations(t);a||(this.#g=`streaming`),this.#N();let i=!a;for(;;){for await(let a of n.stream({follow:i?void 0:!1,signal:r.abortController.signal})){if(!this.#S(r))return;if(t.push(a),this.#T(a),updatePendingAuthorizations(e,a),i&&isCurrentTurnBoundaryEvent(a)&&(a.type!==`session.waiting`||e.size===0))break}if(!this.#S(r))return;if(i||isSettledSessionTail(t))break;i=!0}}else this.#g=this.#l===void 0?`ready`:`error`,this.#N();await this.#y(r),this.#S(r)&&(this.#g=this.#l===void 0?`ready`:`error`)}catch(e){if(!this.#S(r))return;isAbortError(e)?this.#g=`ready`:(this.#l=toError(e),this.#g=`error`,this.#s.onError?.(this.#l))}finally{this.#S(r)&&(r.resolveResponse(void 0),this.#o=void 0,this.#s.onSessionChange?.(n.state),this.#N(),this.#s.onFinish?.(this.#h),r.resolveCompletion())}}cancel(){let e=this.#o;return e===void 0?Promise.resolve({status:`no_active_turn`}):e.cancel()}[detachStore](){this.#o?.abortController.abort()}reset(){let e=this.#o;this.#o=void 0,e?.resolveResponse(void 0),e?.resolveCompletion(),e?.abortController.abort(),this.#t||(this.#m=void 0),this.#u=[],this.#a=createEventDeduper(),this.#d=[],this.#f=[],this.#c=this.#r.initial(),this.#l=void 0,this.#g=`ready`,this.#s.onSessionChange?.(this.#m?.state),this.#N()}async#v(e,t){if(t.message===void 0||t.turnPolicy!==`steer`)throw Error(`eve session is already processing a turn. Send a message with turnPolicy: "steer" to guide it at the next boundary.`);let n=await this.#s.prepareSend?.(t)??t;if(assertExclusiveTurnInput(n),n.message===void 0||n.turnPolicy!==`steer`)throw Error(`An in-flight follow-up requires a message with turnPolicy: "steer".`);if(!this.#S(e))return await this.send(n);let r=this.#C(n);r!==void 0&&e.followUpSubmissionIds.add(r),this.#N();let i;i=(async()=>{try{if(await e.response,!this.#S(e)||this.#m===void 0)throw Error(`The active eve turn ended before the follow-up could be sent.`);let{message:t,...r}=n;await this.#m.send(t,r),e.acceptedFollowUps+=1}catch(e){throw this.#O(toError(e),r),this.#N(),e}finally{e.followUpDispatches.delete(i)}})(),e.followUpDispatches.add(i),await i,await e.completion}async#y(e){for(;e.followUpDispatches.size>0;)await Promise.allSettled(e.followUpDispatches);if(!(e.receivedFollowUps>=e.acceptedFollowUps||this.#m===void 0))for await(let t of this.#m.stream({signal:e.abortController.signal})){if(!this.#S(e))return;if(this.#T(t),isCurrentTurnBoundaryEvent(t)){for(;e.followUpDispatches.size>0;)await Promise.allSettled(e.followUpDispatches);if(e.receivedFollowUps>=e.acceptedFollowUps)return}}}async#b(e){if(this.#e===void 0)throw Error(`An external eve session is required before sending.`);if(e.message===void 0)throw Error(`Cannot answer an input request before the session starts.`);let t=await this.#e.sessions.create({...e,message:e.message});return this.#m=t.session,this.#s.onSessionChange?.(t.session.state),this.#N(),t.response}async#x(e){if(this.#m===void 0)return await this.#b(e);if(e.inputResponses===void 0){let{message:t,...n}=e;return await this.#m.send(t,n)}let{inputResponses:t,...n}=e;return await this.#m.respond(t,n)}#S(e){return this.#o===e}#C(e){if(e.message===void 0)return;let t=createSubmissionId(),n={createdAt:Date.now(),id:t,message:summarizeUserContent(e.message)};return this.#d=[...this.#d,n],this.#n&&this.#k({data:{createdAt:n.createdAt,message:n.message,submissionId:n.id},type:`client.message.submitted`}),t}#w(e){e.inputResponses!==void 0&&e.inputResponses.length!==0&&this.#k({data:{createdAt:Date.now(),responses:e.inputResponses},type:`client.input.responded`})}#T(e,t={}){this.#a.admit(e)&&(this.#u=[...this.#u,e],this.#E(e),this.#s.onEvent?.(e),(t.transitionToStreaming??!0)&&(this.#g=`streaming`),this.#D(e),(t.publish??!0)&&this.#N())}#E(e){let t=this.#d[0];if(e.type===`message.received`&&t!==void 0){let n=t.id;this.#o?.followUpSubmissionIds.delete(n)&&(this.#o.receivedFollowUps+=1),this.#d=this.#d.slice(1),this.#A(e=>e.type===`client.message.submitted`&&e.data.submissionId===n,e);return}this.#k(e)}#D(e){let t=toTerminalStreamFailureError(e);t!==void 0&&(this.#g=`error`,this.#O(t),this.#l===void 0&&(this.#l=t,this.#s.onError?.(t)))}#O(e,t){let n=t===void 0?this.#d[0]:this.#d.find(e=>e.id===t);n!==void 0&&(this.#d=this.#d.filter(e=>e.id!==n.id),this.#A(e=>e.type===`client.message.submitted`&&e.data.submissionId===n.id,{data:{createdAt:n.createdAt,error:{message:e.message},message:n.message,submissionId:n.id},type:`client.message.failed`}))}#k(e){this.#f=[...this.#f,e],this.#c=this.#r.reduce(this.#c,e)}#A(e,t){let n=!1;this.#f=this.#f.map(r=>!n&&e(r)?(n=!0,t):r),n||(this.#f=[...this.#f,t]),this.#c=this.#j(this.#f)}#j(e){let t=this.#r.initial();for(let n of e)t=this.#r.reduce(t,n);return t}#M(){return{data:this.#c,error:this.#l,events:this.#u,session:this.#m?.state,status:this.#g}}#N(){this.#h=this.#M();for(let e of this.#i)e()}};function detachEveAgentStore(e){e[detachStore]()}export{EveAgentStore,detachEveAgentStore};
1
+ import{toError}from"#shared/errors.js";import{createEventDeduper}from"#protocol/event-dedupe.js";import{isCurrentTurnBoundaryEvent}from"#protocol/message.js";import{updatePendingAuthorizations}from"#client/session-utils.js";import{Client}from"#client/client.js";import{consumeMessageResponse}from"#client/message-response.js";import{SessionEventStream}from"#client/session-event-stream.js";import{EveAgentProjection}from"#client/eve-agent-projection.js";import{assertExclusiveTurnInput,createAbortSignal,createActiveTurn,createSubmissionId,followSteeredTurns,isAbortError,isSettledSessionTail,summarizeUserContent,toTerminalStreamFailureError,waitWithSignal}from"#client/eve-agent-store-helpers.js";const detachStore=Symbol(`detachEveAgentStore`),attachStore=Symbol(`attachEveAgentStore`);var EveAgentStore=class{#e;#t;#n=!1;#r;#i=new Set;#a;#o;#s;#c=new Set;#l=createEventDeduper();#u;#d={};#f;#p;#m=[];#h=0;#g;#_;#v;#y;#b;#x=`ready`;constructor(e){this.#t=e.prewarm??!1,this.#a=e.session!==void 0,this.#e=this.#a?void 0:new Client({auth:e.auth,headers:e.headers,host:e.host??``});let t=[];for(let n of e.initialEvents??[])this.#l.admit(n)&&t.push(n),updatePendingAuthorizations(this.#i,n);this.#p=t,this.#s=new EveAgentProjection(e.reducer,this.#p),this.#o=e.optimistic??!0,this.#y=e.session??(e.initialSession===void 0?void 0:this.#e?.sessions.attach(e.initialSession.sessionId,{streamIndex:e.initialSession.streamIndex})),this.#b=this.#I()}get snapshot(){return this.#b}setCallbacks(e){this.#d=e}subscribe(e){return this.#c.add(e),()=>{this.#c.delete(e)}}prewarm(){if(this.#g!==void 0)return this.#g;if(this.#y!==void 0||this.#a)return Promise.resolve();if(this.#u!==void 0)return this.#u.response.then(e=>{if(e===void 0)throw this.#f??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.#h,n=new AbortController;this.#_=n;let r=(async()=>{try{let r=await e.sessions.create({signal:n.signal});if(t!==this.#h)return;this.#y=r.session,this.#f=void 0,this.#x===`error`&&(this.#x=`ready`),this.#d.onSessionChange?.(r.session.state),this.#L(),this.#E()}catch(e){throw t===this.#h&&this.#u===void 0&&this.#f===void 0&&(this.#f=toError(e),this.#x=`error`,this.#d.onError?.(this.#f),this.#L()),e}})();this.#g=r;let clear=()=>{this.#g===r&&(this.#g=void 0,this.#_=void 0)};return r.then(clear,clear),r}async send(e){return await this.#S(e,this.#d.prepareSend)}async#S(e,t){if(this.#u!==void 0){if(this.#x===`resuming`)throw Error(`eve session is resuming.`);return await this.#w(this.#u,e,t)}let n=createActiveTurn(e=>e.acceptedFollowUps>0&&this.#y!==void 0?this.#y.cancel():e.response.then(e=>e===void 0?{status:`no_active_turn`}:e.cancel()));this.#u=n,this.#f=void 0,this.#x=`submitted`,this.#L();let r;try{let i=await(t===void 0?e:waitWithSignal(Promise.resolve(t(e)),createAbortSignal(e.signal,n.abortController.signal)));if(assertExclusiveTurnInput(i),!this.#k(n))return;this.#A(i),this.#j(i),this.#L();let a={...i,signal:createAbortSignal(i.signal,n.abortController.signal)},o=await this.#T(a),s=o.response;if(r=o.reader,!this.#k(n))return;n.resolveResponse(s);for await(let e of consumeMessageResponse(s,r)){if(!this.#k(n))return;n.receivedFollowUpEvents.delete(e)&&(n.receivedFollowUps+=1)}if(!this.#k(n)||(await followSteeredTurns(n,r,()=>this.#k(n)),!this.#k(n)))return;this.#x=this.#f===void 0?`ready`:`error`}catch(e){if(!this.#k(n))return;if(isAbortError(e))this.#x=`ready`,this.#F(toError(e));else{let t=this.#f!==void 0;this.#f??=toError(e),this.#x=`error`,this.#F(this.#f),t||this.#d.onError?.(this.#f)}}finally{r?.[Symbol.dispose](),this.#O(n)}}resume(){if(this.#v!==void 0)return this.#v;let e=this.#C();this.#v=e;let clear=()=>{this.#v===e&&(this.#v=void 0)};return e.then(clear,clear),e}async#C(){if(this.#x===`resuming`||this.#x===`streaming`||this.#x===`submitted`)throw Error(`eve session is already processing a turn.`);if(this.#y===void 0)throw Error(`An eve session is required before resuming.`);let e=this.#y,t=createActiveTurn(()=>e.cancel());this.#u=t,t.resolveResponse(void 0),this.#f=void 0,this.#x=`resuming`,this.#L();try{let n=this.#E({catchUp:!0,startIndex:this.#p.length===e.state.streamIndex?e.state.streamIndex:0});using r=n.subscribe(t.abortController.signal);if(await n.caughtUp,!this.#k(t))return;r.discard();let i=this.#p.at(-1);if(i!==void 0&&this.#P(i),i!==void 0&&this.#f===void 0&&!isSettledSessionTail(this.#p)){this.#x=`streaming`,this.#L();for await(let e of r){if(!this.#k(t))return;if(t.receivedFollowUpEvents.delete(e)&&(t.receivedFollowUps+=1),isCurrentTurnBoundaryEvent(e)&&this.#i.size===0)break}}await followSteeredTurns(t,r,()=>this.#k(t)),this.#k(t)&&(this.#x=this.#f===void 0?`ready`:`error`)}catch(e){if(!this.#k(t))return;isAbortError(e)?this.#x=`ready`:(this.#f=toError(e),this.#x=`error`,this.#d.onError?.(this.#f))}finally{this.#O(t)}}cancel(){let e=this.#u;return e===void 0?this.#x===`streaming`&&this.#y!==void 0?this.#y.cancel():Promise.resolve({status:`no_active_turn`}):e.cancel()}[attachStore](){this.#n=!0,this.#t&&this.#y===void 0&&this.prewarm().catch(()=>{})}[detachStore](){this.#n=!1,this.#r?.close(),this.#r=void 0,this.#u?.abortController.abort(),this.#D(),this.#v=void 0}reset(){this.#r?.close(),this.#r=void 0,this.#i.clear();let e=this.#u;this.#u=void 0,e?.resolveResponse(void 0),e?.resolveCompletion(),e?.abortController.abort(),this.#D(),this.#v=void 0,this.#a||(this.#y=void 0),this.#p=[],this.#l=createEventDeduper(),this.#m=[],this.#s.reset(),this.#f=void 0,this.#x=`ready`,this.#d.onSessionChange?.(this.#y?.state),this.#L(),this.#t&&this.#n&&this.prewarm().catch(()=>{})}async#w(e,t,n){if(t.message===void 0||t.turnPolicy!==`steer`)throw Error(`eve session is already processing a turn. Send a message with turnPolicy: "steer" to guide it at the next boundary.`);let r=this.#h,i=createAbortSignal(t.signal,e.abortController.signal),a=await waitWithSignal(Promise.resolve(n?.(t)),i)??t;if(r!==this.#h)return;if(assertExclusiveTurnInput(a),a.message===void 0||a.turnPolicy!==`steer`)throw Error(`An in-flight follow-up requires a message with turnPolicy: "steer".`);if(!this.#k(e))return await this.#S(a);let o=this.#A(a);o!==void 0&&e.followUpSubmissionIds.add(o),this.#L(),this.#E({headers:a.headers,streamReconnectPolicy:a.streamReconnectPolicy});let s;s=(async()=>{try{let t=createAbortSignal(a.signal,e.abortController.signal);if(await waitWithSignal(e.response,t),!this.#k(e)||this.#y===void 0)throw Error(`The active eve turn ended before the follow-up could be sent.`);let{message:n,...r}=a;await this.#y.send(n,{...r,signal:t}),e.acceptedFollowUps+=1}catch(t){throw this.#k(e)&&(this.#F(toError(t),o),this.#L()),t}finally{e.followUpDispatches.delete(s)}})(),e.followUpDispatches.add(s),await s,await e.completion}async#T(e){let t={headers:e.headers,streamReconnectPolicy:e.streamReconnectPolicy};if(this.#g!==void 0&&(await waitWithSignal(this.#g.catch(e=>{if(this.#y!==void 0)throw e}),e.signal),e.signal?.throwIfAborted()),this.#y===void 0){if(this.#e===void 0)throw Error(`An external eve session is required before sending.`);if(e.message===void 0)throw Error(`Cannot answer an input request before the session starts.`);let n=await this.#e.sessions.create({...e,message:e.message});return e.signal?.throwIfAborted(),this.#y=n.session,this.#d.onSessionChange?.(n.session.state),this.#L(),{response:n.response,reader:this.#E(t).subscribe(e.signal)}}let n=this.#E(t).subscribe(e.signal);try{if(e.inputResponses===void 0){let{message:t,...r}=e;return{response:await this.#y.send(t,r),reader:n}}let{inputResponses:t,...r}=e;return{response:await this.#y.respond(t,r),reader:n}}catch(e){throw n[Symbol.dispose](),e}}#E(e={}){if(this.#r!==void 0&&!this.#r.ended)return this.#r.setOptions(e),this.#r;if(this.#y===void 0)throw Error(`A session is required before opening its stream.`);let t=this.#y,n=this.#h;return this.#r=new SessionEventStream(t,{...e,onEvent:e=>{n===this.#h&&this.#M(e)},onError:e=>{n===this.#h&&(this.#r=void 0,this.#u===void 0&&(this.#f=toError(e),this.#x=`error`,this.#d.onError?.(this.#f),this.#L()))}}),this.#r}#D(){this.#h+=1,this.#_?.abort(),this.#_=void 0,this.#g=void 0}#O(e){if(this.#k(e)){e.resolveResponse(void 0),this.#u=void 0;try{this.#d.onSessionChange?.(this.#y?.state),this.#L(),this.#d.onFinish?.(this.#b)}finally{e.resolveCompletion()}}}#k(e){return this.#u===e}#A(e){if(e.message===void 0)return;let t=createSubmissionId(),n={createdAt:Date.now(),id:t,message:summarizeUserContent(e.message)};return this.#m=[...this.#m,n],this.#o&&this.#s.append({data:{createdAt:n.createdAt,message:n.message,submissionId:n.id},type:`client.message.submitted`}),t}#j(e){e.inputResponses!==void 0&&e.inputResponses.length!==0&&this.#s.append({data:{createdAt:Date.now(),responses:e.inputResponses},type:`client.input.responded`})}#M(e){if(!this.#l.admit(e))return;let t=this.#x===`streaming`;updatePendingAuthorizations(this.#i,e),this.#p=[...this.#p,e],this.#N(e),this.#d.onEvent?.(e),this.#P(e);let n=isCurrentTurnBoundaryEvent(e)&&this.#i.size===0;this.#x!==`resuming`&&this.#f===void 0&&(`data`in e&&`turnId`in e.data&&(this.#x=`streaming`),this.#u===void 0&&n&&(this.#x=`ready`)),this.#d.onSessionChange?.(this.#y?.state),this.#L(),this.#u===void 0&&t&&n&&this.#d.onFinish?.(this.#b)}#N(e){let t=this.#m[0];if(e.type===`message.received`&&t!==void 0){let n=t.id;this.#u?.followUpSubmissionIds.delete(n)&&this.#u.receivedFollowUpEvents.add(e),this.#m=this.#m.slice(1),this.#s.replace(e=>e.type===`client.message.submitted`&&e.data.submissionId===n,e);return}this.#s.append(e)}#P(e){let t=toTerminalStreamFailureError(e);t!==void 0&&(this.#x=`error`,this.#F(t),this.#f===void 0&&(this.#f=t,this.#d.onError?.(t)))}#F(e,t){let n=t===void 0?this.#m[0]:this.#m.find(e=>e.id===t);n!==void 0&&(this.#m=this.#m.filter(e=>e.id!==n.id),this.#s.replace(e=>e.type===`client.message.submitted`&&e.data.submissionId===n.id,{data:{createdAt:n.createdAt,error:{message:e.message},message:n.message,submissionId:n.id},type:`client.message.failed`}))}#I(){return{data:this.#s.data,error:this.#f,events:this.#p,session:this.#y?.state,status:this.#x}}#L(){this.#b=this.#I();for(let e of this.#c)e()}};function detachEveAgentStore(e){e[detachStore]()}function attachEveAgentStore(e){e[attachStore]()}export{EveAgentStore,attachEveAgentStore,detachEveAgentStore};
@@ -9,9 +9,9 @@ export { defaultMessageReducer } from "#client/message-reducer.js";
9
9
  export { createDataUrlFilePart, createTextWithFileContent } from "#client/file-parts.js";
10
10
  export { MessageResponse } from "#client/message-response.js";
11
11
  export { ClientSession } from "#client/session.js";
12
- export { ClientSessions, type CreatedClientSession } from "#client/sessions.js";
12
+ export { ClientSessions, type CreatedClientSession, type CreatedIdleClientSession, } from "#client/sessions.js";
13
13
  export type { EveAgentStoreCallbacks, EveAgentStoreInit, EveAgentStoreSnapshot, EveAgentStoreStatus, PrepareSend, } from "#client/eve-agent-store.js";
14
- export type { AgentInfoEntry, AgentInfoChannelEntry, AgentInfoChannels, AgentInfoConnectionEntry, AgentInfoDynamicResolverEntry, AgentInfoHookEntry, AgentInfoInstructions, AgentInfoInstructionsEntry, AgentInfoResult, AgentInfoRemoteAgentEntry, AgentInfoSandboxEntry, AgentInfoScheduleEntry, AgentInfoSkillEntry, AgentInfoSource, AgentInfoSubagentEntry, AgentInfoToolEntry, AgentInfoTools, CancelSessionResult, ClearResult, CompactResult, ClientAuth, ClientOptions, ClientRedirectPolicy, HeadersValue, HealthResult, MessageResult, RespondTurnOptions, ResetResult, ResolvedStreamReconnectPolicy, SendTurnInput, SendTurnOptions, SessionSnapshot, ClientSessionState, StreamOptions, StreamReconnectPolicy, StreamReconnectRetryPolicy, TokenValue, } from "#client/types.js";
14
+ export type { AgentInfoEntry, AgentInfoChannelEntry, AgentInfoChannels, AgentInfoConnectionEntry, AgentInfoDynamicResolverEntry, AgentInfoHookEntry, AgentInfoInstructions, AgentInfoInstructionsEntry, AgentInfoResult, AgentInfoRemoteAgentEntry, AgentInfoSandboxEntry, AgentInfoScheduleEntry, AgentInfoSkillEntry, AgentInfoSource, AgentInfoSubagentEntry, AgentInfoToolEntry, AgentInfoTools, CancelSessionResult, ClearResult, CompactResult, ClientAuth, ClientOptions, ClientRedirectPolicy, CreateSessionOptions, HeadersValue, HealthResult, MessageResult, RespondTurnOptions, ResetResult, ResolvedStreamReconnectPolicy, SendTurnInput, SendTurnOptions, SessionSnapshot, ClientSessionState, StreamOptions, StreamReconnectPolicy, StreamReconnectRetryPolicy, TokenValue, } from "#client/types.js";
15
15
  export type { EveAgentReducer, EveAgentReducerEvent, ClientInputRespondedEvent, ClientMessageFailedEvent, ClientMessageSubmittedEvent, } from "#client/reducer.js";
16
16
  export type { EveAuthorizationChallenge, EveAuthorizationOutcome, EveAuthorizationPart, EveMessageData, EveDynamicToolPart, EveMessageInputRequest, EveMessage, EveMessageMetadata, EveMessagePart, EveMessageToolMetadata, } from "#client/message-reducer.js";
17
17
  export type { ActionPartialStreamEvent, ActionResultStreamEvent, ActionsRequestedStreamEvent, AssistantStepFinishReason, AuthorizationOutcome, CompactionCompletedStreamEvent, CompactionRequestedStreamEvent, AuthorizationCompletedStreamEvent, ConnectionAuthorizationOutcome, AuthorizationRequiredStreamEvent, HandleMessageStreamEvent, MessageStreamEventMeta, InputResolution, InputResolutionOutcome, InputResolvedStreamEvent, InputRequestedStreamEvent, MessageAppendedStreamEvent, MessageCompletedStreamEvent, MessageReceivedPart, MessageReceivedStreamEvent, ReasoningAppendedStreamEvent, ReasoningCompletedStreamEvent, ResultCompletedStreamEvent, RuntimeTraceContext, SessionCompletedStreamEvent, SessionFailedStreamEvent, SessionStartedStreamEvent, SessionWaitingStreamEvent, MessageStreamEvent, StepCompletedStreamEvent, StepFailedStreamEvent, StepStartedStreamEvent, SubagentCalledStreamEvent, SubagentChildEventStreamEvent, SubagentCompletedStreamEvent, SubagentStartedStreamEvent, TurnCancelledStreamEvent, TurnCompletedStreamEvent, TurnFailedStreamEvent, TurnStartedStreamEvent, TurnFailureStreamEvent, } from "#protocol/message.js";
@@ -1 +1 @@
1
- import{inputOptionSchema,inputRequestKindSchema,inputRequestSchema,inputResponseSchema,isInputRequest,isInputResponse,parseInputResponse,parseInputResponses}from"#shared/input.js";import{isCurrentTurnBoundaryEvent,isTurnFailureEvent}from"#protocol/message.js";import{AgentInfoResponseError}from"#client/agent-info-error.js";import{HealthResponseError}from"#client/health-response-error.js";import{HealthResultSchema}from"#client/health-schema.js";import{AgentInfoResultSchema}from"#client/agent-info-schema.js";import{ClientError}from"#client/client-error.js";import{ClientSessions}from"#client/sessions.js";import{Client}from"#client/client.js";import{EveAgentStore}from"#client/eve-agent-store.js";import{defaultMessageReducer}from"#client/message-reducer.js";import{createDataUrlFilePart,createTextWithFileContent}from"#client/file-parts.js";import{MessageResponse}from"#client/message-response.js";import{ClientSession}from"#client/session.js";import{resolveTextToResponse,resolveTextToResponses}from"#channel/resolve-text.js";export{AgentInfoResponseError,AgentInfoResultSchema,Client,ClientError,ClientSession,ClientSessions,EveAgentStore,HealthResponseError,HealthResultSchema,MessageResponse,createDataUrlFilePart,createTextWithFileContent,defaultMessageReducer,inputOptionSchema,inputRequestKindSchema,inputRequestSchema,inputResponseSchema,isCurrentTurnBoundaryEvent,isInputRequest,isInputResponse,isTurnFailureEvent,parseInputResponse,parseInputResponses,resolveTextToResponse,resolveTextToResponses};
1
+ import{inputOptionSchema,inputRequestKindSchema,inputRequestSchema,inputResponseSchema,isInputRequest,isInputResponse,parseInputResponse,parseInputResponses}from"#shared/input.js";import{isCurrentTurnBoundaryEvent,isTurnFailureEvent}from"#protocol/message.js";import{AgentInfoResponseError}from"#client/agent-info-error.js";import{HealthResponseError}from"#client/health-response-error.js";import{HealthResultSchema}from"#client/health-schema.js";import{AgentInfoResultSchema}from"#client/agent-info-schema.js";import{ClientError}from"#client/client-error.js";import{ClientSessions}from"#client/sessions.js";import{Client}from"#client/client.js";import{MessageResponse}from"#client/message-response.js";import{EveAgentStore}from"#client/eve-agent-store.js";import{defaultMessageReducer}from"#client/message-reducer.js";import{createDataUrlFilePart,createTextWithFileContent}from"#client/file-parts.js";import{ClientSession}from"#client/session.js";import{resolveTextToResponse,resolveTextToResponses}from"#channel/resolve-text.js";export{AgentInfoResponseError,AgentInfoResultSchema,Client,ClientError,ClientSession,ClientSessions,EveAgentStore,HealthResponseError,HealthResultSchema,MessageResponse,createDataUrlFilePart,createTextWithFileContent,defaultMessageReducer,inputOptionSchema,inputRequestKindSchema,inputRequestSchema,inputResponseSchema,isCurrentTurnBoundaryEvent,isInputRequest,isInputResponse,isTurnFailureEvent,parseInputResponse,parseInputResponses,resolveTextToResponse,resolveTextToResponses};
@@ -5,9 +5,10 @@ import type { CancelSessionResult, MessageResult } from "#client/types.js";
5
5
  */
6
6
  interface MessageResponseInput {
7
7
  readonly cancelTurn: (turnId: string) => Promise<CancelSessionResult>;
8
- readonly createStream: () => AsyncGenerator<MessageStreamEvent>;
8
+ readonly createStream: (source?: AsyncIterable<MessageStreamEvent>) => AsyncGenerator<MessageStreamEvent>;
9
9
  readonly sessionId: string;
10
10
  }
11
+ declare const consumeResponse: unique symbol;
11
12
  /**
12
13
  * The response from {@link ClientSession.send}.
13
14
  *
@@ -41,5 +42,8 @@ export declare class MessageResponse<TOutput = unknown> implements AsyncIterable
41
42
  * Each response can only be consumed once.
42
43
  */
43
44
  [Symbol.asyncIterator](): AsyncIterator<MessageStreamEvent>;
45
+ [consumeResponse](source?: AsyncIterable<MessageStreamEvent>): AsyncGenerator<MessageStreamEvent>;
44
46
  }
47
+ /** @internal Observe a turn through the frontend's existing session stream. */
48
+ export declare function consumeMessageResponse(response: MessageResponse, source: AsyncIterable<MessageStreamEvent>): AsyncIterable<MessageStreamEvent>;
45
49
  export {};
@@ -1 +1 @@
1
- import{isCurrentTurnBoundaryEvent}from"#protocol/message.js";import{summarizeTurnEvents}from"#client/session-utils.js";import{extractCompletedResult}from"#client/output-schema.js";var MessageResponse=class{sessionId;#e;#t;#n=!1;#r;#i=!1;#a=Promise.withResolvers();constructor(e){this.#e=e.cancelTurn,this.sessionId=e.sessionId,this.#r=e.createStream}cancel(){if(this.#i)return Promise.resolve({status:`no_active_turn`});if(this.#t!==void 0)return this.#t;let e=this.#a.promise.then(e=>e===void 0?{status:`no_active_turn`}:this.#e(e));return this.#t=e,e.catch(()=>{!this.#i&&this.#t===e&&(this.#t=void 0)}),e}async result(){let e=[];for await(let t of this)e.push(t);let t=summarizeTurnEvents(e);return{data:extractCompletedResult(e),events:e,inputRequests:t.inputRequests,message:t.message,sessionId:this.sessionId,status:t.status}}[Symbol.asyncIterator](){if(this.#n)throw Error(`MessageResponse has already been consumed.`);return this.#n=!0,this.#o()}async*#o(){try{for await(let e of this.#r())e.type===`turn.started`?this.#a.resolve(e.data.turnId):isCurrentTurnBoundaryEvent(e)&&(this.#i=!0,this.#a.resolve(void 0)),yield e}finally{this.#a.resolve(void 0)}}};export{MessageResponse};
1
+ import{isCurrentTurnBoundaryEvent}from"#protocol/message.js";import{summarizeTurnEvents}from"#client/session-utils.js";import{extractCompletedResult}from"#client/output-schema.js";const consumeResponse=Symbol(`consumeMessageResponse`);var MessageResponse=class{sessionId;#e;#t;#n=!1;#r;#i=!1;#a=Promise.withResolvers();constructor(e){this.#e=e.cancelTurn,this.sessionId=e.sessionId,this.#r=e.createStream}cancel(){if(this.#i)return Promise.resolve({status:`no_active_turn`});if(this.#t!==void 0)return this.#t;let e=this.#a.promise.then(e=>e===void 0?{status:`no_active_turn`}:this.#e(e));return this.#t=e,e.catch(()=>{!this.#i&&this.#t===e&&(this.#t=void 0)}),e}async result(){let e=[];for await(let t of this)e.push(t);let t=summarizeTurnEvents(e);return{data:extractCompletedResult(e),events:e,inputRequests:t.inputRequests,message:t.message,sessionId:this.sessionId,status:t.status}}[Symbol.asyncIterator](){return this[consumeResponse]()}[consumeResponse](e){if(this.#n)throw Error(`MessageResponse has already been consumed.`);return this.#n=!0,this.#o(e)}async*#o(e){try{for await(let t of this.#r(e))t.type===`turn.started`?this.#a.resolve(t.data.turnId):isCurrentTurnBoundaryEvent(t)&&(this.#i=!0,this.#a.resolve(void 0)),yield t}finally{this.#a.resolve(void 0)}}};function consumeMessageResponse(e,t){return e[consumeResponse](t)}export{MessageResponse,consumeMessageResponse};
@@ -18,5 +18,6 @@ export declare function readNdjsonStream(body: ReadableStream<Uint8Array>, optio
18
18
  readonly controlVersion?: "1";
19
19
  readonly idleTimeoutMs?: number;
20
20
  readonly onLeaseEnded?: () => void;
21
+ readonly signal?: AbortSignal;
21
22
  readonly streamVersion: MessageStreamVersion;
22
23
  }): AsyncGenerator<MessageStreamEvent>;
@@ -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)$/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;try{for(;;){let e=await readWithIdleTimeout(n,t?.idleTimeoutMs);if(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{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)$/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(`
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
- `)}}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{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};
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};
@@ -15,9 +15,12 @@ interface ResolvedStreamReconnectPolicy {
15
15
  * Internal configuration for following a durable event stream.
16
16
  */
17
17
  interface FollowStreamInput {
18
+ /** Called once after consuming the durable tail captured when the connection opens. */
19
+ readonly onCaughtUp?: () => void;
18
20
  readonly host: string;
19
- /** Keep reconnecting after empty streams until the consumer aborts or stops iteration. */
21
+ /** Keep following empty streams unless the caller configures an idle retry limit. */
20
22
  readonly keepAlive?: boolean;
23
+ readonly resolveReconnectPolicy?: () => StreamReconnectPolicy | undefined;
21
24
  readonly streamReconnectPolicy?: StreamReconnectPolicy;
22
25
  /** @internal Test override for reconnecting an open stream that stops producing bytes. */
23
26
  readonly streamReadIdleTimeoutMs?: number;
@@ -1 +1 @@
1
- import{createEveSessionStreamRoutePath}from"#protocol/routes.js";import{EVE_STREAM_CONTROL_VERSION,EVE_STREAM_CONTROL_VERSION_QUERY,EVE_STREAM_TAIL_INDEX_HEADER}from"#protocol/message.js";import{isStreamDisconnectError,readNdjsonStream}from"#client/ndjson.js";import{readMessageStreamVersion}from"#client/stream-version.js";import{ClientError}from"#client/client-error.js";import{createClientUrl}from"#client/url.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){if(e&&`reconnect`in e&&e.reconnect===!1)return NO_STREAM_RECONNECT_POLICY;let t=e;return{retryableErrorStatuses:t?.retryableErrorStatuses?new Set(t.retryableErrorStatuses):DEFAULT_STREAM_RECONNECT_POLICY.retryableErrorStatuses,streamIdleReconnectPolicy:resolveRetryPolicy(t?.streamIdleReconnectPolicy,DEFAULT_STREAM_RECONNECT_POLICY.streamIdleReconnectPolicy),streamOpenReconnectPolicy:resolveRetryPolicy(t?.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 t=resolveStreamReconnectPolicy(e.streamReconnectPolicy),n=t.streamIdleReconnectPolicy,r=e.startIndex,i=n.baseDelayMs,a=0,o=!0,s;for(;;){let c;try{c=await openStreamBody({...e,retryPolicy:t,startIndex:r,requestTailIndex:e.follow===!1&&s===void 0})}catch(t){if(e.signal?.aborted)return;throw t}if(e.follow===!1&&s===void 0&&(s=c.tailIndex,s===void 0))throw c.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(s!==void 0&&r>s){c.close();return}let l=!1,u=!1;try{for await(let t of readNdjsonStream(c.body,{controlVersion:c.controlVersion,idleTimeoutMs:e.streamReadIdleTimeoutMs??15e3,onLeaseEnded:()=>{u=!0},streamVersion:c.streamVersion}))if(r+=1,l=!0,i=n.baseDelayMs,a=0,yield t,s!==void 0&&r>s)return}catch(e){if(!isStreamDisconnectError(e))throw e}finally{c.close()}if(e.signal?.aborted||e.startIndex<0||n.maxAttempts===0)return;if(!u){if(e.keepAlive!==!0&&!l&&!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),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`);for(let l=0;l<n.maxAttempts;l+=1){let u=createClientUrl(e.host,createEveSessionStreamRoutePath(e.sessionId),Object.keys(c).length>0?c:void 0),d=await e.resolveHeaders(),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)}}if(r=m.status,i=await m.text(),a=m.headers,!t.retryableErrorStatuses.has(m.status))throw new ClientError(m.status,i,m.headers);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{createEveSessionStreamRoutePath}from"#protocol/routes.js";import{EVE_STREAM_CONTROL_VERSION,EVE_STREAM_CONTROL_VERSION_QUERY,EVE_STREAM_TAIL_INDEX_HEADER}from"#protocol/message.js";import{isStreamDisconnectError,readNdjsonStream}from"#client/ndjson.js";import{readMessageStreamVersion}from"#client/stream-version.js";import{ClientError}from"#client/client-error.js";import{createClientUrl}from"#client/url.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?.()),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`);for(let l=0;l<n.maxAttempts;l+=1){e.signal?.throwIfAborted();let u=createClientUrl(e.host,createEveSessionStreamRoutePath(e.sessionId),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)}}if(r=m.status,i=await m.text(),a=m.headers,!t.retryableErrorStatuses.has(m.status))throw new ClientError(m.status,i,m.headers);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};
@@ -0,0 +1,30 @@
1
+ import { type ClientSession } from "#client/session.js";
2
+ import type { MessageStreamEvent } from "#protocol/message.js";
3
+ import type { StreamOptions } from "#client/types.js";
4
+ export interface SessionEventStreamOptions {
5
+ readonly startIndex?: number;
6
+ readonly catchUp?: boolean;
7
+ readonly headers?: Readonly<Record<string, string>>;
8
+ readonly streamReconnectPolicy?: StreamOptions["streamReconnectPolicy"];
9
+ readonly onEvent: (event: MessageStreamEvent) => void;
10
+ readonly onError: (error: unknown) => void;
11
+ }
12
+ /** One transport, with short-lived readers for catch-up and turn completion. */
13
+ export declare class SessionEventStream {
14
+ #private;
15
+ readonly caughtUp: Promise<void>;
16
+ constructor(session: ClientSession, options: SessionEventStreamOptions);
17
+ subscribe(signal?: AbortSignal): SessionEventReader;
18
+ get ended(): boolean;
19
+ setOptions(options: Pick<SessionEventStreamOptions, "headers" | "streamReconnectPolicy">): void;
20
+ close(): void;
21
+ }
22
+ export declare class SessionEventReader implements AsyncIterable<MessageStreamEvent>, Disposable {
23
+ #private;
24
+ constructor(unsubscribe: () => void, signal?: AbortSignal);
25
+ push(event: MessageStreamEvent): void;
26
+ end(error?: unknown): void;
27
+ [Symbol.dispose](): void;
28
+ discard(): void;
29
+ [Symbol.asyncIterator](): AsyncGenerator<MessageStreamEvent>;
30
+ }
@@ -0,0 +1 @@
1
+ import{followClientSession}from"#client/session.js";var SessionEventStream=class{#e=new AbortController;#t=new Set;#n=Promise.withResolvers();caughtUp=this.#n.promise;#r=!1;#i;#a;#o;constructor(e,t){this.setOptions(t),this.caughtUp.catch(()=>{}),t.catchUp||this.#n.resolve(),(async()=>{try{for await(let n of followClientSession(e,{signal:this.#e.signal,resolveHeaders:()=>this.#a,resolveReconnectPolicy:()=>this.#o,startIndex:t.startIndex,onCaughtUp:t.catchUp?()=>this.#n.resolve():void 0})){if(this.#e.signal.aborted)return;t.onEvent(n);for(let e of this.#t)e.push(n);if(n.type===`session.completed`||n.type===`session.failed`)break}this.#n.resolve(),this.#s()}catch(e){this.#n.reject(e),this.#s(e),this.#e.signal.aborted||t.onError(e)}})()}subscribe(e){let t=new SessionEventReader(()=>this.#t.delete(t),e);return this.#r?t.end(this.#i):this.#t.add(t),t}get ended(){return this.#r}setOptions(e){`headers`in e&&(this.#a=e.headers),`streamReconnectPolicy`in e&&(this.#o=e.streamReconnectPolicy)}close(){let e=new DOMException(`Session stream was detached.`,`AbortError`);this.#e.abort(e),this.#n.reject(e),this.#s(e)}#s(e){if(!this.#r){this.#r=!0,this.#i=e;for(let t of this.#t)t.end(e)}}},SessionEventReader=class{#e=[];#t=Promise.withResolvers();#n=!1;#r;#i;constructor(e,t){let abort=()=>this.end(t?.reason);t?.addEventListener(`abort`,abort,{once:!0}),this.#i=()=>{t?.removeEventListener(`abort`,abort),e()},t?.aborted&&abort()}push(e){this.#n||(this.#e.push(e),this.#t.resolve())}end(e){this.#n||(this.#n=!0,this.#r=e,this.#t.resolve())}[Symbol.dispose](){this.end(),this.#e=[],this.#i()}discard(){this.#e=[]}async*[Symbol.asyncIterator](){for(;;){for(;this.#e.length>0;)yield this.#e.shift();if(this.#n){if(this.#r!==void 0)throw this.#r;return}this.#t=Promise.withResolvers(),await this.#t.promise}}};export{SessionEventReader,SessionEventStream};
@@ -1,4 +1,4 @@
1
- import type { AuthorizationRequiredStreamEvent, TurnFailureStreamEvent, UnstampedMessageStreamEvent } from "#protocol/message.js";
1
+ import type { AuthorizationRequiredStreamEvent, MessageStreamEvent, TurnFailureStreamEvent, UnstampedMessageStreamEvent } from "#protocol/message.js";
2
2
  import type { InputRequest } from "#shared/input.js";
3
3
  /** A connection authorization challenge that remains unresolved at a turn boundary. */
4
4
  export interface PendingAuthorization {
@@ -20,3 +20,4 @@ export interface TurnEventSummary {
20
20
  export declare function summarizeTurnEvents(events: readonly UnstampedMessageStreamEvent[]): TurnEventSummary;
21
21
  /** Collects one segment of an event stream through its current-turn boundary. */
22
22
  export declare function collectTurnEvents(stream: AsyncIterable<UnstampedMessageStreamEvent>): Promise<readonly UnstampedMessageStreamEvent[]>;
23
+ export declare function updatePendingAuthorizations(pending: Set<string>, event: MessageStreamEvent): void;
@@ -1 +1 @@
1
- import{isCurrentTurnBoundaryEvent,isTurnFailureEvent}from"#protocol/message.js";function summarizeTurnEvents(e){let t,n,r,i=[],a=new Map;for(let o of e)isCurrentTurnBoundaryEvent(o)&&(t=o),isTurnFailureEvent(o)&&(n=o),isFinalMessageCompleted(o)&&(r=o.data.message??void 0),o.type===`input.requested`&&i.push(...o.data.requests),o.type===`authorization.required`&&a.set(o.data.name,o.data),o.type===`authorization.completed`&&a.delete(o.data.name);return{boundary:t,failure:n,inputRequests:i,message:r,pendingAuthorizations:[...a.values()],status:t?.type===`session.waiting`?`waiting`:t?.type===`session.failed`?`failed`:`completed`}}async function collectTurnEvents(e){let t=[];for await(let n of e)if(t.push(n),isCurrentTurnBoundaryEvent(n))break;return t}function isFinalMessageCompleted(e){return e.type===`message.completed`&&e.data.finishReason!==`tool-calls`}export{collectTurnEvents,summarizeTurnEvents};
1
+ import{isCurrentTurnBoundaryEvent,isTurnFailureEvent}from"#protocol/message.js";function summarizeTurnEvents(e){let t,n,r,i=[],a=new Map;for(let o of e)isCurrentTurnBoundaryEvent(o)&&(t=o),isTurnFailureEvent(o)&&(n=o),isFinalMessageCompleted(o)&&(r=o.data.message??void 0),o.type===`input.requested`&&i.push(...o.data.requests),o.type===`authorization.required`&&a.set(o.data.name,o.data),o.type===`authorization.completed`&&a.delete(o.data.name);return{boundary:t,failure:n,inputRequests:i,message:r,pendingAuthorizations:[...a.values()],status:t?.type===`session.waiting`?`waiting`:t?.type===`session.failed`?`failed`:`completed`}}async function collectTurnEvents(e){let t=[];for await(let n of e)if(t.push(n),isCurrentTurnBoundaryEvent(n))break;return t}function isFinalMessageCompleted(e){return e.type===`message.completed`&&e.data.finishReason!==`tool-calls`}function updatePendingAuthorizations(e,t){t.type===`authorization.required`&&t.data.webhookUrl!==void 0?e.add(t.data.name):t.type===`authorization.completed`&&e.delete(t.data.name)}export{collectTurnEvents,summarizeTurnEvents,updatePendingAuthorizations};
@@ -1,7 +1,14 @@
1
1
  import type { MessageStreamEvent } from "#protocol/message.js";
2
2
  import { MessageResponse } from "#client/message-response.js";
3
3
  import type { InputResponse } from "#shared/input.js";
4
- import type { CancelSessionResult, ClearResult, ClientSessionState, CompactResult, ClientRedirectPolicy, RespondTurnOptions, ResetResult, SendTurnInput, SendTurnOptions, SessionSnapshot, StreamOptions } from "#client/types.js";
4
+ import type { CancelSessionResult, ClearResult, ClientSessionState, CompactResult, ClientRedirectPolicy, CreateSessionOptions, RespondTurnOptions, ResetResult, SendTurnInput, SendTurnOptions, SessionSnapshot, StreamOptions } from "#client/types.js";
5
+ declare const followSession: unique symbol;
6
+ interface FollowSessionOptions extends StreamOptions {
7
+ readonly headers?: Readonly<Record<string, string>>;
8
+ readonly onCaughtUp?: () => void;
9
+ readonly resolveReconnectPolicy?: () => StreamOptions["streamReconnectPolicy"];
10
+ readonly resolveHeaders?: () => Readonly<Record<string, string>> | undefined;
11
+ }
5
12
  /**
6
13
  * Internal interface that a {@link ClientSession} uses to access client-level
7
14
  * configuration without depending on the full {@link Client} class.
@@ -21,6 +28,8 @@ export declare class ClientSession {
21
28
  readonly response: MessageResponse<TOutput>;
22
29
  readonly session: ClientSession;
23
30
  }>;
31
+ /** @internal */
32
+ static prewarm(context: ClientSessionContext, options?: CreateSessionOptions): Promise<ClientSession>;
24
33
  /** Current fixed session identity and durable stream cursor. */
25
34
  get state(): ClientSessionState;
26
35
  /** Reads a finite prefix through the durable tail without advancing this handle. */
@@ -48,4 +57,8 @@ export declare class ClientSession {
48
57
  }): Promise<ResetResult>;
49
58
  /** Opens this session's durable event stream from its stored cursor. */
50
59
  stream(options?: StreamOptions): AsyncIterable<MessageStreamEvent>;
60
+ [followSession](options: FollowSessionOptions): AsyncIterable<MessageStreamEvent>;
51
61
  }
62
+ /** @internal Follow continuously while the frontend owns the session. */
63
+ export declare function followClientSession(session: ClientSession, options: FollowSessionOptions): AsyncIterable<MessageStreamEvent>;
64
+ export {};
@@ -1 +1 @@
1
- import{EVE_SESSION_ROUTE_PATH,createEveSessionRoutePath}from"#protocol/routes.js";import{EVE_SESSION_ID_HEADER,isCurrentTurnBoundaryEvent}from"#protocol/message.js";import{ClientError}from"#client/client-error.js";import{createClientUrl}from"#client/url.js";import{MessageResponse}from"#client/message-response.js";import{followStreamIterable,sleep}from"#client/open-stream.js";import{cancelClientSession,clearClientSession,compactClientSession,resetClientSession}from"#client/session-controls.js";import{serializeOutputSchema}from"#tools/schema.js";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),{sessionId:r}=await readAcceptedMessage(n),i=new ClientSession(e,{sessionId:r,streamIndex:0});return{response:i.#r(n,t,0),session:i}}get state(){return this.#t}async snapshot(e){e?.signal?.throwIfAborted();let t=[];for await(let n of this.#o({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)}#r(e,t,n,r){return e.body?.cancel().catch(()=>{}),new MessageResponse({cancelTurn:async e=>await this.cancel({turnId:e}),createStream:()=>this.#i(n,t,r),sessionId:this.#t.sessionId})}async*#i(e,t,n){let r=0,i=n===void 0,a=!1,o=new Set;try{for await(let s of this.#o({headers:t.headers,keepAlive:shouldKeepActiveTurnAlive(t.streamReconnectPolicy),signal:t.signal,startIndex:e,streamReconnectPolicy:t.streamReconnectPolicy})){if(r+=1,n!==void 0){let e=s.meta?.deliveryIds?.includes(n)===!0,t=s.type===`session.failed`||s.type===`session.completed`;if(!e&&t&&(!i||s.type===`session.completed`))throw Error(`The session ended before the accepted message reached its turn boundary.`);if(!i&&!e||!t&&s.meta?.deliveryIds!==void 0&&!e)continue;i=!0}if(s.type===`authorization.required`&&s.data.webhookUrl!==void 0?o.add(s.data.name):s.type===`authorization.completed`&&o.delete(s.data.name),a=isCurrentTurnBoundaryEvent(s)&&(s.type!==`session.waiting`||o.size===0),yield s,a)break}if(n!==void 0&&!a&&!t.signal?.aborted)throw Error(`The response stream ended before the accepted message reached its turn boundary.`)}finally{this.#t={sessionId:this.#t.sessionId,streamIndex:Math.max(this.#t.streamIndex,e+r)}}}async*#a(e){let t=e?.startIndex??this.#t.streamIndex,n=0;try{for await(let r of this.#o({follow:e?.follow,signal:e?.signal,startIndex:t,streamReconnectPolicy:e?.streamReconnectPolicy}))n+=1,yield r}finally{t>=0&&(this.#t={sessionId:this.#t.sessionId,streamIndex:t+n})}}#o(e){return followStreamIterable({follow:e.follow,host:this.#e.host,keepAlive:e.keepAlive,resolveHeaders:()=>this.#e.resolveHeaders(e.headers),redirect:this.#e.redirect,sessionId:this.#t.sessionId,signal:e.signal,startIndex:e.startIndex,streamReconnectPolicy:e.streamReconnectPolicy})}};async function postSessionSend(e,t,n){let r=250;for(let i=0;;i+=1){try{return await postTurn(e,t,n,!1)}catch(e){if(!isSessionNotActive(e)||i>=3)throw e}await sleep(r,n.signal),n.signal?.throwIfAborted(),r*=2}}function isSessionNotActive(e){return e instanceof ClientError&&e.status===409&&e.code===`session_not_active`}function shouldKeepActiveTurnAlive(e){return e&&`reconnect`in e?!1:e?.streamIdleReconnectPolicy?.maxAttempts===void 0}async function postTurn(e,t,n,r){let i=createMessageBody(n,r);if(i===null)throw Error(r?`Creating a session requires a non-empty message.`:`A session turn requires a non-empty message or inputResponses.`);let a=await e.resolveHeaders(n.headers);a.set(`content-type`,`application/json`);let o=await fetch(createClientUrl(e.host,t),{body:JSON.stringify(i),headers:a,method:`POST`,redirect:e.redirect,signal:n.signal??null});if(!o.ok){let e=await o.text();throw new ClientError(o.status,e,o.headers)}return o}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};
1
+ import{EVE_SESSION_ROUTE_PATH,createEveSessionRoutePath}from"#protocol/routes.js";import{EVE_SESSION_ID_HEADER,isCurrentTurnBoundaryEvent}from"#protocol/message.js";import{updatePendingAuthorizations}from"#client/session-utils.js";import{ClientError}from"#client/client-error.js";import{createClientUrl}from"#client/url.js";import{MessageResponse}from"#client/message-response.js";import{followStreamIterable,sleep}from"#client/open-stream.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),{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)}[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),sessionId:this.#t.sessionId})}async*#i(e,t,n,r){let i=0,a=n===void 0,o=!1,s=new Set;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||!t&&c.meta?.deliveryIds!==void 0&&!e)continue;a=!0}if(updatePendingAuthorizations(s,c),o=isCurrentTurnBoundaryEvent(c)&&(c.type!==`session.waiting`||s.size===0),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),redirect:this.#e.redirect,sessionId:this.#t.sessionId,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=await fetch(createClientUrl(e.host,EVE_SESSION_ROUTE_PATH),{headers:n,method:`POST`,redirect:e.redirect,signal:t.signal??null});if(!r.ok){let e=await r.text();throw new ClientError(r.status,e,r.headers)}return r}function isSessionNotReady(e){return e instanceof ClientError&&e.status===409&&e.code===`session_not_ready`}async function postTurn(e,t,n,r){let i=createMessageBody(n,r);if(i===null)throw Error(r?`Creating a session requires a non-empty message.`:`A session turn requires a non-empty message or inputResponses.`);let a=await e.resolveHeaders(n.headers);a.set(`content-type`,`application/json`);let o=await fetch(createClientUrl(e.host,t),{body:JSON.stringify(i),headers:a,method:`POST`,redirect:e.redirect,signal:n.signal??null});if(!o.ok){let e=await o.text();throw new ClientError(o.status,e,o.headers)}return o}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,18 +1,24 @@
1
1
  import { ClientSession, type ClientSessionContext } from "#client/session.js";
2
2
  import type { MessageResponse } from "#client/message-response.js";
3
- import type { SendTurnInput } from "#client/types.js";
3
+ import type { CreateSessionOptions, SendTurnInput } from "#client/types.js";
4
4
  /** Result of explicitly creating an ID-addressed client session. */
5
5
  export interface CreatedClientSession<TOutput = unknown> {
6
6
  readonly response: MessageResponse<TOutput>;
7
7
  readonly session: ClientSession;
8
8
  }
9
+ /** Result of creating a session before its first turn. */
10
+ export interface CreatedIdleClientSession {
11
+ readonly session: ClientSession;
12
+ }
9
13
  /** Collection surface for explicitly creating or attaching ID-addressed sessions. */
10
14
  export declare class ClientSessions {
11
15
  #private;
12
16
  /** @internal */
13
17
  constructor(context: ClientSessionContext);
14
- /** Creates a session immediately and returns its fixed handle plus first-turn response. */
18
+ /** Creates a session and starts its first turn with a message. */
15
19
  create<TOutput = unknown>(input: SendTurnInput<TOutput>): Promise<CreatedClientSession<TOutput>>;
20
+ /** Creates a conversation session before its first turn. */
21
+ create(options?: CreateSessionOptions): Promise<CreatedIdleClientSession>;
16
22
  /** Attaches a fixed handle to a known session ID without performing I/O. */
17
23
  attach(sessionId: string, options?: {
18
24
  readonly streamIndex?: number;
@@ -1 +1 @@
1
- import{ClientSession}from"#client/session.js";var ClientSessions=class{#e;constructor(e){this.#e=e}async create(e){return await ClientSession.create(this.#e,e)}attach(e,t){if(e.length===0)throw Error(`sessionId must be a non-empty string.`);return new ClientSession(this.#e,{sessionId:e,streamIndex:t?.streamIndex??0})}};export{ClientSessions};
1
+ import{ClientSession}from"#client/session.js";var ClientSessions=class{#e;constructor(e){this.#e=e}async create(e={}){return`message`in e?await ClientSession.create(this.#e,e):{session:await ClientSession.prewarm(this.#e,e)}}attach(e,t){if(e.length===0)throw Error(`sessionId must be a non-empty string.`);return new ClientSession(this.#e,{sessionId:e,streamIndex:t?.streamIndex??0})}};export{ClientSessions};
@@ -79,6 +79,13 @@ export interface ClientOptions {
79
79
  export interface SendTurnInput<TOutput = unknown> extends SendTurnOptions<TOutput> {
80
80
  readonly message: string | UserContent;
81
81
  }
82
+ /** Request options for creating a conversation session before its first turn. */
83
+ export interface CreateSessionOptions {
84
+ /** Abort signal for cancelling the creation request. */
85
+ readonly signal?: AbortSignal;
86
+ /** Additional headers for this request only. */
87
+ readonly headers?: Readonly<Record<string, string>>;
88
+ }
82
89
  /** Options shared by message sends and HITL responses on a client session. */
83
90
  export interface SendTurnOptions<TOutput = unknown> {
84
91
  /** Policy for a message sent while the fixed session has an active turn. */
@@ -44,8 +44,7 @@
44
44
  "@vercel/detect-agent": "1.2.3",
45
45
  "@vercel/oidc": "3.8.0",
46
46
  "@vercel/otel": "2.1.3",
47
- "@vercel/sandbox": "3.2.1",
48
- "@vercel/sandbox-drives": "3.1.0-beta.1",
47
+ "@vercel/sandbox": "3.3.0",
49
48
  "@workflow/builders": "5.0.0-beta.51",
50
49
  "@workflow/core": "5.0.0-beta.51",
51
50
  "@workflow/errors": "5.0.0-beta.21",
@@ -56,7 +55,7 @@
56
55
  "zod": "4.5.4",
57
56
  "zod-validation-error": "5.0.0"
58
57
  },
59
- "scriptHash": "d77af9eb81d59133c8066caa8206a784456f0e037becd27d747830790d234db9",
58
+ "scriptHash": "bf3af03f41372514ffee7f792bcddc6a06f970857bd2d3133f31dc238d9811ea",
60
59
  "toolVersions": {
61
60
  "rolldown": "1.2.7",
62
61
  "typescript": "7.0.2"