@ironflow/browser 0.20.2 → 0.22.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 (66) hide show
  1. package/README.md +1 -1
  2. package/dist/agents/index.d.ts +34 -0
  3. package/dist/agents/index.d.ts.map +1 -0
  4. package/dist/agents/index.js +24 -0
  5. package/dist/agents/index.js.map +1 -0
  6. package/dist/agents/invoke.d.ts +16 -0
  7. package/dist/agents/invoke.d.ts.map +1 -0
  8. package/dist/agents/invoke.js +222 -0
  9. package/dist/agents/invoke.js.map +1 -0
  10. package/dist/agents/readMemory.d.ts +18 -0
  11. package/dist/agents/readMemory.d.ts.map +1 -0
  12. package/dist/agents/readMemory.js +87 -0
  13. package/dist/agents/readMemory.js.map +1 -0
  14. package/dist/agents/subscribe.d.ts +23 -0
  15. package/dist/agents/subscribe.d.ts.map +1 -0
  16. package/dist/agents/subscribe.js +117 -0
  17. package/dist/agents/subscribe.js.map +1 -0
  18. package/dist/agents/types.d.ts +156 -0
  19. package/dist/agents/types.d.ts.map +1 -0
  20. package/dist/agents/types.js +7 -0
  21. package/dist/agents/types.js.map +1 -0
  22. package/dist/client.d.ts +844 -0
  23. package/dist/client.d.ts.map +1 -0
  24. package/dist/client.js +2243 -0
  25. package/dist/client.js.map +1 -0
  26. package/dist/config-client.d.ts +43 -0
  27. package/dist/config-client.d.ts.map +1 -0
  28. package/dist/config-client.js +134 -0
  29. package/dist/config-client.js.map +1 -0
  30. package/dist/config.d.ts +91 -0
  31. package/dist/config.d.ts.map +1 -0
  32. package/dist/config.js +55 -0
  33. package/dist/config.js.map +1 -0
  34. package/dist/index.d.ts +53 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +53 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/kv.d.ts +79 -0
  39. package/dist/kv.d.ts.map +1 -0
  40. package/dist/kv.js +289 -0
  41. package/dist/kv.js.map +1 -0
  42. package/dist/projection-stream.d.ts +42 -0
  43. package/dist/projection-stream.d.ts.map +1 -0
  44. package/dist/projection-stream.js +48 -0
  45. package/dist/projection-stream.js.map +1 -0
  46. package/dist/subscription.d.ts +107 -0
  47. package/dist/subscription.d.ts.map +1 -0
  48. package/dist/subscription.js +450 -0
  49. package/dist/subscription.js.map +1 -0
  50. package/dist/transport/connectrpc.d.ts +74 -0
  51. package/dist/transport/connectrpc.d.ts.map +1 -0
  52. package/dist/transport/connectrpc.js +393 -0
  53. package/dist/transport/connectrpc.js.map +1 -0
  54. package/dist/transport/index.d.ts +7 -0
  55. package/dist/transport/index.d.ts.map +1 -0
  56. package/dist/transport/index.js +6 -0
  57. package/dist/transport/index.js.map +1 -0
  58. package/dist/transport/types.d.ts +69 -0
  59. package/dist/transport/types.d.ts.map +1 -0
  60. package/dist/transport/types.js +5 -0
  61. package/dist/transport/types.js.map +1 -0
  62. package/dist/transport/websocket.d.ts +38 -0
  63. package/dist/transport/websocket.d.ts.map +1 -0
  64. package/dist/transport/websocket.js +276 -0
  65. package/dist/transport/websocket.js.map +1 -0
  66. package/package.json +3 -3
