switchroom 0.19.29 → 0.19.31
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 +2044 -900
- package/dist/host-control/main.js +162 -80
- 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/gateway/gateway.js +1435 -551
- 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/registry/turns-schema.ts +21 -1
- package/telegram-plugin/retry-api-call.ts +46 -21
- 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/tg-post-logger-error-shape.test.ts +161 -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 {}
|
|
@@ -72946,10 +73018,10 @@ function resolveExhaustUntil(resetAtMs, now = Date.now()) {
|
|
|
72946
73018
|
|
|
72947
73019
|
// gateway/auth-add-flow.ts
|
|
72948
73020
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
72949
|
-
import { existsSync as existsSync21, mkdirSync as mkdirSync24, readFileSync as readFileSync22, readdirSync as readdirSync6, rmSync as
|
|
73021
|
+
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
73022
|
import { homedir as homedir8 } from "node:os";
|
|
72951
73023
|
import { join as join29 } from "node:path";
|
|
72952
|
-
import { randomBytes as
|
|
73024
|
+
import { randomBytes as randomBytes9 } from "node:crypto";
|
|
72953
73025
|
|
|
72954
73026
|
// ../src/auth/manager.ts
|
|
72955
73027
|
import {
|
|
@@ -72959,7 +73031,7 @@ import {
|
|
|
72959
73031
|
writeFileSync as writeFileSync19,
|
|
72960
73032
|
mkdirSync as mkdirSync23,
|
|
72961
73033
|
mkdtempSync as mkdtempSync2,
|
|
72962
|
-
rmSync as
|
|
73034
|
+
rmSync as rmSync5,
|
|
72963
73035
|
chmodSync as chmodSync7,
|
|
72964
73036
|
statSync as statSync8
|
|
72965
73037
|
} from "node:fs";
|
|
@@ -73054,12 +73126,12 @@ function makeAuthAddTmuxOps(tmuxBin = "tmux") {
|
|
|
73054
73126
|
}
|
|
73055
73127
|
var pendingAuthAddFlows = new Map;
|
|
73056
73128
|
function pickScratchDir(label, home2 = homedir8()) {
|
|
73057
|
-
const suffix =
|
|
73129
|
+
const suffix = randomBytes9(8).toString("hex");
|
|
73058
73130
|
return join29(home2, ".switchroom", "accounts", ".in-progress", `${label}-${suffix}`);
|
|
73059
73131
|
}
|
|
73060
73132
|
function cleanScratchDir(scratchDir) {
|
|
73061
73133
|
try {
|
|
73062
|
-
|
|
73134
|
+
rmSync6(scratchDir, { recursive: true, force: true });
|
|
73063
73135
|
} catch {}
|
|
73064
73136
|
}
|
|
73065
73137
|
var AUTH_TMUX_SESSION_FILE = ".auth-tmux-session";
|
|
@@ -76377,7 +76449,7 @@ import {
|
|
|
76377
76449
|
mkdirSync as mkdirSync26,
|
|
76378
76450
|
readFileSync as readFileSync23,
|
|
76379
76451
|
readdirSync as readdirSync7,
|
|
76380
|
-
renameSync as
|
|
76452
|
+
renameSync as renameSync11,
|
|
76381
76453
|
statSync as statSync10,
|
|
76382
76454
|
unlinkSync as unlinkSync13,
|
|
76383
76455
|
writeFileSync as writeFileSync21,
|
|
@@ -76413,7 +76485,7 @@ function writeOutboxRecordAtomic(record, stateDir) {
|
|
|
76413
76485
|
return true;
|
|
76414
76486
|
const tmpPath = join31(dir, `.${record.turnNonce}.${process.pid}.tmp`);
|
|
76415
76487
|
writeFileSync21(tmpPath, JSON.stringify(record), { mode: 384 });
|
|
76416
|
-
|
|
76488
|
+
renameSync11(tmpPath, finalPath);
|
|
76417
76489
|
return true;
|
|
76418
76490
|
} catch {
|
|
76419
76491
|
return false;
|
|
@@ -76440,7 +76512,7 @@ function claimRecord(nonce, stateDir) {
|
|
|
76440
76512
|
const from = join31(dir, `${nonce}.json`);
|
|
76441
76513
|
const to = join31(dir, `${nonce}.sending`);
|
|
76442
76514
|
try {
|
|
76443
|
-
|
|
76515
|
+
renameSync11(from, to);
|
|
76444
76516
|
return to;
|
|
76445
76517
|
} catch {
|
|
76446
76518
|
return null;
|
|
@@ -76449,7 +76521,7 @@ function claimRecord(nonce, stateDir) {
|
|
|
76449
76521
|
function releaseClaim(nonce, stateDir) {
|
|
76450
76522
|
const dir = resolveOutboxDir(stateDir);
|
|
76451
76523
|
try {
|
|
76452
|
-
|
|
76524
|
+
renameSync11(join31(dir, `${nonce}.sending`), join31(dir, `${nonce}.json`));
|
|
76453
76525
|
} catch {}
|
|
76454
76526
|
}
|
|
76455
76527
|
function removeClaimed(nonce, stateDir) {
|
|
@@ -76469,7 +76541,7 @@ function reclaimStaleSending(stateDir, now = Date.now()) {
|
|
|
76469
76541
|
try {
|
|
76470
76542
|
const st = statSync10(join31(dir, f));
|
|
76471
76543
|
if (now - st.mtimeMs > OUTBOX_SENDING_TIMEOUT_MS) {
|
|
76472
|
-
|
|
76544
|
+
renameSync11(join31(dir, f), join31(dir, f.replace(/\.sending$/, ".json")));
|
|
76473
76545
|
}
|
|
76474
76546
|
} catch {}
|
|
76475
76547
|
}
|
|
@@ -76543,7 +76615,7 @@ function compactJournalIfLarge(path2) {
|
|
|
76543
76615
|
writeFileSync21(tmp, kept.join(`
|
|
76544
76616
|
`) + `
|
|
76545
76617
|
`, { mode: 384 });
|
|
76546
|
-
|
|
76618
|
+
renameSync11(tmp, path2);
|
|
76547
76619
|
} catch {}
|
|
76548
76620
|
}
|
|
76549
76621
|
function clearOutboxRecord(nonce, stateDir) {
|
|
@@ -76607,7 +76679,7 @@ import {
|
|
|
76607
76679
|
existsSync as existsSync24,
|
|
76608
76680
|
mkdirSync as mkdirSync27,
|
|
76609
76681
|
readFileSync as readFileSync24,
|
|
76610
|
-
renameSync as
|
|
76682
|
+
renameSync as renameSync12,
|
|
76611
76683
|
writeFileSync as writeFileSync22,
|
|
76612
76684
|
appendFileSync as appendFileSync5
|
|
76613
76685
|
} from "node:fs";
|
|
@@ -76741,7 +76813,7 @@ function compactIfLarge(path2) {
|
|
|
76741
76813
|
writeFileSync22(tmp, kept.join(`
|
|
76742
76814
|
`) + `
|
|
76743
76815
|
`, { mode: 384 });
|
|
76744
|
-
|
|
76816
|
+
renameSync12(tmp, path2);
|
|
76745
76817
|
} catch {}
|
|
76746
76818
|
}
|
|
76747
76819
|
|
|
@@ -77198,7 +77270,7 @@ function eagerVoiceEnabled2() {
|
|
|
77198
77270
|
}
|
|
77199
77271
|
|
|
77200
77272
|
// photo-precheck.ts
|
|
77201
|
-
import { closeSync as
|
|
77273
|
+
import { closeSync as closeSync6, fstatSync, openSync as openSync6, readSync } from "node:fs";
|
|
77202
77274
|
var PHOTO_MAX_DIMENSION_SUM = 1e4;
|
|
77203
77275
|
var PHOTO_MAX_ASPECT_RATIO = 10;
|
|
77204
77276
|
var PHOTO_MAX_BYTES = 10 * 1024 * 1024;
|
|
@@ -77279,7 +77351,7 @@ var JPEG_PROBE_BYTES = 64 * 1024;
|
|
|
77279
77351
|
function probeImageFile(path2) {
|
|
77280
77352
|
let fd;
|
|
77281
77353
|
try {
|
|
77282
|
-
fd =
|
|
77354
|
+
fd = openSync6(path2, "r");
|
|
77283
77355
|
const bytes = fstatSync(fd).size;
|
|
77284
77356
|
const headBuf = Buffer.alloc(HEADER_PROBE_BYTES);
|
|
77285
77357
|
const headRead = readSync(fd, headBuf, 0, HEADER_PROBE_BYTES, 0);
|
|
@@ -77298,7 +77370,7 @@ function probeImageFile(path2) {
|
|
|
77298
77370
|
} finally {
|
|
77299
77371
|
if (fd !== undefined) {
|
|
77300
77372
|
try {
|
|
77301
|
-
|
|
77373
|
+
closeSync6(fd);
|
|
77302
77374
|
} catch {}
|
|
77303
77375
|
}
|
|
77304
77376
|
}
|
|
@@ -79526,10 +79598,10 @@ function detectStatusSurfaceDegraded(t) {
|
|
|
79526
79598
|
|
|
79527
79599
|
// gateway/turn-active-marker.ts
|
|
79528
79600
|
import {
|
|
79529
|
-
closeSync as
|
|
79601
|
+
closeSync as closeSync7,
|
|
79530
79602
|
existsSync as existsSync28,
|
|
79531
79603
|
mkdirSync as mkdirSync31,
|
|
79532
|
-
openSync as
|
|
79604
|
+
openSync as openSync7,
|
|
79533
79605
|
readFileSync as readFileSync26,
|
|
79534
79606
|
statSync as statSync12,
|
|
79535
79607
|
unlinkSync as unlinkSync15,
|
|
@@ -79555,8 +79627,8 @@ function touchTurnActiveMarker(stateDir) {
|
|
|
79555
79627
|
utimesSync(path2, now, now);
|
|
79556
79628
|
} catch {
|
|
79557
79629
|
try {
|
|
79558
|
-
const fd =
|
|
79559
|
-
|
|
79630
|
+
const fd = openSync7(path2, "r+");
|
|
79631
|
+
closeSync7(fd);
|
|
79560
79632
|
} catch {}
|
|
79561
79633
|
}
|
|
79562
79634
|
}
|
|
@@ -80882,7 +80954,8 @@ function createNarrativeLane(deps) {
|
|
|
80882
80954
|
toolCount: turn.labeledToolCount,
|
|
80883
80955
|
state: final ? "done" : "running",
|
|
80884
80956
|
model: turn.currentModel,
|
|
80885
|
-
totalTokens: turn.totalTokens
|
|
80957
|
+
totalTokens: turn.totalTokens,
|
|
80958
|
+
resultText: final ? turn.lastReplyText : undefined
|
|
80886
80959
|
};
|
|
80887
80960
|
return renderActivityFeedWithNested(turn.mirrorLines, childLines, final, liveSuffix, stepCount, header);
|
|
80888
80961
|
}
|
|
@@ -81199,7 +81272,8 @@ function createNarrativeLane(deps) {
|
|
|
81199
81272
|
elapsedMs: livenessElapsed,
|
|
81200
81273
|
toolCount: turn.labeledToolCount,
|
|
81201
81274
|
state: "done",
|
|
81202
|
-
model: turn.currentModel
|
|
81275
|
+
model: turn.currentModel,
|
|
81276
|
+
resultText: turn.lastReplyText
|
|
81203
81277
|
};
|
|
81204
81278
|
finalHtml = renderActivityFeedWithNested(["Working\u2026"], [], true, "", undefined, livenessHeader);
|
|
81205
81279
|
}
|
|
@@ -81569,7 +81643,7 @@ function resolveAgentDirFromEnv() {
|
|
|
81569
81643
|
}
|
|
81570
81644
|
|
|
81571
81645
|
// active-reactions.ts
|
|
81572
|
-
import { readFileSync as readFileSync27, writeFileSync as writeFileSync25, renameSync as
|
|
81646
|
+
import { readFileSync as readFileSync27, writeFileSync as writeFileSync25, renameSync as renameSync13, existsSync as existsSync29, unlinkSync as unlinkSync16 } from "node:fs";
|
|
81573
81647
|
import { join as join37 } from "node:path";
|
|
81574
81648
|
var ACTIVE_REACTIONS_FILENAME = ".active-reactions.json";
|
|
81575
81649
|
function reactionsPath(agentDir) {
|
|
@@ -81615,7 +81689,7 @@ function writeActiveReactions(agentDir, reactions) {
|
|
|
81615
81689
|
try {
|
|
81616
81690
|
writeFileSync25(tmp, JSON.stringify(reactions) + `
|
|
81617
81691
|
`, "utf-8");
|
|
81618
|
-
|
|
81692
|
+
renameSync13(tmp, p);
|
|
81619
81693
|
} catch {}
|
|
81620
81694
|
}
|
|
81621
81695
|
function addActiveReaction(agentDir, reaction) {
|
|
@@ -81637,7 +81711,7 @@ function clearActiveReactions(agentDir) {
|
|
|
81637
81711
|
}
|
|
81638
81712
|
|
|
81639
81713
|
// active-reactions.ts
|
|
81640
|
-
import { readFileSync as readFileSync28, writeFileSync as writeFileSync26, renameSync as
|
|
81714
|
+
import { readFileSync as readFileSync28, writeFileSync as writeFileSync26, renameSync as renameSync14, existsSync as existsSync30, unlinkSync as unlinkSync17 } from "node:fs";
|
|
81641
81715
|
import { join as join38 } from "node:path";
|
|
81642
81716
|
var ACTIVE_REACTIONS_FILENAME2 = ".active-reactions.json";
|
|
81643
81717
|
function reactionsPath2(agentDir) {
|
|
@@ -83866,7 +83940,7 @@ async function menuWithBannerStatic(deps, banner) {
|
|
|
83866
83940
|
}
|
|
83867
83941
|
|
|
83868
83942
|
// gateway/session-model-file.ts
|
|
83869
|
-
import { readFileSync as readFileSync30, writeFileSync as writeFileSync27, renameSync as
|
|
83943
|
+
import { readFileSync as readFileSync30, writeFileSync as writeFileSync27, renameSync as renameSync15, rmSync as rmSync7 } from "node:fs";
|
|
83870
83944
|
import { join as join40 } from "node:path";
|
|
83871
83945
|
var SESSION_MODEL_FILE = ".session-model";
|
|
83872
83946
|
var CONFIGURED_DEFAULT_MODEL_FILE = ".configured-default-model";
|
|
@@ -83874,7 +83948,7 @@ var SESSION_MODEL_BOOT_ATTEMPTS_FILE = ".session-model-boot-attempts";
|
|
|
83874
83948
|
function atomicWrite(path2, content3) {
|
|
83875
83949
|
const tmp = `${path2}.tmp-${process.pid}-${Date.now()}`;
|
|
83876
83950
|
writeFileSync27(tmp, content3, "utf8");
|
|
83877
|
-
|
|
83951
|
+
renameSync15(tmp, path2);
|
|
83878
83952
|
}
|
|
83879
83953
|
function serializeSessionModel(rec) {
|
|
83880
83954
|
return `${JSON.stringify({
|
|
@@ -83889,7 +83963,7 @@ function writeSessionModelFile(agentDir, model, configuredDefaultAtWrite) {
|
|
|
83889
83963
|
throw new Error(`refusing to persist non-canonical session model token: ${JSON.stringify(model)}`);
|
|
83890
83964
|
}
|
|
83891
83965
|
try {
|
|
83892
|
-
|
|
83966
|
+
rmSync7(join40(agentDir, SESSION_MODEL_BOOT_ATTEMPTS_FILE), { force: true });
|
|
83893
83967
|
} catch {}
|
|
83894
83968
|
atomicWrite(join40(agentDir, SESSION_MODEL_FILE), serializeSessionModel({ model, configuredDefaultAtWrite, ts: Date.now() }));
|
|
83895
83969
|
}
|
|
@@ -83902,15 +83976,15 @@ function readSessionModelFileRaw(agentDir) {
|
|
|
83902
83976
|
}
|
|
83903
83977
|
function clearSessionModelFile(agentDir) {
|
|
83904
83978
|
try {
|
|
83905
|
-
|
|
83979
|
+
rmSync7(join40(agentDir, SESSION_MODEL_FILE), { force: true });
|
|
83906
83980
|
} catch {}
|
|
83907
83981
|
}
|
|
83908
83982
|
function consumeSessionModelCarrierOnHealthyBoot(agentDir) {
|
|
83909
83983
|
try {
|
|
83910
|
-
|
|
83984
|
+
rmSync7(join40(agentDir, SESSION_MODEL_FILE), { force: true });
|
|
83911
83985
|
} catch {}
|
|
83912
83986
|
try {
|
|
83913
|
-
|
|
83987
|
+
rmSync7(join40(agentDir, SESSION_MODEL_BOOT_ATTEMPTS_FILE), { force: true });
|
|
83914
83988
|
} catch {}
|
|
83915
83989
|
}
|
|
83916
83990
|
function restoreSessionModelFileRaw(agentDir, raw) {
|
|
@@ -83941,7 +84015,7 @@ function writeSessionEffortFile(agentDir, level, configuredDefaultAtWrite) {
|
|
|
83941
84015
|
}
|
|
83942
84016
|
function clearSessionEffortFile(agentDir) {
|
|
83943
84017
|
try {
|
|
83944
|
-
|
|
84018
|
+
rmSync7(join40(agentDir, SESSION_EFFORT_FILE), { force: true });
|
|
83945
84019
|
} catch {}
|
|
83946
84020
|
}
|
|
83947
84021
|
var PREMIUM_RECOVERY_FILE = ".premium-recovery";
|
|
@@ -83983,7 +84057,7 @@ function readPremiumRecoveryFile(agentDir) {
|
|
|
83983
84057
|
}
|
|
83984
84058
|
function clearPremiumRecoveryFile(agentDir) {
|
|
83985
84059
|
try {
|
|
83986
|
-
|
|
84060
|
+
rmSync7(join40(agentDir, PREMIUM_RECOVERY_FILE), { force: true });
|
|
83987
84061
|
} catch {}
|
|
83988
84062
|
}
|
|
83989
84063
|
|
|
@@ -86239,7 +86313,7 @@ function nextCompactNotify(state6, ev) {
|
|
|
86239
86313
|
|
|
86240
86314
|
// gateway/hostd-dispatch.ts
|
|
86241
86315
|
import { existsSync as existsSync36 } from "node:fs";
|
|
86242
|
-
import { randomBytes as
|
|
86316
|
+
import { randomBytes as randomBytes10 } from "node:crypto";
|
|
86243
86317
|
init_loader();
|
|
86244
86318
|
var _hostdEnabled2;
|
|
86245
86319
|
function isHostdEnabled2() {
|
|
@@ -86286,7 +86360,7 @@ async function tryHostdDispatch2(agentName3, req, timeoutMs = 5000) {
|
|
|
86286
86360
|
}
|
|
86287
86361
|
}
|
|
86288
86362
|
function hostdRequestId2(prefix) {
|
|
86289
|
-
return `${prefix}-${Date.now()}-${
|
|
86363
|
+
return `${prefix}-${Date.now()}-${randomBytes10(4).toString("hex")}`;
|
|
86290
86364
|
}
|
|
86291
86365
|
function withOperatorAttestation(req, passphrase) {
|
|
86292
86366
|
if (!passphrase)
|
|
@@ -86348,6 +86422,56 @@ function shouldSweepChatAtBoot(chatId) {
|
|
|
86348
86422
|
return n < 0;
|
|
86349
86423
|
}
|
|
86350
86424
|
|
|
86425
|
+
// gateway/stale-pin-sweep-store.ts
|
|
86426
|
+
var SWEEP_MAX_ATTEMPTS = 8;
|
|
86427
|
+
var SWEEP_ENVELOPE_VERSIONS = new Set([1]);
|
|
86428
|
+
function sweepTargetKey(chatId, threadId) {
|
|
86429
|
+
return `${chatId}:${threadId ?? "-"}`;
|
|
86430
|
+
}
|
|
86431
|
+
function isCursorRow(x) {
|
|
86432
|
+
if (x == null || typeof x !== "object")
|
|
86433
|
+
return false;
|
|
86434
|
+
const o = x;
|
|
86435
|
+
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";
|
|
86436
|
+
}
|
|
86437
|
+
function loadSweepCursors(path2, fs2) {
|
|
86438
|
+
if (!fs2.existsSync(path2))
|
|
86439
|
+
return [];
|
|
86440
|
+
let raw = "";
|
|
86441
|
+
try {
|
|
86442
|
+
raw = fs2.readFileSync(path2);
|
|
86443
|
+
} catch {
|
|
86444
|
+
return [];
|
|
86445
|
+
}
|
|
86446
|
+
let parsed;
|
|
86447
|
+
try {
|
|
86448
|
+
parsed = JSON.parse(raw);
|
|
86449
|
+
} catch {
|
|
86450
|
+
return [];
|
|
86451
|
+
}
|
|
86452
|
+
if (parsed == null || typeof parsed !== "object")
|
|
86453
|
+
return [];
|
|
86454
|
+
const env = parsed;
|
|
86455
|
+
if (typeof env.v !== "number" || !SWEEP_ENVELOPE_VERSIONS.has(env.v) || !Array.isArray(env.cursors)) {
|
|
86456
|
+
return [];
|
|
86457
|
+
}
|
|
86458
|
+
return env.cursors.filter(isCursorRow);
|
|
86459
|
+
}
|
|
86460
|
+
function persistSweepCursors(path2, fs2, cursors, log = (l) => process.stderr.write(l)) {
|
|
86461
|
+
const env = { v: 1, cursors: [...cursors] };
|
|
86462
|
+
try {
|
|
86463
|
+
fs2.writeFileSync(path2, JSON.stringify(env));
|
|
86464
|
+
} catch (err) {
|
|
86465
|
+
log(`stale-pin-sweep-store: persist FAILED path=${path2}: ${err.message} \u2014 ` + `durability degraded; a restart mid-sweep will re-seed instead of resume
|
|
86466
|
+
`);
|
|
86467
|
+
}
|
|
86468
|
+
}
|
|
86469
|
+
function upsertSweepCursor(path2, fs2, cursor, log = (l) => process.stderr.write(l)) {
|
|
86470
|
+
const key = sweepTargetKey(cursor.chatId, cursor.threadId);
|
|
86471
|
+
const others = loadSweepCursors(path2, fs2).filter((c) => sweepTargetKey(c.chatId, c.threadId) !== key);
|
|
86472
|
+
persistSweepCursors(path2, fs2, [...others, cursor], log);
|
|
86473
|
+
}
|
|
86474
|
+
|
|
86351
86475
|
// gateway/boot-sweep-gate.ts
|
|
86352
86476
|
function createBootSweepGate(args) {
|
|
86353
86477
|
let armed = false;
|
|
@@ -86392,21 +86516,22 @@ async function step(name, fn, log) {
|
|
|
86392
86516
|
}
|
|
86393
86517
|
async function runBootPinSweepSteps(deps) {
|
|
86394
86518
|
const log = deps.log ?? ((l) => process.stderr.write(l));
|
|
86395
|
-
let
|
|
86396
|
-
await step("
|
|
86397
|
-
|
|
86519
|
+
let targets = [];
|
|
86520
|
+
await step("sweep-target-scan", async () => {
|
|
86521
|
+
targets = deps.scanSweepTargets();
|
|
86398
86522
|
}, log);
|
|
86399
86523
|
await step("status-pin-cleanup", deps.statusPinCleanup, log);
|
|
86400
86524
|
await step("activity-card-reaper", deps.activityCardReaper, log);
|
|
86401
86525
|
await step("queued-card-reaper", deps.queuedCardReaper, log);
|
|
86402
|
-
await step("enable-
|
|
86403
|
-
for (const
|
|
86404
|
-
await step(`
|
|
86526
|
+
await step("enable-sweep", async () => deps.enableSweep(), log);
|
|
86527
|
+
for (const t of targets) {
|
|
86528
|
+
await step(`stale-pin-sweep:${sweepTargetKey(t.chatId, t.threadId)}`, () => deps.sweepTarget(t), log);
|
|
86529
|
+
}
|
|
86405
86530
|
}
|
|
86406
86531
|
|
|
86407
86532
|
// gateway/status-pin-retarget.ts
|
|
86408
86533
|
async function runStatusPinReconcile(args) {
|
|
86409
|
-
const { pinKey, chatId, prev, desired, persist, runPin, claims } = args;
|
|
86534
|
+
const { pinKey, chatId, threadId, prev, desired, persist, runPin, claims } = args;
|
|
86410
86535
|
const now = args.now ?? Date.now;
|
|
86411
86536
|
const commit = (next) => {
|
|
86412
86537
|
if (next == null) {
|
|
@@ -86414,7 +86539,7 @@ async function runStatusPinReconcile(args) {
|
|
|
86414
86539
|
return;
|
|
86415
86540
|
}
|
|
86416
86541
|
const pinnedAt = claims.get(pinKey)?.pinnedAt ?? now();
|
|
86417
|
-
claims.set(pinKey, { messageId: next.messageId, chatId, pinnedAt });
|
|
86542
|
+
claims.set(pinKey, { messageId: next.messageId, chatId, threadId, pinnedAt });
|
|
86418
86543
|
};
|
|
86419
86544
|
const runLeg = (legAction, from) => {
|
|
86420
86545
|
if (persist == null)
|
|
@@ -86425,6 +86550,7 @@ async function runStatusPinReconcile(args) {
|
|
|
86425
86550
|
fs: persist.fs,
|
|
86426
86551
|
pinKey,
|
|
86427
86552
|
chatId,
|
|
86553
|
+
threadId,
|
|
86428
86554
|
op,
|
|
86429
86555
|
applyPin: () => runPin(legAction, from),
|
|
86430
86556
|
now: now()
|
|
@@ -86524,24 +86650,77 @@ function createStatusPinApi(getBot, robust) {
|
|
|
86524
86650
|
};
|
|
86525
86651
|
}
|
|
86526
86652
|
|
|
86527
|
-
// gateway/
|
|
86528
|
-
|
|
86529
|
-
|
|
86530
|
-
|
|
86531
|
-
|
|
86532
|
-
|
|
86533
|
-
|
|
86653
|
+
// gateway/stale-pin-sweep.ts
|
|
86654
|
+
var GROUP_SWEEP_GATE = {
|
|
86655
|
+
minCallDelayMs: 6000,
|
|
86656
|
+
maxPopsPerChatPerSweep: Number.POSITIVE_INFINITY,
|
|
86657
|
+
maxPinOpsPerMinute: 10
|
|
86658
|
+
};
|
|
86659
|
+
function collectSweepTargets(input) {
|
|
86660
|
+
const out = new Map;
|
|
86534
86661
|
const add = (rows) => {
|
|
86535
86662
|
if (rows == null)
|
|
86536
86663
|
return;
|
|
86537
|
-
for (const r of rows)
|
|
86538
|
-
if (
|
|
86539
|
-
|
|
86664
|
+
for (const r of rows) {
|
|
86665
|
+
if (typeof r.chatId !== "string" || r.chatId.length === 0)
|
|
86666
|
+
continue;
|
|
86667
|
+
const threadId = r.threadId ?? undefined;
|
|
86668
|
+
const key = sweepTargetKey(r.chatId, threadId);
|
|
86669
|
+
let target = out.get(key);
|
|
86670
|
+
if (target == null) {
|
|
86671
|
+
target = { chatId: r.chatId, threadId, messageIds: [] };
|
|
86672
|
+
out.set(key, target);
|
|
86673
|
+
}
|
|
86674
|
+
const id = r.messageId ?? (r.pinned === true ? r.activityMessageId : undefined);
|
|
86675
|
+
if (typeof id === "number" && !target.messageIds.includes(id))
|
|
86676
|
+
target.messageIds.push(id);
|
|
86677
|
+
}
|
|
86540
86678
|
};
|
|
86541
86679
|
add(input.statusPins);
|
|
86542
86680
|
add(input.activityCards);
|
|
86543
86681
|
add(input.queuedCards);
|
|
86544
|
-
return [...out];
|
|
86682
|
+
return [...out.values()];
|
|
86683
|
+
}
|
|
86684
|
+
|
|
86685
|
+
// gateway/stale-pin-sweep.ts
|
|
86686
|
+
var DM_SWEEP_GATE = {
|
|
86687
|
+
minCallDelayMs: 1500,
|
|
86688
|
+
maxPopsPerChatPerSweep: 40,
|
|
86689
|
+
maxPinOpsPerMinute: 30
|
|
86690
|
+
};
|
|
86691
|
+
var GROUP_SWEEP_GATE2 = {
|
|
86692
|
+
minCallDelayMs: 6000,
|
|
86693
|
+
maxPopsPerChatPerSweep: Number.POSITIVE_INFINITY,
|
|
86694
|
+
maxPinOpsPerMinute: 10
|
|
86695
|
+
};
|
|
86696
|
+
var FLOOD_BACKOFF_FACTOR = 2;
|
|
86697
|
+
var MAX_CONSECUTIVE_FLOOD_WAITS = 3;
|
|
86698
|
+
var MAX_IDENTICAL_RETRY_AFTER_NO_PROGRESS = 2;
|
|
86699
|
+
var CIRCUIT_BREAKER_RETRY_AFTER_SEC = 60;
|
|
86700
|
+
var VERIFY_READ_GAP_MS = 1800;
|
|
86701
|
+
var VERIFY_READ_MAX_PAIRS = 3;
|
|
86702
|
+
var UNPIN_ALL_FORUM_TOPIC_ENABLED = false;
|
|
86703
|
+
function mayUnpinAllForumTopic(kind, override) {
|
|
86704
|
+
if (kind !== "forum-topic")
|
|
86705
|
+
return false;
|
|
86706
|
+
return override ?? UNPIN_ALL_FORUM_TOPIC_ENABLED;
|
|
86707
|
+
}
|
|
86708
|
+
function gateFor(kind) {
|
|
86709
|
+
return kind === "dm" ? DM_SWEEP_GATE : GROUP_SWEEP_GATE2;
|
|
86710
|
+
}
|
|
86711
|
+
function budgetClassFor(kind) {
|
|
86712
|
+
return kind === "dm" ? "dm" : "group";
|
|
86713
|
+
}
|
|
86714
|
+
function isDmChatId(chatId) {
|
|
86715
|
+
const n = Number(chatId);
|
|
86716
|
+
return Number.isFinite(n) && Number.isInteger(n) && n > 0;
|
|
86717
|
+
}
|
|
86718
|
+
function classifyChatForSweep(args) {
|
|
86719
|
+
if (isDmChatId(args.chatId))
|
|
86720
|
+
return "dm";
|
|
86721
|
+
if (args.isForum === true && args.threadId != null)
|
|
86722
|
+
return "forum-topic";
|
|
86723
|
+
return "supergroup";
|
|
86545
86724
|
}
|
|
86546
86725
|
function unexpiredStoreRepinIds(rows, chatId, now) {
|
|
86547
86726
|
const out = [];
|
|
@@ -86553,41 +86732,571 @@ function unexpiredStoreRepinIds(rows, chatId, now) {
|
|
|
86553
86732
|
}
|
|
86554
86733
|
return out;
|
|
86555
86734
|
}
|
|
86556
|
-
function
|
|
86557
|
-
|
|
86735
|
+
function description(err) {
|
|
86736
|
+
if (err != null && typeof err === "object") {
|
|
86737
|
+
const o = err;
|
|
86738
|
+
if (typeof o.description === "string" && o.description.length > 0) {
|
|
86739
|
+
return o.description.toLowerCase();
|
|
86740
|
+
}
|
|
86741
|
+
if (typeof o.message === "string" && o.message.length > 0)
|
|
86742
|
+
return o.message.toLowerCase();
|
|
86743
|
+
}
|
|
86744
|
+
return String(err).toLowerCase();
|
|
86745
|
+
}
|
|
86746
|
+
function retryAfterSeconds(err) {
|
|
86747
|
+
if (err == null || typeof err !== "object")
|
|
86748
|
+
return null;
|
|
86749
|
+
const o = err;
|
|
86750
|
+
const fromParams = o.parameters?.retry_after;
|
|
86751
|
+
if (typeof fromParams === "number" && fromParams >= 0)
|
|
86752
|
+
return fromParams;
|
|
86753
|
+
if (o.error_code === 429) {
|
|
86754
|
+
const m = /retry after (\d+)/.exec(description(err));
|
|
86755
|
+
if (m != null)
|
|
86756
|
+
return Number(m[1]);
|
|
86757
|
+
return 0;
|
|
86758
|
+
}
|
|
86759
|
+
return null;
|
|
86760
|
+
}
|
|
86761
|
+
function isPeerFloodError(err) {
|
|
86762
|
+
return description(err).includes("peer_flood");
|
|
86763
|
+
}
|
|
86764
|
+
function isPinRightsError2(err) {
|
|
86765
|
+
return description(err).includes("not enough rights");
|
|
86766
|
+
}
|
|
86767
|
+
function isNothingToUnpinError(err) {
|
|
86768
|
+
return description(err).includes("message to unpin not found");
|
|
86769
|
+
}
|
|
86770
|
+
function createPinOpBudget(now) {
|
|
86771
|
+
const windows = { dm: [], group: [] };
|
|
86772
|
+
const limits = {
|
|
86773
|
+
dm: DM_SWEEP_GATE.maxPinOpsPerMinute,
|
|
86774
|
+
group: GROUP_SWEEP_GATE2.maxPinOpsPerMinute
|
|
86775
|
+
};
|
|
86776
|
+
const prune = (cls, t) => {
|
|
86777
|
+
const w = windows[cls];
|
|
86778
|
+
while (w.length > 0 && t - w[0] >= 60000)
|
|
86779
|
+
w.shift();
|
|
86780
|
+
};
|
|
86558
86781
|
return {
|
|
86559
|
-
|
|
86560
|
-
|
|
86561
|
-
|
|
86562
|
-
|
|
86563
|
-
if (
|
|
86564
|
-
return;
|
|
86565
|
-
|
|
86566
|
-
|
|
86567
|
-
|
|
86568
|
-
|
|
86782
|
+
waitMs(cls) {
|
|
86783
|
+
const t = now();
|
|
86784
|
+
prune(cls, t);
|
|
86785
|
+
const w = windows[cls];
|
|
86786
|
+
if (w.length < limits[cls])
|
|
86787
|
+
return 0;
|
|
86788
|
+
return Math.max(0, 60000 - (t - w[0]));
|
|
86789
|
+
},
|
|
86790
|
+
record(cls) {
|
|
86791
|
+
windows[cls].push(now());
|
|
86792
|
+
}
|
|
86793
|
+
};
|
|
86794
|
+
}
|
|
86795
|
+
function createStalePinSweeper(deps) {
|
|
86796
|
+
const log = deps.log ?? ((l) => process.stderr.write(l));
|
|
86797
|
+
const budget = createPinOpBudget(deps.now);
|
|
86798
|
+
let circuitOpen = false;
|
|
86799
|
+
let lastWriteAt = 0;
|
|
86800
|
+
const commit = (cursor) => {
|
|
86801
|
+
try {
|
|
86802
|
+
upsertSweepCursor(deps.store.path, deps.store.fs, cursor, log);
|
|
86803
|
+
} catch (err) {
|
|
86804
|
+
log(`stale-pin-sweep: cursor persist failed: ${err.message}
|
|
86805
|
+
`);
|
|
86806
|
+
}
|
|
86807
|
+
};
|
|
86808
|
+
const loadCursor = (t, kind) => {
|
|
86809
|
+
const key = sweepTargetKey(t.chatId, t.threadId);
|
|
86810
|
+
let rows = [];
|
|
86811
|
+
try {
|
|
86812
|
+
rows = loadSweepCursors(deps.store.path, deps.store.fs);
|
|
86813
|
+
} catch {
|
|
86814
|
+
rows = [];
|
|
86815
|
+
}
|
|
86816
|
+
const existing = rows.find((c) => sweepTargetKey(c.chatId, c.threadId) === key);
|
|
86817
|
+
if (existing != null)
|
|
86818
|
+
return { ...existing, kind };
|
|
86819
|
+
return {
|
|
86820
|
+
chatId: t.chatId,
|
|
86821
|
+
threadId: t.threadId,
|
|
86822
|
+
kind,
|
|
86823
|
+
popped: 0,
|
|
86824
|
+
done: false,
|
|
86825
|
+
attempts: 0,
|
|
86826
|
+
updatedAt: deps.now()
|
|
86827
|
+
};
|
|
86828
|
+
};
|
|
86829
|
+
const awaitWriteSlot = async (kind) => {
|
|
86830
|
+
const cls = budgetClassFor(kind);
|
|
86831
|
+
const wait = budget.waitMs(cls);
|
|
86832
|
+
if (wait > 0)
|
|
86833
|
+
return false;
|
|
86834
|
+
const gate = gateFor(kind);
|
|
86835
|
+
const since = deps.now() - lastWriteAt;
|
|
86836
|
+
if (lastWriteAt > 0 && since < gate.minCallDelayMs) {
|
|
86837
|
+
await deps.sleep(gate.minCallDelayMs - since);
|
|
86838
|
+
}
|
|
86839
|
+
lastWriteAt = deps.now();
|
|
86840
|
+
budget.record(cls);
|
|
86841
|
+
return true;
|
|
86842
|
+
};
|
|
86843
|
+
const readTopVerified = async (chatId) => {
|
|
86844
|
+
const read = async () => {
|
|
86569
86845
|
try {
|
|
86570
|
-
await deps.
|
|
86846
|
+
return { v: await deps.getTopPinnedMessageId(chatId) };
|
|
86847
|
+
} catch {
|
|
86848
|
+
return null;
|
|
86849
|
+
}
|
|
86850
|
+
};
|
|
86851
|
+
let prev = await read();
|
|
86852
|
+
if (prev == null)
|
|
86853
|
+
return null;
|
|
86854
|
+
for (let i = 0;i < VERIFY_READ_MAX_PAIRS; i++) {
|
|
86855
|
+
await deps.sleep(VERIFY_READ_GAP_MS);
|
|
86856
|
+
const next = await read();
|
|
86857
|
+
if (next == null)
|
|
86858
|
+
return null;
|
|
86859
|
+
if (next.v === prev.v)
|
|
86860
|
+
return { top: next.v };
|
|
86861
|
+
prev = next;
|
|
86862
|
+
}
|
|
86863
|
+
return null;
|
|
86864
|
+
};
|
|
86865
|
+
const classify = (err) => {
|
|
86866
|
+
if (isPeerFloodError(err))
|
|
86867
|
+
return { kind: "breaker", detail: "PEER_FLOOD" };
|
|
86868
|
+
const retry = retryAfterSeconds(err);
|
|
86869
|
+
if (retry != null) {
|
|
86870
|
+
if (retry > CIRCUIT_BREAKER_RETRY_AFTER_SEC) {
|
|
86871
|
+
return { kind: "breaker", detail: `retry_after=${retry}s > ${CIRCUIT_BREAKER_RETRY_AFTER_SEC}s` };
|
|
86872
|
+
}
|
|
86873
|
+
return { kind: "flood", seconds: retry };
|
|
86874
|
+
}
|
|
86875
|
+
if (isPinRightsError2(err))
|
|
86876
|
+
return { kind: "rights" };
|
|
86877
|
+
return { kind: "other", detail: err?.message ?? String(err) };
|
|
86878
|
+
};
|
|
86879
|
+
const repinUnpinLoop = async (target, kind, cursor) => {
|
|
86880
|
+
const gate = gateFor(kind);
|
|
86881
|
+
let popped = 0;
|
|
86882
|
+
let consecutiveFloods = 0;
|
|
86883
|
+
let lastRetryAfter = null;
|
|
86884
|
+
let noProgressAtSameRetryAfter = 0;
|
|
86885
|
+
let lastObservedTop = null;
|
|
86886
|
+
let unverifiedPop = false;
|
|
86887
|
+
const creditPop = () => {
|
|
86888
|
+
popped++;
|
|
86889
|
+
cursor.popped++;
|
|
86890
|
+
cursor.updatedAt = deps.now();
|
|
86891
|
+
commit(cursor);
|
|
86892
|
+
};
|
|
86893
|
+
for (let i = 0;i < gate.maxPopsPerChatPerSweep; i++) {
|
|
86894
|
+
if (circuitOpen) {
|
|
86895
|
+
return { status: "aborted-circuit-breaker", popped, detail: "breaker open" };
|
|
86896
|
+
}
|
|
86897
|
+
const observed = await readTopVerified(target.chatId);
|
|
86898
|
+
if (observed == null) {
|
|
86899
|
+
return { status: "incomplete", popped, detail: "pin-stack read unverifiable" };
|
|
86900
|
+
}
|
|
86901
|
+
if (unverifiedPop) {
|
|
86902
|
+
if (observed.top != null && observed.top === lastObservedTop) {
|
|
86903
|
+
return {
|
|
86904
|
+
status: "incomplete",
|
|
86905
|
+
popped,
|
|
86906
|
+
detail: `no progress: message ${observed.top} still on top after a repin+unpin`
|
|
86907
|
+
};
|
|
86908
|
+
}
|
|
86909
|
+
creditPop();
|
|
86910
|
+
unverifiedPop = false;
|
|
86911
|
+
}
|
|
86912
|
+
if (observed.top == null) {
|
|
86913
|
+
return { status: "drained", popped };
|
|
86914
|
+
}
|
|
86915
|
+
lastObservedTop = observed.top;
|
|
86916
|
+
if (!await awaitWriteSlot(kind)) {
|
|
86917
|
+
return { status: "deferred-budget", popped, detail: "per-minute pin-op budget spent" };
|
|
86918
|
+
}
|
|
86919
|
+
try {
|
|
86920
|
+
await deps.pinSilent(target.chatId, observed.top);
|
|
86571
86921
|
} catch (err) {
|
|
86572
|
-
const
|
|
86573
|
-
|
|
86574
|
-
|
|
86922
|
+
const d = classify(err);
|
|
86923
|
+
if (d.kind === "breaker") {
|
|
86924
|
+
circuitOpen = true;
|
|
86925
|
+
return { status: "aborted-circuit-breaker", popped, detail: d.detail };
|
|
86926
|
+
}
|
|
86927
|
+
if (d.kind === "rights")
|
|
86928
|
+
return { status: "skipped-no-rights", popped };
|
|
86929
|
+
if (d.kind === "flood") {
|
|
86930
|
+
consecutiveFloods++;
|
|
86931
|
+
if (lastRetryAfter === d.seconds)
|
|
86932
|
+
noProgressAtSameRetryAfter++;
|
|
86933
|
+
else
|
|
86934
|
+
noProgressAtSameRetryAfter = 1;
|
|
86935
|
+
lastRetryAfter = d.seconds;
|
|
86936
|
+
if (consecutiveFloods >= MAX_CONSECUTIVE_FLOOD_WAITS || noProgressAtSameRetryAfter >= MAX_IDENTICAL_RETRY_AFTER_NO_PROGRESS) {
|
|
86937
|
+
return {
|
|
86938
|
+
status: "deferred-flood",
|
|
86939
|
+
popped,
|
|
86940
|
+
detail: `flood: ${consecutiveFloods} consecutive 429s, retry_after=${d.seconds}s`
|
|
86941
|
+
};
|
|
86942
|
+
}
|
|
86943
|
+
await deps.sleep(d.seconds * 1000 * Math.pow(FLOOD_BACKOFF_FACTOR, consecutiveFloods - 1));
|
|
86944
|
+
continue;
|
|
86945
|
+
}
|
|
86946
|
+
return { status: "error", popped, detail: d.detail };
|
|
86947
|
+
}
|
|
86948
|
+
if (!await awaitWriteSlot(kind)) {
|
|
86949
|
+
return { status: "deferred-budget", popped, detail: "per-minute pin-op budget spent" };
|
|
86950
|
+
}
|
|
86951
|
+
try {
|
|
86952
|
+
await deps.unpin(target.chatId, observed.top);
|
|
86953
|
+
} catch (err) {
|
|
86954
|
+
const d = classify(err);
|
|
86955
|
+
if (d.kind === "breaker") {
|
|
86956
|
+
circuitOpen = true;
|
|
86957
|
+
return { status: "aborted-circuit-breaker", popped, detail: d.detail };
|
|
86958
|
+
}
|
|
86959
|
+
if (d.kind === "rights")
|
|
86960
|
+
return { status: "skipped-no-rights", popped };
|
|
86961
|
+
if (isNothingToUnpinError(err))
|
|
86962
|
+
return { status: "drained", popped };
|
|
86963
|
+
if (d.kind === "flood") {
|
|
86964
|
+
consecutiveFloods++;
|
|
86965
|
+
if (lastRetryAfter === d.seconds)
|
|
86966
|
+
noProgressAtSameRetryAfter++;
|
|
86967
|
+
else
|
|
86968
|
+
noProgressAtSameRetryAfter = 1;
|
|
86969
|
+
lastRetryAfter = d.seconds;
|
|
86970
|
+
if (consecutiveFloods >= MAX_CONSECUTIVE_FLOOD_WAITS || noProgressAtSameRetryAfter >= MAX_IDENTICAL_RETRY_AFTER_NO_PROGRESS) {
|
|
86971
|
+
return {
|
|
86972
|
+
status: "deferred-flood",
|
|
86973
|
+
popped,
|
|
86974
|
+
detail: `flood: ${consecutiveFloods} consecutive 429s, retry_after=${d.seconds}s`
|
|
86975
|
+
};
|
|
86976
|
+
}
|
|
86977
|
+
await deps.sleep(d.seconds * 1000 * Math.pow(FLOOD_BACKOFF_FACTOR, consecutiveFloods - 1));
|
|
86978
|
+
continue;
|
|
86979
|
+
}
|
|
86980
|
+
return { status: "error", popped, detail: d.detail };
|
|
86981
|
+
}
|
|
86982
|
+
consecutiveFloods = 0;
|
|
86983
|
+
unverifiedPop = true;
|
|
86984
|
+
}
|
|
86985
|
+
const finalRead = await readTopVerified(target.chatId);
|
|
86986
|
+
if (unverifiedPop && finalRead != null && finalRead.top !== lastObservedTop)
|
|
86987
|
+
creditPop();
|
|
86988
|
+
if (finalRead != null && finalRead.top == null)
|
|
86989
|
+
return { status: "drained", popped };
|
|
86990
|
+
return {
|
|
86991
|
+
status: "deferred-budget",
|
|
86992
|
+
popped,
|
|
86993
|
+
detail: `hit the ${gate.maxPopsPerChatPerSweep}-pop cap for this chat; yielding to next boot`
|
|
86994
|
+
};
|
|
86995
|
+
};
|
|
86996
|
+
const targetedUnpinDrain = async (target, kind, cursor, ids) => {
|
|
86997
|
+
const alreadyDone = new Set(cursor.doneIds ?? []);
|
|
86998
|
+
const pending = ids.filter((id) => !alreadyDone.has(id));
|
|
86999
|
+
if (pending.length === 0) {
|
|
87000
|
+
return { status: "drained", popped: 0, issued: 0, detail: "every recorded id already unpinned" };
|
|
87001
|
+
}
|
|
87002
|
+
const before = await readTopVerified(target.chatId);
|
|
87003
|
+
let issued = 0;
|
|
87004
|
+
let deferred = null;
|
|
87005
|
+
for (const id of pending) {
|
|
87006
|
+
if (circuitOpen) {
|
|
87007
|
+
deferred = { status: "aborted-circuit-breaker", popped: 0, issued, detail: "breaker open" };
|
|
87008
|
+
break;
|
|
87009
|
+
}
|
|
87010
|
+
if (!await awaitWriteSlot(kind)) {
|
|
87011
|
+
deferred = {
|
|
87012
|
+
status: "deferred-budget",
|
|
87013
|
+
popped: 0,
|
|
87014
|
+
issued,
|
|
87015
|
+
detail: `per-minute pin-op budget spent with ${pending.length - issued} ids left`
|
|
87016
|
+
};
|
|
87017
|
+
break;
|
|
87018
|
+
}
|
|
87019
|
+
try {
|
|
87020
|
+
await deps.unpin(target.chatId, id);
|
|
87021
|
+
} catch (err) {
|
|
87022
|
+
const d = classify(err);
|
|
87023
|
+
if (d.kind === "breaker") {
|
|
87024
|
+
circuitOpen = true;
|
|
87025
|
+
deferred = { status: "aborted-circuit-breaker", popped: 0, issued, detail: d.detail };
|
|
87026
|
+
break;
|
|
87027
|
+
}
|
|
87028
|
+
if (d.kind === "rights") {
|
|
87029
|
+
deferred = { status: "skipped-no-rights", popped: 0, issued };
|
|
87030
|
+
break;
|
|
87031
|
+
}
|
|
87032
|
+
if (d.kind === "flood") {
|
|
87033
|
+
deferred = {
|
|
87034
|
+
status: "deferred-flood",
|
|
87035
|
+
popped: 0,
|
|
87036
|
+
issued,
|
|
87037
|
+
detail: `flood: retry_after=${d.seconds}s`
|
|
87038
|
+
};
|
|
87039
|
+
break;
|
|
87040
|
+
}
|
|
87041
|
+
if (!isNothingToUnpinError(err)) {
|
|
87042
|
+
deferred = { status: "error", popped: 0, issued, detail: d.detail };
|
|
87043
|
+
break;
|
|
87044
|
+
}
|
|
87045
|
+
}
|
|
87046
|
+
issued++;
|
|
87047
|
+
alreadyDone.add(id);
|
|
87048
|
+
cursor.doneIds = [...alreadyDone];
|
|
87049
|
+
cursor.updatedAt = deps.now();
|
|
87050
|
+
commit(cursor);
|
|
87051
|
+
}
|
|
87052
|
+
const after = await readTopVerified(target.chatId);
|
|
87053
|
+
if (after == null) {
|
|
87054
|
+
return {
|
|
87055
|
+
status: deferred?.status ?? "incomplete",
|
|
87056
|
+
popped: 0,
|
|
87057
|
+
issued,
|
|
87058
|
+
detail: "pin-stack read unverifiable after the unpin pass"
|
|
87059
|
+
};
|
|
87060
|
+
}
|
|
87061
|
+
if (after.top == null) {
|
|
87062
|
+
const popped2 = issued;
|
|
87063
|
+
cursor.popped += popped2;
|
|
87064
|
+
commit(cursor);
|
|
87065
|
+
return { status: "drained", popped: popped2, issued };
|
|
87066
|
+
}
|
|
87067
|
+
if (deferred != null)
|
|
87068
|
+
return { ...deferred, popped: 0 };
|
|
87069
|
+
const ours = new Set(ids);
|
|
87070
|
+
if (ours.has(after.top)) {
|
|
87071
|
+
return {
|
|
87072
|
+
status: "incomplete",
|
|
87073
|
+
popped: 0,
|
|
87074
|
+
issued,
|
|
87075
|
+
detail: `recorded pin ${after.top} is still on top after a targeted unpin`
|
|
87076
|
+
};
|
|
87077
|
+
}
|
|
87078
|
+
const popped = before != null && before.top !== after.top ? 1 : 0;
|
|
87079
|
+
cursor.popped += popped;
|
|
87080
|
+
commit(cursor);
|
|
87081
|
+
return {
|
|
87082
|
+
status: "drained",
|
|
87083
|
+
popped,
|
|
87084
|
+
issued,
|
|
87085
|
+
detail: `unpinned ${issued} recorded id(s); top ${after.top} is not ours and was left alone`
|
|
87086
|
+
};
|
|
87087
|
+
};
|
|
87088
|
+
const forumTopicDrain = async (target, cursor) => {
|
|
87089
|
+
const threadId = target.threadId;
|
|
87090
|
+
if (threadId == null) {
|
|
87091
|
+
return { status: "skipped-nothing-recorded", popped: 0, detail: "no message_thread_id" };
|
|
87092
|
+
}
|
|
87093
|
+
if (!await awaitWriteSlot("forum-topic")) {
|
|
87094
|
+
return { status: "deferred-budget", popped: 0, detail: "per-minute pin-op budget spent" };
|
|
87095
|
+
}
|
|
87096
|
+
try {
|
|
87097
|
+
await deps.unpinAllForumTopicMessages(target.chatId, threadId);
|
|
87098
|
+
} catch (err) {
|
|
87099
|
+
const d = classify(err);
|
|
87100
|
+
if (d.kind === "breaker") {
|
|
87101
|
+
circuitOpen = true;
|
|
87102
|
+
return { status: "aborted-circuit-breaker", popped: 0, detail: d.detail };
|
|
87103
|
+
}
|
|
87104
|
+
if (d.kind === "rights")
|
|
87105
|
+
return { status: "skipped-no-rights", popped: 0 };
|
|
87106
|
+
if (d.kind === "flood") {
|
|
87107
|
+
return {
|
|
87108
|
+
status: "deferred-flood",
|
|
87109
|
+
popped: 0,
|
|
87110
|
+
detail: `unpinAllForumTopicMessages pegged at retry_after=${d.seconds}s; not looping`
|
|
87111
|
+
};
|
|
87112
|
+
}
|
|
87113
|
+
return { status: "error", popped: 0, detail: d.detail };
|
|
87114
|
+
}
|
|
87115
|
+
cursor.popped++;
|
|
87116
|
+
cursor.updatedAt = deps.now();
|
|
87117
|
+
commit(cursor);
|
|
87118
|
+
const observed = await readTopVerified(target.chatId);
|
|
87119
|
+
if (observed != null && observed.top == null)
|
|
87120
|
+
return { status: "drained", popped: 1 };
|
|
87121
|
+
return { status: "drained", popped: 1, detail: "topic drained; chat-wide stack may hold other topics" };
|
|
87122
|
+
};
|
|
87123
|
+
const sweepOnce = async (target) => {
|
|
87124
|
+
if (!deps.eligible())
|
|
87125
|
+
return { status: "skipped-not-eligible", popped: 0 };
|
|
87126
|
+
if (circuitOpen) {
|
|
87127
|
+
return { status: "aborted-circuit-breaker", popped: 0, detail: "breaker already open" };
|
|
87128
|
+
}
|
|
87129
|
+
const kind = classifyChatForSweep(target);
|
|
87130
|
+
const cursor = loadCursor(target, kind);
|
|
87131
|
+
if (cursor.done)
|
|
87132
|
+
return { status: "already-drained", popped: 0 };
|
|
87133
|
+
if (cursor.attempts >= SWEEP_MAX_ATTEMPTS) {
|
|
87134
|
+
return { status: "forfeited", popped: 0, detail: `${cursor.attempts} attempts exhausted` };
|
|
87135
|
+
}
|
|
87136
|
+
if (kind !== "dm") {
|
|
87137
|
+
let allowed = false;
|
|
87138
|
+
try {
|
|
87139
|
+
allowed = await deps.canPinInChat(target.chatId);
|
|
87140
|
+
} catch {
|
|
87141
|
+
allowed = false;
|
|
86575
87142
|
}
|
|
86576
|
-
|
|
87143
|
+
if (!allowed) {
|
|
87144
|
+
cursor.attempts++;
|
|
87145
|
+
cursor.lastStatus = "skipped-no-rights";
|
|
87146
|
+
cursor.updatedAt = deps.now();
|
|
87147
|
+
commit(cursor);
|
|
87148
|
+
return { status: "skipped-no-rights", popped: 0 };
|
|
87149
|
+
}
|
|
87150
|
+
}
|
|
87151
|
+
cursor.attempts++;
|
|
87152
|
+
cursor.updatedAt = deps.now();
|
|
87153
|
+
commit(cursor);
|
|
87154
|
+
const protectedIds = [...new Set(deps.protectedMessageIds(target.chatId))];
|
|
87155
|
+
let result;
|
|
87156
|
+
try {
|
|
87157
|
+
if (kind === "dm") {
|
|
87158
|
+
result = await repinUnpinLoop(target, kind, cursor);
|
|
87159
|
+
} else if (mayUnpinAllForumTopic(kind, deps.allowUnpinAllForumTopic)) {
|
|
87160
|
+
result = await forumTopicDrain(target, cursor);
|
|
87161
|
+
} else {
|
|
87162
|
+
const keep = new Set(protectedIds);
|
|
87163
|
+
const ids = [
|
|
87164
|
+
...new Set([
|
|
87165
|
+
...target.messageIds ?? [],
|
|
87166
|
+
...deps.recordedPinIds(target.chatId, target.threadId)
|
|
87167
|
+
])
|
|
87168
|
+
].filter((id) => !keep.has(id));
|
|
87169
|
+
result = ids.length === 0 ? {
|
|
87170
|
+
status: "skipped-nothing-recorded",
|
|
87171
|
+
popped: 0,
|
|
87172
|
+
issued: 0,
|
|
87173
|
+
detail: "no recorded pin ids for this target \u2014 nothing this gateway may remove"
|
|
87174
|
+
} : await targetedUnpinDrain(target, kind, cursor, ids);
|
|
87175
|
+
}
|
|
87176
|
+
} catch (err) {
|
|
87177
|
+
result = { status: "error", popped: 0, detail: err.message };
|
|
87178
|
+
}
|
|
87179
|
+
if (result.status === "drained" || result.status === "skipped-nothing-recorded") {
|
|
87180
|
+
cursor.done = true;
|
|
87181
|
+
}
|
|
87182
|
+
cursor.lastStatus = result.status;
|
|
87183
|
+
cursor.updatedAt = deps.now();
|
|
87184
|
+
commit(cursor);
|
|
87185
|
+
if (kind === "dm" && (result.status === "drained" || result.popped > 0)) {
|
|
87186
|
+
for (const messageId of protectedIds) {
|
|
87187
|
+
if (circuitOpen)
|
|
87188
|
+
break;
|
|
87189
|
+
if (!await awaitWriteSlot(kind))
|
|
87190
|
+
break;
|
|
86577
87191
|
try {
|
|
86578
|
-
await deps.pinSilent(chatId, messageId);
|
|
87192
|
+
await deps.pinSilent(target.chatId, messageId);
|
|
86579
87193
|
} catch (err) {
|
|
86580
|
-
|
|
86581
|
-
deps.log?.(`telegram gateway: dm-pin-sweep: re-pin failed ` + `(chat=${chatId} msg=${messageId}): ${msg}
|
|
87194
|
+
log(`telegram gateway: stale-pin-sweep: re-pin of protected message failed ` + `(chat=${target.chatId} msg=${messageId}): ${err.message}
|
|
86582
87195
|
`);
|
|
86583
87196
|
}
|
|
86584
87197
|
}
|
|
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
87198
|
}
|
|
87199
|
+
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})` : "") + `
|
|
87200
|
+
`);
|
|
87201
|
+
return result;
|
|
87202
|
+
};
|
|
87203
|
+
const attempted = new Set;
|
|
87204
|
+
const inFlight = new Map;
|
|
87205
|
+
const sweepTarget = (target) => {
|
|
87206
|
+
const key = sweepTargetKey(target.chatId, target.threadId);
|
|
87207
|
+
const running = inFlight.get(key);
|
|
87208
|
+
if (running != null)
|
|
87209
|
+
return running;
|
|
87210
|
+
if (!deps.eligible())
|
|
87211
|
+
return Promise.resolve({ status: "skipped-not-eligible", popped: 0 });
|
|
87212
|
+
if (attempted.has(key))
|
|
87213
|
+
return Promise.resolve({ status: "already-attempted", popped: 0 });
|
|
87214
|
+
attempted.add(key);
|
|
87215
|
+
const p = sweepOnce(target).finally(() => inFlight.delete(key));
|
|
87216
|
+
inFlight.set(key, p);
|
|
87217
|
+
return p;
|
|
86590
87218
|
};
|
|
87219
|
+
return { sweepTarget, isCircuitOpen: () => circuitOpen };
|
|
87220
|
+
}
|
|
87221
|
+
|
|
87222
|
+
// gateway/stale-pin-sweep-wiring.ts
|
|
87223
|
+
function protectedPinIds(args) {
|
|
87224
|
+
const ids = [];
|
|
87225
|
+
for (const claim of args.claims) {
|
|
87226
|
+
if (claim.chatId === args.chatId)
|
|
87227
|
+
ids.push(claim.messageId);
|
|
87228
|
+
}
|
|
87229
|
+
try {
|
|
87230
|
+
ids.push(...unexpiredStoreRepinIds(args.loadPinRows(), args.chatId, args.now));
|
|
87231
|
+
} catch (err) {
|
|
87232
|
+
args.log(`telegram gateway: stale-pin-sweep: store repin scan failed ` + `(chat=${args.chatId}): ${err.message}
|
|
87233
|
+
`);
|
|
87234
|
+
}
|
|
87235
|
+
return ids;
|
|
87236
|
+
}
|
|
87237
|
+
function recordedPinIdsFor(rows, chatId, threadId) {
|
|
87238
|
+
const out = [];
|
|
87239
|
+
for (const r of rows) {
|
|
87240
|
+
if (r.chatId !== chatId)
|
|
87241
|
+
continue;
|
|
87242
|
+
if ((r.threadId ?? undefined) !== threadId)
|
|
87243
|
+
continue;
|
|
87244
|
+
if (typeof r.messageId === "number" && !out.includes(r.messageId))
|
|
87245
|
+
out.push(r.messageId);
|
|
87246
|
+
}
|
|
87247
|
+
return out;
|
|
87248
|
+
}
|
|
87249
|
+
function createGatewayStalePinSweeper(w) {
|
|
87250
|
+
const log = w.log ?? ((line) => process.stderr.write(line));
|
|
87251
|
+
const now = w.now ?? Date.now;
|
|
87252
|
+
const { handle: bot, call } = w.telegram;
|
|
87253
|
+
return createStalePinSweeper({
|
|
87254
|
+
getTopPinnedMessageId: async (chatId) => {
|
|
87255
|
+
const chat = await call(() => bot().api.getChat(chatId), {
|
|
87256
|
+
chat_id: chatId,
|
|
87257
|
+
verb: "stale-pin-sweep.get-chat"
|
|
87258
|
+
});
|
|
87259
|
+
return chat?.pinned_message?.message_id ?? null;
|
|
87260
|
+
},
|
|
87261
|
+
pinSilent: (chatId, messageId) => call(() => bot().api.pinChatMessage(chatId, messageId, { disable_notification: true }), { chat_id: chatId, verb: "stale-pin-sweep.repin" }),
|
|
87262
|
+
unpin: (chatId, messageId) => call(() => bot().api.unpinChatMessage(chatId, messageId), { chat_id: chatId, verb: "stale-pin-sweep.unpin" }),
|
|
87263
|
+
unpinAllForumTopicMessages: (chatId, threadId) => call(() => bot().api.unpinAllForumTopicMessages(chatId, threadId), {
|
|
87264
|
+
chat_id: chatId,
|
|
87265
|
+
verb: "stale-pin-sweep.unpin-all-topic"
|
|
87266
|
+
}),
|
|
87267
|
+
canPinInChat: async (chatId) => {
|
|
87268
|
+
const self = bot().botInfo?.id;
|
|
87269
|
+
if (self == null)
|
|
87270
|
+
return false;
|
|
87271
|
+
const member = await call(() => bot().api.getChatMember(chatId, self), {
|
|
87272
|
+
chat_id: chatId,
|
|
87273
|
+
verb: "stale-pin-sweep.get-chat-member"
|
|
87274
|
+
});
|
|
87275
|
+
return member?.status === "administrator" && member.can_pin_messages === true;
|
|
87276
|
+
},
|
|
87277
|
+
recordedPinIds: (chatId, threadId) => {
|
|
87278
|
+
try {
|
|
87279
|
+
return recordedPinIdsFor(w.loadPinRows(), chatId, threadId);
|
|
87280
|
+
} catch (err) {
|
|
87281
|
+
log(`telegram gateway: stale-pin-sweep: recorded-pin scan failed ` + `(chat=${chatId}): ${err.message}
|
|
87282
|
+
`);
|
|
87283
|
+
return [];
|
|
87284
|
+
}
|
|
87285
|
+
},
|
|
87286
|
+
protectedMessageIds: (chatId) => protectedPinIds({
|
|
87287
|
+
chatId,
|
|
87288
|
+
claims: w.claims(),
|
|
87289
|
+
loadPinRows: w.loadPinRows,
|
|
87290
|
+
now: now(),
|
|
87291
|
+
log
|
|
87292
|
+
}),
|
|
87293
|
+
eligible: w.eligible,
|
|
87294
|
+
sleep: w.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms))),
|
|
87295
|
+
now,
|
|
87296
|
+
store: w.store,
|
|
87297
|
+
allowUnpinAllForumTopic: w.allowUnpinAllForumTopic,
|
|
87298
|
+
log
|
|
87299
|
+
});
|
|
86591
87300
|
}
|
|
86592
87301
|
|
|
86593
87302
|
// gateway/webhook-ingest-server.ts
|
|
@@ -87751,7 +88460,7 @@ function recordWebhookEvent(rec, deps = {}) {
|
|
|
87751
88460
|
|
|
87752
88461
|
// gateway/ipc-server.ts
|
|
87753
88462
|
init_format();
|
|
87754
|
-
import { renameSync as
|
|
88463
|
+
import { renameSync as renameSync17, unlinkSync as unlinkSync20, chmodSync as chmodSync11 } from "fs";
|
|
87755
88464
|
var MAX_BUFFER_SIZE = 1024 * 1024;
|
|
87756
88465
|
var VALID_OPERATOR_KINDS = new Set([
|
|
87757
88466
|
"credentials-expired",
|
|
@@ -87962,7 +88671,7 @@ function createIpcServer(options) {
|
|
|
87962
88671
|
heartbeatTimeoutMs = 30000
|
|
87963
88672
|
} = options;
|
|
87964
88673
|
try {
|
|
87965
|
-
|
|
88674
|
+
renameSync17(socketPath, socketPath + ".bak");
|
|
87966
88675
|
} catch {}
|
|
87967
88676
|
try {
|
|
87968
88677
|
unlinkSync20(socketPath + ".bak");
|
|
@@ -88352,7 +89061,7 @@ function createIpcServer(options) {
|
|
|
88352
89061
|
clientBySocketId.clear();
|
|
88353
89062
|
server.stop(true);
|
|
88354
89063
|
try {
|
|
88355
|
-
|
|
89064
|
+
renameSync17(socketPath, socketPath + ".bak");
|
|
88356
89065
|
} catch {}
|
|
88357
89066
|
}
|
|
88358
89067
|
};
|
|
@@ -89256,6 +89965,7 @@ function obligationEscalationText(o) {
|
|
|
89256
89965
|
}
|
|
89257
89966
|
|
|
89258
89967
|
// gateway/obligation-store.ts
|
|
89968
|
+
import { dirname as dirname20 } from "node:path";
|
|
89259
89969
|
function isObligationRow(x) {
|
|
89260
89970
|
if (x == null || typeof x !== "object")
|
|
89261
89971
|
return false;
|
|
@@ -89311,9 +90021,17 @@ function persistObligations(path3, fs3, snapshot, log = (l) => process.stderr.wr
|
|
|
89311
90021
|
const tmp = path3 + ".tmp";
|
|
89312
90022
|
try {
|
|
89313
90023
|
fs3.writeFileSync(tmp, JSON.stringify(env));
|
|
90024
|
+
fs3.fsyncFileSync(tmp);
|
|
89314
90025
|
fs3.renameSync(tmp, path3);
|
|
89315
90026
|
} catch (err) {
|
|
89316
90027
|
log(`obligation-store: persist FAILED path=${path3}: ${err.message} \u2014 ` + `durability degraded to in-memory
|
|
90028
|
+
`);
|
|
90029
|
+
return;
|
|
90030
|
+
}
|
|
90031
|
+
try {
|
|
90032
|
+
fs3.fsyncDirSync(dirname20(path3));
|
|
90033
|
+
} catch (err) {
|
|
90034
|
+
log(`obligation-store: directory fsync FAILED path=${path3}: ${err.message} \u2014 ` + `snapshot written but the rename may not survive a power cut
|
|
89317
90035
|
`);
|
|
89318
90036
|
}
|
|
89319
90037
|
}
|
|
@@ -89397,12 +90115,12 @@ function createCapturedResumeDispatcher(ports) {
|
|
|
89397
90115
|
|
|
89398
90116
|
// gateway/status-pin-store.ts
|
|
89399
90117
|
var BOOT_UNPIN_MAX_ATTEMPTS = 5;
|
|
89400
|
-
var SNAPSHOT_VERSIONS2 = new Set([1, 2, 3]);
|
|
90118
|
+
var SNAPSHOT_VERSIONS2 = new Set([1, 2, 3, 4]);
|
|
89401
90119
|
function isPinRow2(x) {
|
|
89402
90120
|
if (x == null || typeof x !== "object")
|
|
89403
90121
|
return false;
|
|
89404
90122
|
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");
|
|
90123
|
+
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
90124
|
}
|
|
89407
90125
|
function loadStatusPins2(path3, fs3) {
|
|
89408
90126
|
if (!fs3.existsSync(path3))
|
|
@@ -89427,7 +90145,7 @@ function loadStatusPins2(path3, fs3) {
|
|
|
89427
90145
|
return env.pins.filter(isPinRow2);
|
|
89428
90146
|
}
|
|
89429
90147
|
function persistStatusPins2(path3, fs3, snapshot, log = (l) => process.stderr.write(l)) {
|
|
89430
|
-
const env = { v:
|
|
90148
|
+
const env = { v: 4, pins: [...snapshot] };
|
|
89431
90149
|
const tmp = path3 + ".tmp";
|
|
89432
90150
|
try {
|
|
89433
90151
|
fs3.writeFileSync(tmp, JSON.stringify(env));
|
|
@@ -89775,6 +90493,7 @@ function decideWorkerPinReaps(args) {
|
|
|
89775
90493
|
}
|
|
89776
90494
|
|
|
89777
90495
|
// gateway/inbound-spool.ts
|
|
90496
|
+
import { dirname as dirname21 } from "node:path";
|
|
89778
90497
|
function spoolId(msg) {
|
|
89779
90498
|
if (msg.meta?.source === "subagent_handback" && typeof msg.meta?.subagent_jsonl_id === "string" && msg.meta.subagent_jsonl_id.length > 0) {
|
|
89780
90499
|
return `s:handback:${msg.meta.subagent_jsonl_id}`;
|
|
@@ -89878,6 +90597,7 @@ function createInboundSpool(opts) {
|
|
|
89878
90597
|
try {
|
|
89879
90598
|
fs3.appendFileSync(path3, JSON.stringify(rec) + `
|
|
89880
90599
|
`);
|
|
90600
|
+
fs3.fsyncFileSync(path3);
|
|
89881
90601
|
if (consecutiveAppendFailures > 0) {
|
|
89882
90602
|
log(`inbound-spool: append recovered path=${path3} after ` + `${consecutiveAppendFailures} failure(s) \u2014 durability restored
|
|
89883
90603
|
`);
|
|
@@ -89936,11 +90656,19 @@ function createInboundSpool(opts) {
|
|
|
89936
90656
|
fs3.writeFileSync(tmp, lines.length ? lines.join(`
|
|
89937
90657
|
`) + `
|
|
89938
90658
|
` : "");
|
|
90659
|
+
fs3.fsyncFileSync(tmp);
|
|
89939
90660
|
fs3.renameSync(tmp, path3);
|
|
89940
90661
|
log(`inbound-spool: compacted path=${path3} live=${live.size}
|
|
89941
90662
|
`);
|
|
89942
90663
|
} catch (err) {
|
|
89943
90664
|
log(`inbound-spool: compact FAILED path=${path3}: ${err.message}
|
|
90665
|
+
`);
|
|
90666
|
+
return;
|
|
90667
|
+
}
|
|
90668
|
+
try {
|
|
90669
|
+
fs3.fsyncDirSync(dirname21(path3));
|
|
90670
|
+
} catch (err) {
|
|
90671
|
+
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
90672
|
`);
|
|
89945
90673
|
}
|
|
89946
90674
|
}
|
|
@@ -92163,9 +92891,9 @@ function toolLabel(tool, input, preamble, precomputedLabel) {
|
|
|
92163
92891
|
}
|
|
92164
92892
|
case "Bash":
|
|
92165
92893
|
case "BashOutput": {
|
|
92166
|
-
const
|
|
92167
|
-
if (
|
|
92168
|
-
return truncate4(firstLine(
|
|
92894
|
+
const description2 = str("description");
|
|
92895
|
+
if (description2)
|
|
92896
|
+
return truncate4(firstLine(description2), MAX_DESCRIPTION_CHARS);
|
|
92169
92897
|
const pre = preambleLabel();
|
|
92170
92898
|
if (pre)
|
|
92171
92899
|
return pre;
|
|
@@ -92227,9 +92955,9 @@ function toolLabel(tool, input, preamble, precomputedLabel) {
|
|
|
92227
92955
|
}
|
|
92228
92956
|
default:
|
|
92229
92957
|
if (tool.startsWith("mcp__")) {
|
|
92230
|
-
const
|
|
92231
|
-
if (
|
|
92232
|
-
return truncate4(firstLine(stripHtml(
|
|
92958
|
+
const description2 = str("description");
|
|
92959
|
+
if (description2)
|
|
92960
|
+
return truncate4(firstLine(stripHtml(description2)), MAX_DESCRIPTION_CHARS);
|
|
92233
92961
|
const label = mcpBaseLabel(tool);
|
|
92234
92962
|
const query3 = str("query") ?? str("text") ?? str("name");
|
|
92235
92963
|
if (label && query3) {
|
|
@@ -92596,12 +93324,12 @@ function skillProposalKeyboard(id) {
|
|
|
92596
93324
|
|
|
92597
93325
|
// ../src/self-improve/skill-proposals.ts
|
|
92598
93326
|
import {
|
|
92599
|
-
closeSync as
|
|
93327
|
+
closeSync as closeSync9,
|
|
92600
93328
|
existsSync as existsSync41,
|
|
92601
93329
|
mkdirSync as mkdirSync37,
|
|
92602
|
-
openSync as
|
|
93330
|
+
openSync as openSync9,
|
|
92603
93331
|
readFileSync as readFileSync37,
|
|
92604
|
-
writeSync as
|
|
93332
|
+
writeSync as writeSync6
|
|
92605
93333
|
} from "node:fs";
|
|
92606
93334
|
import { join as join50 } from "node:path";
|
|
92607
93335
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
@@ -92621,12 +93349,12 @@ function ensureDir3(stateDir) {
|
|
|
92621
93349
|
}
|
|
92622
93350
|
}
|
|
92623
93351
|
function appendLine2(path3, obj) {
|
|
92624
|
-
const fd =
|
|
93352
|
+
const fd = openSync9(path3, "a");
|
|
92625
93353
|
try {
|
|
92626
|
-
|
|
93354
|
+
writeSync6(fd, JSON.stringify(obj) + `
|
|
92627
93355
|
`);
|
|
92628
93356
|
} finally {
|
|
92629
|
-
|
|
93357
|
+
closeSync9(fd);
|
|
92630
93358
|
}
|
|
92631
93359
|
}
|
|
92632
93360
|
function readLines2(path3, isValid2) {
|
|
@@ -93231,11 +93959,11 @@ function escapeBody2(s) {
|
|
|
93231
93959
|
}
|
|
93232
93960
|
|
|
93233
93961
|
// gateway/pid-file.ts
|
|
93234
|
-
import { writeFileSync as writeFileSync33, readFileSync as readFileSync38, unlinkSync as unlinkSync21, renameSync as
|
|
93962
|
+
import { writeFileSync as writeFileSync33, readFileSync as readFileSync38, unlinkSync as unlinkSync21, renameSync as renameSync18 } from "node:fs";
|
|
93235
93963
|
function writePidFile(path3, record) {
|
|
93236
93964
|
const tmp = `${path3}.tmp-${process.pid}-${Date.now()}`;
|
|
93237
93965
|
writeFileSync33(tmp, JSON.stringify(record), "utf-8");
|
|
93238
|
-
|
|
93966
|
+
renameSync18(tmp, path3);
|
|
93239
93967
|
}
|
|
93240
93968
|
function clearPidFile(path3) {
|
|
93241
93969
|
try {
|
|
@@ -93456,11 +94184,11 @@ function safeCount(fn) {
|
|
|
93456
94184
|
}
|
|
93457
94185
|
|
|
93458
94186
|
// gateway/session-marker.ts
|
|
93459
|
-
import { writeFileSync as writeFileSync34, readFileSync as readFileSync40, renameSync as
|
|
94187
|
+
import { writeFileSync as writeFileSync34, readFileSync as readFileSync40, renameSync as renameSync19, unlinkSync as unlinkSync22 } from "node:fs";
|
|
93460
94188
|
function writeSessionMarker(path3, marker) {
|
|
93461
94189
|
const tmp = `${path3}.tmp-${process.pid}-${Date.now()}`;
|
|
93462
94190
|
writeFileSync34(tmp, JSON.stringify(marker), "utf-8");
|
|
93463
|
-
|
|
94191
|
+
renameSync19(tmp, path3);
|
|
93464
94192
|
}
|
|
93465
94193
|
function readSessionMarker(path3) {
|
|
93466
94194
|
try {
|
|
@@ -93486,12 +94214,12 @@ function shouldFireRestartBanner(input) {
|
|
|
93486
94214
|
}
|
|
93487
94215
|
|
|
93488
94216
|
// gateway/clean-shutdown-marker.ts
|
|
93489
|
-
import { writeFileSync as writeFileSync35, readFileSync as readFileSync41, renameSync as
|
|
94217
|
+
import { writeFileSync as writeFileSync35, readFileSync as readFileSync41, renameSync as renameSync20, unlinkSync as unlinkSync23 } from "node:fs";
|
|
93490
94218
|
var DEFAULT_MAX_AGE_MS = 60000;
|
|
93491
94219
|
function writeCleanShutdownMarker(path3, marker) {
|
|
93492
94220
|
const tmp = `${path3}.tmp-${process.pid}-${Date.now()}`;
|
|
93493
94221
|
writeFileSync35(tmp, JSON.stringify(marker), "utf-8");
|
|
93494
|
-
|
|
94222
|
+
renameSync20(tmp, path3);
|
|
93495
94223
|
}
|
|
93496
94224
|
function readCleanShutdownMarker(path3) {
|
|
93497
94225
|
try {
|
|
@@ -93868,10 +94596,10 @@ function classifyAdminGate(text4, myAgentName) {
|
|
|
93868
94596
|
// subagent-watcher.ts
|
|
93869
94597
|
import {
|
|
93870
94598
|
existsSync as existsSync42,
|
|
93871
|
-
openSync as
|
|
94599
|
+
openSync as openSync10,
|
|
93872
94600
|
readSync as readSync2,
|
|
93873
94601
|
statSync as statSync15,
|
|
93874
|
-
closeSync as
|
|
94602
|
+
closeSync as closeSync10,
|
|
93875
94603
|
watch,
|
|
93876
94604
|
readdirSync as readdirSync10,
|
|
93877
94605
|
readFileSync as readFileSync42
|
|
@@ -94684,8 +95412,8 @@ function startSubagentWatcher(config) {
|
|
|
94684
95412
|
existsSync: existsSync42,
|
|
94685
95413
|
readdirSync: readdirSync10,
|
|
94686
95414
|
statSync: statSync15,
|
|
94687
|
-
openSync:
|
|
94688
|
-
closeSync:
|
|
95415
|
+
openSync: openSync10,
|
|
95416
|
+
closeSync: closeSync10,
|
|
94689
95417
|
readSync: readSync2,
|
|
94690
95418
|
watch
|
|
94691
95419
|
};
|
|
@@ -95060,13 +95788,13 @@ function startSubagentWatcher(config) {
|
|
|
95060
95788
|
if (size <= rec.sizeAtSynthesis)
|
|
95061
95789
|
continue;
|
|
95062
95790
|
const entry = registry.get(agentId);
|
|
95063
|
-
const
|
|
95791
|
+
const description2 = entry?.description ?? "sub-agent";
|
|
95064
95792
|
if (rec.resurrectionCount >= MAX_RESURRECTIONS) {
|
|
95065
95793
|
rec.lost = true;
|
|
95066
95794
|
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
95795
|
if (config.onWorkerLost != null) {
|
|
95068
95796
|
try {
|
|
95069
|
-
config.onWorkerLost(agentId,
|
|
95797
|
+
config.onWorkerLost(agentId, description2);
|
|
95070
95798
|
} catch (cbErr) {
|
|
95071
95799
|
log?.(`subagent-watcher: onWorkerLost callback error ${agentId}: ${cbErr.message}`);
|
|
95072
95800
|
}
|
|
@@ -95078,7 +95806,7 @@ function startSubagentWatcher(config) {
|
|
|
95078
95806
|
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
95807
|
if (config.onResurrect != null) {
|
|
95080
95808
|
try {
|
|
95081
|
-
config.onResurrect(agentId,
|
|
95809
|
+
config.onResurrect(agentId, description2);
|
|
95082
95810
|
} catch (cbErr) {
|
|
95083
95811
|
log?.(`subagent-watcher: onResurrect callback error ${agentId}: ${cbErr.message}`);
|
|
95084
95812
|
}
|
|
@@ -95431,7 +96159,7 @@ import {
|
|
|
95431
96159
|
readdirSync as readdirSync11,
|
|
95432
96160
|
unlinkSync as unlinkSync24,
|
|
95433
96161
|
existsSync as existsSync43,
|
|
95434
|
-
renameSync as
|
|
96162
|
+
renameSync as renameSync21
|
|
95435
96163
|
} from "node:fs";
|
|
95436
96164
|
import { join as join52, resolve as resolve10 } from "node:path";
|
|
95437
96165
|
import { homedir as homedir15 } from "node:os";
|
|
@@ -95450,7 +96178,7 @@ function writeRecord(record) {
|
|
|
95450
96178
|
const tmp = `${target}.tmp${process.pid}`;
|
|
95451
96179
|
writeFileSync36(tmp, JSON.stringify(record, null, 2) + `
|
|
95452
96180
|
`, { mode: 384 });
|
|
95453
|
-
|
|
96181
|
+
renameSync21(tmp, target);
|
|
95454
96182
|
}
|
|
95455
96183
|
function readRecord(id) {
|
|
95456
96184
|
const path3 = recordPath(id);
|
|
@@ -95613,11 +96341,8 @@ function determineRestartReason(opts) {
|
|
|
95613
96341
|
return "fresh";
|
|
95614
96342
|
}
|
|
95615
96343
|
|
|
95616
|
-
// gateway/gateway.ts
|
|
95617
|
-
init_boot_card();
|
|
95618
|
-
|
|
95619
96344
|
// gateway/update-announce.ts
|
|
95620
|
-
import { existsSync as existsSync48, mkdirSync as mkdirSync42, openSync as
|
|
96345
|
+
import { existsSync as existsSync48, mkdirSync as mkdirSync42, openSync as openSync11, closeSync as closeSync11, readFileSync as readFileSync50 } from "node:fs";
|
|
95621
96346
|
import { join as join57 } from "node:path";
|
|
95622
96347
|
import { homedir as homedir17 } from "node:os";
|
|
95623
96348
|
|
|
@@ -95710,6 +96435,9 @@ function parseAuditLine(line) {
|
|
|
95710
96435
|
entry.failed_step = o.failed_step;
|
|
95711
96436
|
if (typeof o.failed_agent === "string")
|
|
95712
96437
|
entry.failed_agent = o.failed_agent;
|
|
96438
|
+
if (Array.isArray(o.drifted) && o.drifted.every((x) => typeof x === "string")) {
|
|
96439
|
+
entry.drifted = o.drifted;
|
|
96440
|
+
}
|
|
95713
96441
|
if (typeof o.agent === "string")
|
|
95714
96442
|
entry.agent = o.agent;
|
|
95715
96443
|
if (typeof o.n === "number")
|
|
@@ -95826,8 +96554,8 @@ function claimUpdateAnnouncement(requestId, opts = {}) {
|
|
|
95826
96554
|
const safeId = requestId.replace(/[^A-Za-z0-9_.-]/g, "_").slice(0, 200);
|
|
95827
96555
|
const path3 = join57(dir, safeId);
|
|
95828
96556
|
try {
|
|
95829
|
-
const fd =
|
|
95830
|
-
|
|
96557
|
+
const fd = openSync11(path3, "wx");
|
|
96558
|
+
closeSync11(fd);
|
|
95831
96559
|
return true;
|
|
95832
96560
|
} catch {
|
|
95833
96561
|
return false;
|
|
@@ -96050,20 +96778,20 @@ import { join as join59 } from "node:path";
|
|
|
96050
96778
|
|
|
96051
96779
|
// ../src/issues/store.ts
|
|
96052
96780
|
import {
|
|
96053
|
-
closeSync as
|
|
96781
|
+
closeSync as closeSync12,
|
|
96054
96782
|
existsSync as existsSync49,
|
|
96055
96783
|
mkdirSync as mkdirSync43,
|
|
96056
|
-
openSync as
|
|
96784
|
+
openSync as openSync12,
|
|
96057
96785
|
readdirSync as readdirSync13,
|
|
96058
96786
|
readFileSync as readFileSync52,
|
|
96059
|
-
renameSync as
|
|
96787
|
+
renameSync as renameSync24,
|
|
96060
96788
|
statSync as statSync17,
|
|
96061
96789
|
unlinkSync as unlinkSync25,
|
|
96062
96790
|
writeFileSync as writeFileSync42,
|
|
96063
|
-
writeSync as
|
|
96791
|
+
writeSync as writeSync7
|
|
96064
96792
|
} from "node:fs";
|
|
96065
96793
|
import { join as join58 } from "node:path";
|
|
96066
|
-
import { randomBytes as
|
|
96794
|
+
import { randomBytes as randomBytes11 } from "node:crypto";
|
|
96067
96795
|
import { execSync } from "node:child_process";
|
|
96068
96796
|
|
|
96069
96797
|
// ../src/issues/types.ts
|
|
@@ -96138,12 +96866,12 @@ function resolve11(stateDir, fingerprint, nowFn = Date.now) {
|
|
|
96138
96866
|
function writeAll(stateDir, events) {
|
|
96139
96867
|
const path3 = join58(stateDir, ISSUES_FILE);
|
|
96140
96868
|
sweepOrphanTmpFiles(stateDir);
|
|
96141
|
-
const tmp = `${path3}.tmp-${process.pid}-${
|
|
96869
|
+
const tmp = `${path3}.tmp-${process.pid}-${randomBytes11(4).toString("hex")}`;
|
|
96142
96870
|
const body = events.length === 0 ? "" : events.map((e) => JSON.stringify(e)).join(`
|
|
96143
96871
|
`) + `
|
|
96144
96872
|
`;
|
|
96145
96873
|
writeFileSync42(tmp, body, "utf-8");
|
|
96146
|
-
|
|
96874
|
+
renameSync24(tmp, path3);
|
|
96147
96875
|
}
|
|
96148
96876
|
var ORPHAN_TMP_TTL_MS = 60000;
|
|
96149
96877
|
var TMP_PREFIX = `${ISSUES_FILE}.tmp-`;
|
|
@@ -96175,9 +96903,9 @@ function withLock(stateDir, fn) {
|
|
|
96175
96903
|
let fd = null;
|
|
96176
96904
|
while (fd === null) {
|
|
96177
96905
|
try {
|
|
96178
|
-
fd =
|
|
96906
|
+
fd = openSync12(lockPath, "wx");
|
|
96179
96907
|
try {
|
|
96180
|
-
|
|
96908
|
+
writeSync7(fd, String(process.pid));
|
|
96181
96909
|
} catch {}
|
|
96182
96910
|
} catch (err) {
|
|
96183
96911
|
const e = err;
|
|
@@ -96195,7 +96923,7 @@ function withLock(stateDir, fn) {
|
|
|
96195
96923
|
return fn();
|
|
96196
96924
|
} finally {
|
|
96197
96925
|
try {
|
|
96198
|
-
|
|
96926
|
+
closeSync12(fd);
|
|
96199
96927
|
} catch {}
|
|
96200
96928
|
try {
|
|
96201
96929
|
unlinkSync25(lockPath);
|
|
@@ -97087,7 +97815,7 @@ function createScopedGrantStore(stateDir, env = process.env, log = (l) => proces
|
|
|
97087
97815
|
preserveUnreadableStoreFile(filePath, "scoped-grant-store", log);
|
|
97088
97816
|
unreadable = false;
|
|
97089
97817
|
}
|
|
97090
|
-
|
|
97818
|
+
atomicWriteFileSync2(filePath, JSON.stringify(serializeScopedGrants(store3)), 384);
|
|
97091
97819
|
} catch (err) {
|
|
97092
97820
|
log(`telegram gateway: scoped-grant-store write failed: ${err.message}
|
|
97093
97821
|
`);
|
|
@@ -97875,10 +98603,10 @@ init_auth_snapshot_format2();
|
|
|
97875
98603
|
|
|
97876
98604
|
// gateway/turn-active-marker.ts
|
|
97877
98605
|
import {
|
|
97878
|
-
closeSync as
|
|
98606
|
+
closeSync as closeSync13,
|
|
97879
98607
|
existsSync as existsSync53,
|
|
97880
98608
|
mkdirSync as mkdirSync46,
|
|
97881
|
-
openSync as
|
|
98609
|
+
openSync as openSync13,
|
|
97882
98610
|
readFileSync as readFileSync55,
|
|
97883
98611
|
statSync as statSync19,
|
|
97884
98612
|
unlinkSync as unlinkSync26,
|
|
@@ -97963,6 +98691,163 @@ function startGatewayHeartbeat(stateDir, intervalMs = GATEWAY_HEARTBEAT_INTERVAL
|
|
|
97963
98691
|
return timer3;
|
|
97964
98692
|
}
|
|
97965
98693
|
|
|
98694
|
+
// gateway/boot-beacon.ts
|
|
98695
|
+
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
98696
|
+
import {
|
|
98697
|
+
closeSync as closeSync14,
|
|
98698
|
+
fsyncSync as fsyncSync5,
|
|
98699
|
+
mkdirSync as mkdirSync48,
|
|
98700
|
+
openSync as openSync14,
|
|
98701
|
+
readFileSync as readFileSync56,
|
|
98702
|
+
renameSync as renameSync25,
|
|
98703
|
+
unlinkSync as unlinkSync27,
|
|
98704
|
+
writeFileSync as writeFileSync47
|
|
98705
|
+
} from "node:fs";
|
|
98706
|
+
import { join as join65 } from "node:path";
|
|
98707
|
+
var BOOT_BEACON_FILE = "gateway-beacon.json";
|
|
98708
|
+
var HOST_BOOT_ID_PATH = "/proc/sys/kernel/random/boot_id";
|
|
98709
|
+
var CGROUP_MEMORY_EVENTS_PATH = "/sys/fs/cgroup/memory.events";
|
|
98710
|
+
var CGROUP_MEMORY_CURRENT_PATH = "/sys/fs/cgroup/memory.current";
|
|
98711
|
+
var CGROUP_MEMORY_MAX_PATH = "/sys/fs/cgroup/memory.max";
|
|
98712
|
+
var MAX_FIELD_CHARS = 256;
|
|
98713
|
+
function parseHostBootId(raw) {
|
|
98714
|
+
if (typeof raw !== "string")
|
|
98715
|
+
return;
|
|
98716
|
+
const trimmed = raw.trim();
|
|
98717
|
+
if (trimmed.length === 0 || trimmed.length > MAX_FIELD_CHARS)
|
|
98718
|
+
return;
|
|
98719
|
+
if (/\s/.test(trimmed))
|
|
98720
|
+
return;
|
|
98721
|
+
return trimmed;
|
|
98722
|
+
}
|
|
98723
|
+
function parseOomKillCount(raw) {
|
|
98724
|
+
if (typeof raw !== "string")
|
|
98725
|
+
return;
|
|
98726
|
+
for (const line of raw.split(`
|
|
98727
|
+
`)) {
|
|
98728
|
+
const parts = line.trim().split(/\s+/);
|
|
98729
|
+
if (parts.length !== 2 || parts[0] !== "oom_kill")
|
|
98730
|
+
continue;
|
|
98731
|
+
return parseNonNegativeInt2(parts[1]);
|
|
98732
|
+
}
|
|
98733
|
+
return;
|
|
98734
|
+
}
|
|
98735
|
+
function parseMemoryBytes(raw) {
|
|
98736
|
+
if (typeof raw !== "string")
|
|
98737
|
+
return;
|
|
98738
|
+
return parseNonNegativeInt2(raw.trim());
|
|
98739
|
+
}
|
|
98740
|
+
function parseMemoryMax(raw) {
|
|
98741
|
+
if (typeof raw !== "string")
|
|
98742
|
+
return;
|
|
98743
|
+
const trimmed = raw.trim();
|
|
98744
|
+
if (trimmed === "max")
|
|
98745
|
+
return "max";
|
|
98746
|
+
return parseNonNegativeInt2(trimmed);
|
|
98747
|
+
}
|
|
98748
|
+
function parseNonNegativeInt2(text4) {
|
|
98749
|
+
if (typeof text4 !== "string")
|
|
98750
|
+
return;
|
|
98751
|
+
const trimmed = text4.trim();
|
|
98752
|
+
if (trimmed.length === 0 || trimmed.length > MAX_FIELD_CHARS)
|
|
98753
|
+
return;
|
|
98754
|
+
if (!/^\d+$/.test(trimmed))
|
|
98755
|
+
return;
|
|
98756
|
+
const value = Number(trimmed);
|
|
98757
|
+
return Number.isSafeInteger(value) ? value : undefined;
|
|
98758
|
+
}
|
|
98759
|
+
function buildBootBeacon(input) {
|
|
98760
|
+
const beacon = {
|
|
98761
|
+
bootId: input.bootId,
|
|
98762
|
+
pid: input.pid,
|
|
98763
|
+
wallMs: input.wallMs,
|
|
98764
|
+
monotonicMs: input.monotonicMs
|
|
98765
|
+
};
|
|
98766
|
+
const sample3 = input.sample ?? {};
|
|
98767
|
+
if (sample3.hostBootId !== undefined)
|
|
98768
|
+
beacon.hostBootId = sample3.hostBootId;
|
|
98769
|
+
if (sample3.oomKillCount !== undefined)
|
|
98770
|
+
beacon.oomKillCount = sample3.oomKillCount;
|
|
98771
|
+
if (sample3.memCurrent !== undefined)
|
|
98772
|
+
beacon.memCurrent = sample3.memCurrent;
|
|
98773
|
+
if (sample3.memMax !== undefined)
|
|
98774
|
+
beacon.memMax = sample3.memMax;
|
|
98775
|
+
return beacon;
|
|
98776
|
+
}
|
|
98777
|
+
function serializeBootBeacon(beacon) {
|
|
98778
|
+
return `${JSON.stringify(beacon)}
|
|
98779
|
+
`;
|
|
98780
|
+
}
|
|
98781
|
+
function readTextOrNull(path3) {
|
|
98782
|
+
try {
|
|
98783
|
+
return readFileSync56(path3, "utf-8");
|
|
98784
|
+
} catch {
|
|
98785
|
+
return null;
|
|
98786
|
+
}
|
|
98787
|
+
}
|
|
98788
|
+
function sampleBeaconHost(paths = {}) {
|
|
98789
|
+
const sample3 = {};
|
|
98790
|
+
const hostBootId = parseHostBootId(readTextOrNull(paths.hostBootId ?? HOST_BOOT_ID_PATH));
|
|
98791
|
+
if (hostBootId !== undefined)
|
|
98792
|
+
sample3.hostBootId = hostBootId;
|
|
98793
|
+
const oomKillCount = parseOomKillCount(readTextOrNull(paths.memoryEvents ?? CGROUP_MEMORY_EVENTS_PATH));
|
|
98794
|
+
if (oomKillCount !== undefined)
|
|
98795
|
+
sample3.oomKillCount = oomKillCount;
|
|
98796
|
+
const memCurrent = parseMemoryBytes(readTextOrNull(paths.memoryCurrent ?? CGROUP_MEMORY_CURRENT_PATH));
|
|
98797
|
+
if (memCurrent !== undefined)
|
|
98798
|
+
sample3.memCurrent = memCurrent;
|
|
98799
|
+
const memMax = parseMemoryMax(readTextOrNull(paths.memoryMax ?? CGROUP_MEMORY_MAX_PATH));
|
|
98800
|
+
if (memMax !== undefined)
|
|
98801
|
+
sample3.memMax = memMax;
|
|
98802
|
+
return sample3;
|
|
98803
|
+
}
|
|
98804
|
+
function writeBootBeaconFile(stateDir, beacon) {
|
|
98805
|
+
const path3 = join65(stateDir, BOOT_BEACON_FILE);
|
|
98806
|
+
const tmp = `${path3}.tmp-${process.pid}`;
|
|
98807
|
+
let fd;
|
|
98808
|
+
try {
|
|
98809
|
+
mkdirSync48(stateDir, { recursive: true, mode: 448 });
|
|
98810
|
+
fd = openSync14(tmp, "w", 384);
|
|
98811
|
+
writeFileSync47(fd, serializeBootBeacon(beacon));
|
|
98812
|
+
fsyncSync5(fd);
|
|
98813
|
+
closeSync14(fd);
|
|
98814
|
+
fd = undefined;
|
|
98815
|
+
renameSync25(tmp, path3);
|
|
98816
|
+
return true;
|
|
98817
|
+
} catch {
|
|
98818
|
+
if (fd !== undefined) {
|
|
98819
|
+
try {
|
|
98820
|
+
closeSync14(fd);
|
|
98821
|
+
} catch {}
|
|
98822
|
+
}
|
|
98823
|
+
try {
|
|
98824
|
+
unlinkSync27(tmp);
|
|
98825
|
+
} catch {}
|
|
98826
|
+
return false;
|
|
98827
|
+
}
|
|
98828
|
+
}
|
|
98829
|
+
var GATEWAY_BOOT_ID = randomUUID6();
|
|
98830
|
+
function tickBootBeacon(stateDir, bootId = GATEWAY_BOOT_ID) {
|
|
98831
|
+
try {
|
|
98832
|
+
return writeBootBeaconFile(stateDir, buildBootBeacon({
|
|
98833
|
+
bootId,
|
|
98834
|
+
pid: process.pid,
|
|
98835
|
+
wallMs: Date.now(),
|
|
98836
|
+
monotonicMs: Math.round(performance.now()),
|
|
98837
|
+
sample: sampleBeaconHost()
|
|
98838
|
+
}));
|
|
98839
|
+
} catch {
|
|
98840
|
+
return false;
|
|
98841
|
+
}
|
|
98842
|
+
}
|
|
98843
|
+
function attachBootBeacon(stateDir, next) {
|
|
98844
|
+
tickBootBeacon(stateDir);
|
|
98845
|
+
return () => {
|
|
98846
|
+
tickBootBeacon(stateDir);
|
|
98847
|
+
next();
|
|
98848
|
+
};
|
|
98849
|
+
}
|
|
98850
|
+
|
|
97966
98851
|
// gateway/outbox-sweep.ts
|
|
97967
98852
|
init_flood_circuit_breaker();
|
|
97968
98853
|
async function sweepOutbox(deps) {
|
|
@@ -98185,10 +99070,10 @@ function startOutboxSweep(deps) {
|
|
|
98185
99070
|
}
|
|
98186
99071
|
|
|
98187
99072
|
// ../src/build-info.ts
|
|
98188
|
-
var VERSION2 = "0.19.
|
|
98189
|
-
var COMMIT_SHA = "
|
|
98190
|
-
var COMMIT_DATE = "2026-07-
|
|
98191
|
-
var LATEST_PR =
|
|
99073
|
+
var VERSION2 = "0.19.31";
|
|
99074
|
+
var COMMIT_SHA = "d24ee3cc";
|
|
99075
|
+
var COMMIT_DATE = "2026-07-28T23:06:42Z";
|
|
99076
|
+
var LATEST_PR = 3961;
|
|
98192
99077
|
var COMMITS_AHEAD_OF_TAG = 0;
|
|
98193
99078
|
|
|
98194
99079
|
// gateway/boot-version.ts
|
|
@@ -98266,11 +99151,11 @@ init_peercred();
|
|
|
98266
99151
|
import * as net5 from "node:net";
|
|
98267
99152
|
import * as fs3 from "node:fs";
|
|
98268
99153
|
import { homedir as homedir18 } from "node:os";
|
|
98269
|
-
import { join as
|
|
99154
|
+
import { join as join66 } from "node:path";
|
|
98270
99155
|
var DEFAULT_TIMEOUT_MS4 = 2000;
|
|
98271
99156
|
var UNLOCK_TIMEOUT_MS = 30000;
|
|
98272
|
-
var LEGACY_SOCKET_PATH2 =
|
|
98273
|
-
var OPERATOR_SOCKET_PATH2 =
|
|
99157
|
+
var LEGACY_SOCKET_PATH2 = join66(homedir18(), ".switchroom", "vault-broker.sock");
|
|
99158
|
+
var OPERATOR_SOCKET_PATH2 = join66(homedir18(), ".switchroom", "broker-operator", "sock");
|
|
98274
99159
|
function defaultBrokerSocketPath2() {
|
|
98275
99160
|
if (fs3.existsSync(OPERATOR_SOCKET_PATH2))
|
|
98276
99161
|
return OPERATOR_SOCKET_PATH2;
|
|
@@ -98871,8 +99756,8 @@ async function createLinearIssue(args, deps = {}) {
|
|
|
98871
99756
|
}
|
|
98872
99757
|
teamId = nodes[0].id;
|
|
98873
99758
|
}
|
|
98874
|
-
const
|
|
98875
|
-
const input = { teamId, title, description };
|
|
99759
|
+
const description2 = dedupKey ? `${body}${captureDedupMarker(dedupKey)}` : body;
|
|
99760
|
+
const input = { teamId, title, description: description2 };
|
|
98876
99761
|
if (priority !== undefined)
|
|
98877
99762
|
input.priority = priority;
|
|
98878
99763
|
const create = await gql("mutation($input: IssueCreateInput!) { issueCreate(input: $input) { success issue { id identifier url } } }", { input });
|
|
@@ -99152,8 +100037,8 @@ function resolveVaultApprovalPosture(broker) {
|
|
|
99152
100037
|
}
|
|
99153
100038
|
|
|
99154
100039
|
// registry/turns-schema.ts
|
|
99155
|
-
import { chmodSync as chmodSync12, mkdirSync as
|
|
99156
|
-
import { join as
|
|
100040
|
+
import { chmodSync as chmodSync12, mkdirSync as mkdirSync49 } from "fs";
|
|
100041
|
+
import { join as join67 } from "path";
|
|
99157
100042
|
var DatabaseClass3 = null;
|
|
99158
100043
|
function loadDatabaseClass3() {
|
|
99159
100044
|
if (DatabaseClass3 != null)
|
|
@@ -99210,7 +100095,7 @@ var PHASE4_MIGRATIONS = [
|
|
|
99210
100095
|
];
|
|
99211
100096
|
function applySchema(db3) {
|
|
99212
100097
|
db3.exec("PRAGMA journal_mode = WAL");
|
|
99213
|
-
db3.exec("PRAGMA synchronous =
|
|
100098
|
+
db3.exec("PRAGMA synchronous = FULL");
|
|
99214
100099
|
db3.exec("PRAGMA busy_timeout = 5000");
|
|
99215
100100
|
db3.exec(SCHEMA_SQL);
|
|
99216
100101
|
for (const sql of [...PHASE1_MIGRATIONS, ...PHASE2_MIGRATIONS, ...PHASE3_MIGRATIONS, ...PHASE4_MIGRATIONS]) {
|
|
@@ -99225,9 +100110,9 @@ function applySchema(db3) {
|
|
|
99225
100110
|
}
|
|
99226
100111
|
function openTurnsDb(agentDir) {
|
|
99227
100112
|
const Database = loadDatabaseClass3();
|
|
99228
|
-
const dir =
|
|
99229
|
-
|
|
99230
|
-
const path3 =
|
|
100113
|
+
const dir = join67(agentDir, "telegram");
|
|
100114
|
+
mkdirSync49(dir, { recursive: true, mode: 448 });
|
|
100115
|
+
const path3 = join67(dir, "registry.db");
|
|
99231
100116
|
const db3 = new Database(path3, { create: true });
|
|
99232
100117
|
applySchema(db3);
|
|
99233
100118
|
try {
|
|
@@ -99572,7 +100457,7 @@ function selectResumeBuilder(endedVia, opts) {
|
|
|
99572
100457
|
}
|
|
99573
100458
|
|
|
99574
100459
|
// gateway/bridge-dead-watchdog.ts
|
|
99575
|
-
import { readFileSync as
|
|
100460
|
+
import { readFileSync as readFileSync58, writeFileSync as writeFileSync48, renameSync as renameSync26, unlinkSync as unlinkSync28 } from "node:fs";
|
|
99576
100461
|
|
|
99577
100462
|
// gateway/cron-session.ts
|
|
99578
100463
|
var CRON_IDENTITY_SUFFIX2 = "-cron";
|
|
@@ -99605,7 +100490,7 @@ function readFreshCrashLogTail(path3, opts = {}) {
|
|
|
99605
100490
|
const nowMs3 = opts.nowMs ?? Date.now();
|
|
99606
100491
|
const freshWindowMs = opts.freshWindowMs ?? CRASH_LOG_FRESH_WINDOW_MS;
|
|
99607
100492
|
const maxLines = opts.maxLines ?? CRASH_LOG_TAIL_LINES;
|
|
99608
|
-
const readFile = opts.readFile ?? ((p) =>
|
|
100493
|
+
const readFile = opts.readFile ?? ((p) => readFileSync58(p, "utf8"));
|
|
99609
100494
|
let raw;
|
|
99610
100495
|
try {
|
|
99611
100496
|
raw = readFile(path3);
|
|
@@ -99626,13 +100511,13 @@ function readFreshCrashLogTail(path3, opts = {}) {
|
|
|
99626
100511
|
}
|
|
99627
100512
|
function writeBridgeDeadEscalationMarker(path3, marker) {
|
|
99628
100513
|
const tmp = `${path3}.tmp-${process.pid}-${Date.now()}`;
|
|
99629
|
-
|
|
99630
|
-
|
|
100514
|
+
writeFileSync48(tmp, JSON.stringify(marker), "utf8");
|
|
100515
|
+
renameSync26(tmp, path3);
|
|
99631
100516
|
}
|
|
99632
100517
|
function consumeBridgeDeadEscalationMarker(path3, nowMs3 = Date.now(), maxAgeMs = ESCALATION_MARKER_MAX_AGE_MS) {
|
|
99633
100518
|
let marker = null;
|
|
99634
100519
|
try {
|
|
99635
|
-
const parsed = JSON.parse(
|
|
100520
|
+
const parsed = JSON.parse(readFileSync58(path3, "utf8"));
|
|
99636
100521
|
if (typeof parsed.ts === "number" && Number.isFinite(parsed.ts) && typeof parsed.reason === "string") {
|
|
99637
100522
|
const age = nowMs3 - parsed.ts;
|
|
99638
100523
|
if (age >= 0 && age < maxAgeMs) {
|
|
@@ -99644,7 +100529,7 @@ function consumeBridgeDeadEscalationMarker(path3, nowMs3 = Date.now(), maxAgeMs
|
|
|
99644
100529
|
}
|
|
99645
100530
|
} catch {}
|
|
99646
100531
|
try {
|
|
99647
|
-
|
|
100532
|
+
unlinkSync28(path3);
|
|
99648
100533
|
} catch {}
|
|
99649
100534
|
return marker;
|
|
99650
100535
|
}
|
|
@@ -99785,7 +100670,7 @@ function createBridgeDeadWatchdog(opts) {
|
|
|
99785
100670
|
}
|
|
99786
100671
|
|
|
99787
100672
|
// gateway/boot-probes.ts
|
|
99788
|
-
import { readFileSync as
|
|
100673
|
+
import { readFileSync as readFileSync59, readdirSync as readdirSync14, existsSync as existsSync55 } from "fs";
|
|
99789
100674
|
init_quota_cache();
|
|
99790
100675
|
init_generation_stamp();
|
|
99791
100676
|
init_quota_check();
|
|
@@ -99794,7 +100679,7 @@ import { promisify as promisify2 } from "util";
|
|
|
99794
100679
|
var execFile2 = promisify2(execFileCb2);
|
|
99795
100680
|
var realProcFs2 = {
|
|
99796
100681
|
readdir: (p) => readdirSync14(p),
|
|
99797
|
-
readFile: (p) =>
|
|
100682
|
+
readFile: (p) => readFileSync59(p, "utf-8")
|
|
99798
100683
|
};
|
|
99799
100684
|
function findAgentProcessInContainer2(fs4 = realProcFs2) {
|
|
99800
100685
|
let entries;
|
|
@@ -100044,7 +100929,7 @@ if (isGatewayMain) {
|
|
|
100044
100929
|
shutdownAnalytics();
|
|
100045
100930
|
});
|
|
100046
100931
|
}
|
|
100047
|
-
var STATE_DIR = process.env.TELEGRAM_STATE_DIR ??
|
|
100932
|
+
var STATE_DIR = process.env.TELEGRAM_STATE_DIR ?? join68(homedir19(), ".claude", "channels", "telegram");
|
|
100048
100933
|
var permCardStore = createPermissionCardStore(STATE_DIR);
|
|
100049
100934
|
var BLOCKED_APPROVALS_DIR = process.env.SWITCHROOM_BLOCKED_APPROVALS_DIR ?? "/state/blocked-approvals";
|
|
100050
100935
|
var AGENT_NAME = process.env.SWITCHROOM_AGENT_NAME ?? "agent";
|
|
@@ -100083,7 +100968,7 @@ function alwaysAllowDrainDeps() {
|
|
|
100083
100968
|
return {
|
|
100084
100969
|
readConfigText: () => {
|
|
100085
100970
|
const cfgPath = process.env.SWITCHROOM_CONFIG ?? SWITCHROOM_CONFIG ?? findConfigFile2();
|
|
100086
|
-
return
|
|
100971
|
+
return readFileSync60(cfgPath, "utf8");
|
|
100087
100972
|
},
|
|
100088
100973
|
resolveAllowList: (_configText, agentName3) => {
|
|
100089
100974
|
const cfg = loadConfig2();
|
|
@@ -100144,11 +101029,11 @@ function scheduleAlwaysAllowPersistDrain() {
|
|
|
100144
101029
|
}, ALWAYS_ALLOW_DRAIN_INTERVAL_MS);
|
|
100145
101030
|
timer3.unref?.();
|
|
100146
101031
|
}
|
|
100147
|
-
var ACCESS_FILE =
|
|
100148
|
-
var APPROVED_DIR =
|
|
100149
|
-
var ENV_FILE =
|
|
100150
|
-
var INBOX_DIR =
|
|
100151
|
-
var PEOPLE_FILE =
|
|
101032
|
+
var ACCESS_FILE = join68(STATE_DIR, "access.json");
|
|
101033
|
+
var APPROVED_DIR = join68(STATE_DIR, "approved");
|
|
101034
|
+
var ENV_FILE = join68(STATE_DIR, ".env");
|
|
101035
|
+
var INBOX_DIR = join68(STATE_DIR, "inbox");
|
|
101036
|
+
var PEOPLE_FILE = join68(STATE_DIR, "people.json");
|
|
100152
101037
|
function triggerSelfRestart(targetAgent, reason, delayMs = 300) {
|
|
100153
101038
|
const isDocker = process.env.SWITCHROOM_RUNTIME === "docker";
|
|
100154
101039
|
const selfAgent = process.env.SWITCHROOM_AGENT_NAME;
|
|
@@ -100213,7 +101098,7 @@ function formatBootVersion() {
|
|
|
100213
101098
|
}
|
|
100214
101099
|
try {
|
|
100215
101100
|
chmodSync14(ENV_FILE, 384);
|
|
100216
|
-
for (const line of
|
|
101101
|
+
for (const line of readFileSync60(ENV_FILE, "utf8").split(`
|
|
100217
101102
|
`)) {
|
|
100218
101103
|
const m = line.match(/^(\w+)=(.*)$/);
|
|
100219
101104
|
if (m && process.env[m[1]] === undefined)
|
|
@@ -100234,7 +101119,7 @@ var bot;
|
|
|
100234
101119
|
var lastGetUpdatesHeartbeatMs = Date.now();
|
|
100235
101120
|
var GRAMMY_VERSION = (() => {
|
|
100236
101121
|
try {
|
|
100237
|
-
const raw =
|
|
101122
|
+
const raw = readFileSync60(new URL("../../node_modules/grammy/package.json", import.meta.url), "utf8");
|
|
100238
101123
|
return JSON.parse(raw).version ?? "unknown";
|
|
100239
101124
|
} catch {
|
|
100240
101125
|
return "unknown";
|
|
@@ -100297,7 +101182,7 @@ function assertSendable(f) {
|
|
|
100297
101182
|
} catch {
|
|
100298
101183
|
throw new Error(`refusing to send file \u2014 cannot resolve real path: ${f}`);
|
|
100299
101184
|
}
|
|
100300
|
-
const inbox =
|
|
101185
|
+
const inbox = join68(stateReal, "inbox");
|
|
100301
101186
|
if (real.startsWith(stateReal + sep4) && !real.startsWith(inbox + sep4)) {
|
|
100302
101187
|
throw new Error(`refusing to send channel state: ${f}`);
|
|
100303
101188
|
}
|
|
@@ -100316,7 +101201,7 @@ function assertSendable(f) {
|
|
|
100316
101201
|
}
|
|
100317
101202
|
function readAccessFile() {
|
|
100318
101203
|
try {
|
|
100319
|
-
const raw =
|
|
101204
|
+
const raw = readFileSync60(ACCESS_FILE, "utf8");
|
|
100320
101205
|
const parsed = JSON.parse(raw);
|
|
100321
101206
|
const allowFrom = validateStringArray("allowFrom", parsed.allowFrom ?? []);
|
|
100322
101207
|
const groups = {};
|
|
@@ -100356,7 +101241,7 @@ function readAccessFile() {
|
|
|
100356
101241
|
if (err.code === "ENOENT")
|
|
100357
101242
|
return defaultAccess();
|
|
100358
101243
|
try {
|
|
100359
|
-
|
|
101244
|
+
renameSync27(ACCESS_FILE, `${ACCESS_FILE}.corrupt-${Date.now()}`);
|
|
100360
101245
|
} catch {}
|
|
100361
101246
|
process.stderr.write(`telegram gateway: access.json is corrupt, moved aside. Starting fresh.
|
|
100362
101247
|
`);
|
|
@@ -100378,7 +101263,7 @@ function loadAccess() {
|
|
|
100378
101263
|
}
|
|
100379
101264
|
function readPeopleFile() {
|
|
100380
101265
|
try {
|
|
100381
|
-
const raw =
|
|
101266
|
+
const raw = readFileSync60(PEOPLE_FILE, "utf8");
|
|
100382
101267
|
const parsed = JSON.parse(raw);
|
|
100383
101268
|
if (!Array.isArray(parsed.entries))
|
|
100384
101269
|
return [];
|
|
@@ -100400,11 +101285,11 @@ function assertAllowedChat(chat_id) {
|
|
|
100400
101285
|
function saveAccess(a) {
|
|
100401
101286
|
if (STATIC)
|
|
100402
101287
|
return;
|
|
100403
|
-
|
|
101288
|
+
mkdirSync51(STATE_DIR, { recursive: true, mode: 448 });
|
|
100404
101289
|
const tmp = ACCESS_FILE + ".tmp";
|
|
100405
|
-
|
|
101290
|
+
writeFileSync50(tmp, JSON.stringify(a, null, 2) + `
|
|
100406
101291
|
`, { mode: 384 });
|
|
100407
|
-
|
|
101292
|
+
renameSync27(tmp, ACCESS_FILE);
|
|
100408
101293
|
}
|
|
100409
101294
|
function pruneExpired(a) {
|
|
100410
101295
|
const now = Date.now();
|
|
@@ -100422,7 +101307,7 @@ var HISTORY_ENABLED = HISTORY_ACCESS.historyEnabled !== false;
|
|
|
100422
101307
|
if (isGatewayMain && HISTORY_ENABLED) {
|
|
100423
101308
|
try {
|
|
100424
101309
|
initHistory(STATE_DIR, HISTORY_ACCESS.historyRetentionDays ?? 30);
|
|
100425
|
-
process.stderr.write(`telegram gateway: history capture enabled at ${
|
|
101310
|
+
process.stderr.write(`telegram gateway: history capture enabled at ${join68(STATE_DIR, "history.db")}
|
|
100426
101311
|
`);
|
|
100427
101312
|
} catch (err) {
|
|
100428
101313
|
process.stderr.write(`telegram gateway: history init failed (${err.message}) \u2014 capture disabled
|
|
@@ -100441,12 +101326,12 @@ if (isGatewayMain)
|
|
|
100441
101326
|
let markerTurnKey = null;
|
|
100442
101327
|
let markerAgeMs = null;
|
|
100443
101328
|
try {
|
|
100444
|
-
const markerPath =
|
|
101329
|
+
const markerPath = join68(STATE_DIR, TURN_ACTIVE_MARKER_FILE2);
|
|
100445
101330
|
if (existsSync57(markerPath)) {
|
|
100446
101331
|
const st = statSync22(markerPath);
|
|
100447
101332
|
markerAgeMs = Date.now() - st.mtimeMs;
|
|
100448
101333
|
try {
|
|
100449
|
-
const payload = JSON.parse(
|
|
101334
|
+
const payload = JSON.parse(readFileSync60(markerPath, "utf8"));
|
|
100450
101335
|
if (typeof payload.turnKey === "string" && payload.turnKey.length > 0) {
|
|
100451
101336
|
markerTurnKey = payload.turnKey;
|
|
100452
101337
|
}
|
|
@@ -100466,10 +101351,10 @@ if (isGatewayMain)
|
|
|
100466
101351
|
process.stderr.write(`telegram gateway: turn-registry boot-reaper stamped ${reaped} orphaned turn(s)` + `${timeoutTurnKey ? ` (turnKey=${timeoutTurnKey} as 'timeout', markerAgeMs=${markerAgeMs})` : " as 'restart'"}
|
|
100467
101352
|
`);
|
|
100468
101353
|
} else {
|
|
100469
|
-
process.stderr.write(`telegram gateway: turn-registry initialized at ${
|
|
101354
|
+
process.stderr.write(`telegram gateway: turn-registry initialized at ${join68(agentDir, "telegram", "registry.db")}
|
|
100470
101355
|
`);
|
|
100471
101356
|
}
|
|
100472
|
-
const bridgeDeadMarker = consumeBridgeDeadEscalationMarker(
|
|
101357
|
+
const bridgeDeadMarker = consumeBridgeDeadEscalationMarker(join68(STATE_DIR, "bridge-dead-escalation.json"));
|
|
100473
101358
|
if (bridgeDeadMarker != null) {
|
|
100474
101359
|
bridgeDeadPriorStreak = bridgeDeadMarker.count ?? 1;
|
|
100475
101360
|
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 +101367,7 @@ if (isGatewayMain)
|
|
|
100482
101367
|
const pending2 = findLatestTurnIfInterrupted(turnsDb);
|
|
100483
101368
|
const selfAgent = process.env.SWITCHROOM_AGENT_NAME ?? "";
|
|
100484
101369
|
if (pending2 != null && selfAgent) {
|
|
100485
|
-
const bootResumeMarkerPath = process.env.SWITCHROOM_GATEWAY_CLEAN_SHUTDOWN_MARKER ??
|
|
101370
|
+
const bootResumeMarkerPath = process.env.SWITCHROOM_GATEWAY_CLEAN_SHUTDOWN_MARKER ?? join68(STATE_DIR, "clean-shutdown.json");
|
|
100486
101371
|
const bootResumeCleanMarker = readCleanShutdownMarker(bootResumeMarkerPath);
|
|
100487
101372
|
const bootResumeForceAlways = process.env.SWITCHROOM_BOOT_RESUME_ALWAYS === "1";
|
|
100488
101373
|
const bootResumeMode = parseBootResumeMode(process.env.SWITCHROOM_BOOT_RESUME);
|
|
@@ -100595,7 +101480,7 @@ if (isGatewayMain)
|
|
|
100595
101480
|
`);
|
|
100596
101481
|
}
|
|
100597
101482
|
}
|
|
100598
|
-
const pendingEnvPath =
|
|
101483
|
+
const pendingEnvPath = join68(agentDir, ".pending-turn.env");
|
|
100599
101484
|
try {
|
|
100600
101485
|
if (pending2 != null) {
|
|
100601
101486
|
const lines = [
|
|
@@ -100609,14 +101494,14 @@ if (isGatewayMain)
|
|
|
100609
101494
|
pending2.interrupt_reason != null ? `SWITCHROOM_PENDING_INTERRUPT_REASON=${pending2.interrupt_reason}` : `SWITCHROOM_PENDING_INTERRUPT_REASON=`
|
|
100610
101495
|
];
|
|
100611
101496
|
const pendingEnvTmp = `${pendingEnvPath}.tmp-${process.pid}`;
|
|
100612
|
-
|
|
101497
|
+
writeFileSync50(pendingEnvTmp, lines.join(`
|
|
100613
101498
|
`) + `
|
|
100614
101499
|
`, { mode: 384 });
|
|
100615
|
-
|
|
101500
|
+
renameSync27(pendingEnvTmp, pendingEnvPath);
|
|
100616
101501
|
process.stderr.write(`telegram gateway: pending-turn env written to ${pendingEnvPath} turnKey=${pending2.turn_key} endedVia=${pending2.ended_via ?? "open"}
|
|
100617
101502
|
`);
|
|
100618
101503
|
} else if (existsSync57(pendingEnvPath)) {
|
|
100619
|
-
|
|
101504
|
+
rmSync8(pendingEnvPath, { force: true });
|
|
100620
101505
|
process.stderr.write(`telegram gateway: pending-turn env cleared (clean previous shutdown)
|
|
100621
101506
|
`);
|
|
100622
101507
|
}
|
|
@@ -100723,16 +101608,16 @@ function checkApprovals() {
|
|
|
100723
101608
|
return;
|
|
100724
101609
|
}
|
|
100725
101610
|
for (const senderId of files) {
|
|
100726
|
-
const file =
|
|
100727
|
-
bot.api.sendMessage(senderId, "Paired! Say hi to Claude.").then(() =>
|
|
101611
|
+
const file = join68(APPROVED_DIR, senderId);
|
|
101612
|
+
bot.api.sendMessage(senderId, "Paired! Say hi to Claude.").then(() => rmSync8(file, { force: true }), (err) => {
|
|
100728
101613
|
process.stderr.write(`telegram gateway: failed to send approval confirm: ${err}
|
|
100729
101614
|
`);
|
|
100730
|
-
|
|
101615
|
+
rmSync8(file, { force: true });
|
|
100731
101616
|
});
|
|
100732
101617
|
}
|
|
100733
101618
|
}
|
|
100734
101619
|
if (isGatewayMain && !STATIC)
|
|
100735
|
-
setInterval(checkApprovals, 5000).unref();
|
|
101620
|
+
setInterval(attachBootBeacon(STATE_DIR, checkApprovals), 5000).unref();
|
|
100736
101621
|
if (isGatewayMain && !STATIC)
|
|
100737
101622
|
startGatewayHeartbeat(STATE_DIR);
|
|
100738
101623
|
var IDLE_CLEAR_CHECK_MS = Number(process.env.SWITCHROOM_IDLE_CLEAR_CHECK_MS ?? 60000);
|
|
@@ -100897,12 +101782,14 @@ function noteAgentOutputAt(key, ts) {
|
|
|
100897
101782
|
lastAgentOutputAt.delete(oldest);
|
|
100898
101783
|
}
|
|
100899
101784
|
}
|
|
100900
|
-
var OBLIGATION_STORE_PATH =
|
|
101785
|
+
var OBLIGATION_STORE_PATH = join68(STATE_DIR, "obligations.json");
|
|
100901
101786
|
var obligationStoreFs = {
|
|
100902
|
-
readFileSync: (p) =>
|
|
100903
|
-
writeFileSync: (p, d) =>
|
|
100904
|
-
renameSync: (a, b) =>
|
|
100905
|
-
existsSync: (p) => existsSync57(p)
|
|
101787
|
+
readFileSync: (p) => readFileSync60(p, "utf8"),
|
|
101788
|
+
writeFileSync: (p, d) => writeFileSync50(p, d),
|
|
101789
|
+
renameSync: (a, b) => renameSync27(a, b),
|
|
101790
|
+
existsSync: (p) => existsSync57(p),
|
|
101791
|
+
fsyncFileSync: fsyncPathSync,
|
|
101792
|
+
fsyncDirSync: fsyncPathSync
|
|
100906
101793
|
};
|
|
100907
101794
|
var obligationLedger = new ObligationLedger(OBLIGATION_REPRESENT_MAX, {
|
|
100908
101795
|
onChange: STATIC || !OBLIGATION_LEDGER_ENABLED ? undefined : (snapshot) => persistObligations(OBLIGATION_STORE_PATH, obligationStoreFs, snapshot)
|
|
@@ -101677,7 +102564,7 @@ function emitTurnRecord(turn, endedAt) {
|
|
|
101677
102564
|
return;
|
|
101678
102565
|
}
|
|
101679
102566
|
},
|
|
101680
|
-
rename: (from, to) =>
|
|
102567
|
+
rename: (from, to) => renameSync27(from, to)
|
|
101681
102568
|
});
|
|
101682
102569
|
appendFileSync9(turnsPath, rec);
|
|
101683
102570
|
} catch {}
|
|
@@ -102225,7 +103112,7 @@ function maybePostMissedApprovalDigest(reason) {
|
|
|
102225
103112
|
const first = entries[0];
|
|
102226
103113
|
const chatId = first.chatId;
|
|
102227
103114
|
const threadId = first.threadId ?? undefined;
|
|
102228
|
-
const digestId =
|
|
103115
|
+
const digestId = randomBytes13(4).toString("hex");
|
|
102229
103116
|
const text5 = renderMissedApprovalsDigest(entries, {
|
|
102230
103117
|
agentName: process.env.SWITCHROOM_AGENT_NAME ?? null
|
|
102231
103118
|
});
|
|
@@ -103240,27 +104127,27 @@ var PIN_STATUS_WHILE_WORKING = (() => {
|
|
|
103240
104127
|
})();
|
|
103241
104128
|
var statusPinClaims = new Map;
|
|
103242
104129
|
var statusPinRightsCache = new PinRightsCache2;
|
|
103243
|
-
var STATUS_PIN_STORE_PATH =
|
|
104130
|
+
var STATUS_PIN_STORE_PATH = join68(STATE_DIR, "status-pins.json");
|
|
103244
104131
|
var statusPinStoreFs = {
|
|
103245
|
-
readFileSync: (p) =>
|
|
103246
|
-
writeFileSync: (p, d) =>
|
|
103247
|
-
renameSync: (a, b) =>
|
|
104132
|
+
readFileSync: (p) => readFileSync60(p, "utf8"),
|
|
104133
|
+
writeFileSync: (p, d) => writeFileSync50(p, d),
|
|
104134
|
+
renameSync: (a, b) => renameSync27(a, b),
|
|
103248
104135
|
existsSync: (p) => existsSync57(p)
|
|
103249
104136
|
};
|
|
103250
104137
|
var statusPinPersistEnabled = !STATIC && PIN_STATUS_WHILE_WORKING;
|
|
103251
|
-
var ACTIVITY_CARD_STORE_PATH =
|
|
104138
|
+
var ACTIVITY_CARD_STORE_PATH = join68(STATE_DIR, "activity-cards-pending.json");
|
|
103252
104139
|
var activityCardStoreFs = {
|
|
103253
|
-
readFileSync: (p) =>
|
|
103254
|
-
writeFileSync: (p, d) =>
|
|
103255
|
-
renameSync: (a, b) =>
|
|
104140
|
+
readFileSync: (p) => readFileSync60(p, "utf8"),
|
|
104141
|
+
writeFileSync: (p, d) => writeFileSync50(p, d),
|
|
104142
|
+
renameSync: (a, b) => renameSync27(a, b),
|
|
103256
104143
|
existsSync: (p) => existsSync57(p)
|
|
103257
104144
|
};
|
|
103258
104145
|
var activityCardPersistEnabled = !STATIC;
|
|
103259
|
-
var QUEUED_CARD_STORE_PATH =
|
|
104146
|
+
var QUEUED_CARD_STORE_PATH = join68(STATE_DIR, "queued-cards-pending.json");
|
|
103260
104147
|
var queuedCardStoreFs = {
|
|
103261
|
-
readFileSync: (p) =>
|
|
103262
|
-
writeFileSync: (p, d) =>
|
|
103263
|
-
renameSync: (a, b) =>
|
|
104148
|
+
readFileSync: (p) => readFileSync60(p, "utf8"),
|
|
104149
|
+
writeFileSync: (p, d) => writeFileSync50(p, d),
|
|
104150
|
+
renameSync: (a, b) => renameSync27(a, b),
|
|
103264
104151
|
existsSync: (p) => existsSync57(p)
|
|
103265
104152
|
};
|
|
103266
104153
|
var queuedCardPersistEnabled = !STATIC;
|
|
@@ -103499,16 +104386,16 @@ var midSessionCardReaper = isGatewayMain ? setInterval(() => {
|
|
|
103499
104386
|
midSessionReaperGuard.tick();
|
|
103500
104387
|
}, MID_SESSION_CARD_REAPER_INTERVAL_MS) : undefined;
|
|
103501
104388
|
midSessionCardReaper?.unref();
|
|
103502
|
-
async function reconcileStatusPin(pinKey, chatId, desired) {
|
|
104389
|
+
async function reconcileStatusPin(pinKey, chatId, desired, threadId) {
|
|
103503
104390
|
try {
|
|
103504
|
-
await withPinReconcileLock(pinKey, () => reconcileStatusPinInner(pinKey, chatId, desired));
|
|
104391
|
+
await withPinReconcileLock(pinKey, () => reconcileStatusPinInner(pinKey, chatId, desired, threadId));
|
|
103505
104392
|
} catch (err) {
|
|
103506
104393
|
const msg = err instanceof Error ? err.message : String(err);
|
|
103507
104394
|
process.stderr.write(`telegram gateway: status-pin reconcile absorbed error (key=${pinKey} chat=${chatId}): ${msg}
|
|
103508
104395
|
`);
|
|
103509
104396
|
}
|
|
103510
104397
|
}
|
|
103511
|
-
async function reconcileStatusPinInner(pinKey, chatId, desired) {
|
|
104398
|
+
async function reconcileStatusPinInner(pinKey, chatId, desired, threadId) {
|
|
103512
104399
|
if (!PIN_STATUS_WHILE_WORKING)
|
|
103513
104400
|
return;
|
|
103514
104401
|
if (chatId.length === 0)
|
|
@@ -103534,6 +104421,7 @@ async function reconcileStatusPinInner(pinKey, chatId, desired) {
|
|
|
103534
104421
|
await runStatusPinReconcile({
|
|
103535
104422
|
pinKey,
|
|
103536
104423
|
chatId,
|
|
104424
|
+
threadId,
|
|
103537
104425
|
prev,
|
|
103538
104426
|
desired,
|
|
103539
104427
|
persist: statusPinPersistEnabled ? { path: STATUS_PIN_STORE_PATH, fs: statusPinStoreFs } : null,
|
|
@@ -103546,37 +104434,26 @@ async function unpinAllStatusPins() {
|
|
|
103546
104434
|
await reconcileStatusPin(key, claim.chatId, { pinned: false });
|
|
103547
104435
|
}
|
|
103548
104436
|
}
|
|
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
|
-
}
|
|
104437
|
+
var stalePinSweepEligible = false;
|
|
104438
|
+
var STALE_PIN_SWEEP_STORE_PATH = join68(STATE_DIR, "stale-pin-sweep.json");
|
|
104439
|
+
var stalePinSweeper = createGatewayStalePinSweeper({
|
|
104440
|
+
telegram: { handle: () => lockedBot, call: robustApiCall },
|
|
104441
|
+
claims: () => statusPinClaims.values(),
|
|
104442
|
+
loadPinRows: () => statusPinPersistEnabled || bannerPinPersistEnabled || toolPinPersistEnabled ? loadStatusPins2(STATUS_PIN_STORE_PATH, statusPinStoreFs) : [],
|
|
104443
|
+
eligible: () => stalePinSweepEligible,
|
|
104444
|
+
store: {
|
|
104445
|
+
path: STALE_PIN_SWEEP_STORE_PATH,
|
|
104446
|
+
fs: {
|
|
104447
|
+
readFileSync: (p) => readFileSync60(p, "utf-8"),
|
|
104448
|
+
writeFileSync: (p, data) => atomicWriteFileSync(p, data, 384),
|
|
104449
|
+
existsSync: (p) => existsSync57(p)
|
|
103571
104450
|
}
|
|
103572
|
-
return ids;
|
|
103573
104451
|
},
|
|
103574
|
-
|
|
103575
|
-
log: (line) => process.stderr.write(line)
|
|
104452
|
+
allowUnpinAllForumTopic: process.env.SWITCHROOM_PIN_SWEEP_UNPIN_ALL_TOPIC == null ? undefined : process.env.SWITCHROOM_PIN_SWEEP_UNPIN_ALL_TOPIC === "1"
|
|
103576
104453
|
});
|
|
103577
|
-
function
|
|
104454
|
+
function runBootPinCleanupAndStalePinSweep() {
|
|
103578
104455
|
return runBootPinSweepSteps({
|
|
103579
|
-
|
|
104456
|
+
scanSweepTargets: () => collectSweepTargets({
|
|
103580
104457
|
statusPins: statusPinPersistEnabled || bannerPinPersistEnabled || toolPinPersistEnabled ? loadStatusPins2(STATUS_PIN_STORE_PATH, statusPinStoreFs) : [],
|
|
103581
104458
|
activityCards: activityCardPersistEnabled ? loadActivityCards2(ACTIVITY_CARD_STORE_PATH, activityCardStoreFs) : [],
|
|
103582
104459
|
queuedCards: queuedCardPersistEnabled ? loadQueuedCards(QUEUED_CARD_STORE_PATH, queuedCardStoreFs) : []
|
|
@@ -103584,14 +104461,14 @@ function runBootPinCleanupAndDmSweep() {
|
|
|
103584
104461
|
statusPinCleanup: statusPinBootCleanup,
|
|
103585
104462
|
activityCardReaper: activityCardBootReaper,
|
|
103586
104463
|
queuedCardReaper: queuedCardBootReaper,
|
|
103587
|
-
|
|
103588
|
-
|
|
104464
|
+
enableSweep: () => {
|
|
104465
|
+
stalePinSweepEligible = true;
|
|
103589
104466
|
},
|
|
103590
|
-
|
|
104467
|
+
sweepTarget: (t) => stalePinSweeper.sweepTarget(t),
|
|
103591
104468
|
log: (line) => process.stderr.write(line)
|
|
103592
104469
|
});
|
|
103593
104470
|
}
|
|
103594
|
-
var bootPinSweepGate = createBootSweepGate({ run:
|
|
104471
|
+
var bootPinSweepGate = createBootSweepGate({ run: runBootPinCleanupAndStalePinSweep, onError: (err) => process.stderr.write(`telegram gateway: boot pin cleanup / stale-pin sweep failed: ${err.message}
|
|
103595
104472
|
`) });
|
|
103596
104473
|
var progressDriver = null;
|
|
103597
104474
|
var unpinProgressCardForChat = null;
|
|
@@ -103599,12 +104476,12 @@ var getPinnedProgressCardMessageId = null;
|
|
|
103599
104476
|
var completeProgressCardTurn = null;
|
|
103600
104477
|
var subagentWatcher = null;
|
|
103601
104478
|
var workerActivityFeed = null;
|
|
103602
|
-
var SOCKET_PATH = process.env.SWITCHROOM_GATEWAY_SOCKET ??
|
|
104479
|
+
var SOCKET_PATH = process.env.SWITCHROOM_GATEWAY_SOCKET ?? join68(STATE_DIR, "gateway.sock");
|
|
103603
104480
|
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 ??
|
|
104481
|
+
mkdirSync51(STATE_DIR, { recursive: true, mode: 448 });
|
|
104482
|
+
var GATEWAY_PID_PATH = process.env.SWITCHROOM_GATEWAY_PID_FILE ?? join68(STATE_DIR, "gateway.pid.json");
|
|
104483
|
+
var GATEWAY_SESSION_MARKER_PATH = process.env.SWITCHROOM_GATEWAY_SESSION_MARKER ?? join68(STATE_DIR, "gateway-session.json");
|
|
104484
|
+
var GATEWAY_CLEAN_SHUTDOWN_MARKER_PATH = process.env.SWITCHROOM_GATEWAY_CLEAN_SHUTDOWN_MARKER ?? join68(STATE_DIR, "clean-shutdown.json");
|
|
103608
104485
|
var GATEWAY_STARTED_AT_MS = Date.now();
|
|
103609
104486
|
var BOOT_CARD_ENABLED = process.env.SWITCHROOM_BOOT_CARD !== "false";
|
|
103610
104487
|
var activeBootCard = null;
|
|
@@ -103633,7 +104510,7 @@ function ensureIssuesCard(chatId, threadId) {
|
|
|
103633
104510
|
bot: botApi,
|
|
103634
104511
|
log: (msg) => process.stderr.write(`telegram gateway: ${msg}
|
|
103635
104512
|
`),
|
|
103636
|
-
persistPath:
|
|
104513
|
+
persistPath: join68(stateDir, "issues-card.json")
|
|
103637
104514
|
});
|
|
103638
104515
|
activeIssuesWatcher = startIssuesWatcher({
|
|
103639
104516
|
stateDir,
|
|
@@ -103833,14 +104710,16 @@ if (isGatewayMain)
|
|
|
103833
104710
|
var inboundSpool;
|
|
103834
104711
|
if (isGatewayMain)
|
|
103835
104712
|
inboundSpool = STATIC ? undefined : createInboundSpool({
|
|
103836
|
-
path:
|
|
104713
|
+
path: join68(STATE_DIR, "inbound-spool.jsonl"),
|
|
103837
104714
|
fs: {
|
|
103838
104715
|
appendFileSync: (p, d) => appendFileSync9(p, d),
|
|
103839
|
-
readFileSync: (p) =>
|
|
103840
|
-
writeFileSync: (p, d) =>
|
|
103841
|
-
renameSync: (a, b) =>
|
|
104716
|
+
readFileSync: (p) => readFileSync60(p, "utf8"),
|
|
104717
|
+
writeFileSync: (p, d) => writeFileSync50(p, d),
|
|
104718
|
+
renameSync: (a, b) => renameSync27(a, b),
|
|
103842
104719
|
existsSync: (p) => existsSync57(p),
|
|
103843
|
-
statSizeSync: (p) => statSync22(p).size
|
|
104720
|
+
statSizeSync: (p) => statSync22(p).size,
|
|
104721
|
+
fsyncFileSync: fsyncPathSync,
|
|
104722
|
+
fsyncDirSync: fsyncPathSync
|
|
103844
104723
|
},
|
|
103845
104724
|
onDegraded: (info) => {
|
|
103846
104725
|
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 +104780,13 @@ async function maybeRedeliverUndeliveredAnswer() {
|
|
|
103901
104780
|
let transcriptText;
|
|
103902
104781
|
try {
|
|
103903
104782
|
const projectsDir = getProjectsDirForCwd();
|
|
103904
|
-
const path3 =
|
|
104783
|
+
const path3 = join68(projectsDir, `${sessionId}.jsonl`);
|
|
103905
104784
|
if (!existsSync57(path3)) {
|
|
103906
104785
|
process.stderr.write(`telegram gateway: crash-redelivery \u2014 transcript not found for turnKey=${turn.turn_key} session=${sessionId} (${path3}); skipping
|
|
103907
104786
|
`);
|
|
103908
104787
|
return;
|
|
103909
104788
|
}
|
|
103910
|
-
transcriptText =
|
|
104789
|
+
transcriptText = readFileSync60(path3, "utf8");
|
|
103911
104790
|
} catch (err) {
|
|
103912
104791
|
process.stderr.write(`telegram gateway: crash-redelivery \u2014 transcript read failed turnKey=${turn.turn_key}: ${err.message}
|
|
103913
104792
|
`);
|
|
@@ -104024,13 +104903,13 @@ function dispatchPermissionVerdict(ev) {
|
|
|
104024
104903
|
}
|
|
104025
104904
|
}
|
|
104026
104905
|
function rearmPermissionFromStore(msg, persisted) {
|
|
104027
|
-
const { requestId, toolName, description, inputPreview } = msg;
|
|
104906
|
+
const { requestId, toolName, description: description2, inputPreview } = msg;
|
|
104028
104907
|
const startedAt = persisted.reduce((min, c) => c.startedAt < min ? c.startedAt : min, persisted[0].startedAt);
|
|
104029
104908
|
const cardText = persisted[0].cardText;
|
|
104030
104909
|
const cards = persisted.map((c) => ({ chatId: c.chatId, messageId: c.messageId }));
|
|
104031
104910
|
pendingPermissions.set(requestId, {
|
|
104032
104911
|
tool_name: toolName,
|
|
104033
|
-
description,
|
|
104912
|
+
description: description2,
|
|
104034
104913
|
input_preview: inputPreview,
|
|
104035
104914
|
startedAt,
|
|
104036
104915
|
card_text: cardText,
|
|
@@ -104066,8 +104945,8 @@ var bridgeDeadWatchdog = createBridgeDeadWatchdog({
|
|
|
104066
104945
|
isSessionAlive: () => findAgentProcessInContainer2()?.comm === "claude",
|
|
104067
104946
|
isShuttingDown: () => shuttingDown,
|
|
104068
104947
|
escalate: (reason) => triggerSelfRestart(process.env.SWITCHROOM_AGENT_NAME ?? "", reason, 1500),
|
|
104069
|
-
crashLogPath:
|
|
104070
|
-
markerPath:
|
|
104948
|
+
crashLogPath: join68(STATE_DIR, "bridge-crash.log"),
|
|
104949
|
+
markerPath: join68(STATE_DIR, "bridge-dead-escalation.json"),
|
|
104071
104950
|
log: (line) => process.stderr.write(`${line}
|
|
104072
104951
|
`),
|
|
104073
104952
|
priorStreak: bridgeDeadPriorStreak,
|
|
@@ -104173,8 +105052,8 @@ if (isGatewayMain)
|
|
|
104173
105052
|
probeQuotaViaBroker: (t) => probeQuotaForBootCard(agentSlug, t),
|
|
104174
105053
|
tmuxSupervisor: process.env.SWITCHROOM_TMUX_SUPERVISOR === "1",
|
|
104175
105054
|
dockerMode: process.env.SWITCHROOM_RUNTIME === "docker",
|
|
104176
|
-
configSnapshotPath:
|
|
104177
|
-
bootCardStatePath:
|
|
105055
|
+
configSnapshotPath: join68(resolvedAgentDirForCard, ".config-snapshot.json"),
|
|
105056
|
+
bootCardStatePath: join68(resolvedAgentDirForCard, ".boot-card-msgid.json"),
|
|
104178
105057
|
floodStatePath: FLOOD_STATE_PATH,
|
|
104179
105058
|
...updateOutcomeLine ? { updateOutcomeLine } : {}
|
|
104180
105059
|
}, ackMsgId).then((handle) => {
|
|
@@ -104289,7 +105168,7 @@ if (isGatewayMain)
|
|
|
104289
105168
|
}
|
|
104290
105169
|
},
|
|
104291
105170
|
onPermissionRequest(_client, msg) {
|
|
104292
|
-
const { requestId, toolName, description, inputPreview } = msg;
|
|
105171
|
+
const { requestId, toolName, description: description2, inputPreview } = msg;
|
|
104293
105172
|
if (isPermissionRearmEnabled()) {
|
|
104294
105173
|
const persisted = pendingPermissions.has(requestId) ? [] : permCardStore.loadAll().filter((e) => e.requestId === requestId);
|
|
104295
105174
|
const disposition = classifyPermissionRequest({
|
|
@@ -104333,10 +105212,10 @@ if (isGatewayMain)
|
|
|
104333
105212
|
const text5 = formatPermissionCardBody({
|
|
104334
105213
|
toolName,
|
|
104335
105214
|
inputPreview,
|
|
104336
|
-
description,
|
|
105215
|
+
description: description2,
|
|
104337
105216
|
agentName: _client.agentName
|
|
104338
105217
|
});
|
|
104339
|
-
const pendEntry = { tool_name: toolName, description, input_preview: inputPreview, startedAt: Date.now(), card_text: text5, cards: [] };
|
|
105218
|
+
const pendEntry = { tool_name: toolName, description: description2, input_preview: inputPreview, startedAt: Date.now(), card_text: text5, cards: [] };
|
|
104340
105219
|
pendingPermissions.set(requestId, pendEntry);
|
|
104341
105220
|
const activeTurn = currentTurn;
|
|
104342
105221
|
postPermissionCard(requestId, pendEntry);
|
|
@@ -104842,7 +105721,7 @@ if (isGatewayMain)
|
|
|
104842
105721
|
const receiverUid = receiverUidRaw ? Number(receiverUidRaw) : NaN;
|
|
104843
105722
|
if (Number.isInteger(receiverUid))
|
|
104844
105723
|
allowedUids.push(receiverUid);
|
|
104845
|
-
const socketPath =
|
|
105724
|
+
const socketPath = join68(STATE_DIR, "webhook.sock");
|
|
104846
105725
|
const webhookInject = (agentName3, inbound) => {
|
|
104847
105726
|
const msg = inbound;
|
|
104848
105727
|
const delivered = ipcServer.sendToAgent(agentName3, msg);
|
|
@@ -105070,9 +105949,9 @@ function redactOutboundText(text5, site) {
|
|
|
105070
105949
|
var VOICE_OUT_DEFAULT_CHUNK_CHARS = 600;
|
|
105071
105950
|
var VOICE_OUT_HARD_CHUNK_CAP = 4096;
|
|
105072
105951
|
var voiceOnDemandCache = new VoiceOnDemandCache({
|
|
105073
|
-
persistPath:
|
|
105952
|
+
persistPath: join68(STATE_DIR, "voice-ondemand.json")
|
|
105074
105953
|
});
|
|
105075
|
-
var VOICE_CACHE_DIR =
|
|
105954
|
+
var VOICE_CACHE_DIR = join68(STATE_DIR, "voice-cache");
|
|
105076
105955
|
var voicePreSynthQueue = new PreSynthQueue({
|
|
105077
105956
|
runJob: async (job) => {
|
|
105078
105957
|
const sidecarToken = await materializeSidecarToken2();
|
|
@@ -105474,11 +106353,11 @@ async function executeSendGif(rawArgs) {
|
|
|
105474
106353
|
};
|
|
105475
106354
|
}
|
|
105476
106355
|
async function publishToTelegraph(text5, shortName, authorName) {
|
|
105477
|
-
const accountPath =
|
|
106356
|
+
const accountPath = join68(STATE_DIR, "telegraph-account.json");
|
|
105478
106357
|
let account = null;
|
|
105479
106358
|
try {
|
|
105480
106359
|
if (existsSync57(accountPath)) {
|
|
105481
|
-
const raw =
|
|
106360
|
+
const raw = readFileSync60(accountPath, "utf-8");
|
|
105482
106361
|
const parsed = JSON.parse(raw);
|
|
105483
106362
|
if (parsed.shortName && parsed.accessToken) {
|
|
105484
106363
|
account = parsed;
|
|
@@ -105497,8 +106376,8 @@ async function publishToTelegraph(text5, shortName, authorName) {
|
|
|
105497
106376
|
}
|
|
105498
106377
|
account = created.value;
|
|
105499
106378
|
try {
|
|
105500
|
-
|
|
105501
|
-
|
|
106379
|
+
mkdirSync51(STATE_DIR, { recursive: true, mode: 448 });
|
|
106380
|
+
writeFileSync50(accountPath, JSON.stringify(account, null, 2), { mode: 384 });
|
|
105502
106381
|
} catch (err) {
|
|
105503
106382
|
process.stderr.write(`telegram gateway: telegraph cache write failed: ${err.message}
|
|
105504
106383
|
`);
|
|
@@ -105614,7 +106493,7 @@ _The secret was NOT saved. The agent can re-request with \`request_secret\`._`,
|
|
|
105614
106493
|
}
|
|
105615
106494
|
function readLiveSwitchroomConfigText() {
|
|
105616
106495
|
const cfgPath = process.env.SWITCHROOM_CONFIG ?? findConfigFile2();
|
|
105617
|
-
return
|
|
106496
|
+
return readFileSync60(cfgPath, "utf8");
|
|
105618
106497
|
}
|
|
105619
106498
|
async function executeReact(args) {
|
|
105620
106499
|
if (!args.chat_id)
|
|
@@ -105653,9 +106532,9 @@ async function executeDownloadAttachment(args) {
|
|
|
105653
106532
|
fileUniqueId: file.file_unique_id,
|
|
105654
106533
|
now: Date.now()
|
|
105655
106534
|
});
|
|
105656
|
-
|
|
106535
|
+
mkdirSync51(INBOX_DIR, { recursive: true, mode: 448 });
|
|
105657
106536
|
assertInsideInbox2(INBOX_DIR, dlPath);
|
|
105658
|
-
|
|
106537
|
+
writeFileSync50(dlPath, buf, { mode: 384 });
|
|
105659
106538
|
return { content: [{ type: "text", text: dlPath }] };
|
|
105660
106539
|
}
|
|
105661
106540
|
async function executeEditMessage(args) {
|
|
@@ -106299,7 +107178,7 @@ function gate(ctx) {
|
|
|
106299
107178
|
}
|
|
106300
107179
|
if (Object.keys(access.pending).length >= 3)
|
|
106301
107180
|
return { action: "drop", reason: "pairing_capacity" };
|
|
106302
|
-
const code2 =
|
|
107181
|
+
const code2 = randomBytes13(3).toString("hex");
|
|
106303
107182
|
const now = Date.now();
|
|
106304
107183
|
access.pending[code2] = {
|
|
106305
107184
|
senderId,
|
|
@@ -106539,8 +107418,13 @@ async function handleInbound(ctx, text5, downloadImage, attachment, extraAttachm
|
|
|
106539
107418
|
maybePostMissedApprovalDigest("operator inbound");
|
|
106540
107419
|
{
|
|
106541
107420
|
const inboundChatId = ctx.chat?.id;
|
|
106542
|
-
if (inboundChatId != null)
|
|
106543
|
-
|
|
107421
|
+
if (inboundChatId != null) {
|
|
107422
|
+
stalePinSweeper.sweepTarget({
|
|
107423
|
+
chatId: String(inboundChatId),
|
|
107424
|
+
threadId: ctx.message?.message_thread_id,
|
|
107425
|
+
isForum: ctx.chat?.is_forum === true
|
|
107426
|
+
});
|
|
107427
|
+
}
|
|
106544
107428
|
}
|
|
106545
107429
|
const inboundReceivedAt = Date.now();
|
|
106546
107430
|
const machineInTurnAtReceipt = isMachineInTurn();
|
|
@@ -107023,14 +107907,14 @@ function restartMarkerPath() {
|
|
|
107023
107907
|
const agentDir = resolveAgentDirFromEnv();
|
|
107024
107908
|
if (!agentDir)
|
|
107025
107909
|
return null;
|
|
107026
|
-
return
|
|
107910
|
+
return join68(agentDir, "restart-pending.json");
|
|
107027
107911
|
}
|
|
107028
107912
|
function writeRestartMarker(marker) {
|
|
107029
107913
|
const p = restartMarkerPath();
|
|
107030
107914
|
if (!p)
|
|
107031
107915
|
return;
|
|
107032
107916
|
try {
|
|
107033
|
-
|
|
107917
|
+
writeFileSync50(p, JSON.stringify(marker));
|
|
107034
107918
|
lastPlannedRestartAt = Date.now();
|
|
107035
107919
|
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
107920
|
`);
|
|
@@ -107049,7 +107933,7 @@ function readRestartMarker() {
|
|
|
107049
107933
|
if (!p)
|
|
107050
107934
|
return null;
|
|
107051
107935
|
try {
|
|
107052
|
-
return JSON.parse(
|
|
107936
|
+
return JSON.parse(readFileSync60(p, "utf8"));
|
|
107053
107937
|
} catch {
|
|
107054
107938
|
return null;
|
|
107055
107939
|
}
|
|
@@ -107059,7 +107943,7 @@ function clearRestartMarker() {
|
|
|
107059
107943
|
if (!p)
|
|
107060
107944
|
return;
|
|
107061
107945
|
try {
|
|
107062
|
-
|
|
107946
|
+
rmSync8(p, { force: true });
|
|
107063
107947
|
process.stderr.write(`telegram gateway: restart-marker: cleared path=${p}
|
|
107064
107948
|
`);
|
|
107065
107949
|
} catch {}
|
|
@@ -107215,12 +108099,12 @@ function _resetDockerReachableCache() {
|
|
|
107215
108099
|
}
|
|
107216
108100
|
function spawnSwitchroomDetached(args, onFailure) {
|
|
107217
108101
|
const fullArgs = SWITCHROOM_CONFIG ? ["--config", SWITCHROOM_CONFIG, ...args] : args;
|
|
107218
|
-
const logPath =
|
|
108102
|
+
const logPath = join68(STATE_DIR, "detached-spawn.log");
|
|
107219
108103
|
let outFd = null;
|
|
107220
108104
|
try {
|
|
107221
|
-
|
|
107222
|
-
outFd =
|
|
107223
|
-
|
|
108105
|
+
mkdirSync51(STATE_DIR, { recursive: true });
|
|
108106
|
+
outFd = openSync15(logPath, "a");
|
|
108107
|
+
writeFileSync50(logPath, `
|
|
107224
108108
|
[${new Date().toISOString()}] spawn ${SWITCHROOM_CLI} ${fullArgs.join(" ")}
|
|
107225
108109
|
`, { flag: "a" });
|
|
107226
108110
|
} catch {}
|
|
@@ -107234,7 +108118,7 @@ function spawnSwitchroomDetached(args, onFailure) {
|
|
|
107234
108118
|
});
|
|
107235
108119
|
if (outFd != null) {
|
|
107236
108120
|
try {
|
|
107237
|
-
|
|
108121
|
+
closeSync15(outFd);
|
|
107238
108122
|
} catch {}
|
|
107239
108123
|
}
|
|
107240
108124
|
if (onFailure) {
|
|
@@ -107246,7 +108130,7 @@ function spawnSwitchroomDetached(args, onFailure) {
|
|
|
107246
108130
|
return;
|
|
107247
108131
|
let tail = "";
|
|
107248
108132
|
try {
|
|
107249
|
-
const full =
|
|
108133
|
+
const full = readFileSync60(logPath, "utf8");
|
|
107250
108134
|
tail = full.split(`
|
|
107251
108135
|
`).slice(-30).join(`
|
|
107252
108136
|
`).trim();
|
|
@@ -107508,10 +108392,10 @@ ${preBlock(formatSwitchroomOutput(detail))}`, { html: true });
|
|
|
107508
108392
|
}
|
|
107509
108393
|
function readRecentDenialsForAgent(agentName3, windowMs, limit) {
|
|
107510
108394
|
try {
|
|
107511
|
-
const auditPath =
|
|
108395
|
+
const auditPath = join68(homedir19(), ".switchroom", "vault-audit.log");
|
|
107512
108396
|
if (!existsSync57(auditPath))
|
|
107513
108397
|
return [];
|
|
107514
|
-
const raw =
|
|
108398
|
+
const raw = readFileSync60(auditPath, "utf8");
|
|
107515
108399
|
return recentDenialsFromAuditLog(raw, { agentName: agentName3, windowMs, limit });
|
|
107516
108400
|
} catch {
|
|
107517
108401
|
return [];
|
|
@@ -107562,7 +108446,7 @@ async function buildAgentMetadata(agentName3) {
|
|
|
107562
108446
|
try {
|
|
107563
108447
|
const agentDir = resolveAgentDirFromEnv();
|
|
107564
108448
|
if (agentDir) {
|
|
107565
|
-
const raw =
|
|
108449
|
+
const raw = readFileSync60(join68(agentDir, ".claude", ".claude.json"), "utf8");
|
|
107566
108450
|
claudeJson = JSON.parse(raw);
|
|
107567
108451
|
}
|
|
107568
108452
|
} catch {}
|
|
@@ -107691,7 +108575,7 @@ function buildModelDeps(restartCtx) {
|
|
|
107691
108575
|
try {
|
|
107692
108576
|
const agentDir = resolveAgentDirFromEnv();
|
|
107693
108577
|
if (agentDir) {
|
|
107694
|
-
const local = await fetchQuota2({ claudeConfigDir:
|
|
108578
|
+
const local = await fetchQuota2({ claudeConfigDir: join68(agentDir, ".claude") });
|
|
107695
108579
|
if (local.ok)
|
|
107696
108580
|
return formatQuotaLine2(local.data);
|
|
107697
108581
|
}
|
|
@@ -107937,10 +108821,10 @@ function effortMenuReplyMarkup(reply) {
|
|
|
107937
108821
|
function flushAgentHandoff(agentDir) {
|
|
107938
108822
|
let removed = 0;
|
|
107939
108823
|
for (const fname of [".handoff.md", ".handoff-topic"]) {
|
|
107940
|
-
const p =
|
|
108824
|
+
const p = join68(agentDir, fname);
|
|
107941
108825
|
try {
|
|
107942
108826
|
if (existsSync57(p)) {
|
|
107943
|
-
|
|
108827
|
+
unlinkSync30(p);
|
|
107944
108828
|
removed++;
|
|
107945
108829
|
}
|
|
107946
108830
|
} catch (err) {
|
|
@@ -107995,7 +108879,7 @@ async function handleNewCommand(ctx) {
|
|
|
107995
108879
|
writeRestartMarker({ chat_id: chatId, thread_id: threadId ?? null, ack_message_id: ackId, ts: Date.now() });
|
|
107996
108880
|
if (agentDir != null) {
|
|
107997
108881
|
try {
|
|
107998
|
-
|
|
108882
|
+
writeFileSync50(join68(agentDir, ".force-fresh-session"), `${kind} at ${new Date().toISOString()}
|
|
107999
108883
|
`, "utf8");
|
|
108000
108884
|
} catch (err) {
|
|
108001
108885
|
process.stderr.write(`telegram gateway: failed to write force-fresh marker: ${err}
|
|
@@ -108108,11 +108992,11 @@ function buildFolderPickerDeps() {
|
|
|
108108
108992
|
};
|
|
108109
108993
|
}
|
|
108110
108994
|
var lockoutOps = {
|
|
108111
|
-
readFileSync: (p, enc) =>
|
|
108112
|
-
writeFileSync: (p, data, opts) =>
|
|
108995
|
+
readFileSync: (p, enc) => readFileSync60(p, enc),
|
|
108996
|
+
writeFileSync: (p, data, opts) => writeFileSync50(p, data, opts),
|
|
108113
108997
|
existsSync: (p) => existsSync57(p),
|
|
108114
|
-
mkdirSync: (p, opts) =>
|
|
108115
|
-
joinPath: (...parts) =>
|
|
108998
|
+
mkdirSync: (p, opts) => mkdirSync51(p, opts),
|
|
108999
|
+
joinPath: (...parts) => join68(...parts)
|
|
108116
109000
|
};
|
|
108117
109001
|
var FLEET_FALLBACK_DEDUP_MS = 30000;
|
|
108118
109002
|
function isAuthBrokerSocketReachable() {
|
|
@@ -108372,7 +109256,7 @@ async function runCreditWatch() {
|
|
|
108372
109256
|
if (!agentDir)
|
|
108373
109257
|
return;
|
|
108374
109258
|
const agentName3 = getMyAgentName();
|
|
108375
|
-
const claudeConfigDir =
|
|
109259
|
+
const claudeConfigDir = join68(agentDir, ".claude");
|
|
108376
109260
|
const stateDir = STATE_DIR;
|
|
108377
109261
|
const reason = readClaudeJsonOverage(claudeConfigDir);
|
|
108378
109262
|
const prev = loadCreditState(stateDir);
|
|
@@ -110128,7 +111012,7 @@ Send \`/auth ${parsed.provider} cancel\` to abort.`, { html: true });
|
|
|
110128
111012
|
await switchroomReply(ctx, "**/usage:** cannot resolve agent dir.", { html: true });
|
|
110129
111013
|
return;
|
|
110130
111014
|
}
|
|
110131
|
-
const result = await fetchQuota2({ claudeConfigDir:
|
|
111015
|
+
const result = await fetchQuota2({ claudeConfigDir: join68(agentDir, ".claude") });
|
|
110132
111016
|
if (!result.ok) {
|
|
110133
111017
|
await switchroomReply(ctx, `**/usage:** ${escapeHtmlForTg2(result.reason)}`, { html: true });
|
|
110134
111018
|
return;
|
|
@@ -110515,7 +111399,7 @@ ${interimLabel}` : interimLabel
|
|
|
110515
111399
|
const unifiedDiff = (() => {
|
|
110516
111400
|
try {
|
|
110517
111401
|
const cfgPath = process.env.SWITCHROOM_CONFIG ?? SWITCHROOM_CONFIG ?? findConfigFile2();
|
|
110518
|
-
const raw =
|
|
111402
|
+
const raw = readFileSync60(cfgPath, "utf8");
|
|
110519
111403
|
return synthesizeAllowRuleDiff({ agentName: agentName3, rule: chosen.rule, configText: raw });
|
|
110520
111404
|
} catch (err) {
|
|
110521
111405
|
process.stderr.write(`telegram gateway: always-allow diff synth failed: ${err.message}
|
|
@@ -111384,7 +112268,7 @@ async function startGateway() {
|
|
|
111384
112268
|
return;
|
|
111385
112269
|
}
|
|
111386
112270
|
})();
|
|
111387
|
-
const resolvedAgentDirForBootCard = agentDir ??
|
|
112271
|
+
const resolvedAgentDirForBootCard = agentDir ?? join68(homedir19(), ".switchroom", "agents", agentSlug);
|
|
111388
112272
|
const handle = await startBootCard(chatId, threadId, botApiForCard, {
|
|
111389
112273
|
agentName: agentDisplayName,
|
|
111390
112274
|
agentSlug,
|
|
@@ -111398,8 +112282,8 @@ async function startGateway() {
|
|
|
111398
112282
|
probeQuotaViaBroker: (t) => probeQuotaForBootCard(agentSlug, t),
|
|
111399
112283
|
tmuxSupervisor: process.env.SWITCHROOM_TMUX_SUPERVISOR === "1",
|
|
111400
112284
|
dockerMode: process.env.SWITCHROOM_RUNTIME === "docker",
|
|
111401
|
-
configSnapshotPath:
|
|
111402
|
-
bootCardStatePath:
|
|
112285
|
+
configSnapshotPath: join68(resolvedAgentDirForBootCard, ".config-snapshot.json"),
|
|
112286
|
+
bootCardStatePath: join68(resolvedAgentDirForBootCard, ".boot-card-msgid.json"),
|
|
111403
112287
|
floodStatePath: FLOOD_STATE_PATH,
|
|
111404
112288
|
...updateOutcomeLine ? { updateOutcomeLine } : {}
|
|
111405
112289
|
}, ackMsgId);
|
|
@@ -111430,10 +112314,10 @@ async function startGateway() {
|
|
|
111430
112314
|
try {
|
|
111431
112315
|
const smAgentDir = resolveAgentDirFromEnv();
|
|
111432
112316
|
if (smAgentDir) {
|
|
111433
|
-
const activePath =
|
|
112317
|
+
const activePath = join68(smAgentDir, ".active-session-model");
|
|
111434
112318
|
if (existsSync57(activePath)) {
|
|
111435
112319
|
try {
|
|
111436
|
-
const launched =
|
|
112320
|
+
const launched = readFileSync60(activePath, "utf8").trim();
|
|
111437
112321
|
const configured = (() => {
|
|
111438
112322
|
const d = switchroomExecJson(["agent", "list"]);
|
|
111439
112323
|
const raw = d?.agents?.find((a) => a.name === getMyAgentName())?.model ?? null;
|
|
@@ -111466,29 +112350,29 @@ async function startGateway() {
|
|
|
111466
112350
|
deliverModelSwitchBootNotice({
|
|
111467
112351
|
...modelBootCardDeps,
|
|
111468
112352
|
confirmation,
|
|
111469
|
-
hasSessionModelAlert: existsSync57(
|
|
112353
|
+
hasSessionModelAlert: existsSync57(join68(smAgentDir, ".session-model-alert"))
|
|
111470
112354
|
});
|
|
111471
112355
|
}
|
|
111472
112356
|
} catch {}
|
|
111473
112357
|
}
|
|
111474
|
-
const activeEffortPath =
|
|
112358
|
+
const activeEffortPath = join68(smAgentDir, ".active-session-effort");
|
|
111475
112359
|
if (existsSync57(activeEffortPath)) {
|
|
111476
112360
|
try {
|
|
111477
|
-
const launchedEffort =
|
|
112361
|
+
const launchedEffort = readFileSync60(activeEffortPath, "utf8").trim();
|
|
111478
112362
|
const configuredEffort = getConfiguredEffortForPersist();
|
|
111479
112363
|
sessionEffortOverride = launchedEffort.length > 0 && launchedEffort !== configuredEffort ? launchedEffort : null;
|
|
111480
112364
|
} catch {}
|
|
111481
112365
|
}
|
|
111482
|
-
const alertPath =
|
|
112366
|
+
const alertPath = join68(smAgentDir, ".session-model-alert");
|
|
111483
112367
|
if (existsSync57(alertPath)) {
|
|
111484
112368
|
let alertText = null;
|
|
111485
112369
|
try {
|
|
111486
|
-
alertText =
|
|
112370
|
+
alertText = readFileSync60(alertPath, "utf8").trim();
|
|
111487
112371
|
} catch {
|
|
111488
112372
|
alertText = null;
|
|
111489
112373
|
}
|
|
111490
112374
|
try {
|
|
111491
|
-
|
|
112375
|
+
unlinkSync30(alertPath);
|
|
111492
112376
|
} catch {}
|
|
111493
112377
|
if (alertText && alertText.length > 0) {
|
|
111494
112378
|
const operators = loadAccess().allowFrom;
|
|
@@ -111609,12 +112493,12 @@ async function startGateway() {
|
|
|
111609
112493
|
staleWorkerTtlMs: resolveInflightTerminalCapMs() + WORKER_FEED_STALE_TTL_MARGIN_MS,
|
|
111610
112494
|
absoluteRowLifetimeCapMs: resolveInflightTerminalCapMs() * WORKER_FEED_ABSOLUTE_ROW_LIFETIME_CAP_MULTIPLE,
|
|
111611
112495
|
groupMessageLifetimeCapMs: WORKER_FEED_GROUP_MESSAGE_LIFETIME_CAP_MS,
|
|
111612
|
-
reconcilePin: ({ feedKey, chatId, messageId }) => {
|
|
112496
|
+
reconcilePin: ({ feedKey, chatId, threadId, messageId }) => {
|
|
111613
112497
|
if (!PIN_STATUS_WHILE_WORKING)
|
|
111614
112498
|
return;
|
|
111615
112499
|
const key = `wk:group:${feedKey}`;
|
|
111616
112500
|
if (messageId != null) {
|
|
111617
|
-
reconcileStatusPin(key, chatId, { pinned: true, messageId });
|
|
112501
|
+
reconcileStatusPin(key, chatId, { pinned: true, messageId }, threadId);
|
|
111618
112502
|
} else {
|
|
111619
112503
|
const unpinChat = chatId || statusPinClaims.get(key)?.chatId;
|
|
111620
112504
|
if (unpinChat != null && unpinChat.length > 0) {
|
|
@@ -111667,7 +112551,7 @@ async function startGateway() {
|
|
|
111667
112551
|
`);
|
|
111668
112552
|
}
|
|
111669
112553
|
},
|
|
111670
|
-
onFinish: ({ agentId, outcome, description, resultText, toolCount, totalTokens, durationMs, background: entryBackground }) => {
|
|
112554
|
+
onFinish: ({ agentId, outcome, description: description2, resultText, toolCount, totalTokens, durationMs, background: entryBackground }) => {
|
|
111671
112555
|
workerFeedOriginDeferrals.delete(agentId);
|
|
111672
112556
|
deferredDoneReactions.promote();
|
|
111673
112557
|
let fleetChatId = "";
|
|
@@ -111680,10 +112564,10 @@ async function startGateway() {
|
|
|
111680
112564
|
}
|
|
111681
112565
|
}
|
|
111682
112566
|
} catch {}
|
|
111683
|
-
let dispatch = resolveWorkerFeedDispatch(null,
|
|
112567
|
+
let dispatch = resolveWorkerFeedDispatch(null, description2, entryBackground);
|
|
111684
112568
|
if (turnsDb != null) {
|
|
111685
112569
|
try {
|
|
111686
|
-
dispatch = resolveWorkerFeedDispatch(getSubagentByJsonlId(turnsDb, agentId),
|
|
112570
|
+
dispatch = resolveWorkerFeedDispatch(getSubagentByJsonlId(turnsDb, agentId), description2, entryBackground);
|
|
111687
112571
|
} catch {}
|
|
111688
112572
|
}
|
|
111689
112573
|
let isBackground = dispatch.isBackground;
|
|
@@ -111773,7 +112657,7 @@ async function startGateway() {
|
|
|
111773
112657
|
fleetChatId: handbackOrigin?.chatId || fleetChatId,
|
|
111774
112658
|
...handbackOrigin?.threadId != null ? { originThreadId: handbackOrigin.threadId } : {},
|
|
111775
112659
|
ownerChatId: loadAccess().allowFrom[0] ?? "",
|
|
111776
|
-
taskDescription:
|
|
112660
|
+
taskDescription: description2,
|
|
111777
112661
|
resultText,
|
|
111778
112662
|
jsonlAgentId: agentId
|
|
111779
112663
|
});
|
|
@@ -111799,7 +112683,7 @@ async function startGateway() {
|
|
|
111799
112683
|
process.stderr.write(`telegram gateway: subagent-handback queued agent=${agentId} outcome=${outcome} chat=${decision.chatId} resultChars=${resultText.length}
|
|
111800
112684
|
`);
|
|
111801
112685
|
},
|
|
111802
|
-
onProgress: ({ agentId, description, latestSummary, elapsedMs, prevBucketIdx, setBucketIdx, lastTool, toolCount, totalTokens, progressLine, model, skeleton }) => {
|
|
112686
|
+
onProgress: ({ agentId, description: description2, latestSummary, elapsedMs, prevBucketIdx, setBucketIdx, lastTool, toolCount, totalTokens, progressLine, model, skeleton }) => {
|
|
111803
112687
|
let fleetChatId = "";
|
|
111804
112688
|
try {
|
|
111805
112689
|
const fleets = progressDriver?.peekAllFleets() ?? [];
|
|
@@ -111810,10 +112694,10 @@ async function startGateway() {
|
|
|
111810
112694
|
}
|
|
111811
112695
|
}
|
|
111812
112696
|
} catch {}
|
|
111813
|
-
let dispatch = resolveWorkerFeedDispatch(null,
|
|
112697
|
+
let dispatch = resolveWorkerFeedDispatch(null, description2);
|
|
111814
112698
|
if (turnsDb != null) {
|
|
111815
112699
|
try {
|
|
111816
|
-
dispatch = resolveWorkerFeedDispatch(getSubagentByJsonlId(turnsDb, agentId),
|
|
112700
|
+
dispatch = resolveWorkerFeedDispatch(getSubagentByJsonlId(turnsDb, agentId), description2);
|
|
111817
112701
|
} catch {}
|
|
111818
112702
|
}
|
|
111819
112703
|
const isBackground = dispatch.isBackground || dispatch.isNested;
|
|
@@ -111931,7 +112815,7 @@ async function startGateway() {
|
|
|
111931
112815
|
...progressOrigin?.threadId != null ? { originThreadId: progressOrigin.threadId } : {},
|
|
111932
112816
|
ownerChatId: loadAccess().allowFrom[0] ?? "",
|
|
111933
112817
|
subagentJsonlId: agentId,
|
|
111934
|
-
taskDescription:
|
|
112818
|
+
taskDescription: description2,
|
|
111935
112819
|
latestSummary,
|
|
111936
112820
|
elapsedMs,
|
|
111937
112821
|
progressIntervalMs: DEFAULT_PROGRESS_INTERVAL_MS,
|