@superdurable/dex-agents 0.0.0-stage → 0.2.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 (171) hide show
  1. package/LICENSE +105 -0
  2. package/README.md +1981 -2
  3. package/dist/src/agent-built-in-tools.d.ts +81 -0
  4. package/dist/src/agent-built-in-tools.js +246 -0
  5. package/dist/src/agent-built-in-tools.js.map +1 -0
  6. package/dist/src/agent-context-compaction.d.ts +108 -0
  7. package/dist/src/agent-context-compaction.js +39 -0
  8. package/dist/src/agent-context-compaction.js.map +1 -0
  9. package/dist/src/agent-event-writer.d.ts +26 -0
  10. package/dist/src/agent-event-writer.js +110 -0
  11. package/dist/src/agent-event-writer.js.map +1 -0
  12. package/dist/src/agent-framework-runner.d.ts +808 -0
  13. package/dist/src/agent-framework-runner.js +82 -0
  14. package/dist/src/agent-framework-runner.js.map +1 -0
  15. package/dist/src/agent-plans.d.ts +48 -0
  16. package/dist/src/agent-plans.js +86 -0
  17. package/dist/src/agent-plans.js.map +1 -0
  18. package/dist/src/agent-session-cancellation-steps.d.ts +28 -0
  19. package/dist/src/agent-session-cancellation-steps.js +154 -0
  20. package/dist/src/agent-session-cancellation-steps.js.map +1 -0
  21. package/dist/src/agent-session-codecs.d.ts +105 -0
  22. package/dist/src/agent-session-codecs.js +689 -0
  23. package/dist/src/agent-session-codecs.js.map +1 -0
  24. package/dist/src/agent-session-flow.d.ts +416 -0
  25. package/dist/src/agent-session-flow.js +623 -0
  26. package/dist/src/agent-session-flow.js.map +1 -0
  27. package/dist/src/agent-session-persistence.d.ts +133 -0
  28. package/dist/src/agent-session-persistence.js +74 -0
  29. package/dist/src/agent-session-persistence.js.map +1 -0
  30. package/dist/src/agent-session-settings.d.ts +58 -0
  31. package/dist/src/agent-session-settings.js +81 -0
  32. package/dist/src/agent-session-settings.js.map +1 -0
  33. package/dist/src/agent-session-step-options.d.ts +27 -0
  34. package/dist/src/agent-session-step-options.js +39 -0
  35. package/dist/src/agent-session-step-options.js.map +1 -0
  36. package/dist/src/agent-session-step-types.d.ts +20 -0
  37. package/dist/src/agent-session-step-types.js +28 -0
  38. package/dist/src/agent-session-step-types.js.map +1 -0
  39. package/dist/src/agent-session-steps.d.ts +179 -0
  40. package/dist/src/agent-session-steps.js +1272 -0
  41. package/dist/src/agent-session-steps.js.map +1 -0
  42. package/dist/src/agent-session-tracer.d.ts +61 -0
  43. package/dist/src/agent-session-tracer.js +608 -0
  44. package/dist/src/agent-session-tracer.js.map +1 -0
  45. package/dist/src/agent-session-transitions.d.ts +224 -0
  46. package/dist/src/agent-session-transitions.js +850 -0
  47. package/dist/src/agent-session-transitions.js.map +1 -0
  48. package/dist/src/agent-session-values.d.ts +998 -0
  49. package/dist/src/agent-session-values.js +162 -0
  50. package/dist/src/agent-session-values.js.map +1 -0
  51. package/dist/src/agent-session-wait-steps.d.ts +53 -0
  52. package/dist/src/agent-session-wait-steps.js +389 -0
  53. package/dist/src/agent-session-wait-steps.js.map +1 -0
  54. package/dist/src/agent-tracing-options.d.ts +107 -0
  55. package/dist/src/agent-tracing-options.js +20 -0
  56. package/dist/src/agent-tracing-options.js.map +1 -0
  57. package/dist/src/ai-sdk/ai-sdk-model-client.d.ts +40 -0
  58. package/dist/src/ai-sdk/ai-sdk-model-client.js +235 -0
  59. package/dist/src/ai-sdk/ai-sdk-model-client.js.map +1 -0
  60. package/dist/src/ai-sdk/index.d.ts +1 -0
  61. package/dist/src/ai-sdk/index.js +9 -0
  62. package/dist/src/ai-sdk/index.js.map +1 -0
  63. package/dist/src/index.d.ts +10 -0
  64. package/dist/src/index.js +17 -0
  65. package/dist/src/index.js.map +1 -0
  66. package/dist/src/mcp/index.d.ts +3 -0
  67. package/dist/src/mcp/index.js +10 -0
  68. package/dist/src/mcp/index.js.map +1 -0
  69. package/dist/src/mcp/mcp-resource-and-prompt-tools.d.ts +29 -0
  70. package/dist/src/mcp/mcp-resource-and-prompt-tools.js +185 -0
  71. package/dist/src/mcp/mcp-resource-and-prompt-tools.js.map +1 -0
  72. package/dist/src/mcp/mcp-server-config.d.ts +86 -0
  73. package/dist/src/mcp/mcp-server-config.js +38 -0
  74. package/dist/src/mcp/mcp-server-config.js.map +1 -0
  75. package/dist/src/mcp/mcp-tool-source.d.ts +470 -0
  76. package/dist/src/mcp/mcp-tool-source.js +1204 -0
  77. package/dist/src/mcp/mcp-tool-source.js.map +1 -0
  78. package/dist/src/stepwise/agent-definition.d.ts +158 -0
  79. package/dist/src/stepwise/agent-definition.js +9 -0
  80. package/dist/src/stepwise/agent-definition.js.map +1 -0
  81. package/dist/src/stepwise/function-tool.d.ts +130 -0
  82. package/dist/src/stepwise/function-tool.js +75 -0
  83. package/dist/src/stepwise/function-tool.js.map +1 -0
  84. package/dist/src/stepwise/index.d.ts +7 -0
  85. package/dist/src/stepwise/index.js +12 -0
  86. package/dist/src/stepwise/index.js.map +1 -0
  87. package/dist/src/stepwise/json-schema-validation.d.ts +9 -0
  88. package/dist/src/stepwise/json-schema-validation.js +141 -0
  89. package/dist/src/stepwise/json-schema-validation.js.map +1 -0
  90. package/dist/src/stepwise/model-client.d.ts +194 -0
  91. package/dist/src/stepwise/model-client.js +9 -0
  92. package/dist/src/stepwise/model-client.js.map +1 -0
  93. package/dist/src/stepwise/scripted-model-client.d.ts +99 -0
  94. package/dist/src/stepwise/scripted-model-client.js +156 -0
  95. package/dist/src/stepwise/scripted-model-client.js.map +1 -0
  96. package/dist/src/stepwise/stepwise-agent-runner.d.ts +189 -0
  97. package/dist/src/stepwise/stepwise-agent-runner.js +804 -0
  98. package/dist/src/stepwise/stepwise-agent-runner.js.map +1 -0
  99. package/dist/src/stepwise/stepwise-agent-session-flow.d.ts +35 -0
  100. package/dist/src/stepwise/stepwise-agent-session-flow.js +56 -0
  101. package/dist/src/stepwise/stepwise-agent-session-flow.js.map +1 -0
  102. package/dist/src/stepwise/stepwise-input-items.d.ts +12 -0
  103. package/dist/src/stepwise/stepwise-input-items.js +172 -0
  104. package/dist/src/stepwise/stepwise-input-items.js.map +1 -0
  105. package/dist/src/stepwise/tool-source.d.ts +103 -0
  106. package/dist/src/stepwise/tool-source.js +9 -0
  107. package/dist/src/stepwise/tool-source.js.map +1 -0
  108. package/dist/src/testing/agent-session-test-client.d.ts +205 -0
  109. package/dist/src/testing/agent-session-test-client.js +290 -0
  110. package/dist/src/testing/agent-session-test-client.js.map +1 -0
  111. package/dist/src/testing/agent-test-environment.d.ts +52 -0
  112. package/dist/src/testing/agent-test-environment.js +86 -0
  113. package/dist/src/testing/agent-test-environment.js.map +1 -0
  114. package/dist/src/testing/agent-worker-process.d.ts +91 -0
  115. package/dist/src/testing/agent-worker-process.js +150 -0
  116. package/dist/src/testing/agent-worker-process.js.map +1 -0
  117. package/dist/src/testing/child-process-group.d.ts +33 -0
  118. package/dist/src/testing/child-process-group.js +164 -0
  119. package/dist/src/testing/child-process-group.js.map +1 -0
  120. package/dist/src/testing/coordination.d.ts +99 -0
  121. package/dist/src/testing/coordination.js +155 -0
  122. package/dist/src/testing/coordination.js.map +1 -0
  123. package/dist/src/testing/index.d.ts +8 -0
  124. package/dist/src/testing/index.js +16 -0
  125. package/dist/src/testing/index.js.map +1 -0
  126. package/dist/src/testing/polling.d.ts +31 -0
  127. package/dist/src/testing/polling.js +51 -0
  128. package/dist/src/testing/polling.js.map +1 -0
  129. package/dist/src/testing/private-dex-engine.d.ts +101 -0
  130. package/dist/src/testing/private-dex-engine.js +223 -0
  131. package/dist/src/testing/private-dex-engine.js.map +1 -0
  132. package/dist/src/testing/scripted-model-client.d.ts +1 -0
  133. package/dist/src/testing/scripted-model-client.js +10 -0
  134. package/dist/src/testing/scripted-model-client.js.map +1 -0
  135. package/dist/src/testing/step-history.d.ts +40 -0
  136. package/dist/src/testing/step-history.js +59 -0
  137. package/dist/src/testing/step-history.js.map +1 -0
  138. package/dist/src/ui-stream/agent-event-json.d.ts +30 -0
  139. package/dist/src/ui-stream/agent-event-json.js +64 -0
  140. package/dist/src/ui-stream/agent-event-json.js.map +1 -0
  141. package/dist/src/ui-stream/agent-event-sse.d.ts +154 -0
  142. package/dist/src/ui-stream/agent-event-sse.js +159 -0
  143. package/dist/src/ui-stream/agent-event-sse.js.map +1 -0
  144. package/dist/src/ui-stream/agent-event-stream-positions.d.ts +42 -0
  145. package/dist/src/ui-stream/agent-event-stream-positions.js +153 -0
  146. package/dist/src/ui-stream/agent-event-stream-positions.js.map +1 -0
  147. package/dist/src/ui-stream/agent-session-record-reader.d.ts +72 -0
  148. package/dist/src/ui-stream/agent-session-record-reader.js +241 -0
  149. package/dist/src/ui-stream/agent-session-record-reader.js.map +1 -0
  150. package/dist/src/ui-stream/agent-ui-message-stream-responses.d.ts +219 -0
  151. package/dist/src/ui-stream/agent-ui-message-stream-responses.js +440 -0
  152. package/dist/src/ui-stream/agent-ui-message-stream-responses.js.map +1 -0
  153. package/dist/src/ui-stream/agent-ui-message-stream.d.ts +138 -0
  154. package/dist/src/ui-stream/agent-ui-message-stream.js +681 -0
  155. package/dist/src/ui-stream/agent-ui-message-stream.js.map +1 -0
  156. package/dist/src/ui-stream/agent-ui-message-types.d.ts +238 -0
  157. package/dist/src/ui-stream/agent-ui-message-types.js +57 -0
  158. package/dist/src/ui-stream/agent-ui-message-types.js.map +1 -0
  159. package/dist/src/ui-stream/agent-ui-messages.d.ts +66 -0
  160. package/dist/src/ui-stream/agent-ui-messages.js +220 -0
  161. package/dist/src/ui-stream/agent-ui-messages.js.map +1 -0
  162. package/dist/src/ui-stream/agent-ui-stream-cursor.d.ts +64 -0
  163. package/dist/src/ui-stream/agent-ui-stream-cursor.js +186 -0
  164. package/dist/src/ui-stream/agent-ui-stream-cursor.js.map +1 -0
  165. package/dist/src/ui-stream/index.d.ts +14 -0
  166. package/dist/src/ui-stream/index.js +22 -0
  167. package/dist/src/ui-stream/index.js.map +1 -0
  168. package/dist/src/ui-stream/server-sent-event-responses.d.ts +6 -0
  169. package/dist/src/ui-stream/server-sent-event-responses.js +34 -0
  170. package/dist/src/ui-stream/server-sent-event-responses.js.map +1 -0
  171. package/package.json +86 -4