package/README.md CHANGED
@@ -536,7 +536,7 @@ Requires Ironflow server with `waitForProjectionCatchup` (#473) and the unified
536
536
 
537
537
  ### Stuck or hanging?
538
538
 
539
- See `docs/runbooks/runbook-browser-agent-stuck.md` for triage.
539
+ See `_internal/runbooks/runbook-browser-agent-stuck.md` for triage.
540
540
 
541
541
  ## Entity Streams (Event Sourcing)
542
542
 
@@ -0,0 +1,34 @@
1
+ /**
2
+ * `ironflow.agents` namespace.
3
+ *
4
+ * Browser-facing helpers for `agent()` functions: fire-and-wait `invoke`,
5
+ * typed `subscribe` for run/step events, and `readMemory` for typed
6
+ * projection state reads.
7
+ *
8
+ * Spec: ./spec.md
9
+ */
10
+ import type { Subscription } from "@ironflow/core";
11
+ import type { AgentClientLike, AgentInvokeOptions, AgentInvokeResult, AgentMemoryResult, AgentReadMemoryOptions, AgentSubscribeCallbacks } from "./types.js";
12
+ export type { AgentClientLike, AgentInvokeOptions, AgentInvokeResult, AgentMemoryResult, AgentProgressEvent, AgentReadMemoryOptions, AgentStepEvent, AgentSubscribeCallbacks, } from "./types.js";
13
+ /**
14
+ * The shape exposed as `ironflow.agents`.
15
+ */
16
+ export interface AgentSubscribeRuntimeOptions {
17
+ /**
18
+ * Number of historical events to replay on attach. Default: 1000.
19
+ * Covers events emitted between `agents.invoke()` returning a runId
20
+ * via `onRunStarted` and this subscribe attaching.
21
+ */
22
+ replay?: number;
23
+ }
24
+ export interface AgentsNamespace {
25
+ invoke<TOutput = unknown>(name: string, payload: unknown, opts?: AgentInvokeOptions): Promise<AgentInvokeResult<TOutput>>;
26
+ subscribe(runId: string, callbacks: AgentSubscribeCallbacks, opts?: AgentSubscribeRuntimeOptions): Promise<Subscription>;
27
+ readMemory<TState = unknown>(projection: string, opts?: AgentReadMemoryOptions): Promise<AgentMemoryResult<TState>>;
28
+ }
29
+ /**
30
+ * Build the `agents` namespace bound to a specific client. Called by
31
+ * the IronflowClient constructor.
32
+ */
33
+ export declare function createAgentsNamespace(client: AgentClientLike): AgentsNamespace;
34
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/agents/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAInD,OAAO,KAAK,EACV,eAAe,EACf,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,sBAAsB,EACtB,uBAAuB,EACxB,MAAM,YAAY,CAAC;AAEpB,YAAY,EACV,eAAe,EACf,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,sBAAsB,EACtB,cAAc,EACd,uBAAuB,GACxB,MAAM,YAAY,CAAC;AAEpB;;GAEG;AACH,MAAM,WAAW,4BAA4B;IAC3C;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,OAAO,GAAG,OAAO,EACtB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,OAAO,EAChB,IAAI,CAAC,EAAE,kBAAkB,GACxB,OAAO,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC;IAEvC,SAAS,CACP,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,uBAAuB,EAClC,IAAI,CAAC,EAAE,4BAA4B,GAClC,OAAO,CAAC,YAAY,CAAC,CAAC;IAEzB,UAAU,CAAC,MAAM,GAAG,OAAO,EACzB,UAAU,EAAE,MAAM,EAClB,IAAI,CAAC,EAAE,sBAAsB,GAC5B,OAAO,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC;CACvC;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,eAAe,GACtB,eAAe,CAOjB"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * `ironflow.agents` namespace.
3
+ *
4
+ * Browser-facing helpers for `agent()` functions: fire-and-wait `invoke`,
5
+ * typed `subscribe` for run/step events, and `readMemory` for typed
6
+ * projection state reads.
7
+ *
8
+ * Spec: ./spec.md
9
+ */
10
+ import { invoke as agentInvoke } from "./invoke.js";
11
+ import { readMemory as agentReadMemory } from "./readMemory.js";
12
+ import { subscribe as agentSubscribe } from "./subscribe.js";
13
+ /**
14
+ * Build the `agents` namespace bound to a specific client. Called by
15
+ * the IronflowClient constructor.
16
+ */
17
+ export function createAgentsNamespace(client) {
18
+ return {
19
+ invoke: (name, payload, opts) => agentInvoke(client, name, payload, opts),
20
+ subscribe: (runId, callbacks, opts) => agentSubscribe(client, runId, callbacks, opts),
21
+ readMemory: (projection, opts) => agentReadMemory(client, projection, opts),
22
+ };
23
+ }
24
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/agents/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,EAAE,MAAM,IAAI,WAAW,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,UAAU,IAAI,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAE,SAAS,IAAI,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAoD7D;;;GAGG;AACH,MAAM,UAAU,qBAAqB,CACnC,MAAuB;IAEvB,OAAO;QACL,MAAM,EAAE,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC,WAAW,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC;QACzE,SAAS,EAAE,CAAC,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,CACpC,cAAc,CAAC,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC;QAChD,UAAU,EAAE,CAAC,UAAU,EAAE,IAAI,EAAE,EAAE,CAAC,eAAe,CAAC,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC;KAC5E,CAAC;AACJ,CAAC"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * `ironflow.agents.invoke()` — fire-and-wait against an agent function.
3
+ *
4
+ * Composes the existing async `client.invoke()` + `client.subscribe()` to
5
+ * deliver a single Promise<{runId, output, durationMs}>.
6
+ *
7
+ * Race window between Trigger return and subscribe attach is covered by
8
+ * `subscribe({replay})` — see ./spec.md.
9
+ */
10
+ import type { AgentClientLike, AgentInvokeOptions, AgentInvokeResult } from "./types.js";
11
+ /**
12
+ * Fire-and-wait: trigger the named agent function, subscribe to its run
13
+ * events, and resolve when a terminal event arrives.
14
+ */
15
+ export declare function invoke<TOutput = unknown>(client: AgentClientLike, name: string, payload: unknown, opts?: AgentInvokeOptions): Promise<AgentInvokeResult<TOutput>>;
16
+ //# sourceMappingURL=invoke.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invoke.d.ts","sourceRoot":"","sources":["../../src/agents/invoke.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAWH,OAAO,KAAK,EACV,eAAe,EACf,kBAAkB,EAClB,iBAAiB,EAClB,MAAM,YAAY,CAAC;AAsEpB;;;GAGG;AACH,wBAAsB,MAAM,CAAC,OAAO,GAAG,OAAO,EAC5C,MAAM,EAAE,eAAe,EACvB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,OAAO,EAChB,IAAI,GAAE,kBAAuB,GAC5B,OAAO,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAiKrC"}
@@ -0,0 +1,222 @@
1
+ /**
2
+ * `ironflow.agents.invoke()` — fire-and-wait against an agent function.
3
+ *
4
+ * Composes the existing async `client.invoke()` + `client.subscribe()` to
5
+ * deliver a single Promise<{runId, output, durationMs}>.
6
+ *
7
+ * Race window between Trigger return and subscribe attach is covered by
8
+ * `subscribe({replay})` — see ./spec.md.
9
+ */
10
+ import { AgentInvokeTimeoutError, NoRunCreatedError, RunCancelledError, RunFailedError, ValidationError, } from "@ironflow/core";
11
+ const DEFAULT_TIMEOUT_MS = 30_000;
12
+ // Match the server-side `ReplayMaxEvents` default (1000). Replay-from-zero
13
+ // against a per-run subject is bounded by the run's own emission rate, so
14
+ // 1000 covers ~500 steps (each emits `created`+`completed`) plus run
15
+ // lifecycle events. Step-heavier agents should raise both this option and
16
+ // the server's `ReplayMaxEvents` config.
17
+ const DEFAULT_REPLAY = 1000;
18
+ const MAX_NAME_LENGTH = 256;
19
+ // Defense-in-depth: even though the server is the source of `runId`, we
20
+ // guard against a misbehaving server or mock returning NATS metacharacters
21
+ // (`*`, `>`, `.`) that would widen the subscribe pattern.
22
+ const RUN_ID_PATTERN = /^[A-Za-z0-9_-]+$/;
23
+ /**
24
+ * Validate the function name argument. Server validates the rest; we just
25
+ * catch the obviously broken cases client-side to fail fast.
26
+ */
27
+ function validateName(name) {
28
+ if (typeof name !== "string" || name.length === 0) {
29
+ throw new ValidationError("agents.invoke: name must be a non-empty string");
30
+ }
31
+ if (name.length > MAX_NAME_LENGTH) {
32
+ throw new ValidationError(`agents.invoke: name exceeds ${MAX_NAME_LENGTH} chars`);
33
+ }
34
+ }
35
+ /**
36
+ * Extract terminal-event verdict from a topic suffix. Returns null for
37
+ * non-terminal events.
38
+ *
39
+ * Topics: `system.run.{runId}.{event}` where event ∈
40
+ * { created, updated, resumed, completed, failed, cancelled }.
41
+ * Step events live under `.step.{stepId}.{type}`.
42
+ */
43
+ function classifyTerminal(topic) {
44
+ if (topic.includes(".step."))
45
+ return null;
46
+ if (topic.endsWith(".completed"))
47
+ return "completed";
48
+ if (topic.endsWith(".failed"))
49
+ return "failed";
50
+ if (topic.endsWith(".cancelled"))
51
+ return "cancelled";
52
+ return null;
53
+ }
54
+ function extractError(data) {
55
+ if (data && typeof data === "object" && "error" in data) {
56
+ const err = data.error;
57
+ if (typeof err === "string") {
58
+ return { message: err };
59
+ }
60
+ if (err && typeof err === "object") {
61
+ return {
62
+ message: err.message ?? "Run failed",
63
+ code: err.code,
64
+ };
65
+ }
66
+ }
67
+ return { message: "Run failed" };
68
+ }
69
+ /**
70
+ * Fire-and-wait: trigger the named agent function, subscribe to its run
71
+ * events, and resolve when a terminal event arrives.
72
+ */
73
+ export async function invoke(client, name, payload, opts = {}) {
74
+ validateName(name);
75
+ // Pre-flight abort: throw before any network I/O.
76
+ if (opts.signal?.aborted) {
77
+ throw new DOMException("Aborted", "AbortError");
78
+ }
79
+ const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
80
+ const replay = opts.replay ?? DEFAULT_REPLAY;
81
+ const startedAt = Date.now();
82
+ // 1) Trigger the agent. Server returns runId.
83
+ const triggerResult = await client.invoke(name, {
84
+ data: payload,
85
+ idempotencyKey: opts.idempotencyKey,
86
+ });
87
+ const runId = triggerResult.runIds?.[0];
88
+ if (!runId) {
89
+ throw new NoRunCreatedError(name);
90
+ }
91
+ // Defense-in-depth: server is the source of truth, but reject obviously
92
+ // malformed runIds before interpolating them into a NATS subject.
93
+ if (!RUN_ID_PATTERN.test(runId)) {
94
+ throw new ValidationError(`agents.invoke: server returned invalid runId "${runId}" (must match ${RUN_ID_PATTERN})`);
95
+ }
96
+ // Single deferred. resolve/reject from subscribe callback, timeout, or abort.
97
+ let settled = false;
98
+ let resolveOuter = () => { };
99
+ let rejectOuter = () => { };
100
+ const settle = (fn) => {
101
+ if (settled)
102
+ return;
103
+ settled = true;
104
+ fn();
105
+ };
106
+ const outer = new Promise((res, rej) => {
107
+ resolveOuter = res;
108
+ rejectOuter = rej;
109
+ });
110
+ // Attach a no-op handler eagerly so a fast settle() (e.g., synchronous
111
+ // timer or pre-subscribe abort) does not surface as an unhandled
112
+ // rejection before the awaiter below attaches. The original `outer`
113
+ // promise is unchanged and will still reject through `await outer`.
114
+ outer.catch(() => {
115
+ /* observed; real consumer is `await outer` below */
116
+ });
117
+ // Arm timeout + abort BEFORE running the user-provided onRunStarted hook
118
+ // so a hanging hook cannot bypass `timeoutMs` / `signal`.
119
+ const timeoutHandle = setTimeout(() => {
120
+ settle(() => rejectOuter(new AgentInvokeTimeoutError(runId, timeoutMs)));
121
+ }, timeoutMs);
122
+ const abortHandler = () => {
123
+ settle(() => rejectOuter(new DOMException("Aborted", "AbortError")));
124
+ };
125
+ opts.signal?.addEventListener("abort", abortHandler, { once: true });
126
+ // Surface runId immediately so callers can attach a separate progress
127
+ // subscription via agents.subscribe(runId) without waiting for terminal.
128
+ // We await onRunStarted so the caller's async hook (e.g., attaching a
129
+ // watcher) completes before the SDK starts dispatching terminal events,
130
+ // preventing late events from leaking into a subsequent run's UI. The
131
+ // hook is bounded by the timeout/abort armed above.
132
+ if (opts.onRunStarted && !settled) {
133
+ try {
134
+ await opts.onRunStarted(runId);
135
+ }
136
+ catch {
137
+ /* swallow — caller's bug is not ours */
138
+ }
139
+ }
140
+ // Subscribe and wire dispatch. Race the attach against the deferred so
141
+ // a hung subscribe call cannot wedge the invoke past `timeoutMs`/abort.
142
+ let unsubscribe;
143
+ const subscribePromise = client
144
+ .subscribe(`system.run.${runId}.>`, {
145
+ replay,
146
+ onEvent: (event) => {
147
+ if (settled)
148
+ return;
149
+ const verdict = classifyTerminal(event.topic);
150
+ if (!verdict)
151
+ return;
152
+ if (verdict === "completed") {
153
+ const output = event.data?.output;
154
+ settle(() => resolveOuter({
155
+ runId,
156
+ output,
157
+ durationMs: Date.now() - startedAt,
158
+ }));
159
+ return;
160
+ }
161
+ if (verdict === "failed") {
162
+ const err = extractError(event.data);
163
+ settle(() => rejectOuter(new RunFailedError(runId, event.data, err.message)));
164
+ return;
165
+ }
166
+ settle(() => rejectOuter(new RunCancelledError(runId)));
167
+ },
168
+ onError: (subErr) => {
169
+ settle(() => rejectOuter(new Error(`agents.invoke subscription error: ${subErr.message}`)));
170
+ },
171
+ })
172
+ .then((sub) => {
173
+ unsubscribe = () => {
174
+ try {
175
+ sub.unsubscribe();
176
+ }
177
+ catch {
178
+ /* idempotent */
179
+ }
180
+ };
181
+ // Race already settled before subscribe attached: clean up now.
182
+ if (settled)
183
+ unsubscribe();
184
+ })
185
+ .catch((err) => {
186
+ settle(() => rejectOuter(err));
187
+ });
188
+ // Don't block on subscribePromise; the outer race continues to fire on
189
+ // timeout/abort even if the attach never resolves.
190
+ void subscribePromise;
191
+ try {
192
+ return await outer;
193
+ }
194
+ catch (err) {
195
+ // Property check on `name` instead of `instanceof DOMException` for
196
+ // cross-runtime compatibility (some test runners and older Node
197
+ // builds don't share a DOMException prototype).
198
+ const isAbort = typeof err === "object" &&
199
+ err !== null &&
200
+ "name" in err &&
201
+ err.name === "AbortError";
202
+ if (err instanceof AgentInvokeTimeoutError || isAbort) {
203
+ // Fire-and-forget: do NOT await the cancel. A hanging cancelRun
204
+ // would block propagation of the original timeout/abort error to
205
+ // the caller. The unhandled-rejection guard preserves error
206
+ // observability without blocking.
207
+ void client
208
+ .cancelRun(runId, "agents.invoke aborted")
209
+ .catch(() => {
210
+ /* swallow — best-effort */
211
+ });
212
+ }
213
+ throw err;
214
+ }
215
+ finally {
216
+ clearTimeout(timeoutHandle);
217
+ opts.signal?.removeEventListener("abort", abortHandler);
218
+ if (unsubscribe)
219
+ unsubscribe();
220
+ }
221
+ }
222
+ //# sourceMappingURL=invoke.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invoke.js","sourceRoot":"","sources":["../../src/agents/invoke.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * `ironflow.agents.readMemory()` — typed read of an agent memory
3
+ * projection with optional read-your-writes catchup.
4
+ *
5
+ * Composes `client.waitForProjectionCatchup` (when `opts.minSeq` is set)
6
+ * + `client.getProjection`. See ./spec.md.
7
+ */
8
+ import type { AgentClientLike, AgentMemoryResult, AgentReadMemoryOptions } from "./types.js";
9
+ /**
10
+ * Read materialized projection state for an agent memory.
11
+ *
12
+ * When `opts.minSeq` is provided, waits for the projection to catch up
13
+ * before reading. This delivers read-your-writes semantics for callers
14
+ * that just appended an event (use the seq returned from
15
+ * `streams.append`).
16
+ */
17
+ export declare function readMemory<TState = unknown>(client: AgentClientLike, projection: string, opts?: AgentReadMemoryOptions): Promise<AgentMemoryResult<TState>>;
18
+ //# sourceMappingURL=readMemory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"readMemory.d.ts","sourceRoot":"","sources":["../../src/agents/readMemory.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH,OAAO,KAAK,EACV,eAAe,EACf,iBAAiB,EACjB,sBAAsB,EACvB,MAAM,YAAY,CAAC;AAsDpB;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAAC,MAAM,GAAG,OAAO,EAC/C,MAAM,EAAE,eAAe,EACvB,UAAU,EAAE,MAAM,EAClB,IAAI,GAAE,sBAA2B,GAChC,OAAO,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CA4CpC"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * `ironflow.agents.readMemory()` — typed read of an agent memory
3
+ * projection with optional read-your-writes catchup.
4
+ *
5
+ * Composes `client.waitForProjectionCatchup` (when `opts.minSeq` is set)
6
+ * + `client.getProjection`. See ./spec.md.
7
+ */
8
+ import { MemoryCatchupTimeoutError, ValidationError, } from "@ironflow/core";
9
+ const DEFAULT_TIMEOUT_MS = 30_000;
10
+ const MAX_NAME_LENGTH = 256;
11
+ function validateProjection(name) {
12
+ if (typeof name !== "string" || name.length === 0) {
13
+ throw new ValidationError("agents.readMemory: projection must be a non-empty string");
14
+ }
15
+ if (name.length > MAX_NAME_LENGTH) {
16
+ throw new ValidationError(`agents.readMemory: projection exceeds ${MAX_NAME_LENGTH} chars`);
17
+ }
18
+ }
19
+ function throwIfAborted(signal) {
20
+ if (signal?.aborted) {
21
+ throw new DOMException("Aborted", "AbortError");
22
+ }
23
+ }
24
+ /**
25
+ * Race a Promise against a caller-supplied AbortSignal. Resolves with
26
+ * the original promise unless the signal aborts first, in which case
27
+ * an AbortError is thrown. The original promise is left to settle in
28
+ * the background — its result is discarded.
29
+ */
30
+ function raceAbort(p, signal) {
31
+ if (!signal)
32
+ return p;
33
+ return new Promise((resolve, reject) => {
34
+ const onAbort = () => {
35
+ reject(new DOMException("Aborted", "AbortError"));
36
+ };
37
+ if (signal.aborted) {
38
+ onAbort();
39
+ return;
40
+ }
41
+ signal.addEventListener("abort", onAbort, { once: true });
42
+ p.then((v) => {
43
+ signal.removeEventListener("abort", onAbort);
44
+ resolve(v);
45
+ }, (err) => {
46
+ signal.removeEventListener("abort", onAbort);
47
+ reject(err);
48
+ });
49
+ });
50
+ }
51
+ /**
52
+ * Read materialized projection state for an agent memory.
53
+ *
54
+ * When `opts.minSeq` is provided, waits for the projection to catch up
55
+ * before reading. This delivers read-your-writes semantics for callers
56
+ * that just appended an event (use the seq returned from
57
+ * `streams.append`).
58
+ */
59
+ export async function readMemory(client, projection, opts = {}) {
60
+ validateProjection(projection);
61
+ throwIfAborted(opts.signal);
62
+ const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
63
+ // Treat `minSeq=0` / `0n` as "no catchup required" per the spec —
64
+ // saves a no-op round trip when callers default the param.
65
+ const minSeqProvided = opts.minSeq !== undefined && opts.minSeq !== 0 && opts.minSeq !== 0n;
66
+ if (minSeqProvided) {
67
+ const waitResult = await raceAbort(client.waitForProjectionCatchup(projection, {
68
+ minSeq: opts.minSeq,
69
+ timeoutMs,
70
+ partition: opts.partition,
71
+ }), opts.signal);
72
+ if (waitResult.timedOut) {
73
+ throw new MemoryCatchupTimeoutError(projection, BigInt(opts.minSeq), timeoutMs);
74
+ }
75
+ }
76
+ throwIfAborted(opts.signal);
77
+ const stateResult = await raceAbort(client.getProjection(projection, {
78
+ partition: opts.partition,
79
+ }), opts.signal);
80
+ return {
81
+ state: stateResult.state,
82
+ version: stateResult.version,
83
+ lastEventId: stateResult.lastEventId || undefined,
84
+ caughtUp: true,
85
+ };
86
+ }
87
+ //# sourceMappingURL=readMemory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"readMemory.js","sourceRoot":"","sources":["../../src/agents/readMemory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * `ironflow.agents.subscribe()` — typed wrapper over `client.subscribe()`
3
+ * for an agent run's event stream.
4
+ *
5
+ * Spec: see ./spec.md
6
+ */
7
+ import { type Subscription } from "@ironflow/core";
8
+ import type { AgentClientLike, AgentSubscribeCallbacks } from "./types.js";
9
+ /**
10
+ * Promise-returning wrapper. Returns a Subscription whose `unsubscribe()`
11
+ * is idempotent.
12
+ *
13
+ * Topic dispatch:
14
+ * system.run.{runId}.completed → onComplete
15
+ * system.run.{runId}.failed → onFailed
16
+ * system.run.{runId}.cancelled → onCancelled
17
+ * system.run.{runId}.{created|updated|resumed} → onProgress
18
+ * system.run.{runId}.step.{stepId}.{type} → onStep
19
+ */
20
+ export declare function subscribe(client: AgentClientLike, runId: string, callbacks: AgentSubscribeCallbacks, opts?: {
21
+ replay?: number;
22
+ }): Promise<Subscription>;
23
+ //# sourceMappingURL=subscribe.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subscribe.d.ts","sourceRoot":"","sources":["../../src/agents/subscribe.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAGL,KAAK,YAAY,EAClB,MAAM,gBAAgB,CAAC;AAExB,OAAO,KAAK,EACV,eAAe,EAGf,uBAAuB,EACxB,MAAM,YAAY,CAAC;AAiCpB;;;;;;;;;;GAUG;AACH,wBAAsB,SAAS,CAC7B,MAAM,EAAE,eAAe,EACvB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,uBAAuB,EAClC,IAAI,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAO,GAC7B,OAAO,CAAC,YAAY,CAAC,CAiCvB"}
@@ -0,0 +1,117 @@
1
+ /**
2
+ * `ironflow.agents.subscribe()` — typed wrapper over `client.subscribe()`
3
+ * for an agent run's event stream.
4
+ *
5
+ * Spec: see ./spec.md
6
+ */
7
+ import { ValidationError, } from "@ironflow/core";
8
+ const MAX_RUN_ID_LENGTH = 128;
9
+ // Permits server-issued runIds (e.g., `run_<uuid>`, `run-2025-...`) but
10
+ // rejects NATS subject metacharacters that would widen the subscribe to
11
+ // other runs (`*`, `>`, `.`) or break the topic shape.
12
+ const RUN_ID_PATTERN = /^[A-Za-z0-9_-]+$/;
13
+ function validateRunId(runId) {
14
+ if (typeof runId !== "string" || runId.length === 0) {
15
+ throw new ValidationError("agents.subscribe: runId must be a non-empty string");
16
+ }
17
+ if (runId.length > MAX_RUN_ID_LENGTH) {
18
+ throw new ValidationError(`agents.subscribe: runId exceeds ${MAX_RUN_ID_LENGTH} chars`);
19
+ }
20
+ if (!RUN_ID_PATTERN.test(runId)) {
21
+ throw new ValidationError("agents.subscribe: runId may only contain [A-Za-z0-9_-] (no NATS metacharacters)");
22
+ }
23
+ }
24
+ /**
25
+ * Promise-returning wrapper. Returns a Subscription whose `unsubscribe()`
26
+ * is idempotent.
27
+ *
28
+ * Topic dispatch:
29
+ * system.run.{runId}.completed → onComplete
30
+ * system.run.{runId}.failed → onFailed
31
+ * system.run.{runId}.cancelled → onCancelled
32
+ * system.run.{runId}.{created|updated|resumed} → onProgress
33
+ * system.run.{runId}.step.{stepId}.{type} → onStep
34
+ */
35
+ export async function subscribe(client, runId, callbacks, opts = {}) {
36
+ validateRunId(runId);
37
+ const sub = await client.subscribe(`system.run.${runId}.>`, {
38
+ // Default replay 1000 covers events emitted between `agents.invoke`
39
+ // returning a runId via `onRunStarted` and this subscribe attaching.
40
+ replay: opts.replay ?? 1000,
41
+ onEvent: (event) => dispatch(event, runId, callbacks),
42
+ onError: callbacks.onError,
43
+ });
44
+ // Wrap the underlying unsubscribe to make it idempotent.
45
+ let unsubscribed = false;
46
+ const wrapped = {
47
+ id: sub.id ?? "",
48
+ pattern: sub.pattern ?? `system.run.${runId}.>`,
49
+ connectionState: sub.connectionState ?? "connected",
50
+ unsubscribe() {
51
+ if (unsubscribed)
52
+ return;
53
+ unsubscribed = true;
54
+ try {
55
+ sub.unsubscribe();
56
+ }
57
+ catch {
58
+ /* swallow — idempotent */
59
+ }
60
+ },
61
+ };
62
+ return wrapped;
63
+ }
64
+ function dispatch(event, runId, callbacks) {
65
+ const topic = event.topic;
66
+ const stepPrefix = `system.run.${runId}.step.`;
67
+ if (topic.startsWith(stepPrefix)) {
68
+ if (!callbacks.onStep)
69
+ return;
70
+ const remainder = topic.slice(stepPrefix.length); // "{stepId}.{type}"
71
+ const dotIdx = remainder.indexOf(".");
72
+ const stepId = dotIdx === -1 ? remainder : remainder.slice(0, dotIdx);
73
+ const type = dotIdx === -1 ? "" : remainder.slice(dotIdx + 1);
74
+ const stepEvent = {
75
+ topic,
76
+ stepId,
77
+ type,
78
+ data: event.data,
79
+ };
80
+ callbacks.onStep(stepEvent);
81
+ return;
82
+ }
83
+ if (topic.endsWith(".completed")) {
84
+ callbacks.onComplete?.({ output: event.data?.output });
85
+ return;
86
+ }
87
+ if (topic.endsWith(".failed")) {
88
+ const err = event.data?.error;
89
+ if (typeof err === "string") {
90
+ callbacks.onFailed?.({ message: err });
91
+ }
92
+ else if (err && typeof err === "object") {
93
+ callbacks.onFailed?.({
94
+ message: err.message ?? "Run failed",
95
+ code: err.code,
96
+ });
97
+ }
98
+ else {
99
+ callbacks.onFailed?.({ message: "Run failed" });
100
+ }
101
+ return;
102
+ }
103
+ if (topic.endsWith(".cancelled")) {
104
+ callbacks.onCancelled?.();
105
+ return;
106
+ }
107
+ // Non-terminal: created / updated / resumed.
108
+ if (callbacks.onProgress) {
109
+ const progressEvent = {
110
+ topic,
111
+ status: event.data?.status,
112
+ data: event.data,
113
+ };
114
+ callbacks.onProgress(progressEvent);
115
+ }
116
+ }
117
+ //# sourceMappingURL=subscribe.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subscribe.js","sourceRoot":"","sources":["../../src/agents/subscribe.ts"],"names":[],"mappings":"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"}