@noetaris/harness 0.11.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 +98 -2
- package/dist/index.d.ts +216 -4
- package/dist/index.js +897 -246
- 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 {
|
|
@@ -775,6 +772,24 @@ async function runLoop(graph, state, ctx, schema, shouldStop, startCursor, callb
|
|
|
775
772
|
endRun("$stopped");
|
|
776
773
|
return withCarrier({ state, signal: null, cursor, paused: true });
|
|
777
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
|
+
}
|
|
778
793
|
if (isForkCursor(cursor)) {
|
|
779
794
|
const forkCursor = cursor;
|
|
780
795
|
const forkNode = graph.steps.find((s) => s.name === forkCursor.fork);
|
|
@@ -1028,6 +1043,7 @@ async function dispatchFork(forkNode, priorBranches, outerState, outerCtx, schem
|
|
|
1028
1043
|
} else {
|
|
1029
1044
|
outerState[key] = outcome.result.state[key];
|
|
1030
1045
|
}
|
|
1046
|
+
callbacks?.touchedKeys?.add(key);
|
|
1031
1047
|
}
|
|
1032
1048
|
}
|
|
1033
1049
|
return {
|
|
@@ -1183,6 +1199,15 @@ var SessionInFlightError = class extends Error {
|
|
|
1183
1199
|
this.sessionId = sessionId;
|
|
1184
1200
|
}
|
|
1185
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
|
+
};
|
|
1186
1211
|
var SessionPendingInterruptError = class extends Error {
|
|
1187
1212
|
/** The session that is awaiting an interrupt response. */
|
|
1188
1213
|
sessionId;
|
|
@@ -1617,6 +1642,572 @@ function createRunHandle(sessionId, runId, execution, stopFlag, stepRef, resumeF
|
|
|
1617
1642
|
return handle;
|
|
1618
1643
|
}
|
|
1619
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
|
+
|
|
1620
2211
|
// src/agent/create-agent.ts
|
|
1621
2212
|
import { randomUUID } from "crypto";
|
|
1622
2213
|
|
|
@@ -1738,6 +2329,18 @@ var InvalidClaimOptionsError = class extends Error {
|
|
|
1738
2329
|
this.ttlMs = ttlMs;
|
|
1739
2330
|
}
|
|
1740
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
|
+
};
|
|
1741
2344
|
var InvalidRunResourceError = class extends Error {
|
|
1742
2345
|
/** The resource key that was rejected. */
|
|
1743
2346
|
key;
|
|
@@ -1793,6 +2396,23 @@ function createAgent(id, h, slots, agentOptions) {
|
|
|
1793
2396
|
agentClaimOptions = { ttlMs };
|
|
1794
2397
|
}
|
|
1795
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
|
+
};
|
|
1796
2416
|
const resolvedProviders = /* @__PURE__ */ new Map();
|
|
1797
2417
|
const storeEntries = [];
|
|
1798
2418
|
const runtimeKeys = /* @__PURE__ */ new Set();
|
|
@@ -1844,6 +2464,7 @@ function createAgent(id, h, slots, agentOptions) {
|
|
|
1844
2464
|
};
|
|
1845
2465
|
const reservedRunKeys = /* @__PURE__ */ new Set(["sessionId", "requestId", "signal", "events", "listeners", "observer", "onObserverError", "claimOptions", "parentRunId"]);
|
|
1846
2466
|
const inFlightSessions = /* @__PURE__ */ new Set();
|
|
2467
|
+
const debugSessions = /* @__PURE__ */ new Set();
|
|
1847
2468
|
const interruptPendingSessions = /* @__PURE__ */ new Set();
|
|
1848
2469
|
const resumeFailState = () => initializeState(null, {}, agentInternals.stateSchema);
|
|
1849
2470
|
const makeAgentResumeHandle = (resp, sId, iId, resumeResources) => {
|
|
@@ -1933,261 +2554,269 @@ function createAgent(id, h, slots, agentOptions) {
|
|
|
1933
2554
|
};
|
|
1934
2555
|
return createRunHandle(sId, rId, exec, flag, ref, resumeFn);
|
|
1935
2556
|
};
|
|
1936
|
-
const
|
|
1937
|
-
|
|
1938
|
-
|
|
1939
|
-
|
|
1940
|
-
|
|
1941
|
-
if (!agentInternals.runtimeKeys.has(key) && !agentInternals.requiredKeys.has(key)) {
|
|
1942
|
-
throw new UnknownRunSlotError(key);
|
|
1943
|
-
}
|
|
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);
|
|
1944
2562
|
}
|
|
1945
|
-
|
|
1946
|
-
|
|
1947
|
-
|
|
1948
|
-
|
|
1949
|
-
|
|
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);
|
|
1950
2568
|
}
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
2569
|
+
}
|
|
2570
|
+
for (const key of agentInternals.runtimeKeys) {
|
|
2571
|
+
if (!(key in resources)) {
|
|
2572
|
+
throw new MissingRuntimeSlotError(key);
|
|
1955
2573
|
}
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
|
|
1966
|
-
|
|
1967
|
-
|
|
1968
|
-
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
const rawSignal = resources["signal"];
|
|
1974
|
-
let ctxSignal = abortController.signal;
|
|
1975
|
-
if (rawSignal instanceof AbortSignal) {
|
|
1976
|
-
ctxSignal = rawSignal;
|
|
1977
|
-
rawSignal.addEventListener("abort", () => {
|
|
1978
|
-
stopFlag.stopped = true;
|
|
1979
|
-
abortController.abort();
|
|
1980
|
-
}, { once: true });
|
|
1981
|
-
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();
|
|
1982
2591
|
}
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
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);
|
|
1988
2682
|
}
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
sessionId
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
|
|
2005
|
-
|
|
2006
|
-
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
...Object.keys(listeners).length > 0 ? { listeners } : {},
|
|
2023
|
-
...observer !== void 0 ? { observer } : {},
|
|
2024
|
-
...onObserverError !== void 0 ? { onObserverError } : {},
|
|
2025
|
-
...agentOptions?.instanceId !== void 0 ? { instanceId: agentOptions.instanceId } : {},
|
|
2026
|
-
...parentRunId !== void 0 ? { parentRunId } : {},
|
|
2027
|
-
...telemetrySlots.length > 0 ? { telemetrySlots } : {}
|
|
2028
|
-
};
|
|
2029
|
-
let lastResult = null;
|
|
2030
|
-
const execution = (async () => {
|
|
2031
|
-
await Promise.resolve();
|
|
2032
|
-
try {
|
|
2033
|
-
return await runClaimed({
|
|
2034
|
-
store: capturedStore,
|
|
2035
|
-
agentId: id,
|
|
2036
|
-
sessionId,
|
|
2037
|
-
claimOptions,
|
|
2038
|
-
...events.onStoreError !== void 0 ? { onStoreError: events.onStoreError } : {},
|
|
2039
|
-
failState: () => initializeState(null, initialState, agentInternals.stateSchema),
|
|
2040
|
-
body: async (lease) => {
|
|
2041
|
-
const r = await runWithSession(
|
|
2042
|
-
capturedStore,
|
|
2043
|
-
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,
|
|
2044
2716
|
sessionId,
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
ctx,
|
|
2050
|
-
{ ...options, ...lease }
|
|
2051
|
-
);
|
|
2052
|
-
if (capturedStore === void 0 && r.signal === "$interrupt") interruptPendingSessions.add(sessionId);
|
|
2053
|
-
lastResult = { state: r.state, cursor: r.cursor, runId, ...r.carrier !== void 0 ? { carrier: r.carrier } : {} };
|
|
2054
|
-
return { state: r.state, signal: r.signal };
|
|
2055
|
-
}
|
|
2056
|
-
});
|
|
2057
|
-
} finally {
|
|
2058
|
-
inFlightSessions.delete(sessionId);
|
|
2059
|
-
}
|
|
2060
|
-
})();
|
|
2061
|
-
const buildResumeFn = () => {
|
|
2062
|
-
return (response, interruptId) => {
|
|
2063
|
-
if (inFlightSessions.has(sessionId)) throw new SessionInFlightError(sessionId);
|
|
2064
|
-
interruptPendingSessions.delete(sessionId);
|
|
2065
|
-
inFlightSessions.add(sessionId);
|
|
2066
|
-
let _resumeStopped = false;
|
|
2067
|
-
const resumeAbortController = new AbortController();
|
|
2068
|
-
const resumeStopFlag = {
|
|
2069
|
-
get stopped() {
|
|
2070
|
-
return _resumeStopped;
|
|
2071
|
-
},
|
|
2072
|
-
set stopped(v) {
|
|
2073
|
-
_resumeStopped = v;
|
|
2074
|
-
if (v) resumeAbortController.abort();
|
|
2075
|
-
}
|
|
2076
|
-
};
|
|
2077
|
-
const resumeStepRef = { current: null };
|
|
2078
|
-
const resumeRunId = randomUUID();
|
|
2079
|
-
const resumeExecution = (async () => {
|
|
2080
|
-
await Promise.resolve();
|
|
2081
|
-
try {
|
|
2082
|
-
const resumeCtx = {
|
|
2083
|
-
...ctx,
|
|
2084
|
-
runId: resumeRunId,
|
|
2085
|
-
signal: resumeAbortController.signal
|
|
2086
|
-
};
|
|
2087
|
-
if (capturedStore !== void 0) {
|
|
2088
|
-
const store = capturedStore;
|
|
2089
|
-
const onStoreError = events.onStoreError;
|
|
2090
|
-
return await runClaimed({
|
|
2717
|
+
claimOptions,
|
|
2718
|
+
...onStoreError !== void 0 ? { onStoreError } : {},
|
|
2719
|
+
failState: resumeFailState,
|
|
2720
|
+
body: (lease) => injectThenRun({
|
|
2091
2721
|
store,
|
|
2092
2722
|
agentId: id,
|
|
2093
2723
|
sessionId,
|
|
2094
|
-
|
|
2724
|
+
interruptId,
|
|
2725
|
+
response,
|
|
2095
2726
|
...onStoreError !== void 0 ? { onStoreError } : {},
|
|
2096
2727
|
failState: resumeFailState,
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2124
|
-
|
|
2125
|
-
|
|
2126
|
-
|
|
2127
|
-
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
|
|
2135
|
-
);
|
|
2136
|
-
lastResult = { state: r2.state, cursor: r2.cursor, runId: resumeRunId, ...r2.carrier !== void 0 ? { carrier: r2.carrier } : {} };
|
|
2137
|
-
return { state: r2.state, signal: r2.signal };
|
|
2138
|
-
}
|
|
2139
|
-
})
|
|
2140
|
-
});
|
|
2141
|
-
}
|
|
2142
|
-
const prev = lastResult;
|
|
2143
|
-
if (prev === null) throw new NoInterruptError();
|
|
2144
|
-
const injected = injectInterruptResponseIntoState(prev.cursor ?? void 0, prev.state, interruptId, response);
|
|
2145
|
-
if (!injected.found) throw new NoInterruptError();
|
|
2146
|
-
const state = injected.state;
|
|
2147
|
-
const cursor = injected.cursor;
|
|
2148
|
-
const r = await runLoop(
|
|
2149
|
-
agentInternals.loopDef,
|
|
2150
|
-
state,
|
|
2151
|
-
resumeCtx,
|
|
2152
|
-
agentInternals.stateSchema,
|
|
2153
|
-
() => resumeStopFlag.stopped,
|
|
2154
|
-
cursor,
|
|
2155
|
-
{
|
|
2156
|
-
runId: resumeRunId,
|
|
2157
|
-
resumedFrom: { runId: prev.runId, ...prev.carrier !== void 0 ? { carrier: prev.carrier } : {} },
|
|
2158
|
-
onBeforeStep: (n, s) => {
|
|
2159
|
-
resumeStepRef.current = n;
|
|
2160
|
-
events.onBeforeStep?.(n, s);
|
|
2161
|
-
},
|
|
2162
|
-
...events.onAfterStep !== void 0 ? { onAfterStep: events.onAfterStep } : {},
|
|
2163
|
-
...events.onError !== void 0 ? { onError: events.onError } : {},
|
|
2164
|
-
...events.onComplete !== void 0 ? { onComplete: events.onComplete } : {},
|
|
2165
|
-
...events.onInterrupt !== void 0 ? { onInterrupt: events.onInterrupt } : {},
|
|
2166
|
-
...Object.keys(listeners).length > 0 ? { listeners } : {},
|
|
2167
|
-
...observer !== void 0 ? { observer } : {},
|
|
2168
|
-
...onObserverError !== void 0 ? { onObserverError } : {},
|
|
2169
|
-
...telemetrySlots.length > 0 ? { telemetrySlots } : {}
|
|
2170
|
-
}
|
|
2171
|
-
);
|
|
2172
|
-
if (r.signal === "$interrupt") interruptPendingSessions.add(sessionId);
|
|
2173
|
-
lastResult = { state: r.state, cursor: r.cursor, runId: resumeRunId, ...r.carrier !== void 0 ? { carrier: r.carrier } : {} };
|
|
2174
|
-
return { state: r.state, signal: r.signal };
|
|
2175
|
-
} finally {
|
|
2176
|
-
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
|
+
});
|
|
2177
2766
|
}
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
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());
|
|
2181
2806
|
};
|
|
2182
|
-
|
|
2183
|
-
|
|
2807
|
+
};
|
|
2808
|
+
return createRunHandle(sessionId, runId, execution, stopFlag, stepRef, buildResumeFn());
|
|
2809
|
+
};
|
|
2810
|
+
const agent = {
|
|
2811
|
+
id,
|
|
2812
|
+
run: (initialState, resources) => startRun(initialState, resources),
|
|
2184
2813
|
resume: (response, sessionId, interruptId, resources) => {
|
|
2814
|
+
if (debugSessions.has(sessionId)) throw new SessionInDebugError(sessionId);
|
|
2185
2815
|
if (inFlightSessions.has(sessionId)) throw new SessionInFlightError(sessionId);
|
|
2186
2816
|
interruptPendingSessions.delete(sessionId);
|
|
2187
2817
|
inFlightSessions.add(sessionId);
|
|
2188
2818
|
const events = extractRunEvents(resources ?? {});
|
|
2189
|
-
const observer =
|
|
2190
|
-
const onObserverError = extractRunErrorSink(resources ?? {});
|
|
2819
|
+
const { observer, onObserverError } = resolveObserver(resources ?? {});
|
|
2191
2820
|
const telemetrySlots = buildTelemetrySlots(agentInternals.resolvedProviders.entries());
|
|
2192
2821
|
const parentRunId = resources?.["parentRunId"];
|
|
2193
2822
|
const claimOptions = parseClaimOptions(resources?.["claimOptions"], fallbackClaimOptions());
|
|
@@ -2200,12 +2829,33 @@ function createAgent(id, h, slots, agentOptions) {
|
|
|
2200
2829
|
...typeof parentRunId === "string" ? { parentRunId } : {}
|
|
2201
2830
|
});
|
|
2202
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
|
+
},
|
|
2203
2850
|
status: (sessionId) => querySessionPhase(capturedStore, id, sessionId),
|
|
2204
2851
|
[_agentInternals]: agentInternals
|
|
2205
2852
|
};
|
|
2206
2853
|
return agent;
|
|
2207
2854
|
}
|
|
2208
2855
|
export {
|
|
2856
|
+
DebugCommandError,
|
|
2857
|
+
InvalidAgentOptionError,
|
|
2858
|
+
InvalidClaimOptionsError,
|
|
2209
2859
|
InvalidRunResourceError,
|
|
2210
2860
|
LeaseExpiredError,
|
|
2211
2861
|
LoopNotDefinedError,
|
|
@@ -2213,6 +2863,7 @@ export {
|
|
|
2213
2863
|
REQUIRED_TAG,
|
|
2214
2864
|
RUNTIME_TAG,
|
|
2215
2865
|
SessionBusyError,
|
|
2866
|
+
SessionInDebugError,
|
|
2216
2867
|
SessionInFlightError,
|
|
2217
2868
|
SessionPendingInterruptError,
|
|
2218
2869
|
StoreLoadError,
|