@cursor/july 0.1.4 → 0.1.6
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 +14 -6
- package/dist/docs/404.html +2 -2
- package/dist/docs/ab.html +4 -4
- package/dist/docs/assets/{app.DF-Yx4OP.js → app.DMboGKUD.js} +1 -1
- package/dist/docs/assets/chunks/@localSearchIndexroot.O6eP7QZr.js +1 -0
- package/dist/docs/assets/chunks/{VPLocalSearchBox.DSeJSudL.js → VPLocalSearchBox.DkEqEnJU.js} +1 -1
- package/dist/docs/assets/chunks/{theme.DZVLTXOC.js → theme.ASugdMNm.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 +4 -61
- 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 +18 -3
- package/dist/internal/cli-ax.d.ts.map +1 -1
- package/dist/internal/cli-ax.js +80 -42
- package/dist/internal/cli-deploy.d.ts.map +1 -1
- package/dist/internal/cli-deploy.js +5 -2
- package/dist/internal/cursor-event-relay.d.ts +4 -1
- package/dist/internal/cursor-event-relay.d.ts.map +1 -1
- package/dist/internal/cursor-event-relay.js +6 -0
- package/dist/internal/cursor-relay-core.d.ts +36 -1
- package/dist/internal/cursor-relay-core.d.ts.map +1 -1
- package/dist/internal/cursor-relay-core.js +89 -8
- package/dist/internal/cursor-slack-relay.d.ts +2 -2
- package/dist/internal/cursor-slack-relay.d.ts.map +1 -1
- package/dist/internal/cursor-slack-relay.js +4 -0
- package/dist/internal/discovery.js +3 -3
- package/dist/internal/eval-run-store.d.ts +33 -30
- package/dist/internal/eval-run-store.d.ts.map +1 -1
- package/dist/internal/eval-run-store.js +84 -96
- package/dist/internal/init-project.d.ts.map +1 -1
- package/dist/internal/init-project.js +3 -2
- 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 +5 -3
- 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/playground/assets/cursor-icons-16-CQ50JpfO.woff2 +0 -0
- package/dist/playground/assets/index-7GJIUFQj.css +1 -0
- package/dist/playground/assets/index-mux9aj5P.js +319 -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 +14 -6
- package/src/evals.ts +4 -118
- 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 +101 -45
- package/src/internal/cli-deploy.ts +5 -2
- package/src/internal/cursor-event-relay.ts +10 -1
- package/src/internal/cursor-relay-core.ts +115 -9
- package/src/internal/cursor-slack-relay.ts +6 -2
- package/src/internal/discovery.ts +2 -2
- package/src/internal/eval-run-store.ts +86 -100
- package/src/internal/init-project.ts +3 -2
- package/src/internal/playground-proxy.ts +5 -5
- package/src/internal/resolve-prod-target.ts +101 -3
- package/src/internal/server.ts +5 -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.0XrheBv2.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.d.ts +0 -32
- package/dist/internal/json-dir-store.d.ts.map +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-Ct_Usdm8.css +0 -1
- package/dist/playground/assets/index-Dsyb-Vaj.js +0 -319
- package/src/internal/json-dir-store.ts +0 -109
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cursor-relay-core.d.ts","sourceRoot":"","sources":["../../src/internal/cursor-relay-core.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;
|
|
1
|
+
{"version":3,"file":"cursor-relay-core.d.ts","sourceRoot":"","sources":["../../src/internal/cursor-relay-core.ts"],"names":[],"mappings":"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"}
|
|
@@ -29,6 +29,11 @@ const DEFAULT_IDLE_POLL_DELAY_MS = 250;
|
|
|
29
29
|
const MIN_BACKOFF_MS = 1000;
|
|
30
30
|
const MAX_BACKOFF_MS = 30000;
|
|
31
31
|
const AUTH_FAILURE_BACKOFF_MS = 60000;
|
|
32
|
+
/** Attempts per event before the offset advances past it. */
|
|
33
|
+
const DISPATCH_ATTEMPTS = 3;
|
|
34
|
+
const DISPATCH_RETRY_DELAYS_MS = [250, 1000];
|
|
35
|
+
/** Budget for the best-effort deregistration PUT during stop(). */
|
|
36
|
+
const DEREGISTER_TIMEOUT_MS = 1500;
|
|
32
37
|
/** Durable offset snapshot under `<stateDir>/offset.json`. */
|
|
33
38
|
export class RelayOffsetStore {
|
|
34
39
|
constructor(stateDir) {
|
|
@@ -93,6 +98,8 @@ export class CursorRelayCore {
|
|
|
93
98
|
this.options = options;
|
|
94
99
|
this.running = false;
|
|
95
100
|
this.consumerId = "";
|
|
101
|
+
/** Whether any registration succeeded (gates the stop-time deregister). */
|
|
102
|
+
this.registeredOnce = false;
|
|
96
103
|
this.offsetStore = new RelayOffsetStore(options.stateDir);
|
|
97
104
|
this.fetchImpl = (_a = options.fetchImpl) !== null && _a !== void 0 ? _a : fetch;
|
|
98
105
|
}
|
|
@@ -116,7 +123,7 @@ export class CursorRelayCore {
|
|
|
116
123
|
if (!registered)
|
|
117
124
|
return;
|
|
118
125
|
this.registerTimer = setInterval(() => {
|
|
119
|
-
|
|
126
|
+
this.heartbeatPromise = this.registerOnce();
|
|
120
127
|
}, DEFAULT_REGISTER_INTERVAL_MS);
|
|
121
128
|
(_b = (_a = this.registerTimer).unref) === null || _b === void 0 ? void 0 : _b.call(_a);
|
|
122
129
|
yield this.consumeLoop();
|
|
@@ -160,7 +167,7 @@ export class CursorRelayCore {
|
|
|
160
167
|
}
|
|
161
168
|
stop() {
|
|
162
169
|
return __awaiter(this, void 0, void 0, function* () {
|
|
163
|
-
var _a, _b;
|
|
170
|
+
var _a, _b, _c;
|
|
164
171
|
if (!this.running)
|
|
165
172
|
return;
|
|
166
173
|
this.running = false;
|
|
@@ -180,6 +187,55 @@ export class CursorRelayCore {
|
|
|
180
187
|
(_a = timer.unref) === null || _a === void 0 ? void 0 : _a.call(timer);
|
|
181
188
|
}),
|
|
182
189
|
]);
|
|
190
|
+
// A heartbeat re-registration may be in flight (its fetch was just
|
|
191
|
+
// aborted); let it settle so it cannot land after the deregistration.
|
|
192
|
+
yield (_c = this.heartbeatPromise) === null || _c === void 0 ? void 0 : _c.catch(() => { });
|
|
193
|
+
yield this.deregister();
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Best-effort empty-scope PUT on clean stop, so this consumer's
|
|
198
|
+
* registration is dropped immediately instead of lingering until its
|
|
199
|
+
* server-side TTL. A ghost registration keeps this host's agent names
|
|
200
|
+
* live and makes name routing ambiguous for a redeployed sibling with a
|
|
201
|
+
* fresh consumer id. Failures only log — the TTL still cleans up.
|
|
202
|
+
*/
|
|
203
|
+
deregister() {
|
|
204
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
205
|
+
var _a;
|
|
206
|
+
const adapter = this.options.adapter;
|
|
207
|
+
if (adapter.buildDeregistrationBody === undefined ||
|
|
208
|
+
!this.registeredOnce ||
|
|
209
|
+
this.consumerId === "") {
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
const url = `${this.options.baseUrl.replace(/\/+$/, "")}${adapter.subscribePath}`;
|
|
213
|
+
const controller = new AbortController();
|
|
214
|
+
const timer = setTimeout(() => controller.abort(), DEREGISTER_TIMEOUT_MS);
|
|
215
|
+
(_a = timer.unref) === null || _a === void 0 ? void 0 : _a.call(timer);
|
|
216
|
+
try {
|
|
217
|
+
const response = yield this.fetchImpl(url, {
|
|
218
|
+
method: "PUT",
|
|
219
|
+
headers: {
|
|
220
|
+
authorization: `Bearer ${this.options.apiKey}`,
|
|
221
|
+
"content-type": "application/json",
|
|
222
|
+
},
|
|
223
|
+
body: JSON.stringify(adapter.buildDeregistrationBody(this.consumerId)),
|
|
224
|
+
signal: controller.signal,
|
|
225
|
+
});
|
|
226
|
+
if (response.ok) {
|
|
227
|
+
this.log("deregistered on shutdown");
|
|
228
|
+
}
|
|
229
|
+
else {
|
|
230
|
+
this.log(`deregistration failed: ${response.status} (registration lapses by TTL)`);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
catch (error) {
|
|
234
|
+
this.log(`deregistration failed: ${describeRelayError(error)} (registration lapses by TTL)`);
|
|
235
|
+
}
|
|
236
|
+
finally {
|
|
237
|
+
clearTimeout(timer);
|
|
238
|
+
}
|
|
183
239
|
});
|
|
184
240
|
}
|
|
185
241
|
log(line) {
|
|
@@ -225,6 +281,7 @@ export class CursorRelayCore {
|
|
|
225
281
|
}
|
|
226
282
|
const json = (yield response.json());
|
|
227
283
|
this.logRegistrationOutcome(this.options.adapter.applyRegistrationResponse(json));
|
|
284
|
+
this.registeredOnce = true;
|
|
228
285
|
return true;
|
|
229
286
|
}
|
|
230
287
|
catch (error) {
|
|
@@ -298,12 +355,7 @@ export class CursorRelayCore {
|
|
|
298
355
|
if (compareStreamOffsets(event.offset, offset) <= 0)
|
|
299
356
|
continue;
|
|
300
357
|
if (this.options.adapter.shouldDispatch(event)) {
|
|
301
|
-
|
|
302
|
-
yield this.options.adapter.dispatch(event);
|
|
303
|
-
}
|
|
304
|
-
catch (error) {
|
|
305
|
-
this.log(`dispatch failed at offset ${event.offset}: ${describeRelayError(error)}`);
|
|
306
|
-
}
|
|
358
|
+
yield this.dispatchWithRetry(event);
|
|
307
359
|
}
|
|
308
360
|
offset = event.offset;
|
|
309
361
|
}
|
|
@@ -328,6 +380,35 @@ export class CursorRelayCore {
|
|
|
328
380
|
}
|
|
329
381
|
});
|
|
330
382
|
}
|
|
383
|
+
/**
|
|
384
|
+
* Dispatch one event with a small bounded retry before the offset advances
|
|
385
|
+
* past it. Transient local failures (e.g. a connection reset while POSTing
|
|
386
|
+
* to the channel) used to drop the event outright; a poison event still
|
|
387
|
+
* only costs {@link DISPATCH_ATTEMPTS} tries and is then skipped, keeping
|
|
388
|
+
* at-least-once semantics without a retry loop.
|
|
389
|
+
*/
|
|
390
|
+
dispatchWithRetry(event) {
|
|
391
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
392
|
+
for (let attempt = 1; attempt <= DISPATCH_ATTEMPTS; attempt++) {
|
|
393
|
+
if (attempt > 1 && !this.running) {
|
|
394
|
+
this.log(`dispatch abandoned at offset ${event.offset}: relay stopping`);
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
try {
|
|
398
|
+
yield this.options.adapter.dispatch(event);
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
catch (error) {
|
|
402
|
+
if (attempt === DISPATCH_ATTEMPTS) {
|
|
403
|
+
this.log(`dispatch failed at offset ${event.offset} after ${attempt} attempts: ${describeRelayError(error)}`);
|
|
404
|
+
return;
|
|
405
|
+
}
|
|
406
|
+
this.log(`dispatch attempt ${attempt} failed at offset ${event.offset}: ${describeRelayError(error)}; retrying`);
|
|
407
|
+
yield this.sleep(DISPATCH_RETRY_DELAYS_MS[Math.min(attempt - 1, DISPATCH_RETRY_DELAYS_MS.length - 1)]);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
});
|
|
411
|
+
}
|
|
331
412
|
/** Log the failure, sleep, and return the backoff for the NEXT failure. */
|
|
332
413
|
backoffAfterHttpFailure(response, backoffMs) {
|
|
333
414
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -27,8 +27,8 @@ export interface CursorSlackRelayOptions {
|
|
|
27
27
|
agents: readonly CursorSlackAgentRegistration[];
|
|
28
28
|
stateDir: string;
|
|
29
29
|
/**
|
|
30
|
-
* Called for each event addressed to this consumer's agents; failures
|
|
31
|
-
*
|
|
30
|
+
* Called for each event addressed to this consumer's agents; failures
|
|
31
|
+
* retry a bounded number of times, then log and skip.
|
|
32
32
|
*/
|
|
33
33
|
dispatch: (envelope: CursorSlackRelayEvent) => Promise<void>;
|
|
34
34
|
logger: (line: string) => void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cursor-slack-relay.d.ts","sourceRoot":"","sources":["../../src/internal/cursor-slack-relay.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAO/E,sEAAsE;AACtE,MAAM,WAAW,4BAA4B;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAYD,kFAAkF;AAClF,MAAM,MAAM,qBAAqB,GAAG,mBAAmB,GAAG;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7E,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,SAAS,4BAA4B,EAAE,CAAC;IAChD,QAAQ,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,QAAQ,EAAE,CAAC,QAAQ,EAAE,qBAAqB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7D,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,2CAA2C;IAC3C,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,wDAAwD;IACxD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,+DAA+D;AAC/D,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE;IAClD,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GAAG,MAAM,CAGT;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC,GAAG,CACF,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC9B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CA0CpC;AAED;;;;;GAKG;AACH,qBAAa,gBAAgB;IAUf,OAAO,CAAC,QAAQ,CAAC,OAAO;IATpC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAyC;IAC9D;;;;OAIG;IACH,OAAO,CAAC,gBAAgB,CAAqB;IAC7C,OAAO,CAAC,UAAU,CAAM;IAExB,YAA6B,OAAO,EAAE,uBAAuB,
|
|
1
|
+
{"version":3,"file":"cursor-slack-relay.d.ts","sourceRoot":"","sources":["../../src/internal/cursor-slack-relay.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAC;AAO/E,sEAAsE;AACtE,MAAM,WAAW,4BAA4B;IAC3C,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAYD,kFAAkF;AAClF,MAAM,MAAM,qBAAqB,GAAG,mBAAmB,GAAG;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE7E,MAAM,WAAW,uBAAuB;IACtC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,SAAS,4BAA4B,EAAE,CAAC;IAChD,QAAQ,EAAE,MAAM,CAAC;IACjB;;;OAGG;IACH,QAAQ,EAAE,CAAC,QAAQ,EAAE,qBAAqB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7D,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,2CAA2C;IAC3C,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,wDAAwD;IACxD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,+DAA+D;AAC/D,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE;IAClD,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB,GAAG,MAAM,CAGT;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,IAAI,EAAE;IAC/C,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC,GAAG,CACF,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC9B,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CA0CpC;AAED;;;;;GAKG;AACH,qBAAa,gBAAgB;IAUf,OAAO,CAAC,QAAQ,CAAC,OAAO;IATpC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAyC;IAC9D;;;;OAIG;IACH,OAAO,CAAC,gBAAgB,CAAqB;IAC7C,OAAO,CAAC,UAAU,CAAM;IAExB,YAA6B,OAAO,EAAE,uBAAuB,EAqE5D;IAED;;;OAGG;IACG,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC,CAGzC;IAED;;;OAGG;IACH,OAAO,CAAC,cAAc;IAOtB,KAAK,IAAI,IAAI,CAEZ;IAEK,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAE1B;CACF"}
|
|
@@ -106,6 +106,10 @@ export class CursorSlackRelay {
|
|
|
106
106
|
})),
|
|
107
107
|
};
|
|
108
108
|
},
|
|
109
|
+
// Empty agents drop this consumer's registration on clean stop, so a
|
|
110
|
+
// redeployed sibling's identical agent names never tie with this
|
|
111
|
+
// host's ghost until the server-side TTL lapses.
|
|
112
|
+
buildDeregistrationBody: (consumerId) => ({ consumerId, agents: [] }),
|
|
109
113
|
applyRegistrationResponse: (json) => {
|
|
110
114
|
var _a, _b, _c;
|
|
111
115
|
const result = json;
|
|
@@ -1226,7 +1226,7 @@ function loadSeedFiles(ctx, agentDir) {
|
|
|
1226
1226
|
// Info projection
|
|
1227
1227
|
// ============================================================================
|
|
1228
1228
|
export function projectInfo(project) {
|
|
1229
|
-
var _a, _b, _c;
|
|
1229
|
+
var _a, _b, _c, _d;
|
|
1230
1230
|
const agent = project.agent;
|
|
1231
1231
|
const httpRoutes = [
|
|
1232
1232
|
{ method: "POST", path: "/v1/session", url: "/v1/session" },
|
|
@@ -1324,8 +1324,8 @@ export function projectInfo(project) {
|
|
|
1324
1324
|
: {
|
|
1325
1325
|
abConfig: {
|
|
1326
1326
|
maxPlaygroundSessions: resolveABMaxPlaygroundSessions((_a = project.abConfig) === null || _a === void 0 ? void 0 : _a.maxPlaygroundSessions),
|
|
1327
|
-
durableSamples: ((_b = project.
|
|
1328
|
-
durableSnapshots: ((_c = project.
|
|
1327
|
+
durableSamples: ((_b = project.storage) === null || _b === void 0 ? void 0 : _b.abs) !== undefined,
|
|
1328
|
+
durableSnapshots: ((_d = (_c = project.storage) === null || _c === void 0 ? void 0 : _c.abs) === null || _d === void 0 ? void 0 : _d.putSnapshot) !== undefined,
|
|
1329
1329
|
},
|
|
1330
1330
|
})), { storage: project.storage === undefined
|
|
1331
1331
|
? undefined
|
|
@@ -1,13 +1,25 @@
|
|
|
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
|
*/
|
|
9
|
-
import { type
|
|
10
|
+
import { type EvalRunSnapshot } from "../evals.js";
|
|
10
11
|
export type { EvalBatchStatus, EvalCaseRunStatus as EvalCaseStatus, EvalCaseSnapshot, EvalRunSnapshot, } from "../evals.js";
|
|
12
|
+
/**
|
|
13
|
+
* Durable mirror for playground eval batches — the `StorageCoordinator`
|
|
14
|
+
* adapter over the `defineStorage` `evals` table. Writes are
|
|
15
|
+
* fire-and-forget (the coordinator serializes and isolates failures);
|
|
16
|
+
* `list` is the serve-start hydrate read.
|
|
17
|
+
*/
|
|
18
|
+
export interface EvalRunStorage {
|
|
19
|
+
save(run: EvalRunSnapshot): void;
|
|
20
|
+
delete(runId: string): void;
|
|
21
|
+
list(): Promise<EvalRunSnapshot[]>;
|
|
22
|
+
}
|
|
11
23
|
export interface StartEvalRunInput {
|
|
12
24
|
filterIds?: string[];
|
|
13
25
|
tags?: string[];
|
|
@@ -18,33 +30,23 @@ export type EvalListConfig = {
|
|
|
18
30
|
maxConcurrency?: number;
|
|
19
31
|
timeoutMs?: number;
|
|
20
32
|
maxPlaygroundRuns: number;
|
|
21
|
-
/** True when `
|
|
33
|
+
/** True when `agent/storage.ts` declares an `evals` table. */
|
|
22
34
|
durableRuns: boolean;
|
|
23
35
|
};
|
|
24
36
|
export declare class EvalRunStore {
|
|
25
37
|
private readonly projectRoot;
|
|
26
38
|
private readonly logger;
|
|
27
|
-
/**
|
|
28
|
-
|
|
29
|
-
* used when `evals.config.ts` sets no `persistRuns` of its own.
|
|
30
|
-
*/
|
|
31
|
-
private readonly fallbackPersistence?;
|
|
39
|
+
/** `defineStorage` evals-table adapter; undefined ⇒ memory only. */
|
|
40
|
+
private readonly storage?;
|
|
32
41
|
private readonly runs;
|
|
33
42
|
private activeRunId;
|
|
34
43
|
private hydratePromise;
|
|
35
44
|
private hydrated;
|
|
36
|
-
/** Per-run persist chain so intermediate saves cannot overwrite a later final write. */
|
|
37
|
-
private readonly persistChains;
|
|
38
45
|
/** Filled after listen — e.g. `http://127.0.0.1:3000/weather-agent`. */
|
|
39
46
|
loopbackUrl: string | undefined;
|
|
40
47
|
constructor(projectRoot: string, logger: (line: string) => void,
|
|
41
|
-
/**
|
|
42
|
-
|
|
43
|
-
* used when `evals.config.ts` sets no `persistRuns` of its own.
|
|
44
|
-
*/
|
|
45
|
-
fallbackPersistence?: EvalRunPersistence | undefined);
|
|
46
|
-
/** `evals.config.ts` `persistRuns` wins; `defineStorage` is fallback. */
|
|
47
|
-
private resolvePersist;
|
|
48
|
+
/** `defineStorage` evals-table adapter; undefined ⇒ memory only. */
|
|
49
|
+
storage?: EvalRunStorage | undefined);
|
|
48
50
|
list(): Promise<{
|
|
49
51
|
evals: Array<{
|
|
50
52
|
id: string;
|
|
@@ -70,23 +72,24 @@ export declare class EvalRunStore {
|
|
|
70
72
|
start(input?: StartEvalRunInput): Promise<EvalRunSnapshot>;
|
|
71
73
|
private sortedRuns;
|
|
72
74
|
/**
|
|
73
|
-
* Hydrate playground eval history from
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
* Idempotent; concurrent callers share one pass.
|
|
75
|
+
* Hydrate playground eval history from the `defineStorage` evals table.
|
|
76
|
+
* Called eagerly from the serve startup restore step — alongside session
|
|
77
|
+
* restore — and lazily as a safety net by every read. Idempotent;
|
|
78
|
+
* concurrent callers share one pass.
|
|
78
79
|
*/
|
|
79
80
|
hydrate(): Promise<void>;
|
|
80
|
-
private
|
|
81
|
+
private hydrateFromStorage;
|
|
81
82
|
private pruneOldRuns;
|
|
83
|
+
/** Mirror the run onto durable storage (coordinator clones + serializes). */
|
|
84
|
+
private persist;
|
|
82
85
|
/**
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
+
* Serve is draining: durably mark any in-flight batch as interrupted
|
|
87
|
+
* while the storage queue can still deliver. Late `execute` writes are
|
|
88
|
+
* dropped by the closed coordinator, so without this a batch that was
|
|
89
|
+
* running at shutdown would look "running" (or silently lose its final
|
|
90
|
+
* completion write) until the next hydrate repairs it.
|
|
86
91
|
*/
|
|
87
|
-
|
|
88
|
-
private persistSave;
|
|
89
|
-
private persistDelete;
|
|
92
|
+
close(): void;
|
|
90
93
|
private execute;
|
|
91
94
|
private applyCaseResult;
|
|
92
95
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eval-run-store.d.ts","sourceRoot":"","sources":["../../src/internal/eval-run-store.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"eval-run-store.d.ts","sourceRoot":"","sources":["../../src/internal/eval-run-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -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
|
*/
|
|
@@ -22,23 +23,13 @@ const INTERRUPTED_BATCH_ERROR = "Eval run interrupted (serve process exited befo
|
|
|
22
23
|
const INTERRUPTED_CASE_ERROR = "Eval case interrupted (serve process exited before completion)";
|
|
23
24
|
export class EvalRunStore {
|
|
24
25
|
constructor(projectRoot, logger,
|
|
25
|
-
/**
|
|
26
|
-
|
|
27
|
-
* used when `evals.config.ts` sets no `persistRuns` of its own.
|
|
28
|
-
*/
|
|
29
|
-
fallbackPersistence) {
|
|
26
|
+
/** `defineStorage` evals-table adapter; undefined ⇒ memory only. */
|
|
27
|
+
storage) {
|
|
30
28
|
this.projectRoot = projectRoot;
|
|
31
29
|
this.logger = logger;
|
|
32
|
-
this.
|
|
30
|
+
this.storage = storage;
|
|
33
31
|
this.runs = new Map();
|
|
34
32
|
this.hydrated = false;
|
|
35
|
-
/** Per-run persist chain so intermediate saves cannot overwrite a later final write. */
|
|
36
|
-
this.persistChains = new Map();
|
|
37
|
-
}
|
|
38
|
-
/** `evals.config.ts` `persistRuns` wins; `defineStorage` is fallback. */
|
|
39
|
-
resolvePersist(config) {
|
|
40
|
-
var _a;
|
|
41
|
-
return (_a = config.persistRuns) !== null && _a !== void 0 ? _a : this.fallbackPersistence;
|
|
42
33
|
}
|
|
43
34
|
list() {
|
|
44
35
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -48,7 +39,7 @@ export class EvalRunStore {
|
|
|
48
39
|
evals: evals.map((e) => (Object.assign(Object.assign({ id: e.id, fileId: e.fileId }, (e.definition.description === undefined
|
|
49
40
|
? {}
|
|
50
41
|
: { description: e.definition.description })), (e.definition.tags === undefined ? {} : { tags: e.definition.tags })))),
|
|
51
|
-
config: snapshotListConfig(config, this.
|
|
42
|
+
config: snapshotListConfig(config, this.storage !== undefined),
|
|
52
43
|
};
|
|
53
44
|
});
|
|
54
45
|
}
|
|
@@ -114,12 +105,12 @@ export class EvalRunStore {
|
|
|
114
105
|
done: 0,
|
|
115
106
|
},
|
|
116
107
|
cases,
|
|
117
|
-
config: snapshotRunConfig(config, this.
|
|
108
|
+
config: snapshotRunConfig(config, this.storage !== undefined),
|
|
118
109
|
};
|
|
119
110
|
this.runs.set(runId, snapshot);
|
|
120
111
|
this.activeRunId = runId;
|
|
121
|
-
|
|
122
|
-
|
|
112
|
+
this.pruneOldRuns(config);
|
|
113
|
+
this.persist(snapshot);
|
|
123
114
|
this.logger(`[agentkit] eval run ${runId}: starting ${cases.length} case(s)`);
|
|
124
115
|
void this.execute(runId, Object.assign(Object.assign({ baseUrl: loopbackUrl, evals: selected, config }, (input.bearerToken === undefined
|
|
125
116
|
? {}
|
|
@@ -131,11 +122,10 @@ export class EvalRunStore {
|
|
|
131
122
|
return [...this.runs.values()].sort((a, b) => b.startedAt.localeCompare(a.startedAt));
|
|
132
123
|
}
|
|
133
124
|
/**
|
|
134
|
-
* Hydrate playground eval history from
|
|
135
|
-
*
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
* Idempotent; concurrent callers share one pass.
|
|
125
|
+
* Hydrate playground eval history from the `defineStorage` evals table.
|
|
126
|
+
* Called eagerly from the serve startup restore step — alongside session
|
|
127
|
+
* restore — and lazily as a safety net by every read. Idempotent;
|
|
128
|
+
* concurrent callers share one pass.
|
|
139
129
|
*/
|
|
140
130
|
hydrate() {
|
|
141
131
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -143,27 +133,19 @@ export class EvalRunStore {
|
|
|
143
133
|
return;
|
|
144
134
|
}
|
|
145
135
|
if (this.hydratePromise === undefined) {
|
|
146
|
-
this.hydratePromise = this.
|
|
136
|
+
this.hydratePromise = this.hydrateFromStorage();
|
|
147
137
|
}
|
|
148
138
|
yield this.hydratePromise;
|
|
149
139
|
});
|
|
150
140
|
}
|
|
151
|
-
|
|
141
|
+
hydrateFromStorage() {
|
|
152
142
|
return __awaiter(this, void 0, void 0, function* () {
|
|
153
143
|
try {
|
|
154
|
-
|
|
155
|
-
const persist = this.resolvePersist(config);
|
|
156
|
-
if (persist === undefined) {
|
|
157
|
-
this.hydrated = true;
|
|
158
|
-
return;
|
|
159
|
-
}
|
|
160
|
-
const loaded = yield persist.load({ projectRoot: this.projectRoot });
|
|
161
|
-
if (!Array.isArray(loaded)) {
|
|
162
|
-
this.logger("[agentkit] eval persistRuns.load() did not return an array; ignoring");
|
|
144
|
+
if (this.storage === undefined) {
|
|
163
145
|
this.hydrated = true;
|
|
164
146
|
return;
|
|
165
147
|
}
|
|
166
|
-
const
|
|
148
|
+
const loaded = yield this.storage.list();
|
|
167
149
|
for (const run of loaded) {
|
|
168
150
|
if (run === null ||
|
|
169
151
|
typeof run !== "object" ||
|
|
@@ -174,15 +156,22 @@ export class EvalRunStore {
|
|
|
174
156
|
// Incomplete batches from a killed process should not block a new run.
|
|
175
157
|
if (run.status === "running") {
|
|
176
158
|
markInterruptedRun(run);
|
|
177
|
-
|
|
159
|
+
this.persist(run);
|
|
178
160
|
}
|
|
179
161
|
this.runs.set(run.runId, run);
|
|
180
162
|
}
|
|
181
|
-
|
|
182
|
-
|
|
163
|
+
// Prune with the defaults even when eval discovery fails — loaded
|
|
164
|
+
// history must not stay unpruned for the process lifetime just
|
|
165
|
+
// because an eval file has a syntax error at boot.
|
|
166
|
+
let config = {};
|
|
167
|
+
try {
|
|
168
|
+
config = (yield discoverEvals(this.projectRoot)).config;
|
|
169
|
+
}
|
|
170
|
+
catch (error) {
|
|
171
|
+
this.logger(`[agentkit] eval discovery failed during hydrate (pruning with defaults): ${error instanceof Error ? error.message : String(error)}`);
|
|
183
172
|
}
|
|
184
|
-
|
|
185
|
-
this.logger(`[agentkit] hydrated ${this.runs.size} playground eval run(s) from
|
|
173
|
+
this.pruneOldRuns(config);
|
|
174
|
+
this.logger(`[agentkit] hydrated ${this.runs.size} playground eval run(s) from storage`);
|
|
186
175
|
}
|
|
187
176
|
catch (error) {
|
|
188
177
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -194,63 +183,44 @@ export class EvalRunStore {
|
|
|
194
183
|
});
|
|
195
184
|
}
|
|
196
185
|
pruneOldRuns(config) {
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
}
|
|
207
|
-
this.runs.delete(stale.runId);
|
|
208
|
-
yield this.persistDelete(stale.runId, this.resolvePersist(config));
|
|
186
|
+
var _a;
|
|
187
|
+
const limit = resolveEvalMaxPlaygroundRuns(config.maxPlaygroundRuns);
|
|
188
|
+
const ordered = this.sortedRuns();
|
|
189
|
+
if (ordered.length <= limit) {
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
for (const stale of ordered.slice(limit)) {
|
|
193
|
+
if (stale.runId === this.activeRunId) {
|
|
194
|
+
continue;
|
|
209
195
|
}
|
|
210
|
-
|
|
196
|
+
this.runs.delete(stale.runId);
|
|
197
|
+
(_a = this.storage) === null || _a === void 0 ? void 0 : _a.delete(stale.runId);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
/** Mirror the run onto durable storage (coordinator clones + serializes). */
|
|
201
|
+
persist(run) {
|
|
202
|
+
var _a;
|
|
203
|
+
(_a = this.storage) === null || _a === void 0 ? void 0 : _a.save(run);
|
|
211
204
|
}
|
|
212
205
|
/**
|
|
213
|
-
*
|
|
214
|
-
*
|
|
215
|
-
*
|
|
206
|
+
* Serve is draining: durably mark any in-flight batch as interrupted
|
|
207
|
+
* while the storage queue can still deliver. Late `execute` writes are
|
|
208
|
+
* dropped by the closed coordinator, so without this a batch that was
|
|
209
|
+
* running at shutdown would look "running" (or silently lose its final
|
|
210
|
+
* completion write) until the next hydrate repairs it.
|
|
216
211
|
*/
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
if (
|
|
220
|
-
return
|
|
212
|
+
close() {
|
|
213
|
+
const activeRunId = this.activeRunId;
|
|
214
|
+
if (activeRunId === undefined) {
|
|
215
|
+
return;
|
|
221
216
|
}
|
|
222
|
-
const
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
this.
|
|
228
|
-
|
|
229
|
-
}
|
|
230
|
-
persistSave(run, persist) {
|
|
231
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
232
|
-
try {
|
|
233
|
-
yield persist.save(run, { projectRoot: this.projectRoot });
|
|
234
|
-
}
|
|
235
|
-
catch (error) {
|
|
236
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
237
|
-
this.logger(`[agentkit] persistRuns.save(${run.runId}) failed: ${message}`);
|
|
238
|
-
}
|
|
239
|
-
});
|
|
240
|
-
}
|
|
241
|
-
persistDelete(runId, persist) {
|
|
242
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
243
|
-
if (persist === undefined) {
|
|
244
|
-
return;
|
|
245
|
-
}
|
|
246
|
-
try {
|
|
247
|
-
yield persist.delete(runId, { projectRoot: this.projectRoot });
|
|
248
|
-
}
|
|
249
|
-
catch (error) {
|
|
250
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
251
|
-
this.logger(`[agentkit] persistRuns.delete(${runId}) failed: ${message}`);
|
|
252
|
-
}
|
|
253
|
-
});
|
|
217
|
+
const run = this.runs.get(activeRunId);
|
|
218
|
+
if (run === undefined || run.status !== "running") {
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
markInterruptedRun(run);
|
|
222
|
+
this.persist(run);
|
|
223
|
+
this.activeRunId = undefined;
|
|
254
224
|
}
|
|
255
225
|
execute(runId, opts) {
|
|
256
226
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -302,7 +272,7 @@ export class EvalRunStore {
|
|
|
302
272
|
this.applyCaseResult(runId, result);
|
|
303
273
|
const run = this.runs.get(runId);
|
|
304
274
|
if (run !== undefined) {
|
|
305
|
-
|
|
275
|
+
this.persist(run);
|
|
306
276
|
}
|
|
307
277
|
} }));
|
|
308
278
|
const run = this.runs.get(runId);
|
|
@@ -311,7 +281,7 @@ export class EvalRunStore {
|
|
|
311
281
|
}
|
|
312
282
|
run.status = "completed";
|
|
313
283
|
run.finishedAt = new Date().toISOString();
|
|
314
|
-
|
|
284
|
+
this.persist(run);
|
|
315
285
|
this.logger(`[agentkit] eval run ${runId}: done — ${run.summary.passed} passed, ${run.summary.failed} failed`);
|
|
316
286
|
}
|
|
317
287
|
catch (error) {
|
|
@@ -322,7 +292,7 @@ export class EvalRunStore {
|
|
|
322
292
|
run.status = "failed";
|
|
323
293
|
run.finishedAt = new Date().toISOString();
|
|
324
294
|
run.error = error instanceof Error ? error.message : String(error);
|
|
325
|
-
|
|
295
|
+
this.persist(run);
|
|
326
296
|
this.logger(`[agentkit] eval run ${runId}: failed — ${run.error}`);
|
|
327
297
|
}
|
|
328
298
|
finally {
|
|
@@ -383,6 +353,24 @@ function markInterruptedRun(run) {
|
|
|
383
353
|
c.error = (_c = c.error) !== null && _c !== void 0 ? _c : INTERRUPTED_CASE_ERROR;
|
|
384
354
|
}
|
|
385
355
|
}
|
|
356
|
+
// Reconcile the summary with the repaired case rows so a persisted
|
|
357
|
+
// interrupted batch never claims pre-interruption pass counts.
|
|
358
|
+
let passed = 0;
|
|
359
|
+
let failed = 0;
|
|
360
|
+
for (const c of run.cases) {
|
|
361
|
+
if (c.ok === true) {
|
|
362
|
+
passed += 1;
|
|
363
|
+
}
|
|
364
|
+
else {
|
|
365
|
+
failed += 1;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
run.summary = {
|
|
369
|
+
passed,
|
|
370
|
+
failed,
|
|
371
|
+
total: run.cases.length,
|
|
372
|
+
done: run.cases.length,
|
|
373
|
+
};
|
|
386
374
|
}
|
|
387
375
|
function snapshotListConfig(config, durableRuns) {
|
|
388
376
|
return Object.assign(Object.assign(Object.assign({}, (config.maxConcurrency === undefined
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init-project.d.ts","sourceRoot":"","sources":["../../src/internal/init-project.ts"],"names":[],"mappings":"AAAA;;GAEG;AAiBH,MAAM,WAAW,kBAAkB;IACjC,gDAAgD;IAChD,GAAG,EAAE,MAAM,CAAC;IACZ,8DAA8D;IAC9D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEhD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,cAAc,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,iEAAiE;IACjE,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,2BAA2B;IAC3B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,qDAAqD;IACrD,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AA2BD,wBAAsB,WAAW,CAC/B,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,iBAAiB,CAAC,CAgH5B;AAWD,MAAM,WAAW,kCAAkC;IACjD;;;OAGG;IACH,KAAK,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC;IAC3B,yDAAyD;IACzD,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE;QACd,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,EAAE,CAAC;QACf,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE,SAAS,GAAG,MAAM,CAAC;KAC3B,KAAK,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACrD;AAED,MAAM,WAAW,iCAAiC;IAChD,EAAE,EAAE,OAAO,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,kCAAuC,GAC/C,OAAO,CAAC,iCAAiC,CAAC,CAW5C;AAkDD,MAAM,WAAW,0BAA0B;IACzC,0CAA0C;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,0DAA0D;IAC1D,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,+DAA+D;IAC/D,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,oBAAoB;IACnC,0CAA0C;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,sCAAsC;IACtC,GAAG,EAAE,MAAM,CAAC;IACZ;;;OAGG;IACH,QAAQ,EAAE,OAAO,CAAC;IAClB,+DAA+D;IAC/D,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,MAAM,kBAAkB,GAAG,0BAA0B,GACzD,oBAAoB,CAAC;AAMvB;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,0BAA0B,GAClC,MAAM,CAkBR;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,GAAG,MAAM,CAgBzE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,GAAG,MAAM,CAErE;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,GACd,MAAM,GAAG,SAAS,CAQpB;AAwBD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,OAAO,CAAC;CACnB,GAAG,MAAM,EAAE,CAEX;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI,IAAI,
|
|
1
|
+
{"version":3,"file":"init-project.d.ts","sourceRoot":"","sources":["../../src/internal/init-project.ts"],"names":[],"mappings":"AAAA;;GAEG;AAiBH,MAAM,WAAW,kBAAkB;IACjC,gDAAgD;IAChD,GAAG,EAAE,MAAM,CAAC;IACZ,8DAA8D;IAC9D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+CAA+C;IAC/C,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,OAAO,CAAC;AAEhD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,cAAc,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,iEAAiE;IACjE,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,2BAA2B;IAC3B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,qDAAqD;IACrD,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AA2BD,wBAAsB,WAAW,CAC/B,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,iBAAiB,CAAC,CAgH5B;AAWD,MAAM,WAAW,kCAAkC;IACjD;;;OAGG;IACH,KAAK,CAAC,EAAE,SAAS,GAAG,MAAM,CAAC;IAC3B,yDAAyD;IACzD,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE;QACd,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,EAAE,CAAC;QACf,GAAG,EAAE,MAAM,CAAC;QACZ,KAAK,EAAE,SAAS,GAAG,MAAM,CAAC;KAC3B,KAAK,OAAO,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACrD;AAED,MAAM,WAAW,iCAAiC;IAChD,EAAE,EAAE,OAAO,CAAC;IACZ,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAsB,2BAA2B,CAC/C,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,kCAAuC,GAC/C,OAAO,CAAC,iCAAiC,CAAC,CAW5C;AAkDD,MAAM,WAAW,0BAA0B;IACzC,0CAA0C;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,0DAA0D;IAC1D,KAAK,EAAE,aAAa,EAAE,CAAC;IACvB,+DAA+D;IAC/D,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,oBAAoB;IACnC,0CAA0C;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,sCAAsC;IACtC,GAAG,EAAE,MAAM,CAAC;IACZ;;;OAGG;IACH,QAAQ,EAAE,OAAO,CAAC;IAClB,+DAA+D;IAC/D,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,MAAM,kBAAkB,GAAG,0BAA0B,GACzD,oBAAoB,CAAC;AAMvB;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,0BAA0B,GAClC,MAAM,CAkBR;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,GAAG,MAAM,CAgBzE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,kBAAkB,GAAG,MAAM,CAErE;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,GACd,MAAM,GAAG,SAAS,CAQpB;AAwBD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,OAAO,CAAC;CACnB,GAAG,MAAM,EAAE,CAEX;AAED;;;GAGG;AACH,wBAAgB,cAAc,IAAI,IAAI,CAuBrC"}
|