@cursor/july 0.1.5 → 0.1.7
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/ab.d.ts +8 -95
- package/dist/ab.d.ts.map +1 -1
- package/dist/ab.js +9 -150
- package/dist/bin/agent-serve.js +41 -8
- package/dist/channels/slack/post-update-delivery.d.ts +85 -0
- package/dist/channels/slack/post-update-delivery.d.ts.map +1 -0
- package/dist/docs/404.html +2 -2
- package/dist/docs/ab.html +4 -4
- package/dist/docs/assets/{app.DabPG-io.js → app.COTN7wgo.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.B7UcKvIn.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.jmyr0bU0.js → VPLocalSearchBox.BW3TBdT0.js} +1 -1
- package/dist/docs/assets/chunks/{theme.DysN9-VN.js → theme.BEJW0vE7.js} +2 -2
- package/dist/docs/assets/deployment.md.BtfEsc9S.js +55 -0
- package/dist/docs/assets/deployment.md.BtfEsc9S.lean.js +1 -0
- package/dist/docs/assets/example-agents_approval-buddy.md.8R5phXb5.js +10 -0
- package/dist/docs/assets/example-agents_approval-buddy.md.8R5phXb5.lean.js +1 -0
- package/dist/docs/assets/example-agents_benny.md.B0gjhI-p.js +7 -0
- package/dist/docs/assets/example-agents_benny.md.B0gjhI-p.lean.js +1 -0
- package/dist/docs/assets/example-agents_bugbot.md.DelIdhxB.js +11 -0
- package/dist/docs/assets/example-agents_bugbot.md.DelIdhxB.lean.js +1 -0
- package/dist/docs/assets/example-agents_codebase-wiki.md.DC6sgwn0.js +8 -0
- package/dist/docs/assets/example-agents_codebase-wiki.md.DC6sgwn0.lean.js +1 -0
- package/dist/docs/assets/example-agents_codeowners-review.md.Ku_tG2RY.js +8 -0
- package/dist/docs/assets/example-agents_codeowners-review.md.Ku_tG2RY.lean.js +1 -0
- package/dist/docs/assets/example-agents_concierge.md.4rQTSMXt.js +23 -0
- package/dist/docs/assets/example-agents_concierge.md.4rQTSMXt.lean.js +1 -0
- package/dist/docs/assets/example-agents_fsd.md.CzgUrDfi.js +15 -0
- package/dist/docs/assets/example-agents_fsd.md.CzgUrDfi.lean.js +1 -0
- package/dist/docs/assets/example-agents_index.md.CRqJlnIf.js +2 -0
- package/dist/docs/assets/example-agents_index.md.CRqJlnIf.lean.js +1 -0
- package/dist/docs/assets/example-agents_knowledge-base.md.BPJiVueF.js +11 -0
- package/dist/docs/assets/example-agents_knowledge-base.md.BPJiVueF.lean.js +1 -0
- package/dist/docs/assets/example-agents_security-reviewer.md.D2rtwDTO.js +19 -0
- package/dist/docs/assets/example-agents_security-reviewer.md.D2rtwDTO.lean.js +1 -0
- package/dist/docs/assets/example-agents_slack-agent.md.buLbgvBf.js +5 -0
- package/dist/docs/assets/example-agents_slack-agent.md.buLbgvBf.lean.js +1 -0
- package/dist/docs/assets/example-agents_weather-agent.md.C9Qv-W0o.js +24 -0
- package/dist/docs/assets/example-agents_weather-agent.md.C9Qv-W0o.lean.js +1 -0
- package/dist/docs/assets/index.md.COiu-1jL.js +20 -0
- package/dist/docs/assets/{index.md.Cylk70gg.lean.js → index.md.COiu-1jL.lean.js} +1 -1
- package/dist/docs/assets/reference_cli.md.D189RBCH.js +60 -0
- package/dist/docs/assets/reference_cli.md.D189RBCH.lean.js +1 -0
- package/dist/docs/building-with-agents.html +4 -4
- package/dist/docs/concepts.html +4 -4
- package/dist/docs/deployment.html +58 -17
- package/dist/docs/evals.html +4 -4
- package/dist/docs/example-agents/approval-buddy.html +34 -0
- package/dist/docs/example-agents/benny.html +31 -0
- package/dist/docs/example-agents/bugbot.html +35 -0
- package/dist/docs/example-agents/codebase-wiki.html +32 -0
- package/dist/docs/example-agents/codeowners-review.html +32 -0
- package/dist/docs/example-agents/concierge.html +47 -0
- package/dist/docs/example-agents/fsd.html +39 -0
- package/dist/docs/example-agents/index.html +26 -0
- package/dist/docs/example-agents/knowledge-base.html +35 -0
- package/dist/docs/example-agents/security-reviewer.html +43 -0
- package/dist/docs/example-agents/slack-agent.html +29 -0
- package/dist/docs/example-agents/weather-agent.html +48 -0
- package/dist/docs/guides/agent-to-agent.html +4 -4
- package/dist/docs/guides/cloud-runtime.html +5 -5
- package/dist/docs/guides/github.html +4 -4
- package/dist/docs/guides/human-in-the-loop.html +4 -4
- package/dist/docs/guides/slack.html +4 -4
- package/dist/docs/guides/webhooks.html +4 -4
- package/dist/docs/hashmap.json +1 -1
- package/dist/docs/hillclimbing.html +4 -4
- package/dist/docs/index.html +7 -7
- package/dist/docs/quickstart.html +4 -4
- package/dist/docs/reference/agent-config.html +4 -4
- package/dist/docs/reference/channels.html +4 -4
- package/dist/docs/reference/cli.html +52 -30
- package/dist/docs/reference/connections.html +4 -4
- package/dist/docs/reference/hooks.html +4 -4
- package/dist/docs/reference/http-api.html +4 -4
- package/dist/docs/reference/instructions.html +4 -4
- package/dist/docs/reference/playground.html +4 -4
- package/dist/docs/reference/project-layout.html +4 -4
- package/dist/docs/reference/schedules.html +4 -4
- package/dist/docs/reference/sessions.html +4 -4
- package/dist/docs/reference/skills.html +4 -4
- package/dist/docs/reference/subagents.html +4 -4
- package/dist/docs/reference/tools.html +4 -4
- package/dist/docs/scaffolding-agents.html +4 -4
- package/dist/docs/storage.html +4 -4
- package/dist/docs/troubleshooting.html +4 -4
- package/dist/evals.d.ts +5 -62
- package/dist/evals.d.ts.map +1 -1
- package/dist/evals.js +3 -66
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/internal/ab-collector.d.ts +7 -5
- package/dist/internal/ab-collector.d.ts.map +1 -1
- package/dist/internal/ab-collector.js +3 -14
- package/dist/internal/ab-snapshot.d.ts +2 -4
- package/dist/internal/ab-snapshot.d.ts.map +1 -1
- package/dist/internal/cli-ax.d.ts +33 -5
- package/dist/internal/cli-ax.d.ts.map +1 -1
- package/dist/internal/cli-ax.js +428 -87
- package/dist/internal/cli-deploy.js +1 -1
- package/dist/internal/discovery.js +3 -3
- package/dist/internal/eval-run-store.d.ts +35 -30
- package/dist/internal/eval-run-store.d.ts.map +1 -1
- package/dist/internal/eval-run-store.js +88 -100
- package/dist/internal/evals-client.d.ts +96 -0
- package/dist/internal/evals-client.d.ts.map +1 -0
- package/dist/internal/evals-client.js +262 -0
- package/dist/internal/init-project.d.ts.map +1 -1
- package/dist/internal/init-project.js +1 -0
- package/dist/internal/persistence-coordinator.d.ts +127 -0
- package/dist/internal/persistence-coordinator.d.ts.map +1 -0
- package/dist/internal/playground-proxy.d.ts +5 -5
- package/dist/internal/playground-proxy.js +3 -3
- package/dist/internal/resolve-prod-target.d.ts +30 -0
- package/dist/internal/resolve-prod-target.d.ts.map +1 -1
- package/dist/internal/resolve-prod-target.js +74 -2
- package/dist/internal/server.d.ts.map +1 -1
- package/dist/internal/server.js +16 -5
- package/dist/internal/session-engine.d.ts +1 -2
- package/dist/internal/session-engine.d.ts.map +1 -1
- package/dist/internal/session-engine.js +14 -31
- package/dist/internal/storage-coordinator.d.ts +16 -15
- package/dist/internal/storage-coordinator.d.ts.map +1 -1
- package/dist/internal/storage-coordinator.js +73 -80
- package/dist/persistence.d.ts +184 -0
- package/dist/persistence.d.ts.map +1 -0
- package/dist/playground/assets/cursor-icons-16-CQ50JpfO.woff2 +0 -0
- package/dist/playground/assets/index-72vCOBWO.js +86 -0
- package/dist/playground/assets/index-BjnMwYoR.css +1 -0
- package/dist/playground/index.html +2 -2
- package/dist/storage.d.ts +51 -10
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +27 -10
- package/docs/README.md +34 -5
- package/docs/deployment.md +352 -149
- package/docs/example-agents/approval-buddy.md +270 -0
- package/docs/example-agents/benny.md +186 -0
- package/docs/example-agents/bugbot.md +231 -0
- package/docs/example-agents/codebase-wiki.md +174 -0
- package/docs/example-agents/codeowners-review.md +195 -0
- package/docs/example-agents/concierge.md +205 -0
- package/docs/example-agents/fsd.md +330 -0
- package/docs/example-agents/index.md +102 -0
- package/docs/example-agents/knowledge-base.md +171 -0
- package/docs/example-agents/security-reviewer.md +296 -0
- package/docs/example-agents/slack-agent.md +146 -0
- package/docs/example-agents/weather-agent.md +302 -0
- package/docs/reference/cli.md +546 -147
- package/package.json +1 -1
- package/src/ab.ts +9 -261
- package/src/bin/agent-serve.ts +46 -7
- package/src/evals.ts +5 -119
- package/src/index.ts +2 -0
- package/src/internal/ab-collector.ts +12 -22
- package/src/internal/ab-snapshot.ts +2 -4
- package/src/internal/cli-ax.ts +551 -104
- package/src/internal/cli-deploy.ts +1 -1
- package/src/internal/discovery.ts +2 -2
- package/src/internal/eval-run-store.ts +91 -100
- package/src/internal/evals-client.ts +431 -0
- package/src/internal/init-project.ts +1 -0
- package/src/internal/playground-proxy.ts +5 -5
- package/src/internal/resolve-prod-target.ts +101 -3
- package/src/internal/server.ts +17 -3
- package/src/internal/session-engine.ts +9 -29
- package/src/internal/storage-coordinator.ts +109 -101
- package/src/storage.ts +79 -14
- package/dist/docs/assets/chunks/@localSearchIndexroot.QwK5BtEH.js +0 -1
- package/dist/docs/assets/deployment.md.DTKwE15Z.js +0 -14
- package/dist/docs/assets/deployment.md.DTKwE15Z.lean.js +0 -1
- package/dist/docs/assets/index.md.Cylk70gg.js +0 -20
- package/dist/docs/assets/reference_cli.md.Bv6pOxcF.js +0 -38
- package/dist/docs/assets/reference_cli.md.Bv6pOxcF.lean.js +0 -1
- package/dist/internal/json-dir-store.js +0 -100
- package/dist/playground/assets/cursor-icons-outline-BxTT_FVJ.woff2 +0 -0
- package/dist/playground/assets/index-BEauYlII.css +0 -1
- package/dist/playground/assets/index-BtM0wEGg.js +0 -319
- package/src/internal/json-dir-store.ts +0 -109
|
@@ -675,7 +675,7 @@ async function deployOne(
|
|
|
675
675
|
` kind: ${detail.deploymentKind}\n` +
|
|
676
676
|
` alias: ${aliasUrl}\n` +
|
|
677
677
|
` playground: ${aliasUrl}/playground (sign in with the alias token)\n` +
|
|
678
|
-
`
|
|
678
|
+
` open: ${CLI} playground --prod --slug ${slug} --team ${ctx.teamId}\n`
|
|
679
679
|
);
|
|
680
680
|
return 0;
|
|
681
681
|
}
|
|
@@ -1611,8 +1611,8 @@ export function projectInfo(project: AgentProject): AgentProjectInfo {
|
|
|
1611
1611
|
maxPlaygroundSessions: resolveABMaxPlaygroundSessions(
|
|
1612
1612
|
project.abConfig?.maxPlaygroundSessions
|
|
1613
1613
|
),
|
|
1614
|
-
durableSamples: project.
|
|
1615
|
-
durableSnapshots: project.
|
|
1614
|
+
durableSamples: project.storage?.abs !== undefined,
|
|
1615
|
+
durableSnapshots: project.storage?.abs?.putSnapshot !== undefined,
|
|
1616
1616
|
},
|
|
1617
1617
|
}),
|
|
1618
1618
|
storage:
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Store for playground-triggered eval batches.
|
|
3
3
|
*
|
|
4
|
-
* Default: process memory only, capped by `maxPlaygroundRuns` (see
|
|
5
|
-
*
|
|
4
|
+
* Default: process memory only, capped by `maxPlaygroundRuns` (see
|
|
5
|
+
* `defineEvalConfig`). When `agent/storage.ts` (`defineStorage`) declares an
|
|
6
|
+
* `evals` table, runs are mirrored there and survive restart.
|
|
6
7
|
* Runs against the live mount's loopback URL so case sessions appear in
|
|
7
8
|
* the playground session list.
|
|
8
9
|
*/
|
|
@@ -11,7 +12,6 @@ import { randomUUID } from "node:crypto";
|
|
|
11
12
|
import {
|
|
12
13
|
type EvalCaseSnapshot,
|
|
13
14
|
type EvalConfigFile,
|
|
14
|
-
type EvalRunPersistence,
|
|
15
15
|
type EvalRunSnapshot,
|
|
16
16
|
resolveEvalMaxPlaygroundRuns,
|
|
17
17
|
} from "../evals.js";
|
|
@@ -30,18 +30,32 @@ export type {
|
|
|
30
30
|
EvalRunSnapshot,
|
|
31
31
|
} from "../evals.js";
|
|
32
32
|
|
|
33
|
+
/**
|
|
34
|
+
* Durable mirror for playground eval batches — the `StorageCoordinator`
|
|
35
|
+
* adapter over the `defineStorage` `evals` table. Writes are
|
|
36
|
+
* fire-and-forget (the coordinator serializes and isolates failures);
|
|
37
|
+
* `list` is the serve-start hydrate read.
|
|
38
|
+
*/
|
|
39
|
+
export interface EvalRunStorage {
|
|
40
|
+
save(run: EvalRunSnapshot): void;
|
|
41
|
+
delete(runId: string): void;
|
|
42
|
+
list(): Promise<EvalRunSnapshot[]>;
|
|
43
|
+
}
|
|
44
|
+
|
|
33
45
|
export interface StartEvalRunInput {
|
|
34
46
|
filterIds?: string[];
|
|
35
47
|
tags?: string[];
|
|
36
48
|
bearerToken?: string;
|
|
37
49
|
verbose?: boolean;
|
|
50
|
+
/** Per-case timeout override (same semantics as CLI `--timeout-ms`). */
|
|
51
|
+
timeoutMs?: number;
|
|
38
52
|
}
|
|
39
53
|
|
|
40
54
|
export type EvalListConfig = {
|
|
41
55
|
maxConcurrency?: number;
|
|
42
56
|
timeoutMs?: number;
|
|
43
57
|
maxPlaygroundRuns: number;
|
|
44
|
-
/** True when `
|
|
58
|
+
/** True when `agent/storage.ts` declares an `evals` table. */
|
|
45
59
|
durableRuns: boolean;
|
|
46
60
|
};
|
|
47
61
|
|
|
@@ -55,28 +69,16 @@ export class EvalRunStore {
|
|
|
55
69
|
private activeRunId: string | undefined;
|
|
56
70
|
private hydratePromise: Promise<void> | undefined;
|
|
57
71
|
private hydrated = false;
|
|
58
|
-
/** Per-run persist chain so intermediate saves cannot overwrite a later final write. */
|
|
59
|
-
private readonly persistChains = new Map<string, Promise<void>>();
|
|
60
72
|
/** Filled after listen — e.g. `http://127.0.0.1:3000/weather-agent`. */
|
|
61
73
|
loopbackUrl: string | undefined;
|
|
62
74
|
|
|
63
75
|
constructor(
|
|
64
76
|
private readonly projectRoot: string,
|
|
65
77
|
private readonly logger: (line: string) => void,
|
|
66
|
-
/**
|
|
67
|
-
|
|
68
|
-
* used when `evals.config.ts` sets no `persistRuns` of its own.
|
|
69
|
-
*/
|
|
70
|
-
private readonly fallbackPersistence?: EvalRunPersistence
|
|
78
|
+
/** `defineStorage` evals-table adapter; undefined ⇒ memory only. */
|
|
79
|
+
private readonly storage?: EvalRunStorage | undefined
|
|
71
80
|
) {}
|
|
72
81
|
|
|
73
|
-
/** `evals.config.ts` `persistRuns` wins; `defineStorage` is fallback. */
|
|
74
|
-
private resolvePersist(
|
|
75
|
-
config: Partial<EvalConfigFile>
|
|
76
|
-
): EvalRunPersistence | undefined {
|
|
77
|
-
return config.persistRuns ?? this.fallbackPersistence;
|
|
78
|
-
}
|
|
79
|
-
|
|
80
82
|
async list(): Promise<{
|
|
81
83
|
evals: Array<{
|
|
82
84
|
id: string;
|
|
@@ -97,10 +99,7 @@ export class EvalRunStore {
|
|
|
97
99
|
: { description: e.definition.description }),
|
|
98
100
|
...(e.definition.tags === undefined ? {} : { tags: e.definition.tags }),
|
|
99
101
|
})),
|
|
100
|
-
config: snapshotListConfig(
|
|
101
|
-
config,
|
|
102
|
-
this.resolvePersist(config) !== undefined
|
|
103
|
-
),
|
|
102
|
+
config: snapshotListConfig(config, this.storage !== undefined),
|
|
104
103
|
};
|
|
105
104
|
}
|
|
106
105
|
|
|
@@ -175,15 +174,12 @@ export class EvalRunStore {
|
|
|
175
174
|
done: 0,
|
|
176
175
|
},
|
|
177
176
|
cases,
|
|
178
|
-
config: snapshotRunConfig(
|
|
179
|
-
config,
|
|
180
|
-
this.resolvePersist(config) !== undefined
|
|
181
|
-
),
|
|
177
|
+
config: snapshotRunConfig(config, this.storage !== undefined),
|
|
182
178
|
};
|
|
183
179
|
this.runs.set(runId, snapshot);
|
|
184
180
|
this.activeRunId = runId;
|
|
185
|
-
|
|
186
|
-
|
|
181
|
+
this.pruneOldRuns(config);
|
|
182
|
+
this.persist(snapshot);
|
|
187
183
|
this.logger(
|
|
188
184
|
`[agentkit] eval run ${runId}: starting ${cases.length} case(s)`
|
|
189
185
|
);
|
|
@@ -196,6 +192,7 @@ export class EvalRunStore {
|
|
|
196
192
|
? {}
|
|
197
193
|
: { bearerToken: input.bearerToken }),
|
|
198
194
|
...(input.verbose === undefined ? {} : { verbose: input.verbose }),
|
|
195
|
+
...(input.timeoutMs === undefined ? {} : { timeoutMs: input.timeoutMs }),
|
|
199
196
|
});
|
|
200
197
|
|
|
201
198
|
return snapshot;
|
|
@@ -208,39 +205,28 @@ export class EvalRunStore {
|
|
|
208
205
|
}
|
|
209
206
|
|
|
210
207
|
/**
|
|
211
|
-
* Hydrate playground eval history from
|
|
212
|
-
*
|
|
213
|
-
*
|
|
214
|
-
*
|
|
215
|
-
* Idempotent; concurrent callers share one pass.
|
|
208
|
+
* Hydrate playground eval history from the `defineStorage` evals table.
|
|
209
|
+
* Called eagerly from the serve startup restore step — alongside session
|
|
210
|
+
* restore — and lazily as a safety net by every read. Idempotent;
|
|
211
|
+
* concurrent callers share one pass.
|
|
216
212
|
*/
|
|
217
213
|
async hydrate(): Promise<void> {
|
|
218
214
|
if (this.hydrated) {
|
|
219
215
|
return;
|
|
220
216
|
}
|
|
221
217
|
if (this.hydratePromise === undefined) {
|
|
222
|
-
this.hydratePromise = this.
|
|
218
|
+
this.hydratePromise = this.hydrateFromStorage();
|
|
223
219
|
}
|
|
224
220
|
await this.hydratePromise;
|
|
225
221
|
}
|
|
226
222
|
|
|
227
|
-
private async
|
|
223
|
+
private async hydrateFromStorage(): Promise<void> {
|
|
228
224
|
try {
|
|
229
|
-
|
|
230
|
-
const persist = this.resolvePersist(config);
|
|
231
|
-
if (persist === undefined) {
|
|
225
|
+
if (this.storage === undefined) {
|
|
232
226
|
this.hydrated = true;
|
|
233
227
|
return;
|
|
234
228
|
}
|
|
235
|
-
const loaded = await
|
|
236
|
-
if (!Array.isArray(loaded)) {
|
|
237
|
-
this.logger(
|
|
238
|
-
"[agentkit] eval persistRuns.load() did not return an array; ignoring"
|
|
239
|
-
);
|
|
240
|
-
this.hydrated = true;
|
|
241
|
-
return;
|
|
242
|
-
}
|
|
243
|
-
const repaired: EvalRunSnapshot[] = [];
|
|
229
|
+
const loaded = await this.storage.list();
|
|
244
230
|
for (const run of loaded) {
|
|
245
231
|
if (
|
|
246
232
|
run === null ||
|
|
@@ -253,16 +239,26 @@ export class EvalRunStore {
|
|
|
253
239
|
// Incomplete batches from a killed process should not block a new run.
|
|
254
240
|
if (run.status === "running") {
|
|
255
241
|
markInterruptedRun(run);
|
|
256
|
-
|
|
242
|
+
this.persist(run);
|
|
257
243
|
}
|
|
258
244
|
this.runs.set(run.runId, run);
|
|
259
245
|
}
|
|
260
|
-
|
|
261
|
-
|
|
246
|
+
// Prune with the defaults even when eval discovery fails — loaded
|
|
247
|
+
// history must not stay unpruned for the process lifetime just
|
|
248
|
+
// because an eval file has a syntax error at boot.
|
|
249
|
+
let config: Partial<EvalConfigFile> = {};
|
|
250
|
+
try {
|
|
251
|
+
config = (await discoverEvals(this.projectRoot)).config;
|
|
252
|
+
} catch (error) {
|
|
253
|
+
this.logger(
|
|
254
|
+
`[agentkit] eval discovery failed during hydrate (pruning with defaults): ${
|
|
255
|
+
error instanceof Error ? error.message : String(error)
|
|
256
|
+
}`
|
|
257
|
+
);
|
|
262
258
|
}
|
|
263
|
-
|
|
259
|
+
this.pruneOldRuns(config);
|
|
264
260
|
this.logger(
|
|
265
|
-
`[agentkit] hydrated ${this.runs.size} playground eval run(s) from
|
|
261
|
+
`[agentkit] hydrated ${this.runs.size} playground eval run(s) from storage`
|
|
266
262
|
);
|
|
267
263
|
} catch (error) {
|
|
268
264
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -274,7 +270,7 @@ export class EvalRunStore {
|
|
|
274
270
|
}
|
|
275
271
|
}
|
|
276
272
|
|
|
277
|
-
private
|
|
273
|
+
private pruneOldRuns(config: Partial<EvalConfigFile>): void {
|
|
278
274
|
const limit = resolveEvalMaxPlaygroundRuns(config.maxPlaygroundRuns);
|
|
279
275
|
const ordered = this.sortedRuns();
|
|
280
276
|
if (ordered.length <= limit) {
|
|
@@ -285,58 +281,34 @@ export class EvalRunStore {
|
|
|
285
281
|
continue;
|
|
286
282
|
}
|
|
287
283
|
this.runs.delete(stale.runId);
|
|
288
|
-
|
|
284
|
+
this.storage?.delete(stale.runId);
|
|
289
285
|
}
|
|
290
286
|
}
|
|
291
287
|
|
|
292
|
-
/**
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
* fire-and-forget save cannot finish after (and overwrite) a later final save.
|
|
296
|
-
*/
|
|
297
|
-
private enqueuePersist(
|
|
298
|
-
run: EvalRunSnapshot,
|
|
299
|
-
persist: EvalRunPersistence | undefined
|
|
300
|
-
): Promise<void> {
|
|
301
|
-
if (persist === undefined) {
|
|
302
|
-
return Promise.resolve();
|
|
303
|
-
}
|
|
304
|
-
const snapshot = structuredClone(run);
|
|
305
|
-
const prev = this.persistChains.get(run.runId) ?? Promise.resolve();
|
|
306
|
-
const next = prev
|
|
307
|
-
.catch(() => undefined)
|
|
308
|
-
.then(() => this.persistSave(snapshot, persist));
|
|
309
|
-
this.persistChains.set(run.runId, next);
|
|
310
|
-
return next;
|
|
288
|
+
/** Mirror the run onto durable storage (coordinator clones + serializes). */
|
|
289
|
+
private persist(run: EvalRunSnapshot): void {
|
|
290
|
+
this.storage?.save(run);
|
|
311
291
|
}
|
|
312
292
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
);
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
private async persistDelete(
|
|
328
|
-
runId: string,
|
|
329
|
-
persist: EvalRunPersistence | undefined
|
|
330
|
-
): Promise<void> {
|
|
331
|
-
if (persist === undefined) {
|
|
293
|
+
/**
|
|
294
|
+
* Serve is draining: durably mark any in-flight batch as interrupted
|
|
295
|
+
* while the storage queue can still deliver. Late `execute` writes are
|
|
296
|
+
* dropped by the closed coordinator, so without this a batch that was
|
|
297
|
+
* running at shutdown would look "running" (or silently lose its final
|
|
298
|
+
* completion write) until the next hydrate repairs it.
|
|
299
|
+
*/
|
|
300
|
+
close(): void {
|
|
301
|
+
const activeRunId = this.activeRunId;
|
|
302
|
+
if (activeRunId === undefined) {
|
|
332
303
|
return;
|
|
333
304
|
}
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
338
|
-
this.logger(`[agentkit] persistRuns.delete(${runId}) failed: ${message}`);
|
|
305
|
+
const run = this.runs.get(activeRunId);
|
|
306
|
+
if (run === undefined || run.status !== "running") {
|
|
307
|
+
return;
|
|
339
308
|
}
|
|
309
|
+
markInterruptedRun(run);
|
|
310
|
+
this.persist(run);
|
|
311
|
+
this.activeRunId = undefined;
|
|
340
312
|
}
|
|
341
313
|
|
|
342
314
|
private async execute(
|
|
@@ -347,6 +319,7 @@ export class EvalRunStore {
|
|
|
347
319
|
config: Partial<EvalConfigFile>;
|
|
348
320
|
bearerToken?: string;
|
|
349
321
|
verbose?: boolean;
|
|
322
|
+
timeoutMs?: number;
|
|
350
323
|
}
|
|
351
324
|
): Promise<void> {
|
|
352
325
|
if (this.runs.get(runId) === undefined) {
|
|
@@ -361,6 +334,7 @@ export class EvalRunStore {
|
|
|
361
334
|
? {}
|
|
362
335
|
: { bearerToken: opts.bearerToken }),
|
|
363
336
|
...(opts.verbose === undefined ? {} : { verbose: opts.verbose }),
|
|
337
|
+
...(opts.timeoutMs === undefined ? {} : { timeoutMs: opts.timeoutMs }),
|
|
364
338
|
onCaseStart: (id) => {
|
|
365
339
|
const run = this.runs.get(runId);
|
|
366
340
|
if (run === undefined) {
|
|
@@ -408,7 +382,7 @@ export class EvalRunStore {
|
|
|
408
382
|
this.applyCaseResult(runId, result);
|
|
409
383
|
const run = this.runs.get(runId);
|
|
410
384
|
if (run !== undefined) {
|
|
411
|
-
|
|
385
|
+
this.persist(run);
|
|
412
386
|
}
|
|
413
387
|
},
|
|
414
388
|
});
|
|
@@ -418,7 +392,7 @@ export class EvalRunStore {
|
|
|
418
392
|
}
|
|
419
393
|
run.status = "completed";
|
|
420
394
|
run.finishedAt = new Date().toISOString();
|
|
421
|
-
|
|
395
|
+
this.persist(run);
|
|
422
396
|
this.logger(
|
|
423
397
|
`[agentkit] eval run ${runId}: done — ${run.summary.passed} passed, ${run.summary.failed} failed`
|
|
424
398
|
);
|
|
@@ -430,7 +404,7 @@ export class EvalRunStore {
|
|
|
430
404
|
run.status = "failed";
|
|
431
405
|
run.finishedAt = new Date().toISOString();
|
|
432
406
|
run.error = error instanceof Error ? error.message : String(error);
|
|
433
|
-
|
|
407
|
+
this.persist(run);
|
|
434
408
|
this.logger(`[agentkit] eval run ${runId}: failed — ${run.error}`);
|
|
435
409
|
} finally {
|
|
436
410
|
if (this.activeRunId === runId) {
|
|
@@ -489,6 +463,23 @@ function markInterruptedRun(run: EvalRunSnapshot): void {
|
|
|
489
463
|
c.error = c.error ?? INTERRUPTED_CASE_ERROR;
|
|
490
464
|
}
|
|
491
465
|
}
|
|
466
|
+
// Reconcile the summary with the repaired case rows so a persisted
|
|
467
|
+
// interrupted batch never claims pre-interruption pass counts.
|
|
468
|
+
let passed = 0;
|
|
469
|
+
let failed = 0;
|
|
470
|
+
for (const c of run.cases) {
|
|
471
|
+
if (c.ok === true) {
|
|
472
|
+
passed += 1;
|
|
473
|
+
} else {
|
|
474
|
+
failed += 1;
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
run.summary = {
|
|
478
|
+
passed,
|
|
479
|
+
failed,
|
|
480
|
+
total: run.cases.length,
|
|
481
|
+
done: run.cases.length,
|
|
482
|
+
};
|
|
492
483
|
}
|
|
493
484
|
|
|
494
485
|
function snapshotListConfig(
|