@ai-matrx/agents 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.2.0 — 2026-08-22
4
+
5
+ - Added a framework-free request event projector for identity, status, answer/reasoning, phases, operations, tools, render blocks, Content IR metadata, completion, and errors.
6
+ - Added golden lifecycle fixtures, replay suppression, and copy-on-write guarantees.
7
+ - Added conditional ESM/CommonJS artifacts and loader canaries for mixed Vite, Next.js, and Jest consumers.
8
+
3
9
  ## 0.1.0 — 2026-08-22
4
10
 
5
11
  - Published the canonical NDJSON stream reader and envelope normalizer.
package/dist/index.cjs ADDED
@@ -0,0 +1,366 @@
1
+ 'use strict';
2
+
3
+ // stream/ndjson.ts
4
+ function isRecord(value) {
5
+ return typeof value === "object" && value !== null && !Array.isArray(value);
6
+ }
7
+ function normalizeMatrxStreamEnvelope(value) {
8
+ if (!isRecord(value)) return null;
9
+ if (typeof value.event === "string") {
10
+ return { event: value.event, data: value.data };
11
+ }
12
+ if (value.e === "c" && typeof value.t === "string") {
13
+ return { event: "chunk", data: { text: value.t } };
14
+ }
15
+ if (value.e === "r" && typeof value.t === "string") {
16
+ return { event: "reasoning_chunk", data: { text: value.t } };
17
+ }
18
+ return null;
19
+ }
20
+ async function* readMatrxNdjsonStream(body, options = {}) {
21
+ const queue = [];
22
+ let wakeConsumer = null;
23
+ let readerFinished = false;
24
+ const enqueue = (item) => {
25
+ queue.push(item);
26
+ const wake = wakeConsumer;
27
+ wakeConsumer = null;
28
+ wake?.();
29
+ };
30
+ const reader = body.getReader();
31
+ const decoder = new TextDecoder();
32
+ const parseLine = (line) => {
33
+ const trimmed = line.trim();
34
+ if (!trimmed) return;
35
+ let parsed;
36
+ try {
37
+ parsed = JSON.parse(trimmed);
38
+ } catch (error) {
39
+ options.onMalformedLine?.({ line: trimmed, error });
40
+ return;
41
+ }
42
+ const envelope = normalizeMatrxStreamEnvelope(parsed);
43
+ if (envelope) {
44
+ enqueue({ kind: "event", value: envelope });
45
+ } else {
46
+ options.onUnknownEnvelope?.(parsed);
47
+ }
48
+ };
49
+ const onAbort = () => {
50
+ void reader.cancel(options.signal?.reason).catch(() => void 0);
51
+ };
52
+ options.signal?.addEventListener("abort", onAbort, { once: true });
53
+ const readerPromise = (async () => {
54
+ let buffer = "";
55
+ try {
56
+ while (!options.signal?.aborted) {
57
+ const { value, done } = await reader.read();
58
+ if (done) break;
59
+ buffer += decoder.decode(value, { stream: true });
60
+ const lines = buffer.split("\n");
61
+ buffer = lines.pop() ?? "";
62
+ for (const line of lines) parseLine(line);
63
+ }
64
+ buffer += decoder.decode();
65
+ if (!options.signal?.aborted && buffer.trim()) parseLine(buffer);
66
+ } catch (error) {
67
+ const aborted = options.signal?.aborted || error instanceof Error && error.name === "AbortError";
68
+ if (!aborted) enqueue({ kind: "error", error });
69
+ } finally {
70
+ readerFinished = true;
71
+ reader.releaseLock();
72
+ enqueue({ kind: "done" });
73
+ }
74
+ })();
75
+ try {
76
+ while (true) {
77
+ if (queue.length === 0) {
78
+ await new Promise((resolve) => {
79
+ wakeConsumer = resolve;
80
+ });
81
+ }
82
+ const item = queue.shift();
83
+ if (!item || item.kind === "done") return;
84
+ if (item.kind === "error") throw item.error;
85
+ yield item.value;
86
+ }
87
+ } finally {
88
+ options.signal?.removeEventListener("abort", onAbort);
89
+ if (!readerFinished) {
90
+ await reader.cancel().catch(() => void 0);
91
+ }
92
+ await readerPromise;
93
+ }
94
+ }
95
+
96
+ // presentation/result.ts
97
+ var PRIVATE_REASONING_TYPES = /* @__PURE__ */ new Set([
98
+ "thinking",
99
+ "redacted_thinking",
100
+ "reasoning"
101
+ ]);
102
+ var PRIVATE_PROVIDER_KEYS = /* @__PURE__ */ new Set([
103
+ "thought_signature",
104
+ "thoughtSignature",
105
+ "google_thought_signature",
106
+ "anthropic_signature",
107
+ "encrypted_content",
108
+ "signature_encoding"
109
+ ]);
110
+ var SIGNATURE_PROVIDERS = /* @__PURE__ */ new Set([
111
+ "anthropic",
112
+ "google",
113
+ "openai"
114
+ ]);
115
+ var OPAQUE_SIGNATURE_MIN_LENGTH = 200;
116
+ var OMIT = /* @__PURE__ */ Symbol("omit-provider-private-value");
117
+ function isRecord2(value) {
118
+ return typeof value === "object" && value !== null && !Array.isArray(value);
119
+ }
120
+ function isPrivateReasoningBlock(value) {
121
+ return typeof value.type === "string" && PRIVATE_REASONING_TYPES.has(value.type.toLowerCase());
122
+ }
123
+ function isPrivateProviderKey(key, value, parent) {
124
+ if (PRIVATE_PROVIDER_KEYS.has(key)) return true;
125
+ if (key !== "signature") return false;
126
+ const provider = typeof parent.provider === "string" ? parent.provider.toLowerCase() : "";
127
+ return "signature_encoding" in parent || SIGNATURE_PROVIDERS.has(provider) || typeof value === "string" && value.length >= OPAQUE_SIGNATURE_MIN_LENGTH;
128
+ }
129
+ function project(value) {
130
+ if (Array.isArray(value)) {
131
+ let changed2 = false;
132
+ const output2 = [];
133
+ for (const item of value) {
134
+ const projected = project(item);
135
+ if (projected === OMIT) {
136
+ changed2 = true;
137
+ continue;
138
+ }
139
+ if (projected !== item) changed2 = true;
140
+ output2.push(projected);
141
+ }
142
+ return changed2 ? output2 : value;
143
+ }
144
+ if (!isRecord2(value)) return value;
145
+ if (isPrivateReasoningBlock(value)) return OMIT;
146
+ let changed = false;
147
+ const output = {};
148
+ for (const [key, child] of Object.entries(value)) {
149
+ if (isPrivateProviderKey(key, child, value)) {
150
+ changed = true;
151
+ continue;
152
+ }
153
+ const projected = project(child);
154
+ if (projected === OMIT) {
155
+ changed = true;
156
+ continue;
157
+ }
158
+ if (projected !== child) changed = true;
159
+ output[key] = projected;
160
+ }
161
+ return changed ? output : value;
162
+ }
163
+ function projectAgentResultForDisplay(value) {
164
+ const projected = project(value);
165
+ return projected === OMIT ? null : projected;
166
+ }
167
+
168
+ // projection/request.ts
169
+ var asRecord = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
170
+ var asString = (value) => typeof value === "string" ? value : null;
171
+ var asNumber = (value) => typeof value === "number" && Number.isFinite(value) ? value : null;
172
+ function createAgentRequestProjection(input) {
173
+ return {
174
+ requestId: input.requestId,
175
+ conversationId: input.conversationId ?? null,
176
+ status: "pending",
177
+ answer: "",
178
+ reasoning: "",
179
+ reasoningActive: false,
180
+ phase: null,
181
+ phaseHistory: [],
182
+ operations: {},
183
+ tools: {},
184
+ renderBlocks: {},
185
+ renderBlockOrder: [],
186
+ completion: null,
187
+ error: null,
188
+ lastTransportSeq: 0,
189
+ eventCount: 0
190
+ };
191
+ }
192
+ function toolStatus(event) {
193
+ switch (event) {
194
+ case "tool_started":
195
+ return "started";
196
+ case "tool_step":
197
+ return "step";
198
+ case "tool_result_preview":
199
+ return "preview";
200
+ case "tool_completed":
201
+ return "completed";
202
+ case "tool_error":
203
+ return "error";
204
+ case "tool_delegated":
205
+ return "delegated";
206
+ default:
207
+ return "progress";
208
+ }
209
+ }
210
+ function projectAgentEvent(current, event) {
211
+ const streamSeq = asNumber(event.stream_seq);
212
+ if (streamSeq !== null && streamSeq <= current.lastTransportSeq) return current;
213
+ const data = asRecord(event.data);
214
+ const next = {
215
+ ...current,
216
+ status: current.status === "pending" ? "streaming" : current.status,
217
+ lastTransportSeq: streamSeq ?? current.lastTransportSeq,
218
+ eventCount: current.eventCount + 1
219
+ };
220
+ switch (event.event) {
221
+ case "chunk": {
222
+ const text = asString(data.text);
223
+ return text === null ? next : { ...next, answer: current.answer + text };
224
+ }
225
+ case "reasoning_chunk": {
226
+ const text = asString(data.text);
227
+ return text === null ? next : {
228
+ ...next,
229
+ reasoning: current.reasoning + text,
230
+ reasoningActive: true
231
+ };
232
+ }
233
+ case "reasoning":
234
+ return {
235
+ ...next,
236
+ reasoningActive: data.state === "started"
237
+ };
238
+ case "phase": {
239
+ const phase = asString(data.phase);
240
+ if (phase === null) return next;
241
+ return {
242
+ ...next,
243
+ phase,
244
+ phaseHistory: [...current.phaseHistory, phase]
245
+ };
246
+ }
247
+ case "init": {
248
+ const operationId = asString(data.operation_id);
249
+ const operation = asString(data.operation);
250
+ if (operationId === null || operation === null) return next;
251
+ return {
252
+ ...next,
253
+ operations: {
254
+ ...current.operations,
255
+ [operationId]: {
256
+ operationId,
257
+ operation,
258
+ parentOperationId: asString(data.parent_operation_id),
259
+ status: "active",
260
+ metadata: Object.keys(asRecord(data.metadata)).length ? asRecord(data.metadata) : null,
261
+ result: null
262
+ }
263
+ }
264
+ };
265
+ }
266
+ case "completion": {
267
+ const operationId = asString(data.operation_id);
268
+ const operation = asString(data.operation);
269
+ const rawStatus = asString(data.status);
270
+ const status = rawStatus === "failed" || rawStatus === "cancelled" ? rawStatus : "success";
271
+ const result = asRecord(data.result);
272
+ const operations = operationId ? {
273
+ ...current.operations,
274
+ [operationId]: {
275
+ ...current.operations[operationId] ?? {
276
+ operationId,
277
+ operation: operation ?? "unknown",
278
+ parentOperationId: null,
279
+ metadata: null
280
+ },
281
+ status,
282
+ result
283
+ }
284
+ } : current.operations;
285
+ if (operation === "user_request") {
286
+ return {
287
+ ...next,
288
+ operations,
289
+ completion: data,
290
+ status: status === "success" ? "complete" : status === "cancelled" ? "cancelled" : "error"
291
+ };
292
+ }
293
+ return { ...next, operations };
294
+ }
295
+ case "tool_event": {
296
+ const callId = asString(data.call_id);
297
+ const toolName = asString(data.tool_name);
298
+ const lifecycle = asString(data.event);
299
+ if (callId === null || toolName === null || lifecycle === null) return next;
300
+ const status = toolStatus(lifecycle);
301
+ return {
302
+ ...next,
303
+ status: status === "started" || status === "delegated" ? "awaiting-tools" : status === "completed" || status === "error" ? "streaming" : next.status,
304
+ tools: {
305
+ ...current.tools,
306
+ [callId]: {
307
+ callId,
308
+ toolName,
309
+ status,
310
+ message: asString(data.message),
311
+ data: Object.keys(asRecord(data.data)).length ? asRecord(data.data) : null
312
+ }
313
+ }
314
+ };
315
+ }
316
+ case "render_block": {
317
+ const blockId = asString(data.blockId);
318
+ const blockIndex = asNumber(data.blockIndex);
319
+ const type = asString(data.type);
320
+ if (blockId === null || blockIndex === null || type === null) return next;
321
+ const alreadyKnown = Object.hasOwn(current.renderBlocks, blockId);
322
+ return {
323
+ ...next,
324
+ renderBlocks: {
325
+ ...current.renderBlocks,
326
+ [blockId]: {
327
+ blockId,
328
+ blockIndex,
329
+ type,
330
+ status: data.status === "complete" || data.status === "error" ? data.status : "streaming",
331
+ content: asString(data.content),
332
+ data: Object.keys(asRecord(data.data)).length ? asRecord(data.data) : null,
333
+ metadata: Object.keys(asRecord(data.metadata)).length ? asRecord(data.metadata) : null
334
+ }
335
+ },
336
+ renderBlockOrder: alreadyKnown ? current.renderBlockOrder : [...current.renderBlockOrder, blockId]
337
+ };
338
+ }
339
+ case "error":
340
+ return { ...next, status: "error", error: data };
341
+ case "end":
342
+ return {
343
+ ...next,
344
+ status: current.status === "error" || current.status === "cancelled" ? current.status : "complete",
345
+ reasoningActive: false
346
+ };
347
+ case "data": {
348
+ const conversationId = data.type === "conversation_id" ? asString(data.conversation_id) : null;
349
+ return conversationId === null ? next : { ...next, conversationId };
350
+ }
351
+ default:
352
+ return next;
353
+ }
354
+ }
355
+ function projectAgentEvents(initial, events) {
356
+ return events.reduce(projectAgentEvent, initial);
357
+ }
358
+
359
+ exports.createAgentRequestProjection = createAgentRequestProjection;
360
+ exports.normalizeMatrxStreamEnvelope = normalizeMatrxStreamEnvelope;
361
+ exports.projectAgentEvent = projectAgentEvent;
362
+ exports.projectAgentEvents = projectAgentEvents;
363
+ exports.projectAgentResultForDisplay = projectAgentResultForDisplay;
364
+ exports.readMatrxNdjsonStream = readMatrxNdjsonStream;
365
+ //# sourceMappingURL=index.cjs.map
366
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../stream/ndjson.ts","../presentation/result.ts","../projection/request.ts"],"names":["isRecord","changed","output"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Canonical AI Matrx NDJSON wire kernel.\n *\n * This module is deliberately independent of React, Redux, Next.js, Supabase,\n * and generated application types. Every Matrx client uses it to turn the\n * backend's byte stream into the same normalized `{ event, data }` envelopes.\n * Host runtimes remain responsible for HTTP/auth errors and for deciding what\n * each event means in their state model.\n */\n\nexport interface MatrxStreamEnvelope<TData = unknown> {\n event: string;\n data: TData;\n}\n\nexport interface MatrxNdjsonIssue {\n line: string;\n error: unknown;\n}\n\nexport interface ReadMatrxNdjsonOptions {\n signal?: AbortSignal;\n /** Malformed JSON is non-fatal, but it must never disappear silently. */\n onMalformedLine?: (issue: MatrxNdjsonIssue) => void;\n /** Valid JSON with no recognized Matrx event envelope is also non-fatal. */\n onUnknownEnvelope?: (value: unknown) => void;\n}\n\ntype QueueItem =\n | { kind: \"event\"; value: MatrxStreamEnvelope }\n | { kind: \"error\"; error: unknown }\n | { kind: \"done\" };\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/**\n * Normalize both supported Matrx wire shapes:\n *\n * - full: `{ \"event\": \"chunk\", \"data\": { \"text\": \"...\" } }`\n * - compact chunk: `{ \"e\": \"c\", \"t\": \"...\" }`\n * - compact reasoning: `{ \"e\": \"r\", \"t\": \"...\" }`\n */\nexport function normalizeMatrxStreamEnvelope(\n value: unknown,\n): MatrxStreamEnvelope | null {\n if (!isRecord(value)) return null;\n\n if (typeof value.event === \"string\") {\n return { event: value.event, data: value.data };\n }\n if (value.e === \"c\" && typeof value.t === \"string\") {\n return { event: \"chunk\", data: { text: value.t } };\n }\n if (value.e === \"r\" && typeof value.t === \"string\") {\n return { event: \"reasoning_chunk\", data: { text: value.t } };\n }\n return null;\n}\n\n/**\n * Read and normalize a Matrx NDJSON response body without applying consumer\n * backpressure to the network reader. The background read-ahead is important:\n * large tool payloads must keep draining even while React or another host is\n * processing the previous event.\n */\nexport async function* readMatrxNdjsonStream(\n body: ReadableStream<Uint8Array>,\n options: ReadMatrxNdjsonOptions = {},\n): AsyncGenerator<MatrxStreamEnvelope, void, undefined> {\n const queue: QueueItem[] = [];\n let wakeConsumer: (() => void) | null = null;\n let readerFinished = false;\n\n const enqueue = (item: QueueItem): void => {\n queue.push(item);\n const wake = wakeConsumer;\n wakeConsumer = null;\n wake?.();\n };\n\n const reader = body.getReader();\n const decoder = new TextDecoder();\n\n const parseLine = (line: string): void => {\n const trimmed = line.trim();\n if (!trimmed) return;\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(trimmed) as unknown;\n } catch (error) {\n options.onMalformedLine?.({ line: trimmed, error });\n return;\n }\n\n const envelope = normalizeMatrxStreamEnvelope(parsed);\n if (envelope) {\n enqueue({ kind: \"event\", value: envelope });\n } else {\n options.onUnknownEnvelope?.(parsed);\n }\n };\n\n const onAbort = (): void => {\n void reader.cancel(options.signal?.reason).catch(() => undefined);\n };\n options.signal?.addEventListener(\"abort\", onAbort, { once: true });\n\n const readerPromise = (async (): Promise<void> => {\n let buffer = \"\";\n try {\n while (!options.signal?.aborted) {\n const { value, done } = await reader.read();\n if (done) break;\n\n buffer += decoder.decode(value, { stream: true });\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop() ?? \"\";\n for (const line of lines) parseLine(line);\n }\n\n buffer += decoder.decode();\n if (!options.signal?.aborted && buffer.trim()) parseLine(buffer);\n } catch (error) {\n const aborted =\n options.signal?.aborted ||\n (error instanceof Error && error.name === \"AbortError\");\n if (!aborted) enqueue({ kind: \"error\", error });\n } finally {\n readerFinished = true;\n reader.releaseLock();\n enqueue({ kind: \"done\" });\n }\n })();\n\n try {\n while (true) {\n if (queue.length === 0) {\n await new Promise<void>((resolve) => {\n wakeConsumer = resolve;\n });\n }\n\n const item = queue.shift();\n if (!item || item.kind === \"done\") return;\n if (item.kind === \"error\") throw item.error;\n yield item.value;\n }\n } finally {\n options.signal?.removeEventListener(\"abort\", onAbort);\n if (!readerFinished) {\n await reader.cancel().catch(() => undefined);\n }\n await readerPromise;\n }\n}\n","/**\n * Creator-facing projection of an agent execution result.\n *\n * Provider reasoning blocks and their signatures are replay material, not\n * workflow data. The execution engine must retain them so a later turn can be\n * continued correctly, but no result renderer, JSON tab, clipboard export, or\n * Content IR classifier should receive them as displayable values.\n *\n * This is a pure copy-on-write projection: values without private material\n * keep their original reference, while affected branches are cloned. Never\n * feed the projected value back into execution or persistence.\n */\n\nconst PRIVATE_REASONING_TYPES: ReadonlySet<string> = new Set([\n \"thinking\",\n \"redacted_thinking\",\n \"reasoning\",\n]);\n\nconst PRIVATE_PROVIDER_KEYS: ReadonlySet<string> = new Set([\n \"thought_signature\",\n \"thoughtSignature\",\n \"google_thought_signature\",\n \"anthropic_signature\",\n \"encrypted_content\",\n \"signature_encoding\",\n]);\n\nconst SIGNATURE_PROVIDERS: ReadonlySet<string> = new Set([\n \"anthropic\",\n \"google\",\n \"openai\",\n]);\n\nconst OPAQUE_SIGNATURE_MIN_LENGTH = 200;\nconst OMIT = Symbol(\"omit-provider-private-value\");\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isPrivateReasoningBlock(value: Record<string, unknown>): boolean {\n return (\n typeof value.type === \"string\" &&\n PRIVATE_REASONING_TYPES.has(value.type.toLowerCase())\n );\n}\n\nfunction isPrivateProviderKey(\n key: string,\n value: unknown,\n parent: Record<string, unknown>,\n): boolean {\n if (PRIVATE_PROVIDER_KEYS.has(key)) return true;\n if (key !== \"signature\") return false;\n\n const provider =\n typeof parent.provider === \"string\" ? parent.provider.toLowerCase() : \"\";\n return (\n \"signature_encoding\" in parent ||\n SIGNATURE_PROVIDERS.has(provider) ||\n (typeof value === \"string\" && value.length >= OPAQUE_SIGNATURE_MIN_LENGTH)\n );\n}\n\nfunction project(value: unknown): unknown | typeof OMIT {\n if (Array.isArray(value)) {\n let changed = false;\n const output: unknown[] = [];\n for (const item of value) {\n const projected = project(item);\n if (projected === OMIT) {\n changed = true;\n continue;\n }\n if (projected !== item) changed = true;\n output.push(projected);\n }\n return changed ? output : value;\n }\n\n if (!isRecord(value)) return value;\n if (isPrivateReasoningBlock(value)) return OMIT;\n\n let changed = false;\n const output: Record<string, unknown> = {};\n for (const [key, child] of Object.entries(value)) {\n if (isPrivateProviderKey(key, child, value)) {\n changed = true;\n continue;\n }\n const projected = project(child);\n if (projected === OMIT) {\n changed = true;\n continue;\n }\n if (projected !== child) changed = true;\n output[key] = projected;\n }\n return changed ? output : value;\n}\n\n/**\n * Remove provider-private reasoning material from a value crossing a\n * Creator-facing presentation or export boundary.\n */\nexport function projectAgentResultForDisplay(value: unknown): unknown {\n const projected = project(value);\n return projected === OMIT ? null : projected;\n}\n","export type AgentProjectionStatus =\n | \"pending\"\n | \"streaming\"\n | \"awaiting-tools\"\n | \"complete\"\n | \"error\"\n | \"cancelled\";\n\nexport interface AgentProjectionOperation {\n operationId: string;\n operation: string;\n parentOperationId: string | null;\n status: \"active\" | \"success\" | \"failed\" | \"cancelled\";\n metadata: Record<string, unknown> | null;\n result: Record<string, unknown> | null;\n}\n\nexport interface AgentProjectionTool {\n callId: string;\n toolName: string;\n status:\n | \"started\"\n | \"progress\"\n | \"step\"\n | \"preview\"\n | \"completed\"\n | \"error\"\n | \"delegated\";\n message: string | null;\n data: Record<string, unknown> | null;\n}\n\nexport interface AgentProjectionRenderBlock {\n blockId: string;\n blockIndex: number;\n type: string;\n status: \"streaming\" | \"complete\" | \"error\";\n content: string | null;\n data: Record<string, unknown> | null;\n metadata: Record<string, unknown> | null;\n}\n\nexport interface AgentRequestProjection {\n requestId: string;\n conversationId: string | null;\n status: AgentProjectionStatus;\n answer: string;\n reasoning: string;\n reasoningActive: boolean;\n phase: string | null;\n phaseHistory: string[];\n operations: Record<string, AgentProjectionOperation>;\n tools: Record<string, AgentProjectionTool>;\n renderBlocks: Record<string, AgentProjectionRenderBlock>;\n renderBlockOrder: string[];\n completion: Record<string, unknown> | null;\n error: Record<string, unknown> | null;\n lastTransportSeq: number;\n eventCount: number;\n}\n\nexport interface AgentProjectionEvent {\n event: string;\n data?: unknown;\n stream_seq?: number;\n}\n\nconst asRecord = (value: unknown): Record<string, unknown> =>\n value !== null && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : {};\n\nconst asString = (value: unknown): string | null =>\n typeof value === \"string\" ? value : null;\n\nconst asNumber = (value: unknown): number | null =>\n typeof value === \"number\" && Number.isFinite(value) ? value : null;\n\nexport function createAgentRequestProjection(input: {\n requestId: string;\n conversationId?: string | null;\n}): AgentRequestProjection {\n return {\n requestId: input.requestId,\n conversationId: input.conversationId ?? null,\n status: \"pending\",\n answer: \"\",\n reasoning: \"\",\n reasoningActive: false,\n phase: null,\n phaseHistory: [],\n operations: {},\n tools: {},\n renderBlocks: {},\n renderBlockOrder: [],\n completion: null,\n error: null,\n lastTransportSeq: 0,\n eventCount: 0,\n };\n}\n\nfunction toolStatus(event: string): AgentProjectionTool[\"status\"] {\n switch (event) {\n case \"tool_started\":\n return \"started\";\n case \"tool_step\":\n return \"step\";\n case \"tool_result_preview\":\n return \"preview\";\n case \"tool_completed\":\n return \"completed\";\n case \"tool_error\":\n return \"error\";\n case \"tool_delegated\":\n return \"delegated\";\n default:\n return \"progress\";\n }\n}\n\nexport function projectAgentEvent(\n current: AgentRequestProjection,\n event: AgentProjectionEvent,\n): AgentRequestProjection {\n const streamSeq = asNumber(event.stream_seq);\n if (streamSeq !== null && streamSeq <= current.lastTransportSeq) return current;\n\n const data = asRecord(event.data);\n const next: AgentRequestProjection = {\n ...current,\n status: current.status === \"pending\" ? \"streaming\" : current.status,\n lastTransportSeq: streamSeq ?? current.lastTransportSeq,\n eventCount: current.eventCount + 1,\n };\n\n switch (event.event) {\n case \"chunk\": {\n const text = asString(data.text);\n return text === null ? next : { ...next, answer: current.answer + text };\n }\n case \"reasoning_chunk\": {\n const text = asString(data.text);\n return text === null\n ? next\n : {\n ...next,\n reasoning: current.reasoning + text,\n reasoningActive: true,\n };\n }\n case \"reasoning\":\n return {\n ...next,\n reasoningActive: data.state === \"started\",\n };\n case \"phase\": {\n const phase = asString(data.phase);\n if (phase === null) return next;\n return {\n ...next,\n phase,\n phaseHistory: [...current.phaseHistory, phase],\n };\n }\n case \"init\": {\n const operationId = asString(data.operation_id);\n const operation = asString(data.operation);\n if (operationId === null || operation === null) return next;\n return {\n ...next,\n operations: {\n ...current.operations,\n [operationId]: {\n operationId,\n operation,\n parentOperationId: asString(data.parent_operation_id),\n status: \"active\",\n metadata: Object.keys(asRecord(data.metadata)).length\n ? asRecord(data.metadata)\n : null,\n result: null,\n },\n },\n };\n }\n case \"completion\": {\n const operationId = asString(data.operation_id);\n const operation = asString(data.operation);\n const rawStatus = asString(data.status);\n const status: AgentProjectionOperation[\"status\"] =\n rawStatus === \"failed\" || rawStatus === \"cancelled\"\n ? rawStatus\n : \"success\";\n const result = asRecord(data.result);\n const operations = operationId\n ? {\n ...current.operations,\n [operationId]: {\n ...(current.operations[operationId] ?? {\n operationId,\n operation: operation ?? \"unknown\",\n parentOperationId: null,\n metadata: null,\n }),\n status,\n result,\n },\n }\n : current.operations;\n if (operation === \"user_request\") {\n return {\n ...next,\n operations,\n completion: data,\n status:\n status === \"success\"\n ? \"complete\"\n : status === \"cancelled\"\n ? \"cancelled\"\n : \"error\",\n };\n }\n return { ...next, operations };\n }\n case \"tool_event\": {\n const callId = asString(data.call_id);\n const toolName = asString(data.tool_name);\n const lifecycle = asString(data.event);\n if (callId === null || toolName === null || lifecycle === null) return next;\n const status = toolStatus(lifecycle);\n return {\n ...next,\n status:\n status === \"started\" || status === \"delegated\"\n ? \"awaiting-tools\"\n : status === \"completed\" || status === \"error\"\n ? \"streaming\"\n : next.status,\n tools: {\n ...current.tools,\n [callId]: {\n callId,\n toolName,\n status,\n message: asString(data.message),\n data: Object.keys(asRecord(data.data)).length ? asRecord(data.data) : null,\n },\n },\n };\n }\n case \"render_block\": {\n const blockId = asString(data.blockId);\n const blockIndex = asNumber(data.blockIndex);\n const type = asString(data.type);\n if (blockId === null || blockIndex === null || type === null) return next;\n const alreadyKnown = Object.hasOwn(current.renderBlocks, blockId);\n return {\n ...next,\n renderBlocks: {\n ...current.renderBlocks,\n [blockId]: {\n blockId,\n blockIndex,\n type,\n status:\n data.status === \"complete\" || data.status === \"error\"\n ? data.status\n : \"streaming\",\n content: asString(data.content),\n data: Object.keys(asRecord(data.data)).length ? asRecord(data.data) : null,\n metadata: Object.keys(asRecord(data.metadata)).length\n ? asRecord(data.metadata)\n : null,\n },\n },\n renderBlockOrder: alreadyKnown\n ? current.renderBlockOrder\n : [...current.renderBlockOrder, blockId],\n };\n }\n case \"error\":\n return { ...next, status: \"error\", error: data };\n case \"end\":\n return {\n ...next,\n status:\n current.status === \"error\" || current.status === \"cancelled\"\n ? current.status\n : \"complete\",\n reasoningActive: false,\n };\n case \"data\": {\n const conversationId =\n data.type === \"conversation_id\" ? asString(data.conversation_id) : null;\n return conversationId === null ? next : { ...next, conversationId };\n }\n default:\n return next;\n }\n}\n\nexport function projectAgentEvents(\n initial: AgentRequestProjection,\n events: readonly AgentProjectionEvent[],\n): AgentRequestProjection {\n return events.reduce(projectAgentEvent, initial);\n}\n"]}
@@ -0,0 +1,3 @@
1
+ export { MatrxNdjsonIssue, MatrxStreamEnvelope, ReadMatrxNdjsonOptions, normalizeMatrxStreamEnvelope, readMatrxNdjsonStream } from './stream/ndjson.cjs';
2
+ export { projectAgentResultForDisplay } from './presentation/result.cjs';
3
+ export { AgentProjectionEvent, AgentProjectionOperation, AgentProjectionRenderBlock, AgentProjectionStatus, AgentProjectionTool, AgentRequestProjection, createAgentRequestProjection, projectAgentEvent, projectAgentEvents } from './projection/request.cjs';
package/dist/index.d.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  export { MatrxNdjsonIssue, MatrxStreamEnvelope, ReadMatrxNdjsonOptions, normalizeMatrxStreamEnvelope, readMatrxNdjsonStream } from './stream/ndjson.js';
2
2
  export { projectAgentResultForDisplay } from './presentation/result.js';