@@ -0,0 +1,40 @@
1
+ /** History event type of a completed `waitFor` method. */
2
+ export declare const waitForCompletedEvent = "StepWaitForCompleted";
3
+ /** History event type of a completed `execute` method. */
4
+ export declare const executeCompletedEvent = "StepExecuteCompleted";
5
+ /** One completed Step method in a Flow's history, returned by {@link readStepHistory}. */
6
+ export interface StepHistoryEntry {
7
+ /** {@link waitForCompletedEvent} or {@link executeCompletedEvent}. */
8
+ readonly eventType: string;
9
+ /** Step type, such as `"RunModel"`. */
10
+ readonly stepType: string;
11
+ /** Step execution ID, such as `"RunModel-2"`. */
12
+ readonly stepExecutionId: string;
13
+ /** One-based attempt that completed the method. */
14
+ readonly finalAttempt: number;
15
+ }
16
+ /** Options of {@link readStepHistory}. */
17
+ export interface ReadStepHistoryOptions {
18
+ /** Path to `dexcli`. Defaults to the `DEXCLI` environment variable, then `dexcli` on `PATH`. */
19
+ readonly dexcliPath?: string;
20
+ }
21
+ /**
22
+ * Returns every completed Step method of a Flow's current run, in history order.
23
+ *
24
+ * It runs `dexcli flow history --all --output json`, as the Python core's `read_step_history` does. Use
25
+ * it to assert the Step shape of a turn, such as `RunModel`, `CallTool`, `ResumeTurn`, `RunModel`.
26
+ * Steps that are still waiting or running are not included.
27
+ *
28
+ * @example
29
+ * ```ts
30
+ * const executed = (await readStepHistory(engine.serverAddress, sessionId))
31
+ * .filter((entry) => entry.eventType === executeCompletedEvent)
32
+ * .map((entry) => entry.stepType);
33
+ * ```
34
+ * @param serverAddress - Dex Server address.
35
+ * @param flowId - Flow ID to read.
36
+ * @param options - `dexcli` path.
37
+ * @returns One entry per completed `waitFor` or `execute` method.
38
+ * @throws {Error} When `dexcli` fails or prints unexpected JSON.
39
+ */
40
+ export declare function readStepHistory(serverAddress: string, flowId: string, options?: ReadStepHistoryOptions): Promise<StepHistoryEntry[]>;
@@ -0,0 +1,59 @@
1
+ // Copyright (c) 2026 Super Durable, Inc.
2
+ //
3
+ // Licensed under the Sustainable Use License 1.0.
4
+ // You may not use this file except in compliance with the License.
5
+ // See the LICENSE file in the repository root.
6
+ //
7
+ // SPDX-License-Identifier: LicenseRef-Sustainable-Use-1.0
8
+ import { execFile } from "node:child_process";
9
+ import { promisify } from "node:util";
10
+ const execFileAsync = promisify(execFile);
11
+ /** History event type of a completed `waitFor` method. */
12
+ export const waitForCompletedEvent = "StepWaitForCompleted";
13
+ /** History event type of a completed `execute` method. */
14
+ export const executeCompletedEvent = "StepExecuteCompleted";
15
+ /**
16
+ * Returns every completed Step method of a Flow's current run, in history order.
17
+ *
18
+ * It runs `dexcli flow history --all --output json`, as the Python core's `read_step_history` does. Use
19
+ * it to assert the Step shape of a turn, such as `RunModel`, `CallTool`, `ResumeTurn`, `RunModel`.
20
+ * Steps that are still waiting or running are not included.
21
+ *
22
+ * @example
23
+ * ```ts
24
+ * const executed = (await readStepHistory(engine.serverAddress, sessionId))
25
+ * .filter((entry) => entry.eventType === executeCompletedEvent)
26
+ * .map((entry) => entry.stepType);
27
+ * ```
28
+ * @param serverAddress - Dex Server address.
29
+ * @param flowId - Flow ID to read.
30
+ * @param options - `dexcli` path.
31
+ * @returns One entry per completed `waitFor` or `execute` method.
32
+ * @throws {Error} When `dexcli` fails or prints unexpected JSON.
33
+ */
34
+ export async function readStepHistory(serverAddress, flowId, options = {}) {
35
+ const dexcliPath = options.dexcliPath ?? process.env.DEXCLI ?? "dexcli";
36
+ const { stdout } = await execFileAsync(dexcliPath, ["flow", "history", flowId, "--server", serverAddress, "--all", "--output", "json"], { maxBuffer: 64 * 1024 * 1024 });
37
+ const history = JSON.parse(stdout);
38
+ if (!Array.isArray(history.events)) {
39
+ throw new Error(`dexcli flow history printed no events for ${flowId}`);
40
+ }
41
+ const entries = [];
42
+ for (const event of history.events) {
43
+ if (event.type !== waitForCompletedEvent && event.type !== executeCompletedEvent) {
44
+ continue;
45
+ }
46
+ const stepContext = event.payload?.context;
47
+ if (stepContext === undefined) {
48
+ throw new Error(`history event ${event.type} of ${flowId} has no Step context`);
49
+ }
50
+ entries.push({
51
+ eventType: event.type,
52
+ stepType: String(stepContext.stepType),
53
+ stepExecutionId: String(stepContext.stepExecutionId),
54
+ finalAttempt: Number(stepContext.finalAttempt),
55
+ });
56
+ }
57
+ return entries;
58
+ }
59
+ //# sourceMappingURL=step-history.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"step-history.js","sourceRoot":"","sources":["../../../src/testing/step-history.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,EAAE;AACF,kDAAkD;AAClD,mEAAmE;AACnE,+CAA+C;AAC/C,EAAE;AACF,0DAA0D;AAE1D,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,MAAM,aAAa,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AAE1C,0DAA0D;AAC1D,MAAM,CAAC,MAAM,qBAAqB,GAAG,sBAAsB,CAAC;AAC5D,0DAA0D;AAC1D,MAAM,CAAC,MAAM,qBAAqB,GAAG,sBAAsB,CAAC;AAoB5D;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,aAAqB,EACrB,MAAc,EACd,UAAkC,EAAE;IAEpC,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,IAAI,QAAQ,CAAC;IACxE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,aAAa,CACpC,UAAU,EACV,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,aAAa,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,CAAC,EACnF,EAAE,SAAS,EAAE,EAAE,GAAG,IAAI,GAAG,IAAI,EAAE,CAChC,CAAC;IACF,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAyB,CAAC;IAC3D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CAAC,6CAA6C,MAAM,EAAE,CAAC,CAAC;IACzE,CAAC;IACD,MAAM,OAAO,GAAuB,EAAE,CAAC;IACvC,KAAK,MAAM,KAAK,IAAI,OAAO,CAAC,MAAsD,EAAE,CAAC;QACnF,IAAI,KAAK,CAAC,IAAI,KAAK,qBAAqB,IAAI,KAAK,CAAC,IAAI,KAAK,qBAAqB,EAAE,CAAC;YACjF,SAAS;QACX,CAAC;QACD,MAAM,WAAW,GAAI,KAAK,CAAC,OAA6D,EAAE,OAAO,CAAC;QAClG,IAAI,WAAW,KAAK,SAAS,EAAE,CAAC;YAC9B,MAAM,IAAI,KAAK,CAAC,iBAAiB,KAAK,CAAC,IAAI,OAAO,MAAM,sBAAsB,CAAC,CAAC;QAClF,CAAC;QACD,OAAO,CAAC,IAAI,CAAC;YACX,SAAS,EAAE,KAAK,CAAC,IAAI;YACrB,QAAQ,EAAE,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC;YACtC,eAAe,EAAE,MAAM,CAAC,WAAW,CAAC,eAAe,CAAC;YACpD,YAAY,EAAE,MAAM,CAAC,WAAW,CAAC,YAAY,CAAC;SAC/C,CAAC,CAAC;IACL,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,30 @@
1
+ import type { AgentEvent, AgentSnapshot } from "../agent-session-values.js";
2
+ import type { AgentEventJson } from "./agent-ui-message-types.js";
3
+ /**
4
+ * Converts an `AgentEvent` to its snake_case wire JSON, the format of the plain Server-Sent Events stream.
5
+ *
6
+ * @example
7
+ * ```ts
8
+ * const message = await client.readStream(sessionId, flow.agentEvents, resumeToken);
9
+ * response.write(`data: ${JSON.stringify(convertAgentEventToJson(message.value))}\n\n`);
10
+ * ```
11
+ * @param event - Event read from the `AgentEvents` Stream.
12
+ * @returns A new object with `type`, `turn_id`, `attempt`, `step_execution_id`, and `payload` text.
13
+ */
14
+ export declare function convertAgentEventToJson(event: AgentEvent): AgentEventJson;
15
+ /**
16
+ * Converts an `AgentSnapshot` to the snake_case JSON a browser reads, the same JSON the Python core produces.
17
+ *
18
+ * Use it when a browser shared with Python backends reads the snapshot. It is the `get_agent_snapshot` wire
19
+ * format without the fields only the session's Steps use. Messages leave out `framework_item`, the
20
+ * framework's replay data, which can hold the agent's instructions. Tool calls leave out
21
+ * `tool_source_reference`, `trace_context`, `input_continuation`, `input_answers`, and `task_answer_pending`.
22
+ *
23
+ * `session_settings` is included as stored, so the browser sees the settings the next turn starts with. Keep
24
+ * anything a browser must not see out of session settings, or remove the key before serving the JSON.
25
+ *
26
+ * @param snapshot - Output of the `get_agent_snapshot` RPC.
27
+ * @returns A new JSON object with `state`, `messages`, `pending_interrupts`, `tool_calls`, `usage`, and
28
+ * `queued_message_count`.
29
+ */
30
+ export declare function convertAgentSnapshotToJson(snapshot: AgentSnapshot): Readonly<Record<string, unknown>>;
@@ -0,0 +1,64 @@
1
+ // Copyright (c) 2026 Super Durable, Inc.
2
+ //
3
+ // Licensed under the Sustainable Use License 1.0.
4
+ // You may not use this file except in compliance with the License.
5
+ // See the LICENSE file in the repository root.
6
+ //
7
+ // SPDX-License-Identifier: LicenseRef-Sustainable-Use-1.0
8
+ import { encodeAgentSnapshot } from "../agent-session-codecs.js";
9
+ /**
10
+ * Converts an `AgentEvent` to its snake_case wire JSON, the format of the plain Server-Sent Events stream.
11
+ *
12
+ * @example
13
+ * ```ts
14
+ * const message = await client.readStream(sessionId, flow.agentEvents, resumeToken);
15
+ * response.write(`data: ${JSON.stringify(convertAgentEventToJson(message.value))}\n\n`);
16
+ * ```
17
+ * @param event - Event read from the `AgentEvents` Stream.
18
+ * @returns A new object with `type`, `turn_id`, `attempt`, `step_execution_id`, and `payload` text.
19
+ */
20
+ export function convertAgentEventToJson(event) {
21
+ return {
22
+ type: event.type,
23
+ turn_id: event.turnId,
24
+ attempt: event.attempt,
25
+ step_execution_id: event.stepExecutionId,
26
+ payload: event.payload,
27
+ };
28
+ }
29
+ // Replay, routing, tracing, and tool resume state that only the session's Steps read.
30
+ const workerOnlyMessageFieldNames = new Set(["framework_item"]);
31
+ const workerOnlyToolCallFieldNames = new Set([
32
+ "tool_source_reference",
33
+ "trace_context",
34
+ "input_continuation",
35
+ "input_answers",
36
+ "task_answer_pending",
37
+ ]);
38
+ /**
39
+ * Converts an `AgentSnapshot` to the snake_case JSON a browser reads, the same JSON the Python core produces.
40
+ *
41
+ * Use it when a browser shared with Python backends reads the snapshot. It is the `get_agent_snapshot` wire
42
+ * format without the fields only the session's Steps use. Messages leave out `framework_item`, the
43
+ * framework's replay data, which can hold the agent's instructions. Tool calls leave out
44
+ * `tool_source_reference`, `trace_context`, `input_continuation`, `input_answers`, and `task_answer_pending`.
45
+ *
46
+ * `session_settings` is included as stored, so the browser sees the settings the next turn starts with. Keep
47
+ * anything a browser must not see out of session settings, or remove the key before serving the JSON.
48
+ *
49
+ * @param snapshot - Output of the `get_agent_snapshot` RPC.
50
+ * @returns A new JSON object with `state`, `messages`, `pending_interrupts`, `tool_calls`, `usage`, and
51
+ * `queued_message_count`.
52
+ */
53
+ export function convertAgentSnapshotToJson(snapshot) {
54
+ const snapshotJson = encodeAgentSnapshot(snapshot);
55
+ return {
56
+ ...snapshotJson,
57
+ messages: snapshotJson["messages"].map((message) => omitJsonFields(message, workerOnlyMessageFieldNames)),
58
+ tool_calls: snapshotJson["tool_calls"].map((toolCall) => omitJsonFields(toolCall, workerOnlyToolCallFieldNames)),
59
+ };
60
+ }
61
+ function omitJsonFields(value, fieldNames) {
62
+ return Object.fromEntries(Object.entries(value).filter(([fieldName]) => !fieldNames.has(fieldName)));
63
+ }
64
+ //# sourceMappingURL=agent-event-json.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-event-json.js","sourceRoot":"","sources":["../../../src/ui-stream/agent-event-json.ts"],"names":[],"mappings":"AAAA,yCAAyC;AACzC,EAAE;AACF,kDAAkD;AAClD,mEAAmE;AACnE,+CAA+C;AAC/C,EAAE;AACF,0DAA0D;AAE1D,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAIjE;;;;;;;;;;GAUG;AACH,MAAM,UAAU,uBAAuB,CAAC,KAAiB;IACvD,OAAO;QACL,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,OAAO,EAAE,KAAK,CAAC,MAAM;QACrB,OAAO,EAAE,KAAK,CAAC,OAAO;QACtB,iBAAiB,EAAE,KAAK,CAAC,eAAe;QACxC,OAAO,EAAE,KAAK,CAAC,OAAO;KACvB,CAAC;AACJ,CAAC;AAED,sFAAsF;AACtF,MAAM,2BAA2B,GAAwB,IAAI,GAAG,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC;AACrF,MAAM,4BAA4B,GAAwB,IAAI,GAAG,CAAC;IAChE,uBAAuB;IACvB,eAAe;IACf,oBAAoB;IACpB,eAAe;IACf,qBAAqB;CACtB,CAAC,CAAC;AAEH;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,0BAA0B,CAAC,QAAuB;IAChE,MAAM,YAAY,GAAG,mBAAmB,CAAC,QAAQ,CAA4B,CAAC;IAC9E,OAAO;QACL,GAAG,YAAY;QACf,QAAQ,EAAG,YAAY,CAAC,UAAU,CAA+B,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAChF,cAAc,CAAC,OAAO,EAAE,2BAA2B,CAAC,CACrD;QACD,UAAU,EAAG,YAAY,CAAC,YAAY,CAA+B,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CACrF,cAAc,CAAC,QAAQ,EAAE,4BAA4B,CAAC,CACvD;KACF,CAAC;AACJ,CAAC;AAED,SAAS,cAAc,CACrB,KAA8B,EAC9B,UAA+B;IAE/B,OAAO,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AACvG,CAAC"}
@@ -0,0 +1,154 @@
1
+ import type { Client, StreamMessage } from "@superdurable/dex";
2
+ import type { AgentFrameworkRunner, DeferredToolOutcome } from "../agent-framework-runner.js";
3
+ import type { AgentSessionFlow } from "../agent-session-flow.js";
4
+ import type { AgentEvent, AgentSnapshot } from "../agent-session-values.js";
5
+ /** HTTP headers of the plain `AgentEvents` Server-Sent Events response. */
6
+ export declare const agentEventStreamHeaders: Readonly<Record<string, string>>;
7
+ /**
8
+ * Selects the agent session and Stream position of a plain `AgentEvents` Server-Sent Events stream.
9
+ *
10
+ * Pass it to {@link streamAgentEventSseFrames} or {@link createAgentEventSseResponse}.
11
+ */
12
+ export interface AgentEventSseOptions {
13
+ /** Client used for every Stream read. The caller keeps ownership. */
14
+ readonly client: Client;
15
+ /** The agent session Flow, the same object the Worker registered. */
16
+ readonly flow: AgentSessionFlow<AgentFrameworkRunner<DeferredToolOutcome>>;
17
+ /** Session ID: the Flow ID of the agent session. */
18
+ readonly flowId: string;
19
+ /**
20
+ * Dex resume token of the last event the browser received: the `Last-Event-ID` request header, or the
21
+ * `resumeToken` of {@link readAgentEventStreamSnapshot} on the first connection. Omit it, or pass `""`,
22
+ * to start at the oldest retained event.
23
+ */
24
+ readonly resumeToken?: string | undefined;
25
+ /**
26
+ * Long-poll duration of one Stream read, in milliseconds. It must be a whole number of seconds. The
27
+ * stream sends a keep-alive comment after each empty poll. Defaults to 10,000.
28
+ */
29
+ readonly pollTimeoutMs?: number;
30
+ /** Ends the stream before its next Stream read once aborted, such as the request's `signal`. */
31
+ readonly signal?: AbortSignal | undefined;
32
+ }
33
+ /** A session snapshot and the Dex resume token that a plain event stream opened with it starts from. */
34
+ export interface AgentEventStreamSnapshot {
35
+ /** Output of the `get_agent_snapshot` RPC. */
36
+ readonly snapshot: AgentSnapshot;
37
+ /**
38
+ * Dex resume token to open the event stream with. While a turn is active it replays that turn's events
39
+ * from its first retained event; otherwise it starts after the newest event read before the snapshot.
40
+ */
41
+ readonly resumeToken: string;
42
+ }
43
+ /** Snake_case wire JSON of an {@link AgentEventStreamSnapshot}, the same JSON as the Python core. */
44
+ export interface AgentEventStreamSnapshotJson {
45
+ /** The `AgentSnapshot` wire JSON. */
46
+ readonly snapshot: Readonly<Record<string, unknown>>;
47
+ /** Dex resume token to open the event stream with. */
48
+ readonly resume_token: string;
49
+ }
50
+ /**
51
+ * Formats one `AgentEvents` message as a Server-Sent Event whose `id` is its Dex resume token.
52
+ *
53
+ * An `EventSource` sends the `id` back as the `Last-Event-ID` header when it reconnects. The event has no
54
+ * `event:` field, so `EventSource.onmessage` receives every event; switch on `type` in the data.
55
+ *
56
+ * @param message - Message read from the `AgentEvents` Stream.
57
+ * @returns `id: <resume token>`, then `data: <AgentEvent wire JSON>`, then a blank line.
58
+ */
59
+ export declare function formatAgentEventSseFrame(message: StreamMessage<AgentEvent>): string;
60
+ /**
61
+ * Yields an agent session's `AgentEvents` as Server-Sent Event frames, resuming after a Dex resume token.
62
+ *
63
+ * Each event becomes one frame whose `id` is its Dex resume token and whose data is the `AgentEvent` wire
64
+ * JSON: `type`, `turn_id`, `attempt`, `step_execution_id`, and `payload` text. Reconnecting with the last
65
+ * `id` continues with the next event, with no repeated or missing event while the Stream retains them.
66
+ * After each empty long poll it yields a keep-alive comment. The stream never ends on its own; stop
67
+ * iterating, or abort `signal`, when the browser goes away.
68
+ *
69
+ * The browser applies the event rules of the session contract. Within one `step_execution_id` it keeps
70
+ * only the highest `attempt` and drops the partial text of lower attempts. After `turn_completed`,
71
+ * `turn_failed`, `turn_steered`, or `turn_cancelled` it replaces the turn's live text with the stored
72
+ * messages. On every connection, load
73
+ * {@link readAgentEventStreamSnapshot} first and open the stream from its `resumeToken`.
74
+ *
75
+ * @example
76
+ * ```ts
77
+ * for await (const frame of streamAgentEventSseFrames({
78
+ * client, flow, flowId: sessionId, resumeToken: request.headers["last-event-id"] })) {
79
+ * response.write(frame);
80
+ * }
81
+ * ```
82
+ * @param options - Session, start position, and polling.
83
+ * @returns An async generator of SSE frames and keep-alive comments.
84
+ * @throws {RangeError} When `pollTimeoutMs` is not a positive whole number of seconds.
85
+ * @throws {DexServiceError} When a Stream read fails.
86
+ */
87
+ export declare function streamAgentEventSseFrames(options: AgentEventSseOptions): AsyncGenerator<string, void, undefined>;
88
+ /**
89
+ * Returns a streaming `text/event-stream` Response of an agent session's `AgentEvents`.
90
+ *
91
+ * It writes {@link streamAgentEventSseFrames} and stops reading when the browser closes the response.
92
+ * Mount it in any server that returns a Fetch API `Response`. The session ID usually comes from the
93
+ * browser, so the route must check that the caller may read that session.
94
+ *
95
+ * Before it answers 200, it reads once, with a long poll of up to 1 second, to check the resume token.
96
+ * When Dex rejects the token, such as one of another session, it answers 400, which stops an
97
+ * `EventSource` from reconnecting with it; the browser then loads the snapshot again. A token from
98
+ * before a Stream Store restart is accepted and continues at the oldest retained event.
99
+ *
100
+ * @example
101
+ * ```ts
102
+ * // GET /sessions/:id/events
103
+ * export async function GET(request: Request, sessionId: string): Promise<Response> {
104
+ * const url = new URL(request.url);
105
+ * return createAgentEventSseResponse({
106
+ * client, flow, flowId: sessionId,
107
+ * resumeToken: request.headers.get("last-event-id") ?? url.searchParams.get("resumeToken") ?? "",
108
+ * signal: request.signal,
109
+ * });
110
+ * }
111
+ * // In the browser:
112
+ * const { resumeToken } = await (await fetch(`/sessions/${sessionId}/snapshot`)).json();
113
+ * const events = new EventSource(`/sessions/${sessionId}/events?resumeToken=${encodeURIComponent(resumeToken)}`);
114
+ * events.onmessage = (message) => render(JSON.parse(message.data));
115
+ * ```
116
+ * @param options - Session, start position, polling, and extra response headers.
117
+ * @returns A 200 Response with {@link agentEventStreamHeaders} and the application's `headers`; 400 with
118
+ * a text body when Dex rejects the resume token.
119
+ * @throws {RangeError} When `pollTimeoutMs` is not a positive whole number of seconds.
120
+ * @throws {DexServiceError} When the first Stream read fails for another reason.
121
+ */
122
+ export declare function createAgentEventSseResponse(options: AgentEventSseOptions & {
123
+ readonly headers?: Readonly<Record<string, string>>;
124
+ }): Promise<Response>;
125
+ /**
126
+ * Reads the session snapshot together with the Dex resume token to open the plain event stream from.
127
+ *
128
+ * Call it whenever the browser connects or reconnects after a gap. It reads the newest event first and
129
+ * the snapshot second, so events after the token may repeat what the snapshot shows but none is missing.
130
+ * While a turn is active the token replays that turn's events, so the browser can rebuild its live text.
131
+ * The `get_agent_snapshot` RPC needs a running Worker.
132
+ *
133
+ * @example
134
+ * ```ts
135
+ * // GET /sessions/:id/snapshot
136
+ * const value = await readAgentEventStreamSnapshot({ client, flow, flowId: sessionId });
137
+ * return Response.json(convertAgentEventStreamSnapshotToJson(value));
138
+ * ```
139
+ * @param options - Client, Flow, and session ID.
140
+ * @returns The snapshot and the resume token.
141
+ * @throws {DexServiceError} When the Stream read or the RPC fails.
142
+ */
143
+ export declare function readAgentEventStreamSnapshot(options: {
144
+ readonly client: Client;
145
+ readonly flow: AgentSessionFlow<AgentFrameworkRunner<DeferredToolOutcome>>;
146
+ readonly flowId: string;
147
+ }): Promise<AgentEventStreamSnapshot>;
148
+ /**
149
+ * Converts an {@link AgentEventStreamSnapshot} to snake_case wire JSON for an HTTP response.
150
+ *
151
+ * @param value - Snapshot and resume token.
152
+ * @returns `{ snapshot, resume_token }`, with the snapshot in its `AgentSnapshot` wire format.
153
+ */
154
+ export declare function convertAgentEventStreamSnapshotToJson(value: AgentEventStreamSnapshot): AgentEventStreamSnapshotJson;
@@ -0,0 +1,159 @@
1
+ // Copyright (c) 2026 Super Durable, Inc.
2
+ //
3
+ // Licensed under the Sustainable Use License 1.0.
4
+ // You may not use this file except in compliance with the License.
5
+ // See the LICENSE file in the repository root.
6
+ //
7
+ // SPDX-License-Identifier: LicenseRef-Sustainable-Use-1.0
8
+ import { convertAgentEventToJson, convertAgentSnapshotToJson } from "./agent-event-json.js";
9
+ import { findAgentEventResumeTokenBeforeTurn, probeAgentEventResumeToken, readAgentEventsTailResumeToken, readNextAgentEvent, requireAgentEventPollTimeoutMs, } from "./agent-event-stream-positions.js";
10
+ import { createServerSentEventResponse, mergeHeaders, serverSentEventKeepAliveFrame, } from "./server-sent-event-responses.js";
11
+ /** HTTP headers of the plain `AgentEvents` Server-Sent Events response. */
12
+ export const agentEventStreamHeaders = Object.freeze({
13
+ "content-type": "text/event-stream",
14
+ "cache-control": "no-cache",
15
+ connection: "keep-alive",
16
+ "x-accel-buffering": "no",
17
+ });
18
+ /**
19
+ * Formats one `AgentEvents` message as a Server-Sent Event whose `id` is its Dex resume token.
20
+ *
21
+ * An `EventSource` sends the `id` back as the `Last-Event-ID` header when it reconnects. The event has no
22
+ * `event:` field, so `EventSource.onmessage` receives every event; switch on `type` in the data.
23
+ *
24
+ * @param message - Message read from the `AgentEvents` Stream.
25
+ * @returns `id: <resume token>`, then `data: <AgentEvent wire JSON>`, then a blank line.
26
+ */
27
+ export function formatAgentEventSseFrame(message) {
28
+ return `id: ${message.resumeToken}\ndata: ${JSON.stringify(convertAgentEventToJson(message.value))}\n\n`;
29
+ }
30
+ /**
31
+ * Yields an agent session's `AgentEvents` as Server-Sent Event frames, resuming after a Dex resume token.
32
+ *
33
+ * Each event becomes one frame whose `id` is its Dex resume token and whose data is the `AgentEvent` wire
34
+ * JSON: `type`, `turn_id`, `attempt`, `step_execution_id`, and `payload` text. Reconnecting with the last
35
+ * `id` continues with the next event, with no repeated or missing event while the Stream retains them.
36
+ * After each empty long poll it yields a keep-alive comment. The stream never ends on its own; stop
37
+ * iterating, or abort `signal`, when the browser goes away.
38
+ *
39
+ * The browser applies the event rules of the session contract. Within one `step_execution_id` it keeps
40
+ * only the highest `attempt` and drops the partial text of lower attempts. After `turn_completed`,
41
+ * `turn_failed`, `turn_steered`, or `turn_cancelled` it replaces the turn's live text with the stored
42
+ * messages. On every connection, load
43
+ * {@link readAgentEventStreamSnapshot} first and open the stream from its `resumeToken`.
44
+ *
45
+ * @example
46
+ * ```ts
47
+ * for await (const frame of streamAgentEventSseFrames({
48
+ * client, flow, flowId: sessionId, resumeToken: request.headers["last-event-id"] })) {
49
+ * response.write(frame);
50
+ * }
51
+ * ```
52
+ * @param options - Session, start position, and polling.
53
+ * @returns An async generator of SSE frames and keep-alive comments.
54
+ * @throws {RangeError} When `pollTimeoutMs` is not a positive whole number of seconds.
55
+ * @throws {DexServiceError} When a Stream read fails.
56
+ */
57
+ export async function* streamAgentEventSseFrames(options) {
58
+ yield* formatAgentEventSseFramesFrom(options, undefined);
59
+ }
60
+ async function* formatAgentEventSseFramesFrom(options, firstMessage) {
61
+ const pollTimeoutMs = requireAgentEventPollTimeoutMs(options.pollTimeoutMs);
62
+ let eventResumeToken = options.resumeToken ?? "";
63
+ let pendingMessage = firstMessage;
64
+ while (options.signal?.aborted !== true) {
65
+ const message = pendingMessage ??
66
+ (await readNextAgentEvent(options.client, options.flow, options.flowId, eventResumeToken, pollTimeoutMs));
67
+ pendingMessage = undefined;
68
+ if (message === undefined) {
69
+ yield serverSentEventKeepAliveFrame;
70
+ continue;
71
+ }
72
+ eventResumeToken = message.resumeToken;
73
+ yield formatAgentEventSseFrame(message);
74
+ }
75
+ }
76
+ /**
77
+ * Returns a streaming `text/event-stream` Response of an agent session's `AgentEvents`.
78
+ *
79
+ * It writes {@link streamAgentEventSseFrames} and stops reading when the browser closes the response.
80
+ * Mount it in any server that returns a Fetch API `Response`. The session ID usually comes from the
81
+ * browser, so the route must check that the caller may read that session.
82
+ *
83
+ * Before it answers 200, it reads once, with a long poll of up to 1 second, to check the resume token.
84
+ * When Dex rejects the token, such as one of another session, it answers 400, which stops an
85
+ * `EventSource` from reconnecting with it; the browser then loads the snapshot again. A token from
86
+ * before a Stream Store restart is accepted and continues at the oldest retained event.
87
+ *
88
+ * @example
89
+ * ```ts
90
+ * // GET /sessions/:id/events
91
+ * export async function GET(request: Request, sessionId: string): Promise<Response> {
92
+ * const url = new URL(request.url);
93
+ * return createAgentEventSseResponse({
94
+ * client, flow, flowId: sessionId,
95
+ * resumeToken: request.headers.get("last-event-id") ?? url.searchParams.get("resumeToken") ?? "",
96
+ * signal: request.signal,
97
+ * });
98
+ * }
99
+ * // In the browser:
100
+ * const { resumeToken } = await (await fetch(`/sessions/${sessionId}/snapshot`)).json();
101
+ * const events = new EventSource(`/sessions/${sessionId}/events?resumeToken=${encodeURIComponent(resumeToken)}`);
102
+ * events.onmessage = (message) => render(JSON.parse(message.data));
103
+ * ```
104
+ * @param options - Session, start position, polling, and extra response headers.
105
+ * @returns A 200 Response with {@link agentEventStreamHeaders} and the application's `headers`; 400 with
106
+ * a text body when Dex rejects the resume token.
107
+ * @throws {RangeError} When `pollTimeoutMs` is not a positive whole number of seconds.
108
+ * @throws {DexServiceError} When the first Stream read fails for another reason.
109
+ */
110
+ export async function createAgentEventSseResponse(options) {
111
+ requireAgentEventPollTimeoutMs(options.pollTimeoutMs);
112
+ const probe = await probeAgentEventResumeToken(options.client, options.flow, options.flowId, options.resumeToken ?? "");
113
+ if (!probe.isAccepted) {
114
+ return new Response("the resume token does not belong to this session; load the snapshot again", {
115
+ status: 400,
116
+ headers: mergeHeaders({ "content-type": "text/plain; charset=utf-8" }, options.headers),
117
+ });
118
+ }
119
+ return createServerSentEventResponse(formatAgentEventSseFramesFrom(options, probe.firstMessage), agentEventStreamHeaders, options.headers);
120
+ }
121
+ /**
122
+ * Reads the session snapshot together with the Dex resume token to open the plain event stream from.
123
+ *
124
+ * Call it whenever the browser connects or reconnects after a gap. It reads the newest event first and
125
+ * the snapshot second, so events after the token may repeat what the snapshot shows but none is missing.
126
+ * While a turn is active the token replays that turn's events, so the browser can rebuild its live text.
127
+ * The `get_agent_snapshot` RPC needs a running Worker.
128
+ *
129
+ * @example
130
+ * ```ts
131
+ * // GET /sessions/:id/snapshot
132
+ * const value = await readAgentEventStreamSnapshot({ client, flow, flowId: sessionId });
133
+ * return Response.json(convertAgentEventStreamSnapshotToJson(value));
134
+ * ```
135
+ * @param options - Client, Flow, and session ID.
136
+ * @returns The snapshot and the resume token.
137
+ * @throws {DexServiceError} When the Stream read or the RPC fails.
138
+ */
139
+ export async function readAgentEventStreamSnapshot(options) {
140
+ const { client, flow, flowId } = options;
141
+ const tailResumeToken = await readAgentEventsTailResumeToken(client, flow, flowId);
142
+ const snapshot = await client.invokeRPC(flow.getAgentSnapshot, flowId);
143
+ const activeTurnId = snapshot.state?.activeTurnId ?? null;
144
+ if (activeTurnId === null) {
145
+ return { snapshot, resumeToken: tailResumeToken };
146
+ }
147
+ const turnResumeToken = await findAgentEventResumeTokenBeforeTurn(client, flow, flowId, activeTurnId);
148
+ return { snapshot, resumeToken: turnResumeToken ?? tailResumeToken };
149
+ }
150
+ /**
151
+ * Converts an {@link AgentEventStreamSnapshot} to snake_case wire JSON for an HTTP response.
152
+ *
153
+ * @param value - Snapshot and resume token.
154
+ * @returns `{ snapshot, resume_token }`, with the snapshot in its `AgentSnapshot` wire format.
155
+ */
156
+ export function convertAgentEventStreamSnapshotToJson(value) {
157
+ return { snapshot: convertAgentSnapshotToJson(value.snapshot), resume_token: value.resumeToken };
158
+ }
159
+ //# sourceMappingURL=agent-event-sse.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-event-sse.js","sourceRoot":"","sources":["../../../src/ui-stream/agent-event-sse.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,42 @@
1
+ import { type Client, type StreamMessage } from "@superdurable/dex";
2
+ import type { AgentFrameworkRunner, DeferredToolOutcome } from "../agent-framework-runner.js";
3
+ import type { AgentSessionFlow } from "../agent-session-flow.js";
4
+ import type { AgentEvent } from "../agent-session-values.js";
5
+ /** Default long-poll duration of one `AgentEvents` read: 10 seconds. */
6
+ export declare const defaultAgentEventPollTimeoutMs = 10000;
7
+ /** Long poll of the read that checks a resume token before a response commits to status 200. */
8
+ export declare const resumeTokenProbeTimeoutMs = 1000;
9
+ /** Validates a long-poll duration; Dex Stream reads take whole seconds. */
10
+ export declare function requireAgentEventPollTimeoutMs(pollTimeoutMs: number | undefined): number;
11
+ /**
12
+ * Reads the next `AgentEvents` message, or `undefined` when the long poll ends without one.
13
+ * A disabled Stream Store holds no events, so the read waits as an empty poll would.
14
+ */
15
+ export declare function readNextAgentEvent(client: Client, flow: AgentSessionFlow<AgentFrameworkRunner<DeferredToolOutcome>>, flowId: string, eventResumeToken: string, pollTimeoutMs: number): Promise<StreamMessage<AgentEvent> | undefined>;
16
+ /** Reports whether Dex rejected a Stream resume token, such as one of another session. */
17
+ export declare function isStreamResumeTokenRejectedError(error: unknown): boolean;
18
+ /** Reports whether a Stream call failed because the Server's Stream Store is disabled. */
19
+ export declare function isStreamStoreDisabledError(error: unknown): boolean;
20
+ /** The first read after a resume token, done before a response commits to its status. */
21
+ export type AgentEventResumeTokenProbe = {
22
+ readonly isAccepted: true;
23
+ readonly firstMessage: StreamMessage<AgentEvent> | undefined;
24
+ } | {
25
+ readonly isAccepted: false;
26
+ };
27
+ /** Reads once with a short long poll to learn whether Dex accepts a resume token. */
28
+ export declare function probeAgentEventResumeToken(client: Client, flow: AgentSessionFlow<AgentFrameworkRunner<DeferredToolOutcome>>, flowId: string, eventResumeToken: string): Promise<AgentEventResumeTokenProbe>;
29
+ /** Returns the resume token of the newest retained event, or `""` when the Stream holds none. */
30
+ export declare function readAgentEventsTailResumeToken(client: Client, flow: AgentSessionFlow<AgentFrameworkRunner<DeferredToolOutcome>>, flowId: string): Promise<string>;
31
+ /**
32
+ * Finds the position just before a turn's first retained event.
33
+ *
34
+ * @returns The resume token whose next event is the turn's `turn_started`, or the turn's oldest retained
35
+ * event; `""` when that event is the oldest retained one; `undefined` when the Stream holds no event of
36
+ * the turn or the search reached its page limit.
37
+ */
38
+ export declare function findAgentEventResumeTokenBeforeTurn(client: Client, flow: AgentSessionFlow<AgentFrameworkRunner<DeferredToolOutcome>>, flowId: string, turnId: string): Promise<string | undefined>;
39
+ /** Returns the number `n` of a `turn-<n>` turn ID, or `undefined` for another format. */
40
+ export declare function parseTurnNumber(turnId: string): number | undefined;
41
+ /** Returns the Step type of a `StepType-Number` Step execution ID, or `""` when it has no number. */
42
+ export declare function readStepType(stepExecutionId: string): string;