@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.
- package/README.md +1 -1
- package/dist/agents/index.d.ts +34 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/index.js +24 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/agents/invoke.d.ts +16 -0
- package/dist/agents/invoke.d.ts.map +1 -0
- package/dist/agents/invoke.js +222 -0
- package/dist/agents/invoke.js.map +1 -0
- package/dist/agents/readMemory.d.ts +18 -0
- package/dist/agents/readMemory.d.ts.map +1 -0
- package/dist/agents/readMemory.js +87 -0
- package/dist/agents/readMemory.js.map +1 -0
- package/dist/agents/subscribe.d.ts +23 -0
- package/dist/agents/subscribe.d.ts.map +1 -0
- package/dist/agents/subscribe.js +117 -0
- package/dist/agents/subscribe.js.map +1 -0
- package/dist/agents/types.d.ts +156 -0
- package/dist/agents/types.d.ts.map +1 -0
- package/dist/agents/types.js +7 -0
- package/dist/agents/types.js.map +1 -0
- package/dist/client.d.ts +844 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +2243 -0
- package/dist/client.js.map +1 -0
- package/dist/config-client.d.ts +43 -0
- package/dist/config-client.d.ts.map +1 -0
- package/dist/config-client.js +134 -0
- package/dist/config-client.js.map +1 -0
- package/dist/config.d.ts +91 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +55 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +53 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +53 -0
- package/dist/index.js.map +1 -0
- package/dist/kv.d.ts +79 -0
- package/dist/kv.d.ts.map +1 -0
- package/dist/kv.js +289 -0
- package/dist/kv.js.map +1 -0
- package/dist/projection-stream.d.ts +42 -0
- package/dist/projection-stream.d.ts.map +1 -0
- package/dist/projection-stream.js +48 -0
- package/dist/projection-stream.js.map +1 -0
- package/dist/subscription.d.ts +107 -0
- package/dist/subscription.d.ts.map +1 -0
- package/dist/subscription.js +450 -0
- package/dist/subscription.js.map +1 -0
- package/dist/transport/connectrpc.d.ts +74 -0
- package/dist/transport/connectrpc.d.ts.map +1 -0
- package/dist/transport/connectrpc.js +393 -0
- package/dist/transport/connectrpc.js.map +1 -0
- package/dist/transport/index.d.ts +7 -0
- package/dist/transport/index.d.ts.map +1 -0
- package/dist/transport/index.js +6 -0
- package/dist/transport/index.js.map +1 -0
- package/dist/transport/types.d.ts +69 -0
- package/dist/transport/types.d.ts.map +1 -0
- package/dist/transport/types.js +5 -0
- package/dist/transport/types.js.map +1 -0
- package/dist/transport/websocket.d.ts +38 -0
- package/dist/transport/websocket.d.ts.map +1 -0
- package/dist/transport/websocket.js +276 -0
- package/dist/transport/websocket.js.map +1 -0
- 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 `
|
|
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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"}
|