3
+ export { AgentProjectionEvent, AgentProjectionOperation, AgentProjectionRenderBlock, AgentProjectionStatus, AgentProjectionTool, AgentRequestProjection, createAgentRequestProjection, projectAgentEvent, projectAgentEvents } from './projection/request.js';
package/dist/index.js CHANGED
@@ -163,6 +163,197 @@ function projectAgentResultForDisplay(value) {
163
163
  return projected === OMIT ? null : projected;
164
164
  }
165
165
 
166
- export { normalizeMatrxStreamEnvelope, projectAgentResultForDisplay, readMatrxNdjsonStream };
166
+ // projection/request.ts
167
+ var asRecord = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
168
+ var asString = (value) => typeof value === "string" ? value : null;
169
+ var asNumber = (value) => typeof value === "number" && Number.isFinite(value) ? value : null;
170
+ function createAgentRequestProjection(input) {
171
+ return {
172
+ requestId: input.requestId,
173
+ conversationId: input.conversationId ?? null,
174
+ status: "pending",
175
+ answer: "",
176
+ reasoning: "",
177
+ reasoningActive: false,
178
+ phase: null,
179
+ phaseHistory: [],
180
+ operations: {},
181
+ tools: {},
182
+ renderBlocks: {},
183
+ renderBlockOrder: [],
184
+ completion: null,
185
+ error: null,
186
+ lastTransportSeq: 0,
187
+ eventCount: 0
188
+ };
189
+ }
190
+ function toolStatus(event) {
191
+ switch (event) {
192
+ case "tool_started":
193
+ return "started";
194
+ case "tool_step":
195
+ return "step";
196
+ case "tool_result_preview":
197
+ return "preview";
198
+ case "tool_completed":
199
+ return "completed";
200
+ case "tool_error":
201
+ return "error";
202
+ case "tool_delegated":
203
+ return "delegated";
204
+ default:
205
+ return "progress";
206
+ }
207
+ }
208
+ function projectAgentEvent(current, event) {
209
+ const streamSeq = asNumber(event.stream_seq);
210
+ if (streamSeq !== null && streamSeq <= current.lastTransportSeq) return current;
211
+ const data = asRecord(event.data);
212
+ const next = {
213
+ ...current,
214
+ status: current.status === "pending" ? "streaming" : current.status,
215
+ lastTransportSeq: streamSeq ?? current.lastTransportSeq,
216
+ eventCount: current.eventCount + 1
217
+ };
218
+ switch (event.event) {
219
+ case "chunk": {
220
+ const text = asString(data.text);
221
+ return text === null ? next : { ...next, answer: current.answer + text };
222
+ }
223
+ case "reasoning_chunk": {
224
+ const text = asString(data.text);
225
+ return text === null ? next : {
226
+ ...next,
227
+ reasoning: current.reasoning + text,
228
+ reasoningActive: true
229
+ };
230
+ }
231
+ case "reasoning":
232
+ return {
233
+ ...next,
234
+ reasoningActive: data.state === "started"
235
+ };
236
+ case "phase": {
237
+ const phase = asString(data.phase);
238
+ if (phase === null) return next;
239
+ return {
240
+ ...next,
241
+ phase,
242
+ phaseHistory: [...current.phaseHistory, phase]
243
+ };
244
+ }
245
+ case "init": {
246
+ const operationId = asString(data.operation_id);
247
+ const operation = asString(data.operation);
248
+ if (operationId === null || operation === null) return next;
249
+ return {
250
+ ...next,
251
+ operations: {
252
+ ...current.operations,
253
+ [operationId]: {
254
+ operationId,
255
+ operation,
256
+ parentOperationId: asString(data.parent_operation_id),
257
+ status: "active",
258
+ metadata: Object.keys(asRecord(data.metadata)).length ? asRecord(data.metadata) : null,
259
+ result: null
260
+ }
261
+ }
262
+ };
263
+ }
264
+ case "completion": {
265
+ const operationId = asString(data.operation_id);
266
+ const operation = asString(data.operation);
267
+ const rawStatus = asString(data.status);
268
+ const status = rawStatus === "failed" || rawStatus === "cancelled" ? rawStatus : "success";
269
+ const result = asRecord(data.result);
270
+ const operations = operationId ? {
271
+ ...current.operations,
272
+ [operationId]: {
273
+ ...current.operations[operationId] ?? {
274
+ operationId,
275
+ operation: operation ?? "unknown",
276
+ parentOperationId: null,
277
+ metadata: null
278
+ },
279
+ status,
280
+ result
281
+ }
282
+ } : current.operations;
283
+ if (operation === "user_request") {
284
+ return {
285
+ ...next,
286
+ operations,
287
+ completion: data,
288
+ status: status === "success" ? "complete" : status === "cancelled" ? "cancelled" : "error"
289
+ };
290
+ }
291
+ return { ...next, operations };
292
+ }
293
+ case "tool_event": {
294
+ const callId = asString(data.call_id);
295
+ const toolName = asString(data.tool_name);
296
+ const lifecycle = asString(data.event);
297
+ if (callId === null || toolName === null || lifecycle === null) return next;
298
+ const status = toolStatus(lifecycle);
299
+ return {
300
+ ...next,
301
+ status: status === "started" || status === "delegated" ? "awaiting-tools" : status === "completed" || status === "error" ? "streaming" : next.status,
302
+ tools: {
303
+ ...current.tools,
304
+ [callId]: {
305
+ callId,
306
+ toolName,
307
+ status,
308
+ message: asString(data.message),
309
+ data: Object.keys(asRecord(data.data)).length ? asRecord(data.data) : null
310
+ }
311
+ }
312
+ };
313
+ }
314
+ case "render_block": {
315
+ const blockId = asString(data.blockId);
316
+ const blockIndex = asNumber(data.blockIndex);
317
+ const type = asString(data.type);
318
+ if (blockId === null || blockIndex === null || type === null) return next;
319
+ const alreadyKnown = Object.hasOwn(current.renderBlocks, blockId);
320
+ return {
321
+ ...next,
322
+ renderBlocks: {
323
+ ...current.renderBlocks,
324
+ [blockId]: {
325
+ blockId,
326
+ blockIndex,
327
+ type,
328
+ status: data.status === "complete" || data.status === "error" ? data.status : "streaming",
329
+ content: asString(data.content),
330
+ data: Object.keys(asRecord(data.data)).length ? asRecord(data.data) : null,
331
+ metadata: Object.keys(asRecord(data.metadata)).length ? asRecord(data.metadata) : null
332
+ }
333
+ },
334
+ renderBlockOrder: alreadyKnown ? current.renderBlockOrder : [...current.renderBlockOrder, blockId]
335
+ };
336
+ }
337
+ case "error":
338
+ return { ...next, status: "error", error: data };
339
+ case "end":
340
+ return {
341
+ ...next,
342
+ status: current.status === "error" || current.status === "cancelled" ? current.status : "complete",
343
+ reasoningActive: false
344
+ };
345
+ case "data": {
346
+ const conversationId = data.type === "conversation_id" ? asString(data.conversation_id) : null;
347
+ return conversationId === null ? next : { ...next, conversationId };
348
+ }
349
+ default:
350
+ return next;
351
+ }
352
+ }
353
+ function projectAgentEvents(initial, events) {
354
+ return events.reduce(projectAgentEvent, initial);
355
+ }
356
+
357
+ export { createAgentRequestProjection, normalizeMatrxStreamEnvelope, projectAgentEvent, projectAgentEvents, projectAgentResultForDisplay, readMatrxNdjsonStream };
167
358
  //# sourceMappingURL=index.js.map
168
359
  //# sourceMappingURL=index.js.map