@botpress/evals 1.19.0-beta.7 → 2.0.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client.d.ts +25 -11
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +143 -55
- package/dist/client.js.map +4 -4
- package/dist/definition.d.ts +9 -2
- package/dist/definition.d.ts.map +1 -1
- package/dist/definition.js.map +2 -2
- package/dist/errors.d.ts +15 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/graders/index.js +31 -74
- package/dist/graders/index.js.map +3 -3
- package/dist/graders/llm.d.ts +14 -12
- package/dist/graders/llm.d.ts.map +1 -1
- package/dist/graders/llm.js +46 -74
- package/dist/graders/llm.js.map +3 -3
- package/dist/graders/response.js +24 -64
- package/dist/graders/response.js.map +3 -3
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -0
- package/dist/index.js.map +3 -3
- package/dist/loader.d.ts.map +1 -1
- package/dist/loader.js +22 -8
- package/dist/loader.js.map +3 -3
- package/dist/manifest.d.ts +13 -0
- package/dist/manifest.d.ts.map +1 -0
- package/dist/runner.d.ts +7 -1
- package/dist/runner.d.ts.map +1 -1
- package/dist/runner.js +445 -246
- package/dist/runner.js.map +4 -4
- package/dist/spans/index.d.ts +5 -0
- package/dist/spans/index.d.ts.map +1 -0
- package/dist/spans/index.js +687 -0
- package/dist/spans/index.js.map +7 -0
- package/dist/spans/local-span-source.d.ts +19 -0
- package/dist/spans/local-span-source.d.ts.map +1 -0
- package/dist/spans/local-span-source.js +505 -0
- package/dist/spans/local-span-source.js.map +7 -0
- package/dist/spans/span-source.d.ts +40 -0
- package/dist/spans/span-source.d.ts.map +1 -0
- package/dist/spans/span-source.js +1 -0
- package/dist/{sse-collector.d.ts → spans/sse-collector.d.ts} +44 -5
- package/dist/spans/sse-collector.d.ts.map +1 -0
- package/dist/{sse-collector.js → spans/sse-collector.js} +109 -22
- package/dist/spans/sse-collector.js.map +7 -0
- package/dist/spans/trace.d.ts.map +1 -0
- package/dist/spans/trace.js.map +7 -0
- package/dist/spans/vortex-span-source.d.ts +42 -0
- package/dist/spans/vortex-span-source.d.ts.map +1 -0
- package/dist/spans/vortex-span-source.js +184 -0
- package/dist/spans/vortex-span-source.js.map +7 -0
- package/dist/stores/eval-definition-loader.d.ts +4 -0
- package/dist/stores/eval-definition-loader.d.ts.map +1 -0
- package/dist/stores/eval-definition-loader.js +104 -0
- package/dist/stores/eval-definition-loader.js.map +7 -0
- package/dist/stores/eval-store.d.ts +61 -0
- package/dist/stores/eval-store.d.ts.map +1 -0
- package/dist/stores/eval-store.js +1 -0
- package/dist/stores/eval-store.js.map +7 -0
- package/dist/stores/index.d.ts +8 -0
- package/dist/stores/index.d.ts.map +1 -0
- package/dist/stores/index.js +1118 -0
- package/dist/stores/index.js.map +7 -0
- package/dist/stores/local-eval-store.d.ts +66 -0
- package/dist/stores/local-eval-store.d.ts.map +1 -0
- package/dist/stores/local-eval-store.js +557 -0
- package/dist/stores/local-eval-store.js.map +7 -0
- package/dist/stores/vortex-eval-store-entry.d.ts +6 -0
- package/dist/stores/vortex-eval-store-entry.d.ts.map +1 -0
- package/dist/stores/vortex-eval-store-entry.js +664 -0
- package/dist/stores/vortex-eval-store-entry.js.map +7 -0
- package/dist/stores/vortex-eval-store.d.ts +78 -0
- package/dist/stores/vortex-eval-store.d.ts.map +1 -0
- package/dist/stores/vortex-eval-store.js +562 -0
- package/dist/stores/vortex-eval-store.js.map +7 -0
- package/dist/transformer.d.ts +2 -2
- package/dist/transformer.d.ts.map +1 -1
- package/dist/transformer.js +1 -1
- package/dist/transformer.js.map +2 -2
- package/dist/types.d.ts +55 -33
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +5 -1
- package/dist/types.js.map +3 -3
- package/package.json +66 -6
- package/dist/sse-collector.d.ts.map +0 -1
- package/dist/sse-collector.js.map +0 -7
- package/dist/trace.d.ts.map +0 -1
- /package/dist/{trace.js.map → spans/span-source.js.map} +0 -0
- /package/dist/{trace.d.ts → spans/trace.d.ts} +0 -0
- /package/dist/{trace.js → spans/trace.js} +0 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/stores/local-eval-store.ts", "../../src/loader.ts", "../../src/definition.ts", "../../src/errors.ts", "../../src/stores/eval-definition-loader.ts", "../../src/stores/vortex-eval-store.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", "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", "import type { EvalDefinition } from '../definition'\nimport type { EvalFilter, EvalProgressEvent, EvalReport, EvalRunReport, TurnReport, GraderResult } from '../types'\nimport type { EvalStore, EvalSummary, EvalRunSummary, EvalReportHistoryEntry, EvalWatchOptions } from './eval-store'\nimport type { EvalDefinitionLoader } from './eval-definition-loader'\n\n// \u2500\u2500 Vortex response types \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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\ninterface VortexEvalRun {\n id: string\n botId: string\n workspaceId: string\n evalManifestId: string\n status: 'pending' | 'running' | 'completed' | 'failed'\n triggerType: string\n startedAt: string | null\n completedAt: string | null\n createdAt: string\n updatedAt: string\n metadata?: Record<string, unknown> | null\n}\n\ninterface VortexEvalResult {\n id: string\n evalEntryId: string\n turnIndex: number\n graderName: string\n passed: boolean\n score: number | null\n evidence: Record<string, unknown>\n userMessage: string\n botResponse: string\n botDurationMs: number | null\n graderDurationMs: number | null\n createdAt: string\n}\n\ninterface VortexEvalEntry {\n id: string\n evalRunId: string\n evalName: string\n evalType: 'capability' | 'regression'\n description: string\n tags: string[]\n /** null while the entry is in-progress (per-turn lifecycle); set on finalize. */\n passed: boolean | null\n durationMs: number | null\n error: string | null\n createdAt: string\n results: VortexEvalResult[]\n}\n\n/** A single grader result row, as posted to Vortex. */\ninterface VortexResultInput {\n turnIndex: number\n graderName: string\n passed: boolean\n evidence: { expected: string; actual: string }\n userMessage: string\n botResponse: string\n botDurationMs: number\n graderDurationMs: number\n}\n\ntype VortexRunWithEntries = VortexEvalRun & { entries: VortexEvalEntry[] }\n\nconst OUTCOME_TURN_INDEX = -1\n\n// \u2500\u2500 Config \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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\nexport interface VortexEvalStoreConfig {\n url: string\n botId: string\n workspaceId?: string\n token?: string\n evalManifestId?: string | (() => string | undefined)\n loadEvalDefinitions?: EvalDefinitionLoader\n}\n\n// \u2500\u2500 Transformers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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\nfunction vortexEntryToEvalReport(entry: VortexEvalEntry): EvalReport {\n const outcomeAssertions: GraderResult[] = entry.results\n .filter((r) => r.turnIndex === OUTCOME_TURN_INDEX)\n .map((r) => ({\n assertion: r.graderName,\n pass: r.passed,\n expected: (r.evidence?.expected as string) ?? '',\n actual: (r.evidence?.actual as string) ?? '',\n }))\n\n const resultsByTurn = new Map<number, VortexEvalResult[]>()\n for (const r of entry.results) {\n if (r.turnIndex === OUTCOME_TURN_INDEX) continue\n const existing = resultsByTurn.get(r.turnIndex) ?? []\n existing.push(r)\n resultsByTurn.set(r.turnIndex, existing)\n }\n\n const turns: TurnReport[] = [...resultsByTurn.entries()]\n .sort(([a], [b]) => a - b)\n .map(([turnIndex, results]) => {\n const assertions: GraderResult[] = results.map((r) => ({\n assertion: r.graderName,\n pass: r.passed,\n expected: (r.evidence?.expected as string) ?? '',\n actual: (r.evidence?.actual as string) ?? '',\n }))\n const first = results[0]!\n return {\n turnIndex,\n userMessage: first.userMessage,\n botResponse: first.botResponse,\n assertions,\n pass: assertions.every((a) => a.pass),\n botDuration: first.botDurationMs ?? 0,\n evalDuration: first.graderDurationMs ?? 0,\n }\n })\n\n return {\n name: entry.evalName,\n description: entry.description || undefined,\n type: entry.evalType,\n tags: entry.tags,\n turns,\n outcomeAssertions,\n pass: entry.passed ?? false,\n duration: entry.durationMs ?? 0,\n error: entry.error ?? undefined,\n }\n}\n\n/** Run an async fn over items with bounded concurrency, preserving input order. */\nasync function mapWithConcurrency<T, R>(items: T[], concurrency: number, fn: (item: T) => Promise<R>): Promise<R[]> {\n const results = new Array<R>(items.length)\n let next = 0\n const workers = Array.from({ length: Math.min(concurrency, items.length) }, async () => {\n while (next < items.length) {\n const i = next++\n results[i] = await fn(items[i]!)\n }\n })\n await Promise.all(workers)\n return results\n}\n\n/** Map one turn's assertions to Vortex result rows (shared by batch + per-turn writes). */\nfunction turnToResultRows(turn: TurnReport): VortexResultInput[] {\n return graderResultsToRows(turn.assertions, {\n turnIndex: turn.turnIndex,\n userMessage: turn.userMessage,\n botResponse: turn.botResponse,\n botDurationMs: turn.botDuration,\n graderDurationMs: turn.evalDuration,\n })\n}\n\nfunction outcomeToResultRows(assertions: GraderResult[]): VortexResultInput[] {\n return graderResultsToRows(assertions, {\n turnIndex: OUTCOME_TURN_INDEX,\n userMessage: '',\n botResponse: '',\n botDurationMs: 0,\n graderDurationMs: 0,\n })\n}\n\nfunction graderResultsToRows(\n assertions: GraderResult[],\n context: Omit<VortexResultInput, 'graderName' | 'passed' | 'evidence'>\n): VortexResultInput[] {\n return assertions.map((assertion) => ({\n ...context,\n graderName: assertion.assertion,\n passed: assertion.pass,\n evidence: { expected: assertion.expected, actual: assertion.actual },\n }))\n}\n\nfunction runMatchesWatchOptions(run: VortexEvalRun, options: EvalWatchOptions): boolean {\n if (options.runId && run.id !== options.runId) return false\n if (options.workflowId && run.metadata?.workflowId !== options.workflowId) return false\n return true\n}\n\nfunction vortexRunToReport(run: VortexRunWithEntries): EvalRunReport {\n const evals = run.entries.map(vortexEntryToEvalReport)\n return {\n id: run.id,\n timestamp: run.createdAt,\n evals,\n passed: evals.filter((e) => e.pass).length,\n failed: evals.filter((e) => !e.pass).length,\n total: evals.length,\n duration: evals.reduce((s, e) => s + e.duration, 0),\n }\n}\n\nfunction vortexRunToSummary(run: VortexEvalRun & { entries?: VortexEvalEntry[] }): EvalRunSummary {\n const startMs = run.startedAt ? new Date(run.startedAt).getTime() : 0\n const endMs = run.completedAt ? new Date(run.completedAt).getTime() : 0\n\n if (run.entries) {\n const evals = run.entries.map(vortexEntryToEvalReport)\n return {\n id: run.id,\n timestamp: run.createdAt,\n passed: evals.filter((e) => e.pass).length,\n failed: evals.filter((e) => !e.pass).length,\n total: evals.length,\n duration: evals.reduce((s, e) => s + e.duration, 0),\n botDuration: evals.reduce((s, e) => e.turns.reduce((ts, t) => ts + t.botDuration, s), 0),\n evalDuration: evals.reduce((s, e) => e.turns.reduce((ts, t) => ts + t.evalDuration, s), 0),\n evalNames: evals.map((e) => e.name),\n aborted: false,\n }\n }\n\n return {\n id: run.id,\n timestamp: run.createdAt,\n passed: 0,\n failed: 0,\n total: 0,\n duration: startMs && endMs ? endMs - startMs : 0,\n botDuration: 0,\n evalDuration: 0,\n evalNames: [],\n aborted: false,\n }\n}\n\n// \u2500\u2500 VortexEvalStore \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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\nexport class VortexEvalStore implements EvalStore {\n private url: string\n private botId: string\n private workspaceId?: string\n private token?: string\n private _evalManifestId?: string | (() => string | undefined)\n private _loadEvalDefinitions?: EvalDefinitionLoader\n\n constructor(config: VortexEvalStoreConfig) {\n this.url = config.url.replace(/\\/$/, '')\n this.botId = config.botId\n if (config.workspaceId) this.workspaceId = config.workspaceId\n if (config.token) this.token = config.token\n this._evalManifestId = config.evalManifestId\n this._loadEvalDefinitions = config.loadEvalDefinitions\n }\n\n // \u2500\u2500 Eval definitions (from Files API manifest) \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 defs = await this.getEvalDefinitions()\n const filtered = defs.filter((e) => {\n if (filter?.names && !filter.names.includes(e.name)) return false\n if (filter?.type && e.type !== filter.type) return false\n if (filter?.tags && !filter.tags.every((tag) => e.tags?.includes(tag))) return false\n return true\n })\n return filtered.map((e) => ({\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\n async getEval(name: string): Promise<EvalDefinition | null> {\n const defs = await this.getEvalDefinitions()\n return defs.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 = 'scheduled', metadata?: Record<string, unknown>): Promise<string> {\n if (!this.workspaceId) {\n throw new Error('workspaceId is required to create Vortex eval runs')\n }\n\n const triggerType = runType === 'manual' ? 'manual' : 'scheduled'\n const res = await this.fetch(`/v1/evals/bot/${this.botId}/runs`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n evalManifestId:\n (typeof this._evalManifestId === 'function' ? this._evalManifestId() : this._evalManifestId) ?? '',\n workspaceId: this.workspaceId,\n triggerType,\n ...(metadata ? { metadata } : {}),\n }),\n })\n\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`Vortex create run failed: ${res.status} ${text}`)\n }\n\n const { id } = (await res.json()) as { id: string }\n return id\n }\n\n async addRunResults(runId: string, evalReport: EvalReport): Promise<void> {\n const entry = {\n evalName: evalReport.name,\n evalType: evalReport.type ?? 'capability',\n description: evalReport.description ?? '',\n tags: evalReport.tags ?? [],\n passed: evalReport.pass,\n durationMs: evalReport.duration,\n error: evalReport.error,\n results: [...evalReport.turns.flatMap(turnToResultRows), ...outcomeToResultRows(evalReport.outcomeAssertions)],\n }\n\n const res = await this.fetch(`/v1/evals/runs/${runId}/entries`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ entries: [entry] }),\n })\n\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`Vortex ingest entries failed: ${res.status} ${text}`)\n }\n }\n\n async completeRun(runId: string, report: EvalRunReport): Promise<void> {\n const hasRunError = report.aborted === true || report.evals.some((e) => e.error !== undefined)\n const res = await this.fetch(`/v1/evals/runs/${runId}/entries`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n entries: [],\n completed: !hasRunError,\n failed: hasRunError,\n }),\n })\n\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`Vortex complete run failed: ${res.status} ${text}`)\n }\n }\n\n // \u2500\u2500 Per-turn incremental lifecycle (Option B) \u2500\u2500\n //\n // The eval-runner workflow builds each entry up as the eval runs (rather than\n // writing it whole at the end), so the dev console can stream turn-by-turn\n // progress. This is the prod ingestion path and requires Vortex to provide:\n // startEntry POST /runs/{runId}/entries \u2192 { entries:[{ id }] } (passed:null, in-progress)\n // appendTurnResults POST /runs/{runId}/entries/{entryId}/results (idempotent upsert by turnIndex+graderName)\n // finalizeEntry PATCH /runs/{runId}/entries/{entryId} (sets the verdict)\n // markRunComplete POST /runs/{runId}/complete (status \u2192 completed|failed)\n\n /** Create an in-progress entry (metadata only, no results) and return its server id. */\n async startEntry(\n runId: string,\n meta: { evalName: string; evalType?: 'capability' | 'regression'; description?: string; tags?: string[] }\n ): Promise<string> {\n const res = await this.fetch(`/v1/evals/runs/${runId}/entries`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n entries: [\n {\n evalName: meta.evalName,\n evalType: meta.evalType ?? 'capability',\n description: meta.description ?? '',\n tags: meta.tags ?? [],\n },\n ],\n }),\n })\n\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`Vortex start entry failed: ${res.status} ${text}`)\n }\n\n const data = (await res.json()) as { entries?: { id: string }[]; id?: string }\n const entryId = data.entries?.[0]?.id ?? data.id\n if (!entryId) {\n throw new Error('Vortex start entry returned no entry id')\n }\n return entryId\n }\n\n /** Append one turn's grader results to an existing entry. */\n async appendTurnResults(runId: string, entryId: string, turn: TurnReport): Promise<void> {\n const res = await this.fetch(`/v1/evals/runs/${runId}/entries/${entryId}/results`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ results: turnToResultRows(turn) }),\n })\n\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`Vortex append results failed: ${res.status} ${text}`)\n }\n }\n\n /** Append outcome-level grader results to an existing entry. */\n async appendOutcomeResults(runId: string, entryId: string, assertions: GraderResult[]): Promise<void> {\n if (assertions.length === 0) return\n\n const res = await this.fetch(`/v1/evals/runs/${runId}/entries/${entryId}/results`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ results: outcomeToResultRows(assertions) }),\n })\n\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`Vortex append results failed: ${res.status} ${text}`)\n }\n }\n\n /** Set the verdict on an entry once its eval finishes. */\n async finalizeEntry(\n runId: string,\n entryId: string,\n verdict: { passed: boolean; durationMs?: number; error?: string }\n ): Promise<void> {\n const res = await this.fetch(`/v1/evals/runs/${runId}/entries/${entryId}`, {\n method: 'PATCH',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n passed: verdict.passed,\n ...(verdict.durationMs !== undefined ? { durationMs: verdict.durationMs } : {}),\n ...(verdict.error !== undefined ? { error: verdict.error } : {}),\n }),\n })\n\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`Vortex finalize entry failed: ${res.status} ${text}`)\n }\n }\n\n /** Flip the run to its terminal status (replaces completeRun's empty-entries hack). */\n async markRunComplete(runId: string, opts: { failed?: boolean } = {}): Promise<void> {\n const res = await this.fetch(`/v1/evals/runs/${runId}/complete`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({ ...(opts.failed !== undefined ? { failed: opts.failed } : {}) }),\n })\n\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`Vortex complete run failed: ${res.status} ${text}`)\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 data = await this.fetchJson<VortexRunWithEntries>(`/v1/evals/runs/${runId}`)\n return vortexRunToReport(data)\n }\n\n async getLatestRun(): Promise<EvalRunReport | null> {\n const data = await this.fetchJson<{ runs: VortexEvalRun[] }>(`/v1/evals/bot/${this.botId}/runs`, { limit: '1' })\n if (!data.runs.length) return null\n const latest = data.runs[0]!\n return this.loadRunResult(latest.id)\n }\n\n async listRunSummaries(opts?: { limit?: number; since?: number }): Promise<EvalRunSummary[]> {\n // Vortex's list endpoint returns runs WITHOUT entries, so summary counts\n // would all be zero \u2014 which the heatmap renders as \"No evals\". Pull each\n // run's entries to compute real pass/fail/total. N+1, bounded by the list\n // size; a counts field on the list endpoint would let us drop the per-run\n // fetch.\n const runs = await this.fetchRunsWithEntries(opts?.limit ?? 50, opts?.since)\n return runs.map(vortexRunToSummary)\n }\n\n async listEvalReportsByName(\n evalName: string,\n opts?: { limit?: number; since?: number }\n ): Promise<EvalReportHistoryEntry[]> {\n const limit = opts?.limit ?? 20\n const runs = await this.fetchRunsWithEntries(50, opts?.since)\n\n const entries: EvalReportHistoryEntry[] = []\n for (const run of runs) {\n if (entries.length >= limit) break\n const entry = run.entries.find((e) => e.evalName === evalName)\n if (entry) {\n entries.push({\n runId: run.id,\n timestamp: run.createdAt,\n report: vortexEntryToEvalReport(entry),\n totalEvalsInRun: run.entries.length,\n })\n }\n }\n return entries\n }\n\n async listEvalReportsBulk(opts?: {\n perEval?: number\n since?: number\n }): Promise<Record<string, EvalReportHistoryEntry[]>> {\n const per = opts?.perEval ?? 20\n const runs = await this.fetchRunsWithEntries(50, opts?.since)\n\n const grouped: Record<string, EvalReportHistoryEntry[]> = {}\n for (const run of runs) {\n for (const entry of run.entries) {\n if (!grouped[entry.evalName]) grouped[entry.evalName] = []\n if (grouped[entry.evalName]!.length < per) {\n grouped[entry.evalName]!.push({\n runId: run.id,\n timestamp: run.createdAt,\n report: vortexEntryToEvalReport(entry),\n totalEvalsInRun: run.entries.length,\n })\n }\n }\n }\n return grouped\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 // Poll fast enough that batched turns don't arrive in a single visible\n // burst \u2014 the prod path can't push per-event like the dev SSE stream, so a\n // tighter cadence is what keeps it feeling live.\n const POLL_INTERVAL = 1_500\n const POLL_TIMEOUT = 60 * 60 * 1_000 // 60min\n const start = Date.now()\n\n // Capture the run that's already the latest before this invocation begins.\n // The eval-runner workflow now creates its Vortex run UP FRONT (before\n // running the suite), so a genuinely new run appears almost immediately \u2014\n // but until it does, the \"latest\" run is the PREVIOUS one. Reporting that\n // would surface a stale, mismatched run (the runner shows eval \"A\" while\n // watchRun reports the prior run of eval \"B\", and the per-eval replay\n // filter renders \"no results\"). Only act on a run whose id differs from\n // this baseline.\n const hasExpectedRun = !!options.runId || !!options.workflowId\n let baselineRunId: string | null = null\n if (!hasExpectedRun) {\n try {\n const initial = await this.fetchJson<{ runs: VortexEvalRun[] }>(`/v1/evals/bot/${this.botId}/runs`, {\n limit: '1',\n })\n baselineRunId = initial.runs[0]?.id ?? null\n } catch {\n // Couldn't read the baseline; fall back to reporting the first completed run.\n }\n }\n\n // Diff the run on every poll and stream progress: `eval_start` when an\n // entry first appears, `turn_start` for the next in-flight turn (synthesized\n // from the definition so the pending-turn UI shows before results land),\n // `turn_complete` as each turn's results arrive, and `eval_complete` once\n // the entry is finalized (verdict set \u2192 `passed` is non-null).\n // `suite_complete` fires when the run reaches a terminal status. (Depends on\n // the per-turn lifecycle endpoints; see the write methods above.)\n const evalMeta = await this.loadEvalMeta()\n const startedEvals = new Set<string>()\n const seenTurns = new Set<string>()\n const startedTurns = new Set<string>()\n const finalizedEvals = new Set<string>()\n\n while (!signal?.aborted && Date.now() - start < POLL_TIMEOUT) {\n try {\n const data = await this.fetchJson<{ runs: VortexEvalRun[] }>(`/v1/evals/bot/${this.botId}/runs`, {\n limit: hasExpectedRun ? '20' : '1',\n })\n let latest: VortexEvalRun | null = null\n let raw: VortexRunWithEntries | null = null\n for (const candidate of data.runs) {\n if (options.runId && candidate.id !== options.runId) continue\n if (options.workflowId && candidate.metadata?.workflowId !== options.workflowId) {\n const candidateRaw = await this.fetchJson<VortexRunWithEntries>(`/v1/evals/runs/${candidate.id}`)\n if (!runMatchesWatchOptions(candidateRaw, options)) continue\n raw = candidateRaw\n }\n latest = candidate\n break\n }\n\n // Still seeing the pre-existing run (or none yet) \u2014 the new run hasn't\n // been created. Wait and retry.\n if (!latest || (!hasExpectedRun && latest.id === baselineRunId)) {\n await new Promise((r) => setTimeout(r, POLL_INTERVAL))\n continue\n }\n\n raw ??= await this.fetchJson<VortexRunWithEntries>(`/v1/evals/runs/${latest.id}`)\n const terminal = raw.status === 'completed' || raw.status === 'failed'\n\n for (let i = 0; i < raw.entries.length; i++) {\n const entry = raw.entries[i]!\n const evalReport = vortexEntryToEvalReport(entry)\n const meta = evalMeta.get(entry.evalName)\n const totalTurns = meta?.totalTurns ?? evalReport.turns.length\n\n if (!startedEvals.has(entry.evalName)) {\n startedEvals.add(entry.evalName)\n yield { type: 'eval_start', evalName: entry.evalName, index: i, totalTurns }\n }\n for (const turn of evalReport.turns) {\n const turnKey = `${entry.evalName}::${turn.turnIndex}`\n if (seenTurns.has(turnKey)) continue\n seenTurns.add(turnKey)\n yield {\n type: 'turn_complete',\n evalName: entry.evalName,\n evalIndex: i,\n turnIndex: turn.turnIndex,\n totalTurns,\n turnReport: turn,\n }\n }\n // Verdict set (passed non-null) \u2192 the eval is done.\n if (entry.passed != null && !finalizedEvals.has(entry.evalName)) {\n finalizedEvals.add(entry.evalName)\n yield { type: 'eval_complete', evalName: entry.evalName, index: i, report: evalReport }\n } else if (entry.passed == null && !terminal) {\n // Still running: announce the next expected turn so the UI renders\n // the in-flight turn (its user message + spinner) instead of jumping\n // straight from completed turns to the next completed turn. Results\n // land per-turn, so the next index is simply the completed count.\n const nextTurnIndex = evalReport.turns.length\n const startKey = `${entry.evalName}::${nextTurnIndex}`\n if (nextTurnIndex < totalTurns && !startedTurns.has(startKey)) {\n startedTurns.add(startKey)\n yield {\n type: 'turn_start',\n evalName: entry.evalName,\n evalIndex: i,\n turnIndex: nextTurnIndex,\n totalTurns,\n userMessage: meta?.userMessages[nextTurnIndex] ?? '',\n }\n }\n }\n }\n\n if (terminal) {\n const finalReport = vortexRunToReport(raw)\n // Flush any eval that never received an explicit verdict (e.g. it\n // errored out before finalizeEntry was called).\n for (let i = 0; i < finalReport.evals.length; i++) {\n const evalReport = finalReport.evals[i]!\n if (finalizedEvals.has(evalReport.name)) continue\n finalizedEvals.add(evalReport.name)\n yield { type: 'eval_complete', evalName: evalReport.name, index: i, report: evalReport }\n }\n yield {\n type: 'suite_complete',\n report: finalReport,\n error: raw.status === 'failed' ? 'Eval run failed' : undefined,\n }\n return\n }\n } catch {\n // Poll failed, retry next interval\n }\n\n // Settled-but-not-terminal poll (or a failed poll): wait before the next.\n // The \"no new run yet\" branch above already slept and continued, so this\n // is the only other delay point.\n await new Promise((r) => setTimeout(r, POLL_INTERVAL))\n }\n\n if (!signal?.aborted) {\n yield {\n type: 'suite_complete',\n report: {\n id: 'timeout',\n timestamp: new Date().toISOString(),\n evals: [],\n passed: 0,\n failed: 0,\n total: 0,\n duration: 0,\n },\n error: 'Eval run timed out',\n }\n }\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 try {\n const data = await this.fetchJson<{ runs: VortexEvalRun[] }>(`/v1/evals/bot/${this.botId}/runs`, {\n status: 'running',\n limit: '1',\n })\n const active = data.runs[0] ?? null\n return { running: !!active, runId: active?.id ?? null }\n } catch {\n return { running: false, runId: null }\n }\n }\n\n // \u2500\u2500 Internal helpers \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\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 async getEvalDefinitions(): Promise<EvalDefinition[]> {\n if (!this._loadEvalDefinitions) return []\n return this._loadEvalDefinitions()\n }\n\n /**\n * evalName \u2192 { totalTurns, userMessages } from the eval definitions, so\n * watchRun can report `totalTurns` and synthesize `turn_start` events (with\n * the turn's user message) for the in-flight turn \u2014 matching the dev SSE\n * experience where the pending turn is visible before its results land.\n */\n private async loadEvalMeta(): Promise<Map<string, { totalTurns: number; userMessages: string[] }>> {\n try {\n const defs = await this.getEvalDefinitions()\n return new Map(\n defs.map((d) => [\n d.name,\n { totalTurns: d.conversation.length, userMessages: d.conversation.map((t) => t.user ?? '') },\n ])\n )\n } catch {\n return new Map()\n }\n }\n\n private async fetchRunsWithEntries(limit: number, since?: number): Promise<VortexRunWithEntries[]> {\n const data = await this.fetchJson<{ runs: VortexEvalRun[] }>(`/v1/evals/bot/${this.botId}/runs`, {\n limit: String(limit),\n })\n\n let runs = data.runs\n if (since) {\n runs = runs.filter((r) => new Date(r.createdAt).getTime() >= since)\n }\n\n // The list endpoint omits entries, so fetch each run's detail. Bounded\n // concurrency keeps a wide `since` window from opening hundreds of sockets.\n return mapWithConcurrency(runs, 8, (r) => this.fetchJson<VortexRunWithEntries>(`/v1/evals/runs/${r.id}`))\n }\n\n private async fetch(path: string, init?: RequestInit): Promise<Response> {\n const target = new URL(`${this.url}${path}`)\n const headers = new Headers(init?.headers)\n if (this.token) headers.set('Authorization', `Bearer ${this.token}`)\n return globalThis.fetch(target, { ...init, headers })\n }\n\n private async fetchJson<T>(path: string, params?: Record<string, string>): Promise<T> {\n const target = new URL(`${this.url}${path}`)\n if (params) {\n for (const [k, v] of Object.entries(params)) target.searchParams.set(k, v)\n }\n const headers = new Headers()\n if (this.token) headers.set('Authorization', `Bearer ${this.token}`)\n\n const res = await globalThis.fetch(target, { headers })\n if (!res.ok) {\n const text = await res.text().catch(() => '')\n throw new Error(`Vortex ${res.status}: ${text}`)\n }\n return res.json() as Promise<T>\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["existsSync", "readdirSync", "existsSync", "readdirSync"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* LocalEvalStore — local eval store backed by bun:sqlite + disk-loaded definitions.
|
|
3
|
+
*
|
|
4
|
+
* Implements the EvalStore interface for the local dev environment:
|
|
5
|
+
* - Eval definitions loaded from the agent's evals/ directory
|
|
6
|
+
* - Run results persisted in SQLite (.adk/evals/evals.db)
|
|
7
|
+
* - Runner state tracked via in-memory activeRunId
|
|
8
|
+
*
|
|
9
|
+
* The CLI is the single writer and reader of the SQLite database — no
|
|
10
|
+
* concurrent write issues since the CLI process owns the DB.
|
|
11
|
+
*/
|
|
12
|
+
import type { EvalDefinition } from '../definition';
|
|
13
|
+
import type { EvalFilter, EvalProgressEvent, EvalReport, EvalRunReport } from '../types';
|
|
14
|
+
import type { EvalStore, EvalSummary, EvalRunSummary, EvalReportHistoryEntry, EvalWatchOptions } from './eval-store';
|
|
15
|
+
import type { EvalDefinitionLoader } from './eval-definition-loader';
|
|
16
|
+
export interface LocalEvalStoreConfig {
|
|
17
|
+
agentPath: string;
|
|
18
|
+
getActiveRunId?: () => string | null;
|
|
19
|
+
loadEvalDefinitions?: EvalDefinitionLoader;
|
|
20
|
+
}
|
|
21
|
+
export declare class LocalEvalStore implements EvalStore {
|
|
22
|
+
private db;
|
|
23
|
+
private dbPath;
|
|
24
|
+
private evalsDir;
|
|
25
|
+
private insertRunStmt;
|
|
26
|
+
private insertReportStmt;
|
|
27
|
+
private _getActiveRunId;
|
|
28
|
+
private _loadEvalDefinitions;
|
|
29
|
+
constructor(config: LocalEvalStoreConfig);
|
|
30
|
+
listEvals(filter?: EvalFilter): Promise<EvalSummary[]>;
|
|
31
|
+
getEval(name: string): Promise<EvalDefinition | null>;
|
|
32
|
+
createRun(_runType?: string, _metadata?: Record<string, unknown>): Promise<string>;
|
|
33
|
+
addRunResults(_runId: string, _evalReport: EvalReport): Promise<void>;
|
|
34
|
+
completeRun(_runId: string, report: EvalRunReport): Promise<void>;
|
|
35
|
+
loadRunResult(runId: string): Promise<EvalRunReport | null>;
|
|
36
|
+
getLatestRun(): Promise<EvalRunReport | null>;
|
|
37
|
+
listRunSummaries(opts?: {
|
|
38
|
+
limit?: number;
|
|
39
|
+
since?: number;
|
|
40
|
+
}): Promise<EvalRunSummary[]>;
|
|
41
|
+
listEvalReportsByName(evalName: string, opts?: {
|
|
42
|
+
limit?: number;
|
|
43
|
+
since?: number;
|
|
44
|
+
}): Promise<EvalReportHistoryEntry[]>;
|
|
45
|
+
listEvalReportsBulk(opts?: {
|
|
46
|
+
perEval?: number;
|
|
47
|
+
since?: number;
|
|
48
|
+
}): Promise<Record<string, EvalReportHistoryEntry[]>>;
|
|
49
|
+
watchRun(_signal?: AbortSignal, _options?: EvalWatchOptions): AsyncIterable<EvalProgressEvent>;
|
|
50
|
+
getRunnerState(): Promise<{
|
|
51
|
+
running: boolean;
|
|
52
|
+
runId: string | null;
|
|
53
|
+
}>;
|
|
54
|
+
listRunResults(limit?: number, sinceTs?: number): Promise<EvalRunReport[]>;
|
|
55
|
+
close(): void;
|
|
56
|
+
getDbPath(): string;
|
|
57
|
+
private getDb;
|
|
58
|
+
private getMeta;
|
|
59
|
+
private setMeta;
|
|
60
|
+
private importLegacyJsonRunsIfNeeded;
|
|
61
|
+
private insertRunReport;
|
|
62
|
+
private assembleRun;
|
|
63
|
+
}
|
|
64
|
+
export declare function getLocalEvalStore(agentPath: string, getActiveRunId?: () => string | null): LocalEvalStore;
|
|
65
|
+
export declare function closeLocalEvalStores(agentPath?: string): void;
|
|
66
|
+
//# sourceMappingURL=local-eval-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"local-eval-store.d.ts","sourceRoot":"","sources":["../../src/stores/local-eval-store.ts"],"names":[],"mappings":"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"}
|