@tangle-network/agent-runtime 0.259.1 → 0.262.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/dist/{activation-Btw2npV2.js → activation-C0AoYRgS.js} +3 -3
- package/dist/{activation-Btw2npV2.js.map → activation-C0AoYRgS.js.map} +1 -1
- package/dist/{activation-Cus2oZaT.d.ts → activation-CozZXBTg.d.ts} +2 -2
- package/dist/agent.d.ts +2 -2
- package/dist/agent.js +2 -2
- package/dist/{bundle-DXrBPEFw.js → bundle-CvLGRVO-.js} +2 -2
- package/dist/{bundle-DXrBPEFw.js.map → bundle-CvLGRVO-.js.map} +1 -1
- package/dist/candidate-execution/index.js +5 -4
- package/dist/candidate-execution/index.js.map +1 -1
- package/dist/{coordination-driver-BmtrkNPu.js → coordination-driver-COGC8FK2.js} +377 -32
- package/dist/coordination-driver-COGC8FK2.js.map +1 -0
- package/dist/{delegate-DJgmZZKH.js → delegate-BC7Au73v.js} +2 -2
- package/dist/{delegate-DJgmZZKH.js.map → delegate-BC7Au73v.js.map} +1 -1
- package/dist/durable.d.ts +285 -57
- package/dist/durable.js +637 -108
- package/dist/durable.js.map +1 -1
- package/dist/{graph-BKRvWzHx.js → graph-DgODOGWN.js} +4 -3
- package/dist/graph-DgODOGWN.js.map +1 -0
- package/dist/{improvement-cycle-D0Os0Hg_.js → improvement-cycle-DirqO-fX.js} +8 -7
- package/dist/improvement-cycle-DirqO-fX.js.map +1 -0
- package/dist/{index-sGOO254Q.d.ts → index-B8tXCisZ.d.ts} +251 -293
- package/dist/index.d.ts +6 -6
- package/dist/index.js +9 -9
- package/dist/intelligence.d.ts +3 -3
- package/dist/intelligence.js +7 -6
- package/dist/intelligence.js.map +1 -1
- package/dist/kernel.d.ts +4 -4
- package/dist/kernel.js +9 -9
- package/dist/{loop-runner-bin-DAU4rNIL.d.ts → loop-runner-bin-BaZd1XIm.d.ts} +3 -3
- package/dist/{loop-runner-bin-pRlDgm1i.js → loop-runner-bin-C9P1ELVv.js} +3 -3
- package/dist/{loop-runner-bin-pRlDgm1i.js.map → loop-runner-bin-C9P1ELVv.js.map} +1 -1
- package/dist/loop-runner-bin.d.ts +1 -1
- package/dist/loop-runner-bin.js +1 -1
- package/dist/mcp/bin.js +3 -3
- package/dist/mcp/index.d.ts +6 -6
- package/dist/mcp/index.js +4 -4
- package/dist/{openai-tools-BsqD1_Zr.d.ts → openai-tools-CHwN_S24.d.ts} +2 -2
- package/dist/{prepare-RuaAclli.js → prepare-oHUQdC5-.js} +22 -452
- package/dist/prepare-oHUQdC5-.js.map +1 -0
- package/dist/profile-D3eXNBQV.js +438 -0
- package/dist/profile-D3eXNBQV.js.map +1 -0
- package/dist/profiles.d.ts +2 -2
- package/dist/{protected-model-port-BFhSgMAy.js → protected-model-port-DqF0qDU6.js} +4 -3
- package/dist/{protected-model-port-BFhSgMAy.js.map → protected-model-port-DqF0qDU6.js.map} +1 -1
- package/dist/{provision-supervisor-B9tf4soF.js → provision-supervisor-9FMwo-Es.js} +3 -3
- package/dist/{provision-supervisor-B9tf4soF.js.map → provision-supervisor-9FMwo-Es.js.map} +1 -1
- package/dist/{runtime-DKiucqGX.js → runtime-BXWVW51r.js} +218 -20
- package/dist/runtime-BXWVW51r.js.map +1 -0
- package/dist/{server-DIsiQ6mu.js → server-6g6KFwUC.js} +3 -3
- package/dist/{server-DIsiQ6mu.js.map → server-6g6KFwUC.js.map} +1 -1
- package/dist/{stream-agent-turn-DRTFLphI.d.ts → stream-agent-turn-u28hoxuR.d.ts} +2 -2
- package/dist/{structural-rollout-BIBxgW64.js → structural-rollout-WEfWpjub.js} +2 -2
- package/dist/{structural-rollout-BIBxgW64.js.map → structural-rollout-WEfWpjub.js.map} +1 -1
- package/dist/{substrate-BToFBpfh.d.ts → substrate-BeQiXkpa.d.ts} +2 -2
- package/dist/{supervise-DsQjhLN-.js → supervise-BeAI8-On.js} +295 -51
- package/dist/supervise-BeAI8-On.js.map +1 -0
- package/dist/{supervisor-CJyzUjc7.js → supervisor-BGGvnXvV.js} +243 -24
- package/dist/{supervisor-CJyzUjc7.js.map → supervisor-BGGvnXvV.js.map} +1 -1
- package/dist/testing.d.ts +2 -2
- package/dist/testing.js +14 -14
- package/dist/tui/index.d.ts +1 -1
- package/dist/tui/index.js +1 -1
- package/dist/{types-ChewVlpE.d.ts → types-CP3iQ8Ji.d.ts} +376 -4
- package/dist/{workspace-archive-DQGFwvM6.js → workspace-archive-C9lgf77y.js} +11 -11
- package/dist/workspace-archive-C9lgf77y.js.map +1 -0
- package/package.json +5 -5
- package/dist/coordination-driver-BmtrkNPu.js.map +0 -1
- package/dist/graph-BKRvWzHx.js.map +0 -1
- package/dist/improvement-cycle-D0Os0Hg_.js.map +0 -1
- package/dist/prepare-RuaAclli.js.map +0 -1
- package/dist/runtime-DKiucqGX.js.map +0 -1
- package/dist/supervise-DsQjhLN-.js.map +0 -1
- package/dist/workspace-archive-DQGFwvM6.js.map +0 -1
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Ct as InMemorySpawnJournal, Dn as runBrainLoop, Ei as detachedFrozen, Ft as assertValidBudget, H as scopeRetainedOwnerResourceReader, Ji as promptCacheTokenClasses, Mt as parseWorkerToolTraceArtifact, Nt as workerTraceAnalysisStore, St as InMemoryResultBlobStore, Ui as chargedTokens, Xt as createInbox, a as pickBestDelivered, aa as withBudgetResources, ai as writeAllBytes, an as isLiveNodeStatus, bt as FileResultBlobStore, ea as unmeteredSpend, er as resolveRedactor, ii as readCommittedJsonLines, it as errMessage, mi as providerAttemptEvidence, mt as createExecutorRegistry, o as runFinalizer, on as isTerminalNodeStatus, ot as freeSlots, q as resolveSpawnResourcePaths, r as bestDelivered, ra as addResourceSpend, ri as prepareJsonlAppend, s as runTree, tn as createPeerMailbox, v as withDriverExecutor, w as meterRuntimeOwnedProviderAttempt, xt as FileSpawnJournal } from "./supervisor-BGGvnXvV.js";
|
|
2
2
|
import { f as RuntimeRunStateError, m as ValidationError } from "./errors-DodWX-cb.js";
|
|
3
3
|
import { A as writeWorkerCancellation, M as writeWorkerSteerAcknowledgement, b as workerCancellationsDir, c as readWorkerCancelRequests, d as readWorkerSteerRequests, k as writeRunCancellation, l as readWorkerCancellation, o as readRunCancelRequest, r as claimWorkerSteerDelivery, s as readRunCancellation, u as readWorkerSteerAcknowledgement } from "./run-layout-vwd4SwX_.js";
|
|
4
4
|
import { agentProfileSchema, canonicalCandidateDigest } from "@tangle-network/agent-interface";
|
|
@@ -74,6 +74,12 @@ function createEventBus(now = Date.now) {
|
|
|
74
74
|
}
|
|
75
75
|
return best;
|
|
76
76
|
};
|
|
77
|
+
const pullRecord = (kinds) => {
|
|
78
|
+
const i = bestIndex(kinds);
|
|
79
|
+
if (i < 0) return void 0;
|
|
80
|
+
pulled++;
|
|
81
|
+
return queue.splice(i, 1)[0];
|
|
82
|
+
};
|
|
77
83
|
return {
|
|
78
84
|
async publish(event, opts) {
|
|
79
85
|
const record = staged.get(event) ?? {
|
|
@@ -92,10 +98,11 @@ function createEventBus(now = Date.now) {
|
|
|
92
98
|
return record;
|
|
93
99
|
},
|
|
94
100
|
pull(kinds) {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
101
|
+
return pullRecord(kinds)?.event;
|
|
102
|
+
},
|
|
103
|
+
pullRecord,
|
|
104
|
+
queued(kinds) {
|
|
105
|
+
return queue.filter((r) => matches(r, kinds));
|
|
99
106
|
},
|
|
100
107
|
subscribe(handler) {
|
|
101
108
|
subscribers.push(handler);
|
|
@@ -498,7 +505,8 @@ const journalEventKinds = [
|
|
|
498
505
|
"delivery-attempt",
|
|
499
506
|
"mail",
|
|
500
507
|
"escalation",
|
|
501
|
-
"analyst-defined"
|
|
508
|
+
"analyst-defined",
|
|
509
|
+
"acknowledgement"
|
|
502
510
|
];
|
|
503
511
|
/** The reserved coordination verb names — the complete set `createCoordinationTools` can emit
|
|
504
512
|
* (the analyst pair is conditional but still reserved). A driver's extra WORK tools must not
|
|
@@ -522,6 +530,7 @@ const coordinationVerbNames = [
|
|
|
522
530
|
"ask_parent",
|
|
523
531
|
"submit_result",
|
|
524
532
|
"stop",
|
|
533
|
+
"report_blocked",
|
|
525
534
|
"read_journal",
|
|
526
535
|
"list_analysts",
|
|
527
536
|
"run_analyst",
|
|
@@ -713,6 +722,33 @@ function spawnProfileArg() {
|
|
|
713
722
|
}).properties));
|
|
714
723
|
return spawnProfileArgCache;
|
|
715
724
|
}
|
|
725
|
+
/** `spawn_worker`'s `profile` argument when the run has a profiles table: one of the table's names,
|
|
726
|
+
* listed with each entry's description and whether a sealed verdict promoted it, or a profile the
|
|
727
|
+
* manager authors. Without a table the argument is the authored shape alone, byte for byte. */
|
|
728
|
+
function spawnProfileArgWithTable(profiles) {
|
|
729
|
+
const menu = [...profiles].map(([name, entry]) => {
|
|
730
|
+
return `- '${name}'${typeof entry.profile.description === "string" && entry.profile.description.length > 0 ? ` — ${entry.profile.description}` : ""} (${entry.promotion ? `promoted by sealed play ${JSON.stringify(entry.promotion.experiment.spec.id)}` : "exploratory"})`;
|
|
731
|
+
});
|
|
732
|
+
return { anyOf: [{
|
|
733
|
+
type: "string",
|
|
734
|
+
enum: [...profiles.keys()],
|
|
735
|
+
description: `The name of a profile in this run's profiles table. The runtime runs that exact profile, so do not retype it; other profile fields cannot be added to a name. Promoted entries beat their control in a sealed comparison; exploratory ones have no verdict yet.\n${menu.join("\n")}`
|
|
736
|
+
}, spawnProfileArg()] };
|
|
737
|
+
}
|
|
738
|
+
/** Why `spawn_worker` cannot use this `profile` argument against the profiles table, or
|
|
739
|
+
* `undefined` when it can. A name must be in the table. An authored profile must not take a table
|
|
740
|
+
* name: continuity and every per-name record key on `profile.name`, so one name must mean one
|
|
741
|
+
* profile. Without a table nothing is refused here, and the canonical schema answers as before. */
|
|
742
|
+
function profileTableRefusal(table, profile) {
|
|
743
|
+
if (table === void 0) return void 0;
|
|
744
|
+
if (typeof profile === "string") {
|
|
745
|
+
if (table.has(profile)) return void 0;
|
|
746
|
+
return `profile ${JSON.stringify(profile)} is not in this run's profiles table, which holds ${[...table.keys()].map((name) => JSON.stringify(name)).join(", ")}`;
|
|
747
|
+
}
|
|
748
|
+
const name = typeof profile === "object" && profile !== null ? profile.name : void 0;
|
|
749
|
+
if (typeof name !== "string" || !table.has(name)) return void 0;
|
|
750
|
+
return `profile.name ${JSON.stringify(name)} is a profiles-table entry: pass profile: ${JSON.stringify(name)} to run that exact profile, or give the profile you wrote another name`;
|
|
751
|
+
}
|
|
716
752
|
const BUDGET_FIELD = {
|
|
717
753
|
tokens: "maxTokens",
|
|
718
754
|
iterations: "maxIterations",
|
|
@@ -763,6 +799,7 @@ function createCoordinationTools(opts) {
|
|
|
763
799
|
/** Internal manager binding; its lifetime fences delivery without cancelling the worker scope. */
|
|
764
800
|
function createCoordinationToolsForManager(opts, lifetime) {
|
|
765
801
|
const deliverable = opts.deliverable;
|
|
802
|
+
const profileTable = opts.profiles !== void 0 && opts.profiles.size > 0 ? opts.profiles : void 0;
|
|
766
803
|
const readWorkerOutput = createWorkerOutputReader(opts.blobs);
|
|
767
804
|
const priorSubmission = deliverable === void 0 ? void 0 : opts.priorJournal?.find((record) => record.event.type === "submission");
|
|
768
805
|
let stopped = priorSubmission !== void 0;
|
|
@@ -770,6 +807,7 @@ function createCoordinationToolsForManager(opts, lifetime) {
|
|
|
770
807
|
let stopNotified = false;
|
|
771
808
|
let submitted = priorSubmission === void 0 ? void 0 : detachedFrozen({ result: priorSubmission.event.result });
|
|
772
809
|
let submissionInFlight;
|
|
810
|
+
let blockedEvidence;
|
|
773
811
|
let questionSeq = 0;
|
|
774
812
|
const ledger = [];
|
|
775
813
|
const questions = [...opts.priorQuestions ?? []];
|
|
@@ -856,6 +894,27 @@ function createCoordinationToolsForManager(opts, lifetime) {
|
|
|
856
894
|
});
|
|
857
895
|
return readyInFlight;
|
|
858
896
|
};
|
|
897
|
+
const deliveries = [];
|
|
898
|
+
let driverAttempt;
|
|
899
|
+
let journalReadTo = 0;
|
|
900
|
+
let lastRejection;
|
|
901
|
+
const flushedAnalystRuns = /* @__PURE__ */ new Set();
|
|
902
|
+
const eventWorker = (event) => event.type === "settled" ? event.worker.id : event.type === "finding" ? event.finding.fromWorker : event.type === "question" ? event.question.from : void 0;
|
|
903
|
+
const acknowledge = async (targets, by) => {
|
|
904
|
+
const fresh = targets.filter((delivery) => !delivery.acknowledged);
|
|
905
|
+
if (fresh.length === 0) return [];
|
|
906
|
+
const seqs = fresh.map((delivery) => delivery.record.seq);
|
|
907
|
+
await bus.publish({
|
|
908
|
+
type: "acknowledgement",
|
|
909
|
+
acknowledgement: detachedFrozen({
|
|
910
|
+
seqs,
|
|
911
|
+
by,
|
|
912
|
+
...driverAttempt === void 0 ? {} : { attempt: driverAttempt }
|
|
913
|
+
})
|
|
914
|
+
}, { queue: false });
|
|
915
|
+
for (const delivery of fresh) delivery.acknowledged = true;
|
|
916
|
+
return seqs;
|
|
917
|
+
};
|
|
859
918
|
const urgencyPriority = (u) => u === "blocks-run" ? 20 : u === "blocks-step" ? 10 : 0;
|
|
860
919
|
const str = (v, field) => {
|
|
861
920
|
if (typeof v !== "string" || v.length === 0) throw new Error(`coordination tools: "${field}" must be a non-empty string`);
|
|
@@ -1118,6 +1177,7 @@ function createCoordinationToolsForManager(opts, lifetime) {
|
|
|
1118
1177
|
await bus.publish(pending.event);
|
|
1119
1178
|
if (pending.analystRun) {
|
|
1120
1179
|
analystRuns.delete(pending.worker.id);
|
|
1180
|
+
flushedAnalystRuns.add(pending.worker.id);
|
|
1121
1181
|
unwatchWorker(pending.worker.id);
|
|
1122
1182
|
pendingSettlement = void 0;
|
|
1123
1183
|
const { route } = pending.analystRun;
|
|
@@ -1369,6 +1429,10 @@ function createCoordinationToolsForManager(opts, lifetime) {
|
|
|
1369
1429
|
type: "analyst-defined",
|
|
1370
1430
|
...ev.analyst
|
|
1371
1431
|
};
|
|
1432
|
+
if (ev.type === "acknowledgement") return {
|
|
1433
|
+
type: "acknowledgement",
|
|
1434
|
+
...ev.acknowledgement
|
|
1435
|
+
};
|
|
1372
1436
|
return {
|
|
1373
1437
|
type: ev.type,
|
|
1374
1438
|
...ev.down
|
|
@@ -1579,9 +1643,11 @@ function createCoordinationToolsForManager(opts, lifetime) {
|
|
|
1579
1643
|
usedBytes += bytes;
|
|
1580
1644
|
}
|
|
1581
1645
|
const last = entries[entries.length - 1];
|
|
1646
|
+
const nextRow = last === void 0 ? sinceRow : last.row + 1;
|
|
1647
|
+
journalReadTo = Math.max(journalReadTo, nextRow);
|
|
1582
1648
|
return {
|
|
1583
1649
|
entries,
|
|
1584
|
-
nextRow
|
|
1650
|
+
nextRow,
|
|
1585
1651
|
remaining: matching.length - index,
|
|
1586
1652
|
truncated: bounded,
|
|
1587
1653
|
bounds: {
|
|
@@ -1673,6 +1739,39 @@ function createCoordinationToolsForManager(opts, lifetime) {
|
|
|
1673
1739
|
...resumed ? { resumed: true } : {}
|
|
1674
1740
|
});
|
|
1675
1741
|
const liveSnapshot = () => opts.scope.view.nodes.filter((n) => isLiveNodeStatus(n.status)).map((n) => projectNodeEvidence(n));
|
|
1742
|
+
const openWork = () => {
|
|
1743
|
+
const received = new Set(ledger.map((worker) => worker.id));
|
|
1744
|
+
const nodes = opts.scope.view?.nodes ?? [];
|
|
1745
|
+
return {
|
|
1746
|
+
running: nodes.filter((node) => isLiveNodeStatus(node.status) && node.status !== "waiting"),
|
|
1747
|
+
unqueued: nodes.filter((node) => !isLiveNodeStatus(node.status) && !received.has(node.id) && !flushedAnalystRuns.has(node.id)),
|
|
1748
|
+
queued: bus.queued(["settled", "finding"])
|
|
1749
|
+
};
|
|
1750
|
+
};
|
|
1751
|
+
const openWorkRefusal = (verb) => {
|
|
1752
|
+
const { running, unqueued, queued } = openWork();
|
|
1753
|
+
if (running.length === 0 && unqueued.length === 0 && queued.length === 0) return void 0;
|
|
1754
|
+
const parts = [];
|
|
1755
|
+
if (running.length > 0) parts.push(`${running.length} worker${running.length === 1 ? " is" : "s are"} still running (${running.map((node) => node.id).join(", ")})`);
|
|
1756
|
+
const waiting = unqueued.length + queued.length;
|
|
1757
|
+
if (waiting > 0) parts.push(`${waiting} event${waiting === 1 ? " is" : "s are"} waiting for you in await_event`);
|
|
1758
|
+
return {
|
|
1759
|
+
error: "open-work",
|
|
1760
|
+
reason: `${parts.join(" and ")}. Call await_event until it returns idle, read each settled worker's output, and then call ${verb} again. Nothing was ${verb === "stop" ? "stopped" : "checked"}.`,
|
|
1761
|
+
running: running.map((node) => ({
|
|
1762
|
+
id: node.id,
|
|
1763
|
+
label: node.label,
|
|
1764
|
+
status: node.status
|
|
1765
|
+
})),
|
|
1766
|
+
waiting: [...queued.map((record) => ({
|
|
1767
|
+
type: record.event.type,
|
|
1768
|
+
...eventWorker(record.event) === void 0 ? {} : { worker: eventWorker(record.event) }
|
|
1769
|
+
})), ...unqueued.map((node) => ({
|
|
1770
|
+
type: "settled",
|
|
1771
|
+
worker: node.id
|
|
1772
|
+
}))]
|
|
1773
|
+
};
|
|
1774
|
+
};
|
|
1676
1775
|
const freeWorkerSlots = () => usesTreeWideLimit() ? sharedWorkerCapacity()?.freeSlots ?? null : freeSlots(localLiveWorkerCount(), maxLiveWorkers);
|
|
1677
1776
|
const readProgress = (id) => {
|
|
1678
1777
|
const scope = opts.scope;
|
|
@@ -1756,11 +1855,11 @@ function createCoordinationToolsForManager(opts, lifetime) {
|
|
|
1756
1855
|
const tools = [
|
|
1757
1856
|
{
|
|
1758
1857
|
name: "spawn_worker",
|
|
1759
|
-
description: "Start a worker the driver will drive. `profile` is the worker or another driver; `task` is what it should do. Reserves budget from the conserved pool and fails closed. Pass an optional `budget` (per-field) to give a hard sub-task more than the default — it merges over the per-worker default; the conserved pool is still the hard fence. When a max-live-workers cap is set it also fails closed (`error: \"max-live-workers\"`) while that many workers are still in flight — settle or steer one before spawning another. Pass a `key` naming the assignment to make it run-once ACROSS restarts: a key that already completed returns the finished result (`resumed: \"completed\"` — no work re-runs, nothing is spent), a key whose prior attempt failed (`down`) spawns fresh and says so (`resumed: \"retried\"`), and a key with no terminal receipt is refused (`error: \"in-doubt\"`) until its exact prior execution is recovered. A key still running is refused (`error: \"duplicate-key\"`). Returns `freeSlots`: how many MORE workers you can start right now (`null` = uncapped). While `freeSlots > 0` there is idle capacity — call this again to fill it rather than waiting; parallel workers finish the run sooner than one at a time.",
|
|
1858
|
+
description: "Start a worker the driver will drive. `profile` is the worker or another driver; `task` is what it should do. Reserves budget from the conserved pool and fails closed. Pass an optional `budget` (per-field) to give a hard sub-task more than the default — it merges over the per-worker default; the conserved pool is still the hard fence. When a max-live-workers cap is set it also fails closed (`error: \"max-live-workers\"`) while that many workers are still in flight — settle or steer one before spawning another. Pass a `key` naming the assignment to make it run-once ACROSS restarts: a key that already completed returns the finished result (`resumed: \"completed\"` — no work re-runs, nothing is spent), a key whose prior attempt failed (`down`) spawns fresh and says so (`resumed: \"retried\"`), and a key with no terminal receipt is refused (`error: \"in-doubt\"`) until its exact prior execution is recovered. A key still running is refused (`error: \"duplicate-key\"`). Returns `freeSlots`: how many MORE workers you can start right now (`null` = uncapped). While `freeSlots > 0` there is idle capacity — call this again to fill it rather than waiting; parallel workers finish the run sooner than one at a time." + (profileTable === void 0 ? "" : " This run has a profiles table: pass `profile` as one of the table's names to run that exact profile, or write a new profile under a name the table does not hold."),
|
|
1760
1859
|
inputSchema: {
|
|
1761
1860
|
type: "object",
|
|
1762
1861
|
properties: {
|
|
1763
|
-
profile: spawnProfileArg(),
|
|
1862
|
+
profile: profileTable === void 0 ? spawnProfileArg() : spawnProfileArgWithTable(profileTable),
|
|
1764
1863
|
task: { description: "The task the worker should perform." },
|
|
1765
1864
|
label: {
|
|
1766
1865
|
type: "string",
|
|
@@ -1775,6 +1874,10 @@ function createCoordinationToolsForManager(opts, lifetime) {
|
|
|
1775
1874
|
enum: ["fresh", "resume"],
|
|
1776
1875
|
description: "How this spawn continues the node's prior work. \"fresh\" (the default) starts a brand-new session. \"resume\" re-attaches to the node's most recent SETTLED worker: a NEW live worker is spawned whose session continues where that worker stopped (the backend receives the prior workerId and the resume sequence). Resume fails closed when the node has no settled prior worker (`error: \"resume-no-prior\"` — spawn it fresh first), while a prior worker of the node is still live (`error: \"resume-while-live\"` — steer_agent is the live-worker channel), and under a `key` (`error: \"resume-with-key\"` — keys are run-once, resume runs again). Omit to use the run's declared default for this profile name."
|
|
1777
1876
|
},
|
|
1877
|
+
successorOf: {
|
|
1878
|
+
type: "string",
|
|
1879
|
+
description: "The workerId of a SETTLED worker you spawned that this new worker replaces — for example one that failed, stalled, or finished with a weak result, restarted with a changed profile or task. The run record then names the predecessor on the new worker. Refused for an id you did not spawn (`error: \"successor-unknown\"`) and for a worker still live (`error: \"successor-live\"` — await_event until it settles). Put what the successor needs from its predecessor in `task`."
|
|
1880
|
+
},
|
|
1778
1881
|
budget: {
|
|
1779
1882
|
type: "object",
|
|
1780
1883
|
description: "Optional per-spawn budget that merges over the per-worker default (per field). Only set the ceilings this sub-task needs raised; the conserved pool still fences.",
|
|
@@ -1827,7 +1930,21 @@ function createCoordinationToolsForManager(opts, lifetime) {
|
|
|
1827
1930
|
live,
|
|
1828
1931
|
freeSlots: freeWorkerSlots()
|
|
1829
1932
|
}))(liveWorkerCount()));
|
|
1830
|
-
const
|
|
1933
|
+
const tableRefusal = profileTableRefusal(profileTable, a.profile);
|
|
1934
|
+
if (tableRefusal !== void 0) return {
|
|
1935
|
+
error: "invalid-profile",
|
|
1936
|
+
reason: tableRefusal,
|
|
1937
|
+
issues: [{
|
|
1938
|
+
path: "profile",
|
|
1939
|
+
message: tableRefusal
|
|
1940
|
+
}]
|
|
1941
|
+
};
|
|
1942
|
+
const tableEntry = typeof a.profile === "string" ? profileTable?.get(a.profile) : void 0;
|
|
1943
|
+
const resourcePaths = tableEntry === void 0 ? await resolveSpawnResourcePaths(a.profile, opts.spawnResourceReader ?? opts.spawnResourceRoot) : {
|
|
1944
|
+
ok: true,
|
|
1945
|
+
profile: tableEntry.profile,
|
|
1946
|
+
resolved: []
|
|
1947
|
+
};
|
|
1831
1948
|
if (!resourcePaths.ok) return {
|
|
1832
1949
|
error: "invalid-profile",
|
|
1833
1950
|
reason: `resources.${resourcePaths.at}: ${resourcePaths.reason}`,
|
|
@@ -1854,6 +1971,22 @@ function createCoordinationToolsForManager(opts, lifetime) {
|
|
|
1854
1971
|
live: liveWorkerCount(),
|
|
1855
1972
|
freeSlots: freeWorkerSlots()
|
|
1856
1973
|
});
|
|
1974
|
+
const successorOf = a.successorOf === void 0 ? void 0 : str(a.successorOf, "successorOf");
|
|
1975
|
+
if (successorOf !== void 0) {
|
|
1976
|
+
const predecessor = nodeForWorker(successorOf);
|
|
1977
|
+
if (predecessor === void 0 || predecessor.parent !== opts.scope.view.root) return {
|
|
1978
|
+
error: "successor-unknown",
|
|
1979
|
+
reason: `'${successorOf}' is not a worker this manager spawned — successorOf takes a workerId from one of your own spawn_worker results`,
|
|
1980
|
+
live: liveWorkerCount(),
|
|
1981
|
+
freeSlots: freeWorkerSlots()
|
|
1982
|
+
};
|
|
1983
|
+
if (isLiveNodeStatus(predecessor.status)) return {
|
|
1984
|
+
error: "successor-live",
|
|
1985
|
+
reason: `worker '${successorOf}' has not settled — await_event until it does, then spawn its successor (steer_agent redirects a live worker instead)`,
|
|
1986
|
+
live: liveWorkerCount(),
|
|
1987
|
+
freeSlots: freeWorkerSlots()
|
|
1988
|
+
};
|
|
1989
|
+
}
|
|
1857
1990
|
const task = detachedFrozen(a.task);
|
|
1858
1991
|
const label = typeof a.label === "string" ? a.label : "worker";
|
|
1859
1992
|
if (opts.preflightSpawn) {
|
|
@@ -1887,13 +2020,15 @@ function createCoordinationToolsForManager(opts, lifetime) {
|
|
|
1887
2020
|
...key !== void 0 ? { key } : {},
|
|
1888
2021
|
continuity: continuity.continuity,
|
|
1889
2022
|
...continuity.continuity === "resume" ? { resume: continuity.resume } : {},
|
|
2023
|
+
...successorOf !== void 0 ? { successorOf } : {},
|
|
1890
2024
|
...peerMailUrl !== void 0 ? { peerMailUrl } : {}
|
|
1891
2025
|
});
|
|
1892
2026
|
const res = opts.scope.spawn(() => opts.makeWorkerAgent(profile, context), task, {
|
|
1893
2027
|
budget,
|
|
1894
2028
|
label,
|
|
1895
2029
|
assignmentId,
|
|
1896
|
-
...key !== void 0 ? { key } : {}
|
|
2030
|
+
...key !== void 0 ? { key } : {},
|
|
2031
|
+
...successorOf !== void 0 ? { successorOf } : {}
|
|
1897
2032
|
});
|
|
1898
2033
|
if (res.ok && res.prior?.state === "completed") {
|
|
1899
2034
|
const s = res.prior.settled;
|
|
@@ -1932,6 +2067,7 @@ function createCoordinationToolsForManager(opts, lifetime) {
|
|
|
1932
2067
|
...res.handle.executionBindings === void 0 ? {} : { executionBindings: res.handle.executionBindings },
|
|
1933
2068
|
continuity: continuity.continuity,
|
|
1934
2069
|
...continuity.continuity === "resume" ? { resume: continuity.resume } : {},
|
|
2070
|
+
...successorOf !== void 0 ? { successorOf } : {},
|
|
1935
2071
|
live: liveWorkerCount(),
|
|
1936
2072
|
freeSlots: freeWorkerSlots(),
|
|
1937
2073
|
...priorHistory,
|
|
@@ -2045,24 +2181,50 @@ function createCoordinationToolsForManager(opts, lifetime) {
|
|
|
2045
2181
|
},
|
|
2046
2182
|
{
|
|
2047
2183
|
name: "await_event",
|
|
2048
|
-
description: "Wait for and pull the next message a worker, sub-driver, or analyst sent up — the unified inbox. Read a settled artifact with the returned `outputRead` call; the receipt carries its reference, not its bytes. An event is one of: a settled worker output ('settled'), a question needing your answer ('question', from ask_parent / the worker's ask-user), or a trace-analyst finding ('finding', from analyze-on-settle). Pass kinds:['settled'] for just the next finished worker; omit `kinds` to also receive questions and findings. Returns { idle: true } when nothing is queued and no workers are live. If a worker is still running when the wait elapses, returns { pending: true, live: [...] } (the workers still in flight) instead of blocking indefinitely — call await_event again to keep waiting; the settlement is not lost. Every reply carries `freeSlots`: how many more workers you can start right now (`null` = uncapped). A settled worker frees its slot, so `freeSlots > 0` means capacity is sitting idle — spawn into it before waiting again.",
|
|
2184
|
+
description: "Wait for and pull the next message a worker, sub-driver, or analyst sent up — the unified inbox. Read a settled artifact with the returned `outputRead` call; the receipt carries its reference, not its bytes. An event is one of: a settled worker output ('settled'), a question needing your answer ('question', from ask_parent / the worker's ask-user), or a trace-analyst finding ('finding', from analyze-on-settle). Pass kinds:['settled'] for just the next finished worker; omit `kinds` to also receive questions and findings. Returns { idle: true } when nothing is queued and no workers are live. If a worker is still running when the wait elapses, returns { pending: true, live: [...] } (the workers still in flight) instead of blocking indefinitely — call await_event again to keep waiting; the settlement is not lost. Every reply carries `freeSlots`: how many more workers you can start right now (`null` = uncapped). A settled worker frees its slot, so `freeSlots > 0` means capacity is sitting idle — spawn into it before waiting again. Each event carries `eventSeq`; pass the ones you have processed in `acknowledge` on a later call. An event delivered to a turn that ends in failure is named again when you are re-entered, until it is acknowledged.",
|
|
2049
2185
|
inputSchema: {
|
|
2050
2186
|
type: "object",
|
|
2051
|
-
properties: {
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2187
|
+
properties: {
|
|
2188
|
+
kinds: {
|
|
2189
|
+
type: "array",
|
|
2190
|
+
items: {
|
|
2191
|
+
type: "string",
|
|
2192
|
+
enum: [...awaitableEventKinds]
|
|
2193
|
+
},
|
|
2194
|
+
description: "Restrict to these event kinds (any if omitted)."
|
|
2056
2195
|
},
|
|
2057
|
-
|
|
2058
|
-
|
|
2196
|
+
acknowledge: {
|
|
2197
|
+
type: "array",
|
|
2198
|
+
items: {
|
|
2199
|
+
type: "integer",
|
|
2200
|
+
minimum: 0
|
|
2201
|
+
},
|
|
2202
|
+
description: "The eventSeq of each earlier event you have now processed."
|
|
2203
|
+
}
|
|
2204
|
+
}
|
|
2059
2205
|
},
|
|
2060
2206
|
handler: async (raw) => {
|
|
2061
|
-
const
|
|
2207
|
+
const args = raw === void 0 ? {} : obj(raw);
|
|
2208
|
+
const k = args.kinds;
|
|
2062
2209
|
const kinds = Array.isArray(k) ? k.filter(isAwaitableEventKind) : void 0;
|
|
2063
|
-
|
|
2210
|
+
if (Array.isArray(args.acknowledge)) {
|
|
2211
|
+
const named = new Set(args.acknowledge.filter((value) => typeof value === "number" && Number.isInteger(value)));
|
|
2212
|
+
await acknowledge(deliveries.filter((delivery) => named.has(delivery.record.seq)), "manager");
|
|
2213
|
+
}
|
|
2214
|
+
const deliver = (record) => {
|
|
2215
|
+
deliveries.push({
|
|
2216
|
+
record,
|
|
2217
|
+
attempt: driverAttempt,
|
|
2218
|
+
acknowledged: false
|
|
2219
|
+
});
|
|
2220
|
+
return {
|
|
2221
|
+
...projectEvent(record.event),
|
|
2222
|
+
eventSeq: record.seq
|
|
2223
|
+
};
|
|
2224
|
+
};
|
|
2225
|
+
let ev = bus.pullRecord(kinds);
|
|
2064
2226
|
if (ev) return {
|
|
2065
|
-
...
|
|
2227
|
+
...deliver(ev),
|
|
2066
2228
|
freeSlots: freeWorkerSlots()
|
|
2067
2229
|
};
|
|
2068
2230
|
const raced = await raceDrainWithTimeout(ensureDrain());
|
|
@@ -2071,13 +2233,13 @@ function createCoordinationToolsForManager(opts, lifetime) {
|
|
|
2071
2233
|
live: liveSnapshot(),
|
|
2072
2234
|
freeSlots: freeWorkerSlots()
|
|
2073
2235
|
};
|
|
2074
|
-
ev = bus.
|
|
2236
|
+
ev = bus.pullRecord(kinds);
|
|
2075
2237
|
if (!ev) return {
|
|
2076
2238
|
idle: !raced.drained,
|
|
2077
2239
|
freeSlots: freeWorkerSlots()
|
|
2078
2240
|
};
|
|
2079
2241
|
return {
|
|
2080
|
-
...
|
|
2242
|
+
...deliver(ev),
|
|
2081
2243
|
freeSlots: freeWorkerSlots()
|
|
2082
2244
|
};
|
|
2083
2245
|
}
|
|
@@ -2253,6 +2415,18 @@ function createCoordinationToolsForManager(opts, lifetime) {
|
|
|
2253
2415
|
};
|
|
2254
2416
|
const a = obj(raw);
|
|
2255
2417
|
if (!Object.hasOwn(a, "result")) throw new Error("submit_result: \"result\" is required");
|
|
2418
|
+
const open = openWorkRefusal("submit_result");
|
|
2419
|
+
if (open !== void 0) {
|
|
2420
|
+
lastRejection = {
|
|
2421
|
+
at: Date.now(),
|
|
2422
|
+
reason: String(open.reason)
|
|
2423
|
+
};
|
|
2424
|
+
return {
|
|
2425
|
+
accepted: false,
|
|
2426
|
+
stop: false,
|
|
2427
|
+
...open
|
|
2428
|
+
};
|
|
2429
|
+
}
|
|
2256
2430
|
const result = structuredClone(a.result);
|
|
2257
2431
|
let accepted = false;
|
|
2258
2432
|
let thrown;
|
|
@@ -2271,10 +2445,15 @@ function createCoordinationToolsForManager(opts, lifetime) {
|
|
|
2271
2445
|
} catch (error) {
|
|
2272
2446
|
diagnosticError = error instanceof Error ? error.message : String(error);
|
|
2273
2447
|
}
|
|
2448
|
+
const refusal = thrown === void 0 ? `the independent check did not pass on this result${explanation ? `. ${explanation}` : deliverable.describe ? `. Expected: ${deliverable.describe}` : ""}` : `the independent check THREW, so nothing was accepted: ${thrown}. This is a fault in the check, not necessarily in your result — report it rather than resubmitting unchanged`;
|
|
2449
|
+
lastRejection = {
|
|
2450
|
+
at: Date.now(),
|
|
2451
|
+
reason: refusal
|
|
2452
|
+
};
|
|
2274
2453
|
return {
|
|
2275
2454
|
accepted: false,
|
|
2276
2455
|
stop: false,
|
|
2277
|
-
reason:
|
|
2456
|
+
reason: refusal,
|
|
2278
2457
|
...diagnosticError === void 0 ? {} : { diagnosticError }
|
|
2279
2458
|
};
|
|
2280
2459
|
}
|
|
@@ -2307,6 +2486,7 @@ function createCoordinationToolsForManager(opts, lifetime) {
|
|
|
2307
2486
|
} finally {
|
|
2308
2487
|
if (submissionInFlight === commit) submissionInFlight = void 0;
|
|
2309
2488
|
}
|
|
2489
|
+
await acknowledge(deliveries, "result-accepted");
|
|
2310
2490
|
return {
|
|
2311
2491
|
accepted: true,
|
|
2312
2492
|
retained: "this-result",
|
|
@@ -2336,6 +2516,11 @@ function createCoordinationToolsForManager(opts, lifetime) {
|
|
|
2336
2516
|
...unheard.length > 0 ? { unheardQuestionIds: unheard.map((q) => q.id) } : {}
|
|
2337
2517
|
});
|
|
2338
2518
|
}
|
|
2519
|
+
const open = openWorkRefusal("stop");
|
|
2520
|
+
if (open !== void 0) return Promise.resolve({
|
|
2521
|
+
stopped: false,
|
|
2522
|
+
...open
|
|
2523
|
+
});
|
|
2339
2524
|
stopped = true;
|
|
2340
2525
|
const r = obj(raw).reason;
|
|
2341
2526
|
reason = typeof r === "string" ? r : void 0;
|
|
@@ -2343,6 +2528,97 @@ function createCoordinationToolsForManager(opts, lifetime) {
|
|
|
2343
2528
|
return Promise.resolve({ stopped: true });
|
|
2344
2529
|
}
|
|
2345
2530
|
},
|
|
2531
|
+
{
|
|
2532
|
+
name: "report_blocked",
|
|
2533
|
+
description: [
|
|
2534
|
+
"Report that a tool you need keeps failing, so the run cannot go on.",
|
|
2535
|
+
"Name the tool, the arguments you called it with, and the error you saw.",
|
|
2536
|
+
"The coordinator calls that tool again, with those arguments, under your identity.",
|
|
2537
|
+
"When the call succeeds you are not blocked: the reply carries its result, and you continue.",
|
|
2538
|
+
"When it fails again, the run ends as blocked and the record keeps both errors.",
|
|
2539
|
+
"submit_result, stop and report_blocked cannot be probed."
|
|
2540
|
+
].join(" "),
|
|
2541
|
+
inputSchema: {
|
|
2542
|
+
type: "object",
|
|
2543
|
+
properties: {
|
|
2544
|
+
tool: {
|
|
2545
|
+
type: "string",
|
|
2546
|
+
description: "The tool that failed, as you called it."
|
|
2547
|
+
},
|
|
2548
|
+
arguments: {
|
|
2549
|
+
type: "object",
|
|
2550
|
+
description: "The arguments you called it with. Omit for none."
|
|
2551
|
+
},
|
|
2552
|
+
error: {
|
|
2553
|
+
type: "string",
|
|
2554
|
+
description: "The error the tool returned to you."
|
|
2555
|
+
}
|
|
2556
|
+
},
|
|
2557
|
+
required: ["tool", "error"],
|
|
2558
|
+
additionalProperties: false
|
|
2559
|
+
},
|
|
2560
|
+
handler: async (raw) => {
|
|
2561
|
+
const a = obj(raw);
|
|
2562
|
+
const named = str(a.tool, "tool");
|
|
2563
|
+
const reported = str(a.error, "error");
|
|
2564
|
+
const bare = named.replace(/^mcp__.+?__/u, "").replace(/^.*?coordination_+/u, "");
|
|
2565
|
+
if (unprobeableVerbs.has(bare)) return {
|
|
2566
|
+
blocked: false,
|
|
2567
|
+
error: "unprobeable",
|
|
2568
|
+
reason: `${bare} changes the run, so the coordinator does not call it for you`
|
|
2569
|
+
};
|
|
2570
|
+
const target = opts.resolveProbeTool?.(bare) ?? tools.find((tool) => tool.name === bare);
|
|
2571
|
+
if (target === void 0) return {
|
|
2572
|
+
blocked: false,
|
|
2573
|
+
error: "unknown-tool",
|
|
2574
|
+
reason: `no tool named ${JSON.stringify(bare)} is served to you, so there is nothing to probe; call the tools you were given`
|
|
2575
|
+
};
|
|
2576
|
+
const args = a.arguments === void 0 ? {} : typeof a.arguments === "object" && a.arguments !== null && !Array.isArray(a.arguments) ? a.arguments : void 0;
|
|
2577
|
+
if (args === void 0) return {
|
|
2578
|
+
blocked: false,
|
|
2579
|
+
error: "invalid-arguments",
|
|
2580
|
+
reason: "\"arguments\" must be an object"
|
|
2581
|
+
};
|
|
2582
|
+
let probe;
|
|
2583
|
+
try {
|
|
2584
|
+
probe = {
|
|
2585
|
+
ok: true,
|
|
2586
|
+
result: await runWithin(target.handler(structuredClone(args)), REPORT_BLOCKED_PROBE_MS, `the probe of ${bare} did not answer within ${REPORT_BLOCKED_PROBE_MS}ms`)
|
|
2587
|
+
};
|
|
2588
|
+
} catch (error) {
|
|
2589
|
+
probe = {
|
|
2590
|
+
ok: false,
|
|
2591
|
+
error: error instanceof Error ? error.message : String(error)
|
|
2592
|
+
};
|
|
2593
|
+
}
|
|
2594
|
+
if (probe.ok) return {
|
|
2595
|
+
blocked: false,
|
|
2596
|
+
probe: {
|
|
2597
|
+
tool: bare,
|
|
2598
|
+
ok: true,
|
|
2599
|
+
result: probe.result
|
|
2600
|
+
},
|
|
2601
|
+
guidance: "The call worked when the coordinator made it under your identity, so the tool is not blocked. Use this result and continue the objective."
|
|
2602
|
+
};
|
|
2603
|
+
blockedEvidence = Object.freeze({
|
|
2604
|
+
tool: bare,
|
|
2605
|
+
reported,
|
|
2606
|
+
probed: probe.error
|
|
2607
|
+
});
|
|
2608
|
+
stopped = true;
|
|
2609
|
+
reason = `blocked: ${bare} failed when the coordinator probed it: ${probe.error}`;
|
|
2610
|
+
notifyStop();
|
|
2611
|
+
return {
|
|
2612
|
+
blocked: true,
|
|
2613
|
+
stopped: true,
|
|
2614
|
+
probe: {
|
|
2615
|
+
tool: bare,
|
|
2616
|
+
ok: false,
|
|
2617
|
+
error: probe.error
|
|
2618
|
+
}
|
|
2619
|
+
};
|
|
2620
|
+
}
|
|
2621
|
+
},
|
|
2346
2622
|
{
|
|
2347
2623
|
name: "read_journal",
|
|
2348
2624
|
description: [
|
|
@@ -2563,9 +2839,74 @@ function createCoordinationToolsForManager(opts, lifetime) {
|
|
|
2563
2839
|
definedAnalysts: () => definedAnalysts,
|
|
2564
2840
|
drainResolved,
|
|
2565
2841
|
abortWorker,
|
|
2842
|
+
beginDriverAttempt: (attempt) => {
|
|
2843
|
+
driverAttempt = attempt;
|
|
2844
|
+
},
|
|
2845
|
+
endDriverAttempt: async (outcome) => {
|
|
2846
|
+
const attempt = driverAttempt;
|
|
2847
|
+
if (outcome === "completed") await acknowledge(deliveries.filter((delivery) => delivery.attempt === attempt), "turn-completed");
|
|
2848
|
+
},
|
|
2849
|
+
reentryState: () => {
|
|
2850
|
+
const { unqueued, queued } = openWork();
|
|
2851
|
+
const deliveredSettled = new Set(deliveries.flatMap((delivery) => delivery.record.event.type === "settled" ? [delivery.record.event.worker.id] : []));
|
|
2852
|
+
return detachedFrozen({
|
|
2853
|
+
journalRows: priorJournal.length + bus.history().length,
|
|
2854
|
+
journalReadTo,
|
|
2855
|
+
live: (opts.scope.view?.nodes ?? []).filter((node) => isLiveNodeStatus(node.status)).map((node) => ({
|
|
2856
|
+
id: node.id,
|
|
2857
|
+
label: node.label,
|
|
2858
|
+
status: node.status
|
|
2859
|
+
})),
|
|
2860
|
+
settled: [...ledger.map((worker) => ({
|
|
2861
|
+
id: worker.id,
|
|
2862
|
+
status: worker.status,
|
|
2863
|
+
...worker.status === "done" && worker.valid !== void 0 ? { valid: worker.valid } : {},
|
|
2864
|
+
delivered: deliveredSettled.has(worker.id)
|
|
2865
|
+
})), ...unqueued.map((node) => ({
|
|
2866
|
+
id: node.id,
|
|
2867
|
+
status: node.status === "done" ? "done" : "down",
|
|
2868
|
+
delivered: false
|
|
2869
|
+
}))],
|
|
2870
|
+
waiting: [...queued.map((record) => ({
|
|
2871
|
+
type: record.event.type,
|
|
2872
|
+
...eventWorker(record.event) === void 0 ? {} : { worker: eventWorker(record.event) }
|
|
2873
|
+
})), ...unqueued.map((node) => ({
|
|
2874
|
+
type: "settled",
|
|
2875
|
+
worker: node.id
|
|
2876
|
+
}))],
|
|
2877
|
+
unacknowledged: deliveries.filter((delivery) => !delivery.acknowledged).map((delivery) => ({
|
|
2878
|
+
seq: delivery.record.seq,
|
|
2879
|
+
type: delivery.record.event.type,
|
|
2880
|
+
...eventWorker(delivery.record.event) === void 0 ? {} : { worker: eventWorker(delivery.record.event) },
|
|
2881
|
+
...delivery.attempt === void 0 ? {} : { attempt: delivery.attempt }
|
|
2882
|
+
})),
|
|
2883
|
+
...lastRejection === void 0 ? {} : { lastRejection }
|
|
2884
|
+
});
|
|
2885
|
+
},
|
|
2886
|
+
blocked: () => blockedEvidence,
|
|
2566
2887
|
...peerMail ? { peerMail } : {}
|
|
2567
2888
|
};
|
|
2568
2889
|
}
|
|
2890
|
+
/** The verbs `report_blocked` never calls on a manager's behalf: each one changes the run. */
|
|
2891
|
+
const unprobeableVerbs = /* @__PURE__ */ new Set([
|
|
2892
|
+
"submit_result",
|
|
2893
|
+
"stop",
|
|
2894
|
+
"report_blocked"
|
|
2895
|
+
]);
|
|
2896
|
+
/** How long one `report_blocked` probe may run before it counts as a failure. */
|
|
2897
|
+
const REPORT_BLOCKED_PROBE_MS = 6e4;
|
|
2898
|
+
async function runWithin(work, ms, message) {
|
|
2899
|
+
let timer;
|
|
2900
|
+
const timeout = new Promise((_, reject) => {
|
|
2901
|
+
timer = setTimeout(() => reject(new Error(message)), ms);
|
|
2902
|
+
if (typeof timer?.unref === "function") timer.unref();
|
|
2903
|
+
});
|
|
2904
|
+
try {
|
|
2905
|
+
return await Promise.race([work, timeout]);
|
|
2906
|
+
} finally {
|
|
2907
|
+
if (timer) clearTimeout(timer);
|
|
2908
|
+
}
|
|
2909
|
+
}
|
|
2569
2910
|
function nextUnkeyedAssignmentOrdinal(scope) {
|
|
2570
2911
|
let next = 0;
|
|
2571
2912
|
const views = [scope.resume?.view, scope.view];
|
|
@@ -3273,13 +3614,13 @@ function formatOverspend(violation) {
|
|
|
3273
3614
|
* (can't afford a worker) and usd (a usd-capped pool whose ceiling the driver's own metered
|
|
3274
3615
|
* inference has drained — `meter` debits usd, so without this a huge-token/small-usd pool would
|
|
3275
3616
|
* overspend usd up to the turn tripwire). */
|
|
3276
|
-
function poolStarved(scope, perWorker) {
|
|
3617
|
+
function poolStarved(scope, perWorker, preserveOwnerTurns = false) {
|
|
3277
3618
|
const b = scope.budget;
|
|
3278
3619
|
if (scope.view.inFlight > 0 || scope.view.waiting > 0) return false;
|
|
3279
|
-
const tokenStarved = b.tokensLeft < perWorker.maxTokens;
|
|
3620
|
+
const tokenStarved = preserveOwnerTurns ? b.tokensLeft <= 0 : b.tokensLeft < perWorker.maxTokens;
|
|
3280
3621
|
const iterationStarved = b.iterationsLeft <= 0;
|
|
3281
|
-
const usdStarved = b.usdCapped && (b.usdLeft <= 0 || perWorker.maxUsd !== void 0 && b.usdLeft < perWorker.maxUsd);
|
|
3282
|
-
const resourceStarved = Object.entries(b.resources ?? {}).some(([name, value]) => !value.known || value.remaining <= 0 || value.remaining < (perWorker.resources?.[name]?.limit ?? 0));
|
|
3622
|
+
const usdStarved = b.usdCapped && (b.usdLeft <= 0 || !preserveOwnerTurns && perWorker.maxUsd !== void 0 && b.usdLeft < perWorker.maxUsd);
|
|
3623
|
+
const resourceStarved = Object.entries(b.resources ?? {}).some(([name, value]) => !value.known || value.remaining <= 0 || !preserveOwnerTurns && value.remaining < (perWorker.resources?.[name]?.limit ?? 0));
|
|
3283
3624
|
return tokenStarved || iterationStarved || usdStarved || resourceStarved;
|
|
3284
3625
|
}
|
|
3285
3626
|
/** The absolute wall-clock deadline (when the root set one) has passed. */
|
|
@@ -3680,6 +4021,7 @@ function driverAgent(opts) {
|
|
|
3680
4021
|
},
|
|
3681
4022
|
async act(task, scope) {
|
|
3682
4023
|
const ownerReader = opts.spawnResourceReader ?? (opts.spawnResourceRoot === void 0 ? scopeRetainedOwnerResourceReader(scope) : void 0);
|
|
4024
|
+
let probeableByName;
|
|
3683
4025
|
const coord = createCoordinationTools({
|
|
3684
4026
|
scope,
|
|
3685
4027
|
blobs: opts.blobs,
|
|
@@ -3697,6 +4039,7 @@ function driverAgent(opts) {
|
|
|
3697
4039
|
...opts.preflightSpawn ? { preflightSpawn: opts.preflightSpawn } : {},
|
|
3698
4040
|
...opts.resolveSpawnProfile ? { resolveSpawnProfile: opts.resolveSpawnProfile } : {},
|
|
3699
4041
|
...opts.composeSpawnProfile ? { composeSpawnProfile: opts.composeSpawnProfile } : {},
|
|
4042
|
+
...opts.profiles ? { profiles: opts.profiles } : {},
|
|
3700
4043
|
...opts.spawnResourceRoot ? { spawnResourceRoot: opts.spawnResourceRoot } : {},
|
|
3701
4044
|
...ownerReader ? { spawnResourceReader: ownerReader } : {},
|
|
3702
4045
|
...opts.escalateQuestion ? { escalateQuestion: opts.escalateQuestion } : {},
|
|
@@ -3705,7 +4048,8 @@ function driverAgent(opts) {
|
|
|
3705
4048
|
...opts.priorCoordination?.questions.length ? { priorQuestions: opts.priorCoordination.questions } : {},
|
|
3706
4049
|
...opts.priorCoordination?.escalations?.length ? { priorEscalations: opts.priorCoordination.escalations } : {},
|
|
3707
4050
|
...opts.priorCoordination?.records.length ? { priorJournal: opts.priorCoordination.records } : {},
|
|
3708
|
-
...opts.priorCoordination?.analystDefinitions?.length ? { priorAnalystDefinitions: opts.priorCoordination.analystDefinitions } : {}
|
|
4051
|
+
...opts.priorCoordination?.analystDefinitions?.length ? { priorAnalystDefinitions: opts.priorCoordination.analystDefinitions } : {},
|
|
4052
|
+
resolveProbeTool: (name) => probeableByName?.get(name)
|
|
3709
4053
|
});
|
|
3710
4054
|
await coord.ready();
|
|
3711
4055
|
const availableTools = [...coord.tools, ...opts.nodeTools ?? []];
|
|
@@ -3725,6 +4069,7 @@ function driverAgent(opts) {
|
|
|
3725
4069
|
};
|
|
3726
4070
|
});
|
|
3727
4071
|
const modelTools = selectedTools.flatMap((selected) => selected.kind === "descriptor" ? [selected.descriptor] : []);
|
|
4072
|
+
probeableByName = new Map(modelTools.map((tool) => [tool.name, tool]));
|
|
3728
4073
|
const selectedExtraNames = new Set(selectedTools.flatMap((selected) => selected.kind === "extra" ? [selected.extra.name] : []));
|
|
3729
4074
|
opts.onCoordinationTools?.(modelTools);
|
|
3730
4075
|
const acknowledger = opts.controlDir === void 0 ? void 0 : createCancelAcknowledger({
|
|
@@ -3905,7 +4250,7 @@ function driverAgent(opts) {
|
|
|
3905
4250
|
});
|
|
3906
4251
|
},
|
|
3907
4252
|
stopBefore: () => {
|
|
3908
|
-
if (coord.isStopped() || scope.signal.aborted || poolStarved(scope, opts.perWorker) || deadlinePassed(scope, now)) return true;
|
|
4253
|
+
if (coord.isStopped() || scope.signal.aborted || poolStarved(scope, opts.perWorker, opts.preserveOwnerTurns) || deadlinePassed(scope, now)) return true;
|
|
3909
4254
|
if (!opts.stopRule || !tracker) return false;
|
|
3910
4255
|
const decision = progressStop(tracker, opts.stopRule, coord, scope, now, opts.stallAfterMs);
|
|
3911
4256
|
if (!decision.stop) return false;
|
|
@@ -4036,4 +4381,4 @@ function safeJson(v) {
|
|
|
4036
4381
|
//#endregion
|
|
4037
4382
|
export { downMessageRefusalReasons as A, ANALYST_DEFINITION_BOUNDS as C, coordinationVerbNames as D, canonicalFindingEvent as E, defaultToolDetectors as F, watchTrace as I, parseAuthoredAnalystDefinition as M, questionEscalationTargets as N, createCoordinationTools as O, createEventBus as P, watchRunCancellation as S, analystToolGroupNames as T, renderAnytimeTable as _, allOf as a, FileCoordinationLog as b, createProgressTracker as c, progressStop as d, sampleFromSettled as f, plateauLength as g, bestSoFar as h, finalizeBestDelivered as i, normalizeAnalyzeOnSettle as j, createCoordinationToolsForManager as k, noProgressFor as l, areaUnderCurve as m, createSteerAcknowledger as n, allWorkersStalled as o, anytimeReport as p, driverAgent as r, anyOf as s, createCancelAcknowledger as t, plateau as u, createFileRunContext as v, DEFAULT_AWAIT_EVENT_TIMEOUT_MS as w, applyRunCancellation as x, createInMemoryRunContext as y };
|
|
4038
4383
|
|
|
4039
|
-
//# sourceMappingURL=coordination-driver-
|
|
4384
|
+
//# sourceMappingURL=coordination-driver-COGC8FK2.js.map
|