@axlsdk/axl 0.11.6 → 0.13.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/README.md +1 -1
- package/dist/index.cjs +278 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +64 -3
- package/dist/index.d.ts +64 -3
- package/dist/index.js +278 -14
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2520,6 +2520,11 @@ ${JSON.stringify(jsonSchema, null, 2)}`;
|
|
|
2520
2520
|
model: modelUri,
|
|
2521
2521
|
promptVersion: agent2._config.version,
|
|
2522
2522
|
cost: response.cost,
|
|
2523
|
+
tokens: response.usage ? {
|
|
2524
|
+
input: response.usage.prompt_tokens,
|
|
2525
|
+
output: response.usage.completion_tokens,
|
|
2526
|
+
reasoning: response.usage.reasoning_tokens
|
|
2527
|
+
} : void 0,
|
|
2523
2528
|
duration: Date.now() - startTime,
|
|
2524
2529
|
data: { prompt, response: response.content }
|
|
2525
2530
|
});
|
|
@@ -3907,6 +3912,8 @@ var MemoryStore = class {
|
|
|
3907
3912
|
decisions = /* @__PURE__ */ new Map();
|
|
3908
3913
|
executionStates = /* @__PURE__ */ new Map();
|
|
3909
3914
|
memories = /* @__PURE__ */ new Map();
|
|
3915
|
+
executionHistory = /* @__PURE__ */ new Map();
|
|
3916
|
+
evalHistory = /* @__PURE__ */ new Map();
|
|
3910
3917
|
constructor() {
|
|
3911
3918
|
this.loadPersistedState();
|
|
3912
3919
|
}
|
|
@@ -4003,11 +4010,36 @@ var MemoryStore = class {
|
|
|
4003
4010
|
async getAllMemory(scope) {
|
|
4004
4011
|
const scopeMap = this.memories.get(scope);
|
|
4005
4012
|
if (!scopeMap) return [];
|
|
4006
|
-
return Array.from(scopeMap.entries()).map(([key, value]) => ({
|
|
4013
|
+
return Array.from(scopeMap.entries()).map(([key, value]) => ({
|
|
4014
|
+
key,
|
|
4015
|
+
value: structuredClone(value)
|
|
4016
|
+
}));
|
|
4007
4017
|
}
|
|
4008
4018
|
async deleteMemory(scope, key) {
|
|
4009
4019
|
this.memories.get(scope)?.delete(key);
|
|
4010
4020
|
}
|
|
4021
|
+
// ── Execution History ──────────────────────────────────────────────
|
|
4022
|
+
async saveExecution(execution) {
|
|
4023
|
+
this.executionHistory.set(execution.executionId, structuredClone(execution));
|
|
4024
|
+
}
|
|
4025
|
+
async getExecution(executionId) {
|
|
4026
|
+
const exec = this.executionHistory.get(executionId);
|
|
4027
|
+
return exec ? structuredClone(exec) : null;
|
|
4028
|
+
}
|
|
4029
|
+
async listExecutions(limit) {
|
|
4030
|
+
const sorted = [...this.executionHistory.values()].sort((a, b) => b.startedAt - a.startedAt);
|
|
4031
|
+
const result = limit ? sorted.slice(0, limit) : sorted;
|
|
4032
|
+
return result.map((e) => structuredClone(e));
|
|
4033
|
+
}
|
|
4034
|
+
// ── Eval History ──────────────────────────────────────────────────
|
|
4035
|
+
async saveEvalResult(entry) {
|
|
4036
|
+
this.evalHistory.set(entry.id, structuredClone(entry));
|
|
4037
|
+
}
|
|
4038
|
+
async listEvalResults(limit) {
|
|
4039
|
+
const sorted = [...this.evalHistory.values()].sort((a, b) => b.timestamp - a.timestamp);
|
|
4040
|
+
const result = limit ? sorted.slice(0, limit) : sorted;
|
|
4041
|
+
return result.map((e) => structuredClone(e));
|
|
4042
|
+
}
|
|
4011
4043
|
// ── Sessions (Studio introspection) ─────────────────────────────────
|
|
4012
4044
|
async listSessions() {
|
|
4013
4045
|
return [...this.sessions.keys()];
|
|
@@ -4067,6 +4099,19 @@ function safeJsonParse(data) {
|
|
|
4067
4099
|
return null;
|
|
4068
4100
|
}
|
|
4069
4101
|
}
|
|
4102
|
+
function rowToExecutionInfo(row) {
|
|
4103
|
+
return {
|
|
4104
|
+
executionId: row.execution_id,
|
|
4105
|
+
workflow: row.workflow,
|
|
4106
|
+
status: row.status,
|
|
4107
|
+
totalCost: row.total_cost,
|
|
4108
|
+
startedAt: row.started_at,
|
|
4109
|
+
completedAt: row.completed_at ?? void 0,
|
|
4110
|
+
duration: row.duration,
|
|
4111
|
+
error: row.error ?? void 0,
|
|
4112
|
+
steps: safeJsonParse(row.steps) ?? []
|
|
4113
|
+
};
|
|
4114
|
+
}
|
|
4070
4115
|
var SQLiteStore = class {
|
|
4071
4116
|
db;
|
|
4072
4117
|
constructor(filePath) {
|
|
@@ -4127,6 +4172,28 @@ var SQLiteStore = class {
|
|
|
4127
4172
|
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
4128
4173
|
PRIMARY KEY (scope, key)
|
|
4129
4174
|
);
|
|
4175
|
+
|
|
4176
|
+
CREATE TABLE IF NOT EXISTS execution_history (
|
|
4177
|
+
execution_id TEXT PRIMARY KEY,
|
|
4178
|
+
workflow TEXT NOT NULL,
|
|
4179
|
+
status TEXT NOT NULL,
|
|
4180
|
+
total_cost REAL NOT NULL DEFAULT 0,
|
|
4181
|
+
started_at INTEGER NOT NULL,
|
|
4182
|
+
completed_at INTEGER,
|
|
4183
|
+
duration INTEGER NOT NULL DEFAULT 0,
|
|
4184
|
+
error TEXT,
|
|
4185
|
+
steps TEXT NOT NULL
|
|
4186
|
+
);
|
|
4187
|
+
|
|
4188
|
+
CREATE TABLE IF NOT EXISTS eval_history (
|
|
4189
|
+
id TEXT PRIMARY KEY,
|
|
4190
|
+
eval_name TEXT NOT NULL,
|
|
4191
|
+
timestamp INTEGER NOT NULL,
|
|
4192
|
+
data TEXT NOT NULL
|
|
4193
|
+
);
|
|
4194
|
+
|
|
4195
|
+
CREATE INDEX IF NOT EXISTS idx_exec_history_started ON execution_history (started_at DESC);
|
|
4196
|
+
CREATE INDEX IF NOT EXISTS idx_eval_history_timestamp ON eval_history (timestamp DESC);
|
|
4130
4197
|
`);
|
|
4131
4198
|
}
|
|
4132
4199
|
// ── Checkpoints ────────────────────────────────────────────────────────
|
|
@@ -4240,6 +4307,47 @@ var SQLiteStore = class {
|
|
|
4240
4307
|
const rows = stmt.all();
|
|
4241
4308
|
return rows.map((r) => r.execution_id);
|
|
4242
4309
|
}
|
|
4310
|
+
// ── Execution History ────────────────────────────────────────────────────
|
|
4311
|
+
async saveExecution(execution) {
|
|
4312
|
+
this.db.prepare(
|
|
4313
|
+
"INSERT OR REPLACE INTO execution_history (execution_id, workflow, status, total_cost, started_at, completed_at, duration, error, steps) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"
|
|
4314
|
+
).run(
|
|
4315
|
+
execution.executionId,
|
|
4316
|
+
execution.workflow,
|
|
4317
|
+
execution.status,
|
|
4318
|
+
execution.totalCost,
|
|
4319
|
+
execution.startedAt,
|
|
4320
|
+
execution.completedAt ?? null,
|
|
4321
|
+
execution.duration,
|
|
4322
|
+
execution.error ?? null,
|
|
4323
|
+
JSON.stringify(execution.steps)
|
|
4324
|
+
);
|
|
4325
|
+
}
|
|
4326
|
+
async getExecution(executionId) {
|
|
4327
|
+
const row = this.db.prepare("SELECT * FROM execution_history WHERE execution_id = ?").get(executionId);
|
|
4328
|
+
return row ? rowToExecutionInfo(row) : null;
|
|
4329
|
+
}
|
|
4330
|
+
async listExecutions(limit) {
|
|
4331
|
+
const sql = limit ? "SELECT * FROM execution_history ORDER BY started_at DESC LIMIT ?" : "SELECT * FROM execution_history ORDER BY started_at DESC";
|
|
4332
|
+
const rows = limit ? this.db.prepare(sql).all(limit) : this.db.prepare(sql).all();
|
|
4333
|
+
return rows.map(rowToExecutionInfo);
|
|
4334
|
+
}
|
|
4335
|
+
// ── Eval History ────────────────────────────────────────────────────────
|
|
4336
|
+
async saveEvalResult(entry) {
|
|
4337
|
+
this.db.prepare(
|
|
4338
|
+
"INSERT OR REPLACE INTO eval_history (id, eval_name, timestamp, data) VALUES (?, ?, ?, ?)"
|
|
4339
|
+
).run(entry.id, entry.eval, entry.timestamp, JSON.stringify(entry.data));
|
|
4340
|
+
}
|
|
4341
|
+
async listEvalResults(limit) {
|
|
4342
|
+
const sql = limit ? "SELECT * FROM eval_history ORDER BY timestamp DESC LIMIT ?" : "SELECT * FROM eval_history ORDER BY timestamp DESC";
|
|
4343
|
+
const rows = limit ? this.db.prepare(sql).all(limit) : this.db.prepare(sql).all();
|
|
4344
|
+
return rows.map((r) => ({
|
|
4345
|
+
id: r.id,
|
|
4346
|
+
eval: r.eval_name,
|
|
4347
|
+
timestamp: r.timestamp,
|
|
4348
|
+
data: safeJsonParse(r.data)
|
|
4349
|
+
}));
|
|
4350
|
+
}
|
|
4243
4351
|
// ── Sessions (Studio introspection) ────────────────────────────────────
|
|
4244
4352
|
async listSessions() {
|
|
4245
4353
|
const rows = this.db.prepare("SELECT session_id FROM sessions").all();
|
|
@@ -5124,6 +5232,10 @@ var AxlRuntime = class extends EventEmitter2 {
|
|
|
5124
5232
|
mcpManager;
|
|
5125
5233
|
memoryManager;
|
|
5126
5234
|
spanManager = new NoopSpanManager();
|
|
5235
|
+
historicalExecutions = /* @__PURE__ */ new Map();
|
|
5236
|
+
historicalExecutionsLoadPromise = null;
|
|
5237
|
+
evalHistory = [];
|
|
5238
|
+
evalHistoryLoadPromise = null;
|
|
5127
5239
|
constructor(config) {
|
|
5128
5240
|
super();
|
|
5129
5241
|
this.config = resolveConfig(config ?? {});
|
|
@@ -5168,6 +5280,20 @@ var AxlRuntime = class extends EventEmitter2 {
|
|
|
5168
5280
|
return new MemoryStore();
|
|
5169
5281
|
}
|
|
5170
5282
|
}
|
|
5283
|
+
/**
|
|
5284
|
+
* Persist a completed/failed execution to the state store (fire-and-forget)
|
|
5285
|
+
* and move it from the active executions map to the historical cache.
|
|
5286
|
+
*/
|
|
5287
|
+
persistExecution(execInfo) {
|
|
5288
|
+
const snapshot = structuredClone(execInfo);
|
|
5289
|
+
if (this.stateStore.saveExecution) {
|
|
5290
|
+
this.stateStore.saveExecution(snapshot).catch(() => {
|
|
5291
|
+
});
|
|
5292
|
+
}
|
|
5293
|
+
const id = execInfo.executionId;
|
|
5294
|
+
this.historicalExecutions.set(id, snapshot);
|
|
5295
|
+
this.executions.delete(id);
|
|
5296
|
+
}
|
|
5171
5297
|
/** Register a workflow with the runtime. */
|
|
5172
5298
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
5173
5299
|
register(workflow2) {
|
|
@@ -5246,6 +5372,7 @@ var AxlRuntime = class extends EventEmitter2 {
|
|
|
5246
5372
|
async runRegisteredEval(name) {
|
|
5247
5373
|
const entry = this.registeredEvals.get(name);
|
|
5248
5374
|
if (!entry) throw new Error(`Eval "${name}" is not registered`);
|
|
5375
|
+
let result;
|
|
5249
5376
|
if (entry.executeWorkflow) {
|
|
5250
5377
|
let runEvalFn;
|
|
5251
5378
|
try {
|
|
@@ -5257,20 +5384,50 @@ var AxlRuntime = class extends EventEmitter2 {
|
|
|
5257
5384
|
}
|
|
5258
5385
|
const originalExecuteFn = entry.executeWorkflow;
|
|
5259
5386
|
const wrappedExecuteFn = async (input, runtime) => {
|
|
5260
|
-
const { result, cost: trackedCost } = await this.trackCost(async () => {
|
|
5387
|
+
const { result: result2, cost: trackedCost } = await this.trackCost(async () => {
|
|
5261
5388
|
return originalExecuteFn(input, runtime);
|
|
5262
5389
|
});
|
|
5263
|
-
return { output:
|
|
5390
|
+
return { output: result2.output, cost: result2.cost ?? trackedCost };
|
|
5264
5391
|
};
|
|
5265
|
-
|
|
5392
|
+
result = await runEvalFn(entry.config, wrappedExecuteFn, this);
|
|
5393
|
+
} else {
|
|
5394
|
+
result = await this.eval(
|
|
5395
|
+
entry.config
|
|
5396
|
+
);
|
|
5266
5397
|
}
|
|
5267
|
-
|
|
5268
|
-
|
|
5269
|
-
|
|
5398
|
+
const resultObj = result;
|
|
5399
|
+
try {
|
|
5400
|
+
await this.saveEvalResult({
|
|
5401
|
+
id: resultObj.id ?? randomUUID2(),
|
|
5402
|
+
eval: name,
|
|
5403
|
+
timestamp: Date.now(),
|
|
5404
|
+
data: structuredClone(result)
|
|
5405
|
+
});
|
|
5406
|
+
} catch {
|
|
5407
|
+
}
|
|
5408
|
+
return result;
|
|
5270
5409
|
}
|
|
5271
|
-
/** Get all execution info (running + completed). */
|
|
5272
|
-
getExecutions() {
|
|
5273
|
-
|
|
5410
|
+
/** Get all execution info (running + completed + historical). */
|
|
5411
|
+
async getExecutions() {
|
|
5412
|
+
if (!this.historicalExecutionsLoadPromise && this.stateStore.listExecutions) {
|
|
5413
|
+
this.historicalExecutionsLoadPromise = this.stateStore.listExecutions().then((stored) => {
|
|
5414
|
+
for (const exec of stored) {
|
|
5415
|
+
if (!this.executions.has(exec.executionId) && !this.historicalExecutions.has(exec.executionId)) {
|
|
5416
|
+
this.historicalExecutions.set(exec.executionId, exec);
|
|
5417
|
+
}
|
|
5418
|
+
}
|
|
5419
|
+
}).catch(() => {
|
|
5420
|
+
this.historicalExecutionsLoadPromise = null;
|
|
5421
|
+
});
|
|
5422
|
+
}
|
|
5423
|
+
if (this.historicalExecutionsLoadPromise) {
|
|
5424
|
+
await this.historicalExecutionsLoadPromise;
|
|
5425
|
+
}
|
|
5426
|
+
const merged = new Map(this.historicalExecutions);
|
|
5427
|
+
for (const [id, exec] of this.executions) {
|
|
5428
|
+
merged.set(id, exec);
|
|
5429
|
+
}
|
|
5430
|
+
return [...merged.values()].sort((a, b) => b.startedAt - a.startedAt);
|
|
5274
5431
|
}
|
|
5275
5432
|
/**
|
|
5276
5433
|
* Create a WorkflowContext for ad-hoc use (evals, tool testing, prototyping).
|
|
@@ -5311,6 +5468,10 @@ var AxlRuntime = class extends EventEmitter2 {
|
|
|
5311
5468
|
registerProvider(name, provider) {
|
|
5312
5469
|
this.providerRegistry.registerInstance(name, provider);
|
|
5313
5470
|
}
|
|
5471
|
+
/** Resolve a provider:model URI to a Provider instance and model name. */
|
|
5472
|
+
resolveProvider(uri) {
|
|
5473
|
+
return this.providerRegistry.resolve(uri, this.config);
|
|
5474
|
+
}
|
|
5314
5475
|
/** Execute a workflow and return the result. */
|
|
5315
5476
|
async execute(name, input, options) {
|
|
5316
5477
|
const workflow2 = this.workflows.get(name);
|
|
@@ -5402,6 +5563,7 @@ var AxlRuntime = class extends EventEmitter2 {
|
|
|
5402
5563
|
}
|
|
5403
5564
|
span.setAttribute("axl.workflow.cost", execInfo.totalCost);
|
|
5404
5565
|
span.setAttribute("axl.workflow.duration", execInfo.duration);
|
|
5566
|
+
this.persistExecution(execInfo);
|
|
5405
5567
|
return output;
|
|
5406
5568
|
} catch (err) {
|
|
5407
5569
|
execInfo.status = "failed";
|
|
@@ -5409,6 +5571,7 @@ var AxlRuntime = class extends EventEmitter2 {
|
|
|
5409
5571
|
execInfo.duration = execInfo.completedAt - execInfo.startedAt;
|
|
5410
5572
|
execInfo.error = err instanceof Error ? err.message : String(err);
|
|
5411
5573
|
ctx.log("workflow_end", { workflow: name, status: "failed", error: execInfo.error });
|
|
5574
|
+
this.persistExecution(execInfo);
|
|
5412
5575
|
throw err;
|
|
5413
5576
|
} finally {
|
|
5414
5577
|
this.abortControllers.delete(executionId);
|
|
@@ -5422,6 +5585,7 @@ var AxlRuntime = class extends EventEmitter2 {
|
|
|
5422
5585
|
const controller = new AbortController();
|
|
5423
5586
|
axlStream.on("close", () => controller.abort());
|
|
5424
5587
|
let execInfo;
|
|
5588
|
+
let ctx;
|
|
5425
5589
|
const run = async () => {
|
|
5426
5590
|
const workflow2 = this.workflows.get(name);
|
|
5427
5591
|
if (!workflow2) throw new Error(`Workflow "${name}" not registered`);
|
|
@@ -5440,7 +5604,7 @@ var AxlRuntime = class extends EventEmitter2 {
|
|
|
5440
5604
|
duration: 0
|
|
5441
5605
|
};
|
|
5442
5606
|
this.executions.set(executionId, execInfo);
|
|
5443
|
-
const
|
|
5607
|
+
const wfCtx = new WorkflowContext({
|
|
5444
5608
|
input: validated,
|
|
5445
5609
|
executionId,
|
|
5446
5610
|
metadata: options?.metadata,
|
|
@@ -5528,6 +5692,7 @@ var AxlRuntime = class extends EventEmitter2 {
|
|
|
5528
5692
|
policy: "finish_and_stop"
|
|
5529
5693
|
}
|
|
5530
5694
|
});
|
|
5695
|
+
ctx = wfCtx;
|
|
5531
5696
|
return this.spanManager.withSpanAsync(
|
|
5532
5697
|
"axl.workflow.execute",
|
|
5533
5698
|
{
|
|
@@ -5537,16 +5702,23 @@ var AxlRuntime = class extends EventEmitter2 {
|
|
|
5537
5702
|
},
|
|
5538
5703
|
async (span) => {
|
|
5539
5704
|
try {
|
|
5540
|
-
const rawResult = await workflow2.handler(
|
|
5705
|
+
const rawResult = await workflow2.handler(wfCtx);
|
|
5541
5706
|
const result = workflow2.outputSchema ? workflow2.outputSchema.parse(rawResult) : rawResult;
|
|
5542
5707
|
execInfo.status = "completed";
|
|
5543
5708
|
execInfo.completedAt = Date.now();
|
|
5544
5709
|
execInfo.duration = execInfo.completedAt - execInfo.startedAt;
|
|
5710
|
+
wfCtx.log("workflow_end", {
|
|
5711
|
+
workflow: name,
|
|
5712
|
+
status: "completed",
|
|
5713
|
+
duration: execInfo.duration,
|
|
5714
|
+
cost: execInfo.totalCost
|
|
5715
|
+
});
|
|
5545
5716
|
if (this.stateStore.deleteCheckpoints) {
|
|
5546
5717
|
await this.stateStore.deleteCheckpoints(executionId);
|
|
5547
5718
|
}
|
|
5548
5719
|
span.setAttribute("axl.workflow.cost", execInfo.totalCost);
|
|
5549
5720
|
span.setAttribute("axl.workflow.duration", execInfo.duration);
|
|
5721
|
+
this.persistExecution(execInfo);
|
|
5550
5722
|
return result;
|
|
5551
5723
|
} finally {
|
|
5552
5724
|
this.abortControllers.delete(executionId);
|
|
@@ -5560,6 +5732,12 @@ var AxlRuntime = class extends EventEmitter2 {
|
|
|
5560
5732
|
execInfo.completedAt = Date.now();
|
|
5561
5733
|
execInfo.duration = execInfo.completedAt - execInfo.startedAt;
|
|
5562
5734
|
execInfo.error = err instanceof Error ? err.message : String(err);
|
|
5735
|
+
ctx?.log("workflow_end", {
|
|
5736
|
+
workflow: name,
|
|
5737
|
+
status: "failed",
|
|
5738
|
+
error: execInfo.error
|
|
5739
|
+
});
|
|
5740
|
+
this.persistExecution(execInfo);
|
|
5563
5741
|
}
|
|
5564
5742
|
axlStream._error(err instanceof Error ? err : new Error(String(err)));
|
|
5565
5743
|
});
|
|
@@ -5603,7 +5781,45 @@ var AxlRuntime = class extends EventEmitter2 {
|
|
|
5603
5781
|
}
|
|
5604
5782
|
/** Get execution details by ID. */
|
|
5605
5783
|
async getExecution(executionId) {
|
|
5606
|
-
|
|
5784
|
+
const inMemory = this.executions.get(executionId);
|
|
5785
|
+
if (inMemory) return inMemory;
|
|
5786
|
+
const cached = this.historicalExecutions.get(executionId);
|
|
5787
|
+
if (cached) return cached;
|
|
5788
|
+
if (this.stateStore.getExecution) {
|
|
5789
|
+
const stored = await this.stateStore.getExecution(executionId);
|
|
5790
|
+
if (stored) {
|
|
5791
|
+
this.historicalExecutions.set(executionId, stored);
|
|
5792
|
+
return stored;
|
|
5793
|
+
}
|
|
5794
|
+
}
|
|
5795
|
+
return void 0;
|
|
5796
|
+
}
|
|
5797
|
+
/** Save an eval result to history. */
|
|
5798
|
+
async saveEvalResult(entry) {
|
|
5799
|
+
this.evalHistory.unshift(entry);
|
|
5800
|
+
if (this.stateStore.saveEvalResult) {
|
|
5801
|
+
await this.stateStore.saveEvalResult(entry);
|
|
5802
|
+
}
|
|
5803
|
+
}
|
|
5804
|
+
/** Get eval result history (most recent first). */
|
|
5805
|
+
async getEvalHistory() {
|
|
5806
|
+
if (!this.evalHistoryLoadPromise && this.stateStore.listEvalResults) {
|
|
5807
|
+
this.evalHistoryLoadPromise = this.stateStore.listEvalResults().then((stored) => {
|
|
5808
|
+
const ids = new Set(this.evalHistory.map((e) => e.id));
|
|
5809
|
+
for (const entry of stored) {
|
|
5810
|
+
if (!ids.has(entry.id)) {
|
|
5811
|
+
this.evalHistory.push(entry);
|
|
5812
|
+
}
|
|
5813
|
+
}
|
|
5814
|
+
this.evalHistory.sort((a, b) => b.timestamp - a.timestamp);
|
|
5815
|
+
}).catch(() => {
|
|
5816
|
+
this.evalHistoryLoadPromise = null;
|
|
5817
|
+
});
|
|
5818
|
+
}
|
|
5819
|
+
if (this.evalHistoryLoadPromise) {
|
|
5820
|
+
await this.evalHistoryLoadPromise;
|
|
5821
|
+
}
|
|
5822
|
+
return [...this.evalHistory];
|
|
5607
5823
|
}
|
|
5608
5824
|
/** List pending human decisions. */
|
|
5609
5825
|
async getPendingDecisions() {
|
|
@@ -5712,7 +5928,7 @@ var AxlRuntime = class extends EventEmitter2 {
|
|
|
5712
5928
|
});
|
|
5713
5929
|
return { output: result, cost };
|
|
5714
5930
|
};
|
|
5715
|
-
return runEvalFn(config, executeWorkflow,
|
|
5931
|
+
return runEvalFn(config, executeWorkflow, this);
|
|
5716
5932
|
}
|
|
5717
5933
|
/**
|
|
5718
5934
|
* Compare two evaluation results to detect regressions and improvements.
|
|
@@ -5911,6 +6127,18 @@ var RedisStore = class _RedisStore {
|
|
|
5911
6127
|
pendingExecSetKey() {
|
|
5912
6128
|
return "axl:pending-executions";
|
|
5913
6129
|
}
|
|
6130
|
+
execHistoryKey(executionId) {
|
|
6131
|
+
return `axl:exec-history:${executionId}`;
|
|
6132
|
+
}
|
|
6133
|
+
execHistorySetKey() {
|
|
6134
|
+
return "axl:exec-history-ids";
|
|
6135
|
+
}
|
|
6136
|
+
evalHistoryKey(id) {
|
|
6137
|
+
return `axl:eval-history:${id}`;
|
|
6138
|
+
}
|
|
6139
|
+
evalHistorySetKey() {
|
|
6140
|
+
return "axl:eval-history-ids";
|
|
6141
|
+
}
|
|
5914
6142
|
// ── Checkpoints ──────────────────────────────────────────────────────
|
|
5915
6143
|
async saveCheckpoint(executionId, step, data) {
|
|
5916
6144
|
await this.client.hSet(this.checkpointKey(executionId), String(step), JSON.stringify(data));
|
|
@@ -5982,6 +6210,42 @@ var RedisStore = class _RedisStore {
|
|
|
5982
6210
|
async listPendingExecutions() {
|
|
5983
6211
|
return this.client.sMembers(this.pendingExecSetKey());
|
|
5984
6212
|
}
|
|
6213
|
+
// ── Execution History ────────────────────────────────────────────────
|
|
6214
|
+
async saveExecution(execution) {
|
|
6215
|
+
await this.client.sAdd(this.execHistorySetKey(), execution.executionId);
|
|
6216
|
+
await this.client.set(this.execHistoryKey(execution.executionId), JSON.stringify(execution));
|
|
6217
|
+
}
|
|
6218
|
+
async getExecution(executionId) {
|
|
6219
|
+
const raw = await this.client.get(this.execHistoryKey(executionId));
|
|
6220
|
+
return raw ? JSON.parse(raw) : null;
|
|
6221
|
+
}
|
|
6222
|
+
async listExecutions(limit) {
|
|
6223
|
+
const ids = await this.client.sMembers(this.execHistorySetKey());
|
|
6224
|
+
if (ids.length === 0) return [];
|
|
6225
|
+
const entries = [];
|
|
6226
|
+
for (const id of ids) {
|
|
6227
|
+
const raw = await this.client.get(this.execHistoryKey(id));
|
|
6228
|
+
if (raw) entries.push(JSON.parse(raw));
|
|
6229
|
+
}
|
|
6230
|
+
entries.sort((a, b) => b.startedAt - a.startedAt);
|
|
6231
|
+
return limit ? entries.slice(0, limit) : entries;
|
|
6232
|
+
}
|
|
6233
|
+
// ── Eval History ────────────────────────────────────────────────────
|
|
6234
|
+
async saveEvalResult(entry) {
|
|
6235
|
+
await this.client.sAdd(this.evalHistorySetKey(), entry.id);
|
|
6236
|
+
await this.client.set(this.evalHistoryKey(entry.id), JSON.stringify(entry));
|
|
6237
|
+
}
|
|
6238
|
+
async listEvalResults(limit) {
|
|
6239
|
+
const ids = await this.client.sMembers(this.evalHistorySetKey());
|
|
6240
|
+
if (ids.length === 0) return [];
|
|
6241
|
+
const entries = [];
|
|
6242
|
+
for (const id of ids) {
|
|
6243
|
+
const raw = await this.client.get(this.evalHistoryKey(id));
|
|
6244
|
+
if (raw) entries.push(JSON.parse(raw));
|
|
6245
|
+
}
|
|
6246
|
+
entries.sort((a, b) => b.timestamp - a.timestamp);
|
|
6247
|
+
return limit ? entries.slice(0, limit) : entries;
|
|
6248
|
+
}
|
|
5985
6249
|
// ── Sessions (Studio introspection) ────────────────────────────────────
|
|
5986
6250
|
async listSessions() {
|
|
5987
6251
|
return this.client.sMembers("axl:session-ids");
|