switchroom 0.19.30 → 0.19.32
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli/switchroom.js +1121 -584
- package/dist/host-control/main.js +151 -73
- package/package.json +1 -1
- package/profiles/_base/cron-session.sh.hbs +5 -1
- package/profiles/_base/start.sh.hbs +15 -1
- package/telegram-plugin/dist/bridge/bridge.js +3 -0
- package/telegram-plugin/dist/gateway/gateway.js +1660 -677
- package/telegram-plugin/dist/server.js +3 -0
- package/telegram-plugin/edit-flood-fuse.ts +70 -20
- package/telegram-plugin/gateway/boot-beacon.ts +364 -0
- package/telegram-plugin/gateway/boot-sweep-gate.ts +20 -15
- package/telegram-plugin/gateway/gateway.ts +87 -88
- package/telegram-plugin/gateway/inbound-spool.ts +39 -0
- package/telegram-plugin/gateway/narrative-lane.ts +12 -0
- package/telegram-plugin/gateway/obligation-store.ts +28 -0
- package/telegram-plugin/gateway/stale-pin-sweep-store.ts +221 -0
- package/telegram-plugin/gateway/stale-pin-sweep-wiring.ts +211 -0
- package/telegram-plugin/gateway/stale-pin-sweep.test.ts +804 -0
- package/telegram-plugin/gateway/stale-pin-sweep.ts +1146 -0
- package/telegram-plugin/gateway/status-pin-retarget.ts +15 -2
- package/telegram-plugin/gateway/status-pin-store.ts +33 -11
- package/telegram-plugin/gateway/stream-render.ts +578 -321
- package/telegram-plugin/registry/turns-schema.ts +21 -1
- package/telegram-plugin/retry-api-call.ts +46 -21
- package/telegram-plugin/session-tail.ts +13 -0
- package/telegram-plugin/shared/bot-runtime.ts +61 -17
- package/telegram-plugin/shared/gw-trace-gate.ts +18 -2
- package/telegram-plugin/tests/activity-card-wiring.test.ts +7 -7
- package/telegram-plugin/tests/activity-drain-fuse-drop-not-failure.test.ts +324 -0
- package/telegram-plugin/tests/agent-card-result-footer.test.ts +193 -0
- package/telegram-plugin/tests/boot-beacon.test.ts +462 -0
- package/telegram-plugin/tests/boot-pin-sweep-wiring.test.ts +6 -6
- package/telegram-plugin/tests/boot-sweep-gate.test.ts +42 -31
- package/telegram-plugin/tests/inbound-delivery-machine-dispatch.test.ts +2 -0
- package/telegram-plugin/tests/inbound-spool-progress.test.ts +2 -0
- package/telegram-plugin/tests/inbound-spool.test.ts +134 -5
- package/telegram-plugin/tests/narrative-lane-golden.test.ts +28 -0
- package/telegram-plugin/tests/obligation-determinism.test.ts +2 -0
- package/telegram-plugin/tests/obligation-store.test.ts +67 -1
- package/telegram-plugin/tests/status-pin-boot-recovery.test.ts +3 -3
- package/telegram-plugin/tests/status-pin-store.test.ts +26 -5
- package/telegram-plugin/tests/stream-render-golden.test.ts +20 -5
- package/telegram-plugin/tests/tg-post-logger-error-shape.test.ts +161 -0
- package/telegram-plugin/tests/turn-mint-defers-until-dequeue.test.ts +196 -0
- package/telegram-plugin/tests/turn-mint-harness.ts +155 -0
- package/telegram-plugin/tests/turn-supersede-finalizes-prior-card.test.ts +124 -0
- package/telegram-plugin/tests/worker-feed-pin-persistence.test.ts +30 -0
- package/telegram-plugin/tool-activity-summary.ts +104 -38
- package/telegram-plugin/worker-activity-feed.ts +33 -16
- package/telegram-plugin/gateway/dm-pin-sweep.test.ts +0 -251
- package/telegram-plugin/gateway/dm-pin-sweep.ts +0 -178
|
@@ -13658,7 +13658,7 @@ import {
|
|
|
13658
13658
|
mkdirSync as mkdirSync6,
|
|
13659
13659
|
chmodSync as chmodSync2,
|
|
13660
13660
|
unlinkSync as unlinkSync3,
|
|
13661
|
-
renameSync as
|
|
13661
|
+
renameSync as renameSync6
|
|
13662
13662
|
} from "node:fs";
|
|
13663
13663
|
import { dirname as dirname5, join as join5 } from "node:path";
|
|
13664
13664
|
function floodStatePath(stateDir) {
|
|
@@ -23318,17 +23318,17 @@ var init_loader = __esm(() => {
|
|
|
23318
23318
|
var init_flock = () => {};
|
|
23319
23319
|
|
|
23320
23320
|
// ../src/vault/vault.ts
|
|
23321
|
-
import { randomBytes as
|
|
23321
|
+
import { randomBytes as randomBytes4, scryptSync, createCipheriv, createDecipheriv } from "node:crypto";
|
|
23322
23322
|
import {
|
|
23323
23323
|
readFileSync as readFileSync8,
|
|
23324
|
-
writeSync,
|
|
23324
|
+
writeSync as writeSync2,
|
|
23325
23325
|
existsSync as existsSync7,
|
|
23326
|
-
renameSync as
|
|
23326
|
+
renameSync as renameSync7,
|
|
23327
23327
|
mkdirSync as mkdirSync9,
|
|
23328
23328
|
unlinkSync as unlinkSync5,
|
|
23329
|
-
fsyncSync,
|
|
23330
|
-
openSync,
|
|
23331
|
-
closeSync,
|
|
23329
|
+
fsyncSync as fsyncSync2,
|
|
23330
|
+
openSync as openSync2,
|
|
23331
|
+
closeSync as closeSync2,
|
|
23332
23332
|
lstatSync,
|
|
23333
23333
|
realpathSync
|
|
23334
23334
|
} from "node:fs";
|
|
@@ -23414,13 +23414,13 @@ var init_vault = __esm(() => {
|
|
|
23414
23414
|
// ../src/vault/resolver.ts
|
|
23415
23415
|
import {
|
|
23416
23416
|
chmodSync as chmodSync4,
|
|
23417
|
-
closeSync as
|
|
23417
|
+
closeSync as closeSync3,
|
|
23418
23418
|
mkdirSync as mkdirSync10,
|
|
23419
23419
|
mkdtempSync,
|
|
23420
|
-
openSync as
|
|
23421
|
-
rmSync,
|
|
23420
|
+
openSync as openSync3,
|
|
23421
|
+
rmSync as rmSync2,
|
|
23422
23422
|
statSync as statSync6,
|
|
23423
|
-
writeSync as
|
|
23423
|
+
writeSync as writeSync3
|
|
23424
23424
|
} from "node:fs";
|
|
23425
23425
|
import { join as join8 } from "node:path";
|
|
23426
23426
|
import { tmpdir } from "node:os";
|
|
@@ -23448,13 +23448,13 @@ function registerCleanupHook() {
|
|
|
23448
23448
|
const cleanup = () => {
|
|
23449
23449
|
for (const dir of materializedDirs) {
|
|
23450
23450
|
try {
|
|
23451
|
-
|
|
23451
|
+
rmSync2(dir, { recursive: true, force: true });
|
|
23452
23452
|
} catch {}
|
|
23453
23453
|
}
|
|
23454
23454
|
materializedDirs.clear();
|
|
23455
23455
|
if (cachedRoot) {
|
|
23456
23456
|
try {
|
|
23457
|
-
|
|
23457
|
+
rmSync2(cachedRoot, { recursive: true, force: true });
|
|
23458
23458
|
} catch {}
|
|
23459
23459
|
cachedRoot = null;
|
|
23460
23460
|
}
|
|
@@ -23485,18 +23485,18 @@ function materializationRoot() {
|
|
|
23485
23485
|
}
|
|
23486
23486
|
function writeFileExclusive(filePath, content) {
|
|
23487
23487
|
const buf = typeof content === "string" ? Buffer.from(content, "utf8") : content;
|
|
23488
|
-
const fd =
|
|
23488
|
+
const fd = openSync3(filePath, fsConstants.O_WRONLY | fsConstants.O_CREAT | fsConstants.O_EXCL, 384);
|
|
23489
23489
|
try {
|
|
23490
|
-
|
|
23490
|
+
writeSync3(fd, buf);
|
|
23491
23491
|
} finally {
|
|
23492
|
-
|
|
23492
|
+
closeSync3(fd);
|
|
23493
23493
|
}
|
|
23494
23494
|
}
|
|
23495
23495
|
function materializeFilesEntry(key, files) {
|
|
23496
23496
|
const dir = join8(materializationRoot(), key);
|
|
23497
23497
|
if (materializedDirs.has(dir)) {
|
|
23498
23498
|
try {
|
|
23499
|
-
|
|
23499
|
+
rmSync2(dir, { recursive: true, force: true });
|
|
23500
23500
|
} catch {}
|
|
23501
23501
|
}
|
|
23502
23502
|
mkdirSync10(dir, { recursive: true, mode: 448 });
|
|
@@ -23637,21 +23637,21 @@ var init_resolver = __esm(() => {
|
|
|
23637
23637
|
});
|
|
23638
23638
|
|
|
23639
23639
|
// ../src/util/atomic.ts
|
|
23640
|
-
import { randomBytes as
|
|
23641
|
-
import { closeSync as
|
|
23642
|
-
function
|
|
23640
|
+
import { randomBytes as randomBytes5 } from "node:crypto";
|
|
23641
|
+
import { closeSync as closeSync4, constants as constants2, fchmodSync as fchmodSync2, fchownSync as fchownSync2, fsyncSync as fsyncSync3, openSync as openSync4, renameSync as renameSync8, rmSync as rmSync3, writeSync as writeSync4 } from "node:fs";
|
|
23642
|
+
function atomicWriteFileSync2(destPath, contents, modeOrOpts = 384) {
|
|
23643
23643
|
const opts = typeof modeOrOpts === "number" ? { mode: modeOrOpts } : modeOrOpts;
|
|
23644
23644
|
const mode = opts.mode ?? 384;
|
|
23645
|
-
const tmp = `${destPath}.tmp-${process.pid}-${
|
|
23645
|
+
const tmp = `${destPath}.tmp-${process.pid}-${randomBytes5(4).toString("hex")}`;
|
|
23646
23646
|
const buf = typeof contents === "string" ? Buffer.from(contents, "utf-8") : contents;
|
|
23647
23647
|
let fd = null;
|
|
23648
23648
|
try {
|
|
23649
|
-
fd =
|
|
23650
|
-
|
|
23651
|
-
|
|
23649
|
+
fd = openSync4(tmp, TMP_OPEN_FLAGS2, mode);
|
|
23650
|
+
writeSync4(fd, buf, 0, buf.length, 0);
|
|
23651
|
+
fchmodSync2(fd, mode);
|
|
23652
23652
|
if (opts.uid !== undefined) {
|
|
23653
23653
|
try {
|
|
23654
|
-
|
|
23654
|
+
fchownSync2(fd, opts.uid, opts.gid ?? opts.uid);
|
|
23655
23655
|
} catch (chownErr) {
|
|
23656
23656
|
if (opts.onChownError)
|
|
23657
23657
|
opts.onChownError(chownErr);
|
|
@@ -23659,25 +23659,25 @@ function atomicWriteFileSync(destPath, contents, modeOrOpts = 384) {
|
|
|
23659
23659
|
throw chownErr;
|
|
23660
23660
|
}
|
|
23661
23661
|
}
|
|
23662
|
-
|
|
23663
|
-
|
|
23662
|
+
fsyncSync3(fd);
|
|
23663
|
+
closeSync4(fd);
|
|
23664
23664
|
fd = null;
|
|
23665
|
-
|
|
23665
|
+
renameSync8(tmp, destPath);
|
|
23666
23666
|
} catch (err) {
|
|
23667
23667
|
if (fd !== null) {
|
|
23668
23668
|
try {
|
|
23669
|
-
|
|
23669
|
+
closeSync4(fd);
|
|
23670
23670
|
} catch {}
|
|
23671
23671
|
}
|
|
23672
23672
|
try {
|
|
23673
|
-
|
|
23673
|
+
rmSync3(tmp, { force: true });
|
|
23674
23674
|
} catch {}
|
|
23675
23675
|
throw err;
|
|
23676
23676
|
}
|
|
23677
23677
|
}
|
|
23678
|
-
var
|
|
23678
|
+
var TMP_OPEN_FLAGS2;
|
|
23679
23679
|
var init_atomic = __esm(() => {
|
|
23680
|
-
|
|
23680
|
+
TMP_OPEN_FLAGS2 = constants2.O_WRONLY | constants2.O_CREAT | constants2.O_EXCL | (constants2.O_NOFOLLOW ?? 0);
|
|
23681
23681
|
});
|
|
23682
23682
|
|
|
23683
23683
|
// gateway/approval-card.ts
|
|
@@ -35701,7 +35701,7 @@ function renderAuthLine(state7, agentName3, now = Date.now()) {
|
|
|
35701
35701
|
|
|
35702
35702
|
// gateway/quota-cache.ts
|
|
35703
35703
|
import { existsSync as existsSync44, readFileSync as readFileSync44, writeFileSync as writeFileSync37, mkdirSync as mkdirSync39 } from "fs";
|
|
35704
|
-
import { join as join53, dirname as
|
|
35704
|
+
import { join as join53, dirname as dirname22 } from "path";
|
|
35705
35705
|
function defaultCachePath() {
|
|
35706
35706
|
return process.env.SWITCHROOM_QUOTA_CACHE_PATH ?? join53(process.env.HOME ?? "/tmp", ".switchroom", "quota-cache.json");
|
|
35707
35707
|
}
|
|
@@ -35738,7 +35738,7 @@ function writeQuotaCache(result, opts = {}) {
|
|
|
35738
35738
|
result
|
|
35739
35739
|
};
|
|
35740
35740
|
try {
|
|
35741
|
-
mkdirSync39(
|
|
35741
|
+
mkdirSync39(dirname22(path3), { recursive: true });
|
|
35742
35742
|
writeFileSync37(path3, JSON.stringify(entry, null, 2), { mode: 384 });
|
|
35743
35743
|
} catch {}
|
|
35744
35744
|
}
|
|
@@ -36610,8 +36610,8 @@ var init_boot_probes = __esm(() => {
|
|
|
36610
36610
|
});
|
|
36611
36611
|
|
|
36612
36612
|
// gateway/boot-issue-cache.ts
|
|
36613
|
-
import { existsSync as existsSync46, readFileSync as readFileSync46, writeFileSync as writeFileSync38, mkdirSync as mkdirSync40, renameSync as
|
|
36614
|
-
import { dirname as
|
|
36613
|
+
import { existsSync as existsSync46, readFileSync as readFileSync46, writeFileSync as writeFileSync38, mkdirSync as mkdirSync40, renameSync as renameSync22 } from "fs";
|
|
36614
|
+
import { dirname as dirname23 } from "path";
|
|
36615
36615
|
function fingerprintProbe(key, r) {
|
|
36616
36616
|
if (r.status === "ok")
|
|
36617
36617
|
return `${key}:ok`;
|
|
@@ -36703,7 +36703,7 @@ function loadCache(path3, now = Date.now) {
|
|
|
36703
36703
|
parsed = JSON.parse(raw);
|
|
36704
36704
|
} catch {
|
|
36705
36705
|
try {
|
|
36706
|
-
|
|
36706
|
+
renameSync22(path3, `${path3}.corrupt-${now()}`);
|
|
36707
36707
|
} catch {}
|
|
36708
36708
|
return { ...EMPTY_CACHE, probes: {} };
|
|
36709
36709
|
}
|
|
@@ -36737,10 +36737,10 @@ function applyAndSave(path3, cache, diff) {
|
|
|
36737
36737
|
}
|
|
36738
36738
|
}
|
|
36739
36739
|
try {
|
|
36740
|
-
mkdirSync40(
|
|
36740
|
+
mkdirSync40(dirname23(path3), { recursive: true });
|
|
36741
36741
|
const tmp = `${path3}.tmp`;
|
|
36742
36742
|
writeFileSync38(tmp, JSON.stringify(next), { mode: 384 });
|
|
36743
|
-
|
|
36743
|
+
renameSync22(tmp, path3);
|
|
36744
36744
|
} catch {}
|
|
36745
36745
|
return next;
|
|
36746
36746
|
}
|
|
@@ -36753,8 +36753,8 @@ var init_boot_issue_cache = __esm(() => {
|
|
|
36753
36753
|
|
|
36754
36754
|
// gateway/config-snapshot.ts
|
|
36755
36755
|
import { createHash as createHash7 } from "crypto";
|
|
36756
|
-
import { existsSync as existsSync47, readFileSync as readFileSync47, writeFileSync as writeFileSync39, mkdirSync as mkdirSync41, renameSync as
|
|
36757
|
-
import { dirname as
|
|
36756
|
+
import { existsSync as existsSync47, readFileSync as readFileSync47, writeFileSync as writeFileSync39, mkdirSync as mkdirSync41, renameSync as renameSync23 } from "fs";
|
|
36757
|
+
import { dirname as dirname24 } from "path";
|
|
36758
36758
|
function hashStringArray(items) {
|
|
36759
36759
|
if (!items || items.length === 0)
|
|
36760
36760
|
return null;
|
|
@@ -36831,7 +36831,7 @@ function loadSnapshot(path3, now = Date.now) {
|
|
|
36831
36831
|
parsed = JSON.parse(raw);
|
|
36832
36832
|
} catch {
|
|
36833
36833
|
try {
|
|
36834
|
-
|
|
36834
|
+
renameSync23(path3, `${path3}.corrupt-${now()}`);
|
|
36835
36835
|
} catch {}
|
|
36836
36836
|
return null;
|
|
36837
36837
|
}
|
|
@@ -36852,10 +36852,10 @@ function loadSnapshot(path3, now = Date.now) {
|
|
|
36852
36852
|
}
|
|
36853
36853
|
function persistSnapshot(path3, snapshot) {
|
|
36854
36854
|
try {
|
|
36855
|
-
mkdirSync41(
|
|
36855
|
+
mkdirSync41(dirname24(path3), { recursive: true });
|
|
36856
36856
|
const tmp = `${path3}.tmp`;
|
|
36857
36857
|
writeFileSync39(tmp, JSON.stringify(snapshot), { mode: 384 });
|
|
36858
|
-
|
|
36858
|
+
renameSync23(tmp, path3);
|
|
36859
36859
|
} catch {}
|
|
36860
36860
|
}
|
|
36861
36861
|
var init_config_snapshot = __esm(() => {
|
|
@@ -37920,7 +37920,7 @@ __export(exports_tmux2, {
|
|
|
37920
37920
|
captureAgentPane: () => captureAgentPane2
|
|
37921
37921
|
});
|
|
37922
37922
|
import { execFileSync as execFileSync8 } from "node:child_process";
|
|
37923
|
-
import { chmodSync as chmodSync13, mkdirSync as
|
|
37923
|
+
import { chmodSync as chmodSync13, mkdirSync as mkdirSync50, readdirSync as readdirSync15, statSync as statSync21, unlinkSync as unlinkSync29, writeFileSync as writeFileSync49 } from "node:fs";
|
|
37924
37924
|
import { resolve as resolve12 } from "node:path";
|
|
37925
37925
|
function captureAgentPane2(opts) {
|
|
37926
37926
|
const { agentName: agentName3, agentDir, reason } = opts;
|
|
@@ -37932,7 +37932,7 @@ function captureAgentPane2(opts) {
|
|
|
37932
37932
|
const reasonSlug = sanitizeReason2(reason);
|
|
37933
37933
|
const outPath = resolve12(outDir, `${ts}-${reasonSlug}.txt`);
|
|
37934
37934
|
try {
|
|
37935
|
-
|
|
37935
|
+
mkdirSync50(outDir, { recursive: true, mode: 448 });
|
|
37936
37936
|
} catch (err) {
|
|
37937
37937
|
const msg = `mkdir crash-reports failed: ${err.message}`;
|
|
37938
37938
|
console.error(`[tmux-capture] ${agentName3}: ${msg}`);
|
|
@@ -37971,7 +37971,7 @@ function captureAgentPane2(opts) {
|
|
|
37971
37971
|
` + `
|
|
37972
37972
|
`;
|
|
37973
37973
|
try {
|
|
37974
|
-
|
|
37974
|
+
writeFileSync49(outPath, Buffer.concat([Buffer.from(header, "utf8"), body]), {
|
|
37975
37975
|
mode: 384
|
|
37976
37976
|
});
|
|
37977
37977
|
} catch (err) {
|
|
@@ -38055,7 +38055,7 @@ function pruneOldReports2(dir, retain) {
|
|
|
38055
38055
|
}).sort((a, b) => b.mtimeMs - a.mtimeMs);
|
|
38056
38056
|
for (const stale of files.slice(retain)) {
|
|
38057
38057
|
try {
|
|
38058
|
-
|
|
38058
|
+
unlinkSync29(stale.full);
|
|
38059
38059
|
} catch {}
|
|
38060
38060
|
}
|
|
38061
38061
|
}
|
|
@@ -38078,9 +38078,9 @@ __export(exports_config_approval_handler, {
|
|
|
38078
38078
|
_peekPendingConfigApprovalForTest: () => _peekPendingConfigApprovalForTest,
|
|
38079
38079
|
DIFF_SENTINEL: () => DIFF_SENTINEL
|
|
38080
38080
|
});
|
|
38081
|
-
import { randomBytes as
|
|
38081
|
+
import { randomBytes as randomBytes12 } from "node:crypto";
|
|
38082
38082
|
function defaultEpoch() {
|
|
38083
|
-
return
|
|
38083
|
+
return randomBytes12(4).toString("hex");
|
|
38084
38084
|
}
|
|
38085
38085
|
function truncateDiffForCard(unifiedDiff, maxLines = 50, maxChars = 3000) {
|
|
38086
38086
|
const sentinel = `
|
|
@@ -39021,29 +39021,80 @@ var init_approvals_commands = __esm(() => {
|
|
|
39021
39021
|
// gateway/gateway.ts
|
|
39022
39022
|
var import_grammy16 = __toESM(require_mod(), 1);
|
|
39023
39023
|
var import_runner3 = __toESM(require_mod3(), 1);
|
|
39024
|
-
import { randomBytes as
|
|
39024
|
+
import { randomBytes as randomBytes13, createHash as createHash8 } from "crypto";
|
|
39025
39025
|
import { execFileSync as execFileSync9, execSync as execSync2, spawn as spawn2 } from "child_process";
|
|
39026
39026
|
import {
|
|
39027
|
-
readFileSync as
|
|
39028
|
-
writeFileSync as
|
|
39029
|
-
mkdirSync as
|
|
39027
|
+
readFileSync as readFileSync60,
|
|
39028
|
+
writeFileSync as writeFileSync50,
|
|
39029
|
+
mkdirSync as mkdirSync51,
|
|
39030
39030
|
readdirSync as readdirSync16,
|
|
39031
|
-
rmSync as
|
|
39031
|
+
rmSync as rmSync8,
|
|
39032
39032
|
statSync as statSync22,
|
|
39033
|
-
renameSync as
|
|
39033
|
+
renameSync as renameSync27,
|
|
39034
39034
|
realpathSync as realpathSync4,
|
|
39035
39035
|
chmodSync as chmodSync14,
|
|
39036
|
-
openSync as
|
|
39037
|
-
closeSync as
|
|
39036
|
+
openSync as openSync15,
|
|
39037
|
+
closeSync as closeSync15,
|
|
39038
39038
|
existsSync as existsSync57,
|
|
39039
|
-
unlinkSync as
|
|
39039
|
+
unlinkSync as unlinkSync30,
|
|
39040
39040
|
appendFileSync as appendFileSync9
|
|
39041
39041
|
} from "fs";
|
|
39042
|
+
|
|
39043
|
+
// ../src/util/atomic.ts
|
|
39044
|
+
import { randomBytes } from "node:crypto";
|
|
39045
|
+
import { closeSync, constants, fchmodSync, fchownSync, fsyncSync, openSync, renameSync, rmSync, writeSync } from "node:fs";
|
|
39046
|
+
var TMP_OPEN_FLAGS = constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | (constants.O_NOFOLLOW ?? 0);
|
|
39047
|
+
function atomicWriteFileSync(destPath, contents, modeOrOpts = 384) {
|
|
39048
|
+
const opts = typeof modeOrOpts === "number" ? { mode: modeOrOpts } : modeOrOpts;
|
|
39049
|
+
const mode = opts.mode ?? 384;
|
|
39050
|
+
const tmp = `${destPath}.tmp-${process.pid}-${randomBytes(4).toString("hex")}`;
|
|
39051
|
+
const buf = typeof contents === "string" ? Buffer.from(contents, "utf-8") : contents;
|
|
39052
|
+
let fd = null;
|
|
39053
|
+
try {
|
|
39054
|
+
fd = openSync(tmp, TMP_OPEN_FLAGS, mode);
|
|
39055
|
+
writeSync(fd, buf, 0, buf.length, 0);
|
|
39056
|
+
fchmodSync(fd, mode);
|
|
39057
|
+
if (opts.uid !== undefined) {
|
|
39058
|
+
try {
|
|
39059
|
+
fchownSync(fd, opts.uid, opts.gid ?? opts.uid);
|
|
39060
|
+
} catch (chownErr) {
|
|
39061
|
+
if (opts.onChownError)
|
|
39062
|
+
opts.onChownError(chownErr);
|
|
39063
|
+
else
|
|
39064
|
+
throw chownErr;
|
|
39065
|
+
}
|
|
39066
|
+
}
|
|
39067
|
+
fsyncSync(fd);
|
|
39068
|
+
closeSync(fd);
|
|
39069
|
+
fd = null;
|
|
39070
|
+
renameSync(tmp, destPath);
|
|
39071
|
+
} catch (err) {
|
|
39072
|
+
if (fd !== null) {
|
|
39073
|
+
try {
|
|
39074
|
+
closeSync(fd);
|
|
39075
|
+
} catch {}
|
|
39076
|
+
}
|
|
39077
|
+
try {
|
|
39078
|
+
rmSync(tmp, { force: true });
|
|
39079
|
+
} catch {}
|
|
39080
|
+
throw err;
|
|
39081
|
+
}
|
|
39082
|
+
}
|
|
39083
|
+
function fsyncPathSync(path) {
|
|
39084
|
+
const fd = openSync(path, constants.O_RDONLY);
|
|
39085
|
+
try {
|
|
39086
|
+
fsyncSync(fd);
|
|
39087
|
+
} finally {
|
|
39088
|
+
closeSync(fd);
|
|
39089
|
+
}
|
|
39090
|
+
}
|
|
39091
|
+
|
|
39092
|
+
// gateway/gateway.ts
|
|
39042
39093
|
import { homedir as homedir19 } from "os";
|
|
39043
|
-
import { join as
|
|
39094
|
+
import { join as join68, sep as sep4, basename as basename17 } from "path";
|
|
39044
39095
|
|
|
39045
39096
|
// plugin-logger.ts
|
|
39046
|
-
import { appendFileSync, mkdirSync, renameSync, statSync, existsSync } from "fs";
|
|
39097
|
+
import { appendFileSync, mkdirSync, renameSync as renameSync2, statSync, existsSync } from "fs";
|
|
39047
39098
|
import { homedir } from "os";
|
|
39048
39099
|
import { dirname, join } from "path";
|
|
39049
39100
|
var DEFAULT_LOG_PATH = join(homedir(), ".switchroom", "logs", "telegram-plugin.log");
|
|
@@ -39071,11 +39122,11 @@ function rotateIfNeeded(path) {
|
|
|
39071
39122
|
const dst = `${path}.${i + 1}`;
|
|
39072
39123
|
try {
|
|
39073
39124
|
if (existsSync(src))
|
|
39074
|
-
|
|
39125
|
+
renameSync2(src, dst);
|
|
39075
39126
|
} catch {}
|
|
39076
39127
|
}
|
|
39077
39128
|
const backup = `${path}.1`;
|
|
39078
|
-
|
|
39129
|
+
renameSync2(path, backup);
|
|
39079
39130
|
} catch {}
|
|
39080
39131
|
}
|
|
39081
39132
|
function installPluginLogger(env = process.env) {
|
|
@@ -39182,7 +39233,7 @@ function redactAuthCodeMessage(api, chatId, messageId, log) {
|
|
|
39182
39233
|
}
|
|
39183
39234
|
|
|
39184
39235
|
// ask-user.ts
|
|
39185
|
-
import { randomBytes } from "crypto";
|
|
39236
|
+
import { randomBytes as randomBytes2 } from "crypto";
|
|
39186
39237
|
var ASK_USER_DEFAULT_TIMEOUT_MS = 300000;
|
|
39187
39238
|
var ASK_USER_MAX_TIMEOUT_MS = 1800000;
|
|
39188
39239
|
var ASK_USER_MIN_TIMEOUT_MS = 5000;
|
|
@@ -39244,7 +39295,7 @@ function validateAskUserArgs(args) {
|
|
|
39244
39295
|
};
|
|
39245
39296
|
}
|
|
39246
39297
|
function generateAskId() {
|
|
39247
|
-
return
|
|
39298
|
+
return randomBytes2(4).toString("hex");
|
|
39248
39299
|
}
|
|
39249
39300
|
function encodeAskCallback(askId, idx) {
|
|
39250
39301
|
if (!/^[0-9a-f]{8}$/.test(askId)) {
|
|
@@ -39791,7 +39842,7 @@ async function synthesizeViaSidecar(args) {
|
|
|
39791
39842
|
}
|
|
39792
39843
|
|
|
39793
39844
|
// voice-ondemand.ts
|
|
39794
|
-
import { readFileSync, writeFileSync, renameSync as
|
|
39845
|
+
import { readFileSync, writeFileSync, renameSync as renameSync3, mkdirSync as mkdirSync2 } from "fs";
|
|
39795
39846
|
import { dirname as dirname2 } from "path";
|
|
39796
39847
|
var VOICE_ONDEMAND_TTL_MS = 7 * 24 * 60 * 60 * 1000;
|
|
39797
39848
|
var VOICE_ONDEMAND_MAX_ENTRIES = 500;
|
|
@@ -39915,7 +39966,7 @@ class VoiceOnDemandCache {
|
|
|
39915
39966
|
try {
|
|
39916
39967
|
mkdirSync2(dirname2(this.persistPath), { recursive: true });
|
|
39917
39968
|
writeFileSync(tmp, JSON.stringify(doc), "utf8");
|
|
39918
|
-
|
|
39969
|
+
renameSync3(tmp, this.persistPath);
|
|
39919
39970
|
} catch (err) {
|
|
39920
39971
|
process.stderr.write(`voice-ondemand: failed to persist cache ${this.persistPath}: ${String(err)}
|
|
39921
39972
|
`);
|
|
@@ -39924,8 +39975,8 @@ class VoiceOnDemandCache {
|
|
|
39924
39975
|
}
|
|
39925
39976
|
|
|
39926
39977
|
// voice-ondemand.ts
|
|
39927
|
-
import { randomBytes as
|
|
39928
|
-
import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, renameSync as
|
|
39978
|
+
import { randomBytes as randomBytes3 } from "crypto";
|
|
39979
|
+
import { readFileSync as readFileSync2, writeFileSync as writeFileSync2, renameSync as renameSync4, mkdirSync as mkdirSync3 } from "fs";
|
|
39929
39980
|
import { dirname as dirname3 } from "path";
|
|
39930
39981
|
var VOICE_ONDEMAND_CALLBACK_PREFIX = "voice:";
|
|
39931
39982
|
var VOICE_ONDEMAND_TTL_MS2 = 7 * 24 * 60 * 60 * 1000;
|
|
@@ -40050,7 +40101,7 @@ class VoiceOnDemandCache2 {
|
|
|
40050
40101
|
try {
|
|
40051
40102
|
mkdirSync3(dirname3(this.persistPath), { recursive: true });
|
|
40052
40103
|
writeFileSync2(tmp, JSON.stringify(doc), "utf8");
|
|
40053
|
-
|
|
40104
|
+
renameSync4(tmp, this.persistPath);
|
|
40054
40105
|
} catch (err) {
|
|
40055
40106
|
process.stderr.write(`voice-ondemand: failed to persist cache ${this.persistPath}: ${String(err)}
|
|
40056
40107
|
`);
|
|
@@ -40058,7 +40109,7 @@ class VoiceOnDemandCache2 {
|
|
|
40058
40109
|
}
|
|
40059
40110
|
}
|
|
40060
40111
|
function mintVoiceOnDemandToken() {
|
|
40061
|
-
return
|
|
40112
|
+
return randomBytes3(4).toString("hex");
|
|
40062
40113
|
}
|
|
40063
40114
|
function isVoiceOnDemandCallback(data) {
|
|
40064
40115
|
return data.startsWith(VOICE_ONDEMAND_CALLBACK_PREFIX);
|
|
@@ -40124,7 +40175,7 @@ function makeOutboxListenMarkupResolver(deps) {
|
|
|
40124
40175
|
}
|
|
40125
40176
|
|
|
40126
40177
|
// voice-presynth.ts
|
|
40127
|
-
import { readdirSync, statSync as statSync2, unlinkSync, mkdirSync as mkdirSync4, writeFileSync as writeFileSync3, renameSync as
|
|
40178
|
+
import { readdirSync, statSync as statSync2, unlinkSync, mkdirSync as mkdirSync4, writeFileSync as writeFileSync3, renameSync as renameSync5 } from "fs";
|
|
40128
40179
|
import { join as join2 } from "path";
|
|
40129
40180
|
var VOICE_FILE_TTL_MS = 7 * 24 * 60 * 60 * 1000;
|
|
40130
40181
|
var VOICE_CACHE_MAX_BYTES = 500 * 1024 * 1024;
|
|
@@ -40190,7 +40241,7 @@ function writeVoiceCacheFile(dir, token, audio) {
|
|
|
40190
40241
|
const final = voiceCacheFilePath(dir, token);
|
|
40191
40242
|
const tmp = `${final}.tmp`;
|
|
40192
40243
|
writeFileSync3(tmp, audio);
|
|
40193
|
-
|
|
40244
|
+
renameSync5(tmp, final);
|
|
40194
40245
|
return final;
|
|
40195
40246
|
}
|
|
40196
40247
|
function sweepVoiceCacheDir(options) {
|
|
@@ -42779,6 +42830,18 @@ import { AsyncLocalStorage } from "async_hooks";
|
|
|
42779
42830
|
|
|
42780
42831
|
// retry-api-call.ts
|
|
42781
42832
|
var import_grammy2 = __toESM(require_mod2(), 1);
|
|
42833
|
+
function classifyBenignTelegram400(errorCode, description) {
|
|
42834
|
+
if (errorCode !== 400)
|
|
42835
|
+
return null;
|
|
42836
|
+
const desc = (description ?? "").toLowerCase();
|
|
42837
|
+
if (desc.includes("not modified"))
|
|
42838
|
+
return "not_modified";
|
|
42839
|
+
if (desc.includes("message to edit not found"))
|
|
42840
|
+
return "message_not_found";
|
|
42841
|
+
if (desc.includes("message to delete not found"))
|
|
42842
|
+
return "delete_not_found";
|
|
42843
|
+
return null;
|
|
42844
|
+
}
|
|
42782
42845
|
function isLocalResourceError(err) {
|
|
42783
42846
|
const code = err?.code;
|
|
42784
42847
|
if (typeof code === "string" && ["ENOSPC", "EDQUOT", "EIO", "ENOMEM"].includes(code)) {
|
|
@@ -42863,14 +42926,9 @@ function createRetryApiCall(config = {}) {
|
|
|
42863
42926
|
await sleep(delayMs);
|
|
42864
42927
|
continue;
|
|
42865
42928
|
}
|
|
42866
|
-
|
|
42867
|
-
|
|
42868
|
-
|
|
42869
|
-
}
|
|
42870
|
-
if (isGrammyErr && err.error_code === 400 && (desc.includes("message to edit not found") || desc.includes("message to delete not found"))) {
|
|
42871
|
-
observer?.onBenign?.({
|
|
42872
|
-
kind: desc.includes("edit") ? "message_not_found" : "delete_not_found"
|
|
42873
|
-
});
|
|
42929
|
+
const benignKind = isGrammyErr ? classifyBenignTelegram400(err.error_code, desc) : null;
|
|
42930
|
+
if (benignKind !== null) {
|
|
42931
|
+
observer?.onBenign?.({ kind: benignKind });
|
|
42874
42932
|
return;
|
|
42875
42933
|
}
|
|
42876
42934
|
if (isGrammyErr && err.error_code === 400 && desc.includes("thread not found") && opts?.threadId && opts?.chat_id) {
|
|
@@ -44674,12 +44732,12 @@ async function handleVoiceMessage(ctx, deps) {
|
|
|
44674
44732
|
}
|
|
44675
44733
|
|
|
44676
44734
|
// gateway/status-pin-store.ts
|
|
44677
|
-
var SNAPSHOT_VERSIONS = new Set([1, 2, 3]);
|
|
44735
|
+
var SNAPSHOT_VERSIONS = new Set([1, 2, 3, 4]);
|
|
44678
44736
|
function isPinRow(x) {
|
|
44679
44737
|
if (x == null || typeof x !== "object")
|
|
44680
44738
|
return false;
|
|
44681
44739
|
const o = x;
|
|
44682
|
-
return typeof o.pinKey === "string" && o.pinKey.length > 0 && typeof o.chatId === "string" && o.chatId.length > 0 && typeof o.messageId === "number" && (o.pending === undefined || typeof o.pending === "boolean") && (o.expiresAt === undefined || typeof o.expiresAt === "number") && (o.attempts === undefined || typeof o.attempts === "number") && (o.pinnedAt === undefined || typeof o.pinnedAt === "number");
|
|
44740
|
+
return typeof o.pinKey === "string" && o.pinKey.length > 0 && typeof o.chatId === "string" && o.chatId.length > 0 && (o.threadId === undefined || typeof o.threadId === "number") && typeof o.messageId === "number" && (o.pending === undefined || typeof o.pending === "boolean") && (o.expiresAt === undefined || typeof o.expiresAt === "number") && (o.attempts === undefined || typeof o.attempts === "number") && (o.pinnedAt === undefined || typeof o.pinnedAt === "number");
|
|
44683
44741
|
}
|
|
44684
44742
|
function loadStatusPins(path, fs2) {
|
|
44685
44743
|
if (!fs2.existsSync(path))
|
|
@@ -44704,7 +44762,7 @@ function loadStatusPins(path, fs2) {
|
|
|
44704
44762
|
return env.pins.filter(isPinRow);
|
|
44705
44763
|
}
|
|
44706
44764
|
function persistStatusPins(path, fs2, snapshot, log = (l) => process.stderr.write(l)) {
|
|
44707
|
-
const env = { v:
|
|
44765
|
+
const env = { v: 4, pins: [...snapshot] };
|
|
44708
44766
|
const tmp = path + ".tmp";
|
|
44709
44767
|
try {
|
|
44710
44768
|
fs2.writeFileSync(tmp, JSON.stringify(env));
|
|
@@ -44740,7 +44798,7 @@ function applyStatusPinRow(path, fs2, pinKey, row, log) {
|
|
|
44740
44798
|
persistStatusPins(path, fs2, next, log);
|
|
44741
44799
|
}
|
|
44742
44800
|
function reconcileAndPersistStatusPin(args) {
|
|
44743
|
-
const { path, fs: fs2, pinKey, chatId, op } = args;
|
|
44801
|
+
const { path, fs: fs2, pinKey, chatId, threadId, op } = args;
|
|
44744
44802
|
const log = args.log ?? ((l) => process.stderr.write(l));
|
|
44745
44803
|
const now = args.now ?? Date.now();
|
|
44746
44804
|
const claimAge = (messageId) => {
|
|
@@ -44750,20 +44808,20 @@ function reconcileAndPersistStatusPin(args) {
|
|
|
44750
44808
|
return withStoreLock(path, async () => {
|
|
44751
44809
|
if (op.kind === "pin") {
|
|
44752
44810
|
const pinnedAt = claimAge(op.messageId);
|
|
44753
|
-
applyStatusPinRow(path, fs2, pinKey, { pinKey, chatId, messageId: op.messageId, pending: true, pinnedAt }, log);
|
|
44811
|
+
applyStatusPinRow(path, fs2, pinKey, { pinKey, chatId, threadId, messageId: op.messageId, pending: true, pinnedAt }, log);
|
|
44754
44812
|
const next2 = await args.applyPin();
|
|
44755
44813
|
if (next2 == null) {
|
|
44756
44814
|
applyStatusPinRow(path, fs2, pinKey, null, log);
|
|
44757
44815
|
return null;
|
|
44758
44816
|
}
|
|
44759
|
-
applyStatusPinRow(path, fs2, pinKey, { pinKey, chatId, messageId: next2.messageId, pinnedAt: claimAge(next2.messageId) }, log);
|
|
44817
|
+
applyStatusPinRow(path, fs2, pinKey, { pinKey, chatId, threadId, messageId: next2.messageId, pinnedAt: claimAge(next2.messageId) }, log);
|
|
44760
44818
|
return next2;
|
|
44761
44819
|
}
|
|
44762
44820
|
const next = await args.applyPin();
|
|
44763
44821
|
if (next == null) {
|
|
44764
44822
|
applyStatusPinRow(path, fs2, pinKey, null, log);
|
|
44765
44823
|
} else {
|
|
44766
|
-
applyStatusPinRow(path, fs2, pinKey, { pinKey, chatId, messageId: next.messageId, pinnedAt: claimAge(next.messageId) }, log);
|
|
44824
|
+
applyStatusPinRow(path, fs2, pinKey, { pinKey, chatId, threadId, messageId: next.messageId, pinnedAt: claimAge(next.messageId) }, log);
|
|
44767
44825
|
}
|
|
44768
44826
|
return next;
|
|
44769
44827
|
});
|
|
@@ -47361,6 +47419,7 @@ if (isMain)
|
|
|
47361
47419
|
|
|
47362
47420
|
// tool-activity-summary.ts
|
|
47363
47421
|
init_card_format();
|
|
47422
|
+
init_redact();
|
|
47364
47423
|
|
|
47365
47424
|
// tool-names.ts
|
|
47366
47425
|
var TELEGRAM_TOOL_PREFIX_RE = /^mcp__[^_].*?telegram__/;
|
|
@@ -47491,12 +47550,21 @@ function renderStatusCard(opts) {
|
|
|
47491
47550
|
}
|
|
47492
47551
|
var WORKER_RESULT_RULE = "\u2500\u2500\u2500\u2500\u2500";
|
|
47493
47552
|
var WORKER_RESULT_MAX = 320;
|
|
47494
|
-
function
|
|
47495
|
-
if (
|
|
47553
|
+
function deriveCardResult(state, summary) {
|
|
47554
|
+
if (state !== "done" && state !== "failed")
|
|
47555
|
+
return;
|
|
47556
|
+
const text = cleanWorkerResultParagraph(redact(summary ?? ""));
|
|
47557
|
+
if (text.length === 0)
|
|
47558
|
+
return;
|
|
47559
|
+
return { emoji: state === "done" ? "\u2705" : "\u26a0\ufe0f", text };
|
|
47560
|
+
}
|
|
47561
|
+
var AGENT_CARD_EMOJI = "\uD83E\uDD16";
|
|
47562
|
+
function renderAgentCard(lines, children, final, liveSuffix, stepCount, header) {
|
|
47563
|
+
if (lines.length === 0 && children.length === 0 && header == null)
|
|
47496
47564
|
return null;
|
|
47497
47565
|
return renderStatusCard({
|
|
47498
47566
|
header: header != null ? {
|
|
47499
|
-
emoji:
|
|
47567
|
+
emoji: AGENT_CARD_EMOJI,
|
|
47500
47568
|
label: header.label,
|
|
47501
47569
|
elapsedMs: header.elapsedMs,
|
|
47502
47570
|
toolCount: header.toolCount,
|
|
@@ -47505,31 +47573,19 @@ function renderActivityFeed(lines, final = false, liveSuffix = "", stepCount, he
|
|
|
47505
47573
|
totalTokens: header.totalTokens
|
|
47506
47574
|
} : undefined,
|
|
47507
47575
|
steps: lines,
|
|
47576
|
+
...children.length > 0 ? { childSteps: children } : {},
|
|
47508
47577
|
final,
|
|
47509
47578
|
liveSuffix,
|
|
47510
|
-
stepCount
|
|
47579
|
+
stepCount,
|
|
47580
|
+
result: final && header != null ? deriveCardResult(header.state, header.resultText) : undefined
|
|
47511
47581
|
});
|
|
47512
47582
|
}
|
|
47583
|
+
function renderActivityFeed(lines, final = false, liveSuffix = "", stepCount, header) {
|
|
47584
|
+
return renderAgentCard(lines, [], final, liveSuffix, stepCount, header);
|
|
47585
|
+
}
|
|
47513
47586
|
function renderActivityFeedWithNested(lines, childLines, final = false, liveSuffix = "", stepCount, header) {
|
|
47514
47587
|
const children = childLines.map((s) => s.trim()).filter((s) => s.length > 0);
|
|
47515
|
-
|
|
47516
|
-
return renderActivityFeed(lines, final, liveSuffix, stepCount, header);
|
|
47517
|
-
return renderStatusCard({
|
|
47518
|
-
header: header != null ? {
|
|
47519
|
-
emoji: "\uD83E\uDD16",
|
|
47520
|
-
label: header.label,
|
|
47521
|
-
elapsedMs: header.elapsedMs,
|
|
47522
|
-
toolCount: header.toolCount,
|
|
47523
|
-
state: header.state,
|
|
47524
|
-
model: header.model,
|
|
47525
|
-
totalTokens: header.totalTokens
|
|
47526
|
-
} : undefined,
|
|
47527
|
-
steps: lines,
|
|
47528
|
-
childSteps: children,
|
|
47529
|
-
final,
|
|
47530
|
-
liveSuffix,
|
|
47531
|
-
stepCount
|
|
47532
|
-
});
|
|
47588
|
+
return renderAgentCard(lines, children, final, liveSuffix, stepCount, header);
|
|
47533
47589
|
}
|
|
47534
47590
|
var COMBINED_ROW_DESC_MAX = 72;
|
|
47535
47591
|
var PER_WORKER_HEADER_COST = 1;
|
|
@@ -47651,12 +47707,7 @@ function renderWorkerActivity(v, liveSuffix = "") {
|
|
|
47651
47707
|
model: v.model,
|
|
47652
47708
|
totalTokens: v.totalTokens
|
|
47653
47709
|
};
|
|
47654
|
-
|
|
47655
|
-
if (finished && v.state !== "incomplete") {
|
|
47656
|
-
const text = cleanWorkerResultParagraph(v.latestSummary);
|
|
47657
|
-
if (text.length > 0)
|
|
47658
|
-
result = { emoji: v.state === "done" ? "\u2705" : "\u26a0\ufe0f", text };
|
|
47659
|
-
}
|
|
47710
|
+
const result = deriveCardResult(v.state, v.latestSummary);
|
|
47660
47711
|
const card = renderStatusCard({
|
|
47661
47712
|
header,
|
|
47662
47713
|
steps,
|
|
@@ -47734,7 +47785,7 @@ function createWorkerActivityFeed(opts) {
|
|
|
47734
47785
|
}
|
|
47735
47786
|
let heartbeatTimer = null;
|
|
47736
47787
|
function feedKeyOf(chatId, threadId) {
|
|
47737
|
-
return `${chatId}
|
|
47788
|
+
return `${chatId}:${threadId ?? "-"}`;
|
|
47738
47789
|
}
|
|
47739
47790
|
function groupOfAgent(agentId) {
|
|
47740
47791
|
const key = agentIndex.get(agentId);
|
|
@@ -48768,8 +48819,8 @@ import { unlinkSync as unlinkSync7 } from "node:fs";
|
|
|
48768
48819
|
import { join as join12 } from "node:path";
|
|
48769
48820
|
|
|
48770
48821
|
// gateway/store-file.ts
|
|
48771
|
-
import { randomBytes as
|
|
48772
|
-
import { readFileSync as readFileSync12, readdirSync as readdirSync4, renameSync as
|
|
48822
|
+
import { randomBytes as randomBytes6 } from "node:crypto";
|
|
48823
|
+
import { readFileSync as readFileSync12, readdirSync as readdirSync4, renameSync as renameSync9, rmSync as rmSync4, statSync as statSync7 } from "node:fs";
|
|
48773
48824
|
import { basename as basename6, dirname as dirname6, join as join11 } from "node:path";
|
|
48774
48825
|
var defaultLog = (line) => {
|
|
48775
48826
|
process.stderr.write(line);
|
|
@@ -48778,7 +48829,7 @@ var MAX_QUARANTINED_COPIES = 5;
|
|
|
48778
48829
|
var quarantineSeq = 0;
|
|
48779
48830
|
function quarantinePath(filePath) {
|
|
48780
48831
|
const seq = String(quarantineSeq++).padStart(6, "0");
|
|
48781
|
-
return `${filePath}.corrupt-${Date.now()}-${seq}-${
|
|
48832
|
+
return `${filePath}.corrupt-${Date.now()}-${seq}-${randomBytes6(4).toString("hex")}`;
|
|
48782
48833
|
}
|
|
48783
48834
|
function reapOldQuarantines(filePath, log) {
|
|
48784
48835
|
const dir = dirname6(filePath);
|
|
@@ -48792,7 +48843,7 @@ function reapOldQuarantines(filePath, log) {
|
|
|
48792
48843
|
return { name, mtimeNs };
|
|
48793
48844
|
}).sort((a, b) => a.mtimeNs === b.mtimeNs ? a.name.localeCompare(b.name) : a.mtimeNs < b.mtimeNs ? -1 : 1);
|
|
48794
48845
|
for (const stale of copies.slice(0, Math.max(0, copies.length - MAX_QUARANTINED_COPIES))) {
|
|
48795
|
-
|
|
48846
|
+
rmSync4(join11(dir, stale.name), { force: true });
|
|
48796
48847
|
}
|
|
48797
48848
|
} catch (err) {
|
|
48798
48849
|
log(`telegram gateway: quarantine reap failed dir=${dir}: ${err.message}
|
|
@@ -48803,7 +48854,7 @@ function quarantineCorruptStoreFile(filePath, store2, reason, log = defaultLog)
|
|
|
48803
48854
|
const target = quarantinePath(filePath);
|
|
48804
48855
|
let preserved = target;
|
|
48805
48856
|
try {
|
|
48806
|
-
|
|
48857
|
+
renameSync9(filePath, target);
|
|
48807
48858
|
} catch (err) {
|
|
48808
48859
|
preserved = `NOT preserved (${err.message})`;
|
|
48809
48860
|
}
|
|
@@ -48814,7 +48865,7 @@ function quarantineCorruptStoreFile(filePath, store2, reason, log = defaultLog)
|
|
|
48814
48865
|
function preserveUnreadableStoreFile(filePath, store2, log = defaultLog) {
|
|
48815
48866
|
const target = quarantinePath(filePath);
|
|
48816
48867
|
try {
|
|
48817
|
-
|
|
48868
|
+
renameSync9(filePath, target);
|
|
48818
48869
|
} catch (err) {
|
|
48819
48870
|
if (err.code === "ENOENT") {
|
|
48820
48871
|
return;
|
|
@@ -48867,7 +48918,7 @@ function createPendingCardStore(stateDir, log = (l) => process.stderr.write(l))
|
|
|
48867
48918
|
preserveUnreadableStoreFile(filePath, "pending-card-store", log);
|
|
48868
48919
|
unreadable = false;
|
|
48869
48920
|
}
|
|
48870
|
-
|
|
48921
|
+
atomicWriteFileSync2(filePath, JSON.stringify(entries), 384);
|
|
48871
48922
|
} catch (err) {
|
|
48872
48923
|
log(`telegram gateway: pending-card-store write failed: ${err.message}
|
|
48873
48924
|
`);
|
|
@@ -49517,12 +49568,12 @@ function buildSkillProposalApplyInbound(opts) {
|
|
|
49517
49568
|
|
|
49518
49569
|
// ../src/self-improve/skill-proposals.ts
|
|
49519
49570
|
import {
|
|
49520
|
-
closeSync as
|
|
49571
|
+
closeSync as closeSync5,
|
|
49521
49572
|
existsSync as existsSync10,
|
|
49522
49573
|
mkdirSync as mkdirSync13,
|
|
49523
|
-
openSync as
|
|
49574
|
+
openSync as openSync5,
|
|
49524
49575
|
readFileSync as readFileSync13,
|
|
49525
|
-
writeSync as
|
|
49576
|
+
writeSync as writeSync5
|
|
49526
49577
|
} from "node:fs";
|
|
49527
49578
|
import { join as join14 } from "node:path";
|
|
49528
49579
|
var PROPOSALS_FILE = "skill-proposals.jsonl";
|
|
@@ -49540,12 +49591,12 @@ function ensureDir2(stateDir) {
|
|
|
49540
49591
|
}
|
|
49541
49592
|
}
|
|
49542
49593
|
function appendLine(path, obj) {
|
|
49543
|
-
const fd =
|
|
49594
|
+
const fd = openSync5(path, "a");
|
|
49544
49595
|
try {
|
|
49545
|
-
|
|
49596
|
+
writeSync5(fd, JSON.stringify(obj) + `
|
|
49546
49597
|
`);
|
|
49547
49598
|
} finally {
|
|
49548
|
-
|
|
49599
|
+
closeSync5(fd);
|
|
49549
49600
|
}
|
|
49550
49601
|
}
|
|
49551
49602
|
function readLines(path, isValid2) {
|
|
@@ -49696,7 +49747,7 @@ async function addAccountViaBroker(label, credentials, opts = {}) {
|
|
|
49696
49747
|
|
|
49697
49748
|
// gateway/hostd-dispatch.ts
|
|
49698
49749
|
import { existsSync as existsSync11 } from "node:fs";
|
|
49699
|
-
import { randomBytes as
|
|
49750
|
+
import { randomBytes as randomBytes7 } from "node:crypto";
|
|
49700
49751
|
|
|
49701
49752
|
// ../src/host-control/client.ts
|
|
49702
49753
|
import { connect } from "node:net";
|
|
@@ -50042,7 +50093,7 @@ async function tryHostdDispatch(agentName, req, timeoutMs = 5000) {
|
|
|
50042
50093
|
}
|
|
50043
50094
|
}
|
|
50044
50095
|
function hostdRequestId(prefix) {
|
|
50045
|
-
return `${prefix}-${Date.now()}-${
|
|
50096
|
+
return `${prefix}-${Date.now()}-${randomBytes7(4).toString("hex")}`;
|
|
50046
50097
|
}
|
|
50047
50098
|
async function hostdGetStatusOnce(agentName, targetRequestId) {
|
|
50048
50099
|
if (!isHostdEnabled())
|
|
@@ -51684,7 +51735,7 @@ ${trimmed.replace(/```/g, "`\u200b``")}
|
|
|
51684
51735
|
|
|
51685
51736
|
// gateway/card-tool-handlers.ts
|
|
51686
51737
|
init_rich_send();
|
|
51687
|
-
import { randomBytes as
|
|
51738
|
+
import { randomBytes as randomBytes8 } from "crypto";
|
|
51688
51739
|
|
|
51689
51740
|
// gateway/vault-request-access-card.ts
|
|
51690
51741
|
init_approval_card();
|
|
@@ -51819,7 +51870,7 @@ function createCardToolHandlers(deps) {
|
|
|
51819
51870
|
throw new Error(`vault_request_save: key must match ${VAULT_KEY_REGEX_LABEL}`);
|
|
51820
51871
|
}
|
|
51821
51872
|
const agentSlug = process.env.SWITCHROOM_AGENT_NAME || "agent";
|
|
51822
|
-
const stageId =
|
|
51873
|
+
const stageId = randomBytes8(4).toString("hex");
|
|
51823
51874
|
const pending = {
|
|
51824
51875
|
agent: agentSlug,
|
|
51825
51876
|
chat_id,
|
|
@@ -51909,7 +51960,7 @@ function createCardToolHandlers(deps) {
|
|
|
51909
51960
|
}
|
|
51910
51961
|
} catch {}
|
|
51911
51962
|
}
|
|
51912
|
-
const stageId =
|
|
51963
|
+
const stageId = randomBytes8(4).toString("hex");
|
|
51913
51964
|
const pending = {
|
|
51914
51965
|
agent: agentSlug,
|
|
51915
51966
|
chat_id,
|
|
@@ -51971,7 +52022,7 @@ function createCardToolHandlers(deps) {
|
|
|
51971
52022
|
pendingCardStore.remove(sid);
|
|
51972
52023
|
}
|
|
51973
52024
|
}
|
|
51974
|
-
const stageId =
|
|
52025
|
+
const stageId = randomBytes8(4).toString("hex");
|
|
51975
52026
|
const pending = { agent: agentSlug, chat_id, key, reason, staged_at: Date.now() };
|
|
51976
52027
|
pendingSecretRequests.set(stageId, pending);
|
|
51977
52028
|
sweepSecretRequests();
|
|
@@ -52070,7 +52121,7 @@ function createCardToolHandlers(deps) {
|
|
|
52070
52121
|
process.stderr.write(`telegram gateway: mental_model_propose dup pre-check read failed: ${err.message}
|
|
52071
52122
|
`);
|
|
52072
52123
|
}
|
|
52073
|
-
const stageId =
|
|
52124
|
+
const stageId = randomBytes8(4).toString("hex");
|
|
52074
52125
|
const pending = {
|
|
52075
52126
|
agent: agentSlug,
|
|
52076
52127
|
chat_id,
|
|
@@ -52271,7 +52322,7 @@ function createMissedApprovalsStore(stateDir, log = (l) => process.stderr.write(
|
|
|
52271
52322
|
preserveUnreadableStoreFile(filePath, "missed-approvals-store", log);
|
|
52272
52323
|
unreadable = false;
|
|
52273
52324
|
}
|
|
52274
|
-
|
|
52325
|
+
atomicWriteFileSync2(filePath, JSON.stringify(f), 384);
|
|
52275
52326
|
} catch (err) {
|
|
52276
52327
|
log(`telegram gateway: missed-approvals-store write failed: ${err.message}
|
|
52277
52328
|
`);
|
|
@@ -52351,7 +52402,7 @@ function computeBackoffMs(attempts, retryAfterMs) {
|
|
|
52351
52402
|
}
|
|
52352
52403
|
var atomicWriteSeam = (path, data, opts) => {
|
|
52353
52404
|
const mode = typeof opts === "object" && opts !== null && typeof opts.mode === "number" ? opts.mode : 384;
|
|
52354
|
-
|
|
52405
|
+
atomicWriteFileSync2(path, data, mode);
|
|
52355
52406
|
};
|
|
52356
52407
|
function createAlwaysAllowPersistQueue(stateDir, writeFileSyncFn = atomicWriteSeam, log = (l) => process.stderr.write(l)) {
|
|
52357
52408
|
const filePath = join17(stateDir, "always-allow-persist-queue.json");
|
|
@@ -52802,6 +52853,7 @@ function isTelegramSurfaceTool2(toolName) {
|
|
|
52802
52853
|
|
|
52803
52854
|
// tool-activity-summary.ts
|
|
52804
52855
|
init_card_format();
|
|
52856
|
+
init_redact();
|
|
52805
52857
|
function clipNarrative2(s) {
|
|
52806
52858
|
return s.split(`
|
|
52807
52859
|
`)[0].trim().slice(0, STATUS_LINE_MAX);
|
|
@@ -55860,7 +55912,7 @@ var codes = {
|
|
|
55860
55912
|
replacementCharacter: 65533
|
|
55861
55913
|
};
|
|
55862
55914
|
// ../node_modules/.bun/micromark-util-symbol@2.0.1/node_modules/micromark-util-symbol/lib/constants.js
|
|
55863
|
-
var
|
|
55915
|
+
var constants3 = {
|
|
55864
55916
|
attentionSideAfter: 2,
|
|
55865
55917
|
attentionSideBefore: 1,
|
|
55866
55918
|
atxHeadingOpeningFenceSizeMax: 6,
|
|
@@ -56116,7 +56168,7 @@ function splice(list, start, remove, items) {
|
|
|
56116
56168
|
start = start > end ? end : start;
|
|
56117
56169
|
}
|
|
56118
56170
|
remove = remove > 0 ? remove : 0;
|
|
56119
|
-
if (items.length <
|
|
56171
|
+
if (items.length < constants3.v8MaxSafeChunkSize) {
|
|
56120
56172
|
parameters = Array.from(items);
|
|
56121
56173
|
parameters.unshift(start, remove);
|
|
56122
56174
|
list.splice(...parameters);
|
|
@@ -56124,11 +56176,11 @@ function splice(list, start, remove, items) {
|
|
|
56124
56176
|
if (remove)
|
|
56125
56177
|
list.splice(start, remove);
|
|
56126
56178
|
while (chunkStart < items.length) {
|
|
56127
|
-
parameters = items.slice(chunkStart, chunkStart +
|
|
56179
|
+
parameters = items.slice(chunkStart, chunkStart + constants3.v8MaxSafeChunkSize);
|
|
56128
56180
|
parameters.unshift(start, 0);
|
|
56129
56181
|
list.splice(...parameters);
|
|
56130
|
-
chunkStart +=
|
|
56131
|
-
start +=
|
|
56182
|
+
chunkStart += constants3.v8MaxSafeChunkSize;
|
|
56183
|
+
start += constants3.v8MaxSafeChunkSize;
|
|
56132
56184
|
}
|
|
56133
56185
|
}
|
|
56134
56186
|
}
|
|
@@ -56264,7 +56316,7 @@ function initializeContent(effects) {
|
|
|
56264
56316
|
}
|
|
56265
56317
|
function lineStart(code) {
|
|
56266
56318
|
const token = effects.enter(types2.chunkText, {
|
|
56267
|
-
contentType:
|
|
56319
|
+
contentType: constants3.contentTypeText,
|
|
56268
56320
|
previous
|
|
56269
56321
|
});
|
|
56270
56322
|
if (previous) {
|
|
@@ -56386,7 +56438,7 @@ function initializeDocument(effects) {
|
|
|
56386
56438
|
childFlow = childFlow || self.parser.flow(self.now());
|
|
56387
56439
|
effects.enter(types2.chunkFlow, {
|
|
56388
56440
|
_tokenizer: childFlow,
|
|
56389
|
-
contentType:
|
|
56441
|
+
contentType: constants3.contentTypeFlow,
|
|
56390
56442
|
previous: childToken
|
|
56391
56443
|
});
|
|
56392
56444
|
return flowContinue(code);
|
|
@@ -56471,16 +56523,16 @@ function initializeDocument(effects) {
|
|
|
56471
56523
|
}
|
|
56472
56524
|
function tokenizeContainer(effects, ok2, nok) {
|
|
56473
56525
|
ok(this.parser.constructs.disable.null, "expected `disable.null` to be populated");
|
|
56474
|
-
return factorySpace(effects, effects.attempt(this.parser.constructs.document, ok2, nok), types2.linePrefix, this.parser.constructs.disable.null.includes("codeIndented") ? undefined :
|
|
56526
|
+
return factorySpace(effects, effects.attempt(this.parser.constructs.document, ok2, nok), types2.linePrefix, this.parser.constructs.disable.null.includes("codeIndented") ? undefined : constants3.tabSize);
|
|
56475
56527
|
}
|
|
56476
56528
|
|
|
56477
56529
|
// ../node_modules/.bun/micromark-util-classify-character@2.0.1/node_modules/micromark-util-classify-character/dev/index.js
|
|
56478
56530
|
function classifyCharacter(code) {
|
|
56479
56531
|
if (code === codes.eof || markdownLineEndingOrSpace(code) || unicodeWhitespace(code)) {
|
|
56480
|
-
return
|
|
56532
|
+
return constants3.characterGroupWhitespace;
|
|
56481
56533
|
}
|
|
56482
56534
|
if (unicodePunctuation(code)) {
|
|
56483
|
-
return
|
|
56535
|
+
return constants3.characterGroupPunctuation;
|
|
56484
56536
|
}
|
|
56485
56537
|
}
|
|
56486
56538
|
|
|
@@ -56614,8 +56666,8 @@ function tokenizeAttention(effects, ok2) {
|
|
|
56614
56666
|
const token = effects.exit("attentionSequence");
|
|
56615
56667
|
const after = classifyCharacter(code);
|
|
56616
56668
|
ok(attentionMarkers, "expected `attentionMarkers` to be populated");
|
|
56617
|
-
const open = !after || after ===
|
|
56618
|
-
const close = !before || before ===
|
|
56669
|
+
const open = !after || after === constants3.characterGroupPunctuation && before || attentionMarkers.includes(code);
|
|
56670
|
+
const close = !before || before === constants3.characterGroupPunctuation && after || attentionMarkers.includes(previous);
|
|
56619
56671
|
token._open = Boolean(marker === codes.asterisk ? open : open && (before || !close));
|
|
56620
56672
|
token._close = Boolean(marker === codes.asterisk ? close : close && (after || !open));
|
|
56621
56673
|
return ok2(code);
|
|
@@ -56663,7 +56715,7 @@ function tokenizeAutolink(effects, ok2, nok) {
|
|
|
56663
56715
|
size = 0;
|
|
56664
56716
|
return urlInside;
|
|
56665
56717
|
}
|
|
56666
|
-
if ((code === codes.plusSign || code === codes.dash || code === codes.dot || asciiAlphanumeric(code)) && size++ <
|
|
56718
|
+
if ((code === codes.plusSign || code === codes.dash || code === codes.dot || asciiAlphanumeric(code)) && size++ < constants3.autolinkSchemeSizeMax) {
|
|
56667
56719
|
effects.consume(code);
|
|
56668
56720
|
return schemeInsideOrEmailAtext;
|
|
56669
56721
|
}
|
|
@@ -56716,7 +56768,7 @@ function tokenizeAutolink(effects, ok2, nok) {
|
|
|
56716
56768
|
return emailValue(code);
|
|
56717
56769
|
}
|
|
56718
56770
|
function emailValue(code) {
|
|
56719
|
-
if ((code === codes.dash || asciiAlphanumeric(code)) && size++ <
|
|
56771
|
+
if ((code === codes.dash || asciiAlphanumeric(code)) && size++ < constants3.autolinkDomainSizeMax) {
|
|
56720
56772
|
const next = code === codes.dash ? emailValue : emailLabel;
|
|
56721
56773
|
effects.consume(code);
|
|
56722
56774
|
return next;
|
|
@@ -56779,7 +56831,7 @@ function tokenizeBlockQuoteContinuation(effects, ok2, nok) {
|
|
|
56779
56831
|
function contStart(code) {
|
|
56780
56832
|
if (markdownSpace(code)) {
|
|
56781
56833
|
ok(self.parser.constructs.disable.null, "expected `disable.null` to be populated");
|
|
56782
|
-
return factorySpace(effects, contBefore, types2.linePrefix, self.parser.constructs.disable.null.includes("codeIndented") ? undefined :
|
|
56834
|
+
return factorySpace(effects, contBefore, types2.linePrefix, self.parser.constructs.disable.null.includes("codeIndented") ? undefined : constants3.tabSize)(code);
|
|
56783
56835
|
}
|
|
56784
56836
|
return contBefore(code);
|
|
56785
56837
|
}
|
|
@@ -56843,7 +56895,7 @@ function tokenizeCharacterReference(effects, ok2, nok) {
|
|
|
56843
56895
|
return numeric;
|
|
56844
56896
|
}
|
|
56845
56897
|
effects.enter(types2.characterReferenceValue);
|
|
56846
|
-
max =
|
|
56898
|
+
max = constants3.characterReferenceNamedSizeMax;
|
|
56847
56899
|
test = asciiAlphanumeric;
|
|
56848
56900
|
return value(code);
|
|
56849
56901
|
}
|
|
@@ -56853,12 +56905,12 @@ function tokenizeCharacterReference(effects, ok2, nok) {
|
|
|
56853
56905
|
effects.consume(code);
|
|
56854
56906
|
effects.exit(types2.characterReferenceMarkerHexadecimal);
|
|
56855
56907
|
effects.enter(types2.characterReferenceValue);
|
|
56856
|
-
max =
|
|
56908
|
+
max = constants3.characterReferenceHexadecimalSizeMax;
|
|
56857
56909
|
test = asciiHexDigit;
|
|
56858
56910
|
return value;
|
|
56859
56911
|
}
|
|
56860
56912
|
effects.enter(types2.characterReferenceValue);
|
|
56861
|
-
max =
|
|
56913
|
+
max = constants3.characterReferenceDecimalSizeMax;
|
|
56862
56914
|
test = asciiDigit;
|
|
56863
56915
|
return value(code);
|
|
56864
56916
|
}
|
|
@@ -56917,7 +56969,7 @@ function tokenizeCodeFenced(effects, ok2, nok) {
|
|
|
56917
56969
|
effects.consume(code);
|
|
56918
56970
|
return sequenceOpen;
|
|
56919
56971
|
}
|
|
56920
|
-
if (sizeOpen <
|
|
56972
|
+
if (sizeOpen < constants3.codeFencedSequenceSizeMin) {
|
|
56921
56973
|
return nok(code);
|
|
56922
56974
|
}
|
|
56923
56975
|
effects.exit(types2.codeFencedFenceSequence);
|
|
@@ -56929,7 +56981,7 @@ function tokenizeCodeFenced(effects, ok2, nok) {
|
|
|
56929
56981
|
return self.interrupt ? ok2(code) : effects.check(nonLazyContinuation, atNonLazyBreak, after)(code);
|
|
56930
56982
|
}
|
|
56931
56983
|
effects.enter(types2.codeFencedFenceInfo);
|
|
56932
|
-
effects.enter(types2.chunkString, { contentType:
|
|
56984
|
+
effects.enter(types2.chunkString, { contentType: constants3.contentTypeString });
|
|
56933
56985
|
return info(code);
|
|
56934
56986
|
}
|
|
56935
56987
|
function info(code) {
|
|
@@ -56954,7 +57006,7 @@ function tokenizeCodeFenced(effects, ok2, nok) {
|
|
|
56954
57006
|
return infoBefore(code);
|
|
56955
57007
|
}
|
|
56956
57008
|
effects.enter(types2.codeFencedFenceMeta);
|
|
56957
|
-
effects.enter(types2.chunkString, { contentType:
|
|
57009
|
+
effects.enter(types2.chunkString, { contentType: constants3.contentTypeString });
|
|
56958
57010
|
return meta(code);
|
|
56959
57011
|
}
|
|
56960
57012
|
function meta(code) {
|
|
@@ -57015,7 +57067,7 @@ function tokenizeCodeFenced(effects, ok2, nok) {
|
|
|
57015
57067
|
function start2(code) {
|
|
57016
57068
|
ok(self.parser.constructs.disable.null, "expected `disable.null` to be populated");
|
|
57017
57069
|
effects2.enter(types2.codeFencedFence);
|
|
57018
|
-
return markdownSpace(code) ? factorySpace(effects2, beforeSequenceClose, types2.linePrefix, self.parser.constructs.disable.null.includes("codeIndented") ? undefined :
|
|
57070
|
+
return markdownSpace(code) ? factorySpace(effects2, beforeSequenceClose, types2.linePrefix, self.parser.constructs.disable.null.includes("codeIndented") ? undefined : constants3.tabSize)(code) : beforeSequenceClose(code);
|
|
57019
57071
|
}
|
|
57020
57072
|
function beforeSequenceClose(code) {
|
|
57021
57073
|
if (code === marker) {
|
|
@@ -57074,11 +57126,11 @@ function tokenizeCodeIndented(effects, ok2, nok) {
|
|
|
57074
57126
|
function start(code) {
|
|
57075
57127
|
ok(markdownSpace(code));
|
|
57076
57128
|
effects.enter(types2.codeIndented);
|
|
57077
|
-
return factorySpace(effects, afterPrefix, types2.linePrefix,
|
|
57129
|
+
return factorySpace(effects, afterPrefix, types2.linePrefix, constants3.tabSize + 1)(code);
|
|
57078
57130
|
}
|
|
57079
57131
|
function afterPrefix(code) {
|
|
57080
57132
|
const tail = self.events[self.events.length - 1];
|
|
57081
|
-
return tail && tail[1].type === types2.linePrefix && tail[2].sliceSerialize(tail[1], true).length >=
|
|
57133
|
+
return tail && tail[1].type === types2.linePrefix && tail[2].sliceSerialize(tail[1], true).length >= constants3.tabSize ? atBreak(code) : nok(code);
|
|
57082
57134
|
}
|
|
57083
57135
|
function atBreak(code) {
|
|
57084
57136
|
if (code === codes.eof) {
|
|
@@ -57116,11 +57168,11 @@ function tokenizeFurtherStart(effects, ok2, nok) {
|
|
|
57116
57168
|
effects.exit(types2.lineEnding);
|
|
57117
57169
|
return furtherStart2;
|
|
57118
57170
|
}
|
|
57119
|
-
return factorySpace(effects, afterPrefix, types2.linePrefix,
|
|
57171
|
+
return factorySpace(effects, afterPrefix, types2.linePrefix, constants3.tabSize + 1)(code);
|
|
57120
57172
|
}
|
|
57121
57173
|
function afterPrefix(code) {
|
|
57122
57174
|
const tail = self.events[self.events.length - 1];
|
|
57123
|
-
return tail && tail[1].type === types2.linePrefix && tail[2].sliceSerialize(tail[1], true).length >=
|
|
57175
|
+
return tail && tail[1].type === types2.linePrefix && tail[2].sliceSerialize(tail[1], true).length >= constants3.tabSize ? ok2(code) : markdownLineEnding(code) ? furtherStart2(code) : nok(code);
|
|
57124
57176
|
}
|
|
57125
57177
|
}
|
|
57126
57178
|
// ../node_modules/.bun/micromark-core-commonmark@2.0.3/node_modules/micromark-core-commonmark/dev/lib/code-text.js
|
|
@@ -57312,12 +57364,12 @@ class SpliceBuffer {
|
|
|
57312
57364
|
}
|
|
57313
57365
|
function chunkedPush(list, right) {
|
|
57314
57366
|
let chunkStart = 0;
|
|
57315
|
-
if (right.length <
|
|
57367
|
+
if (right.length < constants3.v8MaxSafeChunkSize) {
|
|
57316
57368
|
list.push(...right);
|
|
57317
57369
|
} else {
|
|
57318
57370
|
while (chunkStart < right.length) {
|
|
57319
|
-
list.push(...right.slice(chunkStart, chunkStart +
|
|
57320
|
-
chunkStart +=
|
|
57371
|
+
list.push(...right.slice(chunkStart, chunkStart + constants3.v8MaxSafeChunkSize));
|
|
57372
|
+
chunkStart += constants3.v8MaxSafeChunkSize;
|
|
57321
57373
|
}
|
|
57322
57374
|
}
|
|
57323
57375
|
}
|
|
@@ -57489,7 +57541,7 @@ function tokenizeContent(effects, ok2) {
|
|
|
57489
57541
|
ok(code !== codes.eof && !markdownLineEnding(code), "expected no eof or eol");
|
|
57490
57542
|
effects.enter(types2.content);
|
|
57491
57543
|
previous2 = effects.enter(types2.chunkContent, {
|
|
57492
|
-
contentType:
|
|
57544
|
+
contentType: constants3.contentTypeContent
|
|
57493
57545
|
});
|
|
57494
57546
|
return chunkInside(code);
|
|
57495
57547
|
}
|
|
@@ -57514,7 +57566,7 @@ function tokenizeContent(effects, ok2) {
|
|
|
57514
57566
|
effects.exit(types2.chunkContent);
|
|
57515
57567
|
ok(previous2, "expected previous token");
|
|
57516
57568
|
previous2.next = effects.enter(types2.chunkContent, {
|
|
57517
|
-
contentType:
|
|
57569
|
+
contentType: constants3.contentTypeContent,
|
|
57518
57570
|
previous: previous2
|
|
57519
57571
|
});
|
|
57520
57572
|
previous2 = previous2.next;
|
|
@@ -57538,7 +57590,7 @@ function tokenizeContinuation(effects, ok2, nok) {
|
|
|
57538
57590
|
}
|
|
57539
57591
|
ok(self.parser.constructs.disable.null, "expected `disable.null` to be populated");
|
|
57540
57592
|
const tail = self.events[self.events.length - 1];
|
|
57541
|
-
if (!self.parser.constructs.disable.null.includes("codeIndented") && tail && tail[1].type === types2.linePrefix && tail[2].sliceSerialize(tail[1], true).length >=
|
|
57593
|
+
if (!self.parser.constructs.disable.null.includes("codeIndented") && tail && tail[1].type === types2.linePrefix && tail[2].sliceSerialize(tail[1], true).length >= constants3.tabSize) {
|
|
57542
57594
|
return ok2(code);
|
|
57543
57595
|
}
|
|
57544
57596
|
return effects.interrupt(self.parser.constructs.flow, nok, ok2)(code);
|
|
@@ -57564,7 +57616,7 @@ function factoryDestination(effects, ok2, nok, type, literalType2, literalMarker
|
|
|
57564
57616
|
effects.enter(type);
|
|
57565
57617
|
effects.enter(rawType);
|
|
57566
57618
|
effects.enter(stringType2);
|
|
57567
|
-
effects.enter(types2.chunkString, { contentType:
|
|
57619
|
+
effects.enter(types2.chunkString, { contentType: constants3.contentTypeString });
|
|
57568
57620
|
return raw(code);
|
|
57569
57621
|
}
|
|
57570
57622
|
function enclosedBefore(code) {
|
|
@@ -57577,7 +57629,7 @@ function factoryDestination(effects, ok2, nok, type, literalType2, literalMarker
|
|
|
57577
57629
|
return ok2;
|
|
57578
57630
|
}
|
|
57579
57631
|
effects.enter(stringType2);
|
|
57580
|
-
effects.enter(types2.chunkString, { contentType:
|
|
57632
|
+
effects.enter(types2.chunkString, { contentType: constants3.contentTypeString });
|
|
57581
57633
|
return enclosed(code);
|
|
57582
57634
|
}
|
|
57583
57635
|
function enclosed(code) {
|
|
@@ -57648,7 +57700,7 @@ function factoryLabel(effects, ok2, nok, type, markerType, stringType2) {
|
|
|
57648
57700
|
return atBreak;
|
|
57649
57701
|
}
|
|
57650
57702
|
function atBreak(code) {
|
|
57651
|
-
if (size >
|
|
57703
|
+
if (size > constants3.linkReferenceSizeMax || code === codes.eof || code === codes.leftSquareBracket || code === codes.rightSquareBracket && !seen || code === codes.caret && !size && "_hiddenFootnoteSupport" in self.parser.constructs) {
|
|
57652
57704
|
return nok(code);
|
|
57653
57705
|
}
|
|
57654
57706
|
if (code === codes.rightSquareBracket) {
|
|
@@ -57665,11 +57717,11 @@ function factoryLabel(effects, ok2, nok, type, markerType, stringType2) {
|
|
|
57665
57717
|
effects.exit(types2.lineEnding);
|
|
57666
57718
|
return atBreak;
|
|
57667
57719
|
}
|
|
57668
|
-
effects.enter(types2.chunkString, { contentType:
|
|
57720
|
+
effects.enter(types2.chunkString, { contentType: constants3.contentTypeString });
|
|
57669
57721
|
return labelInside(code);
|
|
57670
57722
|
}
|
|
57671
57723
|
function labelInside(code) {
|
|
57672
|
-
if (code === codes.eof || code === codes.leftSquareBracket || code === codes.rightSquareBracket || markdownLineEnding(code) || size++ >
|
|
57724
|
+
if (code === codes.eof || code === codes.leftSquareBracket || code === codes.rightSquareBracket || markdownLineEnding(code) || size++ > constants3.linkReferenceSizeMax) {
|
|
57673
57725
|
effects.exit(types2.chunkString);
|
|
57674
57726
|
return atBreak(code);
|
|
57675
57727
|
}
|
|
@@ -57728,7 +57780,7 @@ function factoryTitle(effects, ok2, nok, type, markerType, stringType2) {
|
|
|
57728
57780
|
effects.exit(types2.lineEnding);
|
|
57729
57781
|
return factorySpace(effects, atBreak, types2.linePrefix);
|
|
57730
57782
|
}
|
|
57731
|
-
effects.enter(types2.chunkString, { contentType:
|
|
57783
|
+
effects.enter(types2.chunkString, { contentType: constants3.contentTypeString });
|
|
57732
57784
|
return inside(code);
|
|
57733
57785
|
}
|
|
57734
57786
|
function inside(code) {
|
|
@@ -57879,7 +57931,7 @@ function resolveHeadingAtx(events, context) {
|
|
|
57879
57931
|
type: types2.chunkText,
|
|
57880
57932
|
start: events[contentStart][1].start,
|
|
57881
57933
|
end: events[contentEnd][1].end,
|
|
57882
|
-
contentType:
|
|
57934
|
+
contentType: constants3.contentTypeText
|
|
57883
57935
|
};
|
|
57884
57936
|
splice(events, contentStart, contentEnd - contentStart + 1, [
|
|
57885
57937
|
["enter", content3, context],
|
|
@@ -57903,7 +57955,7 @@ function tokenizeHeadingAtx(effects, ok2, nok) {
|
|
|
57903
57955
|
return sequenceOpen(code);
|
|
57904
57956
|
}
|
|
57905
57957
|
function sequenceOpen(code) {
|
|
57906
|
-
if (code === codes.numberSign && size++ <
|
|
57958
|
+
if (code === codes.numberSign && size++ < constants3.atxHeadingOpeningFenceSizeMax) {
|
|
57907
57959
|
effects.consume(code);
|
|
57908
57960
|
return sequenceOpen;
|
|
57909
57961
|
}
|
|
@@ -58068,7 +58120,7 @@ function tokenizeHtmlFlow(effects, ok2, nok) {
|
|
|
58068
58120
|
}
|
|
58069
58121
|
if (code === codes.questionMark) {
|
|
58070
58122
|
effects.consume(code);
|
|
58071
|
-
marker =
|
|
58123
|
+
marker = constants3.htmlInstruction;
|
|
58072
58124
|
return self.interrupt ? ok2 : continuationDeclarationInside;
|
|
58073
58125
|
}
|
|
58074
58126
|
if (asciiAlpha(code)) {
|
|
@@ -58082,18 +58134,18 @@ function tokenizeHtmlFlow(effects, ok2, nok) {
|
|
|
58082
58134
|
function declarationOpen(code) {
|
|
58083
58135
|
if (code === codes.dash) {
|
|
58084
58136
|
effects.consume(code);
|
|
58085
|
-
marker =
|
|
58137
|
+
marker = constants3.htmlComment;
|
|
58086
58138
|
return commentOpenInside;
|
|
58087
58139
|
}
|
|
58088
58140
|
if (code === codes.leftSquareBracket) {
|
|
58089
58141
|
effects.consume(code);
|
|
58090
|
-
marker =
|
|
58142
|
+
marker = constants3.htmlCdata;
|
|
58091
58143
|
index = 0;
|
|
58092
58144
|
return cdataOpenInside;
|
|
58093
58145
|
}
|
|
58094
58146
|
if (asciiAlpha(code)) {
|
|
58095
58147
|
effects.consume(code);
|
|
58096
|
-
marker =
|
|
58148
|
+
marker = constants3.htmlDeclaration;
|
|
58097
58149
|
return self.interrupt ? ok2 : continuationDeclarationInside;
|
|
58098
58150
|
}
|
|
58099
58151
|
return nok(code);
|
|
@@ -58106,7 +58158,7 @@ function tokenizeHtmlFlow(effects, ok2, nok) {
|
|
|
58106
58158
|
return nok(code);
|
|
58107
58159
|
}
|
|
58108
58160
|
function cdataOpenInside(code) {
|
|
58109
|
-
const value =
|
|
58161
|
+
const value = constants3.cdataOpeningString;
|
|
58110
58162
|
if (code === value.charCodeAt(index++)) {
|
|
58111
58163
|
effects.consume(code);
|
|
58112
58164
|
if (index === value.length) {
|
|
@@ -58130,18 +58182,18 @@ function tokenizeHtmlFlow(effects, ok2, nok) {
|
|
|
58130
58182
|
const slash = code === codes.slash;
|
|
58131
58183
|
const name = buffer.toLowerCase();
|
|
58132
58184
|
if (!slash && !closingTag && htmlRawNames.includes(name)) {
|
|
58133
|
-
marker =
|
|
58185
|
+
marker = constants3.htmlRaw;
|
|
58134
58186
|
return self.interrupt ? ok2(code) : continuation(code);
|
|
58135
58187
|
}
|
|
58136
58188
|
if (htmlBlockNames.includes(buffer.toLowerCase())) {
|
|
58137
|
-
marker =
|
|
58189
|
+
marker = constants3.htmlBasic;
|
|
58138
58190
|
if (slash) {
|
|
58139
58191
|
effects.consume(code);
|
|
58140
58192
|
return basicSelfClosing;
|
|
58141
58193
|
}
|
|
58142
58194
|
return self.interrupt ? ok2(code) : continuation(code);
|
|
58143
58195
|
}
|
|
58144
|
-
marker =
|
|
58196
|
+
marker = constants3.htmlComplete;
|
|
58145
58197
|
return self.interrupt && !self.parser.lazy[self.now().line] ? nok(code) : closingTag ? completeClosingTagAfter(code) : completeAttributeNameBefore(code);
|
|
58146
58198
|
}
|
|
58147
58199
|
if (code === codes.dash || asciiAlphanumeric(code)) {
|
|
@@ -58256,27 +58308,27 @@ function tokenizeHtmlFlow(effects, ok2, nok) {
|
|
|
58256
58308
|
return nok(code);
|
|
58257
58309
|
}
|
|
58258
58310
|
function continuation(code) {
|
|
58259
|
-
if (code === codes.dash && marker ===
|
|
58311
|
+
if (code === codes.dash && marker === constants3.htmlComment) {
|
|
58260
58312
|
effects.consume(code);
|
|
58261
58313
|
return continuationCommentInside;
|
|
58262
58314
|
}
|
|
58263
|
-
if (code === codes.lessThan && marker ===
|
|
58315
|
+
if (code === codes.lessThan && marker === constants3.htmlRaw) {
|
|
58264
58316
|
effects.consume(code);
|
|
58265
58317
|
return continuationRawTagOpen;
|
|
58266
58318
|
}
|
|
58267
|
-
if (code === codes.greaterThan && marker ===
|
|
58319
|
+
if (code === codes.greaterThan && marker === constants3.htmlDeclaration) {
|
|
58268
58320
|
effects.consume(code);
|
|
58269
58321
|
return continuationClose;
|
|
58270
58322
|
}
|
|
58271
|
-
if (code === codes.questionMark && marker ===
|
|
58323
|
+
if (code === codes.questionMark && marker === constants3.htmlInstruction) {
|
|
58272
58324
|
effects.consume(code);
|
|
58273
58325
|
return continuationDeclarationInside;
|
|
58274
58326
|
}
|
|
58275
|
-
if (code === codes.rightSquareBracket && marker ===
|
|
58327
|
+
if (code === codes.rightSquareBracket && marker === constants3.htmlCdata) {
|
|
58276
58328
|
effects.consume(code);
|
|
58277
58329
|
return continuationCdataInside;
|
|
58278
58330
|
}
|
|
58279
|
-
if (markdownLineEnding(code) && (marker ===
|
|
58331
|
+
if (markdownLineEnding(code) && (marker === constants3.htmlBasic || marker === constants3.htmlComplete)) {
|
|
58280
58332
|
effects.exit(types2.htmlFlowData);
|
|
58281
58333
|
return effects.check(blankLineBefore, continuationAfter, continuationStart)(code);
|
|
58282
58334
|
}
|
|
@@ -58328,7 +58380,7 @@ function tokenizeHtmlFlow(effects, ok2, nok) {
|
|
|
58328
58380
|
}
|
|
58329
58381
|
return continuation(code);
|
|
58330
58382
|
}
|
|
58331
|
-
if (asciiAlpha(code) && buffer.length <
|
|
58383
|
+
if (asciiAlpha(code) && buffer.length < constants3.htmlRawSizeMax) {
|
|
58332
58384
|
ok(code !== null);
|
|
58333
58385
|
effects.consume(code);
|
|
58334
58386
|
buffer += String.fromCharCode(code);
|
|
@@ -58348,7 +58400,7 @@ function tokenizeHtmlFlow(effects, ok2, nok) {
|
|
|
58348
58400
|
effects.consume(code);
|
|
58349
58401
|
return continuationClose;
|
|
58350
58402
|
}
|
|
58351
|
-
if (code === codes.dash && marker ===
|
|
58403
|
+
if (code === codes.dash && marker === constants3.htmlComment) {
|
|
58352
58404
|
effects.consume(code);
|
|
58353
58405
|
return continuationDeclarationInside;
|
|
58354
58406
|
}
|
|
@@ -58476,7 +58528,7 @@ function tokenizeHtmlText(effects, ok2, nok) {
|
|
|
58476
58528
|
return code === codes.greaterThan ? end(code) : code === codes.dash ? commentClose(code) : comment(code);
|
|
58477
58529
|
}
|
|
58478
58530
|
function cdataOpenInside(code) {
|
|
58479
|
-
const value =
|
|
58531
|
+
const value = constants3.cdataOpeningString;
|
|
58480
58532
|
if (code === value.charCodeAt(index++)) {
|
|
58481
58533
|
effects.consume(code);
|
|
58482
58534
|
return index === value.length ? cdata : cdataOpenInside;
|
|
@@ -58692,7 +58744,7 @@ function tokenizeHtmlText(effects, ok2, nok) {
|
|
|
58692
58744
|
}
|
|
58693
58745
|
function lineEndingAfter(code) {
|
|
58694
58746
|
ok(self.parser.constructs.disable.null, "expected `disable.null` to be populated");
|
|
58695
|
-
return markdownSpace(code) ? factorySpace(effects, lineEndingAfterPrefix, types2.linePrefix, self.parser.constructs.disable.null.includes("codeIndented") ? undefined :
|
|
58747
|
+
return markdownSpace(code) ? factorySpace(effects, lineEndingAfterPrefix, types2.linePrefix, self.parser.constructs.disable.null.includes("codeIndented") ? undefined : constants3.tabSize)(code) : lineEndingAfterPrefix(code);
|
|
58696
58748
|
}
|
|
58697
58749
|
function lineEndingAfterPrefix(code) {
|
|
58698
58750
|
effects.enter(types2.htmlTextData);
|
|
@@ -58855,7 +58907,7 @@ function tokenizeResource(effects, ok2, nok) {
|
|
|
58855
58907
|
if (code === codes.rightParenthesis) {
|
|
58856
58908
|
return resourceEnd(code);
|
|
58857
58909
|
}
|
|
58858
|
-
return factoryDestination(effects, resourceDestinationAfter, resourceDestinationMissing, types2.resourceDestination, types2.resourceDestinationLiteral, types2.resourceDestinationLiteralMarker, types2.resourceDestinationRaw, types2.resourceDestinationString,
|
|
58910
|
+
return factoryDestination(effects, resourceDestinationAfter, resourceDestinationMissing, types2.resourceDestination, types2.resourceDestinationLiteral, types2.resourceDestinationLiteralMarker, types2.resourceDestinationRaw, types2.resourceDestinationString, constants3.linkResourceDestinationBalanceMax)(code);
|
|
58859
58911
|
}
|
|
58860
58912
|
function resourceDestinationAfter(code) {
|
|
58861
58913
|
return markdownLineEndingOrSpace(code) ? factoryWhitespace(effects, resourceBetween)(code) : resourceEnd(code);
|
|
@@ -59006,7 +59058,7 @@ function tokenizeThematicBreak(effects, ok2, nok) {
|
|
|
59006
59058
|
effects.enter(types2.thematicBreakSequence);
|
|
59007
59059
|
return sequence(code);
|
|
59008
59060
|
}
|
|
59009
|
-
if (size >=
|
|
59061
|
+
if (size >= constants3.thematicBreakMarkerCountMin && (code === codes.eof || markdownLineEnding(code))) {
|
|
59010
59062
|
effects.exit(types2.thematicBreak);
|
|
59011
59063
|
return ok2(code);
|
|
59012
59064
|
}
|
|
@@ -59063,7 +59115,7 @@ function tokenizeListStart(effects, ok2, nok) {
|
|
|
59063
59115
|
}
|
|
59064
59116
|
function inside(code) {
|
|
59065
59117
|
ok(self.containerState, "expected state");
|
|
59066
|
-
if (asciiDigit(code) && ++size <
|
|
59118
|
+
if (asciiDigit(code) && ++size < constants3.listItemValueSizeMax) {
|
|
59067
59119
|
effects.consume(code);
|
|
59068
59120
|
return inside;
|
|
59069
59121
|
}
|
|
@@ -59130,7 +59182,7 @@ function tokenizeListContinuation(effects, ok2, nok) {
|
|
|
59130
59182
|
self.containerState._closeFlow = true;
|
|
59131
59183
|
self.interrupt = undefined;
|
|
59132
59184
|
ok(self.parser.constructs.disable.null, "expected `disable.null` to be populated");
|
|
59133
|
-
return factorySpace(effects, effects.attempt(list, ok2, nok), types2.linePrefix, self.parser.constructs.disable.null.includes("codeIndented") ? undefined :
|
|
59185
|
+
return factorySpace(effects, effects.attempt(list, ok2, nok), types2.linePrefix, self.parser.constructs.disable.null.includes("codeIndented") ? undefined : constants3.tabSize)(code);
|
|
59134
59186
|
}
|
|
59135
59187
|
}
|
|
59136
59188
|
function tokenizeIndent(effects, ok2, nok) {
|
|
@@ -59152,7 +59204,7 @@ function tokenizeListEnd(effects) {
|
|
|
59152
59204
|
function tokenizeListItemPrefixWhitespace(effects, ok2, nok) {
|
|
59153
59205
|
const self = this;
|
|
59154
59206
|
ok(self.parser.constructs.disable.null, "expected `disable.null` to be populated");
|
|
59155
|
-
return factorySpace(effects, afterPrefix, types2.listItemPrefixWhitespace, self.parser.constructs.disable.null.includes("codeIndented") ? undefined :
|
|
59207
|
+
return factorySpace(effects, afterPrefix, types2.listItemPrefixWhitespace, self.parser.constructs.disable.null.includes("codeIndented") ? undefined : constants3.tabSize + 1);
|
|
59156
59208
|
function afterPrefix(code) {
|
|
59157
59209
|
const tail = self.events[self.events.length - 1];
|
|
59158
59210
|
return !markdownSpace(code) && tail && tail[1].type === types2.listItemPrefixWhitespace ? ok2(code) : nok(code);
|
|
@@ -59390,7 +59442,7 @@ function resolveAllLineSuffixes(events, context) {
|
|
|
59390
59442
|
}
|
|
59391
59443
|
if (size) {
|
|
59392
59444
|
const token = {
|
|
59393
|
-
type: eventIndex === events.length || tabs || size <
|
|
59445
|
+
type: eventIndex === events.length || tabs || size < constants3.hardBreakPrefixSizeMin ? types2.lineSuffix : types2.hardBreakTrailing,
|
|
59394
59446
|
start: {
|
|
59395
59447
|
_bufferIndex: index ? bufferIndex : data.start._bufferIndex + bufferIndex,
|
|
59396
59448
|
_index: data.start._index + index,
|
|
@@ -59880,7 +59932,7 @@ function preprocess() {
|
|
|
59880
59932
|
break;
|
|
59881
59933
|
}
|
|
59882
59934
|
case codes.ht: {
|
|
59883
|
-
next = Math.ceil(column /
|
|
59935
|
+
next = Math.ceil(column / constants3.tabSize) * constants3.tabSize;
|
|
59884
59936
|
chunks.push(codes.horizontalTab);
|
|
59885
59937
|
while (column++ < next)
|
|
59886
59938
|
chunks.push(codes.virtualSpace);
|
|
@@ -59922,7 +59974,7 @@ function decode($0, $1, $2) {
|
|
|
59922
59974
|
if (head === codes.numberSign) {
|
|
59923
59975
|
const head2 = $2.charCodeAt(1);
|
|
59924
59976
|
const hex = head2 === codes.lowercaseX || head2 === codes.uppercaseX;
|
|
59925
|
-
return decodeNumericCharacterReference($2.slice(hex ? 2 : 1), hex ?
|
|
59977
|
+
return decodeNumericCharacterReference($2.slice(hex ? 2 : 1), hex ? constants3.numericBaseHexadecimal : constants3.numericBaseDecimal);
|
|
59926
59978
|
}
|
|
59927
59979
|
return decodeNamedCharacterReference($2) || $0;
|
|
59928
59980
|
}
|
|
@@ -60259,7 +60311,7 @@ function compiler(options) {
|
|
|
60259
60311
|
const ancestor = this.stack[this.stack.length - 2];
|
|
60260
60312
|
ok(ancestor, "expected nodes on stack");
|
|
60261
60313
|
ok(ancestor.type === "list", "expected list on stack");
|
|
60262
|
-
ancestor.start = Number.parseInt(this.sliceSerialize(token),
|
|
60314
|
+
ancestor.start = Number.parseInt(this.sliceSerialize(token), constants3.numericBaseDecimal);
|
|
60263
60315
|
this.data.expectingFirstListItemValue = undefined;
|
|
60264
60316
|
}
|
|
60265
60317
|
}
|
|
@@ -60500,7 +60552,7 @@ function compiler(options) {
|
|
|
60500
60552
|
const type = this.data.characterReferenceType;
|
|
60501
60553
|
let value;
|
|
60502
60554
|
if (type) {
|
|
60503
|
-
value = decodeNumericCharacterReference(data2, type === types2.characterReferenceMarkerNumeric ?
|
|
60555
|
+
value = decodeNumericCharacterReference(data2, type === types2.characterReferenceMarkerNumeric ? constants3.numericBaseDecimal : constants3.numericBaseHexadecimal);
|
|
60504
60556
|
this.data.characterReferenceType = undefined;
|
|
60505
60557
|
} else {
|
|
60506
60558
|
const result = decodeNamedCharacterReference(data2);
|
|
@@ -61116,7 +61168,7 @@ function tokenizeGfmFootnoteCall(effects, ok2, nok) {
|
|
|
61116
61168
|
return callData;
|
|
61117
61169
|
}
|
|
61118
61170
|
function callData(code2) {
|
|
61119
|
-
if (size >
|
|
61171
|
+
if (size > constants3.linkReferenceSizeMax || code2 === codes.rightSquareBracket && !data || code2 === codes.eof || code2 === codes.leftSquareBracket || markdownLineEndingOrSpace(code2)) {
|
|
61120
61172
|
return nok(code2);
|
|
61121
61173
|
}
|
|
61122
61174
|
if (code2 === codes.rightSquareBracket) {
|
|
@@ -61175,7 +61227,7 @@ function tokenizeDefinitionStart(effects, ok2, nok) {
|
|
|
61175
61227
|
return nok(code2);
|
|
61176
61228
|
}
|
|
61177
61229
|
function labelInside(code2) {
|
|
61178
|
-
if (size >
|
|
61230
|
+
if (size > constants3.linkReferenceSizeMax || code2 === codes.rightSquareBracket && !data || code2 === codes.eof || code2 === codes.leftSquareBracket || markdownLineEndingOrSpace(code2)) {
|
|
61179
61231
|
return nok(code2);
|
|
61180
61232
|
}
|
|
61181
61233
|
if (code2 === codes.rightSquareBracket) {
|
|
@@ -61227,10 +61279,10 @@ function gfmFootnoteDefinitionEnd(effects) {
|
|
|
61227
61279
|
}
|
|
61228
61280
|
function tokenizeIndent2(effects, ok2, nok) {
|
|
61229
61281
|
const self = this;
|
|
61230
|
-
return factorySpace(effects, afterPrefix, "gfmFootnoteDefinitionIndent",
|
|
61282
|
+
return factorySpace(effects, afterPrefix, "gfmFootnoteDefinitionIndent", constants3.tabSize + 1);
|
|
61231
61283
|
function afterPrefix(code2) {
|
|
61232
61284
|
const tail = self.events[self.events.length - 1];
|
|
61233
|
-
return tail && tail[1].type === "gfmFootnoteDefinitionIndent" && tail[2].sliceSerialize(tail[1], true).length ===
|
|
61285
|
+
return tail && tail[1].type === "gfmFootnoteDefinitionIndent" && tail[2].sliceSerialize(tail[1], true).length === constants3.tabSize ? ok2(code2) : nok(code2);
|
|
61234
61286
|
}
|
|
61235
61287
|
}
|
|
61236
61288
|
// ../node_modules/.bun/micromark-extension-gfm-strikethrough@2.1.0/node_modules/micromark-extension-gfm-strikethrough/dev/lib/syntax.js
|
|
@@ -61326,8 +61378,8 @@ function gfmStrikethrough(options) {
|
|
|
61326
61378
|
return nok(code2);
|
|
61327
61379
|
const token = effects.exit("strikethroughSequenceTemporary");
|
|
61328
61380
|
const after = classifyCharacter(code2);
|
|
61329
|
-
token._open = !after || after ===
|
|
61330
|
-
token._close = !before || before ===
|
|
61381
|
+
token._open = !after || after === constants3.attentionSideAfter && Boolean(before);
|
|
61382
|
+
token._close = !before || before === constants3.attentionSideAfter && Boolean(after);
|
|
61331
61383
|
return ok2(code2);
|
|
61332
61384
|
}
|
|
61333
61385
|
}
|
|
@@ -61511,7 +61563,7 @@ function tokenizeTable(effects, ok2, nok) {
|
|
|
61511
61563
|
seen = false;
|
|
61512
61564
|
if (markdownSpace(code2)) {
|
|
61513
61565
|
ok(self.parser.constructs.disable.null, "expected `disabled.null`");
|
|
61514
|
-
return factorySpace(effects, headDelimiterBefore, types2.linePrefix, self.parser.constructs.disable.null.includes("codeIndented") ? undefined :
|
|
61566
|
+
return factorySpace(effects, headDelimiterBefore, types2.linePrefix, self.parser.constructs.disable.null.includes("codeIndented") ? undefined : constants3.tabSize)(code2);
|
|
61515
61567
|
}
|
|
61516
61568
|
return headDelimiterBefore(code2);
|
|
61517
61569
|
}
|
|
@@ -61762,7 +61814,7 @@ function flushCell(map, context, range, rowKind, rowEnd, previousCell) {
|
|
|
61762
61814
|
const end = context.events[range[3]];
|
|
61763
61815
|
start[1].end = Object.assign({}, end[1].end);
|
|
61764
61816
|
start[1].type = types2.chunkText;
|
|
61765
|
-
start[1].contentType =
|
|
61817
|
+
start[1].contentType = constants3.contentTypeText;
|
|
61766
61818
|
if (range[3] > range[2] + 1) {
|
|
61767
61819
|
const a = range[2] + 1;
|
|
61768
61820
|
const b = range[3] - range[2] - 1;
|
|
@@ -63186,6 +63238,18 @@ function createChatLock() {
|
|
|
63186
63238
|
|
|
63187
63239
|
// retry-api-call.ts
|
|
63188
63240
|
var import_grammy6 = __toESM(require_mod2(), 1);
|
|
63241
|
+
function classifyBenignTelegram4002(errorCode, description) {
|
|
63242
|
+
if (errorCode !== 400)
|
|
63243
|
+
return null;
|
|
63244
|
+
const desc = (description ?? "").toLowerCase();
|
|
63245
|
+
if (desc.includes("not modified"))
|
|
63246
|
+
return "not_modified";
|
|
63247
|
+
if (desc.includes("message to edit not found"))
|
|
63248
|
+
return "message_not_found";
|
|
63249
|
+
if (desc.includes("message to delete not found"))
|
|
63250
|
+
return "delete_not_found";
|
|
63251
|
+
return null;
|
|
63252
|
+
}
|
|
63189
63253
|
function isLocalResourceError2(err) {
|
|
63190
63254
|
const code2 = err?.code;
|
|
63191
63255
|
if (typeof code2 === "string" && ["ENOSPC", "EDQUOT", "EIO", "ENOMEM"].includes(code2)) {
|
|
@@ -63270,14 +63334,9 @@ function createRetryApiCall2(config = {}) {
|
|
|
63270
63334
|
await sleep(delayMs);
|
|
63271
63335
|
continue;
|
|
63272
63336
|
}
|
|
63273
|
-
|
|
63274
|
-
|
|
63275
|
-
|
|
63276
|
-
}
|
|
63277
|
-
if (isGrammyErr && err.error_code === 400 && (desc.includes("message to edit not found") || desc.includes("message to delete not found"))) {
|
|
63278
|
-
observer?.onBenign?.({
|
|
63279
|
-
kind: desc.includes("edit") ? "message_not_found" : "delete_not_found"
|
|
63280
|
-
});
|
|
63337
|
+
const benignKind = isGrammyErr ? classifyBenignTelegram4002(err.error_code, desc) : null;
|
|
63338
|
+
if (benignKind !== null) {
|
|
63339
|
+
observer?.onBenign?.({ kind: benignKind });
|
|
63281
63340
|
return;
|
|
63282
63341
|
}
|
|
63283
63342
|
if (isGrammyErr && err.error_code === 400 && desc.includes("thread not found") && opts?.threadId && opts?.chat_id) {
|
|
@@ -63425,7 +63484,7 @@ function editFloodFuseConfigFromEnv(env) {
|
|
|
63425
63484
|
}
|
|
63426
63485
|
return cfg;
|
|
63427
63486
|
}
|
|
63428
|
-
var DROPPED_RESULT = true;
|
|
63487
|
+
var DROPPED_RESULT = { ok: true, result: true };
|
|
63429
63488
|
function createEditFloodFuse(config = {}) {
|
|
63430
63489
|
const enabled2 = config.enabled ?? true;
|
|
63431
63490
|
const clock = config.clock ?? systemClock;
|
|
@@ -63683,12 +63742,12 @@ function createEditFloodFuse(config = {}) {
|
|
|
63683
63742
|
const msgKey = `m:${chat}:${msg}`;
|
|
63684
63743
|
const mw = win(msgKey);
|
|
63685
63744
|
mw.inflight++;
|
|
63745
|
+
const dropGuard = () => mw.inflight > 1;
|
|
63746
|
+
const lateKey = cls === "cosmetic" ? `lr:${chat}` : undefined;
|
|
63686
63747
|
try {
|
|
63687
|
-
const msgSlot = await awaitRoom(msgKey, perMessageWindowMs, cls === "cosmetic" ? (t) => ceiling(cosmeticPerMessageMax, t) : (t) => classCeiling(perMessageMax, cls, t), method, "supersede", cls,
|
|
63748
|
+
const msgSlot = await awaitRoom(msgKey, perMessageWindowMs, cls === "cosmetic" ? (t) => ceiling(cosmeticPerMessageMax, t) : (t) => classCeiling(perMessageMax, cls, t), method, "supersede", cls, dropGuard, deadline, lateKey);
|
|
63688
63749
|
if (msgSlot === null)
|
|
63689
63750
|
return DROPPED_RESULT;
|
|
63690
|
-
const dropGuard = () => mw.inflight > 1;
|
|
63691
|
-
const lateKey = cls === "cosmetic" ? `lr:${chat}` : undefined;
|
|
63692
63751
|
const reserved = [[msgKey, msgSlot]];
|
|
63693
63752
|
const giveBack = () => {
|
|
63694
63753
|
for (const [k, at] of reserved)
|
|
@@ -64607,6 +64666,11 @@ function formatTgPostTags(tags) {
|
|
|
64607
64666
|
}
|
|
64608
64667
|
return parts.length > 0 ? " " + parts.join(" ") : "";
|
|
64609
64668
|
}
|
|
64669
|
+
function shortDesc(raw) {
|
|
64670
|
+
if (!raw)
|
|
64671
|
+
return "-";
|
|
64672
|
+
return raw.replace(/\s+/g, " ").slice(0, 80).replace(/[\r\n]/g, " ") || "-";
|
|
64673
|
+
}
|
|
64610
64674
|
function installTgPostLogger(bot) {
|
|
64611
64675
|
bot.api.config.use(async (prev, method, payload, signal) => {
|
|
64612
64676
|
const p = payload ?? {};
|
|
@@ -64617,20 +64681,28 @@ function installTgPostLogger(bot) {
|
|
|
64617
64681
|
const bytes = text4.length;
|
|
64618
64682
|
const hash = bytes > 0 ? createHash3("sha1").update(text4).digest("hex").slice(0, 12) : "-";
|
|
64619
64683
|
const tagSuffix = formatTgPostTags(_getTgPostTags());
|
|
64684
|
+
const emit = (status, errClass, code2, desc) => {
|
|
64685
|
+
if (!shouldEmitTgPost(method, status))
|
|
64686
|
+
return;
|
|
64687
|
+
process.stderr.write(`tg-post method=${method} chat=${chat} thread=${thread} parse_mode=${parseMode} bytes=${bytes} hash=${hash} status=${status} err=${errClass} code=${code2} desc=${desc}${tagSuffix}
|
|
64688
|
+
`);
|
|
64689
|
+
};
|
|
64620
64690
|
try {
|
|
64621
64691
|
const res = await prev(method, payload, signal);
|
|
64622
|
-
|
|
64623
|
-
|
|
64624
|
-
|
|
64692
|
+
const r = res;
|
|
64693
|
+
if (r != null && typeof r === "object" && r.ok === false) {
|
|
64694
|
+
const code2 = r.error_code;
|
|
64695
|
+
const benign = classifyBenignTelegram400(code2, r.description);
|
|
64696
|
+
emit(benign !== null ? "benign" : "err", `telegram_${code2 ?? "unknown"}`, code2 != null ? String(code2) : "-", shortDesc(r.description));
|
|
64697
|
+
return res;
|
|
64625
64698
|
}
|
|
64699
|
+
emit("ok", "-", "-", "-");
|
|
64626
64700
|
return res;
|
|
64627
64701
|
} catch (err) {
|
|
64628
64702
|
const errClass = err instanceof import_grammy7.GrammyError ? `grammy_${err.error_code}` : err?.constructor?.name ?? "Error";
|
|
64629
64703
|
const code2 = err instanceof import_grammy7.GrammyError ? String(err.error_code) : "-";
|
|
64630
64704
|
const rawDesc = err instanceof import_grammy7.GrammyError ? err.description : err instanceof Error ? err.message : "";
|
|
64631
|
-
|
|
64632
|
-
process.stderr.write(`tg-post method=${method} chat=${chat} thread=${thread} parse_mode=${parseMode} bytes=${bytes} hash=${hash} status=err err=${errClass} code=${code2} desc=${desc}${tagSuffix}
|
|
64633
|
-
`);
|
|
64705
|
+
emit("err", errClass, code2, shortDesc(rawDesc));
|
|
64634
64706
|
throw err;
|
|
64635
64707
|
}
|
|
64636
64708
|
});
|
|
@@ -64660,7 +64732,7 @@ import {
|
|
|
64660
64732
|
mkdirSync as mkdirSync16,
|
|
64661
64733
|
chmodSync as chmodSync6,
|
|
64662
64734
|
unlinkSync as unlinkSync11,
|
|
64663
|
-
renameSync as
|
|
64735
|
+
renameSync as renameSync10
|
|
64664
64736
|
} from "node:fs";
|
|
64665
64737
|
import { dirname as dirname9, join as join19 } from "node:path";
|
|
64666
64738
|
var FLOOD_STATE_FILE2 = "flood-wait.json";
|
|
@@ -64867,7 +64939,7 @@ function writeFloodWindow(path2, record, now) {
|
|
|
64867
64939
|
const arr = [...byScope.values()];
|
|
64868
64940
|
const tmp = `${path2}.tmp-${process.pid}`;
|
|
64869
64941
|
writeFileSync13(tmp, JSON.stringify(arr), { mode: FLOOD_STATE_MODE2 });
|
|
64870
|
-
|
|
64942
|
+
renameSync10(tmp, path2);
|
|
64871
64943
|
try {
|
|
64872
64944
|
chmodSync6(path2, FLOOD_STATE_MODE2);
|
|
64873
64945
|
} catch {}
|
|
@@ -71141,6 +71213,9 @@ function projectTranscriptLine(line) {
|
|
|
71141
71213
|
if (op === "dequeue") {
|
|
71142
71214
|
return [{ kind: "dequeue" }];
|
|
71143
71215
|
}
|
|
71216
|
+
if (op === "remove") {
|
|
71217
|
+
return [{ kind: "queue_remove", rawContent: obj.content ?? "" }];
|
|
71218
|
+
}
|
|
71144
71219
|
return [];
|
|
71145
71220
|
}
|
|
71146
71221
|
if (type === "assistant") {
|
|
@@ -72946,10 +73021,10 @@ function resolveExhaustUntil(resetAtMs, now = Date.now()) {
|
|
|
72946
73021
|
|
|
72947
73022
|
// gateway/auth-add-flow.ts
|
|
72948
73023
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
72949
|
-
import { existsSync as existsSync21, mkdirSync as mkdirSync24, readFileSync as readFileSync22, readdirSync as readdirSync6, rmSync as
|
|
73024
|
+
import { existsSync as existsSync21, mkdirSync as mkdirSync24, readFileSync as readFileSync22, readdirSync as readdirSync6, rmSync as rmSync6, statSync as statSync9, writeFileSync as writeFileSync20 } from "node:fs";
|
|
72950
73025
|
import { homedir as homedir8 } from "node:os";
|
|
72951
73026
|
import { join as join29 } from "node:path";
|
|
72952
|
-
import { randomBytes as
|
|
73027
|
+
import { randomBytes as randomBytes9 } from "node:crypto";
|
|
72953
73028
|
|
|
72954
73029
|
// ../src/auth/manager.ts
|
|
72955
73030
|
import {
|
|
@@ -72959,7 +73034,7 @@ import {
|
|
|
72959
73034
|
writeFileSync as writeFileSync19,
|
|
72960
73035
|
mkdirSync as mkdirSync23,
|
|
72961
73036
|
mkdtempSync as mkdtempSync2,
|
|
72962
|
-
rmSync as
|
|
73037
|
+
rmSync as rmSync5,
|
|
72963
73038
|
chmodSync as chmodSync7,
|
|
72964
73039
|
statSync as statSync8
|
|
72965
73040
|
} from "node:fs";
|
|
@@ -73054,12 +73129,12 @@ function makeAuthAddTmuxOps(tmuxBin = "tmux") {
|
|
|
73054
73129
|
}
|
|
73055
73130
|
var pendingAuthAddFlows = new Map;
|
|
73056
73131
|
function pickScratchDir(label, home2 = homedir8()) {
|
|
73057
|
-
const suffix =
|
|
73132
|
+
const suffix = randomBytes9(8).toString("hex");
|
|
73058
73133
|
return join29(home2, ".switchroom", "accounts", ".in-progress", `${label}-${suffix}`);
|
|
73059
73134
|
}
|
|
73060
73135
|
function cleanScratchDir(scratchDir) {
|
|
73061
73136
|
try {
|
|
73062
|
-
|
|
73137
|
+
rmSync6(scratchDir, { recursive: true, force: true });
|
|
73063
73138
|
} catch {}
|
|
73064
73139
|
}
|
|
73065
73140
|
var AUTH_TMUX_SESSION_FILE = ".auth-tmux-session";
|
|
@@ -76377,7 +76452,7 @@ import {
|
|
|
76377
76452
|
mkdirSync as mkdirSync26,
|
|
76378
76453
|
readFileSync as readFileSync23,
|
|
76379
76454
|
readdirSync as readdirSync7,
|
|
76380
|
-
renameSync as
|
|
76455
|
+
renameSync as renameSync11,
|
|
76381
76456
|
statSync as statSync10,
|
|
76382
76457
|
unlinkSync as unlinkSync13,
|
|
76383
76458
|
writeFileSync as writeFileSync21,
|
|
@@ -76413,7 +76488,7 @@ function writeOutboxRecordAtomic(record, stateDir) {
|
|
|
76413
76488
|
return true;
|
|
76414
76489
|
const tmpPath = join31(dir, `.${record.turnNonce}.${process.pid}.tmp`);
|
|
76415
76490
|
writeFileSync21(tmpPath, JSON.stringify(record), { mode: 384 });
|
|
76416
|
-
|
|
76491
|
+
renameSync11(tmpPath, finalPath);
|
|
76417
76492
|
return true;
|
|
76418
76493
|
} catch {
|
|
76419
76494
|
return false;
|
|
@@ -76440,7 +76515,7 @@ function claimRecord(nonce, stateDir) {
|
|
|
76440
76515
|
const from = join31(dir, `${nonce}.json`);
|
|
76441
76516
|
const to = join31(dir, `${nonce}.sending`);
|
|
76442
76517
|
try {
|
|
76443
|
-
|
|
76518
|
+
renameSync11(from, to);
|
|
76444
76519
|
return to;
|
|
76445
76520
|
} catch {
|
|
76446
76521
|
return null;
|
|
@@ -76449,7 +76524,7 @@ function claimRecord(nonce, stateDir) {
|
|
|
76449
76524
|
function releaseClaim(nonce, stateDir) {
|
|
76450
76525
|
const dir = resolveOutboxDir(stateDir);
|
|
76451
76526
|
try {
|
|
76452
|
-
|
|
76527
|
+
renameSync11(join31(dir, `${nonce}.sending`), join31(dir, `${nonce}.json`));
|
|
76453
76528
|
} catch {}
|
|
76454
76529
|
}
|
|
76455
76530
|
function removeClaimed(nonce, stateDir) {
|
|
@@ -76469,7 +76544,7 @@ function reclaimStaleSending(stateDir, now = Date.now()) {
|
|
|
76469
76544
|
try {
|
|
76470
76545
|
const st = statSync10(join31(dir, f));
|
|
76471
76546
|
if (now - st.mtimeMs > OUTBOX_SENDING_TIMEOUT_MS) {
|
|
76472
|
-
|
|
76547
|
+
renameSync11(join31(dir, f), join31(dir, f.replace(/\.sending$/, ".json")));
|
|
76473
76548
|
}
|
|
76474
76549
|
} catch {}
|
|
76475
76550
|
}
|
|
@@ -76543,7 +76618,7 @@ function compactJournalIfLarge(path2) {
|
|
|
76543
76618
|
writeFileSync21(tmp, kept.join(`
|
|
76544
76619
|
`) + `
|
|
76545
76620
|
`, { mode: 384 });
|
|
76546
|
-
|
|
76621
|
+
renameSync11(tmp, path2);
|
|
76547
76622
|
} catch {}
|
|
76548
76623
|
}
|
|
76549
76624
|
function clearOutboxRecord(nonce, stateDir) {
|
|
@@ -76607,7 +76682,7 @@ import {
|
|
|
76607
76682
|
existsSync as existsSync24,
|
|
76608
76683
|
mkdirSync as mkdirSync27,
|
|
76609
76684
|
readFileSync as readFileSync24,
|
|
76610
|
-
renameSync as
|
|
76685
|
+
renameSync as renameSync12,
|
|
76611
76686
|
writeFileSync as writeFileSync22,
|
|
76612
76687
|
appendFileSync as appendFileSync5
|
|
76613
76688
|
} from "node:fs";
|
|
@@ -76741,7 +76816,7 @@ function compactIfLarge(path2) {
|
|
|
76741
76816
|
writeFileSync22(tmp, kept.join(`
|
|
76742
76817
|
`) + `
|
|
76743
76818
|
`, { mode: 384 });
|
|
76744
|
-
|
|
76819
|
+
renameSync12(tmp, path2);
|
|
76745
76820
|
} catch {}
|
|
76746
76821
|
}
|
|
76747
76822
|
|
|
@@ -77198,7 +77273,7 @@ function eagerVoiceEnabled2() {
|
|
|
77198
77273
|
}
|
|
77199
77274
|
|
|
77200
77275
|
// photo-precheck.ts
|
|
77201
|
-
import { closeSync as
|
|
77276
|
+
import { closeSync as closeSync6, fstatSync, openSync as openSync6, readSync } from "node:fs";
|
|
77202
77277
|
var PHOTO_MAX_DIMENSION_SUM = 1e4;
|
|
77203
77278
|
var PHOTO_MAX_ASPECT_RATIO = 10;
|
|
77204
77279
|
var PHOTO_MAX_BYTES = 10 * 1024 * 1024;
|
|
@@ -77279,7 +77354,7 @@ var JPEG_PROBE_BYTES = 64 * 1024;
|
|
|
77279
77354
|
function probeImageFile(path2) {
|
|
77280
77355
|
let fd;
|
|
77281
77356
|
try {
|
|
77282
|
-
fd =
|
|
77357
|
+
fd = openSync6(path2, "r");
|
|
77283
77358
|
const bytes = fstatSync(fd).size;
|
|
77284
77359
|
const headBuf = Buffer.alloc(HEADER_PROBE_BYTES);
|
|
77285
77360
|
const headRead = readSync(fd, headBuf, 0, HEADER_PROBE_BYTES, 0);
|
|
@@ -77298,7 +77373,7 @@ function probeImageFile(path2) {
|
|
|
77298
77373
|
} finally {
|
|
77299
77374
|
if (fd !== undefined) {
|
|
77300
77375
|
try {
|
|
77301
|
-
|
|
77376
|
+
closeSync6(fd);
|
|
77302
77377
|
} catch {}
|
|
77303
77378
|
}
|
|
77304
77379
|
}
|
|
@@ -79526,10 +79601,10 @@ function detectStatusSurfaceDegraded(t) {
|
|
|
79526
79601
|
|
|
79527
79602
|
// gateway/turn-active-marker.ts
|
|
79528
79603
|
import {
|
|
79529
|
-
closeSync as
|
|
79604
|
+
closeSync as closeSync7,
|
|
79530
79605
|
existsSync as existsSync28,
|
|
79531
79606
|
mkdirSync as mkdirSync31,
|
|
79532
|
-
openSync as
|
|
79607
|
+
openSync as openSync7,
|
|
79533
79608
|
readFileSync as readFileSync26,
|
|
79534
79609
|
statSync as statSync12,
|
|
79535
79610
|
unlinkSync as unlinkSync15,
|
|
@@ -79555,8 +79630,8 @@ function touchTurnActiveMarker(stateDir) {
|
|
|
79555
79630
|
utimesSync(path2, now, now);
|
|
79556
79631
|
} catch {
|
|
79557
79632
|
try {
|
|
79558
|
-
const fd =
|
|
79559
|
-
|
|
79633
|
+
const fd = openSync7(path2, "r+");
|
|
79634
|
+
closeSync7(fd);
|
|
79560
79635
|
} catch {}
|
|
79561
79636
|
}
|
|
79562
79637
|
}
|
|
@@ -79742,6 +79817,195 @@ function decideFallbackTeardownNotice2(input) {
|
|
|
79742
79817
|
}
|
|
79743
79818
|
|
|
79744
79819
|
// gateway/stream-render.ts
|
|
79820
|
+
var PARKED_TURN_START_MAX = 16;
|
|
79821
|
+
var PARKED_TURN_START_TTL_MS = 30 * 60000;
|
|
79822
|
+
var parkedTurnStarts = [];
|
|
79823
|
+
function pruneParkedTurnStarts(now) {
|
|
79824
|
+
for (let i = parkedTurnStarts.length - 1;i >= 0; i--) {
|
|
79825
|
+
if (now - parkedTurnStarts[i].parkedAt > PARKED_TURN_START_TTL_MS) {
|
|
79826
|
+
const [dropped] = parkedTurnStarts.splice(i, 1);
|
|
79827
|
+
process.stderr.write(`telegram gateway: parked-turn-start expired chat=${dropped.chatId ?? "-"} ` + `msg=${dropped.messageId ?? "-"} age_ms=${now - dropped.parkedAt}
|
|
79828
|
+
`);
|
|
79829
|
+
}
|
|
79830
|
+
}
|
|
79831
|
+
}
|
|
79832
|
+
function parkTurnStart(env, now) {
|
|
79833
|
+
parkedTurnStarts.push({ ...env, parkedAt: now });
|
|
79834
|
+
while (parkedTurnStarts.length > PARKED_TURN_START_MAX) {
|
|
79835
|
+
const [dropped] = parkedTurnStarts.splice(0, 1);
|
|
79836
|
+
process.stderr.write(`telegram gateway: parked-turn-start evicted (cap ${PARKED_TURN_START_MAX}) ` + `chat=${dropped.chatId ?? "-"} msg=${dropped.messageId ?? "-"}
|
|
79837
|
+
`);
|
|
79838
|
+
}
|
|
79839
|
+
}
|
|
79840
|
+
function takeParkedTurnStart() {
|
|
79841
|
+
return parkedTurnStarts.pop() ?? null;
|
|
79842
|
+
}
|
|
79843
|
+
function discardParkedTurnStart(rawContent) {
|
|
79844
|
+
for (let i = parkedTurnStarts.length - 1;i >= 0; i--) {
|
|
79845
|
+
if (parkedTurnStarts[i].rawContent === rawContent) {
|
|
79846
|
+
parkedTurnStarts.splice(i, 1);
|
|
79847
|
+
return true;
|
|
79848
|
+
}
|
|
79849
|
+
}
|
|
79850
|
+
return false;
|
|
79851
|
+
}
|
|
79852
|
+
function beginTurn(deps, ev) {
|
|
79853
|
+
const {
|
|
79854
|
+
HANDBACK_PRETURN_ENABLED,
|
|
79855
|
+
STATE_DIR,
|
|
79856
|
+
clearActivitySummary,
|
|
79857
|
+
extractUserPromptPreview,
|
|
79858
|
+
getCurrentTurn,
|
|
79859
|
+
getPendingPtyPartial,
|
|
79860
|
+
handbackPreturnSignal,
|
|
79861
|
+
handlePtyPartial,
|
|
79862
|
+
isDmChatId,
|
|
79863
|
+
makeNarrativeGate,
|
|
79864
|
+
pendingCrossTurnGate,
|
|
79865
|
+
preambleSuppressor,
|
|
79866
|
+
promoteQueuedStatus,
|
|
79867
|
+
rememberRecentTurn,
|
|
79868
|
+
scheduleEarlyLivenessOpen,
|
|
79869
|
+
setCurrentTurn,
|
|
79870
|
+
setPendingPtyPartial,
|
|
79871
|
+
startTurnTypingLoop,
|
|
79872
|
+
statusKey,
|
|
79873
|
+
turnsDb,
|
|
79874
|
+
typingWrapper
|
|
79875
|
+
} = deps;
|
|
79876
|
+
typingWrapper.drainAll();
|
|
79877
|
+
if (ev.chatId) {
|
|
79878
|
+
const enqThreadId = ev.threadId != null ? Number(ev.threadId) : undefined;
|
|
79879
|
+
clearPending2(statusKey(ev.chatId, enqThreadId), "handback");
|
|
79880
|
+
}
|
|
79881
|
+
if (ev.chatId) {
|
|
79882
|
+
const prior = getCurrentTurn();
|
|
79883
|
+
if (prior?.answerStream != null) {
|
|
79884
|
+
prior.answerStream.forceNewMessage();
|
|
79885
|
+
prior.answerStream.stop();
|
|
79886
|
+
prior.answerStream = null;
|
|
79887
|
+
}
|
|
79888
|
+
if (prior?.orphanedReplyTimeoutId != null) {
|
|
79889
|
+
clearTimeout(prior.orphanedReplyTimeoutId);
|
|
79890
|
+
prior.orphanedReplyTimeoutId = null;
|
|
79891
|
+
}
|
|
79892
|
+
prior?.narrativeGate?.teardown();
|
|
79893
|
+
if (prior != null && prior.endedAt == null) {
|
|
79894
|
+
clearActivitySummary(prior);
|
|
79895
|
+
process.stderr.write(`telegram gateway: ${formatTurnLifecycle("clear", "superseded", prior, Date.now())}
|
|
79896
|
+
`);
|
|
79897
|
+
}
|
|
79898
|
+
const startedAt = Date.now();
|
|
79899
|
+
const enqThreadIdNum = ev.threadId != null ? Number(ev.threadId) : undefined;
|
|
79900
|
+
const turnId = deriveTurnId(ev.chatId, enqThreadIdNum ?? null, ev.messageId) ?? `${chatKey(ev.chatId, enqThreadIdNum ?? null)}#synthetic-${startedAt}`;
|
|
79901
|
+
const xTurnGateKey = turnId;
|
|
79902
|
+
const consumedCrossTurnGate = pendingCrossTurnGate.get(xTurnGateKey);
|
|
79903
|
+
if (consumedCrossTurnGate != null)
|
|
79904
|
+
pendingCrossTurnGate.delete(xTurnGateKey);
|
|
79905
|
+
const next = {
|
|
79906
|
+
sessionChatId: ev.chatId,
|
|
79907
|
+
sessionThreadId: enqThreadIdNum,
|
|
79908
|
+
sourceMessageId: parseSourceMessageId(ev.messageId),
|
|
79909
|
+
startedAt,
|
|
79910
|
+
gatewayReceiveAt: startedAt,
|
|
79911
|
+
role: deriveTurnRole(ev.rawContent),
|
|
79912
|
+
...consumedCrossTurnGate != null ? { crossTurnGate: consumedCrossTurnGate } : {},
|
|
79913
|
+
replyCalled: false,
|
|
79914
|
+
finalAnswerDelivered: false,
|
|
79915
|
+
finalAnswerSubstantive: false,
|
|
79916
|
+
finalAnswerEverDelivered: false,
|
|
79917
|
+
answerDelivered: false,
|
|
79918
|
+
flushedAnswerText: null,
|
|
79919
|
+
endedAt: null,
|
|
79920
|
+
firstPingAt: null,
|
|
79921
|
+
firstPingWasSubstantive: false,
|
|
79922
|
+
silentAnchorMessageId: null,
|
|
79923
|
+
silentAnchorText: "",
|
|
79924
|
+
capturedText: [],
|
|
79925
|
+
capturedBlockMeta: [],
|
|
79926
|
+
orphanedReplyTimeoutId: null,
|
|
79927
|
+
answerReadyFlushTimeoutId: null,
|
|
79928
|
+
liveness: new LivenessTracker(startedAt),
|
|
79929
|
+
turnId,
|
|
79930
|
+
registryKey: null,
|
|
79931
|
+
noReplyDrainTimer: null,
|
|
79932
|
+
lastAssistantMsgId: null,
|
|
79933
|
+
lastAssistantDone: false,
|
|
79934
|
+
toolCallCount: 0,
|
|
79935
|
+
labeledToolCount: 0,
|
|
79936
|
+
totalTokens: 0,
|
|
79937
|
+
seenUsageMessageIds: new Set,
|
|
79938
|
+
activityMessageId: null,
|
|
79939
|
+
activityInFlight: null,
|
|
79940
|
+
activityPendingRender: null,
|
|
79941
|
+
activityLastSentRender: null,
|
|
79942
|
+
activityEverOpened: false,
|
|
79943
|
+
activityDrainFailures: 0,
|
|
79944
|
+
mirrorLines: [],
|
|
79945
|
+
narrativeGate: undefined,
|
|
79946
|
+
lastReplyText: "",
|
|
79947
|
+
foregroundSubAgents: new Map,
|
|
79948
|
+
answerStream: null,
|
|
79949
|
+
isDm: isDmChatId(ev.chatId),
|
|
79950
|
+
emissionAuthority: new EmissionAuthority(statusKey(ev.chatId, enqThreadIdNum))
|
|
79951
|
+
};
|
|
79952
|
+
next.narrativeGate = makeNarrativeGate(next);
|
|
79953
|
+
if (HANDBACK_PRETURN_ENABLED) {
|
|
79954
|
+
const handbackAdoption = handbackPreturnSignal.tryAdopt(turnId);
|
|
79955
|
+
if (handbackAdoption != null) {
|
|
79956
|
+
if (handbackAdoption.activityMessageId != null) {
|
|
79957
|
+
next.activityMessageId = handbackAdoption.activityMessageId;
|
|
79958
|
+
next.activityEverOpened = true;
|
|
79959
|
+
}
|
|
79960
|
+
process.stderr.write(`telegram gateway: handback pre-turn adopted turnId=${turnId} ` + `key=${handbackAdoption.statusKey} card=${handbackAdoption.activityMessageId ?? "none"}
|
|
79961
|
+
`);
|
|
79962
|
+
}
|
|
79963
|
+
}
|
|
79964
|
+
startTurnTypingLoop(ev.chatId, enqThreadIdNum ?? null);
|
|
79965
|
+
setCurrentTurn(next, statusKey(ev.chatId, enqThreadIdNum));
|
|
79966
|
+
scheduleEarlyLivenessOpen(next);
|
|
79967
|
+
process.stderr.write(`telegram gateway: ${formatTurnLifecycle("set", "enqueue", next, startedAt)}
|
|
79968
|
+
`);
|
|
79969
|
+
rememberRecentTurn(next);
|
|
79970
|
+
promoteQueuedStatus(ev.chatId, enqThreadIdNum);
|
|
79971
|
+
shadowEmit({
|
|
79972
|
+
kind: "turnStart",
|
|
79973
|
+
key: statusKey(ev.chatId, ev.threadId != null ? Number(ev.threadId) : undefined),
|
|
79974
|
+
at: startedAt
|
|
79975
|
+
});
|
|
79976
|
+
preambleSuppressor.reset();
|
|
79977
|
+
clearSilentEndState2(statusKey(ev.chatId, ev.threadId != null ? Number(ev.threadId) : null));
|
|
79978
|
+
if (turnsDb != null) {
|
|
79979
|
+
const evThreadIdNum = ev.threadId != null ? Number(ev.threadId) : null;
|
|
79980
|
+
const turnKey3 = chatKeyWithSuffix(ev.chatId, evThreadIdNum, String(startedAt));
|
|
79981
|
+
next.registryKey = turnKey3;
|
|
79982
|
+
const userPromptPreview = extractUserPromptPreview(ev.rawContent);
|
|
79983
|
+
try {
|
|
79984
|
+
recordTurnStart(turnsDb, {
|
|
79985
|
+
turnKey: turnKey3,
|
|
79986
|
+
chatId: String(ev.chatId),
|
|
79987
|
+
threadId: ev.threadId != null ? String(ev.threadId) : null,
|
|
79988
|
+
lastUserMsgId: ev.messageId != null ? String(ev.messageId) : null,
|
|
79989
|
+
userPromptPreview
|
|
79990
|
+
});
|
|
79991
|
+
} catch (err) {
|
|
79992
|
+
process.stderr.write(`telegram gateway: recordTurnStart failed turnKey=${turnKey3}: ${err.message}
|
|
79993
|
+
`);
|
|
79994
|
+
}
|
|
79995
|
+
writeTurnActiveMarker(STATE_DIR, {
|
|
79996
|
+
turnKey: turnKey3,
|
|
79997
|
+
chatId: String(ev.chatId),
|
|
79998
|
+
threadId: ev.threadId != null ? String(ev.threadId) : null,
|
|
79999
|
+
startedAt
|
|
80000
|
+
});
|
|
80001
|
+
}
|
|
80002
|
+
const pending = getPendingPtyPartial();
|
|
80003
|
+
if (pending != null) {
|
|
80004
|
+
setPendingPtyPartial(null);
|
|
80005
|
+
handlePtyPartial(pending);
|
|
80006
|
+
}
|
|
80007
|
+
}
|
|
80008
|
+
}
|
|
79745
80009
|
function handleSessionEvent(deps, ev) {
|
|
79746
80010
|
const {
|
|
79747
80011
|
ANSWER_LANE,
|
|
@@ -79838,140 +80102,47 @@ function handleSessionEvent(deps, ev) {
|
|
|
79838
80102
|
}
|
|
79839
80103
|
switch (ev.kind) {
|
|
79840
80104
|
case "enqueue": {
|
|
79841
|
-
|
|
79842
|
-
|
|
79843
|
-
const enqThreadId = ev.threadId != null ? Number(ev.threadId) : undefined;
|
|
79844
|
-
clearPending2(statusKey(ev.chatId, enqThreadId), "handback");
|
|
79845
|
-
}
|
|
80105
|
+
const enqThreadIdNum = ev.threadId != null ? Number(ev.threadId) : undefined;
|
|
80106
|
+
const now = Date.now();
|
|
79846
80107
|
if (ev.chatId) {
|
|
79847
|
-
const prior = getCurrentTurn();
|
|
79848
|
-
if (prior?.answerStream != null) {
|
|
79849
|
-
prior.answerStream.forceNewMessage();
|
|
79850
|
-
prior.answerStream.stop();
|
|
79851
|
-
prior.answerStream = null;
|
|
79852
|
-
}
|
|
79853
|
-
if (prior?.orphanedReplyTimeoutId != null) {
|
|
79854
|
-
clearTimeout(prior.orphanedReplyTimeoutId);
|
|
79855
|
-
prior.orphanedReplyTimeoutId = null;
|
|
79856
|
-
}
|
|
79857
|
-
prior?.narrativeGate?.teardown();
|
|
79858
|
-
const startedAt = Date.now();
|
|
79859
|
-
const enqThreadIdNum = ev.threadId != null ? Number(ev.threadId) : undefined;
|
|
79860
|
-
const turnId = deriveTurnId(ev.chatId, enqThreadIdNum ?? null, ev.messageId) ?? `${chatKey(ev.chatId, enqThreadIdNum ?? null)}#synthetic-${startedAt}`;
|
|
79861
|
-
const xTurnGateKey = turnId;
|
|
79862
|
-
const consumedCrossTurnGate = pendingCrossTurnGate.get(xTurnGateKey);
|
|
79863
|
-
if (consumedCrossTurnGate != null)
|
|
79864
|
-
pendingCrossTurnGate.delete(xTurnGateKey);
|
|
79865
|
-
const next = {
|
|
79866
|
-
sessionChatId: ev.chatId,
|
|
79867
|
-
sessionThreadId: enqThreadIdNum,
|
|
79868
|
-
sourceMessageId: parseSourceMessageId(ev.messageId),
|
|
79869
|
-
startedAt,
|
|
79870
|
-
gatewayReceiveAt: startedAt,
|
|
79871
|
-
role: deriveTurnRole(ev.rawContent),
|
|
79872
|
-
...consumedCrossTurnGate != null ? { crossTurnGate: consumedCrossTurnGate } : {},
|
|
79873
|
-
replyCalled: false,
|
|
79874
|
-
finalAnswerDelivered: false,
|
|
79875
|
-
finalAnswerSubstantive: false,
|
|
79876
|
-
finalAnswerEverDelivered: false,
|
|
79877
|
-
answerDelivered: false,
|
|
79878
|
-
flushedAnswerText: null,
|
|
79879
|
-
endedAt: null,
|
|
79880
|
-
firstPingAt: null,
|
|
79881
|
-
firstPingWasSubstantive: false,
|
|
79882
|
-
silentAnchorMessageId: null,
|
|
79883
|
-
silentAnchorText: "",
|
|
79884
|
-
capturedText: [],
|
|
79885
|
-
capturedBlockMeta: [],
|
|
79886
|
-
orphanedReplyTimeoutId: null,
|
|
79887
|
-
answerReadyFlushTimeoutId: null,
|
|
79888
|
-
liveness: new LivenessTracker(startedAt),
|
|
79889
|
-
turnId,
|
|
79890
|
-
registryKey: null,
|
|
79891
|
-
noReplyDrainTimer: null,
|
|
79892
|
-
lastAssistantMsgId: null,
|
|
79893
|
-
lastAssistantDone: false,
|
|
79894
|
-
toolCallCount: 0,
|
|
79895
|
-
labeledToolCount: 0,
|
|
79896
|
-
totalTokens: 0,
|
|
79897
|
-
seenUsageMessageIds: new Set,
|
|
79898
|
-
activityMessageId: null,
|
|
79899
|
-
activityInFlight: null,
|
|
79900
|
-
activityPendingRender: null,
|
|
79901
|
-
activityLastSentRender: null,
|
|
79902
|
-
activityEverOpened: false,
|
|
79903
|
-
activityDrainFailures: 0,
|
|
79904
|
-
mirrorLines: [],
|
|
79905
|
-
narrativeGate: undefined,
|
|
79906
|
-
lastReplyText: "",
|
|
79907
|
-
foregroundSubAgents: new Map,
|
|
79908
|
-
answerStream: null,
|
|
79909
|
-
isDm: isDmChatId(ev.chatId),
|
|
79910
|
-
emissionAuthority: new EmissionAuthority(statusKey(ev.chatId, enqThreadIdNum))
|
|
79911
|
-
};
|
|
79912
|
-
next.narrativeGate = makeNarrativeGate(next);
|
|
79913
|
-
if (HANDBACK_PRETURN_ENABLED) {
|
|
79914
|
-
const handbackAdoption = handbackPreturnSignal.tryAdopt(turnId);
|
|
79915
|
-
if (handbackAdoption != null) {
|
|
79916
|
-
if (handbackAdoption.activityMessageId != null) {
|
|
79917
|
-
next.activityMessageId = handbackAdoption.activityMessageId;
|
|
79918
|
-
next.activityEverOpened = true;
|
|
79919
|
-
}
|
|
79920
|
-
process.stderr.write(`telegram gateway: handback pre-turn adopted turnId=${turnId} ` + `key=${handbackAdoption.statusKey} card=${handbackAdoption.activityMessageId ?? "none"}
|
|
79921
|
-
`);
|
|
79922
|
-
}
|
|
79923
|
-
}
|
|
79924
|
-
startTurnTypingLoop(ev.chatId, enqThreadIdNum ?? null);
|
|
79925
|
-
setCurrentTurn(next, statusKey(ev.chatId, enqThreadIdNum));
|
|
79926
|
-
scheduleEarlyLivenessOpen(next);
|
|
79927
|
-
process.stderr.write(`telegram gateway: ${formatTurnLifecycle("set", "enqueue", next, startedAt)}
|
|
79928
|
-
`);
|
|
79929
|
-
rememberRecentTurn(next);
|
|
79930
|
-
promoteQueuedStatus(ev.chatId, enqThreadIdNum);
|
|
79931
80108
|
if (DELIVERY_CONFIRM_ENABLED) {
|
|
79932
80109
|
ackDelivery(deliveryQueue, chatKey(ev.chatId, ev.threadId != null ? Number(ev.threadId) : null), ev.messageId, ev.rawContent);
|
|
79933
80110
|
}
|
|
79934
|
-
shadowEmit({
|
|
79935
|
-
kind: "turnStart",
|
|
79936
|
-
key: statusKey(ev.chatId, ev.threadId != null ? Number(ev.threadId) : undefined),
|
|
79937
|
-
at: startedAt
|
|
79938
|
-
});
|
|
79939
|
-
preambleSuppressor.reset();
|
|
79940
|
-
clearSilentEndState2(statusKey(ev.chatId, ev.threadId != null ? Number(ev.threadId) : null));
|
|
79941
|
-
if (turnsDb != null) {
|
|
79942
|
-
const evThreadIdNum = ev.threadId != null ? Number(ev.threadId) : null;
|
|
79943
|
-
const turnKey3 = chatKeyWithSuffix(ev.chatId, evThreadIdNum, String(startedAt));
|
|
79944
|
-
next.registryKey = turnKey3;
|
|
79945
|
-
const userPromptPreview = extractUserPromptPreview(ev.rawContent);
|
|
79946
|
-
try {
|
|
79947
|
-
recordTurnStart(turnsDb, {
|
|
79948
|
-
turnKey: turnKey3,
|
|
79949
|
-
chatId: String(ev.chatId),
|
|
79950
|
-
threadId: ev.threadId != null ? String(ev.threadId) : null,
|
|
79951
|
-
lastUserMsgId: ev.messageId != null ? String(ev.messageId) : null,
|
|
79952
|
-
userPromptPreview
|
|
79953
|
-
});
|
|
79954
|
-
} catch (err) {
|
|
79955
|
-
process.stderr.write(`telegram gateway: recordTurnStart failed turnKey=${turnKey3}: ${err.message}
|
|
79956
|
-
`);
|
|
79957
|
-
}
|
|
79958
|
-
writeTurnActiveMarker(STATE_DIR, {
|
|
79959
|
-
turnKey: turnKey3,
|
|
79960
|
-
chatId: String(ev.chatId),
|
|
79961
|
-
threadId: ev.threadId != null ? String(ev.threadId) : null,
|
|
79962
|
-
startedAt
|
|
79963
|
-
});
|
|
79964
|
-
}
|
|
79965
|
-
const pending = getPendingPtyPartial();
|
|
79966
|
-
if (pending != null) {
|
|
79967
|
-
setPendingPtyPartial(null);
|
|
79968
|
-
handlePtyPartial(pending);
|
|
79969
|
-
}
|
|
79970
80111
|
}
|
|
80112
|
+
pruneParkedTurnStarts(now);
|
|
80113
|
+
if (!ev.chatId) {
|
|
80114
|
+
beginTurn(deps, ev);
|
|
80115
|
+
return;
|
|
80116
|
+
}
|
|
80117
|
+
const live = getCurrentTurn();
|
|
80118
|
+
const sessionBusy = live != null && live.endedAt == null;
|
|
80119
|
+
if (!sessionBusy && parkedTurnStarts.length === 0) {
|
|
80120
|
+
beginTurn(deps, ev);
|
|
80121
|
+
return;
|
|
80122
|
+
}
|
|
80123
|
+
parkTurnStart({
|
|
80124
|
+
chatId: ev.chatId,
|
|
80125
|
+
messageId: ev.messageId,
|
|
80126
|
+
threadId: ev.threadId,
|
|
80127
|
+
rawContent: ev.rawContent
|
|
80128
|
+
}, now);
|
|
80129
|
+
process.stderr.write(`telegram gateway: turn-start parked (session busy) chat=${ev.chatId} ` + `thread=${enqThreadIdNum ?? "-"} msg=${ev.messageId ?? "-"} ` + `parked=${parkedTurnStarts.length}
|
|
80130
|
+
`);
|
|
80131
|
+
return;
|
|
80132
|
+
}
|
|
80133
|
+
case "dequeue": {
|
|
80134
|
+
pruneParkedTurnStarts(Date.now());
|
|
80135
|
+
const parked = takeParkedTurnStart();
|
|
80136
|
+
if (parked == null)
|
|
80137
|
+
return;
|
|
80138
|
+
beginTurn(deps, parked);
|
|
79971
80139
|
return;
|
|
79972
80140
|
}
|
|
79973
|
-
case "
|
|
80141
|
+
case "queue_remove": {
|
|
80142
|
+
pruneParkedTurnStarts(Date.now());
|
|
80143
|
+
discardParkedTurnStart(ev.rawContent);
|
|
79974
80144
|
return;
|
|
80145
|
+
}
|
|
79975
80146
|
case "model": {
|
|
79976
80147
|
const turn = getCurrentTurn();
|
|
79977
80148
|
if (turn != null) {
|
|
@@ -80882,7 +81053,8 @@ function createNarrativeLane(deps) {
|
|
|
80882
81053
|
toolCount: turn.labeledToolCount,
|
|
80883
81054
|
state: final ? "done" : "running",
|
|
80884
81055
|
model: turn.currentModel,
|
|
80885
|
-
totalTokens: turn.totalTokens
|
|
81056
|
+
totalTokens: turn.totalTokens,
|
|
81057
|
+
resultText: final ? turn.lastReplyText : undefined
|
|
80886
81058
|
};
|
|
80887
81059
|
return renderActivityFeedWithNested(turn.mirrorLines, childLines, final, liveSuffix, stepCount, header);
|
|
80888
81060
|
}
|
|
@@ -81199,7 +81371,8 @@ function createNarrativeLane(deps) {
|
|
|
81199
81371
|
elapsedMs: livenessElapsed,
|
|
81200
81372
|
toolCount: turn.labeledToolCount,
|
|
81201
81373
|
state: "done",
|
|
81202
|
-
model: turn.currentModel
|
|
81374
|
+
model: turn.currentModel,
|
|
81375
|
+
resultText: turn.lastReplyText
|
|
81203
81376
|
};
|
|
81204
81377
|
finalHtml = renderActivityFeedWithNested(["Working\u2026"], [], true, "", undefined, livenessHeader);
|
|
81205
81378
|
}
|
|
@@ -81569,7 +81742,7 @@ function resolveAgentDirFromEnv() {
|
|
|
81569
81742
|
}
|
|
81570
81743
|
|
|
81571
81744
|
// active-reactions.ts
|
|
81572
|
-
import { readFileSync as readFileSync27, writeFileSync as writeFileSync25, renameSync as
|
|
81745
|
+
import { readFileSync as readFileSync27, writeFileSync as writeFileSync25, renameSync as renameSync13, existsSync as existsSync29, unlinkSync as unlinkSync16 } from "node:fs";
|
|
81573
81746
|
import { join as join37 } from "node:path";
|
|
81574
81747
|
var ACTIVE_REACTIONS_FILENAME = ".active-reactions.json";
|
|
81575
81748
|
function reactionsPath(agentDir) {
|
|
@@ -81615,7 +81788,7 @@ function writeActiveReactions(agentDir, reactions) {
|
|
|
81615
81788
|
try {
|
|
81616
81789
|
writeFileSync25(tmp, JSON.stringify(reactions) + `
|
|
81617
81790
|
`, "utf-8");
|
|
81618
|
-
|
|
81791
|
+
renameSync13(tmp, p);
|
|
81619
81792
|
} catch {}
|
|
81620
81793
|
}
|
|
81621
81794
|
function addActiveReaction(agentDir, reaction) {
|
|
@@ -81637,7 +81810,7 @@ function clearActiveReactions(agentDir) {
|
|
|
81637
81810
|
}
|
|
81638
81811
|
|
|
81639
81812
|
// active-reactions.ts
|
|
81640
|
-
import { readFileSync as readFileSync28, writeFileSync as writeFileSync26, renameSync as
|
|
81813
|
+
import { readFileSync as readFileSync28, writeFileSync as writeFileSync26, renameSync as renameSync14, existsSync as existsSync30, unlinkSync as unlinkSync17 } from "node:fs";
|
|
81641
81814
|
import { join as join38 } from "node:path";
|
|
81642
81815
|
var ACTIVE_REACTIONS_FILENAME2 = ".active-reactions.json";
|
|
81643
81816
|
function reactionsPath2(agentDir) {
|
|
@@ -83866,7 +84039,7 @@ async function menuWithBannerStatic(deps, banner) {
|
|
|
83866
84039
|
}
|
|
83867
84040
|
|
|
83868
84041
|
// gateway/session-model-file.ts
|
|
83869
|
-
import { readFileSync as readFileSync30, writeFileSync as writeFileSync27, renameSync as
|
|
84042
|
+
import { readFileSync as readFileSync30, writeFileSync as writeFileSync27, renameSync as renameSync15, rmSync as rmSync7 } from "node:fs";
|
|
83870
84043
|
import { join as join40 } from "node:path";
|
|
83871
84044
|
var SESSION_MODEL_FILE = ".session-model";
|
|
83872
84045
|
var CONFIGURED_DEFAULT_MODEL_FILE = ".configured-default-model";
|
|
@@ -83874,7 +84047,7 @@ var SESSION_MODEL_BOOT_ATTEMPTS_FILE = ".session-model-boot-attempts";
|
|
|
83874
84047
|
function atomicWrite(path2, content3) {
|
|
83875
84048
|
const tmp = `${path2}.tmp-${process.pid}-${Date.now()}`;
|
|
83876
84049
|
writeFileSync27(tmp, content3, "utf8");
|
|
83877
|
-
|
|
84050
|
+
renameSync15(tmp, path2);
|
|
83878
84051
|
}
|
|
83879
84052
|
function serializeSessionModel(rec) {
|
|
83880
84053
|
return `${JSON.stringify({
|
|
@@ -83889,7 +84062,7 @@ function writeSessionModelFile(agentDir, model, configuredDefaultAtWrite) {
|
|
|
83889
84062
|
throw new Error(`refusing to persist non-canonical session model token: ${JSON.stringify(model)}`);
|
|
83890
84063
|
}
|
|
83891
84064
|
try {
|
|
83892
|
-
|
|
84065
|
+
rmSync7(join40(agentDir, SESSION_MODEL_BOOT_ATTEMPTS_FILE), { force: true });
|
|
83893
84066
|
} catch {}
|
|
83894
84067
|
atomicWrite(join40(agentDir, SESSION_MODEL_FILE), serializeSessionModel({ model, configuredDefaultAtWrite, ts: Date.now() }));
|
|
83895
84068
|
}
|
|
@@ -83902,15 +84075,15 @@ function readSessionModelFileRaw(agentDir) {
|
|
|
83902
84075
|
}
|
|
83903
84076
|
function clearSessionModelFile(agentDir) {
|
|
83904
84077
|
try {
|
|
83905
|
-
|
|
84078
|
+
rmSync7(join40(agentDir, SESSION_MODEL_FILE), { force: true });
|
|
83906
84079
|
} catch {}
|
|
83907
84080
|
}
|
|
83908
84081
|
function consumeSessionModelCarrierOnHealthyBoot(agentDir) {
|
|
83909
84082
|
try {
|
|
83910
|
-
|
|
84083
|
+
rmSync7(join40(agentDir, SESSION_MODEL_FILE), { force: true });
|
|
83911
84084
|
} catch {}
|
|
83912
84085
|
try {
|
|
83913
|
-
|
|
84086
|
+
rmSync7(join40(agentDir, SESSION_MODEL_BOOT_ATTEMPTS_FILE), { force: true });
|
|
83914
84087
|
} catch {}
|
|
83915
84088
|
}
|
|
83916
84089
|
function restoreSessionModelFileRaw(agentDir, raw) {
|
|
@@ -83941,7 +84114,7 @@ function writeSessionEffortFile(agentDir, level, configuredDefaultAtWrite) {
|
|
|
83941
84114
|
}
|
|
83942
84115
|
function clearSessionEffortFile(agentDir) {
|
|
83943
84116
|
try {
|
|
83944
|
-
|
|
84117
|
+
rmSync7(join40(agentDir, SESSION_EFFORT_FILE), { force: true });
|
|
83945
84118
|
} catch {}
|
|
83946
84119
|
}
|
|
83947
84120
|
var PREMIUM_RECOVERY_FILE = ".premium-recovery";
|
|
@@ -83983,7 +84156,7 @@ function readPremiumRecoveryFile(agentDir) {
|
|
|
83983
84156
|
}
|
|
83984
84157
|
function clearPremiumRecoveryFile(agentDir) {
|
|
83985
84158
|
try {
|
|
83986
|
-
|
|
84159
|
+
rmSync7(join40(agentDir, PREMIUM_RECOVERY_FILE), { force: true });
|
|
83987
84160
|
} catch {}
|
|
83988
84161
|
}
|
|
83989
84162
|
|
|
@@ -86239,7 +86412,7 @@ function nextCompactNotify(state6, ev) {
|
|
|
86239
86412
|
|
|
86240
86413
|
// gateway/hostd-dispatch.ts
|
|
86241
86414
|
import { existsSync as existsSync36 } from "node:fs";
|
|
86242
|
-
import { randomBytes as
|
|
86415
|
+
import { randomBytes as randomBytes10 } from "node:crypto";
|
|
86243
86416
|
init_loader();
|
|
86244
86417
|
var _hostdEnabled2;
|
|
86245
86418
|
function isHostdEnabled2() {
|
|
@@ -86286,7 +86459,7 @@ async function tryHostdDispatch2(agentName3, req, timeoutMs = 5000) {
|
|
|
86286
86459
|
}
|
|
86287
86460
|
}
|
|
86288
86461
|
function hostdRequestId2(prefix) {
|
|
86289
|
-
return `${prefix}-${Date.now()}-${
|
|
86462
|
+
return `${prefix}-${Date.now()}-${randomBytes10(4).toString("hex")}`;
|
|
86290
86463
|
}
|
|
86291
86464
|
function withOperatorAttestation(req, passphrase) {
|
|
86292
86465
|
if (!passphrase)
|
|
@@ -86348,6 +86521,56 @@ function shouldSweepChatAtBoot(chatId) {
|
|
|
86348
86521
|
return n < 0;
|
|
86349
86522
|
}
|
|
86350
86523
|
|
|
86524
|
+
// gateway/stale-pin-sweep-store.ts
|
|
86525
|
+
var SWEEP_MAX_ATTEMPTS = 8;
|
|
86526
|
+
var SWEEP_ENVELOPE_VERSIONS = new Set([1]);
|
|
86527
|
+
function sweepTargetKey(chatId, threadId) {
|
|
86528
|
+
return `${chatId}:${threadId ?? "-"}`;
|
|
86529
|
+
}
|
|
86530
|
+
function isCursorRow(x) {
|
|
86531
|
+
if (x == null || typeof x !== "object")
|
|
86532
|
+
return false;
|
|
86533
|
+
const o = x;
|
|
86534
|
+
return typeof o.chatId === "string" && o.chatId.length > 0 && (o.threadId === undefined || typeof o.threadId === "number") && (o.kind === "dm" || o.kind === "forum-topic" || o.kind === "supergroup") && typeof o.popped === "number" && typeof o.done === "boolean" && typeof o.attempts === "number" && (o.doneIds === undefined || Array.isArray(o.doneIds) && o.doneIds.every((n) => typeof n === "number")) && (o.lastStatus === undefined || typeof o.lastStatus === "string") && typeof o.updatedAt === "number";
|
|
86535
|
+
}
|
|
86536
|
+
function loadSweepCursors(path2, fs2) {
|
|
86537
|
+
if (!fs2.existsSync(path2))
|
|
86538
|
+
return [];
|
|
86539
|
+
let raw = "";
|
|
86540
|
+
try {
|
|
86541
|
+
raw = fs2.readFileSync(path2);
|
|
86542
|
+
} catch {
|
|
86543
|
+
return [];
|
|
86544
|
+
}
|
|
86545
|
+
let parsed;
|
|
86546
|
+
try {
|
|
86547
|
+
parsed = JSON.parse(raw);
|
|
86548
|
+
} catch {
|
|
86549
|
+
return [];
|
|
86550
|
+
}
|
|
86551
|
+
if (parsed == null || typeof parsed !== "object")
|
|
86552
|
+
return [];
|
|
86553
|
+
const env = parsed;
|
|
86554
|
+
if (typeof env.v !== "number" || !SWEEP_ENVELOPE_VERSIONS.has(env.v) || !Array.isArray(env.cursors)) {
|
|
86555
|
+
return [];
|
|
86556
|
+
}
|
|
86557
|
+
return env.cursors.filter(isCursorRow);
|
|
86558
|
+
}
|
|
86559
|
+
function persistSweepCursors(path2, fs2, cursors, log = (l) => process.stderr.write(l)) {
|
|
86560
|
+
const env = { v: 1, cursors: [...cursors] };
|
|
86561
|
+
try {
|
|
86562
|
+
fs2.writeFileSync(path2, JSON.stringify(env));
|
|
86563
|
+
} catch (err) {
|
|
86564
|
+
log(`stale-pin-sweep-store: persist FAILED path=${path2}: ${err.message} \u2014 ` + `durability degraded; a restart mid-sweep will re-seed instead of resume
|
|
86565
|
+
`);
|
|
86566
|
+
}
|
|
86567
|
+
}
|
|
86568
|
+
function upsertSweepCursor(path2, fs2, cursor, log = (l) => process.stderr.write(l)) {
|
|
86569
|
+
const key = sweepTargetKey(cursor.chatId, cursor.threadId);
|
|
86570
|
+
const others = loadSweepCursors(path2, fs2).filter((c) => sweepTargetKey(c.chatId, c.threadId) !== key);
|
|
86571
|
+
persistSweepCursors(path2, fs2, [...others, cursor], log);
|
|
86572
|
+
}
|
|
86573
|
+
|
|
86351
86574
|
// gateway/boot-sweep-gate.ts
|
|
86352
86575
|
function createBootSweepGate(args) {
|
|
86353
86576
|
let armed = false;
|
|
@@ -86392,21 +86615,22 @@ async function step(name, fn, log) {
|
|
|
86392
86615
|
}
|
|
86393
86616
|
async function runBootPinSweepSteps(deps) {
|
|
86394
86617
|
const log = deps.log ?? ((l) => process.stderr.write(l));
|
|
86395
|
-
let
|
|
86396
|
-
await step("
|
|
86397
|
-
|
|
86618
|
+
let targets = [];
|
|
86619
|
+
await step("sweep-target-scan", async () => {
|
|
86620
|
+
targets = deps.scanSweepTargets();
|
|
86398
86621
|
}, log);
|
|
86399
86622
|
await step("status-pin-cleanup", deps.statusPinCleanup, log);
|
|
86400
86623
|
await step("activity-card-reaper", deps.activityCardReaper, log);
|
|
86401
86624
|
await step("queued-card-reaper", deps.queuedCardReaper, log);
|
|
86402
|
-
await step("enable-
|
|
86403
|
-
for (const
|
|
86404
|
-
await step(`
|
|
86625
|
+
await step("enable-sweep", async () => deps.enableSweep(), log);
|
|
86626
|
+
for (const t of targets) {
|
|
86627
|
+
await step(`stale-pin-sweep:${sweepTargetKey(t.chatId, t.threadId)}`, () => deps.sweepTarget(t), log);
|
|
86628
|
+
}
|
|
86405
86629
|
}
|
|
86406
86630
|
|
|
86407
86631
|
// gateway/status-pin-retarget.ts
|
|
86408
86632
|
async function runStatusPinReconcile(args) {
|
|
86409
|
-
const { pinKey, chatId, prev, desired, persist, runPin, claims } = args;
|
|
86633
|
+
const { pinKey, chatId, threadId, prev, desired, persist, runPin, claims } = args;
|
|
86410
86634
|
const now = args.now ?? Date.now;
|
|
86411
86635
|
const commit = (next) => {
|
|
86412
86636
|
if (next == null) {
|
|
@@ -86414,7 +86638,7 @@ async function runStatusPinReconcile(args) {
|
|
|
86414
86638
|
return;
|
|
86415
86639
|
}
|
|
86416
86640
|
const pinnedAt = claims.get(pinKey)?.pinnedAt ?? now();
|
|
86417
|
-
claims.set(pinKey, { messageId: next.messageId, chatId, pinnedAt });
|
|
86641
|
+
claims.set(pinKey, { messageId: next.messageId, chatId, threadId, pinnedAt });
|
|
86418
86642
|
};
|
|
86419
86643
|
const runLeg = (legAction, from) => {
|
|
86420
86644
|
if (persist == null)
|
|
@@ -86425,6 +86649,7 @@ async function runStatusPinReconcile(args) {
|
|
|
86425
86649
|
fs: persist.fs,
|
|
86426
86650
|
pinKey,
|
|
86427
86651
|
chatId,
|
|
86652
|
+
threadId,
|
|
86428
86653
|
op,
|
|
86429
86654
|
applyPin: () => runPin(legAction, from),
|
|
86430
86655
|
now: now()
|
|
@@ -86524,24 +86749,77 @@ function createStatusPinApi(getBot, robust) {
|
|
|
86524
86749
|
};
|
|
86525
86750
|
}
|
|
86526
86751
|
|
|
86527
|
-
// gateway/
|
|
86528
|
-
|
|
86529
|
-
|
|
86530
|
-
|
|
86531
|
-
|
|
86532
|
-
|
|
86533
|
-
|
|
86752
|
+
// gateway/stale-pin-sweep.ts
|
|
86753
|
+
var GROUP_SWEEP_GATE = {
|
|
86754
|
+
minCallDelayMs: 6000,
|
|
86755
|
+
maxPopsPerChatPerSweep: Number.POSITIVE_INFINITY,
|
|
86756
|
+
maxPinOpsPerMinute: 10
|
|
86757
|
+
};
|
|
86758
|
+
function collectSweepTargets(input) {
|
|
86759
|
+
const out = new Map;
|
|
86534
86760
|
const add = (rows) => {
|
|
86535
86761
|
if (rows == null)
|
|
86536
86762
|
return;
|
|
86537
|
-
for (const r of rows)
|
|
86538
|
-
if (
|
|
86539
|
-
|
|
86763
|
+
for (const r of rows) {
|
|
86764
|
+
if (typeof r.chatId !== "string" || r.chatId.length === 0)
|
|
86765
|
+
continue;
|
|
86766
|
+
const threadId = r.threadId ?? undefined;
|
|
86767
|
+
const key = sweepTargetKey(r.chatId, threadId);
|
|
86768
|
+
let target = out.get(key);
|
|
86769
|
+
if (target == null) {
|
|
86770
|
+
target = { chatId: r.chatId, threadId, messageIds: [] };
|
|
86771
|
+
out.set(key, target);
|
|
86772
|
+
}
|
|
86773
|
+
const id = r.messageId ?? (r.pinned === true ? r.activityMessageId : undefined);
|
|
86774
|
+
if (typeof id === "number" && !target.messageIds.includes(id))
|
|
86775
|
+
target.messageIds.push(id);
|
|
86776
|
+
}
|
|
86540
86777
|
};
|
|
86541
86778
|
add(input.statusPins);
|
|
86542
86779
|
add(input.activityCards);
|
|
86543
86780
|
add(input.queuedCards);
|
|
86544
|
-
return [...out];
|
|
86781
|
+
return [...out.values()];
|
|
86782
|
+
}
|
|
86783
|
+
|
|
86784
|
+
// gateway/stale-pin-sweep.ts
|
|
86785
|
+
var DM_SWEEP_GATE = {
|
|
86786
|
+
minCallDelayMs: 1500,
|
|
86787
|
+
maxPopsPerChatPerSweep: 40,
|
|
86788
|
+
maxPinOpsPerMinute: 30
|
|
86789
|
+
};
|
|
86790
|
+
var GROUP_SWEEP_GATE2 = {
|
|
86791
|
+
minCallDelayMs: 6000,
|
|
86792
|
+
maxPopsPerChatPerSweep: Number.POSITIVE_INFINITY,
|
|
86793
|
+
maxPinOpsPerMinute: 10
|
|
86794
|
+
};
|
|
86795
|
+
var FLOOD_BACKOFF_FACTOR = 2;
|
|
86796
|
+
var MAX_CONSECUTIVE_FLOOD_WAITS = 3;
|
|
86797
|
+
var MAX_IDENTICAL_RETRY_AFTER_NO_PROGRESS = 2;
|
|
86798
|
+
var CIRCUIT_BREAKER_RETRY_AFTER_SEC = 60;
|
|
86799
|
+
var VERIFY_READ_GAP_MS = 1800;
|
|
86800
|
+
var VERIFY_READ_MAX_PAIRS = 3;
|
|
86801
|
+
var UNPIN_ALL_FORUM_TOPIC_ENABLED = false;
|
|
86802
|
+
function mayUnpinAllForumTopic(kind, override) {
|
|
86803
|
+
if (kind !== "forum-topic")
|
|
86804
|
+
return false;
|
|
86805
|
+
return override ?? UNPIN_ALL_FORUM_TOPIC_ENABLED;
|
|
86806
|
+
}
|
|
86807
|
+
function gateFor(kind) {
|
|
86808
|
+
return kind === "dm" ? DM_SWEEP_GATE : GROUP_SWEEP_GATE2;
|
|
86809
|
+
}
|
|
86810
|
+
function budgetClassFor(kind) {
|
|
86811
|
+
return kind === "dm" ? "dm" : "group";
|
|
86812
|
+
}
|
|
86813
|
+
function isDmChatId(chatId) {
|
|
86814
|
+
const n = Number(chatId);
|
|
86815
|
+
return Number.isFinite(n) && Number.isInteger(n) && n > 0;
|
|
86816
|
+
}
|
|
86817
|
+
function classifyChatForSweep(args) {
|
|
86818
|
+
if (isDmChatId(args.chatId))
|
|
86819
|
+
return "dm";
|
|
86820
|
+
if (args.isForum === true && args.threadId != null)
|
|
86821
|
+
return "forum-topic";
|
|
86822
|
+
return "supergroup";
|
|
86545
86823
|
}
|
|
86546
86824
|
function unexpiredStoreRepinIds(rows, chatId, now) {
|
|
86547
86825
|
const out = [];
|
|
@@ -86553,41 +86831,571 @@ function unexpiredStoreRepinIds(rows, chatId, now) {
|
|
|
86553
86831
|
}
|
|
86554
86832
|
return out;
|
|
86555
86833
|
}
|
|
86556
|
-
function
|
|
86557
|
-
|
|
86834
|
+
function description(err) {
|
|
86835
|
+
if (err != null && typeof err === "object") {
|
|
86836
|
+
const o = err;
|
|
86837
|
+
if (typeof o.description === "string" && o.description.length > 0) {
|
|
86838
|
+
return o.description.toLowerCase();
|
|
86839
|
+
}
|
|
86840
|
+
if (typeof o.message === "string" && o.message.length > 0)
|
|
86841
|
+
return o.message.toLowerCase();
|
|
86842
|
+
}
|
|
86843
|
+
return String(err).toLowerCase();
|
|
86844
|
+
}
|
|
86845
|
+
function retryAfterSeconds(err) {
|
|
86846
|
+
if (err == null || typeof err !== "object")
|
|
86847
|
+
return null;
|
|
86848
|
+
const o = err;
|
|
86849
|
+
const fromParams = o.parameters?.retry_after;
|
|
86850
|
+
if (typeof fromParams === "number" && fromParams >= 0)
|
|
86851
|
+
return fromParams;
|
|
86852
|
+
if (o.error_code === 429) {
|
|
86853
|
+
const m = /retry after (\d+)/.exec(description(err));
|
|
86854
|
+
if (m != null)
|
|
86855
|
+
return Number(m[1]);
|
|
86856
|
+
return 0;
|
|
86857
|
+
}
|
|
86858
|
+
return null;
|
|
86859
|
+
}
|
|
86860
|
+
function isPeerFloodError(err) {
|
|
86861
|
+
return description(err).includes("peer_flood");
|
|
86862
|
+
}
|
|
86863
|
+
function isPinRightsError2(err) {
|
|
86864
|
+
return description(err).includes("not enough rights");
|
|
86865
|
+
}
|
|
86866
|
+
function isNothingToUnpinError(err) {
|
|
86867
|
+
return description(err).includes("message to unpin not found");
|
|
86868
|
+
}
|
|
86869
|
+
function createPinOpBudget(now) {
|
|
86870
|
+
const windows = { dm: [], group: [] };
|
|
86871
|
+
const limits = {
|
|
86872
|
+
dm: DM_SWEEP_GATE.maxPinOpsPerMinute,
|
|
86873
|
+
group: GROUP_SWEEP_GATE2.maxPinOpsPerMinute
|
|
86874
|
+
};
|
|
86875
|
+
const prune = (cls, t) => {
|
|
86876
|
+
const w = windows[cls];
|
|
86877
|
+
while (w.length > 0 && t - w[0] >= 60000)
|
|
86878
|
+
w.shift();
|
|
86879
|
+
};
|
|
86558
86880
|
return {
|
|
86559
|
-
|
|
86560
|
-
|
|
86561
|
-
|
|
86562
|
-
|
|
86563
|
-
if (
|
|
86564
|
-
return;
|
|
86565
|
-
|
|
86566
|
-
|
|
86567
|
-
|
|
86568
|
-
|
|
86881
|
+
waitMs(cls) {
|
|
86882
|
+
const t = now();
|
|
86883
|
+
prune(cls, t);
|
|
86884
|
+
const w = windows[cls];
|
|
86885
|
+
if (w.length < limits[cls])
|
|
86886
|
+
return 0;
|
|
86887
|
+
return Math.max(0, 60000 - (t - w[0]));
|
|
86888
|
+
},
|
|
86889
|
+
record(cls) {
|
|
86890
|
+
windows[cls].push(now());
|
|
86891
|
+
}
|
|
86892
|
+
};
|
|
86893
|
+
}
|
|
86894
|
+
function createStalePinSweeper(deps) {
|
|
86895
|
+
const log = deps.log ?? ((l) => process.stderr.write(l));
|
|
86896
|
+
const budget = createPinOpBudget(deps.now);
|
|
86897
|
+
let circuitOpen = false;
|
|
86898
|
+
let lastWriteAt = 0;
|
|
86899
|
+
const commit = (cursor) => {
|
|
86900
|
+
try {
|
|
86901
|
+
upsertSweepCursor(deps.store.path, deps.store.fs, cursor, log);
|
|
86902
|
+
} catch (err) {
|
|
86903
|
+
log(`stale-pin-sweep: cursor persist failed: ${err.message}
|
|
86904
|
+
`);
|
|
86905
|
+
}
|
|
86906
|
+
};
|
|
86907
|
+
const loadCursor = (t, kind) => {
|
|
86908
|
+
const key = sweepTargetKey(t.chatId, t.threadId);
|
|
86909
|
+
let rows = [];
|
|
86910
|
+
try {
|
|
86911
|
+
rows = loadSweepCursors(deps.store.path, deps.store.fs);
|
|
86912
|
+
} catch {
|
|
86913
|
+
rows = [];
|
|
86914
|
+
}
|
|
86915
|
+
const existing = rows.find((c) => sweepTargetKey(c.chatId, c.threadId) === key);
|
|
86916
|
+
if (existing != null)
|
|
86917
|
+
return { ...existing, kind };
|
|
86918
|
+
return {
|
|
86919
|
+
chatId: t.chatId,
|
|
86920
|
+
threadId: t.threadId,
|
|
86921
|
+
kind,
|
|
86922
|
+
popped: 0,
|
|
86923
|
+
done: false,
|
|
86924
|
+
attempts: 0,
|
|
86925
|
+
updatedAt: deps.now()
|
|
86926
|
+
};
|
|
86927
|
+
};
|
|
86928
|
+
const awaitWriteSlot = async (kind) => {
|
|
86929
|
+
const cls = budgetClassFor(kind);
|
|
86930
|
+
const wait = budget.waitMs(cls);
|
|
86931
|
+
if (wait > 0)
|
|
86932
|
+
return false;
|
|
86933
|
+
const gate = gateFor(kind);
|
|
86934
|
+
const since = deps.now() - lastWriteAt;
|
|
86935
|
+
if (lastWriteAt > 0 && since < gate.minCallDelayMs) {
|
|
86936
|
+
await deps.sleep(gate.minCallDelayMs - since);
|
|
86937
|
+
}
|
|
86938
|
+
lastWriteAt = deps.now();
|
|
86939
|
+
budget.record(cls);
|
|
86940
|
+
return true;
|
|
86941
|
+
};
|
|
86942
|
+
const readTopVerified = async (chatId) => {
|
|
86943
|
+
const read = async () => {
|
|
86569
86944
|
try {
|
|
86570
|
-
await deps.
|
|
86945
|
+
return { v: await deps.getTopPinnedMessageId(chatId) };
|
|
86946
|
+
} catch {
|
|
86947
|
+
return null;
|
|
86948
|
+
}
|
|
86949
|
+
};
|
|
86950
|
+
let prev = await read();
|
|
86951
|
+
if (prev == null)
|
|
86952
|
+
return null;
|
|
86953
|
+
for (let i = 0;i < VERIFY_READ_MAX_PAIRS; i++) {
|
|
86954
|
+
await deps.sleep(VERIFY_READ_GAP_MS);
|
|
86955
|
+
const next = await read();
|
|
86956
|
+
if (next == null)
|
|
86957
|
+
return null;
|
|
86958
|
+
if (next.v === prev.v)
|
|
86959
|
+
return { top: next.v };
|
|
86960
|
+
prev = next;
|
|
86961
|
+
}
|
|
86962
|
+
return null;
|
|
86963
|
+
};
|
|
86964
|
+
const classify = (err) => {
|
|
86965
|
+
if (isPeerFloodError(err))
|
|
86966
|
+
return { kind: "breaker", detail: "PEER_FLOOD" };
|
|
86967
|
+
const retry = retryAfterSeconds(err);
|
|
86968
|
+
if (retry != null) {
|
|
86969
|
+
if (retry > CIRCUIT_BREAKER_RETRY_AFTER_SEC) {
|
|
86970
|
+
return { kind: "breaker", detail: `retry_after=${retry}s > ${CIRCUIT_BREAKER_RETRY_AFTER_SEC}s` };
|
|
86971
|
+
}
|
|
86972
|
+
return { kind: "flood", seconds: retry };
|
|
86973
|
+
}
|
|
86974
|
+
if (isPinRightsError2(err))
|
|
86975
|
+
return { kind: "rights" };
|
|
86976
|
+
return { kind: "other", detail: err?.message ?? String(err) };
|
|
86977
|
+
};
|
|
86978
|
+
const repinUnpinLoop = async (target, kind, cursor) => {
|
|
86979
|
+
const gate = gateFor(kind);
|
|
86980
|
+
let popped = 0;
|
|
86981
|
+
let consecutiveFloods = 0;
|
|
86982
|
+
let lastRetryAfter = null;
|
|
86983
|
+
let noProgressAtSameRetryAfter = 0;
|
|
86984
|
+
let lastObservedTop = null;
|
|
86985
|
+
let unverifiedPop = false;
|
|
86986
|
+
const creditPop = () => {
|
|
86987
|
+
popped++;
|
|
86988
|
+
cursor.popped++;
|
|
86989
|
+
cursor.updatedAt = deps.now();
|
|
86990
|
+
commit(cursor);
|
|
86991
|
+
};
|
|
86992
|
+
for (let i = 0;i < gate.maxPopsPerChatPerSweep; i++) {
|
|
86993
|
+
if (circuitOpen) {
|
|
86994
|
+
return { status: "aborted-circuit-breaker", popped, detail: "breaker open" };
|
|
86995
|
+
}
|
|
86996
|
+
const observed = await readTopVerified(target.chatId);
|
|
86997
|
+
if (observed == null) {
|
|
86998
|
+
return { status: "incomplete", popped, detail: "pin-stack read unverifiable" };
|
|
86999
|
+
}
|
|
87000
|
+
if (unverifiedPop) {
|
|
87001
|
+
if (observed.top != null && observed.top === lastObservedTop) {
|
|
87002
|
+
return {
|
|
87003
|
+
status: "incomplete",
|
|
87004
|
+
popped,
|
|
87005
|
+
detail: `no progress: message ${observed.top} still on top after a repin+unpin`
|
|
87006
|
+
};
|
|
87007
|
+
}
|
|
87008
|
+
creditPop();
|
|
87009
|
+
unverifiedPop = false;
|
|
87010
|
+
}
|
|
87011
|
+
if (observed.top == null) {
|
|
87012
|
+
return { status: "drained", popped };
|
|
87013
|
+
}
|
|
87014
|
+
lastObservedTop = observed.top;
|
|
87015
|
+
if (!await awaitWriteSlot(kind)) {
|
|
87016
|
+
return { status: "deferred-budget", popped, detail: "per-minute pin-op budget spent" };
|
|
87017
|
+
}
|
|
87018
|
+
try {
|
|
87019
|
+
await deps.pinSilent(target.chatId, observed.top);
|
|
86571
87020
|
} catch (err) {
|
|
86572
|
-
const
|
|
86573
|
-
|
|
86574
|
-
|
|
87021
|
+
const d = classify(err);
|
|
87022
|
+
if (d.kind === "breaker") {
|
|
87023
|
+
circuitOpen = true;
|
|
87024
|
+
return { status: "aborted-circuit-breaker", popped, detail: d.detail };
|
|
87025
|
+
}
|
|
87026
|
+
if (d.kind === "rights")
|
|
87027
|
+
return { status: "skipped-no-rights", popped };
|
|
87028
|
+
if (d.kind === "flood") {
|
|
87029
|
+
consecutiveFloods++;
|
|
87030
|
+
if (lastRetryAfter === d.seconds)
|
|
87031
|
+
noProgressAtSameRetryAfter++;
|
|
87032
|
+
else
|
|
87033
|
+
noProgressAtSameRetryAfter = 1;
|
|
87034
|
+
lastRetryAfter = d.seconds;
|
|
87035
|
+
if (consecutiveFloods >= MAX_CONSECUTIVE_FLOOD_WAITS || noProgressAtSameRetryAfter >= MAX_IDENTICAL_RETRY_AFTER_NO_PROGRESS) {
|
|
87036
|
+
return {
|
|
87037
|
+
status: "deferred-flood",
|
|
87038
|
+
popped,
|
|
87039
|
+
detail: `flood: ${consecutiveFloods} consecutive 429s, retry_after=${d.seconds}s`
|
|
87040
|
+
};
|
|
87041
|
+
}
|
|
87042
|
+
await deps.sleep(d.seconds * 1000 * Math.pow(FLOOD_BACKOFF_FACTOR, consecutiveFloods - 1));
|
|
87043
|
+
continue;
|
|
87044
|
+
}
|
|
87045
|
+
return { status: "error", popped, detail: d.detail };
|
|
87046
|
+
}
|
|
87047
|
+
if (!await awaitWriteSlot(kind)) {
|
|
87048
|
+
return { status: "deferred-budget", popped, detail: "per-minute pin-op budget spent" };
|
|
87049
|
+
}
|
|
87050
|
+
try {
|
|
87051
|
+
await deps.unpin(target.chatId, observed.top);
|
|
87052
|
+
} catch (err) {
|
|
87053
|
+
const d = classify(err);
|
|
87054
|
+
if (d.kind === "breaker") {
|
|
87055
|
+
circuitOpen = true;
|
|
87056
|
+
return { status: "aborted-circuit-breaker", popped, detail: d.detail };
|
|
87057
|
+
}
|
|
87058
|
+
if (d.kind === "rights")
|
|
87059
|
+
return { status: "skipped-no-rights", popped };
|
|
87060
|
+
if (isNothingToUnpinError(err))
|
|
87061
|
+
return { status: "drained", popped };
|
|
87062
|
+
if (d.kind === "flood") {
|
|
87063
|
+
consecutiveFloods++;
|
|
87064
|
+
if (lastRetryAfter === d.seconds)
|
|
87065
|
+
noProgressAtSameRetryAfter++;
|
|
87066
|
+
else
|
|
87067
|
+
noProgressAtSameRetryAfter = 1;
|
|
87068
|
+
lastRetryAfter = d.seconds;
|
|
87069
|
+
if (consecutiveFloods >= MAX_CONSECUTIVE_FLOOD_WAITS || noProgressAtSameRetryAfter >= MAX_IDENTICAL_RETRY_AFTER_NO_PROGRESS) {
|
|
87070
|
+
return {
|
|
87071
|
+
status: "deferred-flood",
|
|
87072
|
+
popped,
|
|
87073
|
+
detail: `flood: ${consecutiveFloods} consecutive 429s, retry_after=${d.seconds}s`
|
|
87074
|
+
};
|
|
87075
|
+
}
|
|
87076
|
+
await deps.sleep(d.seconds * 1000 * Math.pow(FLOOD_BACKOFF_FACTOR, consecutiveFloods - 1));
|
|
87077
|
+
continue;
|
|
87078
|
+
}
|
|
87079
|
+
return { status: "error", popped, detail: d.detail };
|
|
86575
87080
|
}
|
|
86576
|
-
|
|
87081
|
+
consecutiveFloods = 0;
|
|
87082
|
+
unverifiedPop = true;
|
|
87083
|
+
}
|
|
87084
|
+
const finalRead = await readTopVerified(target.chatId);
|
|
87085
|
+
if (unverifiedPop && finalRead != null && finalRead.top !== lastObservedTop)
|
|
87086
|
+
creditPop();
|
|
87087
|
+
if (finalRead != null && finalRead.top == null)
|
|
87088
|
+
return { status: "drained", popped };
|
|
87089
|
+
return {
|
|
87090
|
+
status: "deferred-budget",
|
|
87091
|
+
popped,
|
|
87092
|
+
detail: `hit the ${gate.maxPopsPerChatPerSweep}-pop cap for this chat; yielding to next boot`
|
|
87093
|
+
};
|
|
87094
|
+
};
|
|
87095
|
+
const targetedUnpinDrain = async (target, kind, cursor, ids) => {
|
|
87096
|
+
const alreadyDone = new Set(cursor.doneIds ?? []);
|
|
87097
|
+
const pending = ids.filter((id) => !alreadyDone.has(id));
|
|
87098
|
+
if (pending.length === 0) {
|
|
87099
|
+
return { status: "drained", popped: 0, issued: 0, detail: "every recorded id already unpinned" };
|
|
87100
|
+
}
|
|
87101
|
+
const before = await readTopVerified(target.chatId);
|
|
87102
|
+
let issued = 0;
|
|
87103
|
+
let deferred = null;
|
|
87104
|
+
for (const id of pending) {
|
|
87105
|
+
if (circuitOpen) {
|
|
87106
|
+
deferred = { status: "aborted-circuit-breaker", popped: 0, issued, detail: "breaker open" };
|
|
87107
|
+
break;
|
|
87108
|
+
}
|
|
87109
|
+
if (!await awaitWriteSlot(kind)) {
|
|
87110
|
+
deferred = {
|
|
87111
|
+
status: "deferred-budget",
|
|
87112
|
+
popped: 0,
|
|
87113
|
+
issued,
|
|
87114
|
+
detail: `per-minute pin-op budget spent with ${pending.length - issued} ids left`
|
|
87115
|
+
};
|
|
87116
|
+
break;
|
|
87117
|
+
}
|
|
87118
|
+
try {
|
|
87119
|
+
await deps.unpin(target.chatId, id);
|
|
87120
|
+
} catch (err) {
|
|
87121
|
+
const d = classify(err);
|
|
87122
|
+
if (d.kind === "breaker") {
|
|
87123
|
+
circuitOpen = true;
|
|
87124
|
+
deferred = { status: "aborted-circuit-breaker", popped: 0, issued, detail: d.detail };
|
|
87125
|
+
break;
|
|
87126
|
+
}
|
|
87127
|
+
if (d.kind === "rights") {
|
|
87128
|
+
deferred = { status: "skipped-no-rights", popped: 0, issued };
|
|
87129
|
+
break;
|
|
87130
|
+
}
|
|
87131
|
+
if (d.kind === "flood") {
|
|
87132
|
+
deferred = {
|
|
87133
|
+
status: "deferred-flood",
|
|
87134
|
+
popped: 0,
|
|
87135
|
+
issued,
|
|
87136
|
+
detail: `flood: retry_after=${d.seconds}s`
|
|
87137
|
+
};
|
|
87138
|
+
break;
|
|
87139
|
+
}
|
|
87140
|
+
if (!isNothingToUnpinError(err)) {
|
|
87141
|
+
deferred = { status: "error", popped: 0, issued, detail: d.detail };
|
|
87142
|
+
break;
|
|
87143
|
+
}
|
|
87144
|
+
}
|
|
87145
|
+
issued++;
|
|
87146
|
+
alreadyDone.add(id);
|
|
87147
|
+
cursor.doneIds = [...alreadyDone];
|
|
87148
|
+
cursor.updatedAt = deps.now();
|
|
87149
|
+
commit(cursor);
|
|
87150
|
+
}
|
|
87151
|
+
const after = await readTopVerified(target.chatId);
|
|
87152
|
+
if (after == null) {
|
|
87153
|
+
return {
|
|
87154
|
+
status: deferred?.status ?? "incomplete",
|
|
87155
|
+
popped: 0,
|
|
87156
|
+
issued,
|
|
87157
|
+
detail: "pin-stack read unverifiable after the unpin pass"
|
|
87158
|
+
};
|
|
87159
|
+
}
|
|
87160
|
+
if (after.top == null) {
|
|
87161
|
+
const popped2 = issued;
|
|
87162
|
+
cursor.popped += popped2;
|
|
87163
|
+
commit(cursor);
|
|
87164
|
+
return { status: "drained", popped: popped2, issued };
|
|
87165
|
+
}
|
|
87166
|
+
if (deferred != null)
|
|
87167
|
+
return { ...deferred, popped: 0 };
|
|
87168
|
+
const ours = new Set(ids);
|
|
87169
|
+
if (ours.has(after.top)) {
|
|
87170
|
+
return {
|
|
87171
|
+
status: "incomplete",
|
|
87172
|
+
popped: 0,
|
|
87173
|
+
issued,
|
|
87174
|
+
detail: `recorded pin ${after.top} is still on top after a targeted unpin`
|
|
87175
|
+
};
|
|
87176
|
+
}
|
|
87177
|
+
const popped = before != null && before.top !== after.top ? 1 : 0;
|
|
87178
|
+
cursor.popped += popped;
|
|
87179
|
+
commit(cursor);
|
|
87180
|
+
return {
|
|
87181
|
+
status: "drained",
|
|
87182
|
+
popped,
|
|
87183
|
+
issued,
|
|
87184
|
+
detail: `unpinned ${issued} recorded id(s); top ${after.top} is not ours and was left alone`
|
|
87185
|
+
};
|
|
87186
|
+
};
|
|
87187
|
+
const forumTopicDrain = async (target, cursor) => {
|
|
87188
|
+
const threadId = target.threadId;
|
|
87189
|
+
if (threadId == null) {
|
|
87190
|
+
return { status: "skipped-nothing-recorded", popped: 0, detail: "no message_thread_id" };
|
|
87191
|
+
}
|
|
87192
|
+
if (!await awaitWriteSlot("forum-topic")) {
|
|
87193
|
+
return { status: "deferred-budget", popped: 0, detail: "per-minute pin-op budget spent" };
|
|
87194
|
+
}
|
|
87195
|
+
try {
|
|
87196
|
+
await deps.unpinAllForumTopicMessages(target.chatId, threadId);
|
|
87197
|
+
} catch (err) {
|
|
87198
|
+
const d = classify(err);
|
|
87199
|
+
if (d.kind === "breaker") {
|
|
87200
|
+
circuitOpen = true;
|
|
87201
|
+
return { status: "aborted-circuit-breaker", popped: 0, detail: d.detail };
|
|
87202
|
+
}
|
|
87203
|
+
if (d.kind === "rights")
|
|
87204
|
+
return { status: "skipped-no-rights", popped: 0 };
|
|
87205
|
+
if (d.kind === "flood") {
|
|
87206
|
+
return {
|
|
87207
|
+
status: "deferred-flood",
|
|
87208
|
+
popped: 0,
|
|
87209
|
+
detail: `unpinAllForumTopicMessages pegged at retry_after=${d.seconds}s; not looping`
|
|
87210
|
+
};
|
|
87211
|
+
}
|
|
87212
|
+
return { status: "error", popped: 0, detail: d.detail };
|
|
87213
|
+
}
|
|
87214
|
+
cursor.popped++;
|
|
87215
|
+
cursor.updatedAt = deps.now();
|
|
87216
|
+
commit(cursor);
|
|
87217
|
+
const observed = await readTopVerified(target.chatId);
|
|
87218
|
+
if (observed != null && observed.top == null)
|
|
87219
|
+
return { status: "drained", popped: 1 };
|
|
87220
|
+
return { status: "drained", popped: 1, detail: "topic drained; chat-wide stack may hold other topics" };
|
|
87221
|
+
};
|
|
87222
|
+
const sweepOnce = async (target) => {
|
|
87223
|
+
if (!deps.eligible())
|
|
87224
|
+
return { status: "skipped-not-eligible", popped: 0 };
|
|
87225
|
+
if (circuitOpen) {
|
|
87226
|
+
return { status: "aborted-circuit-breaker", popped: 0, detail: "breaker already open" };
|
|
87227
|
+
}
|
|
87228
|
+
const kind = classifyChatForSweep(target);
|
|
87229
|
+
const cursor = loadCursor(target, kind);
|
|
87230
|
+
if (cursor.done)
|
|
87231
|
+
return { status: "already-drained", popped: 0 };
|
|
87232
|
+
if (cursor.attempts >= SWEEP_MAX_ATTEMPTS) {
|
|
87233
|
+
return { status: "forfeited", popped: 0, detail: `${cursor.attempts} attempts exhausted` };
|
|
87234
|
+
}
|
|
87235
|
+
if (kind !== "dm") {
|
|
87236
|
+
let allowed = false;
|
|
87237
|
+
try {
|
|
87238
|
+
allowed = await deps.canPinInChat(target.chatId);
|
|
87239
|
+
} catch {
|
|
87240
|
+
allowed = false;
|
|
87241
|
+
}
|
|
87242
|
+
if (!allowed) {
|
|
87243
|
+
cursor.attempts++;
|
|
87244
|
+
cursor.lastStatus = "skipped-no-rights";
|
|
87245
|
+
cursor.updatedAt = deps.now();
|
|
87246
|
+
commit(cursor);
|
|
87247
|
+
return { status: "skipped-no-rights", popped: 0 };
|
|
87248
|
+
}
|
|
87249
|
+
}
|
|
87250
|
+
cursor.attempts++;
|
|
87251
|
+
cursor.updatedAt = deps.now();
|
|
87252
|
+
commit(cursor);
|
|
87253
|
+
const protectedIds = [...new Set(deps.protectedMessageIds(target.chatId))];
|
|
87254
|
+
let result;
|
|
87255
|
+
try {
|
|
87256
|
+
if (kind === "dm") {
|
|
87257
|
+
result = await repinUnpinLoop(target, kind, cursor);
|
|
87258
|
+
} else if (mayUnpinAllForumTopic(kind, deps.allowUnpinAllForumTopic)) {
|
|
87259
|
+
result = await forumTopicDrain(target, cursor);
|
|
87260
|
+
} else {
|
|
87261
|
+
const keep = new Set(protectedIds);
|
|
87262
|
+
const ids = [
|
|
87263
|
+
...new Set([
|
|
87264
|
+
...target.messageIds ?? [],
|
|
87265
|
+
...deps.recordedPinIds(target.chatId, target.threadId)
|
|
87266
|
+
])
|
|
87267
|
+
].filter((id) => !keep.has(id));
|
|
87268
|
+
result = ids.length === 0 ? {
|
|
87269
|
+
status: "skipped-nothing-recorded",
|
|
87270
|
+
popped: 0,
|
|
87271
|
+
issued: 0,
|
|
87272
|
+
detail: "no recorded pin ids for this target \u2014 nothing this gateway may remove"
|
|
87273
|
+
} : await targetedUnpinDrain(target, kind, cursor, ids);
|
|
87274
|
+
}
|
|
87275
|
+
} catch (err) {
|
|
87276
|
+
result = { status: "error", popped: 0, detail: err.message };
|
|
87277
|
+
}
|
|
87278
|
+
if (result.status === "drained" || result.status === "skipped-nothing-recorded") {
|
|
87279
|
+
cursor.done = true;
|
|
87280
|
+
}
|
|
87281
|
+
cursor.lastStatus = result.status;
|
|
87282
|
+
cursor.updatedAt = deps.now();
|
|
87283
|
+
commit(cursor);
|
|
87284
|
+
if (kind === "dm" && (result.status === "drained" || result.popped > 0)) {
|
|
87285
|
+
for (const messageId of protectedIds) {
|
|
87286
|
+
if (circuitOpen)
|
|
87287
|
+
break;
|
|
87288
|
+
if (!await awaitWriteSlot(kind))
|
|
87289
|
+
break;
|
|
86577
87290
|
try {
|
|
86578
|
-
await deps.pinSilent(chatId, messageId);
|
|
87291
|
+
await deps.pinSilent(target.chatId, messageId);
|
|
86579
87292
|
} catch (err) {
|
|
86580
|
-
|
|
86581
|
-
deps.log?.(`telegram gateway: dm-pin-sweep: re-pin failed ` + `(chat=${chatId} msg=${messageId}): ${msg}
|
|
87293
|
+
log(`telegram gateway: stale-pin-sweep: re-pin of protected message failed ` + `(chat=${target.chatId} msg=${messageId}): ${err.message}
|
|
86582
87294
|
`);
|
|
86583
87295
|
}
|
|
86584
87296
|
}
|
|
86585
|
-
if (liveIds.length > 0) {
|
|
86586
|
-
deps.log?.(`telegram gateway: dm-pin-sweep: cleared stacked pins in DM ${chatId}, ` + `re-pinned ${liveIds.length} live card(s)
|
|
86587
|
-
`);
|
|
86588
|
-
}
|
|
86589
87297
|
}
|
|
87298
|
+
log(`telegram gateway: stale-pin-sweep: chat=${target.chatId} ` + `thread=${target.threadId ?? "-"} kind=${kind} status=${result.status} ` + `popped=${result.popped} issued=${result.issued ?? 0} total=${cursor.popped}` + (result.detail != null ? ` (${result.detail})` : "") + `
|
|
87299
|
+
`);
|
|
87300
|
+
return result;
|
|
86590
87301
|
};
|
|
87302
|
+
const attempted = new Set;
|
|
87303
|
+
const inFlight = new Map;
|
|
87304
|
+
const sweepTarget = (target) => {
|
|
87305
|
+
const key = sweepTargetKey(target.chatId, target.threadId);
|
|
87306
|
+
const running = inFlight.get(key);
|
|
87307
|
+
if (running != null)
|
|
87308
|
+
return running;
|
|
87309
|
+
if (!deps.eligible())
|
|
87310
|
+
return Promise.resolve({ status: "skipped-not-eligible", popped: 0 });
|
|
87311
|
+
if (attempted.has(key))
|
|
87312
|
+
return Promise.resolve({ status: "already-attempted", popped: 0 });
|
|
87313
|
+
attempted.add(key);
|
|
87314
|
+
const p = sweepOnce(target).finally(() => inFlight.delete(key));
|
|
87315
|
+
inFlight.set(key, p);
|
|
87316
|
+
return p;
|
|
87317
|
+
};
|
|
87318
|
+
return { sweepTarget, isCircuitOpen: () => circuitOpen };
|
|
87319
|
+
}
|
|
87320
|
+
|
|
87321
|
+
// gateway/stale-pin-sweep-wiring.ts
|
|
87322
|
+
function protectedPinIds(args) {
|
|
87323
|
+
const ids = [];
|
|
87324
|
+
for (const claim of args.claims) {
|
|
87325
|
+
if (claim.chatId === args.chatId)
|
|
87326
|
+
ids.push(claim.messageId);
|
|
87327
|
+
}
|
|
87328
|
+
try {
|
|
87329
|
+
ids.push(...unexpiredStoreRepinIds(args.loadPinRows(), args.chatId, args.now));
|
|
87330
|
+
} catch (err) {
|
|
87331
|
+
args.log(`telegram gateway: stale-pin-sweep: store repin scan failed ` + `(chat=${args.chatId}): ${err.message}
|
|
87332
|
+
`);
|
|
87333
|
+
}
|
|
87334
|
+
return ids;
|
|
87335
|
+
}
|
|
87336
|
+
function recordedPinIdsFor(rows, chatId, threadId) {
|
|
87337
|
+
const out = [];
|
|
87338
|
+
for (const r of rows) {
|
|
87339
|
+
if (r.chatId !== chatId)
|
|
87340
|
+
continue;
|
|
87341
|
+
if ((r.threadId ?? undefined) !== threadId)
|
|
87342
|
+
continue;
|
|
87343
|
+
if (typeof r.messageId === "number" && !out.includes(r.messageId))
|
|
87344
|
+
out.push(r.messageId);
|
|
87345
|
+
}
|
|
87346
|
+
return out;
|
|
87347
|
+
}
|
|
87348
|
+
function createGatewayStalePinSweeper(w) {
|
|
87349
|
+
const log = w.log ?? ((line) => process.stderr.write(line));
|
|
87350
|
+
const now = w.now ?? Date.now;
|
|
87351
|
+
const { handle: bot, call } = w.telegram;
|
|
87352
|
+
return createStalePinSweeper({
|
|
87353
|
+
getTopPinnedMessageId: async (chatId) => {
|
|
87354
|
+
const chat = await call(() => bot().api.getChat(chatId), {
|
|
87355
|
+
chat_id: chatId,
|
|
87356
|
+
verb: "stale-pin-sweep.get-chat"
|
|
87357
|
+
});
|
|
87358
|
+
return chat?.pinned_message?.message_id ?? null;
|
|
87359
|
+
},
|
|
87360
|
+
pinSilent: (chatId, messageId) => call(() => bot().api.pinChatMessage(chatId, messageId, { disable_notification: true }), { chat_id: chatId, verb: "stale-pin-sweep.repin" }),
|
|
87361
|
+
unpin: (chatId, messageId) => call(() => bot().api.unpinChatMessage(chatId, messageId), { chat_id: chatId, verb: "stale-pin-sweep.unpin" }),
|
|
87362
|
+
unpinAllForumTopicMessages: (chatId, threadId) => call(() => bot().api.unpinAllForumTopicMessages(chatId, threadId), {
|
|
87363
|
+
chat_id: chatId,
|
|
87364
|
+
verb: "stale-pin-sweep.unpin-all-topic"
|
|
87365
|
+
}),
|
|
87366
|
+
canPinInChat: async (chatId) => {
|
|
87367
|
+
const self = bot().botInfo?.id;
|
|
87368
|
+
if (self == null)
|
|
87369
|
+
return false;
|
|
87370
|
+
const member = await call(() => bot().api.getChatMember(chatId, self), {
|
|
87371
|
+
chat_id: chatId,
|
|
87372
|
+
verb: "stale-pin-sweep.get-chat-member"
|
|
87373
|
+
});
|
|
87374
|
+
return member?.status === "administrator" && member.can_pin_messages === true;
|
|
87375
|
+
},
|
|
87376
|
+
recordedPinIds: (chatId, threadId) => {
|
|
87377
|
+
try {
|
|
87378
|
+
return recordedPinIdsFor(w.loadPinRows(), chatId, threadId);
|
|
87379
|
+
} catch (err) {
|
|
87380
|
+
log(`telegram gateway: stale-pin-sweep: recorded-pin scan failed ` + `(chat=${chatId}): ${err.message}
|
|
87381
|
+
`);
|
|
87382
|
+
return [];
|
|
87383
|
+
}
|
|
87384
|
+
},
|
|
87385
|
+
protectedMessageIds: (chatId) => protectedPinIds({
|
|
87386
|
+
chatId,
|
|
87387
|
+
claims: w.claims(),
|
|
87388
|
+
loadPinRows: w.loadPinRows,
|
|
87389
|
+
now: now(),
|
|
87390
|
+
log
|
|
87391
|
+
}),
|
|
87392
|
+
eligible: w.eligible,
|
|
87393
|
+
sleep: w.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms))),
|
|
87394
|
+
now,
|
|
87395
|
+
store: w.store,
|
|
87396
|
+
allowUnpinAllForumTopic: w.allowUnpinAllForumTopic,
|
|
87397
|
+
log
|
|
87398
|
+
});
|
|
86591
87399
|
}
|
|
86592
87400
|
|
|
86593
87401
|
// gateway/webhook-ingest-server.ts
|
|
@@ -87751,7 +88559,7 @@ function recordWebhookEvent(rec, deps = {}) {
|
|
|
87751
88559
|
|
|
87752
88560
|
// gateway/ipc-server.ts
|
|
87753
88561
|
init_format();
|
|
87754
|
-
import { renameSync as
|
|
88562
|
+
import { renameSync as renameSync17, unlinkSync as unlinkSync20, chmodSync as chmodSync11 } from "fs";
|
|
87755
88563
|
var MAX_BUFFER_SIZE = 1024 * 1024;
|
|
87756
88564
|
var VALID_OPERATOR_KINDS = new Set([
|
|
87757
88565
|
"credentials-expired",
|
|
@@ -87962,7 +88770,7 @@ function createIpcServer(options) {
|
|
|
87962
88770
|
heartbeatTimeoutMs = 30000
|
|
87963
88771
|
} = options;
|
|
87964
88772
|
try {
|
|
87965
|
-
|
|
88773
|
+
renameSync17(socketPath, socketPath + ".bak");
|
|
87966
88774
|
} catch {}
|
|
87967
88775
|
try {
|
|
87968
88776
|
unlinkSync20(socketPath + ".bak");
|
|
@@ -88352,7 +89160,7 @@ function createIpcServer(options) {
|
|
|
88352
89160
|
clientBySocketId.clear();
|
|
88353
89161
|
server.stop(true);
|
|
88354
89162
|
try {
|
|
88355
|
-
|
|
89163
|
+
renameSync17(socketPath, socketPath + ".bak");
|
|
88356
89164
|
} catch {}
|
|
88357
89165
|
}
|
|
88358
89166
|
};
|
|
@@ -89256,6 +90064,7 @@ function obligationEscalationText(o) {
|
|
|
89256
90064
|
}
|
|
89257
90065
|
|
|
89258
90066
|
// gateway/obligation-store.ts
|
|
90067
|
+
import { dirname as dirname20 } from "node:path";
|
|
89259
90068
|
function isObligationRow(x) {
|
|
89260
90069
|
if (x == null || typeof x !== "object")
|
|
89261
90070
|
return false;
|
|
@@ -89311,9 +90120,17 @@ function persistObligations(path3, fs3, snapshot, log = (l) => process.stderr.wr
|
|
|
89311
90120
|
const tmp = path3 + ".tmp";
|
|
89312
90121
|
try {
|
|
89313
90122
|
fs3.writeFileSync(tmp, JSON.stringify(env));
|
|
90123
|
+
fs3.fsyncFileSync(tmp);
|
|
89314
90124
|
fs3.renameSync(tmp, path3);
|
|
89315
90125
|
} catch (err) {
|
|
89316
90126
|
log(`obligation-store: persist FAILED path=${path3}: ${err.message} \u2014 ` + `durability degraded to in-memory
|
|
90127
|
+
`);
|
|
90128
|
+
return;
|
|
90129
|
+
}
|
|
90130
|
+
try {
|
|
90131
|
+
fs3.fsyncDirSync(dirname20(path3));
|
|
90132
|
+
} catch (err) {
|
|
90133
|
+
log(`obligation-store: directory fsync FAILED path=${path3}: ${err.message} \u2014 ` + `snapshot written but the rename may not survive a power cut
|
|
89317
90134
|
`);
|
|
89318
90135
|
}
|
|
89319
90136
|
}
|
|
@@ -89397,12 +90214,12 @@ function createCapturedResumeDispatcher(ports) {
|
|
|
89397
90214
|
|
|
89398
90215
|
// gateway/status-pin-store.ts
|
|
89399
90216
|
var BOOT_UNPIN_MAX_ATTEMPTS = 5;
|
|
89400
|
-
var SNAPSHOT_VERSIONS2 = new Set([1, 2, 3]);
|
|
90217
|
+
var SNAPSHOT_VERSIONS2 = new Set([1, 2, 3, 4]);
|
|
89401
90218
|
function isPinRow2(x) {
|
|
89402
90219
|
if (x == null || typeof x !== "object")
|
|
89403
90220
|
return false;
|
|
89404
90221
|
const o = x;
|
|
89405
|
-
return typeof o.pinKey === "string" && o.pinKey.length > 0 && typeof o.chatId === "string" && o.chatId.length > 0 && typeof o.messageId === "number" && (o.pending === undefined || typeof o.pending === "boolean") && (o.expiresAt === undefined || typeof o.expiresAt === "number") && (o.attempts === undefined || typeof o.attempts === "number") && (o.pinnedAt === undefined || typeof o.pinnedAt === "number");
|
|
90222
|
+
return typeof o.pinKey === "string" && o.pinKey.length > 0 && typeof o.chatId === "string" && o.chatId.length > 0 && (o.threadId === undefined || typeof o.threadId === "number") && typeof o.messageId === "number" && (o.pending === undefined || typeof o.pending === "boolean") && (o.expiresAt === undefined || typeof o.expiresAt === "number") && (o.attempts === undefined || typeof o.attempts === "number") && (o.pinnedAt === undefined || typeof o.pinnedAt === "number");
|
|
89406
90223
|
}
|
|
89407
90224
|
function loadStatusPins2(path3, fs3) {
|
|
89408
90225
|
if (!fs3.existsSync(path3))
|
|
@@ -89427,7 +90244,7 @@ function loadStatusPins2(path3, fs3) {
|
|
|
89427
90244
|
return env.pins.filter(isPinRow2);
|
|
89428
90245
|
}
|
|
89429
90246
|
function persistStatusPins2(path3, fs3, snapshot, log = (l) => process.stderr.write(l)) {
|
|
89430
|
-
const env = { v:
|
|
90247
|
+
const env = { v: 4, pins: [...snapshot] };
|
|
89431
90248
|
const tmp = path3 + ".tmp";
|
|
89432
90249
|
try {
|
|
89433
90250
|
fs3.writeFileSync(tmp, JSON.stringify(env));
|
|
@@ -89775,6 +90592,7 @@ function decideWorkerPinReaps(args) {
|
|
|
89775
90592
|
}
|
|
89776
90593
|
|
|
89777
90594
|
// gateway/inbound-spool.ts
|
|
90595
|
+
import { dirname as dirname21 } from "node:path";
|
|
89778
90596
|
function spoolId(msg) {
|
|
89779
90597
|
if (msg.meta?.source === "subagent_handback" && typeof msg.meta?.subagent_jsonl_id === "string" && msg.meta.subagent_jsonl_id.length > 0) {
|
|
89780
90598
|
return `s:handback:${msg.meta.subagent_jsonl_id}`;
|
|
@@ -89878,6 +90696,7 @@ function createInboundSpool(opts) {
|
|
|
89878
90696
|
try {
|
|
89879
90697
|
fs3.appendFileSync(path3, JSON.stringify(rec) + `
|
|
89880
90698
|
`);
|
|
90699
|
+
fs3.fsyncFileSync(path3);
|
|
89881
90700
|
if (consecutiveAppendFailures > 0) {
|
|
89882
90701
|
log(`inbound-spool: append recovered path=${path3} after ` + `${consecutiveAppendFailures} failure(s) \u2014 durability restored
|
|
89883
90702
|
`);
|
|
@@ -89936,11 +90755,19 @@ function createInboundSpool(opts) {
|
|
|
89936
90755
|
fs3.writeFileSync(tmp, lines.length ? lines.join(`
|
|
89937
90756
|
`) + `
|
|
89938
90757
|
` : "");
|
|
90758
|
+
fs3.fsyncFileSync(tmp);
|
|
89939
90759
|
fs3.renameSync(tmp, path3);
|
|
89940
90760
|
log(`inbound-spool: compacted path=${path3} live=${live.size}
|
|
89941
90761
|
`);
|
|
89942
90762
|
} catch (err) {
|
|
89943
90763
|
log(`inbound-spool: compact FAILED path=${path3}: ${err.message}
|
|
90764
|
+
`);
|
|
90765
|
+
return;
|
|
90766
|
+
}
|
|
90767
|
+
try {
|
|
90768
|
+
fs3.fsyncDirSync(dirname21(path3));
|
|
90769
|
+
} catch (err) {
|
|
90770
|
+
log(`inbound-spool: compact directory fsync FAILED path=${path3}: ` + `${err.message} \u2014 compacted log written but the rename ` + `may not survive a power cut
|
|
89944
90771
|
`);
|
|
89945
90772
|
}
|
|
89946
90773
|
}
|
|
@@ -92163,9 +92990,9 @@ function toolLabel(tool, input, preamble, precomputedLabel) {
|
|
|
92163
92990
|
}
|
|
92164
92991
|
case "Bash":
|
|
92165
92992
|
case "BashOutput": {
|
|
92166
|
-
const
|
|
92167
|
-
if (
|
|
92168
|
-
return truncate4(firstLine(
|
|
92993
|
+
const description2 = str("description");
|
|
92994
|
+
if (description2)
|
|
92995
|
+
return truncate4(firstLine(description2), MAX_DESCRIPTION_CHARS);
|
|
92169
92996
|
const pre = preambleLabel();
|
|
92170
92997
|
if (pre)
|
|
92171
92998
|
return pre;
|
|
@@ -92227,9 +93054,9 @@ function toolLabel(tool, input, preamble, precomputedLabel) {
|
|
|
92227
93054
|
}
|
|
92228
93055
|
default:
|
|
92229
93056
|
if (tool.startsWith("mcp__")) {
|
|
92230
|
-
const
|
|
92231
|
-
if (
|
|
92232
|
-
return truncate4(firstLine(stripHtml(
|
|
93057
|
+
const description2 = str("description");
|
|
93058
|
+
if (description2)
|
|
93059
|
+
return truncate4(firstLine(stripHtml(description2)), MAX_DESCRIPTION_CHARS);
|
|
92233
93060
|
const label = mcpBaseLabel(tool);
|
|
92234
93061
|
const query3 = str("query") ?? str("text") ?? str("name");
|
|
92235
93062
|
if (label && query3) {
|
|
@@ -92596,12 +93423,12 @@ function skillProposalKeyboard(id) {
|
|
|
92596
93423
|
|
|
92597
93424
|
// ../src/self-improve/skill-proposals.ts
|
|
92598
93425
|
import {
|
|
92599
|
-
closeSync as
|
|
93426
|
+
closeSync as closeSync9,
|
|
92600
93427
|
existsSync as existsSync41,
|
|
92601
93428
|
mkdirSync as mkdirSync37,
|
|
92602
|
-
openSync as
|
|
93429
|
+
openSync as openSync9,
|
|
92603
93430
|
readFileSync as readFileSync37,
|
|
92604
|
-
writeSync as
|
|
93431
|
+
writeSync as writeSync6
|
|
92605
93432
|
} from "node:fs";
|
|
92606
93433
|
import { join as join50 } from "node:path";
|
|
92607
93434
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
@@ -92621,12 +93448,12 @@ function ensureDir3(stateDir) {
|
|
|
92621
93448
|
}
|
|
92622
93449
|
}
|
|
92623
93450
|
function appendLine2(path3, obj) {
|
|
92624
|
-
const fd =
|
|
93451
|
+
const fd = openSync9(path3, "a");
|
|
92625
93452
|
try {
|
|
92626
|
-
|
|
93453
|
+
writeSync6(fd, JSON.stringify(obj) + `
|
|
92627
93454
|
`);
|
|
92628
93455
|
} finally {
|
|
92629
|
-
|
|
93456
|
+
closeSync9(fd);
|
|
92630
93457
|
}
|
|
92631
93458
|
}
|
|
92632
93459
|
function readLines2(path3, isValid2) {
|
|
@@ -93231,11 +94058,11 @@ function escapeBody2(s) {
|
|
|
93231
94058
|
}
|
|
93232
94059
|
|
|
93233
94060
|
// gateway/pid-file.ts
|
|
93234
|
-
import { writeFileSync as writeFileSync33, readFileSync as readFileSync38, unlinkSync as unlinkSync21, renameSync as
|
|
94061
|
+
import { writeFileSync as writeFileSync33, readFileSync as readFileSync38, unlinkSync as unlinkSync21, renameSync as renameSync18 } from "node:fs";
|
|
93235
94062
|
function writePidFile(path3, record) {
|
|
93236
94063
|
const tmp = `${path3}.tmp-${process.pid}-${Date.now()}`;
|
|
93237
94064
|
writeFileSync33(tmp, JSON.stringify(record), "utf-8");
|
|
93238
|
-
|
|
94065
|
+
renameSync18(tmp, path3);
|
|
93239
94066
|
}
|
|
93240
94067
|
function clearPidFile(path3) {
|
|
93241
94068
|
try {
|
|
@@ -93456,11 +94283,11 @@ function safeCount(fn) {
|
|
|
93456
94283
|
}
|
|
93457
94284
|
|
|
93458
94285
|
// gateway/session-marker.ts
|
|
93459
|
-
import { writeFileSync as writeFileSync34, readFileSync as readFileSync40, renameSync as
|
|
94286
|
+
import { writeFileSync as writeFileSync34, readFileSync as readFileSync40, renameSync as renameSync19, unlinkSync as unlinkSync22 } from "node:fs";
|
|
93460
94287
|
function writeSessionMarker(path3, marker) {
|
|
93461
94288
|
const tmp = `${path3}.tmp-${process.pid}-${Date.now()}`;
|
|
93462
94289
|
writeFileSync34(tmp, JSON.stringify(marker), "utf-8");
|
|
93463
|
-
|
|
94290
|
+
renameSync19(tmp, path3);
|
|
93464
94291
|
}
|
|
93465
94292
|
function readSessionMarker(path3) {
|
|
93466
94293
|
try {
|
|
@@ -93486,12 +94313,12 @@ function shouldFireRestartBanner(input) {
|
|
|
93486
94313
|
}
|
|
93487
94314
|
|
|
93488
94315
|
// gateway/clean-shutdown-marker.ts
|
|
93489
|
-
import { writeFileSync as writeFileSync35, readFileSync as readFileSync41, renameSync as
|
|
94316
|
+
import { writeFileSync as writeFileSync35, readFileSync as readFileSync41, renameSync as renameSync20, unlinkSync as unlinkSync23 } from "node:fs";
|
|
93490
94317
|
var DEFAULT_MAX_AGE_MS = 60000;
|
|
93491
94318
|
function writeCleanShutdownMarker(path3, marker) {
|
|
93492
94319
|
const tmp = `${path3}.tmp-${process.pid}-${Date.now()}`;
|
|
93493
94320
|
writeFileSync35(tmp, JSON.stringify(marker), "utf-8");
|
|
93494
|
-
|
|
94321
|
+
renameSync20(tmp, path3);
|
|
93495
94322
|
}
|
|
93496
94323
|
function readCleanShutdownMarker(path3) {
|
|
93497
94324
|
try {
|
|
@@ -93868,10 +94695,10 @@ function classifyAdminGate(text4, myAgentName) {
|
|
|
93868
94695
|
// subagent-watcher.ts
|
|
93869
94696
|
import {
|
|
93870
94697
|
existsSync as existsSync42,
|
|
93871
|
-
openSync as
|
|
94698
|
+
openSync as openSync10,
|
|
93872
94699
|
readSync as readSync2,
|
|
93873
94700
|
statSync as statSync15,
|
|
93874
|
-
closeSync as
|
|
94701
|
+
closeSync as closeSync10,
|
|
93875
94702
|
watch,
|
|
93876
94703
|
readdirSync as readdirSync10,
|
|
93877
94704
|
readFileSync as readFileSync42
|
|
@@ -94684,8 +95511,8 @@ function startSubagentWatcher(config) {
|
|
|
94684
95511
|
existsSync: existsSync42,
|
|
94685
95512
|
readdirSync: readdirSync10,
|
|
94686
95513
|
statSync: statSync15,
|
|
94687
|
-
openSync:
|
|
94688
|
-
closeSync:
|
|
95514
|
+
openSync: openSync10,
|
|
95515
|
+
closeSync: closeSync10,
|
|
94689
95516
|
readSync: readSync2,
|
|
94690
95517
|
watch
|
|
94691
95518
|
};
|
|
@@ -95060,13 +95887,13 @@ function startSubagentWatcher(config) {
|
|
|
95060
95887
|
if (size <= rec.sizeAtSynthesis)
|
|
95061
95888
|
continue;
|
|
95062
95889
|
const entry = registry.get(agentId);
|
|
95063
|
-
const
|
|
95890
|
+
const description2 = entry?.description ?? "sub-agent";
|
|
95064
95891
|
if (rec.resurrectionCount >= MAX_RESURRECTIONS) {
|
|
95065
95892
|
rec.lost = true;
|
|
95066
95893
|
log?.(`subagent-watcher: worker ${agentId} FALSELY finalised again after a prior resurrection (resurrectionCount=${rec.resurrectionCount} >= ${MAX_RESURRECTIONS}) \u2014 NAMED AS LOST, not resurrecting again (bounded resurrection chain, issue #3023)`);
|
|
95067
95894
|
if (config.onWorkerLost != null) {
|
|
95068
95895
|
try {
|
|
95069
|
-
config.onWorkerLost(agentId,
|
|
95896
|
+
config.onWorkerLost(agentId, description2);
|
|
95070
95897
|
} catch (cbErr) {
|
|
95071
95898
|
log?.(`subagent-watcher: onWorkerLost callback error ${agentId}: ${cbErr.message}`);
|
|
95072
95899
|
}
|
|
@@ -95078,7 +95905,7 @@ function startSubagentWatcher(config) {
|
|
|
95078
95905
|
log?.(`subagent-watcher: RESURRECTING worker ${agentId} \u2014 JSONL resumed growing (${rec.sizeAtSynthesis} \u2192 ${size} bytes) after a false terminal synthesis; the worker is still alive, reviving its card (resurrection #${rec.resurrectionCount}, issue #3023)`);
|
|
95079
95906
|
if (config.onResurrect != null) {
|
|
95080
95907
|
try {
|
|
95081
|
-
config.onResurrect(agentId,
|
|
95908
|
+
config.onResurrect(agentId, description2);
|
|
95082
95909
|
} catch (cbErr) {
|
|
95083
95910
|
log?.(`subagent-watcher: onResurrect callback error ${agentId}: ${cbErr.message}`);
|
|
95084
95911
|
}
|
|
@@ -95431,7 +96258,7 @@ import {
|
|
|
95431
96258
|
readdirSync as readdirSync11,
|
|
95432
96259
|
unlinkSync as unlinkSync24,
|
|
95433
96260
|
existsSync as existsSync43,
|
|
95434
|
-
renameSync as
|
|
96261
|
+
renameSync as renameSync21
|
|
95435
96262
|
} from "node:fs";
|
|
95436
96263
|
import { join as join52, resolve as resolve10 } from "node:path";
|
|
95437
96264
|
import { homedir as homedir15 } from "node:os";
|
|
@@ -95450,7 +96277,7 @@ function writeRecord(record) {
|
|
|
95450
96277
|
const tmp = `${target}.tmp${process.pid}`;
|
|
95451
96278
|
writeFileSync36(tmp, JSON.stringify(record, null, 2) + `
|
|
95452
96279
|
`, { mode: 384 });
|
|
95453
|
-
|
|
96280
|
+
renameSync21(tmp, target);
|
|
95454
96281
|
}
|
|
95455
96282
|
function readRecord(id) {
|
|
95456
96283
|
const path3 = recordPath(id);
|
|
@@ -95613,11 +96440,8 @@ function determineRestartReason(opts) {
|
|
|
95613
96440
|
return "fresh";
|
|
95614
96441
|
}
|
|
95615
96442
|
|
|
95616
|
-
// gateway/gateway.ts
|
|
95617
|
-
init_boot_card();
|
|
95618
|
-
|
|
95619
96443
|
// gateway/update-announce.ts
|
|
95620
|
-
import { existsSync as existsSync48, mkdirSync as mkdirSync42, openSync as
|
|
96444
|
+
import { existsSync as existsSync48, mkdirSync as mkdirSync42, openSync as openSync11, closeSync as closeSync11, readFileSync as readFileSync50 } from "node:fs";
|
|
95621
96445
|
import { join as join57 } from "node:path";
|
|
95622
96446
|
import { homedir as homedir17 } from "node:os";
|
|
95623
96447
|
|
|
@@ -95710,6 +96534,9 @@ function parseAuditLine(line) {
|
|
|
95710
96534
|
entry.failed_step = o.failed_step;
|
|
95711
96535
|
if (typeof o.failed_agent === "string")
|
|
95712
96536
|
entry.failed_agent = o.failed_agent;
|
|
96537
|
+
if (Array.isArray(o.drifted) && o.drifted.every((x) => typeof x === "string")) {
|
|
96538
|
+
entry.drifted = o.drifted;
|
|
96539
|
+
}
|
|
95713
96540
|
if (typeof o.agent === "string")
|
|
95714
96541
|
entry.agent = o.agent;
|
|
95715
96542
|
if (typeof o.n === "number")
|
|
@@ -95826,8 +96653,8 @@ function claimUpdateAnnouncement(requestId, opts = {}) {
|
|
|
95826
96653
|
const safeId = requestId.replace(/[^A-Za-z0-9_.-]/g, "_").slice(0, 200);
|
|
95827
96654
|
const path3 = join57(dir, safeId);
|
|
95828
96655
|
try {
|
|
95829
|
-
const fd =
|
|
95830
|
-
|
|
96656
|
+
const fd = openSync11(path3, "wx");
|
|
96657
|
+
closeSync11(fd);
|
|
95831
96658
|
return true;
|
|
95832
96659
|
} catch {
|
|
95833
96660
|
return false;
|
|
@@ -96050,20 +96877,20 @@ import { join as join59 } from "node:path";
|
|
|
96050
96877
|
|
|
96051
96878
|
// ../src/issues/store.ts
|
|
96052
96879
|
import {
|
|
96053
|
-
closeSync as
|
|
96880
|
+
closeSync as closeSync12,
|
|
96054
96881
|
existsSync as existsSync49,
|
|
96055
96882
|
mkdirSync as mkdirSync43,
|
|
96056
|
-
openSync as
|
|
96883
|
+
openSync as openSync12,
|
|
96057
96884
|
readdirSync as readdirSync13,
|
|
96058
96885
|
readFileSync as readFileSync52,
|
|
96059
|
-
renameSync as
|
|
96886
|
+
renameSync as renameSync24,
|
|
96060
96887
|
statSync as statSync17,
|
|
96061
96888
|
unlinkSync as unlinkSync25,
|
|
96062
96889
|
writeFileSync as writeFileSync42,
|
|
96063
|
-
writeSync as
|
|
96890
|
+
writeSync as writeSync7
|
|
96064
96891
|
} from "node:fs";
|
|
96065
96892
|
import { join as join58 } from "node:path";
|
|
96066
|
-
import { randomBytes as
|
|
96893
|
+
import { randomBytes as randomBytes11 } from "node:crypto";
|
|
96067
96894
|
import { execSync } from "node:child_process";
|
|
96068
96895
|
|
|
96069
96896
|
// ../src/issues/types.ts
|
|
@@ -96138,12 +96965,12 @@ function resolve11(stateDir, fingerprint, nowFn = Date.now) {
|
|
|
96138
96965
|
function writeAll(stateDir, events) {
|
|
96139
96966
|
const path3 = join58(stateDir, ISSUES_FILE);
|
|
96140
96967
|
sweepOrphanTmpFiles(stateDir);
|
|
96141
|
-
const tmp = `${path3}.tmp-${process.pid}-${
|
|
96968
|
+
const tmp = `${path3}.tmp-${process.pid}-${randomBytes11(4).toString("hex")}`;
|
|
96142
96969
|
const body = events.length === 0 ? "" : events.map((e) => JSON.stringify(e)).join(`
|
|
96143
96970
|
`) + `
|
|
96144
96971
|
`;
|
|
96145
96972
|
writeFileSync42(tmp, body, "utf-8");
|
|
96146
|
-
|
|
96973
|
+
renameSync24(tmp, path3);
|
|
96147
96974
|
}
|
|
96148
96975
|
var ORPHAN_TMP_TTL_MS = 60000;
|
|
96149
96976
|
var TMP_PREFIX = `${ISSUES_FILE}.tmp-`;
|
|
@@ -96175,9 +97002,9 @@ function withLock(stateDir, fn) {
|
|
|
96175
97002
|
let fd = null;
|
|
96176
97003
|
while (fd === null) {
|
|
96177
97004
|
try {
|
|
96178
|
-
fd =
|
|
97005
|
+
fd = openSync12(lockPath, "wx");
|
|
96179
97006
|
try {
|
|
96180
|
-
|
|
97007
|
+
writeSync7(fd, String(process.pid));
|
|
96181
97008
|
} catch {}
|
|
96182
97009
|
} catch (err) {
|
|
96183
97010
|
const e = err;
|
|
@@ -96195,7 +97022,7 @@ function withLock(stateDir, fn) {
|
|
|
96195
97022
|
return fn();
|
|
96196
97023
|
} finally {
|
|
96197
97024
|
try {
|
|
96198
|
-
|
|
97025
|
+
closeSync12(fd);
|
|
96199
97026
|
} catch {}
|
|
96200
97027
|
try {
|
|
96201
97028
|
unlinkSync25(lockPath);
|
|
@@ -97087,7 +97914,7 @@ function createScopedGrantStore(stateDir, env = process.env, log = (l) => proces
|
|
|
97087
97914
|
preserveUnreadableStoreFile(filePath, "scoped-grant-store", log);
|
|
97088
97915
|
unreadable = false;
|
|
97089
97916
|
}
|
|
97090
|
-
|
|
97917
|
+
atomicWriteFileSync2(filePath, JSON.stringify(serializeScopedGrants(store3)), 384);
|
|
97091
97918
|
} catch (err) {
|
|
97092
97919
|
log(`telegram gateway: scoped-grant-store write failed: ${err.message}
|
|
97093
97920
|
`);
|
|
@@ -97875,10 +98702,10 @@ init_auth_snapshot_format2();
|
|
|
97875
98702
|
|
|
97876
98703
|
// gateway/turn-active-marker.ts
|
|
97877
98704
|
import {
|
|
97878
|
-
closeSync as
|
|
98705
|
+
closeSync as closeSync13,
|
|
97879
98706
|
existsSync as existsSync53,
|
|
97880
98707
|
mkdirSync as mkdirSync46,
|
|
97881
|
-
openSync as
|
|
98708
|
+
openSync as openSync13,
|
|
97882
98709
|
readFileSync as readFileSync55,
|
|
97883
98710
|
statSync as statSync19,
|
|
97884
98711
|
unlinkSync as unlinkSync26,
|
|
@@ -97963,6 +98790,163 @@ function startGatewayHeartbeat(stateDir, intervalMs = GATEWAY_HEARTBEAT_INTERVAL
|
|
|
97963
98790
|
return timer3;
|
|
97964
98791
|
}
|
|
97965
98792
|
|
|
98793
|
+
// gateway/boot-beacon.ts
|
|
98794
|
+
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
98795
|
+
import {
|
|
98796
|
+
closeSync as closeSync14,
|
|
98797
|
+
fsyncSync as fsyncSync5,
|
|
98798
|
+
mkdirSync as mkdirSync48,
|
|
98799
|
+
openSync as openSync14,
|
|
98800
|
+
readFileSync as readFileSync56,
|
|
98801
|
+
renameSync as renameSync25,
|
|
98802
|
+
unlinkSync as unlinkSync27,
|
|
98803
|
+
writeFileSync as writeFileSync47
|
|
98804
|
+
} from "node:fs";
|
|
98805
|
+
import { join as join65 } from "node:path";
|
|
98806
|
+
var BOOT_BEACON_FILE = "gateway-beacon.json";
|
|
98807
|
+
var HOST_BOOT_ID_PATH = "/proc/sys/kernel/random/boot_id";
|
|
98808
|
+
var CGROUP_MEMORY_EVENTS_PATH = "/sys/fs/cgroup/memory.events";
|
|
98809
|
+
var CGROUP_MEMORY_CURRENT_PATH = "/sys/fs/cgroup/memory.current";
|
|
98810
|
+
var CGROUP_MEMORY_MAX_PATH = "/sys/fs/cgroup/memory.max";
|
|
98811
|
+
var MAX_FIELD_CHARS = 256;
|
|
98812
|
+
function parseHostBootId(raw) {
|
|
98813
|
+
if (typeof raw !== "string")
|
|
98814
|
+
return;
|
|
98815
|
+
const trimmed = raw.trim();
|
|
98816
|
+
if (trimmed.length === 0 || trimmed.length > MAX_FIELD_CHARS)
|
|
98817
|
+
return;
|
|
98818
|
+
if (/\s/.test(trimmed))
|
|
98819
|
+
return;
|
|
98820
|
+
return trimmed;
|
|
98821
|
+
}
|
|
98822
|
+
function parseOomKillCount(raw) {
|
|
98823
|
+
if (typeof raw !== "string")
|
|
98824
|
+
return;
|
|
98825
|
+
for (const line of raw.split(`
|
|
98826
|
+
`)) {
|
|
98827
|
+
const parts = line.trim().split(/\s+/);
|
|
98828
|
+
if (parts.length !== 2 || parts[0] !== "oom_kill")
|
|
98829
|
+
continue;
|
|
98830
|
+
return parseNonNegativeInt2(parts[1]);
|
|
98831
|
+
}
|
|
98832
|
+
return;
|
|
98833
|
+
}
|
|
98834
|
+
function parseMemoryBytes(raw) {
|
|
98835
|
+
if (typeof raw !== "string")
|
|
98836
|
+
return;
|
|
98837
|
+
return parseNonNegativeInt2(raw.trim());
|
|
98838
|
+
}
|
|
98839
|
+
function parseMemoryMax(raw) {
|
|
98840
|
+
if (typeof raw !== "string")
|
|
98841
|
+
return;
|
|
98842
|
+
const trimmed = raw.trim();
|
|
98843
|
+
if (trimmed === "max")
|
|
98844
|
+
return "max";
|
|
98845
|
+
return parseNonNegativeInt2(trimmed);
|
|
98846
|
+
}
|
|
98847
|
+
function parseNonNegativeInt2(text4) {
|
|
98848
|
+
if (typeof text4 !== "string")
|
|
98849
|
+
return;
|
|
98850
|
+
const trimmed = text4.trim();
|
|
98851
|
+
if (trimmed.length === 0 || trimmed.length > MAX_FIELD_CHARS)
|
|
98852
|
+
return;
|
|
98853
|
+
if (!/^\d+$/.test(trimmed))
|
|
98854
|
+
return;
|
|
98855
|
+
const value = Number(trimmed);
|
|
98856
|
+
return Number.isSafeInteger(value) ? value : undefined;
|
|
98857
|
+
}
|
|
98858
|
+
function buildBootBeacon(input) {
|
|
98859
|
+
const beacon = {
|
|
98860
|
+
bootId: input.bootId,
|
|
98861
|
+
pid: input.pid,
|
|
98862
|
+
wallMs: input.wallMs,
|
|
98863
|
+
monotonicMs: input.monotonicMs
|
|
98864
|
+
};
|
|
98865
|
+
const sample3 = input.sample ?? {};
|
|
98866
|
+
if (sample3.hostBootId !== undefined)
|
|
98867
|
+
beacon.hostBootId = sample3.hostBootId;
|
|
98868
|
+
if (sample3.oomKillCount !== undefined)
|
|
98869
|
+
beacon.oomKillCount = sample3.oomKillCount;
|
|
98870
|
+
if (sample3.memCurrent !== undefined)
|
|
98871
|
+
beacon.memCurrent = sample3.memCurrent;
|
|
98872
|
+
if (sample3.memMax !== undefined)
|
|
98873
|
+
beacon.memMax = sample3.memMax;
|
|
98874
|
+
return beacon;
|
|
98875
|
+
}
|
|
98876
|
+
function serializeBootBeacon(beacon) {
|
|
98877
|
+
return `${JSON.stringify(beacon)}
|
|
98878
|
+
`;
|
|
98879
|
+
}
|
|
98880
|
+
function readTextOrNull(path3) {
|
|
98881
|
+
try {
|
|
98882
|
+
return readFileSync56(path3, "utf-8");
|
|
98883
|
+
} catch {
|
|
98884
|
+
return null;
|
|
98885
|
+
}
|
|
98886
|
+
}
|
|
98887
|
+
function sampleBeaconHost(paths = {}) {
|
|
98888
|
+
const sample3 = {};
|
|
98889
|
+
const hostBootId = parseHostBootId(readTextOrNull(paths.hostBootId ?? HOST_BOOT_ID_PATH));
|
|
98890
|
+
if (hostBootId !== undefined)
|
|
98891
|
+
sample3.hostBootId = hostBootId;
|
|
98892
|
+
const oomKillCount = parseOomKillCount(readTextOrNull(paths.memoryEvents ?? CGROUP_MEMORY_EVENTS_PATH));
|
|
98893
|
+
if (oomKillCount !== undefined)
|
|
98894
|
+
sample3.oomKillCount = oomKillCount;
|
|
98895
|
+
const memCurrent = parseMemoryBytes(readTextOrNull(paths.memoryCurrent ?? CGROUP_MEMORY_CURRENT_PATH));
|
|
98896
|
+
if (memCurrent !== undefined)
|
|
98897
|
+
sample3.memCurrent = memCurrent;
|
|
98898
|
+
const memMax = parseMemoryMax(readTextOrNull(paths.memoryMax ?? CGROUP_MEMORY_MAX_PATH));
|
|
98899
|
+
if (memMax !== undefined)
|
|
98900
|
+
sample3.memMax = memMax;
|
|
98901
|
+
return sample3;
|
|
98902
|
+
}
|
|
98903
|
+
function writeBootBeaconFile(stateDir, beacon) {
|
|
98904
|
+
const path3 = join65(stateDir, BOOT_BEACON_FILE);
|
|
98905
|
+
const tmp = `${path3}.tmp-${process.pid}`;
|
|
98906
|
+
let fd;
|
|
98907
|
+
try {
|
|
98908
|
+
mkdirSync48(stateDir, { recursive: true, mode: 448 });
|
|
98909
|
+
fd = openSync14(tmp, "w", 384);
|
|
98910
|
+
writeFileSync47(fd, serializeBootBeacon(beacon));
|
|
98911
|
+
fsyncSync5(fd);
|
|
98912
|
+
closeSync14(fd);
|
|
98913
|
+
fd = undefined;
|
|
98914
|
+
renameSync25(tmp, path3);
|
|
98915
|
+
return true;
|
|
98916
|
+
} catch {
|
|
98917
|
+
if (fd !== undefined) {
|
|
98918
|
+
try {
|
|
98919
|
+
closeSync14(fd);
|
|
98920
|
+
} catch {}
|
|
98921
|
+
}
|
|
98922
|
+
try {
|
|
98923
|
+
unlinkSync27(tmp);
|
|
98924
|
+
} catch {}
|
|
98925
|
+
return false;
|
|
98926
|
+
}
|
|
98927
|
+
}
|
|
98928
|
+
var GATEWAY_BOOT_ID = randomUUID6();
|
|
98929
|
+
function tickBootBeacon(stateDir, bootId = GATEWAY_BOOT_ID) {
|
|
98930
|
+
try {
|
|
98931
|
+
return writeBootBeaconFile(stateDir, buildBootBeacon({
|
|
98932
|
+
bootId,
|
|
98933
|
+
pid: process.pid,
|
|
98934
|
+
wallMs: Date.now(),
|
|
98935
|
+
monotonicMs: Math.round(performance.now()),
|
|
98936
|
+
sample: sampleBeaconHost()
|
|
98937
|
+
}));
|
|
98938
|
+
} catch {
|
|
98939
|
+
return false;
|
|
98940
|
+
}
|
|
98941
|
+
}
|
|
98942
|
+
function attachBootBeacon(stateDir, next) {
|
|
98943
|
+
tickBootBeacon(stateDir);
|
|
98944
|
+
return () => {
|
|
98945
|
+
tickBootBeacon(stateDir);
|
|
98946
|
+
next();
|
|
98947
|
+
};
|
|
98948
|
+
}
|
|
98949
|
+
|
|
97966
98950
|
// gateway/outbox-sweep.ts
|
|
97967
98951
|
init_flood_circuit_breaker();
|
|
97968
98952
|
async function sweepOutbox(deps) {
|
|
@@ -98185,10 +99169,10 @@ function startOutboxSweep(deps) {
|
|
|
98185
99169
|
}
|
|
98186
99170
|
|
|
98187
99171
|
// ../src/build-info.ts
|
|
98188
|
-
var VERSION2 = "0.19.
|
|
98189
|
-
var COMMIT_SHA = "
|
|
98190
|
-
var COMMIT_DATE = "2026-07-
|
|
98191
|
-
var LATEST_PR =
|
|
99172
|
+
var VERSION2 = "0.19.32";
|
|
99173
|
+
var COMMIT_SHA = "5ccce0a7";
|
|
99174
|
+
var COMMIT_DATE = "2026-07-28T23:48:52Z";
|
|
99175
|
+
var LATEST_PR = 3962;
|
|
98192
99176
|
var COMMITS_AHEAD_OF_TAG = 0;
|
|
98193
99177
|
|
|
98194
99178
|
// gateway/boot-version.ts
|
|
@@ -98266,11 +99250,11 @@ init_peercred();
|
|
|
98266
99250
|
import * as net5 from "node:net";
|
|
98267
99251
|
import * as fs3 from "node:fs";
|
|
98268
99252
|
import { homedir as homedir18 } from "node:os";
|
|
98269
|
-
import { join as
|
|
99253
|
+
import { join as join66 } from "node:path";
|
|
98270
99254
|
var DEFAULT_TIMEOUT_MS4 = 2000;
|
|
98271
99255
|
var UNLOCK_TIMEOUT_MS = 30000;
|
|
98272
|
-
var LEGACY_SOCKET_PATH2 =
|
|
98273
|
-
var OPERATOR_SOCKET_PATH2 =
|
|
99256
|
+
var LEGACY_SOCKET_PATH2 = join66(homedir18(), ".switchroom", "vault-broker.sock");
|
|
99257
|
+
var OPERATOR_SOCKET_PATH2 = join66(homedir18(), ".switchroom", "broker-operator", "sock");
|
|
98274
99258
|
function defaultBrokerSocketPath2() {
|
|
98275
99259
|
if (fs3.existsSync(OPERATOR_SOCKET_PATH2))
|
|
98276
99260
|
return OPERATOR_SOCKET_PATH2;
|
|
@@ -98871,8 +99855,8 @@ async function createLinearIssue(args, deps = {}) {
|
|
|
98871
99855
|
}
|
|
98872
99856
|
teamId = nodes[0].id;
|
|
98873
99857
|
}
|
|
98874
|
-
const
|
|
98875
|
-
const input = { teamId, title, description };
|
|
99858
|
+
const description2 = dedupKey ? `${body}${captureDedupMarker(dedupKey)}` : body;
|
|
99859
|
+
const input = { teamId, title, description: description2 };
|
|
98876
99860
|
if (priority !== undefined)
|
|
98877
99861
|
input.priority = priority;
|
|
98878
99862
|
const create = await gql("mutation($input: IssueCreateInput!) { issueCreate(input: $input) { success issue { id identifier url } } }", { input });
|
|
@@ -99152,8 +100136,8 @@ function resolveVaultApprovalPosture(broker) {
|
|
|
99152
100136
|
}
|
|
99153
100137
|
|
|
99154
100138
|
// registry/turns-schema.ts
|
|
99155
|
-
import { chmodSync as chmodSync12, mkdirSync as
|
|
99156
|
-
import { join as
|
|
100139
|
+
import { chmodSync as chmodSync12, mkdirSync as mkdirSync49 } from "fs";
|
|
100140
|
+
import { join as join67 } from "path";
|
|
99157
100141
|
var DatabaseClass3 = null;
|
|
99158
100142
|
function loadDatabaseClass3() {
|
|
99159
100143
|
if (DatabaseClass3 != null)
|
|
@@ -99210,7 +100194,7 @@ var PHASE4_MIGRATIONS = [
|
|
|
99210
100194
|
];
|
|
99211
100195
|
function applySchema(db3) {
|
|
99212
100196
|
db3.exec("PRAGMA journal_mode = WAL");
|
|
99213
|
-
db3.exec("PRAGMA synchronous =
|
|
100197
|
+
db3.exec("PRAGMA synchronous = FULL");
|
|
99214
100198
|
db3.exec("PRAGMA busy_timeout = 5000");
|
|
99215
100199
|
db3.exec(SCHEMA_SQL);
|
|
99216
100200
|
for (const sql of [...PHASE1_MIGRATIONS, ...PHASE2_MIGRATIONS, ...PHASE3_MIGRATIONS, ...PHASE4_MIGRATIONS]) {
|
|
@@ -99225,9 +100209,9 @@ function applySchema(db3) {
|
|
|
99225
100209
|
}
|
|
99226
100210
|
function openTurnsDb(agentDir) {
|
|
99227
100211
|
const Database = loadDatabaseClass3();
|
|
99228
|
-
const dir =
|
|
99229
|
-
|
|
99230
|
-
const path3 =
|
|
100212
|
+
const dir = join67(agentDir, "telegram");
|
|
100213
|
+
mkdirSync49(dir, { recursive: true, mode: 448 });
|
|
100214
|
+
const path3 = join67(dir, "registry.db");
|
|
99231
100215
|
const db3 = new Database(path3, { create: true });
|
|
99232
100216
|
applySchema(db3);
|
|
99233
100217
|
try {
|
|
@@ -99572,7 +100556,7 @@ function selectResumeBuilder(endedVia, opts) {
|
|
|
99572
100556
|
}
|
|
99573
100557
|
|
|
99574
100558
|
// gateway/bridge-dead-watchdog.ts
|
|
99575
|
-
import { readFileSync as
|
|
100559
|
+
import { readFileSync as readFileSync58, writeFileSync as writeFileSync48, renameSync as renameSync26, unlinkSync as unlinkSync28 } from "node:fs";
|
|
99576
100560
|
|
|
99577
100561
|
// gateway/cron-session.ts
|
|
99578
100562
|
var CRON_IDENTITY_SUFFIX2 = "-cron";
|
|
@@ -99605,7 +100589,7 @@ function readFreshCrashLogTail(path3, opts = {}) {
|
|
|
99605
100589
|
const nowMs3 = opts.nowMs ?? Date.now();
|
|
99606
100590
|
const freshWindowMs = opts.freshWindowMs ?? CRASH_LOG_FRESH_WINDOW_MS;
|
|
99607
100591
|
const maxLines = opts.maxLines ?? CRASH_LOG_TAIL_LINES;
|
|
99608
|
-
const readFile = opts.readFile ?? ((p) =>
|
|
100592
|
+
const readFile = opts.readFile ?? ((p) => readFileSync58(p, "utf8"));
|
|
99609
100593
|
let raw;
|
|
99610
100594
|
try {
|
|
99611
100595
|
raw = readFile(path3);
|
|
@@ -99626,13 +100610,13 @@ function readFreshCrashLogTail(path3, opts = {}) {
|
|
|
99626
100610
|
}
|
|
99627
100611
|
function writeBridgeDeadEscalationMarker(path3, marker) {
|
|
99628
100612
|
const tmp = `${path3}.tmp-${process.pid}-${Date.now()}`;
|
|
99629
|
-
|
|
99630
|
-
|
|
100613
|
+
writeFileSync48(tmp, JSON.stringify(marker), "utf8");
|
|
100614
|
+
renameSync26(tmp, path3);
|
|
99631
100615
|
}
|
|
99632
100616
|
function consumeBridgeDeadEscalationMarker(path3, nowMs3 = Date.now(), maxAgeMs = ESCALATION_MARKER_MAX_AGE_MS) {
|
|
99633
100617
|
let marker = null;
|
|
99634
100618
|
try {
|
|
99635
|
-
const parsed = JSON.parse(
|
|
100619
|
+
const parsed = JSON.parse(readFileSync58(path3, "utf8"));
|
|
99636
100620
|
if (typeof parsed.ts === "number" && Number.isFinite(parsed.ts) && typeof parsed.reason === "string") {
|
|
99637
100621
|
const age = nowMs3 - parsed.ts;
|
|
99638
100622
|
if (age >= 0 && age < maxAgeMs) {
|
|
@@ -99644,7 +100628,7 @@ function consumeBridgeDeadEscalationMarker(path3, nowMs3 = Date.now(), maxAgeMs
|
|
|
99644
100628
|
}
|
|
99645
100629
|
} catch {}
|
|
99646
100630
|
try {
|
|
99647
|
-
|
|
100631
|
+
unlinkSync28(path3);
|
|
99648
100632
|
} catch {}
|
|
99649
100633
|
return marker;
|
|
99650
100634
|
}
|
|
@@ -99785,7 +100769,7 @@ function createBridgeDeadWatchdog(opts) {
|
|
|
99785
100769
|
}
|
|
99786
100770
|
|
|
99787
100771
|
// gateway/boot-probes.ts
|
|
99788
|
-
import { readFileSync as
|
|
100772
|
+
import { readFileSync as readFileSync59, readdirSync as readdirSync14, existsSync as existsSync55 } from "fs";
|
|
99789
100773
|
init_quota_cache();
|
|
99790
100774
|
init_generation_stamp();
|
|
99791
100775
|
init_quota_check();
|
|
@@ -99794,7 +100778,7 @@ import { promisify as promisify2 } from "util";
|
|
|
99794
100778
|
var execFile2 = promisify2(execFileCb2);
|
|
99795
100779
|
var realProcFs2 = {
|
|
99796
100780
|
readdir: (p) => readdirSync14(p),
|
|
99797
|
-
readFile: (p) =>
|
|
100781
|
+
readFile: (p) => readFileSync59(p, "utf-8")
|
|
99798
100782
|
};
|
|
99799
100783
|
function findAgentProcessInContainer2(fs4 = realProcFs2) {
|
|
99800
100784
|
let entries;
|
|
@@ -100044,7 +101028,7 @@ if (isGatewayMain) {
|
|
|
100044
101028
|
shutdownAnalytics();
|
|
100045
101029
|
});
|
|
100046
101030
|
}
|
|
100047
|
-
var STATE_DIR = process.env.TELEGRAM_STATE_DIR ??
|
|
101031
|
+
var STATE_DIR = process.env.TELEGRAM_STATE_DIR ?? join68(homedir19(), ".claude", "channels", "telegram");
|
|
100048
101032
|
var permCardStore = createPermissionCardStore(STATE_DIR);
|
|
100049
101033
|
var BLOCKED_APPROVALS_DIR = process.env.SWITCHROOM_BLOCKED_APPROVALS_DIR ?? "/state/blocked-approvals";
|
|
100050
101034
|
var AGENT_NAME = process.env.SWITCHROOM_AGENT_NAME ?? "agent";
|
|
@@ -100083,7 +101067,7 @@ function alwaysAllowDrainDeps() {
|
|
|
100083
101067
|
return {
|
|
100084
101068
|
readConfigText: () => {
|
|
100085
101069
|
const cfgPath = process.env.SWITCHROOM_CONFIG ?? SWITCHROOM_CONFIG ?? findConfigFile2();
|
|
100086
|
-
return
|
|
101070
|
+
return readFileSync60(cfgPath, "utf8");
|
|
100087
101071
|
},
|
|
100088
101072
|
resolveAllowList: (_configText, agentName3) => {
|
|
100089
101073
|
const cfg = loadConfig2();
|
|
@@ -100144,11 +101128,11 @@ function scheduleAlwaysAllowPersistDrain() {
|
|
|
100144
101128
|
}, ALWAYS_ALLOW_DRAIN_INTERVAL_MS);
|
|
100145
101129
|
timer3.unref?.();
|
|
100146
101130
|
}
|
|
100147
|
-
var ACCESS_FILE =
|
|
100148
|
-
var APPROVED_DIR =
|
|
100149
|
-
var ENV_FILE =
|
|
100150
|
-
var INBOX_DIR =
|
|
100151
|
-
var PEOPLE_FILE =
|
|
101131
|
+
var ACCESS_FILE = join68(STATE_DIR, "access.json");
|
|
101132
|
+
var APPROVED_DIR = join68(STATE_DIR, "approved");
|
|
101133
|
+
var ENV_FILE = join68(STATE_DIR, ".env");
|
|
101134
|
+
var INBOX_DIR = join68(STATE_DIR, "inbox");
|
|
101135
|
+
var PEOPLE_FILE = join68(STATE_DIR, "people.json");
|
|
100152
101136
|
function triggerSelfRestart(targetAgent, reason, delayMs = 300) {
|
|
100153
101137
|
const isDocker = process.env.SWITCHROOM_RUNTIME === "docker";
|
|
100154
101138
|
const selfAgent = process.env.SWITCHROOM_AGENT_NAME;
|
|
@@ -100213,7 +101197,7 @@ function formatBootVersion() {
|
|
|
100213
101197
|
}
|
|
100214
101198
|
try {
|
|
100215
101199
|
chmodSync14(ENV_FILE, 384);
|
|
100216
|
-
for (const line of
|
|
101200
|
+
for (const line of readFileSync60(ENV_FILE, "utf8").split(`
|
|
100217
101201
|
`)) {
|
|
100218
101202
|
const m = line.match(/^(\w+)=(.*)$/);
|
|
100219
101203
|
if (m && process.env[m[1]] === undefined)
|
|
@@ -100234,7 +101218,7 @@ var bot;
|
|
|
100234
101218
|
var lastGetUpdatesHeartbeatMs = Date.now();
|
|
100235
101219
|
var GRAMMY_VERSION = (() => {
|
|
100236
101220
|
try {
|
|
100237
|
-
const raw =
|
|
101221
|
+
const raw = readFileSync60(new URL("../../node_modules/grammy/package.json", import.meta.url), "utf8");
|
|
100238
101222
|
return JSON.parse(raw).version ?? "unknown";
|
|
100239
101223
|
} catch {
|
|
100240
101224
|
return "unknown";
|
|
@@ -100297,7 +101281,7 @@ function assertSendable(f) {
|
|
|
100297
101281
|
} catch {
|
|
100298
101282
|
throw new Error(`refusing to send file \u2014 cannot resolve real path: ${f}`);
|
|
100299
101283
|
}
|
|
100300
|
-
const inbox =
|
|
101284
|
+
const inbox = join68(stateReal, "inbox");
|
|
100301
101285
|
if (real.startsWith(stateReal + sep4) && !real.startsWith(inbox + sep4)) {
|
|
100302
101286
|
throw new Error(`refusing to send channel state: ${f}`);
|
|
100303
101287
|
}
|
|
@@ -100316,7 +101300,7 @@ function assertSendable(f) {
|
|
|
100316
101300
|
}
|
|
100317
101301
|
function readAccessFile() {
|
|
100318
101302
|
try {
|
|
100319
|
-
const raw =
|
|
101303
|
+
const raw = readFileSync60(ACCESS_FILE, "utf8");
|
|
100320
101304
|
const parsed = JSON.parse(raw);
|
|
100321
101305
|
const allowFrom = validateStringArray("allowFrom", parsed.allowFrom ?? []);
|
|
100322
101306
|
const groups = {};
|
|
@@ -100356,7 +101340,7 @@ function readAccessFile() {
|
|
|
100356
101340
|
if (err.code === "ENOENT")
|
|
100357
101341
|
return defaultAccess();
|
|
100358
101342
|
try {
|
|
100359
|
-
|
|
101343
|
+
renameSync27(ACCESS_FILE, `${ACCESS_FILE}.corrupt-${Date.now()}`);
|
|
100360
101344
|
} catch {}
|
|
100361
101345
|
process.stderr.write(`telegram gateway: access.json is corrupt, moved aside. Starting fresh.
|
|
100362
101346
|
`);
|
|
@@ -100378,7 +101362,7 @@ function loadAccess() {
|
|
|
100378
101362
|
}
|
|
100379
101363
|
function readPeopleFile() {
|
|
100380
101364
|
try {
|
|
100381
|
-
const raw =
|
|
101365
|
+
const raw = readFileSync60(PEOPLE_FILE, "utf8");
|
|
100382
101366
|
const parsed = JSON.parse(raw);
|
|
100383
101367
|
if (!Array.isArray(parsed.entries))
|
|
100384
101368
|
return [];
|
|
@@ -100400,11 +101384,11 @@ function assertAllowedChat(chat_id) {
|
|
|
100400
101384
|
function saveAccess(a) {
|
|
100401
101385
|
if (STATIC)
|
|
100402
101386
|
return;
|
|
100403
|
-
|
|
101387
|
+
mkdirSync51(STATE_DIR, { recursive: true, mode: 448 });
|
|
100404
101388
|
const tmp = ACCESS_FILE + ".tmp";
|
|
100405
|
-
|
|
101389
|
+
writeFileSync50(tmp, JSON.stringify(a, null, 2) + `
|
|
100406
101390
|
`, { mode: 384 });
|
|
100407
|
-
|
|
101391
|
+
renameSync27(tmp, ACCESS_FILE);
|
|
100408
101392
|
}
|
|
100409
101393
|
function pruneExpired(a) {
|
|
100410
101394
|
const now = Date.now();
|
|
@@ -100422,7 +101406,7 @@ var HISTORY_ENABLED = HISTORY_ACCESS.historyEnabled !== false;
|
|
|
100422
101406
|
if (isGatewayMain && HISTORY_ENABLED) {
|
|
100423
101407
|
try {
|
|
100424
101408
|
initHistory(STATE_DIR, HISTORY_ACCESS.historyRetentionDays ?? 30);
|
|
100425
|
-
process.stderr.write(`telegram gateway: history capture enabled at ${
|
|
101409
|
+
process.stderr.write(`telegram gateway: history capture enabled at ${join68(STATE_DIR, "history.db")}
|
|
100426
101410
|
`);
|
|
100427
101411
|
} catch (err) {
|
|
100428
101412
|
process.stderr.write(`telegram gateway: history init failed (${err.message}) \u2014 capture disabled
|
|
@@ -100441,12 +101425,12 @@ if (isGatewayMain)
|
|
|
100441
101425
|
let markerTurnKey = null;
|
|
100442
101426
|
let markerAgeMs = null;
|
|
100443
101427
|
try {
|
|
100444
|
-
const markerPath =
|
|
101428
|
+
const markerPath = join68(STATE_DIR, TURN_ACTIVE_MARKER_FILE2);
|
|
100445
101429
|
if (existsSync57(markerPath)) {
|
|
100446
101430
|
const st = statSync22(markerPath);
|
|
100447
101431
|
markerAgeMs = Date.now() - st.mtimeMs;
|
|
100448
101432
|
try {
|
|
100449
|
-
const payload = JSON.parse(
|
|
101433
|
+
const payload = JSON.parse(readFileSync60(markerPath, "utf8"));
|
|
100450
101434
|
if (typeof payload.turnKey === "string" && payload.turnKey.length > 0) {
|
|
100451
101435
|
markerTurnKey = payload.turnKey;
|
|
100452
101436
|
}
|
|
@@ -100466,10 +101450,10 @@ if (isGatewayMain)
|
|
|
100466
101450
|
process.stderr.write(`telegram gateway: turn-registry boot-reaper stamped ${reaped} orphaned turn(s)` + `${timeoutTurnKey ? ` (turnKey=${timeoutTurnKey} as 'timeout', markerAgeMs=${markerAgeMs})` : " as 'restart'"}
|
|
100467
101451
|
`);
|
|
100468
101452
|
} else {
|
|
100469
|
-
process.stderr.write(`telegram gateway: turn-registry initialized at ${
|
|
101453
|
+
process.stderr.write(`telegram gateway: turn-registry initialized at ${join68(agentDir, "telegram", "registry.db")}
|
|
100470
101454
|
`);
|
|
100471
101455
|
}
|
|
100472
|
-
const bridgeDeadMarker = consumeBridgeDeadEscalationMarker(
|
|
101456
|
+
const bridgeDeadMarker = consumeBridgeDeadEscalationMarker(join68(STATE_DIR, "bridge-dead-escalation.json"));
|
|
100473
101457
|
if (bridgeDeadMarker != null) {
|
|
100474
101458
|
bridgeDeadPriorStreak = bridgeDeadMarker.count ?? 1;
|
|
100475
101459
|
process.stderr.write(`telegram gateway: boot: prior restart was a bridge-dead escalation (reason=${bridgeDeadMarker.reason}` + `, consecutive=${bridgeDeadPriorStreak}` + `${bridgeDeadMarker.crashTail ? `, crashTail=${bridgeDeadMarker.crashTail}` : ""})
|
|
@@ -100482,7 +101466,7 @@ if (isGatewayMain)
|
|
|
100482
101466
|
const pending2 = findLatestTurnIfInterrupted(turnsDb);
|
|
100483
101467
|
const selfAgent = process.env.SWITCHROOM_AGENT_NAME ?? "";
|
|
100484
101468
|
if (pending2 != null && selfAgent) {
|
|
100485
|
-
const bootResumeMarkerPath = process.env.SWITCHROOM_GATEWAY_CLEAN_SHUTDOWN_MARKER ??
|
|
101469
|
+
const bootResumeMarkerPath = process.env.SWITCHROOM_GATEWAY_CLEAN_SHUTDOWN_MARKER ?? join68(STATE_DIR, "clean-shutdown.json");
|
|
100486
101470
|
const bootResumeCleanMarker = readCleanShutdownMarker(bootResumeMarkerPath);
|
|
100487
101471
|
const bootResumeForceAlways = process.env.SWITCHROOM_BOOT_RESUME_ALWAYS === "1";
|
|
100488
101472
|
const bootResumeMode = parseBootResumeMode(process.env.SWITCHROOM_BOOT_RESUME);
|
|
@@ -100595,7 +101579,7 @@ if (isGatewayMain)
|
|
|
100595
101579
|
`);
|
|
100596
101580
|
}
|
|
100597
101581
|
}
|
|
100598
|
-
const pendingEnvPath =
|
|
101582
|
+
const pendingEnvPath = join68(agentDir, ".pending-turn.env");
|
|
100599
101583
|
try {
|
|
100600
101584
|
if (pending2 != null) {
|
|
100601
101585
|
const lines = [
|
|
@@ -100609,14 +101593,14 @@ if (isGatewayMain)
|
|
|
100609
101593
|
pending2.interrupt_reason != null ? `SWITCHROOM_PENDING_INTERRUPT_REASON=${pending2.interrupt_reason}` : `SWITCHROOM_PENDING_INTERRUPT_REASON=`
|
|
100610
101594
|
];
|
|
100611
101595
|
const pendingEnvTmp = `${pendingEnvPath}.tmp-${process.pid}`;
|
|
100612
|
-
|
|
101596
|
+
writeFileSync50(pendingEnvTmp, lines.join(`
|
|
100613
101597
|
`) + `
|
|
100614
101598
|
`, { mode: 384 });
|
|
100615
|
-
|
|
101599
|
+
renameSync27(pendingEnvTmp, pendingEnvPath);
|
|
100616
101600
|
process.stderr.write(`telegram gateway: pending-turn env written to ${pendingEnvPath} turnKey=${pending2.turn_key} endedVia=${pending2.ended_via ?? "open"}
|
|
100617
101601
|
`);
|
|
100618
101602
|
} else if (existsSync57(pendingEnvPath)) {
|
|
100619
|
-
|
|
101603
|
+
rmSync8(pendingEnvPath, { force: true });
|
|
100620
101604
|
process.stderr.write(`telegram gateway: pending-turn env cleared (clean previous shutdown)
|
|
100621
101605
|
`);
|
|
100622
101606
|
}
|
|
@@ -100723,16 +101707,16 @@ function checkApprovals() {
|
|
|
100723
101707
|
return;
|
|
100724
101708
|
}
|
|
100725
101709
|
for (const senderId of files) {
|
|
100726
|
-
const file =
|
|
100727
|
-
bot.api.sendMessage(senderId, "Paired! Say hi to Claude.").then(() =>
|
|
101710
|
+
const file = join68(APPROVED_DIR, senderId);
|
|
101711
|
+
bot.api.sendMessage(senderId, "Paired! Say hi to Claude.").then(() => rmSync8(file, { force: true }), (err) => {
|
|
100728
101712
|
process.stderr.write(`telegram gateway: failed to send approval confirm: ${err}
|
|
100729
101713
|
`);
|
|
100730
|
-
|
|
101714
|
+
rmSync8(file, { force: true });
|
|
100731
101715
|
});
|
|
100732
101716
|
}
|
|
100733
101717
|
}
|
|
100734
101718
|
if (isGatewayMain && !STATIC)
|
|
100735
|
-
setInterval(checkApprovals, 5000).unref();
|
|
101719
|
+
setInterval(attachBootBeacon(STATE_DIR, checkApprovals), 5000).unref();
|
|
100736
101720
|
if (isGatewayMain && !STATIC)
|
|
100737
101721
|
startGatewayHeartbeat(STATE_DIR);
|
|
100738
101722
|
var IDLE_CLEAR_CHECK_MS = Number(process.env.SWITCHROOM_IDLE_CLEAR_CHECK_MS ?? 60000);
|
|
@@ -100897,12 +101881,14 @@ function noteAgentOutputAt(key, ts) {
|
|
|
100897
101881
|
lastAgentOutputAt.delete(oldest);
|
|
100898
101882
|
}
|
|
100899
101883
|
}
|
|
100900
|
-
var OBLIGATION_STORE_PATH =
|
|
101884
|
+
var OBLIGATION_STORE_PATH = join68(STATE_DIR, "obligations.json");
|
|
100901
101885
|
var obligationStoreFs = {
|
|
100902
|
-
readFileSync: (p) =>
|
|
100903
|
-
writeFileSync: (p, d) =>
|
|
100904
|
-
renameSync: (a, b) =>
|
|
100905
|
-
existsSync: (p) => existsSync57(p)
|
|
101886
|
+
readFileSync: (p) => readFileSync60(p, "utf8"),
|
|
101887
|
+
writeFileSync: (p, d) => writeFileSync50(p, d),
|
|
101888
|
+
renameSync: (a, b) => renameSync27(a, b),
|
|
101889
|
+
existsSync: (p) => existsSync57(p),
|
|
101890
|
+
fsyncFileSync: fsyncPathSync,
|
|
101891
|
+
fsyncDirSync: fsyncPathSync
|
|
100906
101892
|
};
|
|
100907
101893
|
var obligationLedger = new ObligationLedger(OBLIGATION_REPRESENT_MAX, {
|
|
100908
101894
|
onChange: STATIC || !OBLIGATION_LEDGER_ENABLED ? undefined : (snapshot) => persistObligations(OBLIGATION_STORE_PATH, obligationStoreFs, snapshot)
|
|
@@ -101677,7 +102663,7 @@ function emitTurnRecord(turn, endedAt) {
|
|
|
101677
102663
|
return;
|
|
101678
102664
|
}
|
|
101679
102665
|
},
|
|
101680
|
-
rename: (from, to) =>
|
|
102666
|
+
rename: (from, to) => renameSync27(from, to)
|
|
101681
102667
|
});
|
|
101682
102668
|
appendFileSync9(turnsPath, rec);
|
|
101683
102669
|
} catch {}
|
|
@@ -102225,7 +103211,7 @@ function maybePostMissedApprovalDigest(reason) {
|
|
|
102225
103211
|
const first = entries[0];
|
|
102226
103212
|
const chatId = first.chatId;
|
|
102227
103213
|
const threadId = first.threadId ?? undefined;
|
|
102228
|
-
const digestId =
|
|
103214
|
+
const digestId = randomBytes13(4).toString("hex");
|
|
102229
103215
|
const text5 = renderMissedApprovalsDigest(entries, {
|
|
102230
103216
|
agentName: process.env.SWITCHROOM_AGENT_NAME ?? null
|
|
102231
103217
|
});
|
|
@@ -103240,27 +104226,27 @@ var PIN_STATUS_WHILE_WORKING = (() => {
|
|
|
103240
104226
|
})();
|
|
103241
104227
|
var statusPinClaims = new Map;
|
|
103242
104228
|
var statusPinRightsCache = new PinRightsCache2;
|
|
103243
|
-
var STATUS_PIN_STORE_PATH =
|
|
104229
|
+
var STATUS_PIN_STORE_PATH = join68(STATE_DIR, "status-pins.json");
|
|
103244
104230
|
var statusPinStoreFs = {
|
|
103245
|
-
readFileSync: (p) =>
|
|
103246
|
-
writeFileSync: (p, d) =>
|
|
103247
|
-
renameSync: (a, b) =>
|
|
104231
|
+
readFileSync: (p) => readFileSync60(p, "utf8"),
|
|
104232
|
+
writeFileSync: (p, d) => writeFileSync50(p, d),
|
|
104233
|
+
renameSync: (a, b) => renameSync27(a, b),
|
|
103248
104234
|
existsSync: (p) => existsSync57(p)
|
|
103249
104235
|
};
|
|
103250
104236
|
var statusPinPersistEnabled = !STATIC && PIN_STATUS_WHILE_WORKING;
|
|
103251
|
-
var ACTIVITY_CARD_STORE_PATH =
|
|
104237
|
+
var ACTIVITY_CARD_STORE_PATH = join68(STATE_DIR, "activity-cards-pending.json");
|
|
103252
104238
|
var activityCardStoreFs = {
|
|
103253
|
-
readFileSync: (p) =>
|
|
103254
|
-
writeFileSync: (p, d) =>
|
|
103255
|
-
renameSync: (a, b) =>
|
|
104239
|
+
readFileSync: (p) => readFileSync60(p, "utf8"),
|
|
104240
|
+
writeFileSync: (p, d) => writeFileSync50(p, d),
|
|
104241
|
+
renameSync: (a, b) => renameSync27(a, b),
|
|
103256
104242
|
existsSync: (p) => existsSync57(p)
|
|
103257
104243
|
};
|
|
103258
104244
|
var activityCardPersistEnabled = !STATIC;
|
|
103259
|
-
var QUEUED_CARD_STORE_PATH =
|
|
104245
|
+
var QUEUED_CARD_STORE_PATH = join68(STATE_DIR, "queued-cards-pending.json");
|
|
103260
104246
|
var queuedCardStoreFs = {
|
|
103261
|
-
readFileSync: (p) =>
|
|
103262
|
-
writeFileSync: (p, d) =>
|
|
103263
|
-
renameSync: (a, b) =>
|
|
104247
|
+
readFileSync: (p) => readFileSync60(p, "utf8"),
|
|
104248
|
+
writeFileSync: (p, d) => writeFileSync50(p, d),
|
|
104249
|
+
renameSync: (a, b) => renameSync27(a, b),
|
|
103264
104250
|
existsSync: (p) => existsSync57(p)
|
|
103265
104251
|
};
|
|
103266
104252
|
var queuedCardPersistEnabled = !STATIC;
|
|
@@ -103499,16 +104485,16 @@ var midSessionCardReaper = isGatewayMain ? setInterval(() => {
|
|
|
103499
104485
|
midSessionReaperGuard.tick();
|
|
103500
104486
|
}, MID_SESSION_CARD_REAPER_INTERVAL_MS) : undefined;
|
|
103501
104487
|
midSessionCardReaper?.unref();
|
|
103502
|
-
async function reconcileStatusPin(pinKey, chatId, desired) {
|
|
104488
|
+
async function reconcileStatusPin(pinKey, chatId, desired, threadId) {
|
|
103503
104489
|
try {
|
|
103504
|
-
await withPinReconcileLock(pinKey, () => reconcileStatusPinInner(pinKey, chatId, desired));
|
|
104490
|
+
await withPinReconcileLock(pinKey, () => reconcileStatusPinInner(pinKey, chatId, desired, threadId));
|
|
103505
104491
|
} catch (err) {
|
|
103506
104492
|
const msg = err instanceof Error ? err.message : String(err);
|
|
103507
104493
|
process.stderr.write(`telegram gateway: status-pin reconcile absorbed error (key=${pinKey} chat=${chatId}): ${msg}
|
|
103508
104494
|
`);
|
|
103509
104495
|
}
|
|
103510
104496
|
}
|
|
103511
|
-
async function reconcileStatusPinInner(pinKey, chatId, desired) {
|
|
104497
|
+
async function reconcileStatusPinInner(pinKey, chatId, desired, threadId) {
|
|
103512
104498
|
if (!PIN_STATUS_WHILE_WORKING)
|
|
103513
104499
|
return;
|
|
103514
104500
|
if (chatId.length === 0)
|
|
@@ -103534,6 +104520,7 @@ async function reconcileStatusPinInner(pinKey, chatId, desired) {
|
|
|
103534
104520
|
await runStatusPinReconcile({
|
|
103535
104521
|
pinKey,
|
|
103536
104522
|
chatId,
|
|
104523
|
+
threadId,
|
|
103537
104524
|
prev,
|
|
103538
104525
|
desired,
|
|
103539
104526
|
persist: statusPinPersistEnabled ? { path: STATUS_PIN_STORE_PATH, fs: statusPinStoreFs } : null,
|
|
@@ -103546,37 +104533,26 @@ async function unpinAllStatusPins() {
|
|
|
103546
104533
|
await reconcileStatusPin(key, claim.chatId, { pinned: false });
|
|
103547
104534
|
}
|
|
103548
104535
|
}
|
|
103549
|
-
var
|
|
103550
|
-
var
|
|
103551
|
-
|
|
103552
|
-
|
|
103553
|
-
|
|
103554
|
-
|
|
103555
|
-
|
|
103556
|
-
|
|
103557
|
-
|
|
103558
|
-
|
|
103559
|
-
|
|
103560
|
-
|
|
103561
|
-
|
|
103562
|
-
ids.push(claim.messageId);
|
|
103563
|
-
}
|
|
103564
|
-
if (statusPinPersistEnabled || bannerPinPersistEnabled || toolPinPersistEnabled) {
|
|
103565
|
-
try {
|
|
103566
|
-
ids.push(...unexpiredStoreRepinIds(loadStatusPins2(STATUS_PIN_STORE_PATH, statusPinStoreFs), chatId, Date.now()));
|
|
103567
|
-
} catch (err) {
|
|
103568
|
-
process.stderr.write(`telegram gateway: dm-pin-sweep: store repin scan failed (chat=${chatId}): ${err.message}
|
|
103569
|
-
`);
|
|
103570
|
-
}
|
|
104536
|
+
var stalePinSweepEligible = false;
|
|
104537
|
+
var STALE_PIN_SWEEP_STORE_PATH = join68(STATE_DIR, "stale-pin-sweep.json");
|
|
104538
|
+
var stalePinSweeper = createGatewayStalePinSweeper({
|
|
104539
|
+
telegram: { handle: () => lockedBot, call: robustApiCall },
|
|
104540
|
+
claims: () => statusPinClaims.values(),
|
|
104541
|
+
loadPinRows: () => statusPinPersistEnabled || bannerPinPersistEnabled || toolPinPersistEnabled ? loadStatusPins2(STATUS_PIN_STORE_PATH, statusPinStoreFs) : [],
|
|
104542
|
+
eligible: () => stalePinSweepEligible,
|
|
104543
|
+
store: {
|
|
104544
|
+
path: STALE_PIN_SWEEP_STORE_PATH,
|
|
104545
|
+
fs: {
|
|
104546
|
+
readFileSync: (p) => readFileSync60(p, "utf-8"),
|
|
104547
|
+
writeFileSync: (p, data) => atomicWriteFileSync(p, data, 384),
|
|
104548
|
+
existsSync: (p) => existsSync57(p)
|
|
103571
104549
|
}
|
|
103572
|
-
return ids;
|
|
103573
104550
|
},
|
|
103574
|
-
|
|
103575
|
-
log: (line) => process.stderr.write(line)
|
|
104551
|
+
allowUnpinAllForumTopic: process.env.SWITCHROOM_PIN_SWEEP_UNPIN_ALL_TOPIC == null ? undefined : process.env.SWITCHROOM_PIN_SWEEP_UNPIN_ALL_TOPIC === "1"
|
|
103576
104552
|
});
|
|
103577
|
-
function
|
|
104553
|
+
function runBootPinCleanupAndStalePinSweep() {
|
|
103578
104554
|
return runBootPinSweepSteps({
|
|
103579
|
-
|
|
104555
|
+
scanSweepTargets: () => collectSweepTargets({
|
|
103580
104556
|
statusPins: statusPinPersistEnabled || bannerPinPersistEnabled || toolPinPersistEnabled ? loadStatusPins2(STATUS_PIN_STORE_PATH, statusPinStoreFs) : [],
|
|
103581
104557
|
activityCards: activityCardPersistEnabled ? loadActivityCards2(ACTIVITY_CARD_STORE_PATH, activityCardStoreFs) : [],
|
|
103582
104558
|
queuedCards: queuedCardPersistEnabled ? loadQueuedCards(QUEUED_CARD_STORE_PATH, queuedCardStoreFs) : []
|
|
@@ -103584,14 +104560,14 @@ function runBootPinCleanupAndDmSweep() {
|
|
|
103584
104560
|
statusPinCleanup: statusPinBootCleanup,
|
|
103585
104561
|
activityCardReaper: activityCardBootReaper,
|
|
103586
104562
|
queuedCardReaper: queuedCardBootReaper,
|
|
103587
|
-
|
|
103588
|
-
|
|
104563
|
+
enableSweep: () => {
|
|
104564
|
+
stalePinSweepEligible = true;
|
|
103589
104565
|
},
|
|
103590
|
-
|
|
104566
|
+
sweepTarget: (t) => stalePinSweeper.sweepTarget(t),
|
|
103591
104567
|
log: (line) => process.stderr.write(line)
|
|
103592
104568
|
});
|
|
103593
104569
|
}
|
|
103594
|
-
var bootPinSweepGate = createBootSweepGate({ run:
|
|
104570
|
+
var bootPinSweepGate = createBootSweepGate({ run: runBootPinCleanupAndStalePinSweep, onError: (err) => process.stderr.write(`telegram gateway: boot pin cleanup / stale-pin sweep failed: ${err.message}
|
|
103595
104571
|
`) });
|
|
103596
104572
|
var progressDriver = null;
|
|
103597
104573
|
var unpinProgressCardForChat = null;
|
|
@@ -103599,12 +104575,12 @@ var getPinnedProgressCardMessageId = null;
|
|
|
103599
104575
|
var completeProgressCardTurn = null;
|
|
103600
104576
|
var subagentWatcher = null;
|
|
103601
104577
|
var workerActivityFeed = null;
|
|
103602
|
-
var SOCKET_PATH = process.env.SWITCHROOM_GATEWAY_SOCKET ??
|
|
104578
|
+
var SOCKET_PATH = process.env.SWITCHROOM_GATEWAY_SOCKET ?? join68(STATE_DIR, "gateway.sock");
|
|
103603
104579
|
if (isGatewayMain)
|
|
103604
|
-
|
|
103605
|
-
var GATEWAY_PID_PATH = process.env.SWITCHROOM_GATEWAY_PID_FILE ??
|
|
103606
|
-
var GATEWAY_SESSION_MARKER_PATH = process.env.SWITCHROOM_GATEWAY_SESSION_MARKER ??
|
|
103607
|
-
var GATEWAY_CLEAN_SHUTDOWN_MARKER_PATH = process.env.SWITCHROOM_GATEWAY_CLEAN_SHUTDOWN_MARKER ??
|
|
104580
|
+
mkdirSync51(STATE_DIR, { recursive: true, mode: 448 });
|
|
104581
|
+
var GATEWAY_PID_PATH = process.env.SWITCHROOM_GATEWAY_PID_FILE ?? join68(STATE_DIR, "gateway.pid.json");
|
|
104582
|
+
var GATEWAY_SESSION_MARKER_PATH = process.env.SWITCHROOM_GATEWAY_SESSION_MARKER ?? join68(STATE_DIR, "gateway-session.json");
|
|
104583
|
+
var GATEWAY_CLEAN_SHUTDOWN_MARKER_PATH = process.env.SWITCHROOM_GATEWAY_CLEAN_SHUTDOWN_MARKER ?? join68(STATE_DIR, "clean-shutdown.json");
|
|
103608
104584
|
var GATEWAY_STARTED_AT_MS = Date.now();
|
|
103609
104585
|
var BOOT_CARD_ENABLED = process.env.SWITCHROOM_BOOT_CARD !== "false";
|
|
103610
104586
|
var activeBootCard = null;
|
|
@@ -103633,7 +104609,7 @@ function ensureIssuesCard(chatId, threadId) {
|
|
|
103633
104609
|
bot: botApi,
|
|
103634
104610
|
log: (msg) => process.stderr.write(`telegram gateway: ${msg}
|
|
103635
104611
|
`),
|
|
103636
|
-
persistPath:
|
|
104612
|
+
persistPath: join68(stateDir, "issues-card.json")
|
|
103637
104613
|
});
|
|
103638
104614
|
activeIssuesWatcher = startIssuesWatcher({
|
|
103639
104615
|
stateDir,
|
|
@@ -103833,14 +104809,16 @@ if (isGatewayMain)
|
|
|
103833
104809
|
var inboundSpool;
|
|
103834
104810
|
if (isGatewayMain)
|
|
103835
104811
|
inboundSpool = STATIC ? undefined : createInboundSpool({
|
|
103836
|
-
path:
|
|
104812
|
+
path: join68(STATE_DIR, "inbound-spool.jsonl"),
|
|
103837
104813
|
fs: {
|
|
103838
104814
|
appendFileSync: (p, d) => appendFileSync9(p, d),
|
|
103839
|
-
readFileSync: (p) =>
|
|
103840
|
-
writeFileSync: (p, d) =>
|
|
103841
|
-
renameSync: (a, b) =>
|
|
104815
|
+
readFileSync: (p) => readFileSync60(p, "utf8"),
|
|
104816
|
+
writeFileSync: (p, d) => writeFileSync50(p, d),
|
|
104817
|
+
renameSync: (a, b) => renameSync27(a, b),
|
|
103842
104818
|
existsSync: (p) => existsSync57(p),
|
|
103843
|
-
statSizeSync: (p) => statSync22(p).size
|
|
104819
|
+
statSizeSync: (p) => statSync22(p).size,
|
|
104820
|
+
fsyncFileSync: fsyncPathSync,
|
|
104821
|
+
fsyncDirSync: fsyncPathSync
|
|
103844
104822
|
},
|
|
103845
104823
|
onDegraded: (info) => {
|
|
103846
104824
|
process.stderr.write(`telegram gateway: inbound-spool durability ${info.degraded ? "DEGRADED to in-memory-only" : "RECOVERED"} path=${info.path} consecutiveFailures=${info.consecutiveFailures}${info.error != null ? ` error=${info.error}` : ""}
|
|
@@ -103901,13 +104879,13 @@ async function maybeRedeliverUndeliveredAnswer() {
|
|
|
103901
104879
|
let transcriptText;
|
|
103902
104880
|
try {
|
|
103903
104881
|
const projectsDir = getProjectsDirForCwd();
|
|
103904
|
-
const path3 =
|
|
104882
|
+
const path3 = join68(projectsDir, `${sessionId}.jsonl`);
|
|
103905
104883
|
if (!existsSync57(path3)) {
|
|
103906
104884
|
process.stderr.write(`telegram gateway: crash-redelivery \u2014 transcript not found for turnKey=${turn.turn_key} session=${sessionId} (${path3}); skipping
|
|
103907
104885
|
`);
|
|
103908
104886
|
return;
|
|
103909
104887
|
}
|
|
103910
|
-
transcriptText =
|
|
104888
|
+
transcriptText = readFileSync60(path3, "utf8");
|
|
103911
104889
|
} catch (err) {
|
|
103912
104890
|
process.stderr.write(`telegram gateway: crash-redelivery \u2014 transcript read failed turnKey=${turn.turn_key}: ${err.message}
|
|
103913
104891
|
`);
|
|
@@ -104024,13 +105002,13 @@ function dispatchPermissionVerdict(ev) {
|
|
|
104024
105002
|
}
|
|
104025
105003
|
}
|
|
104026
105004
|
function rearmPermissionFromStore(msg, persisted) {
|
|
104027
|
-
const { requestId, toolName, description, inputPreview } = msg;
|
|
105005
|
+
const { requestId, toolName, description: description2, inputPreview } = msg;
|
|
104028
105006
|
const startedAt = persisted.reduce((min, c) => c.startedAt < min ? c.startedAt : min, persisted[0].startedAt);
|
|
104029
105007
|
const cardText = persisted[0].cardText;
|
|
104030
105008
|
const cards = persisted.map((c) => ({ chatId: c.chatId, messageId: c.messageId }));
|
|
104031
105009
|
pendingPermissions.set(requestId, {
|
|
104032
105010
|
tool_name: toolName,
|
|
104033
|
-
description,
|
|
105011
|
+
description: description2,
|
|
104034
105012
|
input_preview: inputPreview,
|
|
104035
105013
|
startedAt,
|
|
104036
105014
|
card_text: cardText,
|
|
@@ -104066,8 +105044,8 @@ var bridgeDeadWatchdog = createBridgeDeadWatchdog({
|
|
|
104066
105044
|
isSessionAlive: () => findAgentProcessInContainer2()?.comm === "claude",
|
|
104067
105045
|
isShuttingDown: () => shuttingDown,
|
|
104068
105046
|
escalate: (reason) => triggerSelfRestart(process.env.SWITCHROOM_AGENT_NAME ?? "", reason, 1500),
|
|
104069
|
-
crashLogPath:
|
|
104070
|
-
markerPath:
|
|
105047
|
+
crashLogPath: join68(STATE_DIR, "bridge-crash.log"),
|
|
105048
|
+
markerPath: join68(STATE_DIR, "bridge-dead-escalation.json"),
|
|
104071
105049
|
log: (line) => process.stderr.write(`${line}
|
|
104072
105050
|
`),
|
|
104073
105051
|
priorStreak: bridgeDeadPriorStreak,
|
|
@@ -104173,8 +105151,8 @@ if (isGatewayMain)
|
|
|
104173
105151
|
probeQuotaViaBroker: (t) => probeQuotaForBootCard(agentSlug, t),
|
|
104174
105152
|
tmuxSupervisor: process.env.SWITCHROOM_TMUX_SUPERVISOR === "1",
|
|
104175
105153
|
dockerMode: process.env.SWITCHROOM_RUNTIME === "docker",
|
|
104176
|
-
configSnapshotPath:
|
|
104177
|
-
bootCardStatePath:
|
|
105154
|
+
configSnapshotPath: join68(resolvedAgentDirForCard, ".config-snapshot.json"),
|
|
105155
|
+
bootCardStatePath: join68(resolvedAgentDirForCard, ".boot-card-msgid.json"),
|
|
104178
105156
|
floodStatePath: FLOOD_STATE_PATH,
|
|
104179
105157
|
...updateOutcomeLine ? { updateOutcomeLine } : {}
|
|
104180
105158
|
}, ackMsgId).then((handle) => {
|
|
@@ -104289,7 +105267,7 @@ if (isGatewayMain)
|
|
|
104289
105267
|
}
|
|
104290
105268
|
},
|
|
104291
105269
|
onPermissionRequest(_client, msg) {
|
|
104292
|
-
const { requestId, toolName, description, inputPreview } = msg;
|
|
105270
|
+
const { requestId, toolName, description: description2, inputPreview } = msg;
|
|
104293
105271
|
if (isPermissionRearmEnabled()) {
|
|
104294
105272
|
const persisted = pendingPermissions.has(requestId) ? [] : permCardStore.loadAll().filter((e) => e.requestId === requestId);
|
|
104295
105273
|
const disposition = classifyPermissionRequest({
|
|
@@ -104333,10 +105311,10 @@ if (isGatewayMain)
|
|
|
104333
105311
|
const text5 = formatPermissionCardBody({
|
|
104334
105312
|
toolName,
|
|
104335
105313
|
inputPreview,
|
|
104336
|
-
description,
|
|
105314
|
+
description: description2,
|
|
104337
105315
|
agentName: _client.agentName
|
|
104338
105316
|
});
|
|
104339
|
-
const pendEntry = { tool_name: toolName, description, input_preview: inputPreview, startedAt: Date.now(), card_text: text5, cards: [] };
|
|
105317
|
+
const pendEntry = { tool_name: toolName, description: description2, input_preview: inputPreview, startedAt: Date.now(), card_text: text5, cards: [] };
|
|
104340
105318
|
pendingPermissions.set(requestId, pendEntry);
|
|
104341
105319
|
const activeTurn = currentTurn;
|
|
104342
105320
|
postPermissionCard(requestId, pendEntry);
|
|
@@ -104842,7 +105820,7 @@ if (isGatewayMain)
|
|
|
104842
105820
|
const receiverUid = receiverUidRaw ? Number(receiverUidRaw) : NaN;
|
|
104843
105821
|
if (Number.isInteger(receiverUid))
|
|
104844
105822
|
allowedUids.push(receiverUid);
|
|
104845
|
-
const socketPath =
|
|
105823
|
+
const socketPath = join68(STATE_DIR, "webhook.sock");
|
|
104846
105824
|
const webhookInject = (agentName3, inbound) => {
|
|
104847
105825
|
const msg = inbound;
|
|
104848
105826
|
const delivered = ipcServer.sendToAgent(agentName3, msg);
|
|
@@ -105070,9 +106048,9 @@ function redactOutboundText(text5, site) {
|
|
|
105070
106048
|
var VOICE_OUT_DEFAULT_CHUNK_CHARS = 600;
|
|
105071
106049
|
var VOICE_OUT_HARD_CHUNK_CAP = 4096;
|
|
105072
106050
|
var voiceOnDemandCache = new VoiceOnDemandCache({
|
|
105073
|
-
persistPath:
|
|
106051
|
+
persistPath: join68(STATE_DIR, "voice-ondemand.json")
|
|
105074
106052
|
});
|
|
105075
|
-
var VOICE_CACHE_DIR =
|
|
106053
|
+
var VOICE_CACHE_DIR = join68(STATE_DIR, "voice-cache");
|
|
105076
106054
|
var voicePreSynthQueue = new PreSynthQueue({
|
|
105077
106055
|
runJob: async (job) => {
|
|
105078
106056
|
const sidecarToken = await materializeSidecarToken2();
|
|
@@ -105474,11 +106452,11 @@ async function executeSendGif(rawArgs) {
|
|
|
105474
106452
|
};
|
|
105475
106453
|
}
|
|
105476
106454
|
async function publishToTelegraph(text5, shortName, authorName) {
|
|
105477
|
-
const accountPath =
|
|
106455
|
+
const accountPath = join68(STATE_DIR, "telegraph-account.json");
|
|
105478
106456
|
let account = null;
|
|
105479
106457
|
try {
|
|
105480
106458
|
if (existsSync57(accountPath)) {
|
|
105481
|
-
const raw =
|
|
106459
|
+
const raw = readFileSync60(accountPath, "utf-8");
|
|
105482
106460
|
const parsed = JSON.parse(raw);
|
|
105483
106461
|
if (parsed.shortName && parsed.accessToken) {
|
|
105484
106462
|
account = parsed;
|
|
@@ -105497,8 +106475,8 @@ async function publishToTelegraph(text5, shortName, authorName) {
|
|
|
105497
106475
|
}
|
|
105498
106476
|
account = created.value;
|
|
105499
106477
|
try {
|
|
105500
|
-
|
|
105501
|
-
|
|
106478
|
+
mkdirSync51(STATE_DIR, { recursive: true, mode: 448 });
|
|
106479
|
+
writeFileSync50(accountPath, JSON.stringify(account, null, 2), { mode: 384 });
|
|
105502
106480
|
} catch (err) {
|
|
105503
106481
|
process.stderr.write(`telegram gateway: telegraph cache write failed: ${err.message}
|
|
105504
106482
|
`);
|
|
@@ -105614,7 +106592,7 @@ _The secret was NOT saved. The agent can re-request with \`request_secret\`._`,
|
|
|
105614
106592
|
}
|
|
105615
106593
|
function readLiveSwitchroomConfigText() {
|
|
105616
106594
|
const cfgPath = process.env.SWITCHROOM_CONFIG ?? findConfigFile2();
|
|
105617
|
-
return
|
|
106595
|
+
return readFileSync60(cfgPath, "utf8");
|
|
105618
106596
|
}
|
|
105619
106597
|
async function executeReact(args) {
|
|
105620
106598
|
if (!args.chat_id)
|
|
@@ -105653,9 +106631,9 @@ async function executeDownloadAttachment(args) {
|
|
|
105653
106631
|
fileUniqueId: file.file_unique_id,
|
|
105654
106632
|
now: Date.now()
|
|
105655
106633
|
});
|
|
105656
|
-
|
|
106634
|
+
mkdirSync51(INBOX_DIR, { recursive: true, mode: 448 });
|
|
105657
106635
|
assertInsideInbox2(INBOX_DIR, dlPath);
|
|
105658
|
-
|
|
106636
|
+
writeFileSync50(dlPath, buf, { mode: 384 });
|
|
105659
106637
|
return { content: [{ type: "text", text: dlPath }] };
|
|
105660
106638
|
}
|
|
105661
106639
|
async function executeEditMessage(args) {
|
|
@@ -106299,7 +107277,7 @@ function gate(ctx) {
|
|
|
106299
107277
|
}
|
|
106300
107278
|
if (Object.keys(access.pending).length >= 3)
|
|
106301
107279
|
return { action: "drop", reason: "pairing_capacity" };
|
|
106302
|
-
const code2 =
|
|
107280
|
+
const code2 = randomBytes13(3).toString("hex");
|
|
106303
107281
|
const now = Date.now();
|
|
106304
107282
|
access.pending[code2] = {
|
|
106305
107283
|
senderId,
|
|
@@ -106539,8 +107517,13 @@ async function handleInbound(ctx, text5, downloadImage, attachment, extraAttachm
|
|
|
106539
107517
|
maybePostMissedApprovalDigest("operator inbound");
|
|
106540
107518
|
{
|
|
106541
107519
|
const inboundChatId = ctx.chat?.id;
|
|
106542
|
-
if (inboundChatId != null)
|
|
106543
|
-
|
|
107520
|
+
if (inboundChatId != null) {
|
|
107521
|
+
stalePinSweeper.sweepTarget({
|
|
107522
|
+
chatId: String(inboundChatId),
|
|
107523
|
+
threadId: ctx.message?.message_thread_id,
|
|
107524
|
+
isForum: ctx.chat?.is_forum === true
|
|
107525
|
+
});
|
|
107526
|
+
}
|
|
106544
107527
|
}
|
|
106545
107528
|
const inboundReceivedAt = Date.now();
|
|
106546
107529
|
const machineInTurnAtReceipt = isMachineInTurn();
|
|
@@ -107023,14 +108006,14 @@ function restartMarkerPath() {
|
|
|
107023
108006
|
const agentDir = resolveAgentDirFromEnv();
|
|
107024
108007
|
if (!agentDir)
|
|
107025
108008
|
return null;
|
|
107026
|
-
return
|
|
108009
|
+
return join68(agentDir, "restart-pending.json");
|
|
107027
108010
|
}
|
|
107028
108011
|
function writeRestartMarker(marker) {
|
|
107029
108012
|
const p = restartMarkerPath();
|
|
107030
108013
|
if (!p)
|
|
107031
108014
|
return;
|
|
107032
108015
|
try {
|
|
107033
|
-
|
|
108016
|
+
writeFileSync50(p, JSON.stringify(marker));
|
|
107034
108017
|
lastPlannedRestartAt = Date.now();
|
|
107035
108018
|
process.stderr.write(`telegram gateway: restart-marker: write chat_id=${marker.chat_id} thread_id=${marker.thread_id ?? "-"} ack=${marker.ack_message_id ?? "-"} path=${p}
|
|
107036
108019
|
`);
|
|
@@ -107049,7 +108032,7 @@ function readRestartMarker() {
|
|
|
107049
108032
|
if (!p)
|
|
107050
108033
|
return null;
|
|
107051
108034
|
try {
|
|
107052
|
-
return JSON.parse(
|
|
108035
|
+
return JSON.parse(readFileSync60(p, "utf8"));
|
|
107053
108036
|
} catch {
|
|
107054
108037
|
return null;
|
|
107055
108038
|
}
|
|
@@ -107059,7 +108042,7 @@ function clearRestartMarker() {
|
|
|
107059
108042
|
if (!p)
|
|
107060
108043
|
return;
|
|
107061
108044
|
try {
|
|
107062
|
-
|
|
108045
|
+
rmSync8(p, { force: true });
|
|
107063
108046
|
process.stderr.write(`telegram gateway: restart-marker: cleared path=${p}
|
|
107064
108047
|
`);
|
|
107065
108048
|
} catch {}
|
|
@@ -107215,12 +108198,12 @@ function _resetDockerReachableCache() {
|
|
|
107215
108198
|
}
|
|
107216
108199
|
function spawnSwitchroomDetached(args, onFailure) {
|
|
107217
108200
|
const fullArgs = SWITCHROOM_CONFIG ? ["--config", SWITCHROOM_CONFIG, ...args] : args;
|
|
107218
|
-
const logPath =
|
|
108201
|
+
const logPath = join68(STATE_DIR, "detached-spawn.log");
|
|
107219
108202
|
let outFd = null;
|
|
107220
108203
|
try {
|
|
107221
|
-
|
|
107222
|
-
outFd =
|
|
107223
|
-
|
|
108204
|
+
mkdirSync51(STATE_DIR, { recursive: true });
|
|
108205
|
+
outFd = openSync15(logPath, "a");
|
|
108206
|
+
writeFileSync50(logPath, `
|
|
107224
108207
|
[${new Date().toISOString()}] spawn ${SWITCHROOM_CLI} ${fullArgs.join(" ")}
|
|
107225
108208
|
`, { flag: "a" });
|
|
107226
108209
|
} catch {}
|
|
@@ -107234,7 +108217,7 @@ function spawnSwitchroomDetached(args, onFailure) {
|
|
|
107234
108217
|
});
|
|
107235
108218
|
if (outFd != null) {
|
|
107236
108219
|
try {
|
|
107237
|
-
|
|
108220
|
+
closeSync15(outFd);
|
|
107238
108221
|
} catch {}
|
|
107239
108222
|
}
|
|
107240
108223
|
if (onFailure) {
|
|
@@ -107246,7 +108229,7 @@ function spawnSwitchroomDetached(args, onFailure) {
|
|
|
107246
108229
|
return;
|
|
107247
108230
|
let tail = "";
|
|
107248
108231
|
try {
|
|
107249
|
-
const full =
|
|
108232
|
+
const full = readFileSync60(logPath, "utf8");
|
|
107250
108233
|
tail = full.split(`
|
|
107251
108234
|
`).slice(-30).join(`
|
|
107252
108235
|
`).trim();
|
|
@@ -107508,10 +108491,10 @@ ${preBlock(formatSwitchroomOutput(detail))}`, { html: true });
|
|
|
107508
108491
|
}
|
|
107509
108492
|
function readRecentDenialsForAgent(agentName3, windowMs, limit) {
|
|
107510
108493
|
try {
|
|
107511
|
-
const auditPath =
|
|
108494
|
+
const auditPath = join68(homedir19(), ".switchroom", "vault-audit.log");
|
|
107512
108495
|
if (!existsSync57(auditPath))
|
|
107513
108496
|
return [];
|
|
107514
|
-
const raw =
|
|
108497
|
+
const raw = readFileSync60(auditPath, "utf8");
|
|
107515
108498
|
return recentDenialsFromAuditLog(raw, { agentName: agentName3, windowMs, limit });
|
|
107516
108499
|
} catch {
|
|
107517
108500
|
return [];
|
|
@@ -107562,7 +108545,7 @@ async function buildAgentMetadata(agentName3) {
|
|
|
107562
108545
|
try {
|
|
107563
108546
|
const agentDir = resolveAgentDirFromEnv();
|
|
107564
108547
|
if (agentDir) {
|
|
107565
|
-
const raw =
|
|
108548
|
+
const raw = readFileSync60(join68(agentDir, ".claude", ".claude.json"), "utf8");
|
|
107566
108549
|
claudeJson = JSON.parse(raw);
|
|
107567
108550
|
}
|
|
107568
108551
|
} catch {}
|
|
@@ -107691,7 +108674,7 @@ function buildModelDeps(restartCtx) {
|
|
|
107691
108674
|
try {
|
|
107692
108675
|
const agentDir = resolveAgentDirFromEnv();
|
|
107693
108676
|
if (agentDir) {
|
|
107694
|
-
const local = await fetchQuota2({ claudeConfigDir:
|
|
108677
|
+
const local = await fetchQuota2({ claudeConfigDir: join68(agentDir, ".claude") });
|
|
107695
108678
|
if (local.ok)
|
|
107696
108679
|
return formatQuotaLine2(local.data);
|
|
107697
108680
|
}
|
|
@@ -107937,10 +108920,10 @@ function effortMenuReplyMarkup(reply) {
|
|
|
107937
108920
|
function flushAgentHandoff(agentDir) {
|
|
107938
108921
|
let removed = 0;
|
|
107939
108922
|
for (const fname of [".handoff.md", ".handoff-topic"]) {
|
|
107940
|
-
const p =
|
|
108923
|
+
const p = join68(agentDir, fname);
|
|
107941
108924
|
try {
|
|
107942
108925
|
if (existsSync57(p)) {
|
|
107943
|
-
|
|
108926
|
+
unlinkSync30(p);
|
|
107944
108927
|
removed++;
|
|
107945
108928
|
}
|
|
107946
108929
|
} catch (err) {
|
|
@@ -107995,7 +108978,7 @@ async function handleNewCommand(ctx) {
|
|
|
107995
108978
|
writeRestartMarker({ chat_id: chatId, thread_id: threadId ?? null, ack_message_id: ackId, ts: Date.now() });
|
|
107996
108979
|
if (agentDir != null) {
|
|
107997
108980
|
try {
|
|
107998
|
-
|
|
108981
|
+
writeFileSync50(join68(agentDir, ".force-fresh-session"), `${kind} at ${new Date().toISOString()}
|
|
107999
108982
|
`, "utf8");
|
|
108000
108983
|
} catch (err) {
|
|
108001
108984
|
process.stderr.write(`telegram gateway: failed to write force-fresh marker: ${err}
|
|
@@ -108108,11 +109091,11 @@ function buildFolderPickerDeps() {
|
|
|
108108
109091
|
};
|
|
108109
109092
|
}
|
|
108110
109093
|
var lockoutOps = {
|
|
108111
|
-
readFileSync: (p, enc) =>
|
|
108112
|
-
writeFileSync: (p, data, opts) =>
|
|
109094
|
+
readFileSync: (p, enc) => readFileSync60(p, enc),
|
|
109095
|
+
writeFileSync: (p, data, opts) => writeFileSync50(p, data, opts),
|
|
108113
109096
|
existsSync: (p) => existsSync57(p),
|
|
108114
|
-
mkdirSync: (p, opts) =>
|
|
108115
|
-
joinPath: (...parts) =>
|
|
109097
|
+
mkdirSync: (p, opts) => mkdirSync51(p, opts),
|
|
109098
|
+
joinPath: (...parts) => join68(...parts)
|
|
108116
109099
|
};
|
|
108117
109100
|
var FLEET_FALLBACK_DEDUP_MS = 30000;
|
|
108118
109101
|
function isAuthBrokerSocketReachable() {
|
|
@@ -108372,7 +109355,7 @@ async function runCreditWatch() {
|
|
|
108372
109355
|
if (!agentDir)
|
|
108373
109356
|
return;
|
|
108374
109357
|
const agentName3 = getMyAgentName();
|
|
108375
|
-
const claudeConfigDir =
|
|
109358
|
+
const claudeConfigDir = join68(agentDir, ".claude");
|
|
108376
109359
|
const stateDir = STATE_DIR;
|
|
108377
109360
|
const reason = readClaudeJsonOverage(claudeConfigDir);
|
|
108378
109361
|
const prev = loadCreditState(stateDir);
|
|
@@ -110128,7 +111111,7 @@ Send \`/auth ${parsed.provider} cancel\` to abort.`, { html: true });
|
|
|
110128
111111
|
await switchroomReply(ctx, "**/usage:** cannot resolve agent dir.", { html: true });
|
|
110129
111112
|
return;
|
|
110130
111113
|
}
|
|
110131
|
-
const result = await fetchQuota2({ claudeConfigDir:
|
|
111114
|
+
const result = await fetchQuota2({ claudeConfigDir: join68(agentDir, ".claude") });
|
|
110132
111115
|
if (!result.ok) {
|
|
110133
111116
|
await switchroomReply(ctx, `**/usage:** ${escapeHtmlForTg2(result.reason)}`, { html: true });
|
|
110134
111117
|
return;
|
|
@@ -110515,7 +111498,7 @@ ${interimLabel}` : interimLabel
|
|
|
110515
111498
|
const unifiedDiff = (() => {
|
|
110516
111499
|
try {
|
|
110517
111500
|
const cfgPath = process.env.SWITCHROOM_CONFIG ?? SWITCHROOM_CONFIG ?? findConfigFile2();
|
|
110518
|
-
const raw =
|
|
111501
|
+
const raw = readFileSync60(cfgPath, "utf8");
|
|
110519
111502
|
return synthesizeAllowRuleDiff({ agentName: agentName3, rule: chosen.rule, configText: raw });
|
|
110520
111503
|
} catch (err) {
|
|
110521
111504
|
process.stderr.write(`telegram gateway: always-allow diff synth failed: ${err.message}
|
|
@@ -111384,7 +112367,7 @@ async function startGateway() {
|
|
|
111384
112367
|
return;
|
|
111385
112368
|
}
|
|
111386
112369
|
})();
|
|
111387
|
-
const resolvedAgentDirForBootCard = agentDir ??
|
|
112370
|
+
const resolvedAgentDirForBootCard = agentDir ?? join68(homedir19(), ".switchroom", "agents", agentSlug);
|
|
111388
112371
|
const handle = await startBootCard(chatId, threadId, botApiForCard, {
|
|
111389
112372
|
agentName: agentDisplayName,
|
|
111390
112373
|
agentSlug,
|
|
@@ -111398,8 +112381,8 @@ async function startGateway() {
|
|
|
111398
112381
|
probeQuotaViaBroker: (t) => probeQuotaForBootCard(agentSlug, t),
|
|
111399
112382
|
tmuxSupervisor: process.env.SWITCHROOM_TMUX_SUPERVISOR === "1",
|
|
111400
112383
|
dockerMode: process.env.SWITCHROOM_RUNTIME === "docker",
|
|
111401
|
-
configSnapshotPath:
|
|
111402
|
-
bootCardStatePath:
|
|
112384
|
+
configSnapshotPath: join68(resolvedAgentDirForBootCard, ".config-snapshot.json"),
|
|
112385
|
+
bootCardStatePath: join68(resolvedAgentDirForBootCard, ".boot-card-msgid.json"),
|
|
111403
112386
|
floodStatePath: FLOOD_STATE_PATH,
|
|
111404
112387
|
...updateOutcomeLine ? { updateOutcomeLine } : {}
|
|
111405
112388
|
}, ackMsgId);
|
|
@@ -111430,10 +112413,10 @@ async function startGateway() {
|
|
|
111430
112413
|
try {
|
|
111431
112414
|
const smAgentDir = resolveAgentDirFromEnv();
|
|
111432
112415
|
if (smAgentDir) {
|
|
111433
|
-
const activePath =
|
|
112416
|
+
const activePath = join68(smAgentDir, ".active-session-model");
|
|
111434
112417
|
if (existsSync57(activePath)) {
|
|
111435
112418
|
try {
|
|
111436
|
-
const launched =
|
|
112419
|
+
const launched = readFileSync60(activePath, "utf8").trim();
|
|
111437
112420
|
const configured = (() => {
|
|
111438
112421
|
const d = switchroomExecJson(["agent", "list"]);
|
|
111439
112422
|
const raw = d?.agents?.find((a) => a.name === getMyAgentName())?.model ?? null;
|
|
@@ -111466,29 +112449,29 @@ async function startGateway() {
|
|
|
111466
112449
|
deliverModelSwitchBootNotice({
|
|
111467
112450
|
...modelBootCardDeps,
|
|
111468
112451
|
confirmation,
|
|
111469
|
-
hasSessionModelAlert: existsSync57(
|
|
112452
|
+
hasSessionModelAlert: existsSync57(join68(smAgentDir, ".session-model-alert"))
|
|
111470
112453
|
});
|
|
111471
112454
|
}
|
|
111472
112455
|
} catch {}
|
|
111473
112456
|
}
|
|
111474
|
-
const activeEffortPath =
|
|
112457
|
+
const activeEffortPath = join68(smAgentDir, ".active-session-effort");
|
|
111475
112458
|
if (existsSync57(activeEffortPath)) {
|
|
111476
112459
|
try {
|
|
111477
|
-
const launchedEffort =
|
|
112460
|
+
const launchedEffort = readFileSync60(activeEffortPath, "utf8").trim();
|
|
111478
112461
|
const configuredEffort = getConfiguredEffortForPersist();
|
|
111479
112462
|
sessionEffortOverride = launchedEffort.length > 0 && launchedEffort !== configuredEffort ? launchedEffort : null;
|
|
111480
112463
|
} catch {}
|
|
111481
112464
|
}
|
|
111482
|
-
const alertPath =
|
|
112465
|
+
const alertPath = join68(smAgentDir, ".session-model-alert");
|
|
111483
112466
|
if (existsSync57(alertPath)) {
|
|
111484
112467
|
let alertText = null;
|
|
111485
112468
|
try {
|
|
111486
|
-
alertText =
|
|
112469
|
+
alertText = readFileSync60(alertPath, "utf8").trim();
|
|
111487
112470
|
} catch {
|
|
111488
112471
|
alertText = null;
|
|
111489
112472
|
}
|
|
111490
112473
|
try {
|
|
111491
|
-
|
|
112474
|
+
unlinkSync30(alertPath);
|
|
111492
112475
|
} catch {}
|
|
111493
112476
|
if (alertText && alertText.length > 0) {
|
|
111494
112477
|
const operators = loadAccess().allowFrom;
|
|
@@ -111609,12 +112592,12 @@ async function startGateway() {
|
|
|
111609
112592
|
staleWorkerTtlMs: resolveInflightTerminalCapMs() + WORKER_FEED_STALE_TTL_MARGIN_MS,
|
|
111610
112593
|
absoluteRowLifetimeCapMs: resolveInflightTerminalCapMs() * WORKER_FEED_ABSOLUTE_ROW_LIFETIME_CAP_MULTIPLE,
|
|
111611
112594
|
groupMessageLifetimeCapMs: WORKER_FEED_GROUP_MESSAGE_LIFETIME_CAP_MS,
|
|
111612
|
-
reconcilePin: ({ feedKey, chatId, messageId }) => {
|
|
112595
|
+
reconcilePin: ({ feedKey, chatId, threadId, messageId }) => {
|
|
111613
112596
|
if (!PIN_STATUS_WHILE_WORKING)
|
|
111614
112597
|
return;
|
|
111615
112598
|
const key = `wk:group:${feedKey}`;
|
|
111616
112599
|
if (messageId != null) {
|
|
111617
|
-
reconcileStatusPin(key, chatId, { pinned: true, messageId });
|
|
112600
|
+
reconcileStatusPin(key, chatId, { pinned: true, messageId }, threadId);
|
|
111618
112601
|
} else {
|
|
111619
112602
|
const unpinChat = chatId || statusPinClaims.get(key)?.chatId;
|
|
111620
112603
|
if (unpinChat != null && unpinChat.length > 0) {
|
|
@@ -111667,7 +112650,7 @@ async function startGateway() {
|
|
|
111667
112650
|
`);
|
|
111668
112651
|
}
|
|
111669
112652
|
},
|
|
111670
|
-
onFinish: ({ agentId, outcome, description, resultText, toolCount, totalTokens, durationMs, background: entryBackground }) => {
|
|
112653
|
+
onFinish: ({ agentId, outcome, description: description2, resultText, toolCount, totalTokens, durationMs, background: entryBackground }) => {
|
|
111671
112654
|
workerFeedOriginDeferrals.delete(agentId);
|
|
111672
112655
|
deferredDoneReactions.promote();
|
|
111673
112656
|
let fleetChatId = "";
|
|
@@ -111680,10 +112663,10 @@ async function startGateway() {
|
|
|
111680
112663
|
}
|
|
111681
112664
|
}
|
|
111682
112665
|
} catch {}
|
|
111683
|
-
let dispatch = resolveWorkerFeedDispatch(null,
|
|
112666
|
+
let dispatch = resolveWorkerFeedDispatch(null, description2, entryBackground);
|
|
111684
112667
|
if (turnsDb != null) {
|
|
111685
112668
|
try {
|
|
111686
|
-
dispatch = resolveWorkerFeedDispatch(getSubagentByJsonlId(turnsDb, agentId),
|
|
112669
|
+
dispatch = resolveWorkerFeedDispatch(getSubagentByJsonlId(turnsDb, agentId), description2, entryBackground);
|
|
111687
112670
|
} catch {}
|
|
111688
112671
|
}
|
|
111689
112672
|
let isBackground = dispatch.isBackground;
|
|
@@ -111773,7 +112756,7 @@ async function startGateway() {
|
|
|
111773
112756
|
fleetChatId: handbackOrigin?.chatId || fleetChatId,
|
|
111774
112757
|
...handbackOrigin?.threadId != null ? { originThreadId: handbackOrigin.threadId } : {},
|
|
111775
112758
|
ownerChatId: loadAccess().allowFrom[0] ?? "",
|
|
111776
|
-
taskDescription:
|
|
112759
|
+
taskDescription: description2,
|
|
111777
112760
|
resultText,
|
|
111778
112761
|
jsonlAgentId: agentId
|
|
111779
112762
|
});
|
|
@@ -111799,7 +112782,7 @@ async function startGateway() {
|
|
|
111799
112782
|
process.stderr.write(`telegram gateway: subagent-handback queued agent=${agentId} outcome=${outcome} chat=${decision.chatId} resultChars=${resultText.length}
|
|
111800
112783
|
`);
|
|
111801
112784
|
},
|
|
111802
|
-
onProgress: ({ agentId, description, latestSummary, elapsedMs, prevBucketIdx, setBucketIdx, lastTool, toolCount, totalTokens, progressLine, model, skeleton }) => {
|
|
112785
|
+
onProgress: ({ agentId, description: description2, latestSummary, elapsedMs, prevBucketIdx, setBucketIdx, lastTool, toolCount, totalTokens, progressLine, model, skeleton }) => {
|
|
111803
112786
|
let fleetChatId = "";
|
|
111804
112787
|
try {
|
|
111805
112788
|
const fleets = progressDriver?.peekAllFleets() ?? [];
|
|
@@ -111810,10 +112793,10 @@ async function startGateway() {
|
|
|
111810
112793
|
}
|
|
111811
112794
|
}
|
|
111812
112795
|
} catch {}
|
|
111813
|
-
let dispatch = resolveWorkerFeedDispatch(null,
|
|
112796
|
+
let dispatch = resolveWorkerFeedDispatch(null, description2);
|
|
111814
112797
|
if (turnsDb != null) {
|
|
111815
112798
|
try {
|
|
111816
|
-
dispatch = resolveWorkerFeedDispatch(getSubagentByJsonlId(turnsDb, agentId),
|
|
112799
|
+
dispatch = resolveWorkerFeedDispatch(getSubagentByJsonlId(turnsDb, agentId), description2);
|
|
111817
112800
|
} catch {}
|
|
111818
112801
|
}
|
|
111819
112802
|
const isBackground = dispatch.isBackground || dispatch.isNested;
|
|
@@ -111931,7 +112914,7 @@ async function startGateway() {
|
|
|
111931
112914
|
...progressOrigin?.threadId != null ? { originThreadId: progressOrigin.threadId } : {},
|
|
111932
112915
|
ownerChatId: loadAccess().allowFrom[0] ?? "",
|
|
111933
112916
|
subagentJsonlId: agentId,
|
|
111934
|
-
taskDescription:
|
|
112917
|
+
taskDescription: description2,
|
|
111935
112918
|
latestSummary,
|
|
111936
112919
|
elapsedMs,
|
|
111937
112920
|
progressIntervalMs: DEFAULT_PROGRESS_INTERVAL_MS,
|