@axlsdk/testing 0.22.1 → 0.22.3

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 CHANGED
@@ -66,6 +66,15 @@ const provider = MockProvider.fn(() => ({
66
66
  usage: { prompt_tokens: 120, completion_tokens: 200, total_tokens: 320 },
67
67
  cost: 0.005,
68
68
  }));
69
+
70
+ // Report a clamped `effort`, so the runtime emits a `provider_diagnostic`
71
+ // event (and its deduped warn) exactly as a real adapter would.
72
+ const provider = MockProvider.echo().withEffortResolution({
73
+ requested: 'none',
74
+ effective: 'minimal',
75
+ clamped: true,
76
+ cause: 'this model cannot disable thinking',
77
+ });
69
78
  ```
70
79
 
71
80
  MockProvider also supports tool call simulation:
package/dist/index.cjs CHANGED
@@ -180,6 +180,29 @@ var MockProvider = class _MockProvider {
180
180
  * Set via `provider.chunkDelayMs = 50` after construction. Not part of
181
181
  * any factory's surface to keep the test API minimal. */
182
182
  chunkDelayMs = 0;
183
+ /** How this mock reports the unified `effort` it was asked for. Undefined (the
184
+ * default) means the mock implements no `effortResolution` at all, so the
185
+ * runtime emits no `provider_diagnostic`. Set it with
186
+ * {@link MockProvider.withEffortResolution} to drive the clamp-reporting path. */
187
+ effortResolution;
188
+ /**
189
+ * Make this mock report an effort clamp, so a test can exercise the runtime's
190
+ * `provider_diagnostic` path without a real adapter. Pass a fixed
191
+ * {@link EffortResolution} or a function of the request knobs.
192
+ *
193
+ * ```ts
194
+ * const provider = MockProvider.echo().withEffortResolution({
195
+ * requested: 'none',
196
+ * effective: 'minimal',
197
+ * clamped: true,
198
+ * cause: 'this model cannot disable thinking',
199
+ * });
200
+ * ```
201
+ */
202
+ withEffortResolution(resolution) {
203
+ this.effortResolution = typeof resolution === "function" ? resolution : () => resolution;
204
+ return this;
205
+ }
183
206
  get calls() {
184
207
  return this._calls;
185
208
  }
@@ -1 +1 @@
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"]}
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 EffortResolution,\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 /** How this mock reports the unified `effort` it was asked for. Undefined (the\n * default) means the mock implements no `effortResolution` at all, so the\n * runtime emits no `provider_diagnostic`. Set it with\n * {@link MockProvider.withEffortResolution} to drive the clamp-reporting path. */\n effortResolution?: (\n options: Pick<\n ChatOptions,\n 'model' | 'effort' | 'thinkingBudget' | 'includeThoughts' | 'providerOptions'\n >,\n ) => EffortResolution | undefined;\n\n /**\n * Make this mock report an effort clamp, so a test can exercise the runtime's\n * `provider_diagnostic` path without a real adapter. Pass a fixed\n * {@link EffortResolution} or a function of the request knobs.\n *\n * ```ts\n * const provider = MockProvider.echo().withEffortResolution({\n * requested: 'none',\n * effective: 'minimal',\n * clamped: true,\n * cause: 'this model cannot disable thinking',\n * });\n * ```\n */\n withEffortResolution(\n resolution:\n | EffortResolution\n | undefined\n | ((\n options: Pick<\n ChatOptions,\n 'model' | 'effort' | 'thinkingBudget' | 'includeThoughts' | 'providerOptions'\n >,\n ) => EffortResolution | undefined),\n ): this {\n this.effortResolution = typeof resolution === 'function' ? resolution : () => resolution;\n return this;\n }\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, InputMediaSource, ProviderInputValidationRequest, ProviderInputValidationResult, StreamChunk, ToolCallMessage, TranscriptionProvider, TranscriptionProviderRequest, TranscriptionProviderResult, TranscriptionCapabilities, AwaitHumanOptions, HumanDecision, AxlConfig, AnyWorkflow, EventStreamOptions, ToolCallOutcome, AgentCallInfo, AxlEvent } from '@axlsdk/axl';
1
+ import { Provider, ChatOptions, EffortResolution, ChatMessage, 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;
@@ -17,6 +17,26 @@ declare class MockProvider implements Provider {
17
17
  * Set via `provider.chunkDelayMs = 50` after construction. Not part of
18
18
  * any factory's surface to keep the test API minimal. */
19
19
  chunkDelayMs: number;
20
+ /** How this mock reports the unified `effort` it was asked for. Undefined (the
21
+ * default) means the mock implements no `effortResolution` at all, so the
22
+ * runtime emits no `provider_diagnostic`. Set it with
23
+ * {@link MockProvider.withEffortResolution} to drive the clamp-reporting path. */
24
+ effortResolution?: (options: Pick<ChatOptions, 'model' | 'effort' | 'thinkingBudget' | 'includeThoughts' | 'providerOptions'>) => EffortResolution | undefined;
25
+ /**
26
+ * Make this mock report an effort clamp, so a test can exercise the runtime's
27
+ * `provider_diagnostic` path without a real adapter. Pass a fixed
28
+ * {@link EffortResolution} or a function of the request knobs.
29
+ *
30
+ * ```ts
31
+ * const provider = MockProvider.echo().withEffortResolution({
32
+ * requested: 'none',
33
+ * effective: 'minimal',
34
+ * clamped: true,
35
+ * cause: 'this model cannot disable thinking',
36
+ * });
37
+ * ```
38
+ */
39
+ withEffortResolution(resolution: EffortResolution | undefined | ((options: Pick<ChatOptions, 'model' | 'effort' | 'thinkingBudget' | 'includeThoughts' | 'providerOptions'>) => EffortResolution | undefined)): this;
20
40
  private constructor();
21
41
  get calls(): {
22
42
  messages: ChatMessage[];
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
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';
1
+ import { Provider, ChatOptions, EffortResolution, ChatMessage, 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;
@@ -17,6 +17,26 @@ declare class MockProvider implements Provider {
17
17
  * Set via `provider.chunkDelayMs = 50` after construction. Not part of
18
18
  * any factory's surface to keep the test API minimal. */
19
19
  chunkDelayMs: number;
20
+ /** How this mock reports the unified `effort` it was asked for. Undefined (the
21
+ * default) means the mock implements no `effortResolution` at all, so the
22
+ * runtime emits no `provider_diagnostic`. Set it with
23
+ * {@link MockProvider.withEffortResolution} to drive the clamp-reporting path. */
24
+ effortResolution?: (options: Pick<ChatOptions, 'model' | 'effort' | 'thinkingBudget' | 'includeThoughts' | 'providerOptions'>) => EffortResolution | undefined;
25
+ /**
26
+ * Make this mock report an effort clamp, so a test can exercise the runtime's
27
+ * `provider_diagnostic` path without a real adapter. Pass a fixed
28
+ * {@link EffortResolution} or a function of the request knobs.
29
+ *
30
+ * ```ts
31
+ * const provider = MockProvider.echo().withEffortResolution({
32
+ * requested: 'none',
33
+ * effective: 'minimal',
34
+ * clamped: true,
35
+ * cause: 'this model cannot disable thinking',
36
+ * });
37
+ * ```
38
+ */
39
+ withEffortResolution(resolution: EffortResolution | undefined | ((options: Pick<ChatOptions, 'model' | 'effort' | 'thinkingBudget' | 'includeThoughts' | 'providerOptions'>) => EffortResolution | undefined)): this;
20
40
  private constructor();
21
41
  get calls(): {
22
42
  messages: ChatMessage[];
package/dist/index.js CHANGED
@@ -141,6 +141,29 @@ var MockProvider = class _MockProvider {
141
141
  * Set via `provider.chunkDelayMs = 50` after construction. Not part of
142
142
  * any factory's surface to keep the test API minimal. */
143
143
  chunkDelayMs = 0;
144
+ /** How this mock reports the unified `effort` it was asked for. Undefined (the
145
+ * default) means the mock implements no `effortResolution` at all, so the
146
+ * runtime emits no `provider_diagnostic`. Set it with
147
+ * {@link MockProvider.withEffortResolution} to drive the clamp-reporting path. */
148
+ effortResolution;
149
+ /**
150
+ * Make this mock report an effort clamp, so a test can exercise the runtime's
151
+ * `provider_diagnostic` path without a real adapter. Pass a fixed
152
+ * {@link EffortResolution} or a function of the request knobs.
153
+ *
154
+ * ```ts
155
+ * const provider = MockProvider.echo().withEffortResolution({
156
+ * requested: 'none',
157
+ * effective: 'minimal',
158
+ * clamped: true,
159
+ * cause: 'this model cannot disable thinking',
160
+ * });
161
+ * ```
162
+ */
163
+ withEffortResolution(resolution) {
164
+ this.effortResolution = typeof resolution === "function" ? resolution : () => resolution;
165
+ return this;
166
+ }
144
167
  get calls() {
145
168
  return this._calls;
146
169
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
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":"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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 EffortResolution,\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 /** How this mock reports the unified `effort` it was asked for. Undefined (the\n * default) means the mock implements no `effortResolution` at all, so the\n * runtime emits no `provider_diagnostic`. Set it with\n * {@link MockProvider.withEffortResolution} to drive the clamp-reporting path. */\n effortResolution?: (\n options: Pick<\n ChatOptions,\n 'model' | 'effort' | 'thinkingBudget' | 'includeThoughts' | 'providerOptions'\n >,\n ) => EffortResolution | undefined;\n\n /**\n * Make this mock report an effort clamp, so a test can exercise the runtime's\n * `provider_diagnostic` path without a real adapter. Pass a fixed\n * {@link EffortResolution} or a function of the request knobs.\n *\n * ```ts\n * const provider = MockProvider.echo().withEffortResolution({\n * requested: 'none',\n * effective: 'minimal',\n * clamped: true,\n * cause: 'this model cannot disable thinking',\n * });\n * ```\n */\n withEffortResolution(\n resolution:\n | EffortResolution\n | undefined\n | ((\n options: Pick<\n ChatOptions,\n 'model' | 'effort' | 'thinkingBudget' | 'includeThoughts' | 'providerOptions'\n >,\n ) => EffortResolution | undefined),\n ): this {\n this.effortResolution = typeof resolution === 'function' ? resolution : () => resolution;\n return this;\n }\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":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@axlsdk/testing",
3
- "version": "0.22.1",
3
+ "version": "0.22.3",
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.22.1"
25
+ "@axlsdk/axl": "0.22.3"
26
26
  },
27
27
  "peerDependencies": {
28
28
  "zod": "^4.0.0"