commonswarm 0.1.53 → 0.1.54
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/cswarm.cjs +194 -26
- package/package.json +1 -1
package/cswarm.cjs
CHANGED
|
@@ -13519,7 +13519,8 @@ __export(cli_exports, {
|
|
|
13519
13519
|
replyRefusalHint: () => replyRefusalHint,
|
|
13520
13520
|
resolveDetachedClaudeExecutable: () => resolveDetachedClaudeExecutable,
|
|
13521
13521
|
resolveDetachedCodexExecutable: () => resolveDetachedCodexExecutable,
|
|
13522
|
-
resolveTurnBudgetOrDefer: () => resolveTurnBudgetOrDefer
|
|
13522
|
+
resolveTurnBudgetOrDefer: () => resolveTurnBudgetOrDefer,
|
|
13523
|
+
usage: () => usage
|
|
13523
13524
|
});
|
|
13524
13525
|
module.exports = __toCommonJS(cli_exports);
|
|
13525
13526
|
var import_node_crypto22 = require("node:crypto");
|
|
@@ -34518,6 +34519,25 @@ async function resolveBudgetAndPrompt(session, prompt, budget) {
|
|
|
34518
34519
|
const timeoutMs = typeof budget === "number" ? budget : await budget();
|
|
34519
34520
|
return await session.prompt(prompt, { timeoutMs });
|
|
34520
34521
|
}
|
|
34522
|
+
var LISTENER_DELIVERY_MAX_LEASE_MS = 9e5;
|
|
34523
|
+
var LISTENER_DELIVERY_HOLD_RELEASE_REASONS = [
|
|
34524
|
+
"hold_budget",
|
|
34525
|
+
"lease_budget"
|
|
34526
|
+
];
|
|
34527
|
+
var LISTENER_DELIVERY_HOLD_RELEASE_CLAUSES = {
|
|
34528
|
+
hold_budget: "it used the turn budget for one delivery",
|
|
34529
|
+
lease_budget: "what was left of its lease could not cover the next step"
|
|
34530
|
+
};
|
|
34531
|
+
var LISTENER_DELIVERY_HOLD_RELEASE_REMEDIES = {
|
|
34532
|
+
hold_budget: `a larger --turn-budget gives one delivery more of the seat. Past the ${LISTENER_DELIVERY_MAX_LEASE_MS / 6e4} minutes the service leases a delivery for it stops helping, because the turn then outlives its lease and the reply can no longer be acknowledged. The bound is read when the listener starts, so stop this listener and start it again to change it`,
|
|
34533
|
+
/* NOT a cap: nothing clamps the turn budget to the lease, and leaseSpent
|
|
34534
|
+
refuses to START a phase rather than interrupting one, so a 60m budget
|
|
34535
|
+
really does hold the worker for 60m. The sentence says raising past the
|
|
34536
|
+
lease stops helping, and why, which is what the code supports. An earlier
|
|
34537
|
+
version read "up to the 15 minutes the service leases it for", which a
|
|
34538
|
+
review arm read as a cap the code does not enforce. */
|
|
34539
|
+
lease_budget: "nothing needs raising: the row comes back under a new lease of full length, so the next attempt starts with the room this one ran out of. If it keeps being handed back, the service stops retrying it in the end, so look at the delivery rather than at the bound"
|
|
34540
|
+
};
|
|
34521
34541
|
|
|
34522
34542
|
// src/listener/engine.ts
|
|
34523
34543
|
var UUID_RE14 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
@@ -36739,11 +36759,11 @@ function pendingMainEntry(signal, principalId, provenance, now, options = {}) {
|
|
|
36739
36759
|
// src/listener/runtime.ts
|
|
36740
36760
|
var LISTENER_PAGE_LIMIT = 100;
|
|
36741
36761
|
var LISTENER_IDLE_POLL_MS = 2e3;
|
|
36742
|
-
var LISTENER_DELIVERY_MAX_LEASE_MS = 9e5;
|
|
36743
36762
|
var LISTENER_DELIVERY_SAFETY_MARGIN_MS = 3e4;
|
|
36744
36763
|
var LISTENER_ACK_ONLY_MINIMUM_MS = DELIVERY_REQUEST_TIMEOUT_MS + LISTENER_DELIVERY_SAFETY_MARGIN_MS;
|
|
36745
36764
|
var LISTENER_REPLY_ONLY_MINIMUM_MS = SIGNAL_REQUEST_TIMEOUT_MS + LISTENER_ACK_ONLY_MINIMUM_MS;
|
|
36746
36765
|
var LISTENER_PROMPT_START_MINIMUM_MS = SIGNAL_READ_TIMEOUT_MS + ACP_DEFAULT_REQUEST_TIMEOUT_MS + LISTENER_REPLY_ONLY_MINIMUM_MS;
|
|
36766
|
+
var LISTENER_DELIVERY_HOLD_BUDGET_MS = LISTENER_PROMPT_TIMEOUT_MS;
|
|
36747
36767
|
var LISTENER_DELIVERY_RETRY_INITIAL_MS = 500;
|
|
36748
36768
|
var LISTENER_DELIVERY_RETRY_MAX_MS = 3e4;
|
|
36749
36769
|
var LISTENER_HOST_PORTS_PROBE_MS = 6e4;
|
|
@@ -37016,6 +37036,7 @@ async function runListenerRuntime(options) {
|
|
|
37016
37036
|
const pollMs = options.pollMs ?? LISTENER_IDLE_POLL_MS;
|
|
37017
37037
|
const routeMode = options.routeMode ?? "worker";
|
|
37018
37038
|
const deferOverChars = options.deferOverChars ?? null;
|
|
37039
|
+
const deliveryHoldBudgetMs = options.deliveryHoldBudgetMs ?? LISTENER_DELIVERY_HOLD_BUDGET_MS;
|
|
37019
37040
|
const abort = options.signal;
|
|
37020
37041
|
const hasInstanceId = options.listenerInstanceId !== void 0;
|
|
37021
37042
|
const hasJournal = options.deliveryJournal !== void 0;
|
|
@@ -37037,6 +37058,12 @@ async function runListenerRuntime(options) {
|
|
|
37037
37058
|
new Error("an injected delivery client requires durable delivery configuration")
|
|
37038
37059
|
);
|
|
37039
37060
|
}
|
|
37061
|
+
if (!Number.isSafeInteger(deliveryHoldBudgetMs) || deliveryHoldBudgetMs <= 0) {
|
|
37062
|
+
return await closeBeforeStart(
|
|
37063
|
+
options.model,
|
|
37064
|
+
new Error("listener delivery hold budget must be a positive number of milliseconds")
|
|
37065
|
+
);
|
|
37066
|
+
}
|
|
37040
37067
|
try {
|
|
37041
37068
|
decideListenerRoute(routeMode, deferOverChars, 0);
|
|
37042
37069
|
if (routeMode !== "worker" && options.pendingMainQueue === void 0) {
|
|
@@ -37630,6 +37657,8 @@ async function runListenerRuntime(options) {
|
|
|
37630
37657
|
stop = { reason: "cancelled" };
|
|
37631
37658
|
break;
|
|
37632
37659
|
}
|
|
37660
|
+
const claimedAtMs = Date.parse(active.claimCreatedAt);
|
|
37661
|
+
const holdStartedAtMs = Number.isFinite(claimedAtMs) ? Math.min(claimedAtMs, now()) : now();
|
|
37633
37662
|
const signal = authoritativeSignal(claimed);
|
|
37634
37663
|
let terminal = null;
|
|
37635
37664
|
try {
|
|
@@ -37696,22 +37725,18 @@ async function runListenerRuntime(options) {
|
|
|
37696
37725
|
throw new Error("stored listener effect does not match the authoritative delivery");
|
|
37697
37726
|
}
|
|
37698
37727
|
const requiredBudget = effectPhaseBudget(before);
|
|
37699
|
-
|
|
37700
|
-
|
|
37701
|
-
|
|
37702
|
-
|
|
37703
|
-
|
|
37704
|
-
|
|
37705
|
-
|
|
37706
|
-
|
|
37707
|
-
|
|
37708
|
-
|
|
37709
|
-
|
|
37710
|
-
}
|
|
37711
|
-
if (now() >= leasedUntilMs + LISTENER_DELIVERY_SAFETY_MARGIN_MS) {
|
|
37712
|
-
await journal.clearActive(eventTime(now));
|
|
37713
|
-
after = null;
|
|
37714
|
-
}
|
|
37728
|
+
const holdSpent = processAttempt > 0 && now() - holdStartedAtMs >= deliveryHoldBudgetMs;
|
|
37729
|
+
const leaseSpent = leasedUntilMs <= now() + requiredBudget;
|
|
37730
|
+
if (holdSpent || leaseSpent) {
|
|
37731
|
+
await journal.clearActive(eventTime(now));
|
|
37732
|
+
after = null;
|
|
37733
|
+
options.onEvent?.({
|
|
37734
|
+
type: "delivery_hold_released",
|
|
37735
|
+
signalId: signal.id,
|
|
37736
|
+
reason: holdSpent ? "hold_budget" : "lease_budget",
|
|
37737
|
+
heldMs: Math.max(0, now() - holdStartedAtMs),
|
|
37738
|
+
ts: eventTime(now)
|
|
37739
|
+
});
|
|
37715
37740
|
break;
|
|
37716
37741
|
}
|
|
37717
37742
|
const processed = await engine.process(signal);
|
|
@@ -38210,6 +38235,10 @@ var STATUS_ALLOWED_KEYS = /* @__PURE__ */ new Set([
|
|
|
38210
38235
|
"lastAckOutcome",
|
|
38211
38236
|
"consecutiveAckFailureCount",
|
|
38212
38237
|
"lastAckSignalId",
|
|
38238
|
+
"currentDeliverySignalId",
|
|
38239
|
+
"currentDeliverySince",
|
|
38240
|
+
"heldBackDeliveries",
|
|
38241
|
+
"pendingDeliveryCountAt",
|
|
38213
38242
|
"routeMode",
|
|
38214
38243
|
"deferOverChars",
|
|
38215
38244
|
"pendingForMainCount",
|
|
@@ -38254,6 +38283,30 @@ var STATUS_DELIVERY_KEYS = [
|
|
|
38254
38283
|
"consecutiveAckFailureCount"
|
|
38255
38284
|
];
|
|
38256
38285
|
var deliveryOutcomes = DELIVERY_ACK_OUTCOMES;
|
|
38286
|
+
var LISTENER_HELD_BACK_MAX = 16;
|
|
38287
|
+
function parseHeldBackDeliveries(value) {
|
|
38288
|
+
if (!Array.isArray(value) || value.length > LISTENER_HELD_BACK_MAX) return null;
|
|
38289
|
+
const parsed = [];
|
|
38290
|
+
for (const item of value) {
|
|
38291
|
+
if (!item || typeof item !== "object" || Array.isArray(item)) return null;
|
|
38292
|
+
const entry = item;
|
|
38293
|
+
for (const key2 of Object.keys(entry)) {
|
|
38294
|
+
if (key2 !== "signalId" && key2 !== "at" && key2 !== "reason") return null;
|
|
38295
|
+
}
|
|
38296
|
+
if (typeof entry.signalId !== "string" || !UUID_RE18.test(entry.signalId) || typeof entry.at !== "string" || !Number.isFinite(Date.parse(entry.at)) || typeof entry.reason !== "string" || !LISTENER_DELIVERY_HOLD_RELEASE_REASONS.includes(
|
|
38297
|
+
entry.reason
|
|
38298
|
+
)) {
|
|
38299
|
+
return null;
|
|
38300
|
+
}
|
|
38301
|
+
if (parsed.some((seen) => seen.signalId === entry.signalId)) return null;
|
|
38302
|
+
parsed.push({
|
|
38303
|
+
signalId: entry.signalId,
|
|
38304
|
+
at: entry.at,
|
|
38305
|
+
reason: entry.reason
|
|
38306
|
+
});
|
|
38307
|
+
}
|
|
38308
|
+
return parsed;
|
|
38309
|
+
}
|
|
38257
38310
|
function parseStatus(raw, rejectUnknownKeys = false) {
|
|
38258
38311
|
let value;
|
|
38259
38312
|
try {
|
|
@@ -38277,7 +38330,8 @@ function parseStatus(raw, rejectUnknownKeys = false) {
|
|
|
38277
38330
|
const nullableCount = (candidate) => candidate === null || typeof candidate === "number" && Number.isSafeInteger(candidate) && candidate >= 0;
|
|
38278
38331
|
const nullableTimestamp3 = (candidate) => candidate === null || typeof candidate === "string" && Number.isFinite(Date.parse(candidate));
|
|
38279
38332
|
const readHealth = row.readHealth === void 0 ? void 0 : parseListenerReadHealth(row.readHealth, rejectUnknownKeys);
|
|
38280
|
-
|
|
38333
|
+
const heldBackDeliveries = row.heldBackDeliveries === void 0 ? void 0 : parseHeldBackDeliveries(row.heldBackDeliveries);
|
|
38334
|
+
if (row.version !== 1 || typeof row.instanceId !== "string" || !UUID_RE18.test(row.instanceId) || row.provider !== "grok" && row.provider !== "opencode" && row.provider !== "claude" && row.provider !== "codex" || typeof row.profileId !== "string" || typeof row.workspaceId !== "string" || !UUID_RE18.test(row.workspaceId) || typeof row.principalId !== "string" || !UUID_RE18.test(row.principalId) || !Number.isSafeInteger(row.pid) || row.pid < 1 || typeof row.state !== "string" || !["starting", "ready", "stopping", "stopped", "failed"].includes(row.state) || typeof row.startedAt !== "string" || !Number.isFinite(Date.parse(row.startedAt)) || !(row.readyAt === null || typeof row.readyAt === "string" && Number.isFinite(Date.parse(row.readyAt))) || typeof row.updatedAt !== "string" || !Number.isFinite(Date.parse(row.updatedAt)) || !(row.stoppedAt === null || typeof row.stoppedAt === "string" && Number.isFinite(Date.parse(row.stoppedAt))) || !nullableUuid3(row.lastSignalId) || !(row.lastErrorCode === null || typeof row.lastErrorCode === "string" && /^[a-z0-9_-]{1,96}$/.test(row.lastErrorCode)) || !(row.lastErrorDetail === void 0 || row.lastErrorDetail === null || typeof row.lastErrorDetail === "string" && row.lastErrorDetail.length > 0 && row.lastErrorDetail.length <= 2048 && !/swm_(?:agt|inv|cap)_/i.test(row.lastErrorDetail)) || !(row.lastErrorReasonCode === void 0 || row.lastErrorReasonCode === null || typeof row.lastErrorReasonCode === "string" && /^[a-z0-9_-]{1,96}$/.test(row.lastErrorReasonCode)) || !(row.providerExecutable === void 0 || row.providerExecutable === null || typeof row.providerExecutable === "string" && (0, import_node_path16.isAbsolute)(row.providerExecutable)) || !(row.providerVersion === void 0 || row.providerVersion === null || typeof row.providerVersion === "string" && SEMVER_RE2.test(row.providerVersion)) || !(row.providerLastMeasuredVersion === void 0 || row.providerLastMeasuredVersion === null || typeof row.providerLastMeasuredVersion === "string" && SEMVER_RE2.test(row.providerLastMeasuredVersion)) || !(row.providerBundledAgentSdkVersion === void 0 || row.providerBundledAgentSdkVersion === null || typeof row.providerBundledAgentSdkVersion === "string" && SEMVER_RE2.test(row.providerBundledAgentSdkVersion)) || !(row.providerBundledClaudeCodeVersion === void 0 || row.providerBundledClaudeCodeVersion === null || typeof row.providerBundledClaudeCodeVersion === "string" && SEMVER_RE2.test(row.providerBundledClaudeCodeVersion)) || !(row.providerMinimumRequiredVersion === void 0 || row.providerMinimumRequiredVersion === null || typeof row.providerMinimumRequiredVersion === "string" && SEMVER_RE2.test(row.providerMinimumRequiredVersion)) || !(row.cswarmVersion === void 0 || row.cswarmVersion === null || typeof row.cswarmVersion === "string" && SEMVER_RE2.test(row.cswarmVersion)) || (row.providerVersion === null || row.providerVersion === void 0) !== (row.providerLastMeasuredVersion === null || row.providerLastMeasuredVersion === void 0) || !(row.lastWorkerStderrTail === void 0 || row.lastWorkerStderrTail === null || typeof row.lastWorkerStderrTail === "string" && row.lastWorkerStderrTail.length > 0 && row.lastWorkerStderrTail.length <= 2048 && !/swm_(?:agt|inv|cap)_/i.test(row.lastWorkerStderrTail)) || typeof row.logPath !== "string" || !(0, import_node_path16.isAbsolute)(row.logPath) || !(row.deliveryMode === void 0 || row.deliveryMode === null || typeof row.deliveryMode === "string" && STATUS_DELIVERY_MODES.has(row.deliveryMode)) || !(row.pendingDeliveryCount === void 0 || nullableCount(row.pendingDeliveryCount)) || !(row.lastTerminalDeliveryFailureCount === void 0 || nullableCount(row.lastTerminalDeliveryFailureCount)) || !(row.lastTerminalDeliveryFailureAt === void 0 || nullableTimestamp3(row.lastTerminalDeliveryFailureAt)) || !(row.lastClaimAt === void 0 || nullableTimestamp3(row.lastClaimAt)) || !(row.lastAckAt === void 0 || nullableTimestamp3(row.lastAckAt)) || !(row.lastAckOutcome === void 0 || row.lastAckOutcome === null || typeof row.lastAckOutcome === "string" && deliveryOutcomes.has(row.lastAckOutcome)) || !(row.consecutiveAckFailureCount === void 0 || nullableCount(row.consecutiveAckFailureCount)) || !(row.lastAckSignalId === void 0 || row.lastAckSignalId === null || typeof row.lastAckSignalId === "string" && UUID_RE18.test(row.lastAckSignalId)) || !(row.currentDeliverySignalId === void 0 || row.currentDeliverySignalId === null || typeof row.currentDeliverySignalId === "string" && UUID_RE18.test(row.currentDeliverySignalId)) || !(row.currentDeliverySince === void 0 || nullableTimestamp3(row.currentDeliverySince)) || heldBackDeliveries === null || !(row.pendingDeliveryCountAt === void 0 || nullableTimestamp3(row.pendingDeliveryCountAt)) || !(row.routeMode === void 0 || row.routeMode === "worker" || row.routeMode === "main" || row.routeMode === "split") || !(row.deferOverChars === void 0 || row.deferOverChars === null || typeof row.deferOverChars === "number" && Number.isSafeInteger(row.deferOverChars) && row.deferOverChars >= 1 && row.deferOverChars <= 1e4) || !(row.pendingForMainCount === void 0 || typeof row.pendingForMainCount === "number" && Number.isSafeInteger(row.pendingForMainCount) && row.pendingForMainCount >= 0) || !(row.droppedForMainCount === void 0 || typeof row.droppedForMainCount === "number" && Number.isSafeInteger(row.droppedForMainCount) && row.droppedForMainCount >= 0) || readHealth === null || !(row.connectionsOpened === void 0 || typeof row.connectionsOpened === "number" && Number.isSafeInteger(row.connectionsOpened) && row.connectionsOpened >= 0) || !(row.connectionReuseRatio === void 0 || typeof row.connectionReuseRatio === "number" && Number.isFinite(row.connectionReuseRatio) && row.connectionReuseRatio >= 0) || !(row.activityPublishFailures === void 0 || typeof row.activityPublishFailures === "number" && Number.isSafeInteger(row.activityPublishFailures) && row.activityPublishFailures >= 0) || !(row.activityLastErrorCode === void 0 || row.activityLastErrorCode === null || typeof row.activityLastErrorCode === "string" && STATUS_ACTIVITY_ERROR_CODES.has(
|
|
38281
38335
|
row.activityLastErrorCode
|
|
38282
38336
|
))) {
|
|
38283
38337
|
throw new Error("stored listener status is malformed");
|
|
@@ -38303,6 +38357,16 @@ function parseStatus(raw, rejectUnknownKeys = false) {
|
|
|
38303
38357
|
// Optional key: present only when the file carried it, so a status written
|
|
38304
38358
|
// without it round-trips byte-for-byte (the routeMode pattern).
|
|
38305
38359
|
...row.lastAckSignalId === void 0 ? {} : { lastAckSignalId: row.lastAckSignalId ?? null },
|
|
38360
|
+
...row.currentDeliverySignalId === void 0 ? {} : {
|
|
38361
|
+
currentDeliverySignalId: row.currentDeliverySignalId ?? null
|
|
38362
|
+
},
|
|
38363
|
+
...row.currentDeliverySince === void 0 ? {} : {
|
|
38364
|
+
currentDeliverySince: row.currentDeliverySince ?? null
|
|
38365
|
+
},
|
|
38366
|
+
...heldBackDeliveries === void 0 ? {} : { heldBackDeliveries },
|
|
38367
|
+
...row.pendingDeliveryCountAt === void 0 ? {} : {
|
|
38368
|
+
pendingDeliveryCountAt: row.pendingDeliveryCountAt ?? null
|
|
38369
|
+
},
|
|
38306
38370
|
lastErrorDetail: row.lastErrorDetail ?? null,
|
|
38307
38371
|
lastWorkerStderrTail: row.lastWorkerStderrTail ?? null,
|
|
38308
38372
|
providerVersion: row.providerVersion ?? null,
|
|
@@ -38379,7 +38443,10 @@ async function appendListenerEvent(paths, event) {
|
|
|
38379
38443
|
"defer_over_chars",
|
|
38380
38444
|
"body_length",
|
|
38381
38445
|
"pending_main_count",
|
|
38382
|
-
"dropped_count"
|
|
38446
|
+
"dropped_count",
|
|
38447
|
+
// How long one delivery held the worker seat, and why it gave it back.
|
|
38448
|
+
"held_ms",
|
|
38449
|
+
"release_reason"
|
|
38383
38450
|
]);
|
|
38384
38451
|
const deliveryModes = /* @__PURE__ */ new Set(["durable_claim", "cursor_fallback"]);
|
|
38385
38452
|
const routeModes = /* @__PURE__ */ new Set(["worker", "main", "split"]);
|
|
@@ -38441,6 +38508,14 @@ async function appendListenerEvent(paths, event) {
|
|
|
38441
38508
|
if ((key2 === "body_length" || key2 === "pending_main_count" || key2 === "dropped_count") && !(typeof value === "number" && Number.isSafeInteger(value) && value >= 0)) {
|
|
38442
38509
|
throw new Error("listener event main-route count is not allowed");
|
|
38443
38510
|
}
|
|
38511
|
+
if (key2 === "held_ms" && !(typeof value === "number" && Number.isSafeInteger(value) && value >= 0)) {
|
|
38512
|
+
throw new Error("listener event hold duration is not allowed");
|
|
38513
|
+
}
|
|
38514
|
+
if (key2 === "release_reason" && !(typeof value === "string" && LISTENER_DELIVERY_HOLD_RELEASE_REASONS.includes(
|
|
38515
|
+
value
|
|
38516
|
+
))) {
|
|
38517
|
+
throw new Error("listener event hold release reason is not allowed");
|
|
38518
|
+
}
|
|
38444
38519
|
if (key2 === "worker_stderr_tail" && !(typeof value === "string" && value.length > 0 && value.length <= 2048)) {
|
|
38445
38520
|
throw new Error("listener event stderr tail is not allowed");
|
|
38446
38521
|
}
|
|
@@ -38820,6 +38895,7 @@ async function runListenerSupervisor(options) {
|
|
|
38820
38895
|
lastWorkerStderrTail: null,
|
|
38821
38896
|
deliveryMode: null,
|
|
38822
38897
|
pendingDeliveryCount: null,
|
|
38898
|
+
pendingDeliveryCountAt: null,
|
|
38823
38899
|
lastTerminalDeliveryFailureCount: null,
|
|
38824
38900
|
lastTerminalDeliveryFailureAt: null,
|
|
38825
38901
|
lastClaimAt: null,
|
|
@@ -38831,6 +38907,11 @@ async function runListenerSupervisor(options) {
|
|
|
38831
38907
|
lastAckOutcome: carried?.lastAckOutcome ?? null,
|
|
38832
38908
|
consecutiveAckFailureCount: carried?.consecutiveAckFailureCount ?? null,
|
|
38833
38909
|
lastAckSignalId: carried?.lastAckSignalId ?? null,
|
|
38910
|
+
/* Never carried across a restart: a seat this process does not hold cannot
|
|
38911
|
+
be reported as held, and the queue age restarts with the observations. */
|
|
38912
|
+
currentDeliverySignalId: null,
|
|
38913
|
+
currentDeliverySince: null,
|
|
38914
|
+
heldBackDeliveries: [],
|
|
38834
38915
|
routeMode: options.routeMode ?? "worker",
|
|
38835
38916
|
deferOverChars: options.deferOverChars ?? null,
|
|
38836
38917
|
pendingForMainCount: 0,
|
|
@@ -38864,9 +38945,15 @@ async function runListenerSupervisor(options) {
|
|
|
38864
38945
|
chain(() => appendListenerEvent(options.paths, event));
|
|
38865
38946
|
};
|
|
38866
38947
|
const transition = (state, changes = {}) => {
|
|
38948
|
+
const notWatching = state === "starting" || state === "stopped" || state === "failed";
|
|
38867
38949
|
status = {
|
|
38868
38950
|
...status,
|
|
38869
38951
|
...changes,
|
|
38952
|
+
...notWatching ? {
|
|
38953
|
+
currentDeliverySignalId: null,
|
|
38954
|
+
currentDeliverySince: null,
|
|
38955
|
+
heldBackDeliveries: []
|
|
38956
|
+
} : {},
|
|
38870
38957
|
state,
|
|
38871
38958
|
updatedAt: iso2(now)
|
|
38872
38959
|
};
|
|
@@ -39055,6 +39142,7 @@ async function runListenerSupervisor(options) {
|
|
|
39055
39142
|
...status,
|
|
39056
39143
|
deliveryMode: event.mode,
|
|
39057
39144
|
pendingDeliveryCount: event.pendingDeliveryCount,
|
|
39145
|
+
pendingDeliveryCountAt: event.pendingDeliveryCount === null ? null : event.ts,
|
|
39058
39146
|
updatedAt: event.ts
|
|
39059
39147
|
};
|
|
39060
39148
|
persist();
|
|
@@ -39067,6 +39155,7 @@ async function runListenerSupervisor(options) {
|
|
|
39067
39155
|
return;
|
|
39068
39156
|
}
|
|
39069
39157
|
if (event.type === "delivery_claim") {
|
|
39158
|
+
const heldBack = (status.heldBackDeliveries ?? []).filter((entry) => entry.signalId !== event.signalId);
|
|
39070
39159
|
status = {
|
|
39071
39160
|
...status,
|
|
39072
39161
|
readHealth: recordListenerClaim(
|
|
@@ -39074,6 +39163,10 @@ async function runListenerSupervisor(options) {
|
|
|
39074
39163
|
event.ts
|
|
39075
39164
|
),
|
|
39076
39165
|
pendingDeliveryCount: event.pendingDeliveryCount,
|
|
39166
|
+
pendingDeliveryCountAt: event.ts,
|
|
39167
|
+
currentDeliverySignalId: event.signalId,
|
|
39168
|
+
currentDeliverySince: event.signalId === null ? null : event.ts,
|
|
39169
|
+
heldBackDeliveries: heldBack,
|
|
39077
39170
|
lastClaimAt: event.ts,
|
|
39078
39171
|
updatedAt: event.ts
|
|
39079
39172
|
};
|
|
@@ -39105,6 +39198,36 @@ async function runListenerSupervisor(options) {
|
|
|
39105
39198
|
});
|
|
39106
39199
|
return;
|
|
39107
39200
|
}
|
|
39201
|
+
if (event.type === "delivery_hold_released") {
|
|
39202
|
+
status = {
|
|
39203
|
+
...status,
|
|
39204
|
+
currentDeliverySignalId: null,
|
|
39205
|
+
currentDeliverySince: null,
|
|
39206
|
+
/* Held back, NOT waiting to be claimed: the row keeps its live lease,
|
|
39207
|
+
so the service cannot hand it to anyone until that lease expires.
|
|
39208
|
+
Both review arms on 33cd24b measured the earlier wording counting it
|
|
39209
|
+
among deliveries "waiting to be claimed". Newest first, deduplicated
|
|
39210
|
+
on the id (a row can be released, redelivered and released again),
|
|
39211
|
+
and bounded. */
|
|
39212
|
+
heldBackDeliveries: [
|
|
39213
|
+
{ signalId: event.signalId, at: event.ts, reason: event.reason },
|
|
39214
|
+
...(status.heldBackDeliveries ?? []).filter(
|
|
39215
|
+
(entry) => entry.signalId !== event.signalId
|
|
39216
|
+
)
|
|
39217
|
+
].slice(0, LISTENER_HELD_BACK_MAX),
|
|
39218
|
+
lastSignalId: event.signalId,
|
|
39219
|
+
updatedAt: event.ts
|
|
39220
|
+
};
|
|
39221
|
+
persist();
|
|
39222
|
+
log({
|
|
39223
|
+
ts: event.ts,
|
|
39224
|
+
event: "listener_delivery_hold_released",
|
|
39225
|
+
signal_id: event.signalId,
|
|
39226
|
+
release_reason: event.reason,
|
|
39227
|
+
held_ms: Math.max(0, Math.trunc(event.heldMs))
|
|
39228
|
+
});
|
|
39229
|
+
return;
|
|
39230
|
+
}
|
|
39108
39231
|
if (event.type === "delivery_ack") {
|
|
39109
39232
|
const failed = event.outcome === "failed_terminal";
|
|
39110
39233
|
const providerProven = DELIVERY_PROVIDER_PROVEN_OUTCOMES.has(event.outcome);
|
|
@@ -39115,6 +39238,13 @@ async function runListenerSupervisor(options) {
|
|
|
39115
39238
|
lastAckSignalId: event.signalId,
|
|
39116
39239
|
consecutiveAckFailureCount: failed ? (status.consecutiveAckFailureCount ?? 0) + 1 : providerProven ? 0 : status.consecutiveAckFailureCount,
|
|
39117
39240
|
pendingDeliveryCount: null,
|
|
39241
|
+
pendingDeliveryCountAt: null,
|
|
39242
|
+
currentDeliverySignalId: null,
|
|
39243
|
+
currentDeliverySince: null,
|
|
39244
|
+
// An acknowledged row is answered and gone; drop just that one.
|
|
39245
|
+
heldBackDeliveries: (status.heldBackDeliveries ?? []).filter(
|
|
39246
|
+
(entry) => entry.signalId !== event.signalId
|
|
39247
|
+
),
|
|
39118
39248
|
lastSignalId: event.signalId,
|
|
39119
39249
|
updatedAt: event.ts
|
|
39120
39250
|
};
|
|
@@ -39285,7 +39415,14 @@ async function effectiveListenerStatus(paths) {
|
|
|
39285
39415
|
state: "failed",
|
|
39286
39416
|
updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
39287
39417
|
stoppedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
39288
|
-
lastErrorCode: "unclean_exit"
|
|
39418
|
+
lastErrorCode: "unclean_exit",
|
|
39419
|
+
/* The process is gone: it holds nothing and observes nothing, so every
|
|
39420
|
+
field whose sentence is rendered in the present tense against read
|
|
39421
|
+
time is cleared. pendingDeliveryCount stays, because its line already
|
|
39422
|
+
says it is what the service reported. */
|
|
39423
|
+
currentDeliverySignalId: null,
|
|
39424
|
+
currentDeliverySince: null,
|
|
39425
|
+
heldBackDeliveries: []
|
|
39289
39426
|
};
|
|
39290
39427
|
await writeListenerStatus(paths, failed);
|
|
39291
39428
|
return failed;
|
|
@@ -42142,8 +42279,8 @@ var BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
|
|
|
42142
42279
|
]);
|
|
42143
42280
|
var UUID_RE23 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
42144
42281
|
function packageVersion() {
|
|
42145
|
-
if ("0.1.
|
|
42146
|
-
return "0.1.
|
|
42282
|
+
if ("0.1.54".length > 0) {
|
|
42283
|
+
return "0.1.54";
|
|
42147
42284
|
}
|
|
42148
42285
|
try {
|
|
42149
42286
|
const value = JSON.parse(
|
|
@@ -42368,7 +42505,10 @@ due \u2014 a turn never outlives its credential. Right after a rotation the full
|
|
|
42368
42505
|
budget is available up to the token TTL minus 60s (about 59m on the default 1h
|
|
42369
42506
|
TTL); a turn that lands just before a rotation can be clamped to the ~5m
|
|
42370
42507
|
renewal lead, and if it times out there, durable delivery retries it on the
|
|
42371
|
-
fresh credential.
|
|
42508
|
+
fresh credential. The same budget also bounds how long ONE delivery may hold the
|
|
42509
|
+
worker seat across its retries: when it is spent the listener hands the seat
|
|
42510
|
+
back and claims the next delivery. After the lease ends the service either
|
|
42511
|
+
delivers the released one again or terminates it.
|
|
42372
42512
|
|
|
42373
42513
|
listen start --route worker|main|split chooses where directed messages go. worker
|
|
42374
42514
|
is the unchanged default. main queues every ask or note for the interactive session.
|
|
@@ -45391,6 +45531,12 @@ function listenerStatusJson(status, permissionMode, evidence = {
|
|
|
45391
45531
|
lastAckOutcome: status.lastAckOutcome ?? null,
|
|
45392
45532
|
consecutiveAckFailureCount: status.consecutiveAckFailureCount ?? null,
|
|
45393
45533
|
lastAckSignalId: status.lastAckSignalId ?? null,
|
|
45534
|
+
currentDeliverySignalId: status.currentDeliverySignalId ?? null,
|
|
45535
|
+
currentDeliverySince: status.currentDeliverySince ?? null,
|
|
45536
|
+
currentDeliveryElapsedMs: status.currentDeliverySince ? Math.max(0, nowMs - Date.parse(status.currentDeliverySince)) : null,
|
|
45537
|
+
pendingDeliveryCountAt: status.pendingDeliveryCountAt ?? null,
|
|
45538
|
+
heldBackDeliveries: status.heldBackDeliveries ?? [],
|
|
45539
|
+
heldBackDeliveryCount: (status.heldBackDeliveries ?? []).length,
|
|
45394
45540
|
routeMode: status.routeMode ?? "worker",
|
|
45395
45541
|
deferOverChars: status.deferOverChars ?? null,
|
|
45396
45542
|
pendingForMainCount: status.pendingForMainCount ?? 0,
|
|
@@ -45513,8 +45659,26 @@ function renderListenerStatus(status, evidence = {
|
|
|
45513
45659
|
lines.push("Delivery mode has not been reported yet.");
|
|
45514
45660
|
}
|
|
45515
45661
|
if (status.pendingDeliveryCount !== null) {
|
|
45662
|
+
const observedAt = status.pendingDeliveryCountAt ?? null;
|
|
45663
|
+
lines.push(
|
|
45664
|
+
`Pending deliveries reported by the service: ${status.pendingDeliveryCount}.` + (observedAt === null ? " When the service reported it was not recorded." : ` The service reported that ${relativeAge(observedAt, nowMs)}.`)
|
|
45665
|
+
);
|
|
45666
|
+
}
|
|
45667
|
+
const currentDeliveryId = status.currentDeliverySignalId ?? null;
|
|
45668
|
+
const currentDeliverySince = status.currentDeliverySince ?? null;
|
|
45669
|
+
if (currentDeliveryId !== null && currentDeliverySince !== null) {
|
|
45670
|
+
lines.push(
|
|
45671
|
+
`Working on delivery ${currentDeliveryId}, claimed ${relativeAge(currentDeliverySince, nowMs)}.`
|
|
45672
|
+
);
|
|
45673
|
+
} else {
|
|
45674
|
+
lines.push("No delivery is being worked on right now.");
|
|
45675
|
+
}
|
|
45676
|
+
const heldBack = status.heldBackDeliveries ?? [];
|
|
45677
|
+
const newestHeldBack = heldBack[0];
|
|
45678
|
+
if (newestHeldBack !== void 0) {
|
|
45679
|
+
const others = heldBack.length - 1;
|
|
45516
45680
|
lines.push(
|
|
45517
|
-
`
|
|
45681
|
+
`Delivery ${newestHeldBack.signalId} was handed back ${relativeAge(newestHeldBack.at, nowMs)} because ${LISTENER_DELIVERY_HOLD_RELEASE_CLAUSES[newestHeldBack.reason]}.` + (others > 0 ? ` This listener is still tracking ${others} other handed-back ${others === 1 ? "delivery" : "deliveries"}.` : "") + ` This listener has not answered it. After the lease ends the service either delivers it again or terminates it. If this repeats, ${LISTENER_DELIVERY_HOLD_RELEASE_REMEDIES[newestHeldBack.reason]}.`
|
|
45518
45682
|
);
|
|
45519
45683
|
}
|
|
45520
45684
|
lines.push(
|
|
@@ -46055,6 +46219,9 @@ async function runConfiguredListener(options) {
|
|
|
46055
46219
|
},
|
|
46056
46220
|
routeMode,
|
|
46057
46221
|
deferOverChars,
|
|
46222
|
+
/* One delivery may hold the seat for one turn budget, not for the
|
|
46223
|
+
whole 15-minute lease. Same lever, so the two cannot drift. */
|
|
46224
|
+
deliveryHoldBudgetMs: turnBudgetMs,
|
|
46058
46225
|
pendingMainQueue,
|
|
46059
46226
|
fetcher: httpClient.fetch
|
|
46060
46227
|
});
|
|
@@ -47734,5 +47901,6 @@ ${usage()}
|
|
|
47734
47901
|
replyRefusalHint,
|
|
47735
47902
|
resolveDetachedClaudeExecutable,
|
|
47736
47903
|
resolveDetachedCodexExecutable,
|
|
47737
|
-
resolveTurnBudgetOrDefer
|
|
47904
|
+
resolveTurnBudgetOrDefer,
|
|
47905
|
+
usage
|
|
47738
47906
|
});
|