commonswarm 0.1.56 → 0.1.57
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 +386 -115
- package/package.json +1 -1
package/cswarm.cjs
CHANGED
|
@@ -13512,6 +13512,7 @@ __export(cli_exports, {
|
|
|
13512
13512
|
listenerFailureMessage: () => listenerFailureMessage,
|
|
13513
13513
|
listenerHostLimits: () => listenerHostLimits,
|
|
13514
13514
|
listenerPermissionMode: () => listenerPermissionMode,
|
|
13515
|
+
listenerPollIntervalMs: () => listenerPollIntervalMs,
|
|
13515
13516
|
listenerProviderInstallEvidence: () => listenerProviderInstallEvidence,
|
|
13516
13517
|
listenerRouteConfiguration: () => listenerRouteConfiguration,
|
|
13517
13518
|
listenerStatusJson: () => listenerStatusJson,
|
|
@@ -13528,10 +13529,10 @@ module.exports = __toCommonJS(cli_exports);
|
|
|
13528
13529
|
var import_node_crypto22 = require("node:crypto");
|
|
13529
13530
|
var import_node_child_process9 = require("node:child_process");
|
|
13530
13531
|
var import_node_fs7 = require("node:fs");
|
|
13531
|
-
var
|
|
13532
|
+
var import_promises13 = require("node:fs/promises");
|
|
13532
13533
|
var import_node_os10 = require("node:os");
|
|
13533
13534
|
var import_node_path21 = require("node:path");
|
|
13534
|
-
var
|
|
13535
|
+
var import_promises14 = require("node:readline/promises");
|
|
13535
13536
|
|
|
13536
13537
|
// src/protocol/events.ts
|
|
13537
13538
|
var SCHEMA_VERSION = 1;
|
|
@@ -26174,7 +26175,7 @@ var src_default = Postgres;
|
|
|
26174
26175
|
function Postgres(a, b2) {
|
|
26175
26176
|
const options = parseOptions(a, b2), subscribe = options.no_subscribe || Subscribe(Postgres, { ...options });
|
|
26176
26177
|
let ending = false;
|
|
26177
|
-
const queries = queue_default(), connecting = queue_default(), reserved = queue_default(), closed = queue_default(), ended = queue_default(),
|
|
26178
|
+
const queries = queue_default(), connecting = queue_default(), reserved = queue_default(), closed = queue_default(), ended = queue_default(), open7 = queue_default(), busy = queue_default(), full = queue_default(), queues = { connecting, reserved, closed, ended, open: open7, busy, full };
|
|
26178
26179
|
const connections = [...Array(options.max)].map(() => connection_default(options, queues, { onopen, onend, onclose }));
|
|
26179
26180
|
const sql = Sql(handler);
|
|
26180
26181
|
Object.assign(sql, {
|
|
@@ -26287,7 +26288,7 @@ function Postgres(a, b2) {
|
|
|
26287
26288
|
}
|
|
26288
26289
|
async function reserve() {
|
|
26289
26290
|
const queue = queue_default();
|
|
26290
|
-
const c =
|
|
26291
|
+
const c = open7.length ? open7.shift() : await new Promise((resolve3, reject) => {
|
|
26291
26292
|
const query = { reserve: resolve3, reject };
|
|
26292
26293
|
queries.push(query);
|
|
26293
26294
|
closed.length && connect(closed.shift(), query);
|
|
@@ -26360,7 +26361,7 @@ function Postgres(a, b2) {
|
|
|
26360
26361
|
c.queue.remove(c);
|
|
26361
26362
|
queue.push(c);
|
|
26362
26363
|
c.queue = queue;
|
|
26363
|
-
queue ===
|
|
26364
|
+
queue === open7 ? c.idleTimer.start() : c.idleTimer.cancel();
|
|
26364
26365
|
return c;
|
|
26365
26366
|
}
|
|
26366
26367
|
function json(x) {
|
|
@@ -26374,8 +26375,8 @@ function Postgres(a, b2) {
|
|
|
26374
26375
|
function handler(query) {
|
|
26375
26376
|
if (ending)
|
|
26376
26377
|
return query.reject(Errors.connection("CONNECTION_ENDED", options, options));
|
|
26377
|
-
if (
|
|
26378
|
-
return go(
|
|
26378
|
+
if (open7.length)
|
|
26379
|
+
return go(open7.shift(), query);
|
|
26379
26380
|
if (closed.length)
|
|
26380
26381
|
return connect(closed.shift(), query);
|
|
26381
26382
|
busy.length ? go(busy.shift(), query) : queries.push(query);
|
|
@@ -26420,7 +26421,7 @@ function Postgres(a, b2) {
|
|
|
26420
26421
|
}
|
|
26421
26422
|
function onopen(c) {
|
|
26422
26423
|
if (queries.length === 0)
|
|
26423
|
-
return move(c,
|
|
26424
|
+
return move(c, open7);
|
|
26424
26425
|
let max = Math.ceil(queries.length / (connecting.length + 1)), ready = true;
|
|
26425
26426
|
while (ready && queries.length && max-- > 0) {
|
|
26426
26427
|
const query = queries.shift();
|
|
@@ -30720,10 +30721,86 @@ async function runInboxFollow(options) {
|
|
|
30720
30721
|
// src/cloud/arrival-watch.ts
|
|
30721
30722
|
var import_node_os4 = require("node:os");
|
|
30722
30723
|
var import_node_path4 = require("node:path");
|
|
30724
|
+
var import_promises4 = require("node:fs/promises");
|
|
30725
|
+
|
|
30726
|
+
// src/cloud/idle-poll.ts
|
|
30727
|
+
var IDLE_POLL_DEFAULT_MS = 15e3;
|
|
30728
|
+
var IDLE_POLL_MAX_MS = 6e4;
|
|
30729
|
+
var IDLE_POLL_MIN_MS = 1e3;
|
|
30730
|
+
var ARRIVAL_WATCH_POLL_MS = IDLE_POLL_MAX_MS;
|
|
30731
|
+
var DURATION_RE = /^([1-9]\d*)(s|m)$/;
|
|
30732
|
+
function formatIdlePollDuration(ms) {
|
|
30733
|
+
if (!Number.isSafeInteger(ms) || ms <= 0) {
|
|
30734
|
+
throw new Error("idle poll duration must be a positive number of milliseconds");
|
|
30735
|
+
}
|
|
30736
|
+
if (ms % 6e4 === 0) return `${ms / 6e4}m`;
|
|
30737
|
+
if (ms % 1e3 === 0) return `${ms / 1e3}s`;
|
|
30738
|
+
throw new Error("idle poll duration must be a whole number of seconds");
|
|
30739
|
+
}
|
|
30740
|
+
var IDLE_POLL_MIN_LABEL = formatIdlePollDuration(IDLE_POLL_MIN_MS);
|
|
30741
|
+
var IDLE_POLL_DEFAULT_LABEL = formatIdlePollDuration(IDLE_POLL_DEFAULT_MS);
|
|
30742
|
+
var IDLE_POLL_MAX_LABEL = formatIdlePollDuration(IDLE_POLL_MAX_MS);
|
|
30743
|
+
function idlePollDurationExamples() {
|
|
30744
|
+
const midMs = Math.min(IDLE_POLL_MAX_MS, IDLE_POLL_DEFAULT_MS * 2);
|
|
30745
|
+
const labels = [];
|
|
30746
|
+
const seen = /* @__PURE__ */ new Set();
|
|
30747
|
+
for (const ms of [IDLE_POLL_DEFAULT_MS, midMs, IDLE_POLL_MAX_MS]) {
|
|
30748
|
+
const label = formatIdlePollDuration(ms);
|
|
30749
|
+
if (seen.has(label)) continue;
|
|
30750
|
+
seen.add(label);
|
|
30751
|
+
labels.push(label);
|
|
30752
|
+
}
|
|
30753
|
+
return labels;
|
|
30754
|
+
}
|
|
30755
|
+
var IDLE_POLL_DURATION_EXAMPLES = idlePollDurationExamples();
|
|
30756
|
+
function idlePollDurationHint() {
|
|
30757
|
+
return idlePollDurationExamples().join(", ");
|
|
30758
|
+
}
|
|
30759
|
+
function idlePollBoundSentence() {
|
|
30760
|
+
return `between ${IDLE_POLL_MIN_LABEL} and ${IDLE_POLL_MAX_LABEL}`;
|
|
30761
|
+
}
|
|
30762
|
+
function parseIdlePollIntervalMs(value, defaultMs = IDLE_POLL_DEFAULT_MS) {
|
|
30763
|
+
if (value === void 0) return defaultMs;
|
|
30764
|
+
const match = DURATION_RE.exec(value);
|
|
30765
|
+
if (!match) {
|
|
30766
|
+
throw new Error(
|
|
30767
|
+
`--poll-interval must be a duration such as ${idlePollDurationHint()}`
|
|
30768
|
+
);
|
|
30769
|
+
}
|
|
30770
|
+
const unit = match[2] === "s" ? 1e3 : 6e4;
|
|
30771
|
+
const milliseconds = Number(match[1]) * unit;
|
|
30772
|
+
if (!Number.isSafeInteger(milliseconds) || milliseconds < IDLE_POLL_MIN_MS || milliseconds > IDLE_POLL_MAX_MS) {
|
|
30773
|
+
throw new Error(`--poll-interval must be ${idlePollBoundSentence()}`);
|
|
30774
|
+
}
|
|
30775
|
+
return milliseconds;
|
|
30776
|
+
}
|
|
30777
|
+
function nextIdlePollMs(baseMs, emptyStreak, maxMs = IDLE_POLL_MAX_MS) {
|
|
30778
|
+
if (!Number.isSafeInteger(baseMs) || baseMs < 0) {
|
|
30779
|
+
throw new Error("idle poll base must be a non-negative number of milliseconds");
|
|
30780
|
+
}
|
|
30781
|
+
if (!Number.isSafeInteger(emptyStreak) || emptyStreak < 0) {
|
|
30782
|
+
throw new Error("idle poll empty streak must be a non-negative integer");
|
|
30783
|
+
}
|
|
30784
|
+
if (!Number.isSafeInteger(maxMs) || maxMs < 0) {
|
|
30785
|
+
throw new Error("idle poll max must be a non-negative number of milliseconds");
|
|
30786
|
+
}
|
|
30787
|
+
const shift = Math.min(emptyStreak, 16);
|
|
30788
|
+
const grown = baseMs * 2 ** shift;
|
|
30789
|
+
return Math.min(maxMs, grown);
|
|
30790
|
+
}
|
|
30791
|
+
function idlePollStatusSentence(currentMs) {
|
|
30792
|
+
return `Current idle poll interval: ${formatIdlePollDuration(currentMs)}.`;
|
|
30793
|
+
}
|
|
30794
|
+
function idlePollHelpSentence(defaultMs = IDLE_POLL_DEFAULT_MS) {
|
|
30795
|
+
return `listen start --poll-interval sets how long the listener waits after an empty claim (default ${formatIdlePollDuration(defaultMs)}). A whole number plus s or m (for example ${idlePollDurationHint()}), ${idlePollBoundSentence()}. Empty polls double that wait up to ${IDLE_POLL_MAX_LABEL}; any delivery resets it to the configured interval.`;
|
|
30796
|
+
}
|
|
30797
|
+
|
|
30798
|
+
// src/cloud/arrival-watch.ts
|
|
30723
30799
|
var UUID_RE11 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
30724
30800
|
var CURSOR_MAX_BYTES = 4 * 1024;
|
|
30725
30801
|
var ARRIVAL_SNIPPET_MAX = 180;
|
|
30726
|
-
var
|
|
30802
|
+
var WATCH_LOCK_MAX_BYTES = 512;
|
|
30803
|
+
var ARRIVAL_WATCH_POLL_MS2 = ARRIVAL_WATCH_POLL_MS;
|
|
30727
30804
|
var ARRIVAL_RETRY_NOTICE_THRESHOLD_MS = 6e4;
|
|
30728
30805
|
var EXIT_NOTIFY_ORPHANED = 74;
|
|
30729
30806
|
var NotifyStdoutClosedError = class extends Error {
|
|
@@ -30776,6 +30853,94 @@ function arrivalCursorPath(target2, workspaceId2, principalId, root = stateRoot(
|
|
|
30776
30853
|
`${target2.profileId}-${workspaceId2.toLowerCase()}-${principalId.toLowerCase()}.json`
|
|
30777
30854
|
);
|
|
30778
30855
|
}
|
|
30856
|
+
function arrivalWatchLockPath(target2, workspaceId2, principalId, root = stateRoot()) {
|
|
30857
|
+
return arrivalCursorPath(target2, workspaceId2, principalId, root).replace(
|
|
30858
|
+
/\.json$/u,
|
|
30859
|
+
".lock"
|
|
30860
|
+
);
|
|
30861
|
+
}
|
|
30862
|
+
function arrivalWatchAlreadyRunningSentence(pid) {
|
|
30863
|
+
return `inbox --notify is already running for this agent as pid ${pid}.`;
|
|
30864
|
+
}
|
|
30865
|
+
var ArrivalWatchAlreadyRunningError = class extends Error {
|
|
30866
|
+
code = "notify_already_running";
|
|
30867
|
+
pid;
|
|
30868
|
+
constructor(pid) {
|
|
30869
|
+
super(arrivalWatchAlreadyRunningSentence(pid));
|
|
30870
|
+
this.name = "ArrivalWatchAlreadyRunningError";
|
|
30871
|
+
this.pid = pid;
|
|
30872
|
+
}
|
|
30873
|
+
};
|
|
30874
|
+
function pidIsAlive(pid) {
|
|
30875
|
+
if (!Number.isSafeInteger(pid) || pid <= 0) return false;
|
|
30876
|
+
try {
|
|
30877
|
+
process.kill(pid, 0);
|
|
30878
|
+
return true;
|
|
30879
|
+
} catch (error) {
|
|
30880
|
+
return error.code !== "ESRCH";
|
|
30881
|
+
}
|
|
30882
|
+
}
|
|
30883
|
+
function parseWatchLock(raw) {
|
|
30884
|
+
let value;
|
|
30885
|
+
try {
|
|
30886
|
+
value = JSON.parse(raw);
|
|
30887
|
+
} catch {
|
|
30888
|
+
return null;
|
|
30889
|
+
}
|
|
30890
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
30891
|
+
const row = value;
|
|
30892
|
+
if (row.version !== 1 || !Number.isSafeInteger(row.pid) || row.pid <= 0) {
|
|
30893
|
+
return null;
|
|
30894
|
+
}
|
|
30895
|
+
return { pid: row.pid };
|
|
30896
|
+
}
|
|
30897
|
+
async function acquireArrivalWatchLock(path, pid = process.pid) {
|
|
30898
|
+
if (!Number.isSafeInteger(pid) || pid <= 0) {
|
|
30899
|
+
throw new Error("arrival watch lock pid must be a positive integer");
|
|
30900
|
+
}
|
|
30901
|
+
await ensureSecureStateDirectory((0, import_node_path4.dirname)(path));
|
|
30902
|
+
const payload = `${JSON.stringify({ version: 1, pid })}
|
|
30903
|
+
`;
|
|
30904
|
+
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
30905
|
+
try {
|
|
30906
|
+
const handle = await (0, import_promises4.open)(path, "wx", 384);
|
|
30907
|
+
try {
|
|
30908
|
+
await handle.writeFile(payload, "utf8");
|
|
30909
|
+
} finally {
|
|
30910
|
+
await handle.close();
|
|
30911
|
+
}
|
|
30912
|
+
return;
|
|
30913
|
+
} catch (error) {
|
|
30914
|
+
if (error.code !== "EEXIST") throw error;
|
|
30915
|
+
}
|
|
30916
|
+
let existing = null;
|
|
30917
|
+
try {
|
|
30918
|
+
const raw = await (0, import_promises4.readFile)(path, "utf8");
|
|
30919
|
+
if (Buffer.byteLength(raw, "utf8") <= WATCH_LOCK_MAX_BYTES) {
|
|
30920
|
+
existing = parseWatchLock(raw);
|
|
30921
|
+
}
|
|
30922
|
+
} catch (error) {
|
|
30923
|
+
if (error.code !== "ENOENT") throw error;
|
|
30924
|
+
continue;
|
|
30925
|
+
}
|
|
30926
|
+
if (existing !== null && pidIsAlive(existing.pid)) {
|
|
30927
|
+
throw new ArrivalWatchAlreadyRunningError(existing.pid);
|
|
30928
|
+
}
|
|
30929
|
+
await (0, import_promises4.unlink)(path).catch(() => void 0);
|
|
30930
|
+
}
|
|
30931
|
+
throw new Error("arrival watch lock could not be acquired");
|
|
30932
|
+
}
|
|
30933
|
+
async function releaseArrivalWatchLock(path, pid = process.pid) {
|
|
30934
|
+
try {
|
|
30935
|
+
const raw = await (0, import_promises4.readFile)(path, "utf8");
|
|
30936
|
+
const existing = parseWatchLock(raw);
|
|
30937
|
+
if (existing === null || existing.pid !== pid) return;
|
|
30938
|
+
await (0, import_promises4.unlink)(path);
|
|
30939
|
+
} catch (error) {
|
|
30940
|
+
if (error.code === "ENOENT") return;
|
|
30941
|
+
throw error;
|
|
30942
|
+
}
|
|
30943
|
+
}
|
|
30779
30944
|
function parseCursor(raw, workspaceId2, principalId) {
|
|
30780
30945
|
let value;
|
|
30781
30946
|
try {
|
|
@@ -30889,8 +31054,9 @@ function assertCursorPage(page) {
|
|
|
30889
31054
|
}
|
|
30890
31055
|
}
|
|
30891
31056
|
async function runArrivalWatch(options) {
|
|
30892
|
-
const pollMs = options.pollMs ??
|
|
31057
|
+
const pollMs = options.pollMs ?? ARRIVAL_WATCH_POLL_MS2;
|
|
30893
31058
|
const random = options.random ?? Math.random;
|
|
31059
|
+
let emptyIdleStreak = 0;
|
|
30894
31060
|
let cursor = await options.store.read();
|
|
30895
31061
|
let baseline = cursor === void 0;
|
|
30896
31062
|
let attempt = 0;
|
|
@@ -30915,6 +31081,12 @@ async function runArrivalWatch(options) {
|
|
|
30915
31081
|
timer2 = setTimeout(finish, ms);
|
|
30916
31082
|
});
|
|
30917
31083
|
};
|
|
31084
|
+
const idleWait = async (hadDelivery) => {
|
|
31085
|
+
if (hadDelivery) emptyIdleStreak = 0;
|
|
31086
|
+
const intervalMs = nextIdlePollMs(pollMs, emptyIdleStreak, IDLE_POLL_MAX_MS);
|
|
31087
|
+
if (!hadDelivery) emptyIdleStreak += 1;
|
|
31088
|
+
await wait(intervalMs);
|
|
31089
|
+
};
|
|
30918
31090
|
while (!cancelled()) {
|
|
30919
31091
|
try {
|
|
30920
31092
|
const page = await options.readPage({
|
|
@@ -30940,7 +31112,7 @@ async function runArrivalWatch(options) {
|
|
|
30940
31112
|
await options.store.write(cursor);
|
|
30941
31113
|
baseline = false;
|
|
30942
31114
|
if (cancelled()) break;
|
|
30943
|
-
await
|
|
31115
|
+
await idleWait(false);
|
|
30944
31116
|
continue;
|
|
30945
31117
|
}
|
|
30946
31118
|
const emittedSignals = [];
|
|
@@ -30956,7 +31128,8 @@ async function runArrivalWatch(options) {
|
|
|
30956
31128
|
}
|
|
30957
31129
|
if (cancelled()) break;
|
|
30958
31130
|
const fullPage = page.rawCount >= SIGNAL_FOLLOW_PAGE_LIMIT;
|
|
30959
|
-
|
|
31131
|
+
if (fullPage) await wait(0);
|
|
31132
|
+
else await idleWait(emittedSignals.length > 0);
|
|
30960
31133
|
} catch (error) {
|
|
30961
31134
|
if (cancelled()) break;
|
|
30962
31135
|
const http = followHttpDetails(error);
|
|
@@ -32288,12 +32461,13 @@ var CONTROL_AND_SEPARATOR_STRIP_RE = new RegExp(
|
|
|
32288
32461
|
"[\\u0000-\\u0008\\u000b-\\u001f\\u007f-\\u009f" + EXOTIC_SEPARATORS + "]",
|
|
32289
32462
|
"g"
|
|
32290
32463
|
);
|
|
32291
|
-
var
|
|
32292
|
-
`swm_(?:agt|inv|cap)_[^${SEPARATOR_CLASS_SOURCE}]
|
|
32293
|
-
"
|
|
32464
|
+
var SECRET_SHAPE_RE = new RegExp(
|
|
32465
|
+
`swm_(?:agt|inv|cap)_[^${SEPARATOR_CLASS_SOURCE}]*|cswarm-wake:[A-Za-z0-9_-]{43}`,
|
|
32466
|
+
"i"
|
|
32294
32467
|
);
|
|
32468
|
+
var SECRET_SHAPE_GLOBAL_RE = new RegExp(SECRET_SHAPE_RE.source, "gi");
|
|
32295
32469
|
function redactCredentialText(value) {
|
|
32296
|
-
return value.replace(ANSI_ESCAPE_GLOBAL_RE2, "").replace(CONTROL_AND_SEPARATOR_STRIP_RE, "").replace(
|
|
32470
|
+
return value.replace(ANSI_ESCAPE_GLOBAL_RE2, "").replace(CONTROL_AND_SEPARATOR_STRIP_RE, "").replace(SECRET_SHAPE_GLOBAL_RE, "[redacted-credential]");
|
|
32297
32471
|
}
|
|
32298
32472
|
|
|
32299
32473
|
// src/host/stderr-tail.ts
|
|
@@ -32368,7 +32542,7 @@ function attachStderrTailExitObserver(child, onStderrTail) {
|
|
|
32368
32542
|
|
|
32369
32543
|
// src/host/opencode.ts
|
|
32370
32544
|
var import_node_fs3 = require("node:fs");
|
|
32371
|
-
var
|
|
32545
|
+
var import_promises5 = require("node:fs/promises");
|
|
32372
32546
|
var import_node_os5 = require("node:os");
|
|
32373
32547
|
var import_node_path6 = require("node:path");
|
|
32374
32548
|
|
|
@@ -33712,18 +33886,18 @@ function buildOpenCodeHomeOwner(options) {
|
|
|
33712
33886
|
}
|
|
33713
33887
|
async function writeOpenCodeHomeOwner(home, owner) {
|
|
33714
33888
|
const path = (0, import_node_path6.join)(home, OPENCODE_HOME_OWNER_FILE);
|
|
33715
|
-
await (0,
|
|
33889
|
+
await (0, import_promises5.writeFile)(path, `${JSON.stringify(owner)}
|
|
33716
33890
|
`, {
|
|
33717
33891
|
flag: "wx",
|
|
33718
33892
|
mode: 384
|
|
33719
33893
|
});
|
|
33720
|
-
await (0,
|
|
33894
|
+
await (0, import_promises5.chmod)(path, 384);
|
|
33721
33895
|
}
|
|
33722
33896
|
async function readOpenCodeHomeOwner(home) {
|
|
33723
33897
|
const path = (0, import_node_path6.join)(home, OPENCODE_HOME_OWNER_FILE);
|
|
33724
33898
|
let raw;
|
|
33725
33899
|
try {
|
|
33726
|
-
raw = await (0,
|
|
33900
|
+
raw = await (0, import_promises5.readFile)(path, "utf8");
|
|
33727
33901
|
} catch {
|
|
33728
33902
|
return null;
|
|
33729
33903
|
}
|
|
@@ -33744,10 +33918,10 @@ async function releaseOpenCodeHome(home, instanceId) {
|
|
|
33744
33918
|
return;
|
|
33745
33919
|
}
|
|
33746
33920
|
try {
|
|
33747
|
-
await (0,
|
|
33921
|
+
await (0, import_promises5.rm)(home, { recursive: true, force: true });
|
|
33748
33922
|
} catch {
|
|
33749
|
-
await (0,
|
|
33750
|
-
await (0,
|
|
33923
|
+
await (0, import_promises5.chmod)(home, 448);
|
|
33924
|
+
await (0, import_promises5.rm)(home, { recursive: true, force: true });
|
|
33751
33925
|
}
|
|
33752
33926
|
}
|
|
33753
33927
|
function parseOpenCodeVersionOutput(stdout) {
|
|
@@ -33815,7 +33989,7 @@ function buildOpenCodeSafeConfigJson(options) {
|
|
|
33815
33989
|
async function readValidatedOpenCodeAuth(sourceAuthPath, options) {
|
|
33816
33990
|
let info;
|
|
33817
33991
|
try {
|
|
33818
|
-
info = await (0,
|
|
33992
|
+
info = await (0, import_promises5.lstat)(sourceAuthPath);
|
|
33819
33993
|
} catch (error) {
|
|
33820
33994
|
if (error.code === "ENOENT") {
|
|
33821
33995
|
if (options?.allowMissing) return null;
|
|
@@ -33844,7 +34018,7 @@ async function readValidatedOpenCodeAuth(sourceAuthPath, options) {
|
|
|
33844
34018
|
"OpenCode auth file exceeds the listener safety bound"
|
|
33845
34019
|
);
|
|
33846
34020
|
}
|
|
33847
|
-
const raw = await (0,
|
|
34021
|
+
const raw = await (0, import_promises5.readFile)(sourceAuthPath);
|
|
33848
34022
|
if (raw.byteLength > MAX_OPENCODE_AUTH_BYTES) {
|
|
33849
34023
|
throw new AcpHostError(
|
|
33850
34024
|
"opencode_auth_too_large",
|
|
@@ -33870,53 +34044,53 @@ function resolveOpenCodeAuthSourcePath(parent = process.env) {
|
|
|
33870
34044
|
return (0, import_node_path6.join)(home, ".local", "share", "opencode", "auth.json");
|
|
33871
34045
|
}
|
|
33872
34046
|
async function prepareOpenCodeIsolatedHome(options) {
|
|
33873
|
-
const home = options.home ?? await (0,
|
|
34047
|
+
const home = options.home ?? await (0, import_promises5.mkdtemp)((0, import_node_path6.join)((0, import_node_os5.tmpdir)(), OPENCODE_HOME_PREFIX));
|
|
33874
34048
|
if (!(0, import_node_path6.isAbsolute)(home)) {
|
|
33875
34049
|
throw new AcpHostError(
|
|
33876
34050
|
"isolated_home_invalid",
|
|
33877
34051
|
"isolated OpenCode home must be absolute"
|
|
33878
34052
|
);
|
|
33879
34053
|
}
|
|
33880
|
-
await (0,
|
|
34054
|
+
await (0, import_promises5.chmod)(home, 448);
|
|
33881
34055
|
try {
|
|
33882
34056
|
const xdgConfig = (0, import_node_path6.join)(home, "xdg-config");
|
|
33883
34057
|
const xdgData = (0, import_node_path6.join)(home, "xdg-data");
|
|
33884
34058
|
const xdgCache = (0, import_node_path6.join)(home, "xdg-cache");
|
|
33885
34059
|
const xdgState = (0, import_node_path6.join)(home, "xdg-state");
|
|
33886
34060
|
for (const dir of [xdgConfig, xdgData, xdgCache, xdgState]) {
|
|
33887
|
-
await (0,
|
|
33888
|
-
await (0,
|
|
34061
|
+
await (0, import_promises5.mkdir)(dir, { recursive: true, mode: 448 });
|
|
34062
|
+
await (0, import_promises5.chmod)(dir, 448);
|
|
33889
34063
|
}
|
|
33890
34064
|
const configDir = (0, import_node_path6.join)(xdgConfig, "opencode");
|
|
33891
34065
|
const dataDir = (0, import_node_path6.join)(xdgData, "opencode");
|
|
33892
|
-
await (0,
|
|
33893
|
-
await (0,
|
|
33894
|
-
await (0,
|
|
33895
|
-
await (0,
|
|
34066
|
+
await (0, import_promises5.mkdir)(configDir, { recursive: true, mode: 448 });
|
|
34067
|
+
await (0, import_promises5.mkdir)(dataDir, { recursive: true, mode: 448 });
|
|
34068
|
+
await (0, import_promises5.chmod)(configDir, 448);
|
|
34069
|
+
await (0, import_promises5.chmod)(dataDir, 448);
|
|
33896
34070
|
const configPath = (0, import_node_path6.join)(configDir, "opencode.json");
|
|
33897
|
-
await (0,
|
|
34071
|
+
await (0, import_promises5.writeFile)(
|
|
33898
34072
|
configPath,
|
|
33899
34073
|
buildOpenCodeSafeConfigJson(
|
|
33900
34074
|
options.model ? { model: options.model } : void 0
|
|
33901
34075
|
),
|
|
33902
34076
|
{ flag: "wx", mode: 384 }
|
|
33903
34077
|
);
|
|
33904
|
-
await (0,
|
|
34078
|
+
await (0, import_promises5.chmod)(configPath, 384);
|
|
33905
34079
|
const sourceAuth = resolveOpenCodeAuthSourcePath(options.env ?? process.env);
|
|
33906
34080
|
const authBytes = await readValidatedOpenCodeAuth(sourceAuth, {
|
|
33907
34081
|
allowMissing: options.allowMissingAuth === true
|
|
33908
34082
|
});
|
|
33909
34083
|
if (authBytes) {
|
|
33910
34084
|
const destAuth = (0, import_node_path6.join)(dataDir, "auth.json");
|
|
33911
|
-
await (0,
|
|
33912
|
-
await (0,
|
|
34085
|
+
await (0, import_promises5.writeFile)(destAuth, authBytes, { flag: "wx", mode: 384 });
|
|
34086
|
+
await (0, import_promises5.chmod)(destAuth, 384);
|
|
33913
34087
|
}
|
|
33914
34088
|
const owner = options.owner ?? buildOpenCodeHomeOwner({ role: "ephemeral" });
|
|
33915
34089
|
await writeOpenCodeHomeOwner(home, owner);
|
|
33916
34090
|
return home;
|
|
33917
34091
|
} catch (error) {
|
|
33918
34092
|
if (!options.home) {
|
|
33919
|
-
await (0,
|
|
34093
|
+
await (0, import_promises5.rm)(home, { recursive: true, force: true }).catch(() => void 0);
|
|
33920
34094
|
}
|
|
33921
34095
|
throw error;
|
|
33922
34096
|
}
|
|
@@ -33941,10 +34115,10 @@ function buildOpenCodeChildEnv(parent, home) {
|
|
|
33941
34115
|
};
|
|
33942
34116
|
}
|
|
33943
34117
|
async function assertOpenCodeEffectiveConfig(options) {
|
|
33944
|
-
const hostile = await (0,
|
|
34118
|
+
const hostile = await (0, import_promises5.mkdtemp)((0, import_node_path6.join)((0, import_node_os5.tmpdir)(), "cswarm-opencode-hostile-"));
|
|
33945
34119
|
try {
|
|
33946
|
-
await (0,
|
|
33947
|
-
await (0,
|
|
34120
|
+
await (0, import_promises5.chmod)(hostile, 448);
|
|
34121
|
+
await (0, import_promises5.writeFile)(
|
|
33948
34122
|
(0, import_node_path6.join)(hostile, "opencode.json"),
|
|
33949
34123
|
`${JSON.stringify({
|
|
33950
34124
|
permission: {
|
|
@@ -34007,7 +34181,7 @@ async function assertOpenCodeEffectiveConfig(options) {
|
|
|
34007
34181
|
assertForcedAskPermissionMap(map);
|
|
34008
34182
|
return { permission: map };
|
|
34009
34183
|
} finally {
|
|
34010
|
-
await (0,
|
|
34184
|
+
await (0, import_promises5.rm)(hostile, { recursive: true, force: true }).catch(() => void 0);
|
|
34011
34185
|
}
|
|
34012
34186
|
}
|
|
34013
34187
|
function assertForcedAskPermissionMap(map) {
|
|
@@ -34058,7 +34232,7 @@ async function sweepStaleOpenCodeHomes(options) {
|
|
|
34058
34232
|
let removed = 0;
|
|
34059
34233
|
let entries;
|
|
34060
34234
|
try {
|
|
34061
|
-
entries = await (0,
|
|
34235
|
+
entries = await (0, import_promises5.readdir)(root);
|
|
34062
34236
|
} catch {
|
|
34063
34237
|
return 0;
|
|
34064
34238
|
}
|
|
@@ -34066,7 +34240,7 @@ async function sweepStaleOpenCodeHomes(options) {
|
|
|
34066
34240
|
if (!name.startsWith(OPENCODE_HOME_PREFIX)) continue;
|
|
34067
34241
|
const full = (0, import_node_path6.join)(root, name);
|
|
34068
34242
|
try {
|
|
34069
|
-
const st = await (0,
|
|
34243
|
+
const st = await (0, import_promises5.lstat)(full);
|
|
34070
34244
|
if (!st.isDirectory() || st.isSymbolicLink()) continue;
|
|
34071
34245
|
if (selfUid !== null && typeof st.uid === "number" && st.uid !== selfUid) {
|
|
34072
34246
|
continue;
|
|
@@ -34080,12 +34254,12 @@ async function sweepStaleOpenCodeHomes(options) {
|
|
|
34080
34254
|
if (alive(owner.pid)) {
|
|
34081
34255
|
continue;
|
|
34082
34256
|
}
|
|
34083
|
-
await (0,
|
|
34257
|
+
await (0, import_promises5.rm)(full, { recursive: true, force: true });
|
|
34084
34258
|
removed += 1;
|
|
34085
34259
|
continue;
|
|
34086
34260
|
}
|
|
34087
34261
|
if (now - st.mtimeMs < maxAgeMs) continue;
|
|
34088
|
-
await (0,
|
|
34262
|
+
await (0, import_promises5.rm)(full, { recursive: true, force: true });
|
|
34089
34263
|
removed += 1;
|
|
34090
34264
|
} catch {
|
|
34091
34265
|
}
|
|
@@ -34146,10 +34320,10 @@ async function openOpenCodeAcpSession(options) {
|
|
|
34146
34320
|
const disposeHome = async () => {
|
|
34147
34321
|
if (createdHome) {
|
|
34148
34322
|
try {
|
|
34149
|
-
await (0,
|
|
34323
|
+
await (0, import_promises5.rm)(home, { recursive: true, force: true });
|
|
34150
34324
|
} catch {
|
|
34151
|
-
await (0,
|
|
34152
|
-
await (0,
|
|
34325
|
+
await (0, import_promises5.chmod)(home, 448);
|
|
34326
|
+
await (0, import_promises5.rm)(home, { recursive: true, force: true });
|
|
34153
34327
|
}
|
|
34154
34328
|
}
|
|
34155
34329
|
};
|
|
@@ -35827,7 +36001,7 @@ var FileListenerEffectStore = class {
|
|
|
35827
36001
|
|
|
35828
36002
|
// src/listener/grok-model.ts
|
|
35829
36003
|
var import_node_crypto14 = require("node:crypto");
|
|
35830
|
-
var
|
|
36004
|
+
var import_promises6 = require("node:fs/promises");
|
|
35831
36005
|
var import_node_os7 = require("node:os");
|
|
35832
36006
|
var import_node_path11 = require("node:path");
|
|
35833
36007
|
|
|
@@ -36099,9 +36273,9 @@ var GrokListenerModel = class {
|
|
|
36099
36273
|
}
|
|
36100
36274
|
let sentinelCreated = false;
|
|
36101
36275
|
try {
|
|
36102
|
-
await (0,
|
|
36276
|
+
await (0, import_promises6.lstat)(sentinelPath);
|
|
36103
36277
|
sentinelCreated = true;
|
|
36104
|
-
await (0,
|
|
36278
|
+
await (0, import_promises6.unlink)(sentinelPath);
|
|
36105
36279
|
} catch (error) {
|
|
36106
36280
|
if (error.code !== "ENOENT") throw error;
|
|
36107
36281
|
}
|
|
@@ -36123,7 +36297,7 @@ var GrokListenerModel = class {
|
|
|
36123
36297
|
const sourceAuth = (0, import_node_path11.join)(sourceHome, "auth.json");
|
|
36124
36298
|
let info;
|
|
36125
36299
|
try {
|
|
36126
|
-
info = await (0,
|
|
36300
|
+
info = await (0, import_promises6.lstat)(sourceAuth);
|
|
36127
36301
|
} catch (error) {
|
|
36128
36302
|
if (error.code !== "ENOENT") throw error;
|
|
36129
36303
|
throw new AcpHostError(
|
|
@@ -36149,7 +36323,7 @@ var GrokListenerModel = class {
|
|
|
36149
36323
|
"Grok auth file exceeds the listener safety bound"
|
|
36150
36324
|
);
|
|
36151
36325
|
}
|
|
36152
|
-
const raw = await (0,
|
|
36326
|
+
const raw = await (0, import_promises6.readFile)(sourceAuth);
|
|
36153
36327
|
if (raw.byteLength > MAX_GROK_AUTH_BYTES) {
|
|
36154
36328
|
throw new AcpHostError(
|
|
36155
36329
|
"grok_auth_too_large",
|
|
@@ -36169,7 +36343,7 @@ var GrokListenerModel = class {
|
|
|
36169
36343
|
|
|
36170
36344
|
// src/listener/opencode-model.ts
|
|
36171
36345
|
var import_node_crypto15 = require("node:crypto");
|
|
36172
|
-
var
|
|
36346
|
+
var import_promises7 = require("node:fs/promises");
|
|
36173
36347
|
var import_node_path12 = require("node:path");
|
|
36174
36348
|
function asError(error) {
|
|
36175
36349
|
return error instanceof Error ? error : new Error(String(error));
|
|
@@ -36181,8 +36355,8 @@ var OpenCodeListenerModel = class {
|
|
|
36181
36355
|
this.openSession = options.open ?? openOpenCodeAcpSession;
|
|
36182
36356
|
this.prepareHome = options.prepareHome ?? prepareOpenCodeIsolatedHome;
|
|
36183
36357
|
this.prepareWorkerCwd = options.prepareWorkerCwd ?? (async (home) => {
|
|
36184
|
-
const cwd = await (0,
|
|
36185
|
-
await (0,
|
|
36358
|
+
const cwd = await (0, import_promises7.mkdtemp)((0, import_node_path12.join)(home, "canary-cwd-"));
|
|
36359
|
+
await (0, import_promises7.chmod)(cwd, 448);
|
|
36186
36360
|
return cwd;
|
|
36187
36361
|
});
|
|
36188
36362
|
this.permissionMode = options.permissionMode ?? "deny";
|
|
@@ -36526,11 +36700,11 @@ var OpenCodeListenerModel = class {
|
|
|
36526
36700
|
await closeWorker();
|
|
36527
36701
|
} catch (error) {
|
|
36528
36702
|
if (error?.code !== "child_exit_timeout") {
|
|
36529
|
-
await (0,
|
|
36703
|
+
await (0, import_promises7.rm)(ownedCanaryCwd, { recursive: true, force: true }).catch(() => void 0);
|
|
36530
36704
|
}
|
|
36531
36705
|
throw error;
|
|
36532
36706
|
}
|
|
36533
|
-
await (0,
|
|
36707
|
+
await (0, import_promises7.rm)(ownedCanaryCwd, { recursive: true, force: true }).catch(() => void 0);
|
|
36534
36708
|
})();
|
|
36535
36709
|
return await closePromise;
|
|
36536
36710
|
};
|
|
@@ -36601,7 +36775,7 @@ var OpenCodeListenerModel = class {
|
|
|
36601
36775
|
throw finalErr;
|
|
36602
36776
|
} finally {
|
|
36603
36777
|
if (canaryCwd !== null && !canaryCwdOwnedByHandle && !retainCanaryCwd) {
|
|
36604
|
-
await (0,
|
|
36778
|
+
await (0, import_promises7.rm)(canaryCwd, { recursive: true, force: true }).catch(() => void 0);
|
|
36605
36779
|
}
|
|
36606
36780
|
}
|
|
36607
36781
|
}
|
|
@@ -36609,7 +36783,7 @@ var OpenCodeListenerModel = class {
|
|
|
36609
36783
|
|
|
36610
36784
|
// src/listener/claude-model.ts
|
|
36611
36785
|
var import_node_crypto16 = require("node:crypto");
|
|
36612
|
-
var
|
|
36786
|
+
var import_promises8 = require("node:fs/promises");
|
|
36613
36787
|
var import_node_os8 = require("node:os");
|
|
36614
36788
|
var import_node_path13 = require("node:path");
|
|
36615
36789
|
var CLAUDE_CODE_VERSION_REQUIRED_RE = /\bClaude Code (\d+\.\d+\.\d+) does not support this model; version (\d+\.\d+\.\d+) or newer is required\b/;
|
|
@@ -36798,9 +36972,9 @@ var ClaudeListenerModel = class {
|
|
|
36798
36972
|
canaryError = error;
|
|
36799
36973
|
} finally {
|
|
36800
36974
|
try {
|
|
36801
|
-
await (0,
|
|
36975
|
+
await (0, import_promises8.lstat)(sentinelPath);
|
|
36802
36976
|
sentinelCreated = true;
|
|
36803
|
-
await (0,
|
|
36977
|
+
await (0, import_promises8.unlink)(sentinelPath);
|
|
36804
36978
|
} catch (error) {
|
|
36805
36979
|
if (error.code !== "ENOENT") throw error;
|
|
36806
36980
|
}
|
|
@@ -36829,7 +37003,7 @@ var ClaudeListenerModel = class {
|
|
|
36829
37003
|
|
|
36830
37004
|
// src/listener/codex-model.ts
|
|
36831
37005
|
var import_node_crypto17 = require("node:crypto");
|
|
36832
|
-
var
|
|
37006
|
+
var import_promises9 = require("node:fs/promises");
|
|
36833
37007
|
var import_node_os9 = require("node:os");
|
|
36834
37008
|
var import_node_path14 = require("node:path");
|
|
36835
37009
|
var CodexListenerClosedDuringOpen = class extends Error {
|
|
@@ -36977,11 +37151,11 @@ var CodexListenerModel = class {
|
|
|
36977
37151
|
const configuredHome = this.options.env?.HOME;
|
|
36978
37152
|
const home = configuredHome && (0, import_node_path14.isAbsolute)(configuredHome) ? configuredHome : (0, import_node_os9.homedir)();
|
|
36979
37153
|
const sentinelDirectory = (0, import_node_path14.join)(home, ".cswarm", "canary");
|
|
36980
|
-
await (0,
|
|
36981
|
-
await (0,
|
|
37154
|
+
await (0, import_promises9.mkdir)(sentinelDirectory, { recursive: true, mode: 448 });
|
|
37155
|
+
await (0, import_promises9.chmod)(sentinelDirectory, 448);
|
|
36982
37156
|
const [workerCwd, canaryDirectory] = await Promise.all([
|
|
36983
|
-
(0,
|
|
36984
|
-
(0,
|
|
37157
|
+
(0, import_promises9.realpath)(this.options.cwd),
|
|
37158
|
+
(0, import_promises9.realpath)(sentinelDirectory)
|
|
36985
37159
|
]);
|
|
36986
37160
|
if (pathIsInsideOrEqual(workerCwd, canaryDirectory)) {
|
|
36987
37161
|
throw new AcpPermissionCanaryError(
|
|
@@ -37004,9 +37178,9 @@ var CodexListenerModel = class {
|
|
|
37004
37178
|
canaryError = error;
|
|
37005
37179
|
} finally {
|
|
37006
37180
|
try {
|
|
37007
|
-
await (0,
|
|
37181
|
+
await (0, import_promises9.lstat)(sentinelPath);
|
|
37008
37182
|
sentinelCreated = true;
|
|
37009
|
-
await (0,
|
|
37183
|
+
await (0, import_promises9.unlink)(sentinelPath);
|
|
37010
37184
|
} catch (error) {
|
|
37011
37185
|
if (error.code !== "ENOENT") throw error;
|
|
37012
37186
|
}
|
|
@@ -37240,7 +37414,8 @@ function pendingMainEntry(signal, principalId, provenance, now, options = {}) {
|
|
|
37240
37414
|
|
|
37241
37415
|
// src/listener/runtime.ts
|
|
37242
37416
|
var LISTENER_PAGE_LIMIT = 100;
|
|
37243
|
-
var LISTENER_IDLE_POLL_MS =
|
|
37417
|
+
var LISTENER_IDLE_POLL_MS = IDLE_POLL_DEFAULT_MS;
|
|
37418
|
+
var LISTENER_IDLE_POLL_MAX_MS = IDLE_POLL_MAX_MS;
|
|
37244
37419
|
var LISTENER_DELIVERY_SAFETY_MARGIN_MS = 3e4;
|
|
37245
37420
|
var LISTENER_ACK_ONLY_MINIMUM_MS = DELIVERY_REQUEST_TIMEOUT_MS + LISTENER_DELIVERY_SAFETY_MARGIN_MS;
|
|
37246
37421
|
var LISTENER_REPLY_ONLY_MINIMUM_MS = SIGNAL_REQUEST_TIMEOUT_MS + LISTENER_ACK_ONLY_MINIMUM_MS;
|
|
@@ -37525,10 +37700,22 @@ async function runListenerRuntime(options) {
|
|
|
37525
37700
|
const random = options.random ?? Math.random;
|
|
37526
37701
|
const pageLimit = options.pageLimit ?? LISTENER_PAGE_LIMIT;
|
|
37527
37702
|
const pollMs = options.pollMs ?? LISTENER_IDLE_POLL_MS;
|
|
37703
|
+
let emptyIdleStreak = 0;
|
|
37528
37704
|
const routeMode = options.routeMode ?? "worker";
|
|
37529
37705
|
const deferOverChars = options.deferOverChars ?? null;
|
|
37530
37706
|
const deliveryHoldBudgetMs = options.deliveryHoldBudgetMs ?? LISTENER_DELIVERY_HOLD_BUDGET_MS;
|
|
37531
37707
|
const abort = options.signal;
|
|
37708
|
+
const idleSleep = async (hadDelivery) => {
|
|
37709
|
+
if (hadDelivery) emptyIdleStreak = 0;
|
|
37710
|
+
const intervalMs = nextIdlePollMs(pollMs, emptyIdleStreak, LISTENER_IDLE_POLL_MAX_MS);
|
|
37711
|
+
if (!hadDelivery) emptyIdleStreak += 1;
|
|
37712
|
+
options.onEvent?.({
|
|
37713
|
+
type: "idle_poll",
|
|
37714
|
+
intervalMs,
|
|
37715
|
+
ts: eventTime(now)
|
|
37716
|
+
});
|
|
37717
|
+
await sleep2(intervalMs, abort);
|
|
37718
|
+
};
|
|
37532
37719
|
const hasInstanceId = options.listenerInstanceId !== void 0;
|
|
37533
37720
|
const hasJournal = options.deliveryJournal !== void 0;
|
|
37534
37721
|
if (hasInstanceId !== hasJournal) {
|
|
@@ -37936,7 +38123,7 @@ async function runListenerRuntime(options) {
|
|
|
37936
38123
|
stop = { reason: "cancelled" };
|
|
37937
38124
|
break;
|
|
37938
38125
|
}
|
|
37939
|
-
await
|
|
38126
|
+
await idleSleep(true);
|
|
37940
38127
|
continue;
|
|
37941
38128
|
}
|
|
37942
38129
|
await sleep2(Math.max(0, horizon - now()), abort);
|
|
@@ -38114,9 +38301,15 @@ async function runListenerRuntime(options) {
|
|
|
38114
38301
|
stop = { reason: "fatal", error: asError2(error) };
|
|
38115
38302
|
break;
|
|
38116
38303
|
}
|
|
38117
|
-
await
|
|
38304
|
+
await idleSleep(false);
|
|
38118
38305
|
continue;
|
|
38119
38306
|
}
|
|
38307
|
+
emptyIdleStreak = 0;
|
|
38308
|
+
options.onEvent?.({
|
|
38309
|
+
type: "idle_poll",
|
|
38310
|
+
intervalMs: pollMs,
|
|
38311
|
+
ts: eventTime(now)
|
|
38312
|
+
});
|
|
38120
38313
|
const leasedUntilMs = Date.parse(claimed.leasedUntil);
|
|
38121
38314
|
if (!Number.isFinite(leasedUntilMs) || leasedUntilMs > now() + LISTENER_DELIVERY_MAX_LEASE_MS) {
|
|
38122
38315
|
stop = { reason: "fatal", error: new Error("delivery lease deadline is invalid") };
|
|
@@ -38389,7 +38582,7 @@ async function runListenerRuntime(options) {
|
|
|
38389
38582
|
continue;
|
|
38390
38583
|
}
|
|
38391
38584
|
after = null;
|
|
38392
|
-
await
|
|
38585
|
+
await idleSleep(page.signals.length > 0);
|
|
38393
38586
|
}
|
|
38394
38587
|
} finally {
|
|
38395
38588
|
abort?.removeEventListener("abort", onAbort);
|
|
@@ -38507,8 +38700,20 @@ function recordListenerReadRecovery(health, input) {
|
|
|
38507
38700
|
retryHours: trimNewest(retryHours, LISTENER_READ_RETRY_HOUR_CAP)
|
|
38508
38701
|
};
|
|
38509
38702
|
}
|
|
38510
|
-
function recordListenerClaimCadence(health, cadenceMs) {
|
|
38511
|
-
|
|
38703
|
+
function recordListenerClaimCadence(health, cadenceMs, ts) {
|
|
38704
|
+
const hourStart = bucketStart(ts, HOUR_MS);
|
|
38705
|
+
const claimHours = health.claimHours.map((row) => ({ ...row }));
|
|
38706
|
+
const hour = claimHours.find((row) => row.hourStart === hourStart);
|
|
38707
|
+
if (hour) {
|
|
38708
|
+
hour.cadenceMs = hour.cadenceMs === void 0 ? cadenceMs : Math.max(hour.cadenceMs, cadenceMs);
|
|
38709
|
+
} else {
|
|
38710
|
+
claimHours.push({ hourStart, claims: 0, cadenceMs });
|
|
38711
|
+
}
|
|
38712
|
+
return {
|
|
38713
|
+
...health,
|
|
38714
|
+
claimCadenceMs: cadenceMs,
|
|
38715
|
+
claimHours: trimNewest(claimHours, LISTENER_CLAIM_HOUR_CAP)
|
|
38716
|
+
};
|
|
38512
38717
|
}
|
|
38513
38718
|
function recordListenerClaim(health, ts) {
|
|
38514
38719
|
const hourStart = bucketStart(ts, HOUR_MS);
|
|
@@ -38567,7 +38772,11 @@ function parseListenerReadHealth(value, rejectUnknownKeys = false) {
|
|
|
38567
38772
|
for (const value2 of row.claimHours) {
|
|
38568
38773
|
if (!value2 || typeof value2 !== "object" || Array.isArray(value2)) return null;
|
|
38569
38774
|
const hour = value2;
|
|
38570
|
-
if (!hasExpectedKeys(hour, ["hourStart", "claims"],
|
|
38775
|
+
if (!hasExpectedKeys(hour, ["hourStart", "claims"], false) || !validTimestamp(hour.hourStart) || !validCount(hour.claims)) return null;
|
|
38776
|
+
if (rejectUnknownKeys && Object.keys(hour).some(
|
|
38777
|
+
(key2) => key2 !== "hourStart" && key2 !== "claims" && key2 !== "cadenceMs"
|
|
38778
|
+
)) return null;
|
|
38779
|
+
if (hour.cadenceMs !== void 0 && !(typeof hour.cadenceMs === "number" && Number.isSafeInteger(hour.cadenceMs) && hour.cadenceMs >= 1)) return null;
|
|
38571
38780
|
}
|
|
38572
38781
|
return {
|
|
38573
38782
|
currentEpisodeStartedAt: row.currentEpisodeStartedAt,
|
|
@@ -38587,10 +38796,14 @@ function parseListenerReadHealth(value, rejectUnknownKeys = false) {
|
|
|
38587
38796
|
retries: minute.retries
|
|
38588
38797
|
})),
|
|
38589
38798
|
claimCadenceMs: row.claimCadenceMs,
|
|
38590
|
-
claimHours: row.claimHours.map((hour) =>
|
|
38591
|
-
|
|
38592
|
-
|
|
38593
|
-
|
|
38799
|
+
claimHours: row.claimHours.map((hour) => {
|
|
38800
|
+
const cadenceMs = hour.cadenceMs;
|
|
38801
|
+
return {
|
|
38802
|
+
hourStart: hour.hourStart,
|
|
38803
|
+
claims: hour.claims,
|
|
38804
|
+
...typeof cadenceMs === "number" ? { cadenceMs } : {}
|
|
38805
|
+
};
|
|
38806
|
+
})
|
|
38594
38807
|
};
|
|
38595
38808
|
}
|
|
38596
38809
|
function summarizeListenerReadHealth(health, readyAt, nowMs) {
|
|
@@ -38624,10 +38837,15 @@ function summarizeListenerReadHealth(health, readyAt, nowMs) {
|
|
|
38624
38837
|
const claimsByHour = new Map(
|
|
38625
38838
|
health.claimHours.map((row) => [row.hourStart, row.claims])
|
|
38626
38839
|
);
|
|
38627
|
-
const
|
|
38840
|
+
const cadenceByHour = /* @__PURE__ */ new Map();
|
|
38841
|
+
for (const row of health.claimHours) {
|
|
38842
|
+
if (row.cadenceMs !== void 0) cadenceByHour.set(row.hourStart, row.cadenceMs);
|
|
38843
|
+
}
|
|
38628
38844
|
for (let hour = first; hour < currentHour; hour += HOUR_MS) {
|
|
38629
38845
|
const hourStart = new Date(hour).toISOString();
|
|
38630
38846
|
const claims = claimsByHour.get(hourStart) ?? 0;
|
|
38847
|
+
const cadenceMs = cadenceByHour.get(hourStart) ?? health.claimCadenceMs;
|
|
38848
|
+
const expectedClaims = HOUR_MS / cadenceMs;
|
|
38631
38849
|
claimThroughputHours.push({
|
|
38632
38850
|
hourStart,
|
|
38633
38851
|
claims,
|
|
@@ -38654,7 +38872,7 @@ function summarizeListenerReadHealth(health, readyAt, nowMs) {
|
|
|
38654
38872
|
// src/listener/control.ts
|
|
38655
38873
|
var import_node_crypto19 = require("node:crypto");
|
|
38656
38874
|
var import_node_net = require("node:net");
|
|
38657
|
-
var
|
|
38875
|
+
var import_promises10 = require("node:fs/promises");
|
|
38658
38876
|
var import_node_path16 = require("node:path");
|
|
38659
38877
|
var UUID_RE18 = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
38660
38878
|
var SEMVER_RE2 = /^(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-(?:0|[1-9]\d*|[A-Za-z-][0-9A-Za-z-]*)(?:\.(?:0|[1-9]\d*|[A-Za-z-][0-9A-Za-z-]*))*)?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
|
|
@@ -38741,7 +38959,8 @@ var STATUS_ALLOWED_KEYS = /* @__PURE__ */ new Set([
|
|
|
38741
38959
|
"connectionsOpened",
|
|
38742
38960
|
"connectionReuseRatio",
|
|
38743
38961
|
"activityPublishFailures",
|
|
38744
|
-
"activityLastErrorCode"
|
|
38962
|
+
"activityLastErrorCode",
|
|
38963
|
+
"idlePollMs"
|
|
38745
38964
|
]);
|
|
38746
38965
|
var STATUS_ACTIVITY_ERROR_CODES = /* @__PURE__ */ new Set([
|
|
38747
38966
|
"activity_credential_failed",
|
|
@@ -38825,9 +39044,9 @@ function parseStatus(raw, rejectUnknownKeys = false) {
|
|
|
38825
39044
|
const nullableTimestamp3 = (candidate) => candidate === null || typeof candidate === "string" && Number.isFinite(Date.parse(candidate));
|
|
38826
39045
|
const readHealth = row.readHealth === void 0 ? void 0 : parseListenerReadHealth(row.readHealth, rejectUnknownKeys);
|
|
38827
39046
|
const heldBackDeliveries = row.heldBackDeliveries === void 0 ? void 0 : parseHeldBackDeliveries(row.heldBackDeliveries);
|
|
38828
|
-
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 &&
|
|
39047
|
+
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 && !SECRET_SHAPE_RE.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 && !SECRET_SHAPE_RE.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(
|
|
38829
39048
|
row.activityLastErrorCode
|
|
38830
|
-
))) {
|
|
39049
|
+
)) || !(row.idlePollMs === void 0 || row.idlePollMs === null || typeof row.idlePollMs === "number" && Number.isSafeInteger(row.idlePollMs) && row.idlePollMs >= 0)) {
|
|
38831
39050
|
throw new Error("stored listener status is malformed");
|
|
38832
39051
|
}
|
|
38833
39052
|
const routeMode = row.routeMode ?? "worker";
|
|
@@ -38870,7 +39089,8 @@ function parseStatus(raw, rejectUnknownKeys = false) {
|
|
|
38870
39089
|
deferOverChars,
|
|
38871
39090
|
pendingForMainCount: row.pendingForMainCount ?? 0,
|
|
38872
39091
|
droppedForMainCount: row.droppedForMainCount ?? 0,
|
|
38873
|
-
...readHealth === void 0 ? {} : { readHealth }
|
|
39092
|
+
...readHealth === void 0 ? {} : { readHealth },
|
|
39093
|
+
...row.idlePollMs === void 0 ? {} : { idlePollMs: row.idlePollMs ?? null }
|
|
38874
39094
|
};
|
|
38875
39095
|
}
|
|
38876
39096
|
async function writeListenerStatus(paths, status) {
|
|
@@ -38940,7 +39160,8 @@ async function appendListenerEvent(paths, event) {
|
|
|
38940
39160
|
"dropped_count",
|
|
38941
39161
|
// How long one delivery held the worker seat, and why it gave it back.
|
|
38942
39162
|
"held_ms",
|
|
38943
|
-
"release_reason"
|
|
39163
|
+
"release_reason",
|
|
39164
|
+
"idle_poll_ms"
|
|
38944
39165
|
]);
|
|
38945
39166
|
const deliveryModes = /* @__PURE__ */ new Set(["durable_claim", "cursor_fallback"]);
|
|
38946
39167
|
const routeModes = /* @__PURE__ */ new Set(["worker", "main", "split"]);
|
|
@@ -39005,6 +39226,9 @@ async function appendListenerEvent(paths, event) {
|
|
|
39005
39226
|
if (key2 === "held_ms" && !(typeof value === "number" && Number.isSafeInteger(value) && value >= 0)) {
|
|
39006
39227
|
throw new Error("listener event hold duration is not allowed");
|
|
39007
39228
|
}
|
|
39229
|
+
if (key2 === "idle_poll_ms" && !(typeof value === "number" && Number.isSafeInteger(value) && value >= 0)) {
|
|
39230
|
+
throw new Error("listener event idle poll interval is not allowed");
|
|
39231
|
+
}
|
|
39008
39232
|
if (key2 === "release_reason" && !(typeof value === "string" && LISTENER_DELIVERY_HOLD_RELEASE_REASONS.includes(
|
|
39009
39233
|
value
|
|
39010
39234
|
))) {
|
|
@@ -39019,7 +39243,7 @@ async function appendListenerEvent(paths, event) {
|
|
|
39019
39243
|
if (typeof value === "string" && // worker_stderr_tail is deliberately exempt from the generic 128-char
|
|
39020
39244
|
// cap (its own bound is 2048, above); the secret scan still applies to
|
|
39021
39245
|
// every string, the tail included.
|
|
39022
|
-
(key2 !== "worker_stderr_tail" && value.length > 128 ||
|
|
39246
|
+
(key2 !== "worker_stderr_tail" && value.length > 128 || SECRET_SHAPE_RE.test(value))) {
|
|
39023
39247
|
throw new Error("listener event contains unsafe text");
|
|
39024
39248
|
}
|
|
39025
39249
|
}
|
|
@@ -39039,7 +39263,7 @@ async function appendListenerEvent(paths, event) {
|
|
|
39039
39263
|
throw new Error("listener event is too large");
|
|
39040
39264
|
}
|
|
39041
39265
|
try {
|
|
39042
|
-
const info = await (0,
|
|
39266
|
+
const info = await (0, import_promises10.lstat)(paths.logPath);
|
|
39043
39267
|
if (!info.isFile() || info.isSymbolicLink() || (info.mode & 511) !== 384) {
|
|
39044
39268
|
throw new Error("listener event log is not a secure regular file");
|
|
39045
39269
|
}
|
|
@@ -39049,14 +39273,14 @@ async function appendListenerEvent(paths, event) {
|
|
|
39049
39273
|
} catch (error) {
|
|
39050
39274
|
if (error.code !== "ENOENT") throw error;
|
|
39051
39275
|
}
|
|
39052
|
-
const handle = await (0,
|
|
39276
|
+
const handle = await (0, import_promises10.open)(paths.logPath, "a", 384);
|
|
39053
39277
|
try {
|
|
39054
39278
|
await handle.writeFile(serialized, "utf8");
|
|
39055
39279
|
await handle.sync();
|
|
39056
39280
|
} finally {
|
|
39057
39281
|
await handle.close();
|
|
39058
39282
|
}
|
|
39059
|
-
await (0,
|
|
39283
|
+
await (0, import_promises10.chmod)(paths.logPath, 384);
|
|
39060
39284
|
}
|
|
39061
39285
|
function parseControlRequest(raw) {
|
|
39062
39286
|
let value;
|
|
@@ -39091,7 +39315,7 @@ async function startupLock(paths) {
|
|
|
39091
39315
|
while (Date.now() < deadline) {
|
|
39092
39316
|
let handle;
|
|
39093
39317
|
try {
|
|
39094
|
-
handle = await (0,
|
|
39318
|
+
handle = await (0, import_promises10.open)(lockPath, "wx", 384);
|
|
39095
39319
|
} catch (error) {
|
|
39096
39320
|
if (error.code !== "EEXIST") throw error;
|
|
39097
39321
|
try {
|
|
@@ -39100,9 +39324,9 @@ async function startupLock(paths) {
|
|
|
39100
39324
|
} catch (queryError) {
|
|
39101
39325
|
if (queryError instanceof ListenerAlreadyRunningError) throw queryError;
|
|
39102
39326
|
}
|
|
39103
|
-
const info = await (0,
|
|
39327
|
+
const info = await (0, import_promises10.lstat)(lockPath).catch(() => null);
|
|
39104
39328
|
if (info && Date.now() - info.mtimeMs >= START_LOCK_STALE_MS) {
|
|
39105
|
-
await (0,
|
|
39329
|
+
await (0, import_promises10.unlink)(lockPath).catch(() => void 0);
|
|
39106
39330
|
continue;
|
|
39107
39331
|
}
|
|
39108
39332
|
await new Promise((resolve3) => setTimeout(resolve3, 25));
|
|
@@ -39114,12 +39338,12 @@ async function startupLock(paths) {
|
|
|
39114
39338
|
await handle.sync();
|
|
39115
39339
|
} catch (error) {
|
|
39116
39340
|
await handle.close().catch(() => void 0);
|
|
39117
|
-
await (0,
|
|
39341
|
+
await (0, import_promises10.unlink)(lockPath).catch(() => void 0);
|
|
39118
39342
|
throw error;
|
|
39119
39343
|
}
|
|
39120
39344
|
return async () => {
|
|
39121
39345
|
await handle.close().catch(() => void 0);
|
|
39122
|
-
await (0,
|
|
39346
|
+
await (0, import_promises10.unlink)(lockPath).catch(() => void 0);
|
|
39123
39347
|
};
|
|
39124
39348
|
}
|
|
39125
39349
|
throw new ListenerAlreadyRunningError();
|
|
@@ -39136,7 +39360,7 @@ async function prepareSocket(paths) {
|
|
|
39136
39360
|
} catch (error) {
|
|
39137
39361
|
if (error instanceof ListenerAlreadyRunningError) throw error;
|
|
39138
39362
|
if (process.platform !== "win32") {
|
|
39139
|
-
await (0,
|
|
39363
|
+
await (0, import_promises10.unlink)(paths.socketPath).catch((unlinkError) => {
|
|
39140
39364
|
if (unlinkError.code !== "ENOENT") {
|
|
39141
39365
|
throw unlinkError;
|
|
39142
39366
|
}
|
|
@@ -39193,13 +39417,13 @@ async function startListenerControlServer(options) {
|
|
|
39193
39417
|
server.listen(options.paths.socketPath);
|
|
39194
39418
|
});
|
|
39195
39419
|
if (process.platform !== "win32") {
|
|
39196
|
-
await (0,
|
|
39420
|
+
await (0, import_promises10.chmod)(options.paths.socketPath, 384);
|
|
39197
39421
|
}
|
|
39198
39422
|
} catch (error) {
|
|
39199
39423
|
if (server.listening) {
|
|
39200
39424
|
await new Promise((resolve3) => server.close(() => resolve3()));
|
|
39201
39425
|
if (process.platform !== "win32") {
|
|
39202
|
-
await (0,
|
|
39426
|
+
await (0, import_promises10.unlink)(options.paths.socketPath).catch(() => void 0);
|
|
39203
39427
|
}
|
|
39204
39428
|
}
|
|
39205
39429
|
throw error;
|
|
@@ -39210,7 +39434,7 @@ async function startListenerControlServer(options) {
|
|
|
39210
39434
|
close: async () => {
|
|
39211
39435
|
await new Promise((resolve3) => server.close(() => resolve3()));
|
|
39212
39436
|
if (process.platform !== "win32") {
|
|
39213
|
-
await (0,
|
|
39437
|
+
await (0, import_promises10.unlink)(options.paths.socketPath).catch(() => void 0);
|
|
39214
39438
|
}
|
|
39215
39439
|
}
|
|
39216
39440
|
};
|
|
@@ -39307,7 +39531,7 @@ function safeErrorCode(error) {
|
|
|
39307
39531
|
}
|
|
39308
39532
|
function localDiagnostic(message, maxChars) {
|
|
39309
39533
|
const redacted = message.replace(
|
|
39310
|
-
|
|
39534
|
+
new RegExp(SECRET_SHAPE_RE.source, "gi"),
|
|
39311
39535
|
"[redacted]"
|
|
39312
39536
|
).trim();
|
|
39313
39537
|
if (redacted.length === 0) return null;
|
|
@@ -39415,6 +39639,7 @@ async function runListenerSupervisor(options) {
|
|
|
39415
39639
|
connectionReuseRatio: 0,
|
|
39416
39640
|
activityPublishFailures: 0,
|
|
39417
39641
|
activityLastErrorCode: null,
|
|
39642
|
+
idlePollMs: null,
|
|
39418
39643
|
logPath: options.paths.logPath
|
|
39419
39644
|
};
|
|
39420
39645
|
let writes = Promise.resolve();
|
|
@@ -39488,6 +39713,25 @@ async function runListenerSupervisor(options) {
|
|
|
39488
39713
|
return fitted.length > 0 ? fitted : null;
|
|
39489
39714
|
};
|
|
39490
39715
|
const onEvent = (event) => {
|
|
39716
|
+
if (event.type === "idle_poll") {
|
|
39717
|
+
status = {
|
|
39718
|
+
...status,
|
|
39719
|
+
idlePollMs: event.intervalMs,
|
|
39720
|
+
readHealth: recordListenerClaimCadence(
|
|
39721
|
+
status.readHealth ?? emptyListenerReadHealth(),
|
|
39722
|
+
event.intervalMs > 0 ? event.intervalMs : 1,
|
|
39723
|
+
event.ts
|
|
39724
|
+
),
|
|
39725
|
+
updatedAt: event.ts
|
|
39726
|
+
};
|
|
39727
|
+
persist();
|
|
39728
|
+
log({
|
|
39729
|
+
ts: event.ts,
|
|
39730
|
+
event: "listener_idle_poll",
|
|
39731
|
+
idle_poll_ms: event.intervalMs
|
|
39732
|
+
});
|
|
39733
|
+
return;
|
|
39734
|
+
}
|
|
39491
39735
|
if (event.type === "ready") {
|
|
39492
39736
|
const versionNotice = options.getProviderVersionNotice?.() ?? null;
|
|
39493
39737
|
transition("ready", {
|
|
@@ -39512,7 +39756,8 @@ async function runListenerSupervisor(options) {
|
|
|
39512
39756
|
...event.cadenceMs === void 0 ? {} : {
|
|
39513
39757
|
readHealth: recordListenerClaimCadence(
|
|
39514
39758
|
status.readHealth ?? emptyListenerReadHealth(),
|
|
39515
|
-
event.cadenceMs
|
|
39759
|
+
event.cadenceMs,
|
|
39760
|
+
event.ts
|
|
39516
39761
|
)
|
|
39517
39762
|
}
|
|
39518
39763
|
});
|
|
@@ -40785,6 +41030,7 @@ function buildListenerChildArgs(spec) {
|
|
|
40785
41030
|
...spec.model ? ["--model", spec.model] : [],
|
|
40786
41031
|
...provider === "grok" && spec.effort ? ["--effort", spec.effort] : [],
|
|
40787
41032
|
...spec.turnBudget ? ["--turn-budget", spec.turnBudget] : [],
|
|
41033
|
+
...spec.pollInterval ? ["--poll-interval", spec.pollInterval] : [],
|
|
40788
41034
|
...spec.route && spec.route !== "worker" ? ["--route", spec.route] : [],
|
|
40789
41035
|
...spec.deferOver !== void 0 ? ["--defer-over", String(spec.deferOver)] : []
|
|
40790
41036
|
];
|
|
@@ -40820,7 +41066,7 @@ async function spawnDetachedListener(options) {
|
|
|
40820
41066
|
}
|
|
40821
41067
|
|
|
40822
41068
|
// src/listener/hook.ts
|
|
40823
|
-
var
|
|
41069
|
+
var import_promises11 = require("node:fs/promises");
|
|
40824
41070
|
var import_node_path20 = require("node:path");
|
|
40825
41071
|
|
|
40826
41072
|
// src/listener/brain-digest.ts
|
|
@@ -41218,7 +41464,7 @@ async function listenerIsLive(context) {
|
|
|
41218
41464
|
async function discoverStoredStatusContexts(stateDirectory2) {
|
|
41219
41465
|
let entries;
|
|
41220
41466
|
try {
|
|
41221
|
-
entries = await (0,
|
|
41467
|
+
entries = await (0, import_promises11.readdir)(stateDirectory2, { withFileTypes: true });
|
|
41222
41468
|
} catch (error) {
|
|
41223
41469
|
if (error.code === "ENOENT") return [];
|
|
41224
41470
|
throw error;
|
|
@@ -41618,7 +41864,7 @@ async function runListenerHookCheck(options = {}) {
|
|
|
41618
41864
|
}
|
|
41619
41865
|
|
|
41620
41866
|
// src/listener/attendance-canary.ts
|
|
41621
|
-
var
|
|
41867
|
+
var import_promises12 = require("node:fs/promises");
|
|
41622
41868
|
var LOG_TAIL_BYTES = 256 * 1024;
|
|
41623
41869
|
function agentReceipt(receipts, principalId) {
|
|
41624
41870
|
for (const receipt of receipts) {
|
|
@@ -41631,7 +41877,7 @@ function agentReceipt(receipts, principalId) {
|
|
|
41631
41877
|
async function readLogTail(path) {
|
|
41632
41878
|
let handle;
|
|
41633
41879
|
try {
|
|
41634
|
-
handle = await (0,
|
|
41880
|
+
handle = await (0, import_promises12.open)(path, "r");
|
|
41635
41881
|
} catch (error) {
|
|
41636
41882
|
if (error.code === "ENOENT") return "";
|
|
41637
41883
|
throw error;
|
|
@@ -42735,6 +42981,7 @@ var KNOWN_FLAGS = /* @__PURE__ */ new Set([
|
|
|
42735
42981
|
"slug",
|
|
42736
42982
|
"state-dir",
|
|
42737
42983
|
"thread",
|
|
42984
|
+
"poll-interval",
|
|
42738
42985
|
"renewal-horizon-days",
|
|
42739
42986
|
"standing",
|
|
42740
42987
|
"task-id",
|
|
@@ -42781,8 +43028,8 @@ var BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
|
|
|
42781
43028
|
]);
|
|
42782
43029
|
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;
|
|
42783
43030
|
function packageVersion() {
|
|
42784
|
-
if ("0.1.
|
|
42785
|
-
return "0.1.
|
|
43031
|
+
if ("0.1.57".length > 0) {
|
|
43032
|
+
return "0.1.57";
|
|
42786
43033
|
}
|
|
42787
43034
|
try {
|
|
42788
43035
|
const value = JSON.parse(
|
|
@@ -42923,7 +43170,7 @@ Usage:
|
|
|
42923
43170
|
cswarm brain get <topic>[@<version>] [--version <n>] [--url <url> --anon-key <key>] [--workspace-id <uuid>] ${agentCredential2} [--json]
|
|
42924
43171
|
cswarm brain put <topic> [<markdown-path>] [--url <url> --anon-key <key>] [--workspace-id <uuid>] ${agentCredential2} [--if-version <n>] [--json] # without a path, reads Markdown from stdin; --if-version refuses the write unless the live version is still <n>
|
|
42925
43172
|
cswarm feedback "<text>" --kind bug|idea|friction [--about <ref>] [--url <url> --anon-key <key>] [--workspace-id <uuid>] ${agentCredential2} [--json]
|
|
42926
|
-
cswarm listen start ${requiredAgentCredential} [--url <url> --anon-key <key>] --workspace-id <uuid> --provider grok|opencode|claude|codex [--cwd <absolute-path>] [--model <model>] [--effort <level>] [--permissions deny|allow] [--grok-executable <path>] [--opencode-executable <path>] [--claude-executable <path>] [--codex-executable <path>] [--turn-budget <duration>] [--route worker|main|split] [--defer-over <chars>] [--allow-unattended] [--foreground] [--json]
|
|
43173
|
+
cswarm listen start ${requiredAgentCredential} [--url <url> --anon-key <key>] --workspace-id <uuid> --provider grok|opencode|claude|codex [--cwd <absolute-path>] [--model <model>] [--effort <level>] [--permissions deny|allow] [--grok-executable <path>] [--opencode-executable <path>] [--claude-executable <path>] [--codex-executable <path>] [--turn-budget <duration>] [--poll-interval <duration>] [--route worker|main|split] [--defer-over <chars>] [--allow-unattended] [--foreground] [--json]
|
|
42927
43174
|
cswarm listen canary ${requiredAgentCredential} [--url <url> --anon-key <key>] --workspace-id <uuid> [--state-dir <path>] [--wait <seconds>] [--json]
|
|
42928
43175
|
cswarm listen status ${agentCredential2} [--url <url> --anon-key <key>] --workspace-id <uuid> [--principal-id <uuid>] [--json]
|
|
42929
43176
|
cswarm listen stop ${agentCredential2} [--url <url> --anon-key <key>] --workspace-id <uuid> [--principal-id <uuid>] [--json]
|
|
@@ -43013,6 +43260,8 @@ Place -- before signal text that itself begins with -- to stop option parsing.
|
|
|
43013
43260
|
Signal text is at most 8000 characters and --about at most 500; a longer body is
|
|
43014
43261
|
refused locally before any network call, so compose within the limit.
|
|
43015
43262
|
|
|
43263
|
+
${idlePollHelpSentence()}
|
|
43264
|
+
|
|
43016
43265
|
listen start --turn-budget bounds ONE worker prompt turn (default 10m): how long
|
|
43017
43266
|
the worker may think and use tools on a single message before the turn times out
|
|
43018
43267
|
and durable delivery retries it. A whole number plus s, m, or h (for example
|
|
@@ -43251,7 +43500,7 @@ async function stdinInviteLink() {
|
|
|
43251
43500
|
return link;
|
|
43252
43501
|
}
|
|
43253
43502
|
async function confirmationLine(prompt) {
|
|
43254
|
-
const reader = (0,
|
|
43503
|
+
const reader = (0, import_promises14.createInterface)({
|
|
43255
43504
|
input: process.stdin,
|
|
43256
43505
|
output: process.stderr,
|
|
43257
43506
|
terminal: Boolean(process.stdin.isTTY)
|
|
@@ -44555,6 +44804,9 @@ function listenerTurnBudgetMs(value) {
|
|
|
44555
44804
|
}
|
|
44556
44805
|
return milliseconds;
|
|
44557
44806
|
}
|
|
44807
|
+
function listenerPollIntervalMs(value) {
|
|
44808
|
+
return parseIdlePollIntervalMs(value);
|
|
44809
|
+
}
|
|
44558
44810
|
function listenerRouteConfiguration(routeValue, deferOverValue) {
|
|
44559
44811
|
const routeMode = routeValue ?? "worker";
|
|
44560
44812
|
if (routeMode !== "worker" && routeMode !== "main" && routeMode !== "split") {
|
|
@@ -45535,6 +45787,12 @@ async function runInboxNotifyCommand(args) {
|
|
|
45535
45787
|
const stop = () => controller.abort();
|
|
45536
45788
|
process.on("SIGINT", stop);
|
|
45537
45789
|
process.on("SIGTERM", stop);
|
|
45790
|
+
const lockPath = arrivalWatchLockPath(
|
|
45791
|
+
cloud,
|
|
45792
|
+
selected.selectedWorkspace,
|
|
45793
|
+
principalId
|
|
45794
|
+
);
|
|
45795
|
+
await acquireArrivalWatchLock(lockPath);
|
|
45538
45796
|
try {
|
|
45539
45797
|
const retryNotices = createArrivalRetryNoticePolicy();
|
|
45540
45798
|
let renderedBearer = selected.bearer;
|
|
@@ -45608,6 +45866,7 @@ async function runInboxNotifyCommand(args) {
|
|
|
45608
45866
|
process.off("SIGINT", stop);
|
|
45609
45867
|
process.off("SIGTERM", stop);
|
|
45610
45868
|
httpClient.close();
|
|
45869
|
+
await releaseArrivalWatchLock(lockPath);
|
|
45611
45870
|
}
|
|
45612
45871
|
}
|
|
45613
45872
|
async function runReceipt(args) {
|
|
@@ -46107,6 +46366,8 @@ function listenerStatusJson(status, permissionMode, evidence = {
|
|
|
46107
46366
|
readRetriesLastHour: readSummary.retriesLastHour,
|
|
46108
46367
|
readRetryHours: readSummary.retryHours,
|
|
46109
46368
|
claimCadenceMs: readHealth.claimCadenceMs,
|
|
46369
|
+
idlePollMs: status.idlePollMs ?? null,
|
|
46370
|
+
idlePollSentence: status.idlePollMs === void 0 || status.idlePollMs === null ? null : idlePollStatusSentence(status.idlePollMs),
|
|
46110
46371
|
claimThroughputHours: readSummary.claimThroughputHours,
|
|
46111
46372
|
listenerLapse: lapseNotices.length > 0,
|
|
46112
46373
|
listenerLapseCodes: lapseNotices.map((notice) => notice.code),
|
|
@@ -46177,7 +46438,8 @@ function renderListenerStatus(status, evidence = {
|
|
|
46177
46438
|
`Read retry episodes in the last 24h: ${readSummary.episodesLast24h}; retries in the rolling hour: ${readSummary.retriesLastHour}.`,
|
|
46178
46439
|
readSummary.longestEpisodeAttemptsLast24h === 0 ? "Longest read retry episode in the last 24h: none recorded." : `Longest read retry episode in the last 24h: ${readSummary.longestEpisodeAttemptsLast24h} attempts over ${Math.floor(readSummary.longestEpisodeDurationMsLast24h / 1e3)}s.`,
|
|
46179
46440
|
readSummary.retryHours.length === 0 ? "Read retries by hour in the last 24h: none." : `Read retries by hour in the last 24h: ${readSummary.retryHours.map((hour) => `${hour.hourStart}=${hour.retries}`).join("; ")}.`,
|
|
46180
|
-
readSummary.claimThroughputHours.length === 0 ? "Claim throughput by full hour: no complete listener hour is available yet." : `Claim throughput by full hour: ${readSummary.claimThroughputHours.map((hour) => `${hour.hourStart} ${hour.claims}/${Math.round(hour.expectedClaims)} (${hour.ratio.toFixed(3)})`).join("; ")}
|
|
46441
|
+
readSummary.claimThroughputHours.length === 0 ? "Claim throughput by full hour: no complete listener hour is available yet." : `Claim throughput by full hour: ${readSummary.claimThroughputHours.map((hour) => `${hour.hourStart} ${hour.claims}/${Math.round(hour.expectedClaims)} (${hour.ratio.toFixed(3)})`).join("; ")}.`,
|
|
46442
|
+
status.idlePollMs === void 0 || status.idlePollMs === null ? "Current idle poll interval has not been reported yet." : idlePollStatusSentence(status.idlePollMs)
|
|
46181
46443
|
];
|
|
46182
46444
|
for (const notice of lapseNotices) {
|
|
46183
46445
|
lines.push(`WARNING [${notice.code}]: ${notice.message}`);
|
|
@@ -46811,6 +47073,7 @@ async function runConfiguredListener(options) {
|
|
|
46811
47073
|
/* One delivery may hold the seat for one turn budget, not for the
|
|
46812
47074
|
whole 15-minute lease. Same lever, so the two cannot drift. */
|
|
46813
47075
|
deliveryHoldBudgetMs: turnBudgetMs,
|
|
47076
|
+
...options.pollMs === void 0 ? {} : { pollMs: options.pollMs },
|
|
46814
47077
|
pendingMainQueue,
|
|
46815
47078
|
fetcher: httpClient.fetch
|
|
46816
47079
|
});
|
|
@@ -46841,6 +47104,7 @@ async function runListenStart(args) {
|
|
|
46841
47104
|
"codex-executable",
|
|
46842
47105
|
"state-dir",
|
|
46843
47106
|
"turn-budget",
|
|
47107
|
+
"poll-interval",
|
|
46844
47108
|
"route",
|
|
46845
47109
|
"defer-over",
|
|
46846
47110
|
"allow-unattended",
|
|
@@ -46855,6 +47119,7 @@ async function runListenStart(args) {
|
|
|
46855
47119
|
const provider = listenerProvider(args);
|
|
46856
47120
|
validateListenerProviderFlags(args, provider);
|
|
46857
47121
|
const turnBudgetMs = listenerTurnBudgetMs(args.optional("turn-budget"));
|
|
47122
|
+
const pollMs = listenerPollIntervalMs(args.optional("poll-interval"));
|
|
46858
47123
|
const routing = listenerRouteConfiguration(
|
|
46859
47124
|
args.optional("route"),
|
|
46860
47125
|
args.optional("defer-over")
|
|
@@ -46897,6 +47162,7 @@ async function runListenStart(args) {
|
|
|
46897
47162
|
permissionMode,
|
|
46898
47163
|
provider,
|
|
46899
47164
|
turnBudgetMs,
|
|
47165
|
+
pollMs,
|
|
46900
47166
|
...routing,
|
|
46901
47167
|
...args.optional("model") ? { model: args.required("model") } : {},
|
|
46902
47168
|
...args.optional("effort") ? { effort: args.required("effort") } : {},
|
|
@@ -46951,6 +47217,7 @@ async function runListenStart(args) {
|
|
|
46951
47217
|
...args.optional("model") ? { model: args.required("model") } : {},
|
|
46952
47218
|
...args.optional("effort") ? { effort: args.required("effort") } : {},
|
|
46953
47219
|
...args.optional("turn-budget") ? { turnBudget: args.required("turn-budget") } : {},
|
|
47220
|
+
...args.optional("poll-interval") ? { pollInterval: args.required("poll-interval") } : {},
|
|
46954
47221
|
...args.optional("grok-executable") ? { executable: args.required("grok-executable") } : {},
|
|
46955
47222
|
...opencodeExecutable ? { opencodeExecutable } : {},
|
|
46956
47223
|
...claudeExecutable ? { claudeExecutable } : {},
|
|
@@ -47059,12 +47326,14 @@ async function runListenSupervisor(args) {
|
|
|
47059
47326
|
"codex-executable",
|
|
47060
47327
|
"state-dir",
|
|
47061
47328
|
"turn-budget",
|
|
47329
|
+
"poll-interval",
|
|
47062
47330
|
"route",
|
|
47063
47331
|
"defer-over"
|
|
47064
47332
|
], 1);
|
|
47065
47333
|
const provider = listenerProvider(args);
|
|
47066
47334
|
validateListenerProviderFlags(args, provider);
|
|
47067
47335
|
const turnBudgetMs = listenerTurnBudgetMs(args.optional("turn-budget"));
|
|
47336
|
+
const pollMs = listenerPollIntervalMs(args.optional("poll-interval"));
|
|
47068
47337
|
const routing = listenerRouteConfiguration(
|
|
47069
47338
|
args.optional("route"),
|
|
47070
47339
|
args.optional("defer-over")
|
|
@@ -47085,6 +47354,7 @@ async function runListenSupervisor(args) {
|
|
|
47085
47354
|
permissionMode: listenerPermissionMode(args.optional("permissions")),
|
|
47086
47355
|
provider,
|
|
47087
47356
|
turnBudgetMs,
|
|
47357
|
+
pollMs,
|
|
47088
47358
|
...routing,
|
|
47089
47359
|
...args.optional("model") ? { model: args.required("model") } : {},
|
|
47090
47360
|
...args.optional("effort") ? { effort: args.required("effort") } : {},
|
|
@@ -48337,7 +48607,7 @@ async function runSeed(args) {
|
|
|
48337
48607
|
if (!tokenOut || !(0, import_node_path21.isAbsolute)(tokenOut)) {
|
|
48338
48608
|
throw new Error("SEED_TOKEN_OUT must be an absolute path");
|
|
48339
48609
|
}
|
|
48340
|
-
const tokenFile = await (0,
|
|
48610
|
+
const tokenFile = await (0, import_promises13.open)(tokenOut, "wx", 384).catch((error) => {
|
|
48341
48611
|
if (error.code === "EEXIST") {
|
|
48342
48612
|
throw new Error("SEED_TOKEN_OUT already exists; refusing to overwrite it");
|
|
48343
48613
|
}
|
|
@@ -48376,7 +48646,7 @@ async function runSeed(args) {
|
|
|
48376
48646
|
tokenWritten = true;
|
|
48377
48647
|
}
|
|
48378
48648
|
await tokenFile.close();
|
|
48379
|
-
if (!tokenWritten) await (0,
|
|
48649
|
+
if (!tokenWritten) await (0, import_promises13.unlink)(tokenOut);
|
|
48380
48650
|
process.stdout.write(`${JSON.stringify({
|
|
48381
48651
|
userId: result.userId,
|
|
48382
48652
|
membershipRole: result.membershipRole,
|
|
@@ -48389,7 +48659,7 @@ async function runSeed(args) {
|
|
|
48389
48659
|
`);
|
|
48390
48660
|
} catch (error) {
|
|
48391
48661
|
await tokenFile.close().catch(() => void 0);
|
|
48392
|
-
if (!tokenWritten) await (0,
|
|
48662
|
+
if (!tokenWritten) await (0, import_promises13.unlink)(tokenOut).catch(() => void 0);
|
|
48393
48663
|
throw error;
|
|
48394
48664
|
}
|
|
48395
48665
|
}
|
|
@@ -48653,6 +48923,7 @@ ${usage()}
|
|
|
48653
48923
|
listenerFailureMessage,
|
|
48654
48924
|
listenerHostLimits,
|
|
48655
48925
|
listenerPermissionMode,
|
|
48926
|
+
listenerPollIntervalMs,
|
|
48656
48927
|
listenerProviderInstallEvidence,
|
|
48657
48928
|
listenerRouteConfiguration,
|
|
48658
48929
|
listenerStatusJson,
|