@ai-matrx/agents 0.5.1 → 0.6.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 (41) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/README.md +41 -16
  3. package/dist/index.cjs +415 -40
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.d.cts +3 -1
  6. package/dist/index.d.ts +3 -1
  7. package/dist/index.js +396 -3
  8. package/dist/index.js.map +1 -1
  9. package/dist/matrx/index.cjs +401 -26
  10. package/dist/matrx/index.cjs.map +1 -1
  11. package/dist/matrx/index.d.cts +345 -1
  12. package/dist/matrx/index.d.ts +345 -1
  13. package/dist/matrx/index.js +382 -3
  14. package/dist/matrx/index.js.map +1 -1
  15. package/dist/presentation/result.cjs +23 -4
  16. package/dist/presentation/result.cjs.map +1 -1
  17. package/dist/presentation/result.js +3 -3
  18. package/dist/presentation/result.js.map +1 -1
  19. package/dist/projection/request.cjs +25 -6
  20. package/dist/projection/request.cjs.map +1 -1
  21. package/dist/projection/request.js +5 -3
  22. package/dist/projection/request.js.map +1 -1
  23. package/dist/projection/workflow.cjs +25 -6
  24. package/dist/projection/workflow.cjs.map +1 -1
  25. package/dist/projection/workflow.js +5 -3
  26. package/dist/projection/workflow.js.map +1 -1
  27. package/dist/react/index.cjs +1038 -0
  28. package/dist/react/index.cjs.map +1 -0
  29. package/dist/react/index.d.cts +540 -0
  30. package/dist/react/index.d.ts +540 -0
  31. package/dist/react/index.js +1016 -0
  32. package/dist/react/index.js.map +1 -0
  33. package/dist/stream/ndjson.cjs +26 -7
  34. package/dist/stream/ndjson.cjs.map +1 -1
  35. package/dist/stream/ndjson.js +6 -3
  36. package/dist/stream/ndjson.js.map +1 -1
  37. package/dist/stream/sse.cjs +25 -6
  38. package/dist/stream/sse.cjs.map +1 -1
  39. package/dist/stream/sse.js +5 -3
  40. package/dist/stream/sse.js.map +1 -1
  41. package/package.json +28 -2
