@copilotkit/aimock 1.27.0 → 1.27.2
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 +28 -0
- package/dist/agui-handler.cjs +11 -2
- package/dist/agui-handler.cjs.map +1 -1
- package/dist/agui-handler.d.cts +2 -0
- package/dist/agui-handler.d.cts.map +1 -1
- package/dist/agui-handler.d.ts +2 -0
- package/dist/agui-handler.d.ts.map +1 -1
- package/dist/agui-handler.js +11 -2
- package/dist/agui-handler.js.map +1 -1
- package/dist/agui-mock.cjs +6 -0
- package/dist/agui-mock.cjs.map +1 -1
- package/dist/agui-mock.d.cts.map +1 -1
- package/dist/agui-mock.d.ts.map +1 -1
- package/dist/agui-mock.js +6 -0
- package/dist/agui-mock.js.map +1 -1
- package/dist/agui-types.d.cts.map +1 -1
- package/dist/agui-types.d.ts.map +1 -1
- package/dist/config-loader.cjs +11 -1
- package/dist/config-loader.cjs.map +1 -1
- package/dist/config-loader.d.cts.map +1 -1
- package/dist/config-loader.d.ts.map +1 -1
- package/dist/config-loader.js +11 -1
- package/dist/config-loader.js.map +1 -1
- package/dist/elevenlabs-audio.cjs +2 -2
- package/dist/elevenlabs-audio.cjs.map +1 -1
- package/dist/elevenlabs-audio.js +2 -2
- package/dist/elevenlabs-audio.js.map +1 -1
- package/dist/fal-audio.cjs +32 -8
- package/dist/fal-audio.cjs.map +1 -1
- package/dist/fal-audio.js +32 -8
- package/dist/fal-audio.js.map +1 -1
- package/dist/fixture-loader.cjs +1 -26
- package/dist/fixture-loader.cjs.map +1 -1
- package/dist/fixture-loader.d.cts.map +1 -1
- package/dist/fixture-loader.d.ts.map +1 -1
- package/dist/fixture-loader.js +1 -26
- package/dist/fixture-loader.js.map +1 -1
- package/dist/gemini-interactions.cjs +8 -5
- package/dist/gemini-interactions.cjs.map +1 -1
- package/dist/gemini-interactions.d.cts.map +1 -1
- package/dist/gemini-interactions.d.ts.map +1 -1
- package/dist/gemini-interactions.js +8 -5
- package/dist/gemini-interactions.js.map +1 -1
- package/dist/helpers.cjs +7 -7
- package/dist/helpers.cjs.map +1 -1
- package/dist/helpers.d.cts +4 -1
- package/dist/helpers.d.cts.map +1 -1
- package/dist/helpers.d.ts +4 -1
- package/dist/helpers.d.ts.map +1 -1
- package/dist/helpers.js +7 -7
- package/dist/helpers.js.map +1 -1
- package/dist/recorder.cjs +3 -3
- package/dist/recorder.cjs.map +1 -1
- package/dist/recorder.d.cts.map +1 -1
- package/dist/recorder.d.ts.map +1 -1
- package/dist/recorder.js +3 -3
- package/dist/recorder.js.map +1 -1
- package/dist/router.cjs +2 -7
- package/dist/router.cjs.map +1 -1
- package/dist/router.js +2 -7
- package/dist/router.js.map +1 -1
- package/dist/transcription.cjs +3 -1
- package/dist/transcription.cjs.map +1 -1
- package/dist/transcription.d.cts.map +1 -1
- package/dist/transcription.d.ts.map +1 -1
- package/dist/transcription.js +3 -1
- package/dist/transcription.js.map +1 -1
- package/dist/vector-types.d.cts.map +1 -1
- package/dist/vector-types.d.ts.map +1 -1
- package/dist/ws-gemini-live.cjs +28 -14
- package/dist/ws-gemini-live.cjs.map +1 -1
- package/dist/ws-gemini-live.d.cts.map +1 -1
- package/dist/ws-gemini-live.d.ts.map +1 -1
- package/dist/ws-gemini-live.js +28 -14
- package/dist/ws-gemini-live.js.map +1 -1
- package/dist/ws-realtime.cjs +64 -41
- package/dist/ws-realtime.cjs.map +1 -1
- package/dist/ws-realtime.d.cts.map +1 -1
- package/dist/ws-realtime.d.ts.map +1 -1
- package/dist/ws-realtime.js +64 -41
- package/dist/ws-realtime.js.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.27.
|
|
12
|
+
"version": "^1.27.2"
|
|
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,34 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [1.27.2] - 2026-05-26
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- **Fixture loader** — full recursive directory traversal replaces 2-level cap; supports per-integration showcase layouts like `d6/<integration>/<feature>.json`.
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- **Docker image** — added `git` binary to production stage for sparse-checkout fixture fetching at boot.
|
|
14
|
+
|
|
15
|
+
## [1.27.1] - 2026-05-22
|
|
16
|
+
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
19
|
+
- **Router** — systemMessage array exact-match logic was unsatisfiable for 2+ needles; collapsed to substring matching. Added `elevenlabs-tts` and `translation` to endpoint compatibility filter.
|
|
20
|
+
- **Recorder** — Content-Type empty-string fallback (`??` → `||`), derived `EndpointType` from `FixtureMatch` instead of duplicate union, negative guards on Gemini Interactions outputs detection, scoped `turnIndex`/`hasToolResult` to chat endpoints only.
|
|
21
|
+
- **WS-Realtime** — session.update rollback now captures full snapshot instead of just model/type. Added Beta flat fields for noise reduction, transcription, and turn_detection. Joined all text content parts in `realtimeItemsToMessages`. Added try-catch with debug logging around `sendEvent` for WebSocket close race safety.
|
|
22
|
+
- **WS-Gemini-Live** — replaced deterministic `call_gemini_${name}_${i}` tool call IDs with random `generateToolCallId()` to prevent cross-turn collisions. Pre-computed `resolvedToolCalls` for wire/history ID consistency. Added unrecognized-role warning and ws.send try-catch with debug logging.
|
|
23
|
+
- **Gemini Interactions** — `interactionsUsage` honors Gemini-native field names (`promptTokenCount`/`candidatesTokenCount`/`totalTokenCount`). `truncateAfterChunks` only counts `content.delta` events. Added `webSearches` warning on tool-call branch.
|
|
24
|
+
- **fal-audio + ElevenLabs** — all journal entries now use `flattenHeaders(req.headers)` instead of `{}`. `handleSyncRun` accepts `RawJSONResponse` fixtures from queue-walk recordings.
|
|
25
|
+
- **Helpers** — extended `resolveUsage` with Gemini-native token fields. Preserved error cause in `resolveResponse` factory rethrow. `buildEmbeddingResponse` accepts optional usage. `extractFormField` escapes regex metacharacters.
|
|
26
|
+
- **Drift test infra** — retry logging with body consumption, broadened `redactUrl` to cover `api_key`/`apikey`/`token`/`access_token` patterns, URL threaded into error messages with redaction, `parseDataOnlySSE` [DONE] filter fix, `parseTypedSSE` multi-line data handling with null guards.
|
|
27
|
+
- **Drift collector** — invoke vitest directly via npx to avoid pnpm stdout prefix breaking JSON parse; classify raw stack traces as infrastructure errors instead of crashing.
|
|
28
|
+
- **AG-UI config loader** — removed `/.*/` catch-all regex fallback when `match.message` is absent; fixtures without a message pattern no longer shadow other fixtures.
|
|
29
|
+
- **AG-UI input validation** — runtime check that `input.messages` is an array after JSON parse; returns 400 instead of confusing downstream 404.
|
|
30
|
+
- **AG-UI SSE writer** — `writeAGUIEventStream` uses logger abstraction instead of `console.warn`; handles non-Error throws.
|
|
31
|
+
- **Drift test helpers** — `parseDataOnlySSE` handles multi-line data blocks, aligned with `providers.ts` implementation.
|
|
32
|
+
|
|
5
33
|
## [1.27.0] - 2026-05-20
|
|
6
34
|
|
|
7
35
|
### Added
|
package/dist/agui-handler.cjs
CHANGED
|
@@ -444,8 +444,17 @@ async function writeAGUIEventStream(res, events, opts) {
|
|
|
444
444
|
try {
|
|
445
445
|
res.write(`data: ${JSON.stringify(stamped)}\n\n`);
|
|
446
446
|
} catch (err) {
|
|
447
|
-
if (err instanceof TypeError || err instanceof RangeError)
|
|
448
|
-
|
|
447
|
+
if (err instanceof TypeError || err instanceof RangeError) {
|
|
448
|
+
const msg = err.message;
|
|
449
|
+
if (opts?.logger) opts.logger.warn("AG-UI SSE write failed (serialization):", msg);
|
|
450
|
+
else console.warn("AG-UI SSE write failed (serialization):", msg);
|
|
451
|
+
} else if (err instanceof Error) if (opts?.logger) opts.logger.warn("AG-UI SSE write failed:", err.message);
|
|
452
|
+
else console.warn("AG-UI SSE write failed:", err.message);
|
|
453
|
+
else {
|
|
454
|
+
const msg = String(err);
|
|
455
|
+
if (opts?.logger) opts.logger.warn("AG-UI SSE write failed:", msg);
|
|
456
|
+
else console.warn("AG-UI SSE write failed:", msg);
|
|
457
|
+
}
|
|
449
458
|
break;
|
|
450
459
|
}
|
|
451
460
|
if (delayMs > 0) await new Promise((resolve) => setTimeout(resolve, delayMs));
|
|
@@ -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 * 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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"}
|
|
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 { Logger } from \"./logger.js\";\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; logger?: Logger },\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 const msg = (err as Error).message;\n if (opts?.logger) {\n opts.logger.warn(\"AG-UI SSE write failed (serialization):\", msg);\n } else {\n console.warn(\"AG-UI SSE write failed (serialization):\", msg);\n }\n } else if (err instanceof Error) {\n if (opts?.logger) {\n opts.logger.warn(\"AG-UI SSE write failed:\", err.message);\n } else {\n console.warn(\"AG-UI SSE write failed:\", err.message);\n }\n } else {\n const msg = String(err);\n if (opts?.logger) {\n opts.logger.warn(\"AG-UI SSE write failed:\", msg);\n } else {\n console.warn(\"AG-UI SSE write failed:\", msg);\n }\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
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Logger } from "./logger.cjs";
|
|
1
2
|
import { AGUIEvent, AGUIFixture, AGUIFixtureMatch, AGUIMessage, AGUIReasoningEncryptedValueSubtype, AGUIRunAgentInput } from "./agui-types.cjs";
|
|
2
3
|
import * as http$1 from "node:http";
|
|
3
4
|
|
|
@@ -131,6 +132,7 @@ declare function buildReasoningEncryptedValue(subtype: AGUIReasoningEncryptedVal
|
|
|
131
132
|
declare function writeAGUIEventStream(res: http$1.ServerResponse, events: AGUIEvent[], opts?: {
|
|
132
133
|
delayMs?: number;
|
|
133
134
|
signal?: AbortSignal;
|
|
135
|
+
logger?: Logger;
|
|
134
136
|
}): Promise<void>;
|
|
135
137
|
//# sourceMappingURL=agui-handler.d.ts.map
|
|
136
138
|
//#endregion
|
|
@@ -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
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Logger } from "./logger.js";
|
|
1
2
|
import { AGUIEvent, AGUIFixture, AGUIFixtureMatch, AGUIMessage, AGUIReasoningEncryptedValueSubtype, AGUIRunAgentInput } from "./agui-types.js";
|
|
2
3
|
import * as http$1 from "node:http";
|
|
3
4
|
|
|
@@ -131,6 +132,7 @@ declare function buildReasoningEncryptedValue(subtype: AGUIReasoningEncryptedVal
|
|
|
131
132
|
declare function writeAGUIEventStream(res: http$1.ServerResponse, events: AGUIEvent[], opts?: {
|
|
132
133
|
delayMs?: number;
|
|
133
134
|
signal?: AbortSignal;
|
|
135
|
+
logger?: Logger;
|
|
134
136
|
}): Promise<void>;
|
|
135
137
|
//# sourceMappingURL=agui-handler.d.ts.map
|
|
136
138
|
//#endregion
|
|
@@ -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
|
@@ -443,8 +443,17 @@ async function writeAGUIEventStream(res, events, opts) {
|
|
|
443
443
|
try {
|
|
444
444
|
res.write(`data: ${JSON.stringify(stamped)}\n\n`);
|
|
445
445
|
} catch (err) {
|
|
446
|
-
if (err instanceof TypeError || err instanceof RangeError)
|
|
447
|
-
|
|
446
|
+
if (err instanceof TypeError || err instanceof RangeError) {
|
|
447
|
+
const msg = err.message;
|
|
448
|
+
if (opts?.logger) opts.logger.warn("AG-UI SSE write failed (serialization):", msg);
|
|
449
|
+
else console.warn("AG-UI SSE write failed (serialization):", msg);
|
|
450
|
+
} else if (err instanceof Error) if (opts?.logger) opts.logger.warn("AG-UI SSE write failed:", err.message);
|
|
451
|
+
else console.warn("AG-UI SSE write failed:", err.message);
|
|
452
|
+
else {
|
|
453
|
+
const msg = String(err);
|
|
454
|
+
if (opts?.logger) opts.logger.warn("AG-UI SSE write failed:", msg);
|
|
455
|
+
else console.warn("AG-UI SSE write failed:", msg);
|
|
456
|
+
}
|
|
448
457
|
break;
|
|
449
458
|
}
|
|
450
459
|
if (delayMs > 0) await new Promise((resolve) => setTimeout(resolve, delayMs));
|
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 * 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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"}
|
|
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 { Logger } from \"./logger.js\";\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; logger?: Logger },\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 const msg = (err as Error).message;\n if (opts?.logger) {\n opts.logger.warn(\"AG-UI SSE write failed (serialization):\", msg);\n } else {\n console.warn(\"AG-UI SSE write failed (serialization):\", msg);\n }\n } else if (err instanceof Error) {\n if (opts?.logger) {\n opts.logger.warn(\"AG-UI SSE write failed:\", err.message);\n } else {\n console.warn(\"AG-UI SSE write failed:\", err.message);\n }\n } else {\n const msg = String(err);\n if (opts?.logger) {\n opts.logger.warn(\"AG-UI SSE write failed:\", msg);\n } else {\n console.warn(\"AG-UI SSE write failed:\", msg);\n }\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
|
@@ -116,6 +116,12 @@ var AGUIMock = class {
|
|
|
116
116
|
this.journalRequest(req, pathname, 400);
|
|
117
117
|
return true;
|
|
118
118
|
}
|
|
119
|
+
if (input.messages !== void 0 && !Array.isArray(input.messages)) {
|
|
120
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
121
|
+
res.end(JSON.stringify({ error: "Invalid input: 'messages' must be an array when provided" }));
|
|
122
|
+
this.journalRequest(req, pathname, 400);
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
119
125
|
const fixture = require_agui_handler.findFixture(input, this.fixtures);
|
|
120
126
|
if (fixture) {
|
|
121
127
|
await require_agui_handler.writeAGUIEventStream(res, fixture.events, { delayMs: fixture.delayMs });
|
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 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":";;;;;;;;;AAuBA,IAAa,WAAb,MAA2C;CACzC,AAAQ,WAA0B,EAAE;CACpC,AAAQ,SAA6B;CACrC,AAAQ,UAA0B;CAClC,AAAQ,WAAmC;CAC3C,AAAQ;CACR,AAAQ,UAAU;CAClB,AAAQ;CACR,AAAQ;CAER,YAAY,SAA2B;AACrC,OAAK,UAAU,WAAW,EAAE;AAC5B,OAAK,SAAS,IAAIA,sBAAQ,SAAS,YAAyB,OAAO;;CAKrE,WAAW,SAA4B;AACrC,OAAK,SAAS,KAAK,QAAQ;AAC3B,SAAO;;CAGT,UAAU,SAA0B,MAAc,MAAmC;EACnF,MAAM,SAASC,uCAAkB,KAAK;AACtC,OAAK,SAAS,KAAK;GACjB,OAAO,EAAE,SAAS,SAAS;GAC3B;GACA,SAAS,MAAM;GAChB,CAAC;AACF,SAAO;;CAGT,MAAM,SAA0B,QAAqB,SAAwB;AAC3E,OAAK,SAAS,KAAK;GACjB,OAAO,EAAE,SAAS,SAAS;GAC3B;GACA;GACD,CAAC;AACF,SAAO;;CAGT,WACE,SACA,UACA,MACA,MACM;EACN,MAAM,SAASC,2CAAsB,UAAU,MAAM,EACnD,QAAQ,MAAM,QACf,CAAC;AACF,OAAK,SAAS,KAAK;GACjB,OAAO,EAAE,SAAS,SAAS;GAC3B;GACA,SAAS,MAAM;GAChB,CAAC;AACF,SAAO;;CAGT,WAAW,KAAa,UAAmC,SAAwB;EACjF,MAAM,SAASC,sCAAiB,SAAS;AACzC,OAAK,SAAS,KAAK;GACjB,OAAO,EAAE,UAAU,KAAK;GACxB;GACA;GACD,CAAC;AACF,SAAO;;CAGT,YAAY,SAA0B,MAAc,MAAmC;EACrF,MAAM,SAASC,4CAAuB,KAAK;AAC3C,OAAK,SAAS,KAAK;GACjB,OAAO,EAAE,SAAS,SAAS;GAC3B;GACA,SAAS,MAAM;GAChB,CAAC;AACF,SAAO;;CAGT,YACE,WACA,QACA,SACM;AACN,OAAK,SAAS,KAAK;GACjB,OAAO,EAAE,WAAW;GACpB;GACA;GACD,CAAC;AACF,SAAO;;CAGT,aAAa,YAAoB,QAAqB,SAAwB;AAC5E,OAAK,SAAS,KAAK;GACjB,OAAO,EAAE,YAAY;GACrB;GACA;GACD,CAAC;AACF,SAAO;;CAGT,gBAAgB,QAAgC;AAC9C,OAAK,eAAe;AACpB,SAAO;;CAGT,QAAc;AACZ,OAAK,WAAW,EAAE;AAClB,OAAK,eAAe;AACpB,SAAO;;CAKT,MAAM,cACJ,KACA,KACA,UACkB;AAClB,MAAI,IAAI,WAAW,UAAW,aAAa,OAAO,aAAa,GAC7D,QAAO;AAGT,MAAI,KAAK,SACP,MAAK,SAAS,iBAAiB,8BAA8B,EAAE,QAAQ,QAAQ,CAAC;EAGlF,IAAI;AACJ,MAAI;AACF,UAAO,MAAMC,yBAAS,IAAI;WACnB,KAAK;AACZ,OAAI,UAAU,KAAK,EAAE,gBAAgB,oBAAoB,CAAC;GAC1D,MAAM,SAAS,eAAe,QAAQ,IAAI,UAAU;AACpD,OAAI,IAAI,KAAK,UAAU,EAAE,OAAO,gCAAgC,UAAU,CAAC,CAAC;AAC5E,QAAK,eAAe,KAAK,UAAU,IAAI;AACvC,UAAO;;EAGT,IAAI;AACJ,MAAI;AACF,WAAQ,KAAK,MAAM,KAAK;WACjB,KAAK;AACZ,OAAI,UAAU,KAAK,EAAE,gBAAgB,oBAAoB,CAAC;GAC1D,MAAM,SAAS,eAAe,QAAQ,IAAI,UAAU;AACpD,OAAI,IAAI,KAAK,UAAU,EAAE,OAAO,sBAAsB,UAAU,CAAC,CAAC;AAClE,QAAK,eAAe,KAAK,UAAU,IAAI;AACvC,UAAO;;EAGT,MAAM,UAAUC,iCAAY,OAAO,KAAK,SAAS;AAEjD,MAAI,SAAS;AACX,SAAMC,0CAAqB,KAAK,QAAQ,QAAQ,EAAE,SAAS,QAAQ,SAAS,CAAC;AAC7E,QAAK,eAAe,KAAK,UAAU,IAAI;AACvC,UAAO;;AAIT,MAAI,KAAK,cAAc;GACrB,MAAM,SAAS,MAAMC,yCACnB,KACA,KACA,OACA,KAAK,UACL,KAAK,cACL,KAAK,OACN;AACD,OAAI,WAAW,OAAO;AACpB,SAAK,eAAe,KAAK,UAAU,OAAO;AAC1C,WAAO;;;AAKX,MAAI,UAAU,KAAK,EAAE,gBAAgB,oBAAoB,CAAC;AAC1D,MAAI,IAAI,KAAK,UAAU,EAAE,OAAO,6BAA6B,CAAC,CAAC;AAC/D,OAAK,eAAe,KAAK,UAAU,IAAI;AACvC,SAAO;;CAGT,SAA+C;AAC7C,SAAO;GACL,QAAQ;GACR,UAAU,KAAK,SAAS;GACzB;;CAGH,WAAW,SAAwB;AACjC,OAAK,UAAU;;CAGjB,WAAW,KAAmB;AAC5B,OAAK,UAAU;;CAGjB,YAAY,UAAiC;AAC3C,OAAK,WAAW;;CAKlB,MAAM,QAAyB;AAC7B,MAAI,KAAK,OACP,OAAM,IAAI,MAAM,kCAAkC;EAGpD,MAAM,OAAO,KAAK,QAAQ,QAAQ;EAClC,MAAM,OAAO,KAAK,QAAQ,QAAQ;AAElC,SAAO,IAAI,SAAiB,SAAS,WAAW;GAC9C,MAAM,MAAMC,UAAK,aAAa,OAAO,KAAK,QAAQ;IAChD,MAAM,MAAM,IAAI,IAAI,IAAI,OAAO,KAAK,UAAU,IAAI,QAAQ,QAAQ,cAAc;AAWhF,QAAI,CAVY,MAAM,KAAK,cAAc,KAAK,KAAK,IAAI,SAAS,CAAC,OAAO,QAAQ;AAC9E,UAAK,OAAO,MAAM,2BAA2B,eAAe,QAAQ,IAAI,UAAU,MAAM;AACxF,SAAI,CAAC,IAAI,aAAa;AACpB,UAAI,UAAU,IAAI;AAClB,UAAI,IAAI,wBAAwB;gBACvB,CAAC,IAAI,cACd,KAAI,KAAK;AAEX,YAAO;MACP,IACc,CAAC,IAAI,aAAa;AAChC,SAAI,UAAU,KAAK,EAAE,gBAAgB,oBAAoB,CAAC;AAC1D,SAAI,IAAI,KAAK,UAAU,EAAE,OAAO,aAAa,CAAC,CAAC;;KAEjD;AAEF,OAAI,GAAG,SAAS,OAAO;AAEvB,OAAI,OAAO,MAAM,YAAY;IAC3B,MAAM,OAAO,IAAI,SAAS;AAC1B,QAAI,OAAO,SAAS,YAAY,SAAS,KACvC,MAAK,UAAU,UAAU,KAAK,GAAG,KAAK;AAExC,SAAK,SAAS;AACd,YAAQ,KAAK,QAAQ;KACrB;IACF;;CAGJ,MAAM,OAAsB;AAC1B,MAAI,CAAC,KAAK,OACR,OAAM,IAAI,MAAM,8BAA8B;EAEhD,MAAM,MAAM,KAAK;AACjB,QAAM,IAAI,SAAe,SAAS,WAAW;AAC3C,OAAI,OAAO,QAA4B,MAAM,OAAO,IAAI,GAAG,SAAS,CAAE;IACtE;AACF,OAAK,SAAS;;CAGhB,IAAI,MAAc;AAChB,MAAI,CAAC,KAAK,OACR,OAAM,IAAI,MAAM,8BAA8B;AAEhD,SAAO,KAAK;;CAKd,AAAQ,eAAe,KAA2B,UAAkB,QAAsB;AACxF,MAAI,KAAK,QACP,MAAK,QAAQ,IAAI;GACf,QAAQ,IAAI,UAAU;GACtB,MAAM,IAAI,OAAO;GACjB,SAASC,+BAAe,IAAI,QAAQ;GACpC,MAAM;GACN,SAAS;GACT,UAAU;IAAE;IAAQ,SAAS;IAAM;GACpC,CAAC"}
|
|
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 if (input.messages !== undefined && !Array.isArray(input.messages)) {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n res.end(\n JSON.stringify({\n error: \"Invalid input: 'messages' must be an array when provided\",\n }),\n );\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.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;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;
|
|
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;YAgFiB,CAAA,GAAA,EAAA,MAAA,EAAA,QAAA,EA3Ic,MA2Id,CAAA,MAAA,EAAA,OAAA,CAAA,EAAA,OAAA,CAAA,EAAA,MAAA,CAAA,EAAA,IAAA;aAQE,CAAA,OAAA,EAAA,MAAA,GAzIQ,MAyIR,EAAA,IAAA,EAAA,MAAA,EAAA,KAAA,EAAA;IAMP,OAAA,CAAA,EAAA,MAAA;MAwCD,IAAA;aA3PiB,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;;;;;sBAgFiB;;wBAQE;WAMP;UAwCD"}
|
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;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;
|
|
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;YAgFiB,CAAA,GAAA,EAAA,MAAA,EAAA,QAAA,EA3Ic,MA2Id,CAAA,MAAA,EAAA,OAAA,CAAA,EAAA,OAAA,CAAA,EAAA,MAAA,CAAA,EAAA,IAAA;aAQE,CAAA,OAAA,EAAA,MAAA,GAzIQ,MAyIR,EAAA,IAAA,EAAA,MAAA,EAAA,KAAA,EAAA;IAMP,OAAA,CAAA,EAAA,MAAA;MAwCD,IAAA;aA3PiB,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;;;;;sBAgFiB;;wBAQE;WAMP;UAwCD"}
|
package/dist/agui-mock.js
CHANGED
|
@@ -114,6 +114,12 @@ var AGUIMock = class {
|
|
|
114
114
|
this.journalRequest(req, pathname, 400);
|
|
115
115
|
return true;
|
|
116
116
|
}
|
|
117
|
+
if (input.messages !== void 0 && !Array.isArray(input.messages)) {
|
|
118
|
+
res.writeHead(400, { "Content-Type": "application/json" });
|
|
119
|
+
res.end(JSON.stringify({ error: "Invalid input: 'messages' must be an array when provided" }));
|
|
120
|
+
this.journalRequest(req, pathname, 400);
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
117
123
|
const fixture = findFixture(input, this.fixtures);
|
|
118
124
|
if (fixture) {
|
|
119
125
|
await writeAGUIEventStream(res, fixture.events, { delayMs: fixture.delayMs });
|
package/dist/agui-mock.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agui-mock.js","names":["http"],"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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"}
|
|
1
|
+
{"version":3,"file":"agui-mock.js","names":["http"],"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 if (input.messages !== undefined && !Array.isArray(input.messages)) {\n res.writeHead(400, { \"Content-Type\": \"application/json\" });\n res.end(\n JSON.stringify({\n error: \"Invalid input: 'messages' must be an array when provided\",\n }),\n );\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":";;;;;;;AAuBA,IAAa,WAAb,MAA2C;CACzC,AAAQ,WAA0B,EAAE;CACpC,AAAQ,SAA6B;CACrC,AAAQ,UAA0B;CAClC,AAAQ,WAAmC;CAC3C,AAAQ;CACR,AAAQ,UAAU;CAClB,AAAQ;CACR,AAAQ;CAER,YAAY,SAA2B;AACrC,OAAK,UAAU,WAAW,EAAE;AAC5B,OAAK,SAAS,IAAI,OAAQ,SAAS,YAAyB,OAAO;;CAKrE,WAAW,SAA4B;AACrC,OAAK,SAAS,KAAK,QAAQ;AAC3B,SAAO;;CAGT,UAAU,SAA0B,MAAc,MAAmC;EACnF,MAAM,SAAS,kBAAkB,KAAK;AACtC,OAAK,SAAS,KAAK;GACjB,OAAO,EAAE,SAAS,SAAS;GAC3B;GACA,SAAS,MAAM;GAChB,CAAC;AACF,SAAO;;CAGT,MAAM,SAA0B,QAAqB,SAAwB;AAC3E,OAAK,SAAS,KAAK;GACjB,OAAO,EAAE,SAAS,SAAS;GAC3B;GACA;GACD,CAAC;AACF,SAAO;;CAGT,WACE,SACA,UACA,MACA,MACM;EACN,MAAM,SAAS,sBAAsB,UAAU,MAAM,EACnD,QAAQ,MAAM,QACf,CAAC;AACF,OAAK,SAAS,KAAK;GACjB,OAAO,EAAE,SAAS,SAAS;GAC3B;GACA,SAAS,MAAM;GAChB,CAAC;AACF,SAAO;;CAGT,WAAW,KAAa,UAAmC,SAAwB;EACjF,MAAM,SAAS,iBAAiB,SAAS;AACzC,OAAK,SAAS,KAAK;GACjB,OAAO,EAAE,UAAU,KAAK;GACxB;GACA;GACD,CAAC;AACF,SAAO;;CAGT,YAAY,SAA0B,MAAc,MAAmC;EACrF,MAAM,SAAS,uBAAuB,KAAK;AAC3C,OAAK,SAAS,KAAK;GACjB,OAAO,EAAE,SAAS,SAAS;GAC3B;GACA,SAAS,MAAM;GAChB,CAAC;AACF,SAAO;;CAGT,YACE,WACA,QACA,SACM;AACN,OAAK,SAAS,KAAK;GACjB,OAAO,EAAE,WAAW;GACpB;GACA;GACD,CAAC;AACF,SAAO;;CAGT,aAAa,YAAoB,QAAqB,SAAwB;AAC5E,OAAK,SAAS,KAAK;GACjB,OAAO,EAAE,YAAY;GACrB;GACA;GACD,CAAC;AACF,SAAO;;CAGT,gBAAgB,QAAgC;AAC9C,OAAK,eAAe;AACpB,SAAO;;CAGT,QAAc;AACZ,OAAK,WAAW,EAAE;AAClB,OAAK,eAAe;AACpB,SAAO;;CAKT,MAAM,cACJ,KACA,KACA,UACkB;AAClB,MAAI,IAAI,WAAW,UAAW,aAAa,OAAO,aAAa,GAC7D,QAAO;AAGT,MAAI,KAAK,SACP,MAAK,SAAS,iBAAiB,8BAA8B,EAAE,QAAQ,QAAQ,CAAC;EAGlF,IAAI;AACJ,MAAI;AACF,UAAO,MAAM,SAAS,IAAI;WACnB,KAAK;AACZ,OAAI,UAAU,KAAK,EAAE,gBAAgB,oBAAoB,CAAC;GAC1D,MAAM,SAAS,eAAe,QAAQ,IAAI,UAAU;AACpD,OAAI,IAAI,KAAK,UAAU,EAAE,OAAO,gCAAgC,UAAU,CAAC,CAAC;AAC5E,QAAK,eAAe,KAAK,UAAU,IAAI;AACvC,UAAO;;EAGT,IAAI;AACJ,MAAI;AACF,WAAQ,KAAK,MAAM,KAAK;WACjB,KAAK;AACZ,OAAI,UAAU,KAAK,EAAE,gBAAgB,oBAAoB,CAAC;GAC1D,MAAM,SAAS,eAAe,QAAQ,IAAI,UAAU;AACpD,OAAI,IAAI,KAAK,UAAU,EAAE,OAAO,sBAAsB,UAAU,CAAC,CAAC;AAClE,QAAK,eAAe,KAAK,UAAU,IAAI;AACvC,UAAO;;AAGT,MAAI,MAAM,aAAa,UAAa,CAAC,MAAM,QAAQ,MAAM,SAAS,EAAE;AAClE,OAAI,UAAU,KAAK,EAAE,gBAAgB,oBAAoB,CAAC;AAC1D,OAAI,IACF,KAAK,UAAU,EACb,OAAO,4DACR,CAAC,CACH;AACD,QAAK,eAAe,KAAK,UAAU,IAAI;AACvC,UAAO;;EAGT,MAAM,UAAU,YAAY,OAAO,KAAK,SAAS;AAEjD,MAAI,SAAS;AACX,SAAM,qBAAqB,KAAK,QAAQ,QAAQ,EAAE,SAAS,QAAQ,SAAS,CAAC;AAC7E,QAAK,eAAe,KAAK,UAAU,IAAI;AACvC,UAAO;;AAIT,MAAI,KAAK,cAAc;GACrB,MAAM,SAAS,MAAM,mBACnB,KACA,KACA,OACA,KAAK,UACL,KAAK,cACL,KAAK,OACN;AACD,OAAI,WAAW,OAAO;AACpB,SAAK,eAAe,KAAK,UAAU,OAAO;AAC1C,WAAO;;;AAKX,MAAI,UAAU,KAAK,EAAE,gBAAgB,oBAAoB,CAAC;AAC1D,MAAI,IAAI,KAAK,UAAU,EAAE,OAAO,6BAA6B,CAAC,CAAC;AAC/D,OAAK,eAAe,KAAK,UAAU,IAAI;AACvC,SAAO;;CAGT,SAA+C;AAC7C,SAAO;GACL,QAAQ;GACR,UAAU,KAAK,SAAS;GACzB;;CAGH,WAAW,SAAwB;AACjC,OAAK,UAAU;;CAGjB,WAAW,KAAmB;AAC5B,OAAK,UAAU;;CAGjB,YAAY,UAAiC;AAC3C,OAAK,WAAW;;CAKlB,MAAM,QAAyB;AAC7B,MAAI,KAAK,OACP,OAAM,IAAI,MAAM,kCAAkC;EAGpD,MAAM,OAAO,KAAK,QAAQ,QAAQ;EAClC,MAAM,OAAO,KAAK,QAAQ,QAAQ;AAElC,SAAO,IAAI,SAAiB,SAAS,WAAW;GAC9C,MAAM,MAAMA,OAAK,aAAa,OAAO,KAAK,QAAQ;IAChD,MAAM,MAAM,IAAI,IAAI,IAAI,OAAO,KAAK,UAAU,IAAI,QAAQ,QAAQ,cAAc;AAWhF,QAAI,CAVY,MAAM,KAAK,cAAc,KAAK,KAAK,IAAI,SAAS,CAAC,OAAO,QAAQ;AAC9E,UAAK,OAAO,MAAM,2BAA2B,eAAe,QAAQ,IAAI,UAAU,MAAM;AACxF,SAAI,CAAC,IAAI,aAAa;AACpB,UAAI,UAAU,IAAI;AAClB,UAAI,IAAI,wBAAwB;gBACvB,CAAC,IAAI,cACd,KAAI,KAAK;AAEX,YAAO;MACP,IACc,CAAC,IAAI,aAAa;AAChC,SAAI,UAAU,KAAK,EAAE,gBAAgB,oBAAoB,CAAC;AAC1D,SAAI,IAAI,KAAK,UAAU,EAAE,OAAO,aAAa,CAAC,CAAC;;KAEjD;AAEF,OAAI,GAAG,SAAS,OAAO;AAEvB,OAAI,OAAO,MAAM,YAAY;IAC3B,MAAM,OAAO,IAAI,SAAS;AAC1B,QAAI,OAAO,SAAS,YAAY,SAAS,KACvC,MAAK,UAAU,UAAU,KAAK,GAAG,KAAK;AAExC,SAAK,SAAS;AACd,YAAQ,KAAK,QAAQ;KACrB;IACF;;CAGJ,MAAM,OAAsB;AAC1B,MAAI,CAAC,KAAK,OACR,OAAM,IAAI,MAAM,8BAA8B;EAEhD,MAAM,MAAM,KAAK;AACjB,QAAM,IAAI,SAAe,SAAS,WAAW;AAC3C,OAAI,OAAO,QAA4B,MAAM,OAAO,IAAI,GAAG,SAAS,CAAE;IACtE;AACF,OAAK,SAAS;;CAGhB,IAAI,MAAc;AAChB,MAAI,CAAC,KAAK,OACR,OAAM,IAAI,MAAM,8BAA8B;AAEhD,SAAO,KAAK;;CAKd,AAAQ,eAAe,KAA2B,UAAkB,QAAsB;AACxF,MAAI,KAAK,QACP,MAAK,QAAQ,IAAI;GACf,QAAQ,IAAI,UAAU;GACtB,MAAM,IAAI,OAAO;GACjB,SAAS,eAAe,IAAI,QAAQ;GACpC,MAAM;GACN,SAAS;GACT,UAAU;IAAE;IAAQ,SAAS;IAAM;GACpC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agui-types.d.cts","names":[],"sources":["../src/agui-types.ts"],"sourcesContent":[],"mappings":";KAOY,aAAA;AAAA,UA6CK,aAAA,CA7CQ;EA6CR,IAAA,EACT,aADsB;EAUb,SAAA,CAAA,EAAA,MAAA;EAAoB,QAAA,CAAA,EAAA,OAAA;;AAAQ,UAA5B,mBAAA,SAA4B,aAAA,CAAA;EAAa,IAAA,EAAA,aAAA;EAQzC,QAAA,EAAA,MAAA;EAAqB,KAAA,EAAA,MAAA;aAK1B,CAAA,EAAA,MAAA;OALkC,CAAA,EAHpC,iBAGoC;;AAQ7B,UARA,oBAAA,SAA6B,aAQU,CAAA;EAMvC,IAAA,EAAA,cAAA;EAKA,QAAA,EAAA,MAAA;EAOL,KAAA,EAAA,MAAA;EAEA,MAAA,CAAA,EAAA,OAAA;EASK,OAAA,CAAA,EAhCL,sBAgC+B;;AAGnC,UAhCS,iBAAA,SAA0B,aAgCnC,CAAA;MAH2C,EAAA,WAAA;EAAa,OAAA,EAAA,MAAA;EAO/C,IAAA,CAAA,EAAA,MAAA;AAMjB;AAKiB,UAzCA,oBAAA,SAA6B,aAyCH,CAAA;EAAA,IAAA,EAAA,cAAA;UAGlC,EAAA,MAAA;;AAHuD,UApC/C,qBAAA,SAA8B,aAoCiB,CAAA;EAU/C,IAAA,EAAA,eAAA;EAOA,QAAA,EAAA,MAAA;AAMjB;AAKiB,KAzDL,mBAAA,GAyD4B,WAAQ,GAAA,QAAa,GAAA,WAAA,GAAA,MAAA;AAQ5C,KA/DL,eAAA,GA+D6B,
|
|
1
|
+
{"version":3,"file":"agui-types.d.cts","names":[],"sources":["../src/agui-types.ts"],"sourcesContent":[],"mappings":"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"}
|