@axlsdk/testing 0.21.1 → 0.22.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +29 -0
- package/dist/index.cjs +177 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +23 -2
- package/dist/index.d.ts +23 -2
- package/dist/index.js +170 -4
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -90,6 +90,35 @@ All model parameters (`effort`, `thinkingBudget`, `includeThoughts`, `temperatur
|
|
|
90
90
|
expect(provider.calls[0].options.effort).toBe('high');
|
|
91
91
|
```
|
|
92
92
|
|
|
93
|
+
`MockProvider` also certifies logical image input in tests. It accepts ordered text/image
|
|
94
|
+
parts from URL, bytes, base64, and `provider-file` sources (the latter must be owned by
|
|
95
|
+
`mock`), preserves them in `calls`, and copies inline bytes before recording. `echo()`
|
|
96
|
+
returns only the deterministic text projection, never serialized media.
|
|
97
|
+
|
|
98
|
+
### `MockTranscriptionProvider`
|
|
99
|
+
|
|
100
|
+
Completed-file transcription has a separate mock so chat fixtures cannot
|
|
101
|
+
accidentally stand in for transcription adapters:
|
|
102
|
+
|
|
103
|
+
```typescript
|
|
104
|
+
import { AxlTestRuntime, MockTranscriptionProvider } from '@axlsdk/testing';
|
|
105
|
+
|
|
106
|
+
const runtime = new AxlTestRuntime();
|
|
107
|
+
const transcription = MockTranscriptionProvider.text('The recorded transcript.');
|
|
108
|
+
|
|
109
|
+
runtime.mockTranscriptionProvider('mock-stt', transcription);
|
|
110
|
+
|
|
111
|
+
// A workflow can now call ctx.transcribe({ model: 'mock-stt:any-model', ... }).
|
|
112
|
+
// Inspect defensive request snapshots after execution:
|
|
113
|
+
expect(transcription.calls).toHaveLength(1);
|
|
114
|
+
expect(transcription.calls[0].audio.type).toBe('bytes');
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Use the constructor for request-aware or asynchronous fixtures. Its optional
|
|
118
|
+
second callback declares model capabilities. Inline bytes, provider options,
|
|
119
|
+
and results are defensively copied; recorded requests omit `AbortSignal`, while
|
|
120
|
+
the fixture callback receives the original signal so cancellation is testable.
|
|
121
|
+
|
|
93
122
|
### `MockTool`
|
|
94
123
|
|
|
95
124
|
Create a mock tool to intercept and record calls:
|
package/dist/index.cjs
CHANGED
|
@@ -32,13 +32,93 @@ var index_exports = {};
|
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
AxlTestRuntime: () => AxlTestRuntime,
|
|
34
34
|
MockProvider: () => MockProvider,
|
|
35
|
-
MockTool: () => MockTool
|
|
35
|
+
MockTool: () => MockTool,
|
|
36
|
+
MockTranscriptionProvider: () => MockTranscriptionProvider
|
|
36
37
|
});
|
|
37
38
|
module.exports = __toCommonJS(index_exports);
|
|
38
39
|
|
|
39
40
|
// src/mock-provider.ts
|
|
40
41
|
var import_node_fs = require("fs");
|
|
41
42
|
var import_zod = require("zod");
|
|
43
|
+
var import_axl = require("@axlsdk/axl");
|
|
44
|
+
function cloneValue(value) {
|
|
45
|
+
if (value instanceof Uint8Array) return value.slice();
|
|
46
|
+
if (Array.isArray(value)) return value.map(cloneValue);
|
|
47
|
+
if (value && typeof value === "object") {
|
|
48
|
+
return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, cloneValue(item)]));
|
|
49
|
+
}
|
|
50
|
+
return value;
|
|
51
|
+
}
|
|
52
|
+
function cloneModelInput(input) {
|
|
53
|
+
if (typeof input === "string") return input;
|
|
54
|
+
return input.map((part) => {
|
|
55
|
+
if (part.type === "text") return { type: "text", text: part.text };
|
|
56
|
+
const { source } = part;
|
|
57
|
+
switch (source.type) {
|
|
58
|
+
case "bytes":
|
|
59
|
+
return {
|
|
60
|
+
type: "image",
|
|
61
|
+
source: { type: "bytes", data: source.data.slice(), mediaType: source.mediaType },
|
|
62
|
+
...part.label ? { label: part.label } : {}
|
|
63
|
+
};
|
|
64
|
+
case "url":
|
|
65
|
+
return {
|
|
66
|
+
type: "image",
|
|
67
|
+
source: {
|
|
68
|
+
type: "url",
|
|
69
|
+
url: source.url,
|
|
70
|
+
...source.mediaType ? { mediaType: source.mediaType } : {}
|
|
71
|
+
},
|
|
72
|
+
...part.label ? { label: part.label } : {}
|
|
73
|
+
};
|
|
74
|
+
case "base64":
|
|
75
|
+
return {
|
|
76
|
+
type: "image",
|
|
77
|
+
source: { type: "base64", data: source.data, mediaType: source.mediaType },
|
|
78
|
+
...part.label ? { label: part.label } : {}
|
|
79
|
+
};
|
|
80
|
+
case "provider-file":
|
|
81
|
+
return {
|
|
82
|
+
type: "image",
|
|
83
|
+
source: {
|
|
84
|
+
type: "provider-file",
|
|
85
|
+
provider: source.provider,
|
|
86
|
+
reference: source.reference,
|
|
87
|
+
...source.mediaType ? { mediaType: source.mediaType } : {}
|
|
88
|
+
},
|
|
89
|
+
...part.label ? { label: part.label } : {}
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
function cloneMessages(messages) {
|
|
95
|
+
return messages.map((message) => ({
|
|
96
|
+
...message,
|
|
97
|
+
content: cloneModelInput(message.content),
|
|
98
|
+
...message.tool_calls ? {
|
|
99
|
+
tool_calls: message.tool_calls.map((toolCall) => ({
|
|
100
|
+
...toolCall,
|
|
101
|
+
function: { ...toolCall.function }
|
|
102
|
+
}))
|
|
103
|
+
} : {},
|
|
104
|
+
...message.providerMetadata ? { providerMetadata: cloneValue(message.providerMetadata) } : {}
|
|
105
|
+
}));
|
|
106
|
+
}
|
|
107
|
+
function cloneOptions(options) {
|
|
108
|
+
return {
|
|
109
|
+
...options,
|
|
110
|
+
...options.tools ? {
|
|
111
|
+
tools: options.tools.map((tool) => ({
|
|
112
|
+
...tool,
|
|
113
|
+
function: { ...tool.function, parameters: cloneValue(tool.function.parameters) }
|
|
114
|
+
}))
|
|
115
|
+
} : {},
|
|
116
|
+
...options.providerOptions ? { providerOptions: cloneValue(options.providerOptions) } : {}
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
function richParts(input) {
|
|
120
|
+
return typeof input === "string" ? [] : input;
|
|
121
|
+
}
|
|
42
122
|
function randomAlphanumeric(length) {
|
|
43
123
|
const chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
|
44
124
|
let result = "";
|
|
@@ -104,8 +184,42 @@ var MockProvider = class _MockProvider {
|
|
|
104
184
|
return this._calls;
|
|
105
185
|
}
|
|
106
186
|
async chat(messages, options) {
|
|
107
|
-
|
|
108
|
-
|
|
187
|
+
const recordedMessages = cloneMessages(messages);
|
|
188
|
+
this._calls.push({ messages: recordedMessages, options: cloneOptions(options) });
|
|
189
|
+
return await this.responseFn(cloneMessages(messages), this._calls.length - 1);
|
|
190
|
+
}
|
|
191
|
+
inputCapabilities(_model) {
|
|
192
|
+
return { image: { sources: ["url", "bytes", "base64", "provider-file"] } };
|
|
193
|
+
}
|
|
194
|
+
validateInput(request) {
|
|
195
|
+
const effectiveModel = typeof request.providerOptions?.model === "string" ? request.providerOptions.model : request.model;
|
|
196
|
+
const fail = (source, feature) => {
|
|
197
|
+
throw new import_axl.UnsupportedModelInputError({
|
|
198
|
+
provider: this.name,
|
|
199
|
+
model: effectiveModel || request.model,
|
|
200
|
+
modality: "image",
|
|
201
|
+
...source ? { source } : {},
|
|
202
|
+
...feature ? { feature } : {}
|
|
203
|
+
});
|
|
204
|
+
};
|
|
205
|
+
if (request.providerOptions && "input" in request.providerOptions) {
|
|
206
|
+
fail(void 0, "raw input-container providerOptions");
|
|
207
|
+
}
|
|
208
|
+
for (const message of request.history) {
|
|
209
|
+
if (typeof message.content === "string") continue;
|
|
210
|
+
if (message.role !== "user") fail(void 0, "rich non-user history");
|
|
211
|
+
for (const part of richParts(message.content)) {
|
|
212
|
+
if (part.type === "image" && part.source.type === "provider-file" && part.source.provider !== this.name) {
|
|
213
|
+
fail("provider-file");
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
for (const part of richParts(request.input)) {
|
|
218
|
+
if (part.type === "image" && part.source.type === "provider-file" && part.source.provider !== this.name) {
|
|
219
|
+
fail("provider-file");
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
return { effectiveModel };
|
|
109
223
|
}
|
|
110
224
|
async *stream(messages, options) {
|
|
111
225
|
const callIndex = this._calls.length;
|
|
@@ -177,7 +291,7 @@ var MockProvider = class _MockProvider {
|
|
|
177
291
|
return new _MockProvider((messages) => {
|
|
178
292
|
const lastUser = [...messages].reverse().find((m) => m.role === "user");
|
|
179
293
|
return {
|
|
180
|
-
content: lastUser
|
|
294
|
+
content: lastUser ? (0, import_axl.inputText)(lastUser.content) : "",
|
|
181
295
|
usage: { prompt_tokens: 10, completion_tokens: 10, total_tokens: 20 },
|
|
182
296
|
cost: 0
|
|
183
297
|
};
|
|
@@ -230,8 +344,50 @@ var MockTool = class _MockTool {
|
|
|
230
344
|
}
|
|
231
345
|
};
|
|
232
346
|
|
|
347
|
+
// src/mock-transcription-provider.ts
|
|
348
|
+
function clone(value) {
|
|
349
|
+
return structuredClone(value);
|
|
350
|
+
}
|
|
351
|
+
function cloneRequest(request, includeSignal) {
|
|
352
|
+
const audio = request.audio.type === "bytes" ? { ...request.audio, data: request.audio.data.slice() } : { ...request.audio };
|
|
353
|
+
return {
|
|
354
|
+
model: request.model,
|
|
355
|
+
audio,
|
|
356
|
+
...request.language !== void 0 ? { language: request.language } : {},
|
|
357
|
+
...request.timestamps !== void 0 ? { timestamps: request.timestamps } : {},
|
|
358
|
+
...request.diarization !== void 0 ? { diarization: request.diarization } : {},
|
|
359
|
+
...request.providerOptions ? { providerOptions: clone(request.providerOptions) } : {},
|
|
360
|
+
...includeSignal && request.signal ? { signal: request.signal } : {}
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
var MockTranscriptionProvider = class _MockTranscriptionProvider {
|
|
364
|
+
constructor(response, capabilitiesFor = () => ({
|
|
365
|
+
sources: ["bytes", "base64", "provider-file"],
|
|
366
|
+
timestamps: ["segment", "word"],
|
|
367
|
+
diarization: true
|
|
368
|
+
})) {
|
|
369
|
+
this.response = response;
|
|
370
|
+
this.capabilitiesFor = capabilitiesFor;
|
|
371
|
+
}
|
|
372
|
+
_calls = [];
|
|
373
|
+
get calls() {
|
|
374
|
+
return this._calls.map(clone);
|
|
375
|
+
}
|
|
376
|
+
capabilities(model) {
|
|
377
|
+
return this.capabilitiesFor(model);
|
|
378
|
+
}
|
|
379
|
+
async transcribe(request) {
|
|
380
|
+
const snapshot = cloneRequest(request, false);
|
|
381
|
+
this._calls.push(snapshot);
|
|
382
|
+
return clone(await this.response(cloneRequest(request, true), this._calls.length - 1));
|
|
383
|
+
}
|
|
384
|
+
static text(text) {
|
|
385
|
+
return new _MockTranscriptionProvider(() => ({ transcript: { text } }));
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
|
|
233
389
|
// src/test-runtime.ts
|
|
234
|
-
var
|
|
390
|
+
var import_axl2 = require("@axlsdk/axl");
|
|
235
391
|
function generateExecutionId() {
|
|
236
392
|
return `test-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;
|
|
237
393
|
}
|
|
@@ -247,6 +403,7 @@ function preserveDrainCause(error, cause) {
|
|
|
247
403
|
var AxlTestRuntime = class {
|
|
248
404
|
workflows = /* @__PURE__ */ new Map();
|
|
249
405
|
mockProviders = /* @__PURE__ */ new Map();
|
|
406
|
+
mockTranscriptionProviders = /* @__PURE__ */ new Map();
|
|
250
407
|
mockToolMap = /* @__PURE__ */ new Map();
|
|
251
408
|
_toolCalls = [];
|
|
252
409
|
_agentCalls = [];
|
|
@@ -271,6 +428,9 @@ var AxlTestRuntime = class {
|
|
|
271
428
|
mockProvider(name, provider) {
|
|
272
429
|
this.mockProviders.set(name, provider);
|
|
273
430
|
}
|
|
431
|
+
mockTranscriptionProvider(name, provider) {
|
|
432
|
+
this.mockTranscriptionProviders.set(name, provider);
|
|
433
|
+
}
|
|
274
434
|
mockTool(name, handler) {
|
|
275
435
|
this.mockToolMap.set(name, MockTool.create(name, handler));
|
|
276
436
|
}
|
|
@@ -287,11 +447,15 @@ var AxlTestRuntime = class {
|
|
|
287
447
|
this.recorded = [];
|
|
288
448
|
this._executionId = generateExecutionId();
|
|
289
449
|
const validated = workflow.inputSchema.parse(input);
|
|
290
|
-
const registry = new
|
|
450
|
+
const registry = new import_axl2.ProviderRegistry();
|
|
291
451
|
registry.clearFactories();
|
|
292
452
|
for (const [name, provider] of this.mockProviders) {
|
|
293
453
|
registry.registerInstance(name, provider);
|
|
294
454
|
}
|
|
455
|
+
const transcriptionRegistry = new import_axl2.TranscriptionProviderRegistry();
|
|
456
|
+
for (const [name, provider] of this.mockTranscriptionProviders) {
|
|
457
|
+
transcriptionRegistry.registerInstance(name, provider);
|
|
458
|
+
}
|
|
295
459
|
const defaultProvider = this.mockProviders.get("default");
|
|
296
460
|
if (defaultProvider) {
|
|
297
461
|
registry.setFallback(defaultProvider);
|
|
@@ -323,7 +487,8 @@ var AxlTestRuntime = class {
|
|
|
323
487
|
// any eval runner) see the same attribution in tests and prod.
|
|
324
488
|
workflowName,
|
|
325
489
|
providerRegistry: registry,
|
|
326
|
-
|
|
490
|
+
transcriptionProviderRegistry: transcriptionRegistry,
|
|
491
|
+
stateStore: new import_axl2.MemoryStore(),
|
|
327
492
|
toolOverrides: toolOverrides.size > 0 ? toolOverrides : void 0,
|
|
328
493
|
awaitHumanHandler: this._humanDecisionHandler ? (opts) => this._humanDecisionHandler(opts) : void 0,
|
|
329
494
|
onTrace: (event) => {
|
|
@@ -346,8 +511,8 @@ var AxlTestRuntime = class {
|
|
|
346
511
|
outcome
|
|
347
512
|
});
|
|
348
513
|
}
|
|
349
|
-
this._totalCost += (0,
|
|
350
|
-
if ((0,
|
|
514
|
+
this._totalCost += (0, import_axl2.eventCostContribution)(event);
|
|
515
|
+
if ((0, import_axl2.isUnpricedLeaf)(event)) this._unpriced = true;
|
|
351
516
|
if (event.type === "agent_call_end" && event.data) {
|
|
352
517
|
const { response } = event.data;
|
|
353
518
|
if (response !== void 0) {
|
|
@@ -368,7 +533,7 @@ var AxlTestRuntime = class {
|
|
|
368
533
|
this._agentCalls.push(call);
|
|
369
534
|
}
|
|
370
535
|
};
|
|
371
|
-
const ctx = new
|
|
536
|
+
const ctx = new import_axl2.WorkflowContext(init);
|
|
372
537
|
const startedAt = Date.now();
|
|
373
538
|
ctx._emitWorkflowStart(validated);
|
|
374
539
|
try {
|
|
@@ -434,6 +599,7 @@ var AxlTestRuntime = class {
|
|
|
434
599
|
0 && (module.exports = {
|
|
435
600
|
AxlTestRuntime,
|
|
436
601
|
MockProvider,
|
|
437
|
-
MockTool
|
|
602
|
+
MockTool,
|
|
603
|
+
MockTranscriptionProvider
|
|
438
604
|
});
|
|
439
605
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/mock-provider.ts","../src/mock-tool.ts","../src/test-runtime.ts"],"sourcesContent":["export { AxlTestRuntime } from './test-runtime.js';\nexport type { RecordedToolCall, RecordedAgentCall, RecordedStep } from './test-runtime.js';\nexport { MockProvider } from './mock-provider.js';\nexport { MockTool } from './mock-tool.js';\n","import { readFileSync } from 'node:fs';\nimport { z } from 'zod';\nimport type {\n ChatMessage,\n ChatOptions,\n ToolCallMessage,\n ProviderResponse,\n StreamChunk,\n Provider,\n} from '@axlsdk/axl';\n\nfunction randomAlphanumeric(length: number): string {\n const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';\n let result = '';\n for (let i = 0; i < length; i++) {\n result += chars[Math.floor(Math.random() * chars.length)];\n }\n return result;\n}\n\nfunction generateFromSchema(schema: unknown): unknown {\n if (schema instanceof z.ZodString) return randomAlphanumeric(8 + Math.floor(Math.random() * 13));\n if (schema instanceof z.ZodNumber) {\n const min = Number.isFinite(schema.minValue) ? schema.minValue! : 0;\n const max = Number.isFinite(schema.maxValue) ? schema.maxValue! : 100;\n return min + Math.random() * (max - min);\n }\n if (schema instanceof z.ZodBoolean) return Math.random() < 0.5;\n if (schema instanceof z.ZodArray) {\n const count = 1 + Math.floor(Math.random() * 3);\n return Array.from({ length: count }, () => generateFromSchema(schema.element));\n }\n if (schema instanceof z.ZodObject) {\n const obj: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(schema.shape)) obj[key] = generateFromSchema(value);\n return obj;\n }\n if (schema instanceof z.ZodOptional) {\n if (Math.random() < 0.5) return undefined;\n return generateFromSchema(schema.unwrap());\n }\n if (schema instanceof z.ZodDefault) return schema.parse(undefined);\n if (schema instanceof z.ZodEnum) {\n const values = schema.options;\n return values.length > 0 ? values[Math.floor(Math.random() * values.length)] : '';\n }\n if (schema instanceof z.ZodLiteral) return [...schema.values][0];\n if (schema instanceof z.ZodNullable) return null;\n if (schema instanceof z.ZodUnion) {\n const options = schema.options;\n return generateFromSchema(options[Math.floor(Math.random() * options.length)]);\n }\n return {};\n}\n\nexport class MockProvider implements Provider {\n readonly name = 'mock';\n private _calls: { messages: ChatMessage[]; options: ChatOptions }[] = [];\n /** Per-call optional chunk arrays, set by `sequence()` / `chunked()` so\n * `stream()` can yield one `text_delta` per chunk. Per-call indexed\n * alongside the response sequence. */\n private chunkSequence?: Array<string[] | undefined>;\n /** Optional ms delay between successive chunks during `stream()`. Useful\n * for dev fixtures that need to demonstrate streaming UX visually\n * (without a delay, mock chunks fire synchronously and complete in\n * microseconds — invisible to a human watching). Default 0 keeps\n * every existing test fast.\n *\n * Set via `provider.chunkDelayMs = 50` after construction. Not part of\n * any factory's surface to keep the test API minimal. */\n chunkDelayMs = 0;\n\n private constructor(\n private responseFn: (\n messages: ChatMessage[],\n callIndex: number,\n ) => ProviderResponse | Promise<ProviderResponse>,\n ) {}\n\n get calls() {\n return this._calls;\n }\n\n async chat(messages: ChatMessage[], options: ChatOptions): Promise<ProviderResponse> {\n this._calls.push({ messages, options });\n return await this.responseFn(messages, this._calls.length - 1);\n }\n\n async *stream(messages: ChatMessage[], options: ChatOptions): AsyncGenerator<StreamChunk> {\n const callIndex = this._calls.length;\n const response = await this.chat(messages, options);\n const chunks = this.chunkSequence?.[callIndex];\n if (chunks && chunks.length > 0) {\n // Sanity guard — if a caller passes chunks AND content, they MUST\n // match. Otherwise tests pass while the real prod content silently\n // diverges from what the streaming path observes.\n const joined = chunks.join('');\n if (joined !== response.content) {\n throw new Error(\n `MockProvider.stream: chunks.join('') !== content. ` +\n `chunks=\"${joined}\" content=\"${response.content}\"`,\n );\n }\n for (let i = 0; i < chunks.length; i++) {\n yield { type: 'text_delta', content: chunks[i] };\n if (this.chunkDelayMs > 0 && i < chunks.length - 1) {\n await new Promise((resolve) => setTimeout(resolve, this.chunkDelayMs));\n }\n }\n } else if (response.content) {\n yield { type: 'text_delta', content: response.content };\n }\n if (response.tool_calls) {\n for (const tc of response.tool_calls) {\n yield {\n type: 'tool_call_delta',\n id: tc.id,\n name: tc.function.name,\n arguments: tc.function.arguments,\n };\n }\n }\n yield { type: 'done', usage: response.usage, providerMetadata: response.providerMetadata };\n }\n\n static sequence(\n responses: Array<{\n content: string;\n tool_calls?: ToolCallMessage[];\n providerMetadata?: Record<string, unknown>;\n usage?: { prompt_tokens: number; completion_tokens: number; total_tokens: number };\n cost?: number;\n /** When set, `stream()` yields one `text_delta` per entry instead\n * of one big delta with the full content. Use to exercise\n * partial-JSON parsing, structural-boundary throttling, and\n * cross-attempt token retention in tests. Must satisfy\n * `chunks.join('') === content`. */\n chunks?: string[];\n }>,\n ): MockProvider {\n const provider = new MockProvider((_messages, callIndex) => {\n if (callIndex >= responses.length) {\n throw new Error(\n `MockProvider.sequence: no response for call index ${callIndex}. Only ${responses.length} responses defined.`,\n );\n }\n const resp = responses[callIndex];\n return {\n content: resp.content,\n tool_calls: resp.tool_calls,\n providerMetadata: resp.providerMetadata,\n usage: resp.usage ?? { prompt_tokens: 10, completion_tokens: 10, total_tokens: 20 },\n cost: resp.cost ?? 0,\n };\n });\n provider.chunkSequence = responses.map((r) => r.chunks);\n return provider;\n }\n\n /**\n * Convenience: build a `sequence()` from plain content strings, splitting\n * each one into fixed-size chunks for the streaming path. Default\n * `chunkSize` is 4 chars (≈1 token).\n */\n static chunked(contents: string[], chunkSize = 4): MockProvider {\n const responses = contents.map((content) => {\n const chunks: string[] = [];\n for (let i = 0; i < content.length; i += chunkSize) {\n chunks.push(content.slice(i, i + chunkSize));\n }\n return { content, chunks };\n });\n return MockProvider.sequence(responses);\n }\n\n static echo(): MockProvider {\n return new MockProvider((messages) => {\n const lastUser = [...messages].reverse().find((m) => m.role === 'user');\n return {\n content: lastUser?.content ?? '',\n usage: { prompt_tokens: 10, completion_tokens: 10, total_tokens: 20 },\n cost: 0,\n };\n });\n }\n\n static json(schema: unknown): MockProvider {\n return new MockProvider(() => ({\n content: JSON.stringify(generateFromSchema(schema)),\n usage: { prompt_tokens: 10, completion_tokens: 10, total_tokens: 20 },\n cost: 0,\n }));\n }\n\n static replay(source: string | ProviderResponse[]): MockProvider {\n const data =\n typeof source === 'string'\n ? (JSON.parse(readFileSync(source, 'utf-8')) as ProviderResponse[])\n : source;\n return new MockProvider((_messages, callIndex) => {\n if (callIndex >= data.length) {\n throw new Error(`MockProvider.replay: no recorded response for call index ${callIndex}`);\n }\n return data[callIndex];\n });\n }\n\n static fn(\n handler: (\n messages: ChatMessage[],\n callIndex: number,\n ) =>\n | {\n content: string;\n tool_calls?: ToolCallMessage[];\n providerMetadata?: Record<string, unknown>;\n usage?: { prompt_tokens: number; completion_tokens: number; total_tokens: number };\n cost?: number;\n }\n | Promise<{\n content: string;\n tool_calls?: ToolCallMessage[];\n providerMetadata?: Record<string, unknown>;\n usage?: { prompt_tokens: number; completion_tokens: number; total_tokens: number };\n cost?: number;\n }>,\n ): MockProvider {\n return new MockProvider(async (messages, callIndex) => {\n const result = await handler(messages, callIndex);\n return {\n ...result,\n usage: result.usage ?? { prompt_tokens: 10, completion_tokens: 10, total_tokens: 20 },\n cost: result.cost ?? 0,\n };\n });\n }\n}\n","export class MockTool {\n private _calls: { input: unknown }[] = [];\n\n constructor(\n readonly name: string,\n private handler: (input: unknown) => unknown | Promise<unknown>,\n ) {}\n\n get calls() {\n return this._calls;\n }\n\n async execute(input: unknown): Promise<unknown> {\n this._calls.push({ input });\n return this.handler(input);\n }\n\n static create(name: string, handler: (input: unknown) => unknown | Promise<unknown>): MockTool {\n return new MockTool(name, handler);\n }\n}\n","import { MockProvider } from './mock-provider.js';\nimport { MockTool } from './mock-tool.js';\nimport type {\n AxlEvent,\n AwaitHumanOptions,\n HumanDecision,\n ProviderResponse,\n AgentCallInfo,\n AxlConfig,\n AnyWorkflow,\n ToolCallOutcome,\n ObservationStatus,\n} from '@axlsdk/axl';\nimport {\n WorkflowContext,\n MemoryStore,\n ProviderRegistry,\n eventCostContribution,\n isUnpricedLeaf,\n} from '@axlsdk/axl';\nimport type { EventStreamOptions, WorkflowContextInit } from '@axlsdk/axl';\n\n// `AnyWorkflow` is a re-exported alias for `Workflow<any, any>` — see\n// the JSDoc on `AnyWorkflow` in `@axlsdk/axl/workflow.ts`. The bivariant\n// `any` is load-bearing for satisfying narrowly-typed handlers (e.g., a\n// `Workflow<TInput=MsgType>` whose handler takes `WorkflowContext<MsgType>`).\n\n/** One accepted provider-issued tool invocation, recorded from its terminal v2 event.\n *\n * Narrow `outcome.status` before reading status-specific fields. Correlation uses\n * `(executionId, askId, callId)`; `name` is the canonical tool name.\n */\nexport type RecordedToolCall = {\n name: string;\n executionId: string;\n askId: string;\n callId: string;\n args: unknown;\n requestedTool?: string;\n outcome: ToolCallOutcome;\n};\nexport type RecordedAgentCall = Partial<AgentCallInfo> &\n Pick<AgentCallInfo, 'agent' | 'prompt' | 'response'>;\nexport type RecordedStep = { step: number; type: string; data: unknown };\n\nfunction generateExecutionId(): string {\n return `test-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nfunction preserveDrainCause(error: Error, cause: unknown): Error {\n if (cause === undefined || cause === error || 'cause' in error) return error;\n Object.defineProperty(error, 'cause', {\n configurable: true,\n enumerable: false,\n value: cause,\n });\n return error;\n}\n\nexport type AxlTestRuntimeOptions = {\n record?: string;\n humanDecisions?: (options: AwaitHumanOptions) => HumanDecision;\n /** AxlConfig for the test runtime. Controls trace level/redact, context management, etc.\n * Defaults to `{}`. Set `{ trace: { level: 'full' } }` to verify verbose-mode snapshots\n * in tests, or `{ trace: { redact: true } }` to verify redaction policy in tests. */\n config?: AxlConfig;\n};\n\nexport class AxlTestRuntime {\n private workflows = new Map<string, AnyWorkflow>();\n private mockProviders = new Map<string, MockProvider>();\n private mockToolMap = new Map<string, MockTool>();\n private _toolCalls: RecordedToolCall[] = [];\n private _agentCalls: RecordedAgentCall[] = [];\n private _steps: RecordedStep[] = [];\n private _traceLog: AxlEvent[] = [];\n private _totalCost = 0;\n private _unpriced = false;\n private _stepCounter = 0;\n private recordPath?: string;\n private recorded: ProviderResponse[] = [];\n private _executionId: string = generateExecutionId();\n private _humanDecisionHandler?: (options: AwaitHumanOptions) => HumanDecision;\n private _config: AxlConfig;\n\n constructor(options?: AxlTestRuntimeOptions) {\n this.recordPath = options?.record;\n this._humanDecisionHandler = options?.humanDecisions;\n this._config = options?.config ?? {};\n }\n\n register(workflow: AnyWorkflow): void {\n this.workflows.set(workflow.name, workflow);\n }\n\n mockProvider(name: string, provider: MockProvider): void {\n this.mockProviders.set(name, provider);\n }\n\n mockTool<TInput = unknown>(\n name: string,\n handler: (input: TInput) => unknown | Promise<unknown>,\n ): void {\n // The MockTool registry is type-erased (`(input: unknown) => unknown`)\n // because the runtime can't statically know each tool's input shape; tests\n // opt in to a typed input via the generic, and we cast on storage.\n this.mockToolMap.set(name, MockTool.create(name, handler as (input: unknown) => unknown));\n }\n\n async execute(\n workflowName: string,\n input: unknown,\n options?: {\n metadata?: Record<string, unknown>;\n events?: EventStreamOptions;\n branchDrainTimeoutMs?: number;\n },\n ): Promise<unknown> {\n const workflow = this.workflows.get(workflowName);\n if (!workflow) throw new Error(`Workflow \"${workflowName}\" not registered`);\n\n // Reset state between executions\n this._toolCalls = [];\n this._agentCalls = [];\n this._steps = [];\n this._traceLog = [];\n this._totalCost = 0;\n this._unpriced = false;\n this._stepCounter = 0;\n this.recorded = [];\n this._executionId = generateExecutionId();\n\n const validated = workflow.inputSchema.parse(input);\n\n // Build ProviderRegistry from registered mock providers\n const registry = new ProviderRegistry();\n registry.clearFactories(); // Remove built-in factories; only use explicit mocks\n for (const [name, provider] of this.mockProviders) {\n registry.registerInstance(name, provider);\n }\n // Fallback resolution: 'default' key or single-provider\n const defaultProvider = this.mockProviders.get('default');\n if (defaultProvider) {\n registry.setFallback(defaultProvider);\n } else if (this.mockProviders.size === 1) {\n const onlyProvider = this.mockProviders.values().next().value!;\n registry.setFallback(onlyProvider);\n }\n\n // Build toolOverrides from mockToolMap\n const toolOverrides = new Map<string, (args: unknown) => Promise<unknown>>();\n for (const [name, mockTool] of this.mockToolMap) {\n toolOverrides.set(name, async (args: unknown) => {\n return mockTool.execute(args);\n });\n }\n\n // Previously `_recordStep('workflow_start', ...)` was called here with\n // raw `{ workflow, input }` data, AND `ctx._emitWorkflowStart` below\n // pushed through the onTrace handler (which also bumps `_stepCounter`\n // and appends to `_steps`). Result: two entries in `steps()` per\n // workflow_start, with the first bypassing `config.trace.redact`.\n // The `_recordStep` call is removed — onTrace is the single source\n // of truth for `_steps`, matching the behavior of every other event\n // type in the test runtime. Reviewer architecture §5.\n\n const init: WorkflowContextInit = {\n input: validated,\n executionId: this._executionId,\n metadata: options?.metadata,\n // Thread the constructor-provided config so tests can exercise\n // trace.level === 'full' and trace.redact behavior end-to-end.\n config: this._config,\n // Thread `events` config so tests can exercise the queue cap and\n // overflow policy on `ctx.events`. Mirrors the production runtime.\n eventStreamOptions: options?.events,\n branchDrainTimeoutMs: options?.branchDrainTimeoutMs,\n // Production runtime threads this (see `runtime.ts:594` in\n // `execute()` and `:765` in `stream()`). `emitEvent` auto-stamps\n // `event.workflow` from it, so consumers grouping by workflow\n // (Cost Dashboard `byWorkflow`, `trackExecution.metadata.workflows`,\n // any eval runner) see the same attribution in tests and prod.\n workflowName,\n providerRegistry: registry,\n stateStore: new MemoryStore(),\n toolOverrides: toolOverrides.size > 0 ? toolOverrides : undefined,\n awaitHumanHandler: this._humanDecisionHandler\n ? (opts: AwaitHumanOptions) => this._humanDecisionHandler!(opts)\n : undefined,\n onTrace: (event: AxlEvent) => {\n this._traceLog.push(event);\n this._stepCounter++;\n this._steps.push({\n step: this._stepCounter,\n type: event.type,\n data: (event as { data?: unknown }).data,\n });\n\n if (event.type === 'tool_call_end') {\n const { args, requestedTool, outcome } = event.data;\n this._toolCalls.push({\n name: event.tool,\n executionId: event.executionId,\n askId: event.askId,\n callId: event.callId,\n args,\n ...(requestedTool !== undefined ? { requestedTool } : {}),\n outcome,\n });\n }\n\n // Single-source-of-truth cost accumulator. Skips ask_end\n // rollups (decision 10) and guards NaN/Infinity.\n this._totalCost += eventCostContribution(event);\n // Honest aggregate: one unpriced leaf makes `totalCost()` a lower bound.\n if (isUnpricedLeaf(event)) this._unpriced = true;\n\n // Track provider responses for recording\n if (event.type === 'agent_call_end' && event.data) {\n const { response } = event.data as { prompt?: string; response?: string };\n if (response !== undefined) {\n this.recorded.push({\n content: response,\n usage: event.tokens\n ? {\n prompt_tokens: event.tokens.input ?? 0,\n completion_tokens: event.tokens.output ?? 0,\n total_tokens:\n (event.tokens.input ?? 0) +\n (event.tokens.output ?? 0) +\n (event.tokens.reasoning ?? 0),\n ...(event.tokens.reasoning !== undefined\n ? { reasoning_tokens: event.tokens.reasoning }\n : {}),\n }\n : { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 },\n ...(event.cost !== undefined ? { cost: event.cost } : {}),\n });\n }\n }\n },\n onAgentCallComplete: (call: AgentCallInfo) => {\n this._agentCalls.push(call);\n },\n };\n\n const ctx = new WorkflowContext(init);\n\n // Emit workflow_start through the same pipeline production uses,\n // AFTER ctx exists so `emitEvent`'s redact/step/timestamp handling\n // applies. Previously emitted via `_pushTrace` which bypassed\n // redaction — `config: { trace: { redact: true } }` on the test\n // runtime would scrub intermediate events but leak `input`/`result`\n // through the synthesized workflow_start/end.\n const startedAt = Date.now();\n ctx._emitWorkflowStart(validated);\n try {\n const result = await workflow.handler(ctx);\n const observation = await ctx._drainBranchWork();\n\n // Validate output schema if defined\n if (workflow.outputSchema) workflow.outputSchema.parse(result);\n\n ctx._emitWorkflowEnd({\n status: 'completed',\n duration: Date.now() - startedAt,\n result,\n observation,\n });\n // `_steps` is populated by onTrace for every event (including\n // workflow_end); no separate `_recordStep` call needed — that\n // would double-count.\n\n if (this.recordPath) await this._writeRecording();\n return result;\n } catch (err) {\n let workflowError = err;\n let observation: ObservationStatus = { complete: true };\n try {\n observation = await ctx._drainBranchWork();\n } catch (drainError) {\n workflowError =\n drainError instanceof Error ? preserveDrainCause(drainError, workflowError) : drainError;\n }\n // Parity with production: failed workflows get a terminal\n // `workflow_end(status: 'failed')` event so consumers counting\n // workflow_start ↔ workflow_end pairs never see an unclosed one.\n // `aborted` flag mirrors the runtime.ts AbortError detection.\n const aborted =\n typeof workflowError === 'object' &&\n workflowError !== null &&\n (workflowError as { name?: unknown }).name === 'AbortError';\n ctx._emitWorkflowEnd({\n status: 'failed',\n duration: Date.now() - startedAt,\n error: workflowError instanceof Error ? workflowError.message : String(workflowError),\n ...(aborted ? { aborted: true } : {}),\n observation,\n });\n // `_steps` populated by onTrace (see comment on the success path).\n throw workflowError;\n }\n }\n\n toolCalls(name?: string): RecordedToolCall[] {\n return name ? this._toolCalls.filter((c) => c.name === name) : this._toolCalls;\n }\n\n agentCalls(name?: string): RecordedAgentCall[] {\n return name ? this._agentCalls.filter((c) => c.agent === name) : this._agentCalls;\n }\n\n totalCost(): number {\n return this._totalCost;\n }\n /** True when any cost-bearing call was unpriced — `totalCost()` is then a\n * LOWER BOUND. Mirrors `ExecutionInfo.unpriced` / `BudgetResult.unpriced`. */\n unpriced(): boolean {\n return this._unpriced;\n }\n steps(): RecordedStep[] {\n return this._steps;\n }\n traceLog(): AxlEvent[] {\n return this._traceLog;\n }\n\n private async _writeRecording(): Promise<void> {\n if (!this.recordPath) return;\n const { writeFile, mkdir } = await import('node:fs/promises');\n const { dirname } = await import('node:path');\n await mkdir(dirname(this.recordPath), { recursive: true });\n await writeFile(this.recordPath, JSON.stringify(this.recorded, null, 2), 'utf8');\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,qBAA6B;AAC7B,iBAAkB;AAUlB,SAAS,mBAAmB,QAAwB;AAClD,QAAM,QAAQ;AACd,MAAI,SAAS;AACb,WAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAC/B,cAAU,MAAM,KAAK,MAAM,KAAK,OAAO,IAAI,MAAM,MAAM,CAAC;AAAA,EAC1D;AACA,SAAO;AACT;AAEA,SAAS,mBAAmB,QAA0B;AACpD,MAAI,kBAAkB,aAAE,UAAW,QAAO,mBAAmB,IAAI,KAAK,MAAM,KAAK,OAAO,IAAI,EAAE,CAAC;AAC/F,MAAI,kBAAkB,aAAE,WAAW;AACjC,UAAM,MAAM,OAAO,SAAS,OAAO,QAAQ,IAAI,OAAO,WAAY;AAClE,UAAM,MAAM,OAAO,SAAS,OAAO,QAAQ,IAAI,OAAO,WAAY;AAClE,WAAO,MAAM,KAAK,OAAO,KAAK,MAAM;AAAA,EACtC;AACA,MAAI,kBAAkB,aAAE,WAAY,QAAO,KAAK,OAAO,IAAI;AAC3D,MAAI,kBAAkB,aAAE,UAAU;AAChC,UAAM,QAAQ,IAAI,KAAK,MAAM,KAAK,OAAO,IAAI,CAAC;AAC9C,WAAO,MAAM,KAAK,EAAE,QAAQ,MAAM,GAAG,MAAM,mBAAmB,OAAO,OAAO,CAAC;AAAA,EAC/E;AACA,MAAI,kBAAkB,aAAE,WAAW;AACjC,UAAM,MAA+B,CAAC;AACtC,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,OAAO,KAAK,EAAG,KAAI,GAAG,IAAI,mBAAmB,KAAK;AAC5F,WAAO;AAAA,EACT;AACA,MAAI,kBAAkB,aAAE,aAAa;AACnC,QAAI,KAAK,OAAO,IAAI,IAAK,QAAO;AAChC,WAAO,mBAAmB,OAAO,OAAO,CAAC;AAAA,EAC3C;AACA,MAAI,kBAAkB,aAAE,WAAY,QAAO,OAAO,MAAM,MAAS;AACjE,MAAI,kBAAkB,aAAE,SAAS;AAC/B,UAAM,SAAS,OAAO;AACtB,WAAO,OAAO,SAAS,IAAI,OAAO,KAAK,MAAM,KAAK,OAAO,IAAI,OAAO,MAAM,CAAC,IAAI;AAAA,EACjF;AACA,MAAI,kBAAkB,aAAE,WAAY,QAAO,CAAC,GAAG,OAAO,MAAM,EAAE,CAAC;AAC/D,MAAI,kBAAkB,aAAE,YAAa,QAAO;AAC5C,MAAI,kBAAkB,aAAE,UAAU;AAChC,UAAM,UAAU,OAAO;AACvB,WAAO,mBAAmB,QAAQ,KAAK,MAAM,KAAK,OAAO,IAAI,QAAQ,MAAM,CAAC,CAAC;AAAA,EAC/E;AACA,SAAO,CAAC;AACV;AAEO,IAAM,eAAN,MAAM,cAAiC;AAAA,EAiBpC,YACE,YAIR;AAJQ;AAAA,EAIP;AAAA,EArBM,OAAO;AAAA,EACR,SAA8D,CAAC;AAAA;AAAA;AAAA;AAAA,EAI/D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASR,eAAe;AAAA,EASf,IAAI,QAAQ;AACV,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,KAAK,UAAyB,SAAiD;AACnF,SAAK,OAAO,KAAK,EAAE,UAAU,QAAQ,CAAC;AACtC,WAAO,MAAM,KAAK,WAAW,UAAU,KAAK,OAAO,SAAS,CAAC;AAAA,EAC/D;AAAA,EAEA,OAAO,OAAO,UAAyB,SAAmD;AACxF,UAAM,YAAY,KAAK,OAAO;AAC9B,UAAM,WAAW,MAAM,KAAK,KAAK,UAAU,OAAO;AAClD,UAAM,SAAS,KAAK,gBAAgB,SAAS;AAC7C,QAAI,UAAU,OAAO,SAAS,GAAG;AAI/B,YAAM,SAAS,OAAO,KAAK,EAAE;AAC7B,UAAI,WAAW,SAAS,SAAS;AAC/B,cAAM,IAAI;AAAA,UACR,6DACa,MAAM,cAAc,SAAS,OAAO;AAAA,QACnD;AAAA,MACF;AACA,eAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,cAAM,EAAE,MAAM,cAAc,SAAS,OAAO,CAAC,EAAE;AAC/C,YAAI,KAAK,eAAe,KAAK,IAAI,OAAO,SAAS,GAAG;AAClD,gBAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,KAAK,YAAY,CAAC;AAAA,QACvE;AAAA,MACF;AAAA,IACF,WAAW,SAAS,SAAS;AAC3B,YAAM,EAAE,MAAM,cAAc,SAAS,SAAS,QAAQ;AAAA,IACxD;AACA,QAAI,SAAS,YAAY;AACvB,iBAAW,MAAM,SAAS,YAAY;AACpC,cAAM;AAAA,UACJ,MAAM;AAAA,UACN,IAAI,GAAG;AAAA,UACP,MAAM,GAAG,SAAS;AAAA,UAClB,WAAW,GAAG,SAAS;AAAA,QACzB;AAAA,MACF;AAAA,IACF;AACA,UAAM,EAAE,MAAM,QAAQ,OAAO,SAAS,OAAO,kBAAkB,SAAS,iBAAiB;AAAA,EAC3F;AAAA,EAEA,OAAO,SACL,WAac;AACd,UAAM,WAAW,IAAI,cAAa,CAAC,WAAW,cAAc;AAC1D,UAAI,aAAa,UAAU,QAAQ;AACjC,cAAM,IAAI;AAAA,UACR,qDAAqD,SAAS,UAAU,UAAU,MAAM;AAAA,QAC1F;AAAA,MACF;AACA,YAAM,OAAO,UAAU,SAAS;AAChC,aAAO;AAAA,QACL,SAAS,KAAK;AAAA,QACd,YAAY,KAAK;AAAA,QACjB,kBAAkB,KAAK;AAAA,QACvB,OAAO,KAAK,SAAS,EAAE,eAAe,IAAI,mBAAmB,IAAI,cAAc,GAAG;AAAA,QAClF,MAAM,KAAK,QAAQ;AAAA,MACrB;AAAA,IACF,CAAC;AACD,aAAS,gBAAgB,UAAU,IAAI,CAAC,MAAM,EAAE,MAAM;AACtD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,QAAQ,UAAoB,YAAY,GAAiB;AAC9D,UAAM,YAAY,SAAS,IAAI,CAAC,YAAY;AAC1C,YAAM,SAAmB,CAAC;AAC1B,eAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK,WAAW;AAClD,eAAO,KAAK,QAAQ,MAAM,GAAG,IAAI,SAAS,CAAC;AAAA,MAC7C;AACA,aAAO,EAAE,SAAS,OAAO;AAAA,IAC3B,CAAC;AACD,WAAO,cAAa,SAAS,SAAS;AAAA,EACxC;AAAA,EAEA,OAAO,OAAqB;AAC1B,WAAO,IAAI,cAAa,CAAC,aAAa;AACpC,YAAM,WAAW,CAAC,GAAG,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM;AACtE,aAAO;AAAA,QACL,SAAS,UAAU,WAAW;AAAA,QAC9B,OAAO,EAAE,eAAe,IAAI,mBAAmB,IAAI,cAAc,GAAG;AAAA,QACpE,MAAM;AAAA,MACR;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,OAAO,KAAK,QAA+B;AACzC,WAAO,IAAI,cAAa,OAAO;AAAA,MAC7B,SAAS,KAAK,UAAU,mBAAmB,MAAM,CAAC;AAAA,MAClD,OAAO,EAAE,eAAe,IAAI,mBAAmB,IAAI,cAAc,GAAG;AAAA,MACpE,MAAM;AAAA,IACR,EAAE;AAAA,EACJ;AAAA,EAEA,OAAO,OAAO,QAAmD;AAC/D,UAAM,OACJ,OAAO,WAAW,WACb,KAAK,UAAM,6BAAa,QAAQ,OAAO,CAAC,IACzC;AACN,WAAO,IAAI,cAAa,CAAC,WAAW,cAAc;AAChD,UAAI,aAAa,KAAK,QAAQ;AAC5B,cAAM,IAAI,MAAM,4DAA4D,SAAS,EAAE;AAAA,MACzF;AACA,aAAO,KAAK,SAAS;AAAA,IACvB,CAAC;AAAA,EACH;AAAA,EAEA,OAAO,GACL,SAkBc;AACd,WAAO,IAAI,cAAa,OAAO,UAAU,cAAc;AACrD,YAAM,SAAS,MAAM,QAAQ,UAAU,SAAS;AAChD,aAAO;AAAA,QACL,GAAG;AAAA,QACH,OAAO,OAAO,SAAS,EAAE,eAAe,IAAI,mBAAmB,IAAI,cAAc,GAAG;AAAA,QACpF,MAAM,OAAO,QAAQ;AAAA,MACvB;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;AC5OO,IAAM,WAAN,MAAM,UAAS;AAAA,EAGpB,YACW,MACD,SACR;AAFS;AACD;AAAA,EACP;AAAA,EALK,SAA+B,CAAC;AAAA,EAOxC,IAAI,QAAQ;AACV,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,QAAQ,OAAkC;AAC9C,SAAK,OAAO,KAAK,EAAE,MAAM,CAAC;AAC1B,WAAO,KAAK,QAAQ,KAAK;AAAA,EAC3B;AAAA,EAEA,OAAO,OAAO,MAAc,SAAmE;AAC7F,WAAO,IAAI,UAAS,MAAM,OAAO;AAAA,EACnC;AACF;;;ACPA,iBAMO;AA0BP,SAAS,sBAA8B;AACrC,SAAO,QAAQ,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC;AACtE;AAEA,SAAS,mBAAmB,OAAc,OAAuB;AAC/D,MAAI,UAAU,UAAa,UAAU,SAAS,WAAW,MAAO,QAAO;AACvE,SAAO,eAAe,OAAO,SAAS;AAAA,IACpC,cAAc;AAAA,IACd,YAAY;AAAA,IACZ,OAAO;AAAA,EACT,CAAC;AACD,SAAO;AACT;AAWO,IAAM,iBAAN,MAAqB;AAAA,EAClB,YAAY,oBAAI,IAAyB;AAAA,EACzC,gBAAgB,oBAAI,IAA0B;AAAA,EAC9C,cAAc,oBAAI,IAAsB;AAAA,EACxC,aAAiC,CAAC;AAAA,EAClC,cAAmC,CAAC;AAAA,EACpC,SAAyB,CAAC;AAAA,EAC1B,YAAwB,CAAC;AAAA,EACzB,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,eAAe;AAAA,EACf;AAAA,EACA,WAA+B,CAAC;AAAA,EAChC,eAAuB,oBAAoB;AAAA,EAC3C;AAAA,EACA;AAAA,EAER,YAAY,SAAiC;AAC3C,SAAK,aAAa,SAAS;AAC3B,SAAK,wBAAwB,SAAS;AACtC,SAAK,UAAU,SAAS,UAAU,CAAC;AAAA,EACrC;AAAA,EAEA,SAAS,UAA6B;AACpC,SAAK,UAAU,IAAI,SAAS,MAAM,QAAQ;AAAA,EAC5C;AAAA,EAEA,aAAa,MAAc,UAA8B;AACvD,SAAK,cAAc,IAAI,MAAM,QAAQ;AAAA,EACvC;AAAA,EAEA,SACE,MACA,SACM;AAIN,SAAK,YAAY,IAAI,MAAM,SAAS,OAAO,MAAM,OAAsC,CAAC;AAAA,EAC1F;AAAA,EAEA,MAAM,QACJ,cACA,OACA,SAKkB;AAClB,UAAM,WAAW,KAAK,UAAU,IAAI,YAAY;AAChD,QAAI,CAAC,SAAU,OAAM,IAAI,MAAM,aAAa,YAAY,kBAAkB;AAG1E,SAAK,aAAa,CAAC;AACnB,SAAK,cAAc,CAAC;AACpB,SAAK,SAAS,CAAC;AACf,SAAK,YAAY,CAAC;AAClB,SAAK,aAAa;AAClB,SAAK,YAAY;AACjB,SAAK,eAAe;AACpB,SAAK,WAAW,CAAC;AACjB,SAAK,eAAe,oBAAoB;AAExC,UAAM,YAAY,SAAS,YAAY,MAAM,KAAK;AAGlD,UAAM,WAAW,IAAI,4BAAiB;AACtC,aAAS,eAAe;AACxB,eAAW,CAAC,MAAM,QAAQ,KAAK,KAAK,eAAe;AACjD,eAAS,iBAAiB,MAAM,QAAQ;AAAA,IAC1C;AAEA,UAAM,kBAAkB,KAAK,cAAc,IAAI,SAAS;AACxD,QAAI,iBAAiB;AACnB,eAAS,YAAY,eAAe;AAAA,IACtC,WAAW,KAAK,cAAc,SAAS,GAAG;AACxC,YAAM,eAAe,KAAK,cAAc,OAAO,EAAE,KAAK,EAAE;AACxD,eAAS,YAAY,YAAY;AAAA,IACnC;AAGA,UAAM,gBAAgB,oBAAI,IAAiD;AAC3E,eAAW,CAAC,MAAM,QAAQ,KAAK,KAAK,aAAa;AAC/C,oBAAc,IAAI,MAAM,OAAO,SAAkB;AAC/C,eAAO,SAAS,QAAQ,IAAI;AAAA,MAC9B,CAAC;AAAA,IACH;AAWA,UAAM,OAA4B;AAAA,MAChC,OAAO;AAAA,MACP,aAAa,KAAK;AAAA,MAClB,UAAU,SAAS;AAAA;AAAA;AAAA,MAGnB,QAAQ,KAAK;AAAA;AAAA;AAAA,MAGb,oBAAoB,SAAS;AAAA,MAC7B,sBAAsB,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAM/B;AAAA,MACA,kBAAkB;AAAA,MAClB,YAAY,IAAI,uBAAY;AAAA,MAC5B,eAAe,cAAc,OAAO,IAAI,gBAAgB;AAAA,MACxD,mBAAmB,KAAK,wBACpB,CAAC,SAA4B,KAAK,sBAAuB,IAAI,IAC7D;AAAA,MACJ,SAAS,CAAC,UAAoB;AAC5B,aAAK,UAAU,KAAK,KAAK;AACzB,aAAK;AACL,aAAK,OAAO,KAAK;AAAA,UACf,MAAM,KAAK;AAAA,UACX,MAAM,MAAM;AAAA,UACZ,MAAO,MAA6B;AAAA,QACtC,CAAC;AAED,YAAI,MAAM,SAAS,iBAAiB;AAClC,gBAAM,EAAE,MAAM,eAAe,QAAQ,IAAI,MAAM;AAC/C,eAAK,WAAW,KAAK;AAAA,YACnB,MAAM,MAAM;AAAA,YACZ,aAAa,MAAM;AAAA,YACnB,OAAO,MAAM;AAAA,YACb,QAAQ,MAAM;AAAA,YACd;AAAA,YACA,GAAI,kBAAkB,SAAY,EAAE,cAAc,IAAI,CAAC;AAAA,YACvD;AAAA,UACF,CAAC;AAAA,QACH;AAIA,aAAK,kBAAc,kCAAsB,KAAK;AAE9C,gBAAI,2BAAe,KAAK,EAAG,MAAK,YAAY;AAG5C,YAAI,MAAM,SAAS,oBAAoB,MAAM,MAAM;AACjD,gBAAM,EAAE,SAAS,IAAI,MAAM;AAC3B,cAAI,aAAa,QAAW;AAC1B,iBAAK,SAAS,KAAK;AAAA,cACjB,SAAS;AAAA,cACT,OAAO,MAAM,SACT;AAAA,gBACE,eAAe,MAAM,OAAO,SAAS;AAAA,gBACrC,mBAAmB,MAAM,OAAO,UAAU;AAAA,gBAC1C,eACG,MAAM,OAAO,SAAS,MACtB,MAAM,OAAO,UAAU,MACvB,MAAM,OAAO,aAAa;AAAA,gBAC7B,GAAI,MAAM,OAAO,cAAc,SAC3B,EAAE,kBAAkB,MAAM,OAAO,UAAU,IAC3C,CAAC;AAAA,cACP,IACA,EAAE,eAAe,GAAG,mBAAmB,GAAG,cAAc,EAAE;AAAA,cAC9D,GAAI,MAAM,SAAS,SAAY,EAAE,MAAM,MAAM,KAAK,IAAI,CAAC;AAAA,YACzD,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF;AAAA,MACA,qBAAqB,CAAC,SAAwB;AAC5C,aAAK,YAAY,KAAK,IAAI;AAAA,MAC5B;AAAA,IACF;AAEA,UAAM,MAAM,IAAI,2BAAgB,IAAI;AAQpC,UAAM,YAAY,KAAK,IAAI;AAC3B,QAAI,mBAAmB,SAAS;AAChC,QAAI;AACF,YAAM,SAAS,MAAM,SAAS,QAAQ,GAAG;AACzC,YAAM,cAAc,MAAM,IAAI,iBAAiB;AAG/C,UAAI,SAAS,aAAc,UAAS,aAAa,MAAM,MAAM;AAE7D,UAAI,iBAAiB;AAAA,QACnB,QAAQ;AAAA,QACR,UAAU,KAAK,IAAI,IAAI;AAAA,QACvB;AAAA,QACA;AAAA,MACF,CAAC;AAKD,UAAI,KAAK,WAAY,OAAM,KAAK,gBAAgB;AAChD,aAAO;AAAA,IACT,SAAS,KAAK;AACZ,UAAI,gBAAgB;AACpB,UAAI,cAAiC,EAAE,UAAU,KAAK;AACtD,UAAI;AACF,sBAAc,MAAM,IAAI,iBAAiB;AAAA,MAC3C,SAAS,YAAY;AACnB,wBACE,sBAAsB,QAAQ,mBAAmB,YAAY,aAAa,IAAI;AAAA,MAClF;AAKA,YAAM,UACJ,OAAO,kBAAkB,YACzB,kBAAkB,QACjB,cAAqC,SAAS;AACjD,UAAI,iBAAiB;AAAA,QACnB,QAAQ;AAAA,QACR,UAAU,KAAK,IAAI,IAAI;AAAA,QACvB,OAAO,yBAAyB,QAAQ,cAAc,UAAU,OAAO,aAAa;AAAA,QACpF,GAAI,UAAU,EAAE,SAAS,KAAK,IAAI,CAAC;AAAA,QACnC;AAAA,MACF,CAAC;AAED,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,UAAU,MAAmC;AAC3C,WAAO,OAAO,KAAK,WAAW,OAAO,CAAC,MAAM,EAAE,SAAS,IAAI,IAAI,KAAK;AAAA,EACtE;AAAA,EAEA,WAAW,MAAoC;AAC7C,WAAO,OAAO,KAAK,YAAY,OAAO,CAAC,MAAM,EAAE,UAAU,IAAI,IAAI,KAAK;AAAA,EACxE;AAAA,EAEA,YAAoB;AAClB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA,EAGA,WAAoB;AAClB,WAAO,KAAK;AAAA,EACd;AAAA,EACA,QAAwB;AACtB,WAAO,KAAK;AAAA,EACd;AAAA,EACA,WAAuB;AACrB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAc,kBAAiC;AAC7C,QAAI,CAAC,KAAK,WAAY;AACtB,UAAM,EAAE,WAAW,MAAM,IAAI,MAAM,OAAO,aAAkB;AAC5D,UAAM,EAAE,QAAQ,IAAI,MAAM,OAAO,MAAW;AAC5C,UAAM,MAAM,QAAQ,KAAK,UAAU,GAAG,EAAE,WAAW,KAAK,CAAC;AACzD,UAAM,UAAU,KAAK,YAAY,KAAK,UAAU,KAAK,UAAU,MAAM,CAAC,GAAG,MAAM;AAAA,EACjF;AACF;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/mock-provider.ts","../src/mock-tool.ts","../src/mock-transcription-provider.ts","../src/test-runtime.ts"],"sourcesContent":["export { AxlTestRuntime } from './test-runtime.js';\nexport type { RecordedToolCall, RecordedAgentCall, RecordedStep } from './test-runtime.js';\nexport { MockProvider } from './mock-provider.js';\nexport { MockTranscriptionProvider } from './mock-transcription-provider.js';\nexport { MockTool } from './mock-tool.js';\n","import { readFileSync } from 'node:fs';\nimport { z } from 'zod';\nimport type {\n ChatMessage,\n ChatOptions,\n InputContentPart,\n InputMediaSource,\n ModelInput,\n ToolCallMessage,\n ProviderResponse,\n StreamChunk,\n Provider,\n ProviderInputValidationRequest,\n ProviderInputValidationResult,\n} from '@axlsdk/axl';\nimport { inputText, UnsupportedModelInputError } from '@axlsdk/axl';\n\nfunction cloneValue(value: unknown): unknown {\n if (value instanceof Uint8Array) return value.slice();\n if (Array.isArray(value)) return value.map(cloneValue);\n if (value && typeof value === 'object') {\n return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, cloneValue(item)]));\n }\n return value;\n}\n\nfunction cloneModelInput(input: ModelInput): ModelInput {\n if (typeof input === 'string') return input;\n return input.map((part): InputContentPart => {\n if (part.type === 'text') return { type: 'text', text: part.text };\n const { source } = part;\n switch (source.type) {\n case 'bytes':\n return {\n type: 'image',\n source: { type: 'bytes', data: source.data.slice(), mediaType: source.mediaType },\n ...(part.label ? { label: part.label } : {}),\n };\n case 'url':\n return {\n type: 'image',\n source: {\n type: 'url',\n url: source.url,\n ...(source.mediaType ? { mediaType: source.mediaType } : {}),\n },\n ...(part.label ? { label: part.label } : {}),\n };\n case 'base64':\n return {\n type: 'image',\n source: { type: 'base64', data: source.data, mediaType: source.mediaType },\n ...(part.label ? { label: part.label } : {}),\n };\n case 'provider-file':\n return {\n type: 'image',\n source: {\n type: 'provider-file',\n provider: source.provider,\n reference: source.reference,\n ...(source.mediaType ? { mediaType: source.mediaType } : {}),\n },\n ...(part.label ? { label: part.label } : {}),\n };\n }\n });\n}\n\nfunction cloneMessages(messages: readonly ChatMessage[]): ChatMessage[] {\n return messages.map((message) => ({\n ...message,\n content: cloneModelInput(message.content),\n ...(message.tool_calls\n ? {\n tool_calls: message.tool_calls.map((toolCall) => ({\n ...toolCall,\n function: { ...toolCall.function },\n })),\n }\n : {}),\n ...(message.providerMetadata\n ? { providerMetadata: cloneValue(message.providerMetadata) as Record<string, unknown> }\n : {}),\n }));\n}\n\nfunction cloneOptions(options: ChatOptions): ChatOptions {\n return {\n ...options,\n ...(options.tools\n ? {\n tools: options.tools.map((tool) => ({\n ...tool,\n function: { ...tool.function, parameters: cloneValue(tool.function.parameters) },\n })),\n }\n : {}),\n ...(options.providerOptions\n ? { providerOptions: cloneValue(options.providerOptions) as Record<string, unknown> }\n : {}),\n };\n}\n\nfunction richParts(input: ModelInput): readonly InputContentPart[] {\n return typeof input === 'string' ? [] : input;\n}\n\nfunction randomAlphanumeric(length: number): string {\n const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';\n let result = '';\n for (let i = 0; i < length; i++) {\n result += chars[Math.floor(Math.random() * chars.length)];\n }\n return result;\n}\n\nfunction generateFromSchema(schema: unknown): unknown {\n if (schema instanceof z.ZodString) return randomAlphanumeric(8 + Math.floor(Math.random() * 13));\n if (schema instanceof z.ZodNumber) {\n const min = Number.isFinite(schema.minValue) ? schema.minValue! : 0;\n const max = Number.isFinite(schema.maxValue) ? schema.maxValue! : 100;\n return min + Math.random() * (max - min);\n }\n if (schema instanceof z.ZodBoolean) return Math.random() < 0.5;\n if (schema instanceof z.ZodArray) {\n const count = 1 + Math.floor(Math.random() * 3);\n return Array.from({ length: count }, () => generateFromSchema(schema.element));\n }\n if (schema instanceof z.ZodObject) {\n const obj: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(schema.shape)) obj[key] = generateFromSchema(value);\n return obj;\n }\n if (schema instanceof z.ZodOptional) {\n if (Math.random() < 0.5) return undefined;\n return generateFromSchema(schema.unwrap());\n }\n if (schema instanceof z.ZodDefault) return schema.parse(undefined);\n if (schema instanceof z.ZodEnum) {\n const values = schema.options;\n return values.length > 0 ? values[Math.floor(Math.random() * values.length)] : '';\n }\n if (schema instanceof z.ZodLiteral) return [...schema.values][0];\n if (schema instanceof z.ZodNullable) return null;\n if (schema instanceof z.ZodUnion) {\n const options = schema.options;\n return generateFromSchema(options[Math.floor(Math.random() * options.length)]);\n }\n return {};\n}\n\nexport class MockProvider implements Provider {\n readonly name = 'mock';\n private _calls: { messages: ChatMessage[]; options: ChatOptions }[] = [];\n /** Per-call optional chunk arrays, set by `sequence()` / `chunked()` so\n * `stream()` can yield one `text_delta` per chunk. Per-call indexed\n * alongside the response sequence. */\n private chunkSequence?: Array<string[] | undefined>;\n /** Optional ms delay between successive chunks during `stream()`. Useful\n * for dev fixtures that need to demonstrate streaming UX visually\n * (without a delay, mock chunks fire synchronously and complete in\n * microseconds — invisible to a human watching). Default 0 keeps\n * every existing test fast.\n *\n * Set via `provider.chunkDelayMs = 50` after construction. Not part of\n * any factory's surface to keep the test API minimal. */\n chunkDelayMs = 0;\n\n private constructor(\n private responseFn: (\n messages: ChatMessage[],\n callIndex: number,\n ) => ProviderResponse | Promise<ProviderResponse>,\n ) {}\n\n get calls() {\n return this._calls;\n }\n\n async chat(messages: ChatMessage[], options: ChatOptions): Promise<ProviderResponse> {\n // Each consumer gets independent ownership: a handler can inspect or mutate\n // its copy without changing the durable assertion record (including bytes).\n const recordedMessages = cloneMessages(messages);\n this._calls.push({ messages: recordedMessages, options: cloneOptions(options) });\n return await this.responseFn(cloneMessages(messages), this._calls.length - 1);\n }\n\n inputCapabilities(_model: string): { image: { sources: readonly InputMediaSource['type'][] } } {\n return { image: { sources: ['url', 'bytes', 'base64', 'provider-file'] } };\n }\n\n validateInput(request: ProviderInputValidationRequest): ProviderInputValidationResult {\n const effectiveModel =\n typeof request.providerOptions?.model === 'string'\n ? request.providerOptions.model\n : request.model;\n const fail = (source?: string, feature?: string): never => {\n throw new UnsupportedModelInputError({\n provider: this.name,\n model: effectiveModel || request.model,\n modality: 'image',\n ...(source ? { source } : {}),\n ...(feature ? { feature } : {}),\n });\n };\n\n if (request.providerOptions && 'input' in request.providerOptions) {\n fail(undefined, 'raw input-container providerOptions');\n }\n for (const message of request.history) {\n if (typeof message.content === 'string') continue;\n if (message.role !== 'user') fail(undefined, 'rich non-user history');\n for (const part of richParts(message.content)) {\n if (\n part.type === 'image' &&\n part.source.type === 'provider-file' &&\n part.source.provider !== this.name\n ) {\n fail('provider-file');\n }\n }\n }\n for (const part of richParts(request.input)) {\n if (\n part.type === 'image' &&\n part.source.type === 'provider-file' &&\n part.source.provider !== this.name\n ) {\n fail('provider-file');\n }\n }\n return { effectiveModel };\n }\n\n async *stream(messages: ChatMessage[], options: ChatOptions): AsyncGenerator<StreamChunk> {\n const callIndex = this._calls.length;\n const response = await this.chat(messages, options);\n const chunks = this.chunkSequence?.[callIndex];\n if (chunks && chunks.length > 0) {\n // Sanity guard — if a caller passes chunks AND content, they MUST\n // match. Otherwise tests pass while the real prod content silently\n // diverges from what the streaming path observes.\n const joined = chunks.join('');\n if (joined !== response.content) {\n throw new Error(\n `MockProvider.stream: chunks.join('') !== content. ` +\n `chunks=\"${joined}\" content=\"${response.content}\"`,\n );\n }\n for (let i = 0; i < chunks.length; i++) {\n yield { type: 'text_delta', content: chunks[i] };\n if (this.chunkDelayMs > 0 && i < chunks.length - 1) {\n await new Promise((resolve) => setTimeout(resolve, this.chunkDelayMs));\n }\n }\n } else if (response.content) {\n yield { type: 'text_delta', content: response.content };\n }\n if (response.tool_calls) {\n for (const tc of response.tool_calls) {\n yield {\n type: 'tool_call_delta',\n id: tc.id,\n name: tc.function.name,\n arguments: tc.function.arguments,\n };\n }\n }\n yield { type: 'done', usage: response.usage, providerMetadata: response.providerMetadata };\n }\n\n static sequence(\n responses: Array<{\n content: string;\n tool_calls?: ToolCallMessage[];\n providerMetadata?: Record<string, unknown>;\n usage?: { prompt_tokens: number; completion_tokens: number; total_tokens: number };\n cost?: number;\n /** When set, `stream()` yields one `text_delta` per entry instead\n * of one big delta with the full content. Use to exercise\n * partial-JSON parsing, structural-boundary throttling, and\n * cross-attempt token retention in tests. Must satisfy\n * `chunks.join('') === content`. */\n chunks?: string[];\n }>,\n ): MockProvider {\n const provider = new MockProvider((_messages, callIndex) => {\n if (callIndex >= responses.length) {\n throw new Error(\n `MockProvider.sequence: no response for call index ${callIndex}. Only ${responses.length} responses defined.`,\n );\n }\n const resp = responses[callIndex];\n return {\n content: resp.content,\n tool_calls: resp.tool_calls,\n providerMetadata: resp.providerMetadata,\n usage: resp.usage ?? { prompt_tokens: 10, completion_tokens: 10, total_tokens: 20 },\n cost: resp.cost ?? 0,\n };\n });\n provider.chunkSequence = responses.map((r) => r.chunks);\n return provider;\n }\n\n /**\n * Convenience: build a `sequence()` from plain content strings, splitting\n * each one into fixed-size chunks for the streaming path. Default\n * `chunkSize` is 4 chars (≈1 token).\n */\n static chunked(contents: string[], chunkSize = 4): MockProvider {\n const responses = contents.map((content) => {\n const chunks: string[] = [];\n for (let i = 0; i < content.length; i += chunkSize) {\n chunks.push(content.slice(i, i + chunkSize));\n }\n return { content, chunks };\n });\n return MockProvider.sequence(responses);\n }\n\n static echo(): MockProvider {\n return new MockProvider((messages) => {\n const lastUser = [...messages].reverse().find((m) => m.role === 'user');\n return {\n content: lastUser ? inputText(lastUser.content) : '',\n usage: { prompt_tokens: 10, completion_tokens: 10, total_tokens: 20 },\n cost: 0,\n };\n });\n }\n\n static json(schema: unknown): MockProvider {\n return new MockProvider(() => ({\n content: JSON.stringify(generateFromSchema(schema)),\n usage: { prompt_tokens: 10, completion_tokens: 10, total_tokens: 20 },\n cost: 0,\n }));\n }\n\n static replay(source: string | ProviderResponse[]): MockProvider {\n const data =\n typeof source === 'string'\n ? (JSON.parse(readFileSync(source, 'utf-8')) as ProviderResponse[])\n : source;\n return new MockProvider((_messages, callIndex) => {\n if (callIndex >= data.length) {\n throw new Error(`MockProvider.replay: no recorded response for call index ${callIndex}`);\n }\n return data[callIndex];\n });\n }\n\n static fn(\n handler: (\n messages: ChatMessage[],\n callIndex: number,\n ) =>\n | {\n content: string;\n tool_calls?: ToolCallMessage[];\n providerMetadata?: Record<string, unknown>;\n usage?: { prompt_tokens: number; completion_tokens: number; total_tokens: number };\n cost?: number;\n }\n | Promise<{\n content: string;\n tool_calls?: ToolCallMessage[];\n providerMetadata?: Record<string, unknown>;\n usage?: { prompt_tokens: number; completion_tokens: number; total_tokens: number };\n cost?: number;\n }>,\n ): MockProvider {\n return new MockProvider(async (messages, callIndex) => {\n const result = await handler(messages, callIndex);\n return {\n ...result,\n usage: result.usage ?? { prompt_tokens: 10, completion_tokens: 10, total_tokens: 20 },\n cost: result.cost ?? 0,\n };\n });\n }\n}\n","export class MockTool {\n private _calls: { input: unknown }[] = [];\n\n constructor(\n readonly name: string,\n private handler: (input: unknown) => unknown | Promise<unknown>,\n ) {}\n\n get calls() {\n return this._calls;\n }\n\n async execute(input: unknown): Promise<unknown> {\n this._calls.push({ input });\n return this.handler(input);\n }\n\n static create(name: string, handler: (input: unknown) => unknown | Promise<unknown>): MockTool {\n return new MockTool(name, handler);\n }\n}\n","import type {\n TranscriptionCapabilities,\n TranscriptionProvider,\n TranscriptionProviderRequest,\n TranscriptionProviderResult,\n} from '@axlsdk/axl';\n\nfunction clone<T>(value: T): T {\n return structuredClone(value);\n}\n\nfunction cloneRequest(\n request: TranscriptionProviderRequest,\n includeSignal: boolean,\n): TranscriptionProviderRequest {\n const audio =\n request.audio.type === 'bytes'\n ? { ...request.audio, data: request.audio.data.slice() }\n : { ...request.audio };\n return {\n model: request.model,\n audio,\n ...(request.language !== undefined ? { language: request.language } : {}),\n ...(request.timestamps !== undefined ? { timestamps: request.timestamps } : {}),\n ...(request.diarization !== undefined ? { diarization: request.diarization } : {}),\n ...(request.providerOptions ? { providerOptions: clone(request.providerOptions) } : {}),\n ...(includeSignal && request.signal ? { signal: request.signal } : {}),\n };\n}\n\n/** Dedicated transcription mock. It intentionally does not extend MockProvider,\n * so chat fixtures cannot accidentally become transcription adapters. */\nexport class MockTranscriptionProvider implements TranscriptionProvider {\n private _calls: TranscriptionProviderRequest[] = [];\n\n constructor(\n private readonly response: (\n request: TranscriptionProviderRequest,\n callIndex: number,\n ) => TranscriptionProviderResult | Promise<TranscriptionProviderResult>,\n private readonly capabilitiesFor: (\n model: string,\n ) => TranscriptionCapabilities | undefined = () => ({\n sources: ['bytes', 'base64', 'provider-file'],\n timestamps: ['segment', 'word'],\n diarization: true,\n }),\n ) {}\n\n get calls(): readonly TranscriptionProviderRequest[] {\n return this._calls.map(clone);\n }\n\n capabilities(model: string): TranscriptionCapabilities | undefined {\n return this.capabilitiesFor(model);\n }\n\n async transcribe(request: TranscriptionProviderRequest): Promise<TranscriptionProviderResult> {\n // AbortSignal cannot be structured-cloned. Keep it only on the callback\n // request so fixtures can observe cancellation; recorded calls omit it.\n const snapshot = cloneRequest(request, false);\n this._calls.push(snapshot);\n return clone(await this.response(cloneRequest(request, true), this._calls.length - 1));\n }\n\n static text(text: string): MockTranscriptionProvider {\n return new MockTranscriptionProvider(() => ({ transcript: { text } }));\n }\n}\n","import { MockProvider } from './mock-provider.js';\nimport { MockTool } from './mock-tool.js';\nimport { MockTranscriptionProvider } from './mock-transcription-provider.js';\nimport type {\n AxlEvent,\n AwaitHumanOptions,\n HumanDecision,\n ProviderResponse,\n AgentCallInfo,\n AxlConfig,\n AnyWorkflow,\n ToolCallOutcome,\n ObservationStatus,\n} from '@axlsdk/axl';\nimport {\n WorkflowContext,\n MemoryStore,\n ProviderRegistry,\n TranscriptionProviderRegistry,\n eventCostContribution,\n isUnpricedLeaf,\n} from '@axlsdk/axl';\nimport type { EventStreamOptions, WorkflowContextInit } from '@axlsdk/axl';\n\n// `AnyWorkflow` is a re-exported alias for `Workflow<any, any>` — see\n// the JSDoc on `AnyWorkflow` in `@axlsdk/axl/workflow.ts`. The bivariant\n// `any` is load-bearing for satisfying narrowly-typed handlers (e.g., a\n// `Workflow<TInput=MsgType>` whose handler takes `WorkflowContext<MsgType>`).\n\n/** One accepted provider-issued tool invocation, recorded from its terminal v2 event.\n *\n * Narrow `outcome.status` before reading status-specific fields. Correlation uses\n * `(executionId, askId, callId)`; `name` is the canonical tool name.\n */\nexport type RecordedToolCall = {\n name: string;\n executionId: string;\n askId: string;\n callId: string;\n args: unknown;\n requestedTool?: string;\n outcome: ToolCallOutcome;\n};\nexport type RecordedAgentCall = Partial<AgentCallInfo> &\n Pick<AgentCallInfo, 'agent' | 'prompt' | 'response'>;\nexport type RecordedStep = { step: number; type: string; data: unknown };\n\nfunction generateExecutionId(): string {\n return `test-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nfunction preserveDrainCause(error: Error, cause: unknown): Error {\n if (cause === undefined || cause === error || 'cause' in error) return error;\n Object.defineProperty(error, 'cause', {\n configurable: true,\n enumerable: false,\n value: cause,\n });\n return error;\n}\n\nexport type AxlTestRuntimeOptions = {\n record?: string;\n humanDecisions?: (options: AwaitHumanOptions) => HumanDecision;\n /** AxlConfig for the test runtime. Controls trace level/redact, context management, etc.\n * Defaults to `{}`. Set `{ trace: { level: 'full' } }` to verify verbose-mode snapshots\n * in tests, or `{ trace: { redact: true } }` to verify redaction policy in tests. */\n config?: AxlConfig;\n};\n\nexport class AxlTestRuntime {\n private workflows = new Map<string, AnyWorkflow>();\n private mockProviders = new Map<string, MockProvider>();\n private mockTranscriptionProviders = new Map<string, MockTranscriptionProvider>();\n private mockToolMap = new Map<string, MockTool>();\n private _toolCalls: RecordedToolCall[] = [];\n private _agentCalls: RecordedAgentCall[] = [];\n private _steps: RecordedStep[] = [];\n private _traceLog: AxlEvent[] = [];\n private _totalCost = 0;\n private _unpriced = false;\n private _stepCounter = 0;\n private recordPath?: string;\n private recorded: ProviderResponse[] = [];\n private _executionId: string = generateExecutionId();\n private _humanDecisionHandler?: (options: AwaitHumanOptions) => HumanDecision;\n private _config: AxlConfig;\n\n constructor(options?: AxlTestRuntimeOptions) {\n this.recordPath = options?.record;\n this._humanDecisionHandler = options?.humanDecisions;\n this._config = options?.config ?? {};\n }\n\n register(workflow: AnyWorkflow): void {\n this.workflows.set(workflow.name, workflow);\n }\n\n mockProvider(name: string, provider: MockProvider): void {\n this.mockProviders.set(name, provider);\n }\n\n mockTranscriptionProvider(name: string, provider: MockTranscriptionProvider): void {\n this.mockTranscriptionProviders.set(name, provider);\n }\n\n mockTool<TInput = unknown>(\n name: string,\n handler: (input: TInput) => unknown | Promise<unknown>,\n ): void {\n // The MockTool registry is type-erased (`(input: unknown) => unknown`)\n // because the runtime can't statically know each tool's input shape; tests\n // opt in to a typed input via the generic, and we cast on storage.\n this.mockToolMap.set(name, MockTool.create(name, handler as (input: unknown) => unknown));\n }\n\n async execute(\n workflowName: string,\n input: unknown,\n options?: {\n metadata?: Record<string, unknown>;\n events?: EventStreamOptions;\n branchDrainTimeoutMs?: number;\n },\n ): Promise<unknown> {\n const workflow = this.workflows.get(workflowName);\n if (!workflow) throw new Error(`Workflow \"${workflowName}\" not registered`);\n\n // Reset state between executions\n this._toolCalls = [];\n this._agentCalls = [];\n this._steps = [];\n this._traceLog = [];\n this._totalCost = 0;\n this._unpriced = false;\n this._stepCounter = 0;\n this.recorded = [];\n this._executionId = generateExecutionId();\n\n const validated = workflow.inputSchema.parse(input);\n\n // Build ProviderRegistry from registered mock providers\n const registry = new ProviderRegistry();\n registry.clearFactories(); // Remove built-in factories; only use explicit mocks\n for (const [name, provider] of this.mockProviders) {\n registry.registerInstance(name, provider);\n }\n const transcriptionRegistry = new TranscriptionProviderRegistry();\n for (const [name, provider] of this.mockTranscriptionProviders) {\n transcriptionRegistry.registerInstance(name, provider);\n }\n // Fallback resolution: 'default' key or single-provider\n const defaultProvider = this.mockProviders.get('default');\n if (defaultProvider) {\n registry.setFallback(defaultProvider);\n } else if (this.mockProviders.size === 1) {\n const onlyProvider = this.mockProviders.values().next().value!;\n registry.setFallback(onlyProvider);\n }\n\n // Build toolOverrides from mockToolMap\n const toolOverrides = new Map<string, (args: unknown) => Promise<unknown>>();\n for (const [name, mockTool] of this.mockToolMap) {\n toolOverrides.set(name, async (args: unknown) => {\n return mockTool.execute(args);\n });\n }\n\n // Previously `_recordStep('workflow_start', ...)` was called here with\n // raw `{ workflow, input }` data, AND `ctx._emitWorkflowStart` below\n // pushed through the onTrace handler (which also bumps `_stepCounter`\n // and appends to `_steps`). Result: two entries in `steps()` per\n // workflow_start, with the first bypassing `config.trace.redact`.\n // The `_recordStep` call is removed — onTrace is the single source\n // of truth for `_steps`, matching the behavior of every other event\n // type in the test runtime. Reviewer architecture §5.\n\n const init: WorkflowContextInit = {\n input: validated,\n executionId: this._executionId,\n metadata: options?.metadata,\n // Thread the constructor-provided config so tests can exercise\n // trace.level === 'full' and trace.redact behavior end-to-end.\n config: this._config,\n // Thread `events` config so tests can exercise the queue cap and\n // overflow policy on `ctx.events`. Mirrors the production runtime.\n eventStreamOptions: options?.events,\n branchDrainTimeoutMs: options?.branchDrainTimeoutMs,\n // Production runtime threads this (see `runtime.ts:594` in\n // `execute()` and `:765` in `stream()`). `emitEvent` auto-stamps\n // `event.workflow` from it, so consumers grouping by workflow\n // (Cost Dashboard `byWorkflow`, `trackExecution.metadata.workflows`,\n // any eval runner) see the same attribution in tests and prod.\n workflowName,\n providerRegistry: registry,\n transcriptionProviderRegistry: transcriptionRegistry,\n stateStore: new MemoryStore(),\n toolOverrides: toolOverrides.size > 0 ? toolOverrides : undefined,\n awaitHumanHandler: this._humanDecisionHandler\n ? (opts: AwaitHumanOptions) => this._humanDecisionHandler!(opts)\n : undefined,\n onTrace: (event: AxlEvent) => {\n this._traceLog.push(event);\n this._stepCounter++;\n this._steps.push({\n step: this._stepCounter,\n type: event.type,\n data: (event as { data?: unknown }).data,\n });\n\n if (event.type === 'tool_call_end') {\n const { args, requestedTool, outcome } = event.data;\n this._toolCalls.push({\n name: event.tool,\n executionId: event.executionId,\n askId: event.askId,\n callId: event.callId,\n args,\n ...(requestedTool !== undefined ? { requestedTool } : {}),\n outcome,\n });\n }\n\n // Single-source-of-truth cost accumulator. Skips ask_end\n // rollups (decision 10) and guards NaN/Infinity.\n this._totalCost += eventCostContribution(event);\n // Honest aggregate: one unpriced leaf makes `totalCost()` a lower bound.\n if (isUnpricedLeaf(event)) this._unpriced = true;\n\n // Track provider responses for recording\n if (event.type === 'agent_call_end' && event.data) {\n const { response } = event.data as { prompt?: string; response?: string };\n if (response !== undefined) {\n this.recorded.push({\n content: response,\n usage: event.tokens\n ? {\n prompt_tokens: event.tokens.input ?? 0,\n completion_tokens: event.tokens.output ?? 0,\n total_tokens:\n (event.tokens.input ?? 0) +\n (event.tokens.output ?? 0) +\n (event.tokens.reasoning ?? 0),\n ...(event.tokens.reasoning !== undefined\n ? { reasoning_tokens: event.tokens.reasoning }\n : {}),\n }\n : { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 },\n ...(event.cost !== undefined ? { cost: event.cost } : {}),\n });\n }\n }\n },\n onAgentCallComplete: (call: AgentCallInfo) => {\n this._agentCalls.push(call);\n },\n };\n\n const ctx = new WorkflowContext(init);\n\n // Emit workflow_start through the same pipeline production uses,\n // AFTER ctx exists so `emitEvent`'s redact/step/timestamp handling\n // applies. Previously emitted via `_pushTrace` which bypassed\n // redaction — `config: { trace: { redact: true } }` on the test\n // runtime would scrub intermediate events but leak `input`/`result`\n // through the synthesized workflow_start/end.\n const startedAt = Date.now();\n ctx._emitWorkflowStart(validated);\n try {\n const result = await workflow.handler(ctx);\n const observation = await ctx._drainBranchWork();\n\n // Validate output schema if defined\n if (workflow.outputSchema) workflow.outputSchema.parse(result);\n\n ctx._emitWorkflowEnd({\n status: 'completed',\n duration: Date.now() - startedAt,\n result,\n observation,\n });\n // `_steps` is populated by onTrace for every event (including\n // workflow_end); no separate `_recordStep` call needed — that\n // would double-count.\n\n if (this.recordPath) await this._writeRecording();\n return result;\n } catch (err) {\n let workflowError = err;\n let observation: ObservationStatus = { complete: true };\n try {\n observation = await ctx._drainBranchWork();\n } catch (drainError) {\n workflowError =\n drainError instanceof Error ? preserveDrainCause(drainError, workflowError) : drainError;\n }\n // Parity with production: failed workflows get a terminal\n // `workflow_end(status: 'failed')` event so consumers counting\n // workflow_start ↔ workflow_end pairs never see an unclosed one.\n // `aborted` flag mirrors the runtime.ts AbortError detection.\n const aborted =\n typeof workflowError === 'object' &&\n workflowError !== null &&\n (workflowError as { name?: unknown }).name === 'AbortError';\n ctx._emitWorkflowEnd({\n status: 'failed',\n duration: Date.now() - startedAt,\n error: workflowError instanceof Error ? workflowError.message : String(workflowError),\n ...(aborted ? { aborted: true } : {}),\n observation,\n });\n // `_steps` populated by onTrace (see comment on the success path).\n throw workflowError;\n }\n }\n\n toolCalls(name?: string): RecordedToolCall[] {\n return name ? this._toolCalls.filter((c) => c.name === name) : this._toolCalls;\n }\n\n agentCalls(name?: string): RecordedAgentCall[] {\n return name ? this._agentCalls.filter((c) => c.agent === name) : this._agentCalls;\n }\n\n totalCost(): number {\n return this._totalCost;\n }\n /** True when any cost-bearing call was unpriced — `totalCost()` is then a\n * LOWER BOUND. Mirrors `ExecutionInfo.unpriced` / `BudgetResult.unpriced`. */\n unpriced(): boolean {\n return this._unpriced;\n }\n steps(): RecordedStep[] {\n return this._steps;\n }\n traceLog(): AxlEvent[] {\n return this._traceLog;\n }\n\n private async _writeRecording(): Promise<void> {\n if (!this.recordPath) return;\n const { writeFile, mkdir } = await import('node:fs/promises');\n const { dirname } = await import('node:path');\n await mkdir(dirname(this.recordPath), { recursive: true });\n await writeFile(this.recordPath, JSON.stringify(this.recorded, null, 2), 'utf8');\n }\n}\n"],"mappings":"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","names":["import_axl"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Provider, ChatMessage, ChatOptions, ProviderResponse, StreamChunk, ToolCallMessage, AwaitHumanOptions, HumanDecision, AxlConfig, AnyWorkflow, EventStreamOptions, ToolCallOutcome, AgentCallInfo, AxlEvent } from '@axlsdk/axl';
|
|
1
|
+
import { Provider, ChatMessage, ChatOptions, ProviderResponse, InputMediaSource, ProviderInputValidationRequest, ProviderInputValidationResult, StreamChunk, ToolCallMessage, TranscriptionProvider, TranscriptionProviderRequest, TranscriptionProviderResult, TranscriptionCapabilities, AwaitHumanOptions, HumanDecision, AxlConfig, AnyWorkflow, EventStreamOptions, ToolCallOutcome, AgentCallInfo, AxlEvent } from '@axlsdk/axl';
|
|
2
2
|
|
|
3
3
|
declare class MockProvider implements Provider {
|
|
4
4
|
private responseFn;
|
|
@@ -23,6 +23,12 @@ declare class MockProvider implements Provider {
|
|
|
23
23
|
options: ChatOptions;
|
|
24
24
|
}[];
|
|
25
25
|
chat(messages: ChatMessage[], options: ChatOptions): Promise<ProviderResponse>;
|
|
26
|
+
inputCapabilities(_model: string): {
|
|
27
|
+
image: {
|
|
28
|
+
sources: readonly InputMediaSource['type'][];
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
validateInput(request: ProviderInputValidationRequest): ProviderInputValidationResult;
|
|
26
32
|
stream(messages: ChatMessage[], options: ChatOptions): AsyncGenerator<StreamChunk>;
|
|
27
33
|
static sequence(responses: Array<{
|
|
28
34
|
content: string;
|
|
@@ -73,6 +79,19 @@ declare class MockProvider implements Provider {
|
|
|
73
79
|
}>): MockProvider;
|
|
74
80
|
}
|
|
75
81
|
|
|
82
|
+
/** Dedicated transcription mock. It intentionally does not extend MockProvider,
|
|
83
|
+
* so chat fixtures cannot accidentally become transcription adapters. */
|
|
84
|
+
declare class MockTranscriptionProvider implements TranscriptionProvider {
|
|
85
|
+
private readonly response;
|
|
86
|
+
private readonly capabilitiesFor;
|
|
87
|
+
private _calls;
|
|
88
|
+
constructor(response: (request: TranscriptionProviderRequest, callIndex: number) => TranscriptionProviderResult | Promise<TranscriptionProviderResult>, capabilitiesFor?: (model: string) => TranscriptionCapabilities | undefined);
|
|
89
|
+
get calls(): readonly TranscriptionProviderRequest[];
|
|
90
|
+
capabilities(model: string): TranscriptionCapabilities | undefined;
|
|
91
|
+
transcribe(request: TranscriptionProviderRequest): Promise<TranscriptionProviderResult>;
|
|
92
|
+
static text(text: string): MockTranscriptionProvider;
|
|
93
|
+
}
|
|
94
|
+
|
|
76
95
|
/** One accepted provider-issued tool invocation, recorded from its terminal v2 event.
|
|
77
96
|
*
|
|
78
97
|
* Narrow `outcome.status` before reading status-specific fields. Correlation uses
|
|
@@ -104,6 +123,7 @@ type AxlTestRuntimeOptions = {
|
|
|
104
123
|
declare class AxlTestRuntime {
|
|
105
124
|
private workflows;
|
|
106
125
|
private mockProviders;
|
|
126
|
+
private mockTranscriptionProviders;
|
|
107
127
|
private mockToolMap;
|
|
108
128
|
private _toolCalls;
|
|
109
129
|
private _agentCalls;
|
|
@@ -120,6 +140,7 @@ declare class AxlTestRuntime {
|
|
|
120
140
|
constructor(options?: AxlTestRuntimeOptions);
|
|
121
141
|
register(workflow: AnyWorkflow): void;
|
|
122
142
|
mockProvider(name: string, provider: MockProvider): void;
|
|
143
|
+
mockTranscriptionProvider(name: string, provider: MockTranscriptionProvider): void;
|
|
123
144
|
mockTool<TInput = unknown>(name: string, handler: (input: TInput) => unknown | Promise<unknown>): void;
|
|
124
145
|
execute(workflowName: string, input: unknown, options?: {
|
|
125
146
|
metadata?: Record<string, unknown>;
|
|
@@ -149,4 +170,4 @@ declare class MockTool {
|
|
|
149
170
|
static create(name: string, handler: (input: unknown) => unknown | Promise<unknown>): MockTool;
|
|
150
171
|
}
|
|
151
172
|
|
|
152
|
-
export { AxlTestRuntime, MockProvider, MockTool, type RecordedAgentCall, type RecordedStep, type RecordedToolCall };
|
|
173
|
+
export { AxlTestRuntime, MockProvider, MockTool, MockTranscriptionProvider, type RecordedAgentCall, type RecordedStep, type RecordedToolCall };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Provider, ChatMessage, ChatOptions, ProviderResponse, StreamChunk, ToolCallMessage, AwaitHumanOptions, HumanDecision, AxlConfig, AnyWorkflow, EventStreamOptions, ToolCallOutcome, AgentCallInfo, AxlEvent } from '@axlsdk/axl';
|
|
1
|
+
import { Provider, ChatMessage, ChatOptions, ProviderResponse, InputMediaSource, ProviderInputValidationRequest, ProviderInputValidationResult, StreamChunk, ToolCallMessage, TranscriptionProvider, TranscriptionProviderRequest, TranscriptionProviderResult, TranscriptionCapabilities, AwaitHumanOptions, HumanDecision, AxlConfig, AnyWorkflow, EventStreamOptions, ToolCallOutcome, AgentCallInfo, AxlEvent } from '@axlsdk/axl';
|
|
2
2
|
|
|
3
3
|
declare class MockProvider implements Provider {
|
|
4
4
|
private responseFn;
|
|
@@ -23,6 +23,12 @@ declare class MockProvider implements Provider {
|
|
|
23
23
|
options: ChatOptions;
|
|
24
24
|
}[];
|
|
25
25
|
chat(messages: ChatMessage[], options: ChatOptions): Promise<ProviderResponse>;
|
|
26
|
+
inputCapabilities(_model: string): {
|
|
27
|
+
image: {
|
|
28
|
+
sources: readonly InputMediaSource['type'][];
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
validateInput(request: ProviderInputValidationRequest): ProviderInputValidationResult;
|
|
26
32
|
stream(messages: ChatMessage[], options: ChatOptions): AsyncGenerator<StreamChunk>;
|
|
27
33
|
static sequence(responses: Array<{
|
|
28
34
|
content: string;
|
|
@@ -73,6 +79,19 @@ declare class MockProvider implements Provider {
|
|
|
73
79
|
}>): MockProvider;
|
|
74
80
|
}
|
|
75
81
|
|
|
82
|
+
/** Dedicated transcription mock. It intentionally does not extend MockProvider,
|
|
83
|
+
* so chat fixtures cannot accidentally become transcription adapters. */
|
|
84
|
+
declare class MockTranscriptionProvider implements TranscriptionProvider {
|
|
85
|
+
private readonly response;
|
|
86
|
+
private readonly capabilitiesFor;
|
|
87
|
+
private _calls;
|
|
88
|
+
constructor(response: (request: TranscriptionProviderRequest, callIndex: number) => TranscriptionProviderResult | Promise<TranscriptionProviderResult>, capabilitiesFor?: (model: string) => TranscriptionCapabilities | undefined);
|
|
89
|
+
get calls(): readonly TranscriptionProviderRequest[];
|
|
90
|
+
capabilities(model: string): TranscriptionCapabilities | undefined;
|
|
91
|
+
transcribe(request: TranscriptionProviderRequest): Promise<TranscriptionProviderResult>;
|
|
92
|
+
static text(text: string): MockTranscriptionProvider;
|
|
93
|
+
}
|
|
94
|
+
|
|
76
95
|
/** One accepted provider-issued tool invocation, recorded from its terminal v2 event.
|
|
77
96
|
*
|
|
78
97
|
* Narrow `outcome.status` before reading status-specific fields. Correlation uses
|
|
@@ -104,6 +123,7 @@ type AxlTestRuntimeOptions = {
|
|
|
104
123
|
declare class AxlTestRuntime {
|
|
105
124
|
private workflows;
|
|
106
125
|
private mockProviders;
|
|
126
|
+
private mockTranscriptionProviders;
|
|
107
127
|
private mockToolMap;
|
|
108
128
|
private _toolCalls;
|
|
109
129
|
private _agentCalls;
|
|
@@ -120,6 +140,7 @@ declare class AxlTestRuntime {
|
|
|
120
140
|
constructor(options?: AxlTestRuntimeOptions);
|
|
121
141
|
register(workflow: AnyWorkflow): void;
|
|
122
142
|
mockProvider(name: string, provider: MockProvider): void;
|
|
143
|
+
mockTranscriptionProvider(name: string, provider: MockTranscriptionProvider): void;
|
|
123
144
|
mockTool<TInput = unknown>(name: string, handler: (input: TInput) => unknown | Promise<unknown>): void;
|
|
124
145
|
execute(workflowName: string, input: unknown, options?: {
|
|
125
146
|
metadata?: Record<string, unknown>;
|
|
@@ -149,4 +170,4 @@ declare class MockTool {
|
|
|
149
170
|
static create(name: string, handler: (input: unknown) => unknown | Promise<unknown>): MockTool;
|
|
150
171
|
}
|
|
151
172
|
|
|
152
|
-
export { AxlTestRuntime, MockProvider, MockTool, type RecordedAgentCall, type RecordedStep, type RecordedToolCall };
|
|
173
|
+
export { AxlTestRuntime, MockProvider, MockTool, MockTranscriptionProvider, type RecordedAgentCall, type RecordedStep, type RecordedToolCall };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,85 @@
|
|
|
1
1
|
// src/mock-provider.ts
|
|
2
2
|
import { readFileSync } from "fs";
|
|
3
3
|
import { z } from "zod";
|
|
4
|
+
import { inputText, UnsupportedModelInputError } from "@axlsdk/axl";
|
|
5
|
+
function cloneValue(value) {
|
|
6
|
+
if (value instanceof Uint8Array) return value.slice();
|
|
7
|
+
if (Array.isArray(value)) return value.map(cloneValue);
|
|
8
|
+
if (value && typeof value === "object") {
|
|
9
|
+
return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, cloneValue(item)]));
|
|
10
|
+
}
|
|
11
|
+
return value;
|
|
12
|
+
}
|
|
13
|
+
function cloneModelInput(input) {
|
|
14
|
+
if (typeof input === "string") return input;
|
|
15
|
+
return input.map((part) => {
|
|
16
|
+
if (part.type === "text") return { type: "text", text: part.text };
|
|
17
|
+
const { source } = part;
|
|
18
|
+
switch (source.type) {
|
|
19
|
+
case "bytes":
|
|
20
|
+
return {
|
|
21
|
+
type: "image",
|
|
22
|
+
source: { type: "bytes", data: source.data.slice(), mediaType: source.mediaType },
|
|
23
|
+
...part.label ? { label: part.label } : {}
|
|
24
|
+
};
|
|
25
|
+
case "url":
|
|
26
|
+
return {
|
|
27
|
+
type: "image",
|
|
28
|
+
source: {
|
|
29
|
+
type: "url",
|
|
30
|
+
url: source.url,
|
|
31
|
+
...source.mediaType ? { mediaType: source.mediaType } : {}
|
|
32
|
+
},
|
|
33
|
+
...part.label ? { label: part.label } : {}
|
|
34
|
+
};
|
|
35
|
+
case "base64":
|
|
36
|
+
return {
|
|
37
|
+
type: "image",
|
|
38
|
+
source: { type: "base64", data: source.data, mediaType: source.mediaType },
|
|
39
|
+
...part.label ? { label: part.label } : {}
|
|
40
|
+
};
|
|
41
|
+
case "provider-file":
|
|
42
|
+
return {
|
|
43
|
+
type: "image",
|
|
44
|
+
source: {
|
|
45
|
+
type: "provider-file",
|
|
46
|
+
provider: source.provider,
|
|
47
|
+
reference: source.reference,
|
|
48
|
+
...source.mediaType ? { mediaType: source.mediaType } : {}
|
|
49
|
+
},
|
|
50
|
+
...part.label ? { label: part.label } : {}
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
function cloneMessages(messages) {
|
|
56
|
+
return messages.map((message) => ({
|
|
57
|
+
...message,
|
|
58
|
+
content: cloneModelInput(message.content),
|
|
59
|
+
...message.tool_calls ? {
|
|
60
|
+
tool_calls: message.tool_calls.map((toolCall) => ({
|
|
61
|
+
...toolCall,
|
|
62
|
+
function: { ...toolCall.function }
|
|
63
|
+
}))
|
|
64
|
+
} : {},
|
|
65
|
+
...message.providerMetadata ? { providerMetadata: cloneValue(message.providerMetadata) } : {}
|
|
66
|
+
}));
|
|
67
|
+
}
|
|
68
|
+
function cloneOptions(options) {
|
|
69
|
+
return {
|
|
70
|
+
...options,
|
|
71
|
+
...options.tools ? {
|
|
72
|
+
tools: options.tools.map((tool) => ({
|
|
73
|
+
...tool,
|
|
74
|
+
function: { ...tool.function, parameters: cloneValue(tool.function.parameters) }
|
|
75
|
+
}))
|
|
76
|
+
} : {},
|
|
77
|
+
...options.providerOptions ? { providerOptions: cloneValue(options.providerOptions) } : {}
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
function richParts(input) {
|
|
81
|
+
return typeof input === "string" ? [] : input;
|
|
82
|
+
}
|
|
4
83
|
function randomAlphanumeric(length) {
|
|
5
84
|
const chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
|
6
85
|
let result = "";
|
|
@@ -66,8 +145,42 @@ var MockProvider = class _MockProvider {
|
|
|
66
145
|
return this._calls;
|
|
67
146
|
}
|
|
68
147
|
async chat(messages, options) {
|
|
69
|
-
|
|
70
|
-
|
|
148
|
+
const recordedMessages = cloneMessages(messages);
|
|
149
|
+
this._calls.push({ messages: recordedMessages, options: cloneOptions(options) });
|
|
150
|
+
return await this.responseFn(cloneMessages(messages), this._calls.length - 1);
|
|
151
|
+
}
|
|
152
|
+
inputCapabilities(_model) {
|
|
153
|
+
return { image: { sources: ["url", "bytes", "base64", "provider-file"] } };
|
|
154
|
+
}
|
|
155
|
+
validateInput(request) {
|
|
156
|
+
const effectiveModel = typeof request.providerOptions?.model === "string" ? request.providerOptions.model : request.model;
|
|
157
|
+
const fail = (source, feature) => {
|
|
158
|
+
throw new UnsupportedModelInputError({
|
|
159
|
+
provider: this.name,
|
|
160
|
+
model: effectiveModel || request.model,
|
|
161
|
+
modality: "image",
|
|
162
|
+
...source ? { source } : {},
|
|
163
|
+
...feature ? { feature } : {}
|
|
164
|
+
});
|
|
165
|
+
};
|
|
166
|
+
if (request.providerOptions && "input" in request.providerOptions) {
|
|
167
|
+
fail(void 0, "raw input-container providerOptions");
|
|
168
|
+
}
|
|
169
|
+
for (const message of request.history) {
|
|
170
|
+
if (typeof message.content === "string") continue;
|
|
171
|
+
if (message.role !== "user") fail(void 0, "rich non-user history");
|
|
172
|
+
for (const part of richParts(message.content)) {
|
|
173
|
+
if (part.type === "image" && part.source.type === "provider-file" && part.source.provider !== this.name) {
|
|
174
|
+
fail("provider-file");
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
for (const part of richParts(request.input)) {
|
|
179
|
+
if (part.type === "image" && part.source.type === "provider-file" && part.source.provider !== this.name) {
|
|
180
|
+
fail("provider-file");
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return { effectiveModel };
|
|
71
184
|
}
|
|
72
185
|
async *stream(messages, options) {
|
|
73
186
|
const callIndex = this._calls.length;
|
|
@@ -139,7 +252,7 @@ var MockProvider = class _MockProvider {
|
|
|
139
252
|
return new _MockProvider((messages) => {
|
|
140
253
|
const lastUser = [...messages].reverse().find((m) => m.role === "user");
|
|
141
254
|
return {
|
|
142
|
-
content: lastUser
|
|
255
|
+
content: lastUser ? inputText(lastUser.content) : "",
|
|
143
256
|
usage: { prompt_tokens: 10, completion_tokens: 10, total_tokens: 20 },
|
|
144
257
|
cost: 0
|
|
145
258
|
};
|
|
@@ -192,11 +305,54 @@ var MockTool = class _MockTool {
|
|
|
192
305
|
}
|
|
193
306
|
};
|
|
194
307
|
|
|
308
|
+
// src/mock-transcription-provider.ts
|
|
309
|
+
function clone(value) {
|
|
310
|
+
return structuredClone(value);
|
|
311
|
+
}
|
|
312
|
+
function cloneRequest(request, includeSignal) {
|
|
313
|
+
const audio = request.audio.type === "bytes" ? { ...request.audio, data: request.audio.data.slice() } : { ...request.audio };
|
|
314
|
+
return {
|
|
315
|
+
model: request.model,
|
|
316
|
+
audio,
|
|
317
|
+
...request.language !== void 0 ? { language: request.language } : {},
|
|
318
|
+
...request.timestamps !== void 0 ? { timestamps: request.timestamps } : {},
|
|
319
|
+
...request.diarization !== void 0 ? { diarization: request.diarization } : {},
|
|
320
|
+
...request.providerOptions ? { providerOptions: clone(request.providerOptions) } : {},
|
|
321
|
+
...includeSignal && request.signal ? { signal: request.signal } : {}
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
var MockTranscriptionProvider = class _MockTranscriptionProvider {
|
|
325
|
+
constructor(response, capabilitiesFor = () => ({
|
|
326
|
+
sources: ["bytes", "base64", "provider-file"],
|
|
327
|
+
timestamps: ["segment", "word"],
|
|
328
|
+
diarization: true
|
|
329
|
+
})) {
|
|
330
|
+
this.response = response;
|
|
331
|
+
this.capabilitiesFor = capabilitiesFor;
|
|
332
|
+
}
|
|
333
|
+
_calls = [];
|
|
334
|
+
get calls() {
|
|
335
|
+
return this._calls.map(clone);
|
|
336
|
+
}
|
|
337
|
+
capabilities(model) {
|
|
338
|
+
return this.capabilitiesFor(model);
|
|
339
|
+
}
|
|
340
|
+
async transcribe(request) {
|
|
341
|
+
const snapshot = cloneRequest(request, false);
|
|
342
|
+
this._calls.push(snapshot);
|
|
343
|
+
return clone(await this.response(cloneRequest(request, true), this._calls.length - 1));
|
|
344
|
+
}
|
|
345
|
+
static text(text) {
|
|
346
|
+
return new _MockTranscriptionProvider(() => ({ transcript: { text } }));
|
|
347
|
+
}
|
|
348
|
+
};
|
|
349
|
+
|
|
195
350
|
// src/test-runtime.ts
|
|
196
351
|
import {
|
|
197
352
|
WorkflowContext,
|
|
198
353
|
MemoryStore,
|
|
199
354
|
ProviderRegistry,
|
|
355
|
+
TranscriptionProviderRegistry,
|
|
200
356
|
eventCostContribution,
|
|
201
357
|
isUnpricedLeaf
|
|
202
358
|
} from "@axlsdk/axl";
|
|
@@ -215,6 +371,7 @@ function preserveDrainCause(error, cause) {
|
|
|
215
371
|
var AxlTestRuntime = class {
|
|
216
372
|
workflows = /* @__PURE__ */ new Map();
|
|
217
373
|
mockProviders = /* @__PURE__ */ new Map();
|
|
374
|
+
mockTranscriptionProviders = /* @__PURE__ */ new Map();
|
|
218
375
|
mockToolMap = /* @__PURE__ */ new Map();
|
|
219
376
|
_toolCalls = [];
|
|
220
377
|
_agentCalls = [];
|
|
@@ -239,6 +396,9 @@ var AxlTestRuntime = class {
|
|
|
239
396
|
mockProvider(name, provider) {
|
|
240
397
|
this.mockProviders.set(name, provider);
|
|
241
398
|
}
|
|
399
|
+
mockTranscriptionProvider(name, provider) {
|
|
400
|
+
this.mockTranscriptionProviders.set(name, provider);
|
|
401
|
+
}
|
|
242
402
|
mockTool(name, handler) {
|
|
243
403
|
this.mockToolMap.set(name, MockTool.create(name, handler));
|
|
244
404
|
}
|
|
@@ -260,6 +420,10 @@ var AxlTestRuntime = class {
|
|
|
260
420
|
for (const [name, provider] of this.mockProviders) {
|
|
261
421
|
registry.registerInstance(name, provider);
|
|
262
422
|
}
|
|
423
|
+
const transcriptionRegistry = new TranscriptionProviderRegistry();
|
|
424
|
+
for (const [name, provider] of this.mockTranscriptionProviders) {
|
|
425
|
+
transcriptionRegistry.registerInstance(name, provider);
|
|
426
|
+
}
|
|
263
427
|
const defaultProvider = this.mockProviders.get("default");
|
|
264
428
|
if (defaultProvider) {
|
|
265
429
|
registry.setFallback(defaultProvider);
|
|
@@ -291,6 +455,7 @@ var AxlTestRuntime = class {
|
|
|
291
455
|
// any eval runner) see the same attribution in tests and prod.
|
|
292
456
|
workflowName,
|
|
293
457
|
providerRegistry: registry,
|
|
458
|
+
transcriptionProviderRegistry: transcriptionRegistry,
|
|
294
459
|
stateStore: new MemoryStore(),
|
|
295
460
|
toolOverrides: toolOverrides.size > 0 ? toolOverrides : void 0,
|
|
296
461
|
awaitHumanHandler: this._humanDecisionHandler ? (opts) => this._humanDecisionHandler(opts) : void 0,
|
|
@@ -401,6 +566,7 @@ var AxlTestRuntime = class {
|
|
|
401
566
|
export {
|
|
402
567
|
AxlTestRuntime,
|
|
403
568
|
MockProvider,
|
|
404
|
-
MockTool
|
|
569
|
+
MockTool,
|
|
570
|
+
MockTranscriptionProvider
|
|
405
571
|
};
|
|
406
572
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/mock-provider.ts","../src/mock-tool.ts","../src/test-runtime.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\nimport { z } from 'zod';\nimport type {\n ChatMessage,\n ChatOptions,\n ToolCallMessage,\n ProviderResponse,\n StreamChunk,\n Provider,\n} from '@axlsdk/axl';\n\nfunction randomAlphanumeric(length: number): string {\n const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';\n let result = '';\n for (let i = 0; i < length; i++) {\n result += chars[Math.floor(Math.random() * chars.length)];\n }\n return result;\n}\n\nfunction generateFromSchema(schema: unknown): unknown {\n if (schema instanceof z.ZodString) return randomAlphanumeric(8 + Math.floor(Math.random() * 13));\n if (schema instanceof z.ZodNumber) {\n const min = Number.isFinite(schema.minValue) ? schema.minValue! : 0;\n const max = Number.isFinite(schema.maxValue) ? schema.maxValue! : 100;\n return min + Math.random() * (max - min);\n }\n if (schema instanceof z.ZodBoolean) return Math.random() < 0.5;\n if (schema instanceof z.ZodArray) {\n const count = 1 + Math.floor(Math.random() * 3);\n return Array.from({ length: count }, () => generateFromSchema(schema.element));\n }\n if (schema instanceof z.ZodObject) {\n const obj: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(schema.shape)) obj[key] = generateFromSchema(value);\n return obj;\n }\n if (schema instanceof z.ZodOptional) {\n if (Math.random() < 0.5) return undefined;\n return generateFromSchema(schema.unwrap());\n }\n if (schema instanceof z.ZodDefault) return schema.parse(undefined);\n if (schema instanceof z.ZodEnum) {\n const values = schema.options;\n return values.length > 0 ? values[Math.floor(Math.random() * values.length)] : '';\n }\n if (schema instanceof z.ZodLiteral) return [...schema.values][0];\n if (schema instanceof z.ZodNullable) return null;\n if (schema instanceof z.ZodUnion) {\n const options = schema.options;\n return generateFromSchema(options[Math.floor(Math.random() * options.length)]);\n }\n return {};\n}\n\nexport class MockProvider implements Provider {\n readonly name = 'mock';\n private _calls: { messages: ChatMessage[]; options: ChatOptions }[] = [];\n /** Per-call optional chunk arrays, set by `sequence()` / `chunked()` so\n * `stream()` can yield one `text_delta` per chunk. Per-call indexed\n * alongside the response sequence. */\n private chunkSequence?: Array<string[] | undefined>;\n /** Optional ms delay between successive chunks during `stream()`. Useful\n * for dev fixtures that need to demonstrate streaming UX visually\n * (without a delay, mock chunks fire synchronously and complete in\n * microseconds — invisible to a human watching). Default 0 keeps\n * every existing test fast.\n *\n * Set via `provider.chunkDelayMs = 50` after construction. Not part of\n * any factory's surface to keep the test API minimal. */\n chunkDelayMs = 0;\n\n private constructor(\n private responseFn: (\n messages: ChatMessage[],\n callIndex: number,\n ) => ProviderResponse | Promise<ProviderResponse>,\n ) {}\n\n get calls() {\n return this._calls;\n }\n\n async chat(messages: ChatMessage[], options: ChatOptions): Promise<ProviderResponse> {\n this._calls.push({ messages, options });\n return await this.responseFn(messages, this._calls.length - 1);\n }\n\n async *stream(messages: ChatMessage[], options: ChatOptions): AsyncGenerator<StreamChunk> {\n const callIndex = this._calls.length;\n const response = await this.chat(messages, options);\n const chunks = this.chunkSequence?.[callIndex];\n if (chunks && chunks.length > 0) {\n // Sanity guard — if a caller passes chunks AND content, they MUST\n // match. Otherwise tests pass while the real prod content silently\n // diverges from what the streaming path observes.\n const joined = chunks.join('');\n if (joined !== response.content) {\n throw new Error(\n `MockProvider.stream: chunks.join('') !== content. ` +\n `chunks=\"${joined}\" content=\"${response.content}\"`,\n );\n }\n for (let i = 0; i < chunks.length; i++) {\n yield { type: 'text_delta', content: chunks[i] };\n if (this.chunkDelayMs > 0 && i < chunks.length - 1) {\n await new Promise((resolve) => setTimeout(resolve, this.chunkDelayMs));\n }\n }\n } else if (response.content) {\n yield { type: 'text_delta', content: response.content };\n }\n if (response.tool_calls) {\n for (const tc of response.tool_calls) {\n yield {\n type: 'tool_call_delta',\n id: tc.id,\n name: tc.function.name,\n arguments: tc.function.arguments,\n };\n }\n }\n yield { type: 'done', usage: response.usage, providerMetadata: response.providerMetadata };\n }\n\n static sequence(\n responses: Array<{\n content: string;\n tool_calls?: ToolCallMessage[];\n providerMetadata?: Record<string, unknown>;\n usage?: { prompt_tokens: number; completion_tokens: number; total_tokens: number };\n cost?: number;\n /** When set, `stream()` yields one `text_delta` per entry instead\n * of one big delta with the full content. Use to exercise\n * partial-JSON parsing, structural-boundary throttling, and\n * cross-attempt token retention in tests. Must satisfy\n * `chunks.join('') === content`. */\n chunks?: string[];\n }>,\n ): MockProvider {\n const provider = new MockProvider((_messages, callIndex) => {\n if (callIndex >= responses.length) {\n throw new Error(\n `MockProvider.sequence: no response for call index ${callIndex}. Only ${responses.length} responses defined.`,\n );\n }\n const resp = responses[callIndex];\n return {\n content: resp.content,\n tool_calls: resp.tool_calls,\n providerMetadata: resp.providerMetadata,\n usage: resp.usage ?? { prompt_tokens: 10, completion_tokens: 10, total_tokens: 20 },\n cost: resp.cost ?? 0,\n };\n });\n provider.chunkSequence = responses.map((r) => r.chunks);\n return provider;\n }\n\n /**\n * Convenience: build a `sequence()` from plain content strings, splitting\n * each one into fixed-size chunks for the streaming path. Default\n * `chunkSize` is 4 chars (≈1 token).\n */\n static chunked(contents: string[], chunkSize = 4): MockProvider {\n const responses = contents.map((content) => {\n const chunks: string[] = [];\n for (let i = 0; i < content.length; i += chunkSize) {\n chunks.push(content.slice(i, i + chunkSize));\n }\n return { content, chunks };\n });\n return MockProvider.sequence(responses);\n }\n\n static echo(): MockProvider {\n return new MockProvider((messages) => {\n const lastUser = [...messages].reverse().find((m) => m.role === 'user');\n return {\n content: lastUser?.content ?? '',\n usage: { prompt_tokens: 10, completion_tokens: 10, total_tokens: 20 },\n cost: 0,\n };\n });\n }\n\n static json(schema: unknown): MockProvider {\n return new MockProvider(() => ({\n content: JSON.stringify(generateFromSchema(schema)),\n usage: { prompt_tokens: 10, completion_tokens: 10, total_tokens: 20 },\n cost: 0,\n }));\n }\n\n static replay(source: string | ProviderResponse[]): MockProvider {\n const data =\n typeof source === 'string'\n ? (JSON.parse(readFileSync(source, 'utf-8')) as ProviderResponse[])\n : source;\n return new MockProvider((_messages, callIndex) => {\n if (callIndex >= data.length) {\n throw new Error(`MockProvider.replay: no recorded response for call index ${callIndex}`);\n }\n return data[callIndex];\n });\n }\n\n static fn(\n handler: (\n messages: ChatMessage[],\n callIndex: number,\n ) =>\n | {\n content: string;\n tool_calls?: ToolCallMessage[];\n providerMetadata?: Record<string, unknown>;\n usage?: { prompt_tokens: number; completion_tokens: number; total_tokens: number };\n cost?: number;\n }\n | Promise<{\n content: string;\n tool_calls?: ToolCallMessage[];\n providerMetadata?: Record<string, unknown>;\n usage?: { prompt_tokens: number; completion_tokens: number; total_tokens: number };\n cost?: number;\n }>,\n ): MockProvider {\n return new MockProvider(async (messages, callIndex) => {\n const result = await handler(messages, callIndex);\n return {\n ...result,\n usage: result.usage ?? { prompt_tokens: 10, completion_tokens: 10, total_tokens: 20 },\n cost: result.cost ?? 0,\n };\n });\n }\n}\n","export class MockTool {\n private _calls: { input: unknown }[] = [];\n\n constructor(\n readonly name: string,\n private handler: (input: unknown) => unknown | Promise<unknown>,\n ) {}\n\n get calls() {\n return this._calls;\n }\n\n async execute(input: unknown): Promise<unknown> {\n this._calls.push({ input });\n return this.handler(input);\n }\n\n static create(name: string, handler: (input: unknown) => unknown | Promise<unknown>): MockTool {\n return new MockTool(name, handler);\n }\n}\n","import { MockProvider } from './mock-provider.js';\nimport { MockTool } from './mock-tool.js';\nimport type {\n AxlEvent,\n AwaitHumanOptions,\n HumanDecision,\n ProviderResponse,\n AgentCallInfo,\n AxlConfig,\n AnyWorkflow,\n ToolCallOutcome,\n ObservationStatus,\n} from '@axlsdk/axl';\nimport {\n WorkflowContext,\n MemoryStore,\n ProviderRegistry,\n eventCostContribution,\n isUnpricedLeaf,\n} from '@axlsdk/axl';\nimport type { EventStreamOptions, WorkflowContextInit } from '@axlsdk/axl';\n\n// `AnyWorkflow` is a re-exported alias for `Workflow<any, any>` — see\n// the JSDoc on `AnyWorkflow` in `@axlsdk/axl/workflow.ts`. The bivariant\n// `any` is load-bearing for satisfying narrowly-typed handlers (e.g., a\n// `Workflow<TInput=MsgType>` whose handler takes `WorkflowContext<MsgType>`).\n\n/** One accepted provider-issued tool invocation, recorded from its terminal v2 event.\n *\n * Narrow `outcome.status` before reading status-specific fields. Correlation uses\n * `(executionId, askId, callId)`; `name` is the canonical tool name.\n */\nexport type RecordedToolCall = {\n name: string;\n executionId: string;\n askId: string;\n callId: string;\n args: unknown;\n requestedTool?: string;\n outcome: ToolCallOutcome;\n};\nexport type RecordedAgentCall = Partial<AgentCallInfo> &\n Pick<AgentCallInfo, 'agent' | 'prompt' | 'response'>;\nexport type RecordedStep = { step: number; type: string; data: unknown };\n\nfunction generateExecutionId(): string {\n return `test-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nfunction preserveDrainCause(error: Error, cause: unknown): Error {\n if (cause === undefined || cause === error || 'cause' in error) return error;\n Object.defineProperty(error, 'cause', {\n configurable: true,\n enumerable: false,\n value: cause,\n });\n return error;\n}\n\nexport type AxlTestRuntimeOptions = {\n record?: string;\n humanDecisions?: (options: AwaitHumanOptions) => HumanDecision;\n /** AxlConfig for the test runtime. Controls trace level/redact, context management, etc.\n * Defaults to `{}`. Set `{ trace: { level: 'full' } }` to verify verbose-mode snapshots\n * in tests, or `{ trace: { redact: true } }` to verify redaction policy in tests. */\n config?: AxlConfig;\n};\n\nexport class AxlTestRuntime {\n private workflows = new Map<string, AnyWorkflow>();\n private mockProviders = new Map<string, MockProvider>();\n private mockToolMap = new Map<string, MockTool>();\n private _toolCalls: RecordedToolCall[] = [];\n private _agentCalls: RecordedAgentCall[] = [];\n private _steps: RecordedStep[] = [];\n private _traceLog: AxlEvent[] = [];\n private _totalCost = 0;\n private _unpriced = false;\n private _stepCounter = 0;\n private recordPath?: string;\n private recorded: ProviderResponse[] = [];\n private _executionId: string = generateExecutionId();\n private _humanDecisionHandler?: (options: AwaitHumanOptions) => HumanDecision;\n private _config: AxlConfig;\n\n constructor(options?: AxlTestRuntimeOptions) {\n this.recordPath = options?.record;\n this._humanDecisionHandler = options?.humanDecisions;\n this._config = options?.config ?? {};\n }\n\n register(workflow: AnyWorkflow): void {\n this.workflows.set(workflow.name, workflow);\n }\n\n mockProvider(name: string, provider: MockProvider): void {\n this.mockProviders.set(name, provider);\n }\n\n mockTool<TInput = unknown>(\n name: string,\n handler: (input: TInput) => unknown | Promise<unknown>,\n ): void {\n // The MockTool registry is type-erased (`(input: unknown) => unknown`)\n // because the runtime can't statically know each tool's input shape; tests\n // opt in to a typed input via the generic, and we cast on storage.\n this.mockToolMap.set(name, MockTool.create(name, handler as (input: unknown) => unknown));\n }\n\n async execute(\n workflowName: string,\n input: unknown,\n options?: {\n metadata?: Record<string, unknown>;\n events?: EventStreamOptions;\n branchDrainTimeoutMs?: number;\n },\n ): Promise<unknown> {\n const workflow = this.workflows.get(workflowName);\n if (!workflow) throw new Error(`Workflow \"${workflowName}\" not registered`);\n\n // Reset state between executions\n this._toolCalls = [];\n this._agentCalls = [];\n this._steps = [];\n this._traceLog = [];\n this._totalCost = 0;\n this._unpriced = false;\n this._stepCounter = 0;\n this.recorded = [];\n this._executionId = generateExecutionId();\n\n const validated = workflow.inputSchema.parse(input);\n\n // Build ProviderRegistry from registered mock providers\n const registry = new ProviderRegistry();\n registry.clearFactories(); // Remove built-in factories; only use explicit mocks\n for (const [name, provider] of this.mockProviders) {\n registry.registerInstance(name, provider);\n }\n // Fallback resolution: 'default' key or single-provider\n const defaultProvider = this.mockProviders.get('default');\n if (defaultProvider) {\n registry.setFallback(defaultProvider);\n } else if (this.mockProviders.size === 1) {\n const onlyProvider = this.mockProviders.values().next().value!;\n registry.setFallback(onlyProvider);\n }\n\n // Build toolOverrides from mockToolMap\n const toolOverrides = new Map<string, (args: unknown) => Promise<unknown>>();\n for (const [name, mockTool] of this.mockToolMap) {\n toolOverrides.set(name, async (args: unknown) => {\n return mockTool.execute(args);\n });\n }\n\n // Previously `_recordStep('workflow_start', ...)` was called here with\n // raw `{ workflow, input }` data, AND `ctx._emitWorkflowStart` below\n // pushed through the onTrace handler (which also bumps `_stepCounter`\n // and appends to `_steps`). Result: two entries in `steps()` per\n // workflow_start, with the first bypassing `config.trace.redact`.\n // The `_recordStep` call is removed — onTrace is the single source\n // of truth for `_steps`, matching the behavior of every other event\n // type in the test runtime. Reviewer architecture §5.\n\n const init: WorkflowContextInit = {\n input: validated,\n executionId: this._executionId,\n metadata: options?.metadata,\n // Thread the constructor-provided config so tests can exercise\n // trace.level === 'full' and trace.redact behavior end-to-end.\n config: this._config,\n // Thread `events` config so tests can exercise the queue cap and\n // overflow policy on `ctx.events`. Mirrors the production runtime.\n eventStreamOptions: options?.events,\n branchDrainTimeoutMs: options?.branchDrainTimeoutMs,\n // Production runtime threads this (see `runtime.ts:594` in\n // `execute()` and `:765` in `stream()`). `emitEvent` auto-stamps\n // `event.workflow` from it, so consumers grouping by workflow\n // (Cost Dashboard `byWorkflow`, `trackExecution.metadata.workflows`,\n // any eval runner) see the same attribution in tests and prod.\n workflowName,\n providerRegistry: registry,\n stateStore: new MemoryStore(),\n toolOverrides: toolOverrides.size > 0 ? toolOverrides : undefined,\n awaitHumanHandler: this._humanDecisionHandler\n ? (opts: AwaitHumanOptions) => this._humanDecisionHandler!(opts)\n : undefined,\n onTrace: (event: AxlEvent) => {\n this._traceLog.push(event);\n this._stepCounter++;\n this._steps.push({\n step: this._stepCounter,\n type: event.type,\n data: (event as { data?: unknown }).data,\n });\n\n if (event.type === 'tool_call_end') {\n const { args, requestedTool, outcome } = event.data;\n this._toolCalls.push({\n name: event.tool,\n executionId: event.executionId,\n askId: event.askId,\n callId: event.callId,\n args,\n ...(requestedTool !== undefined ? { requestedTool } : {}),\n outcome,\n });\n }\n\n // Single-source-of-truth cost accumulator. Skips ask_end\n // rollups (decision 10) and guards NaN/Infinity.\n this._totalCost += eventCostContribution(event);\n // Honest aggregate: one unpriced leaf makes `totalCost()` a lower bound.\n if (isUnpricedLeaf(event)) this._unpriced = true;\n\n // Track provider responses for recording\n if (event.type === 'agent_call_end' && event.data) {\n const { response } = event.data as { prompt?: string; response?: string };\n if (response !== undefined) {\n this.recorded.push({\n content: response,\n usage: event.tokens\n ? {\n prompt_tokens: event.tokens.input ?? 0,\n completion_tokens: event.tokens.output ?? 0,\n total_tokens:\n (event.tokens.input ?? 0) +\n (event.tokens.output ?? 0) +\n (event.tokens.reasoning ?? 0),\n ...(event.tokens.reasoning !== undefined\n ? { reasoning_tokens: event.tokens.reasoning }\n : {}),\n }\n : { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 },\n ...(event.cost !== undefined ? { cost: event.cost } : {}),\n });\n }\n }\n },\n onAgentCallComplete: (call: AgentCallInfo) => {\n this._agentCalls.push(call);\n },\n };\n\n const ctx = new WorkflowContext(init);\n\n // Emit workflow_start through the same pipeline production uses,\n // AFTER ctx exists so `emitEvent`'s redact/step/timestamp handling\n // applies. Previously emitted via `_pushTrace` which bypassed\n // redaction — `config: { trace: { redact: true } }` on the test\n // runtime would scrub intermediate events but leak `input`/`result`\n // through the synthesized workflow_start/end.\n const startedAt = Date.now();\n ctx._emitWorkflowStart(validated);\n try {\n const result = await workflow.handler(ctx);\n const observation = await ctx._drainBranchWork();\n\n // Validate output schema if defined\n if (workflow.outputSchema) workflow.outputSchema.parse(result);\n\n ctx._emitWorkflowEnd({\n status: 'completed',\n duration: Date.now() - startedAt,\n result,\n observation,\n });\n // `_steps` is populated by onTrace for every event (including\n // workflow_end); no separate `_recordStep` call needed — that\n // would double-count.\n\n if (this.recordPath) await this._writeRecording();\n return result;\n } catch (err) {\n let workflowError = err;\n let observation: ObservationStatus = { complete: true };\n try {\n observation = await ctx._drainBranchWork();\n } catch (drainError) {\n workflowError =\n drainError instanceof Error ? preserveDrainCause(drainError, workflowError) : drainError;\n }\n // Parity with production: failed workflows get a terminal\n // `workflow_end(status: 'failed')` event so consumers counting\n // workflow_start ↔ workflow_end pairs never see an unclosed one.\n // `aborted` flag mirrors the runtime.ts AbortError detection.\n const aborted =\n typeof workflowError === 'object' &&\n workflowError !== null &&\n (workflowError as { name?: unknown }).name === 'AbortError';\n ctx._emitWorkflowEnd({\n status: 'failed',\n duration: Date.now() - startedAt,\n error: workflowError instanceof Error ? workflowError.message : String(workflowError),\n ...(aborted ? { aborted: true } : {}),\n observation,\n });\n // `_steps` populated by onTrace (see comment on the success path).\n throw workflowError;\n }\n }\n\n toolCalls(name?: string): RecordedToolCall[] {\n return name ? this._toolCalls.filter((c) => c.name === name) : this._toolCalls;\n }\n\n agentCalls(name?: string): RecordedAgentCall[] {\n return name ? this._agentCalls.filter((c) => c.agent === name) : this._agentCalls;\n }\n\n totalCost(): number {\n return this._totalCost;\n }\n /** True when any cost-bearing call was unpriced — `totalCost()` is then a\n * LOWER BOUND. Mirrors `ExecutionInfo.unpriced` / `BudgetResult.unpriced`. */\n unpriced(): boolean {\n return this._unpriced;\n }\n steps(): RecordedStep[] {\n return this._steps;\n }\n traceLog(): AxlEvent[] {\n return this._traceLog;\n }\n\n private async _writeRecording(): Promise<void> {\n if (!this.recordPath) return;\n const { writeFile, mkdir } = await import('node:fs/promises');\n const { dirname } = await import('node:path');\n await mkdir(dirname(this.recordPath), { recursive: true });\n await writeFile(this.recordPath, JSON.stringify(this.recorded, null, 2), 'utf8');\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/mock-provider.ts","../src/mock-tool.ts","../src/mock-transcription-provider.ts","../src/test-runtime.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\nimport { z } from 'zod';\nimport type {\n ChatMessage,\n ChatOptions,\n InputContentPart,\n InputMediaSource,\n ModelInput,\n ToolCallMessage,\n ProviderResponse,\n StreamChunk,\n Provider,\n ProviderInputValidationRequest,\n ProviderInputValidationResult,\n} from '@axlsdk/axl';\nimport { inputText, UnsupportedModelInputError } from '@axlsdk/axl';\n\nfunction cloneValue(value: unknown): unknown {\n if (value instanceof Uint8Array) return value.slice();\n if (Array.isArray(value)) return value.map(cloneValue);\n if (value && typeof value === 'object') {\n return Object.fromEntries(Object.entries(value).map(([key, item]) => [key, cloneValue(item)]));\n }\n return value;\n}\n\nfunction cloneModelInput(input: ModelInput): ModelInput {\n if (typeof input === 'string') return input;\n return input.map((part): InputContentPart => {\n if (part.type === 'text') return { type: 'text', text: part.text };\n const { source } = part;\n switch (source.type) {\n case 'bytes':\n return {\n type: 'image',\n source: { type: 'bytes', data: source.data.slice(), mediaType: source.mediaType },\n ...(part.label ? { label: part.label } : {}),\n };\n case 'url':\n return {\n type: 'image',\n source: {\n type: 'url',\n url: source.url,\n ...(source.mediaType ? { mediaType: source.mediaType } : {}),\n },\n ...(part.label ? { label: part.label } : {}),\n };\n case 'base64':\n return {\n type: 'image',\n source: { type: 'base64', data: source.data, mediaType: source.mediaType },\n ...(part.label ? { label: part.label } : {}),\n };\n case 'provider-file':\n return {\n type: 'image',\n source: {\n type: 'provider-file',\n provider: source.provider,\n reference: source.reference,\n ...(source.mediaType ? { mediaType: source.mediaType } : {}),\n },\n ...(part.label ? { label: part.label } : {}),\n };\n }\n });\n}\n\nfunction cloneMessages(messages: readonly ChatMessage[]): ChatMessage[] {\n return messages.map((message) => ({\n ...message,\n content: cloneModelInput(message.content),\n ...(message.tool_calls\n ? {\n tool_calls: message.tool_calls.map((toolCall) => ({\n ...toolCall,\n function: { ...toolCall.function },\n })),\n }\n : {}),\n ...(message.providerMetadata\n ? { providerMetadata: cloneValue(message.providerMetadata) as Record<string, unknown> }\n : {}),\n }));\n}\n\nfunction cloneOptions(options: ChatOptions): ChatOptions {\n return {\n ...options,\n ...(options.tools\n ? {\n tools: options.tools.map((tool) => ({\n ...tool,\n function: { ...tool.function, parameters: cloneValue(tool.function.parameters) },\n })),\n }\n : {}),\n ...(options.providerOptions\n ? { providerOptions: cloneValue(options.providerOptions) as Record<string, unknown> }\n : {}),\n };\n}\n\nfunction richParts(input: ModelInput): readonly InputContentPart[] {\n return typeof input === 'string' ? [] : input;\n}\n\nfunction randomAlphanumeric(length: number): string {\n const chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';\n let result = '';\n for (let i = 0; i < length; i++) {\n result += chars[Math.floor(Math.random() * chars.length)];\n }\n return result;\n}\n\nfunction generateFromSchema(schema: unknown): unknown {\n if (schema instanceof z.ZodString) return randomAlphanumeric(8 + Math.floor(Math.random() * 13));\n if (schema instanceof z.ZodNumber) {\n const min = Number.isFinite(schema.minValue) ? schema.minValue! : 0;\n const max = Number.isFinite(schema.maxValue) ? schema.maxValue! : 100;\n return min + Math.random() * (max - min);\n }\n if (schema instanceof z.ZodBoolean) return Math.random() < 0.5;\n if (schema instanceof z.ZodArray) {\n const count = 1 + Math.floor(Math.random() * 3);\n return Array.from({ length: count }, () => generateFromSchema(schema.element));\n }\n if (schema instanceof z.ZodObject) {\n const obj: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(schema.shape)) obj[key] = generateFromSchema(value);\n return obj;\n }\n if (schema instanceof z.ZodOptional) {\n if (Math.random() < 0.5) return undefined;\n return generateFromSchema(schema.unwrap());\n }\n if (schema instanceof z.ZodDefault) return schema.parse(undefined);\n if (schema instanceof z.ZodEnum) {\n const values = schema.options;\n return values.length > 0 ? values[Math.floor(Math.random() * values.length)] : '';\n }\n if (schema instanceof z.ZodLiteral) return [...schema.values][0];\n if (schema instanceof z.ZodNullable) return null;\n if (schema instanceof z.ZodUnion) {\n const options = schema.options;\n return generateFromSchema(options[Math.floor(Math.random() * options.length)]);\n }\n return {};\n}\n\nexport class MockProvider implements Provider {\n readonly name = 'mock';\n private _calls: { messages: ChatMessage[]; options: ChatOptions }[] = [];\n /** Per-call optional chunk arrays, set by `sequence()` / `chunked()` so\n * `stream()` can yield one `text_delta` per chunk. Per-call indexed\n * alongside the response sequence. */\n private chunkSequence?: Array<string[] | undefined>;\n /** Optional ms delay between successive chunks during `stream()`. Useful\n * for dev fixtures that need to demonstrate streaming UX visually\n * (without a delay, mock chunks fire synchronously and complete in\n * microseconds — invisible to a human watching). Default 0 keeps\n * every existing test fast.\n *\n * Set via `provider.chunkDelayMs = 50` after construction. Not part of\n * any factory's surface to keep the test API minimal. */\n chunkDelayMs = 0;\n\n private constructor(\n private responseFn: (\n messages: ChatMessage[],\n callIndex: number,\n ) => ProviderResponse | Promise<ProviderResponse>,\n ) {}\n\n get calls() {\n return this._calls;\n }\n\n async chat(messages: ChatMessage[], options: ChatOptions): Promise<ProviderResponse> {\n // Each consumer gets independent ownership: a handler can inspect or mutate\n // its copy without changing the durable assertion record (including bytes).\n const recordedMessages = cloneMessages(messages);\n this._calls.push({ messages: recordedMessages, options: cloneOptions(options) });\n return await this.responseFn(cloneMessages(messages), this._calls.length - 1);\n }\n\n inputCapabilities(_model: string): { image: { sources: readonly InputMediaSource['type'][] } } {\n return { image: { sources: ['url', 'bytes', 'base64', 'provider-file'] } };\n }\n\n validateInput(request: ProviderInputValidationRequest): ProviderInputValidationResult {\n const effectiveModel =\n typeof request.providerOptions?.model === 'string'\n ? request.providerOptions.model\n : request.model;\n const fail = (source?: string, feature?: string): never => {\n throw new UnsupportedModelInputError({\n provider: this.name,\n model: effectiveModel || request.model,\n modality: 'image',\n ...(source ? { source } : {}),\n ...(feature ? { feature } : {}),\n });\n };\n\n if (request.providerOptions && 'input' in request.providerOptions) {\n fail(undefined, 'raw input-container providerOptions');\n }\n for (const message of request.history) {\n if (typeof message.content === 'string') continue;\n if (message.role !== 'user') fail(undefined, 'rich non-user history');\n for (const part of richParts(message.content)) {\n if (\n part.type === 'image' &&\n part.source.type === 'provider-file' &&\n part.source.provider !== this.name\n ) {\n fail('provider-file');\n }\n }\n }\n for (const part of richParts(request.input)) {\n if (\n part.type === 'image' &&\n part.source.type === 'provider-file' &&\n part.source.provider !== this.name\n ) {\n fail('provider-file');\n }\n }\n return { effectiveModel };\n }\n\n async *stream(messages: ChatMessage[], options: ChatOptions): AsyncGenerator<StreamChunk> {\n const callIndex = this._calls.length;\n const response = await this.chat(messages, options);\n const chunks = this.chunkSequence?.[callIndex];\n if (chunks && chunks.length > 0) {\n // Sanity guard — if a caller passes chunks AND content, they MUST\n // match. Otherwise tests pass while the real prod content silently\n // diverges from what the streaming path observes.\n const joined = chunks.join('');\n if (joined !== response.content) {\n throw new Error(\n `MockProvider.stream: chunks.join('') !== content. ` +\n `chunks=\"${joined}\" content=\"${response.content}\"`,\n );\n }\n for (let i = 0; i < chunks.length; i++) {\n yield { type: 'text_delta', content: chunks[i] };\n if (this.chunkDelayMs > 0 && i < chunks.length - 1) {\n await new Promise((resolve) => setTimeout(resolve, this.chunkDelayMs));\n }\n }\n } else if (response.content) {\n yield { type: 'text_delta', content: response.content };\n }\n if (response.tool_calls) {\n for (const tc of response.tool_calls) {\n yield {\n type: 'tool_call_delta',\n id: tc.id,\n name: tc.function.name,\n arguments: tc.function.arguments,\n };\n }\n }\n yield { type: 'done', usage: response.usage, providerMetadata: response.providerMetadata };\n }\n\n static sequence(\n responses: Array<{\n content: string;\n tool_calls?: ToolCallMessage[];\n providerMetadata?: Record<string, unknown>;\n usage?: { prompt_tokens: number; completion_tokens: number; total_tokens: number };\n cost?: number;\n /** When set, `stream()` yields one `text_delta` per entry instead\n * of one big delta with the full content. Use to exercise\n * partial-JSON parsing, structural-boundary throttling, and\n * cross-attempt token retention in tests. Must satisfy\n * `chunks.join('') === content`. */\n chunks?: string[];\n }>,\n ): MockProvider {\n const provider = new MockProvider((_messages, callIndex) => {\n if (callIndex >= responses.length) {\n throw new Error(\n `MockProvider.sequence: no response for call index ${callIndex}. Only ${responses.length} responses defined.`,\n );\n }\n const resp = responses[callIndex];\n return {\n content: resp.content,\n tool_calls: resp.tool_calls,\n providerMetadata: resp.providerMetadata,\n usage: resp.usage ?? { prompt_tokens: 10, completion_tokens: 10, total_tokens: 20 },\n cost: resp.cost ?? 0,\n };\n });\n provider.chunkSequence = responses.map((r) => r.chunks);\n return provider;\n }\n\n /**\n * Convenience: build a `sequence()` from plain content strings, splitting\n * each one into fixed-size chunks for the streaming path. Default\n * `chunkSize` is 4 chars (≈1 token).\n */\n static chunked(contents: string[], chunkSize = 4): MockProvider {\n const responses = contents.map((content) => {\n const chunks: string[] = [];\n for (let i = 0; i < content.length; i += chunkSize) {\n chunks.push(content.slice(i, i + chunkSize));\n }\n return { content, chunks };\n });\n return MockProvider.sequence(responses);\n }\n\n static echo(): MockProvider {\n return new MockProvider((messages) => {\n const lastUser = [...messages].reverse().find((m) => m.role === 'user');\n return {\n content: lastUser ? inputText(lastUser.content) : '',\n usage: { prompt_tokens: 10, completion_tokens: 10, total_tokens: 20 },\n cost: 0,\n };\n });\n }\n\n static json(schema: unknown): MockProvider {\n return new MockProvider(() => ({\n content: JSON.stringify(generateFromSchema(schema)),\n usage: { prompt_tokens: 10, completion_tokens: 10, total_tokens: 20 },\n cost: 0,\n }));\n }\n\n static replay(source: string | ProviderResponse[]): MockProvider {\n const data =\n typeof source === 'string'\n ? (JSON.parse(readFileSync(source, 'utf-8')) as ProviderResponse[])\n : source;\n return new MockProvider((_messages, callIndex) => {\n if (callIndex >= data.length) {\n throw new Error(`MockProvider.replay: no recorded response for call index ${callIndex}`);\n }\n return data[callIndex];\n });\n }\n\n static fn(\n handler: (\n messages: ChatMessage[],\n callIndex: number,\n ) =>\n | {\n content: string;\n tool_calls?: ToolCallMessage[];\n providerMetadata?: Record<string, unknown>;\n usage?: { prompt_tokens: number; completion_tokens: number; total_tokens: number };\n cost?: number;\n }\n | Promise<{\n content: string;\n tool_calls?: ToolCallMessage[];\n providerMetadata?: Record<string, unknown>;\n usage?: { prompt_tokens: number; completion_tokens: number; total_tokens: number };\n cost?: number;\n }>,\n ): MockProvider {\n return new MockProvider(async (messages, callIndex) => {\n const result = await handler(messages, callIndex);\n return {\n ...result,\n usage: result.usage ?? { prompt_tokens: 10, completion_tokens: 10, total_tokens: 20 },\n cost: result.cost ?? 0,\n };\n });\n }\n}\n","export class MockTool {\n private _calls: { input: unknown }[] = [];\n\n constructor(\n readonly name: string,\n private handler: (input: unknown) => unknown | Promise<unknown>,\n ) {}\n\n get calls() {\n return this._calls;\n }\n\n async execute(input: unknown): Promise<unknown> {\n this._calls.push({ input });\n return this.handler(input);\n }\n\n static create(name: string, handler: (input: unknown) => unknown | Promise<unknown>): MockTool {\n return new MockTool(name, handler);\n }\n}\n","import type {\n TranscriptionCapabilities,\n TranscriptionProvider,\n TranscriptionProviderRequest,\n TranscriptionProviderResult,\n} from '@axlsdk/axl';\n\nfunction clone<T>(value: T): T {\n return structuredClone(value);\n}\n\nfunction cloneRequest(\n request: TranscriptionProviderRequest,\n includeSignal: boolean,\n): TranscriptionProviderRequest {\n const audio =\n request.audio.type === 'bytes'\n ? { ...request.audio, data: request.audio.data.slice() }\n : { ...request.audio };\n return {\n model: request.model,\n audio,\n ...(request.language !== undefined ? { language: request.language } : {}),\n ...(request.timestamps !== undefined ? { timestamps: request.timestamps } : {}),\n ...(request.diarization !== undefined ? { diarization: request.diarization } : {}),\n ...(request.providerOptions ? { providerOptions: clone(request.providerOptions) } : {}),\n ...(includeSignal && request.signal ? { signal: request.signal } : {}),\n };\n}\n\n/** Dedicated transcription mock. It intentionally does not extend MockProvider,\n * so chat fixtures cannot accidentally become transcription adapters. */\nexport class MockTranscriptionProvider implements TranscriptionProvider {\n private _calls: TranscriptionProviderRequest[] = [];\n\n constructor(\n private readonly response: (\n request: TranscriptionProviderRequest,\n callIndex: number,\n ) => TranscriptionProviderResult | Promise<TranscriptionProviderResult>,\n private readonly capabilitiesFor: (\n model: string,\n ) => TranscriptionCapabilities | undefined = () => ({\n sources: ['bytes', 'base64', 'provider-file'],\n timestamps: ['segment', 'word'],\n diarization: true,\n }),\n ) {}\n\n get calls(): readonly TranscriptionProviderRequest[] {\n return this._calls.map(clone);\n }\n\n capabilities(model: string): TranscriptionCapabilities | undefined {\n return this.capabilitiesFor(model);\n }\n\n async transcribe(request: TranscriptionProviderRequest): Promise<TranscriptionProviderResult> {\n // AbortSignal cannot be structured-cloned. Keep it only on the callback\n // request so fixtures can observe cancellation; recorded calls omit it.\n const snapshot = cloneRequest(request, false);\n this._calls.push(snapshot);\n return clone(await this.response(cloneRequest(request, true), this._calls.length - 1));\n }\n\n static text(text: string): MockTranscriptionProvider {\n return new MockTranscriptionProvider(() => ({ transcript: { text } }));\n }\n}\n","import { MockProvider } from './mock-provider.js';\nimport { MockTool } from './mock-tool.js';\nimport { MockTranscriptionProvider } from './mock-transcription-provider.js';\nimport type {\n AxlEvent,\n AwaitHumanOptions,\n HumanDecision,\n ProviderResponse,\n AgentCallInfo,\n AxlConfig,\n AnyWorkflow,\n ToolCallOutcome,\n ObservationStatus,\n} from '@axlsdk/axl';\nimport {\n WorkflowContext,\n MemoryStore,\n ProviderRegistry,\n TranscriptionProviderRegistry,\n eventCostContribution,\n isUnpricedLeaf,\n} from '@axlsdk/axl';\nimport type { EventStreamOptions, WorkflowContextInit } from '@axlsdk/axl';\n\n// `AnyWorkflow` is a re-exported alias for `Workflow<any, any>` — see\n// the JSDoc on `AnyWorkflow` in `@axlsdk/axl/workflow.ts`. The bivariant\n// `any` is load-bearing for satisfying narrowly-typed handlers (e.g., a\n// `Workflow<TInput=MsgType>` whose handler takes `WorkflowContext<MsgType>`).\n\n/** One accepted provider-issued tool invocation, recorded from its terminal v2 event.\n *\n * Narrow `outcome.status` before reading status-specific fields. Correlation uses\n * `(executionId, askId, callId)`; `name` is the canonical tool name.\n */\nexport type RecordedToolCall = {\n name: string;\n executionId: string;\n askId: string;\n callId: string;\n args: unknown;\n requestedTool?: string;\n outcome: ToolCallOutcome;\n};\nexport type RecordedAgentCall = Partial<AgentCallInfo> &\n Pick<AgentCallInfo, 'agent' | 'prompt' | 'response'>;\nexport type RecordedStep = { step: number; type: string; data: unknown };\n\nfunction generateExecutionId(): string {\n return `test-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`;\n}\n\nfunction preserveDrainCause(error: Error, cause: unknown): Error {\n if (cause === undefined || cause === error || 'cause' in error) return error;\n Object.defineProperty(error, 'cause', {\n configurable: true,\n enumerable: false,\n value: cause,\n });\n return error;\n}\n\nexport type AxlTestRuntimeOptions = {\n record?: string;\n humanDecisions?: (options: AwaitHumanOptions) => HumanDecision;\n /** AxlConfig for the test runtime. Controls trace level/redact, context management, etc.\n * Defaults to `{}`. Set `{ trace: { level: 'full' } }` to verify verbose-mode snapshots\n * in tests, or `{ trace: { redact: true } }` to verify redaction policy in tests. */\n config?: AxlConfig;\n};\n\nexport class AxlTestRuntime {\n private workflows = new Map<string, AnyWorkflow>();\n private mockProviders = new Map<string, MockProvider>();\n private mockTranscriptionProviders = new Map<string, MockTranscriptionProvider>();\n private mockToolMap = new Map<string, MockTool>();\n private _toolCalls: RecordedToolCall[] = [];\n private _agentCalls: RecordedAgentCall[] = [];\n private _steps: RecordedStep[] = [];\n private _traceLog: AxlEvent[] = [];\n private _totalCost = 0;\n private _unpriced = false;\n private _stepCounter = 0;\n private recordPath?: string;\n private recorded: ProviderResponse[] = [];\n private _executionId: string = generateExecutionId();\n private _humanDecisionHandler?: (options: AwaitHumanOptions) => HumanDecision;\n private _config: AxlConfig;\n\n constructor(options?: AxlTestRuntimeOptions) {\n this.recordPath = options?.record;\n this._humanDecisionHandler = options?.humanDecisions;\n this._config = options?.config ?? {};\n }\n\n register(workflow: AnyWorkflow): void {\n this.workflows.set(workflow.name, workflow);\n }\n\n mockProvider(name: string, provider: MockProvider): void {\n this.mockProviders.set(name, provider);\n }\n\n mockTranscriptionProvider(name: string, provider: MockTranscriptionProvider): void {\n this.mockTranscriptionProviders.set(name, provider);\n }\n\n mockTool<TInput = unknown>(\n name: string,\n handler: (input: TInput) => unknown | Promise<unknown>,\n ): void {\n // The MockTool registry is type-erased (`(input: unknown) => unknown`)\n // because the runtime can't statically know each tool's input shape; tests\n // opt in to a typed input via the generic, and we cast on storage.\n this.mockToolMap.set(name, MockTool.create(name, handler as (input: unknown) => unknown));\n }\n\n async execute(\n workflowName: string,\n input: unknown,\n options?: {\n metadata?: Record<string, unknown>;\n events?: EventStreamOptions;\n branchDrainTimeoutMs?: number;\n },\n ): Promise<unknown> {\n const workflow = this.workflows.get(workflowName);\n if (!workflow) throw new Error(`Workflow \"${workflowName}\" not registered`);\n\n // Reset state between executions\n this._toolCalls = [];\n this._agentCalls = [];\n this._steps = [];\n this._traceLog = [];\n this._totalCost = 0;\n this._unpriced = false;\n this._stepCounter = 0;\n this.recorded = [];\n this._executionId = generateExecutionId();\n\n const validated = workflow.inputSchema.parse(input);\n\n // Build ProviderRegistry from registered mock providers\n const registry = new ProviderRegistry();\n registry.clearFactories(); // Remove built-in factories; only use explicit mocks\n for (const [name, provider] of this.mockProviders) {\n registry.registerInstance(name, provider);\n }\n const transcriptionRegistry = new TranscriptionProviderRegistry();\n for (const [name, provider] of this.mockTranscriptionProviders) {\n transcriptionRegistry.registerInstance(name, provider);\n }\n // Fallback resolution: 'default' key or single-provider\n const defaultProvider = this.mockProviders.get('default');\n if (defaultProvider) {\n registry.setFallback(defaultProvider);\n } else if (this.mockProviders.size === 1) {\n const onlyProvider = this.mockProviders.values().next().value!;\n registry.setFallback(onlyProvider);\n }\n\n // Build toolOverrides from mockToolMap\n const toolOverrides = new Map<string, (args: unknown) => Promise<unknown>>();\n for (const [name, mockTool] of this.mockToolMap) {\n toolOverrides.set(name, async (args: unknown) => {\n return mockTool.execute(args);\n });\n }\n\n // Previously `_recordStep('workflow_start', ...)` was called here with\n // raw `{ workflow, input }` data, AND `ctx._emitWorkflowStart` below\n // pushed through the onTrace handler (which also bumps `_stepCounter`\n // and appends to `_steps`). Result: two entries in `steps()` per\n // workflow_start, with the first bypassing `config.trace.redact`.\n // The `_recordStep` call is removed — onTrace is the single source\n // of truth for `_steps`, matching the behavior of every other event\n // type in the test runtime. Reviewer architecture §5.\n\n const init: WorkflowContextInit = {\n input: validated,\n executionId: this._executionId,\n metadata: options?.metadata,\n // Thread the constructor-provided config so tests can exercise\n // trace.level === 'full' and trace.redact behavior end-to-end.\n config: this._config,\n // Thread `events` config so tests can exercise the queue cap and\n // overflow policy on `ctx.events`. Mirrors the production runtime.\n eventStreamOptions: options?.events,\n branchDrainTimeoutMs: options?.branchDrainTimeoutMs,\n // Production runtime threads this (see `runtime.ts:594` in\n // `execute()` and `:765` in `stream()`). `emitEvent` auto-stamps\n // `event.workflow` from it, so consumers grouping by workflow\n // (Cost Dashboard `byWorkflow`, `trackExecution.metadata.workflows`,\n // any eval runner) see the same attribution in tests and prod.\n workflowName,\n providerRegistry: registry,\n transcriptionProviderRegistry: transcriptionRegistry,\n stateStore: new MemoryStore(),\n toolOverrides: toolOverrides.size > 0 ? toolOverrides : undefined,\n awaitHumanHandler: this._humanDecisionHandler\n ? (opts: AwaitHumanOptions) => this._humanDecisionHandler!(opts)\n : undefined,\n onTrace: (event: AxlEvent) => {\n this._traceLog.push(event);\n this._stepCounter++;\n this._steps.push({\n step: this._stepCounter,\n type: event.type,\n data: (event as { data?: unknown }).data,\n });\n\n if (event.type === 'tool_call_end') {\n const { args, requestedTool, outcome } = event.data;\n this._toolCalls.push({\n name: event.tool,\n executionId: event.executionId,\n askId: event.askId,\n callId: event.callId,\n args,\n ...(requestedTool !== undefined ? { requestedTool } : {}),\n outcome,\n });\n }\n\n // Single-source-of-truth cost accumulator. Skips ask_end\n // rollups (decision 10) and guards NaN/Infinity.\n this._totalCost += eventCostContribution(event);\n // Honest aggregate: one unpriced leaf makes `totalCost()` a lower bound.\n if (isUnpricedLeaf(event)) this._unpriced = true;\n\n // Track provider responses for recording\n if (event.type === 'agent_call_end' && event.data) {\n const { response } = event.data as { prompt?: string; response?: string };\n if (response !== undefined) {\n this.recorded.push({\n content: response,\n usage: event.tokens\n ? {\n prompt_tokens: event.tokens.input ?? 0,\n completion_tokens: event.tokens.output ?? 0,\n total_tokens:\n (event.tokens.input ?? 0) +\n (event.tokens.output ?? 0) +\n (event.tokens.reasoning ?? 0),\n ...(event.tokens.reasoning !== undefined\n ? { reasoning_tokens: event.tokens.reasoning }\n : {}),\n }\n : { prompt_tokens: 0, completion_tokens: 0, total_tokens: 0 },\n ...(event.cost !== undefined ? { cost: event.cost } : {}),\n });\n }\n }\n },\n onAgentCallComplete: (call: AgentCallInfo) => {\n this._agentCalls.push(call);\n },\n };\n\n const ctx = new WorkflowContext(init);\n\n // Emit workflow_start through the same pipeline production uses,\n // AFTER ctx exists so `emitEvent`'s redact/step/timestamp handling\n // applies. Previously emitted via `_pushTrace` which bypassed\n // redaction — `config: { trace: { redact: true } }` on the test\n // runtime would scrub intermediate events but leak `input`/`result`\n // through the synthesized workflow_start/end.\n const startedAt = Date.now();\n ctx._emitWorkflowStart(validated);\n try {\n const result = await workflow.handler(ctx);\n const observation = await ctx._drainBranchWork();\n\n // Validate output schema if defined\n if (workflow.outputSchema) workflow.outputSchema.parse(result);\n\n ctx._emitWorkflowEnd({\n status: 'completed',\n duration: Date.now() - startedAt,\n result,\n observation,\n });\n // `_steps` is populated by onTrace for every event (including\n // workflow_end); no separate `_recordStep` call needed — that\n // would double-count.\n\n if (this.recordPath) await this._writeRecording();\n return result;\n } catch (err) {\n let workflowError = err;\n let observation: ObservationStatus = { complete: true };\n try {\n observation = await ctx._drainBranchWork();\n } catch (drainError) {\n workflowError =\n drainError instanceof Error ? preserveDrainCause(drainError, workflowError) : drainError;\n }\n // Parity with production: failed workflows get a terminal\n // `workflow_end(status: 'failed')` event so consumers counting\n // workflow_start ↔ workflow_end pairs never see an unclosed one.\n // `aborted` flag mirrors the runtime.ts AbortError detection.\n const aborted =\n typeof workflowError === 'object' &&\n workflowError !== null &&\n (workflowError as { name?: unknown }).name === 'AbortError';\n ctx._emitWorkflowEnd({\n status: 'failed',\n duration: Date.now() - startedAt,\n error: workflowError instanceof Error ? workflowError.message : String(workflowError),\n ...(aborted ? { aborted: true } : {}),\n observation,\n });\n // `_steps` populated by onTrace (see comment on the success path).\n throw workflowError;\n }\n }\n\n toolCalls(name?: string): RecordedToolCall[] {\n return name ? this._toolCalls.filter((c) => c.name === name) : this._toolCalls;\n }\n\n agentCalls(name?: string): RecordedAgentCall[] {\n return name ? this._agentCalls.filter((c) => c.agent === name) : this._agentCalls;\n }\n\n totalCost(): number {\n return this._totalCost;\n }\n /** True when any cost-bearing call was unpriced — `totalCost()` is then a\n * LOWER BOUND. Mirrors `ExecutionInfo.unpriced` / `BudgetResult.unpriced`. */\n unpriced(): boolean {\n return this._unpriced;\n }\n steps(): RecordedStep[] {\n return this._steps;\n }\n traceLog(): AxlEvent[] {\n return this._traceLog;\n }\n\n private async _writeRecording(): Promise<void> {\n if (!this.recordPath) return;\n const { writeFile, mkdir } = await import('node:fs/promises');\n const { dirname } = await import('node:path');\n await mkdir(dirname(this.recordPath), { recursive: true });\n await writeFile(this.recordPath, JSON.stringify(this.recorded, null, 2), 'utf8');\n }\n}\n"],"mappings":";AAAA,SAAS,oBAAoB;AAC7B,SAAS,SAAS;AAclB,SAAS,WAAW,kCAAkC;AAEtD,SAAS,WAAW,OAAyB;AAC3C,MAAI,iBAAiB,WAAY,QAAO,MAAM,MAAM;AACpD,MAAI,MAAM,QAAQ,KAAK,EAAG,QAAO,MAAM,IAAI,UAAU;AACrD,MAAI,SAAS,OAAO,UAAU,UAAU;AACtC,WAAO,OAAO,YAAY,OAAO,QAAQ,KAAK,EAAE,IAAI,CAAC,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,WAAW,IAAI,CAAC,CAAC,CAAC;AAAA,EAC/F;AACA,SAAO;AACT;AAEA,SAAS,gBAAgB,OAA+B;AACtD,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,SAAO,MAAM,IAAI,CAAC,SAA2B;AAC3C,QAAI,KAAK,SAAS,OAAQ,QAAO,EAAE,MAAM,QAAQ,MAAM,KAAK,KAAK;AACjE,UAAM,EAAE,OAAO,IAAI;AACnB,YAAQ,OAAO,MAAM;AAAA,MACnB,KAAK;AACH,eAAO;AAAA,UACL,MAAM;AAAA,UACN,QAAQ,EAAE,MAAM,SAAS,MAAM,OAAO,KAAK,MAAM,GAAG,WAAW,OAAO,UAAU;AAAA,UAChF,GAAI,KAAK,QAAQ,EAAE,OAAO,KAAK,MAAM,IAAI,CAAC;AAAA,QAC5C;AAAA,MACF,KAAK;AACH,eAAO;AAAA,UACL,MAAM;AAAA,UACN,QAAQ;AAAA,YACN,MAAM;AAAA,YACN,KAAK,OAAO;AAAA,YACZ,GAAI,OAAO,YAAY,EAAE,WAAW,OAAO,UAAU,IAAI,CAAC;AAAA,UAC5D;AAAA,UACA,GAAI,KAAK,QAAQ,EAAE,OAAO,KAAK,MAAM,IAAI,CAAC;AAAA,QAC5C;AAAA,MACF,KAAK;AACH,eAAO;AAAA,UACL,MAAM;AAAA,UACN,QAAQ,EAAE,MAAM,UAAU,MAAM,OAAO,MAAM,WAAW,OAAO,UAAU;AAAA,UACzE,GAAI,KAAK,QAAQ,EAAE,OAAO,KAAK,MAAM,IAAI,CAAC;AAAA,QAC5C;AAAA,MACF,KAAK;AACH,eAAO;AAAA,UACL,MAAM;AAAA,UACN,QAAQ;AAAA,YACN,MAAM;AAAA,YACN,UAAU,OAAO;AAAA,YACjB,WAAW,OAAO;AAAA,YAClB,GAAI,OAAO,YAAY,EAAE,WAAW,OAAO,UAAU,IAAI,CAAC;AAAA,UAC5D;AAAA,UACA,GAAI,KAAK,QAAQ,EAAE,OAAO,KAAK,MAAM,IAAI,CAAC;AAAA,QAC5C;AAAA,IACJ;AAAA,EACF,CAAC;AACH;AAEA,SAAS,cAAc,UAAiD;AACtE,SAAO,SAAS,IAAI,CAAC,aAAa;AAAA,IAChC,GAAG;AAAA,IACH,SAAS,gBAAgB,QAAQ,OAAO;AAAA,IACxC,GAAI,QAAQ,aACR;AAAA,MACE,YAAY,QAAQ,WAAW,IAAI,CAAC,cAAc;AAAA,QAChD,GAAG;AAAA,QACH,UAAU,EAAE,GAAG,SAAS,SAAS;AAAA,MACnC,EAAE;AAAA,IACJ,IACA,CAAC;AAAA,IACL,GAAI,QAAQ,mBACR,EAAE,kBAAkB,WAAW,QAAQ,gBAAgB,EAA6B,IACpF,CAAC;AAAA,EACP,EAAE;AACJ;AAEA,SAAS,aAAa,SAAmC;AACvD,SAAO;AAAA,IACL,GAAG;AAAA,IACH,GAAI,QAAQ,QACR;AAAA,MACE,OAAO,QAAQ,MAAM,IAAI,CAAC,UAAU;AAAA,QAClC,GAAG;AAAA,QACH,UAAU,EAAE,GAAG,KAAK,UAAU,YAAY,WAAW,KAAK,SAAS,UAAU,EAAE;AAAA,MACjF,EAAE;AAAA,IACJ,IACA,CAAC;AAAA,IACL,GAAI,QAAQ,kBACR,EAAE,iBAAiB,WAAW,QAAQ,eAAe,EAA6B,IAClF,CAAC;AAAA,EACP;AACF;AAEA,SAAS,UAAU,OAAgD;AACjE,SAAO,OAAO,UAAU,WAAW,CAAC,IAAI;AAC1C;AAEA,SAAS,mBAAmB,QAAwB;AAClD,QAAM,QAAQ;AACd,MAAI,SAAS;AACb,WAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAC/B,cAAU,MAAM,KAAK,MAAM,KAAK,OAAO,IAAI,MAAM,MAAM,CAAC;AAAA,EAC1D;AACA,SAAO;AACT;AAEA,SAAS,mBAAmB,QAA0B;AACpD,MAAI,kBAAkB,EAAE,UAAW,QAAO,mBAAmB,IAAI,KAAK,MAAM,KAAK,OAAO,IAAI,EAAE,CAAC;AAC/F,MAAI,kBAAkB,EAAE,WAAW;AACjC,UAAM,MAAM,OAAO,SAAS,OAAO,QAAQ,IAAI,OAAO,WAAY;AAClE,UAAM,MAAM,OAAO,SAAS,OAAO,QAAQ,IAAI,OAAO,WAAY;AAClE,WAAO,MAAM,KAAK,OAAO,KAAK,MAAM;AAAA,EACtC;AACA,MAAI,kBAAkB,EAAE,WAAY,QAAO,KAAK,OAAO,IAAI;AAC3D,MAAI,kBAAkB,EAAE,UAAU;AAChC,UAAM,QAAQ,IAAI,KAAK,MAAM,KAAK,OAAO,IAAI,CAAC;AAC9C,WAAO,MAAM,KAAK,EAAE,QAAQ,MAAM,GAAG,MAAM,mBAAmB,OAAO,OAAO,CAAC;AAAA,EAC/E;AACA,MAAI,kBAAkB,EAAE,WAAW;AACjC,UAAM,MAA+B,CAAC;AACtC,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,OAAO,KAAK,EAAG,KAAI,GAAG,IAAI,mBAAmB,KAAK;AAC5F,WAAO;AAAA,EACT;AACA,MAAI,kBAAkB,EAAE,aAAa;AACnC,QAAI,KAAK,OAAO,IAAI,IAAK,QAAO;AAChC,WAAO,mBAAmB,OAAO,OAAO,CAAC;AAAA,EAC3C;AACA,MAAI,kBAAkB,EAAE,WAAY,QAAO,OAAO,MAAM,MAAS;AACjE,MAAI,kBAAkB,EAAE,SAAS;AAC/B,UAAM,SAAS,OAAO;AACtB,WAAO,OAAO,SAAS,IAAI,OAAO,KAAK,MAAM,KAAK,OAAO,IAAI,OAAO,MAAM,CAAC,IAAI;AAAA,EACjF;AACA,MAAI,kBAAkB,EAAE,WAAY,QAAO,CAAC,GAAG,OAAO,MAAM,EAAE,CAAC;AAC/D,MAAI,kBAAkB,EAAE,YAAa,QAAO;AAC5C,MAAI,kBAAkB,EAAE,UAAU;AAChC,UAAM,UAAU,OAAO;AACvB,WAAO,mBAAmB,QAAQ,KAAK,MAAM,KAAK,OAAO,IAAI,QAAQ,MAAM,CAAC,CAAC;AAAA,EAC/E;AACA,SAAO,CAAC;AACV;AAEO,IAAM,eAAN,MAAM,cAAiC;AAAA,EAiBpC,YACE,YAIR;AAJQ;AAAA,EAIP;AAAA,EArBM,OAAO;AAAA,EACR,SAA8D,CAAC;AAAA;AAAA;AAAA;AAAA,EAI/D;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASR,eAAe;AAAA,EASf,IAAI,QAAQ;AACV,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,KAAK,UAAyB,SAAiD;AAGnF,UAAM,mBAAmB,cAAc,QAAQ;AAC/C,SAAK,OAAO,KAAK,EAAE,UAAU,kBAAkB,SAAS,aAAa,OAAO,EAAE,CAAC;AAC/E,WAAO,MAAM,KAAK,WAAW,cAAc,QAAQ,GAAG,KAAK,OAAO,SAAS,CAAC;AAAA,EAC9E;AAAA,EAEA,kBAAkB,QAA6E;AAC7F,WAAO,EAAE,OAAO,EAAE,SAAS,CAAC,OAAO,SAAS,UAAU,eAAe,EAAE,EAAE;AAAA,EAC3E;AAAA,EAEA,cAAc,SAAwE;AACpF,UAAM,iBACJ,OAAO,QAAQ,iBAAiB,UAAU,WACtC,QAAQ,gBAAgB,QACxB,QAAQ;AACd,UAAM,OAAO,CAAC,QAAiB,YAA4B;AACzD,YAAM,IAAI,2BAA2B;AAAA,QACnC,UAAU,KAAK;AAAA,QACf,OAAO,kBAAkB,QAAQ;AAAA,QACjC,UAAU;AAAA,QACV,GAAI,SAAS,EAAE,OAAO,IAAI,CAAC;AAAA,QAC3B,GAAI,UAAU,EAAE,QAAQ,IAAI,CAAC;AAAA,MAC/B,CAAC;AAAA,IACH;AAEA,QAAI,QAAQ,mBAAmB,WAAW,QAAQ,iBAAiB;AACjE,WAAK,QAAW,qCAAqC;AAAA,IACvD;AACA,eAAW,WAAW,QAAQ,SAAS;AACrC,UAAI,OAAO,QAAQ,YAAY,SAAU;AACzC,UAAI,QAAQ,SAAS,OAAQ,MAAK,QAAW,uBAAuB;AACpE,iBAAW,QAAQ,UAAU,QAAQ,OAAO,GAAG;AAC7C,YACE,KAAK,SAAS,WACd,KAAK,OAAO,SAAS,mBACrB,KAAK,OAAO,aAAa,KAAK,MAC9B;AACA,eAAK,eAAe;AAAA,QACtB;AAAA,MACF;AAAA,IACF;AACA,eAAW,QAAQ,UAAU,QAAQ,KAAK,GAAG;AAC3C,UACE,KAAK,SAAS,WACd,KAAK,OAAO,SAAS,mBACrB,KAAK,OAAO,aAAa,KAAK,MAC9B;AACA,aAAK,eAAe;AAAA,MACtB;AAAA,IACF;AACA,WAAO,EAAE,eAAe;AAAA,EAC1B;AAAA,EAEA,OAAO,OAAO,UAAyB,SAAmD;AACxF,UAAM,YAAY,KAAK,OAAO;AAC9B,UAAM,WAAW,MAAM,KAAK,KAAK,UAAU,OAAO;AAClD,UAAM,SAAS,KAAK,gBAAgB,SAAS;AAC7C,QAAI,UAAU,OAAO,SAAS,GAAG;AAI/B,YAAM,SAAS,OAAO,KAAK,EAAE;AAC7B,UAAI,WAAW,SAAS,SAAS;AAC/B,cAAM,IAAI;AAAA,UACR,6DACa,MAAM,cAAc,SAAS,OAAO;AAAA,QACnD;AAAA,MACF;AACA,eAAS,IAAI,GAAG,IAAI,OAAO,QAAQ,KAAK;AACtC,cAAM,EAAE,MAAM,cAAc,SAAS,OAAO,CAAC,EAAE;AAC/C,YAAI,KAAK,eAAe,KAAK,IAAI,OAAO,SAAS,GAAG;AAClD,gBAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,KAAK,YAAY,CAAC;AAAA,QACvE;AAAA,MACF;AAAA,IACF,WAAW,SAAS,SAAS;AAC3B,YAAM,EAAE,MAAM,cAAc,SAAS,SAAS,QAAQ;AAAA,IACxD;AACA,QAAI,SAAS,YAAY;AACvB,iBAAW,MAAM,SAAS,YAAY;AACpC,cAAM;AAAA,UACJ,MAAM;AAAA,UACN,IAAI,GAAG;AAAA,UACP,MAAM,GAAG,SAAS;AAAA,UAClB,WAAW,GAAG,SAAS;AAAA,QACzB;AAAA,MACF;AAAA,IACF;AACA,UAAM,EAAE,MAAM,QAAQ,OAAO,SAAS,OAAO,kBAAkB,SAAS,iBAAiB;AAAA,EAC3F;AAAA,EAEA,OAAO,SACL,WAac;AACd,UAAM,WAAW,IAAI,cAAa,CAAC,WAAW,cAAc;AAC1D,UAAI,aAAa,UAAU,QAAQ;AACjC,cAAM,IAAI;AAAA,UACR,qDAAqD,SAAS,UAAU,UAAU,MAAM;AAAA,QAC1F;AAAA,MACF;AACA,YAAM,OAAO,UAAU,SAAS;AAChC,aAAO;AAAA,QACL,SAAS,KAAK;AAAA,QACd,YAAY,KAAK;AAAA,QACjB,kBAAkB,KAAK;AAAA,QACvB,OAAO,KAAK,SAAS,EAAE,eAAe,IAAI,mBAAmB,IAAI,cAAc,GAAG;AAAA,QAClF,MAAM,KAAK,QAAQ;AAAA,MACrB;AAAA,IACF,CAAC;AACD,aAAS,gBAAgB,UAAU,IAAI,CAAC,MAAM,EAAE,MAAM;AACtD,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,QAAQ,UAAoB,YAAY,GAAiB;AAC9D,UAAM,YAAY,SAAS,IAAI,CAAC,YAAY;AAC1C,YAAM,SAAmB,CAAC;AAC1B,eAAS,IAAI,GAAG,IAAI,QAAQ,QAAQ,KAAK,WAAW;AAClD,eAAO,KAAK,QAAQ,MAAM,GAAG,IAAI,SAAS,CAAC;AAAA,MAC7C;AACA,aAAO,EAAE,SAAS,OAAO;AAAA,IAC3B,CAAC;AACD,WAAO,cAAa,SAAS,SAAS;AAAA,EACxC;AAAA,EAEA,OAAO,OAAqB;AAC1B,WAAO,IAAI,cAAa,CAAC,aAAa;AACpC,YAAM,WAAW,CAAC,GAAG,QAAQ,EAAE,QAAQ,EAAE,KAAK,CAAC,MAAM,EAAE,SAAS,MAAM;AACtE,aAAO;AAAA,QACL,SAAS,WAAW,UAAU,SAAS,OAAO,IAAI;AAAA,QAClD,OAAO,EAAE,eAAe,IAAI,mBAAmB,IAAI,cAAc,GAAG;AAAA,QACpE,MAAM;AAAA,MACR;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,OAAO,KAAK,QAA+B;AACzC,WAAO,IAAI,cAAa,OAAO;AAAA,MAC7B,SAAS,KAAK,UAAU,mBAAmB,MAAM,CAAC;AAAA,MAClD,OAAO,EAAE,eAAe,IAAI,mBAAmB,IAAI,cAAc,GAAG;AAAA,MACpE,MAAM;AAAA,IACR,EAAE;AAAA,EACJ;AAAA,EAEA,OAAO,OAAO,QAAmD;AAC/D,UAAM,OACJ,OAAO,WAAW,WACb,KAAK,MAAM,aAAa,QAAQ,OAAO,CAAC,IACzC;AACN,WAAO,IAAI,cAAa,CAAC,WAAW,cAAc;AAChD,UAAI,aAAa,KAAK,QAAQ;AAC5B,cAAM,IAAI,MAAM,4DAA4D,SAAS,EAAE;AAAA,MACzF;AACA,aAAO,KAAK,SAAS;AAAA,IACvB,CAAC;AAAA,EACH;AAAA,EAEA,OAAO,GACL,SAkBc;AACd,WAAO,IAAI,cAAa,OAAO,UAAU,cAAc;AACrD,YAAM,SAAS,MAAM,QAAQ,UAAU,SAAS;AAChD,aAAO;AAAA,QACL,GAAG;AAAA,QACH,OAAO,OAAO,SAAS,EAAE,eAAe,IAAI,mBAAmB,IAAI,cAAc,GAAG;AAAA,QACpF,MAAM,OAAO,QAAQ;AAAA,MACvB;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;AC/XO,IAAM,WAAN,MAAM,UAAS;AAAA,EAGpB,YACW,MACD,SACR;AAFS;AACD;AAAA,EACP;AAAA,EALK,SAA+B,CAAC;AAAA,EAOxC,IAAI,QAAQ;AACV,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,QAAQ,OAAkC;AAC9C,SAAK,OAAO,KAAK,EAAE,MAAM,CAAC;AAC1B,WAAO,KAAK,QAAQ,KAAK;AAAA,EAC3B;AAAA,EAEA,OAAO,OAAO,MAAc,SAAmE;AAC7F,WAAO,IAAI,UAAS,MAAM,OAAO;AAAA,EACnC;AACF;;;ACbA,SAAS,MAAS,OAAa;AAC7B,SAAO,gBAAgB,KAAK;AAC9B;AAEA,SAAS,aACP,SACA,eAC8B;AAC9B,QAAM,QACJ,QAAQ,MAAM,SAAS,UACnB,EAAE,GAAG,QAAQ,OAAO,MAAM,QAAQ,MAAM,KAAK,MAAM,EAAE,IACrD,EAAE,GAAG,QAAQ,MAAM;AACzB,SAAO;AAAA,IACL,OAAO,QAAQ;AAAA,IACf;AAAA,IACA,GAAI,QAAQ,aAAa,SAAY,EAAE,UAAU,QAAQ,SAAS,IAAI,CAAC;AAAA,IACvE,GAAI,QAAQ,eAAe,SAAY,EAAE,YAAY,QAAQ,WAAW,IAAI,CAAC;AAAA,IAC7E,GAAI,QAAQ,gBAAgB,SAAY,EAAE,aAAa,QAAQ,YAAY,IAAI,CAAC;AAAA,IAChF,GAAI,QAAQ,kBAAkB,EAAE,iBAAiB,MAAM,QAAQ,eAAe,EAAE,IAAI,CAAC;AAAA,IACrF,GAAI,iBAAiB,QAAQ,SAAS,EAAE,QAAQ,QAAQ,OAAO,IAAI,CAAC;AAAA,EACtE;AACF;AAIO,IAAM,4BAAN,MAAM,2BAA2D;AAAA,EAGtE,YACmB,UAIA,kBAE4B,OAAO;AAAA,IAClD,SAAS,CAAC,SAAS,UAAU,eAAe;AAAA,IAC5C,YAAY,CAAC,WAAW,MAAM;AAAA,IAC9B,aAAa;AAAA,EACf,IACA;AAXiB;AAIA;AAAA,EAOhB;AAAA,EAdK,SAAyC,CAAC;AAAA,EAgBlD,IAAI,QAAiD;AACnD,WAAO,KAAK,OAAO,IAAI,KAAK;AAAA,EAC9B;AAAA,EAEA,aAAa,OAAsD;AACjE,WAAO,KAAK,gBAAgB,KAAK;AAAA,EACnC;AAAA,EAEA,MAAM,WAAW,SAA6E;AAG5F,UAAM,WAAW,aAAa,SAAS,KAAK;AAC5C,SAAK,OAAO,KAAK,QAAQ;AACzB,WAAO,MAAM,MAAM,KAAK,SAAS,aAAa,SAAS,IAAI,GAAG,KAAK,OAAO,SAAS,CAAC,CAAC;AAAA,EACvF;AAAA,EAEA,OAAO,KAAK,MAAyC;AACnD,WAAO,IAAI,2BAA0B,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,EAAE;AAAA,EACvE;AACF;;;ACtDA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AA0BP,SAAS,sBAA8B;AACrC,SAAO,QAAQ,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,EAAE,CAAC;AACtE;AAEA,SAAS,mBAAmB,OAAc,OAAuB;AAC/D,MAAI,UAAU,UAAa,UAAU,SAAS,WAAW,MAAO,QAAO;AACvE,SAAO,eAAe,OAAO,SAAS;AAAA,IACpC,cAAc;AAAA,IACd,YAAY;AAAA,IACZ,OAAO;AAAA,EACT,CAAC;AACD,SAAO;AACT;AAWO,IAAM,iBAAN,MAAqB;AAAA,EAClB,YAAY,oBAAI,IAAyB;AAAA,EACzC,gBAAgB,oBAAI,IAA0B;AAAA,EAC9C,6BAA6B,oBAAI,IAAuC;AAAA,EACxE,cAAc,oBAAI,IAAsB;AAAA,EACxC,aAAiC,CAAC;AAAA,EAClC,cAAmC,CAAC;AAAA,EACpC,SAAyB,CAAC;AAAA,EAC1B,YAAwB,CAAC;AAAA,EACzB,aAAa;AAAA,EACb,YAAY;AAAA,EACZ,eAAe;AAAA,EACf;AAAA,EACA,WAA+B,CAAC;AAAA,EAChC,eAAuB,oBAAoB;AAAA,EAC3C;AAAA,EACA;AAAA,EAER,YAAY,SAAiC;AAC3C,SAAK,aAAa,SAAS;AAC3B,SAAK,wBAAwB,SAAS;AACtC,SAAK,UAAU,SAAS,UAAU,CAAC;AAAA,EACrC;AAAA,EAEA,SAAS,UAA6B;AACpC,SAAK,UAAU,IAAI,SAAS,MAAM,QAAQ;AAAA,EAC5C;AAAA,EAEA,aAAa,MAAc,UAA8B;AACvD,SAAK,cAAc,IAAI,MAAM,QAAQ;AAAA,EACvC;AAAA,EAEA,0BAA0B,MAAc,UAA2C;AACjF,SAAK,2BAA2B,IAAI,MAAM,QAAQ;AAAA,EACpD;AAAA,EAEA,SACE,MACA,SACM;AAIN,SAAK,YAAY,IAAI,MAAM,SAAS,OAAO,MAAM,OAAsC,CAAC;AAAA,EAC1F;AAAA,EAEA,MAAM,QACJ,cACA,OACA,SAKkB;AAClB,UAAM,WAAW,KAAK,UAAU,IAAI,YAAY;AAChD,QAAI,CAAC,SAAU,OAAM,IAAI,MAAM,aAAa,YAAY,kBAAkB;AAG1E,SAAK,aAAa,CAAC;AACnB,SAAK,cAAc,CAAC;AACpB,SAAK,SAAS,CAAC;AACf,SAAK,YAAY,CAAC;AAClB,SAAK,aAAa;AAClB,SAAK,YAAY;AACjB,SAAK,eAAe;AACpB,SAAK,WAAW,CAAC;AACjB,SAAK,eAAe,oBAAoB;AAExC,UAAM,YAAY,SAAS,YAAY,MAAM,KAAK;AAGlD,UAAM,WAAW,IAAI,iBAAiB;AACtC,aAAS,eAAe;AACxB,eAAW,CAAC,MAAM,QAAQ,KAAK,KAAK,eAAe;AACjD,eAAS,iBAAiB,MAAM,QAAQ;AAAA,IAC1C;AACA,UAAM,wBAAwB,IAAI,8BAA8B;AAChE,eAAW,CAAC,MAAM,QAAQ,KAAK,KAAK,4BAA4B;AAC9D,4BAAsB,iBAAiB,MAAM,QAAQ;AAAA,IACvD;AAEA,UAAM,kBAAkB,KAAK,cAAc,IAAI,SAAS;AACxD,QAAI,iBAAiB;AACnB,eAAS,YAAY,eAAe;AAAA,IACtC,WAAW,KAAK,cAAc,SAAS,GAAG;AACxC,YAAM,eAAe,KAAK,cAAc,OAAO,EAAE,KAAK,EAAE;AACxD,eAAS,YAAY,YAAY;AAAA,IACnC;AAGA,UAAM,gBAAgB,oBAAI,IAAiD;AAC3E,eAAW,CAAC,MAAM,QAAQ,KAAK,KAAK,aAAa;AAC/C,oBAAc,IAAI,MAAM,OAAO,SAAkB;AAC/C,eAAO,SAAS,QAAQ,IAAI;AAAA,MAC9B,CAAC;AAAA,IACH;AAWA,UAAM,OAA4B;AAAA,MAChC,OAAO;AAAA,MACP,aAAa,KAAK;AAAA,MAClB,UAAU,SAAS;AAAA;AAAA;AAAA,MAGnB,QAAQ,KAAK;AAAA;AAAA;AAAA,MAGb,oBAAoB,SAAS;AAAA,MAC7B,sBAAsB,SAAS;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAM/B;AAAA,MACA,kBAAkB;AAAA,MAClB,+BAA+B;AAAA,MAC/B,YAAY,IAAI,YAAY;AAAA,MAC5B,eAAe,cAAc,OAAO,IAAI,gBAAgB;AAAA,MACxD,mBAAmB,KAAK,wBACpB,CAAC,SAA4B,KAAK,sBAAuB,IAAI,IAC7D;AAAA,MACJ,SAAS,CAAC,UAAoB;AAC5B,aAAK,UAAU,KAAK,KAAK;AACzB,aAAK;AACL,aAAK,OAAO,KAAK;AAAA,UACf,MAAM,KAAK;AAAA,UACX,MAAM,MAAM;AAAA,UACZ,MAAO,MAA6B;AAAA,QACtC,CAAC;AAED,YAAI,MAAM,SAAS,iBAAiB;AAClC,gBAAM,EAAE,MAAM,eAAe,QAAQ,IAAI,MAAM;AAC/C,eAAK,WAAW,KAAK;AAAA,YACnB,MAAM,MAAM;AAAA,YACZ,aAAa,MAAM;AAAA,YACnB,OAAO,MAAM;AAAA,YACb,QAAQ,MAAM;AAAA,YACd;AAAA,YACA,GAAI,kBAAkB,SAAY,EAAE,cAAc,IAAI,CAAC;AAAA,YACvD;AAAA,UACF,CAAC;AAAA,QACH;AAIA,aAAK,cAAc,sBAAsB,KAAK;AAE9C,YAAI,eAAe,KAAK,EAAG,MAAK,YAAY;AAG5C,YAAI,MAAM,SAAS,oBAAoB,MAAM,MAAM;AACjD,gBAAM,EAAE,SAAS,IAAI,MAAM;AAC3B,cAAI,aAAa,QAAW;AAC1B,iBAAK,SAAS,KAAK;AAAA,cACjB,SAAS;AAAA,cACT,OAAO,MAAM,SACT;AAAA,gBACE,eAAe,MAAM,OAAO,SAAS;AAAA,gBACrC,mBAAmB,MAAM,OAAO,UAAU;AAAA,gBAC1C,eACG,MAAM,OAAO,SAAS,MACtB,MAAM,OAAO,UAAU,MACvB,MAAM,OAAO,aAAa;AAAA,gBAC7B,GAAI,MAAM,OAAO,cAAc,SAC3B,EAAE,kBAAkB,MAAM,OAAO,UAAU,IAC3C,CAAC;AAAA,cACP,IACA,EAAE,eAAe,GAAG,mBAAmB,GAAG,cAAc,EAAE;AAAA,cAC9D,GAAI,MAAM,SAAS,SAAY,EAAE,MAAM,MAAM,KAAK,IAAI,CAAC;AAAA,YACzD,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF;AAAA,MACA,qBAAqB,CAAC,SAAwB;AAC5C,aAAK,YAAY,KAAK,IAAI;AAAA,MAC5B;AAAA,IACF;AAEA,UAAM,MAAM,IAAI,gBAAgB,IAAI;AAQpC,UAAM,YAAY,KAAK,IAAI;AAC3B,QAAI,mBAAmB,SAAS;AAChC,QAAI;AACF,YAAM,SAAS,MAAM,SAAS,QAAQ,GAAG;AACzC,YAAM,cAAc,MAAM,IAAI,iBAAiB;AAG/C,UAAI,SAAS,aAAc,UAAS,aAAa,MAAM,MAAM;AAE7D,UAAI,iBAAiB;AAAA,QACnB,QAAQ;AAAA,QACR,UAAU,KAAK,IAAI,IAAI;AAAA,QACvB;AAAA,QACA;AAAA,MACF,CAAC;AAKD,UAAI,KAAK,WAAY,OAAM,KAAK,gBAAgB;AAChD,aAAO;AAAA,IACT,SAAS,KAAK;AACZ,UAAI,gBAAgB;AACpB,UAAI,cAAiC,EAAE,UAAU,KAAK;AACtD,UAAI;AACF,sBAAc,MAAM,IAAI,iBAAiB;AAAA,MAC3C,SAAS,YAAY;AACnB,wBACE,sBAAsB,QAAQ,mBAAmB,YAAY,aAAa,IAAI;AAAA,MAClF;AAKA,YAAM,UACJ,OAAO,kBAAkB,YACzB,kBAAkB,QACjB,cAAqC,SAAS;AACjD,UAAI,iBAAiB;AAAA,QACnB,QAAQ;AAAA,QACR,UAAU,KAAK,IAAI,IAAI;AAAA,QACvB,OAAO,yBAAyB,QAAQ,cAAc,UAAU,OAAO,aAAa;AAAA,QACpF,GAAI,UAAU,EAAE,SAAS,KAAK,IAAI,CAAC;AAAA,QACnC;AAAA,MACF,CAAC;AAED,YAAM;AAAA,IACR;AAAA,EACF;AAAA,EAEA,UAAU,MAAmC;AAC3C,WAAO,OAAO,KAAK,WAAW,OAAO,CAAC,MAAM,EAAE,SAAS,IAAI,IAAI,KAAK;AAAA,EACtE;AAAA,EAEA,WAAW,MAAoC;AAC7C,WAAO,OAAO,KAAK,YAAY,OAAO,CAAC,MAAM,EAAE,UAAU,IAAI,IAAI,KAAK;AAAA,EACxE;AAAA,EAEA,YAAoB;AAClB,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA,EAGA,WAAoB;AAClB,WAAO,KAAK;AAAA,EACd;AAAA,EACA,QAAwB;AACtB,WAAO,KAAK;AAAA,EACd;AAAA,EACA,WAAuB;AACrB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAc,kBAAiC;AAC7C,QAAI,CAAC,KAAK,WAAY;AACtB,UAAM,EAAE,WAAW,MAAM,IAAI,MAAM,OAAO,aAAkB;AAC5D,UAAM,EAAE,QAAQ,IAAI,MAAM,OAAO,MAAW;AAC5C,UAAM,MAAM,QAAQ,KAAK,UAAU,GAAG,EAAE,WAAW,KAAK,CAAC;AACzD,UAAM,UAAU,KAAK,YAAY,KAAK,UAAU,KAAK,UAAU,MAAM,CAAC,GAAG,MAAM;AAAA,EACjF;AACF;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@axlsdk/testing",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.22.0",
|
|
4
4
|
"description": "Testing utilities for Axl agentic workflows",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"dist"
|
|
23
23
|
],
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@axlsdk/axl": "0.
|
|
25
|
+
"@axlsdk/axl": "0.22.0"
|
|
26
26
|
},
|
|
27
27
|
"peerDependencies": {
|
|
28
28
|
"zod": "^4.0.0"
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"access": "public"
|
|
55
55
|
},
|
|
56
56
|
"engines": {
|
|
57
|
-
"node": ">=
|
|
57
|
+
"node": ">=22.0.0"
|
|
58
58
|
},
|
|
59
59
|
"scripts": {
|
|
60
60
|
"build": "tsup",
|