@@ -0,0 +1,540 @@
1
+ type AgentProjectionStatus = "pending" | "streaming" | "awaiting-tools" | "complete" | "error" | "cancelled";
2
+ interface AgentProjectionOperation {
3
+ operationId: string;
4
+ operation: string;
5
+ parentOperationId: string | null;
6
+ status: "active" | "success" | "failed" | "cancelled";
7
+ metadata: Record<string, unknown> | null;
8
+ result: Record<string, unknown> | null;
9
+ }
10
+ interface AgentProjectionTool {
11
+ callId: string;
12
+ toolName: string;
13
+ status: "started" | "progress" | "step" | "preview" | "completed" | "error" | "delegated";
14
+ message: string | null;
15
+ data: Record<string, unknown> | null;
16
+ }
17
+ interface AgentProjectionRenderBlock {
18
+ blockId: string;
19
+ blockIndex: number;
20
+ type: string;
21
+ status: "streaming" | "complete" | "error";
22
+ content: string | null;
23
+ data: Record<string, unknown> | null;
24
+ metadata: Record<string, unknown> | null;
25
+ }
26
+ interface AgentRequestProjection {
27
+ requestId: string;
28
+ conversationId: string | null;
29
+ status: AgentProjectionStatus;
30
+ answer: string;
31
+ reasoning: string;
32
+ reasoningActive: boolean;
33
+ phase: string | null;
34
+ phaseHistory: string[];
35
+ operations: Record<string, AgentProjectionOperation>;
36
+ tools: Record<string, AgentProjectionTool>;
37
+ renderBlocks: Record<string, AgentProjectionRenderBlock>;
38
+ renderBlockOrder: string[];
39
+ completion: Record<string, unknown> | null;
40
+ error: Record<string, unknown> | null;
41
+ lastTransportSeq: number;
42
+ eventCount: number;
43
+ }
44
+
45
+ /**
46
+ * `@ai-matrx/agents/matrx` — the Matrx transport port.
47
+ *
48
+ * The ONE seam between this package's wire semantics and a host's connection
49
+ * policy. This package owns WHAT is said to the AI Matrx server — paths,
50
+ * methods, JSON bodies, streaming Accept headers, the `Last-Event-ID` cursor
51
+ * header — and the host owns HOW the connection is made:
52
+ *
53
+ * - base-URL / backend-channel resolution (global, sandbox override, local
54
+ * engine, EC2-dedicated — whatever ladder the host runs);
55
+ * - credentials (Supabase JWT `Authorization: Bearer`, guest
56
+ * `X-Fingerprint-ID`, or the API-key lane) — NEVER implemented here;
57
+ * - the `X-Organization-Id` context header;
58
+ * - retry policy, network-level timeouts, and diagnostics capture.
59
+ *
60
+ * A host implements the port in a few lines:
61
+ *
62
+ * ```ts
63
+ * const transport: MatrxTransport = {
64
+ * fetch: (path, init) =>
65
+ * fetch(`${baseUrl}${path}`, {
66
+ * ...init,
67
+ * headers: { ...init.headers, ...authHeaders() },
68
+ * }),
69
+ * };
70
+ * ```
71
+ *
72
+ * The port is deliberately structural and `fetch`-shaped so `@ai-matrx/data`'s
73
+ * `/api` transport can implement it without importing this package.
74
+ */
75
+ /**
76
+ * The request this package hands the port. A strict subset of `RequestInit`,
77
+ * so a host can spread it straight into `fetch`.
78
+ */
79
+ interface MatrxTransportRequest {
80
+ method: "GET" | "POST";
81
+ /**
82
+ * Wire-semantic headers the CALL requires (`Content-Type`, `Accept`,
83
+ * `Last-Event-ID`). The host merges its policy headers (auth, org) on top;
84
+ * it must not drop these.
85
+ */
86
+ headers: Record<string, string>;
87
+ /** Pre-serialized JSON body, present on POST calls that carry one. */
88
+ body?: string;
89
+ /** Caller cancellation. The host must wire it to the underlying fetch. */
90
+ signal?: AbortSignal;
91
+ }
92
+ /**
93
+ * The transport port. `path` is server-relative and always starts with `/`
94
+ * (`/ai/...`, `/runtime/...`); the host prepends its resolved base URL.
95
+ */
96
+ interface MatrxTransport {
97
+ fetch(path: string, init: MatrxTransportRequest): Promise<Response>;
98
+ }
99
+
100
+ /**
101
+ * The PRODUCTION `MatrxTransport` — the full connection pipeline every Matrx
102
+ * host used to hand-roll, moved in under C22 (THE HARD PARTS LIVE IN THE
103
+ * PACKAGE). A host constructs it from identity alone:
104
+ *
105
+ * ```ts
106
+ * const transport = createMatrxTransport({
107
+ * baseUrl: "https://server.app.matrxserver.com",
108
+ * credentials, // CredentialsPort (@ai-matrx/data)
109
+ * organizationId: () => activeOrgId, // omit for conversation-lane calls
110
+ * });
111
+ * ```
112
+ *
113
+ * Everything else is defaulted to the proven production values:
114
+ *
115
+ * - **timeouts** — connect 15s (for a non-streaming FastAPI handler this is
116
+ * effectively time-to-response), total UNCAPPED (the port cannot tell a JSON
117
+ * call from a long-lived NDJSON/SSE stream; the connect timeout is the JSON
118
+ * guard), via `@ai-matrx/data/net`'s `resilientFetch`;
119
+ * - **protocol** — the AI API version transform (`applyAiApiVersion`, default
120
+ * v2) + the loud v2 → v1 transport fallback (`./protocol`);
121
+ * - **credentials** — read fresh from the injected `CredentialsPort` on EVERY
122
+ * call, so a token refresh mid-run is picked up; mapped to headers by the
123
+ * ONE `credentialToHeaders`;
124
+ * - **org context** — the fail-closed `X-Organization-Id` binding
125
+ * (`./org-context`): configured lanes REQUIRE an org and refuse before the
126
+ * wire; unconfigured lanes (conversation-scoped calls, which carry org in
127
+ * the body) send none;
128
+ * - **error classification** — every failure normalizes through
129
+ * `normalizeMatrxError` into the ONE `MatrxCallError` envelope;
130
+ * - **diagnostics** — a typed sink the host wires to its capture/telemetry
131
+ * (`onRequest`, `onError`, `onProtocolDowngrade`); wiring it is optional,
132
+ * the transport works silently without it.
133
+ *
134
+ * Header merge order is part of the port contract: wire headers first
135
+ * (`Content-Type` / `Accept` / `Last-Event-ID` — the package's), then
136
+ * credentials, then resolver policy headers, then the org header. Policy
137
+ * headers never carry `Content-Type` — the wire owns it, and a policy
138
+ * `Content-Type` merged over a GET SSE call would corrupt the wire, so the
139
+ * factory strips it defensively.
140
+ */
141
+
142
+ /**
143
+ * The ONE classified error shape for Matrx client calls — the envelope hosts
144
+ * branch on instead of string-matching exceptions. Structurally compatible
145
+ * with matrx-frontend's `ApiCallError` by design.
146
+ */
147
+ interface MatrxCallError {
148
+ type: "auth_error" | "network_error" | "http_error" | "validation_error" | "abort_error" | "unknown";
149
+ message: string;
150
+ /** HTTP status code, if applicable. */
151
+ status?: number;
152
+ /** Raw error detail from the server (the parsed error body). */
153
+ serverDetail?: unknown;
154
+ /** Machine code preserved through normalization (server `code`, org-context code, …). */
155
+ code?: string;
156
+ /** Original exception identity for diagnostics. */
157
+ name?: string;
158
+ /** Original exception stack. */
159
+ stack?: string;
160
+ }
161
+
162
+ /**
163
+ * The conversation-start contract — client-minted `conversation_id`, `is_new`,
164
+ * `store` — typed exactly per the cross-repo System of Record
165
+ * (`common-docs/systems/agents/conversation-start-contract/FEATURE.md`;
166
+ * server truth `aidream/services/conversation_context/scope.py::
167
+ * ConversationStartRequest`).
168
+ *
169
+ * Every request that STARTS a conversation sends all three fields, no
170
+ * defaults:
171
+ *
172
+ * | `is_new` | `store` | Result |
173
+ * |----------|---------|----------------------------------------------------------|
174
+ * | true | true | Create the row with the caller's id — 409 if it exists |
175
+ * | true | false | No row. The id is correlation only (ephemeral run) |
176
+ * | false | true | Continue it — 404 if the caller doesn't own it |
177
+ * | false | false | Ephemeral run on a known id; nothing read, nothing written |
178
+ *
179
+ * `store` is the ONLY ephemeral signal; `is_new` is the caller's assertion
180
+ * about the id, never a persistence switch. `prior_messages` (the client-owned
181
+ * transcript of an ephemeral multi-turn run) is only valid with
182
+ * `store: false` — the union below makes the invalid combination
183
+ * unrepresentable, mirroring the server's 422.
184
+ *
185
+ * Continue routes (`POST /ai/conversations/{id}`) take the id from the path
186
+ * and do not carry this triple.
187
+ */
188
+ /** Recursive JSON value — the package's honest type for free-form wire bags. */
189
+ type MatrxJsonValue = string | number | boolean | null | MatrxJsonValue[] | {
190
+ [key: string]: MatrxJsonValue;
191
+ };
192
+ /** A JSON object on the wire. */
193
+ type MatrxJsonObject = {
194
+ [key: string]: MatrxJsonValue;
195
+ };
196
+ /**
197
+ * One LLM message on the request wire — `prior_messages` entries for
198
+ * stateless multi-turn runs. Mirrors aidream's `ChatMessageInput`
199
+ * (`aidream/schemas/messages.py`, `extra="allow"` — additional provider
200
+ * fields round-trip untouched).
201
+ */
202
+ interface MatrxChatMessage {
203
+ role: string;
204
+ content?: string | MatrxJsonValue[] | null;
205
+ name?: string | null;
206
+ tool_call_id?: string | null;
207
+ tool_calls?: MatrxJsonObject[] | null;
208
+ [extra: string]: MatrxJsonValue | undefined;
209
+ }
210
+ /** `is_new: true, store: true` — create the row with the caller's id. */
211
+ interface MatrxStoredConversationCreate {
212
+ conversation_id: string;
213
+ is_new: true;
214
+ store: true;
215
+ }
216
+ /** `is_new: false, store: true` — continue an owned stored conversation via a start route. */
217
+ interface MatrxStoredConversationContinue {
218
+ conversation_id: string;
219
+ is_new: false;
220
+ store: true;
221
+ }
222
+ /**
223
+ * `store: false` — ephemeral: nothing read, nothing written; the id is the
224
+ * caller's correlation handle. This is the ONLY member that may carry
225
+ * `prior_messages` (the server 422s a client transcript on a stored run).
226
+ */
227
+ interface MatrxEphemeralConversation {
228
+ conversation_id: string;
229
+ is_new: boolean;
230
+ store: false;
231
+ prior_messages?: MatrxChatMessage[];
232
+ }
233
+ /** The full conversation-start triple, one member per contract cell. */
234
+ type MatrxConversationStart = MatrxStoredConversationCreate | MatrxStoredConversationContinue | MatrxEphemeralConversation;
235
+
236
+ /**
237
+ * Canonical AI Matrx NDJSON wire kernel.
238
+ *
239
+ * This module is deliberately independent of React, Redux, Next.js, Supabase,
240
+ * and generated application types. Every Matrx client uses it to turn the
241
+ * backend's byte stream into the same normalized `{ event, data }` envelopes.
242
+ * Host runtimes remain responsible for HTTP/auth errors and for deciding what
243
+ * each event means in their state model.
244
+ */
245
+ interface MatrxStreamEnvelope<TData = unknown> {
246
+ event: string;
247
+ data: TData;
248
+ /** Monotonic transport sequence from full envelopes, when supplied. */
249
+ stream_seq?: number;
250
+ }
251
+ interface MatrxNdjsonIssue {
252
+ line: string;
253
+ error: unknown;
254
+ /** One-based physical NDJSON line number. */
255
+ lineNumber: number;
256
+ /** True when an unterminated trailing fragment was parsed by `finish()`. */
257
+ atCompletion: boolean;
258
+ }
259
+ interface MatrxStreamEnvelopeObservation {
260
+ /** Exact parsed JSON value before compact/full normalization. */
261
+ raw: unknown;
262
+ envelope: MatrxStreamEnvelope;
263
+ line: string;
264
+ lineNumber: number;
265
+ atCompletion: boolean;
266
+ }
267
+
268
+ /**
269
+ * Internal request plumbing for `@ai-matrx/agents/matrx`. Not part of the
270
+ * public surface — `matrx/index.ts` deliberately does not re-export this
271
+ * module. Everything here is pure: no globals, no work at import time.
272
+ */
273
+
274
+ /**
275
+ * Options for every streaming call, riding the NDJSON kernel's contract.
276
+ * Public via `./run`'s re-export.
277
+ */
278
+ interface MatrxStreamCallOptions {
279
+ /** Abort the fetch and end the events iterator. */
280
+ signal?: AbortSignal;
281
+ /** Bounded background read-ahead (see `stream/ndjson`). */
282
+ maxReadAhead?: number;
283
+ /** Malformed NDJSON is non-fatal but must never disappear silently. */
284
+ onMalformedLine?: (issue: MatrxNdjsonIssue) => void;
285
+ /** Valid JSON with no recognized Matrx envelope. */
286
+ onUnknownEnvelope?: (value: unknown) => void;
287
+ /** Observe every valid envelope in its exact wire form. */
288
+ onValidEnvelope?: (observation: MatrxStreamEnvelopeObservation) => void;
289
+ }
290
+
291
+ /**
292
+ * Agent run lifecycle against the AI Matrx API — start, continue, resume,
293
+ * cancel — over the `MatrxTransport` port, with every streaming response
294
+ * parsed through the package's ONE NDJSON wire kernel (`stream/ndjson`).
295
+ *
296
+ * Server truth (verified against aidream source):
297
+ * - `POST /ai/agents/{agent_id}` — start (`aidream/api/routers/agents.py`)
298
+ * - `POST /ai/conversations/{conversation_id}` — continue (`aidream/api/routers/conversations.py`)
299
+ * - `POST /ai/conversations/{conversation_id}/resume` — resume after
300
+ * client-delegated tool suspension (same router)
301
+ * - `POST /ai/cancel/{request_id}?mode=interrupt` — cancel (`aidream/api/routers/cancel.py`)
302
+ *
303
+ * Response headers arrive before the body: `X-Conversation-ID` and
304
+ * `X-Request-ID` are surfaced on the run handle immediately. `X-Request-ID`
305
+ * is the ONLY id the server accepts for cancel — a client-local id means
306
+ * nothing to it.
307
+ *
308
+ * Host policy stays out: no retry, no store, no timeouts, no persistence
309
+ * (C10: no-persistence). Cancellation is the caller's `AbortSignal`; a client
310
+ * disconnect never stops server work (`detach_on_disconnect`).
311
+ */
312
+
313
+ /**
314
+ * Stable identity of the durable entity whose saved context owns a run —
315
+ * the server reloads the row and uses ITS scope (`ContextAnchor`,
316
+ * `aidream/services/conversation_context/scope.py`).
317
+ */
318
+ interface MatrxContextAnchor {
319
+ resource_type: string;
320
+ resource_id: string;
321
+ }
322
+ /**
323
+ * Scope and source fields shared by every scoped request
324
+ * (`ScopedRequest` / `AcceptsInjectedScope` server-side). All optional here;
325
+ * the start request narrows `organization_id` to required.
326
+ */
327
+ interface MatrxRequestScope {
328
+ organization_id?: string;
329
+ project_id?: string | null;
330
+ task_id?: string | null;
331
+ /** Active context-scope ids from the client's global picker (membership-validated server-side). */
332
+ scope_ids?: string[] | null;
333
+ /** Active scope-TYPE ids — a type-level selection with no specific scope chosen. */
334
+ active_scope_type_ids?: string[] | null;
335
+ context_anchor?: MatrxContextAnchor | null;
336
+ /** Stable application slug that initiated the request. */
337
+ source_app?: string | null;
338
+ /** Stable feature slug within the source application. */
339
+ source_feature?: string | null;
340
+ /** "user" = a person directly triggered this; "auto" = client automation; omit for API callers. */
341
+ initiation?: "user" | "auto" | null;
342
+ /** Specific connected desktop instance allowed to claim delegated local tools. */
343
+ target_instance_id?: string | null;
344
+ }
345
+ /**
346
+ * Fields shared by start/continue turn requests (tool injection, client
347
+ * capability envelope, context object). The complex bags (`tools`, `client`,
348
+ * `user`, `config_overrides`) are typed as JSON objects — their authoritative
349
+ * schemas are the server's Pydantic models and the generated API types;
350
+ * this package stays payload-agnostic about them by design.
351
+ */
352
+ interface MatrxTurnFields {
353
+ /** What the human typed (string), or structured input parts. Never smuggle machine content here. */
354
+ user_input?: string | MatrxJsonValue[] | null;
355
+ /** Per-run model/config overrides (LLMParams shape). */
356
+ config_overrides?: MatrxJsonObject | null;
357
+ debug?: boolean;
358
+ /** Additive tool specs merged into the agent's resolved tool set. */
359
+ tools?: MatrxJsonObject[];
360
+ /** When set, becomes the agent's ENTIRE tool set for the turn. */
361
+ tools_replace?: MatrxJsonObject[] | null;
362
+ /** Client capability envelope (`ClientContext`). */
363
+ client?: MatrxJsonObject | null;
364
+ /** Per-request user-level tool inclusion/exclusion overrides. */
365
+ user?: MatrxJsonObject | null;
366
+ /** Per-route context object, free-form by design. */
367
+ context?: MatrxJsonObject;
368
+ writable_variables?: string[];
369
+ allow_context_create?: boolean;
370
+ /** Request-snapshot capture override (tri-state; omit for the platform default). */
371
+ snapshot?: boolean | null;
372
+ }
373
+ /**
374
+ * `POST /ai/agents/{agent_id}` body (`AgentStartRequest` server-side).
375
+ * The conversation-start triple is required by construction; `organization_id`
376
+ * is required (the server 422s a blank one — it never manufactures an org).
377
+ * `stream` is not accepted here: this client is the streaming path and always
378
+ * sends `stream: true`.
379
+ */
380
+ type MatrxAgentStartRequest = MatrxConversationStart & Omit<MatrxRequestScope, "organization_id"> & MatrxTurnFields & {
381
+ organization_id: string;
382
+ /** Variable name → value map filling the agent's declared variables. */
383
+ variables?: MatrxJsonObject | null;
384
+ /** Run the versions table row instead of the live agent row. */
385
+ is_version?: boolean;
386
+ max_iterations?: number;
387
+ max_retries_per_iteration?: number;
388
+ };
389
+ /** `POST /ai/conversations/{id}` body (`ConversationContinueRequest` server-side). */
390
+ type MatrxConversationContinueRequest = MatrxRequestScope & MatrxTurnFields & {
391
+ /** Re-run the conversation's current persisted state (recovery after a failed turn); omit `user_input`. */
392
+ retry?: boolean;
393
+ };
394
+ /** `POST /ai/cancel/{request_id}` response (`CancelResponse` server-side). */
395
+ interface MatrxCancelResponse {
396
+ status: string;
397
+ request_id: string;
398
+ spine_executions_signalled: string[];
399
+ }
400
+
401
+ /**
402
+ * Runtime operations — the canonical reconnect & resume read surface of the
403
+ * execution spine, over the `MatrxTransport` port.
404
+ *
405
+ * Server truth (verified against aidream source,
406
+ * `aidream/api/routers/runtime_operations.py` + `aidream/services/runtime/
407
+ * reconnect.py`; mounted at bare `/runtime`):
408
+ * - `GET /runtime/operations/{request_id}` — identify by `X-Request-ID`
409
+ * - `GET /runtime/operations/by-link/{kind}/{id}` — identify by feature record
410
+ * - `GET /runtime/executions/{id}/events` — durable seq-cursored page
411
+ * - `GET /runtime/executions/{id}/events/stream` — SSE replay-then-follow,
412
+ * `id:` = per-tree seq, reconnect with `Last-Event-ID`
413
+ * - `POST /runtime/operations/{request_id}/rejoin` — replay + follow the
414
+ * ORIGINAL NDJSON response while its detached task is alive (409 when live
415
+ * delivery is unavailable — fall back to the durable lifecycle stream)
416
+ *
417
+ * The contract: identify → recover durable progress → follow live → re-query
418
+ * the final result from the feature's own record. Token text is deliberately
419
+ * never replayed on the lifecycle stream — that is what `/rejoin` is for.
420
+ *
421
+ * The SSE wire rides the package's own `stream/sse` kernel. This module owns
422
+ * ONE connection's semantics (frames → typed events, cursor advancement,
423
+ * terminal `end`); stall timers, retry budgets, and reconnect loops stay host
424
+ * policy — every yielded item carries the cursor the next attempt resumes from.
425
+ */
426
+
427
+ /** `matrx_runtime.models.ExecutionStatus` — the only progress column. */
428
+ type MatrxRuntimeExecutionStatus = "pending" | "running" | "paused" | "waiting_input" | "completed" | "failed" | "cancelled";
429
+ /** One durable spine event on the wire (`OperationEvent`) — `seq` is the reconnect cursor. */
430
+ interface MatrxRuntimeOperationEvent {
431
+ seq: number | null;
432
+ /** Lifecycle vocabulary: created | started | paused | resumed | waiting_input | completed | failed | cancelled | checkpoint_saved | note. */
433
+ kind: string;
434
+ execution_id: string;
435
+ root_execution_id: string | null;
436
+ detail: MatrxJsonObject | null;
437
+ created_at: string | null;
438
+ }
439
+
440
+ /**
441
+ * `useAgentRun` — the package's run/stream hook: start, continue, and cancel
442
+ * an agent run over an injected `MatrxTransport`, with the streamed state
443
+ * exposed as the parity-proven request projection
444
+ * (`@ai-matrx/agents/projection/request` — the ONE event interpreter).
445
+ *
446
+ * The hook owns the whole loop the hosts used to hand-roll: the streaming
447
+ * call, folding every NDJSON envelope through `projectAgentEvent`, terminal
448
+ * status/error interpretation, unmount/stale-run teardown, and server-side
449
+ * cancel by the run's `X-Request-ID` (the ONLY id the cancel route accepts).
450
+ * The host injects only the transport — typically the production
451
+ * `createMatrxTransport` from `@ai-matrx/agents/matrx`.
452
+ */
453
+
454
+ type AgentRunPhase = "idle" | "starting" | "streaming" | "complete" | "error" | "cancelled";
455
+ interface UseAgentRunOptions {
456
+ /** The transport (or a per-run factory — resolved fresh at each start). */
457
+ transport: MatrxTransport | (() => MatrxTransport);
458
+ /** Stream-kernel knobs forwarded to every run (malformed-line hooks, read-ahead). */
459
+ streamOptions?: Omit<MatrxStreamCallOptions, "signal">;
460
+ /** Fired after every folded event with the fresh projection. */
461
+ onProjection?: (projection: AgentRequestProjection) => void;
462
+ /** Fired when a run fails, with the classified envelope. */
463
+ onError?: (error: MatrxCallError) => void;
464
+ }
465
+ interface UseAgentRun {
466
+ /** The lifecycle phase of the CURRENT run. */
467
+ phase: AgentRunPhase;
468
+ /** The live projection of the current run (null before the first start). */
469
+ projection: AgentRequestProjection | null;
470
+ /** Server-assigned `X-Request-ID` — feeds cancel and reconnect. */
471
+ requestId: string | null;
472
+ /** Server-assigned `X-Conversation-ID`. */
473
+ conversationId: string | null;
474
+ /** The classified failure of the current run, when phase is "error". */
475
+ error: MatrxCallError | null;
476
+ /** Start an agent run (`POST /ai/agents/{agent_id}`); resolves the final projection. */
477
+ start: (agentId: string, request: MatrxAgentStartRequest) => Promise<AgentRequestProjection>;
478
+ /** Continue a stored conversation (`POST /ai/conversations/{id}`); resolves the final projection. */
479
+ continueConversation: (conversationId: string, request: MatrxConversationContinueRequest) => Promise<AgentRequestProjection>;
480
+ /**
481
+ * Server-side cancel of the current run by its `X-Request-ID`.
482
+ * `mode: "interrupt"` = stop-and-fork. Resolves null when no run id is
483
+ * known yet. The stream stays open until the server ends it — everything
484
+ * already streamed persists.
485
+ */
486
+ cancel: (mode?: "cancel" | "interrupt") => Promise<MatrxCancelResponse | null>;
487
+ /** Abort the in-flight fetch/stream locally (server work continues by design). */
488
+ abort: () => void;
489
+ /** Clear state back to idle (aborts any in-flight run first). */
490
+ reset: () => void;
491
+ }
492
+ declare function useAgentRun(options: UseAgentRunOptions): UseAgentRun;
493
+
494
+ /**
495
+ * `useFollowRuntimeOperation` — the reconnect follower as a hook: follow one
496
+ * runtime operation's durable lifecycle stream
497
+ * (`GET /runtime/executions/{id}/events/stream`, `@ai-matrx/agents/stream/sse`
498
+ * under the hood) with the FULL production reconnect policy built in —
499
+ * stall watchdog, bounded retry budget, `Last-Event-ID` cursor — via
500
+ * `followRuntimeOperationToEnd`. Tuning knobs are typed and default to the
501
+ * proven production values (45s stall, 60 × 2s budget).
502
+ *
503
+ * The host injects the transport and what each event MEANS (`onEvent`);
504
+ * everything else is package policy.
505
+ */
506
+
507
+ interface UseFollowRuntimeOperationOptions {
508
+ /** The transport (typically the production `createMatrxTransport`). */
509
+ transport: MatrxTransport | (() => MatrxTransport);
510
+ /** The execution to follow — null/undefined idles the hook. */
511
+ executionId: string | null | undefined;
512
+ /** Resume cursor — the operation view's `last_event_seq` (0 = from start). */
513
+ lastEventSeq?: number;
514
+ /** Gate — false tears the follow down (default true when an id is set). */
515
+ enabled?: boolean;
516
+ /** Stall watchdog, ms. Default 45_000. */
517
+ stallTimeoutMs?: number;
518
+ /** Consecutive-failure budget. Default 60. */
519
+ reconnectLimit?: number;
520
+ /** Delay between attempts, ms. Default 2_000. */
521
+ reconnectDelayMs?: number;
522
+ /** Fired per durable spine event (lifecycle transitions + notes). */
523
+ onEvent?: (event: MatrxRuntimeOperationEvent, seq: number | null) => void;
524
+ /** Fired once when the follow settles (server `end`, exhausted budget, or teardown). */
525
+ onSettled?: (result: {
526
+ ended: boolean;
527
+ status: MatrxRuntimeExecutionStatus | null;
528
+ }) => void;
529
+ }
530
+ interface UseFollowRuntimeOperation {
531
+ /** True while a follow loop is live for the current execution. */
532
+ following: boolean;
533
+ /** True once the server sent the terminal `end` frame. */
534
+ ended: boolean;
535
+ /** The root status from the `end` frame, when ended. */
536
+ status: MatrxRuntimeExecutionStatus | null;
537
+ }
538
+ declare function useFollowRuntimeOperation(options: UseFollowRuntimeOperationOptions): UseFollowRuntimeOperation;
539
+
540
+ export { type AgentRunPhase, type UseAgentRun, type UseAgentRunOptions, type UseFollowRuntimeOperation, type UseFollowRuntimeOperationOptions, useAgentRun, useFollowRuntimeOperation };