@botpress/evals 2.0.4 → 3.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client.js +4 -3
- package/dist/client.js.map +2 -2
- package/dist/graders/index.js +3 -2
- package/dist/graders/index.js.map +2 -2
- package/dist/graders/llm.d.ts.map +1 -1
- package/dist/graders/llm.js +3 -2
- package/dist/graders/llm.js.map +2 -2
- package/dist/graders/response.js.map +2 -2
- package/dist/loader.js +4 -3
- package/dist/loader.js.map +2 -2
- package/dist/runner.js +7 -5
- package/dist/runner.js.map +2 -2
- package/dist/spans/index.js +4 -3
- package/dist/spans/index.js.map +2 -2
- package/dist/spans/local-span-source.js +4 -3
- package/dist/spans/local-span-source.js.map +2 -2
- package/dist/spans/sse-collector.js +4 -3
- package/dist/spans/sse-collector.js.map +2 -2
- package/dist/stores/eval-definition-loader.js +4 -3
- package/dist/stores/eval-definition-loader.js.map +2 -2
- package/dist/stores/index.js +29 -8
- package/dist/stores/index.js.map +2 -2
- package/dist/stores/local-eval-store.js +4 -3
- package/dist/stores/local-eval-store.js.map +2 -2
- package/dist/stores/vortex-eval-store-entry.js +29 -8
- package/dist/stores/vortex-eval-store-entry.js.map +2 -2
- package/dist/stores/vortex-eval-store.d.ts +8 -7
- package/dist/stores/vortex-eval-store.d.ts.map +1 -1
- package/dist/stores/vortex-eval-store.js +25 -5
- package/dist/stores/vortex-eval-store.js.map +2 -2
- package/package.json +7 -6
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/stores/local-eval-store.ts", "../../src/loader.ts", "../../src/definition.ts", "../../../analytics/src/errors.ts", "../../src/errors.ts", "../../src/stores/eval-definition-loader.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * LocalEvalStore \u2014 local eval store backed by bun:sqlite + disk-loaded definitions.\n *\n * Implements the EvalStore interface for the local dev environment:\n * - Eval definitions loaded from the agent's evals/ directory\n * - Run results persisted in SQLite (.adk/evals/evals.db)\n * - Runner state tracked via in-memory activeRunId\n *\n * The CLI is the single writer and reader of the SQLite database \u2014 no\n * concurrent write issues since the CLI process owns the DB.\n */\n\nimport { Database, type Statement } from 'bun:sqlite'\nimport { existsSync, mkdirSync, readdirSync, readFileSync, renameSync } from 'fs'\nimport { join } from 'path'\nimport type { EvalDefinition } from '../definition'\nimport type { EvalFilter, EvalProgressEvent, EvalReport, EvalRunReport } from '../types'\nimport type { EvalStore, EvalSummary, EvalRunSummary, EvalReportHistoryEntry, EvalWatchOptions } from './eval-store'\nimport type { EvalDefinitionLoader } from './eval-definition-loader'\nimport { createDiskEvalLoader } from './eval-definition-loader'\nimport { filterEvals } from '../loader'\n\nconst errText = (err: unknown): string => (err instanceof Error ? err.message : String(err))\n\nconst SCHEMA_VERSION = '2'\n\nconst SCHEMA = `\nCREATE TABLE IF NOT EXISTS eval_runs (\n id TEXT PRIMARY KEY,\n timestamp TEXT NOT NULL,\n started_at INTEGER NOT NULL,\n passed INTEGER NOT NULL,\n failed INTEGER NOT NULL,\n total INTEGER NOT NULL,\n duration REAL NOT NULL,\n bot_duration REAL NOT NULL DEFAULT 0,\n eval_duration REAL NOT NULL DEFAULT 0,\n aborted INTEGER NOT NULL DEFAULT 0,\n filter_json TEXT,\n eval_names TEXT NOT NULL DEFAULT '[]'\n);\nCREATE INDEX IF NOT EXISTS idx_eval_runs_started ON eval_runs(started_at DESC);\n\nCREATE TABLE IF NOT EXISTS eval_reports (\n run_id TEXT NOT NULL REFERENCES eval_runs(id) ON DELETE CASCADE,\n seq INTEGER NOT NULL,\n name TEXT NOT NULL,\n started_at INTEGER NOT NULL,\n pass INTEGER NOT NULL,\n duration REAL NOT NULL,\n type TEXT,\n error TEXT,\n report_json TEXT NOT NULL,\n PRIMARY KEY (run_id, seq)\n);\nCREATE INDEX IF NOT EXISTS idx_eval_reports_name_time ON eval_reports(name, started_at DESC);\n\nCREATE TABLE IF NOT EXISTS schema_meta (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL\n);\n`\n\ninterface RunRow {\n id: string\n timestamp: string\n started_at: number\n passed: number\n failed: number\n total: number\n duration: number\n bot_duration: number\n eval_duration: number\n aborted: number\n filter_json: string | null\n eval_names: string\n}\n\ninterface ReportRow {\n run_id: string\n seq: number\n name: string\n started_at: number\n pass: number\n duration: number\n type: string | null\n error: string | null\n report_json: string\n}\n\nfunction aggregateTurnTimings(report: EvalRunReport): { botDuration: number; evalDuration: number } {\n let botDuration = 0\n let evalDuration = 0\n for (const e of report.evals) {\n for (const t of e.turns) {\n botDuration += t.botDuration\n evalDuration += t.evalDuration\n }\n }\n return { botDuration, evalDuration }\n}\n\nfunction toEvalSummary(e: EvalDefinition): EvalSummary {\n return {\n name: e.name,\n description: e.description,\n tags: e.tags || [],\n type: e.type || 'capability',\n turnCount: e.conversation.length,\n hasOutcome: !!e.outcome,\n }\n}\n\nexport interface LocalEvalStoreConfig {\n agentPath: string\n getActiveRunId?: () => string | null\n loadEvalDefinitions?: EvalDefinitionLoader\n}\n\nexport class LocalEvalStore implements EvalStore {\n private db: Database | null = null\n private dbPath: string\n private evalsDir: string\n private insertRunStmt: Statement | null = null\n private insertReportStmt: Statement | null = null\n private _getActiveRunId: () => string | null\n private _loadEvalDefinitions: EvalDefinitionLoader\n\n constructor(config: LocalEvalStoreConfig) {\n this.evalsDir = join(config.agentPath, '.adk', 'evals')\n this.dbPath = join(this.evalsDir, 'evals.db')\n this._getActiveRunId = config.getActiveRunId ?? (() => null)\n this._loadEvalDefinitions = config.loadEvalDefinitions ?? createDiskEvalLoader(join(config.agentPath, 'evals'))\n }\n\n // \u2500\u2500 Eval definitions (from disk) \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 async listEvals(filter?: EvalFilter): Promise<EvalSummary[]> {\n const allEvals = await this._loadEvalDefinitions()\n const evals = filter ? filterEvals(allEvals, filter) : allEvals\n return evals.map(toEvalSummary)\n }\n\n async getEval(name: string): Promise<EvalDefinition | null> {\n const allEvals = await this._loadEvalDefinitions()\n return allEvals.find((e) => e.name === name) ?? null\n }\n\n // \u2500\u2500 Run lifecycle \u2014 write \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 async createRun(_runType?: string, _metadata?: Record<string, unknown>): Promise<string> {\n return crypto.randomUUID().replace(/-/g, '').slice(0, 26)\n }\n\n async addRunResults(_runId: string, _evalReport: EvalReport): Promise<void> {\n // Local store writes atomically in completeRun \u2014 no incremental inserts.\n }\n\n async completeRun(_runId: string, report: EvalRunReport): Promise<void> {\n const db = this.getDb()\n if (!db) return\n\n db.run('BEGIN')\n try {\n this.insertRunReport(report)\n db.run('COMMIT')\n } catch (err) {\n db.run('ROLLBACK')\n console.error(`[local-eval-store] completeRun transaction failed (run ${report.id}): ${errText(err)}`)\n throw err\n }\n }\n\n // \u2500\u2500 Run results \u2014 read \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 async loadRunResult(runId: string): Promise<EvalRunReport | null> {\n const db = this.getDb()\n if (!db) return null\n\n const runRow = db.prepare<RunRow, [string]>('SELECT * FROM eval_runs WHERE id = ?').get(runId)\n if (!runRow) return null\n\n const reportRows = db\n .prepare<ReportRow, [string]>('SELECT * FROM eval_reports WHERE run_id = ? ORDER BY seq')\n .all(runRow.id)\n\n return this.assembleRun(runRow, reportRows)\n }\n\n async getLatestRun(): Promise<EvalRunReport | null> {\n const db = this.getDb()\n if (!db) return null\n\n const runRow = db.prepare<RunRow, []>('SELECT * FROM eval_runs ORDER BY started_at DESC LIMIT 1').get()\n if (!runRow) return null\n\n const reportRows = db\n .prepare<ReportRow, [string]>('SELECT * FROM eval_reports WHERE run_id = ? ORDER BY seq')\n .all(runRow.id)\n\n return this.assembleRun(runRow, reportRows)\n }\n\n async listRunSummaries(opts?: { limit?: number; since?: number }): Promise<EvalRunSummary[]> {\n const db = this.getDb()\n if (!db) return []\n\n const limit = opts?.limit ?? 50\n const sinceTs = opts?.since\n\n const rows: RunRow[] =\n sinceTs !== undefined\n ? db\n .prepare<RunRow, [number, number]>(\n 'SELECT * FROM eval_runs WHERE started_at >= ? ORDER BY started_at DESC LIMIT ?'\n )\n .all(sinceTs, limit)\n : db.prepare<RunRow, [number]>('SELECT * FROM eval_runs ORDER BY started_at DESC LIMIT ?').all(limit)\n\n return rows.map((r) => ({\n id: r.id,\n timestamp: r.timestamp,\n passed: r.passed,\n failed: r.failed,\n total: r.total,\n duration: r.duration,\n botDuration: r.bot_duration,\n evalDuration: r.eval_duration,\n filter: r.filter_json ? (JSON.parse(r.filter_json) as EvalFilter) : undefined,\n evalNames: JSON.parse(r.eval_names) as string[],\n aborted: r.aborted === 1,\n }))\n }\n\n async listEvalReportsByName(\n evalName: string,\n opts?: { limit?: number; since?: number }\n ): Promise<EvalReportHistoryEntry[]> {\n const db = this.getDb()\n if (!db) return []\n\n const limit = opts?.limit ?? 20\n const sinceTs = opts?.since\n\n type JoinedRow = ReportRow & {\n run_timestamp: string\n run_total: number\n run_filter_json: string | null\n }\n\n const baseSql = `\n SELECT er.*,\n r.timestamp AS run_timestamp,\n r.total AS run_total,\n r.filter_json AS run_filter_json\n FROM eval_reports er\n JOIN eval_runs r ON r.id = er.run_id\n WHERE er.name = ?\n `\n\n const rows: JoinedRow[] =\n sinceTs !== undefined\n ? db\n .prepare<JoinedRow, [string, number, number]>(\n `${baseSql} AND er.started_at >= ? ORDER BY er.started_at DESC LIMIT ?`\n )\n .all(evalName, sinceTs, limit)\n : db.prepare<JoinedRow, [string, number]>(`${baseSql} ORDER BY er.started_at DESC LIMIT ?`).all(evalName, limit)\n\n return rows.map((row) => ({\n runId: row.run_id,\n timestamp: row.run_timestamp,\n report: JSON.parse(row.report_json) as EvalReport,\n totalEvalsInRun: row.run_total,\n filter: row.run_filter_json ? (JSON.parse(row.run_filter_json) as EvalFilter) : undefined,\n }))\n }\n\n async listEvalReportsBulk(opts?: {\n perEval?: number\n since?: number\n }): Promise<Record<string, EvalReportHistoryEntry[]>> {\n const db = this.getDb()\n if (!db) return {}\n\n const perEval = opts?.perEval ?? 20\n const sinceTs = opts?.since\n\n type JoinedRow = ReportRow & {\n run_timestamp: string\n run_total: number\n run_filter_json: string | null\n }\n\n const sinceClause = sinceTs !== undefined ? 'WHERE er.started_at >= ?' : ''\n const sql = `\n WITH ranked AS (\n SELECT er.*, ROW_NUMBER() OVER (PARTITION BY name ORDER BY started_at DESC) AS rn\n FROM eval_reports er\n ${sinceClause}\n )\n SELECT ranked.run_id, ranked.name, ranked.started_at, ranked.pass,\n ranked.duration, ranked.type, ranked.error, ranked.report_json,\n r.timestamp AS run_timestamp,\n r.total AS run_total,\n r.filter_json AS run_filter_json\n FROM ranked\n JOIN eval_runs r ON r.id = ranked.run_id\n WHERE ranked.rn <= ?\n ORDER BY ranked.name, ranked.started_at DESC\n `\n\n const rows: JoinedRow[] =\n sinceTs !== undefined\n ? db.prepare<JoinedRow, [number, number]>(sql).all(sinceTs, perEval)\n : db.prepare<JoinedRow, [number]>(sql).all(perEval)\n\n const out: Record<string, EvalReportHistoryEntry[]> = {}\n for (const row of rows) {\n const entry: EvalReportHistoryEntry = {\n runId: row.run_id,\n timestamp: row.run_timestamp,\n report: JSON.parse(row.report_json) as EvalReport,\n totalEvalsInRun: row.run_total,\n filter: row.run_filter_json ? (JSON.parse(row.run_filter_json) as EvalFilter) : undefined,\n }\n const arr = out[row.name]\n if (arr) arr.push(entry)\n else out[row.name] = [entry]\n }\n return out\n }\n\n // \u2500\u2500 Live run tracking \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 async *watchRun(_signal?: AbortSignal, _options?: EvalWatchOptions): AsyncIterable<EvalProgressEvent> {\n // Local runs push progress events directly via SSE (handleRunEvals owns\n // the stream). This method satisfies the interface but is not the\n // primary consumption path for local runs.\n }\n\n // \u2500\u2500 Runner state \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\u2500\n\n async getRunnerState(): Promise<{ running: boolean; runId: string | null }> {\n const runId = this._getActiveRunId()\n return { running: runId !== null, runId }\n }\n\n // \u2500\u2500 Extra (not on EvalStore interface) \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 async listRunResults(limit = 50, sinceTs?: number): Promise<EvalRunReport[]> {\n const db = this.getDb()\n if (!db) return []\n\n let runRows: RunRow[]\n if (sinceTs !== undefined) {\n runRows = db\n .prepare<RunRow, [number, number]>(\n 'SELECT * FROM eval_runs WHERE started_at >= ? ORDER BY started_at DESC LIMIT ?'\n )\n .all(sinceTs, limit)\n } else {\n runRows = db.prepare<RunRow, [number]>('SELECT * FROM eval_runs ORDER BY started_at DESC LIMIT ?').all(limit)\n }\n\n if (runRows.length === 0) return []\n\n const ids = runRows.map((r) => r.id)\n const placeholders = ids.map(() => '?').join(',')\n const reportRows = db\n .prepare<ReportRow, string[]>(`SELECT * FROM eval_reports WHERE run_id IN (${placeholders}) ORDER BY seq`)\n .all(...ids)\n\n const byRun = new Map<string, ReportRow[]>()\n for (const row of reportRows) {\n const arr = byRun.get(row.run_id)\n if (arr) arr.push(row)\n else byRun.set(row.run_id, [row])\n }\n\n return runRows.map((row) => this.assembleRun(row, byRun.get(row.id) ?? []))\n }\n\n // \u2500\u2500 Lifecycle \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\u2500\u2500\u2500\u2500\n\n close(): void {\n try {\n this.db?.close()\n } catch {\n // silent\n }\n this.db = null\n this.insertRunStmt = null\n this.insertReportStmt = null\n }\n\n getDbPath(): string {\n return this.dbPath\n }\n\n // \u2500\u2500 SQLite internals \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 private getDb(): Database | null {\n if (this.db) return this.db\n\n mkdirSync(this.evalsDir, { recursive: true })\n\n try {\n this.db = new Database(this.dbPath)\n this.db.run('PRAGMA journal_mode=WAL')\n this.db.run('PRAGMA synchronous=NORMAL')\n this.db.run('PRAGMA busy_timeout=5000')\n this.db.run('PRAGMA foreign_keys=ON')\n this.db.run(SCHEMA)\n\n this.setMeta('schema_version', SCHEMA_VERSION)\n\n this.insertRunStmt = this.db.prepare(`\n INSERT OR REPLACE INTO eval_runs (\n id, timestamp, started_at, passed, failed, total, duration,\n bot_duration, eval_duration, aborted, filter_json, eval_names\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `)\n\n this.insertReportStmt = this.db.prepare(`\n INSERT OR REPLACE INTO eval_reports (\n run_id, seq, name, started_at, pass, duration, type, error, report_json\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)\n `)\n\n this.importLegacyJsonRunsIfNeeded()\n\n return this.db\n } catch (err) {\n console.warn('[local-eval-store] Failed to initialize database:', err)\n try {\n this.db?.close()\n } catch {\n // best effort\n }\n try {\n if (existsSync(this.dbPath)) {\n renameSync(this.dbPath, `${this.dbPath}.corrupt-${Date.now()}`)\n }\n } catch {\n // best effort\n }\n this.db = null\n this.insertRunStmt = null\n this.insertReportStmt = null\n return null\n }\n }\n\n private getMeta(key: string): string | null {\n const db = this.db\n if (!db) return null\n const row = db.prepare<{ value: string }, [string]>('SELECT value FROM schema_meta WHERE key = ?').get(key)\n return row?.value ?? null\n }\n\n private setMeta(key: string, value: string): void {\n const db = this.db\n if (!db) return\n db.prepare('INSERT OR REPLACE INTO schema_meta (key, value) VALUES (?, ?)').run(key, value)\n }\n\n private importLegacyJsonRunsIfNeeded(): void {\n const db = this.db\n if (!db) return\n if (this.getMeta('imported_legacy') === '1') return\n\n const legacyDir = join(this.evalsDir, 'runs')\n if (!existsSync(legacyDir)) {\n this.setMeta('imported_legacy', '1')\n return\n }\n\n let files: string[] = []\n try {\n files = readdirSync(legacyDir).filter((f) => f.endsWith('.json'))\n } catch (err) {\n console.warn('[local-eval-store] Could not read legacy runs dir:', err)\n return\n }\n\n if (files.length === 0) {\n this.setMeta('imported_legacy', '1')\n return\n }\n\n let imported = 0\n let skipped = 0\n db.run('BEGIN')\n try {\n for (const file of files) {\n db.run('SAVEPOINT import_file')\n try {\n const raw = readFileSync(join(legacyDir, file), 'utf-8')\n const report = JSON.parse(raw) as EvalRunReport\n this.insertRunReport(report)\n db.run('RELEASE import_file')\n imported++\n } catch (err) {\n db.run('ROLLBACK TO import_file')\n db.run('RELEASE import_file')\n skipped++\n console.warn(`[local-eval-store] Skipping unreadable legacy run ${file}:`, err)\n }\n }\n this.setMeta('imported_legacy', '1')\n db.run('COMMIT')\n } catch (err) {\n db.run('ROLLBACK')\n console.warn('[local-eval-store] Legacy import failed, will retry on next start:', err)\n return\n }\n\n try {\n renameSync(legacyDir, join(this.evalsDir, 'runs.json-migrated'))\n } catch (err) {\n console.warn('[local-eval-store] Could not rename legacy runs dir:', err)\n }\n\n console.log(\n `[local-eval-store] Imported ${imported} legacy eval run${imported === 1 ? '' : 's'}` +\n (skipped > 0 ? ` (${skipped} skipped)` : '')\n )\n }\n\n private insertRunReport(report: EvalRunReport): void {\n if (!this.insertRunStmt || !this.insertReportStmt) return\n\n const startedAt = Date.parse(report.timestamp)\n const { botDuration, evalDuration } = aggregateTurnTimings(report)\n\n this.insertRunStmt.run(\n report.id,\n report.timestamp,\n Number.isNaN(startedAt) ? 0 : startedAt,\n report.passed,\n report.failed,\n report.total,\n report.duration,\n botDuration,\n evalDuration,\n report.aborted ? 1 : 0,\n report.filter ? JSON.stringify(report.filter) : null,\n JSON.stringify(report.evals.map((e) => e.name))\n )\n\n for (let i = 0; i < report.evals.length; i++) {\n const evalReport = report.evals[i]!\n this.insertReportStmt.run(\n report.id,\n i,\n evalReport.name,\n Number.isNaN(startedAt) ? 0 : startedAt,\n evalReport.pass ? 1 : 0,\n evalReport.duration,\n evalReport.type ?? null,\n evalReport.error ?? null,\n JSON.stringify(evalReport)\n )\n }\n }\n\n private assembleRun(runRow: RunRow, reportRows: ReportRow[]): EvalRunReport {\n const evals = reportRows.map((r) => JSON.parse(r.report_json) as EvalReport)\n const report: EvalRunReport = {\n id: runRow.id,\n timestamp: runRow.timestamp,\n evals,\n passed: runRow.passed,\n failed: runRow.failed,\n total: runRow.total,\n duration: runRow.duration,\n }\n if (runRow.filter_json) {\n report.filter = JSON.parse(runRow.filter_json) as EvalFilter\n }\n if (runRow.aborted === 1) {\n report.aborted = true\n }\n return report\n }\n}\n\n// \u2500\u2500 Module-level singleton per agentPath \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\nconst stores = new Map<string, LocalEvalStore>()\n\nexport function getLocalEvalStore(agentPath: string, getActiveRunId?: () => string | null): LocalEvalStore {\n let store = stores.get(agentPath)\n if (!store) {\n store = new LocalEvalStore({ agentPath, getActiveRunId })\n stores.set(agentPath, store)\n }\n return store\n}\n\nexport function closeLocalEvalStores(agentPath?: string): void {\n if (agentPath) {\n stores.get(agentPath)?.close()\n stores.delete(agentPath)\n return\n }\n for (const store of stores.values()) store.close()\n stores.clear()\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", "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?: { payload: Record<string, unknown> }\n expectSilence?: boolean\n assert?: TurnAssertions\n /**\n * Run this turn in a NEW conversation under the same user. The prior\n * transcript is absent, so recall here can only come from user-scoped\n * persistence, not context. Ignored on the first turn.\n */\n newConversation?: boolean\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 /** @deprecated No-op: the LLM judge is boolean (zai.check); there is no score threshold. */\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 /** @deprecated No-op: the LLM judge is boolean (zai.check); there is no score threshold. */\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 * 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", "import type { EvalDefinition } from '../definition'\nimport { loadEvalsFromDir } from '../loader'\n\nexport type EvalDefinitionLoader = () => Promise<EvalDefinition[]>\n\nexport function createDiskEvalLoader(evalsDir: string): EvalDefinitionLoader {\n return () => loadEvalsFromDir(evalsDir)\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["/**\n * LocalEvalStore \u2014 local eval store backed by bun:sqlite + disk-loaded definitions.\n *\n * Implements the EvalStore interface for the local dev environment:\n * - Eval definitions loaded from the agent's evals/ directory\n * - Run results persisted in SQLite (.adk/evals/evals.db)\n * - Runner state tracked via in-memory activeRunId\n *\n * The CLI is the single writer and reader of the SQLite database \u2014 no\n * concurrent write issues since the CLI process owns the DB.\n */\n\nimport { Database, type Statement } from 'bun:sqlite'\nimport { existsSync, mkdirSync, readdirSync, readFileSync, renameSync } from 'fs'\nimport { join } from 'path'\nimport type { EvalDefinition } from '../definition'\nimport type { EvalFilter, EvalProgressEvent, EvalReport, EvalRunReport } from '../types'\nimport type { EvalStore, EvalSummary, EvalRunSummary, EvalReportHistoryEntry, EvalWatchOptions } from './eval-store'\nimport type { EvalDefinitionLoader } from './eval-definition-loader'\nimport { createDiskEvalLoader } from './eval-definition-loader'\nimport { filterEvals } from '../loader'\n\nconst errText = (err: unknown): string => (err instanceof Error ? err.message : String(err))\n\nconst SCHEMA_VERSION = '2'\n\nconst SCHEMA = `\nCREATE TABLE IF NOT EXISTS eval_runs (\n id TEXT PRIMARY KEY,\n timestamp TEXT NOT NULL,\n started_at INTEGER NOT NULL,\n passed INTEGER NOT NULL,\n failed INTEGER NOT NULL,\n total INTEGER NOT NULL,\n duration REAL NOT NULL,\n bot_duration REAL NOT NULL DEFAULT 0,\n eval_duration REAL NOT NULL DEFAULT 0,\n aborted INTEGER NOT NULL DEFAULT 0,\n filter_json TEXT,\n eval_names TEXT NOT NULL DEFAULT '[]'\n);\nCREATE INDEX IF NOT EXISTS idx_eval_runs_started ON eval_runs(started_at DESC);\n\nCREATE TABLE IF NOT EXISTS eval_reports (\n run_id TEXT NOT NULL REFERENCES eval_runs(id) ON DELETE CASCADE,\n seq INTEGER NOT NULL,\n name TEXT NOT NULL,\n started_at INTEGER NOT NULL,\n pass INTEGER NOT NULL,\n duration REAL NOT NULL,\n type TEXT,\n error TEXT,\n report_json TEXT NOT NULL,\n PRIMARY KEY (run_id, seq)\n);\nCREATE INDEX IF NOT EXISTS idx_eval_reports_name_time ON eval_reports(name, started_at DESC);\n\nCREATE TABLE IF NOT EXISTS schema_meta (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL\n);\n`\n\ninterface RunRow {\n id: string\n timestamp: string\n started_at: number\n passed: number\n failed: number\n total: number\n duration: number\n bot_duration: number\n eval_duration: number\n aborted: number\n filter_json: string | null\n eval_names: string\n}\n\ninterface ReportRow {\n run_id: string\n seq: number\n name: string\n started_at: number\n pass: number\n duration: number\n type: string | null\n error: string | null\n report_json: string\n}\n\nfunction aggregateTurnTimings(report: EvalRunReport): { botDuration: number; evalDuration: number } {\n let botDuration = 0\n let evalDuration = 0\n for (const e of report.evals) {\n for (const t of e.turns) {\n botDuration += t.botDuration\n evalDuration += t.evalDuration\n }\n }\n return { botDuration, evalDuration }\n}\n\nfunction toEvalSummary(e: EvalDefinition): EvalSummary {\n return {\n name: e.name,\n description: e.description,\n tags: e.tags || [],\n type: e.type || 'capability',\n turnCount: e.conversation.length,\n hasOutcome: !!e.outcome,\n }\n}\n\nexport interface LocalEvalStoreConfig {\n agentPath: string\n getActiveRunId?: () => string | null\n loadEvalDefinitions?: EvalDefinitionLoader\n}\n\nexport class LocalEvalStore implements EvalStore {\n private db: Database | null = null\n private dbPath: string\n private evalsDir: string\n private insertRunStmt: Statement | null = null\n private insertReportStmt: Statement | null = null\n private _getActiveRunId: () => string | null\n private _loadEvalDefinitions: EvalDefinitionLoader\n\n constructor(config: LocalEvalStoreConfig) {\n this.evalsDir = join(config.agentPath, '.adk', 'evals')\n this.dbPath = join(this.evalsDir, 'evals.db')\n this._getActiveRunId = config.getActiveRunId ?? (() => null)\n this._loadEvalDefinitions = config.loadEvalDefinitions ?? createDiskEvalLoader(join(config.agentPath, 'evals'))\n }\n\n // \u2500\u2500 Eval definitions (from disk) \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 async listEvals(filter?: EvalFilter): Promise<EvalSummary[]> {\n const allEvals = await this._loadEvalDefinitions()\n const evals = filter ? filterEvals(allEvals, filter) : allEvals\n return evals.map(toEvalSummary)\n }\n\n async getEval(name: string): Promise<EvalDefinition | null> {\n const allEvals = await this._loadEvalDefinitions()\n return allEvals.find((e) => e.name === name) ?? null\n }\n\n // \u2500\u2500 Run lifecycle \u2014 write \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 async createRun(_runType?: string, _metadata?: Record<string, unknown>): Promise<string> {\n return crypto.randomUUID().replace(/-/g, '').slice(0, 26)\n }\n\n async addRunResults(_runId: string, _evalReport: EvalReport): Promise<void> {\n // Local store writes atomically in completeRun \u2014 no incremental inserts.\n }\n\n async completeRun(_runId: string, report: EvalRunReport): Promise<void> {\n const db = this.getDb()\n if (!db) return\n\n db.run('BEGIN')\n try {\n this.insertRunReport(report)\n db.run('COMMIT')\n } catch (err) {\n db.run('ROLLBACK')\n console.error(`[local-eval-store] completeRun transaction failed (run ${report.id}): ${errText(err)}`)\n throw err\n }\n }\n\n // \u2500\u2500 Run results \u2014 read \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 async loadRunResult(runId: string): Promise<EvalRunReport | null> {\n const db = this.getDb()\n if (!db) return null\n\n const runRow = db.prepare<RunRow, [string]>('SELECT * FROM eval_runs WHERE id = ?').get(runId)\n if (!runRow) return null\n\n const reportRows = db\n .prepare<ReportRow, [string]>('SELECT * FROM eval_reports WHERE run_id = ? ORDER BY seq')\n .all(runRow.id)\n\n return this.assembleRun(runRow, reportRows)\n }\n\n async getLatestRun(): Promise<EvalRunReport | null> {\n const db = this.getDb()\n if (!db) return null\n\n const runRow = db.prepare<RunRow, []>('SELECT * FROM eval_runs ORDER BY started_at DESC LIMIT 1').get()\n if (!runRow) return null\n\n const reportRows = db\n .prepare<ReportRow, [string]>('SELECT * FROM eval_reports WHERE run_id = ? ORDER BY seq')\n .all(runRow.id)\n\n return this.assembleRun(runRow, reportRows)\n }\n\n async listRunSummaries(opts?: { limit?: number; since?: number }): Promise<EvalRunSummary[]> {\n const db = this.getDb()\n if (!db) return []\n\n const limit = opts?.limit ?? 50\n const sinceTs = opts?.since\n\n const rows: RunRow[] =\n sinceTs !== undefined\n ? db\n .prepare<RunRow, [number, number]>(\n 'SELECT * FROM eval_runs WHERE started_at >= ? ORDER BY started_at DESC LIMIT ?'\n )\n .all(sinceTs, limit)\n : db.prepare<RunRow, [number]>('SELECT * FROM eval_runs ORDER BY started_at DESC LIMIT ?').all(limit)\n\n return rows.map((r) => ({\n id: r.id,\n timestamp: r.timestamp,\n passed: r.passed,\n failed: r.failed,\n total: r.total,\n duration: r.duration,\n botDuration: r.bot_duration,\n evalDuration: r.eval_duration,\n filter: r.filter_json ? (JSON.parse(r.filter_json) as EvalFilter) : undefined,\n evalNames: JSON.parse(r.eval_names) as string[],\n aborted: r.aborted === 1,\n }))\n }\n\n async listEvalReportsByName(\n evalName: string,\n opts?: { limit?: number; since?: number }\n ): Promise<EvalReportHistoryEntry[]> {\n const db = this.getDb()\n if (!db) return []\n\n const limit = opts?.limit ?? 20\n const sinceTs = opts?.since\n\n type JoinedRow = ReportRow & {\n run_timestamp: string\n run_total: number\n run_filter_json: string | null\n }\n\n const baseSql = `\n SELECT er.*,\n r.timestamp AS run_timestamp,\n r.total AS run_total,\n r.filter_json AS run_filter_json\n FROM eval_reports er\n JOIN eval_runs r ON r.id = er.run_id\n WHERE er.name = ?\n `\n\n const rows: JoinedRow[] =\n sinceTs !== undefined\n ? db\n .prepare<JoinedRow, [string, number, number]>(\n `${baseSql} AND er.started_at >= ? ORDER BY er.started_at DESC LIMIT ?`\n )\n .all(evalName, sinceTs, limit)\n : db.prepare<JoinedRow, [string, number]>(`${baseSql} ORDER BY er.started_at DESC LIMIT ?`).all(evalName, limit)\n\n return rows.map((row) => ({\n runId: row.run_id,\n timestamp: row.run_timestamp,\n report: JSON.parse(row.report_json) as EvalReport,\n totalEvalsInRun: row.run_total,\n filter: row.run_filter_json ? (JSON.parse(row.run_filter_json) as EvalFilter) : undefined,\n }))\n }\n\n async listEvalReportsBulk(opts?: {\n perEval?: number\n since?: number\n }): Promise<Record<string, EvalReportHistoryEntry[]>> {\n const db = this.getDb()\n if (!db) return {}\n\n const perEval = opts?.perEval ?? 20\n const sinceTs = opts?.since\n\n type JoinedRow = ReportRow & {\n run_timestamp: string\n run_total: number\n run_filter_json: string | null\n }\n\n const sinceClause = sinceTs !== undefined ? 'WHERE er.started_at >= ?' : ''\n const sql = `\n WITH ranked AS (\n SELECT er.*, ROW_NUMBER() OVER (PARTITION BY name ORDER BY started_at DESC) AS rn\n FROM eval_reports er\n ${sinceClause}\n )\n SELECT ranked.run_id, ranked.name, ranked.started_at, ranked.pass,\n ranked.duration, ranked.type, ranked.error, ranked.report_json,\n r.timestamp AS run_timestamp,\n r.total AS run_total,\n r.filter_json AS run_filter_json\n FROM ranked\n JOIN eval_runs r ON r.id = ranked.run_id\n WHERE ranked.rn <= ?\n ORDER BY ranked.name, ranked.started_at DESC\n `\n\n const rows: JoinedRow[] =\n sinceTs !== undefined\n ? db.prepare<JoinedRow, [number, number]>(sql).all(sinceTs, perEval)\n : db.prepare<JoinedRow, [number]>(sql).all(perEval)\n\n const out: Record<string, EvalReportHistoryEntry[]> = {}\n for (const row of rows) {\n const entry: EvalReportHistoryEntry = {\n runId: row.run_id,\n timestamp: row.run_timestamp,\n report: JSON.parse(row.report_json) as EvalReport,\n totalEvalsInRun: row.run_total,\n filter: row.run_filter_json ? (JSON.parse(row.run_filter_json) as EvalFilter) : undefined,\n }\n const arr = out[row.name]\n if (arr) arr.push(entry)\n else out[row.name] = [entry]\n }\n return out\n }\n\n // \u2500\u2500 Live run tracking \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 async *watchRun(_signal?: AbortSignal, _options?: EvalWatchOptions): AsyncIterable<EvalProgressEvent> {\n // Local runs push progress events directly via SSE (handleRunEvals owns\n // the stream). This method satisfies the interface but is not the\n // primary consumption path for local runs.\n }\n\n // \u2500\u2500 Runner state \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\u2500\n\n async getRunnerState(): Promise<{ running: boolean; runId: string | null }> {\n const runId = this._getActiveRunId()\n return { running: runId !== null, runId }\n }\n\n // \u2500\u2500 Extra (not on EvalStore interface) \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 async listRunResults(limit = 50, sinceTs?: number): Promise<EvalRunReport[]> {\n const db = this.getDb()\n if (!db) return []\n\n let runRows: RunRow[]\n if (sinceTs !== undefined) {\n runRows = db\n .prepare<RunRow, [number, number]>(\n 'SELECT * FROM eval_runs WHERE started_at >= ? ORDER BY started_at DESC LIMIT ?'\n )\n .all(sinceTs, limit)\n } else {\n runRows = db.prepare<RunRow, [number]>('SELECT * FROM eval_runs ORDER BY started_at DESC LIMIT ?').all(limit)\n }\n\n if (runRows.length === 0) return []\n\n const ids = runRows.map((r) => r.id)\n const placeholders = ids.map(() => '?').join(',')\n const reportRows = db\n .prepare<ReportRow, string[]>(`SELECT * FROM eval_reports WHERE run_id IN (${placeholders}) ORDER BY seq`)\n .all(...ids)\n\n const byRun = new Map<string, ReportRow[]>()\n for (const row of reportRows) {\n const arr = byRun.get(row.run_id)\n if (arr) arr.push(row)\n else byRun.set(row.run_id, [row])\n }\n\n return runRows.map((row) => this.assembleRun(row, byRun.get(row.id) ?? []))\n }\n\n // \u2500\u2500 Lifecycle \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\u2500\u2500\u2500\u2500\n\n close(): void {\n try {\n this.db?.close()\n } catch {\n // silent\n }\n this.db = null\n this.insertRunStmt = null\n this.insertReportStmt = null\n }\n\n getDbPath(): string {\n return this.dbPath\n }\n\n // \u2500\u2500 SQLite internals \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 private getDb(): Database | null {\n if (this.db) return this.db\n\n mkdirSync(this.evalsDir, { recursive: true })\n\n try {\n this.db = new Database(this.dbPath)\n this.db.run('PRAGMA journal_mode=WAL')\n this.db.run('PRAGMA synchronous=NORMAL')\n this.db.run('PRAGMA busy_timeout=5000')\n this.db.run('PRAGMA foreign_keys=ON')\n this.db.run(SCHEMA)\n\n this.setMeta('schema_version', SCHEMA_VERSION)\n\n this.insertRunStmt = this.db.prepare(`\n INSERT OR REPLACE INTO eval_runs (\n id, timestamp, started_at, passed, failed, total, duration,\n bot_duration, eval_duration, aborted, filter_json, eval_names\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `)\n\n this.insertReportStmt = this.db.prepare(`\n INSERT OR REPLACE INTO eval_reports (\n run_id, seq, name, started_at, pass, duration, type, error, report_json\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)\n `)\n\n this.importLegacyJsonRunsIfNeeded()\n\n return this.db\n } catch (err) {\n console.warn('[local-eval-store] Failed to initialize database:', err)\n try {\n this.db?.close()\n } catch {\n // best effort\n }\n try {\n if (existsSync(this.dbPath)) {\n renameSync(this.dbPath, `${this.dbPath}.corrupt-${Date.now()}`)\n }\n } catch {\n // best effort\n }\n this.db = null\n this.insertRunStmt = null\n this.insertReportStmt = null\n return null\n }\n }\n\n private getMeta(key: string): string | null {\n const db = this.db\n if (!db) return null\n const row = db.prepare<{ value: string }, [string]>('SELECT value FROM schema_meta WHERE key = ?').get(key)\n return row?.value ?? null\n }\n\n private setMeta(key: string, value: string): void {\n const db = this.db\n if (!db) return\n db.prepare('INSERT OR REPLACE INTO schema_meta (key, value) VALUES (?, ?)').run(key, value)\n }\n\n private importLegacyJsonRunsIfNeeded(): void {\n const db = this.db\n if (!db) return\n if (this.getMeta('imported_legacy') === '1') return\n\n const legacyDir = join(this.evalsDir, 'runs')\n if (!existsSync(legacyDir)) {\n this.setMeta('imported_legacy', '1')\n return\n }\n\n let files: string[] = []\n try {\n files = readdirSync(legacyDir).filter((f) => f.endsWith('.json'))\n } catch (err) {\n console.warn('[local-eval-store] Could not read legacy runs dir:', err)\n return\n }\n\n if (files.length === 0) {\n this.setMeta('imported_legacy', '1')\n return\n }\n\n let imported = 0\n let skipped = 0\n db.run('BEGIN')\n try {\n for (const file of files) {\n db.run('SAVEPOINT import_file')\n try {\n const raw = readFileSync(join(legacyDir, file), 'utf-8')\n const report = JSON.parse(raw) as EvalRunReport\n this.insertRunReport(report)\n db.run('RELEASE import_file')\n imported++\n } catch (err) {\n db.run('ROLLBACK TO import_file')\n db.run('RELEASE import_file')\n skipped++\n console.warn(`[local-eval-store] Skipping unreadable legacy run ${file}:`, err)\n }\n }\n this.setMeta('imported_legacy', '1')\n db.run('COMMIT')\n } catch (err) {\n db.run('ROLLBACK')\n console.warn('[local-eval-store] Legacy import failed, will retry on next start:', err)\n return\n }\n\n try {\n renameSync(legacyDir, join(this.evalsDir, 'runs.json-migrated'))\n } catch (err) {\n console.warn('[local-eval-store] Could not rename legacy runs dir:', err)\n }\n\n console.log(\n `[local-eval-store] Imported ${imported} legacy eval run${imported === 1 ? '' : 's'}` +\n (skipped > 0 ? ` (${skipped} skipped)` : '')\n )\n }\n\n private insertRunReport(report: EvalRunReport): void {\n if (!this.insertRunStmt || !this.insertReportStmt) return\n\n const startedAt = Date.parse(report.timestamp)\n const { botDuration, evalDuration } = aggregateTurnTimings(report)\n\n this.insertRunStmt.run(\n report.id,\n report.timestamp,\n Number.isNaN(startedAt) ? 0 : startedAt,\n report.passed,\n report.failed,\n report.total,\n report.duration,\n botDuration,\n evalDuration,\n report.aborted ? 1 : 0,\n report.filter ? JSON.stringify(report.filter) : null,\n JSON.stringify(report.evals.map((e) => e.name))\n )\n\n for (let i = 0; i < report.evals.length; i++) {\n const evalReport = report.evals[i]!\n this.insertReportStmt.run(\n report.id,\n i,\n evalReport.name,\n Number.isNaN(startedAt) ? 0 : startedAt,\n evalReport.pass ? 1 : 0,\n evalReport.duration,\n evalReport.type ?? null,\n evalReport.error ?? null,\n JSON.stringify(evalReport)\n )\n }\n }\n\n private assembleRun(runRow: RunRow, reportRows: ReportRow[]): EvalRunReport {\n const evals = reportRows.map((r) => JSON.parse(r.report_json) as EvalReport)\n const report: EvalRunReport = {\n id: runRow.id,\n timestamp: runRow.timestamp,\n evals,\n passed: runRow.passed,\n failed: runRow.failed,\n total: runRow.total,\n duration: runRow.duration,\n }\n if (runRow.filter_json) {\n report.filter = JSON.parse(runRow.filter_json) as EvalFilter\n }\n if (runRow.aborted === 1) {\n report.aborted = true\n }\n return report\n }\n}\n\n// \u2500\u2500 Module-level singleton per agentPath \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\nconst stores = new Map<string, LocalEvalStore>()\n\nexport function getLocalEvalStore(agentPath: string, getActiveRunId?: () => string | null): LocalEvalStore {\n let store = stores.get(agentPath)\n if (!store) {\n store = new LocalEvalStore({ agentPath, getActiveRunId })\n stores.set(agentPath, store)\n }\n return store\n}\n\nexport function closeLocalEvalStores(agentPath?: string): void {\n if (agentPath) {\n stores.get(agentPath)?.close()\n stores.delete(agentPath)\n return\n }\n for (const store of stores.values()) store.close()\n stores.clear()\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", "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?: { payload: Record<string, unknown> }\n expectSilence?: boolean\n assert?: TurnAssertions\n /**\n * Run this turn in a NEW conversation under the same user. The prior\n * transcript is absent, so recall here can only come from user-scoped\n * persistence, not context. Ignored on the first turn.\n */\n newConversation?: boolean\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 /** @deprecated No-op: the LLM judge is boolean (zai.check); there is no score threshold. */\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 /** @deprecated No-op: the LLM judge is boolean (zai.check); there is no score threshold. */\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 * 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 * `expected` defaults to **true**: the overwhelming majority of thrown errors\n * are user/environment conditions, and expected errors are reported as plain\n * `error.expected` analytics events rather than PostHog `$exception`s. Genuine\n * bugs must opt out explicitly with `expected: false` so they reach Error\n * Tracking. There is a single base class \u2014 everything thrown is an `AdkError`\n * or a subclass.\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) \u2014 reported as `error.expected` events.\n * False for internal bugs \u2014 reported as PostHog `$exception`s. Defaults to\n * **true**; set `expected: false` explicitly to flag a genuine bug.\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 ?? true\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\n/**\n * True for an `AdkError` (or subclass) flagged `expected` \u2014 a user/environment\n * condition that should be reported as an `error.expected` analytics event\n * rather than a PostHog `$exception`. Used by the telemetry capture funnel to\n * route errors. Non-`AdkError` throws (and `expected: false` bugs) are not\n * expected and keep flowing to Error Tracking.\n */\nexport function isExpectedError(error: unknown): error is AdkError {\n return isAdkError(error) && error.expected\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", "import type { EvalDefinition } from '../definition'\nimport { loadEvalsFromDir } from '../loader'\n\nexport type EvalDefinitionLoader = () => Promise<EvalDefinition[]>\n\nexport function createDiskEvalLoader(evalsDir: string): EvalDefinitionLoader {\n return () => loadEvalsFromDir(evalsDir)\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["existsSync", "readdirSync", "existsSync", "readdirSync"]
|
|
7
7
|
}
|
|
@@ -309,7 +309,9 @@ var VortexEvalStore = class {
|
|
|
309
309
|
const res = await this.fetch(`/v1/evals/runs/${runId}/complete`, {
|
|
310
310
|
method: "POST",
|
|
311
311
|
headers: { "Content-Type": "application/json" },
|
|
312
|
-
body: JSON.stringify({
|
|
312
|
+
body: JSON.stringify({
|
|
313
|
+
...opts.failed !== void 0 ? { failed: opts.failed } : {}
|
|
314
|
+
})
|
|
313
315
|
});
|
|
314
316
|
if (!res.ok) {
|
|
315
317
|
const text = await res.text().catch(() => "");
|
|
@@ -419,7 +421,12 @@ var VortexEvalStore = class {
|
|
|
419
421
|
const totalTurns = meta?.totalTurns ?? evalReport.turns.length;
|
|
420
422
|
if (!startedEvals.has(entry.evalName)) {
|
|
421
423
|
startedEvals.add(entry.evalName);
|
|
422
|
-
yield {
|
|
424
|
+
yield {
|
|
425
|
+
type: "eval_start",
|
|
426
|
+
evalName: entry.evalName,
|
|
427
|
+
index: i,
|
|
428
|
+
totalTurns
|
|
429
|
+
};
|
|
423
430
|
}
|
|
424
431
|
for (const turn of evalReport.turns) {
|
|
425
432
|
const turnKey = `${entry.evalName}::${turn.turnIndex}`;
|
|
@@ -436,7 +443,12 @@ var VortexEvalStore = class {
|
|
|
436
443
|
}
|
|
437
444
|
if (entry.passed != null && !finalizedEvals.has(entry.evalName)) {
|
|
438
445
|
finalizedEvals.add(entry.evalName);
|
|
439
|
-
yield {
|
|
446
|
+
yield {
|
|
447
|
+
type: "eval_complete",
|
|
448
|
+
evalName: entry.evalName,
|
|
449
|
+
index: i,
|
|
450
|
+
report: evalReport
|
|
451
|
+
};
|
|
440
452
|
} else if (entry.passed == null && !terminal) {
|
|
441
453
|
const nextTurnIndex = evalReport.turns.length;
|
|
442
454
|
const startKey = `${entry.evalName}::${nextTurnIndex}`;
|
|
@@ -459,7 +471,12 @@ var VortexEvalStore = class {
|
|
|
459
471
|
const evalReport = finalReport.evals[i];
|
|
460
472
|
if (finalizedEvals.has(evalReport.name)) continue;
|
|
461
473
|
finalizedEvals.add(evalReport.name);
|
|
462
|
-
yield {
|
|
474
|
+
yield {
|
|
475
|
+
type: "eval_complete",
|
|
476
|
+
evalName: evalReport.name,
|
|
477
|
+
index: i,
|
|
478
|
+
report: evalReport
|
|
479
|
+
};
|
|
463
480
|
}
|
|
464
481
|
yield {
|
|
465
482
|
type: "suite_complete",
|
|
@@ -518,7 +535,10 @@ var VortexEvalStore = class {
|
|
|
518
535
|
return new Map(
|
|
519
536
|
defs.map((d) => [
|
|
520
537
|
d.name,
|
|
521
|
-
{
|
|
538
|
+
{
|
|
539
|
+
totalTurns: d.conversation.length,
|
|
540
|
+
userMessages: d.conversation.map((t) => t.user ?? "")
|
|
541
|
+
}
|
|
522
542
|
])
|
|
523
543
|
);
|
|
524
544
|
} catch {
|
|
@@ -600,8 +620,9 @@ var AdkError = class extends Error {
|
|
|
600
620
|
code;
|
|
601
621
|
/**
|
|
602
622
|
* True for user/environment conditions the developer can fix themselves
|
|
603
|
-
* (validation, auth, connectivity)
|
|
604
|
-
*
|
|
623
|
+
* (validation, auth, connectivity) — reported as `error.expected` events.
|
|
624
|
+
* False for internal bugs — reported as PostHog `$exception`s. Defaults to
|
|
625
|
+
* **true**; set `expected: false` explicitly to flag a genuine bug.
|
|
605
626
|
*/
|
|
606
627
|
expected;
|
|
607
628
|
/** Structured context. Sanitized before any telemetry leaves the machine. */
|
|
@@ -612,7 +633,7 @@ var AdkError = class extends Error {
|
|
|
612
633
|
super(opts.message, opts.cause !== void 0 ? { cause: opts.cause } : void 0);
|
|
613
634
|
this.name = this.constructor.name;
|
|
614
635
|
this.code = opts.code;
|
|
615
|
-
this.expected = opts.expected ??
|
|
636
|
+
this.expected = opts.expected ?? true;
|
|
616
637
|
if (opts.details !== void 0) {
|
|
617
638
|
this.details = opts.details;
|
|
618
639
|
}
|