@axiom-lattice/pg-stores 1.0.53 → 1.0.55
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/.turbo/turbo-build.log +10 -10
- package/CHANGELOG.md +16 -0
- package/dist/index.d.mts +124 -3
- package/dist/index.d.ts +124 -3
- package/dist/index.js +937 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +930 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -3
- package/src/index.ts +14 -0
- package/src/migrations/eval_migrations.ts +218 -0
- package/src/stores/PostgreSQLEvalStore.ts +880 -0
package/dist/index.js
CHANGED
|
@@ -32,10 +32,11 @@ var index_exports = {};
|
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
ChannelIdentityMappingStore: () => ChannelIdentityMappingStore,
|
|
34
34
|
MigrationManager: () => MigrationManager,
|
|
35
|
-
Pool: () =>
|
|
35
|
+
Pool: () => import_pg17.Pool,
|
|
36
36
|
PostgreSQLAssistantStore: () => PostgreSQLAssistantStore,
|
|
37
37
|
PostgreSQLChannelInstallationStore: () => PostgreSQLChannelInstallationStore,
|
|
38
38
|
PostgreSQLDatabaseConfigStore: () => PostgreSQLDatabaseConfigStore,
|
|
39
|
+
PostgreSQLEvalStore: () => PostgreSQLEvalStore,
|
|
39
40
|
PostgreSQLMcpServerConfigStore: () => PostgreSQLMcpServerConfigStore,
|
|
40
41
|
PostgreSQLMetricsServerConfigStore: () => PostgreSQLMetricsServerConfigStore,
|
|
41
42
|
PostgreSQLProjectStore: () => PostgreSQLProjectStore,
|
|
@@ -59,6 +60,11 @@ __export(index_exports, {
|
|
|
59
60
|
createChannelIdentityMappingTables: () => createChannelIdentityMappingTables,
|
|
60
61
|
createChannelInstallationsTable: () => createChannelInstallationsTable,
|
|
61
62
|
createDatabaseConfigsTable: () => createDatabaseConfigsTable,
|
|
63
|
+
createEvalCasesTable: () => createEvalCasesTable,
|
|
64
|
+
createEvalProjectsTable: () => createEvalProjectsTable,
|
|
65
|
+
createEvalRunResultsTable: () => createEvalRunResultsTable,
|
|
66
|
+
createEvalRunsTable: () => createEvalRunsTable,
|
|
67
|
+
createEvalSuitesTable: () => createEvalSuitesTable,
|
|
62
68
|
createMcpServerConfigsTable: () => createMcpServerConfigsTable,
|
|
63
69
|
createMetricsConfigsTable: () => createMetricsConfigsTable,
|
|
64
70
|
createProjectsTable: () => createProjectsTable,
|
|
@@ -70,10 +76,11 @@ __export(index_exports, {
|
|
|
70
76
|
createUsersTable: () => createUsersTable,
|
|
71
77
|
createWorkflowTrackingTables: () => createWorkflowTrackingTables,
|
|
72
78
|
createWorkspacesTable: () => createWorkspacesTable,
|
|
79
|
+
evalMigrations: () => evalMigrations,
|
|
73
80
|
getThreadMessageQueueStore: () => getThreadMessageQueueStore
|
|
74
81
|
});
|
|
75
82
|
module.exports = __toCommonJS(index_exports);
|
|
76
|
-
var
|
|
83
|
+
var import_pg17 = require("pg");
|
|
77
84
|
|
|
78
85
|
// src/stores/PostgreSQLThreadStore.ts
|
|
79
86
|
var import_pg = require("pg");
|
|
@@ -5213,6 +5220,927 @@ var PostgreSQLWorkflowTrackingStore = class {
|
|
|
5213
5220
|
};
|
|
5214
5221
|
}
|
|
5215
5222
|
};
|
|
5223
|
+
|
|
5224
|
+
// src/stores/PostgreSQLEvalStore.ts
|
|
5225
|
+
var import_pg16 = require("pg");
|
|
5226
|
+
|
|
5227
|
+
// src/migrations/eval_migrations.ts
|
|
5228
|
+
var createEvalProjectsTable = {
|
|
5229
|
+
version: 104,
|
|
5230
|
+
name: "create_eval_projects_table",
|
|
5231
|
+
up: async (client) => {
|
|
5232
|
+
await client.query(`
|
|
5233
|
+
CREATE TABLE IF NOT EXISTS lattice_eval_projects (
|
|
5234
|
+
id UUID PRIMARY KEY,
|
|
5235
|
+
tenant_id VARCHAR(255) NOT NULL,
|
|
5236
|
+
name TEXT NOT NULL,
|
|
5237
|
+
description TEXT,
|
|
5238
|
+
version TEXT,
|
|
5239
|
+
judge_model_config JSONB NOT NULL DEFAULT '{}',
|
|
5240
|
+
target_server_config JSONB NOT NULL DEFAULT '{}',
|
|
5241
|
+
concurrency INTEGER NOT NULL DEFAULT 3,
|
|
5242
|
+
report_config JSONB DEFAULT '{}',
|
|
5243
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
5244
|
+
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
5245
|
+
)
|
|
5246
|
+
`);
|
|
5247
|
+
await client.query(`
|
|
5248
|
+
CREATE INDEX IF NOT EXISTS idx_lattice_eval_projects_tenant_id
|
|
5249
|
+
ON lattice_eval_projects(tenant_id)
|
|
5250
|
+
`);
|
|
5251
|
+
await client.query(`
|
|
5252
|
+
CREATE INDEX IF NOT EXISTS idx_lattice_eval_projects_created_at
|
|
5253
|
+
ON lattice_eval_projects(created_at)
|
|
5254
|
+
`);
|
|
5255
|
+
},
|
|
5256
|
+
down: async (client) => {
|
|
5257
|
+
await client.query("DROP INDEX IF EXISTS idx_lattice_eval_projects_created_at");
|
|
5258
|
+
await client.query("DROP INDEX IF EXISTS idx_lattice_eval_projects_tenant_id");
|
|
5259
|
+
await client.query("DROP TABLE IF EXISTS lattice_eval_projects");
|
|
5260
|
+
}
|
|
5261
|
+
};
|
|
5262
|
+
var createEvalSuitesTable = {
|
|
5263
|
+
version: 105,
|
|
5264
|
+
name: "create_eval_suites_table",
|
|
5265
|
+
up: async (client) => {
|
|
5266
|
+
await client.query(`
|
|
5267
|
+
CREATE TABLE IF NOT EXISTS lattice_eval_suites (
|
|
5268
|
+
id UUID PRIMARY KEY,
|
|
5269
|
+
tenant_id VARCHAR(255) NOT NULL,
|
|
5270
|
+
project_id UUID NOT NULL REFERENCES lattice_eval_projects(id) ON DELETE CASCADE,
|
|
5271
|
+
name TEXT NOT NULL,
|
|
5272
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
5273
|
+
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
5274
|
+
UNIQUE(project_id, name)
|
|
5275
|
+
)
|
|
5276
|
+
`);
|
|
5277
|
+
await client.query(`
|
|
5278
|
+
CREATE INDEX IF NOT EXISTS idx_lattice_eval_suites_tenant_id
|
|
5279
|
+
ON lattice_eval_suites(tenant_id)
|
|
5280
|
+
`);
|
|
5281
|
+
await client.query(`
|
|
5282
|
+
CREATE INDEX IF NOT EXISTS idx_lattice_eval_suites_project_id
|
|
5283
|
+
ON lattice_eval_suites(project_id)
|
|
5284
|
+
`);
|
|
5285
|
+
},
|
|
5286
|
+
down: async (client) => {
|
|
5287
|
+
await client.query("DROP INDEX IF EXISTS idx_lattice_eval_suites_project_id");
|
|
5288
|
+
await client.query("DROP INDEX IF EXISTS idx_lattice_eval_suites_tenant_id");
|
|
5289
|
+
await client.query("DROP TABLE IF EXISTS lattice_eval_suites");
|
|
5290
|
+
}
|
|
5291
|
+
};
|
|
5292
|
+
var createEvalCasesTable = {
|
|
5293
|
+
version: 106,
|
|
5294
|
+
name: "create_eval_cases_table",
|
|
5295
|
+
up: async (client) => {
|
|
5296
|
+
await client.query(`
|
|
5297
|
+
CREATE TABLE IF NOT EXISTS lattice_eval_cases (
|
|
5298
|
+
id UUID PRIMARY KEY,
|
|
5299
|
+
tenant_id VARCHAR(255) NOT NULL,
|
|
5300
|
+
suite_id UUID NOT NULL REFERENCES lattice_eval_suites(id) ON DELETE CASCADE,
|
|
5301
|
+
template_id UUID,
|
|
5302
|
+
input_message TEXT NOT NULL,
|
|
5303
|
+
input_files JSONB DEFAULT '{}',
|
|
5304
|
+
steps JSONB NOT NULL DEFAULT '[]',
|
|
5305
|
+
output_type TEXT NOT NULL DEFAULT 'message_content',
|
|
5306
|
+
content_assertion TEXT,
|
|
5307
|
+
rubrics JSONB DEFAULT '[]',
|
|
5308
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
5309
|
+
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
5310
|
+
)
|
|
5311
|
+
`);
|
|
5312
|
+
await client.query(`
|
|
5313
|
+
CREATE INDEX IF NOT EXISTS idx_lattice_eval_cases_tenant_id
|
|
5314
|
+
ON lattice_eval_cases(tenant_id)
|
|
5315
|
+
`);
|
|
5316
|
+
await client.query(`
|
|
5317
|
+
CREATE INDEX IF NOT EXISTS idx_lattice_eval_cases_suite_id
|
|
5318
|
+
ON lattice_eval_cases(suite_id)
|
|
5319
|
+
`);
|
|
5320
|
+
},
|
|
5321
|
+
down: async (client) => {
|
|
5322
|
+
await client.query("DROP INDEX IF EXISTS idx_lattice_eval_cases_suite_id");
|
|
5323
|
+
await client.query("DROP INDEX IF EXISTS idx_lattice_eval_cases_tenant_id");
|
|
5324
|
+
await client.query("DROP TABLE IF EXISTS lattice_eval_cases");
|
|
5325
|
+
}
|
|
5326
|
+
};
|
|
5327
|
+
var createEvalRunsTable = {
|
|
5328
|
+
version: 107,
|
|
5329
|
+
name: "create_eval_runs_table",
|
|
5330
|
+
up: async (client) => {
|
|
5331
|
+
await client.query(`
|
|
5332
|
+
CREATE TABLE IF NOT EXISTS lattice_eval_runs (
|
|
5333
|
+
id UUID PRIMARY KEY,
|
|
5334
|
+
project_id UUID NOT NULL REFERENCES lattice_eval_projects(id) ON DELETE CASCADE,
|
|
5335
|
+
tenant_id VARCHAR(255) NOT NULL,
|
|
5336
|
+
status TEXT NOT NULL DEFAULT 'running',
|
|
5337
|
+
concurrency INTEGER NOT NULL DEFAULT 3,
|
|
5338
|
+
total_cases INTEGER NOT NULL DEFAULT 0,
|
|
5339
|
+
passed_cases INTEGER NOT NULL DEFAULT 0,
|
|
5340
|
+
failed_cases INTEGER NOT NULL DEFAULT 0,
|
|
5341
|
+
avg_score FLOAT NOT NULL DEFAULT 0,
|
|
5342
|
+
error TEXT,
|
|
5343
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
5344
|
+
started_at TIMESTAMPTZ,
|
|
5345
|
+
completed_at TIMESTAMPTZ
|
|
5346
|
+
)
|
|
5347
|
+
`);
|
|
5348
|
+
await client.query(`
|
|
5349
|
+
CREATE INDEX IF NOT EXISTS idx_lattice_eval_runs_tenant_id
|
|
5350
|
+
ON lattice_eval_runs(tenant_id)
|
|
5351
|
+
`);
|
|
5352
|
+
await client.query(`
|
|
5353
|
+
CREATE INDEX IF NOT EXISTS idx_lattice_eval_runs_project_id
|
|
5354
|
+
ON lattice_eval_runs(project_id)
|
|
5355
|
+
`);
|
|
5356
|
+
await client.query(`
|
|
5357
|
+
CREATE INDEX IF NOT EXISTS idx_lattice_eval_runs_status
|
|
5358
|
+
ON lattice_eval_runs(status)
|
|
5359
|
+
`);
|
|
5360
|
+
await client.query(`
|
|
5361
|
+
CREATE INDEX IF NOT EXISTS idx_lattice_eval_runs_created_at
|
|
5362
|
+
ON lattice_eval_runs(created_at)
|
|
5363
|
+
`);
|
|
5364
|
+
},
|
|
5365
|
+
down: async (client) => {
|
|
5366
|
+
await client.query("DROP INDEX IF EXISTS idx_lattice_eval_runs_created_at");
|
|
5367
|
+
await client.query("DROP INDEX IF EXISTS idx_lattice_eval_runs_status");
|
|
5368
|
+
await client.query("DROP INDEX IF EXISTS idx_lattice_eval_runs_project_id");
|
|
5369
|
+
await client.query("DROP INDEX IF EXISTS idx_lattice_eval_runs_tenant_id");
|
|
5370
|
+
await client.query("DROP TABLE IF EXISTS lattice_eval_runs");
|
|
5371
|
+
}
|
|
5372
|
+
};
|
|
5373
|
+
var createEvalRunResultsTable = {
|
|
5374
|
+
version: 108,
|
|
5375
|
+
name: "create_eval_run_results_table",
|
|
5376
|
+
up: async (client) => {
|
|
5377
|
+
await client.query(`
|
|
5378
|
+
CREATE TABLE IF NOT EXISTS lattice_eval_run_results (
|
|
5379
|
+
id UUID PRIMARY KEY,
|
|
5380
|
+
run_id UUID NOT NULL REFERENCES lattice_eval_runs(id) ON DELETE CASCADE,
|
|
5381
|
+
suite_name TEXT NOT NULL DEFAULT '',
|
|
5382
|
+
case_id UUID,
|
|
5383
|
+
pass BOOLEAN NOT NULL DEFAULT false,
|
|
5384
|
+
score FLOAT NOT NULL DEFAULT 0,
|
|
5385
|
+
summary TEXT,
|
|
5386
|
+
dimension_results JSONB DEFAULT '[]',
|
|
5387
|
+
duration_ms INTEGER DEFAULT 0,
|
|
5388
|
+
messages JSONB DEFAULT '[]',
|
|
5389
|
+
logs JSONB DEFAULT '[]',
|
|
5390
|
+
error TEXT,
|
|
5391
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
5392
|
+
)
|
|
5393
|
+
`);
|
|
5394
|
+
await client.query(`
|
|
5395
|
+
CREATE INDEX IF NOT EXISTS idx_lattice_eval_run_results_run_id
|
|
5396
|
+
ON lattice_eval_run_results(run_id)
|
|
5397
|
+
`);
|
|
5398
|
+
await client.query(`
|
|
5399
|
+
CREATE INDEX IF NOT EXISTS idx_lattice_eval_run_results_case_id
|
|
5400
|
+
ON lattice_eval_run_results(case_id)
|
|
5401
|
+
`);
|
|
5402
|
+
},
|
|
5403
|
+
down: async (client) => {
|
|
5404
|
+
await client.query("DROP INDEX IF EXISTS idx_lattice_eval_run_results_case_id");
|
|
5405
|
+
await client.query("DROP INDEX IF EXISTS idx_lattice_eval_run_results_run_id");
|
|
5406
|
+
await client.query("DROP TABLE IF EXISTS lattice_eval_run_results");
|
|
5407
|
+
}
|
|
5408
|
+
};
|
|
5409
|
+
var evalMigrations = [
|
|
5410
|
+
createEvalProjectsTable,
|
|
5411
|
+
createEvalSuitesTable,
|
|
5412
|
+
createEvalCasesTable,
|
|
5413
|
+
createEvalRunsTable,
|
|
5414
|
+
createEvalRunResultsTable
|
|
5415
|
+
];
|
|
5416
|
+
|
|
5417
|
+
// src/stores/PostgreSQLEvalStore.ts
|
|
5418
|
+
var import_uuid = require("uuid");
|
|
5419
|
+
var PostgreSQLEvalStore = class {
|
|
5420
|
+
constructor(options) {
|
|
5421
|
+
this.initialized = false;
|
|
5422
|
+
this.ownsPool = true;
|
|
5423
|
+
this.initPromise = null;
|
|
5424
|
+
if (typeof options.poolConfig === "string") {
|
|
5425
|
+
this.pool = new import_pg16.Pool({ connectionString: options.poolConfig });
|
|
5426
|
+
} else {
|
|
5427
|
+
this.pool = new import_pg16.Pool(options.poolConfig);
|
|
5428
|
+
}
|
|
5429
|
+
this.migrationManager = new MigrationManager(this.pool);
|
|
5430
|
+
for (const m of evalMigrations) {
|
|
5431
|
+
this.migrationManager.register(m);
|
|
5432
|
+
}
|
|
5433
|
+
if (options.autoMigrate !== false) {
|
|
5434
|
+
this.initialize().catch((error) => {
|
|
5435
|
+
console.error("Failed to initialize PostgreSQLEvalStore:", error);
|
|
5436
|
+
throw error;
|
|
5437
|
+
});
|
|
5438
|
+
}
|
|
5439
|
+
}
|
|
5440
|
+
/** Dispose resources and close the connection pool */
|
|
5441
|
+
async dispose() {
|
|
5442
|
+
if (this.ownsPool && this.pool) {
|
|
5443
|
+
await this.pool.end();
|
|
5444
|
+
}
|
|
5445
|
+
}
|
|
5446
|
+
/**
|
|
5447
|
+
* Initialize the store and run migrations
|
|
5448
|
+
* Uses a promise-based lock to prevent concurrent initialization
|
|
5449
|
+
*/
|
|
5450
|
+
async initialize() {
|
|
5451
|
+
if (this.initialized) {
|
|
5452
|
+
return;
|
|
5453
|
+
}
|
|
5454
|
+
if (this.initPromise) {
|
|
5455
|
+
return this.initPromise;
|
|
5456
|
+
}
|
|
5457
|
+
this.initPromise = (async () => {
|
|
5458
|
+
try {
|
|
5459
|
+
await this.migrationManager.migrate();
|
|
5460
|
+
this.initialized = true;
|
|
5461
|
+
} finally {
|
|
5462
|
+
this.initPromise = null;
|
|
5463
|
+
}
|
|
5464
|
+
})();
|
|
5465
|
+
return this.initPromise;
|
|
5466
|
+
}
|
|
5467
|
+
/** Ensure store is initialized */
|
|
5468
|
+
async ensureInitialized() {
|
|
5469
|
+
if (!this.initialized) {
|
|
5470
|
+
await this.initialize();
|
|
5471
|
+
}
|
|
5472
|
+
}
|
|
5473
|
+
// ---------------------------------------------------------------------------
|
|
5474
|
+
// Row mappers
|
|
5475
|
+
// ---------------------------------------------------------------------------
|
|
5476
|
+
mapRowToProject(row) {
|
|
5477
|
+
return {
|
|
5478
|
+
id: row.id,
|
|
5479
|
+
tenantId: row.tenant_id,
|
|
5480
|
+
name: row.name,
|
|
5481
|
+
description: row.description,
|
|
5482
|
+
version: row.version,
|
|
5483
|
+
judgeModelConfig: this.parseRequiredJson(row.judge_model_config, {}),
|
|
5484
|
+
targetServerConfig: this.parseRequiredJson(row.target_server_config, {}),
|
|
5485
|
+
concurrency: row.concurrency ?? 3,
|
|
5486
|
+
reportConfig: this.parseOptionalJson(row.report_config),
|
|
5487
|
+
createdAt: new Date(row.created_at),
|
|
5488
|
+
updatedAt: new Date(row.updated_at)
|
|
5489
|
+
};
|
|
5490
|
+
}
|
|
5491
|
+
mapRowToSuite(row) {
|
|
5492
|
+
return {
|
|
5493
|
+
id: row.id,
|
|
5494
|
+
tenantId: row.tenant_id,
|
|
5495
|
+
projectId: row.project_id,
|
|
5496
|
+
name: row.name,
|
|
5497
|
+
createdAt: new Date(row.created_at),
|
|
5498
|
+
updatedAt: new Date(row.updated_at),
|
|
5499
|
+
caseCount: row.case_count !== void 0 ? row.case_count : void 0
|
|
5500
|
+
};
|
|
5501
|
+
}
|
|
5502
|
+
mapRowToCase(row) {
|
|
5503
|
+
return {
|
|
5504
|
+
id: row.id,
|
|
5505
|
+
tenantId: row.tenant_id,
|
|
5506
|
+
suiteId: row.suite_id,
|
|
5507
|
+
inputMessage: row.input_message,
|
|
5508
|
+
inputFiles: this.parseOptionalJson(row.input_files),
|
|
5509
|
+
steps: this.parseRequiredJson(row.steps, []),
|
|
5510
|
+
outputType: row.output_type || "message_content",
|
|
5511
|
+
contentAssertion: row.content_assertion || "",
|
|
5512
|
+
rubrics: this.parseOptionalJson(row.rubrics),
|
|
5513
|
+
createdAt: new Date(row.created_at),
|
|
5514
|
+
updatedAt: new Date(row.updated_at)
|
|
5515
|
+
};
|
|
5516
|
+
}
|
|
5517
|
+
mapRowToRun(row) {
|
|
5518
|
+
return {
|
|
5519
|
+
id: row.id,
|
|
5520
|
+
projectId: row.project_id,
|
|
5521
|
+
tenantId: row.tenant_id,
|
|
5522
|
+
status: row.status,
|
|
5523
|
+
concurrency: row.concurrency ?? 3,
|
|
5524
|
+
totalCases: row.total_cases ?? 0,
|
|
5525
|
+
passedCases: row.passed_cases ?? 0,
|
|
5526
|
+
failedCases: row.failed_cases ?? 0,
|
|
5527
|
+
avgScore: row.avg_score ?? 0,
|
|
5528
|
+
error: row.error,
|
|
5529
|
+
createdAt: new Date(row.created_at),
|
|
5530
|
+
startedAt: row.started_at ? new Date(row.started_at) : void 0,
|
|
5531
|
+
completedAt: row.completed_at ? new Date(row.completed_at) : void 0
|
|
5532
|
+
};
|
|
5533
|
+
}
|
|
5534
|
+
mapRowToRunResult(row) {
|
|
5535
|
+
return {
|
|
5536
|
+
id: row.id,
|
|
5537
|
+
runId: row.run_id,
|
|
5538
|
+
suiteName: row.suite_name,
|
|
5539
|
+
caseId: row.case_id,
|
|
5540
|
+
pass: row.pass ?? false,
|
|
5541
|
+
score: row.score ?? 0,
|
|
5542
|
+
summary: row.summary,
|
|
5543
|
+
dimensionResults: this.parseOptionalJson(row.dimension_results),
|
|
5544
|
+
durationMs: row.duration_ms,
|
|
5545
|
+
messages: this.parseOptionalJson(row.messages),
|
|
5546
|
+
logs: this.parseOptionalJson(row.logs),
|
|
5547
|
+
error: row.error,
|
|
5548
|
+
createdAt: new Date(row.created_at)
|
|
5549
|
+
};
|
|
5550
|
+
}
|
|
5551
|
+
parseRequiredJson(val, fallback) {
|
|
5552
|
+
if (val == null) return fallback;
|
|
5553
|
+
if (typeof val === "string") {
|
|
5554
|
+
try {
|
|
5555
|
+
return JSON.parse(val);
|
|
5556
|
+
} catch {
|
|
5557
|
+
return fallback;
|
|
5558
|
+
}
|
|
5559
|
+
}
|
|
5560
|
+
return val;
|
|
5561
|
+
}
|
|
5562
|
+
parseOptionalJson(val) {
|
|
5563
|
+
if (val == null) return void 0;
|
|
5564
|
+
if (typeof val === "string") {
|
|
5565
|
+
try {
|
|
5566
|
+
return JSON.parse(val);
|
|
5567
|
+
} catch {
|
|
5568
|
+
return void 0;
|
|
5569
|
+
}
|
|
5570
|
+
}
|
|
5571
|
+
return val;
|
|
5572
|
+
}
|
|
5573
|
+
// ---------------------------------------------------------------------------
|
|
5574
|
+
// Projects
|
|
5575
|
+
// ---------------------------------------------------------------------------
|
|
5576
|
+
/** Get all eval projects for a tenant */
|
|
5577
|
+
async getProjectsByTenant(tenantId) {
|
|
5578
|
+
await this.ensureInitialized();
|
|
5579
|
+
const { rows } = await this.pool.query(
|
|
5580
|
+
`SELECT id, tenant_id, name, description, version,
|
|
5581
|
+
judge_model_config, target_server_config, concurrency,
|
|
5582
|
+
report_config, created_at, updated_at
|
|
5583
|
+
FROM lattice_eval_projects
|
|
5584
|
+
WHERE tenant_id = $1
|
|
5585
|
+
ORDER BY created_at DESC`,
|
|
5586
|
+
[tenantId]
|
|
5587
|
+
);
|
|
5588
|
+
return rows.map((r) => this.mapRowToProject(r));
|
|
5589
|
+
}
|
|
5590
|
+
/** Get a single eval project by ID for a tenant */
|
|
5591
|
+
async getProjectById(tenantId, id) {
|
|
5592
|
+
await this.ensureInitialized();
|
|
5593
|
+
const { rows } = await this.pool.query(
|
|
5594
|
+
`SELECT id, tenant_id, name, description, version,
|
|
5595
|
+
judge_model_config, target_server_config, concurrency,
|
|
5596
|
+
report_config, created_at, updated_at
|
|
5597
|
+
FROM lattice_eval_projects
|
|
5598
|
+
WHERE id = $1 AND tenant_id = $2`,
|
|
5599
|
+
[id, tenantId]
|
|
5600
|
+
);
|
|
5601
|
+
return rows.length ? this.mapRowToProject(rows[0]) : null;
|
|
5602
|
+
}
|
|
5603
|
+
/** Create a new eval project */
|
|
5604
|
+
async createProject(tenantId, id, data) {
|
|
5605
|
+
await this.ensureInitialized();
|
|
5606
|
+
const actualId = id || (0, import_uuid.v4)();
|
|
5607
|
+
const { rows } = await this.pool.query(
|
|
5608
|
+
`INSERT INTO lattice_eval_projects
|
|
5609
|
+
(id, tenant_id, name, description, version, judge_model_config, target_server_config, concurrency, report_config)
|
|
5610
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
|
|
5611
|
+
RETURNING id, tenant_id, name, description, version,
|
|
5612
|
+
judge_model_config, target_server_config, concurrency,
|
|
5613
|
+
report_config, created_at, updated_at`,
|
|
5614
|
+
[
|
|
5615
|
+
actualId,
|
|
5616
|
+
tenantId,
|
|
5617
|
+
data.name,
|
|
5618
|
+
data.description || null,
|
|
5619
|
+
data.version || null,
|
|
5620
|
+
JSON.stringify(data.judgeModelConfig),
|
|
5621
|
+
JSON.stringify(data.targetServerConfig),
|
|
5622
|
+
data.concurrency ?? 3,
|
|
5623
|
+
data.reportConfig === void 0 ? null : JSON.stringify(data.reportConfig)
|
|
5624
|
+
]
|
|
5625
|
+
);
|
|
5626
|
+
return this.mapRowToProject(rows[0]);
|
|
5627
|
+
}
|
|
5628
|
+
/** Update an eval project */
|
|
5629
|
+
async updateProject(tenantId, id, updates) {
|
|
5630
|
+
await this.ensureInitialized();
|
|
5631
|
+
const set = [];
|
|
5632
|
+
const vals = [];
|
|
5633
|
+
let i = 1;
|
|
5634
|
+
if (updates.name !== void 0) {
|
|
5635
|
+
set.push(`name = $${i++}`);
|
|
5636
|
+
vals.push(updates.name);
|
|
5637
|
+
}
|
|
5638
|
+
if (updates.description !== void 0) {
|
|
5639
|
+
set.push(`description = $${i++}`);
|
|
5640
|
+
vals.push(updates.description);
|
|
5641
|
+
}
|
|
5642
|
+
if (updates.version !== void 0) {
|
|
5643
|
+
set.push(`version = $${i++}`);
|
|
5644
|
+
vals.push(updates.version);
|
|
5645
|
+
}
|
|
5646
|
+
if (updates.judgeModelConfig !== void 0) {
|
|
5647
|
+
set.push(`judge_model_config = $${i++}`);
|
|
5648
|
+
vals.push(JSON.stringify(updates.judgeModelConfig));
|
|
5649
|
+
}
|
|
5650
|
+
if (updates.targetServerConfig !== void 0) {
|
|
5651
|
+
set.push(`target_server_config = $${i++}`);
|
|
5652
|
+
vals.push(JSON.stringify(updates.targetServerConfig));
|
|
5653
|
+
}
|
|
5654
|
+
if (updates.concurrency !== void 0) {
|
|
5655
|
+
set.push(`concurrency = $${i++}`);
|
|
5656
|
+
vals.push(updates.concurrency);
|
|
5657
|
+
}
|
|
5658
|
+
if (updates.reportConfig !== void 0) {
|
|
5659
|
+
set.push(`report_config = $${i++}`);
|
|
5660
|
+
vals.push(JSON.stringify(updates.reportConfig));
|
|
5661
|
+
}
|
|
5662
|
+
if (set.length === 0) return this.getProjectById(tenantId, id);
|
|
5663
|
+
set.push(`updated_at = NOW()`);
|
|
5664
|
+
vals.push(id, tenantId);
|
|
5665
|
+
const { rows } = await this.pool.query(
|
|
5666
|
+
`UPDATE lattice_eval_projects SET ${set.join(", ")}
|
|
5667
|
+
WHERE id = $${i} AND tenant_id = $${i + 1}
|
|
5668
|
+
RETURNING id, tenant_id, name, description, version,
|
|
5669
|
+
judge_model_config, target_server_config, concurrency,
|
|
5670
|
+
report_config, created_at, updated_at`,
|
|
5671
|
+
vals
|
|
5672
|
+
);
|
|
5673
|
+
return rows.length ? this.mapRowToProject(rows[0]) : null;
|
|
5674
|
+
}
|
|
5675
|
+
/** Delete an eval project */
|
|
5676
|
+
async deleteProject(tenantId, id) {
|
|
5677
|
+
await this.ensureInitialized();
|
|
5678
|
+
const result = await this.pool.query(
|
|
5679
|
+
`DELETE FROM lattice_eval_projects WHERE id = $1 AND tenant_id = $2`,
|
|
5680
|
+
[id, tenantId]
|
|
5681
|
+
);
|
|
5682
|
+
return (result.rowCount ?? 0) > 0;
|
|
5683
|
+
}
|
|
5684
|
+
// ---------------------------------------------------------------------------
|
|
5685
|
+
// Suites
|
|
5686
|
+
// ---------------------------------------------------------------------------
|
|
5687
|
+
/** Get all suites in a project with case counts */
|
|
5688
|
+
async getSuitesByProject(tenantId, projectId) {
|
|
5689
|
+
await this.ensureInitialized();
|
|
5690
|
+
const { rows } = await this.pool.query(
|
|
5691
|
+
`SELECT s.id, s.tenant_id, s.project_id, s.name, s.created_at, s.updated_at,
|
|
5692
|
+
COUNT(c.id)::int AS case_count
|
|
5693
|
+
FROM lattice_eval_suites s
|
|
5694
|
+
LEFT JOIN lattice_eval_cases c ON c.suite_id = s.id
|
|
5695
|
+
WHERE s.tenant_id = $1 AND s.project_id = $2
|
|
5696
|
+
GROUP BY s.id
|
|
5697
|
+
ORDER BY s.created_at DESC`,
|
|
5698
|
+
[tenantId, projectId]
|
|
5699
|
+
);
|
|
5700
|
+
return rows.map((r) => this.mapRowToSuite(r));
|
|
5701
|
+
}
|
|
5702
|
+
/** Get a single suite by ID with case count */
|
|
5703
|
+
async getSuiteById(tenantId, id) {
|
|
5704
|
+
await this.ensureInitialized();
|
|
5705
|
+
const { rows } = await this.pool.query(
|
|
5706
|
+
`SELECT s.id, s.tenant_id, s.project_id, s.name, s.created_at, s.updated_at,
|
|
5707
|
+
COUNT(c.id)::int AS case_count
|
|
5708
|
+
FROM lattice_eval_suites s
|
|
5709
|
+
LEFT JOIN lattice_eval_cases c ON c.suite_id = s.id
|
|
5710
|
+
WHERE s.tenant_id = $1 AND s.id = $2
|
|
5711
|
+
GROUP BY s.id`,
|
|
5712
|
+
[tenantId, id]
|
|
5713
|
+
);
|
|
5714
|
+
return rows.length ? this.mapRowToSuite(rows[0]) : null;
|
|
5715
|
+
}
|
|
5716
|
+
/** Create a new eval suite */
|
|
5717
|
+
async createSuite(tenantId, projectId, id, data) {
|
|
5718
|
+
await this.ensureInitialized();
|
|
5719
|
+
const actualId = id || (0, import_uuid.v4)();
|
|
5720
|
+
const { rows } = await this.pool.query(
|
|
5721
|
+
`INSERT INTO lattice_eval_suites (id, tenant_id, project_id, name)
|
|
5722
|
+
VALUES ($1, $2, $3, $4)
|
|
5723
|
+
RETURNING id, tenant_id, project_id, name, created_at, updated_at`,
|
|
5724
|
+
[actualId, tenantId, projectId, data.name]
|
|
5725
|
+
);
|
|
5726
|
+
return this.mapRowToSuite(rows[0]);
|
|
5727
|
+
}
|
|
5728
|
+
/** Update a suite's name */
|
|
5729
|
+
async updateSuite(tenantId, id, updates) {
|
|
5730
|
+
await this.ensureInitialized();
|
|
5731
|
+
const set = [];
|
|
5732
|
+
const vals = [];
|
|
5733
|
+
let i = 1;
|
|
5734
|
+
if (updates.name !== void 0) {
|
|
5735
|
+
set.push(`name = $${i++}`);
|
|
5736
|
+
vals.push(updates.name);
|
|
5737
|
+
}
|
|
5738
|
+
if (set.length === 0) return this.getSuiteById(tenantId, id);
|
|
5739
|
+
set.push(`updated_at = NOW()`);
|
|
5740
|
+
vals.push(id, tenantId);
|
|
5741
|
+
const { rows } = await this.pool.query(
|
|
5742
|
+
`UPDATE lattice_eval_suites SET ${set.join(", ")}
|
|
5743
|
+
WHERE id = $${i} AND tenant_id = $${i + 1}
|
|
5744
|
+
RETURNING id, tenant_id, project_id, name, created_at, updated_at`,
|
|
5745
|
+
vals
|
|
5746
|
+
);
|
|
5747
|
+
return rows.length ? this.mapRowToSuite(rows[0]) : null;
|
|
5748
|
+
}
|
|
5749
|
+
/** Delete a suite */
|
|
5750
|
+
async deleteSuite(tenantId, id) {
|
|
5751
|
+
await this.ensureInitialized();
|
|
5752
|
+
const result = await this.pool.query(
|
|
5753
|
+
`DELETE FROM lattice_eval_suites WHERE id = $1 AND tenant_id = $2`,
|
|
5754
|
+
[id, tenantId]
|
|
5755
|
+
);
|
|
5756
|
+
return (result.rowCount ?? 0) > 0;
|
|
5757
|
+
}
|
|
5758
|
+
// ---------------------------------------------------------------------------
|
|
5759
|
+
// Cases
|
|
5760
|
+
// ---------------------------------------------------------------------------
|
|
5761
|
+
/** Get all test cases in a suite */
|
|
5762
|
+
async getCasesBySuite(tenantId, suiteId) {
|
|
5763
|
+
await this.ensureInitialized();
|
|
5764
|
+
const { rows } = await this.pool.query(
|
|
5765
|
+
`SELECT id, tenant_id, suite_id,
|
|
5766
|
+
input_message, input_files, steps,
|
|
5767
|
+
output_type, content_assertion, rubrics,
|
|
5768
|
+
created_at, updated_at
|
|
5769
|
+
FROM lattice_eval_cases
|
|
5770
|
+
WHERE tenant_id = $1 AND suite_id = $2
|
|
5771
|
+
ORDER BY created_at`,
|
|
5772
|
+
[tenantId, suiteId]
|
|
5773
|
+
);
|
|
5774
|
+
return rows.map((r) => this.mapRowToCase(r));
|
|
5775
|
+
}
|
|
5776
|
+
/** Get a single test case by ID */
|
|
5777
|
+
async getCaseById(tenantId, id) {
|
|
5778
|
+
await this.ensureInitialized();
|
|
5779
|
+
const { rows } = await this.pool.query(
|
|
5780
|
+
`SELECT id, tenant_id, suite_id,
|
|
5781
|
+
input_message, input_files, steps,
|
|
5782
|
+
output_type, content_assertion, rubrics,
|
|
5783
|
+
created_at, updated_at
|
|
5784
|
+
FROM lattice_eval_cases
|
|
5785
|
+
WHERE id = $1 AND tenant_id = $2`,
|
|
5786
|
+
[id, tenantId]
|
|
5787
|
+
);
|
|
5788
|
+
return rows.length ? this.mapRowToCase(rows[0]) : null;
|
|
5789
|
+
}
|
|
5790
|
+
/** Create a new test case */
|
|
5791
|
+
async createCase(tenantId, suiteId, id, data) {
|
|
5792
|
+
await this.ensureInitialized();
|
|
5793
|
+
const actualId = id || (0, import_uuid.v4)();
|
|
5794
|
+
const { rows } = await this.pool.query(
|
|
5795
|
+
`INSERT INTO lattice_eval_cases
|
|
5796
|
+
(id, tenant_id, suite_id, input_message, input_files, steps, output_type, content_assertion, rubrics)
|
|
5797
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
|
|
5798
|
+
RETURNING id, tenant_id, suite_id,
|
|
5799
|
+
input_message, input_files, steps,
|
|
5800
|
+
output_type, content_assertion, rubrics,
|
|
5801
|
+
created_at, updated_at`,
|
|
5802
|
+
[
|
|
5803
|
+
actualId,
|
|
5804
|
+
tenantId,
|
|
5805
|
+
suiteId,
|
|
5806
|
+
data.inputMessage,
|
|
5807
|
+
JSON.stringify(data.inputFiles || {}),
|
|
5808
|
+
JSON.stringify(data.steps),
|
|
5809
|
+
data.outputType,
|
|
5810
|
+
data.contentAssertion || null,
|
|
5811
|
+
JSON.stringify(data.rubrics || [])
|
|
5812
|
+
]
|
|
5813
|
+
);
|
|
5814
|
+
return this.mapRowToCase(rows[0]);
|
|
5815
|
+
}
|
|
5816
|
+
/** Update a test case */
|
|
5817
|
+
async updateCase(tenantId, id, updates) {
|
|
5818
|
+
await this.ensureInitialized();
|
|
5819
|
+
const set = [];
|
|
5820
|
+
const vals = [];
|
|
5821
|
+
let i = 1;
|
|
5822
|
+
if (updates.inputMessage !== void 0) {
|
|
5823
|
+
set.push(`input_message = $${i++}`);
|
|
5824
|
+
vals.push(updates.inputMessage);
|
|
5825
|
+
}
|
|
5826
|
+
if (updates.inputFiles !== void 0) {
|
|
5827
|
+
set.push(`input_files = $${i++}`);
|
|
5828
|
+
vals.push(JSON.stringify(updates.inputFiles));
|
|
5829
|
+
}
|
|
5830
|
+
if (updates.steps !== void 0) {
|
|
5831
|
+
set.push(`steps = $${i++}`);
|
|
5832
|
+
vals.push(JSON.stringify(updates.steps));
|
|
5833
|
+
}
|
|
5834
|
+
if (updates.outputType !== void 0) {
|
|
5835
|
+
set.push(`output_type = $${i++}`);
|
|
5836
|
+
vals.push(updates.outputType);
|
|
5837
|
+
}
|
|
5838
|
+
if (updates.contentAssertion !== void 0) {
|
|
5839
|
+
set.push(`content_assertion = $${i++}`);
|
|
5840
|
+
vals.push(updates.contentAssertion);
|
|
5841
|
+
}
|
|
5842
|
+
if (updates.rubrics !== void 0) {
|
|
5843
|
+
set.push(`rubrics = $${i++}`);
|
|
5844
|
+
vals.push(JSON.stringify(updates.rubrics));
|
|
5845
|
+
}
|
|
5846
|
+
if (set.length === 0) return this.getCaseById(tenantId, id);
|
|
5847
|
+
set.push(`updated_at = NOW()`);
|
|
5848
|
+
vals.push(id, tenantId);
|
|
5849
|
+
const { rows } = await this.pool.query(
|
|
5850
|
+
`UPDATE lattice_eval_cases SET ${set.join(", ")}
|
|
5851
|
+
WHERE id = $${i} AND tenant_id = $${i + 1}
|
|
5852
|
+
RETURNING id, tenant_id, suite_id,
|
|
5853
|
+
input_message, input_files, steps,
|
|
5854
|
+
output_type, content_assertion, rubrics,
|
|
5855
|
+
created_at, updated_at`,
|
|
5856
|
+
vals
|
|
5857
|
+
);
|
|
5858
|
+
return rows.length ? this.mapRowToCase(rows[0]) : null;
|
|
5859
|
+
}
|
|
5860
|
+
/** Delete a test case */
|
|
5861
|
+
async deleteCase(tenantId, id) {
|
|
5862
|
+
await this.ensureInitialized();
|
|
5863
|
+
const result = await this.pool.query(
|
|
5864
|
+
`DELETE FROM lattice_eval_cases WHERE id = $1 AND tenant_id = $2`,
|
|
5865
|
+
[id, tenantId]
|
|
5866
|
+
);
|
|
5867
|
+
return (result.rowCount ?? 0) > 0;
|
|
5868
|
+
}
|
|
5869
|
+
// ---------------------------------------------------------------------------
|
|
5870
|
+
// Runs
|
|
5871
|
+
// ---------------------------------------------------------------------------
|
|
5872
|
+
/** Get all runs for a tenant, optionally filtered by project or status */
|
|
5873
|
+
async getRunsByTenant(tenantId, opts) {
|
|
5874
|
+
await this.ensureInitialized();
|
|
5875
|
+
const conditions = ["tenant_id = $1"];
|
|
5876
|
+
const vals = [tenantId];
|
|
5877
|
+
let i = 2;
|
|
5878
|
+
if (opts?.projectId) {
|
|
5879
|
+
conditions.push(`project_id = $${i++}`);
|
|
5880
|
+
vals.push(opts.projectId);
|
|
5881
|
+
}
|
|
5882
|
+
if (opts?.status) {
|
|
5883
|
+
conditions.push(`status = $${i++}`);
|
|
5884
|
+
vals.push(opts.status);
|
|
5885
|
+
}
|
|
5886
|
+
const { rows } = await this.pool.query(
|
|
5887
|
+
`SELECT id, project_id, tenant_id,
|
|
5888
|
+
status, concurrency, total_cases,
|
|
5889
|
+
passed_cases, failed_cases, avg_score,
|
|
5890
|
+
error, created_at, started_at, completed_at
|
|
5891
|
+
FROM lattice_eval_runs
|
|
5892
|
+
WHERE ${conditions.join(" AND ")}
|
|
5893
|
+
ORDER BY created_at DESC`,
|
|
5894
|
+
vals
|
|
5895
|
+
);
|
|
5896
|
+
return rows.map((r) => this.mapRowToRun(r));
|
|
5897
|
+
}
|
|
5898
|
+
/** Get a single run by ID */
|
|
5899
|
+
async getRunById(tenantId, id) {
|
|
5900
|
+
await this.ensureInitialized();
|
|
5901
|
+
const { rows } = await this.pool.query(
|
|
5902
|
+
`SELECT id, project_id, tenant_id,
|
|
5903
|
+
status, concurrency, total_cases,
|
|
5904
|
+
passed_cases, failed_cases, avg_score,
|
|
5905
|
+
error, created_at, started_at, completed_at
|
|
5906
|
+
FROM lattice_eval_runs
|
|
5907
|
+
WHERE id = $1 AND tenant_id = $2`,
|
|
5908
|
+
[id, tenantId]
|
|
5909
|
+
);
|
|
5910
|
+
return rows.length ? this.mapRowToRun(rows[0]) : null;
|
|
5911
|
+
}
|
|
5912
|
+
/** Create a new eval run */
|
|
5913
|
+
async createRun(tenantId, projectId, id, data) {
|
|
5914
|
+
await this.ensureInitialized();
|
|
5915
|
+
const actualId = id || (0, import_uuid.v4)();
|
|
5916
|
+
const { rows } = await this.pool.query(
|
|
5917
|
+
`INSERT INTO lattice_eval_runs
|
|
5918
|
+
(id, project_id, tenant_id, status, concurrency, total_cases, passed_cases, failed_cases, avg_score, started_at)
|
|
5919
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
|
|
5920
|
+
RETURNING id, project_id, tenant_id,
|
|
5921
|
+
status, concurrency, total_cases,
|
|
5922
|
+
passed_cases, failed_cases, avg_score,
|
|
5923
|
+
error, created_at, started_at, completed_at`,
|
|
5924
|
+
[
|
|
5925
|
+
actualId,
|
|
5926
|
+
projectId,
|
|
5927
|
+
tenantId,
|
|
5928
|
+
"running",
|
|
5929
|
+
data.concurrency,
|
|
5930
|
+
data.totalCases,
|
|
5931
|
+
0,
|
|
5932
|
+
0,
|
|
5933
|
+
0,
|
|
5934
|
+
/* @__PURE__ */ new Date()
|
|
5935
|
+
]
|
|
5936
|
+
);
|
|
5937
|
+
return this.mapRowToRun(rows[0]);
|
|
5938
|
+
}
|
|
5939
|
+
/** Update a run's status and aggregate fields */
|
|
5940
|
+
async updateRunStatus(tenantId, id, updates) {
|
|
5941
|
+
await this.ensureInitialized();
|
|
5942
|
+
const set = [];
|
|
5943
|
+
const vals = [];
|
|
5944
|
+
let i = 1;
|
|
5945
|
+
if (updates.status !== void 0) {
|
|
5946
|
+
set.push(`status = $${i++}`);
|
|
5947
|
+
vals.push(updates.status);
|
|
5948
|
+
}
|
|
5949
|
+
if (updates.passedCases !== void 0) {
|
|
5950
|
+
set.push(`passed_cases = $${i++}`);
|
|
5951
|
+
vals.push(updates.passedCases);
|
|
5952
|
+
}
|
|
5953
|
+
if (updates.failedCases !== void 0) {
|
|
5954
|
+
set.push(`failed_cases = $${i++}`);
|
|
5955
|
+
vals.push(updates.failedCases);
|
|
5956
|
+
}
|
|
5957
|
+
if (updates.avgScore !== void 0) {
|
|
5958
|
+
set.push(`avg_score = $${i++}`);
|
|
5959
|
+
vals.push(updates.avgScore);
|
|
5960
|
+
}
|
|
5961
|
+
if (updates.completedAt !== void 0) {
|
|
5962
|
+
set.push(`completed_at = $${i++}`);
|
|
5963
|
+
vals.push(updates.completedAt);
|
|
5964
|
+
}
|
|
5965
|
+
if (updates.error !== void 0) {
|
|
5966
|
+
set.push(`error = $${i++}`);
|
|
5967
|
+
vals.push(updates.error);
|
|
5968
|
+
}
|
|
5969
|
+
if (set.length === 0) return this.getRunById(tenantId, id);
|
|
5970
|
+
vals.push(id, tenantId);
|
|
5971
|
+
const { rows } = await this.pool.query(
|
|
5972
|
+
`UPDATE lattice_eval_runs SET ${set.join(", ")}
|
|
5973
|
+
WHERE id = $${i} AND tenant_id = $${i + 1}
|
|
5974
|
+
RETURNING id, project_id, tenant_id,
|
|
5975
|
+
status, concurrency, total_cases,
|
|
5976
|
+
passed_cases, failed_cases, avg_score,
|
|
5977
|
+
error, created_at, started_at, completed_at`,
|
|
5978
|
+
vals
|
|
5979
|
+
);
|
|
5980
|
+
return rows.length ? this.mapRowToRun(rows[0]) : null;
|
|
5981
|
+
}
|
|
5982
|
+
/** Delete a run and its results */
|
|
5983
|
+
async deleteRun(tenantId, id) {
|
|
5984
|
+
await this.ensureInitialized();
|
|
5985
|
+
await this.pool.query(`DELETE FROM lattice_eval_run_results WHERE run_id = $1 AND tenant_id = $2`, [id, tenantId]);
|
|
5986
|
+
const { rowCount } = await this.pool.query(
|
|
5987
|
+
`DELETE FROM lattice_eval_runs WHERE id = $1 AND tenant_id = $2`,
|
|
5988
|
+
[id, tenantId]
|
|
5989
|
+
);
|
|
5990
|
+
return (rowCount ?? 0) > 0;
|
|
5991
|
+
}
|
|
5992
|
+
// ---------------------------------------------------------------------------
|
|
5993
|
+
// Run Results
|
|
5994
|
+
// ---------------------------------------------------------------------------
|
|
5995
|
+
/** Get all results belonging to a run */
|
|
5996
|
+
async getResultsByRun(tenantId, runId) {
|
|
5997
|
+
await this.ensureInitialized();
|
|
5998
|
+
const { rows } = await this.pool.query(
|
|
5999
|
+
`SELECT rr.id, rr.run_id, rr.suite_name, rr.case_id,
|
|
6000
|
+
rr.pass, rr.score, rr.summary, rr.dimension_results,
|
|
6001
|
+
rr.duration_ms, rr.messages, rr.logs, rr.error, rr.created_at
|
|
6002
|
+
FROM lattice_eval_run_results rr
|
|
6003
|
+
INNER JOIN lattice_eval_runs r ON r.id = rr.run_id
|
|
6004
|
+
WHERE r.tenant_id = $1 AND rr.run_id = $2
|
|
6005
|
+
ORDER BY rr.created_at`,
|
|
6006
|
+
[tenantId, runId]
|
|
6007
|
+
);
|
|
6008
|
+
return rows.map((r) => this.mapRowToRunResult(r));
|
|
6009
|
+
}
|
|
6010
|
+
/** Create a result for a case within a run */
|
|
6011
|
+
async createRunResult(tenantId, runId, id, data) {
|
|
6012
|
+
await this.ensureInitialized();
|
|
6013
|
+
const actualId = id || (0, import_uuid.v4)();
|
|
6014
|
+
const { rows } = await this.pool.query(
|
|
6015
|
+
`INSERT INTO lattice_eval_run_results
|
|
6016
|
+
(id, run_id, suite_name, case_id, pass, score, summary, dimension_results, duration_ms, messages, logs, error)
|
|
6017
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12)
|
|
6018
|
+
RETURNING id, run_id, suite_name, case_id,
|
|
6019
|
+
pass, score, summary, dimension_results,
|
|
6020
|
+
duration_ms, messages, logs, error, created_at`,
|
|
6021
|
+
[
|
|
6022
|
+
actualId,
|
|
6023
|
+
runId,
|
|
6024
|
+
data.suiteName,
|
|
6025
|
+
data.caseId || null,
|
|
6026
|
+
data.pass,
|
|
6027
|
+
data.score,
|
|
6028
|
+
data.summary || null,
|
|
6029
|
+
JSON.stringify(data.dimensionResults || []),
|
|
6030
|
+
data.durationMs ?? null,
|
|
6031
|
+
JSON.stringify(data.messages || []),
|
|
6032
|
+
JSON.stringify(data.logs || []),
|
|
6033
|
+
data.error || null
|
|
6034
|
+
]
|
|
6035
|
+
);
|
|
6036
|
+
return this.mapRowToRunResult(rows[0]);
|
|
6037
|
+
}
|
|
6038
|
+
/** Update a run result with tenant isolation via the parent run */
|
|
6039
|
+
async updateRunResult(tenantId, id, updates) {
|
|
6040
|
+
await this.ensureInitialized();
|
|
6041
|
+
if (updates.runId !== void 0) {
|
|
6042
|
+
throw new Error("runId cannot be updated on an existing result");
|
|
6043
|
+
}
|
|
6044
|
+
const set = [];
|
|
6045
|
+
const vals = [];
|
|
6046
|
+
let i = 1;
|
|
6047
|
+
if (updates.suiteName !== void 0) {
|
|
6048
|
+
set.push(`suite_name = $${i++}`);
|
|
6049
|
+
vals.push(updates.suiteName);
|
|
6050
|
+
}
|
|
6051
|
+
if (updates.caseId !== void 0) {
|
|
6052
|
+
set.push(`case_id = $${i++}`);
|
|
6053
|
+
vals.push(updates.caseId);
|
|
6054
|
+
}
|
|
6055
|
+
if (updates.pass !== void 0) {
|
|
6056
|
+
set.push(`pass = $${i++}`);
|
|
6057
|
+
vals.push(updates.pass);
|
|
6058
|
+
}
|
|
6059
|
+
if (updates.score !== void 0) {
|
|
6060
|
+
set.push(`score = $${i++}`);
|
|
6061
|
+
vals.push(updates.score);
|
|
6062
|
+
}
|
|
6063
|
+
if (updates.summary !== void 0) {
|
|
6064
|
+
set.push(`summary = $${i++}`);
|
|
6065
|
+
vals.push(updates.summary);
|
|
6066
|
+
}
|
|
6067
|
+
if (updates.dimensionResults !== void 0) {
|
|
6068
|
+
set.push(`dimension_results = $${i++}`);
|
|
6069
|
+
vals.push(JSON.stringify(updates.dimensionResults));
|
|
6070
|
+
}
|
|
6071
|
+
if (updates.durationMs !== void 0) {
|
|
6072
|
+
set.push(`duration_ms = $${i++}`);
|
|
6073
|
+
vals.push(updates.durationMs);
|
|
6074
|
+
}
|
|
6075
|
+
if (updates.messages !== void 0) {
|
|
6076
|
+
set.push(`messages = $${i++}`);
|
|
6077
|
+
vals.push(JSON.stringify(updates.messages));
|
|
6078
|
+
}
|
|
6079
|
+
if (updates.logs !== void 0) {
|
|
6080
|
+
set.push(`logs = $${i++}`);
|
|
6081
|
+
vals.push(JSON.stringify(updates.logs));
|
|
6082
|
+
}
|
|
6083
|
+
if (updates.error !== void 0) {
|
|
6084
|
+
set.push(`error = $${i++}`);
|
|
6085
|
+
vals.push(updates.error);
|
|
6086
|
+
}
|
|
6087
|
+
if (set.length === 0) return this.getRunResultById(tenantId, id);
|
|
6088
|
+
vals.push(id, tenantId);
|
|
6089
|
+
const { rows } = await this.pool.query(
|
|
6090
|
+
`UPDATE lattice_eval_run_results SET ${set.join(", ")}
|
|
6091
|
+
WHERE id = $${i}
|
|
6092
|
+
AND run_id IN (SELECT id FROM lattice_eval_runs WHERE tenant_id = $${i + 1})
|
|
6093
|
+
RETURNING id, run_id, suite_name, case_id,
|
|
6094
|
+
pass, score, summary, dimension_results,
|
|
6095
|
+
duration_ms, messages, logs, error, created_at`,
|
|
6096
|
+
vals
|
|
6097
|
+
);
|
|
6098
|
+
return rows.length ? this.mapRowToRunResult(rows[0]) : null;
|
|
6099
|
+
}
|
|
6100
|
+
/** Get a single run result by ID with tenant isolation */
|
|
6101
|
+
async getRunResultById(tenantId, id) {
|
|
6102
|
+
await this.ensureInitialized();
|
|
6103
|
+
const { rows } = await this.pool.query(
|
|
6104
|
+
`SELECT rr.id, rr.run_id, rr.suite_name, rr.case_id,
|
|
6105
|
+
rr.pass, rr.score, rr.summary, rr.dimension_results,
|
|
6106
|
+
rr.duration_ms, rr.messages, rr.logs, rr.error, rr.created_at
|
|
6107
|
+
FROM lattice_eval_run_results rr
|
|
6108
|
+
INNER JOIN lattice_eval_runs r ON r.id = rr.run_id
|
|
6109
|
+
WHERE rr.id = $1 AND r.tenant_id = $2`,
|
|
6110
|
+
[id, tenantId]
|
|
6111
|
+
);
|
|
6112
|
+
return rows.length ? this.mapRowToRunResult(rows[0]) : null;
|
|
6113
|
+
}
|
|
6114
|
+
// ---------------------------------------------------------------------------
|
|
6115
|
+
// Reports
|
|
6116
|
+
// ---------------------------------------------------------------------------
|
|
6117
|
+
/** Aggregate report for a project including all runs */
|
|
6118
|
+
async getProjectReport(tenantId, projectId) {
|
|
6119
|
+
await this.ensureInitialized();
|
|
6120
|
+
const projectRows = await this.pool.query(
|
|
6121
|
+
`SELECT id, tenant_id, name, description, version,
|
|
6122
|
+
judge_model_config, target_server_config, concurrency,
|
|
6123
|
+
report_config, created_at, updated_at
|
|
6124
|
+
FROM lattice_eval_projects
|
|
6125
|
+
WHERE id = $1 AND tenant_id = $2`,
|
|
6126
|
+
[projectId, tenantId]
|
|
6127
|
+
);
|
|
6128
|
+
if (projectRows.rows.length === 0) return null;
|
|
6129
|
+
const project = this.mapRowToProject(projectRows.rows[0]);
|
|
6130
|
+
const runs = await this.getRunsByTenant(tenantId, { projectId });
|
|
6131
|
+
const totalRuns = runs.length;
|
|
6132
|
+
const latestPassRate = runs.length > 0 ? runs[0].totalCases > 0 ? runs[0].passedCases / runs[0].totalCases : 0 : 0;
|
|
6133
|
+
const avgScore = runs.length > 0 ? runs.reduce((sum, r) => sum + r.avgScore, 0) / runs.length : 0;
|
|
6134
|
+
return {
|
|
6135
|
+
projectId: project.id,
|
|
6136
|
+
projectName: project.name,
|
|
6137
|
+
totalRuns,
|
|
6138
|
+
latestPassRate,
|
|
6139
|
+
avgScore,
|
|
6140
|
+
runs
|
|
6141
|
+
};
|
|
6142
|
+
}
|
|
6143
|
+
};
|
|
5216
6144
|
// Annotate the CommonJS export names for ESM import in node:
|
|
5217
6145
|
0 && (module.exports = {
|
|
5218
6146
|
ChannelIdentityMappingStore,
|
|
@@ -5221,6 +6149,7 @@ var PostgreSQLWorkflowTrackingStore = class {
|
|
|
5221
6149
|
PostgreSQLAssistantStore,
|
|
5222
6150
|
PostgreSQLChannelInstallationStore,
|
|
5223
6151
|
PostgreSQLDatabaseConfigStore,
|
|
6152
|
+
PostgreSQLEvalStore,
|
|
5224
6153
|
PostgreSQLMcpServerConfigStore,
|
|
5225
6154
|
PostgreSQLMetricsServerConfigStore,
|
|
5226
6155
|
PostgreSQLProjectStore,
|
|
@@ -5244,6 +6173,11 @@ var PostgreSQLWorkflowTrackingStore = class {
|
|
|
5244
6173
|
createChannelIdentityMappingTables,
|
|
5245
6174
|
createChannelInstallationsTable,
|
|
5246
6175
|
createDatabaseConfigsTable,
|
|
6176
|
+
createEvalCasesTable,
|
|
6177
|
+
createEvalProjectsTable,
|
|
6178
|
+
createEvalRunResultsTable,
|
|
6179
|
+
createEvalRunsTable,
|
|
6180
|
+
createEvalSuitesTable,
|
|
5247
6181
|
createMcpServerConfigsTable,
|
|
5248
6182
|
createMetricsConfigsTable,
|
|
5249
6183
|
createProjectsTable,
|
|
@@ -5255,6 +6189,7 @@ var PostgreSQLWorkflowTrackingStore = class {
|
|
|
5255
6189
|
createUsersTable,
|
|
5256
6190
|
createWorkflowTrackingTables,
|
|
5257
6191
|
createWorkspacesTable,
|
|
6192
|
+
evalMigrations,
|
|
5258
6193
|
getThreadMessageQueueStore
|
|
5259
6194
|
});
|
|
5260
6195
|
//# sourceMappingURL=index.js.map
|