omp-fabric 1.13.1 → 1.14.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/CHANGELOG.md +20 -0
- package/dist/chunks/{chunk-ANAXFBUE.js → chunk-GIBZGL4G.js} +3 -1
- package/dist/chunks/chunk-GIBZGL4G.js.map +7 -0
- package/dist/chunks/{chunk-IIX4W4N4.js → chunk-PV453JOK.js} +2 -2
- package/dist/chunks/{chunk-U5QWDSIL.js → chunk-XQCAIIEM.js} +3 -3
- package/dist/compaction/lcm-maintenance.d.ts +19 -2
- package/dist/compaction/lcm-maintenance.d.ts.map +1 -1
- package/dist/compaction/lcm-runtime.d.ts +1 -0
- package/dist/compaction/lcm-runtime.d.ts.map +1 -1
- package/dist/compaction/lcm-runtime.js +114 -33
- package/dist/compaction/lcm-runtime.js.map +2 -2
- package/dist/config.d.ts +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/fabric-runtime-state.js +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +2 -2
- package/dist/residency/host.js +3 -3
- package/dist/residency/omp-entry.js +3 -3
- package/dist/ui/settings.d.ts.map +1 -1
- package/dist/ui/settings.js +10 -1
- package/dist/ui/settings.js.map +2 -2
- package/docs/compaction.md +3 -2
- package/docs/configuration.md +1 -1
- package/package.json +1 -1
- package/dist/chunks/chunk-ANAXFBUE.js.map +0 -7
- /package/dist/chunks/{chunk-IIX4W4N4.js.map → chunk-PV453JOK.js.map} +0 -0
- /package/dist/chunks/{chunk-U5QWDSIL.js.map → chunk-XQCAIIEM.js.map} +0 -0
|
@@ -867,6 +867,20 @@ function migrateSessions(options) {
|
|
|
867
867
|
import crypto3 from "node:crypto";
|
|
868
868
|
var DEFAULT_LCM_BUDGET = { calls: Number.POSITIVE_INFINITY, inputTokens: Number.POSITIVE_INFINITY, outputTokens: Number.POSITIVE_INFINITY, cost: Number.POSITIVE_INFINITY, wallMs: Number.POSITIVE_INFINITY, sessionCalls: Number.POSITIVE_INFINITY };
|
|
869
869
|
var DEFAULT_LEAF_ENTRIES = 32;
|
|
870
|
+
var DEFAULT_MAINTENANCE_CONCURRENCY = 3;
|
|
871
|
+
var LEASE_MS = 3e4;
|
|
872
|
+
var LEASE_SWEEP_GRACE_MS = 6e4;
|
|
873
|
+
var LcmRejection = class extends Error {
|
|
874
|
+
reason;
|
|
875
|
+
constructor(reason) {
|
|
876
|
+
super(reason);
|
|
877
|
+
this.name = "LcmRejection";
|
|
878
|
+
this.reason = reason;
|
|
879
|
+
}
|
|
880
|
+
};
|
|
881
|
+
var isLcmRejection = (error) => error instanceof LcmRejection;
|
|
882
|
+
var isLcmCapacityRejection = (error) => isLcmRejection(error) && (error.reason === "project lease held" || error.reason === "budget exhausted");
|
|
883
|
+
var LEGACY_CONTENTION_RETIREMENTS = /* @__PURE__ */ new Set(["job lease held", "project lease held", "LcmRejection: job lease held", "LcmRejection: project lease held"]);
|
|
870
884
|
var hash3 = (v) => hashLcmPayload(v);
|
|
871
885
|
var parse = (v) => JSON.parse(String(v));
|
|
872
886
|
var rawHash = (e) => e.payloadHash;
|
|
@@ -881,9 +895,14 @@ AND CAST(json_extract(j.payload,'$.nextRetryAt') AS INTEGER)<=?
|
|
|
881
895
|
AND (? IS NULL OR json_extract(n.payload,'$.sessionId')=?)
|
|
882
896
|
ORDER BY CAST(json_extract(j.payload,'$.priority') AS INTEGER) DESC, j.created_at, j.job_id
|
|
883
897
|
LIMIT ?`;
|
|
898
|
+
var LIVE_LEASES_SQL = `SELECT coalesce(json_extract(n.payload,'$.sessionId'),'') sessionId
|
|
899
|
+
FROM maintenance_jobs j
|
|
900
|
+
LEFT JOIN summary_nodes n ON n.node_id=json_extract(j.payload,'$.nodeId') AND n.project_key=j.project_key
|
|
901
|
+
WHERE j.project_key=? AND j.status='running' AND j.job_id<>? AND CAST(coalesce(json_extract(j.payload,'$.leaseUntil'),0) AS INTEGER)>?`;
|
|
884
902
|
var LcmMaintenance = class {
|
|
885
903
|
constructor(ledger, options = {}) {
|
|
886
904
|
this.ledger = ledger;
|
|
905
|
+
this.maxConcurrentJobs = options.maxConcurrentJobs ?? DEFAULT_MAINTENANCE_CONCURRENCY;
|
|
887
906
|
this.projectKey = ledger.project.key;
|
|
888
907
|
this.now = options.now ?? Date.now;
|
|
889
908
|
this.ownerId = options.ownerId ?? crypto3.randomUUID();
|
|
@@ -905,9 +924,27 @@ var LcmMaintenance = class {
|
|
|
905
924
|
maxOutputChars;
|
|
906
925
|
budget;
|
|
907
926
|
modelTimeoutMs;
|
|
927
|
+
maxConcurrentJobs;
|
|
908
928
|
budgetPolicy() {
|
|
909
929
|
return { ...this.budget };
|
|
910
930
|
}
|
|
931
|
+
get concurrencyLimit() {
|
|
932
|
+
const raw = typeof this.maxConcurrentJobs === "function" ? this.maxConcurrentJobs() : this.maxConcurrentJobs;
|
|
933
|
+
return Number.isFinite(raw) ? Math.max(1, Math.floor(raw)) : DEFAULT_MAINTENANCE_CONCURRENCY;
|
|
934
|
+
}
|
|
935
|
+
liveLeases(db, at, excludeJobId) {
|
|
936
|
+
return db.prepare(LIVE_LEASES_SQL).all(this.projectKey, excludeJobId ?? "", at - LEASE_SWEEP_GRACE_MS);
|
|
937
|
+
}
|
|
938
|
+
admits(db, at, sessionId, leases) {
|
|
939
|
+
const day = this.day(at);
|
|
940
|
+
const project = this.usage(db, day);
|
|
941
|
+
const session = this.usage(db, day, sessionId);
|
|
942
|
+
let sessionReserved = 0;
|
|
943
|
+
for (const lease of leases) if (lease.sessionId === sessionId) sessionReserved += 1;
|
|
944
|
+
const reserved = leases.length + 1;
|
|
945
|
+
const fits = (used, cap) => used < cap && used + (project.calls > 0 ? used / project.calls * reserved : 0) <= cap;
|
|
946
|
+
return project.calls + leases.length < this.budget.calls && fits(project.inputTokens, this.budget.inputTokens) && fits(project.outputTokens, this.budget.outputTokens) && fits(project.cost, this.budget.cost) && fits(project.wallMs, this.budget.wallMs) && session.calls + sessionReserved < this.budget.sessionCalls;
|
|
947
|
+
}
|
|
911
948
|
recordRevision(db, node) {
|
|
912
949
|
if (!node.text) return;
|
|
913
950
|
const row = db.prepare("SELECT coalesce(max(revision),0) n FROM summary_node_revisions WHERE node_id=?").get(node.nodeId);
|
|
@@ -990,7 +1027,7 @@ var LcmMaintenance = class {
|
|
|
990
1027
|
claimableJobs(sessionId, limit = 64) {
|
|
991
1028
|
const t = this.now();
|
|
992
1029
|
const scope = sessionId ?? null;
|
|
993
|
-
return this.ledger.readOnly((db) => db.prepare(CLAIMABLE_JOBS_SQL).all(this.projectKey, t, t, t, scope, scope, limit).map((r) => {
|
|
1030
|
+
return this.ledger.readOnly((db) => db.prepare(CLAIMABLE_JOBS_SQL).all(this.projectKey, t - LEASE_SWEEP_GRACE_MS, t, t, scope, scope, limit).map((r) => {
|
|
994
1031
|
const job = parse(r.payload);
|
|
995
1032
|
if (job.projectKey !== this.projectKey) throw new Error("job project does not match ledger project");
|
|
996
1033
|
return job;
|
|
@@ -1001,25 +1038,43 @@ var LcmMaintenance = class {
|
|
|
1001
1038
|
}
|
|
1002
1039
|
isClaimable(job) {
|
|
1003
1040
|
const t = this.now();
|
|
1004
|
-
return (job.state === "pending" || job.state === "running" && (job.leaseUntil ?? 0) <= t) && job.eligibleAt <= t && job.nextRetryAt <= t;
|
|
1041
|
+
return (job.state === "pending" || job.state === "running" && (job.leaseUntil ?? 0) + LEASE_SWEEP_GRACE_MS <= t) && job.eligibleAt <= t && job.nextRetryAt <= t;
|
|
1005
1042
|
}
|
|
1006
|
-
sweepExpiredLeases(
|
|
1043
|
+
sweepExpiredLeases() {
|
|
1007
1044
|
return this.ledger.transaction((db) => {
|
|
1008
|
-
const t = this.now();
|
|
1045
|
+
const t = this.now() - LEASE_SWEEP_GRACE_MS;
|
|
1009
1046
|
const rows = db.prepare("SELECT payload FROM maintenance_jobs WHERE project_key=? AND status=?").all(this.projectKey, "running");
|
|
1010
1047
|
const swept = [];
|
|
1011
1048
|
for (const row of rows) {
|
|
1012
1049
|
const old = parse(row.payload);
|
|
1013
1050
|
if (old.projectKey !== this.projectKey) throw new Error("job project does not match ledger project");
|
|
1014
|
-
if ((old.leaseUntil ?? 0)
|
|
1051
|
+
if ((old.leaseUntil ?? 0) > t) continue;
|
|
1052
|
+
const now = this.now();
|
|
1015
1053
|
const { ownerId: _ownerId, leaseToken: _leaseToken, leaseUntil: _leaseUntil, ...base } = old;
|
|
1016
|
-
const job = { ...base, state: "pending", error: "lease expired", eligibleAt:
|
|
1054
|
+
const job = { ...base, state: "pending", error: "lease expired", eligibleAt: now, nextRetryAt: now, updatedAt: now };
|
|
1017
1055
|
db.prepare("UPDATE maintenance_jobs SET status=?,payload=?,updated_at=? WHERE job_id=? AND project_key=?").run(job.state, JSON.stringify(job), job.updatedAt, job.jobId, this.projectKey);
|
|
1018
1056
|
swept.push(job);
|
|
1019
1057
|
}
|
|
1020
1058
|
return swept;
|
|
1021
1059
|
});
|
|
1022
1060
|
}
|
|
1061
|
+
recoverLegacyContentionRetirements() {
|
|
1062
|
+
return this.ledger.transaction((db) => {
|
|
1063
|
+
const rows = db.prepare("SELECT payload FROM maintenance_jobs WHERE project_key=? AND status=?").all(this.projectKey, "failed");
|
|
1064
|
+
const recovered = [];
|
|
1065
|
+
for (const row of rows) {
|
|
1066
|
+
const old = parse(row.payload);
|
|
1067
|
+
if (old.projectKey !== this.projectKey) throw new Error("job project does not match ledger project");
|
|
1068
|
+
if (old.legacyRecovery || !LEGACY_CONTENTION_RETIREMENTS.has(old.error ?? "")) continue;
|
|
1069
|
+
const t = this.now();
|
|
1070
|
+
const { error: _error, ...base } = old;
|
|
1071
|
+
const job = { ...base, state: "pending", attempts: 0, legacyRecovery: true, eligibleAt: t, nextRetryAt: t, updatedAt: t };
|
|
1072
|
+
db.prepare("UPDATE maintenance_jobs SET status=?,payload=?,updated_at=? WHERE job_id=? AND project_key=?").run(job.state, JSON.stringify(job), job.updatedAt, job.jobId, this.projectKey);
|
|
1073
|
+
recovered.push(job);
|
|
1074
|
+
}
|
|
1075
|
+
return recovered;
|
|
1076
|
+
});
|
|
1077
|
+
}
|
|
1023
1078
|
recordFailure(job, error) {
|
|
1024
1079
|
return this.ledger.transaction((db) => {
|
|
1025
1080
|
const row = db.prepare("SELECT payload FROM maintenance_jobs WHERE job_id=? AND project_key=?").get(job.jobId, this.projectKey);
|
|
@@ -1132,18 +1187,15 @@ var LcmMaintenance = class {
|
|
|
1132
1187
|
const old = parse(row.payload);
|
|
1133
1188
|
if (old.projectKey !== this.projectKey) throw new Error("job project does not match ledger project");
|
|
1134
1189
|
const t = this.now();
|
|
1135
|
-
const expired = old.state === "running" && (old.leaseUntil ?? 0) <= t;
|
|
1136
|
-
if (old.state === "running" && !expired) throw new
|
|
1137
|
-
if (old.state !== "pending" && !expired || old.eligibleAt > t || old.nextRetryAt > t) throw new
|
|
1138
|
-
const
|
|
1139
|
-
if (
|
|
1190
|
+
const expired = old.state === "running" && (old.leaseUntil ?? 0) + LEASE_SWEEP_GRACE_MS <= t;
|
|
1191
|
+
if (old.state === "running" && !expired) throw new LcmRejection("job lease held");
|
|
1192
|
+
if (old.state !== "pending" && !expired || old.eligibleAt > t || old.nextRetryAt > t) throw new LcmRejection("job not eligible");
|
|
1193
|
+
const leases = this.liveLeases(db, t, old.jobId);
|
|
1194
|
+
if (leases.length >= this.concurrencyLimit) throw new LcmRejection("project lease held");
|
|
1140
1195
|
const nodeRow = db.prepare("SELECT payload FROM summary_nodes WHERE node_id=? AND project_key=?").get(old.nodeId, this.projectKey);
|
|
1141
1196
|
const sessionId = nodeRow?.payload ? parse(nodeRow.payload).sessionId : "";
|
|
1142
|
-
|
|
1143
|
-
const
|
|
1144
|
-
const sessionUsage = this.usage(db, day, sessionId);
|
|
1145
|
-
if (projectUsage.calls >= this.budget.calls || projectUsage.inputTokens >= this.budget.inputTokens || projectUsage.outputTokens >= this.budget.outputTokens || projectUsage.cost >= this.budget.cost || projectUsage.wallMs >= this.budget.wallMs || sessionUsage.calls >= this.budget.sessionCalls) throw new Error("budget exhausted");
|
|
1146
|
-
const out = { ...old, state: "running", ownerId, leaseToken: token(), leaseUntil: t + 3e4, updatedAt: t };
|
|
1197
|
+
if (!this.admits(db, t, sessionId, leases)) throw new LcmRejection("budget exhausted");
|
|
1198
|
+
const out = { ...old, state: "running", ownerId, leaseToken: token(), leaseUntil: t + LEASE_MS, updatedAt: t };
|
|
1147
1199
|
db.prepare("UPDATE maintenance_jobs SET status=?,payload=?,updated_at=? WHERE job_id=? AND project_key=?").run(out.state, JSON.stringify(out), t, jobId, this.projectKey);
|
|
1148
1200
|
return out;
|
|
1149
1201
|
});
|
|
@@ -1156,15 +1208,15 @@ var LcmMaintenance = class {
|
|
|
1156
1208
|
if (old.projectKey !== this.projectKey) throw new Error("job project does not match ledger project");
|
|
1157
1209
|
const t = this.now();
|
|
1158
1210
|
const expired = old.state === "running" && (old.leaseUntil ?? 0) <= t;
|
|
1159
|
-
if (old.state === "running" && !expired) throw new
|
|
1211
|
+
if (old.state === "running" && !expired) throw new LcmRejection("job lease held");
|
|
1160
1212
|
if (old.state === "completed") throw new Error("job already completed");
|
|
1161
|
-
const out = { ...old, state: "running", ownerId, leaseToken: token(), leaseUntil: t +
|
|
1213
|
+
const out = { ...old, state: "running", ownerId, leaseToken: token(), leaseUntil: t + LEASE_MS, updatedAt: t };
|
|
1162
1214
|
db.prepare("UPDATE maintenance_jobs SET status=?,payload=?,updated_at=? WHERE job_id=? AND project_key=?").run(out.state, JSON.stringify(out), t, jobId, this.projectKey);
|
|
1163
1215
|
return out;
|
|
1164
1216
|
});
|
|
1165
1217
|
}
|
|
1166
1218
|
renew(job) {
|
|
1167
|
-
return this.fenced(job, (old) => ({ ...old, leaseUntil: this.now() +
|
|
1219
|
+
return this.fenced(job, (old) => ({ ...old, leaseUntil: this.now() + LEASE_MS, updatedAt: this.now() }));
|
|
1168
1220
|
}
|
|
1169
1221
|
validateText(text) {
|
|
1170
1222
|
if (typeof text !== "string" || text.length === 0) throw new Error("invalid summary text");
|
|
@@ -1178,12 +1230,10 @@ var LcmMaintenance = class {
|
|
|
1178
1230
|
if (!Number.isSafeInteger(inputBytes) || inputBytes < 0) throw new Error("invalid input bound");
|
|
1179
1231
|
if (utf8Bytes(text) >= inputBytes) throw new Error("summary does not shrink its input");
|
|
1180
1232
|
}
|
|
1181
|
-
withinBudget(sessionId) {
|
|
1233
|
+
withinBudget(sessionId, excludeJobId) {
|
|
1182
1234
|
return this.ledger.readOnly((db) => {
|
|
1183
|
-
const
|
|
1184
|
-
|
|
1185
|
-
const session = this.usage(db, day, sessionId);
|
|
1186
|
-
return project.calls < this.budget.calls && project.inputTokens < this.budget.inputTokens && project.outputTokens < this.budget.outputTokens && project.cost < this.budget.cost && project.wallMs < this.budget.wallMs && session.calls < this.budget.sessionCalls;
|
|
1235
|
+
const at = this.now();
|
|
1236
|
+
return this.admits(db, at, sessionId, this.liveLeases(db, at, excludeJobId));
|
|
1187
1237
|
});
|
|
1188
1238
|
}
|
|
1189
1239
|
accountRejected(sessionId, result) {
|
|
@@ -1277,7 +1327,7 @@ var LcmMaintenance = class {
|
|
|
1277
1327
|
let lastError = new Error("LCM summarization did not converge");
|
|
1278
1328
|
for (const [index, level] of LCM_MODEL_LEVELS.entries()) {
|
|
1279
1329
|
if (controller.signal.aborted) break;
|
|
1280
|
-
if (index > 0 && !this.withinBudget(sessionId)) break;
|
|
1330
|
+
if (index > 0 && !this.withinBudget(sessionId, job.jobId)) break;
|
|
1281
1331
|
const target = Math.max(1, Math.min(Math.floor(this.maxOutputChars * level.share), inputBytes - 1));
|
|
1282
1332
|
let result;
|
|
1283
1333
|
try {
|
|
@@ -1302,7 +1352,8 @@ var LcmMaintenance = class {
|
|
|
1302
1352
|
const fallback = emergencyReduce(input, this.maxOutputChars, sources);
|
|
1303
1353
|
try {
|
|
1304
1354
|
return this.completeEmergency(claimed, fallback);
|
|
1305
|
-
} catch {
|
|
1355
|
+
} catch (fenced) {
|
|
1356
|
+
if (isLcmRejection(fenced) && fenced.reason === "lease fenced") throw fenced;
|
|
1306
1357
|
try {
|
|
1307
1358
|
this.fail(claimed, String(error));
|
|
1308
1359
|
} catch {
|
|
@@ -1335,7 +1386,7 @@ var LcmMaintenance = class {
|
|
|
1335
1386
|
return job;
|
|
1336
1387
|
}
|
|
1337
1388
|
assertLease(current, expected) {
|
|
1338
|
-
if (current.ownerId !== expected.ownerId || current.leaseToken !== expected.leaseToken || current.state !== "running" || (current.leaseUntil ?? 0) < this.now()) throw new
|
|
1389
|
+
if (current.ownerId !== expected.ownerId || current.leaseToken !== expected.leaseToken || current.state !== "running" || (current.leaseUntil ?? 0) < this.now()) throw new LcmRejection("lease fenced");
|
|
1339
1390
|
}
|
|
1340
1391
|
fenced(job, update) {
|
|
1341
1392
|
return this.ledger.transaction((db) => {
|
|
@@ -1349,7 +1400,6 @@ var LcmMaintenance = class {
|
|
|
1349
1400
|
};
|
|
1350
1401
|
|
|
1351
1402
|
// src/compaction/lcm-runtime.ts
|
|
1352
|
-
var LEASE_SWEEP_GRACE_MS = 6e4;
|
|
1353
1403
|
var MAX_RECONCILE_RECOVERIES = 3;
|
|
1354
1404
|
var CLAIMABLE_JOB_LIMIT = 256;
|
|
1355
1405
|
var FAILED_JOB_WINDOW_MS = 24 * 60 * 60 * 1e3;
|
|
@@ -1445,6 +1495,7 @@ var LcmRuntime = class {
|
|
|
1445
1495
|
...initial.lcmMaxInputChars === void 0 ? {} : { maxInputChars: initial.lcmMaxInputChars },
|
|
1446
1496
|
...initial.lcmMaxOutputChars === void 0 ? {} : { maxOutputChars: initial.lcmMaxOutputChars },
|
|
1447
1497
|
...initial.modelTimeoutSeconds === void 0 ? {} : { modelTimeoutMs: initial.modelTimeoutSeconds * 1e3 },
|
|
1498
|
+
maxConcurrentJobs: () => this.resolveOptions().maintenanceConcurrency ?? DEFAULT_MAINTENANCE_CONCURRENCY,
|
|
1448
1499
|
budget: {
|
|
1449
1500
|
...initial.maxDailyModelCalls ? { calls: initial.maxDailyModelCalls } : {},
|
|
1450
1501
|
...initial.maxSessionModelCalls ? { sessionCalls: initial.maxSessionModelCalls } : {},
|
|
@@ -1587,7 +1638,7 @@ var LcmRuntime = class {
|
|
|
1587
1638
|
reclaimExpiredLeases() {
|
|
1588
1639
|
if (this.closed) return 0;
|
|
1589
1640
|
try {
|
|
1590
|
-
return this.maintenance.sweepExpiredLeases(
|
|
1641
|
+
return this.maintenance.sweepExpiredLeases().length + this.maintenance.recoverLegacyContentionRetirements().length;
|
|
1591
1642
|
} catch (error) {
|
|
1592
1643
|
this.degradedError = error;
|
|
1593
1644
|
return 0;
|
|
@@ -1680,24 +1731,49 @@ var LcmRuntime = class {
|
|
|
1680
1731
|
try {
|
|
1681
1732
|
const input = inputFor(node);
|
|
1682
1733
|
await this.maintenance.run(job, model, input, this.signal);
|
|
1734
|
+
return "done";
|
|
1683
1735
|
} catch (error) {
|
|
1736
|
+
if (isLcmCapacityRejection(error)) return "capacity";
|
|
1737
|
+
if (isLcmRejection(error)) return "rejected";
|
|
1684
1738
|
this.degradedError = error;
|
|
1685
1739
|
try {
|
|
1686
1740
|
this.maintenance.recordFailure(job, error);
|
|
1687
1741
|
} catch {
|
|
1688
1742
|
}
|
|
1743
|
+
return "done";
|
|
1689
1744
|
}
|
|
1690
1745
|
};
|
|
1746
|
+
const dispatch = async (items) => {
|
|
1747
|
+
let next = 0;
|
|
1748
|
+
const worker = async (slot) => {
|
|
1749
|
+
while (!this.closed && Date.now() < runDeadline && slot < this.maintenance.concurrencyLimit) {
|
|
1750
|
+
const item = items[next];
|
|
1751
|
+
if (!item) return;
|
|
1752
|
+
next += 1;
|
|
1753
|
+
if (await runJob(item.job, item.node) === "capacity") return;
|
|
1754
|
+
}
|
|
1755
|
+
};
|
|
1756
|
+
await Promise.all(Array.from({ length: Math.min(this.maintenance.concurrencyLimit, items.length) }, (_unused, slot) => worker(slot)));
|
|
1757
|
+
};
|
|
1691
1758
|
this.reclaimExpiredLeases();
|
|
1692
1759
|
for (let pass = 0; pass < passes && !this.closed && Date.now() < runDeadline; pass += 1) {
|
|
1693
1760
|
const leafCandidate = this.maintenance.createLeaf(this.maintenance.selectLeaf(raw, this.context.sessionManager.getLeafId()));
|
|
1694
1761
|
const leaf = leafCandidate ? this.maintenance.getNode(leafCandidate.nodeId) : void 0;
|
|
1762
|
+
const batch = [];
|
|
1763
|
+
const queued = /* @__PURE__ */ new Set();
|
|
1695
1764
|
if (leaf?.state === "pending") {
|
|
1696
1765
|
const job = this.maintenance.jobForNode(leaf.nodeId);
|
|
1697
|
-
if (job && this.maintenance.isClaimable(job))
|
|
1766
|
+
if (job && this.maintenance.isClaimable(job)) {
|
|
1767
|
+
batch.push({ job, node: leaf });
|
|
1768
|
+
queued.add(job.jobId);
|
|
1769
|
+
}
|
|
1698
1770
|
}
|
|
1699
1771
|
const pending = this.actionableJobs(sessionId, this.context.sessionManager.getLeafId(), passes);
|
|
1700
|
-
for (const item of pending)
|
|
1772
|
+
for (const item of pending) if (!queued.has(item.job.jobId)) {
|
|
1773
|
+
queued.add(item.job.jobId);
|
|
1774
|
+
batch.push(item);
|
|
1775
|
+
}
|
|
1776
|
+
await dispatch(batch);
|
|
1701
1777
|
const children = this.maintenance.selectCondensation(sessionId, this.activeSources, this.context.sessionManager.getLeafId());
|
|
1702
1778
|
if (children.length >= fanIn) {
|
|
1703
1779
|
const node = this.maintenance.createCondensed(children);
|
|
@@ -1766,8 +1842,13 @@ var LcmRuntime = class {
|
|
|
1766
1842
|
}
|
|
1767
1843
|
const job = this.maintenance.jobForNode(leaf.nodeId);
|
|
1768
1844
|
if (!job) throw new Error("LCM emergency fallback job was not created");
|
|
1769
|
-
|
|
1770
|
-
|
|
1845
|
+
try {
|
|
1846
|
+
const completed = this.maintenance.completeEmergency(this.maintenance.claimEmergency(job.jobId), fallback);
|
|
1847
|
+
return { summary: completed.text ?? fallback, firstKeptEntryId: input.firstKeptEntryId, tokensBefore: input.tokensBefore, source: "emergency", branch: input.branch };
|
|
1848
|
+
} catch (error) {
|
|
1849
|
+
if (!isLcmRejection(error)) throw error;
|
|
1850
|
+
return { summary: fallback, firstKeptEntryId: input.firstKeptEntryId, tokensBefore: input.tokensBefore, source: "emergency", branch: input.branch };
|
|
1851
|
+
}
|
|
1771
1852
|
}
|
|
1772
1853
|
report() {
|
|
1773
1854
|
const day = new Date(Date.now()).toISOString().slice(0, 10);
|