@ironflow/browser 0.19.2 → 0.20.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.
package/README.md CHANGED
@@ -12,6 +12,7 @@ This is a **private npm package**. This README is the sole reference for coding
12
12
  - [Events and Subscriptions](#events-and-subscriptions)
13
13
  - [Emitting Events](#emitting-events)
14
14
  - [Workflow Operations](#workflow-operations)
15
+ - [Agents (`ironflow.agents.*`)](#agents-ironflowagents)
15
16
  - [Entity Streams (Event Sourcing)](#entity-streams-event-sourcing)
16
17
  - [Projections](#projections)
17
18
  - [KV Store](#kv-store)
@@ -442,6 +443,101 @@ console.log(output.output);
442
443
  console.log(output.patched); // Whether output was injected
443
444
  ```
444
445
 
446
+ ## Agents (`ironflow.agents.*`)
447
+
448
+ Browser helpers for `agent()` functions. Mirror the `@ironflow/node/agent` shape so the same agent runs in browser-driven UIs and server workers without divergence.
449
+
450
+ Spec: `src/agents/spec.md`. Issue #625.
451
+
452
+ ### `agents.invoke(name, payload, opts?)`
453
+
454
+ Fire-and-wait. Triggers the agent, subscribes to its run events, resolves on the terminal `system.run.{runId}.completed` event.
455
+
456
+ ```typescript
457
+ import { ironflow } from '@ironflow/browser';
458
+
459
+ const result = await ironflow.agents.invoke<{ category: string }>(
460
+ 'doc-processor',
461
+ { docId: 'doc-1', imageUrl: 'https://example.com/x.png' },
462
+ {
463
+ timeoutMs: 60_000, // default 30s
464
+ idempotencyKey: 'click-abc', // server-side dedup
465
+ signal: ac.signal, // AbortController
466
+ replay: 1000, // default; covers the race window
467
+ onRunStarted: (runId) => {}, // optional: surfaces runId before terminal
468
+ }
469
+ );
470
+ console.log(result.runId, result.output, result.durationMs);
471
+ ```
472
+
473
+ Errors:
474
+
475
+ | Throws | When |
476
+ |---|---|
477
+ | `ValidationError` | empty/oversized `name` |
478
+ | `AbortError` (DOMException) | `signal` aborts; SDK calls `cancelRun(runId)` server-side |
479
+ | `AgentInvokeTimeoutError` | local `timeoutMs` elapsed; SDK calls `cancelRun(runId)` |
480
+ | `NoRunCreatedError` | server returned empty `runIds` |
481
+ | `RunFailedError` | `system.run.{runId}.failed` |
482
+ | `RunCancelledError` | `system.run.{runId}.cancelled` |
483
+
484
+ ### `agents.subscribe(runId, callbacks)`
485
+
486
+ Typed wrapper over the broader `subscribe(pattern)` API. Dispatches by topic.
487
+
488
+ ```typescript
489
+ const sub = await ironflow.agents.subscribe(runId, {
490
+ onProgress: (e) => console.log('progress', e.topic, e.status),
491
+ onStep: (e) => console.log('step', e.stepId, e.type),
492
+ onComplete: (r) => console.log('done', r.output),
493
+ onFailed: (err) => console.warn('failed', err.message),
494
+ onCancelled: () => console.warn('cancelled'),
495
+ onError: (err) => console.error('transport', err),
496
+ });
497
+
498
+ // Unsubscribe is idempotent.
499
+ sub.unsubscribe();
500
+ ```
501
+
502
+ ### `agents.readMemory(projection, opts?)`
503
+
504
+ Typed read of an agent memory projection. Optional read-your-writes via `minSeq` from a prior `streams.append`.
505
+
506
+ ```typescript
507
+ interface DocMemory {
508
+ docs: Record<string, { status: 'ocr' | 'classified' | 'published'; category?: string }>;
509
+ }
510
+
511
+ // Read current state — eventual consistency.
512
+ const mem = await ironflow.agents.readMemory<DocMemory>('doc-processor-memory');
513
+ console.log(mem.state.docs, mem.version);
514
+
515
+ // Read-your-writes: pass the seq returned by a prior append so the
516
+ // projection has caught up before the read.
517
+ const { sequence } = await ironflow.streams.append('agent-memory:doc-1', {
518
+ name: 'DocProcessed',
519
+ data: { docId: 'doc-1', status: 'classified' },
520
+ });
521
+ const fresh = await ironflow.agents.readMemory<DocMemory>('doc-processor-memory', {
522
+ minSeq: sequence,
523
+ timeoutMs: 5_000,
524
+ });
525
+ ```
526
+
527
+ Throws `MemoryCatchupTimeoutError` if the projection cannot catch up to `minSeq` within `timeoutMs`. Throws `AbortError` on caller cancellation.
528
+
529
+ ### React example
530
+
531
+ A complete browser-driven demo lives at `examples/agents/doc-processor-agent/web/`. It exercises `agents.invoke` + `agents.subscribe` against the doc-processor agent's crash-resume flow, and `agents.readMemory` to render per-doc state.
532
+
533
+ ### Server compatibility
534
+
535
+ Requires Ironflow server with `waitForProjectionCatchup` (#473) and the unified Trigger path. Any server built from `main` after #608 (Lane D) supports the full surface.
536
+
537
+ ### Stuck or hanging?
538
+
539
+ See `docs/runbooks/runbook-browser-agent-stuck.md` for triage.
540
+
445
541
  ## Entity Streams (Event Sourcing)
446
542
 
447
543
  Entity streams store domain events per entity with optimistic concurrency control.
@@ -540,11 +636,15 @@ const result = await ironflow.getProjection<{ totalOrders: number }>('order-stat
540
636
 
541
637
  console.log(result.name); // 'order-stats'
542
638
  console.log(result.state); // { totalOrders: 42 }
543
- console.log(result.partition); // '__global__' or partition key
639
+ console.log(result.partition); // '__global__' or partition key
544
640
  console.log(result.lastEventId); // Last processed event ID
545
- console.log(result.lastEventTime); // Date
641
+ console.log(result.lastEventTime); // Date | undefined (undefined before first event)
642
+ console.log(result.lastEventSeq); // Last processed sequence number
546
643
  console.log(result.version); // Projection version
547
644
  console.log(result.mode); // 'managed' | 'external'
645
+ console.log(result.status); // 'active' | 'rebuilding' | 'paused' | 'error'
646
+ console.log(result.errorMessage); // Error string when status is 'error', else undefined
647
+ console.log(result.updatedAt); // Date
548
648
 
549
649
  // Get partitioned projection state
550
650
  const result = await ironflow.getProjection('order-stats', {
@@ -736,16 +836,18 @@ await config.delete('app-settings');
736
836
  // all reach the subscriber. Payload includes `revision`; drop events whose
737
837
  // revision is lower than the last one you applied to guard against rare
738
838
  // out-of-order deliveries under retry.
739
- const sub = await config.watch('app-settings', {
740
- onEvent: (configResponse) => {
741
- console.log('Config updated:', configResponse.data, configResponse.revision);
839
+ const watcher = await config.watch('app-settings', {
840
+ onUpdate: (event) => {
841
+ // event: ConfigWatchEvent ({ type: "config_update", name, data, revision, updatedAt })
842
+ console.log('Config updated:', event.data, event.revision);
742
843
  },
743
844
  onError: (error) => {
744
845
  console.error('Watch error:', error);
745
846
  },
746
847
  });
747
848
 
748
- sub.unsubscribe();
849
+ // `watcher` is a Subscription — call unsubscribe() to stop watching.
850
+ watcher.unsubscribe();
749
851
  ```
750
852
 
751
853
  When the tab is backgrounded long enough that the browser silently kills the
@@ -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":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EACL,uBAAuB,EACvB,iBAAiB,EACjB,iBAAiB,EACjB,cAAc,EACd,eAAe,GAEhB,MAAM,gBAAgB,CAAC;AAQxB,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAClC,2EAA2E;AAC3E,0EAA0E;AAC1E,qEAAqE;AACrE,0EAA0E;AAC1E,yCAAyC;AACzC,MAAM,cAAc,GAAG,IAAI,CAAC;AAC5B,MAAM,eAAe,GAAG,GAAG,CAAC;AAC5B,wEAAwE;AACxE,2EAA2E;AAC3E,0DAA0D;AAC1D,MAAM,cAAc,GAAG,kBAAkB,CAAC;AAE1C;;;GAGG;AACH,SAAS,YAAY,CAAC,IAAY;IAChC,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAClD,MAAM,IAAI,eAAe,CAAC,gDAAgD,CAAC,CAAC;IAC9E,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,GAAG,eAAe,EAAE,CAAC;QAClC,MAAM,IAAI,eAAe,CACvB,+BAA+B,eAAe,QAAQ,CACvD,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,gBAAgB,CACvB,KAAa;IAEb,IAAI,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAAE,OAAO,IAAI,CAAC;IAC1C,IAAI,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC;QAAE,OAAO,WAAW,CAAC;IACrD,IAAI,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC;QAAE,OAAO,QAAQ,CAAC;IAC/C,IAAI,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC;QAAE,OAAO,WAAW,CAAC;IACrD,OAAO,IAAI,CAAC;AACd,CAAC;AAQD,SAAS,YAAY,CAAC,IAAa;IACjC,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC;QACxD,MAAM,GAAG,GAAI,IAAwB,CAAC,KAAK,CAAC;QAC5C,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;YAC5B,OAAO,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC;QAC1B,CAAC;QACD,IAAI,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;YACnC,OAAO;gBACL,OAAO,EAAE,GAAG,CAAC,OAAO,IAAI,YAAY;gBACpC,IAAI,EAAE,GAAG,CAAC,IAAI;aACf,CAAC;QACJ,CAAC;IACH,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,CAAC;AACnC,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,MAAM,CAC1B,MAAuB,EACvB,IAAY,EACZ,OAAgB,EAChB,OAA2B,EAAE;IAE7B,YAAY,CAAC,IAAI,CAAC,CAAC;IAEnB,kDAAkD;IAClD,IAAI,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;QACzB,MAAM,IAAI,YAAY,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC;IAClD,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,kBAAkB,CAAC;IACvD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,cAAc,CAAC;IAC7C,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAE7B,8CAA8C;IAC9C,MAAM,aAAa,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE;QAC9C,IAAI,EAAE,OAAO;QACb,cAAc,EAAE,IAAI,CAAC,cAAc;KACpC,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,aAAa,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;IACxC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,iBAAiB,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;IACD,wEAAwE;IACxE,kEAAkE;IAClE,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAChC,MAAM,IAAI,eAAe,CACvB,iDAAiD,KAAK,iBAAiB,cAAc,GAAG,CACzF,CAAC;IACJ,CAAC;IAED,8EAA8E;IAC9E,IAAI,OAAO,GAAG,KAAK,CAAC;IACpB,IAAI,YAAY,GAA4C,GAAG,EAAE,GAAE,CAAC,CAAC;IACrE,IAAI,WAAW,GAAuB,GAAG,EAAE,GAAE,CAAC,CAAC;IAC/C,MAAM,MAAM,GAAG,CAAC,EAAc,EAAQ,EAAE;QACtC,IAAI,OAAO;YAAE,OAAO;QACpB,OAAO,GAAG,IAAI,CAAC;QACf,EAAE,EAAE,CAAC;IACP,CAAC,CAAC;IACF,MAAM,KAAK,GAAG,IAAI,OAAO,CAA6B,CAAC,GAAG,EAAE,GAAG,EAAE,EAAE;QACjE,YAAY,GAAG,GAAG,CAAC;QACnB,WAAW,GAAG,GAAG,CAAC;IACpB,CAAC,CAAC,CAAC;IACH,uEAAuE;IACvE,iEAAiE;IACjE,oEAAoE;IACpE,oEAAoE;IACpE,KAAK,CAAC,KAAK,CAAC,GAAG,EAAE;QACf,oDAAoD;IACtD,CAAC,CAAC,CAAC;IAEH,yEAAyE;IACzE,0DAA0D;IAC1D,MAAM,aAAa,GAAG,UAAU,CAAC,GAAG,EAAE;QACpC,MAAM,CAAC,GAAG,EAAE,CACV,WAAW,CAAC,IAAI,uBAAuB,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,CAC3D,CAAC;IACJ,CAAC,EAAE,SAAS,CAAC,CAAC;IACd,MAAM,YAAY,GAAG,GAAS,EAAE;QAC9B,MAAM,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,YAAY,CAAC,SAAS,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC;IACvE,CAAC,CAAC;IACF,IAAI,CAAC,MAAM,EAAE,gBAAgB,CAAC,OAAO,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAErE,sEAAsE;IACtE,yEAAyE;IACzE,sEAAsE;IACtE,wEAAwE;IACxE,sEAAsE;IACtE,oDAAoD;IACpD,IAAI,IAAI,CAAC,YAAY,IAAI,CAAC,OAAO,EAAE,CAAC;QAClC,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;QACjC,CAAC;QAAC,MAAM,CAAC;YACP,wCAAwC;QAC1C,CAAC;IACH,CAAC;IAED,uEAAuE;IACvE,wEAAwE;IACxE,IAAI,WAAqC,CAAC;IAC1C,MAAM,gBAAgB,GAAG,MAAM;SAC5B,SAAS,CAAkB,cAAc,KAAK,IAAI,EAAE;QACnD,MAAM;QACN,OAAO,EAAE,CAAC,KAAyC,EAAE,EAAE;YACrD,IAAI,OAAO;gBAAE,OAAO;YACpB,MAAM,OAAO,GAAG,gBAAgB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC9C,IAAI,CAAC,OAAO;gBAAE,OAAO;YACrB,IAAI,OAAO,KAAK,WAAW,EAAE,CAAC;gBAC5B,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,EAAE,MAA6B,CAAC;gBACzD,MAAM,CAAC,GAAG,EAAE,CACV,YAAY,CAAC;oBACX,KAAK;oBACL,MAAM;oBACN,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;iBACnC,CAAC,CACH,CAAC;gBACF,OAAO;YACT,CAAC;YACD,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;gBACzB,MAAM,GAAG,GAAG,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBACrC,MAAM,CAAC,GAAG,EAAE,CACV,WAAW,CAAC,IAAI,cAAc,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC,CAChE,CAAC;gBACF,OAAO;YACT,CAAC;YACD,MAAM,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,iBAAiB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC1D,CAAC;QACD,OAAO,EAAE,CAAC,MAAM,EAAE,EAAE;YAClB,MAAM,CAAC,GAAG,EAAE,CACV,WAAW,CACT,IAAI,KAAK,CAAC,qCAAqC,MAAM,CAAC,OAAO,EAAE,CAAC,CACjE,CACF,CAAC;QACJ,CAAC;KACF,CAAC;SACD,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE;QACZ,WAAW,GAAG,GAAG,EAAE;YACjB,IAAI,CAAC;gBACH,GAAG,CAAC,WAAW,EAAE,CAAC;YACpB,CAAC;YAAC,MAAM,CAAC;gBACP,gBAAgB;YAClB,CAAC;QACH,CAAC,CAAC;QACF,gEAAgE;QAChE,IAAI,OAAO;YAAE,WAAW,EAAE,CAAC;IAC7B,CAAC,CAAC;SACD,KAAK,CAAC,CAAC,GAAU,EAAE,EAAE;QACpB,MAAM,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC;IACjC,CAAC,CAAC,CAAC;IACL,uEAAuE;IACvE,mDAAmD;IACnD,KAAK,gBAAgB,CAAC;IAEtB,IAAI,CAAC;QACH,OAAO,MAAM,KAAK,CAAC;IACrB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,oEAAoE;QACpE,gEAAgE;QAChE,gDAAgD;QAChD,MAAM,OAAO,GACX,OAAO,GAAG,KAAK,QAAQ;YACvB,GAAG,KAAK,IAAI;YACZ,MAAM,IAAI,GAAG;YACZ,GAAyB,CAAC,IAAI,KAAK,YAAY,CAAC;QACnD,IAAI,GAAG,YAAY,uBAAuB,IAAI,OAAO,EAAE,CAAC;YACtD,gEAAgE;YAChE,iEAAiE;YACjE,4DAA4D;YAC5D,kCAAkC;YAClC,KAAK,MAAM;iBACR,SAAS,CAAC,KAAK,EAAE,uBAAuB,CAAC;iBACzC,KAAK,CAAC,GAAG,EAAE;gBACV,2BAA2B;YAC7B,CAAC,CAAC,CAAC;QACP,CAAC;QACD,MAAM,GAAG,CAAC;IACZ,CAAC;YAAS,CAAC;QACT,YAAY,CAAC,aAAa,CAAC,CAAC;QAC5B,IAAI,CAAC,MAAM,EAAE,mBAAmB,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC;QACxD,IAAI,WAAW;YAAE,WAAW,EAAE,CAAC;IACjC,CAAC;AACH,CAAC"}
@@ -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"}