@noetaris/harness 0.10.0 → 0.12.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 +157 -9
- package/dist/index.d.ts +276 -19
- package/dist/index.js +978 -264
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -634,16 +634,14 @@ function extractRunListeners(resources) {
|
|
|
634
634
|
// src/agent/ctx-within.ts
|
|
635
635
|
function createWithinFn(observer, currentStep, onObserverError) {
|
|
636
636
|
return (type, payload, fn) => {
|
|
637
|
-
const wrap = observer?.wrap;
|
|
638
637
|
const stepCtx = currentStep();
|
|
639
|
-
if (wrap === void 0 || stepCtx === null) return fn();
|
|
640
|
-
return runWrapped((inner) => wrap(stepCtx, { kind: "event", type, payload }, inner), fn, onObserverError);
|
|
638
|
+
if (observer?.wrap === void 0 || stepCtx === null) return fn();
|
|
639
|
+
return runWrapped((inner) => observer.wrap?.(stepCtx, { kind: "event", type, payload }, inner), fn, onObserverError);
|
|
641
640
|
};
|
|
642
641
|
}
|
|
643
642
|
function runStepScope(observer, stepCtx, fn, onObserverError) {
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
return runWrapped((inner) => wrap(stepCtx, { kind: "step" }, inner), fn, onObserverError);
|
|
643
|
+
if (observer?.wrap === void 0) return fn();
|
|
644
|
+
return runWrapped((inner) => observer.wrap?.(stepCtx, { kind: "step" }, inner), fn, onObserverError);
|
|
647
645
|
}
|
|
648
646
|
|
|
649
647
|
// src/loop/loop-executor.ts
|
|
@@ -707,10 +705,9 @@ function applyUpdate(state, update, schema, touchedKeys) {
|
|
|
707
705
|
}
|
|
708
706
|
}
|
|
709
707
|
function fireSettled(obs, stepCtx, stepStart, fields, onObserverError) {
|
|
710
|
-
|
|
711
|
-
if (hook === void 0) return;
|
|
708
|
+
if (obs?.onStepSettled === void 0) return;
|
|
712
709
|
const event = { ...fields, durationMs: Date.now() - stepStart };
|
|
713
|
-
safeInvoke("onStepSettled", () =>
|
|
710
|
+
safeInvoke("onStepSettled", () => obs.onStepSettled?.(stepCtx, event), onObserverError);
|
|
714
711
|
}
|
|
715
712
|
function stepContextOf(runCtx, stepName) {
|
|
716
713
|
return {
|
|
@@ -745,11 +742,13 @@ async function runLoop(graph, state, ctx, schema, shouldStop, startCursor, callb
|
|
|
745
742
|
sessionId: ctx.sessionId,
|
|
746
743
|
runId: typeof callbacks?.runId === "string" ? callbacks.runId : "",
|
|
747
744
|
...typeof callbacks?.parentRunId === "string" ? { parentRunId: callbacks.parentRunId } : {},
|
|
745
|
+
...typeof callbacks?.requestId === "string" ? { requestId: callbacks.requestId } : {},
|
|
748
746
|
...typeof ctx.instanceId === "string" ? { instanceId: ctx.instanceId } : {},
|
|
749
747
|
...isBranch ? { branchPath } : {},
|
|
750
748
|
// Branch runLoops receive the outer callbacks by spread, so the refs are dropped here.
|
|
751
749
|
...!isBranch && callbacks?.resumedFrom !== void 0 ? { resumedFrom: callbacks.resumedFrom } : {},
|
|
752
|
-
...!isBranch && callbacks?.branchedFrom !== void 0 ? { branchedFrom: callbacks.branchedFrom } : {}
|
|
750
|
+
...!isBranch && callbacks?.branchedFrom !== void 0 ? { branchedFrom: callbacks.branchedFrom } : {},
|
|
751
|
+
...!isBranch && callbacks?.continuedFrom !== void 0 ? { continuedFrom: callbacks.continuedFrom } : {}
|
|
753
752
|
};
|
|
754
753
|
safeInvoke("onRunStart", () => obs?.onRunStart?.(runCtx), onObserverError);
|
|
755
754
|
const carrier = isBranch ? void 0 : normalizeCarrier(safeCall("carry", () => obs?.carry?.(runCtx), onObserverError));
|
|
@@ -773,6 +772,24 @@ async function runLoop(graph, state, ctx, schema, shouldStop, startCursor, callb
|
|
|
773
772
|
endRun("$stopped");
|
|
774
773
|
return withCarrier({ state, signal: null, cursor, paused: true });
|
|
775
774
|
}
|
|
775
|
+
if (callbacks?.debugGate !== void 0) {
|
|
776
|
+
const next = isForkCursor(cursor) ? cursor.fork : cursor;
|
|
777
|
+
const fork = isForkCursor(cursor) || graph.steps.some((s) => s.name === next && isForkDef(s));
|
|
778
|
+
const { patches, halt } = await callbacks.debugGate(next, state, {
|
|
779
|
+
branchPath: branchPath ?? [],
|
|
780
|
+
fork,
|
|
781
|
+
...callbacks.touchedKeys !== void 0 ? { touchedKeys: callbacks.touchedKeys } : {},
|
|
782
|
+
...ctx.signal !== void 0 ? { signal: ctx.signal } : {}
|
|
783
|
+
});
|
|
784
|
+
const nextCtx = stepContextOf(runCtx, next);
|
|
785
|
+
for (const patch of patches) {
|
|
786
|
+
safeInvoke("onEvent", () => obs?.onEvent?.(nextCtx, "debug.setState", { patch }), onObserverError);
|
|
787
|
+
}
|
|
788
|
+
if (halt || shouldStop?.()) {
|
|
789
|
+
endRun("$stopped");
|
|
790
|
+
return withCarrier({ state, signal: null, cursor, paused: true });
|
|
791
|
+
}
|
|
792
|
+
}
|
|
776
793
|
if (isForkCursor(cursor)) {
|
|
777
794
|
const forkCursor = cursor;
|
|
778
795
|
const forkNode = graph.steps.find((s) => s.name === forkCursor.fork);
|
|
@@ -1026,6 +1043,7 @@ async function dispatchFork(forkNode, priorBranches, outerState, outerCtx, schem
|
|
|
1026
1043
|
} else {
|
|
1027
1044
|
outerState[key] = outcome.result.state[key];
|
|
1028
1045
|
}
|
|
1046
|
+
callbacks?.touchedKeys?.add(key);
|
|
1029
1047
|
}
|
|
1030
1048
|
}
|
|
1031
1049
|
return {
|
|
@@ -1181,6 +1199,15 @@ var SessionInFlightError = class extends Error {
|
|
|
1181
1199
|
this.sessionId = sessionId;
|
|
1182
1200
|
}
|
|
1183
1201
|
};
|
|
1202
|
+
var SessionInDebugError = class extends Error {
|
|
1203
|
+
/** The session being debugged. */
|
|
1204
|
+
sessionId;
|
|
1205
|
+
constructor(sessionId) {
|
|
1206
|
+
super(`session "${sessionId}" is being debugged`);
|
|
1207
|
+
this.name = "SessionInDebugError";
|
|
1208
|
+
this.sessionId = sessionId;
|
|
1209
|
+
}
|
|
1210
|
+
};
|
|
1184
1211
|
var SessionPendingInterruptError = class extends Error {
|
|
1185
1212
|
/** The session that is awaiting an interrupt response. */
|
|
1186
1213
|
sessionId;
|
|
@@ -1287,12 +1314,32 @@ async function querySessionPhase(store, agentId, sessionId) {
|
|
|
1287
1314
|
return storedSessionToPhase(loaded);
|
|
1288
1315
|
}
|
|
1289
1316
|
function runRefsOf(loaded) {
|
|
1290
|
-
if (loaded === null
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
}
|
|
1317
|
+
if (loaded === null) return {};
|
|
1318
|
+
const ref = { runId: loaded.runId, ...loaded.carrier !== void 0 ? { carrier: loaded.carrier } : {} };
|
|
1319
|
+
if (loaded.phase === "completed") return { continuedFrom: ref };
|
|
1320
|
+
if (loaded.step !== void 0) return { resumedFrom: ref };
|
|
1294
1321
|
return loaded.branchedFrom !== void 0 ? { branchedFrom: loaded.branchedFrom } : {};
|
|
1295
1322
|
}
|
|
1323
|
+
function decideRun(args) {
|
|
1324
|
+
const { loaded, older, mode, requestId, sessionId } = args;
|
|
1325
|
+
if (loaded === null) return { action: "start" };
|
|
1326
|
+
const pending = loaded.phase === "paused" && collectPendingInterrupts(loaded.step, loaded.finalState).length > 0;
|
|
1327
|
+
if (mode === "resume") {
|
|
1328
|
+
return loaded.phase === "completed" ? { action: "replay", row: loaded } : { action: "continue", mergeInput: false };
|
|
1329
|
+
}
|
|
1330
|
+
if (requestId !== void 0 && loaded.requestId === requestId) {
|
|
1331
|
+
if (loaded.phase === "completed" || pending) return { action: "replay", row: loaded };
|
|
1332
|
+
return { action: "continue", mergeInput: false };
|
|
1333
|
+
}
|
|
1334
|
+
if (older !== null) return { action: "replay", row: older };
|
|
1335
|
+
if (loaded.phase === "completed") return { action: "new-turn" };
|
|
1336
|
+
if (pending) return { action: "reject", error: new SessionPendingInterruptError(sessionId) };
|
|
1337
|
+
return { action: "continue", mergeInput: true };
|
|
1338
|
+
}
|
|
1339
|
+
function withoutSystemFields(loaded) {
|
|
1340
|
+
const { $error: _error, $interrupt: _interrupt, $interruptResponses: _responses, ...finalState } = loaded.finalState;
|
|
1341
|
+
return { ...loaded, finalState };
|
|
1342
|
+
}
|
|
1296
1343
|
async function runWithSession(store, agentId, sessionId, runId, graph, initialStateArg, schema, ctx, options) {
|
|
1297
1344
|
const leaseRef = options?.leaseRef ?? { current: null };
|
|
1298
1345
|
const keepAlive = createKeepAliveFn(leaseRef, store, options?.claimTtlMs ?? defaultClaimTtlMs());
|
|
@@ -1306,10 +1353,11 @@ async function runWithSession(store, agentId, sessionId, runId, graph, initialSt
|
|
|
1306
1353
|
}
|
|
1307
1354
|
return false;
|
|
1308
1355
|
};
|
|
1356
|
+
const { mode = "run", requestId: callerRequestId, ...loopOptions } = options ?? {};
|
|
1309
1357
|
if (store === void 0) {
|
|
1310
1358
|
const state2 = initializeState(null, initialStateArg, schema);
|
|
1311
1359
|
const result2 = await runLoop(graph, state2, ctx, schema, composedShouldStop, void 0, {
|
|
1312
|
-
...
|
|
1360
|
+
...loopOptions,
|
|
1313
1361
|
runId,
|
|
1314
1362
|
...options?.parentRunId !== void 0 ? { parentRunId: options.parentRunId } : {}
|
|
1315
1363
|
});
|
|
@@ -1320,31 +1368,46 @@ async function runWithSession(store, agentId, sessionId, runId, graph, initialSt
|
|
|
1320
1368
|
}
|
|
1321
1369
|
return result2;
|
|
1322
1370
|
}
|
|
1371
|
+
const requestId = mode === "run" ? callerRequestId : void 0;
|
|
1372
|
+
const fail = (error) => {
|
|
1373
|
+
const failState = initializeState(null, initialStateArg, schema);
|
|
1374
|
+
failState["$error"] = error;
|
|
1375
|
+
return { state: failState, signal: "$error", paused: false, cursor: null };
|
|
1376
|
+
};
|
|
1323
1377
|
let loaded;
|
|
1378
|
+
let older = null;
|
|
1324
1379
|
try {
|
|
1325
1380
|
loaded = await store.load(agentId, sessionId);
|
|
1381
|
+
if (requestId !== void 0 && loaded !== null && loaded.requestId !== requestId && typeof store.findRequest === "function") {
|
|
1382
|
+
older = await store.findRequest(agentId, sessionId, requestId);
|
|
1383
|
+
}
|
|
1326
1384
|
} catch (error) {
|
|
1327
1385
|
const storeError = new StoreLoadError(error);
|
|
1328
1386
|
options?.onStoreError?.(storeError, "load");
|
|
1329
|
-
|
|
1330
|
-
failState["$error"] = storeError;
|
|
1331
|
-
return { state: failState, signal: "$error", paused: false, cursor: null };
|
|
1387
|
+
return fail(storeError);
|
|
1332
1388
|
}
|
|
1333
|
-
|
|
1389
|
+
const decision = decideRun({ loaded, older, mode, requestId, sessionId });
|
|
1390
|
+
if (decision.action === "reject") return fail(decision.error);
|
|
1391
|
+
if (decision.action === "replay") {
|
|
1392
|
+
const { row } = decision;
|
|
1334
1393
|
return {
|
|
1335
|
-
state:
|
|
1336
|
-
signal:
|
|
1337
|
-
cursor: null,
|
|
1338
|
-
paused:
|
|
1394
|
+
state: row.finalState,
|
|
1395
|
+
signal: row.signal ?? null,
|
|
1396
|
+
cursor: row.step ?? null,
|
|
1397
|
+
paused: row.phase === "paused"
|
|
1339
1398
|
};
|
|
1340
1399
|
}
|
|
1341
|
-
const
|
|
1400
|
+
const segmentRequestId = mode === "run" ? requestId : loaded?.requestId;
|
|
1401
|
+
const base = decision.action === "new-turn" && loaded !== null ? withoutSystemFields(loaded) : loaded;
|
|
1402
|
+
const input = decision.action === "continue" && !decision.mergeInput ? {} : initialStateArg;
|
|
1403
|
+
const state = initializeState(base, input, schema);
|
|
1342
1404
|
const initialStateSnapshot = { ...state };
|
|
1343
1405
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
1344
1406
|
const result = await runLoop(graph, state, ctx, schema, composedShouldStop, loaded?.step, {
|
|
1345
|
-
...
|
|
1407
|
+
...loopOptions,
|
|
1346
1408
|
runId,
|
|
1347
1409
|
...options?.parentRunId !== void 0 ? { parentRunId: options.parentRunId } : {},
|
|
1410
|
+
...segmentRequestId !== void 0 ? { requestId: segmentRequestId } : {},
|
|
1348
1411
|
...runRefsOf(loaded)
|
|
1349
1412
|
});
|
|
1350
1413
|
if (leaseExpired) {
|
|
@@ -1370,7 +1433,8 @@ async function runWithSession(store, agentId, sessionId, runId, graph, initialSt
|
|
|
1370
1433
|
step: result.cursor,
|
|
1371
1434
|
...result.signal !== null ? { signal: result.signal } : {},
|
|
1372
1435
|
...metadata !== void 0 ? { metadata } : {},
|
|
1373
|
-
...result.carrier !== void 0 ? { carrier: result.carrier } : {}
|
|
1436
|
+
...result.carrier !== void 0 ? { carrier: result.carrier } : {},
|
|
1437
|
+
...segmentRequestId !== void 0 ? { requestId: segmentRequestId } : {}
|
|
1374
1438
|
};
|
|
1375
1439
|
await store.save(agentId, sessionId, saved);
|
|
1376
1440
|
} else {
|
|
@@ -1386,7 +1450,8 @@ async function runWithSession(store, agentId, sessionId, runId, graph, initialSt
|
|
|
1386
1450
|
finalState: result.state,
|
|
1387
1451
|
...result.signal !== null ? { signal: result.signal } : {},
|
|
1388
1452
|
...metadata !== void 0 ? { metadata } : {},
|
|
1389
|
-
...result.carrier !== void 0 ? { carrier: result.carrier } : {}
|
|
1453
|
+
...result.carrier !== void 0 ? { carrier: result.carrier } : {},
|
|
1454
|
+
...segmentRequestId !== void 0 ? { requestId: segmentRequestId } : {}
|
|
1390
1455
|
};
|
|
1391
1456
|
await store.save(agentId, sessionId, saved);
|
|
1392
1457
|
}
|
|
@@ -1510,7 +1575,8 @@ async function injectInterruptResponse(store, agentId, sessionId, interruptId, r
|
|
|
1510
1575
|
...loaded.signal !== void 0 ? { signal: loaded.signal } : {},
|
|
1511
1576
|
...loaded.metadata !== void 0 ? { metadata: loaded.metadata } : {},
|
|
1512
1577
|
...loaded.carrier !== void 0 ? { carrier: loaded.carrier } : {},
|
|
1513
|
-
...loaded.branchedFrom !== void 0 ? { branchedFrom: loaded.branchedFrom } : {}
|
|
1578
|
+
...loaded.branchedFrom !== void 0 ? { branchedFrom: loaded.branchedFrom } : {},
|
|
1579
|
+
...loaded.requestId !== void 0 ? { requestId: loaded.requestId } : {}
|
|
1514
1580
|
};
|
|
1515
1581
|
await store.save(agentId, sessionId, updated);
|
|
1516
1582
|
}
|
|
@@ -1576,6 +1642,572 @@ function createRunHandle(sessionId, runId, execution, stopFlag, stepRef, resumeF
|
|
|
1576
1642
|
return handle;
|
|
1577
1643
|
}
|
|
1578
1644
|
|
|
1645
|
+
// src/agent/debug-session.ts
|
|
1646
|
+
var DebugCommandError = class extends Error {
|
|
1647
|
+
/**
|
|
1648
|
+
* - `busy`: another command is still running
|
|
1649
|
+
* - `not-held`: the focused frame is not held at a step stop (or, for `answer`, the session is not at
|
|
1650
|
+
* an interrupt stop; for `focus`, the frame is not held)
|
|
1651
|
+
* - `not-a-fork`: `stepInto` where the next step is not a fork node
|
|
1652
|
+
* - `reserved-key`: `setState` was given a framework key (`$…`)
|
|
1653
|
+
* - `ended`: the session is over
|
|
1654
|
+
*/
|
|
1655
|
+
reason;
|
|
1656
|
+
/** The command that was refused. */
|
|
1657
|
+
command;
|
|
1658
|
+
constructor(reason, command, detail) {
|
|
1659
|
+
super(`${command}(): ${detail ?? describeReason(reason)}`);
|
|
1660
|
+
this.name = "DebugCommandError";
|
|
1661
|
+
this.reason = reason;
|
|
1662
|
+
this.command = command;
|
|
1663
|
+
}
|
|
1664
|
+
};
|
|
1665
|
+
function describeReason(reason) {
|
|
1666
|
+
switch (reason) {
|
|
1667
|
+
case "busy":
|
|
1668
|
+
return "another debug command is still running";
|
|
1669
|
+
case "not-held":
|
|
1670
|
+
return "the debug session is not stopped where this command applies";
|
|
1671
|
+
case "not-a-fork":
|
|
1672
|
+
return "the next step is not a fork";
|
|
1673
|
+
case "reserved-key":
|
|
1674
|
+
return "framework keys ($\u2026) cannot be set";
|
|
1675
|
+
case "ended":
|
|
1676
|
+
return "the debug session has ended";
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
function cloneOrShare(value) {
|
|
1680
|
+
try {
|
|
1681
|
+
return { value: structuredClone(value), shared: false };
|
|
1682
|
+
} catch {
|
|
1683
|
+
return { value, shared: true };
|
|
1684
|
+
}
|
|
1685
|
+
}
|
|
1686
|
+
function snapshotOf(source) {
|
|
1687
|
+
const values = {};
|
|
1688
|
+
const shared = [];
|
|
1689
|
+
for (const [key, raw] of Object.entries(source)) {
|
|
1690
|
+
const copy = cloneOrShare(raw);
|
|
1691
|
+
values[key] = copy.value;
|
|
1692
|
+
if (copy.shared) shared.push(key);
|
|
1693
|
+
}
|
|
1694
|
+
return { values, shared };
|
|
1695
|
+
}
|
|
1696
|
+
function deferred() {
|
|
1697
|
+
let resolve;
|
|
1698
|
+
let reject;
|
|
1699
|
+
const promise = new Promise((res, rej) => {
|
|
1700
|
+
resolve = res;
|
|
1701
|
+
reject = rej;
|
|
1702
|
+
});
|
|
1703
|
+
promise.catch(() => {
|
|
1704
|
+
});
|
|
1705
|
+
return { promise, resolve, reject };
|
|
1706
|
+
}
|
|
1707
|
+
var keyOf = (path) => JSON.stringify(path);
|
|
1708
|
+
var samePath = (a, b) => a.length === b.length && a.every((s, i) => s === b[i]);
|
|
1709
|
+
var within = (path, root) => path.length >= root.length && root.every((s, i) => s === path[i]);
|
|
1710
|
+
function branchStart(parentForkMode) {
|
|
1711
|
+
return {
|
|
1712
|
+
mode: parentForkMode === "fork-entry" ? "fork-entry" : "continue",
|
|
1713
|
+
lastRelease: parentForkMode === "continue" || parentForkMode === void 0 ? "continue" : "hold"
|
|
1714
|
+
};
|
|
1715
|
+
}
|
|
1716
|
+
function createDebugSession(args) {
|
|
1717
|
+
const { store, signal, onEnd } = args;
|
|
1718
|
+
let status = "starting";
|
|
1719
|
+
let handle;
|
|
1720
|
+
let topMode = "start";
|
|
1721
|
+
let frames = /* @__PURE__ */ new Map();
|
|
1722
|
+
let seq = 0;
|
|
1723
|
+
let focus = [];
|
|
1724
|
+
let lastByFrame = /* @__PURE__ */ new Map();
|
|
1725
|
+
let topInterrupt;
|
|
1726
|
+
let interrupts = [];
|
|
1727
|
+
let pausedForks = /* @__PURE__ */ new Map();
|
|
1728
|
+
let paused;
|
|
1729
|
+
let stopRequested = false;
|
|
1730
|
+
let lease = {};
|
|
1731
|
+
let renewal;
|
|
1732
|
+
const breakpoints = /* @__PURE__ */ new Map();
|
|
1733
|
+
let command;
|
|
1734
|
+
let idle;
|
|
1735
|
+
const first = deferred();
|
|
1736
|
+
let current = first.promise;
|
|
1737
|
+
let started = false;
|
|
1738
|
+
const ended = deferred();
|
|
1739
|
+
const done = deferred();
|
|
1740
|
+
const anyHeld = () => [...frames.values()].some((f) => f.status === "held");
|
|
1741
|
+
const updateRenewal = () => {
|
|
1742
|
+
if (!anyHeld()) {
|
|
1743
|
+
if (renewal !== void 0) clearInterval(renewal);
|
|
1744
|
+
renewal = void 0;
|
|
1745
|
+
return;
|
|
1746
|
+
}
|
|
1747
|
+
if (renewal !== void 0) return;
|
|
1748
|
+
const { leaseRef, claimTtlMs } = lease;
|
|
1749
|
+
const extendClaim = store?.extendClaim;
|
|
1750
|
+
if (leaseRef === void 0 || claimTtlMs === void 0 || typeof extendClaim !== "function") return;
|
|
1751
|
+
const renew = () => {
|
|
1752
|
+
const held = leaseRef.current;
|
|
1753
|
+
if (held === null) return;
|
|
1754
|
+
extendClaim.call(store, held, { ttlMs: claimTtlMs }).then((renewed) => {
|
|
1755
|
+
leaseRef.current = renewed;
|
|
1756
|
+
}, () => {
|
|
1757
|
+
});
|
|
1758
|
+
};
|
|
1759
|
+
renew();
|
|
1760
|
+
renewal = setInterval(renew, claimTtlMs / 3);
|
|
1761
|
+
renewal.unref?.();
|
|
1762
|
+
};
|
|
1763
|
+
const frameOf = (path) => frames.get(keyOf(path));
|
|
1764
|
+
const addFrame = (path, init) => {
|
|
1765
|
+
const frame = { path, seq: seq++, patches: [], ...init };
|
|
1766
|
+
frames.set(keyOf(path), frame);
|
|
1767
|
+
return frame;
|
|
1768
|
+
};
|
|
1769
|
+
const treeOrder = (a, b) => {
|
|
1770
|
+
const n = Math.min(a.path.length, b.path.length);
|
|
1771
|
+
for (let i = 0; i < n; i++) {
|
|
1772
|
+
if (a.path[i] !== b.path[i]) {
|
|
1773
|
+
const sa = frameOf(a.path.slice(0, i + 1))?.seq ?? 0;
|
|
1774
|
+
const sb = frameOf(b.path.slice(0, i + 1))?.seq ?? 0;
|
|
1775
|
+
return sa - sb;
|
|
1776
|
+
}
|
|
1777
|
+
}
|
|
1778
|
+
return a.path.length - b.path.length;
|
|
1779
|
+
};
|
|
1780
|
+
const sortedFrames = () => [...frames.values()].sort(treeOrder);
|
|
1781
|
+
const dropDescendants = (root) => {
|
|
1782
|
+
for (const [key, frame] of frames) {
|
|
1783
|
+
if (frame.path.length > root.length && within(frame.path, root)) frames.delete(key);
|
|
1784
|
+
}
|
|
1785
|
+
};
|
|
1786
|
+
const seedPausedFork = (frame, forkName) => {
|
|
1787
|
+
const settled = pausedForks.get(keyOf(frame.path));
|
|
1788
|
+
if (settled?.fork === void 0 || settled.name !== forkName) return;
|
|
1789
|
+
pausedForks.delete(keyOf(frame.path));
|
|
1790
|
+
for (const branch of settled.fork.branches) {
|
|
1791
|
+
addFrame([...frame.path, branch.name], { status: branch.status === "done" ? "ended" : "running", ...branchStart(frame.forkMode) });
|
|
1792
|
+
}
|
|
1793
|
+
};
|
|
1794
|
+
const setCurrent = (stop) => {
|
|
1795
|
+
current = Promise.resolve(stop);
|
|
1796
|
+
if (!started) {
|
|
1797
|
+
started = true;
|
|
1798
|
+
first.resolve(stop);
|
|
1799
|
+
}
|
|
1800
|
+
};
|
|
1801
|
+
const deliver = (stop, frame) => {
|
|
1802
|
+
focus = frame;
|
|
1803
|
+
setCurrent(stop);
|
|
1804
|
+
const c = command;
|
|
1805
|
+
command = void 0;
|
|
1806
|
+
c?.result.resolve(stop);
|
|
1807
|
+
const w = idle;
|
|
1808
|
+
idle = void 0;
|
|
1809
|
+
w?.resolve(stop);
|
|
1810
|
+
};
|
|
1811
|
+
const offerStop = (stop) => {
|
|
1812
|
+
if (!started) return deliver(stop, stop.frame);
|
|
1813
|
+
if (command !== void 0) {
|
|
1814
|
+
const { target, orphan } = command;
|
|
1815
|
+
if (target === "any" || orphan !== void 0 || within(stop.frame, target)) deliver(stop, stop.frame);
|
|
1816
|
+
return;
|
|
1817
|
+
}
|
|
1818
|
+
if (idle !== void 0) deliver(stop, stop.frame);
|
|
1819
|
+
};
|
|
1820
|
+
const branchEndStop = (frame, endedFrame) => {
|
|
1821
|
+
const held = frame.stop;
|
|
1822
|
+
const stop = {
|
|
1823
|
+
kind: "step",
|
|
1824
|
+
frame: frame.path,
|
|
1825
|
+
reason: "branch-end",
|
|
1826
|
+
ended: endedFrame,
|
|
1827
|
+
runId: held.runId,
|
|
1828
|
+
next: held.next,
|
|
1829
|
+
...held.last !== void 0 ? { last: held.last } : {},
|
|
1830
|
+
state: held.state
|
|
1831
|
+
};
|
|
1832
|
+
frame.stop = stop;
|
|
1833
|
+
return stop;
|
|
1834
|
+
};
|
|
1835
|
+
const afterFrameEnd = (endedFrame) => {
|
|
1836
|
+
setTimeout(() => {
|
|
1837
|
+
if (status !== "active") return;
|
|
1838
|
+
const heldFrame = sortedFrames().find((f) => f.status === "held");
|
|
1839
|
+
if (command !== void 0) {
|
|
1840
|
+
if (command.orphan !== endedFrame) return;
|
|
1841
|
+
if (heldFrame !== void 0) deliver(branchEndStop(heldFrame, endedFrame), heldFrame.path);
|
|
1842
|
+
return;
|
|
1843
|
+
}
|
|
1844
|
+
if (!samePath(focus, endedFrame.frame)) return;
|
|
1845
|
+
if (heldFrame !== void 0) {
|
|
1846
|
+
focus = heldFrame.path;
|
|
1847
|
+
setCurrent(branchEndStop(heldFrame, endedFrame));
|
|
1848
|
+
} else {
|
|
1849
|
+
idle ??= deferred();
|
|
1850
|
+
current = idle.promise;
|
|
1851
|
+
}
|
|
1852
|
+
}, 0);
|
|
1853
|
+
};
|
|
1854
|
+
const onFrameEnd = (path, signal2) => {
|
|
1855
|
+
const frame = frameOf(path);
|
|
1856
|
+
if (frame === void 0) return;
|
|
1857
|
+
frame.status = "ended";
|
|
1858
|
+
const parent = frameOf(path.slice(0, -1));
|
|
1859
|
+
if (parent !== void 0) parent.joinHold = frame.lastRelease === "hold";
|
|
1860
|
+
const outcome = signal2 === "$interrupt" ? "interrupt" : signal2 === "$error" ? "error" : signal2 === "$stopped" ? "stopped" : "done";
|
|
1861
|
+
const last = lastByFrame.get(keyOf(path));
|
|
1862
|
+
const endedFrame = { frame: path, outcome, ...last !== void 0 ? { last } : {} };
|
|
1863
|
+
updateRenewal();
|
|
1864
|
+
if (command !== void 0) {
|
|
1865
|
+
if (command.target !== "any" && samePath(command.target, path)) {
|
|
1866
|
+
command.orphan = endedFrame;
|
|
1867
|
+
afterFrameEnd(endedFrame);
|
|
1868
|
+
}
|
|
1869
|
+
return;
|
|
1870
|
+
}
|
|
1871
|
+
if (samePath(focus, path)) afterFrameEnd(endedFrame);
|
|
1872
|
+
};
|
|
1873
|
+
const onAbort = () => {
|
|
1874
|
+
void session.stop();
|
|
1875
|
+
};
|
|
1876
|
+
const cleanup = () => {
|
|
1877
|
+
for (const frame of frames.values()) if (frame.status === "held") frame.status = "ended";
|
|
1878
|
+
updateRenewal();
|
|
1879
|
+
signal?.removeEventListener("abort", onAbort);
|
|
1880
|
+
onEnd();
|
|
1881
|
+
};
|
|
1882
|
+
const topLast = () => lastByFrame.get(keyOf([]));
|
|
1883
|
+
const finish = (outcome) => {
|
|
1884
|
+
const last = topLast();
|
|
1885
|
+
const stop = { kind: "end", runId: handle.runId, ...last !== void 0 ? { last } : {}, outcome };
|
|
1886
|
+
status = "ended";
|
|
1887
|
+
cleanup();
|
|
1888
|
+
done.resolve(outcome);
|
|
1889
|
+
deliver(stop, []);
|
|
1890
|
+
ended.resolve(stop);
|
|
1891
|
+
};
|
|
1892
|
+
const fail = (error) => {
|
|
1893
|
+
status = "ended";
|
|
1894
|
+
cleanup();
|
|
1895
|
+
done.reject(error);
|
|
1896
|
+
const c = command;
|
|
1897
|
+
command = void 0;
|
|
1898
|
+
c?.result.reject(error);
|
|
1899
|
+
const w = idle;
|
|
1900
|
+
idle = void 0;
|
|
1901
|
+
w?.reject(error);
|
|
1902
|
+
if (!started) first.reject(error);
|
|
1903
|
+
else current = done.promise.then(() => {
|
|
1904
|
+
throw error;
|
|
1905
|
+
});
|
|
1906
|
+
current.catch(() => {
|
|
1907
|
+
});
|
|
1908
|
+
ended.reject(error);
|
|
1909
|
+
};
|
|
1910
|
+
const pendingInterrupts = () => {
|
|
1911
|
+
const pending = [];
|
|
1912
|
+
const walk = (path) => {
|
|
1913
|
+
const settled = lastByFrame.get(keyOf(path));
|
|
1914
|
+
if (settled?.fork === void 0) return;
|
|
1915
|
+
for (const branch of settled.fork.branches) {
|
|
1916
|
+
if (branch.status !== "paused") continue;
|
|
1917
|
+
const branchPath = [...path, branch.name];
|
|
1918
|
+
const raised = interrupts.find((i) => samePath(i.branchPath, branchPath));
|
|
1919
|
+
if (raised !== void 0) pending.push({ interruptId: raised.interruptId, prompt: raised.prompt, frame: branchPath });
|
|
1920
|
+
else walk(branchPath);
|
|
1921
|
+
}
|
|
1922
|
+
};
|
|
1923
|
+
if (topInterrupt !== void 0 && topLast()?.fork === void 0) {
|
|
1924
|
+
pending.push({ interruptId: topInterrupt.interruptId, prompt: topInterrupt.prompt, frame: [] });
|
|
1925
|
+
} else {
|
|
1926
|
+
walk([]);
|
|
1927
|
+
}
|
|
1928
|
+
return pending;
|
|
1929
|
+
};
|
|
1930
|
+
const attach = (h) => {
|
|
1931
|
+
h.then((outcome) => {
|
|
1932
|
+
const last = topLast();
|
|
1933
|
+
if (outcome.signal === "$interrupt" && !stopRequested && last !== void 0) {
|
|
1934
|
+
const pending = pendingInterrupts();
|
|
1935
|
+
const head = pending[0];
|
|
1936
|
+
if (head !== void 0) {
|
|
1937
|
+
status = "interrupt";
|
|
1938
|
+
paused = { outcome, pending };
|
|
1939
|
+
for (const frame of frames.values()) if (frame.status === "held") frame.status = "ended";
|
|
1940
|
+
updateRenewal();
|
|
1941
|
+
deliver({
|
|
1942
|
+
kind: "interrupt",
|
|
1943
|
+
frame: head.frame,
|
|
1944
|
+
runId: h.runId,
|
|
1945
|
+
last,
|
|
1946
|
+
interruptId: head.interruptId,
|
|
1947
|
+
prompt: head.prompt,
|
|
1948
|
+
pending,
|
|
1949
|
+
state: snapshotOf(outcome.state)
|
|
1950
|
+
}, head.frame);
|
|
1951
|
+
return;
|
|
1952
|
+
}
|
|
1953
|
+
}
|
|
1954
|
+
finish(outcome);
|
|
1955
|
+
}, fail);
|
|
1956
|
+
};
|
|
1957
|
+
const gate = async (next, state, info) => {
|
|
1958
|
+
const path = info.branchPath;
|
|
1959
|
+
let frame = frameOf(path);
|
|
1960
|
+
if (frame === void 0) {
|
|
1961
|
+
if (path.length === 0) {
|
|
1962
|
+
frame = addFrame(path, { status: "running", mode: topMode, lastRelease: "hold" });
|
|
1963
|
+
} else {
|
|
1964
|
+
frame = addFrame(path, { status: "running", ...branchStart(frameOf(path.slice(0, -1))?.forkMode) });
|
|
1965
|
+
}
|
|
1966
|
+
} else if (frame.status === "in-fork") {
|
|
1967
|
+
dropDescendants(path);
|
|
1968
|
+
frame.mode = frame.joinHold === false ? "continue" : "step";
|
|
1969
|
+
frame.joinHold = void 0;
|
|
1970
|
+
frame.forkMode = void 0;
|
|
1971
|
+
}
|
|
1972
|
+
if (info.signal?.aborted === true) return { patches: [], halt: true };
|
|
1973
|
+
let reason;
|
|
1974
|
+
let condition;
|
|
1975
|
+
if (frame.mode !== "continue") {
|
|
1976
|
+
reason = frame.mode;
|
|
1977
|
+
} else {
|
|
1978
|
+
const breakpoint = breakpoints.get(next);
|
|
1979
|
+
if (breakpoint !== void 0) {
|
|
1980
|
+
try {
|
|
1981
|
+
if (breakpoint.when === void 0 || breakpoint.when(state)) reason = "breakpoint";
|
|
1982
|
+
} catch (error) {
|
|
1983
|
+
reason = "breakpoint";
|
|
1984
|
+
condition = { error };
|
|
1985
|
+
}
|
|
1986
|
+
}
|
|
1987
|
+
}
|
|
1988
|
+
const enter = () => {
|
|
1989
|
+
frame.before = snapshotOf(state);
|
|
1990
|
+
if (info.fork) {
|
|
1991
|
+
frame.status = "in-fork";
|
|
1992
|
+
frame.forkMode ??= frame.mode === "continue" ? "continue" : "over";
|
|
1993
|
+
seedPausedFork(frame, next);
|
|
1994
|
+
} else {
|
|
1995
|
+
frame.status = "running";
|
|
1996
|
+
}
|
|
1997
|
+
};
|
|
1998
|
+
if (reason === void 0) {
|
|
1999
|
+
enter();
|
|
2000
|
+
return { patches: [], halt: false };
|
|
2001
|
+
}
|
|
2002
|
+
frame.status = "held";
|
|
2003
|
+
frame.next = next;
|
|
2004
|
+
frame.isFork = info.fork;
|
|
2005
|
+
frame.live = state;
|
|
2006
|
+
frame.forkMode = void 0;
|
|
2007
|
+
if (info.touchedKeys !== void 0) frame.touched = info.touchedKeys;
|
|
2008
|
+
const last = lastByFrame.get(keyOf(path));
|
|
2009
|
+
const stop = {
|
|
2010
|
+
kind: "step",
|
|
2011
|
+
frame: path,
|
|
2012
|
+
reason,
|
|
2013
|
+
runId: handle.runId,
|
|
2014
|
+
next,
|
|
2015
|
+
...last !== void 0 ? { last } : {},
|
|
2016
|
+
state: snapshotOf(state),
|
|
2017
|
+
...condition !== void 0 ? { conditionError: condition.error } : {}
|
|
2018
|
+
};
|
|
2019
|
+
frame.stop = stop;
|
|
2020
|
+
const released = new Promise((resolve) => {
|
|
2021
|
+
frame.release = resolve;
|
|
2022
|
+
});
|
|
2023
|
+
const onHalt = () => {
|
|
2024
|
+
frame.release?.({ patches: [], halt: true });
|
|
2025
|
+
};
|
|
2026
|
+
info.signal?.addEventListener("abort", onHalt);
|
|
2027
|
+
updateRenewal();
|
|
2028
|
+
offerStop(stop);
|
|
2029
|
+
const result = await released;
|
|
2030
|
+
info.signal?.removeEventListener("abort", onHalt);
|
|
2031
|
+
frame.release = void 0;
|
|
2032
|
+
frame.live = void 0;
|
|
2033
|
+
if (!result.halt) enter();
|
|
2034
|
+
updateRenewal();
|
|
2035
|
+
return result;
|
|
2036
|
+
};
|
|
2037
|
+
const release = (frame, how, halt = false) => {
|
|
2038
|
+
if (!halt) {
|
|
2039
|
+
frame.mode = how === "next" ? "step" : "continue";
|
|
2040
|
+
frame.lastRelease = how === "next" || how === "stepInto" ? "hold" : "continue";
|
|
2041
|
+
if (frame.isFork === true) frame.forkMode = how === "stepInto" ? "fork-entry" : how === "next" ? "over" : "continue";
|
|
2042
|
+
frame.status = frame.isFork === true ? "in-fork" : "running";
|
|
2043
|
+
}
|
|
2044
|
+
const patches = frame.patches;
|
|
2045
|
+
frame.patches = [];
|
|
2046
|
+
const r = frame.release;
|
|
2047
|
+
frame.release = void 0;
|
|
2048
|
+
r?.({ patches, halt });
|
|
2049
|
+
};
|
|
2050
|
+
const observer = {
|
|
2051
|
+
onStepSettled: (ctx, e) => {
|
|
2052
|
+
const path = ctx.branchPath ?? [];
|
|
2053
|
+
if (path.length === 0) {
|
|
2054
|
+
topInterrupt = e.interrupt !== void 0 ? { interruptId: e.interrupt.interruptId, prompt: e.interrupt.prompt, branchPath: [] } : void 0;
|
|
2055
|
+
}
|
|
2056
|
+
lastByFrame.set(keyOf(path), {
|
|
2057
|
+
name: ctx.stepName,
|
|
2058
|
+
outcome: e.outcome,
|
|
2059
|
+
...e.update !== void 0 ? { update: snapshotOf(e.update) } : {},
|
|
2060
|
+
...e.signal !== void 0 ? { signal: e.signal } : {},
|
|
2061
|
+
next: e.next,
|
|
2062
|
+
...e.error !== void 0 ? { error: e.error } : {},
|
|
2063
|
+
before: frameOf(path)?.before ?? { values: {}, shared: [] },
|
|
2064
|
+
durationMs: e.durationMs,
|
|
2065
|
+
...e.fork !== void 0 ? { fork: e.fork } : {}
|
|
2066
|
+
});
|
|
2067
|
+
},
|
|
2068
|
+
onInterrupt: (ctx, e) => {
|
|
2069
|
+
interrupts.push({ interruptId: e.interruptId, prompt: e.prompt, branchPath: ctx.branchPath ?? [] });
|
|
2070
|
+
},
|
|
2071
|
+
onRunEnd: (ctx, e) => {
|
|
2072
|
+
if (ctx.branchPath !== void 0) onFrameEnd(ctx.branchPath, e.signal);
|
|
2073
|
+
}
|
|
2074
|
+
};
|
|
2075
|
+
const refuse = (name) => {
|
|
2076
|
+
if (status === "ended") return new DebugCommandError("ended", name);
|
|
2077
|
+
if (status === "starting" || !started || command !== void 0) return new DebugCommandError("busy", name);
|
|
2078
|
+
if (status === "interrupt" && name !== "answer") return new DebugCommandError("not-held", name);
|
|
2079
|
+
if (status === "active" && name === "answer") return new DebugCommandError("not-held", name);
|
|
2080
|
+
return void 0;
|
|
2081
|
+
};
|
|
2082
|
+
const issue = (target) => {
|
|
2083
|
+
const result = deferred();
|
|
2084
|
+
command = { target, result };
|
|
2085
|
+
return result.promise;
|
|
2086
|
+
};
|
|
2087
|
+
const drive = (how) => {
|
|
2088
|
+
const refused = refuse(how);
|
|
2089
|
+
if (refused !== void 0) return Promise.reject(refused);
|
|
2090
|
+
const frame = frameOf(focus);
|
|
2091
|
+
if (frame === void 0 || frame.status !== "held") return Promise.reject(new DebugCommandError("not-held", how));
|
|
2092
|
+
if (how === "stepInto" && frame.isFork !== true) return Promise.reject(new DebugCommandError("not-a-fork", how));
|
|
2093
|
+
const p = issue(frame.path);
|
|
2094
|
+
release(frame, how);
|
|
2095
|
+
updateRenewal();
|
|
2096
|
+
return p;
|
|
2097
|
+
};
|
|
2098
|
+
const session = {
|
|
2099
|
+
get sessionId() {
|
|
2100
|
+
return handle.sessionId;
|
|
2101
|
+
},
|
|
2102
|
+
get runId() {
|
|
2103
|
+
return handle.runId;
|
|
2104
|
+
},
|
|
2105
|
+
get current() {
|
|
2106
|
+
return current;
|
|
2107
|
+
},
|
|
2108
|
+
get done() {
|
|
2109
|
+
return done.promise;
|
|
2110
|
+
},
|
|
2111
|
+
get breakpoints() {
|
|
2112
|
+
return [...breakpoints.values()];
|
|
2113
|
+
},
|
|
2114
|
+
get frames() {
|
|
2115
|
+
return sortedFrames().map((f) => ({ frame: f.path, status: f.status, ...f.status === "held" && f.next !== void 0 ? { next: f.next } : {} }));
|
|
2116
|
+
},
|
|
2117
|
+
focus: (path) => {
|
|
2118
|
+
const frame = frameOf(path);
|
|
2119
|
+
if (status !== "active" || frame === void 0 || frame.status !== "held" || frame.stop === void 0) {
|
|
2120
|
+
throw new DebugCommandError("not-held", "focus");
|
|
2121
|
+
}
|
|
2122
|
+
focus = frame.path;
|
|
2123
|
+
setCurrent(frame.stop);
|
|
2124
|
+
return frame.stop;
|
|
2125
|
+
},
|
|
2126
|
+
next: () => drive("next"),
|
|
2127
|
+
continue: () => drive("continue"),
|
|
2128
|
+
stepInto: () => drive("stepInto"),
|
|
2129
|
+
continueAll: () => {
|
|
2130
|
+
const refused = refuse("continueAll");
|
|
2131
|
+
if (refused !== void 0) return Promise.reject(refused);
|
|
2132
|
+
const p = issue("any");
|
|
2133
|
+
for (const frame of sortedFrames()) if (frame.status === "held") release(frame, "continueAll");
|
|
2134
|
+
updateRenewal();
|
|
2135
|
+
return p;
|
|
2136
|
+
},
|
|
2137
|
+
answer: (response, id) => {
|
|
2138
|
+
const at = paused;
|
|
2139
|
+
const refused = refuse("answer") ?? (at === void 0 ? new DebugCommandError("not-held", "answer") : void 0);
|
|
2140
|
+
if (refused !== void 0 || at === void 0) return Promise.reject(refused);
|
|
2141
|
+
const target = id ?? at.pending[0].interruptId;
|
|
2142
|
+
if (!at.pending.some((p2) => p2.interruptId === target)) return Promise.reject(new NoInterruptError());
|
|
2143
|
+
let resumed;
|
|
2144
|
+
try {
|
|
2145
|
+
resumed = handle.resume(response, target);
|
|
2146
|
+
} catch (error) {
|
|
2147
|
+
return Promise.reject(error);
|
|
2148
|
+
}
|
|
2149
|
+
pausedForks = new Map([...lastByFrame].filter(([, s]) => s.fork !== void 0 && (s.outcome === "interrupt" || s.outcome === "stopped")));
|
|
2150
|
+
handle = resumed;
|
|
2151
|
+
paused = void 0;
|
|
2152
|
+
status = "active";
|
|
2153
|
+
topMode = "resume";
|
|
2154
|
+
frames = /* @__PURE__ */ new Map();
|
|
2155
|
+
focus = [];
|
|
2156
|
+
lastByFrame = /* @__PURE__ */ new Map();
|
|
2157
|
+
topInterrupt = void 0;
|
|
2158
|
+
interrupts = [];
|
|
2159
|
+
lease = {};
|
|
2160
|
+
const p = issue([]);
|
|
2161
|
+
attach(handle);
|
|
2162
|
+
return p;
|
|
2163
|
+
},
|
|
2164
|
+
setState: (patch) => {
|
|
2165
|
+
if (status === "ended") throw new DebugCommandError("ended", "setState");
|
|
2166
|
+
const frame = frameOf(focus);
|
|
2167
|
+
if (status !== "active" || frame === void 0 || frame.status !== "held" || frame.live === void 0) {
|
|
2168
|
+
throw new DebugCommandError("not-held", "setState");
|
|
2169
|
+
}
|
|
2170
|
+
const reserved = Object.keys(patch).find((k) => k.startsWith("$"));
|
|
2171
|
+
if (reserved !== void 0) throw new DebugCommandError("reserved-key", "setState", `framework key "${reserved}" cannot be set`);
|
|
2172
|
+
const reported = {};
|
|
2173
|
+
for (const [key, value] of Object.entries(patch)) {
|
|
2174
|
+
frame.live[key] = cloneOrShare(value).value;
|
|
2175
|
+
reported[key] = cloneOrShare(value).value;
|
|
2176
|
+
frame.touched?.add(key);
|
|
2177
|
+
}
|
|
2178
|
+
frame.patches.push(reported);
|
|
2179
|
+
return snapshotOf(frame.live);
|
|
2180
|
+
},
|
|
2181
|
+
setBreakpoint: (step, when) => {
|
|
2182
|
+
breakpoints.set(step, { step, ...when !== void 0 ? { when } : {} });
|
|
2183
|
+
},
|
|
2184
|
+
clearBreakpoint: (step) => {
|
|
2185
|
+
breakpoints.delete(step);
|
|
2186
|
+
},
|
|
2187
|
+
stop: () => {
|
|
2188
|
+
if (status === "ended") return ended.promise;
|
|
2189
|
+
stopRequested = true;
|
|
2190
|
+
if (status === "interrupt" && paused !== void 0) {
|
|
2191
|
+
finish(paused.outcome);
|
|
2192
|
+
return ended.promise;
|
|
2193
|
+
}
|
|
2194
|
+
handle.stop();
|
|
2195
|
+
for (const frame of frames.values()) if (frame.status === "held") release(frame, "continueAll", true);
|
|
2196
|
+
return ended.promise;
|
|
2197
|
+
}
|
|
2198
|
+
};
|
|
2199
|
+
handle = args.start({ gate, observer, onLease: (l) => {
|
|
2200
|
+
lease = l;
|
|
2201
|
+
} });
|
|
2202
|
+
status = "active";
|
|
2203
|
+
attach(handle);
|
|
2204
|
+
if (signal !== void 0) {
|
|
2205
|
+
signal.addEventListener("abort", onAbort);
|
|
2206
|
+
if (signal.aborted) onAbort();
|
|
2207
|
+
}
|
|
2208
|
+
return session;
|
|
2209
|
+
}
|
|
2210
|
+
|
|
1579
2211
|
// src/agent/create-agent.ts
|
|
1580
2212
|
import { randomUUID } from "crypto";
|
|
1581
2213
|
|
|
@@ -1697,6 +2329,36 @@ var InvalidClaimOptionsError = class extends Error {
|
|
|
1697
2329
|
this.ttlMs = ttlMs;
|
|
1698
2330
|
}
|
|
1699
2331
|
};
|
|
2332
|
+
var InvalidAgentOptionError = class extends Error {
|
|
2333
|
+
/** The option that was rejected. */
|
|
2334
|
+
key;
|
|
2335
|
+
/** The rejected value, as given. */
|
|
2336
|
+
value;
|
|
2337
|
+
constructor(key, value) {
|
|
2338
|
+
super(`${key} must be ${key === "observer" ? "an object" : "a function"} \u2014 got ${describeValue(value)} in createAgent options`);
|
|
2339
|
+
this.name = "InvalidAgentOptionError";
|
|
2340
|
+
this.key = key;
|
|
2341
|
+
this.value = value;
|
|
2342
|
+
}
|
|
2343
|
+
};
|
|
2344
|
+
var InvalidRunResourceError = class extends Error {
|
|
2345
|
+
/** The resource key that was rejected. */
|
|
2346
|
+
key;
|
|
2347
|
+
/** The rejected value, as given. */
|
|
2348
|
+
value;
|
|
2349
|
+
constructor(key, value) {
|
|
2350
|
+
super(`${key} must be a non-empty string \u2014 got ${describeValue(value)} in agent.run() resources`);
|
|
2351
|
+
this.name = "InvalidRunResourceError";
|
|
2352
|
+
this.key = key;
|
|
2353
|
+
this.value = value;
|
|
2354
|
+
}
|
|
2355
|
+
};
|
|
2356
|
+
function readIdResource(resources, key) {
|
|
2357
|
+
const value = resources[key];
|
|
2358
|
+
if (value === void 0) return void 0;
|
|
2359
|
+
if (typeof value !== "string" || value.length === 0) throw new InvalidRunResourceError(key, value);
|
|
2360
|
+
return value;
|
|
2361
|
+
}
|
|
1700
2362
|
var _agentInternals = /* @__PURE__ */ Symbol("_agentInternals");
|
|
1701
2363
|
function createAgent(id, h, slots, agentOptions) {
|
|
1702
2364
|
const internals = getInternals(h);
|
|
@@ -1734,6 +2396,23 @@ function createAgent(id, h, slots, agentOptions) {
|
|
|
1734
2396
|
agentClaimOptions = { ttlMs };
|
|
1735
2397
|
}
|
|
1736
2398
|
const fallbackClaimOptions = () => agentClaimOptions ?? { ttlMs: defaultClaimTtlMs() };
|
|
2399
|
+
const agentObserver = agentOptions?.observer;
|
|
2400
|
+
if (agentObserver !== void 0 && (agentObserver === null || typeof agentObserver !== "object" || Array.isArray(agentObserver))) {
|
|
2401
|
+
throw new InvalidAgentOptionError("observer", agentObserver);
|
|
2402
|
+
}
|
|
2403
|
+
const agentErrorSink = agentOptions?.onObserverError;
|
|
2404
|
+
if (agentErrorSink !== void 0 && typeof agentErrorSink !== "function") {
|
|
2405
|
+
throw new InvalidAgentOptionError("onObserverError", agentErrorSink);
|
|
2406
|
+
}
|
|
2407
|
+
const resolveObserver = (resources) => {
|
|
2408
|
+
const runObserver = extractRunObserver(resources);
|
|
2409
|
+
const onObserverError = extractRunErrorSink(resources) ?? agentErrorSink;
|
|
2410
|
+
const observer = agentObserver === void 0 ? runObserver : runObserver === void 0 || runObserver === agentObserver ? agentObserver : composeObservers([agentObserver, runObserver], onObserverError);
|
|
2411
|
+
return {
|
|
2412
|
+
...observer !== void 0 ? { observer } : {},
|
|
2413
|
+
...onObserverError !== void 0 ? { onObserverError } : {}
|
|
2414
|
+
};
|
|
2415
|
+
};
|
|
1737
2416
|
const resolvedProviders = /* @__PURE__ */ new Map();
|
|
1738
2417
|
const storeEntries = [];
|
|
1739
2418
|
const runtimeKeys = /* @__PURE__ */ new Set();
|
|
@@ -1783,8 +2462,9 @@ function createAgent(id, h, slots, agentOptions) {
|
|
|
1783
2462
|
runtimeKeys,
|
|
1784
2463
|
requiredKeys
|
|
1785
2464
|
};
|
|
1786
|
-
const reservedRunKeys = /* @__PURE__ */ new Set(["sessionId", "signal", "events", "listeners", "observer", "onObserverError", "claimOptions", "parentRunId"]);
|
|
2465
|
+
const reservedRunKeys = /* @__PURE__ */ new Set(["sessionId", "requestId", "signal", "events", "listeners", "observer", "onObserverError", "claimOptions", "parentRunId"]);
|
|
1787
2466
|
const inFlightSessions = /* @__PURE__ */ new Set();
|
|
2467
|
+
const debugSessions = /* @__PURE__ */ new Set();
|
|
1788
2468
|
const interruptPendingSessions = /* @__PURE__ */ new Set();
|
|
1789
2469
|
const resumeFailState = () => initializeState(null, {}, agentInternals.stateSchema);
|
|
1790
2470
|
const makeAgentResumeHandle = (resp, sId, iId, resumeResources) => {
|
|
@@ -1842,6 +2522,7 @@ function createAgent(id, h, slots, agentOptions) {
|
|
|
1842
2522
|
agentInternals.stateSchema,
|
|
1843
2523
|
agentCtx,
|
|
1844
2524
|
{
|
|
2525
|
+
mode: "resume",
|
|
1845
2526
|
shouldStop: () => flag.stopped,
|
|
1846
2527
|
onBeforeStep: (n) => {
|
|
1847
2528
|
ref.current = n;
|
|
@@ -1855,7 +2536,6 @@ function createAgent(id, h, slots, agentOptions) {
|
|
|
1855
2536
|
...parentRunId !== void 0 ? { parentRunId } : {}
|
|
1856
2537
|
}
|
|
1857
2538
|
);
|
|
1858
|
-
if (r.signal === "$interrupt") interruptPendingSessions.add(sId);
|
|
1859
2539
|
return { state: r.state, signal: r.signal };
|
|
1860
2540
|
}
|
|
1861
2541
|
});
|
|
@@ -1874,258 +2554,269 @@ function createAgent(id, h, slots, agentOptions) {
|
|
|
1874
2554
|
};
|
|
1875
2555
|
return createRunHandle(sId, rId, exec, flag, ref, resumeFn);
|
|
1876
2556
|
};
|
|
1877
|
-
const
|
|
1878
|
-
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
if (!agentInternals.runtimeKeys.has(key) && !agentInternals.requiredKeys.has(key)) {
|
|
1883
|
-
throw new UnknownRunSlotError(key);
|
|
1884
|
-
}
|
|
2557
|
+
const startRun = (initialState, resources, debug) => {
|
|
2558
|
+
for (const key of Object.keys(resources)) {
|
|
2559
|
+
if (reservedRunKeys.has(key)) continue;
|
|
2560
|
+
if (!agentInternals.runtimeKeys.has(key) && !agentInternals.requiredKeys.has(key)) {
|
|
2561
|
+
throw new UnknownRunSlotError(key);
|
|
1885
2562
|
}
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
2563
|
+
}
|
|
2564
|
+
for (const key of Object.keys(resources)) {
|
|
2565
|
+
if (reservedRunKeys.has(key)) continue;
|
|
2566
|
+
if (agentInternals.requiredKeys.has(key)) {
|
|
2567
|
+
throw new RequiredSlotInRunError(key);
|
|
1891
2568
|
}
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
2569
|
+
}
|
|
2570
|
+
for (const key of agentInternals.runtimeKeys) {
|
|
2571
|
+
if (!(key in resources)) {
|
|
2572
|
+
throw new MissingRuntimeSlotError(key);
|
|
1896
2573
|
}
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1905
|
-
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1910
|
-
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
let ctxSignal = abortController.signal;
|
|
1915
|
-
if (rawSignal instanceof AbortSignal) {
|
|
1916
|
-
ctxSignal = rawSignal;
|
|
1917
|
-
rawSignal.addEventListener("abort", () => {
|
|
1918
|
-
stopFlag.stopped = true;
|
|
1919
|
-
abortController.abort();
|
|
1920
|
-
}, { once: true });
|
|
1921
|
-
if (rawSignal.aborted) stopFlag.stopped = true;
|
|
2574
|
+
}
|
|
2575
|
+
const sessionId = readIdResource(resources, "sessionId") ?? randomUUID();
|
|
2576
|
+
const requestId = readIdResource(resources, "requestId");
|
|
2577
|
+
const runId = randomUUID();
|
|
2578
|
+
if (debugSessions.has(sessionId)) throw new SessionInDebugError(sessionId);
|
|
2579
|
+
if (inFlightSessions.has(sessionId)) throw new SessionInFlightError(sessionId);
|
|
2580
|
+
if (capturedStore === void 0 && interruptPendingSessions.has(sessionId)) throw new SessionPendingInterruptError(sessionId);
|
|
2581
|
+
inFlightSessions.add(sessionId);
|
|
2582
|
+
let _stopped = false;
|
|
2583
|
+
const abortController = new AbortController();
|
|
2584
|
+
const stopFlag = {
|
|
2585
|
+
get stopped() {
|
|
2586
|
+
return _stopped;
|
|
2587
|
+
},
|
|
2588
|
+
set stopped(v) {
|
|
2589
|
+
_stopped = v;
|
|
2590
|
+
if (v) abortController.abort();
|
|
1922
2591
|
}
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1927
|
-
|
|
2592
|
+
};
|
|
2593
|
+
const rawSignal = debug === void 0 ? resources["signal"] : void 0;
|
|
2594
|
+
let ctxSignal = abortController.signal;
|
|
2595
|
+
if (rawSignal instanceof AbortSignal) {
|
|
2596
|
+
ctxSignal = rawSignal;
|
|
2597
|
+
rawSignal.addEventListener("abort", () => {
|
|
2598
|
+
stopFlag.stopped = true;
|
|
2599
|
+
abortController.abort();
|
|
2600
|
+
}, { once: true });
|
|
2601
|
+
if (rawSignal.aborted) stopFlag.stopped = true;
|
|
2602
|
+
}
|
|
2603
|
+
const stepRef = { current: null };
|
|
2604
|
+
const runtimeSlots = {};
|
|
2605
|
+
for (const key of agentInternals.runtimeKeys) {
|
|
2606
|
+
if (reservedRunKeys.has(key)) continue;
|
|
2607
|
+
runtimeSlots[key] = resources[key];
|
|
2608
|
+
}
|
|
2609
|
+
const ctx = {
|
|
2610
|
+
...Object.fromEntries(agentInternals.resolvedProviders),
|
|
2611
|
+
...runtimeSlots,
|
|
2612
|
+
agentId: id,
|
|
2613
|
+
sessionId,
|
|
2614
|
+
runId,
|
|
2615
|
+
signal: ctxSignal,
|
|
2616
|
+
...agentOptions?.instanceId !== void 0 ? { instanceId: agentOptions.instanceId } : {}
|
|
2617
|
+
};
|
|
2618
|
+
const events = extractRunEvents(resources);
|
|
2619
|
+
const listeners = extractRunListeners(resources);
|
|
2620
|
+
const resolved = resolveObserver(resources);
|
|
2621
|
+
const onObserverError = resolved.onObserverError;
|
|
2622
|
+
const observer = debug === void 0 ? resolved.observer : resolved.observer === void 0 ? debug.observer : composeObservers([resolved.observer, debug.observer], onObserverError);
|
|
2623
|
+
const telemetrySlots = buildTelemetrySlots([
|
|
2624
|
+
...agentInternals.resolvedProviders.entries(),
|
|
2625
|
+
...Object.entries(runtimeSlots)
|
|
2626
|
+
]);
|
|
2627
|
+
const parentRunId = typeof resources["parentRunId"] === "string" ? resources["parentRunId"] : void 0;
|
|
2628
|
+
const claimOptions = parseClaimOptions(resources["claimOptions"], fallbackClaimOptions());
|
|
2629
|
+
const options = {
|
|
2630
|
+
mode: "run",
|
|
2631
|
+
...requestId !== void 0 ? { requestId } : {},
|
|
2632
|
+
shouldStop: () => stopFlag.stopped,
|
|
2633
|
+
onBeforeStep: (name, state) => {
|
|
2634
|
+
stepRef.current = name;
|
|
2635
|
+
events.onBeforeStep?.(name, state);
|
|
2636
|
+
},
|
|
2637
|
+
// spread optional event callbacks only when defined (exactOptionalPropertyTypes requires omission, not undefined)
|
|
2638
|
+
...events.onStoreError !== void 0 ? { onStoreError: events.onStoreError } : {},
|
|
2639
|
+
...events.onAfterStep !== void 0 ? { onAfterStep: events.onAfterStep } : {},
|
|
2640
|
+
...events.onError !== void 0 ? { onError: events.onError } : {},
|
|
2641
|
+
...events.onComplete !== void 0 ? { onComplete: events.onComplete } : {},
|
|
2642
|
+
...events.onInterrupt !== void 0 ? { onInterrupt: events.onInterrupt } : {},
|
|
2643
|
+
...Object.keys(listeners).length > 0 ? { listeners } : {},
|
|
2644
|
+
...observer !== void 0 ? { observer } : {},
|
|
2645
|
+
...onObserverError !== void 0 ? { onObserverError } : {},
|
|
2646
|
+
...agentOptions?.instanceId !== void 0 ? { instanceId: agentOptions.instanceId } : {},
|
|
2647
|
+
...parentRunId !== void 0 ? { parentRunId } : {},
|
|
2648
|
+
...telemetrySlots.length > 0 ? { telemetrySlots } : {},
|
|
2649
|
+
...debug !== void 0 ? { debugGate: debug.gate } : {}
|
|
2650
|
+
};
|
|
2651
|
+
let lastResult = null;
|
|
2652
|
+
const execution = (async () => {
|
|
2653
|
+
await Promise.resolve();
|
|
2654
|
+
try {
|
|
2655
|
+
return await runClaimed({
|
|
2656
|
+
store: capturedStore,
|
|
2657
|
+
agentId: id,
|
|
2658
|
+
sessionId,
|
|
2659
|
+
claimOptions,
|
|
2660
|
+
...events.onStoreError !== void 0 ? { onStoreError: events.onStoreError } : {},
|
|
2661
|
+
failState: () => initializeState(null, initialState, agentInternals.stateSchema),
|
|
2662
|
+
body: async (lease) => {
|
|
2663
|
+
debug?.onLease(lease);
|
|
2664
|
+
const r = await runWithSession(
|
|
2665
|
+
capturedStore,
|
|
2666
|
+
id,
|
|
2667
|
+
sessionId,
|
|
2668
|
+
runId,
|
|
2669
|
+
agentInternals.loopDef,
|
|
2670
|
+
initialState,
|
|
2671
|
+
agentInternals.stateSchema,
|
|
2672
|
+
ctx,
|
|
2673
|
+
{ ...options, ...lease }
|
|
2674
|
+
);
|
|
2675
|
+
if (capturedStore === void 0 && r.signal === "$interrupt") interruptPendingSessions.add(sessionId);
|
|
2676
|
+
lastResult = { state: r.state, cursor: r.cursor, runId, ...r.carrier !== void 0 ? { carrier: r.carrier } : {} };
|
|
2677
|
+
return { state: r.state, signal: r.signal };
|
|
2678
|
+
}
|
|
2679
|
+
});
|
|
2680
|
+
} finally {
|
|
2681
|
+
inFlightSessions.delete(sessionId);
|
|
1928
2682
|
}
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
sessionId
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
...onObserverError !== void 0 ? { onObserverError } : {},
|
|
1963
|
-
...agentOptions?.instanceId !== void 0 ? { instanceId: agentOptions.instanceId } : {},
|
|
1964
|
-
...parentRunId !== void 0 ? { parentRunId } : {},
|
|
1965
|
-
...telemetrySlots.length > 0 ? { telemetrySlots } : {}
|
|
1966
|
-
};
|
|
1967
|
-
let lastResult = null;
|
|
1968
|
-
const execution = (async () => {
|
|
1969
|
-
await Promise.resolve();
|
|
1970
|
-
try {
|
|
1971
|
-
return await runClaimed({
|
|
1972
|
-
store: capturedStore,
|
|
1973
|
-
agentId: id,
|
|
1974
|
-
sessionId,
|
|
1975
|
-
claimOptions,
|
|
1976
|
-
...events.onStoreError !== void 0 ? { onStoreError: events.onStoreError } : {},
|
|
1977
|
-
failState: () => initializeState(null, initialState, agentInternals.stateSchema),
|
|
1978
|
-
body: async (lease) => {
|
|
1979
|
-
const r = await runWithSession(
|
|
1980
|
-
capturedStore,
|
|
1981
|
-
id,
|
|
2683
|
+
})();
|
|
2684
|
+
const buildResumeFn = () => {
|
|
2685
|
+
return (response, interruptId) => {
|
|
2686
|
+
if (inFlightSessions.has(sessionId)) throw new SessionInFlightError(sessionId);
|
|
2687
|
+
interruptPendingSessions.delete(sessionId);
|
|
2688
|
+
inFlightSessions.add(sessionId);
|
|
2689
|
+
let _resumeStopped = false;
|
|
2690
|
+
const resumeAbortController = new AbortController();
|
|
2691
|
+
const resumeStopFlag = {
|
|
2692
|
+
get stopped() {
|
|
2693
|
+
return _resumeStopped;
|
|
2694
|
+
},
|
|
2695
|
+
set stopped(v) {
|
|
2696
|
+
_resumeStopped = v;
|
|
2697
|
+
if (v) resumeAbortController.abort();
|
|
2698
|
+
}
|
|
2699
|
+
};
|
|
2700
|
+
const resumeStepRef = { current: null };
|
|
2701
|
+
const resumeRunId = randomUUID();
|
|
2702
|
+
const resumeExecution = (async () => {
|
|
2703
|
+
await Promise.resolve();
|
|
2704
|
+
try {
|
|
2705
|
+
const resumeCtx = {
|
|
2706
|
+
...ctx,
|
|
2707
|
+
runId: resumeRunId,
|
|
2708
|
+
signal: resumeAbortController.signal
|
|
2709
|
+
};
|
|
2710
|
+
if (capturedStore !== void 0) {
|
|
2711
|
+
const store = capturedStore;
|
|
2712
|
+
const onStoreError = events.onStoreError;
|
|
2713
|
+
return await runClaimed({
|
|
2714
|
+
store,
|
|
2715
|
+
agentId: id,
|
|
1982
2716
|
sessionId,
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
ctx,
|
|
1988
|
-
{ ...options, ...lease }
|
|
1989
|
-
);
|
|
1990
|
-
if (r.signal === "$interrupt") interruptPendingSessions.add(sessionId);
|
|
1991
|
-
lastResult = { state: r.state, cursor: r.cursor, runId, ...r.carrier !== void 0 ? { carrier: r.carrier } : {} };
|
|
1992
|
-
return { state: r.state, signal: r.signal };
|
|
1993
|
-
}
|
|
1994
|
-
});
|
|
1995
|
-
} finally {
|
|
1996
|
-
inFlightSessions.delete(sessionId);
|
|
1997
|
-
}
|
|
1998
|
-
})();
|
|
1999
|
-
const buildResumeFn = () => {
|
|
2000
|
-
return (response, interruptId) => {
|
|
2001
|
-
if (inFlightSessions.has(sessionId)) throw new SessionInFlightError(sessionId);
|
|
2002
|
-
interruptPendingSessions.delete(sessionId);
|
|
2003
|
-
inFlightSessions.add(sessionId);
|
|
2004
|
-
let _resumeStopped = false;
|
|
2005
|
-
const resumeAbortController = new AbortController();
|
|
2006
|
-
const resumeStopFlag = {
|
|
2007
|
-
get stopped() {
|
|
2008
|
-
return _resumeStopped;
|
|
2009
|
-
},
|
|
2010
|
-
set stopped(v) {
|
|
2011
|
-
_resumeStopped = v;
|
|
2012
|
-
if (v) resumeAbortController.abort();
|
|
2013
|
-
}
|
|
2014
|
-
};
|
|
2015
|
-
const resumeStepRef = { current: null };
|
|
2016
|
-
const resumeRunId = randomUUID();
|
|
2017
|
-
const resumeExecution = (async () => {
|
|
2018
|
-
await Promise.resolve();
|
|
2019
|
-
try {
|
|
2020
|
-
const resumeCtx = {
|
|
2021
|
-
...ctx,
|
|
2022
|
-
runId: resumeRunId,
|
|
2023
|
-
signal: resumeAbortController.signal
|
|
2024
|
-
};
|
|
2025
|
-
if (capturedStore !== void 0) {
|
|
2026
|
-
const store = capturedStore;
|
|
2027
|
-
const onStoreError = events.onStoreError;
|
|
2028
|
-
return await runClaimed({
|
|
2717
|
+
claimOptions,
|
|
2718
|
+
...onStoreError !== void 0 ? { onStoreError } : {},
|
|
2719
|
+
failState: resumeFailState,
|
|
2720
|
+
body: (lease) => injectThenRun({
|
|
2029
2721
|
store,
|
|
2030
2722
|
agentId: id,
|
|
2031
2723
|
sessionId,
|
|
2032
|
-
|
|
2724
|
+
interruptId,
|
|
2725
|
+
response,
|
|
2033
2726
|
...onStoreError !== void 0 ? { onStoreError } : {},
|
|
2034
2727
|
failState: resumeFailState,
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
if (r2.signal === "$interrupt") interruptPendingSessions.add(sessionId);
|
|
2074
|
-
lastResult = { state: r2.state, cursor: r2.cursor, runId: resumeRunId, ...r2.carrier !== void 0 ? { carrier: r2.carrier } : {} };
|
|
2075
|
-
return { state: r2.state, signal: r2.signal };
|
|
2076
|
-
}
|
|
2077
|
-
})
|
|
2078
|
-
});
|
|
2079
|
-
}
|
|
2080
|
-
const prev = lastResult;
|
|
2081
|
-
if (prev === null) throw new NoInterruptError();
|
|
2082
|
-
const injected = injectInterruptResponseIntoState(prev.cursor ?? void 0, prev.state, interruptId, response);
|
|
2083
|
-
if (!injected.found) throw new NoInterruptError();
|
|
2084
|
-
const state = injected.state;
|
|
2085
|
-
const cursor = injected.cursor;
|
|
2086
|
-
const r = await runLoop(
|
|
2087
|
-
agentInternals.loopDef,
|
|
2088
|
-
state,
|
|
2089
|
-
resumeCtx,
|
|
2090
|
-
agentInternals.stateSchema,
|
|
2091
|
-
() => resumeStopFlag.stopped,
|
|
2092
|
-
cursor,
|
|
2093
|
-
{
|
|
2094
|
-
runId: resumeRunId,
|
|
2095
|
-
resumedFrom: { runId: prev.runId, ...prev.carrier !== void 0 ? { carrier: prev.carrier } : {} },
|
|
2096
|
-
onBeforeStep: (n, s) => {
|
|
2097
|
-
resumeStepRef.current = n;
|
|
2098
|
-
events.onBeforeStep?.(n, s);
|
|
2099
|
-
},
|
|
2100
|
-
...events.onAfterStep !== void 0 ? { onAfterStep: events.onAfterStep } : {},
|
|
2101
|
-
...events.onError !== void 0 ? { onError: events.onError } : {},
|
|
2102
|
-
...events.onComplete !== void 0 ? { onComplete: events.onComplete } : {},
|
|
2103
|
-
...events.onInterrupt !== void 0 ? { onInterrupt: events.onInterrupt } : {},
|
|
2104
|
-
...Object.keys(listeners).length > 0 ? { listeners } : {},
|
|
2105
|
-
...observer !== void 0 ? { observer } : {},
|
|
2106
|
-
...onObserverError !== void 0 ? { onObserverError } : {},
|
|
2107
|
-
...telemetrySlots.length > 0 ? { telemetrySlots } : {}
|
|
2108
|
-
}
|
|
2109
|
-
);
|
|
2110
|
-
if (r.signal === "$interrupt") interruptPendingSessions.add(sessionId);
|
|
2111
|
-
lastResult = { state: r.state, cursor: r.cursor, runId: resumeRunId, ...r.carrier !== void 0 ? { carrier: r.carrier } : {} };
|
|
2112
|
-
return { state: r.state, signal: r.signal };
|
|
2113
|
-
} finally {
|
|
2114
|
-
inFlightSessions.delete(sessionId);
|
|
2728
|
+
run: async () => {
|
|
2729
|
+
debug?.onLease(lease);
|
|
2730
|
+
const r2 = await runWithSession(
|
|
2731
|
+
store,
|
|
2732
|
+
id,
|
|
2733
|
+
sessionId,
|
|
2734
|
+
resumeRunId,
|
|
2735
|
+
agentInternals.loopDef,
|
|
2736
|
+
{},
|
|
2737
|
+
agentInternals.stateSchema,
|
|
2738
|
+
resumeCtx,
|
|
2739
|
+
{
|
|
2740
|
+
mode: "resume",
|
|
2741
|
+
shouldStop: () => resumeStopFlag.stopped,
|
|
2742
|
+
onBeforeStep: (n, s) => {
|
|
2743
|
+
resumeStepRef.current = n;
|
|
2744
|
+
events.onBeforeStep?.(n, s);
|
|
2745
|
+
},
|
|
2746
|
+
// spread optional event callbacks only when defined (exactOptionalPropertyTypes requires omission, not undefined)
|
|
2747
|
+
...events.onStoreError !== void 0 ? { onStoreError: events.onStoreError } : {},
|
|
2748
|
+
...events.onAfterStep !== void 0 ? { onAfterStep: events.onAfterStep } : {},
|
|
2749
|
+
...events.onError !== void 0 ? { onError: events.onError } : {},
|
|
2750
|
+
...events.onComplete !== void 0 ? { onComplete: events.onComplete } : {},
|
|
2751
|
+
...events.onInterrupt !== void 0 ? { onInterrupt: events.onInterrupt } : {},
|
|
2752
|
+
...Object.keys(listeners).length > 0 ? { listeners } : {},
|
|
2753
|
+
...observer !== void 0 ? { observer } : {},
|
|
2754
|
+
...onObserverError !== void 0 ? { onObserverError } : {},
|
|
2755
|
+
...telemetrySlots.length > 0 ? { telemetrySlots } : {},
|
|
2756
|
+
...agentOptions?.instanceId !== void 0 ? { instanceId: agentOptions.instanceId } : {},
|
|
2757
|
+
...debug !== void 0 ? { debugGate: debug.gate } : {},
|
|
2758
|
+
...lease
|
|
2759
|
+
}
|
|
2760
|
+
);
|
|
2761
|
+
lastResult = { state: r2.state, cursor: r2.cursor, runId: resumeRunId, ...r2.carrier !== void 0 ? { carrier: r2.carrier } : {} };
|
|
2762
|
+
return { state: r2.state, signal: r2.signal };
|
|
2763
|
+
}
|
|
2764
|
+
})
|
|
2765
|
+
});
|
|
2115
2766
|
}
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2767
|
+
const prev = lastResult;
|
|
2768
|
+
if (prev === null) throw new NoInterruptError();
|
|
2769
|
+
const injected = injectInterruptResponseIntoState(prev.cursor ?? void 0, prev.state, interruptId, response);
|
|
2770
|
+
if (!injected.found) throw new NoInterruptError();
|
|
2771
|
+
const state = injected.state;
|
|
2772
|
+
const cursor = injected.cursor;
|
|
2773
|
+
const r = await runLoop(
|
|
2774
|
+
agentInternals.loopDef,
|
|
2775
|
+
state,
|
|
2776
|
+
resumeCtx,
|
|
2777
|
+
agentInternals.stateSchema,
|
|
2778
|
+
() => resumeStopFlag.stopped,
|
|
2779
|
+
cursor,
|
|
2780
|
+
{
|
|
2781
|
+
runId: resumeRunId,
|
|
2782
|
+
resumedFrom: { runId: prev.runId, ...prev.carrier !== void 0 ? { carrier: prev.carrier } : {} },
|
|
2783
|
+
onBeforeStep: (n, s) => {
|
|
2784
|
+
resumeStepRef.current = n;
|
|
2785
|
+
events.onBeforeStep?.(n, s);
|
|
2786
|
+
},
|
|
2787
|
+
...events.onAfterStep !== void 0 ? { onAfterStep: events.onAfterStep } : {},
|
|
2788
|
+
...events.onError !== void 0 ? { onError: events.onError } : {},
|
|
2789
|
+
...events.onComplete !== void 0 ? { onComplete: events.onComplete } : {},
|
|
2790
|
+
...events.onInterrupt !== void 0 ? { onInterrupt: events.onInterrupt } : {},
|
|
2791
|
+
...Object.keys(listeners).length > 0 ? { listeners } : {},
|
|
2792
|
+
...observer !== void 0 ? { observer } : {},
|
|
2793
|
+
...onObserverError !== void 0 ? { onObserverError } : {},
|
|
2794
|
+
...telemetrySlots.length > 0 ? { telemetrySlots } : {},
|
|
2795
|
+
...debug !== void 0 ? { debugGate: debug.gate } : {}
|
|
2796
|
+
}
|
|
2797
|
+
);
|
|
2798
|
+
if (r.signal === "$interrupt") interruptPendingSessions.add(sessionId);
|
|
2799
|
+
lastResult = { state: r.state, cursor: r.cursor, runId: resumeRunId, ...r.carrier !== void 0 ? { carrier: r.carrier } : {} };
|
|
2800
|
+
return { state: r.state, signal: r.signal };
|
|
2801
|
+
} finally {
|
|
2802
|
+
inFlightSessions.delete(sessionId);
|
|
2803
|
+
}
|
|
2804
|
+
})();
|
|
2805
|
+
return createRunHandle(sessionId, resumeRunId, resumeExecution, resumeStopFlag, resumeStepRef, buildResumeFn());
|
|
2119
2806
|
};
|
|
2120
|
-
|
|
2121
|
-
|
|
2807
|
+
};
|
|
2808
|
+
return createRunHandle(sessionId, runId, execution, stopFlag, stepRef, buildResumeFn());
|
|
2809
|
+
};
|
|
2810
|
+
const agent = {
|
|
2811
|
+
id,
|
|
2812
|
+
run: (initialState, resources) => startRun(initialState, resources),
|
|
2122
2813
|
resume: (response, sessionId, interruptId, resources) => {
|
|
2814
|
+
if (debugSessions.has(sessionId)) throw new SessionInDebugError(sessionId);
|
|
2123
2815
|
if (inFlightSessions.has(sessionId)) throw new SessionInFlightError(sessionId);
|
|
2124
2816
|
interruptPendingSessions.delete(sessionId);
|
|
2125
2817
|
inFlightSessions.add(sessionId);
|
|
2126
2818
|
const events = extractRunEvents(resources ?? {});
|
|
2127
|
-
const observer =
|
|
2128
|
-
const onObserverError = extractRunErrorSink(resources ?? {});
|
|
2819
|
+
const { observer, onObserverError } = resolveObserver(resources ?? {});
|
|
2129
2820
|
const telemetrySlots = buildTelemetrySlots(agentInternals.resolvedProviders.entries());
|
|
2130
2821
|
const parentRunId = resources?.["parentRunId"];
|
|
2131
2822
|
const claimOptions = parseClaimOptions(resources?.["claimOptions"], fallbackClaimOptions());
|
|
@@ -2138,18 +2829,41 @@ function createAgent(id, h, slots, agentOptions) {
|
|
|
2138
2829
|
...typeof parentRunId === "string" ? { parentRunId } : {}
|
|
2139
2830
|
});
|
|
2140
2831
|
},
|
|
2832
|
+
debug: (initialState, resources) => {
|
|
2833
|
+
const rawSignal = resources["signal"];
|
|
2834
|
+
let sessionId;
|
|
2835
|
+
const session = createDebugSession({
|
|
2836
|
+
start: (hooks) => {
|
|
2837
|
+
const handle = startRun(initialState, resources, hooks);
|
|
2838
|
+
sessionId = handle.sessionId;
|
|
2839
|
+
return handle;
|
|
2840
|
+
},
|
|
2841
|
+
store: capturedStore,
|
|
2842
|
+
signal: rawSignal instanceof AbortSignal ? rawSignal : void 0,
|
|
2843
|
+
onEnd: () => {
|
|
2844
|
+
if (sessionId !== void 0) debugSessions.delete(sessionId);
|
|
2845
|
+
}
|
|
2846
|
+
});
|
|
2847
|
+
debugSessions.add(session.sessionId);
|
|
2848
|
+
return session;
|
|
2849
|
+
},
|
|
2141
2850
|
status: (sessionId) => querySessionPhase(capturedStore, id, sessionId),
|
|
2142
2851
|
[_agentInternals]: agentInternals
|
|
2143
2852
|
};
|
|
2144
2853
|
return agent;
|
|
2145
2854
|
}
|
|
2146
2855
|
export {
|
|
2856
|
+
DebugCommandError,
|
|
2857
|
+
InvalidAgentOptionError,
|
|
2858
|
+
InvalidClaimOptionsError,
|
|
2859
|
+
InvalidRunResourceError,
|
|
2147
2860
|
LeaseExpiredError,
|
|
2148
2861
|
LoopNotDefinedError,
|
|
2149
2862
|
NoInterruptError,
|
|
2150
2863
|
REQUIRED_TAG,
|
|
2151
2864
|
RUNTIME_TAG,
|
|
2152
2865
|
SessionBusyError,
|
|
2866
|
+
SessionInDebugError,
|
|
2153
2867
|
SessionInFlightError,
|
|
2154
2868
|
SessionPendingInterruptError,
|
|
2155
2869
|
StoreLoadError,
|