@copilotkit/aimock 1.26.1 → 1.27.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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +11 -0
- package/dist/agui-handler.cjs +25 -1
- package/dist/agui-handler.cjs.map +1 -1
- package/dist/agui-handler.d.cts +7 -1
- package/dist/agui-handler.d.cts.map +1 -1
- package/dist/agui-handler.d.ts +7 -1
- package/dist/agui-handler.d.ts.map +1 -1
- package/dist/agui-handler.js +25 -2
- package/dist/agui-handler.js.map +1 -1
- package/dist/agui-mock.cjs +8 -0
- package/dist/agui-mock.cjs.map +1 -1
- package/dist/agui-mock.d.cts +1 -0
- package/dist/agui-mock.d.cts.map +1 -1
- package/dist/agui-mock.d.ts +1 -0
- package/dist/agui-mock.d.ts.map +1 -1
- package/dist/agui-mock.js +8 -0
- package/dist/agui-mock.js.map +1 -1
- package/dist/agui-recorder.cjs +49 -21
- package/dist/agui-recorder.cjs.map +1 -1
- package/dist/agui-recorder.d.cts +0 -1
- package/dist/agui-recorder.d.cts.map +1 -1
- package/dist/agui-recorder.d.ts +0 -1
- package/dist/agui-recorder.d.ts.map +1 -1
- package/dist/agui-recorder.js +50 -22
- package/dist/agui-recorder.js.map +1 -1
- package/dist/agui-stub.cjs +1 -0
- package/dist/agui-stub.d.cts +3 -3
- package/dist/agui-stub.d.ts +3 -3
- package/dist/agui-stub.js +2 -2
- package/dist/agui-types.d.cts +10 -2
- package/dist/agui-types.d.cts.map +1 -1
- package/dist/agui-types.d.ts +10 -2
- package/dist/agui-types.d.ts.map +1 -1
- package/dist/config-loader.cjs +15 -11
- package/dist/config-loader.cjs.map +1 -1
- package/dist/config-loader.d.cts +1 -0
- package/dist/config-loader.d.cts.map +1 -1
- package/dist/config-loader.d.ts +1 -0
- package/dist/config-loader.d.ts.map +1 -1
- package/dist/config-loader.js +15 -11
- package/dist/config-loader.js.map +1 -1
- package/dist/gemini-interactions.cjs +53 -1
- package/dist/gemini-interactions.cjs.map +1 -1
- package/dist/gemini-interactions.d.cts +18 -1
- package/dist/gemini-interactions.d.cts.map +1 -1
- package/dist/gemini-interactions.d.ts +18 -1
- package/dist/gemini-interactions.d.ts.map +1 -1
- package/dist/gemini-interactions.js +53 -1
- package/dist/gemini-interactions.js.map +1 -1
- package/dist/index.cjs +1 -0
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/vector-types.d.cts.map +1 -1
- package/package.json +1 -1
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"source": {
|
|
10
10
|
"source": "npm",
|
|
11
11
|
"package": "@copilotkit/aimock",
|
|
12
|
-
"version": "^1.
|
|
12
|
+
"version": "^1.27.0"
|
|
13
13
|
},
|
|
14
14
|
"description": "Fixture authoring skill for @copilotkit/aimock — LLM, multimedia (image/TTS/transcription/video), MCP, A2A, AG-UI, vector, embeddings, structured output, sequential responses, streaming physics, record/replay, agent loop patterns, and debugging"
|
|
15
15
|
}
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [1.27.0] - 2026-05-20
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- **HITL continuation recording/replay support** — `toolCallId` matching for continuation fixtures. New `toolCallId` field on `AGUIFixtureMatch` and `AGUIConfigFixture`. `getLastMessageIfToolResult` helper and `onToolResult` fluent API. Recorder uses tool-result-first priority for continuation fixtures. ([#233](https://github.com/CopilotKit/aimock/pull/233), closes [#232](https://github.com/CopilotKit/aimock/issues/232))
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- **Walk structured content arrays in `extractLastUserMessage`** — handle multimodal user content (`AGUIMessageContentPart[]`) by joining text parts and skipping non-text. Export `NO_USER_MESSAGE_SENTINEL` constant and `AGUIMessageContentPart` type. ([#231](https://github.com/CopilotKit/aimock/pull/231))
|
|
14
|
+
- **Harden recorder against error responses, double-settle, and broken sentinel persistence** — guard against recording fixtures from non-2xx upstream responses, add `settled` flag to prevent error+end race, skip disk write for predicate fixtures (sentinel was semantically broken on reload), include parse error reason in SSE warning log
|
|
15
|
+
|
|
5
16
|
## [1.26.1] - 2026-05-19
|
|
6
17
|
|
|
7
18
|
### Added
|
package/dist/agui-handler.cjs
CHANGED
|
@@ -4,15 +4,34 @@ let node_crypto = require("node:crypto");
|
|
|
4
4
|
//#region src/agui-handler.ts
|
|
5
5
|
/**
|
|
6
6
|
* Extract the content of the last message with role "user" from the input.
|
|
7
|
+
* Walks structured content arrays (e.g. `[{type:"text", text:"..."}, {type:"document", ...}]`)
|
|
8
|
+
* and joins their text parts. Returns `""` when no user message is present or has no text.
|
|
7
9
|
*/
|
|
8
10
|
function extractLastUserMessage(input) {
|
|
9
11
|
if (!input.messages || input.messages.length === 0) return "";
|
|
10
12
|
for (let i = input.messages.length - 1; i >= 0; i--) {
|
|
11
13
|
const msg = input.messages[i];
|
|
12
|
-
if (msg.role
|
|
14
|
+
if (msg.role !== "user") continue;
|
|
15
|
+
const text = extractTextFromContent(msg.content);
|
|
16
|
+
if (text) return text;
|
|
13
17
|
}
|
|
14
18
|
return "";
|
|
15
19
|
}
|
|
20
|
+
function extractTextFromContent(content) {
|
|
21
|
+
if (typeof content === "string") return content;
|
|
22
|
+
if (!Array.isArray(content)) return "";
|
|
23
|
+
const parts = [];
|
|
24
|
+
for (const part of content) if (part && typeof part === "object" && part.type === "text" && typeof part.text === "string" && part.text) parts.push(part.text);
|
|
25
|
+
return parts.join(" ").trim();
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Return the absolute last message if it has role "tool", otherwise null.
|
|
29
|
+
*/
|
|
30
|
+
function getLastMessageIfToolResult(input) {
|
|
31
|
+
if (!input.messages || input.messages.length === 0) return null;
|
|
32
|
+
const last = input.messages[input.messages.length - 1];
|
|
33
|
+
return last.role === "tool" ? last : null;
|
|
34
|
+
}
|
|
16
35
|
/**
|
|
17
36
|
* Check whether an input matches a fixture's match criteria.
|
|
18
37
|
* All specified criteria must pass (AND logic).
|
|
@@ -27,6 +46,10 @@ function matchesFixture(input, match) {
|
|
|
27
46
|
if (!match.message.test(text)) return false;
|
|
28
47
|
}
|
|
29
48
|
}
|
|
49
|
+
if (match.toolCallId !== void 0) {
|
|
50
|
+
const lastMsg = input.messages?.[input.messages.length - 1];
|
|
51
|
+
if (!lastMsg || lastMsg.role !== "tool" || lastMsg.toolCallId !== match.toolCallId) return false;
|
|
52
|
+
}
|
|
30
53
|
if (match.toolName !== void 0) {
|
|
31
54
|
if (!(input.tools ?? []).some((t) => t.name === match.toolName)) return false;
|
|
32
55
|
}
|
|
@@ -450,6 +473,7 @@ exports.buildToolCallChunk = buildToolCallChunk;
|
|
|
450
473
|
exports.buildToolCallResponse = buildToolCallResponse;
|
|
451
474
|
exports.extractLastUserMessage = extractLastUserMessage;
|
|
452
475
|
exports.findFixture = findFixture;
|
|
476
|
+
exports.getLastMessageIfToolResult = getLastMessageIfToolResult;
|
|
453
477
|
exports.matchesFixture = matchesFixture;
|
|
454
478
|
exports.writeAGUIEventStream = writeAGUIEventStream;
|
|
455
479
|
//# sourceMappingURL=agui-handler.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agui-handler.cjs","names":[],"sources":["../src/agui-handler.ts"],"sourcesContent":["// ─── AG-UI Handler ───────────────────────────────────────────────────────────\n//\n// Matching functions, event builders, and SSE writer for AG-UI protocol.\n\nimport * as http from \"node:http\";\nimport { randomUUID } from \"node:crypto\";\n\nimport type {\n AGUIRunAgentInput,\n AGUIFixtureMatch,\n AGUIFixture,\n AGUIEvent,\n AGUIMessage,\n AGUIRunStartedEvent,\n AGUIRunFinishedEvent,\n AGUIRunFinishedOutcome,\n AGUIRunErrorEvent,\n AGUITextMessageStartEvent,\n AGUITextMessageContentEvent,\n AGUITextMessageEndEvent,\n AGUITextMessageChunkEvent,\n AGUIToolCallStartEvent,\n AGUIToolCallArgsEvent,\n AGUIToolCallEndEvent,\n AGUIToolCallChunkEvent,\n AGUIToolCallResultEvent,\n AGUIStateSnapshotEvent,\n AGUIStateDeltaEvent,\n AGUIMessagesSnapshotEvent,\n AGUIStepStartedEvent,\n AGUIStepFinishedEvent,\n AGUIReasoningStartEvent,\n AGUIReasoningMessageStartEvent,\n AGUIReasoningMessageContentEvent,\n AGUIReasoningMessageEndEvent,\n AGUIReasoningMessageChunkEvent,\n AGUIReasoningEndEvent,\n AGUIReasoningEncryptedValueEvent,\n AGUIReasoningEncryptedValueSubtype,\n AGUIActivitySnapshotEvent,\n AGUIActivityDeltaEvent,\n AGUIRawEvent,\n AGUICustomEvent,\n} from \"./agui-types.js\";\n\n// ─── Matching functions ──────────────────────────────────────────────────────\n\n/**\n * Extract the content of the last message with role \"user\" from the input.\n */\nexport function extractLastUserMessage(input: AGUIRunAgentInput): string {\n if (!input.messages || input.messages.length === 0) return \"\";\n for (let i = input.messages.length - 1; i >= 0; i--) {\n const msg = input.messages[i];\n if (msg.role === \"user\" && typeof msg.content === \"string\") {\n return msg.content;\n }\n }\n return \"\";\n}\n\n/**\n * Check whether an input matches a fixture's match criteria.\n * All specified criteria must pass (AND logic).\n */\nexport function matchesFixture(input: AGUIRunAgentInput, match: AGUIFixtureMatch): boolean {\n if (match.message !== undefined) {\n const text = extractLastUserMessage(input);\n if (typeof match.message === \"string\") {\n if (!text.includes(match.message)) return false;\n } else {\n match.message.lastIndex = 0;\n if (!match.message.test(text)) return false;\n }\n }\n\n if (match.toolName !== undefined) {\n const tools = input.tools ?? [];\n if (!tools.some((t) => t.name === match.toolName)) return false;\n }\n\n if (match.stateKey !== undefined) {\n if (\n input.state === null ||\n input.state === undefined ||\n typeof input.state !== \"object\" ||\n !(match.stateKey in (input.state as Record<string, unknown>))\n ) {\n return false;\n }\n }\n\n if (match.predicate !== undefined) {\n if (!match.predicate(input)) return false;\n }\n\n return true;\n}\n\n/**\n * Find the first fixture whose match criteria pass for the given input.\n */\nexport function findFixture(input: AGUIRunAgentInput, fixtures: AGUIFixture[]): AGUIFixture | null {\n for (const fixture of fixtures) {\n if (matchesFixture(input, fixture.match)) {\n return fixture;\n }\n }\n return null;\n}\n\n// ─── Builder options ─────────────────────────────────────────────────────────\n\nexport interface AGUIBuildOpts {\n threadId?: string;\n runId?: string;\n parentRunId?: string;\n /** For tool call builder: include a result event */\n result?: string;\n}\n\n// ─── Event builders ──────────────────────────────────────────────────────────\n\nfunction makeRunStarted(opts?: AGUIBuildOpts): AGUIRunStartedEvent {\n return {\n type: \"RUN_STARTED\",\n threadId: opts?.threadId ?? randomUUID(),\n runId: opts?.runId ?? randomUUID(),\n ...(opts?.parentRunId ? { parentRunId: opts.parentRunId } : {}),\n };\n}\n\nfunction makeRunFinished(\n started: AGUIRunStartedEvent,\n finishOpts?: { outcome?: AGUIRunFinishedOutcome; result?: unknown },\n): AGUIRunFinishedEvent {\n return {\n type: \"RUN_FINISHED\",\n threadId: started.threadId,\n runId: started.runId,\n ...(finishOpts?.result !== undefined ? { result: finishOpts.result } : {}),\n ...(finishOpts?.outcome !== undefined ? { outcome: finishOpts.outcome } : {}),\n };\n}\n\n/**\n * Build a complete text message response sequence.\n * [RUN_STARTED, TEXT_MESSAGE_START, TEXT_MESSAGE_CONTENT, TEXT_MESSAGE_END, RUN_FINISHED]\n */\nexport function buildTextResponse(text: string, opts?: AGUIBuildOpts): AGUIEvent[] {\n const started = makeRunStarted(opts);\n const messageId = randomUUID();\n return [\n started,\n {\n type: \"TEXT_MESSAGE_START\",\n messageId,\n role: \"assistant\",\n } as AGUITextMessageStartEvent,\n {\n type: \"TEXT_MESSAGE_CONTENT\",\n messageId,\n delta: text,\n } as AGUITextMessageContentEvent,\n {\n type: \"TEXT_MESSAGE_END\",\n messageId,\n } as AGUITextMessageEndEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build a text chunk response (single chunk, no start/end envelope).\n * [RUN_STARTED, TEXT_MESSAGE_CHUNK, RUN_FINISHED]\n */\nexport function buildTextChunkResponse(text: string, opts?: AGUIBuildOpts): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"TEXT_MESSAGE_CHUNK\",\n messageId: randomUUID(),\n role: \"assistant\",\n delta: text,\n } as AGUITextMessageChunkEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build a tool call response sequence.\n * [RUN_STARTED, TOOL_CALL_START, TOOL_CALL_ARGS, TOOL_CALL_END, (TOOL_CALL_RESULT)?, RUN_FINISHED]\n */\nexport function buildToolCallResponse(\n toolName: string,\n args: string,\n opts?: AGUIBuildOpts,\n): AGUIEvent[] {\n const started = makeRunStarted(opts);\n const toolCallId = randomUUID();\n const events: AGUIEvent[] = [\n started,\n {\n type: \"TOOL_CALL_START\",\n toolCallId,\n toolCallName: toolName,\n } as AGUIToolCallStartEvent,\n {\n type: \"TOOL_CALL_ARGS\",\n toolCallId,\n delta: args,\n } as AGUIToolCallArgsEvent,\n {\n type: \"TOOL_CALL_END\",\n toolCallId,\n } as AGUIToolCallEndEvent,\n ];\n\n if (opts?.result !== undefined) {\n events.push({\n type: \"TOOL_CALL_RESULT\",\n messageId: randomUUID(),\n toolCallId,\n content: opts.result,\n role: \"tool\",\n } as AGUIToolCallResultEvent);\n }\n\n events.push(makeRunFinished(started));\n return events;\n}\n\n/**\n * Build a state snapshot response.\n * [RUN_STARTED, STATE_SNAPSHOT, RUN_FINISHED]\n */\nexport function buildStateUpdate(snapshot: unknown, opts?: AGUIBuildOpts): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"STATE_SNAPSHOT\",\n snapshot,\n } as AGUIStateSnapshotEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build a state delta response (JSON Patch).\n * [RUN_STARTED, STATE_DELTA, RUN_FINISHED]\n */\nexport function buildStateDelta(patches: unknown[], opts?: AGUIBuildOpts): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"STATE_DELTA\",\n delta: patches,\n } as AGUIStateDeltaEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build a messages snapshot response.\n * [RUN_STARTED, MESSAGES_SNAPSHOT, RUN_FINISHED]\n */\nexport function buildMessagesSnapshot(messages: AGUIMessage[], opts?: AGUIBuildOpts): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"MESSAGES_SNAPSHOT\",\n messages,\n } as AGUIMessagesSnapshotEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build a reasoning response sequence.\n * [RUN_STARTED, REASONING_START, REASONING_MESSAGE_START, REASONING_MESSAGE_CONTENT,\n * REASONING_MESSAGE_END, REASONING_END, RUN_FINISHED]\n */\nexport function buildReasoningResponse(text: string, opts?: AGUIBuildOpts): AGUIEvent[] {\n const started = makeRunStarted(opts);\n const messageId = randomUUID();\n return [\n started,\n {\n type: \"REASONING_START\",\n messageId,\n } as AGUIReasoningStartEvent,\n {\n type: \"REASONING_MESSAGE_START\",\n messageId,\n role: \"reasoning\",\n } as AGUIReasoningMessageStartEvent,\n {\n type: \"REASONING_MESSAGE_CONTENT\",\n messageId,\n delta: text,\n } as AGUIReasoningMessageContentEvent,\n {\n type: \"REASONING_MESSAGE_END\",\n messageId,\n } as AGUIReasoningMessageEndEvent,\n {\n type: \"REASONING_END\",\n messageId,\n } as AGUIReasoningEndEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build an activity snapshot response.\n * [RUN_STARTED, ACTIVITY_SNAPSHOT, RUN_FINISHED]\n */\nexport function buildActivityResponse(\n messageId: string,\n activityType: string,\n content: Record<string, unknown>,\n opts?: AGUIBuildOpts,\n): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"ACTIVITY_SNAPSHOT\",\n messageId,\n activityType,\n content,\n replace: true,\n } as AGUIActivitySnapshotEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build an error response.\n * [RUN_STARTED, RUN_ERROR] (no RUN_FINISHED — the run errored)\n */\nexport function buildErrorResponse(\n message: string,\n code?: string,\n opts?: AGUIBuildOpts,\n): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"RUN_ERROR\",\n message,\n ...(code !== undefined ? { code } : {}),\n } as AGUIRunErrorEvent,\n ];\n}\n\n/**\n * Build a step-wrapped text response.\n * [RUN_STARTED, STEP_STARTED, TEXT_MESSAGE_START, TEXT_MESSAGE_CONTENT,\n * TEXT_MESSAGE_END, STEP_FINISHED, RUN_FINISHED]\n */\nexport function buildStepWithText(\n stepName: string,\n text: string,\n opts?: AGUIBuildOpts,\n): AGUIEvent[] {\n const started = makeRunStarted(opts);\n const messageId = randomUUID();\n return [\n started,\n {\n type: \"STEP_STARTED\",\n stepName,\n } as AGUIStepStartedEvent,\n {\n type: \"TEXT_MESSAGE_START\",\n messageId,\n role: \"assistant\",\n } as AGUITextMessageStartEvent,\n {\n type: \"TEXT_MESSAGE_CONTENT\",\n messageId,\n delta: text,\n } as AGUITextMessageContentEvent,\n {\n type: \"TEXT_MESSAGE_END\",\n messageId,\n } as AGUITextMessageEndEvent,\n {\n type: \"STEP_FINISHED\",\n stepName,\n } as AGUIStepFinishedEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Combine multiple builder outputs into a single run.\n * Strips RUN_STARTED/RUN_FINISHED from each input, wraps all inner events\n * in one RUN_STARTED...RUN_FINISHED pair.\n */\nexport function buildCompositeResponse(\n builderOutputs: AGUIEvent[][],\n opts?: AGUIBuildOpts,\n): AGUIEvent[] {\n const started = makeRunStarted(opts);\n const inner: AGUIEvent[] = [];\n\n for (const events of builderOutputs) {\n for (const event of events) {\n if (event.type !== \"RUN_STARTED\" && event.type !== \"RUN_FINISHED\") {\n inner.push(event);\n }\n }\n }\n\n const hasError = inner.some((e) => e.type === \"RUN_ERROR\");\n return [started, ...inner, ...(hasError ? [] : [makeRunFinished(started)])];\n}\n\n// ─── Convenience event builders ─────────────────────────────────────────────\n\n/**\n * Build an activity delta response (JSON Patch on an activity).\n * [RUN_STARTED, ACTIVITY_DELTA, RUN_FINISHED]\n */\nexport function buildActivityDelta(\n messageId: string,\n activityType: string,\n patch: unknown[],\n opts?: AGUIBuildOpts,\n): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"ACTIVITY_DELTA\",\n messageId,\n activityType,\n patch,\n } as AGUIActivityDeltaEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build a tool call chunk response (single chunk, no start/end envelope).\n * [RUN_STARTED, TOOL_CALL_CHUNK, RUN_FINISHED]\n */\nexport function buildToolCallChunk(\n delta: string,\n opts?: AGUIBuildOpts & {\n toolCallId?: string;\n toolCallName?: string;\n parentMessageId?: string;\n },\n): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"TOOL_CALL_CHUNK\",\n ...(opts?.toolCallId !== undefined ? { toolCallId: opts.toolCallId } : {}),\n ...(opts?.toolCallName !== undefined ? { toolCallName: opts.toolCallName } : {}),\n ...(opts?.parentMessageId !== undefined ? { parentMessageId: opts.parentMessageId } : {}),\n delta,\n } as AGUIToolCallChunkEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build a raw event response.\n * [RUN_STARTED, RAW, RUN_FINISHED]\n */\nexport function buildRawEvent(event: unknown, source?: string, opts?: AGUIBuildOpts): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"RAW\",\n event,\n ...(source !== undefined ? { source } : {}),\n } as AGUIRawEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build a custom event response.\n * [RUN_STARTED, CUSTOM, RUN_FINISHED]\n */\nexport function buildCustomEvent(name: string, value: unknown, opts?: AGUIBuildOpts): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"CUSTOM\",\n name,\n value,\n } as AGUICustomEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build a reasoning message chunk response (single chunk, no start/end envelope).\n * [RUN_STARTED, REASONING_MESSAGE_CHUNK, RUN_FINISHED]\n */\nexport function buildReasoningChunk(\n delta: string,\n opts?: AGUIBuildOpts & { messageId?: string },\n): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"REASONING_MESSAGE_CHUNK\",\n ...(opts?.messageId !== undefined ? { messageId: opts.messageId } : {}),\n delta,\n } as AGUIReasoningMessageChunkEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build a reasoning encrypted value event response.\n * [RUN_STARTED, REASONING_ENCRYPTED_VALUE, RUN_FINISHED]\n */\nexport function buildReasoningEncryptedValue(\n subtype: AGUIReasoningEncryptedValueSubtype,\n entityId: string,\n encryptedValue: string,\n opts?: AGUIBuildOpts,\n): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"REASONING_ENCRYPTED_VALUE\",\n subtype,\n entityId,\n encryptedValue,\n } as AGUIReasoningEncryptedValueEvent,\n makeRunFinished(started),\n ];\n}\n\n// ─── SSE writer ──────────────────────────────────────────────────────────────\n\n/**\n * Write AG-UI events as an SSE stream to an HTTP response.\n * Sets appropriate headers, serializes each event as `data: {...}\\n\\n`,\n * and optionally delays between events.\n */\nexport async function writeAGUIEventStream(\n res: http.ServerResponse,\n events: AGUIEvent[],\n opts?: { delayMs?: number; signal?: AbortSignal },\n): Promise<void> {\n const delayMs = opts?.delayMs ?? 0;\n\n res.writeHead(200, {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n });\n\n for (const event of events) {\n if (opts?.signal?.aborted) break;\n if (res.socket?.destroyed) break;\n\n const stamped = { ...event, timestamp: event.timestamp ?? Date.now() };\n try {\n res.write(`data: ${JSON.stringify(stamped)}\\n\\n`);\n } catch (err) {\n if (err instanceof TypeError || err instanceof RangeError) {\n console.warn(\"AG-UI SSE write failed (serialization):\", (err as Error).message);\n } else if (err instanceof Error) {\n console.warn(\"AG-UI SSE write failed:\", err.message);\n }\n break;\n }\n\n if (delayMs > 0) {\n await new Promise<void>((resolve) => setTimeout(resolve, delayMs));\n }\n }\n\n if (!res.writableEnded) res.end();\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"agui-handler.cjs","names":[],"sources":["../src/agui-handler.ts"],"sourcesContent":["// ─── AG-UI Handler ───────────────────────────────────────────────────────────\n//\n// Matching functions, event builders, and SSE writer for AG-UI protocol.\n\nimport * as http from \"node:http\";\nimport { randomUUID } from \"node:crypto\";\n\nimport type {\n AGUIRunAgentInput,\n AGUIFixtureMatch,\n AGUIFixture,\n AGUIEvent,\n AGUIMessage,\n AGUIRunStartedEvent,\n AGUIRunFinishedEvent,\n AGUIRunFinishedOutcome,\n AGUIRunErrorEvent,\n AGUITextMessageStartEvent,\n AGUITextMessageContentEvent,\n AGUITextMessageEndEvent,\n AGUITextMessageChunkEvent,\n AGUIToolCallStartEvent,\n AGUIToolCallArgsEvent,\n AGUIToolCallEndEvent,\n AGUIToolCallChunkEvent,\n AGUIToolCallResultEvent,\n AGUIStateSnapshotEvent,\n AGUIStateDeltaEvent,\n AGUIMessagesSnapshotEvent,\n AGUIStepStartedEvent,\n AGUIStepFinishedEvent,\n AGUIReasoningStartEvent,\n AGUIReasoningMessageStartEvent,\n AGUIReasoningMessageContentEvent,\n AGUIReasoningMessageEndEvent,\n AGUIReasoningMessageChunkEvent,\n AGUIReasoningEndEvent,\n AGUIReasoningEncryptedValueEvent,\n AGUIReasoningEncryptedValueSubtype,\n AGUIActivitySnapshotEvent,\n AGUIActivityDeltaEvent,\n AGUIRawEvent,\n AGUICustomEvent,\n} from \"./agui-types.js\";\n\n// ─── Matching functions ──────────────────────────────────────────────────────\n\n/**\n * Extract the content of the last message with role \"user\" from the input.\n * Walks structured content arrays (e.g. `[{type:\"text\", text:\"...\"}, {type:\"document\", ...}]`)\n * and joins their text parts. Returns `\"\"` when no user message is present or has no text.\n */\nexport function extractLastUserMessage(input: AGUIRunAgentInput): string {\n if (!input.messages || input.messages.length === 0) return \"\";\n for (let i = input.messages.length - 1; i >= 0; i--) {\n const msg = input.messages[i];\n if (msg.role !== \"user\") continue;\n const text = extractTextFromContent(msg.content);\n if (text) return text;\n }\n return \"\";\n}\n\nfunction extractTextFromContent(content: AGUIMessage[\"content\"]): string {\n if (typeof content === \"string\") return content;\n if (!Array.isArray(content)) return \"\";\n const parts: string[] = [];\n for (const part of content) {\n if (\n part &&\n typeof part === \"object\" &&\n part.type === \"text\" &&\n typeof part.text === \"string\" &&\n part.text\n ) {\n parts.push(part.text);\n }\n }\n return parts.join(\" \").trim();\n}\n\n/**\n * Return the absolute last message if it has role \"tool\", otherwise null.\n */\nexport function getLastMessageIfToolResult(input: AGUIRunAgentInput): AGUIMessage | null {\n if (!input.messages || input.messages.length === 0) return null;\n const last = input.messages[input.messages.length - 1];\n return last.role === \"tool\" ? last : null;\n}\n\n/**\n * Check whether an input matches a fixture's match criteria.\n * All specified criteria must pass (AND logic).\n */\nexport function matchesFixture(input: AGUIRunAgentInput, match: AGUIFixtureMatch): boolean {\n if (match.message !== undefined) {\n const text = extractLastUserMessage(input);\n if (typeof match.message === \"string\") {\n if (!text.includes(match.message)) return false;\n } else {\n match.message.lastIndex = 0;\n if (!match.message.test(text)) return false;\n }\n }\n\n if (match.toolCallId !== undefined) {\n const lastMsg = input.messages?.[input.messages.length - 1];\n if (!lastMsg || lastMsg.role !== \"tool\" || lastMsg.toolCallId !== match.toolCallId) {\n return false;\n }\n }\n\n if (match.toolName !== undefined) {\n const tools = input.tools ?? [];\n if (!tools.some((t) => t.name === match.toolName)) return false;\n }\n\n if (match.stateKey !== undefined) {\n if (\n input.state === null ||\n input.state === undefined ||\n typeof input.state !== \"object\" ||\n !(match.stateKey in (input.state as Record<string, unknown>))\n ) {\n return false;\n }\n }\n\n if (match.predicate !== undefined) {\n if (!match.predicate(input)) return false;\n }\n\n return true;\n}\n\n/**\n * Find the first fixture whose match criteria pass for the given input.\n */\nexport function findFixture(input: AGUIRunAgentInput, fixtures: AGUIFixture[]): AGUIFixture | null {\n for (const fixture of fixtures) {\n if (matchesFixture(input, fixture.match)) {\n return fixture;\n }\n }\n return null;\n}\n\n// ─── Builder options ─────────────────────────────────────────────────────────\n\nexport interface AGUIBuildOpts {\n threadId?: string;\n runId?: string;\n parentRunId?: string;\n /** For tool call builder: include a result event */\n result?: string;\n}\n\n// ─── Event builders ──────────────────────────────────────────────────────────\n\nfunction makeRunStarted(opts?: AGUIBuildOpts): AGUIRunStartedEvent {\n return {\n type: \"RUN_STARTED\",\n threadId: opts?.threadId ?? randomUUID(),\n runId: opts?.runId ?? randomUUID(),\n ...(opts?.parentRunId ? { parentRunId: opts.parentRunId } : {}),\n };\n}\n\nfunction makeRunFinished(\n started: AGUIRunStartedEvent,\n finishOpts?: { outcome?: AGUIRunFinishedOutcome; result?: unknown },\n): AGUIRunFinishedEvent {\n return {\n type: \"RUN_FINISHED\",\n threadId: started.threadId,\n runId: started.runId,\n ...(finishOpts?.result !== undefined ? { result: finishOpts.result } : {}),\n ...(finishOpts?.outcome !== undefined ? { outcome: finishOpts.outcome } : {}),\n };\n}\n\n/**\n * Build a complete text message response sequence.\n * [RUN_STARTED, TEXT_MESSAGE_START, TEXT_MESSAGE_CONTENT, TEXT_MESSAGE_END, RUN_FINISHED]\n */\nexport function buildTextResponse(text: string, opts?: AGUIBuildOpts): AGUIEvent[] {\n const started = makeRunStarted(opts);\n const messageId = randomUUID();\n return [\n started,\n {\n type: \"TEXT_MESSAGE_START\",\n messageId,\n role: \"assistant\",\n } as AGUITextMessageStartEvent,\n {\n type: \"TEXT_MESSAGE_CONTENT\",\n messageId,\n delta: text,\n } as AGUITextMessageContentEvent,\n {\n type: \"TEXT_MESSAGE_END\",\n messageId,\n } as AGUITextMessageEndEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build a text chunk response (single chunk, no start/end envelope).\n * [RUN_STARTED, TEXT_MESSAGE_CHUNK, RUN_FINISHED]\n */\nexport function buildTextChunkResponse(text: string, opts?: AGUIBuildOpts): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"TEXT_MESSAGE_CHUNK\",\n messageId: randomUUID(),\n role: \"assistant\",\n delta: text,\n } as AGUITextMessageChunkEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build a tool call response sequence.\n * [RUN_STARTED, TOOL_CALL_START, TOOL_CALL_ARGS, TOOL_CALL_END, (TOOL_CALL_RESULT)?, RUN_FINISHED]\n */\nexport function buildToolCallResponse(\n toolName: string,\n args: string,\n opts?: AGUIBuildOpts,\n): AGUIEvent[] {\n const started = makeRunStarted(opts);\n const toolCallId = randomUUID();\n const events: AGUIEvent[] = [\n started,\n {\n type: \"TOOL_CALL_START\",\n toolCallId,\n toolCallName: toolName,\n } as AGUIToolCallStartEvent,\n {\n type: \"TOOL_CALL_ARGS\",\n toolCallId,\n delta: args,\n } as AGUIToolCallArgsEvent,\n {\n type: \"TOOL_CALL_END\",\n toolCallId,\n } as AGUIToolCallEndEvent,\n ];\n\n if (opts?.result !== undefined) {\n events.push({\n type: \"TOOL_CALL_RESULT\",\n messageId: randomUUID(),\n toolCallId,\n content: opts.result,\n role: \"tool\",\n } as AGUIToolCallResultEvent);\n }\n\n events.push(makeRunFinished(started));\n return events;\n}\n\n/**\n * Build a state snapshot response.\n * [RUN_STARTED, STATE_SNAPSHOT, RUN_FINISHED]\n */\nexport function buildStateUpdate(snapshot: unknown, opts?: AGUIBuildOpts): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"STATE_SNAPSHOT\",\n snapshot,\n } as AGUIStateSnapshotEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build a state delta response (JSON Patch).\n * [RUN_STARTED, STATE_DELTA, RUN_FINISHED]\n */\nexport function buildStateDelta(patches: unknown[], opts?: AGUIBuildOpts): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"STATE_DELTA\",\n delta: patches,\n } as AGUIStateDeltaEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build a messages snapshot response.\n * [RUN_STARTED, MESSAGES_SNAPSHOT, RUN_FINISHED]\n */\nexport function buildMessagesSnapshot(messages: AGUIMessage[], opts?: AGUIBuildOpts): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"MESSAGES_SNAPSHOT\",\n messages,\n } as AGUIMessagesSnapshotEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build a reasoning response sequence.\n * [RUN_STARTED, REASONING_START, REASONING_MESSAGE_START, REASONING_MESSAGE_CONTENT,\n * REASONING_MESSAGE_END, REASONING_END, RUN_FINISHED]\n */\nexport function buildReasoningResponse(text: string, opts?: AGUIBuildOpts): AGUIEvent[] {\n const started = makeRunStarted(opts);\n const messageId = randomUUID();\n return [\n started,\n {\n type: \"REASONING_START\",\n messageId,\n } as AGUIReasoningStartEvent,\n {\n type: \"REASONING_MESSAGE_START\",\n messageId,\n role: \"reasoning\",\n } as AGUIReasoningMessageStartEvent,\n {\n type: \"REASONING_MESSAGE_CONTENT\",\n messageId,\n delta: text,\n } as AGUIReasoningMessageContentEvent,\n {\n type: \"REASONING_MESSAGE_END\",\n messageId,\n } as AGUIReasoningMessageEndEvent,\n {\n type: \"REASONING_END\",\n messageId,\n } as AGUIReasoningEndEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build an activity snapshot response.\n * [RUN_STARTED, ACTIVITY_SNAPSHOT, RUN_FINISHED]\n */\nexport function buildActivityResponse(\n messageId: string,\n activityType: string,\n content: Record<string, unknown>,\n opts?: AGUIBuildOpts,\n): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"ACTIVITY_SNAPSHOT\",\n messageId,\n activityType,\n content,\n replace: true,\n } as AGUIActivitySnapshotEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build an error response.\n * [RUN_STARTED, RUN_ERROR] (no RUN_FINISHED — the run errored)\n */\nexport function buildErrorResponse(\n message: string,\n code?: string,\n opts?: AGUIBuildOpts,\n): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"RUN_ERROR\",\n message,\n ...(code !== undefined ? { code } : {}),\n } as AGUIRunErrorEvent,\n ];\n}\n\n/**\n * Build a step-wrapped text response.\n * [RUN_STARTED, STEP_STARTED, TEXT_MESSAGE_START, TEXT_MESSAGE_CONTENT,\n * TEXT_MESSAGE_END, STEP_FINISHED, RUN_FINISHED]\n */\nexport function buildStepWithText(\n stepName: string,\n text: string,\n opts?: AGUIBuildOpts,\n): AGUIEvent[] {\n const started = makeRunStarted(opts);\n const messageId = randomUUID();\n return [\n started,\n {\n type: \"STEP_STARTED\",\n stepName,\n } as AGUIStepStartedEvent,\n {\n type: \"TEXT_MESSAGE_START\",\n messageId,\n role: \"assistant\",\n } as AGUITextMessageStartEvent,\n {\n type: \"TEXT_MESSAGE_CONTENT\",\n messageId,\n delta: text,\n } as AGUITextMessageContentEvent,\n {\n type: \"TEXT_MESSAGE_END\",\n messageId,\n } as AGUITextMessageEndEvent,\n {\n type: \"STEP_FINISHED\",\n stepName,\n } as AGUIStepFinishedEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Combine multiple builder outputs into a single run.\n * Strips RUN_STARTED/RUN_FINISHED from each input, wraps all inner events\n * in one RUN_STARTED...RUN_FINISHED pair.\n */\nexport function buildCompositeResponse(\n builderOutputs: AGUIEvent[][],\n opts?: AGUIBuildOpts,\n): AGUIEvent[] {\n const started = makeRunStarted(opts);\n const inner: AGUIEvent[] = [];\n\n for (const events of builderOutputs) {\n for (const event of events) {\n if (event.type !== \"RUN_STARTED\" && event.type !== \"RUN_FINISHED\") {\n inner.push(event);\n }\n }\n }\n\n const hasError = inner.some((e) => e.type === \"RUN_ERROR\");\n return [started, ...inner, ...(hasError ? [] : [makeRunFinished(started)])];\n}\n\n// ─── Convenience event builders ─────────────────────────────────────────────\n\n/**\n * Build an activity delta response (JSON Patch on an activity).\n * [RUN_STARTED, ACTIVITY_DELTA, RUN_FINISHED]\n */\nexport function buildActivityDelta(\n messageId: string,\n activityType: string,\n patch: unknown[],\n opts?: AGUIBuildOpts,\n): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"ACTIVITY_DELTA\",\n messageId,\n activityType,\n patch,\n } as AGUIActivityDeltaEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build a tool call chunk response (single chunk, no start/end envelope).\n * [RUN_STARTED, TOOL_CALL_CHUNK, RUN_FINISHED]\n */\nexport function buildToolCallChunk(\n delta: string,\n opts?: AGUIBuildOpts & {\n toolCallId?: string;\n toolCallName?: string;\n parentMessageId?: string;\n },\n): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"TOOL_CALL_CHUNK\",\n ...(opts?.toolCallId !== undefined ? { toolCallId: opts.toolCallId } : {}),\n ...(opts?.toolCallName !== undefined ? { toolCallName: opts.toolCallName } : {}),\n ...(opts?.parentMessageId !== undefined ? { parentMessageId: opts.parentMessageId } : {}),\n delta,\n } as AGUIToolCallChunkEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build a raw event response.\n * [RUN_STARTED, RAW, RUN_FINISHED]\n */\nexport function buildRawEvent(event: unknown, source?: string, opts?: AGUIBuildOpts): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"RAW\",\n event,\n ...(source !== undefined ? { source } : {}),\n } as AGUIRawEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build a custom event response.\n * [RUN_STARTED, CUSTOM, RUN_FINISHED]\n */\nexport function buildCustomEvent(name: string, value: unknown, opts?: AGUIBuildOpts): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"CUSTOM\",\n name,\n value,\n } as AGUICustomEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build a reasoning message chunk response (single chunk, no start/end envelope).\n * [RUN_STARTED, REASONING_MESSAGE_CHUNK, RUN_FINISHED]\n */\nexport function buildReasoningChunk(\n delta: string,\n opts?: AGUIBuildOpts & { messageId?: string },\n): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"REASONING_MESSAGE_CHUNK\",\n ...(opts?.messageId !== undefined ? { messageId: opts.messageId } : {}),\n delta,\n } as AGUIReasoningMessageChunkEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build a reasoning encrypted value event response.\n * [RUN_STARTED, REASONING_ENCRYPTED_VALUE, RUN_FINISHED]\n */\nexport function buildReasoningEncryptedValue(\n subtype: AGUIReasoningEncryptedValueSubtype,\n entityId: string,\n encryptedValue: string,\n opts?: AGUIBuildOpts,\n): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"REASONING_ENCRYPTED_VALUE\",\n subtype,\n entityId,\n encryptedValue,\n } as AGUIReasoningEncryptedValueEvent,\n makeRunFinished(started),\n ];\n}\n\n// ─── SSE writer ──────────────────────────────────────────────────────────────\n\n/**\n * Write AG-UI events as an SSE stream to an HTTP response.\n * Sets appropriate headers, serializes each event as `data: {...}\\n\\n`,\n * and optionally delays between events.\n */\nexport async function writeAGUIEventStream(\n res: http.ServerResponse,\n events: AGUIEvent[],\n opts?: { delayMs?: number; signal?: AbortSignal },\n): Promise<void> {\n const delayMs = opts?.delayMs ?? 0;\n\n res.writeHead(200, {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n });\n\n for (const event of events) {\n if (opts?.signal?.aborted) break;\n if (res.socket?.destroyed) break;\n\n const stamped = { ...event, timestamp: event.timestamp ?? Date.now() };\n try {\n res.write(`data: ${JSON.stringify(stamped)}\\n\\n`);\n } catch (err) {\n if (err instanceof TypeError || err instanceof RangeError) {\n console.warn(\"AG-UI SSE write failed (serialization):\", (err as Error).message);\n } else if (err instanceof Error) {\n console.warn(\"AG-UI SSE write failed:\", err.message);\n }\n break;\n }\n\n if (delayMs > 0) {\n await new Promise<void>((resolve) => setTimeout(resolve, delayMs));\n }\n }\n\n if (!res.writableEnded) res.end();\n}\n"],"mappings":"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"}
|
package/dist/agui-handler.d.cts
CHANGED
|
@@ -5,8 +5,14 @@ import * as http$1 from "node:http";
|
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Extract the content of the last message with role "user" from the input.
|
|
8
|
+
* Walks structured content arrays (e.g. `[{type:"text", text:"..."}, {type:"document", ...}]`)
|
|
9
|
+
* and joins their text parts. Returns `""` when no user message is present or has no text.
|
|
8
10
|
*/
|
|
9
11
|
declare function extractLastUserMessage(input: AGUIRunAgentInput): string;
|
|
12
|
+
/**
|
|
13
|
+
* Return the absolute last message if it has role "tool", otherwise null.
|
|
14
|
+
*/
|
|
15
|
+
declare function getLastMessageIfToolResult(input: AGUIRunAgentInput): AGUIMessage | null;
|
|
10
16
|
/**
|
|
11
17
|
* Check whether an input matches a fixture's match criteria.
|
|
12
18
|
* All specified criteria must pass (AND logic).
|
|
@@ -128,5 +134,5 @@ declare function writeAGUIEventStream(res: http$1.ServerResponse, events: AGUIEv
|
|
|
128
134
|
}): Promise<void>;
|
|
129
135
|
//# sourceMappingURL=agui-handler.d.ts.map
|
|
130
136
|
//#endregion
|
|
131
|
-
export { AGUIBuildOpts, buildActivityDelta, buildActivityResponse, buildCompositeResponse, buildCustomEvent, buildErrorResponse, buildMessagesSnapshot, buildRawEvent, buildReasoningChunk, buildReasoningEncryptedValue, buildReasoningResponse, buildStateDelta, buildStateUpdate, buildStepWithText, buildTextChunkResponse, buildTextResponse, buildToolCallChunk, buildToolCallResponse, extractLastUserMessage, findFixture, matchesFixture, writeAGUIEventStream };
|
|
137
|
+
export { AGUIBuildOpts, buildActivityDelta, buildActivityResponse, buildCompositeResponse, buildCustomEvent, buildErrorResponse, buildMessagesSnapshot, buildRawEvent, buildReasoningChunk, buildReasoningEncryptedValue, buildReasoningResponse, buildStateDelta, buildStateUpdate, buildStepWithText, buildTextChunkResponse, buildTextResponse, buildToolCallChunk, buildToolCallResponse, extractLastUserMessage, findFixture, getLastMessageIfToolResult, matchesFixture, writeAGUIEventStream };
|
|
132
138
|
//# sourceMappingURL=agui-handler.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agui-handler.d.cts","names":[],"sources":["../src/agui-handler.ts"],"sourcesContent":[],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"file":"agui-handler.d.cts","names":[],"sources":["../src/agui-handler.ts"],"sourcesContent":[],"mappings":"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"}
|
package/dist/agui-handler.d.ts
CHANGED
|
@@ -5,8 +5,14 @@ import * as http$1 from "node:http";
|
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* Extract the content of the last message with role "user" from the input.
|
|
8
|
+
* Walks structured content arrays (e.g. `[{type:"text", text:"..."}, {type:"document", ...}]`)
|
|
9
|
+
* and joins their text parts. Returns `""` when no user message is present or has no text.
|
|
8
10
|
*/
|
|
9
11
|
declare function extractLastUserMessage(input: AGUIRunAgentInput): string;
|
|
12
|
+
/**
|
|
13
|
+
* Return the absolute last message if it has role "tool", otherwise null.
|
|
14
|
+
*/
|
|
15
|
+
declare function getLastMessageIfToolResult(input: AGUIRunAgentInput): AGUIMessage | null;
|
|
10
16
|
/**
|
|
11
17
|
* Check whether an input matches a fixture's match criteria.
|
|
12
18
|
* All specified criteria must pass (AND logic).
|
|
@@ -128,5 +134,5 @@ declare function writeAGUIEventStream(res: http$1.ServerResponse, events: AGUIEv
|
|
|
128
134
|
}): Promise<void>;
|
|
129
135
|
//# sourceMappingURL=agui-handler.d.ts.map
|
|
130
136
|
//#endregion
|
|
131
|
-
export { AGUIBuildOpts, buildActivityDelta, buildActivityResponse, buildCompositeResponse, buildCustomEvent, buildErrorResponse, buildMessagesSnapshot, buildRawEvent, buildReasoningChunk, buildReasoningEncryptedValue, buildReasoningResponse, buildStateDelta, buildStateUpdate, buildStepWithText, buildTextChunkResponse, buildTextResponse, buildToolCallChunk, buildToolCallResponse, extractLastUserMessage, findFixture, matchesFixture, writeAGUIEventStream };
|
|
137
|
+
export { AGUIBuildOpts, buildActivityDelta, buildActivityResponse, buildCompositeResponse, buildCustomEvent, buildErrorResponse, buildMessagesSnapshot, buildRawEvent, buildReasoningChunk, buildReasoningEncryptedValue, buildReasoningResponse, buildStateDelta, buildStateUpdate, buildStepWithText, buildTextChunkResponse, buildTextResponse, buildToolCallChunk, buildToolCallResponse, extractLastUserMessage, findFixture, getLastMessageIfToolResult, matchesFixture, writeAGUIEventStream };
|
|
132
138
|
//# sourceMappingURL=agui-handler.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agui-handler.d.ts","names":[],"sources":["../src/agui-handler.ts"],"sourcesContent":[],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"file":"agui-handler.d.ts","names":[],"sources":["../src/agui-handler.ts"],"sourcesContent":[],"mappings":"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"}
|
package/dist/agui-handler.js
CHANGED
|
@@ -3,15 +3,34 @@ import { randomUUID } from "node:crypto";
|
|
|
3
3
|
//#region src/agui-handler.ts
|
|
4
4
|
/**
|
|
5
5
|
* Extract the content of the last message with role "user" from the input.
|
|
6
|
+
* Walks structured content arrays (e.g. `[{type:"text", text:"..."}, {type:"document", ...}]`)
|
|
7
|
+
* and joins their text parts. Returns `""` when no user message is present or has no text.
|
|
6
8
|
*/
|
|
7
9
|
function extractLastUserMessage(input) {
|
|
8
10
|
if (!input.messages || input.messages.length === 0) return "";
|
|
9
11
|
for (let i = input.messages.length - 1; i >= 0; i--) {
|
|
10
12
|
const msg = input.messages[i];
|
|
11
|
-
if (msg.role
|
|
13
|
+
if (msg.role !== "user") continue;
|
|
14
|
+
const text = extractTextFromContent(msg.content);
|
|
15
|
+
if (text) return text;
|
|
12
16
|
}
|
|
13
17
|
return "";
|
|
14
18
|
}
|
|
19
|
+
function extractTextFromContent(content) {
|
|
20
|
+
if (typeof content === "string") return content;
|
|
21
|
+
if (!Array.isArray(content)) return "";
|
|
22
|
+
const parts = [];
|
|
23
|
+
for (const part of content) if (part && typeof part === "object" && part.type === "text" && typeof part.text === "string" && part.text) parts.push(part.text);
|
|
24
|
+
return parts.join(" ").trim();
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Return the absolute last message if it has role "tool", otherwise null.
|
|
28
|
+
*/
|
|
29
|
+
function getLastMessageIfToolResult(input) {
|
|
30
|
+
if (!input.messages || input.messages.length === 0) return null;
|
|
31
|
+
const last = input.messages[input.messages.length - 1];
|
|
32
|
+
return last.role === "tool" ? last : null;
|
|
33
|
+
}
|
|
15
34
|
/**
|
|
16
35
|
* Check whether an input matches a fixture's match criteria.
|
|
17
36
|
* All specified criteria must pass (AND logic).
|
|
@@ -26,6 +45,10 @@ function matchesFixture(input, match) {
|
|
|
26
45
|
if (!match.message.test(text)) return false;
|
|
27
46
|
}
|
|
28
47
|
}
|
|
48
|
+
if (match.toolCallId !== void 0) {
|
|
49
|
+
const lastMsg = input.messages?.[input.messages.length - 1];
|
|
50
|
+
if (!lastMsg || lastMsg.role !== "tool" || lastMsg.toolCallId !== match.toolCallId) return false;
|
|
51
|
+
}
|
|
29
52
|
if (match.toolName !== void 0) {
|
|
30
53
|
if (!(input.tools ?? []).some((t) => t.name === match.toolName)) return false;
|
|
31
54
|
}
|
|
@@ -430,5 +453,5 @@ async function writeAGUIEventStream(res, events, opts) {
|
|
|
430
453
|
}
|
|
431
454
|
|
|
432
455
|
//#endregion
|
|
433
|
-
export { buildActivityDelta, buildActivityResponse, buildCompositeResponse, buildCustomEvent, buildErrorResponse, buildMessagesSnapshot, buildRawEvent, buildReasoningChunk, buildReasoningEncryptedValue, buildReasoningResponse, buildStateDelta, buildStateUpdate, buildStepWithText, buildTextChunkResponse, buildTextResponse, buildToolCallChunk, buildToolCallResponse, extractLastUserMessage, findFixture, matchesFixture, writeAGUIEventStream };
|
|
456
|
+
export { buildActivityDelta, buildActivityResponse, buildCompositeResponse, buildCustomEvent, buildErrorResponse, buildMessagesSnapshot, buildRawEvent, buildReasoningChunk, buildReasoningEncryptedValue, buildReasoningResponse, buildStateDelta, buildStateUpdate, buildStepWithText, buildTextChunkResponse, buildTextResponse, buildToolCallChunk, buildToolCallResponse, extractLastUserMessage, findFixture, getLastMessageIfToolResult, matchesFixture, writeAGUIEventStream };
|
|
434
457
|
//# sourceMappingURL=agui-handler.js.map
|
package/dist/agui-handler.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agui-handler.js","names":[],"sources":["../src/agui-handler.ts"],"sourcesContent":["// ─── AG-UI Handler ───────────────────────────────────────────────────────────\n//\n// Matching functions, event builders, and SSE writer for AG-UI protocol.\n\nimport * as http from \"node:http\";\nimport { randomUUID } from \"node:crypto\";\n\nimport type {\n AGUIRunAgentInput,\n AGUIFixtureMatch,\n AGUIFixture,\n AGUIEvent,\n AGUIMessage,\n AGUIRunStartedEvent,\n AGUIRunFinishedEvent,\n AGUIRunFinishedOutcome,\n AGUIRunErrorEvent,\n AGUITextMessageStartEvent,\n AGUITextMessageContentEvent,\n AGUITextMessageEndEvent,\n AGUITextMessageChunkEvent,\n AGUIToolCallStartEvent,\n AGUIToolCallArgsEvent,\n AGUIToolCallEndEvent,\n AGUIToolCallChunkEvent,\n AGUIToolCallResultEvent,\n AGUIStateSnapshotEvent,\n AGUIStateDeltaEvent,\n AGUIMessagesSnapshotEvent,\n AGUIStepStartedEvent,\n AGUIStepFinishedEvent,\n AGUIReasoningStartEvent,\n AGUIReasoningMessageStartEvent,\n AGUIReasoningMessageContentEvent,\n AGUIReasoningMessageEndEvent,\n AGUIReasoningMessageChunkEvent,\n AGUIReasoningEndEvent,\n AGUIReasoningEncryptedValueEvent,\n AGUIReasoningEncryptedValueSubtype,\n AGUIActivitySnapshotEvent,\n AGUIActivityDeltaEvent,\n AGUIRawEvent,\n AGUICustomEvent,\n} from \"./agui-types.js\";\n\n// ─── Matching functions ──────────────────────────────────────────────────────\n\n/**\n * Extract the content of the last message with role \"user\" from the input.\n */\nexport function extractLastUserMessage(input: AGUIRunAgentInput): string {\n if (!input.messages || input.messages.length === 0) return \"\";\n for (let i = input.messages.length - 1; i >= 0; i--) {\n const msg = input.messages[i];\n if (msg.role === \"user\" && typeof msg.content === \"string\") {\n return msg.content;\n }\n }\n return \"\";\n}\n\n/**\n * Check whether an input matches a fixture's match criteria.\n * All specified criteria must pass (AND logic).\n */\nexport function matchesFixture(input: AGUIRunAgentInput, match: AGUIFixtureMatch): boolean {\n if (match.message !== undefined) {\n const text = extractLastUserMessage(input);\n if (typeof match.message === \"string\") {\n if (!text.includes(match.message)) return false;\n } else {\n match.message.lastIndex = 0;\n if (!match.message.test(text)) return false;\n }\n }\n\n if (match.toolName !== undefined) {\n const tools = input.tools ?? [];\n if (!tools.some((t) => t.name === match.toolName)) return false;\n }\n\n if (match.stateKey !== undefined) {\n if (\n input.state === null ||\n input.state === undefined ||\n typeof input.state !== \"object\" ||\n !(match.stateKey in (input.state as Record<string, unknown>))\n ) {\n return false;\n }\n }\n\n if (match.predicate !== undefined) {\n if (!match.predicate(input)) return false;\n }\n\n return true;\n}\n\n/**\n * Find the first fixture whose match criteria pass for the given input.\n */\nexport function findFixture(input: AGUIRunAgentInput, fixtures: AGUIFixture[]): AGUIFixture | null {\n for (const fixture of fixtures) {\n if (matchesFixture(input, fixture.match)) {\n return fixture;\n }\n }\n return null;\n}\n\n// ─── Builder options ─────────────────────────────────────────────────────────\n\nexport interface AGUIBuildOpts {\n threadId?: string;\n runId?: string;\n parentRunId?: string;\n /** For tool call builder: include a result event */\n result?: string;\n}\n\n// ─── Event builders ──────────────────────────────────────────────────────────\n\nfunction makeRunStarted(opts?: AGUIBuildOpts): AGUIRunStartedEvent {\n return {\n type: \"RUN_STARTED\",\n threadId: opts?.threadId ?? randomUUID(),\n runId: opts?.runId ?? randomUUID(),\n ...(opts?.parentRunId ? { parentRunId: opts.parentRunId } : {}),\n };\n}\n\nfunction makeRunFinished(\n started: AGUIRunStartedEvent,\n finishOpts?: { outcome?: AGUIRunFinishedOutcome; result?: unknown },\n): AGUIRunFinishedEvent {\n return {\n type: \"RUN_FINISHED\",\n threadId: started.threadId,\n runId: started.runId,\n ...(finishOpts?.result !== undefined ? { result: finishOpts.result } : {}),\n ...(finishOpts?.outcome !== undefined ? { outcome: finishOpts.outcome } : {}),\n };\n}\n\n/**\n * Build a complete text message response sequence.\n * [RUN_STARTED, TEXT_MESSAGE_START, TEXT_MESSAGE_CONTENT, TEXT_MESSAGE_END, RUN_FINISHED]\n */\nexport function buildTextResponse(text: string, opts?: AGUIBuildOpts): AGUIEvent[] {\n const started = makeRunStarted(opts);\n const messageId = randomUUID();\n return [\n started,\n {\n type: \"TEXT_MESSAGE_START\",\n messageId,\n role: \"assistant\",\n } as AGUITextMessageStartEvent,\n {\n type: \"TEXT_MESSAGE_CONTENT\",\n messageId,\n delta: text,\n } as AGUITextMessageContentEvent,\n {\n type: \"TEXT_MESSAGE_END\",\n messageId,\n } as AGUITextMessageEndEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build a text chunk response (single chunk, no start/end envelope).\n * [RUN_STARTED, TEXT_MESSAGE_CHUNK, RUN_FINISHED]\n */\nexport function buildTextChunkResponse(text: string, opts?: AGUIBuildOpts): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"TEXT_MESSAGE_CHUNK\",\n messageId: randomUUID(),\n role: \"assistant\",\n delta: text,\n } as AGUITextMessageChunkEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build a tool call response sequence.\n * [RUN_STARTED, TOOL_CALL_START, TOOL_CALL_ARGS, TOOL_CALL_END, (TOOL_CALL_RESULT)?, RUN_FINISHED]\n */\nexport function buildToolCallResponse(\n toolName: string,\n args: string,\n opts?: AGUIBuildOpts,\n): AGUIEvent[] {\n const started = makeRunStarted(opts);\n const toolCallId = randomUUID();\n const events: AGUIEvent[] = [\n started,\n {\n type: \"TOOL_CALL_START\",\n toolCallId,\n toolCallName: toolName,\n } as AGUIToolCallStartEvent,\n {\n type: \"TOOL_CALL_ARGS\",\n toolCallId,\n delta: args,\n } as AGUIToolCallArgsEvent,\n {\n type: \"TOOL_CALL_END\",\n toolCallId,\n } as AGUIToolCallEndEvent,\n ];\n\n if (opts?.result !== undefined) {\n events.push({\n type: \"TOOL_CALL_RESULT\",\n messageId: randomUUID(),\n toolCallId,\n content: opts.result,\n role: \"tool\",\n } as AGUIToolCallResultEvent);\n }\n\n events.push(makeRunFinished(started));\n return events;\n}\n\n/**\n * Build a state snapshot response.\n * [RUN_STARTED, STATE_SNAPSHOT, RUN_FINISHED]\n */\nexport function buildStateUpdate(snapshot: unknown, opts?: AGUIBuildOpts): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"STATE_SNAPSHOT\",\n snapshot,\n } as AGUIStateSnapshotEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build a state delta response (JSON Patch).\n * [RUN_STARTED, STATE_DELTA, RUN_FINISHED]\n */\nexport function buildStateDelta(patches: unknown[], opts?: AGUIBuildOpts): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"STATE_DELTA\",\n delta: patches,\n } as AGUIStateDeltaEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build a messages snapshot response.\n * [RUN_STARTED, MESSAGES_SNAPSHOT, RUN_FINISHED]\n */\nexport function buildMessagesSnapshot(messages: AGUIMessage[], opts?: AGUIBuildOpts): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"MESSAGES_SNAPSHOT\",\n messages,\n } as AGUIMessagesSnapshotEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build a reasoning response sequence.\n * [RUN_STARTED, REASONING_START, REASONING_MESSAGE_START, REASONING_MESSAGE_CONTENT,\n * REASONING_MESSAGE_END, REASONING_END, RUN_FINISHED]\n */\nexport function buildReasoningResponse(text: string, opts?: AGUIBuildOpts): AGUIEvent[] {\n const started = makeRunStarted(opts);\n const messageId = randomUUID();\n return [\n started,\n {\n type: \"REASONING_START\",\n messageId,\n } as AGUIReasoningStartEvent,\n {\n type: \"REASONING_MESSAGE_START\",\n messageId,\n role: \"reasoning\",\n } as AGUIReasoningMessageStartEvent,\n {\n type: \"REASONING_MESSAGE_CONTENT\",\n messageId,\n delta: text,\n } as AGUIReasoningMessageContentEvent,\n {\n type: \"REASONING_MESSAGE_END\",\n messageId,\n } as AGUIReasoningMessageEndEvent,\n {\n type: \"REASONING_END\",\n messageId,\n } as AGUIReasoningEndEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build an activity snapshot response.\n * [RUN_STARTED, ACTIVITY_SNAPSHOT, RUN_FINISHED]\n */\nexport function buildActivityResponse(\n messageId: string,\n activityType: string,\n content: Record<string, unknown>,\n opts?: AGUIBuildOpts,\n): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"ACTIVITY_SNAPSHOT\",\n messageId,\n activityType,\n content,\n replace: true,\n } as AGUIActivitySnapshotEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build an error response.\n * [RUN_STARTED, RUN_ERROR] (no RUN_FINISHED — the run errored)\n */\nexport function buildErrorResponse(\n message: string,\n code?: string,\n opts?: AGUIBuildOpts,\n): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"RUN_ERROR\",\n message,\n ...(code !== undefined ? { code } : {}),\n } as AGUIRunErrorEvent,\n ];\n}\n\n/**\n * Build a step-wrapped text response.\n * [RUN_STARTED, STEP_STARTED, TEXT_MESSAGE_START, TEXT_MESSAGE_CONTENT,\n * TEXT_MESSAGE_END, STEP_FINISHED, RUN_FINISHED]\n */\nexport function buildStepWithText(\n stepName: string,\n text: string,\n opts?: AGUIBuildOpts,\n): AGUIEvent[] {\n const started = makeRunStarted(opts);\n const messageId = randomUUID();\n return [\n started,\n {\n type: \"STEP_STARTED\",\n stepName,\n } as AGUIStepStartedEvent,\n {\n type: \"TEXT_MESSAGE_START\",\n messageId,\n role: \"assistant\",\n } as AGUITextMessageStartEvent,\n {\n type: \"TEXT_MESSAGE_CONTENT\",\n messageId,\n delta: text,\n } as AGUITextMessageContentEvent,\n {\n type: \"TEXT_MESSAGE_END\",\n messageId,\n } as AGUITextMessageEndEvent,\n {\n type: \"STEP_FINISHED\",\n stepName,\n } as AGUIStepFinishedEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Combine multiple builder outputs into a single run.\n * Strips RUN_STARTED/RUN_FINISHED from each input, wraps all inner events\n * in one RUN_STARTED...RUN_FINISHED pair.\n */\nexport function buildCompositeResponse(\n builderOutputs: AGUIEvent[][],\n opts?: AGUIBuildOpts,\n): AGUIEvent[] {\n const started = makeRunStarted(opts);\n const inner: AGUIEvent[] = [];\n\n for (const events of builderOutputs) {\n for (const event of events) {\n if (event.type !== \"RUN_STARTED\" && event.type !== \"RUN_FINISHED\") {\n inner.push(event);\n }\n }\n }\n\n const hasError = inner.some((e) => e.type === \"RUN_ERROR\");\n return [started, ...inner, ...(hasError ? [] : [makeRunFinished(started)])];\n}\n\n// ─── Convenience event builders ─────────────────────────────────────────────\n\n/**\n * Build an activity delta response (JSON Patch on an activity).\n * [RUN_STARTED, ACTIVITY_DELTA, RUN_FINISHED]\n */\nexport function buildActivityDelta(\n messageId: string,\n activityType: string,\n patch: unknown[],\n opts?: AGUIBuildOpts,\n): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"ACTIVITY_DELTA\",\n messageId,\n activityType,\n patch,\n } as AGUIActivityDeltaEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build a tool call chunk response (single chunk, no start/end envelope).\n * [RUN_STARTED, TOOL_CALL_CHUNK, RUN_FINISHED]\n */\nexport function buildToolCallChunk(\n delta: string,\n opts?: AGUIBuildOpts & {\n toolCallId?: string;\n toolCallName?: string;\n parentMessageId?: string;\n },\n): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"TOOL_CALL_CHUNK\",\n ...(opts?.toolCallId !== undefined ? { toolCallId: opts.toolCallId } : {}),\n ...(opts?.toolCallName !== undefined ? { toolCallName: opts.toolCallName } : {}),\n ...(opts?.parentMessageId !== undefined ? { parentMessageId: opts.parentMessageId } : {}),\n delta,\n } as AGUIToolCallChunkEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build a raw event response.\n * [RUN_STARTED, RAW, RUN_FINISHED]\n */\nexport function buildRawEvent(event: unknown, source?: string, opts?: AGUIBuildOpts): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"RAW\",\n event,\n ...(source !== undefined ? { source } : {}),\n } as AGUIRawEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build a custom event response.\n * [RUN_STARTED, CUSTOM, RUN_FINISHED]\n */\nexport function buildCustomEvent(name: string, value: unknown, opts?: AGUIBuildOpts): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"CUSTOM\",\n name,\n value,\n } as AGUICustomEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build a reasoning message chunk response (single chunk, no start/end envelope).\n * [RUN_STARTED, REASONING_MESSAGE_CHUNK, RUN_FINISHED]\n */\nexport function buildReasoningChunk(\n delta: string,\n opts?: AGUIBuildOpts & { messageId?: string },\n): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"REASONING_MESSAGE_CHUNK\",\n ...(opts?.messageId !== undefined ? { messageId: opts.messageId } : {}),\n delta,\n } as AGUIReasoningMessageChunkEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build a reasoning encrypted value event response.\n * [RUN_STARTED, REASONING_ENCRYPTED_VALUE, RUN_FINISHED]\n */\nexport function buildReasoningEncryptedValue(\n subtype: AGUIReasoningEncryptedValueSubtype,\n entityId: string,\n encryptedValue: string,\n opts?: AGUIBuildOpts,\n): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"REASONING_ENCRYPTED_VALUE\",\n subtype,\n entityId,\n encryptedValue,\n } as AGUIReasoningEncryptedValueEvent,\n makeRunFinished(started),\n ];\n}\n\n// ─── SSE writer ──────────────────────────────────────────────────────────────\n\n/**\n * Write AG-UI events as an SSE stream to an HTTP response.\n * Sets appropriate headers, serializes each event as `data: {...}\\n\\n`,\n * and optionally delays between events.\n */\nexport async function writeAGUIEventStream(\n res: http.ServerResponse,\n events: AGUIEvent[],\n opts?: { delayMs?: number; signal?: AbortSignal },\n): Promise<void> {\n const delayMs = opts?.delayMs ?? 0;\n\n res.writeHead(200, {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n });\n\n for (const event of events) {\n if (opts?.signal?.aborted) break;\n if (res.socket?.destroyed) break;\n\n const stamped = { ...event, timestamp: event.timestamp ?? Date.now() };\n try {\n res.write(`data: ${JSON.stringify(stamped)}\\n\\n`);\n } catch (err) {\n if (err instanceof TypeError || err instanceof RangeError) {\n console.warn(\"AG-UI SSE write failed (serialization):\", (err as Error).message);\n } else if (err instanceof Error) {\n console.warn(\"AG-UI SSE write failed:\", err.message);\n }\n break;\n }\n\n if (delayMs > 0) {\n await new Promise<void>((resolve) => setTimeout(resolve, delayMs));\n }\n }\n\n if (!res.writableEnded) res.end();\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"agui-handler.js","names":[],"sources":["../src/agui-handler.ts"],"sourcesContent":["// ─── AG-UI Handler ───────────────────────────────────────────────────────────\n//\n// Matching functions, event builders, and SSE writer for AG-UI protocol.\n\nimport * as http from \"node:http\";\nimport { randomUUID } from \"node:crypto\";\n\nimport type {\n AGUIRunAgentInput,\n AGUIFixtureMatch,\n AGUIFixture,\n AGUIEvent,\n AGUIMessage,\n AGUIRunStartedEvent,\n AGUIRunFinishedEvent,\n AGUIRunFinishedOutcome,\n AGUIRunErrorEvent,\n AGUITextMessageStartEvent,\n AGUITextMessageContentEvent,\n AGUITextMessageEndEvent,\n AGUITextMessageChunkEvent,\n AGUIToolCallStartEvent,\n AGUIToolCallArgsEvent,\n AGUIToolCallEndEvent,\n AGUIToolCallChunkEvent,\n AGUIToolCallResultEvent,\n AGUIStateSnapshotEvent,\n AGUIStateDeltaEvent,\n AGUIMessagesSnapshotEvent,\n AGUIStepStartedEvent,\n AGUIStepFinishedEvent,\n AGUIReasoningStartEvent,\n AGUIReasoningMessageStartEvent,\n AGUIReasoningMessageContentEvent,\n AGUIReasoningMessageEndEvent,\n AGUIReasoningMessageChunkEvent,\n AGUIReasoningEndEvent,\n AGUIReasoningEncryptedValueEvent,\n AGUIReasoningEncryptedValueSubtype,\n AGUIActivitySnapshotEvent,\n AGUIActivityDeltaEvent,\n AGUIRawEvent,\n AGUICustomEvent,\n} from \"./agui-types.js\";\n\n// ─── Matching functions ──────────────────────────────────────────────────────\n\n/**\n * Extract the content of the last message with role \"user\" from the input.\n * Walks structured content arrays (e.g. `[{type:\"text\", text:\"...\"}, {type:\"document\", ...}]`)\n * and joins their text parts. Returns `\"\"` when no user message is present or has no text.\n */\nexport function extractLastUserMessage(input: AGUIRunAgentInput): string {\n if (!input.messages || input.messages.length === 0) return \"\";\n for (let i = input.messages.length - 1; i >= 0; i--) {\n const msg = input.messages[i];\n if (msg.role !== \"user\") continue;\n const text = extractTextFromContent(msg.content);\n if (text) return text;\n }\n return \"\";\n}\n\nfunction extractTextFromContent(content: AGUIMessage[\"content\"]): string {\n if (typeof content === \"string\") return content;\n if (!Array.isArray(content)) return \"\";\n const parts: string[] = [];\n for (const part of content) {\n if (\n part &&\n typeof part === \"object\" &&\n part.type === \"text\" &&\n typeof part.text === \"string\" &&\n part.text\n ) {\n parts.push(part.text);\n }\n }\n return parts.join(\" \").trim();\n}\n\n/**\n * Return the absolute last message if it has role \"tool\", otherwise null.\n */\nexport function getLastMessageIfToolResult(input: AGUIRunAgentInput): AGUIMessage | null {\n if (!input.messages || input.messages.length === 0) return null;\n const last = input.messages[input.messages.length - 1];\n return last.role === \"tool\" ? last : null;\n}\n\n/**\n * Check whether an input matches a fixture's match criteria.\n * All specified criteria must pass (AND logic).\n */\nexport function matchesFixture(input: AGUIRunAgentInput, match: AGUIFixtureMatch): boolean {\n if (match.message !== undefined) {\n const text = extractLastUserMessage(input);\n if (typeof match.message === \"string\") {\n if (!text.includes(match.message)) return false;\n } else {\n match.message.lastIndex = 0;\n if (!match.message.test(text)) return false;\n }\n }\n\n if (match.toolCallId !== undefined) {\n const lastMsg = input.messages?.[input.messages.length - 1];\n if (!lastMsg || lastMsg.role !== \"tool\" || lastMsg.toolCallId !== match.toolCallId) {\n return false;\n }\n }\n\n if (match.toolName !== undefined) {\n const tools = input.tools ?? [];\n if (!tools.some((t) => t.name === match.toolName)) return false;\n }\n\n if (match.stateKey !== undefined) {\n if (\n input.state === null ||\n input.state === undefined ||\n typeof input.state !== \"object\" ||\n !(match.stateKey in (input.state as Record<string, unknown>))\n ) {\n return false;\n }\n }\n\n if (match.predicate !== undefined) {\n if (!match.predicate(input)) return false;\n }\n\n return true;\n}\n\n/**\n * Find the first fixture whose match criteria pass for the given input.\n */\nexport function findFixture(input: AGUIRunAgentInput, fixtures: AGUIFixture[]): AGUIFixture | null {\n for (const fixture of fixtures) {\n if (matchesFixture(input, fixture.match)) {\n return fixture;\n }\n }\n return null;\n}\n\n// ─── Builder options ─────────────────────────────────────────────────────────\n\nexport interface AGUIBuildOpts {\n threadId?: string;\n runId?: string;\n parentRunId?: string;\n /** For tool call builder: include a result event */\n result?: string;\n}\n\n// ─── Event builders ──────────────────────────────────────────────────────────\n\nfunction makeRunStarted(opts?: AGUIBuildOpts): AGUIRunStartedEvent {\n return {\n type: \"RUN_STARTED\",\n threadId: opts?.threadId ?? randomUUID(),\n runId: opts?.runId ?? randomUUID(),\n ...(opts?.parentRunId ? { parentRunId: opts.parentRunId } : {}),\n };\n}\n\nfunction makeRunFinished(\n started: AGUIRunStartedEvent,\n finishOpts?: { outcome?: AGUIRunFinishedOutcome; result?: unknown },\n): AGUIRunFinishedEvent {\n return {\n type: \"RUN_FINISHED\",\n threadId: started.threadId,\n runId: started.runId,\n ...(finishOpts?.result !== undefined ? { result: finishOpts.result } : {}),\n ...(finishOpts?.outcome !== undefined ? { outcome: finishOpts.outcome } : {}),\n };\n}\n\n/**\n * Build a complete text message response sequence.\n * [RUN_STARTED, TEXT_MESSAGE_START, TEXT_MESSAGE_CONTENT, TEXT_MESSAGE_END, RUN_FINISHED]\n */\nexport function buildTextResponse(text: string, opts?: AGUIBuildOpts): AGUIEvent[] {\n const started = makeRunStarted(opts);\n const messageId = randomUUID();\n return [\n started,\n {\n type: \"TEXT_MESSAGE_START\",\n messageId,\n role: \"assistant\",\n } as AGUITextMessageStartEvent,\n {\n type: \"TEXT_MESSAGE_CONTENT\",\n messageId,\n delta: text,\n } as AGUITextMessageContentEvent,\n {\n type: \"TEXT_MESSAGE_END\",\n messageId,\n } as AGUITextMessageEndEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build a text chunk response (single chunk, no start/end envelope).\n * [RUN_STARTED, TEXT_MESSAGE_CHUNK, RUN_FINISHED]\n */\nexport function buildTextChunkResponse(text: string, opts?: AGUIBuildOpts): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"TEXT_MESSAGE_CHUNK\",\n messageId: randomUUID(),\n role: \"assistant\",\n delta: text,\n } as AGUITextMessageChunkEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build a tool call response sequence.\n * [RUN_STARTED, TOOL_CALL_START, TOOL_CALL_ARGS, TOOL_CALL_END, (TOOL_CALL_RESULT)?, RUN_FINISHED]\n */\nexport function buildToolCallResponse(\n toolName: string,\n args: string,\n opts?: AGUIBuildOpts,\n): AGUIEvent[] {\n const started = makeRunStarted(opts);\n const toolCallId = randomUUID();\n const events: AGUIEvent[] = [\n started,\n {\n type: \"TOOL_CALL_START\",\n toolCallId,\n toolCallName: toolName,\n } as AGUIToolCallStartEvent,\n {\n type: \"TOOL_CALL_ARGS\",\n toolCallId,\n delta: args,\n } as AGUIToolCallArgsEvent,\n {\n type: \"TOOL_CALL_END\",\n toolCallId,\n } as AGUIToolCallEndEvent,\n ];\n\n if (opts?.result !== undefined) {\n events.push({\n type: \"TOOL_CALL_RESULT\",\n messageId: randomUUID(),\n toolCallId,\n content: opts.result,\n role: \"tool\",\n } as AGUIToolCallResultEvent);\n }\n\n events.push(makeRunFinished(started));\n return events;\n}\n\n/**\n * Build a state snapshot response.\n * [RUN_STARTED, STATE_SNAPSHOT, RUN_FINISHED]\n */\nexport function buildStateUpdate(snapshot: unknown, opts?: AGUIBuildOpts): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"STATE_SNAPSHOT\",\n snapshot,\n } as AGUIStateSnapshotEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build a state delta response (JSON Patch).\n * [RUN_STARTED, STATE_DELTA, RUN_FINISHED]\n */\nexport function buildStateDelta(patches: unknown[], opts?: AGUIBuildOpts): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"STATE_DELTA\",\n delta: patches,\n } as AGUIStateDeltaEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build a messages snapshot response.\n * [RUN_STARTED, MESSAGES_SNAPSHOT, RUN_FINISHED]\n */\nexport function buildMessagesSnapshot(messages: AGUIMessage[], opts?: AGUIBuildOpts): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"MESSAGES_SNAPSHOT\",\n messages,\n } as AGUIMessagesSnapshotEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build a reasoning response sequence.\n * [RUN_STARTED, REASONING_START, REASONING_MESSAGE_START, REASONING_MESSAGE_CONTENT,\n * REASONING_MESSAGE_END, REASONING_END, RUN_FINISHED]\n */\nexport function buildReasoningResponse(text: string, opts?: AGUIBuildOpts): AGUIEvent[] {\n const started = makeRunStarted(opts);\n const messageId = randomUUID();\n return [\n started,\n {\n type: \"REASONING_START\",\n messageId,\n } as AGUIReasoningStartEvent,\n {\n type: \"REASONING_MESSAGE_START\",\n messageId,\n role: \"reasoning\",\n } as AGUIReasoningMessageStartEvent,\n {\n type: \"REASONING_MESSAGE_CONTENT\",\n messageId,\n delta: text,\n } as AGUIReasoningMessageContentEvent,\n {\n type: \"REASONING_MESSAGE_END\",\n messageId,\n } as AGUIReasoningMessageEndEvent,\n {\n type: \"REASONING_END\",\n messageId,\n } as AGUIReasoningEndEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build an activity snapshot response.\n * [RUN_STARTED, ACTIVITY_SNAPSHOT, RUN_FINISHED]\n */\nexport function buildActivityResponse(\n messageId: string,\n activityType: string,\n content: Record<string, unknown>,\n opts?: AGUIBuildOpts,\n): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"ACTIVITY_SNAPSHOT\",\n messageId,\n activityType,\n content,\n replace: true,\n } as AGUIActivitySnapshotEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build an error response.\n * [RUN_STARTED, RUN_ERROR] (no RUN_FINISHED — the run errored)\n */\nexport function buildErrorResponse(\n message: string,\n code?: string,\n opts?: AGUIBuildOpts,\n): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"RUN_ERROR\",\n message,\n ...(code !== undefined ? { code } : {}),\n } as AGUIRunErrorEvent,\n ];\n}\n\n/**\n * Build a step-wrapped text response.\n * [RUN_STARTED, STEP_STARTED, TEXT_MESSAGE_START, TEXT_MESSAGE_CONTENT,\n * TEXT_MESSAGE_END, STEP_FINISHED, RUN_FINISHED]\n */\nexport function buildStepWithText(\n stepName: string,\n text: string,\n opts?: AGUIBuildOpts,\n): AGUIEvent[] {\n const started = makeRunStarted(opts);\n const messageId = randomUUID();\n return [\n started,\n {\n type: \"STEP_STARTED\",\n stepName,\n } as AGUIStepStartedEvent,\n {\n type: \"TEXT_MESSAGE_START\",\n messageId,\n role: \"assistant\",\n } as AGUITextMessageStartEvent,\n {\n type: \"TEXT_MESSAGE_CONTENT\",\n messageId,\n delta: text,\n } as AGUITextMessageContentEvent,\n {\n type: \"TEXT_MESSAGE_END\",\n messageId,\n } as AGUITextMessageEndEvent,\n {\n type: \"STEP_FINISHED\",\n stepName,\n } as AGUIStepFinishedEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Combine multiple builder outputs into a single run.\n * Strips RUN_STARTED/RUN_FINISHED from each input, wraps all inner events\n * in one RUN_STARTED...RUN_FINISHED pair.\n */\nexport function buildCompositeResponse(\n builderOutputs: AGUIEvent[][],\n opts?: AGUIBuildOpts,\n): AGUIEvent[] {\n const started = makeRunStarted(opts);\n const inner: AGUIEvent[] = [];\n\n for (const events of builderOutputs) {\n for (const event of events) {\n if (event.type !== \"RUN_STARTED\" && event.type !== \"RUN_FINISHED\") {\n inner.push(event);\n }\n }\n }\n\n const hasError = inner.some((e) => e.type === \"RUN_ERROR\");\n return [started, ...inner, ...(hasError ? [] : [makeRunFinished(started)])];\n}\n\n// ─── Convenience event builders ─────────────────────────────────────────────\n\n/**\n * Build an activity delta response (JSON Patch on an activity).\n * [RUN_STARTED, ACTIVITY_DELTA, RUN_FINISHED]\n */\nexport function buildActivityDelta(\n messageId: string,\n activityType: string,\n patch: unknown[],\n opts?: AGUIBuildOpts,\n): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"ACTIVITY_DELTA\",\n messageId,\n activityType,\n patch,\n } as AGUIActivityDeltaEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build a tool call chunk response (single chunk, no start/end envelope).\n * [RUN_STARTED, TOOL_CALL_CHUNK, RUN_FINISHED]\n */\nexport function buildToolCallChunk(\n delta: string,\n opts?: AGUIBuildOpts & {\n toolCallId?: string;\n toolCallName?: string;\n parentMessageId?: string;\n },\n): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"TOOL_CALL_CHUNK\",\n ...(opts?.toolCallId !== undefined ? { toolCallId: opts.toolCallId } : {}),\n ...(opts?.toolCallName !== undefined ? { toolCallName: opts.toolCallName } : {}),\n ...(opts?.parentMessageId !== undefined ? { parentMessageId: opts.parentMessageId } : {}),\n delta,\n } as AGUIToolCallChunkEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build a raw event response.\n * [RUN_STARTED, RAW, RUN_FINISHED]\n */\nexport function buildRawEvent(event: unknown, source?: string, opts?: AGUIBuildOpts): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"RAW\",\n event,\n ...(source !== undefined ? { source } : {}),\n } as AGUIRawEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build a custom event response.\n * [RUN_STARTED, CUSTOM, RUN_FINISHED]\n */\nexport function buildCustomEvent(name: string, value: unknown, opts?: AGUIBuildOpts): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"CUSTOM\",\n name,\n value,\n } as AGUICustomEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build a reasoning message chunk response (single chunk, no start/end envelope).\n * [RUN_STARTED, REASONING_MESSAGE_CHUNK, RUN_FINISHED]\n */\nexport function buildReasoningChunk(\n delta: string,\n opts?: AGUIBuildOpts & { messageId?: string },\n): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"REASONING_MESSAGE_CHUNK\",\n ...(opts?.messageId !== undefined ? { messageId: opts.messageId } : {}),\n delta,\n } as AGUIReasoningMessageChunkEvent,\n makeRunFinished(started),\n ];\n}\n\n/**\n * Build a reasoning encrypted value event response.\n * [RUN_STARTED, REASONING_ENCRYPTED_VALUE, RUN_FINISHED]\n */\nexport function buildReasoningEncryptedValue(\n subtype: AGUIReasoningEncryptedValueSubtype,\n entityId: string,\n encryptedValue: string,\n opts?: AGUIBuildOpts,\n): AGUIEvent[] {\n const started = makeRunStarted(opts);\n return [\n started,\n {\n type: \"REASONING_ENCRYPTED_VALUE\",\n subtype,\n entityId,\n encryptedValue,\n } as AGUIReasoningEncryptedValueEvent,\n makeRunFinished(started),\n ];\n}\n\n// ─── SSE writer ──────────────────────────────────────────────────────────────\n\n/**\n * Write AG-UI events as an SSE stream to an HTTP response.\n * Sets appropriate headers, serializes each event as `data: {...}\\n\\n`,\n * and optionally delays between events.\n */\nexport async function writeAGUIEventStream(\n res: http.ServerResponse,\n events: AGUIEvent[],\n opts?: { delayMs?: number; signal?: AbortSignal },\n): Promise<void> {\n const delayMs = opts?.delayMs ?? 0;\n\n res.writeHead(200, {\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n });\n\n for (const event of events) {\n if (opts?.signal?.aborted) break;\n if (res.socket?.destroyed) break;\n\n const stamped = { ...event, timestamp: event.timestamp ?? Date.now() };\n try {\n res.write(`data: ${JSON.stringify(stamped)}\\n\\n`);\n } catch (err) {\n if (err instanceof TypeError || err instanceof RangeError) {\n console.warn(\"AG-UI SSE write failed (serialization):\", (err as Error).message);\n } else if (err instanceof Error) {\n console.warn(\"AG-UI SSE write failed:\", err.message);\n }\n break;\n }\n\n if (delayMs > 0) {\n await new Promise<void>((resolve) => setTimeout(resolve, delayMs));\n }\n }\n\n if (!res.writableEnded) res.end();\n}\n"],"mappings":"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"}
|
package/dist/agui-mock.cjs
CHANGED
|
@@ -76,6 +76,14 @@ var AGUIMock = class {
|
|
|
76
76
|
});
|
|
77
77
|
return this;
|
|
78
78
|
}
|
|
79
|
+
onToolResult(toolCallId, events, delayMs) {
|
|
80
|
+
this.fixtures.push({
|
|
81
|
+
match: { toolCallId },
|
|
82
|
+
events,
|
|
83
|
+
delayMs
|
|
84
|
+
});
|
|
85
|
+
return this;
|
|
86
|
+
}
|
|
79
87
|
enableRecording(config) {
|
|
80
88
|
this.recordConfig = config;
|
|
81
89
|
return this;
|
package/dist/agui-mock.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agui-mock.cjs","names":["Logger","buildTextResponse","buildToolCallResponse","buildStateUpdate","buildReasoningResponse","readBody","findFixture","writeAGUIEventStream","proxyAndRecordAGUI","http","flattenHeaders"],"sources":["../src/agui-mock.ts"],"sourcesContent":["import * as http from \"node:http\";\nimport type { Mountable } from \"./types.js\";\nimport type { Journal } from \"./journal.js\";\nimport type { MetricsRegistry } from \"./metrics.js\";\nimport type {\n AGUIFixture,\n AGUIMockOptions,\n AGUIRecordConfig,\n AGUIEvent,\n AGUIRunAgentInput,\n} from \"./agui-types.js\";\nimport {\n findFixture,\n buildTextResponse,\n buildToolCallResponse,\n buildStateUpdate,\n buildReasoningResponse,\n writeAGUIEventStream,\n} from \"./agui-handler.js\";\nimport { flattenHeaders, readBody } from \"./helpers.js\";\nimport { proxyAndRecordAGUI } from \"./agui-recorder.js\";\nimport { Logger, type LogLevel } from \"./logger.js\";\n\nexport class AGUIMock implements Mountable {\n private fixtures: AGUIFixture[] = [];\n private server: http.Server | null = null;\n private journal: Journal | null = null;\n private registry: MetricsRegistry | null = null;\n private options: AGUIMockOptions;\n private baseUrl = \"\";\n private recordConfig: AGUIRecordConfig | undefined;\n private logger: Logger;\n\n constructor(options?: AGUIMockOptions) {\n this.options = options ?? {};\n this.logger = new Logger((options?.logLevel as LogLevel) ?? \"warn\");\n }\n\n // ---- Fluent registration API ----\n\n addFixture(fixture: AGUIFixture): this {\n this.fixtures.push(fixture);\n return this;\n }\n\n onMessage(pattern: string | RegExp, text: string, opts?: { delayMs?: number }): this {\n const events = buildTextResponse(text);\n this.fixtures.push({\n match: { message: pattern },\n events,\n delayMs: opts?.delayMs,\n });\n return this;\n }\n\n onRun(pattern: string | RegExp, events: AGUIEvent[], delayMs?: number): this {\n this.fixtures.push({\n match: { message: pattern },\n events,\n delayMs,\n });\n return this;\n }\n\n onToolCall(\n pattern: string | RegExp,\n toolName: string,\n args: string,\n opts?: { result?: string; delayMs?: number },\n ): this {\n const events = buildToolCallResponse(toolName, args, {\n result: opts?.result,\n });\n this.fixtures.push({\n match: { message: pattern },\n events,\n delayMs: opts?.delayMs,\n });\n return this;\n }\n\n onStateKey(key: string, snapshot: Record<string, unknown>, delayMs?: number): this {\n const events = buildStateUpdate(snapshot);\n this.fixtures.push({\n match: { stateKey: key },\n events,\n delayMs,\n });\n return this;\n }\n\n onReasoning(pattern: string | RegExp, text: string, opts?: { delayMs?: number }): this {\n const events = buildReasoningResponse(text);\n this.fixtures.push({\n match: { message: pattern },\n events,\n delayMs: opts?.delayMs,\n });\n return this;\n }\n\n onPredicate(\n predicate: (input: AGUIRunAgentInput) => boolean,\n events: AGUIEvent[],\n delayMs?: number,\n ): this {\n this.fixtures.push({\n match: { predicate },\n events,\n delayMs,\n });\n return this;\n }\n\n enableRecording(config: AGUIRecordConfig): this {\n this.recordConfig = config;\n return this;\n }\n\n reset(): this {\n this.fixtures = [];\n this.recordConfig = undefined;\n return this;\n }\n\n // ---- Mountable interface ----\n\n async handleRequest(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n pathname: string,\n ): Promise<boolean> {\n if (req.method !== \"POST\" || (pathname !== \"/\" && pathname !== \"\")) {\n return false;\n }\n\n if (this.registry) {\n this.registry.incrementCounter(\"aimock_agui_requests_total\", { method: \"POST\" });\n }\n\n let body: string;\n try {\n body = await readBody(req);\n } catch (err) {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n const detail = err instanceof Error ? err.message : \"body read failed\";\n res.end(JSON.stringify({ error: `Failed to read request body: ${detail}` }));\n this.journalRequest(req, pathname, 400);\n return true;\n }\n\n let input: AGUIRunAgentInput;\n try {\n input = JSON.parse(body) as AGUIRunAgentInput;\n } catch (err) {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n const detail = err instanceof Error ? err.message : \"unknown parse error\";\n res.end(JSON.stringify({ error: `Invalid JSON body: ${detail}` }));\n this.journalRequest(req, pathname, 400);\n return true;\n }\n\n const fixture = findFixture(input, this.fixtures);\n\n if (fixture) {\n await writeAGUIEventStream(res, fixture.events, { delayMs: fixture.delayMs });\n this.journalRequest(req, pathname, 200);\n return true;\n }\n\n // No match — if recording is enabled, proxy to upstream\n if (this.recordConfig) {\n const result = await proxyAndRecordAGUI(\n req,\n res,\n input,\n this.fixtures,\n this.recordConfig,\n this.logger,\n );\n if (result !== false) {\n this.journalRequest(req, pathname, result);\n return true;\n }\n }\n\n // No match, no recorder — 404\n res.writeHead(404, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"No matching AG-UI fixture\" }));\n this.journalRequest(req, pathname, 404);\n return true;\n }\n\n health(): { status: string; fixtures: number } {\n return {\n status: \"ok\",\n fixtures: this.fixtures.length,\n };\n }\n\n setJournal(journal: Journal): void {\n this.journal = journal;\n }\n\n setBaseUrl(url: string): void {\n this.baseUrl = url;\n }\n\n setRegistry(registry: MetricsRegistry): void {\n this.registry = registry;\n }\n\n // ---- Standalone mode ----\n\n async start(): Promise<string> {\n if (this.server) {\n throw new Error(\"AGUIMock server already started\");\n }\n\n const host = this.options.host ?? \"127.0.0.1\";\n const port = this.options.port ?? 0;\n\n return new Promise<string>((resolve, reject) => {\n const srv = http.createServer(async (req, res) => {\n const url = new URL(req.url ?? \"/\", `http://${req.headers.host ?? \"localhost\"}`);\n const handled = await this.handleRequest(req, res, url.pathname).catch((err) => {\n this.logger.error(`AGUIMock request error: ${err instanceof Error ? err.message : err}`);\n if (!res.headersSent) {\n res.writeHead(500);\n res.end(\"Internal server error\");\n } else if (!res.writableEnded) {\n res.end();\n }\n return true;\n });\n if (!handled && !res.headersSent) {\n res.writeHead(404, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Not found\" }));\n }\n });\n\n srv.on(\"error\", reject);\n\n srv.listen(port, host, () => {\n const addr = srv.address();\n if (typeof addr === \"object\" && addr !== null) {\n this.baseUrl = `http://${host}:${addr.port}`;\n }\n this.server = srv;\n resolve(this.baseUrl);\n });\n });\n }\n\n async stop(): Promise<void> {\n if (!this.server) {\n throw new Error(\"AGUIMock server not started\");\n }\n const srv = this.server;\n await new Promise<void>((resolve, reject) => {\n srv.close((err: Error | undefined) => (err ? reject(err) : resolve()));\n });\n this.server = null;\n }\n\n get url(): string {\n if (!this.server) {\n throw new Error(\"AGUIMock server not started\");\n }\n return this.baseUrl;\n }\n\n // ---- Private helpers ----\n\n private journalRequest(req: http.IncomingMessage, pathname: string, status: number): void {\n if (this.journal) {\n this.journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? pathname,\n headers: flattenHeaders(req.headers),\n body: null,\n service: \"agui\",\n response: { status, fixture: null },\n });\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"agui-mock.cjs","names":["Logger","buildTextResponse","buildToolCallResponse","buildStateUpdate","buildReasoningResponse","readBody","findFixture","writeAGUIEventStream","proxyAndRecordAGUI","http","flattenHeaders"],"sources":["../src/agui-mock.ts"],"sourcesContent":["import * as http from \"node:http\";\nimport type { Mountable } from \"./types.js\";\nimport type { Journal } from \"./journal.js\";\nimport type { MetricsRegistry } from \"./metrics.js\";\nimport type {\n AGUIFixture,\n AGUIMockOptions,\n AGUIRecordConfig,\n AGUIEvent,\n AGUIRunAgentInput,\n} from \"./agui-types.js\";\nimport {\n findFixture,\n buildTextResponse,\n buildToolCallResponse,\n buildStateUpdate,\n buildReasoningResponse,\n writeAGUIEventStream,\n} from \"./agui-handler.js\";\nimport { flattenHeaders, readBody } from \"./helpers.js\";\nimport { proxyAndRecordAGUI } from \"./agui-recorder.js\";\nimport { Logger, type LogLevel } from \"./logger.js\";\n\nexport class AGUIMock implements Mountable {\n private fixtures: AGUIFixture[] = [];\n private server: http.Server | null = null;\n private journal: Journal | null = null;\n private registry: MetricsRegistry | null = null;\n private options: AGUIMockOptions;\n private baseUrl = \"\";\n private recordConfig: AGUIRecordConfig | undefined;\n private logger: Logger;\n\n constructor(options?: AGUIMockOptions) {\n this.options = options ?? {};\n this.logger = new Logger((options?.logLevel as LogLevel) ?? \"warn\");\n }\n\n // ---- Fluent registration API ----\n\n addFixture(fixture: AGUIFixture): this {\n this.fixtures.push(fixture);\n return this;\n }\n\n onMessage(pattern: string | RegExp, text: string, opts?: { delayMs?: number }): this {\n const events = buildTextResponse(text);\n this.fixtures.push({\n match: { message: pattern },\n events,\n delayMs: opts?.delayMs,\n });\n return this;\n }\n\n onRun(pattern: string | RegExp, events: AGUIEvent[], delayMs?: number): this {\n this.fixtures.push({\n match: { message: pattern },\n events,\n delayMs,\n });\n return this;\n }\n\n onToolCall(\n pattern: string | RegExp,\n toolName: string,\n args: string,\n opts?: { result?: string; delayMs?: number },\n ): this {\n const events = buildToolCallResponse(toolName, args, {\n result: opts?.result,\n });\n this.fixtures.push({\n match: { message: pattern },\n events,\n delayMs: opts?.delayMs,\n });\n return this;\n }\n\n onStateKey(key: string, snapshot: Record<string, unknown>, delayMs?: number): this {\n const events = buildStateUpdate(snapshot);\n this.fixtures.push({\n match: { stateKey: key },\n events,\n delayMs,\n });\n return this;\n }\n\n onReasoning(pattern: string | RegExp, text: string, opts?: { delayMs?: number }): this {\n const events = buildReasoningResponse(text);\n this.fixtures.push({\n match: { message: pattern },\n events,\n delayMs: opts?.delayMs,\n });\n return this;\n }\n\n onPredicate(\n predicate: (input: AGUIRunAgentInput) => boolean,\n events: AGUIEvent[],\n delayMs?: number,\n ): this {\n this.fixtures.push({\n match: { predicate },\n events,\n delayMs,\n });\n return this;\n }\n\n onToolResult(toolCallId: string, events: AGUIEvent[], delayMs?: number): this {\n this.fixtures.push({\n match: { toolCallId },\n events,\n delayMs,\n });\n return this;\n }\n\n enableRecording(config: AGUIRecordConfig): this {\n this.recordConfig = config;\n return this;\n }\n\n reset(): this {\n this.fixtures = [];\n this.recordConfig = undefined;\n return this;\n }\n\n // ---- Mountable interface ----\n\n async handleRequest(\n req: http.IncomingMessage,\n res: http.ServerResponse,\n pathname: string,\n ): Promise<boolean> {\n if (req.method !== \"POST\" || (pathname !== \"/\" && pathname !== \"\")) {\n return false;\n }\n\n if (this.registry) {\n this.registry.incrementCounter(\"aimock_agui_requests_total\", { method: \"POST\" });\n }\n\n let body: string;\n try {\n body = await readBody(req);\n } catch (err) {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n const detail = err instanceof Error ? err.message : \"body read failed\";\n res.end(JSON.stringify({ error: `Failed to read request body: ${detail}` }));\n this.journalRequest(req, pathname, 400);\n return true;\n }\n\n let input: AGUIRunAgentInput;\n try {\n input = JSON.parse(body) as AGUIRunAgentInput;\n } catch (err) {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n const detail = err instanceof Error ? err.message : \"unknown parse error\";\n res.end(JSON.stringify({ error: `Invalid JSON body: ${detail}` }));\n this.journalRequest(req, pathname, 400);\n return true;\n }\n\n const fixture = findFixture(input, this.fixtures);\n\n if (fixture) {\n await writeAGUIEventStream(res, fixture.events, { delayMs: fixture.delayMs });\n this.journalRequest(req, pathname, 200);\n return true;\n }\n\n // No match — if recording is enabled, proxy to upstream\n if (this.recordConfig) {\n const result = await proxyAndRecordAGUI(\n req,\n res,\n input,\n this.fixtures,\n this.recordConfig,\n this.logger,\n );\n if (result !== false) {\n this.journalRequest(req, pathname, result);\n return true;\n }\n }\n\n // No match, no recorder — 404\n res.writeHead(404, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"No matching AG-UI fixture\" }));\n this.journalRequest(req, pathname, 404);\n return true;\n }\n\n health(): { status: string; fixtures: number } {\n return {\n status: \"ok\",\n fixtures: this.fixtures.length,\n };\n }\n\n setJournal(journal: Journal): void {\n this.journal = journal;\n }\n\n setBaseUrl(url: string): void {\n this.baseUrl = url;\n }\n\n setRegistry(registry: MetricsRegistry): void {\n this.registry = registry;\n }\n\n // ---- Standalone mode ----\n\n async start(): Promise<string> {\n if (this.server) {\n throw new Error(\"AGUIMock server already started\");\n }\n\n const host = this.options.host ?? \"127.0.0.1\";\n const port = this.options.port ?? 0;\n\n return new Promise<string>((resolve, reject) => {\n const srv = http.createServer(async (req, res) => {\n const url = new URL(req.url ?? \"/\", `http://${req.headers.host ?? \"localhost\"}`);\n const handled = await this.handleRequest(req, res, url.pathname).catch((err) => {\n this.logger.error(`AGUIMock request error: ${err instanceof Error ? err.message : err}`);\n if (!res.headersSent) {\n res.writeHead(500);\n res.end(\"Internal server error\");\n } else if (!res.writableEnded) {\n res.end();\n }\n return true;\n });\n if (!handled && !res.headersSent) {\n res.writeHead(404, { \"Content-Type\": \"application/json\" });\n res.end(JSON.stringify({ error: \"Not found\" }));\n }\n });\n\n srv.on(\"error\", reject);\n\n srv.listen(port, host, () => {\n const addr = srv.address();\n if (typeof addr === \"object\" && addr !== null) {\n this.baseUrl = `http://${host}:${addr.port}`;\n }\n this.server = srv;\n resolve(this.baseUrl);\n });\n });\n }\n\n async stop(): Promise<void> {\n if (!this.server) {\n throw new Error(\"AGUIMock server not started\");\n }\n const srv = this.server;\n await new Promise<void>((resolve, reject) => {\n srv.close((err: Error | undefined) => (err ? reject(err) : resolve()));\n });\n this.server = null;\n }\n\n get url(): string {\n if (!this.server) {\n throw new Error(\"AGUIMock server not started\");\n }\n return this.baseUrl;\n }\n\n // ---- Private helpers ----\n\n private journalRequest(req: http.IncomingMessage, pathname: string, status: number): void {\n if (this.journal) {\n this.journal.add({\n method: req.method ?? \"POST\",\n path: req.url ?? pathname,\n headers: flattenHeaders(req.headers),\n body: null,\n service: \"agui\",\n response: { status, fixture: null },\n });\n }\n }\n}\n"],"mappings":"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"}
|
package/dist/agui-mock.d.cts
CHANGED
|
@@ -29,6 +29,7 @@ declare class AGUIMock implements Mountable {
|
|
|
29
29
|
delayMs?: number;
|
|
30
30
|
}): this;
|
|
31
31
|
onPredicate(predicate: (input: AGUIRunAgentInput) => boolean, events: AGUIEvent[], delayMs?: number): this;
|
|
32
|
+
onToolResult(toolCallId: string, events: AGUIEvent[], delayMs?: number): this;
|
|
32
33
|
enableRecording(config: AGUIRecordConfig): this;
|
|
33
34
|
reset(): this;
|
|
34
35
|
handleRequest(req: http$1.IncomingMessage, res: http$1.ServerResponse, pathname: string): Promise<boolean>;
|
package/dist/agui-mock.d.cts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agui-mock.d.cts","names":[],"sources":["../src/agui-mock.ts"],"sourcesContent":[],"mappings":";;;;;;;cAuBa,QAAA,YAAoB;;EAApB,QAAA,MAAS;EAAA,QAAA,OAAA;UAUE,QAAA;UAOF,OAAA;UAKQ,OAAA;UAUJ,YAAA;UAAgB,MAAA;aAUpB,CAAA,OAAA,CAAA,EAhCE,eAgCF;YAgBc,CAAA,OAAA,EAzCd,WAyCc,CAAA,EAAA,IAAA;WAUJ,CAAA,OAAA,EAAA,MAAA,GA9CF,MA8CE,EAAA,IAAA,EAAA,MAAA,EAAA,KAAA,EAAA;IAWT,OAAA,CAAA,EAAA,MAAA;MACX,IAAA;
|
|
1
|
+
{"version":3,"file":"agui-mock.d.cts","names":[],"sources":["../src/agui-mock.ts"],"sourcesContent":[],"mappings":";;;;;;;cAuBa,QAAA,YAAoB;;EAApB,QAAA,MAAS;EAAA,QAAA,OAAA;UAUE,QAAA;UAOF,OAAA;UAKQ,OAAA;UAUJ,YAAA;UAAgB,MAAA;aAUpB,CAAA,OAAA,CAAA,EAhCE,eAgCF;YAgBc,CAAA,OAAA,EAzCd,WAyCc,CAAA,EAAA,IAAA;WAUJ,CAAA,OAAA,EAAA,MAAA,GA9CF,MA8CE,EAAA,IAAA,EAAA,MAAA,EAAA,KAAA,EAAA;IAWT,OAAA,CAAA,EAAA,MAAA;MACX,IAAA;OAW+B,CAAA,OAAA,EAAA,MAAA,GA3DjB,MA2DiB,EAAA,MAAA,EA3DD,SA2DC,EAAA,EAAA,OAAA,CAAA,EAAA,MAAA,CAAA,EAAA,IAAA;YASjB,CAAA,OAAA,EAAA,MAAA,GA1DJ,MA0DI,EAAA,QAAA,EAAA,MAAA,EAAA,IAAA,EAAA,MAAA,EAAA,KAAA,EAAA;IAcjB,MAAK,CAAA,EAAA,MAAA;IACL,OAAK,CAAA,EAAA,MAAA;MAET,IAAA;YAqEiB,CAAA,GAAA,EAAA,MAAA,EAAA,QAAA,EAhIc,MAgId,CAAA,MAAA,EAAA,OAAA,CAAA,EAAA,OAAA,CAAA,EAAA,MAAA,CAAA,EAAA,IAAA;aAQE,CAAA,OAAA,EAAA,MAAA,GA9HQ,MA8HR,EAAA,IAAA,EAAA,MAAA,EAAA,KAAA,EAAA;IAMP,OAAA,CAAA,EAAA,MAAA;MAwCD,IAAA;aAhPiB,CAAA,SAAA,EAAA,CAAA,KAAA,EA+EV,iBA/EU,EAAA,GAAA,OAAA,EAAA,MAAA,EAgFrB,SAhFqB,EAAA,EAAA,OAAA,CAAA,EAAA,MAAA,CAAA,EAAA,IAAA;EAAS,YAAA,CAAA,UAAA,EAAA,MAAA,EAAA,MAAA,EA2FC,SA3FD,EAAA,EAAA,OAAA,CAAA,EAAA,MAAA,CAAA,EAAA,IAAA;0BAoGhB;;qBAcjB,MAAA,CAAK,sBACL,MAAA,CAAK,mCAET;;;;;sBAqEiB;;wBAQE;WAMP;UAwCD"}
|
package/dist/agui-mock.d.ts
CHANGED
|
@@ -29,6 +29,7 @@ declare class AGUIMock implements Mountable {
|
|
|
29
29
|
delayMs?: number;
|
|
30
30
|
}): this;
|
|
31
31
|
onPredicate(predicate: (input: AGUIRunAgentInput) => boolean, events: AGUIEvent[], delayMs?: number): this;
|
|
32
|
+
onToolResult(toolCallId: string, events: AGUIEvent[], delayMs?: number): this;
|
|
32
33
|
enableRecording(config: AGUIRecordConfig): this;
|
|
33
34
|
reset(): this;
|
|
34
35
|
handleRequest(req: http$1.IncomingMessage, res: http$1.ServerResponse, pathname: string): Promise<boolean>;
|
package/dist/agui-mock.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agui-mock.d.ts","names":[],"sources":["../src/agui-mock.ts"],"sourcesContent":[],"mappings":";;;;;;;cAuBa,QAAA,YAAoB;;EAApB,QAAA,MAAS;EAAA,QAAA,OAAA;UAUE,QAAA;UAOF,OAAA;UAKQ,OAAA;UAUJ,YAAA;UAAgB,MAAA;aAUpB,CAAA,OAAA,CAAA,EAhCE,eAgCF;YAgBc,CAAA,OAAA,EAzCd,WAyCc,CAAA,EAAA,IAAA;WAUJ,CAAA,OAAA,EAAA,MAAA,GA9CF,MA8CE,EAAA,IAAA,EAAA,MAAA,EAAA,KAAA,EAAA;IAWT,OAAA,CAAA,EAAA,MAAA;MACX,IAAA;
|
|
1
|
+
{"version":3,"file":"agui-mock.d.ts","names":[],"sources":["../src/agui-mock.ts"],"sourcesContent":[],"mappings":";;;;;;;cAuBa,QAAA,YAAoB;;EAApB,QAAA,MAAS;EAAA,QAAA,OAAA;UAUE,QAAA;UAOF,OAAA;UAKQ,OAAA;UAUJ,YAAA;UAAgB,MAAA;aAUpB,CAAA,OAAA,CAAA,EAhCE,eAgCF;YAgBc,CAAA,OAAA,EAzCd,WAyCc,CAAA,EAAA,IAAA;WAUJ,CAAA,OAAA,EAAA,MAAA,GA9CF,MA8CE,EAAA,IAAA,EAAA,MAAA,EAAA,KAAA,EAAA;IAWT,OAAA,CAAA,EAAA,MAAA;MACX,IAAA;OAW+B,CAAA,OAAA,EAAA,MAAA,GA3DjB,MA2DiB,EAAA,MAAA,EA3DD,SA2DC,EAAA,EAAA,OAAA,CAAA,EAAA,MAAA,CAAA,EAAA,IAAA;YASjB,CAAA,OAAA,EAAA,MAAA,GA1DJ,MA0DI,EAAA,QAAA,EAAA,MAAA,EAAA,IAAA,EAAA,MAAA,EAAA,KAAA,EAAA;IAcjB,MAAK,CAAA,EAAA,MAAA;IACL,OAAK,CAAA,EAAA,MAAA;MAET,IAAA;YAqEiB,CAAA,GAAA,EAAA,MAAA,EAAA,QAAA,EAhIc,MAgId,CAAA,MAAA,EAAA,OAAA,CAAA,EAAA,OAAA,CAAA,EAAA,MAAA,CAAA,EAAA,IAAA;aAQE,CAAA,OAAA,EAAA,MAAA,GA9HQ,MA8HR,EAAA,IAAA,EAAA,MAAA,EAAA,KAAA,EAAA;IAMP,OAAA,CAAA,EAAA,MAAA;MAwCD,IAAA;aAhPiB,CAAA,SAAA,EAAA,CAAA,KAAA,EA+EV,iBA/EU,EAAA,GAAA,OAAA,EAAA,MAAA,EAgFrB,SAhFqB,EAAA,EAAA,OAAA,CAAA,EAAA,MAAA,CAAA,EAAA,IAAA;EAAS,YAAA,CAAA,UAAA,EAAA,MAAA,EAAA,MAAA,EA2FC,SA3FD,EAAA,EAAA,OAAA,CAAA,EAAA,MAAA,CAAA,EAAA,IAAA;0BAoGhB;;qBAcjB,MAAA,CAAK,sBACL,MAAA,CAAK,mCAET;;;;;sBAqEiB;;wBAQE;WAMP;UAwCD"}
|
package/dist/agui-mock.js
CHANGED
|
@@ -74,6 +74,14 @@ var AGUIMock = class {
|
|
|
74
74
|
});
|
|
75
75
|
return this;
|
|
76
76
|
}
|
|
77
|
+
onToolResult(toolCallId, events, delayMs) {
|
|
78
|
+
this.fixtures.push({
|
|
79
|
+
match: { toolCallId },
|
|
80
|
+
events,
|
|
81
|
+
delayMs
|
|
82
|
+
});
|
|
83
|
+
return this;
|
|
84
|
+
}
|
|
77
85
|
enableRecording(config) {
|
|
78
86
|
this.recordConfig = config;
|
|
79
87
|
return this;
|