@ai-matrx/agents 0.1.0 → 0.2.1

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.
@@ -0,0 +1,118 @@
1
+ 'use strict';
2
+
3
+ // projection/workflow.ts
4
+ var MAX_OPEN_FRAME_SETS = 32;
5
+ function createWorkflowNodeProjection(input) {
6
+ return {
7
+ runId: input.runId,
8
+ nodeId: input.nodeId,
9
+ answer: "",
10
+ reasoning: "",
11
+ blockShadowed: false,
12
+ renderBlocks: {},
13
+ renderBlockOrder: [],
14
+ openFrames: {},
15
+ chunksReceived: 0,
16
+ charsStreamed: 0,
17
+ lastStreamingTs: null,
18
+ lastPhase: null,
19
+ lastTool: null,
20
+ lastWarning: null,
21
+ lastTransportSeq: 0
22
+ };
23
+ }
24
+ function asRecord(value) {
25
+ return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
26
+ }
27
+ function asString(value) {
28
+ return typeof value === "string" ? value : null;
29
+ }
30
+ function asNumber(value) {
31
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
32
+ }
33
+ function toRenderBlock(value) {
34
+ const data = asRecord(value);
35
+ if (!data) return null;
36
+ const blockId = asString(data.blockId);
37
+ const blockIndex = asNumber(data.blockIndex);
38
+ const type = asString(data.type);
39
+ if (blockId === null || blockIndex === null || type === null) return null;
40
+ return {
41
+ blockId,
42
+ blockIndex,
43
+ type,
44
+ status: data.status === "complete" || data.status === "error" ? data.status : "streaming",
45
+ content: asString(data.content),
46
+ data: asRecord(data.data),
47
+ metadata: asRecord(data.metadata)
48
+ };
49
+ }
50
+ function projectRenderFrame(current, event, next) {
51
+ const frameId = event.frame_id;
52
+ const frameCount = event.frame_count ?? 1;
53
+ const frameIndex = event.frame_index ?? 0;
54
+ if (!frameId || frameCount < 1 || frameIndex < 0 || frameIndex >= frameCount) {
55
+ return next;
56
+ }
57
+ const prior = current.openFrames[frameId];
58
+ const set = {
59
+ frameCount,
60
+ slices: { ...prior?.frameCount === frameCount ? prior.slices : {}, [frameIndex]: event.delta }
61
+ };
62
+ const openFrames = { ...current.openFrames, [frameId]: set };
63
+ const keys = Object.keys(openFrames);
64
+ const oldestKey = keys[0];
65
+ if (keys.length > MAX_OPEN_FRAME_SETS && oldestKey !== void 0) {
66
+ delete openFrames[oldestKey];
67
+ }
68
+ if (Object.keys(set.slices).length !== frameCount) return { ...next, openFrames };
69
+ delete openFrames[frameId];
70
+ let block = null;
71
+ try {
72
+ block = toRenderBlock(JSON.parse(
73
+ Array.from({ length: frameCount }, (_, index) => set.slices[index] ?? "").join("")
74
+ ));
75
+ } catch {
76
+ return { ...next, openFrames };
77
+ }
78
+ if (!block) return { ...next, openFrames };
79
+ return {
80
+ ...next,
81
+ openFrames,
82
+ renderBlocks: { ...current.renderBlocks, [block.blockId]: block },
83
+ renderBlockOrder: Object.hasOwn(current.renderBlocks, block.blockId) ? current.renderBlockOrder : [...current.renderBlockOrder, block.blockId]
84
+ };
85
+ }
86
+ function projectWorkflowNodeEvent(current, event) {
87
+ if (event.run_id !== current.runId || (event.node_id ?? "") !== current.nodeId) return current;
88
+ if (event.stream_seq <= current.lastTransportSeq) return current;
89
+ const next = {
90
+ ...current,
91
+ chunksReceived: event.chunks_received,
92
+ charsStreamed: event.chars_streamed,
93
+ lastStreamingTs: event.ts,
94
+ lastTransportSeq: event.stream_seq,
95
+ blockShadowed: current.blockShadowed || Boolean(event.block_shadowed)
96
+ };
97
+ switch (event.kind) {
98
+ case "chunk":
99
+ return { ...next, answer: current.answer + event.delta };
100
+ case "reasoning":
101
+ return { ...next, reasoning: current.reasoning + event.delta };
102
+ case "phase":
103
+ return { ...next, lastPhase: event.delta };
104
+ case "tool":
105
+ return { ...next, lastTool: event.delta };
106
+ case "warning":
107
+ return { ...next, lastWarning: event.delta };
108
+ case "render_block":
109
+ return projectRenderFrame(current, event, next);
110
+ default:
111
+ return next;
112
+ }
113
+ }
114
+
115
+ exports.createWorkflowNodeProjection = createWorkflowNodeProjection;
116
+ exports.projectWorkflowNodeEvent = projectWorkflowNodeEvent;
117
+ //# sourceMappingURL=workflow.cjs.map
118
+ //# sourceMappingURL=workflow.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../projection/workflow.ts"],"names":[],"mappings":"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","file":"workflow.cjs","sourcesContent":["import type { AgentProjectionRenderBlock } from \"./request\";\n\nexport interface WorkflowNodeStreamEvent {\n run_id: string;\n node_id?: string | null;\n kind:\n | \"chunk\"\n | \"reasoning\"\n | \"phase\"\n | \"tool\"\n | \"warning\"\n | \"record_update\"\n | \"resource_changed\"\n | \"render_block\";\n delta: string;\n stream_seq: number;\n ts: string;\n chunks_received: number;\n chars_streamed: number;\n frame_id?: string | null;\n frame_index?: number;\n frame_count?: number;\n block_shadowed?: boolean;\n}\n\nexport interface WorkflowRenderFrameSet {\n frameCount: number;\n slices: Record<number, string>;\n}\n\nexport interface WorkflowNodeProjection {\n runId: string;\n nodeId: string;\n answer: string;\n reasoning: string;\n blockShadowed: boolean;\n renderBlocks: Record<string, AgentProjectionRenderBlock>;\n renderBlockOrder: string[];\n openFrames: Record<string, WorkflowRenderFrameSet>;\n chunksReceived: number;\n charsStreamed: number;\n lastStreamingTs: string | null;\n lastPhase: string | null;\n lastTool: string | null;\n lastWarning: string | null;\n lastTransportSeq: number;\n}\n\nconst MAX_OPEN_FRAME_SETS = 32;\n\nexport function createWorkflowNodeProjection(input: {\n runId: string;\n nodeId: string;\n}): WorkflowNodeProjection {\n return {\n runId: input.runId,\n nodeId: input.nodeId,\n answer: \"\",\n reasoning: \"\",\n blockShadowed: false,\n renderBlocks: {},\n renderBlockOrder: [],\n openFrames: {},\n chunksReceived: 0,\n charsStreamed: 0,\n lastStreamingTs: null,\n lastPhase: null,\n lastTool: null,\n lastWarning: null,\n lastTransportSeq: 0,\n };\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | null {\n return value !== null && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : null;\n}\n\nfunction asString(value: unknown): string | null {\n return typeof value === \"string\" ? value : null;\n}\n\nfunction asNumber(value: unknown): number | null {\n return typeof value === \"number\" && Number.isFinite(value) ? value : null;\n}\n\nfunction toRenderBlock(value: unknown): AgentProjectionRenderBlock | null {\n const data = asRecord(value);\n if (!data) return null;\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 null;\n return {\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: asRecord(data.data),\n metadata: asRecord(data.metadata),\n };\n}\n\nfunction projectRenderFrame(\n current: WorkflowNodeProjection,\n event: WorkflowNodeStreamEvent,\n next: WorkflowNodeProjection,\n): WorkflowNodeProjection {\n const frameId = event.frame_id;\n const frameCount = event.frame_count ?? 1;\n const frameIndex = event.frame_index ?? 0;\n if (!frameId || frameCount < 1 || frameIndex < 0 || frameIndex >= frameCount) {\n return next;\n }\n const prior = current.openFrames[frameId];\n const set: WorkflowRenderFrameSet = {\n frameCount,\n slices: { ...(prior?.frameCount === frameCount ? prior.slices : {}), [frameIndex]: event.delta },\n };\n const openFrames = { ...current.openFrames, [frameId]: set };\n const keys = Object.keys(openFrames);\n const oldestKey = keys[0];\n if (keys.length > MAX_OPEN_FRAME_SETS && oldestKey !== undefined) {\n delete openFrames[oldestKey];\n }\n if (Object.keys(set.slices).length !== frameCount) return { ...next, openFrames };\n\n delete openFrames[frameId];\n let block: AgentProjectionRenderBlock | null = null;\n try {\n block = toRenderBlock(JSON.parse(\n Array.from({ length: frameCount }, (_, index) => set.slices[index] ?? \"\").join(\"\"),\n ));\n } catch {\n return { ...next, openFrames };\n }\n if (!block) return { ...next, openFrames };\n return {\n ...next,\n openFrames,\n renderBlocks: { ...current.renderBlocks, [block.blockId]: block },\n renderBlockOrder: Object.hasOwn(current.renderBlocks, block.blockId)\n ? current.renderBlockOrder\n : [...current.renderBlockOrder, block.blockId],\n };\n}\n\nexport function projectWorkflowNodeEvent(\n current: WorkflowNodeProjection,\n event: WorkflowNodeStreamEvent,\n): WorkflowNodeProjection {\n if (event.run_id !== current.runId || (event.node_id ?? \"\") !== current.nodeId) return current;\n if (event.stream_seq <= current.lastTransportSeq) return current;\n const next: WorkflowNodeProjection = {\n ...current,\n chunksReceived: event.chunks_received,\n charsStreamed: event.chars_streamed,\n lastStreamingTs: event.ts,\n lastTransportSeq: event.stream_seq,\n blockShadowed: current.blockShadowed || Boolean(event.block_shadowed),\n };\n switch (event.kind) {\n case \"chunk\":\n return { ...next, answer: current.answer + event.delta };\n case \"reasoning\":\n return { ...next, reasoning: current.reasoning + event.delta };\n case \"phase\":\n return { ...next, lastPhase: event.delta };\n case \"tool\":\n return { ...next, lastTool: event.delta };\n case \"warning\":\n return { ...next, lastWarning: event.delta };\n case \"render_block\":\n return projectRenderFrame(current, event, next);\n default:\n return next;\n }\n}\n"]}
@@ -0,0 +1,44 @@
1
+ import { AgentProjectionRenderBlock } from './request.cjs';
2
+
3
+ interface WorkflowNodeStreamEvent {
4
+ run_id: string;
5
+ node_id?: string | null;
6
+ kind: "chunk" | "reasoning" | "phase" | "tool" | "warning" | "record_update" | "resource_changed" | "render_block";
7
+ delta: string;
8
+ stream_seq: number;
9
+ ts: string;
10
+ chunks_received: number;
11
+ chars_streamed: number;
12
+ frame_id?: string | null;
13
+ frame_index?: number;
14
+ frame_count?: number;
15
+ block_shadowed?: boolean;
16
+ }
17
+ interface WorkflowRenderFrameSet {
18
+ frameCount: number;
19
+ slices: Record<number, string>;
20
+ }
21
+ interface WorkflowNodeProjection {
22
+ runId: string;
23
+ nodeId: string;
24
+ answer: string;
25
+ reasoning: string;
26
+ blockShadowed: boolean;
27
+ renderBlocks: Record<string, AgentProjectionRenderBlock>;
28
+ renderBlockOrder: string[];
29
+ openFrames: Record<string, WorkflowRenderFrameSet>;
30
+ chunksReceived: number;
31
+ charsStreamed: number;
32
+ lastStreamingTs: string | null;
33
+ lastPhase: string | null;
34
+ lastTool: string | null;
35
+ lastWarning: string | null;
36
+ lastTransportSeq: number;
37
+ }
38
+ declare function createWorkflowNodeProjection(input: {
39
+ runId: string;
40
+ nodeId: string;
41
+ }): WorkflowNodeProjection;
42
+ declare function projectWorkflowNodeEvent(current: WorkflowNodeProjection, event: WorkflowNodeStreamEvent): WorkflowNodeProjection;
43
+
44
+ export { type WorkflowNodeProjection, type WorkflowNodeStreamEvent, type WorkflowRenderFrameSet, createWorkflowNodeProjection, projectWorkflowNodeEvent };
@@ -0,0 +1,44 @@
1
+ import { AgentProjectionRenderBlock } from './request.js';
2
+
3
+ interface WorkflowNodeStreamEvent {
4
+ run_id: string;
5
+ node_id?: string | null;
6
+ kind: "chunk" | "reasoning" | "phase" | "tool" | "warning" | "record_update" | "resource_changed" | "render_block";
7
+ delta: string;
8
+ stream_seq: number;
9
+ ts: string;
10
+ chunks_received: number;
11
+ chars_streamed: number;
12
+ frame_id?: string | null;
13
+ frame_index?: number;
14
+ frame_count?: number;
15
+ block_shadowed?: boolean;
16
+ }
17
+ interface WorkflowRenderFrameSet {
18
+ frameCount: number;
19
+ slices: Record<number, string>;
20
+ }
21
+ interface WorkflowNodeProjection {
22
+ runId: string;
23
+ nodeId: string;
24
+ answer: string;
25
+ reasoning: string;
26
+ blockShadowed: boolean;
27
+ renderBlocks: Record<string, AgentProjectionRenderBlock>;
28
+ renderBlockOrder: string[];
29
+ openFrames: Record<string, WorkflowRenderFrameSet>;
30
+ chunksReceived: number;
31
+ charsStreamed: number;
32
+ lastStreamingTs: string | null;
33
+ lastPhase: string | null;
34
+ lastTool: string | null;
35
+ lastWarning: string | null;
36
+ lastTransportSeq: number;
37
+ }
38
+ declare function createWorkflowNodeProjection(input: {
39
+ runId: string;
40
+ nodeId: string;
41
+ }): WorkflowNodeProjection;
42
+ declare function projectWorkflowNodeEvent(current: WorkflowNodeProjection, event: WorkflowNodeStreamEvent): WorkflowNodeProjection;
43
+
44
+ export { type WorkflowNodeProjection, type WorkflowNodeStreamEvent, type WorkflowRenderFrameSet, createWorkflowNodeProjection, projectWorkflowNodeEvent };
@@ -0,0 +1,115 @@
1
+ // projection/workflow.ts
2
+ var MAX_OPEN_FRAME_SETS = 32;
3
+ function createWorkflowNodeProjection(input) {
4
+ return {
5
+ runId: input.runId,
6
+ nodeId: input.nodeId,
7
+ answer: "",
8
+ reasoning: "",
9
+ blockShadowed: false,
10
+ renderBlocks: {},
11
+ renderBlockOrder: [],
12
+ openFrames: {},
13
+ chunksReceived: 0,
14
+ charsStreamed: 0,
15
+ lastStreamingTs: null,
16
+ lastPhase: null,
17
+ lastTool: null,
18
+ lastWarning: null,
19
+ lastTransportSeq: 0
20
+ };
21
+ }
22
+ function asRecord(value) {
23
+ return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
24
+ }
25
+ function asString(value) {
26
+ return typeof value === "string" ? value : null;
27
+ }
28
+ function asNumber(value) {
29
+ return typeof value === "number" && Number.isFinite(value) ? value : null;
30
+ }
31
+ function toRenderBlock(value) {
32
+ const data = asRecord(value);
33
+ if (!data) return null;
34
+ const blockId = asString(data.blockId);
35
+ const blockIndex = asNumber(data.blockIndex);
36
+ const type = asString(data.type);
37
+ if (blockId === null || blockIndex === null || type === null) return null;
38
+ return {
39
+ blockId,
40
+ blockIndex,
41
+ type,
42
+ status: data.status === "complete" || data.status === "error" ? data.status : "streaming",
43
+ content: asString(data.content),
44
+ data: asRecord(data.data),
45
+ metadata: asRecord(data.metadata)
46
+ };
47
+ }
48
+ function projectRenderFrame(current, event, next) {
49
+ const frameId = event.frame_id;
50
+ const frameCount = event.frame_count ?? 1;
51
+ const frameIndex = event.frame_index ?? 0;
52
+ if (!frameId || frameCount < 1 || frameIndex < 0 || frameIndex >= frameCount) {
53
+ return next;
54
+ }
55
+ const prior = current.openFrames[frameId];
56
+ const set = {
57
+ frameCount,
58
+ slices: { ...prior?.frameCount === frameCount ? prior.slices : {}, [frameIndex]: event.delta }
59
+ };
60
+ const openFrames = { ...current.openFrames, [frameId]: set };
61
+ const keys = Object.keys(openFrames);
62
+ const oldestKey = keys[0];
63
+ if (keys.length > MAX_OPEN_FRAME_SETS && oldestKey !== void 0) {
64
+ delete openFrames[oldestKey];
65
+ }
66
+ if (Object.keys(set.slices).length !== frameCount) return { ...next, openFrames };
67
+ delete openFrames[frameId];
68
+ let block = null;
69
+ try {
70
+ block = toRenderBlock(JSON.parse(
71
+ Array.from({ length: frameCount }, (_, index) => set.slices[index] ?? "").join("")
72
+ ));
73
+ } catch {
74
+ return { ...next, openFrames };
75
+ }
76
+ if (!block) return { ...next, openFrames };
77
+ return {
78
+ ...next,
79
+ openFrames,
80
+ renderBlocks: { ...current.renderBlocks, [block.blockId]: block },
81
+ renderBlockOrder: Object.hasOwn(current.renderBlocks, block.blockId) ? current.renderBlockOrder : [...current.renderBlockOrder, block.blockId]
82
+ };
83
+ }
84
+ function projectWorkflowNodeEvent(current, event) {
85
+ if (event.run_id !== current.runId || (event.node_id ?? "") !== current.nodeId) return current;
86
+ if (event.stream_seq <= current.lastTransportSeq) return current;
87
+ const next = {
88
+ ...current,
89
+ chunksReceived: event.chunks_received,
90
+ charsStreamed: event.chars_streamed,
91
+ lastStreamingTs: event.ts,
92
+ lastTransportSeq: event.stream_seq,
93
+ blockShadowed: current.blockShadowed || Boolean(event.block_shadowed)
94
+ };
95
+ switch (event.kind) {
96
+ case "chunk":
97
+ return { ...next, answer: current.answer + event.delta };
98
+ case "reasoning":
99
+ return { ...next, reasoning: current.reasoning + event.delta };
100
+ case "phase":
101
+ return { ...next, lastPhase: event.delta };
102
+ case "tool":
103
+ return { ...next, lastTool: event.delta };
104
+ case "warning":
105
+ return { ...next, lastWarning: event.delta };
106
+ case "render_block":
107
+ return projectRenderFrame(current, event, next);
108
+ default:
109
+ return next;
110
+ }
111
+ }
112
+
113
+ export { createWorkflowNodeProjection, projectWorkflowNodeEvent };
114
+ //# sourceMappingURL=workflow.js.map
115
+ //# sourceMappingURL=workflow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../projection/workflow.ts"],"names":[],"mappings":"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","file":"workflow.js","sourcesContent":["import type { AgentProjectionRenderBlock } from \"./request\";\n\nexport interface WorkflowNodeStreamEvent {\n run_id: string;\n node_id?: string | null;\n kind:\n | \"chunk\"\n | \"reasoning\"\n | \"phase\"\n | \"tool\"\n | \"warning\"\n | \"record_update\"\n | \"resource_changed\"\n | \"render_block\";\n delta: string;\n stream_seq: number;\n ts: string;\n chunks_received: number;\n chars_streamed: number;\n frame_id?: string | null;\n frame_index?: number;\n frame_count?: number;\n block_shadowed?: boolean;\n}\n\nexport interface WorkflowRenderFrameSet {\n frameCount: number;\n slices: Record<number, string>;\n}\n\nexport interface WorkflowNodeProjection {\n runId: string;\n nodeId: string;\n answer: string;\n reasoning: string;\n blockShadowed: boolean;\n renderBlocks: Record<string, AgentProjectionRenderBlock>;\n renderBlockOrder: string[];\n openFrames: Record<string, WorkflowRenderFrameSet>;\n chunksReceived: number;\n charsStreamed: number;\n lastStreamingTs: string | null;\n lastPhase: string | null;\n lastTool: string | null;\n lastWarning: string | null;\n lastTransportSeq: number;\n}\n\nconst MAX_OPEN_FRAME_SETS = 32;\n\nexport function createWorkflowNodeProjection(input: {\n runId: string;\n nodeId: string;\n}): WorkflowNodeProjection {\n return {\n runId: input.runId,\n nodeId: input.nodeId,\n answer: \"\",\n reasoning: \"\",\n blockShadowed: false,\n renderBlocks: {},\n renderBlockOrder: [],\n openFrames: {},\n chunksReceived: 0,\n charsStreamed: 0,\n lastStreamingTs: null,\n lastPhase: null,\n lastTool: null,\n lastWarning: null,\n lastTransportSeq: 0,\n };\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | null {\n return value !== null && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : null;\n}\n\nfunction asString(value: unknown): string | null {\n return typeof value === \"string\" ? value : null;\n}\n\nfunction asNumber(value: unknown): number | null {\n return typeof value === \"number\" && Number.isFinite(value) ? value : null;\n}\n\nfunction toRenderBlock(value: unknown): AgentProjectionRenderBlock | null {\n const data = asRecord(value);\n if (!data) return null;\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 null;\n return {\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: asRecord(data.data),\n metadata: asRecord(data.metadata),\n };\n}\n\nfunction projectRenderFrame(\n current: WorkflowNodeProjection,\n event: WorkflowNodeStreamEvent,\n next: WorkflowNodeProjection,\n): WorkflowNodeProjection {\n const frameId = event.frame_id;\n const frameCount = event.frame_count ?? 1;\n const frameIndex = event.frame_index ?? 0;\n if (!frameId || frameCount < 1 || frameIndex < 0 || frameIndex >= frameCount) {\n return next;\n }\n const prior = current.openFrames[frameId];\n const set: WorkflowRenderFrameSet = {\n frameCount,\n slices: { ...(prior?.frameCount === frameCount ? prior.slices : {}), [frameIndex]: event.delta },\n };\n const openFrames = { ...current.openFrames, [frameId]: set };\n const keys = Object.keys(openFrames);\n const oldestKey = keys[0];\n if (keys.length > MAX_OPEN_FRAME_SETS && oldestKey !== undefined) {\n delete openFrames[oldestKey];\n }\n if (Object.keys(set.slices).length !== frameCount) return { ...next, openFrames };\n\n delete openFrames[frameId];\n let block: AgentProjectionRenderBlock | null = null;\n try {\n block = toRenderBlock(JSON.parse(\n Array.from({ length: frameCount }, (_, index) => set.slices[index] ?? \"\").join(\"\"),\n ));\n } catch {\n return { ...next, openFrames };\n }\n if (!block) return { ...next, openFrames };\n return {\n ...next,\n openFrames,\n renderBlocks: { ...current.renderBlocks, [block.blockId]: block },\n renderBlockOrder: Object.hasOwn(current.renderBlocks, block.blockId)\n ? current.renderBlockOrder\n : [...current.renderBlockOrder, block.blockId],\n };\n}\n\nexport function projectWorkflowNodeEvent(\n current: WorkflowNodeProjection,\n event: WorkflowNodeStreamEvent,\n): WorkflowNodeProjection {\n if (event.run_id !== current.runId || (event.node_id ?? \"\") !== current.nodeId) return current;\n if (event.stream_seq <= current.lastTransportSeq) return current;\n const next: WorkflowNodeProjection = {\n ...current,\n chunksReceived: event.chunks_received,\n charsStreamed: event.chars_streamed,\n lastStreamingTs: event.ts,\n lastTransportSeq: event.stream_seq,\n blockShadowed: current.blockShadowed || Boolean(event.block_shadowed),\n };\n switch (event.kind) {\n case \"chunk\":\n return { ...next, answer: current.answer + event.delta };\n case \"reasoning\":\n return { ...next, reasoning: current.reasoning + event.delta };\n case \"phase\":\n return { ...next, lastPhase: event.delta };\n case \"tool\":\n return { ...next, lastTool: event.delta };\n case \"warning\":\n return { ...next, lastWarning: event.delta };\n case \"render_block\":\n return projectRenderFrame(current, event, next);\n default:\n return next;\n }\n}\n"]}
@@ -0,0 +1,99 @@
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
+ exports.normalizeMatrxStreamEnvelope = normalizeMatrxStreamEnvelope;
97
+ exports.readMatrxNdjsonStream = readMatrxNdjsonStream;
98
+ //# sourceMappingURL=ndjson.cjs.map
99
+ //# sourceMappingURL=ndjson.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../stream/ndjson.ts"],"names":[],"mappings":"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","file":"ndjson.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"]}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Canonical AI Matrx NDJSON wire kernel.
3
+ *
4
+ * This module is deliberately independent of React, Redux, Next.js, Supabase,
5
+ * and generated application types. Every Matrx client uses it to turn the
6
+ * backend's byte stream into the same normalized `{ event, data }` envelopes.
7
+ * Host runtimes remain responsible for HTTP/auth errors and for deciding what
8
+ * each event means in their state model.
9
+ */
10
+ interface MatrxStreamEnvelope<TData = unknown> {
11
+ event: string;
12
+ data: TData;
13
+ }
14
+ interface MatrxNdjsonIssue {
15
+ line: string;
16
+ error: unknown;
17
+ }
18
+ interface ReadMatrxNdjsonOptions {
19
+ signal?: AbortSignal;
20
+ /** Malformed JSON is non-fatal, but it must never disappear silently. */
21
+ onMalformedLine?: (issue: MatrxNdjsonIssue) => void;
22
+ /** Valid JSON with no recognized Matrx event envelope is also non-fatal. */
23
+ onUnknownEnvelope?: (value: unknown) => void;
24
+ }
25
+ /**
26
+ * Normalize both supported Matrx wire shapes:
27
+ *
28
+ * - full: `{ "event": "chunk", "data": { "text": "..." } }`
29
+ * - compact chunk: `{ "e": "c", "t": "..." }`
30
+ * - compact reasoning: `{ "e": "r", "t": "..." }`
31
+ */
32
+ declare function normalizeMatrxStreamEnvelope(value: unknown): MatrxStreamEnvelope | null;
33
+ /**
34
+ * Read and normalize a Matrx NDJSON response body without applying consumer
35
+ * backpressure to the network reader. The background read-ahead is important:
36
+ * large tool payloads must keep draining even while React or another host is
37
+ * processing the previous event.
38
+ */
39
+ declare function readMatrxNdjsonStream(body: ReadableStream<Uint8Array>, options?: ReadMatrxNdjsonOptions): AsyncGenerator<MatrxStreamEnvelope, void, undefined>;
40
+
41
+ export { type MatrxNdjsonIssue, type MatrxStreamEnvelope, type ReadMatrxNdjsonOptions, normalizeMatrxStreamEnvelope, readMatrxNdjsonStream };
package/package.json CHANGED
@@ -1,8 +1,11 @@
1
1
  {
2
2
  "name": "@ai-matrx/agents",
3
- "version": "0.1.0",
4
- "description": "Portable AI Matrx agent stream protocol and safe result-presentation primitives.",
3
+ "version": "0.2.1",
4
+ "description": "Portable AI Matrx agent stream protocol, event projection, and safe result-presentation primitives.",
5
5
  "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
6
9
  "license": "MIT",
7
10
  "keywords": [
8
11
  "agents",
@@ -27,16 +30,54 @@
27
30
  ],
28
31
  "exports": {
29
32
  ".": {
30
- "types": "./dist/index.d.ts",
31
- "import": "./dist/index.js"
33
+ "import": {
34
+ "types": "./dist/index.d.ts",
35
+ "default": "./dist/index.js"
36
+ },
37
+ "require": {
38
+ "types": "./dist/index.d.cts",
39
+ "default": "./dist/index.cjs"
40
+ }
32
41
  },
33
42
  "./stream/ndjson": {
34
- "types": "./dist/stream/ndjson.d.ts",
35
- "import": "./dist/stream/ndjson.js"
43
+ "import": {
44
+ "types": "./dist/stream/ndjson.d.ts",
45
+ "default": "./dist/stream/ndjson.js"
46
+ },
47
+ "require": {
48
+ "types": "./dist/stream/ndjson.d.cts",
49
+ "default": "./dist/stream/ndjson.cjs"
50
+ }
36
51
  },
37
52
  "./presentation/result": {
38
- "types": "./dist/presentation/result.d.ts",
39
- "import": "./dist/presentation/result.js"
53
+ "import": {
54
+ "types": "./dist/presentation/result.d.ts",
55
+ "default": "./dist/presentation/result.js"
56
+ },
57
+ "require": {
58
+ "types": "./dist/presentation/result.d.cts",
59
+ "default": "./dist/presentation/result.cjs"
60
+ }
61
+ },
62
+ "./projection/request": {
63
+ "import": {
64
+ "types": "./dist/projection/request.d.ts",
65
+ "default": "./dist/projection/request.js"
66
+ },
67
+ "require": {
68
+ "types": "./dist/projection/request.d.cts",
69
+ "default": "./dist/projection/request.cjs"
70
+ }
71
+ },
72
+ "./projection/workflow": {
73
+ "import": {
74
+ "types": "./dist/projection/workflow.d.ts",
75
+ "default": "./dist/projection/workflow.js"
76
+ },
77
+ "require": {
78
+ "types": "./dist/projection/workflow.d.cts",
79
+ "default": "./dist/projection/workflow.cjs"
80
+ }
40
81
  },
41
82
  "./package.json": "./package.json"
42
83
  },
@@ -50,7 +91,6 @@
50
91
  },
51
92
  "publishConfig": {
52
93
  "access": "public",
53
- "provenance": true,
54
94
  "registry": "https://registry.npmjs.org/"
55
95
  },
56
96
  "engines": {