@botpress/evals 1.18.3 → 1.19.0-beta.10

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.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/runner.ts", "../src/client.ts", "../src/sse-collector.ts", "../src/transformer.ts", "../src/graders/llm.ts", "../src/graders/response.ts", "../src/graders/match.ts", "../src/graders/tools.ts", "../src/graders/state.ts", "../src/graders/workflow.ts", "../src/graders/timing.ts", "../src/graders/outcome.ts", "../src/loader.ts", "../src/definition.ts"],
4
- "sourcesContent": ["/**\n * Eval runner \u2014 orchestrates eval execution.\n *\n * Observation is trace-driven: SSECollector streams spans in real-time,\n * transformSpans() projects them into grader-friendly TurnData, and graders\n * are pure functions over that output. The only network calls are emitter\n * actions (sending messages, triggering workflows, seeding state, LLM judge).\n */\n\nimport { Client as BpClient } from '@botpress/client'\nimport type {\n EvalDefinition,\n EvalProgressEvent,\n EvalReport,\n EvalRunReport,\n EvalRunnerConfig,\n EvalFilter,\n GraderResult,\n TurnReport,\n BotConnection,\n EvalSetup,\n} from './types'\nimport { ChatSession, discoverWebhookId, assertChatChannelBound } from './client'\nimport { SSECollector } from './sse-collector'\nimport { transformSpans } from './transformer'\nimport { gradeResponse } from './graders/response'\nimport { gradeTools } from './graders/tools'\nimport { gradeState } from './graders/state'\nimport { gradeWorkflows } from './graders/workflow'\nimport { gradeTiming } from './graders/timing'\nimport { gradeOutcome } from './graders/outcome'\nimport { initLLMJudge } from './graders/llm'\nimport { loadEvalsFromDir, filterEvals } from './loader'\nimport { randomUUID } from 'crypto'\n\n/**\n * Run a single eval against a bot.\n */\nconst DEFAULT_IDLE_TIMEOUT = 30_000\nconst DEFAULT_DEV_SERVER_URL = 'http://localhost:3001'\nconst WORKFLOW_TRIGGER_TIMEOUT_MS = 5 * 60 * 1000\n\nconst BUILT_IN_STATES = {\n conversation: 'state',\n user: 'userState',\n bot: 'botState',\n} as const\n\nfunction buildStatePayload(value: Record<string, unknown>) {\n // `location` is required by the Botpress setState API schema.\n return {\n value,\n location: { type: 'state' as const },\n }\n}\n\nasync function seedEvalState(\n client: BpClient,\n ctx: { botId: string; userId: string; conversationId?: string },\n setup?: EvalSetup\n): Promise<void> {\n const state = setup?.state\n if (!state) return\n\n const writes: Array<Promise<unknown>> = []\n\n if (state.bot) {\n writes.push(\n client.setState({\n type: 'bot',\n id: ctx.botId,\n name: BUILT_IN_STATES.bot,\n payload: buildStatePayload(state.bot),\n })\n )\n }\n\n if (state.user) {\n writes.push(\n client.setState({\n type: 'user',\n id: ctx.userId,\n name: BUILT_IN_STATES.user,\n payload: buildStatePayload(state.user),\n })\n )\n }\n\n if (state.conversation) {\n if (!ctx.conversationId) {\n throw new Error('Cannot seed conversation state before a conversation is created.')\n }\n\n writes.push(\n client.setState({\n type: 'conversation',\n id: ctx.conversationId,\n name: BUILT_IN_STATES.conversation,\n payload: buildStatePayload(state.conversation),\n })\n )\n }\n\n await Promise.all(writes)\n}\n\nasync function triggerEvalWorkflow(\n client: BpClient,\n ctx: { userId: string; conversationId?: string },\n setup?: EvalSetup\n): Promise<void> {\n const workflow = setup?.workflow\n if (!workflow) return\n\n await client.createWorkflow({\n name: workflow.trigger,\n input: workflow.input ?? {},\n status: 'pending',\n userId: ctx.userId,\n timeoutAt: new Date(Date.now() + WORKFLOW_TRIGGER_TIMEOUT_MS).toISOString(),\n ...(ctx.conversationId !== undefined ? { conversationId: ctx.conversationId } : {}),\n })\n}\n\nfunction evalMetadata(evalDef: EvalDefinition) {\n return {\n name: evalDef.name,\n ...(evalDef.description !== undefined ? { description: evalDef.description } : {}),\n ...(evalDef.type !== undefined ? { type: evalDef.type } : {}),\n ...(evalDef.tags !== undefined ? { tags: evalDef.tags } : {}),\n }\n}\n\nexport async function runEval(\n evalDef: EvalDefinition,\n connection: BotConnection,\n options: {\n devServerUrl?: string\n idleTimeout?: number\n judgePassThreshold?: number\n onProgress?: (event: EvalProgressEvent) => void\n evalIndex?: number\n /** Forwarded from EvalRunnerConfig \u2014 lets per-turn workflow waits unblock immediately on Stop instead of burning the full idleTimeout each. */\n signal?: AbortSignal\n devServerHeaders?: Record<string, string>\n chatClient?: EvalRunnerConfig['chatClient']\n } = {}\n): Promise<EvalReport> {\n const devServerUrl = options.devServerUrl || DEFAULT_DEV_SERVER_URL\n const devServerHeaders = options.devServerHeaders ?? {}\n const idleTimeout = evalDef.options?.idleTimeout ?? options.idleTimeout ?? DEFAULT_IDLE_TIMEOUT\n const judgePassThreshold = evalDef.options?.judgePassThreshold ?? options.judgePassThreshold\n const start = Date.now()\n const turns: TurnReport[] = []\n let outcomeAssertions: GraderResult[] = []\n\n const collector = new SSECollector(devServerUrl, devServerHeaders)\n\n try {\n const session = new ChatSession(connection.webhookId, options.chatClient)\n await session.connect()\n\n let bpClient: BpClient | null = null\n const getBpClient = () => {\n if (!bpClient) {\n bpClient = new BpClient({\n token: connection.token,\n botId: connection.botId,\n apiUrl: connection.apiUrl,\n })\n }\n return bpClient\n }\n\n let conversationId = ''\n if (evalDef.setup?.state?.conversation || evalDef.setup?.workflow) {\n conversationId = await session.ensureConversation()\n }\n\n await seedEvalState(\n getBpClient(),\n {\n botId: connection.botId,\n userId: session.userId,\n ...(conversationId ? { conversationId } : {}),\n },\n evalDef.setup\n )\n\n await triggerEvalWorkflow(\n getBpClient(),\n {\n userId: session.userId,\n ...(conversationId ? { conversationId } : {}),\n },\n evalDef.setup\n )\n\n // Ensure we have a conversation before connecting the collector\n if (!conversationId && evalDef.conversation.length > 0) {\n conversationId = await session.ensureConversation()\n }\n\n // Connect the collector filtered by conversationId\n if (conversationId) {\n await collector.connect({ conversationId })\n } else if (evalDef.conversation.length > 0) {\n throw new Error('Cannot run conversation eval without a conversationId \u2014 no chat session or setup created one.')\n }\n\n for (let i = 0; i < evalDef.conversation.length; i++) {\n // Bail mid-eval the moment the caller signals abort, so a long\n // multi-turn eval doesn't keep ticking through turns after Stop.\n if (options.signal?.aborted) break\n\n const turn = evalDef.conversation[i]!\n\n if (turn.expectSilence && turn.assert?.response) {\n throw new Error(`Turn ${i + 1}: 'expectSilence' and 'assert.response' are mutually exclusive.`)\n }\n if (turn.user && turn.event) {\n throw new Error(`Turn ${i + 1}: 'user' and 'event' are mutually exclusive.`)\n }\n if (!turn.user && !turn.event) {\n throw new Error(`Turn ${i + 1}: must have either 'user' or 'event'.`)\n }\n\n const turnLabelForEvent = turn.event ? `[event: ${turn.event.type}]` : turn.user!\n options.onProgress?.({\n type: 'turn_start',\n evalName: evalDef.name,\n evalIndex: options.evalIndex ?? 0,\n turnNumber: i + 1,\n totalTurns: evalDef.conversation.length,\n userMessage: turnLabelForEvent,\n })\n\n // Mark turn boundary, emit message, wait for handler completion via traces\n collector.startTurn()\n\n if (turn.event) {\n await session.sendEvent(turn.event.type, turn.event.payload ?? {})\n } else {\n await session.sendMessage(turn.user!)\n }\n\n try {\n await collector.waitForTurnComplete({\n timeout: idleTimeout,\n ...(options.signal !== undefined ? { abortSignal: options.signal } : {}),\n })\n } catch (err) {\n // If the wait was aborted, exit the turn loop cleanly rather than\n // surfacing an error on the eval \u2014 Stop is a user action, not a\n // failure. Other errors (timeout, etc.) still propagate.\n if (options.signal?.aborted) break\n throw err\n }\n\n // Wait for per-turn workflow assertions.\n // Skip the wait for negative assertions (entered: false / completed: false) \u2014 the\n // grader will check already-collected spans, so blocking on a signal that's expected\n // not to arrive just burns the full idleTimeout per assertion.\n if (turn.assert?.workflow) {\n for (const wfAssert of turn.assert.workflow) {\n const expectsPositive = wfAssert.entered !== false && wfAssert.completed !== false\n if (!expectsPositive) continue\n const wfSignal = wfAssert.completed ? 'completed' : 'entered'\n await collector\n .waitForWorkflow(wfAssert.name, {\n signal: wfSignal,\n timeout: idleTimeout,\n ...(options.signal !== undefined ? { abortSignal: options.signal } : {}),\n })\n .catch(() => {\n // Timeout is OK \u2014 the grader will report the failure\n })\n }\n }\n\n // Transform turn spans into grader-friendly data\n const turnSpans = collector.getTurnSpans()\n const turnData = transformSpans(turnSpans)\n\n const botResponse = turnData.messages.join('\\n')\n const botDuration = turnData.handlerDuration\n const turnLabel = turn.event ? `[event: ${turn.event.type}]` : turn.user!\n\n if (!turn.expectSilence && turnData.messages.length === 0) {\n throw new Error(`Turn ${i + 1}: bot produced no response.`)\n }\n\n const evalStart = Date.now()\n let assertions: GraderResult[] = []\n\n if (turn.expectSilence) {\n const wasSilent = turnData.messages.length === 0\n assertions.push({\n assertion: 'no_response',\n pass: wasSilent,\n expected: 'No response',\n actual: wasSilent ? 'No response' : `Bot responded: \"${botResponse}\"`,\n })\n }\n\n // Response assertions\n if (turn.assert?.response) {\n assertions = await gradeResponse(botResponse, turn.assert.response, {\n userMessage: turnLabel,\n ...(judgePassThreshold !== undefined ? { judgePassThreshold } : {}),\n })\n }\n\n // Tool assertions from turn spans\n if (turn.assert?.tools) {\n const toolResults = gradeTools(turnData.toolCalls, turn.assert.tools)\n assertions = [...assertions, ...toolResults]\n }\n\n // Per-turn state assertions\n if (turn.assert?.state) {\n try {\n const stateResults = gradeState(turnData.stateMutations, turn.assert.state)\n assertions.push(...stateResults)\n } catch (err) {\n assertions.push({\n assertion: 'state',\n pass: false,\n expected: 'State assertions executed',\n actual: `Error: ${(err as Error).message}`,\n })\n }\n }\n\n // Per-turn workflow assertions\n if (turn.assert?.workflow) {\n const workflowResults = gradeWorkflows(turnData.workflowSpans, turn.assert.workflow)\n assertions.push(...workflowResults)\n }\n\n // Per-turn timing assertions\n if (turn.assert?.timing) {\n const timingResults = gradeTiming(botDuration, turn.assert.timing)\n assertions.push(...timingResults)\n }\n\n const turnPass = assertions.every((a) => a.pass)\n\n const evalDuration = Date.now() - evalStart\n\n const turnReport: TurnReport = {\n turnNumber: i + 1,\n userMessage: turnLabel,\n botResponse,\n assertions,\n pass: turnPass,\n botDuration,\n evalDuration,\n }\n turns.push(turnReport)\n\n options.onProgress?.({\n type: 'turn_complete',\n evalName: evalDef.name,\n evalIndex: options.evalIndex ?? 0,\n turnNumber: i + 1,\n totalTurns: evalDef.conversation.length,\n turnReport,\n })\n }\n\n // Outcome assertions (after all turns)\n if (evalDef.outcome && !options.signal?.aborted) {\n // Wait for outcome-level workflow assertions. Same negative-assertion gate as the per-turn loop.\n if (evalDef.outcome.workflow) {\n for (const wfAssert of evalDef.outcome.workflow) {\n const expectsPositive = wfAssert.entered !== false && wfAssert.completed !== false\n if (!expectsPositive) continue\n const wfSignal = wfAssert.completed ? 'completed' : 'entered'\n await collector\n .waitForWorkflow(wfAssert.name, {\n signal: wfSignal,\n timeout: idleTimeout,\n ...(options.signal !== undefined ? { abortSignal: options.signal } : {}),\n })\n .catch(() => {\n // Timeout is OK \u2014 the grader will report the failure\n })\n }\n }\n\n try {\n const allTurnData = transformSpans(collector.getAllSpans())\n outcomeAssertions = gradeOutcome(allTurnData.stateMutations, evalDef, allTurnData.workflowSpans)\n } catch (err) {\n outcomeAssertions = [\n {\n assertion: 'outcome',\n pass: false,\n expected: 'Outcome assertions executed',\n actual: `Error: ${(err as Error).message}`,\n },\n ]\n }\n }\n\n const aborted = options.signal?.aborted === true\n const turnsPass = turns.every((t) => t.pass)\n const outcomePass = outcomeAssertions.every((a) => a.pass)\n\n return {\n ...evalMetadata(evalDef),\n turns,\n outcomeAssertions,\n pass: !aborted && turnsPass && outcomePass,\n duration: Date.now() - start,\n ...(aborted ? { error: 'Eval aborted' } : {}),\n }\n } catch (err) {\n return {\n ...evalMetadata(evalDef),\n turns,\n outcomeAssertions,\n pass: false,\n duration: Date.now() - start,\n error: (err as Error).message,\n }\n } finally {\n collector.disconnect()\n }\n}\n\n/**\n * Run a suite of evals.\n */\nexport async function runEvalSuite(config: EvalRunnerConfig, filter?: EvalFilter): Promise<EvalRunReport> {\n const start = Date.now()\n const runId = randomUUID().replace(/-/g, '').slice(0, 26)\n\n // Load eval definitions\n const evalsDir = `${config.agentPath}/evals`\n const allEvals = await loadEvalsFromDir(evalsDir)\n const evals = filterEvals(allEvals, filter)\n\n if (evals.length === 0) {\n return {\n id: runId,\n timestamp: new Date().toISOString(),\n evals: [],\n passed: 0,\n failed: 0,\n total: 0,\n duration: 0,\n ...(filter !== undefined ? { filter } : {}),\n }\n }\n\n // Initialize the LLM judge with credentials\n await initLLMJudge(\n {\n token: config.credentials.token,\n apiUrl: config.credentials.apiUrl,\n botId: config.credentials.botId,\n ...(config.credentials.workspaceId !== undefined ? { workspaceId: config.credentials.workspaceId } : {}),\n },\n {\n ...(config.evalOptions?.judgeModel !== undefined ? { model: config.evalOptions.judgeModel } : {}),\n ...(config.logger !== undefined ? { logger: config.logger } : {}),\n }\n )\n\n // Discover webhookId if not provided\n let webhookId = config.credentials.webhookId\n if (!webhookId) {\n webhookId = await discoverWebhookId(config.credentials.botId, config.credentials.token, config.credentials.apiUrl)\n }\n\n const connection: BotConnection = {\n webhookId,\n botId: config.credentials.botId,\n token: config.credentials.token,\n apiUrl: config.credentials.apiUrl,\n }\n\n const devServerUrl = config.devServerUrl || DEFAULT_DEV_SERVER_URL\n const devServerHeaders = config.devServerHeaders ?? {}\n\n // Fast-fail if no Conversation listens on chat.channel \u2014 otherwise evals time out silently.\n await assertChatChannelBound(devServerUrl, devServerHeaders)\n\n const reports: EvalReport[] = []\n\n config.onProgress?.({ type: 'suite_start', totalEvals: evals.length })\n\n for (let i = 0; i < evals.length; i++) {\n // Stop starting new evals if the caller aborted. The eval loop only\n // checks between evals \u2014 an in-flight eval (with possibly in-flight LLM\n // calls) finishes naturally because those calls can't always be cancelled\n // mid-flight.\n if (config.signal?.aborted) break\n\n const evalDef = evals[i]!\n config.onProgress?.({\n type: 'eval_start',\n evalName: evalDef.name,\n index: i,\n totalTurns: evalDef.conversation.length,\n })\n\n const report = await runEval(evalDef, connection, {\n devServerUrl,\n devServerHeaders,\n evalIndex: i,\n ...(config.evalOptions?.idleTimeout !== undefined ? { idleTimeout: config.evalOptions.idleTimeout } : {}),\n ...(config.evalOptions?.judgePassThreshold !== undefined\n ? { judgePassThreshold: config.evalOptions.judgePassThreshold }\n : {}),\n ...(config.onProgress !== undefined ? { onProgress: config.onProgress } : {}),\n ...(config.signal !== undefined ? { signal: config.signal } : {}),\n ...(config.chatClient !== undefined ? { chatClient: config.chatClient } : {}),\n })\n reports.push(report)\n\n config.onProgress?.({ type: 'eval_complete', evalName: evalDef.name, index: i, report })\n }\n\n const runReport: EvalRunReport = {\n id: runId,\n timestamp: new Date().toISOString(),\n evals: reports,\n passed: reports.filter((r) => r.pass).length,\n failed: reports.filter((r) => !r.pass).length,\n total: reports.length,\n duration: Date.now() - start,\n ...(filter !== undefined ? { filter } : {}),\n }\n\n if (config.signal?.aborted) {\n runReport.aborted = true\n }\n\n config.onProgress?.({ type: 'suite_complete', report: runReport })\n\n return runReport\n}\n", "/**\n * Chat client for eval conversations.\n * Drives conversations against a running ADK bot via @botpress/chat.\n *\n * This is a send-only client. Observation (bot responses, tool calls, state)\n * is handled by the SSECollector via trace spans \u2014 not via WebSocket listeners.\n */\n\nimport { Client as BpClient } from '@botpress/client'\nimport { createRequire } from 'module'\nimport type { ChatClient, ChatClientConnection } from './types'\n\nlet defaultChatClient: ChatClient | null = null\n\nexport function setDefaultChatClient(chatClient: ChatClient | null): void {\n defaultChatClient = chatClient\n}\n\nfunction getDefaultChatClient(): ChatClient {\n if (defaultChatClient) return defaultChatClient\n\n const require = createRequire(import.meta.url)\n const mod = require('@botpress/chat') as { Client?: ChatClient; default?: { Client?: ChatClient } }\n const ChatClient = mod.default?.Client ?? mod.Client\n if (!ChatClient) {\n throw new Error('@botpress/chat did not expose a Client export. Pass EvalRunnerConfig.chatClient explicitly.')\n }\n return ChatClient\n}\n\n/**\n * A send-only chat session that maintains a single client connection across turns.\n * Messages and events are fire-and-forget; the SSECollector observes results via traces.\n */\nexport class ChatSession {\n private client: ChatClientConnection | null = null\n private conversationId: string | null = null\n\n constructor(\n private webhookId: string,\n private chatClient?: ChatClient\n ) {}\n\n async connect() {\n const ChatClient = this.chatClient ?? getDefaultChatClient()\n this.client = await ChatClient.connect({ webhookId: this.webhookId })\n }\n\n get userId(): string {\n if (!this.client) {\n throw new Error('ChatSession not connected. Call connect() first.')\n }\n return this.client.user.id\n }\n\n async ensureConversation(): Promise<string> {\n if (!this.client) {\n throw new Error('ChatSession not connected. Call connect() first.')\n }\n\n if (!this.conversationId) {\n const conv = await this.client.createConversation({})\n this.conversationId = conv.conversation.id\n return conv.conversation.id\n }\n\n return this.conversationId\n }\n\n /**\n * Send a user message. Fire-and-forget \u2014 observation is via SSECollector.\n */\n async sendMessage(message: string): Promise<void> {\n if (!this.client) {\n throw new Error('ChatSession not connected. Call connect() first.')\n }\n\n const conversationId = await this.ensureConversation()\n await this.client.createMessage({ conversationId, payload: { type: 'text', text: message } })\n }\n\n /**\n * Send an event. Fire-and-forget \u2014 observation is via SSECollector.\n */\n async sendEvent(type: string, payload: Record<string, unknown>): Promise<void> {\n if (!this.client) {\n throw new Error('ChatSession not connected. Call connect() first.')\n }\n\n const conversationId = await this.ensureConversation()\n await this.client.createEvent({ type, payload, conversationId })\n }\n}\n\n/**\n * Discover the chat integration's webhookId from a bot.\n *\n * Evals talk to the bot through the `chat` integration (via @botpress/chat).\n * If the bot doesn't have that integration installed, evals can't run.\n */\nexport async function discoverWebhookId(botId: string, token: string, apiUrl: string): Promise<string> {\n const client = new BpClient({ token, botId, apiUrl })\n const { bot } = await client.getBot({ id: botId })\n const integrations = bot.integrations || {}\n\n const chat = Object.values(integrations).find((int) => (int as Record<string, unknown>).name === 'chat')\n const webhookId = (chat as Record<string, unknown> | undefined)?.webhookId\n\n if (!webhookId || typeof webhookId !== 'string') {\n throw new Error(\n [\n 'The `chat` integration is not installed on this bot \u2014 evals require it.',\n '',\n 'To fix:',\n ' 1. Install it: adk add chat',\n ' 2. Redeploy: adk dev (or: adk deploy)',\n ].join('\\n')\n )\n }\n\n return webhookId\n}\n\n/**\n * Verify the bot has at least one Conversation bound to `chat.channel`.\n *\n * The `chat` integration can be installed without any handler listening on its\n * channel \u2014 in that case messages sent via @botpress/chat produce no response\n * and the caller times out silently. Fail fast with actionable guidance instead.\n *\n * Uses the dev server's `/api/agent` endpoint, so this is a no-op against\n * production bots (no devServerUrl).\n */\nexport async function assertChatChannelBound(\n devServerUrl: string,\n headers: Record<string, string> = {}\n): Promise<void> {\n type ConversationSummary = { channel?: string | string[] }\n let conversations: ConversationSummary[] = []\n try {\n const res = await fetch(`${devServerUrl}/api/agent`, { headers })\n if (!res.ok) return // Dev server unreachable \u2014 skip, let downstream errors surface\n const agent = (await res.json()) as { conversations?: ConversationSummary[] }\n conversations = agent.conversations ?? []\n } catch {\n return // Network error \u2014 skip check\n }\n\n if (conversations.length === 0) return // Bot has no conversations at all \u2014 different problem\n\n // Mirrors the runtime's matchesChannel semantics: a handler matches `chat.channel`\n // if it is the wildcard '*', the literal string 'chat.channel', or an array\n // containing either.\n const matchesChatChannel = (ch: string | string[] | undefined): boolean => {\n if (!ch) return false\n if (ch === '*' || ch === 'chat.channel') return true\n return Array.isArray(ch) && (ch.includes('chat.channel') || ch.includes('*'))\n }\n\n const bound = conversations.some((c) => matchesChatChannel(c.channel))\n if (bound) return\n\n throw new Error(\n [\n 'No Conversation is bound to `chat.channel` \u2014 messages via `@botpress/chat` will time out silently.',\n '',\n 'To fix, bind a Conversation in `src/conversations/` to `chat.channel` (or `*`):',\n \" channel: 'chat.channel', // explicit\",\n \" channel: '*', // wildcard \u2014 matches every channel\",\n \" channel: ['chat.channel', ...], // array form\",\n '',\n 'The `chat` integration is how evals and `adk chat --single` send messages programmatically.',\n ].join('\\n')\n )\n}\n", "/**\n * SSECollector \u2014 connects to the ADK dev server's SSE trace stream,\n * accumulates spans, and provides promise-based wait methods for\n * turn completion and workflow signals.\n *\n * Uses fetch() + async iteration with manual SSE line parsing\n * (Bun does not have native EventSource).\n */\n\nimport type { Span } from './trace'\n\ntype SSEFilter = { conversationId: string } | { workflowId: string }\n\ninterface WaitOptions {\n timeout: number\n /**\n * Optional abort signal \u2014 when fired, the wait rejects immediately rather\n * than burning the full timeout. Used by the runner so Stop unblocks\n * pending workflow assertions (otherwise a single negative-result wait\n * can hold the suite hostage for `idleTimeout` per assertion).\n */\n abortSignal?: AbortSignal\n}\n\ninterface WorkflowWaitOptions extends WaitOptions {\n signal: 'entered' | 'completed'\n}\n\n/**\n * Unique key for span deduplication.\n */\nfunction spanKey(span: Span): string {\n return `${span.id.trace}:${span.id.span}`\n}\n\n/**\n * Type-safe accessor for span.data fields.\n */\nfunction spanData(span: Span): Record<string, unknown> {\n return span.data && typeof span.data === 'object' ? (span.data as Record<string, unknown>) : {}\n}\n\nexport class SSECollector {\n private devServerUrl: string\n private headers: Record<string, string>\n\n /** All spans accumulated since connect(), keyed by spanKey for dedup. */\n private spanMap = new Map<string, Span>()\n\n /** Index into spanMap insertion order marking where the current turn started. */\n private turnStartKeys = new Set<string>()\n\n /** Handler span IDs seen before the current turn (for startTurn filtering). */\n private seenHandlerKeys = new Set<string>()\n\n /** Callbacks waiting for span updates. */\n private waiters: Array<(span: Span) => void> = []\n\n /** AbortController for the active SSE connection. */\n private abortController: AbortController | null = null\n\n /** Whether the background loop is running. */\n private connected = false\n\n /** Error from the SSE stream if it died unexpectedly. */\n private streamError: Error | null = null\n\n /** Set while a settle phase is in flight; called by disconnect() to short-circuit. */\n private _cancelSettle: (() => void) | null = null\n\n constructor(devServerUrl: string, headers: Record<string, string> = {}) {\n this.devServerUrl = devServerUrl\n this.headers = headers\n }\n\n /**\n * Open a streaming SSE connection filtered by conversationId or workflowId.\n * Starts a background loop that parses SSE events and accumulates spans.\n */\n async connect(filter: SSEFilter): Promise<void> {\n const attributeName = 'conversationId' in filter ? 'conversationId' : 'workflowId'\n const attributeValue = 'conversationId' in filter ? filter.conversationId : filter.workflowId\n\n const url = `${this.devServerUrl}/api/traces/stream?attributeName=${encodeURIComponent(attributeName)}&attributeValue=${encodeURIComponent(attributeValue)}`\n\n this.abortController = new AbortController()\n\n const response = await fetch(url, {\n headers: { ...this.headers, Accept: 'text/event-stream' },\n signal: this.abortController.signal,\n })\n\n if (!response.ok) {\n throw new Error(`SSE connection failed: ${response.status} ${response.statusText}`)\n }\n\n if (!response.body) {\n throw new Error('SSE response has no body')\n }\n\n this.connected = true\n\n // Start background parsing loop\n this._consumeStream(response.body).catch((err) => {\n if (this.connected) {\n this.streamError = err instanceof Error ? err : new Error(String(err))\n }\n })\n\n // Wait for the initial snapshot to arrive before returning.\n // This ensures that connect() resolves only after the snapshot\n // has been processed so callers can immediately check spans.\n await this._waitForSnapshot()\n }\n\n /**\n * Mark the beginning of a new turn.\n * Records which handler.conversation span IDs have been seen so far,\n * so waitForTurnComplete() only resolves on NEW handler completions.\n */\n startTurn(): void {\n // Snapshot the current set of span keys as the turn boundary\n this.turnStartKeys = new Set(this.spanMap.keys())\n\n // Record all handler.conversation spans seen so far\n for (const [key, span] of this.spanMap) {\n if (span.name === 'handler.conversation') {\n this.seenHandlerKeys.add(key)\n }\n }\n }\n\n private static readonly SETTLE_MS = 100\n\n /**\n * Wait for a handler.conversation span to reach terminal status (ok or error).\n * Only considers spans NOT seen before the last startTurn() call.\n *\n * After the handler closes, waits for a quiet period (no new spans for SETTLE_MS)\n * to ensure all child spans (tool calls, messages, state saves) have arrived.\n * The runtime's HttpSpanExporter fires POSTs without awaiting them, so child\n * spans may arrive slightly after the handler close event.\n */\n async waitForTurnComplete(opts: WaitOptions): Promise<void> {\n // Check if a completed handler already exists (e.g. from snapshot)\n if (this._hasNewCompletedHandler()) {\n return this._settleAfterHandler()\n }\n if (opts.abortSignal?.aborted) {\n throw new Error('waitForTurnComplete aborted')\n }\n\n return new Promise<void>((resolve, reject) => {\n const timer = setTimeout(() => {\n this._removeWaiter(waiter)\n opts.abortSignal?.removeEventListener('abort', onAbort)\n const reason = this.streamError\n ? `SSE stream died: ${this.streamError.message}`\n : 'no handler.conversation span completed'\n reject(new Error(`waitForTurnComplete timed out after ${opts.timeout}ms \u2014 ${reason}`))\n }, opts.timeout)\n\n const onAbort = () => {\n clearTimeout(timer)\n this._removeWaiter(waiter)\n reject(new Error('waitForTurnComplete aborted'))\n }\n opts.abortSignal?.addEventListener('abort', onAbort, { once: true })\n\n const waiter = (_span: Span) => {\n if (this._hasNewCompletedHandler()) {\n clearTimeout(timer)\n this._removeWaiter(waiter)\n opts.abortSignal?.removeEventListener('abort', onAbort)\n this._settleAfterHandler().then(resolve, reject)\n }\n }\n\n this.waiters.push(waiter)\n })\n }\n\n private static readonly MAX_SETTLE_MS = 2_000\n\n /**\n * After the handler span closes, wait for spans to stop arriving.\n * Resolves when no new spans arrive for SETTLE_MS, or after MAX_SETTLE_MS hard cap.\n *\n * Exposes a cancellation hook via _cancelSettle so disconnect() can short-\n * circuit an in-flight settle phase and avoid leaking timers for up to 2s.\n */\n private _settleAfterHandler(): Promise<void> {\n return new Promise<void>((resolve) => {\n let resolved = false\n const done = () => {\n if (resolved) return\n resolved = true\n clearTimeout(hardCap)\n clearTimeout(settleTimer)\n this._removeWaiter(settleWaiter)\n this._cancelSettle = null\n resolve()\n }\n\n const hardCap = setTimeout(done, SSECollector.MAX_SETTLE_MS)\n\n let settleTimer = setTimeout(done, SSECollector.SETTLE_MS)\n\n const settleWaiter = () => {\n if (resolved) return\n clearTimeout(settleTimer)\n settleTimer = setTimeout(done, SSECollector.SETTLE_MS)\n }\n\n this.waiters.push(settleWaiter)\n this._cancelSettle = done\n })\n }\n\n /**\n * Wait for a handler.workflow span with matching workflow name.\n * - signal 'entered': resolves when the span appears (any status)\n * - signal 'completed': resolves when the span has status !== 'running'\n */\n async waitForWorkflow(name: string, opts: WorkflowWaitOptions): Promise<void> {\n // Check if condition is already met\n if (this._matchesWorkflowCondition(name, opts.signal)) {\n return\n }\n if (opts.abortSignal?.aborted) {\n throw new Error(`waitForWorkflow(\"${name}\", { signal: \"${opts.signal}\" }) aborted`)\n }\n\n return new Promise<void>((resolve, reject) => {\n const timer = setTimeout(() => {\n this._removeWaiter(waiter)\n opts.abortSignal?.removeEventListener('abort', onAbort)\n const reason = this.streamError ? `SSE stream died: ${this.streamError.message}` : 'span not found'\n reject(\n new Error(\n `waitForWorkflow(\"${name}\", { signal: \"${opts.signal}\" }) timed out after ${opts.timeout}ms \u2014 ${reason}`\n )\n )\n }, opts.timeout)\n\n const onAbort = () => {\n clearTimeout(timer)\n this._removeWaiter(waiter)\n reject(new Error(`waitForWorkflow(\"${name}\", { signal: \"${opts.signal}\" }) aborted`))\n }\n opts.abortSignal?.addEventListener('abort', onAbort, { once: true })\n\n const waiter = (_span: Span) => {\n if (this._matchesWorkflowCondition(name, opts.signal)) {\n clearTimeout(timer)\n this._removeWaiter(waiter)\n opts.abortSignal?.removeEventListener('abort', onAbort)\n resolve()\n }\n }\n\n this.waiters.push(waiter)\n })\n }\n\n /**\n * Return spans accumulated since the last startTurn() call.\n */\n getTurnSpans(): Span[] {\n const result: Span[] = []\n for (const [key, span] of this.spanMap) {\n if (!this.turnStartKeys.has(key)) {\n result.push(span)\n }\n }\n return result\n }\n\n /**\n * Return all spans accumulated since connect().\n */\n getAllSpans(): Span[] {\n return Array.from(this.spanMap.values())\n }\n\n /**\n * Close the SSE connection and clean up.\n */\n disconnect(): void {\n this.connected = false\n this.abortController?.abort()\n this.abortController = null\n // Short-circuit an in-flight settle phase so its hardCap / settleTimer\n // don't fire after disconnect.\n this._cancelSettle?.()\n this._cancelSettle = null\n // Waiters hold setTimeout references that will reject on their own;\n // clearing the array just prevents further notifications.\n this.waiters = []\n this.snapshotResolvers = []\n }\n\n // \u2500\u2500 Private \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /** Whether we have received the initial snapshot. */\n private snapshotReceived = false\n private snapshotResolvers: Array<() => void> = []\n\n private static readonly SNAPSHOT_TIMEOUT_MS = 10_000\n\n /**\n * Returns a promise that resolves once the snapshot event has been processed,\n * or rejects after a timeout to prevent connect() from hanging indefinitely.\n */\n private _waitForSnapshot(): Promise<void> {\n if (this.snapshotReceived) {\n return Promise.resolve()\n }\n return new Promise<void>((resolve, reject) => {\n let settled = false\n const resolver = () => {\n if (settled) return\n settled = true\n clearTimeout(timer)\n resolve()\n }\n const timer = setTimeout(() => {\n if (settled) return\n settled = true\n const idx = this.snapshotResolvers.indexOf(resolver)\n if (idx !== -1) this.snapshotResolvers.splice(idx, 1)\n reject(\n new Error(\n `SSE snapshot not received within ${SSECollector.SNAPSHOT_TIMEOUT_MS}ms \u2014 is the dev server healthy?`\n )\n )\n }, SSECollector.SNAPSHOT_TIMEOUT_MS)\n this.snapshotResolvers.push(resolver)\n })\n }\n\n /**\n * Consume the ReadableStream body, parse SSE lines, and dispatch events.\n */\n private async _consumeStream(body: ReadableStream<Uint8Array>): Promise<void> {\n const decoder = new TextDecoder()\n let buffer = ''\n\n const reader = body.getReader()\n\n try {\n while (this.connected) {\n const { done, value } = await reader.read()\n if (done) break\n\n buffer += decoder.decode(value, { stream: true })\n\n // Split on double-newline boundaries to get complete SSE events\n const parts = buffer.split('\\n\\n')\n // The last part may be incomplete \u2014 keep it in the buffer\n buffer = parts.pop() ?? ''\n\n for (const part of parts) {\n this._parseSSEBlock(part)\n }\n }\n } finally {\n reader.releaseLock()\n }\n }\n\n /**\n * Parse a single SSE event block (text between \\n\\n boundaries).\n * Extracts event name and data payload.\n */\n private _parseSSEBlock(block: string): void {\n const lines = block.split('\\n')\n let eventName = ''\n let dataLine = ''\n\n for (const line of lines) {\n if (line.startsWith('event:')) {\n eventName = line.slice('event:'.length).trim()\n } else if (line.startsWith('data:')) {\n const value = line.slice('data:'.length).trim()\n dataLine = dataLine ? `${dataLine}\\n${value}` : value\n }\n // id: and retry: lines are ignored\n }\n\n if (!eventName || !dataLine) {\n // Could be a retry: line or empty block \u2014 skip\n if (!this.snapshotReceived && block.includes('retry:')) {\n // The retry line comes before the snapshot; don't resolve yet\n }\n return\n }\n\n try {\n const payload = JSON.parse(dataLine)\n this._handleEvent(eventName, payload)\n } catch {\n // Malformed JSON \u2014 skip\n }\n }\n\n /**\n * Dispatch a parsed SSE event to the appropriate handler.\n */\n private _handleEvent(eventName: string, payload: unknown): void {\n if (eventName === 'snapshot') {\n const data = payload as { spans: Span[] }\n const spans = Array.isArray(data.spans) ? data.spans : []\n for (const span of spans) {\n this._upsertSpan(span)\n }\n this.snapshotReceived = true\n for (const resolve of this.snapshotResolvers) {\n resolve()\n }\n this.snapshotResolvers = []\n } else if (eventName === 'update') {\n const data = payload as { span: Span }\n if (data.span) {\n this._upsertSpan(data.span)\n this._notifyWaiters(data.span)\n }\n }\n // keepalive events are intentionally ignored\n }\n\n /**\n * Insert or replace a span in the map (dedup by trace+span ID).\n */\n private _upsertSpan(span: Span): void {\n this.spanMap.set(spanKey(span), span)\n }\n\n /**\n * Notify all waiters that a new span was received.\n */\n private _notifyWaiters(span: Span): void {\n // Copy the array since waiters may remove themselves during iteration\n const current = [...this.waiters]\n for (const waiter of current) {\n waiter(span)\n }\n }\n\n /**\n * Remove a waiter callback from the list.\n */\n private _removeWaiter(fn: (span: Span) => void): void {\n const idx = this.waiters.indexOf(fn)\n if (idx !== -1) {\n this.waiters.splice(idx, 1)\n }\n }\n\n /**\n * Check if there is a handler.conversation span that:\n * 1. Was NOT seen before startTurn()\n * 2. Has terminal status (ok or error)\n *\n * Marks the matched key as consumed so the same handler span cannot\n * satisfy both the current turn's settle phase AND the next turn's\n * waitForTurnComplete check (which would otherwise resolve instantly\n * against stale data instead of waiting for the new turn's handler).\n */\n private _hasNewCompletedHandler(): boolean {\n for (const [key, span] of this.spanMap) {\n if (\n span.name === 'handler.conversation' &&\n !this.seenHandlerKeys.has(key) &&\n (span.status === 'ok' || span.status === 'error')\n ) {\n this.seenHandlerKeys.add(key)\n return true\n }\n }\n return false\n }\n\n /**\n * Check if a handler.workflow span matches the given condition.\n */\n private _matchesWorkflowCondition(name: string, signal: 'entered' | 'completed'): boolean {\n for (const span of this.spanMap.values()) {\n if (span.name !== 'handler.workflow') continue\n\n const d = spanData(span)\n const wfName = d['workflow.name'] || d['workflowName']\n if (wfName !== name) continue\n\n if (signal === 'entered') {\n // Any status means the workflow was entered\n return true\n }\n\n if (signal === 'completed') {\n return span.status === 'ok' || span.status === 'error'\n }\n }\n return false\n }\n}\n", "/**\n * Transformer: projects raw trace spans into grader-friendly TurnData.\n * Pure function \u2014 no side effects, no network calls.\n */\n\nimport type { Span } from './trace'\nimport type { StateMutation, ToolCall, TurnData, WorkflowSpan } from './types'\n\n/** Safe accessor for span.data as a string-keyed record. */\nfunction data(span: Span): Record<string, unknown> {\n return (span.data && typeof span.data === 'object' ? span.data : {}) as Record<string, unknown>\n}\n\n/** Attempt to parse a JSON string. Returns parsed result, raw value on parse failure, or fallback if value is nullish. */\nfunction tryParseJson(value: unknown): unknown {\n if (value == null) return undefined\n if (typeof value !== 'string') return value\n try {\n return JSON.parse(value)\n } catch {\n return value\n }\n}\n\n/** Parse JSON with a strict fallback \u2014 returns fallback on parse failure instead of the raw string. */\nfunction parseJsonOrFallback<T>(value: unknown, fallback: T): T {\n if (typeof value !== 'string') return fallback\n try {\n return JSON.parse(value) as T\n } catch {\n return fallback\n }\n}\n\n/**\n * Transform raw trace spans into structured TurnData for graders.\n *\n * Extraction logic:\n * - messages: from `chat.sendMessage` spans, ordered by startedAt\n * - toolCalls: from `autonomous.tool` spans with terminal status, deduped by span id, ordered by endedAt\n * - stateMutations: from `state.save` spans where changed_keys has length > 0\n * - workflowSpans: from `handler.workflow` spans\n * - handler: from `handler.conversation` or `handler.workflow` span with terminal status\n */\nexport function transformSpans(spans: Span[]): TurnData {\n return {\n messages: extractMessages(spans),\n toolCalls: extractToolCalls(spans),\n stateMutations: extractStateMutations(spans),\n workflowSpans: extractWorkflowSpans(spans),\n ...extractHandler(spans),\n }\n}\n\nfunction extractMessages(spans: Span[]): string[] {\n return spans\n .filter((s) => s.name === 'chat.sendMessage' && data(s)['message.preview'])\n .sort((a, b) => a.timing.startedAt - b.timing.startedAt)\n .map((s) => String(data(s)['message.preview']))\n}\n\nfunction extractToolCalls(spans: Span[]): ToolCall[] {\n const toolSpans = spans.filter(\n (s) => s.name === 'autonomous.tool' && s.status !== 'running' && data(s)['autonomous.tool.name']\n )\n\n // Deduplicate by span id\n const seen = new Set<string>()\n const unique = toolSpans.filter((s) => {\n if (seen.has(s.id.span)) return false\n seen.add(s.id.span)\n return true\n })\n\n return unique\n .sort((a, b) => (a.timing.endedAt ?? Infinity) - (b.timing.endedAt ?? Infinity))\n .map((s) => {\n const d = data(s)\n const input = parseJsonOrFallback<Record<string, unknown>>(d['autonomous.tool.input'], {})\n return {\n name: String(d['autonomous.tool.name']),\n input,\n output: String(d['autonomous.tool.output'] ?? ''),\n status: String(d['autonomous.tool.status'] ?? 'unknown'),\n }\n })\n}\n\nfunction extractStateMutations(spans: Span[]): StateMutation[] {\n return spans\n .filter((s) => {\n if (s.name !== 'state.save') return false\n const d = data(s)\n const changedKeys = d['state.changed_keys']\n return Array.isArray(changedKeys) && changedKeys.length > 0\n })\n .map((s) => {\n const d = data(s)\n return {\n type: String(d['type'] ?? 'unknown'),\n changedKeys: (d['state.changed_keys'] as string[]) ?? [],\n previous: tryParseJson(d['state.previous_value']),\n current: tryParseJson(d['state.value']),\n swappedToFile: d['swapped_to_file'] === true,\n }\n })\n}\n\nfunction extractWorkflowSpans(spans: Span[]): WorkflowSpan[] {\n return spans\n .filter((s) => s.name === 'handler.workflow')\n .map((s) => {\n const d = data(s)\n const result: WorkflowSpan = {\n name: String(d['workflow.name'] || d['workflowName'] || ''),\n status: s.status as WorkflowSpan['status'],\n }\n const statusFinal = d['workflow.status.final']\n if (statusFinal) {\n result.statusFinal = String(statusFinal)\n }\n return result\n })\n}\n\nfunction extractHandler(spans: Span[]): { handlerDuration: number; handlerStatus: 'ok' | 'error' } {\n const handler = spans.find(\n (s) => (s.name === 'handler.conversation' || s.name === 'handler.workflow') && s.status !== 'running'\n )\n\n if (!handler) {\n return { handlerDuration: 0, handlerStatus: 'ok' }\n }\n\n return {\n handlerDuration: handler.timing.duration ?? 0,\n handlerStatus: handler.status === 'error' ? 'error' : 'ok',\n }\n}\n", "/**\n * LLM judge grader using @botpress/cognitive.\n * Replaces the OpenAI-based implementation from the standalone project.\n */\n\nimport { Client } from '@botpress/client'\nimport { Cognitive } from '@botpress/cognitive'\nimport type { EvalLogger, GraderResult } from '../types'\n\nconst DEFAULT_PASS_THRESHOLD = 3\n\nfunction buildJudgeSystemPrompt(passThreshold: number): string {\n return `You are an evaluation judge for a chatbot. You will be given:\n- The user's message\n- The bot's response\n- Grading criteria\n\nYour job is to determine if the bot's response meets the criteria.\n\nRespond with a JSON object:\n{\n \"pass\": true/false,\n \"score\": 1-5,\n \"reason\": \"brief explanation\"\n}\n\nScoring guide:\n- 5: Fully meets criteria, excellent response\n- 4: Mostly meets criteria, minor issues\n- 3: Partially meets criteria, notable gaps\n- 2: Barely meets criteria, significant issues\n- 1: Does not meet criteria\n\nA score of ${passThreshold} or above is a pass.`\n}\n\nconst MODEL_ALIASES = ['fast', 'best']\n\nlet _cognitive: Cognitive | null = null\nlet _availableModels: string[] = []\nlet _judgeModel: string = 'fast'\n\nfunction _isModelValid(model: string): boolean {\n if (MODEL_ALIASES.includes(model)) return true\n if (_availableModels.length === 0) return false\n\n return _availableModels.includes(model)\n}\n\n/**\n * Initialize the LLM judge with explicit credentials.\n * Call this before running evals so the judge doesn't need env vars.\n */\nexport async function initLLMJudge(\n credentials: { token: string; apiUrl: string; botId: string; workspaceId?: string },\n options?: { model?: string; logger?: EvalLogger }\n) {\n const log = options?.logger ?? console\n\n const client = new Client({\n token: credentials.token,\n apiUrl: credentials.apiUrl,\n botId: credentials.botId,\n ...(credentials.workspaceId !== undefined ? { workspaceId: credentials.workspaceId } : {}),\n })\n _cognitive = new Cognitive({ client, __experimental_beta: true })\n\n try {\n _availableModels = Array.from((await _cognitive.fetchRemoteModels()).keys())\n } catch (err) {\n log.warn(`Failed to fetch available models: ${(err as Error).message}. LLM judge will be unavailable.`)\n _availableModels = []\n }\n\n _judgeModel = options?.model ?? 'fast'\n\n if (_availableModels.length === 0) {\n log.warn('No available Cognitive models: cannot validate judge model.')\n } else if (!_isModelValid(_judgeModel)) {\n log.warn(`Configured LLM judge model \"${_judgeModel}\" is invalid. Run \"adk models\" to list available models.`)\n }\n}\n\nexport async function gradeLLMJudge(\n botResponse: string,\n criteria: string,\n context: { userMessage: string; passThreshold?: number }\n): Promise<GraderResult> {\n const threshold = Math.max(1, Math.min(5, context.passThreshold ?? DEFAULT_PASS_THRESHOLD))\n\n try {\n if (!_cognitive) {\n return {\n assertion: `llm_judge: \"${criteria}\"`,\n pass: true,\n expected: criteria,\n actual: 'SKIPPED \u2014 LLM judge unavailable: no credentials configured',\n }\n }\n\n if (!_isModelValid(_judgeModel)) {\n return {\n assertion: `llm_judge: \"${criteria}\"`,\n pass: false,\n expected: criteria,\n actual: 'FAILED \u2014 invalid LLM judge model',\n }\n }\n\n type CognitiveModel = Exclude<Parameters<Cognitive['generateContent']>[0]['model'], undefined>\n\n const { output } = await _cognitive.generateContent({\n model: _judgeModel as CognitiveModel,\n temperature: 0,\n responseFormat: 'json_object',\n systemPrompt: buildJudgeSystemPrompt(threshold),\n messages: [\n {\n role: 'user',\n content: `User message: ${context.userMessage}\\n\\nBot response: ${botResponse}\\n\\nCriteria: ${criteria}`,\n },\n ],\n })\n\n const rawContent = output?.choices?.[0]?.content\n const content = typeof rawContent === 'string' ? rawContent : null\n if (!content) {\n return {\n assertion: `llm_judge: \"${criteria}\"`,\n pass: true,\n expected: criteria,\n actual: 'SKIPPED \u2014 LLM judge returned empty response',\n }\n }\n\n const verdict = JSON.parse(content) as {\n pass: boolean\n score: number\n reason: string\n }\n\n return {\n assertion: `llm_judge: \"${criteria}\"`,\n pass: verdict.score >= threshold,\n expected: criteria,\n actual: `Score ${verdict.score}/5 (threshold: ${threshold}) \u2014 ${verdict.reason}`,\n }\n } catch (err) {\n return {\n assertion: `llm_judge: \"${criteria}\"`,\n pass: true,\n expected: criteria,\n actual: `SKIPPED \u2014 LLM judge unavailable: ${(err as Error).message}`,\n }\n }\n}\n", "/**\n * Response assertion graders.\n * Checks bot response text against expected assertions.\n */\n\nimport type { ResponseAssertion, GraderResult } from '../types'\nimport { gradeLLMJudge } from './llm'\n\nexport async function gradeResponse(\n botResponse: string,\n assertions: ResponseAssertion[],\n context: { userMessage: string; judgePassThreshold?: number }\n): Promise<GraderResult[]> {\n const results: GraderResult[] = []\n\n for (const assertion of assertions) {\n if ('contains' in assertion) {\n const pass = botResponse.toLowerCase().includes(assertion.contains.toLowerCase())\n results.push({\n assertion: `contains \"${assertion.contains}\"`,\n pass,\n expected: `Response contains \"${assertion.contains}\"`,\n actual: pass ? `Found in response` : `Not found in response`,\n })\n continue\n }\n\n if ('not_contains' in assertion) {\n const pass = !botResponse.toLowerCase().includes(assertion.not_contains.toLowerCase())\n results.push({\n assertion: `not_contains \"${assertion.not_contains}\"`,\n pass,\n expected: `Response does not contain \"${assertion.not_contains}\"`,\n actual: pass ? `Not found in response` : `Found in response`,\n })\n continue\n }\n\n if ('matches' in assertion) {\n const regex = new RegExp(assertion.matches, 'i')\n const pass = regex.test(botResponse)\n results.push({\n assertion: `matches ${assertion.matches}`,\n pass,\n expected: `Response matches /${assertion.matches}/`,\n actual: pass ? `Matched` : `No match`,\n })\n continue\n }\n\n if ('llm_judge' in assertion) {\n const result = await gradeLLMJudge(botResponse, assertion.llm_judge, {\n userMessage: context.userMessage,\n ...(context.judgePassThreshold !== undefined ? { passThreshold: context.judgePassThreshold } : {}),\n })\n results.push(result)\n continue\n }\n\n // TODO: uncomment this once we support it\n // if ('similar_to' in assertion) {\n // results.push({\n // assertion: `similar_to: \"${assertion.similar_to}\"`,\n // pass: true,\n // expected: assertion.similar_to,\n // actual: 'SKIPPED \u2014 similar_to not yet implemented',\n // })\n // continue\n // }\n\n results.push({\n assertion: 'unknown',\n pass: false,\n expected: 'known assertion type',\n actual: `Unknown assertion: ${JSON.stringify(assertion)}`,\n })\n }\n\n return results\n}\n", "/**\n * Shared match utilities for assertion grading.\n * Used by tool, state, and table graders.\n */\n\nimport type { MatchOperator } from '../types'\n\n/**\n * Evaluate a single match operator against a value.\n */\nexport function matchValue(operator: MatchOperator, actual: unknown): boolean {\n // Shorthand: string means exact match\n if (typeof operator === 'string') {\n return String(actual) === operator\n }\n\n if ('equals' in operator) {\n return actual === operator.equals\n }\n\n if ('contains' in operator) {\n return String(actual).toLowerCase().includes(operator.contains.toLowerCase())\n }\n\n if ('not_contains' in operator) {\n return !String(actual).toLowerCase().includes(operator.not_contains.toLowerCase())\n }\n\n if ('matches' in operator) {\n return new RegExp(operator.matches, 'i').test(String(actual))\n }\n\n if ('in' in operator) {\n return operator.in.includes(actual)\n }\n\n if ('exists' in operator) {\n return operator.exists ? actual !== undefined && actual !== null : actual === undefined || actual === null\n }\n\n if ('gte' in operator) {\n return Number(actual) >= operator.gte\n }\n\n if ('lte' in operator) {\n return Number(actual) <= operator.lte\n }\n\n return false\n}\n\nexport function operatorToString(operator: MatchOperator): string {\n if (typeof operator === 'string') return `equals \"${operator}\"`\n if ('equals' in operator) return `equals ${JSON.stringify(operator.equals)}`\n if ('contains' in operator) return `contains \"${operator.contains}\"`\n if ('not_contains' in operator) return `not_contains \"${operator.not_contains}\"`\n if ('matches' in operator) return `matches /${operator.matches}/`\n if ('in' in operator) return `in [${operator.in.map((v) => JSON.stringify(v)).join(', ')}]`\n if ('exists' in operator) return operator.exists ? 'exists' : 'does not exist'\n if ('gte' in operator) return `>= ${operator.gte}`\n if ('lte' in operator) return `<= ${operator.lte}`\n return JSON.stringify(operator)\n}\n", "/**\n * Tool assertion graders.\n * Checks tool calls from traces against expected assertions.\n */\n\nimport type { ToolAssertion, ToolCall, GraderResult } from '../types'\nimport { matchValue, operatorToString } from './match'\n\nexport function gradeTools(toolCalls: ToolCall[], assertions: ToolAssertion[]): GraderResult[] {\n return assertions.map((assertion) => {\n // --- called ---\n if ('called' in assertion && !('not_called' in assertion) && !('call_order' in assertion)) {\n const matches = toolCalls.filter((tc) => tc.name === assertion.called)\n const wasCalled = matches.length > 0\n\n if (!wasCalled) {\n return {\n assertion: `tool called: ${assertion.called}`,\n pass: false,\n expected: `${assertion.called} was called`,\n actual: `Not called. Tools called: [${toolCalls.map((tc) => tc.name).join(', ') || 'none'}]`,\n }\n }\n\n // Check params if specified\n if (assertion.params) {\n const paramResults: { key: string; pass: boolean; detail: string }[] = []\n\n for (const [key, operator] of Object.entries(assertion.params)) {\n // Check across all matching calls \u2014 pass if any call matches\n const anyMatch = matches.some((tc) => matchValue(operator, tc.input[key]))\n paramResults.push({\n key,\n pass: anyMatch,\n detail: anyMatch\n ? `matched`\n : `expected ${key} ${operatorToString(operator)}, got ${JSON.stringify(matches.map((tc) => tc.input[key]))}`,\n })\n }\n\n const allParamsPass = paramResults.every((p) => p.pass)\n const failedParams = paramResults.filter((p) => !p.pass)\n\n return {\n assertion: `tool called: ${assertion.called} with params`,\n pass: allParamsPass,\n expected: `${assertion.called} called with ${Object.entries(assertion.params)\n .map(([k, v]) => `${k} ${operatorToString(v)}`)\n .join(', ')}`,\n actual: allParamsPass ? `Matched` : failedParams.map((p) => p.detail).join('; '),\n }\n }\n\n return {\n assertion: `tool called: ${assertion.called}`,\n pass: true,\n expected: `${assertion.called} was called`,\n actual: `Called ${matches.length} time(s)`,\n }\n }\n\n // --- not_called ---\n if ('not_called' in assertion) {\n const wasCalled = toolCalls.some((tc) => tc.name === assertion.not_called)\n return {\n assertion: `tool not_called: ${assertion.not_called}`,\n pass: !wasCalled,\n expected: `${assertion.not_called} was NOT called`,\n actual: wasCalled ? `Was called` : `Not called`,\n }\n }\n\n // --- call_order ---\n if ('call_order' in assertion) {\n const calledNames = toolCalls.map((tc) => tc.name)\n const expectedOrder = assertion.call_order as string[]\n\n // Check that the expected sequence appears in order (not necessarily contiguous)\n let cursor = 0\n for (const name of calledNames) {\n if (cursor < expectedOrder.length && name === expectedOrder[cursor]) {\n cursor++\n }\n }\n const inOrder = cursor === expectedOrder.length\n\n return {\n assertion: `call_order: [${expectedOrder.join(' \u2192 ')}]`,\n pass: inOrder,\n expected: `Tools called in order: [${expectedOrder.join(' \u2192 ')}]`,\n actual: `Actual order: [${calledNames.join(' \u2192 ') || 'none'}]`,\n }\n }\n\n return {\n assertion: 'unknown tool assertion',\n pass: false,\n expected: 'known assertion type',\n actual: `Unknown: ${JSON.stringify(assertion)}`,\n }\n })\n}\n", "/**\n * State assertion graders.\n * Pure functions that grade state assertions against StateMutation[] from the transformer.\n * No API calls, no retries, no BpClient.\n */\n\nimport type { StateMutation, StateAssertion, GraderResult } from '../types'\n\n/**\n * Parse a state path like \"conversation.lastCity\" into its components.\n * bot.* -> type: \"bot\", field: \"*\"\n * user.* -> type: \"user\", field: \"*\"\n * conversation.* -> type: \"conversation\", field: \"*\"\n */\nfunction parseStatePath(path: string): { type: string; field: string } {\n const dot = path.indexOf('.')\n if (dot === -1) {\n throw new Error(`Invalid state path \"${path}\" \u2014 expected \"type.field\" format`)\n }\n\n const type = path.slice(0, dot)\n const field = path.slice(dot + 1)\n\n if (type !== 'bot' && type !== 'user' && type !== 'conversation') {\n throw new Error(`Unknown state type \"${type}\" in path \"${path}\" \u2014 expected bot, user, or conversation`)\n }\n\n return { type, field }\n}\n\n/**\n * Grade state assertions using StateMutation[] from the transformer.\n *\n * - `equals`: find the LAST mutation matching the state type, extract field from `current`, deep-compare\n * - `changed: true`: check if the field appears in ANY mutation's `changedKeys` for that state type\n * - `changed: false`: check that the field appears in NO mutation's `changedKeys`\n * - Swapped state: when `swappedToFile` is true, current/previous are undefined \u2014 report a clear message\n */\nexport function gradeState(mutations: StateMutation[], assertions: StateAssertion[]): GraderResult[] {\n const results: GraderResult[] = []\n\n for (const assertion of assertions) {\n const parsed = parseStatePath(assertion.path)\n const matchingMutations = mutations.filter((m) => m.type === parsed.type)\n\n if (assertion.equals !== undefined) {\n if (matchingMutations.length === 0) {\n results.push({\n assertion: `state: ${assertion.path} equals`,\n pass: false,\n expected: JSON.stringify(assertion.equals),\n actual:\n `No state.save span found for \"${parsed.type}\" \u2014 the bot did not mutate this state during the turn. ` +\n 'If this state was seeded via setup.state, assert on the tool/action that reads it, or use a conversation turn that triggers a state write.',\n })\n continue\n }\n\n const lastMutation = matchingMutations[matchingMutations.length - 1]!\n\n if (lastMutation.swappedToFile) {\n results.push({\n assertion: `state: ${assertion.path} equals`,\n pass: false,\n expected: JSON.stringify(assertion.equals),\n actual: 'State was too large for trace-based assertion (swapped to file)',\n })\n continue\n }\n\n const currentState = lastMutation.current as Record<string, unknown> | undefined\n const actualValue = currentState ? currentState[parsed.field] : undefined\n const pass = deepEqual(actualValue, assertion.equals)\n\n results.push({\n assertion: `state: ${assertion.path} equals`,\n pass,\n expected: JSON.stringify(assertion.equals),\n actual: JSON.stringify(actualValue),\n })\n }\n\n if (assertion.changed !== undefined) {\n if (matchingMutations.length === 0) {\n results.push({\n assertion: `state: ${assertion.path} ${assertion.changed ? 'changed' : 'unchanged'}`,\n pass: !assertion.changed,\n expected: assertion.changed\n ? `Field \"${parsed.field}\" changed in a \"${parsed.type}\" state mutation`\n : `Field \"${parsed.field}\" unchanged`,\n actual: 'No state mutation found for type \"' + parsed.type + '\"',\n })\n continue\n }\n\n // Check for swapped state in any matching mutation\n const hasSwapped = matchingMutations.some((m) => m.swappedToFile)\n if (hasSwapped) {\n results.push({\n assertion: `state: ${assertion.path} ${assertion.changed ? 'changed' : 'unchanged'}`,\n pass: false,\n expected: assertion.changed\n ? `Field \"${parsed.field}\" changed in a \"${parsed.type}\" state mutation`\n : `Field \"${parsed.field}\" unchanged`,\n actual: 'State was too large for trace-based assertion (swapped to file)',\n })\n continue\n }\n\n const fieldChanged = matchingMutations.some((m) => m.changedKeys.includes(parsed.field))\n const pass = assertion.changed ? fieldChanged : !fieldChanged\n\n results.push({\n assertion: `state: ${assertion.path} ${assertion.changed ? 'changed' : 'unchanged'}`,\n pass,\n expected: assertion.changed\n ? `Field \"${parsed.field}\" changed in a \"${parsed.type}\" state mutation`\n : `Field \"${parsed.field}\" unchanged`,\n actual: fieldChanged ? `Field \"${parsed.field}\" was changed` : `Field \"${parsed.field}\" was not changed`,\n })\n }\n }\n\n return results\n}\n\nfunction deepEqual(a: unknown, b: unknown): boolean {\n if (a === b) return true\n if (a === null || b === null) return false\n if (typeof a !== typeof b) return false\n\n if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) return false\n return a.every((v, i) => deepEqual(v, b[i]))\n }\n\n if (Array.isArray(a) !== Array.isArray(b)) return false\n\n if (typeof a === 'object' && typeof b === 'object') {\n const keysA = Object.keys(a as object)\n const keysB = Object.keys(b as object)\n if (keysA.length !== keysB.length) return false\n return keysA.every((k) => deepEqual((a as Record<string, unknown>)[k], (b as Record<string, unknown>)[k]))\n }\n\n return false\n}\n", "/**\n * Workflow assertion graders.\n * Checks workflow execution via transformer-produced WorkflowSpan data.\n */\n\nimport type { WorkflowAssertion, WorkflowSpan, GraderResult } from '../types'\n\nexport function gradeWorkflows(workflows: WorkflowSpan[], assertions: WorkflowAssertion[]): GraderResult[] {\n const results: GraderResult[] = []\n\n for (const assertion of assertions) {\n const matching = workflows.filter((wf) => wf.name === assertion.name)\n\n // entered \u2014 was the workflow triggered at all?\n if (assertion.entered !== undefined) {\n const wasEntered = matching.length > 0\n const pass = assertion.entered ? wasEntered : !wasEntered\n\n results.push({\n assertion: `workflow: ${assertion.name} ${assertion.entered ? 'entered' : 'not entered'}`,\n pass,\n expected: assertion.entered\n ? `Workflow \"${assertion.name}\" was entered`\n : `Workflow \"${assertion.name}\" was not entered`,\n actual: wasEntered ? `Found ${matching.length} workflow span(s)` : `No workflow spans found`,\n })\n }\n\n // completed \u2014 did the workflow complete?\n if (assertion.completed !== undefined) {\n const didComplete = matching.some(\n (wf) => wf.statusFinal === 'completed' || wf.status === 'ok' || wf.status === 'error'\n )\n const pass = assertion.completed ? didComplete : !didComplete\n\n results.push({\n assertion: `workflow: ${assertion.name} ${assertion.completed ? 'completed' : 'not completed'}`,\n pass,\n expected: assertion.completed\n ? `Workflow \"${assertion.name}\" completed`\n : `Workflow \"${assertion.name}\" did not complete`,\n actual: didComplete ? `Completed` : `Not completed`,\n })\n }\n }\n\n return results\n}\n", "/**\n * Timing assertion graders.\n * Checks bot response duration against expected thresholds.\n */\n\nimport type { TimingAssertion, GraderResult } from '../types'\nimport { matchValue, operatorToString } from './match'\n\nexport function gradeTiming(botDuration: number, assertions: TimingAssertion[]): GraderResult[] {\n const results: GraderResult[] = []\n\n for (const assertion of assertions) {\n const pass = matchValue(assertion.response_time, botDuration)\n const expected = operatorToString(assertion.response_time)\n\n results.push({\n assertion: `response_time ${expected}`,\n pass,\n expected: `Response time ${expected}`,\n actual: `${botDuration}ms`,\n })\n }\n\n return results\n}\n", "/**\n * Outcome assertion orchestrator.\n * Runs state and workflow graders after all conversation turns complete.\n */\n\nimport type { EvalDefinition, GraderResult, StateMutation, WorkflowSpan } from '../types'\nimport { gradeState } from './state'\nimport { gradeWorkflows } from './workflow'\n\n/**\n * Grade all outcome assertions after the conversation completes.\n * Takes transformer output (StateMutation[], WorkflowSpan[]) \u2014 no raw spans, no API calls.\n */\nexport function gradeOutcome(\n mutations: StateMutation[],\n evalDef: EvalDefinition,\n workflowSpans: WorkflowSpan[]\n): GraderResult[] {\n const outcome = evalDef.outcome\n if (!outcome) return []\n\n const results: GraderResult[] = []\n\n if (outcome.state && outcome.state.length > 0) {\n const stateResults = gradeState(mutations, outcome.state)\n results.push(...stateResults)\n }\n\n if (outcome.workflow && outcome.workflow.length > 0) {\n const workflowResults = gradeWorkflows(workflowSpans, outcome.workflow)\n results.push(...workflowResults)\n }\n\n return results\n}\n", "/**\n * Eval file loader.\n * Loads *.eval.ts files from a directory using dynamic imports.\n * Supports both default and named exports, and multiple evals per file.\n */\n\nimport { readdirSync, existsSync } from 'fs'\nimport { resolve } from 'path'\nimport type { EvalDefinition, EvalFilter } from './types'\nimport { Eval } from './types'\n\nfunction isEvalDefinition(value: unknown): value is EvalDefinition {\n return (\n value !== null &&\n typeof value === 'object' &&\n typeof (value as Record<string, unknown>).name === 'string' &&\n (value as Record<string, unknown>).name !== '' &&\n Array.isArray((value as Record<string, unknown>).conversation)\n )\n}\n\nexport async function loadEvalFile(filePath: string): Promise<EvalDefinition[]> {\n const absPath = resolve(filePath)\n\n let mod: Record<string, unknown>\n try {\n mod = await import(absPath)\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n throw new Error(\n `Failed to load eval file ${filePath}: ${msg}\\n\\n` +\n 'Make sure your eval file:\\n' +\n ' - Has no syntax or type errors\\n' +\n ' - Exports one or more `new Eval({...})` instances\\n' +\n ' - Has all dependencies installed (`bun install`)',\n { cause: err }\n )\n }\n\n const results: EvalDefinition[] = []\n\n for (const [key, value] of Object.entries(mod)) {\n if (key === '__esModule') continue\n if (value instanceof Eval || isEvalDefinition(value)) {\n results.push(value)\n }\n }\n\n if (results.length === 0) {\n throw new Error(\n `Invalid eval file ${filePath}: no valid evals found. Export one or more \\`new Eval({...})\\` instances (as default or named exports).`\n )\n }\n\n return results\n}\n\nexport async function loadEvalsFromDir(dirPath: string): Promise<EvalDefinition[]> {\n const absDir = resolve(dirPath)\n if (!existsSync(absDir)) {\n return []\n }\n\n const files = readdirSync(absDir).filter((f) => f.endsWith('.eval.ts'))\n const evals: EvalDefinition[] = []\n\n for (const f of files) {\n const defs = await loadEvalFile(`${absDir}/${f}`)\n evals.push(...defs)\n }\n\n const seen = new Set<string>()\n for (const e of evals) {\n if (seen.has(e.name)) {\n throw new Error(`Duplicate eval name \"${e.name}\" found in ${dirPath}`)\n }\n seen.add(e.name)\n }\n\n return evals\n}\n\nexport async function loadEvalByName(dirPath: string, name: string): Promise<EvalDefinition | null> {\n const absDir = resolve(dirPath)\n if (!existsSync(absDir)) return null\n\n const files = readdirSync(absDir).filter((f) => f.endsWith('.eval.ts'))\n\n for (const f of files) {\n const defs = await loadEvalFile(`${absDir}/${f}`)\n const found = defs.find((d) => d.name === name)\n if (found) return found\n }\n\n return null\n}\n\nexport function filterEvals(evals: EvalDefinition[], filter?: EvalFilter): EvalDefinition[] {\n if (!filter) return evals\n\n return evals.filter((e) => {\n if (filter.names && filter.names.length > 0) {\n if (!filter.names.includes(e.name)) return false\n }\n if (filter.tags && filter.tags.length > 0) {\n if (!e.tags || !filter.tags.some((t) => e.tags!.includes(t))) return false\n }\n if (filter.type) {\n if (e.type !== filter.type) return false\n }\n return true\n })\n}\n", "export type MatchOperator =\n | string\n | { equals: unknown }\n | { contains: string }\n | { not_contains: string }\n | { matches: string }\n | { in: unknown[] }\n | { exists: boolean }\n | { gte: number }\n | { lte: number }\n\nexport type ResponseAssertion =\n | { contains: string }\n | { not_contains: string }\n | { matches: string }\n | { llm_judge: string }\n// | { similar_to: string } TODO: uncomment this when it gets implemented\n\nexport type ToolAssertion =\n | { called: string; params?: Record<string, MatchOperator> }\n | { not_called: string }\n | { call_order: string[] }\n\nexport interface StateAssertion {\n path: string\n equals?: unknown\n changed?: boolean\n}\n\nexport interface WorkflowAssertion {\n name: string\n entered?: boolean\n completed?: boolean\n}\n\nexport type NumericOperator = { equals: number } | { gte: number } | { lte: number }\n\nexport interface TimingAssertion {\n response_time: NumericOperator\n}\n\nexport interface TurnAssertions {\n response?: ResponseAssertion[]\n tools?: ToolAssertion[]\n state?: StateAssertion[]\n workflow?: WorkflowAssertion[]\n timing?: TimingAssertion[]\n}\n\nexport interface ConversationTurn {\n user?: string\n event?: { type: string; payload?: Record<string, unknown> }\n expectSilence?: boolean\n assert?: TurnAssertions\n}\n\nexport interface OutcomeAssertions {\n state?: StateAssertion[]\n workflow?: WorkflowAssertion[]\n}\n\nexport interface EvalSetup {\n state?: {\n bot?: Record<string, unknown>\n user?: Record<string, unknown>\n conversation?: Record<string, unknown>\n }\n workflow?: {\n trigger: string\n input?: Record<string, unknown>\n }\n}\n\nexport interface EvalDefinition {\n name: string\n description?: string\n tags?: string[]\n type?: 'capability' | 'regression'\n setup?: EvalSetup\n conversation: ConversationTurn[]\n outcome?: OutcomeAssertions\n options?: {\n idleTimeout?: number\n judgePassThreshold?: number\n }\n}\n\nexport class Eval implements EvalDefinition {\n readonly name: string\n readonly description?: string\n readonly tags?: string[]\n readonly type?: 'capability' | 'regression'\n readonly setup?: EvalSetup\n readonly conversation: ConversationTurn[]\n readonly outcome?: OutcomeAssertions\n readonly options?: {\n idleTimeout?: number\n judgePassThreshold?: number\n }\n\n constructor(def: EvalDefinition) {\n this.name = def.name\n this.conversation = def.conversation\n if (def.description !== undefined) this.description = def.description\n if (def.tags !== undefined) this.tags = def.tags\n if (def.type !== undefined) this.type = def.type\n if (def.setup !== undefined) this.setup = def.setup\n if (def.outcome !== undefined) this.outcome = def.outcome\n if (def.options !== undefined) this.options = def.options\n }\n}\n"],
5
- "mappings": "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",
3
+ "sources": ["../src/runner.ts", "../src/definition.ts", "../src/types.ts", "../src/client.ts", "../../analytics/src/errors.ts", "../src/errors.ts", "../src/sse-collector.ts", "../src/transformer.ts", "../src/graders/llm.ts", "../src/graders/response.ts", "../src/graders/match.ts", "../src/graders/tools.ts", "../src/graders/state.ts", "../src/graders/workflow.ts", "../src/graders/timing.ts", "../src/graders/outcome.ts", "../src/loader.ts"],
4
+ "sourcesContent": ["/**\n * Eval runner \u2014 orchestrates eval execution.\n *\n * Observation is trace-driven: SSECollector streams spans in real-time,\n * transformSpans() projects them into grader-friendly TurnData, and graders\n * are pure functions over that output. The only network calls are emitter\n * actions (sending messages, triggering workflows, seeding state, LLM judge).\n */\n\nimport { Client as BpClient } from '@botpress/client'\nimport type {\n EvalDefinition,\n EvalProgressEvent,\n EvalReport,\n EvalRunReport,\n EvalRunnerConfig,\n EvalFilter,\n GraderResult,\n TurnReport,\n BotConnection,\n EvalSetup,\n} from './types'\nimport { defaultLogger } from './types'\nimport { ChatSession, discoverWebhookId, assertChatChannelBound, assertTraceStreamReadable } from './client'\nimport { SSECollector } from './sse-collector'\nimport { transformSpans } from './transformer'\nimport { gradeResponse } from './graders/response'\nimport { gradeTools } from './graders/tools'\nimport { gradeState } from './graders/state'\nimport { gradeWorkflows } from './graders/workflow'\nimport { gradeTiming } from './graders/timing'\nimport { gradeOutcome } from './graders/outcome'\nimport { initLLMJudge } from './graders/llm'\nimport { loadEvalsFromDir, filterEvals } from './loader'\nimport { EvalRunnerError } from './errors'\nimport { isAdkError } from '@botpress/analytics'\nimport { randomUUID } from 'crypto'\n\n/**\n * Run a single eval against a bot.\n */\nconst DEFAULT_IDLE_TIMEOUT = 30_000\nconst DEFAULT_DEV_SERVER_URL = 'http://localhost:3001'\nconst WORKFLOW_TRIGGER_TIMEOUT_MS = 5 * 60 * 1000\n\nconst BUILT_IN_STATES = {\n conversation: 'state',\n user: 'userState',\n bot: 'botState',\n} as const\n\nfunction buildStatePayload(value: Record<string, unknown>) {\n // `location` is required by the Botpress setState API schema.\n return {\n value,\n location: { type: 'state' as const },\n }\n}\n\nasync function seedEvalState(\n client: BpClient,\n ctx: { botId: string; userId: string; conversationId?: string },\n setup?: EvalSetup\n): Promise<void> {\n const state = setup?.state\n if (!state) return\n\n const writes: Array<Promise<unknown>> = []\n\n if (state.bot) {\n writes.push(\n client.setState({\n type: 'bot',\n id: ctx.botId,\n name: BUILT_IN_STATES.bot,\n payload: buildStatePayload(state.bot),\n })\n )\n }\n\n if (state.user) {\n writes.push(\n client.setState({\n type: 'user',\n id: ctx.userId,\n name: BUILT_IN_STATES.user,\n payload: buildStatePayload(state.user),\n })\n )\n }\n\n if (state.conversation) {\n if (!ctx.conversationId) {\n throw new EvalRunnerError({\n code: 'EVAL_SEED_NO_CONVERSATION',\n message: 'Cannot seed conversation state before a conversation is created.',\n })\n }\n\n writes.push(\n client.setState({\n type: 'conversation',\n id: ctx.conversationId,\n name: BUILT_IN_STATES.conversation,\n payload: buildStatePayload(state.conversation),\n })\n )\n }\n\n await Promise.all(writes)\n}\n\nasync function triggerEvalWorkflow(\n client: BpClient,\n ctx: { userId: string; conversationId?: string },\n setup?: EvalSetup\n): Promise<void> {\n const workflow = setup?.workflow\n if (!workflow) return\n\n await client.createWorkflow({\n name: workflow.trigger,\n input: workflow.input ?? {},\n status: 'pending',\n userId: ctx.userId,\n timeoutAt: new Date(Date.now() + WORKFLOW_TRIGGER_TIMEOUT_MS).toISOString(),\n ...(ctx.conversationId !== undefined ? { conversationId: ctx.conversationId } : {}),\n })\n}\n\nfunction evalMetadata(evalDef: EvalDefinition) {\n return {\n name: evalDef.name,\n ...(evalDef.description !== undefined ? { description: evalDef.description } : {}),\n ...(evalDef.type !== undefined ? { type: evalDef.type } : {}),\n ...(evalDef.tags !== undefined ? { tags: evalDef.tags } : {}),\n }\n}\n\nexport async function runEval(\n evalDef: EvalDefinition,\n connection: BotConnection,\n options: {\n devServerUrl?: string\n idleTimeout?: number\n judgePassThreshold?: number\n onProgress?: (event: EvalProgressEvent) => void\n evalIndex?: number\n /** Forwarded from EvalRunnerConfig \u2014 lets per-turn workflow waits unblock immediately on Stop instead of burning the full idleTimeout each. */\n signal?: AbortSignal\n devServerHeaders?: Record<string, string>\n chatClient?: EvalRunnerConfig['chatClient']\n logger?: EvalRunnerConfig['logger']\n onException?: EvalRunnerConfig['onException']\n } = {}\n): Promise<EvalReport> {\n const devServerUrl = options.devServerUrl || DEFAULT_DEV_SERVER_URL\n const devServerHeaders = options.devServerHeaders ?? {}\n const logger = options.logger ?? defaultLogger\n const idleTimeout = evalDef.options?.idleTimeout ?? options.idleTimeout ?? DEFAULT_IDLE_TIMEOUT\n const judgePassThreshold = evalDef.options?.judgePassThreshold ?? options.judgePassThreshold\n const start = Date.now()\n const turns: TurnReport[] = []\n let outcomeAssertions: GraderResult[] = []\n\n const collector = new SSECollector(devServerUrl, devServerHeaders)\n\n try {\n const session = new ChatSession(connection.webhookId, options.chatClient)\n await session.connect()\n\n let bpClient: BpClient | null = null\n const getBpClient = () => {\n if (!bpClient) {\n bpClient = new BpClient({\n token: connection.token,\n botId: connection.botId,\n apiUrl: connection.apiUrl,\n })\n }\n return bpClient\n }\n\n let conversationId = ''\n if (evalDef.setup?.state?.conversation || evalDef.setup?.workflow) {\n conversationId = await session.ensureConversation()\n }\n\n await seedEvalState(\n getBpClient(),\n {\n botId: connection.botId,\n userId: session.userId,\n ...(conversationId ? { conversationId } : {}),\n },\n evalDef.setup\n )\n\n await triggerEvalWorkflow(\n getBpClient(),\n {\n userId: session.userId,\n ...(conversationId ? { conversationId } : {}),\n },\n evalDef.setup\n )\n\n // Ensure we have a conversation before connecting the collector\n if (!conversationId && evalDef.conversation.length > 0) {\n conversationId = await session.ensureConversation()\n }\n\n // Connect the collector filtered by conversationId\n if (conversationId) {\n await collector.connect({ conversationId })\n } else if (evalDef.conversation.length > 0) {\n throw new EvalRunnerError({\n code: 'EVAL_NO_CONVERSATION_ID',\n message: 'Cannot run conversation eval without a conversationId \u2014 no chat session or setup created one.',\n })\n }\n\n for (let i = 0; i < evalDef.conversation.length; i++) {\n // Bail mid-eval the moment the caller signals abort, so a long\n // multi-turn eval doesn't keep ticking through turns after Stop.\n if (options.signal?.aborted) break\n\n const turn = evalDef.conversation[i]!\n\n const turnConfigError = (message: string) =>\n new EvalRunnerError({\n code: 'EVAL_TURN_CONFIG_INVALID',\n message: `Turn ${i + 1}: ${message}`,\n expected: true,\n details: { turn: i + 1 },\n })\n\n if (turn.expectSilence && turn.assert?.response) {\n throw turnConfigError(`'expectSilence' and 'assert.response' are mutually exclusive.`)\n }\n if (turn.user && turn.event) {\n throw turnConfigError(`'user' and 'event' are mutually exclusive.`)\n }\n if (!turn.user && !turn.event) {\n throw turnConfigError(`must have either 'user' or 'event'.`)\n }\n\n const turnLabelForEvent = turn.event ? `[event: ${turn.event.type}]` : turn.user!\n options.onProgress?.({\n type: 'turn_start',\n evalName: evalDef.name,\n evalIndex: options.evalIndex ?? 0,\n turnNumber: i + 1,\n totalTurns: evalDef.conversation.length,\n userMessage: turnLabelForEvent,\n })\n\n // Mark turn boundary, emit message, wait for handler completion via traces\n collector.startTurn()\n\n if (turn.event) {\n await session.sendEvent(turn.event.type, turn.event.payload ?? {})\n } else {\n await session.sendMessage(turn.user!)\n }\n\n try {\n await collector.waitForTurnComplete({\n timeout: idleTimeout,\n ...(options.signal !== undefined ? { abortSignal: options.signal } : {}),\n })\n } catch (err) {\n // If the wait was aborted, exit the turn loop cleanly rather than\n // surfacing an error on the eval \u2014 Stop is a user action, not a\n // failure. Other errors (timeout, etc.) still propagate.\n if (options.signal?.aborted) break\n throw err\n }\n\n // Wait for per-turn workflow assertions.\n // Skip the wait for negative assertions (entered: false / completed: false) \u2014 the\n // grader will check already-collected spans, so blocking on a signal that's expected\n // not to arrive just burns the full idleTimeout per assertion.\n if (turn.assert?.workflow) {\n for (const wfAssert of turn.assert.workflow) {\n const expectsPositive = wfAssert.entered !== false && wfAssert.completed !== false\n if (!expectsPositive) continue\n const wfSignal = wfAssert.completed ? 'completed' : 'entered'\n await collector\n .waitForWorkflow(wfAssert.name, {\n signal: wfSignal,\n timeout: idleTimeout,\n ...(options.signal !== undefined ? { abortSignal: options.signal } : {}),\n })\n .catch(() => {\n // Timeout is OK \u2014 the grader will report the failure\n })\n }\n }\n\n // Transform turn spans into grader-friendly data\n const turnSpans = collector.getTurnSpans()\n const turnData = transformSpans(turnSpans)\n\n const botResponse = turnData.messages.join('\\n')\n const botDuration = turnData.handlerDuration\n const turnLabel = turn.event ? `[event: ${turn.event.type}]` : turn.user!\n\n const evalStart = Date.now()\n let assertions: GraderResult[] = []\n const noResponse = !turn.expectSilence && turnData.messages.length === 0\n\n if (noResponse) {\n // A missing response is a graded outcome, not an exceptional state \u2014\n // record the failure and keep going so later turns and outcome\n // assertions still produce data (a throw here used to abort the whole\n // eval and discard everything after this turn).\n assertions.push({\n assertion: 'response',\n pass: false,\n expected: 'Bot produces a response',\n actual: `Turn ${i + 1}: bot produced no response.`,\n })\n }\n\n if (turn.expectSilence) {\n const wasSilent = turnData.messages.length === 0\n assertions.push({\n assertion: 'no_response',\n pass: wasSilent,\n expected: 'No response',\n actual: wasSilent ? 'No response' : `Bot responded: \"${botResponse}\"`,\n })\n }\n\n // Response assertions \u2014 skipped when there's no response: the failing\n // 'response' assertion above already covers it, and grading an empty\n // string would only add noise.\n if (turn.assert?.response && !noResponse) {\n assertions = await gradeResponse(botResponse, turn.assert.response, {\n userMessage: turnLabel,\n ...(judgePassThreshold !== undefined ? { judgePassThreshold } : {}),\n })\n }\n\n // Tool assertions from turn spans\n if (turn.assert?.tools) {\n const toolResults = gradeTools(turnData.toolCalls, turn.assert.tools)\n assertions = [...assertions, ...toolResults]\n }\n\n // Per-turn state assertions\n if (turn.assert?.state) {\n try {\n const stateResults = gradeState(turnData.stateMutations, turn.assert.state)\n assertions.push(...stateResults)\n } catch (err) {\n assertions.push({\n assertion: 'state',\n pass: false,\n expected: 'State assertions executed',\n actual: `Error: ${(err as Error).message}`,\n })\n }\n }\n\n // Per-turn workflow assertions\n if (turn.assert?.workflow) {\n const workflowResults = gradeWorkflows(turnData.workflowSpans, turn.assert.workflow)\n assertions.push(...workflowResults)\n }\n\n // Per-turn timing assertions\n if (turn.assert?.timing) {\n const timingResults = gradeTiming(botDuration, turn.assert.timing)\n assertions.push(...timingResults)\n }\n\n const turnPass = assertions.every((a) => a.pass)\n\n const evalDuration = Date.now() - evalStart\n\n const turnReport: TurnReport = {\n turnNumber: i + 1,\n userMessage: turnLabel,\n botResponse,\n assertions,\n pass: turnPass,\n botDuration,\n evalDuration,\n }\n turns.push(turnReport)\n\n options.onProgress?.({\n type: 'turn_complete',\n evalName: evalDef.name,\n evalIndex: options.evalIndex ?? 0,\n turnNumber: i + 1,\n totalTurns: evalDef.conversation.length,\n turnReport,\n })\n }\n\n // Outcome assertions (after all turns)\n if (evalDef.outcome && !options.signal?.aborted) {\n // Wait for outcome-level workflow assertions. Same negative-assertion gate as the per-turn loop.\n if (evalDef.outcome.workflow) {\n for (const wfAssert of evalDef.outcome.workflow) {\n const expectsPositive = wfAssert.entered !== false && wfAssert.completed !== false\n if (!expectsPositive) continue\n const wfSignal = wfAssert.completed ? 'completed' : 'entered'\n await collector\n .waitForWorkflow(wfAssert.name, {\n signal: wfSignal,\n timeout: idleTimeout,\n ...(options.signal !== undefined ? { abortSignal: options.signal } : {}),\n })\n .catch(() => {\n // Timeout is OK \u2014 the grader will report the failure\n })\n }\n }\n\n try {\n const allTurnData = transformSpans(collector.getAllSpans())\n outcomeAssertions = gradeOutcome(allTurnData.stateMutations, evalDef, allTurnData.workflowSpans)\n } catch (err) {\n outcomeAssertions = [\n {\n assertion: 'outcome',\n pass: false,\n expected: 'Outcome assertions executed',\n actual: `Error: ${(err as Error).message}`,\n },\n ]\n }\n }\n\n const aborted = options.signal?.aborted === true\n const turnsPass = turns.every((t) => t.pass)\n const outcomePass = outcomeAssertions.every((a) => a.pass)\n\n return {\n ...evalMetadata(evalDef),\n turns,\n outcomeAssertions,\n pass: !aborted && turnsPass && outcomePass,\n duration: Date.now() - start,\n ...(aborted ? { error: 'Eval aborted' } : {}),\n }\n } catch (err) {\n // Preserve the stable code/expected flag on the report instead of\n // flattening everything to a message string. Unexpected (internal-bug)\n // failures are logged AND reported to the injected exception hook \u2014\n // this catch swallows the error into report.error, so it never reaches\n // the CLI's command boundary and would otherwise be invisible to\n // PostHog error tracking.\n const adkErr = isAdkError(err) ? err : undefined\n if (!adkErr || !adkErr.expected) {\n logger.error(`Eval \"${evalDef.name}\" failed unexpectedly: ${(err as Error).message}`)\n options.onException?.(err, { source: 'evals', eval_name: evalDef.name })\n }\n return {\n ...evalMetadata(evalDef),\n turns,\n outcomeAssertions,\n pass: false,\n duration: Date.now() - start,\n error: (err as Error).message,\n ...(adkErr ? { errorCode: adkErr.code } : {}),\n }\n } finally {\n collector.disconnect()\n }\n}\n\n/**\n * Run a suite of evals.\n */\nexport async function runEvalSuite(config: EvalRunnerConfig, filter?: EvalFilter): Promise<EvalRunReport> {\n const start = Date.now()\n const runId = randomUUID().replace(/-/g, '').slice(0, 26)\n\n // Load eval definitions\n const evalsDir = `${config.agentPath}/evals`\n const allEvals = await loadEvalsFromDir(evalsDir)\n const evals = filterEvals(allEvals, filter)\n\n if (evals.length === 0) {\n return {\n id: runId,\n timestamp: new Date().toISOString(),\n evals: [],\n passed: 0,\n failed: 0,\n total: 0,\n duration: 0,\n ...(filter !== undefined ? { filter } : {}),\n }\n }\n\n // Initialize the LLM judge with credentials\n await initLLMJudge(\n {\n token: config.credentials.token,\n apiUrl: config.credentials.apiUrl,\n botId: config.credentials.botId,\n ...(config.credentials.workspaceId !== undefined ? { workspaceId: config.credentials.workspaceId } : {}),\n },\n {\n ...(config.evalOptions?.judgeModel !== undefined ? { model: config.evalOptions.judgeModel } : {}),\n ...(config.logger !== undefined ? { logger: config.logger } : {}),\n }\n )\n\n // Discover webhookId if not provided\n let webhookId = config.credentials.webhookId\n if (!webhookId) {\n webhookId = await discoverWebhookId(config.credentials.botId, config.credentials.token, config.credentials.apiUrl)\n }\n\n const connection: BotConnection = {\n webhookId,\n botId: config.credentials.botId,\n token: config.credentials.token,\n apiUrl: config.credentials.apiUrl,\n }\n\n const devServerUrl = config.devServerUrl || DEFAULT_DEV_SERVER_URL\n const devServerHeaders = config.devServerHeaders ?? {}\n\n // Fast-fail if no Conversation listens on chat.channel \u2014 otherwise evals time out silently.\n await assertChatChannelBound(devServerUrl, devServerHeaders, config.logger)\n // Fast-fail if the trace stream itself is unavailable before the first turn.\n await assertTraceStreamReadable(devServerUrl, devServerHeaders)\n\n const reports: EvalReport[] = []\n\n config.onProgress?.({ type: 'suite_start', totalEvals: evals.length })\n\n for (let i = 0; i < evals.length; i++) {\n // Stop starting new evals if the caller aborted. The eval loop only\n // checks between evals \u2014 an in-flight eval (with possibly in-flight LLM\n // calls) finishes naturally because those calls can't always be cancelled\n // mid-flight.\n if (config.signal?.aborted) break\n\n const evalDef = evals[i]!\n config.onProgress?.({\n type: 'eval_start',\n evalName: evalDef.name,\n index: i,\n totalTurns: evalDef.conversation.length,\n })\n\n const report = await runEval(evalDef, connection, {\n devServerUrl,\n devServerHeaders,\n evalIndex: i,\n ...(config.evalOptions?.idleTimeout !== undefined ? { idleTimeout: config.evalOptions.idleTimeout } : {}),\n ...(config.evalOptions?.judgePassThreshold !== undefined\n ? { judgePassThreshold: config.evalOptions.judgePassThreshold }\n : {}),\n ...(config.onProgress !== undefined ? { onProgress: config.onProgress } : {}),\n ...(config.signal !== undefined ? { signal: config.signal } : {}),\n ...(config.chatClient !== undefined ? { chatClient: config.chatClient } : {}),\n ...(config.logger !== undefined ? { logger: config.logger } : {}),\n ...(config.onException !== undefined ? { onException: config.onException } : {}),\n })\n reports.push(report)\n\n config.onProgress?.({ type: 'eval_complete', evalName: evalDef.name, index: i, report })\n }\n\n const runReport: EvalRunReport = {\n id: runId,\n timestamp: new Date().toISOString(),\n evals: reports,\n passed: reports.filter((r) => r.pass).length,\n failed: reports.filter((r) => !r.pass).length,\n total: reports.length,\n duration: Date.now() - start,\n ...(filter !== undefined ? { filter } : {}),\n }\n\n if (config.signal?.aborted) {\n runReport.aborted = true\n }\n\n config.onProgress?.({ type: 'suite_complete', report: runReport })\n\n return runReport\n}\n", "export type MatchOperator =\n | string\n | { equals: unknown }\n | { contains: string }\n | { not_contains: string }\n | { matches: string }\n | { in: unknown[] }\n | { exists: boolean }\n | { gte: number }\n | { lte: number }\n\nexport type ResponseAssertion =\n | { contains: string }\n | { not_contains: string }\n | { matches: string }\n | { llm_judge: string }\n// | { similar_to: string } TODO: uncomment this when it gets implemented\n\nexport type ToolAssertion =\n | { called: string; params?: Record<string, MatchOperator> }\n | { not_called: string }\n | { call_order: string[] }\n\nexport interface StateAssertion {\n path: string\n equals?: unknown\n changed?: boolean\n}\n\nexport interface WorkflowAssertion {\n name: string\n entered?: boolean\n completed?: boolean\n}\n\nexport type NumericOperator = { equals: number } | { gte: number } | { lte: number }\n\nexport interface TimingAssertion {\n response_time: NumericOperator\n}\n\nexport interface TurnAssertions {\n response?: ResponseAssertion[]\n tools?: ToolAssertion[]\n state?: StateAssertion[]\n workflow?: WorkflowAssertion[]\n timing?: TimingAssertion[]\n}\n\nexport interface ConversationTurn {\n user?: string\n event?: { type: string; payload?: Record<string, unknown> }\n expectSilence?: boolean\n assert?: TurnAssertions\n}\n\nexport interface OutcomeAssertions {\n state?: StateAssertion[]\n workflow?: WorkflowAssertion[]\n}\n\nexport interface EvalSetup {\n state?: {\n bot?: Record<string, unknown>\n user?: Record<string, unknown>\n conversation?: Record<string, unknown>\n }\n workflow?: {\n trigger: string\n input?: Record<string, unknown>\n }\n}\n\nexport interface EvalDefinition {\n name: string\n description?: string\n tags?: string[]\n type?: 'capability' | 'regression'\n setup?: EvalSetup\n conversation: ConversationTurn[]\n outcome?: OutcomeAssertions\n options?: {\n idleTimeout?: number\n judgePassThreshold?: number\n }\n}\n\nexport class Eval implements EvalDefinition {\n readonly name: string\n readonly description?: string\n readonly tags?: string[]\n readonly type?: 'capability' | 'regression'\n readonly setup?: EvalSetup\n readonly conversation: ConversationTurn[]\n readonly outcome?: OutcomeAssertions\n readonly options?: {\n idleTimeout?: number\n judgePassThreshold?: number\n }\n\n constructor(def: EvalDefinition) {\n this.name = def.name\n this.conversation = def.conversation\n if (def.description !== undefined) this.description = def.description\n if (def.tags !== undefined) this.tags = def.tags\n if (def.type !== undefined) this.type = def.type\n if (def.setup !== undefined) this.setup = def.setup\n if (def.outcome !== undefined) this.outcome = def.outcome\n if (def.options !== undefined) this.options = def.options\n }\n}\n", "/**\n * Eval type definitions.\n *\n * User-facing types live in @botpress/evals so eval authors can update eval\n * tooling without tying the authoring API to the agent runtime package.\n */\n\nexport {\n Eval,\n type EvalDefinition,\n type EvalSetup,\n type ConversationTurn,\n type TurnAssertions,\n type OutcomeAssertions,\n type ResponseAssertion,\n type ToolAssertion,\n type StateAssertion,\n type WorkflowAssertion,\n type TimingAssertion,\n type MatchOperator,\n type NumericOperator,\n} from './definition'\n\nexport type { Span, SpanStatus } from './trace'\n\nexport interface ChatClientConnection {\n user: { id: string }\n createConversation: (props: Record<string, unknown>) => Promise<{ conversation: { id: string } }>\n // Broad parameter types keep this compatible with @botpress/chat's narrower\n // generated payload unions while avoiding a dependency on those definitions.\n createMessage: (props: any) => Promise<unknown>\n createEvent: (props: any) => Promise<unknown>\n}\n\nexport interface ChatClient {\n connect: (props: { webhookId: string }) => Promise<ChatClientConnection>\n}\n\n// --- Grader result (universal currency for all graders) ---\n\nexport interface GraderResult {\n assertion: string\n pass: boolean\n expected: string\n actual: string\n}\n\n// --- Tool call extracted from traces ---\n\nexport interface ToolCall {\n name: string\n input: Record<string, unknown>\n output: string\n status: string\n}\n\n// --- Turn report ---\n\nexport interface TurnReport {\n turnNumber: number\n userMessage: string\n botResponse: string\n assertions: GraderResult[]\n pass: boolean\n /** Time spent waiting for the bot to respond (ms) */\n botDuration: number\n /** Time spent fetching traces + running graders (ms) */\n evalDuration: number\n}\n\n// --- Single eval report ---\n\nexport interface EvalReport {\n name: string\n description?: string\n type?: 'capability' | 'regression'\n tags?: string[]\n turns: TurnReport[]\n outcomeAssertions: GraderResult[]\n pass: boolean\n duration: number\n error?: string\n /** Stable EvalErrorCode when `error` came from a typed EvalRunnerError \u2014 lets consumers distinguish setup/config failures from bot failures. */\n errorCode?: string\n}\n\n// --- Progress event for real-time UI updates ---\n\nexport type EvalProgressEvent =\n | { type: 'suite_start'; totalEvals: number }\n | { type: 'eval_start'; evalName: string; index: number; totalTurns: number }\n | {\n type: 'turn_start'\n evalName: string\n evalIndex: number\n turnNumber: number\n totalTurns: number\n userMessage: string\n }\n | {\n type: 'turn_complete'\n evalName: string\n evalIndex: number\n turnNumber: number\n totalTurns: number\n turnReport: TurnReport\n }\n | { type: 'eval_complete'; evalName: string; index: number; report: EvalReport }\n | { type: 'suite_complete'; report: EvalRunReport; error?: string }\n\n// --- Eval run report (full suite) ---\n\nexport interface EvalRunReport {\n id: string\n timestamp: string\n evals: EvalReport[]\n passed: number\n failed: number\n total: number\n duration: number\n filter?: {\n names?: string[]\n tags?: string[]\n type?: 'capability' | 'regression'\n }\n /**\n * True when the suite was aborted mid-run (e.g. user clicked Stop). The\n * persisted report is partial \u2014 `evals` reflects only the completed evals,\n * and `total` matches that count, not the original suite size.\n */\n aborted?: boolean\n}\n\n// --- Bot connection info ---\n\nexport interface BotConnection {\n webhookId: string\n botId: string\n token: string\n apiUrl: string\n}\n\n// --- Logger interface ---\n\nexport interface EvalLogger {\n info: (message: string) => void\n warn: (message: string) => void\n error: (message: string) => void\n}\n\n/**\n * Fallback when no logger is injected (programmatic use outside the CLI).\n * console rather than a no-op so warnings stay visible \u2014 a silent default\n * would hide judge failures and skipped pre-flights, the exact swallow\n * anti-pattern docs/ERROR-HANDLING.md bans. The CLI always injects its own\n * structured logger via EvalRunnerConfig.logger.\n */\nexport const defaultLogger: EvalLogger = console\n\n// --- Eval runner configuration ---\n\nexport interface EvalRunnerConfig {\n credentials: {\n token: string\n apiUrl: string\n botId: string\n workspaceId?: string\n webhookId?: string\n }\n agentPath: string\n /** URL of the dev server providing traces and config. Defaults to the discovered DevConsole URL. */\n devServerUrl?: string\n /** Headers for dev-server requests, e.g. X-Agent-Path when routed through the singleton proxy. */\n devServerHeaders?: Record<string, string>\n /**\n * Optional host-provided chat client. The CLI passes its bundled chat client\n * here so the eval engine does not depend on @botpress/adk.\n */\n chatClient?: ChatClient\n onProgress?: (event: EvalProgressEvent) => void\n /** Logger for warnings and errors. Defaults to console. */\n logger?: EvalLogger\n /**\n * Called for unexpected (internal-bug) eval failures that runEval folds\n * into report.error \u2014 they never propagate to the CLI's command boundary,\n * so without this hook they'd be invisible to error tracking. The CLI binds\n * this to telemetry.captureException; evals itself stays telemetry-free.\n */\n onException?: (error: unknown, properties?: Record<string, unknown>) => void\n /**\n * Optional abort signal \u2014 when fired, the suite stops starting new evals.\n * The currently running eval continues to completion (LLM calls in flight\n * cannot always be cancelled), but no further evals are started.\n */\n signal?: AbortSignal\n /** Bot-level eval options from agent.config.ts. Cascades: eval > agent config > default. */\n evalOptions?: {\n idleTimeout?: number\n /** LLM judge pass threshold (integer, 1-5). Values outside this range are clamped. Cascades: eval > agent config > default (3). */\n judgePassThreshold?: number\n /** Model to use for llm_judge assertions (e.g. 'openai:gpt-4o'). Defaults to 'fast'. */\n judgeModel?: string\n }\n}\n\n// --- Eval suite filter ---\n\nexport interface EvalFilter {\n names?: string[]\n tags?: string[]\n type?: 'capability' | 'regression'\n}\n\n// --- Transformer types (trace-driven eval engine) ---\n\nexport interface StateMutation {\n type: string // 'bot', 'user', 'conversation'\n changedKeys: string[]\n previous: unknown\n current: unknown\n swappedToFile: boolean // data['swapped_to_file'] === true\n}\n\nexport interface WorkflowSpan {\n name: string\n status: 'running' | 'ok' | 'error'\n statusFinal?: string // 'completed', 'continue', 'failed'\n}\n\nexport interface TurnData {\n messages: string[]\n toolCalls: ToolCall[]\n stateMutations: StateMutation[]\n workflowSpans: WorkflowSpan[]\n handlerDuration: number\n handlerStatus: 'ok' | 'error'\n}\n", "/**\n * Chat client for eval conversations.\n * Drives conversations against a running ADK bot via @botpress/chat.\n *\n * This is a send-only client. Observation (bot responses, tool calls, state)\n * is handled by the SSECollector via trace spans \u2014 not via WebSocket listeners.\n */\n\nimport { Client as BpClient } from '@botpress/client'\nimport { createRequire } from 'module'\nimport type { ChatClient, ChatClientConnection, EvalLogger } from './types'\nimport { defaultLogger } from './types'\nimport { EvalRunnerError } from './errors'\n\nconst TRACE_STREAM_PREFLIGHT_TIMEOUT_MS = 10_000\n\nlet defaultChatClient: ChatClient | null = null\n\nexport function setDefaultChatClient(chatClient: ChatClient | null): void {\n defaultChatClient = chatClient\n}\n\nfunction getDefaultChatClient(): ChatClient {\n if (defaultChatClient) return defaultChatClient\n\n const require = createRequire(import.meta.url)\n const mod = require('@botpress/chat') as { Client?: ChatClient; default?: { Client?: ChatClient } }\n const ChatClient = mod.default?.Client ?? mod.Client\n if (!ChatClient) {\n throw new EvalRunnerError({\n code: 'CHAT_CLIENT_MISSING',\n message: '@botpress/chat did not expose a Client export. Pass EvalRunnerConfig.chatClient explicitly.',\n })\n }\n return ChatClient\n}\n\n/**\n * A send-only chat session that maintains a single client connection across turns.\n * Messages and events are fire-and-forget; the SSECollector observes results via traces.\n */\nexport class ChatSession {\n private client: ChatClientConnection | null = null\n private conversationId: string | null = null\n\n constructor(\n private webhookId: string,\n private chatClient?: ChatClient\n ) {}\n\n async connect() {\n const ChatClient = this.chatClient ?? getDefaultChatClient()\n this.client = await ChatClient.connect({ webhookId: this.webhookId })\n }\n\n /** Invariant guard \u2014 calling any session method before connect() is a runner bug. */\n private assertConnected(): ChatClientConnection {\n if (!this.client) {\n throw new EvalRunnerError({\n code: 'CHAT_NOT_CONNECTED',\n message: 'ChatSession not connected. Call connect() first.',\n })\n }\n return this.client\n }\n\n get userId(): string {\n return this.assertConnected().user.id\n }\n\n async ensureConversation(): Promise<string> {\n const client = this.assertConnected()\n\n if (!this.conversationId) {\n const conv = await client.createConversation({})\n this.conversationId = conv.conversation.id\n return conv.conversation.id\n }\n\n return this.conversationId\n }\n\n /**\n * Send a user message. Fire-and-forget \u2014 observation is via SSECollector.\n */\n async sendMessage(message: string): Promise<void> {\n const client = this.assertConnected()\n const conversationId = await this.ensureConversation()\n await client.createMessage({ conversationId, payload: { type: 'text', text: message } })\n }\n\n /**\n * Send an event. Fire-and-forget \u2014 observation is via SSECollector.\n */\n async sendEvent(type: string, payload: Record<string, unknown>): Promise<void> {\n const client = this.assertConnected()\n const conversationId = await this.ensureConversation()\n await client.createEvent({ type, payload, conversationId })\n }\n}\n\n/**\n * Discover the chat integration's webhookId from a bot.\n *\n * Evals talk to the bot through the `chat` integration (via @botpress/chat).\n * If the bot doesn't have that integration installed, evals can't run.\n */\nexport async function discoverWebhookId(botId: string, token: string, apiUrl: string): Promise<string> {\n const client = new BpClient({ token, botId, apiUrl })\n const { bot } = await client.getBot({ id: botId })\n const integrations = bot.integrations || {}\n\n const chat = Object.values(integrations).find((int) => (int as Record<string, unknown>).name === 'chat')\n const webhookId = (chat as Record<string, unknown> | undefined)?.webhookId\n\n if (!webhookId || typeof webhookId !== 'string') {\n throw new EvalRunnerError({\n code: 'CHAT_INTEGRATION_MISSING',\n message: [\n 'The `chat` integration is not installed on this bot \u2014 evals require it.',\n '',\n 'To fix:',\n ' 1. Install it: adk add chat',\n ' 2. Redeploy: adk dev (or: adk deploy)',\n ].join('\\n'),\n expected: true,\n })\n }\n\n return webhookId\n}\n\n/**\n * Verify the dev server's trace stream can be read before eval turns start.\n *\n * This only checks that `/api/traces/stream` is reachable and emits its initial\n * snapshot. It does not prove the private runtime span-ingest path is healthy.\n */\nexport async function assertTraceStreamReadable(\n devServerUrl: string,\n headers: Record<string, string> = {},\n timeoutMs = TRACE_STREAM_PREFLIGHT_TIMEOUT_MS\n): Promise<void> {\n const url = `${devServerUrl.replace(/\\/$/, '')}/api/traces/stream?count=1`\n const abortController = new AbortController()\n let timedOut = false\n let reader: ReadableStreamDefaultReader<Uint8Array> | null = null\n\n const timer = setTimeout(() => {\n timedOut = true\n abortController.abort()\n }, timeoutMs)\n\n try {\n const res = await fetch(url, {\n headers: { ...headers, Accept: 'text/event-stream' },\n signal: abortController.signal,\n })\n\n if (!res.ok) {\n throw traceStreamPreflightError(`Trace stream pre-flight failed: ${res.status} ${res.statusText}`)\n }\n\n if (!res.body) {\n throw traceStreamPreflightError('Trace stream pre-flight failed: response had no body.')\n }\n\n reader = res.body.getReader()\n const decoder = new TextDecoder()\n let buffer = ''\n\n while (true) {\n const { done, value } = await reader.read()\n if (done) {\n throw traceStreamPreflightError('Trace stream pre-flight failed: stream closed before snapshot.')\n }\n\n buffer += decoder.decode(value, { stream: true })\n const parts = buffer.split('\\n\\n')\n buffer = parts.pop() ?? ''\n\n for (const part of parts) {\n if (parseSSEEventName(part) === 'snapshot') {\n return\n }\n }\n }\n } catch (err) {\n if (err instanceof EvalRunnerError) {\n throw err\n }\n\n if (timedOut) {\n throw traceStreamPreflightError(\n `Trace stream pre-flight timed out after ${timeoutMs}ms before receiving a snapshot.`\n )\n }\n\n throw traceStreamPreflightError(\n `Trace stream pre-flight failed: ${err instanceof Error ? err.message : String(err)}`\n )\n } finally {\n clearTimeout(timer)\n reader?.cancel().catch(() => {})\n }\n}\n\nfunction parseSSEEventName(block: string): string | null {\n for (const line of block.split('\\n')) {\n if (line.startsWith('event:')) {\n return line.slice('event:'.length).trim()\n }\n }\n return null\n}\n\nfunction traceStreamPreflightError(message: string): EvalRunnerError {\n return new EvalRunnerError({\n code: 'SSE_CONNECT_FAILED',\n message,\n expected: true,\n suggestion: 'Make sure the dev server is running (`adk dev`) and trace streaming is available.',\n })\n}\n\n/**\n * Verify the bot has at least one Conversation bound to `chat.channel`.\n *\n * The `chat` integration can be installed without any handler listening on its\n * channel \u2014 in that case messages sent via @botpress/chat produce no response\n * and the caller times out silently. Fail fast with actionable guidance instead.\n *\n * Uses the dev server's `/api/agent` endpoint, so this is a no-op against\n * production bots (no devServerUrl).\n */\nexport async function assertChatChannelBound(\n devServerUrl: string,\n headers: Record<string, string> = {},\n logger: EvalLogger = defaultLogger\n): Promise<void> {\n type ConversationSummary = { channel?: string | string[] }\n let conversations: ConversationSummary[] = []\n try {\n const res = await fetch(`${devServerUrl}/api/agent`, { headers })\n if (!res.ok) return // Dev server unreachable \u2014 skip, let downstream errors surface\n const agent = (await res.json()) as { conversations?: ConversationSummary[] }\n conversations = agent.conversations ?? []\n } catch (err) {\n // Soft pre-flight only \u2014 a missing dev server is normal (e.g. prod bots),\n // but log the skip so a *broken* dev server (malformed /api/agent JSON)\n // isn't invisible while every eval afterwards times out mysteriously.\n logger?.warn(\n `Skipping chat.channel binding pre-flight \u2014 could not query ${devServerUrl}/api/agent: ${err instanceof Error ? err.message : String(err)}`\n )\n return\n }\n\n if (conversations.length === 0) return // Bot has no conversations at all \u2014 different problem\n\n // Mirrors the runtime's matchesChannel semantics: a handler matches `chat.channel`\n // if it is the wildcard '*', the literal string 'chat.channel', or an array\n // containing either.\n const matchesChatChannel = (ch: string | string[] | undefined): boolean => {\n if (!ch) return false\n if (ch === '*' || ch === 'chat.channel') return true\n return Array.isArray(ch) && (ch.includes('chat.channel') || ch.includes('*'))\n }\n\n const bound = conversations.some((c) => matchesChatChannel(c.channel))\n if (bound) return\n\n throw new EvalRunnerError({\n code: 'CHAT_CHANNEL_UNBOUND',\n message: [\n 'No Conversation is bound to `chat.channel` \u2014 messages via `@botpress/chat` will time out silently.',\n '',\n 'To fix, bind a Conversation in `src/conversations/` to `chat.channel` (or `*`):',\n \" channel: 'chat.channel', // explicit\",\n \" channel: '*', // wildcard \u2014 matches every channel\",\n \" channel: ['chat.channel', ...], // array form\",\n '',\n 'The `chat` integration is how evals and `adk chat --single` send messages programmatically.',\n ].join('\\n'),\n expected: true,\n })\n}\n", "/**\n * Shared base error for ADK packages. Lives in `@botpress/analytics` because\n * it's the dependency-light package every surface already shares (cli, adk,\n * ui) \u2014 so all typed errors can genuinely inherit one base instead of\n * mirroring its shape.\n *\n * The policy lives in docs/ERROR-HANDLING.md. The short version: every error\n * we *intend* to throw should carry a stable `code` (so PostHog error\n * tracking can slice issues by code) and an `expected` flag separating\n * user/environment conditions (bad input, not logged in, network down \u2014 render\n * a friendly message, low alert priority) from internal bugs (invariant\n * violations \u2014 full stack, page someone).\n *\n * The runtime package is out of scope and keeps its own `Errors.AbstractError`\n * hierarchy. The adk typed families (`DependencyError`, `Agent0*Error`) extend\n * this base; new code should start here.\n */\nexport class AdkError<Code extends string = string> extends Error {\n /**\n * Marker for cross-module-instance checks \u2014 `instanceof` breaks when a\n * package is duplicated in the dependency graph.\n * @internal\n */\n public static readonly __IS_ADK_BASE_ERROR = true\n\n /**\n * Stable SCREAMING_SNAKE_CASE identifier, e.g. 'BOT_NOT_FOUND'. Subclasses\n * pin `Code` to a literal union (`class EvalRunnerError extends\n * AdkError<EvalErrorCode>`) so typos are compile errors and `code` narrows\n * in switches.\n */\n readonly code: Code\n /**\n * True for user/environment conditions the developer can fix themselves\n * (validation, auth, connectivity). False for internal bugs. Defaults to\n * false so unclassified errors surface as bugs until someone triages them.\n */\n readonly expected: boolean\n /** Structured context. Sanitized before any telemetry leaves the machine. */\n readonly details?: Record<string, unknown>\n /** Actionable next step shown to the user, e.g. \"Run 'adk login' first.\" */\n readonly suggestion?: string\n\n constructor(opts: {\n code: Code\n message: string\n expected?: boolean\n details?: Record<string, unknown>\n suggestion?: string\n cause?: unknown\n }) {\n super(opts.message, opts.cause !== undefined ? { cause: opts.cause } : undefined)\n this.name = this.constructor.name\n this.code = opts.code\n this.expected = opts.expected ?? false\n // Conditional assignment keeps the optional fields absent-not-undefined,\n // which downstream tsconfigs with exactOptionalPropertyTypes require.\n if (opts.details !== undefined) {\n this.details = opts.details\n }\n if (opts.suggestion !== undefined) {\n this.suggestion = opts.suggestion\n }\n }\n}\n\n/**\n * Duck-typed guard that survives duplicated module instances in the\n * dependency graph, where `instanceof AdkError` returns false for an error\n * constructed from another copy of this module. No manual prototype walking\n * needed: static properties are inherited through the constructor chain, so\n * a subclass's constructor resolves the marker in one lookup.\n */\nexport function isAdkError(error: unknown): error is AdkError {\n if (error instanceof AdkError) return true\n if (!(error instanceof Error)) return false\n return (error.constructor as unknown as Record<string, unknown> | undefined)?.__IS_ADK_BASE_ERROR === true\n}\n", "import { AdkError } from '@botpress/analytics'\n\n/**\n * Stable error codes for the eval engine. Typed as a literal union so a typo'd\n * code is a compile error and PostHog issue-slicing stays consistent.\n * Conventions per docs/ERROR-HANDLING.md.\n */\nexport const EVAL_ERROR_CODES = [\n 'EVAL_LOAD_FAILED',\n 'EVAL_FILE_EMPTY',\n 'EVAL_DUPLICATE_NAME',\n 'EVAL_SEED_NO_CONVERSATION',\n 'EVAL_NO_CONVERSATION_ID',\n 'EVAL_TURN_CONFIG_INVALID',\n 'SSE_CONNECT_FAILED',\n 'SSE_NO_BODY',\n 'CHAT_CLIENT_MISSING',\n 'CHAT_NOT_CONNECTED',\n 'CHAT_INTEGRATION_MISSING',\n 'CHAT_CHANNEL_UNBOUND',\n] as const\n\nexport type EvalErrorCode = (typeof EVAL_ERROR_CODES)[number]\n\n/**\n * Typed error for the eval engine. Named EvalRunnerError (not EvalError) to\n * avoid shadowing the JS built-in `EvalError`.\n */\nexport class EvalRunnerError extends AdkError<EvalErrorCode> {}\n", "/**\n * SSECollector \u2014 connects to the ADK dev server's SSE trace stream,\n * accumulates spans, and provides promise-based wait methods for\n * turn completion and workflow signals.\n *\n * Uses fetch() + async iteration with manual SSE line parsing\n * (Bun does not have native EventSource).\n */\n\nimport type { Span } from './trace'\nimport { EvalRunnerError } from './errors'\n\ntype SSEFilter = { conversationId: string } | { workflowId: string }\n\ninterface WaitOptions {\n timeout: number\n /**\n * Optional abort signal \u2014 when fired, the wait rejects immediately rather\n * than burning the full timeout. Used by the runner so Stop unblocks\n * pending workflow assertions (otherwise a single negative-result wait\n * can hold the suite hostage for `idleTimeout` per assertion).\n */\n abortSignal?: AbortSignal\n}\n\ninterface WorkflowWaitOptions extends WaitOptions {\n signal: 'entered' | 'completed'\n}\n\n/**\n * Unique key for span deduplication.\n */\nfunction spanKey(span: Span): string {\n return `${span.id.trace}:${span.id.span}`\n}\n\n/**\n * Type-safe accessor for span.data fields.\n */\nfunction spanData(span: Span): Record<string, unknown> {\n return span.data && typeof span.data === 'object' ? (span.data as Record<string, unknown>) : {}\n}\n\nexport class SSECollector {\n private devServerUrl: string\n private headers: Record<string, string>\n\n /** All spans accumulated since connect(), keyed by spanKey for dedup. */\n private spanMap = new Map<string, Span>()\n\n /** Index into spanMap insertion order marking where the current turn started. */\n private turnStartKeys = new Set<string>()\n\n /** Handler span IDs seen before the current turn (for startTurn filtering). */\n private seenHandlerKeys = new Set<string>()\n\n /** Callbacks waiting for span updates. */\n private waiters: Array<(span: Span) => void> = []\n\n /** AbortController for the active SSE connection. */\n private abortController: AbortController | null = null\n\n /** Whether the background loop is running. */\n private connected = false\n\n /** Error from the SSE stream if it died unexpectedly. */\n private streamError: Error | null = null\n\n /** Passive counters used only to explain timeout failures. */\n private updateEventCount = 0\n private keepaliveEventCount = 0\n private lastEvent: { name: string; at: number } | null = null\n\n /** Set while a settle phase is in flight; called by disconnect() to short-circuit. */\n private _cancelSettle: (() => void) | null = null\n\n constructor(devServerUrl: string, headers: Record<string, string> = {}) {\n this.devServerUrl = devServerUrl\n this.headers = headers\n }\n\n /**\n * Open a streaming SSE connection filtered by conversationId or workflowId.\n * Starts a background loop that parses SSE events and accumulates spans.\n */\n async connect(filter: SSEFilter): Promise<void> {\n const attributeName = 'conversationId' in filter ? 'conversationId' : 'workflowId'\n const attributeValue = 'conversationId' in filter ? filter.conversationId : filter.workflowId\n\n const url = `${this.devServerUrl}/api/traces/stream?attributeName=${encodeURIComponent(attributeName)}&attributeValue=${encodeURIComponent(attributeValue)}`\n\n this.abortController = new AbortController()\n\n const response = await fetch(url, {\n headers: { ...this.headers, Accept: 'text/event-stream' },\n signal: this.abortController.signal,\n })\n\n if (!response.ok) {\n throw new EvalRunnerError({\n code: 'SSE_CONNECT_FAILED',\n message: `SSE connection failed: ${response.status} ${response.statusText}`,\n expected: true,\n suggestion: 'Make sure the dev server is running (`adk dev`) and reachable.',\n })\n }\n\n if (!response.body) {\n throw new EvalRunnerError({ code: 'SSE_NO_BODY', message: 'SSE response has no body' })\n }\n\n this.connected = true\n\n // Start background parsing loop\n this._consumeStream(response.body).catch((err) => {\n if (this.connected) {\n this.streamError = err instanceof Error ? err : new Error(String(err))\n }\n })\n\n // Wait for the initial snapshot to arrive before returning.\n // This ensures that connect() resolves only after the snapshot\n // has been processed so callers can immediately check spans.\n await this._waitForSnapshot()\n }\n\n /**\n * Mark the beginning of a new turn.\n * Records which handler.conversation span IDs have been seen so far,\n * so waitForTurnComplete() only resolves on NEW handler completions.\n */\n startTurn(): void {\n // Snapshot the current set of span keys as the turn boundary\n this.turnStartKeys = new Set(this.spanMap.keys())\n\n // Record all handler.conversation spans seen so far\n for (const [key, span] of this.spanMap) {\n if (span.name === 'handler.conversation') {\n this.seenHandlerKeys.add(key)\n }\n }\n }\n\n private static readonly SETTLE_MS = 100\n\n /**\n * Wait for a handler.conversation span to reach terminal status (ok or error).\n * Only considers spans NOT seen before the last startTurn() call.\n *\n * After the handler closes, waits for a quiet period (no new spans for SETTLE_MS)\n * to ensure all child spans (tool calls, messages, state saves) have arrived.\n * The runtime's HttpSpanExporter fires POSTs without awaiting them, so child\n * spans may arrive slightly after the handler close event.\n */\n async waitForTurnComplete(opts: WaitOptions): Promise<void> {\n // Check if a completed handler already exists (e.g. from snapshot)\n if (this._hasNewCompletedHandler()) {\n return this._settleAfterHandler()\n }\n if (opts.abortSignal?.aborted) {\n throw new Error('waitForTurnComplete aborted')\n }\n\n return new Promise<void>((resolve, reject) => {\n const timer = setTimeout(() => {\n this._removeWaiter(waiter)\n opts.abortSignal?.removeEventListener('abort', onAbort)\n const reason = this.streamError\n ? `SSE stream died: ${this.streamError.message}`\n : 'no handler.conversation span completed'\n reject(\n new Error(\n `waitForTurnComplete timed out after ${opts.timeout}ms \u2014 ${reason}; diagnostics: ${this._formatTurnDiagnostics()}`\n )\n )\n }, opts.timeout)\n\n const onAbort = () => {\n clearTimeout(timer)\n this._removeWaiter(waiter)\n reject(new Error('waitForTurnComplete aborted'))\n }\n opts.abortSignal?.addEventListener('abort', onAbort, { once: true })\n\n const waiter = (_span: Span) => {\n if (this._hasNewCompletedHandler()) {\n clearTimeout(timer)\n this._removeWaiter(waiter)\n opts.abortSignal?.removeEventListener('abort', onAbort)\n this._settleAfterHandler().then(resolve, reject)\n }\n }\n\n this.waiters.push(waiter)\n })\n }\n\n private static readonly MAX_SETTLE_MS = 2_000\n\n /**\n * After the handler span closes, wait for spans to stop arriving.\n * Resolves when no new spans arrive for SETTLE_MS, or after MAX_SETTLE_MS hard cap.\n *\n * Exposes a cancellation hook via _cancelSettle so disconnect() can short-\n * circuit an in-flight settle phase and avoid leaking timers for up to 2s.\n */\n private _settleAfterHandler(): Promise<void> {\n return new Promise<void>((resolve) => {\n let resolved = false\n const done = () => {\n if (resolved) return\n resolved = true\n clearTimeout(hardCap)\n clearTimeout(settleTimer)\n this._removeWaiter(settleWaiter)\n this._cancelSettle = null\n resolve()\n }\n\n const hardCap = setTimeout(done, SSECollector.MAX_SETTLE_MS)\n\n let settleTimer = setTimeout(done, SSECollector.SETTLE_MS)\n\n const settleWaiter = () => {\n if (resolved) return\n clearTimeout(settleTimer)\n settleTimer = setTimeout(done, SSECollector.SETTLE_MS)\n }\n\n this.waiters.push(settleWaiter)\n this._cancelSettle = done\n })\n }\n\n /**\n * Wait for a handler.workflow span with matching workflow name.\n * - signal 'entered': resolves when the span appears (any status)\n * - signal 'completed': resolves when the span has status !== 'running'\n */\n async waitForWorkflow(name: string, opts: WorkflowWaitOptions): Promise<void> {\n // Check if condition is already met\n if (this._matchesWorkflowCondition(name, opts.signal)) {\n return\n }\n if (opts.abortSignal?.aborted) {\n throw new Error(`waitForWorkflow(\"${name}\", { signal: \"${opts.signal}\" }) aborted`)\n }\n\n return new Promise<void>((resolve, reject) => {\n const timer = setTimeout(() => {\n this._removeWaiter(waiter)\n opts.abortSignal?.removeEventListener('abort', onAbort)\n const reason = this.streamError ? `SSE stream died: ${this.streamError.message}` : 'span not found'\n reject(\n new Error(\n `waitForWorkflow(\"${name}\", { signal: \"${opts.signal}\" }) timed out after ${opts.timeout}ms \u2014 ${reason}`\n )\n )\n }, opts.timeout)\n\n const onAbort = () => {\n clearTimeout(timer)\n this._removeWaiter(waiter)\n reject(new Error(`waitForWorkflow(\"${name}\", { signal: \"${opts.signal}\" }) aborted`))\n }\n opts.abortSignal?.addEventListener('abort', onAbort, { once: true })\n\n const waiter = (_span: Span) => {\n if (this._matchesWorkflowCondition(name, opts.signal)) {\n clearTimeout(timer)\n this._removeWaiter(waiter)\n opts.abortSignal?.removeEventListener('abort', onAbort)\n resolve()\n }\n }\n\n this.waiters.push(waiter)\n })\n }\n\n /**\n * Return spans accumulated since the last startTurn() call.\n */\n getTurnSpans(): Span[] {\n const result: Span[] = []\n for (const [key, span] of this.spanMap) {\n if (!this.turnStartKeys.has(key)) {\n result.push(span)\n }\n }\n return result\n }\n\n /**\n * Return all spans accumulated since connect().\n */\n getAllSpans(): Span[] {\n return Array.from(this.spanMap.values())\n }\n\n /**\n * Close the SSE connection and clean up.\n */\n disconnect(): void {\n this.connected = false\n this.abortController?.abort()\n this.abortController = null\n // Short-circuit an in-flight settle phase so its hardCap / settleTimer\n // don't fire after disconnect.\n this._cancelSettle?.()\n this._cancelSettle = null\n // Waiters hold setTimeout references that will reject on their own;\n // clearing the array just prevents further notifications.\n this.waiters = []\n this.snapshotResolvers = []\n }\n\n // \u2500\u2500 Private \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n /** Whether we have received the initial snapshot. */\n private snapshotReceived = false\n private snapshotResolvers: Array<() => void> = []\n\n private static readonly SNAPSHOT_TIMEOUT_MS = 10_000\n\n /**\n * Returns a promise that resolves once the snapshot event has been processed,\n * or rejects after a timeout to prevent connect() from hanging indefinitely.\n */\n private _waitForSnapshot(): Promise<void> {\n if (this.snapshotReceived) {\n return Promise.resolve()\n }\n return new Promise<void>((resolve, reject) => {\n let settled = false\n const resolver = () => {\n if (settled) return\n settled = true\n clearTimeout(timer)\n resolve()\n }\n const timer = setTimeout(() => {\n if (settled) return\n settled = true\n const idx = this.snapshotResolvers.indexOf(resolver)\n if (idx !== -1) this.snapshotResolvers.splice(idx, 1)\n reject(\n new Error(\n `SSE snapshot not received within ${SSECollector.SNAPSHOT_TIMEOUT_MS}ms \u2014 is the dev server healthy?`\n )\n )\n }, SSECollector.SNAPSHOT_TIMEOUT_MS)\n this.snapshotResolvers.push(resolver)\n })\n }\n\n /**\n * Consume the ReadableStream body, parse SSE lines, and dispatch events.\n */\n private async _consumeStream(body: ReadableStream<Uint8Array>): Promise<void> {\n const decoder = new TextDecoder()\n let buffer = ''\n\n const reader = body.getReader()\n\n try {\n while (this.connected) {\n const { done, value } = await reader.read()\n if (done) break\n\n buffer += decoder.decode(value, { stream: true })\n\n // Split on double-newline boundaries to get complete SSE events\n const parts = buffer.split('\\n\\n')\n // The last part may be incomplete \u2014 keep it in the buffer\n buffer = parts.pop() ?? ''\n\n for (const part of parts) {\n this._parseSSEBlock(part)\n }\n }\n } finally {\n reader.releaseLock()\n }\n }\n\n /**\n * Parse a single SSE event block (text between \\n\\n boundaries).\n * Extracts event name and data payload.\n */\n private _parseSSEBlock(block: string): void {\n const lines = block.split('\\n')\n let eventName = ''\n let dataLine = ''\n\n for (const line of lines) {\n if (line.startsWith('event:')) {\n eventName = line.slice('event:'.length).trim()\n } else if (line.startsWith('data:')) {\n const value = line.slice('data:'.length).trim()\n dataLine = dataLine ? `${dataLine}\\n${value}` : value\n }\n // id: and retry: lines are ignored\n }\n\n if (!eventName || !dataLine) {\n // Could be a retry: line or empty block \u2014 skip\n if (!this.snapshotReceived && block.includes('retry:')) {\n // The retry line comes before the snapshot; don't resolve yet\n }\n return\n }\n\n try {\n const payload = JSON.parse(dataLine)\n this._handleEvent(eventName, payload)\n } catch {\n // Malformed JSON \u2014 skip\n }\n }\n\n /**\n * Dispatch a parsed SSE event to the appropriate handler.\n */\n private _handleEvent(eventName: string, payload: unknown): void {\n this._recordEvent(eventName)\n\n if (eventName === 'snapshot') {\n const data = payload as { spans: Span[] }\n const spans = Array.isArray(data.spans) ? data.spans : []\n for (const span of spans) {\n this._upsertSpan(span)\n }\n this.snapshotReceived = true\n for (const resolve of this.snapshotResolvers) {\n resolve()\n }\n this.snapshotResolvers = []\n } else if (eventName === 'update') {\n const data = payload as { span: Span }\n if (data.span) {\n this._upsertSpan(data.span)\n this._notifyWaiters(data.span)\n }\n }\n // keepalive events are intentionally ignored\n }\n\n private _recordEvent(eventName: string): void {\n this.lastEvent = { name: eventName, at: Date.now() }\n\n if (eventName === 'update') {\n this.updateEventCount++\n } else if (eventName === 'keepalive') {\n this.keepaliveEventCount++\n }\n }\n\n private _formatTurnDiagnostics(): string {\n const turnSpans = this.getTurnSpans()\n const spanNames = new Set<string>()\n const handlerStatuses = new Set<string>()\n\n for (const span of turnSpans) {\n spanNames.add(span.name)\n if (span.name === 'handler.conversation') {\n handlerStatuses.add(span.status)\n }\n }\n\n const lastEvent = this.lastEvent ? `${this.lastEvent.name} ${Date.now() - this.lastEvent.at}ms ago` : 'none'\n\n return [\n `snapshotReceived=${this.snapshotReceived}`,\n `totalUpdates=${this.updateEventCount}`,\n `totalKeepalives=${this.keepaliveEventCount}`,\n `lastEvent=${lastEvent}`,\n `totalSpans=${this.spanMap.size}`,\n `turnSpans=${turnSpans.length}`,\n `turnSpanNames=${this._formatSet(spanNames)}`,\n `handlerConversationStatuses=${this._formatSet(handlerStatuses)}`,\n ].join(', ')\n }\n\n private _formatSet(values: Set<string>, limit = 12): string {\n if (values.size === 0) {\n return 'none'\n }\n\n const items = Array.from(values)\n const suffix = items.length > limit ? `|+${items.length - limit} more` : ''\n return `${items.slice(0, limit).join('|')}${suffix}`\n }\n\n /**\n * Insert or replace a span in the map (dedup by trace+span ID).\n */\n private _upsertSpan(span: Span): void {\n this.spanMap.set(spanKey(span), span)\n }\n\n /**\n * Notify all waiters that a new span was received.\n */\n private _notifyWaiters(span: Span): void {\n // Copy the array since waiters may remove themselves during iteration\n const current = [...this.waiters]\n for (const waiter of current) {\n waiter(span)\n }\n }\n\n /**\n * Remove a waiter callback from the list.\n */\n private _removeWaiter(fn: (span: Span) => void): void {\n const idx = this.waiters.indexOf(fn)\n if (idx !== -1) {\n this.waiters.splice(idx, 1)\n }\n }\n\n /**\n * Check if there is a handler.conversation span that:\n * 1. Was NOT seen before startTurn()\n * 2. Has terminal status (ok or error)\n *\n * Marks the matched key as consumed so the same handler span cannot\n * satisfy both the current turn's settle phase AND the next turn's\n * waitForTurnComplete check (which would otherwise resolve instantly\n * against stale data instead of waiting for the new turn's handler).\n */\n private _hasNewCompletedHandler(): boolean {\n for (const [key, span] of this.spanMap) {\n if (\n span.name === 'handler.conversation' &&\n !this.seenHandlerKeys.has(key) &&\n (span.status === 'ok' || span.status === 'error')\n ) {\n this.seenHandlerKeys.add(key)\n return true\n }\n }\n return false\n }\n\n /**\n * Check if a handler.workflow span matches the given condition.\n */\n private _matchesWorkflowCondition(name: string, signal: 'entered' | 'completed'): boolean {\n for (const span of this.spanMap.values()) {\n if (span.name !== 'handler.workflow') continue\n\n const d = spanData(span)\n const wfName = d['workflow.name'] || d['workflowName']\n if (wfName !== name) continue\n\n if (signal === 'entered') {\n // Any status means the workflow was entered\n return true\n }\n\n if (signal === 'completed') {\n return span.status === 'ok' || span.status === 'error'\n }\n }\n return false\n }\n}\n", "/**\n * Transformer: projects raw trace spans into grader-friendly TurnData.\n * Pure function \u2014 no side effects, no network calls.\n */\n\nimport type { Span } from './trace'\nimport type { StateMutation, ToolCall, TurnData, WorkflowSpan } from './types'\n\n/** Safe accessor for span.data as a string-keyed record. */\nfunction data(span: Span): Record<string, unknown> {\n return (span.data && typeof span.data === 'object' ? span.data : {}) as Record<string, unknown>\n}\n\n/** Attempt to parse a JSON string. Returns parsed result, raw value on parse failure, or fallback if value is nullish. */\nfunction tryParseJson(value: unknown): unknown {\n if (value == null) return undefined\n if (typeof value !== 'string') return value\n try {\n return JSON.parse(value)\n } catch {\n // Not JSON \u2014 fall back to the raw value, per this function's contract\n return value\n }\n}\n\n/** Parse JSON with a strict fallback \u2014 returns fallback on parse failure instead of the raw string. */\nfunction parseJsonOrFallback<T>(value: unknown, fallback: T): T {\n if (typeof value !== 'string') return fallback\n try {\n return JSON.parse(value) as T\n } catch {\n // Not JSON \u2014 return the caller's fallback, per this function's contract\n return fallback\n }\n}\n\n/**\n * Transform raw trace spans into structured TurnData for graders.\n *\n * Extraction logic:\n * - messages: from `chat.sendMessage` spans, ordered by startedAt\n * - toolCalls: from `autonomous.tool` spans with terminal status, deduped by span id, ordered by endedAt\n * - stateMutations: from `state.save` spans where changed_keys has length > 0\n * - workflowSpans: from `handler.workflow` spans\n * - handler: from `handler.conversation` or `handler.workflow` span with terminal status\n */\nexport function transformSpans(spans: Span[]): TurnData {\n return {\n messages: extractMessages(spans),\n toolCalls: extractToolCalls(spans),\n stateMutations: extractStateMutations(spans),\n workflowSpans: extractWorkflowSpans(spans),\n ...extractHandler(spans),\n }\n}\n\nfunction extractMessages(spans: Span[]): string[] {\n return spans\n .filter((s) => s.name === 'chat.sendMessage' && data(s)['message.preview'])\n .sort((a, b) => a.timing.startedAt - b.timing.startedAt)\n .map((s) => String(data(s)['message.preview']))\n}\n\nfunction extractToolCalls(spans: Span[]): ToolCall[] {\n const toolSpans = spans.filter(\n (s) => s.name === 'autonomous.tool' && s.status !== 'running' && data(s)['autonomous.tool.name']\n )\n\n // Deduplicate by span id\n const seen = new Set<string>()\n const unique = toolSpans.filter((s) => {\n if (seen.has(s.id.span)) return false\n seen.add(s.id.span)\n return true\n })\n\n return unique\n .sort((a, b) => (a.timing.endedAt ?? Infinity) - (b.timing.endedAt ?? Infinity))\n .map((s) => {\n const d = data(s)\n const input = parseJsonOrFallback<Record<string, unknown>>(d['autonomous.tool.input'], {})\n return {\n name: String(d['autonomous.tool.name']),\n input,\n output: String(d['autonomous.tool.output'] ?? ''),\n status: String(d['autonomous.tool.status'] ?? 'unknown'),\n }\n })\n}\n\nfunction extractStateMutations(spans: Span[]): StateMutation[] {\n return spans\n .filter((s) => {\n if (s.name !== 'state.save') return false\n const d = data(s)\n const changedKeys = d['state.changed_keys']\n return Array.isArray(changedKeys) && changedKeys.length > 0\n })\n .map((s) => {\n const d = data(s)\n return {\n type: String(d['type'] ?? 'unknown'),\n changedKeys: (d['state.changed_keys'] as string[]) ?? [],\n previous: tryParseJson(d['state.previous_value']),\n current: tryParseJson(d['state.value']),\n swappedToFile: d['swapped_to_file'] === true,\n }\n })\n}\n\nfunction extractWorkflowSpans(spans: Span[]): WorkflowSpan[] {\n return spans\n .filter((s) => s.name === 'handler.workflow')\n .map((s) => {\n const d = data(s)\n const result: WorkflowSpan = {\n name: String(d['workflow.name'] || d['workflowName'] || ''),\n status: s.status as WorkflowSpan['status'],\n }\n const statusFinal = d['workflow.status.final']\n if (statusFinal) {\n result.statusFinal = String(statusFinal)\n }\n return result\n })\n}\n\nfunction extractHandler(spans: Span[]): { handlerDuration: number; handlerStatus: 'ok' | 'error' } {\n const handler = spans.find(\n (s) => (s.name === 'handler.conversation' || s.name === 'handler.workflow') && s.status !== 'running'\n )\n\n if (!handler) {\n return { handlerDuration: 0, handlerStatus: 'ok' }\n }\n\n return {\n handlerDuration: handler.timing.duration ?? 0,\n handlerStatus: handler.status === 'error' ? 'error' : 'ok',\n }\n}\n", "/**\n * LLM judge grader using @botpress/cognitive.\n * Replaces the OpenAI-based implementation from the standalone project.\n */\n\nimport { Client } from '@botpress/client'\nimport { Cognitive } from '@botpress/cognitive'\nimport type { EvalLogger, GraderResult } from '../types'\nimport { defaultLogger } from '../types'\n\nconst DEFAULT_PASS_THRESHOLD = 3\n\nfunction buildJudgeSystemPrompt(passThreshold: number): string {\n return `You are an evaluation judge for a chatbot. You will be given:\n- The user's message\n- The bot's response\n- Grading criteria\n\nYour job is to determine if the bot's response meets the criteria.\n\nRespond with a JSON object:\n{\n \"pass\": true/false,\n \"score\": 1-5,\n \"reason\": \"brief explanation\"\n}\n\nScoring guide:\n- 5: Fully meets criteria, excellent response\n- 4: Mostly meets criteria, minor issues\n- 3: Partially meets criteria, notable gaps\n- 2: Barely meets criteria, significant issues\n- 1: Does not meet criteria\n\nA score of ${passThreshold} or above is a pass.`\n}\n\nconst MODEL_ALIASES = ['fast', 'best']\n\nlet _cognitive: Cognitive | null = null\nlet _availableModels: string[] = []\nlet _judgeModel: string = 'fast'\nlet _log: EvalLogger = defaultLogger\n\n/** @internal Test-only: clears module judge state so tests stay hermetic in the shared bun test process. */\nexport function _resetLLMJudgeForTests(): void {\n _cognitive = null\n _availableModels = []\n _judgeModel = 'fast'\n _log = defaultLogger\n}\n\nfunction _isModelValid(model: string): boolean {\n if (MODEL_ALIASES.includes(model)) return true\n if (_availableModels.length === 0) return false\n\n return _availableModels.includes(model)\n}\n\n/**\n * Initialize the LLM judge with explicit credentials.\n * Call this before running evals so the judge doesn't need env vars.\n */\nexport async function initLLMJudge(\n credentials: { token: string; apiUrl: string; botId: string; workspaceId?: string },\n options?: { model?: string; logger?: EvalLogger }\n) {\n const log = options?.logger ?? defaultLogger\n _log = log\n\n const client = new Client({\n token: credentials.token,\n apiUrl: credentials.apiUrl,\n botId: credentials.botId,\n ...(credentials.workspaceId !== undefined ? { workspaceId: credentials.workspaceId } : {}),\n })\n _cognitive = new Cognitive({ client, __experimental_beta: true })\n\n try {\n _availableModels = Array.from((await _cognitive.fetchRemoteModels()).keys())\n } catch (err) {\n log.warn(`Failed to fetch available models: ${(err as Error).message}. LLM judge will be unavailable.`)\n _availableModels = []\n }\n\n _judgeModel = options?.model ?? 'fast'\n\n if (_availableModels.length === 0) {\n log.warn('No available Cognitive models: cannot validate judge model.')\n } else if (!_isModelValid(_judgeModel)) {\n log.warn(`Configured LLM judge model \"${_judgeModel}\" is invalid. Run \"adk models\" to list available models.`)\n }\n}\n\nexport async function gradeLLMJudge(\n botResponse: string,\n criteria: string,\n context: { userMessage: string; passThreshold?: number }\n): Promise<GraderResult> {\n const threshold = Math.max(1, Math.min(5, context.passThreshold ?? DEFAULT_PASS_THRESHOLD))\n\n try {\n // A judge that can't run must NOT silently pass the assertion \u2014 a flaky\n // LLM call or missing credentials would turn real assertions green.\n // Unavailability is a visible failure with a clear reason.\n if (!_cognitive) {\n _log.warn(`LLM judge unavailable for \"${criteria}\": no credentials configured (initLLMJudge not called)`)\n return {\n assertion: `llm_judge: \"${criteria}\"`,\n pass: false,\n expected: criteria,\n actual: 'FAILED \u2014 LLM judge unavailable: no credentials configured',\n }\n }\n\n if (!_isModelValid(_judgeModel)) {\n return {\n assertion: `llm_judge: \"${criteria}\"`,\n pass: false,\n expected: criteria,\n actual: 'FAILED \u2014 invalid LLM judge model',\n }\n }\n\n type CognitiveModel = Exclude<Parameters<Cognitive['generateContent']>[0]['model'], undefined>\n\n const { output } = await _cognitive.generateContent({\n model: _judgeModel as CognitiveModel,\n temperature: 0,\n responseFormat: 'json_object',\n systemPrompt: buildJudgeSystemPrompt(threshold),\n messages: [\n {\n role: 'user',\n content: `User message: ${context.userMessage}\\n\\nBot response: ${botResponse}\\n\\nCriteria: ${criteria}`,\n },\n ],\n })\n\n const rawContent = output?.choices?.[0]?.content\n const content = typeof rawContent === 'string' ? rawContent : null\n if (!content) {\n _log.warn(`LLM judge returned an empty response for \"${criteria}\"`)\n return {\n assertion: `llm_judge: \"${criteria}\"`,\n pass: false,\n expected: criteria,\n actual: 'FAILED \u2014 LLM judge returned empty response',\n }\n }\n\n const verdict = JSON.parse(content) as {\n pass: boolean\n score: number\n reason: string\n }\n\n return {\n assertion: `llm_judge: \"${criteria}\"`,\n pass: verdict.score >= threshold,\n expected: criteria,\n actual: `Score ${verdict.score}/5 (threshold: ${threshold}) \u2014 ${verdict.reason}`,\n }\n } catch (err) {\n _log.warn(`LLM judge failed for \"${criteria}\": ${(err as Error).message}`)\n return {\n assertion: `llm_judge: \"${criteria}\"`,\n pass: false,\n expected: criteria,\n actual: `FAILED \u2014 LLM judge unavailable: ${(err as Error).message}`,\n }\n }\n}\n", "/**\n * Response assertion graders.\n * Checks bot response text against expected assertions.\n */\n\nimport type { ResponseAssertion, GraderResult } from '../types'\nimport { gradeLLMJudge } from './llm'\n\nexport async function gradeResponse(\n botResponse: string,\n assertions: ResponseAssertion[],\n context: { userMessage: string; judgePassThreshold?: number }\n): Promise<GraderResult[]> {\n const results: GraderResult[] = []\n\n for (const assertion of assertions) {\n if ('contains' in assertion) {\n const pass = botResponse.toLowerCase().includes(assertion.contains.toLowerCase())\n results.push({\n assertion: `contains \"${assertion.contains}\"`,\n pass,\n expected: `Response contains \"${assertion.contains}\"`,\n actual: pass ? `Found in response` : `Not found in response`,\n })\n continue\n }\n\n if ('not_contains' in assertion) {\n const pass = !botResponse.toLowerCase().includes(assertion.not_contains.toLowerCase())\n results.push({\n assertion: `not_contains \"${assertion.not_contains}\"`,\n pass,\n expected: `Response does not contain \"${assertion.not_contains}\"`,\n actual: pass ? `Not found in response` : `Found in response`,\n })\n continue\n }\n\n if ('matches' in assertion) {\n const regex = new RegExp(assertion.matches, 'i')\n const pass = regex.test(botResponse)\n results.push({\n assertion: `matches ${assertion.matches}`,\n pass,\n expected: `Response matches /${assertion.matches}/`,\n actual: pass ? `Matched` : `No match`,\n })\n continue\n }\n\n if ('llm_judge' in assertion) {\n const result = await gradeLLMJudge(botResponse, assertion.llm_judge, {\n userMessage: context.userMessage,\n ...(context.judgePassThreshold !== undefined ? { passThreshold: context.judgePassThreshold } : {}),\n })\n results.push(result)\n continue\n }\n\n // TODO: uncomment this once we support it\n // if ('similar_to' in assertion) {\n // results.push({\n // assertion: `similar_to: \"${assertion.similar_to}\"`,\n // pass: true,\n // expected: assertion.similar_to,\n // actual: 'SKIPPED \u2014 similar_to not yet implemented',\n // })\n // continue\n // }\n\n results.push({\n assertion: 'unknown',\n pass: false,\n expected: 'known assertion type',\n actual: `Unknown assertion: ${JSON.stringify(assertion)}`,\n })\n }\n\n return results\n}\n", "/**\n * Shared match utilities for assertion grading.\n * Used by tool, state, and table graders.\n */\n\nimport type { MatchOperator } from '../types'\n\n/**\n * Evaluate a single match operator against a value.\n */\nexport function matchValue(operator: MatchOperator, actual: unknown): boolean {\n // Shorthand: string means exact match\n if (typeof operator === 'string') {\n return String(actual) === operator\n }\n\n if ('equals' in operator) {\n return actual === operator.equals\n }\n\n if ('contains' in operator) {\n return String(actual).toLowerCase().includes(operator.contains.toLowerCase())\n }\n\n if ('not_contains' in operator) {\n return !String(actual).toLowerCase().includes(operator.not_contains.toLowerCase())\n }\n\n if ('matches' in operator) {\n return new RegExp(operator.matches, 'i').test(String(actual))\n }\n\n if ('in' in operator) {\n return operator.in.includes(actual)\n }\n\n if ('exists' in operator) {\n return operator.exists ? actual !== undefined && actual !== null : actual === undefined || actual === null\n }\n\n if ('gte' in operator) {\n return Number(actual) >= operator.gte\n }\n\n if ('lte' in operator) {\n return Number(actual) <= operator.lte\n }\n\n return false\n}\n\nexport function operatorToString(operator: MatchOperator): string {\n if (typeof operator === 'string') return `equals \"${operator}\"`\n if ('equals' in operator) return `equals ${JSON.stringify(operator.equals)}`\n if ('contains' in operator) return `contains \"${operator.contains}\"`\n if ('not_contains' in operator) return `not_contains \"${operator.not_contains}\"`\n if ('matches' in operator) return `matches /${operator.matches}/`\n if ('in' in operator) return `in [${operator.in.map((v) => JSON.stringify(v)).join(', ')}]`\n if ('exists' in operator) return operator.exists ? 'exists' : 'does not exist'\n if ('gte' in operator) return `>= ${operator.gte}`\n if ('lte' in operator) return `<= ${operator.lte}`\n return JSON.stringify(operator)\n}\n", "/**\n * Tool assertion graders.\n * Checks tool calls from traces against expected assertions.\n */\n\nimport type { ToolAssertion, ToolCall, GraderResult } from '../types'\nimport { matchValue, operatorToString } from './match'\n\nexport function gradeTools(toolCalls: ToolCall[], assertions: ToolAssertion[]): GraderResult[] {\n return assertions.map((assertion) => {\n // --- called ---\n if ('called' in assertion && !('not_called' in assertion) && !('call_order' in assertion)) {\n const matches = toolCalls.filter((tc) => tc.name === assertion.called)\n const wasCalled = matches.length > 0\n\n if (!wasCalled) {\n return {\n assertion: `tool called: ${assertion.called}`,\n pass: false,\n expected: `${assertion.called} was called`,\n actual: `Not called. Tools called: [${toolCalls.map((tc) => tc.name).join(', ') || 'none'}]`,\n }\n }\n\n // Check params if specified\n if (assertion.params) {\n const paramResults: { key: string; pass: boolean; detail: string }[] = []\n\n for (const [key, operator] of Object.entries(assertion.params)) {\n // Check across all matching calls \u2014 pass if any call matches\n const anyMatch = matches.some((tc) => matchValue(operator, tc.input[key]))\n paramResults.push({\n key,\n pass: anyMatch,\n detail: anyMatch\n ? `matched`\n : `expected ${key} ${operatorToString(operator)}, got ${JSON.stringify(matches.map((tc) => tc.input[key]))}`,\n })\n }\n\n const allParamsPass = paramResults.every((p) => p.pass)\n const failedParams = paramResults.filter((p) => !p.pass)\n\n return {\n assertion: `tool called: ${assertion.called} with params`,\n pass: allParamsPass,\n expected: `${assertion.called} called with ${Object.entries(assertion.params)\n .map(([k, v]) => `${k} ${operatorToString(v)}`)\n .join(', ')}`,\n actual: allParamsPass ? `Matched` : failedParams.map((p) => p.detail).join('; '),\n }\n }\n\n return {\n assertion: `tool called: ${assertion.called}`,\n pass: true,\n expected: `${assertion.called} was called`,\n actual: `Called ${matches.length} time(s)`,\n }\n }\n\n // --- not_called ---\n if ('not_called' in assertion) {\n const wasCalled = toolCalls.some((tc) => tc.name === assertion.not_called)\n return {\n assertion: `tool not_called: ${assertion.not_called}`,\n pass: !wasCalled,\n expected: `${assertion.not_called} was NOT called`,\n actual: wasCalled ? `Was called` : `Not called`,\n }\n }\n\n // --- call_order ---\n if ('call_order' in assertion) {\n const calledNames = toolCalls.map((tc) => tc.name)\n const expectedOrder = assertion.call_order as string[]\n\n // Check that the expected sequence appears in order (not necessarily contiguous)\n let cursor = 0\n for (const name of calledNames) {\n if (cursor < expectedOrder.length && name === expectedOrder[cursor]) {\n cursor++\n }\n }\n const inOrder = cursor === expectedOrder.length\n\n return {\n assertion: `call_order: [${expectedOrder.join(' \u2192 ')}]`,\n pass: inOrder,\n expected: `Tools called in order: [${expectedOrder.join(' \u2192 ')}]`,\n actual: `Actual order: [${calledNames.join(' \u2192 ') || 'none'}]`,\n }\n }\n\n return {\n assertion: 'unknown tool assertion',\n pass: false,\n expected: 'known assertion type',\n actual: `Unknown: ${JSON.stringify(assertion)}`,\n }\n })\n}\n", "/**\n * State assertion graders.\n * Pure functions that grade state assertions against StateMutation[] from the transformer.\n * No API calls, no retries, no BpClient.\n */\n\nimport type { StateMutation, StateAssertion, GraderResult } from '../types'\n\n/**\n * Parse a state path like \"conversation.lastCity\" into its components.\n * bot.* -> type: \"bot\", field: \"*\"\n * user.* -> type: \"user\", field: \"*\"\n * conversation.* -> type: \"conversation\", field: \"*\"\n */\nfunction parseStatePath(path: string): { type: string; field: string } {\n const dot = path.indexOf('.')\n if (dot === -1) {\n throw new Error(`Invalid state path \"${path}\" \u2014 expected \"type.field\" format`)\n }\n\n const type = path.slice(0, dot)\n const field = path.slice(dot + 1)\n\n if (type !== 'bot' && type !== 'user' && type !== 'conversation') {\n throw new Error(`Unknown state type \"${type}\" in path \"${path}\" \u2014 expected bot, user, or conversation`)\n }\n\n return { type, field }\n}\n\n/**\n * Grade state assertions using StateMutation[] from the transformer.\n *\n * - `equals`: find the LAST mutation matching the state type, extract field from `current`, deep-compare\n * - `changed: true`: check if the field appears in ANY mutation's `changedKeys` for that state type\n * - `changed: false`: check that the field appears in NO mutation's `changedKeys`\n * - Swapped state: when `swappedToFile` is true, current/previous are undefined \u2014 report a clear message\n */\nexport function gradeState(mutations: StateMutation[], assertions: StateAssertion[]): GraderResult[] {\n const results: GraderResult[] = []\n\n for (const assertion of assertions) {\n const parsed = parseStatePath(assertion.path)\n const matchingMutations = mutations.filter((m) => m.type === parsed.type)\n\n if (assertion.equals !== undefined) {\n if (matchingMutations.length === 0) {\n results.push({\n assertion: `state: ${assertion.path} equals`,\n pass: false,\n expected: JSON.stringify(assertion.equals),\n actual:\n `No state.save span found for \"${parsed.type}\" \u2014 the bot did not mutate this state during the turn. ` +\n 'If this state was seeded via setup.state, assert on the tool/action that reads it, or use a conversation turn that triggers a state write.',\n })\n continue\n }\n\n const lastMutation = matchingMutations[matchingMutations.length - 1]!\n\n if (lastMutation.swappedToFile) {\n results.push({\n assertion: `state: ${assertion.path} equals`,\n pass: false,\n expected: JSON.stringify(assertion.equals),\n actual: 'State was too large for trace-based assertion (swapped to file)',\n })\n continue\n }\n\n const currentState = lastMutation.current as Record<string, unknown> | undefined\n const actualValue = currentState ? currentState[parsed.field] : undefined\n const pass = deepEqual(actualValue, assertion.equals)\n\n results.push({\n assertion: `state: ${assertion.path} equals`,\n pass,\n expected: JSON.stringify(assertion.equals),\n actual: JSON.stringify(actualValue),\n })\n }\n\n if (assertion.changed !== undefined) {\n if (matchingMutations.length === 0) {\n results.push({\n assertion: `state: ${assertion.path} ${assertion.changed ? 'changed' : 'unchanged'}`,\n pass: !assertion.changed,\n expected: assertion.changed\n ? `Field \"${parsed.field}\" changed in a \"${parsed.type}\" state mutation`\n : `Field \"${parsed.field}\" unchanged`,\n actual: 'No state mutation found for type \"' + parsed.type + '\"',\n })\n continue\n }\n\n // Check for swapped state in any matching mutation\n const hasSwapped = matchingMutations.some((m) => m.swappedToFile)\n if (hasSwapped) {\n results.push({\n assertion: `state: ${assertion.path} ${assertion.changed ? 'changed' : 'unchanged'}`,\n pass: false,\n expected: assertion.changed\n ? `Field \"${parsed.field}\" changed in a \"${parsed.type}\" state mutation`\n : `Field \"${parsed.field}\" unchanged`,\n actual: 'State was too large for trace-based assertion (swapped to file)',\n })\n continue\n }\n\n const fieldChanged = matchingMutations.some((m) => m.changedKeys.includes(parsed.field))\n const pass = assertion.changed ? fieldChanged : !fieldChanged\n\n results.push({\n assertion: `state: ${assertion.path} ${assertion.changed ? 'changed' : 'unchanged'}`,\n pass,\n expected: assertion.changed\n ? `Field \"${parsed.field}\" changed in a \"${parsed.type}\" state mutation`\n : `Field \"${parsed.field}\" unchanged`,\n actual: fieldChanged ? `Field \"${parsed.field}\" was changed` : `Field \"${parsed.field}\" was not changed`,\n })\n }\n }\n\n return results\n}\n\nfunction deepEqual(a: unknown, b: unknown): boolean {\n if (a === b) return true\n if (a === null || b === null) return false\n if (typeof a !== typeof b) return false\n\n if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) return false\n return a.every((v, i) => deepEqual(v, b[i]))\n }\n\n if (Array.isArray(a) !== Array.isArray(b)) return false\n\n if (typeof a === 'object' && typeof b === 'object') {\n const keysA = Object.keys(a as object)\n const keysB = Object.keys(b as object)\n if (keysA.length !== keysB.length) return false\n return keysA.every((k) => deepEqual((a as Record<string, unknown>)[k], (b as Record<string, unknown>)[k]))\n }\n\n return false\n}\n", "/**\n * Workflow assertion graders.\n * Checks workflow execution via transformer-produced WorkflowSpan data.\n */\n\nimport type { WorkflowAssertion, WorkflowSpan, GraderResult } from '../types'\n\nexport function gradeWorkflows(workflows: WorkflowSpan[], assertions: WorkflowAssertion[]): GraderResult[] {\n const results: GraderResult[] = []\n\n for (const assertion of assertions) {\n const matching = workflows.filter((wf) => wf.name === assertion.name)\n\n // entered \u2014 was the workflow triggered at all?\n if (assertion.entered !== undefined) {\n const wasEntered = matching.length > 0\n const pass = assertion.entered ? wasEntered : !wasEntered\n\n results.push({\n assertion: `workflow: ${assertion.name} ${assertion.entered ? 'entered' : 'not entered'}`,\n pass,\n expected: assertion.entered\n ? `Workflow \"${assertion.name}\" was entered`\n : `Workflow \"${assertion.name}\" was not entered`,\n actual: wasEntered ? `Found ${matching.length} workflow span(s)` : `No workflow spans found`,\n })\n }\n\n // completed \u2014 did the workflow complete?\n if (assertion.completed !== undefined) {\n const didComplete = matching.some(\n (wf) => wf.statusFinal === 'completed' || wf.status === 'ok' || wf.status === 'error'\n )\n const pass = assertion.completed ? didComplete : !didComplete\n\n results.push({\n assertion: `workflow: ${assertion.name} ${assertion.completed ? 'completed' : 'not completed'}`,\n pass,\n expected: assertion.completed\n ? `Workflow \"${assertion.name}\" completed`\n : `Workflow \"${assertion.name}\" did not complete`,\n actual: didComplete ? `Completed` : `Not completed`,\n })\n }\n }\n\n return results\n}\n", "/**\n * Timing assertion graders.\n * Checks bot response duration against expected thresholds.\n */\n\nimport type { TimingAssertion, GraderResult } from '../types'\nimport { matchValue, operatorToString } from './match'\n\nexport function gradeTiming(botDuration: number, assertions: TimingAssertion[]): GraderResult[] {\n const results: GraderResult[] = []\n\n for (const assertion of assertions) {\n const pass = matchValue(assertion.response_time, botDuration)\n const expected = operatorToString(assertion.response_time)\n\n results.push({\n assertion: `response_time ${expected}`,\n pass,\n expected: `Response time ${expected}`,\n actual: `${botDuration}ms`,\n })\n }\n\n return results\n}\n", "/**\n * Outcome assertion orchestrator.\n * Runs state and workflow graders after all conversation turns complete.\n */\n\nimport type { EvalDefinition, GraderResult, StateMutation, WorkflowSpan } from '../types'\nimport { gradeState } from './state'\nimport { gradeWorkflows } from './workflow'\n\n/**\n * Grade all outcome assertions after the conversation completes.\n * Takes transformer output (StateMutation[], WorkflowSpan[]) \u2014 no raw spans, no API calls.\n */\nexport function gradeOutcome(\n mutations: StateMutation[],\n evalDef: EvalDefinition,\n workflowSpans: WorkflowSpan[]\n): GraderResult[] {\n const outcome = evalDef.outcome\n if (!outcome) return []\n\n const results: GraderResult[] = []\n\n if (outcome.state && outcome.state.length > 0) {\n const stateResults = gradeState(mutations, outcome.state)\n results.push(...stateResults)\n }\n\n if (outcome.workflow && outcome.workflow.length > 0) {\n const workflowResults = gradeWorkflows(workflowSpans, outcome.workflow)\n results.push(...workflowResults)\n }\n\n return results\n}\n", "/**\n * Eval file loader.\n * Loads *.eval.ts files from a directory using dynamic imports.\n * Supports both default and named exports, and multiple evals per file.\n */\n\nimport { readdirSync, existsSync } from 'fs'\nimport { resolve } from 'path'\nimport type { EvalDefinition, EvalFilter } from './types'\nimport { Eval } from './types'\nimport { EvalRunnerError } from './errors'\n\nfunction isEvalDefinition(value: unknown): value is EvalDefinition {\n return (\n value !== null &&\n typeof value === 'object' &&\n typeof (value as Record<string, unknown>).name === 'string' &&\n (value as Record<string, unknown>).name !== '' &&\n Array.isArray((value as Record<string, unknown>).conversation)\n )\n}\n\nexport async function loadEvalFile(filePath: string): Promise<EvalDefinition[]> {\n const absPath = resolve(filePath)\n\n let mod: Record<string, unknown>\n try {\n mod = await import(absPath)\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err)\n // Guidance stays in the message until the CLI renders `suggestion`\n // (cli-package remediation) \u2014 report.error/logger.fatal only show message.\n throw new EvalRunnerError({\n code: 'EVAL_LOAD_FAILED',\n message:\n `Failed to load eval file ${filePath}: ${msg}\\n\\n` +\n 'Make sure your eval file:\\n' +\n ' - Has no syntax or type errors\\n' +\n ' - Exports one or more `new Eval({...})` instances\\n' +\n ' - Has all dependencies installed (`bun install`)',\n expected: true,\n cause: err,\n })\n }\n\n const results: EvalDefinition[] = []\n\n for (const [key, value] of Object.entries(mod)) {\n if (key === '__esModule') continue\n if (value instanceof Eval || isEvalDefinition(value)) {\n results.push(value)\n }\n }\n\n if (results.length === 0) {\n throw new EvalRunnerError({\n code: 'EVAL_FILE_EMPTY',\n message: `Invalid eval file ${filePath}: no valid evals found. Export one or more \\`new Eval({...})\\` instances (as default or named exports).`,\n expected: true,\n })\n }\n\n return results\n}\n\nexport async function loadEvalsFromDir(dirPath: string): Promise<EvalDefinition[]> {\n const absDir = resolve(dirPath)\n if (!existsSync(absDir)) {\n return []\n }\n\n const files = readdirSync(absDir).filter((f) => f.endsWith('.eval.ts'))\n const evals: EvalDefinition[] = []\n\n for (const f of files) {\n const defs = await loadEvalFile(`${absDir}/${f}`)\n evals.push(...defs)\n }\n\n const seen = new Set<string>()\n for (const e of evals) {\n if (seen.has(e.name)) {\n throw new EvalRunnerError({\n code: 'EVAL_DUPLICATE_NAME',\n message: `Duplicate eval name \"${e.name}\" found in ${dirPath} \u2014 names must be unique across the evals directory.`,\n expected: true,\n details: { name: e.name },\n })\n }\n seen.add(e.name)\n }\n\n return evals\n}\n\nexport async function loadEvalByName(dirPath: string, name: string): Promise<EvalDefinition | null> {\n const absDir = resolve(dirPath)\n if (!existsSync(absDir)) return null\n\n const files = readdirSync(absDir).filter((f) => f.endsWith('.eval.ts'))\n\n for (const f of files) {\n const defs = await loadEvalFile(`${absDir}/${f}`)\n const found = defs.find((d) => d.name === name)\n if (found) return found\n }\n\n return null\n}\n\nexport function filterEvals(evals: EvalDefinition[], filter?: EvalFilter): EvalDefinition[] {\n if (!filter) return evals\n\n return evals.filter((e) => {\n if (filter.names && filter.names.length > 0) {\n if (!filter.names.includes(e.name)) return false\n }\n if (filter.tags && filter.tags.length > 0) {\n if (!e.tags || !filter.tags.some((t) => e.tags!.includes(t))) return false\n }\n if (filter.type) {\n if (e.type !== filter.type) return false\n }\n return true\n })\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["BpClient", "require", "resolve", "data", "BpClient"]
7
7
  }