@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 +6 -0
- package/dist/index.cjs +366 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +3 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +192 -1
- package/dist/index.js.map +1 -1
- package/dist/presentation/result.cjs +77 -0
- package/dist/presentation/result.cjs.map +1 -0
- package/dist/presentation/result.d.cts +19 -0
- package/dist/projection/request.cjs +198 -0
- package/dist/projection/request.cjs.map +1 -0
- package/dist/projection/request.d.cts +56 -0
- package/dist/projection/request.d.ts +56 -0
- package/dist/projection/request.js +194 -0
- package/dist/projection/request.js.map +1 -0
- package/dist/stream/ndjson.cjs +99 -0
- package/dist/stream/ndjson.cjs.map +1 -0
- package/dist/stream/ndjson.d.cts +41 -0
- package/package.json +39 -9
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
// projection/request.ts
|
|
2
|
+
var asRecord = (value) => value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
3
|
+
var asString = (value) => typeof value === "string" ? value : null;
|
|
4
|
+
var asNumber = (value) => typeof value === "number" && Number.isFinite(value) ? value : null;
|
|
5
|
+
function createAgentRequestProjection(input) {
|
|
6
|
+
return {
|
|
7
|
+
requestId: input.requestId,
|
|
8
|
+
conversationId: input.conversationId ?? null,
|
|
9
|
+
status: "pending",
|
|
10
|
+
answer: "",
|
|
11
|
+
reasoning: "",
|
|
12
|
+
reasoningActive: false,
|
|
13
|
+
phase: null,
|
|
14
|
+
phaseHistory: [],
|
|
15
|
+
operations: {},
|
|
16
|
+
tools: {},
|
|
17
|
+
renderBlocks: {},
|
|
18
|
+
renderBlockOrder: [],
|
|
19
|
+
completion: null,
|
|
20
|
+
error: null,
|
|
21
|
+
lastTransportSeq: 0,
|
|
22
|
+
eventCount: 0
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
function toolStatus(event) {
|
|
26
|
+
switch (event) {
|
|
27
|
+
case "tool_started":
|
|
28
|
+
return "started";
|
|
29
|
+
case "tool_step":
|
|
30
|
+
return "step";
|
|
31
|
+
case "tool_result_preview":
|
|
32
|
+
return "preview";
|
|
33
|
+
case "tool_completed":
|
|
34
|
+
return "completed";
|
|
35
|
+
case "tool_error":
|
|
36
|
+
return "error";
|
|
37
|
+
case "tool_delegated":
|
|
38
|
+
return "delegated";
|
|
39
|
+
default:
|
|
40
|
+
return "progress";
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
function projectAgentEvent(current, event) {
|
|
44
|
+
const streamSeq = asNumber(event.stream_seq);
|
|
45
|
+
if (streamSeq !== null && streamSeq <= current.lastTransportSeq) return current;
|
|
46
|
+
const data = asRecord(event.data);
|
|
47
|
+
const next = {
|
|
48
|
+
...current,
|
|
49
|
+
status: current.status === "pending" ? "streaming" : current.status,
|
|
50
|
+
lastTransportSeq: streamSeq ?? current.lastTransportSeq,
|
|
51
|
+
eventCount: current.eventCount + 1
|
|
52
|
+
};
|
|
53
|
+
switch (event.event) {
|
|
54
|
+
case "chunk": {
|
|
55
|
+
const text = asString(data.text);
|
|
56
|
+
return text === null ? next : { ...next, answer: current.answer + text };
|
|
57
|
+
}
|
|
58
|
+
case "reasoning_chunk": {
|
|
59
|
+
const text = asString(data.text);
|
|
60
|
+
return text === null ? next : {
|
|
61
|
+
...next,
|
|
62
|
+
reasoning: current.reasoning + text,
|
|
63
|
+
reasoningActive: true
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
case "reasoning":
|
|
67
|
+
return {
|
|
68
|
+
...next,
|
|
69
|
+
reasoningActive: data.state === "started"
|
|
70
|
+
};
|
|
71
|
+
case "phase": {
|
|
72
|
+
const phase = asString(data.phase);
|
|
73
|
+
if (phase === null) return next;
|
|
74
|
+
return {
|
|
75
|
+
...next,
|
|
76
|
+
phase,
|
|
77
|
+
phaseHistory: [...current.phaseHistory, phase]
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
case "init": {
|
|
81
|
+
const operationId = asString(data.operation_id);
|
|
82
|
+
const operation = asString(data.operation);
|
|
83
|
+
if (operationId === null || operation === null) return next;
|
|
84
|
+
return {
|
|
85
|
+
...next,
|
|
86
|
+
operations: {
|
|
87
|
+
...current.operations,
|
|
88
|
+
[operationId]: {
|
|
89
|
+
operationId,
|
|
90
|
+
operation,
|
|
91
|
+
parentOperationId: asString(data.parent_operation_id),
|
|
92
|
+
status: "active",
|
|
93
|
+
metadata: Object.keys(asRecord(data.metadata)).length ? asRecord(data.metadata) : null,
|
|
94
|
+
result: null
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
case "completion": {
|
|
100
|
+
const operationId = asString(data.operation_id);
|
|
101
|
+
const operation = asString(data.operation);
|
|
102
|
+
const rawStatus = asString(data.status);
|
|
103
|
+
const status = rawStatus === "failed" || rawStatus === "cancelled" ? rawStatus : "success";
|
|
104
|
+
const result = asRecord(data.result);
|
|
105
|
+
const operations = operationId ? {
|
|
106
|
+
...current.operations,
|
|
107
|
+
[operationId]: {
|
|
108
|
+
...current.operations[operationId] ?? {
|
|
109
|
+
operationId,
|
|
110
|
+
operation: operation ?? "unknown",
|
|
111
|
+
parentOperationId: null,
|
|
112
|
+
metadata: null
|
|
113
|
+
},
|
|
114
|
+
status,
|
|
115
|
+
result
|
|
116
|
+
}
|
|
117
|
+
} : current.operations;
|
|
118
|
+
if (operation === "user_request") {
|
|
119
|
+
return {
|
|
120
|
+
...next,
|
|
121
|
+
operations,
|
|
122
|
+
completion: data,
|
|
123
|
+
status: status === "success" ? "complete" : status === "cancelled" ? "cancelled" : "error"
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
return { ...next, operations };
|
|
127
|
+
}
|
|
128
|
+
case "tool_event": {
|
|
129
|
+
const callId = asString(data.call_id);
|
|
130
|
+
const toolName = asString(data.tool_name);
|
|
131
|
+
const lifecycle = asString(data.event);
|
|
132
|
+
if (callId === null || toolName === null || lifecycle === null) return next;
|
|
133
|
+
const status = toolStatus(lifecycle);
|
|
134
|
+
return {
|
|
135
|
+
...next,
|
|
136
|
+
status: status === "started" || status === "delegated" ? "awaiting-tools" : status === "completed" || status === "error" ? "streaming" : next.status,
|
|
137
|
+
tools: {
|
|
138
|
+
...current.tools,
|
|
139
|
+
[callId]: {
|
|
140
|
+
callId,
|
|
141
|
+
toolName,
|
|
142
|
+
status,
|
|
143
|
+
message: asString(data.message),
|
|
144
|
+
data: Object.keys(asRecord(data.data)).length ? asRecord(data.data) : null
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
case "render_block": {
|
|
150
|
+
const blockId = asString(data.blockId);
|
|
151
|
+
const blockIndex = asNumber(data.blockIndex);
|
|
152
|
+
const type = asString(data.type);
|
|
153
|
+
if (blockId === null || blockIndex === null || type === null) return next;
|
|
154
|
+
const alreadyKnown = Object.hasOwn(current.renderBlocks, blockId);
|
|
155
|
+
return {
|
|
156
|
+
...next,
|
|
157
|
+
renderBlocks: {
|
|
158
|
+
...current.renderBlocks,
|
|
159
|
+
[blockId]: {
|
|
160
|
+
blockId,
|
|
161
|
+
blockIndex,
|
|
162
|
+
type,
|
|
163
|
+
status: data.status === "complete" || data.status === "error" ? data.status : "streaming",
|
|
164
|
+
content: asString(data.content),
|
|
165
|
+
data: Object.keys(asRecord(data.data)).length ? asRecord(data.data) : null,
|
|
166
|
+
metadata: Object.keys(asRecord(data.metadata)).length ? asRecord(data.metadata) : null
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
renderBlockOrder: alreadyKnown ? current.renderBlockOrder : [...current.renderBlockOrder, blockId]
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
case "error":
|
|
173
|
+
return { ...next, status: "error", error: data };
|
|
174
|
+
case "end":
|
|
175
|
+
return {
|
|
176
|
+
...next,
|
|
177
|
+
status: current.status === "error" || current.status === "cancelled" ? current.status : "complete",
|
|
178
|
+
reasoningActive: false
|
|
179
|
+
};
|
|
180
|
+
case "data": {
|
|
181
|
+
const conversationId = data.type === "conversation_id" ? asString(data.conversation_id) : null;
|
|
182
|
+
return conversationId === null ? next : { ...next, conversationId };
|
|
183
|
+
}
|
|
184
|
+
default:
|
|
185
|
+
return next;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
function projectAgentEvents(initial, events) {
|
|
189
|
+
return events.reduce(projectAgentEvent, initial);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export { createAgentRequestProjection, projectAgentEvent, projectAgentEvents };
|
|
193
|
+
//# sourceMappingURL=request.js.map
|
|
194
|
+
//# sourceMappingURL=request.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../projection/request.ts"],"names":[],"mappings":"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","file":"request.js","sourcesContent":["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,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":";;;AAiCA,SAAS,SAAS,KAAA,EAAkD;AAClE,EAAA,OAAO,OAAO,UAAU,QAAA,IAAY,KAAA,KAAU,QAAQ,CAAC,KAAA,CAAM,QAAQ,KAAK,CAAA;AAC5E;AASO,SAAS,6BACd,KAAA,EAC4B;AAC5B,EAAA,IAAI,CAAC,QAAA,CAAS,KAAK,CAAA,EAAG,OAAO,IAAA;AAE7B,EAAA,IAAI,OAAO,KAAA,CAAM,KAAA,KAAU,QAAA,EAAU;AACnC,IAAA,OAAO,EAAE,KAAA,EAAO,KAAA,CAAM,KAAA,EAAO,IAAA,EAAM,MAAM,IAAA,EAAK;AAAA,EAChD;AACA,EAAA,IAAI,MAAM,CAAA,KAAM,GAAA,IAAO,OAAO,KAAA,CAAM,MAAM,QAAA,EAAU;AAClD,IAAA,OAAO,EAAE,OAAO,OAAA,EAAS,IAAA,EAAM,EAAE,IAAA,EAAM,KAAA,CAAM,GAAE,EAAE;AAAA,EACnD;AACA,EAAA,IAAI,MAAM,CAAA,KAAM,GAAA,IAAO,OAAO,KAAA,CAAM,MAAM,QAAA,EAAU;AAClD,IAAA,OAAO,EAAE,OAAO,iBAAA,EAAmB,IAAA,EAAM,EAAE,IAAA,EAAM,KAAA,CAAM,GAAE,EAAE;AAAA,EAC7D;AACA,EAAA,OAAO,IAAA;AACT;AAQA,gBAAuB,qBAAA,CACrB,IAAA,EACA,OAAA,GAAkC,EAAC,EACmB;AACtD,EAAA,MAAM,QAAqB,EAAC;AAC5B,EAAA,IAAI,YAAA,GAAoC,IAAA;AACxC,EAAA,IAAI,cAAA,GAAiB,KAAA;AAErB,EAAA,MAAM,OAAA,GAAU,CAAC,IAAA,KAA0B;AACzC,IAAA,KAAA,CAAM,KAAK,IAAI,CAAA;AACf,IAAA,MAAM,IAAA,GAAO,YAAA;AACb,IAAA,YAAA,GAAe,IAAA;AACf,IAAA,IAAA,IAAO;AAAA,EACT,CAAA;AAEA,EAAA,MAAM,MAAA,GAAS,KAAK,SAAA,EAAU;AAC9B,EAAA,MAAM,OAAA,GAAU,IAAI,WAAA,EAAY;AAEhC,EAAA,MAAM,SAAA,GAAY,CAAC,IAAA,KAAuB;AACxC,IAAA,MAAM,OAAA,GAAU,KAAK,IAAA,EAAK;AAC1B,IAAA,IAAI,CAAC,OAAA,EAAS;AAEd,IAAA,IAAI,MAAA;AACJ,IAAA,IAAI;AACF,MAAA,MAAA,GAAS,IAAA,CAAK,MAAM,OAAO,CAAA;AAAA,IAC7B,SAAS,KAAA,EAAO;AACd,MAAA,OAAA,CAAQ,eAAA,GAAkB,EAAE,IAAA,EAAM,OAAA,EAAS,OAAO,CAAA;AAClD,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,QAAA,GAAW,6BAA6B,MAAM,CAAA;AACpD,IAAA,IAAI,QAAA,EAAU;AACZ,MAAA,OAAA,CAAQ,EAAE,IAAA,EAAM,OAAA,EAAS,KAAA,EAAO,UAAU,CAAA;AAAA,IAC5C,CAAA,MAAO;AACL,MAAA,OAAA,CAAQ,oBAAoB,MAAM,CAAA;AAAA,IACpC;AAAA,EACF,CAAA;AAEA,EAAA,MAAM,UAAU,MAAY;AAC1B,IAAA,KAAK,MAAA,CAAO,OAAO,OAAA,CAAQ,MAAA,EAAQ,MAAM,CAAA,CAAE,KAAA,CAAM,MAAM,MAAS,CAAA;AAAA,EAClE,CAAA;AACA,EAAA,OAAA,CAAQ,QAAQ,gBAAA,CAAiB,OAAA,EAAS,SAAS,EAAE,IAAA,EAAM,MAAM,CAAA;AAEjE,EAAA,MAAM,iBAAiB,YAA2B;AAChD,IAAA,IAAI,MAAA,GAAS,EAAA;AACb,IAAA,IAAI;AACF,MAAA,OAAO,CAAC,OAAA,CAAQ,MAAA,EAAQ,OAAA,EAAS;AAC/B,QAAA,MAAM,EAAE,KAAA,EAAO,IAAA,EAAK,GAAI,MAAM,OAAO,IAAA,EAAK;AAC1C,QAAA,IAAI,IAAA,EAAM;AAEV,QAAA,MAAA,IAAU,QAAQ,MAAA,CAAO,KAAA,EAAO,EAAE,MAAA,EAAQ,MAAM,CAAA;AAChD,QAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,KAAA,CAAM,IAAI,CAAA;AAC/B,QAAA,MAAA,GAAS,KAAA,CAAM,KAAI,IAAK,EAAA;AACxB,QAAA,KAAA,MAAW,IAAA,IAAQ,KAAA,EAAO,SAAA,CAAU,IAAI,CAAA;AAAA,MAC1C;AAEA,MAAA,MAAA,IAAU,QAAQ,MAAA,EAAO;AACzB,MAAA,IAAI,CAAC,QAAQ,MAAA,EAAQ,OAAA,IAAW,OAAO,IAAA,EAAK,YAAa,MAAM,CAAA;AAAA,IACjE,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,UACJ,OAAA,CAAQ,MAAA,EAAQ,WACf,KAAA,YAAiB,KAAA,IAAS,MAAM,IAAA,KAAS,YAAA;AAC5C,MAAA,IAAI,CAAC,OAAA,EAAS,OAAA,CAAQ,EAAE,IAAA,EAAM,OAAA,EAAS,OAAO,CAAA;AAAA,IAChD,CAAA,SAAE;AACA,MAAA,cAAA,GAAiB,IAAA;AACjB,MAAA,MAAA,CAAO,WAAA,EAAY;AACnB,MAAA,OAAA,CAAQ,EAAE,IAAA,EAAM,MAAA,EAAQ,CAAA;AAAA,IAC1B;AAAA,EACF,CAAA,GAAG;AAEH,EAAA,IAAI;AACF,IAAA,OAAO,IAAA,EAAM;AACX,MAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AACtB,QAAA,MAAM,IAAI,OAAA,CAAc,CAAC,OAAA,KAAY;AACnC,UAAA,YAAA,GAAe,OAAA;AAAA,QACjB,CAAC,CAAA;AAAA,MACH;AAEA,MAAA,MAAM,IAAA,GAAO,MAAM,KAAA,EAAM;AACzB,MAAA,IAAI,CAAC,IAAA,IAAQ,IAAA,CAAK,IAAA,KAAS,MAAA,EAAQ;AACnC,MAAA,IAAI,IAAA,CAAK,IAAA,KAAS,OAAA,EAAS,MAAM,IAAA,CAAK,KAAA;AACtC,MAAA,MAAM,IAAA,CAAK,KAAA;AAAA,IACb;AAAA,EACF,CAAA,SAAE;AACA,IAAA,OAAA,CAAQ,MAAA,EAAQ,mBAAA,CAAoB,OAAA,EAAS,OAAO,CAAA;AACpD,IAAA,IAAI,CAAC,cAAA,EAAgB;AACnB,MAAA,MAAM,MAAA,CAAO,MAAA,EAAO,CAAE,KAAA,CAAM,MAAM,MAAS,CAAA;AAAA,IAC7C;AACA,IAAA,MAAM,aAAA;AAAA,EACR;AACF","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.
|
|
4
|
-
"description": "Portable AI Matrx agent stream protocol and safe result-presentation primitives.",
|
|
3
|
+
"version": "0.2.0",
|
|
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,44 @@
|
|
|
27
30
|
],
|
|
28
31
|
"exports": {
|
|
29
32
|
".": {
|
|
30
|
-
"
|
|
31
|
-
|
|
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
|
-
"
|
|
35
|
-
|
|
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
|
-
"
|
|
39
|
-
|
|
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
|
+
}
|
|
40
71
|
},
|
|
41
72
|
"./package.json": "./package.json"
|
|
42
73
|
},
|
|
@@ -50,7 +81,6 @@
|
|
|
50
81
|
},
|
|
51
82
|
"publishConfig": {
|
|
52
83
|
"access": "public",
|
|
53
|
-
"provenance": true,
|
|
54
84
|
"registry": "https://registry.npmjs.org/"
|
|
55
85
|
},
|
|
56
86
|
"engines": {
|