switchroom 0.19.14 → 0.19.15
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 +1 -1
- package/dist/host-control/main.js +1 -1
- package/package.json +1 -1
- package/telegram-plugin/bridge/bridge.ts +1 -1
- package/telegram-plugin/dist/bridge/bridge.js +1 -1
- package/telegram-plugin/dist/gateway/gateway.js +1002 -504
- package/telegram-plugin/dist/server.js +1 -1
- package/telegram-plugin/gateway/forward-origin.ts +6 -1
- package/telegram-plugin/gateway/gateway.ts +4 -0
- package/telegram-plugin/gateway/narrative-lane.ts +11 -0
- package/telegram-plugin/gateway/outbox-sweep.ts +32 -2
- package/telegram-plugin/gateway/rich-message-handler.ts +235 -0
- package/telegram-plugin/gateway/stream-render.ts +107 -15
- package/telegram-plugin/gateway/unhandled-message.ts +14 -0
- package/telegram-plugin/hooks/narration-classify.d.mts +23 -0
- package/telegram-plugin/hooks/narration-classify.mjs +210 -0
- package/telegram-plugin/hooks/silent-end-scan.mjs +136 -82
- package/telegram-plugin/narrative-flush.ts +35 -0
- package/telegram-plugin/outbox.ts +73 -3
- package/telegram-plugin/shown-ledger.ts +145 -0
- package/telegram-plugin/silent-end.ts +42 -0
- package/telegram-plugin/tests/backstop-exactly-once.test.ts +335 -0
- package/telegram-plugin/tests/catch-all-unhandled-message.test.ts +14 -0
- package/telegram-plugin/tests/forward-origin.test.ts +20 -0
- package/telegram-plugin/tests/forwarded-rich-message.test.ts +305 -0
- package/telegram-plugin/tests/gateway-handler-registration-wiring.test.ts +1 -0
- package/telegram-plugin/tests/narration-leak-3513.test.ts +352 -0
- package/telegram-plugin/tests/silent-end-interrupt-stop-scan.test.ts +42 -13
- package/telegram-plugin/tests/silent-end.test.ts +7 -1
- package/telegram-plugin/tests/turn-flush-safety.test.ts +35 -3
- package/telegram-plugin/turn-flush-safety.ts +66 -53
|
@@ -29091,8 +29091,8 @@ __export(exports_history, {
|
|
|
29091
29091
|
_resetForTests: () => _resetForTests,
|
|
29092
29092
|
MIN_PREFIX_MATCH_CHARS: () => MIN_PREFIX_MATCH_CHARS2
|
|
29093
29093
|
});
|
|
29094
|
-
import { chmodSync as chmodSync9, existsSync as
|
|
29095
|
-
import { join as
|
|
29094
|
+
import { chmodSync as chmodSync9, existsSync as existsSync27, mkdirSync as mkdirSync28 } from "fs";
|
|
29095
|
+
import { join as join31 } from "path";
|
|
29096
29096
|
function loadDatabaseClass2() {
|
|
29097
29097
|
if (DatabaseClass2 != null)
|
|
29098
29098
|
return DatabaseClass2;
|
|
@@ -29123,8 +29123,8 @@ function initHistory2(stateDir, retentionDays = 30) {
|
|
|
29123
29123
|
if (db2 != null)
|
|
29124
29124
|
return;
|
|
29125
29125
|
const Database = loadDatabaseClass2();
|
|
29126
|
-
|
|
29127
|
-
const path2 =
|
|
29126
|
+
mkdirSync28(stateDir, { recursive: true, mode: 448 });
|
|
29127
|
+
const path2 = join31(stateDir, "history.db");
|
|
29128
29128
|
dbPath2 = path2;
|
|
29129
29129
|
db2 = new Database(path2, { create: true });
|
|
29130
29130
|
db2.exec("PRAGMA journal_mode = WAL");
|
|
@@ -29190,7 +29190,7 @@ function initHistory2(stateDir, retentionDays = 30) {
|
|
|
29190
29190
|
}
|
|
29191
29191
|
for (const suffix of ["", "-shm", "-wal"]) {
|
|
29192
29192
|
const f = path2 + suffix;
|
|
29193
|
-
if (
|
|
29193
|
+
if (existsSync27(f)) {
|
|
29194
29194
|
try {
|
|
29195
29195
|
chmodSync9(f, 420);
|
|
29196
29196
|
} catch {}
|
|
@@ -29242,7 +29242,7 @@ function checkpointWal2() {
|
|
|
29242
29242
|
if (dbPath2) {
|
|
29243
29243
|
for (const suffix of ["-shm", "-wal"]) {
|
|
29244
29244
|
const f = dbPath2 + suffix;
|
|
29245
|
-
if (
|
|
29245
|
+
if (existsSync27(f)) {
|
|
29246
29246
|
try {
|
|
29247
29247
|
chmodSync9(f, 420);
|
|
29248
29248
|
} catch {}
|
|
@@ -29489,7 +29489,7 @@ var FLUSH_SUPPRESSION_WINDOW_MS = 2000;
|
|
|
29489
29489
|
var init_turn_flush_suppression = () => {};
|
|
29490
29490
|
|
|
29491
29491
|
// ../src/util/atomic.ts
|
|
29492
|
-
import { closeSync as closeSync6, constants as constants2, fchmodSync, fchownSync, fsyncSync as fsyncSync2, openSync as openSync6, renameSync as
|
|
29492
|
+
import { closeSync as closeSync6, constants as constants2, fchmodSync, fchownSync, fsyncSync as fsyncSync2, openSync as openSync6, renameSync as renameSync13, rmSync as rmSync5, writeSync as writeSync4 } from "node:fs";
|
|
29493
29493
|
var TMP_OPEN_FLAGS;
|
|
29494
29494
|
var init_atomic = __esm(() => {
|
|
29495
29495
|
TMP_OPEN_FLAGS = constants2.O_WRONLY | constants2.O_CREAT | constants2.O_EXCL | (constants2.O_NOFOLLOW ?? 0);
|
|
@@ -32451,7 +32451,7 @@ var require_util = __commonJS((exports2) => {
|
|
|
32451
32451
|
return path2;
|
|
32452
32452
|
}
|
|
32453
32453
|
exports2.normalize = normalize;
|
|
32454
|
-
function
|
|
32454
|
+
function join39(aRoot, aPath) {
|
|
32455
32455
|
if (aRoot === "") {
|
|
32456
32456
|
aRoot = ".";
|
|
32457
32457
|
}
|
|
@@ -32483,7 +32483,7 @@ var require_util = __commonJS((exports2) => {
|
|
|
32483
32483
|
}
|
|
32484
32484
|
return joined;
|
|
32485
32485
|
}
|
|
32486
|
-
exports2.join =
|
|
32486
|
+
exports2.join = join39;
|
|
32487
32487
|
exports2.isAbsolute = function(aPath) {
|
|
32488
32488
|
return aPath.charAt(0) === "/" || urlRegexp.test(aPath);
|
|
32489
32489
|
};
|
|
@@ -32656,7 +32656,7 @@ var require_util = __commonJS((exports2) => {
|
|
|
32656
32656
|
parsed.path = parsed.path.substring(0, index2 + 1);
|
|
32657
32657
|
}
|
|
32658
32658
|
}
|
|
32659
|
-
sourceURL =
|
|
32659
|
+
sourceURL = join39(urlGenerate(parsed), sourceURL);
|
|
32660
32660
|
}
|
|
32661
32661
|
return normalize(sourceURL);
|
|
32662
32662
|
}
|
|
@@ -35261,19 +35261,19 @@ function renderAuthLine(state7, agentName3, now = Date.now()) {
|
|
|
35261
35261
|
}
|
|
35262
35262
|
|
|
35263
35263
|
// gateway/quota-cache.ts
|
|
35264
|
-
import { existsSync as
|
|
35265
|
-
import { join as
|
|
35264
|
+
import { existsSync as existsSync43, readFileSync as readFileSync44, writeFileSync as writeFileSync37, mkdirSync as mkdirSync38 } from "fs";
|
|
35265
|
+
import { join as join48, dirname as dirname15 } from "path";
|
|
35266
35266
|
function defaultCachePath() {
|
|
35267
|
-
return process.env.SWITCHROOM_QUOTA_CACHE_PATH ??
|
|
35267
|
+
return process.env.SWITCHROOM_QUOTA_CACHE_PATH ?? join48(process.env.HOME ?? "/tmp", ".switchroom", "quota-cache.json");
|
|
35268
35268
|
}
|
|
35269
35269
|
function readQuotaCache(opts = {}) {
|
|
35270
35270
|
const path2 = opts.path ?? defaultCachePath();
|
|
35271
35271
|
const now = opts.now ?? Date.now();
|
|
35272
|
-
if (!
|
|
35272
|
+
if (!existsSync43(path2))
|
|
35273
35273
|
return null;
|
|
35274
35274
|
let entry;
|
|
35275
35275
|
try {
|
|
35276
|
-
entry = JSON.parse(
|
|
35276
|
+
entry = JSON.parse(readFileSync44(path2, "utf8"));
|
|
35277
35277
|
} catch {
|
|
35278
35278
|
return null;
|
|
35279
35279
|
}
|
|
@@ -35299,8 +35299,8 @@ function writeQuotaCache(result, opts = {}) {
|
|
|
35299
35299
|
result
|
|
35300
35300
|
};
|
|
35301
35301
|
try {
|
|
35302
|
-
|
|
35303
|
-
|
|
35302
|
+
mkdirSync38(dirname15(path2), { recursive: true });
|
|
35303
|
+
writeFileSync37(path2, JSON.stringify(entry, null, 2), { mode: 384 });
|
|
35304
35304
|
} catch {}
|
|
35305
35305
|
}
|
|
35306
35306
|
var DEFAULT_TTL_MS4, RATE_LIMIT_TTL_MS;
|
|
@@ -35310,8 +35310,8 @@ var init_quota_cache = __esm(() => {
|
|
|
35310
35310
|
});
|
|
35311
35311
|
|
|
35312
35312
|
// gateway/boot-probes.ts
|
|
35313
|
-
import { readFileSync as
|
|
35314
|
-
import { join as
|
|
35313
|
+
import { readFileSync as readFileSync45, readdirSync as readdirSync10, existsSync as existsSync44 } from "fs";
|
|
35314
|
+
import { join as join49 } from "path";
|
|
35315
35315
|
import { execFile as execFileCb } from "child_process";
|
|
35316
35316
|
import { promisify } from "util";
|
|
35317
35317
|
async function withTimeout(label, p, timeoutMs = PROBE_TIMEOUT_MS) {
|
|
@@ -35353,11 +35353,11 @@ function mapPlan(billingType, hasExtra) {
|
|
|
35353
35353
|
}
|
|
35354
35354
|
async function probeAccount(agentDir) {
|
|
35355
35355
|
return withTimeout("Account", (async () => {
|
|
35356
|
-
const claudeDir =
|
|
35357
|
-
const claudeJsonPath =
|
|
35356
|
+
const claudeDir = join49(agentDir, ".claude");
|
|
35357
|
+
const claudeJsonPath = join49(claudeDir, ".claude.json");
|
|
35358
35358
|
let cfg = {};
|
|
35359
35359
|
try {
|
|
35360
|
-
const raw =
|
|
35360
|
+
const raw = readFileSync45(claudeJsonPath, "utf8");
|
|
35361
35361
|
cfg = JSON.parse(raw);
|
|
35362
35362
|
} catch {
|
|
35363
35363
|
return { status: "fail", label: "Account", detail: "no .claude.json" };
|
|
@@ -35375,12 +35375,12 @@ async function probeAccount(agentDir) {
|
|
|
35375
35375
|
let tokenStr = "";
|
|
35376
35376
|
let status = "ok";
|
|
35377
35377
|
for (const candidate of [
|
|
35378
|
-
|
|
35379
|
-
|
|
35378
|
+
join49(claudeDir, ".oauth-token.meta.json"),
|
|
35379
|
+
join49(claudeDir, "accounts", "default", ".oauth-token.meta.json")
|
|
35380
35380
|
]) {
|
|
35381
|
-
if (
|
|
35381
|
+
if (existsSync44(candidate)) {
|
|
35382
35382
|
try {
|
|
35383
|
-
const meta = JSON.parse(
|
|
35383
|
+
const meta = JSON.parse(readFileSync45(candidate, "utf8"));
|
|
35384
35384
|
if (meta.expiresAt) {
|
|
35385
35385
|
tokenStr = " \u00b7 " + formatDaysFromNow(meta.expiresAt);
|
|
35386
35386
|
const daysLeft = Math.round((meta.expiresAt - Date.now()) / 86400000);
|
|
@@ -35555,9 +35555,9 @@ async function resolveTmuxSupervisorPid(agentName3, execFileImpl) {
|
|
|
35555
35555
|
if (!cgroup)
|
|
35556
35556
|
return null;
|
|
35557
35557
|
const procsPath = `/sys/fs/cgroup${cgroup}/cgroup.procs`;
|
|
35558
|
-
if (!
|
|
35558
|
+
if (!existsSync44(procsPath))
|
|
35559
35559
|
return null;
|
|
35560
|
-
const pidsRaw =
|
|
35560
|
+
const pidsRaw = readFileSync45(procsPath, "utf-8");
|
|
35561
35561
|
const pids = pidsRaw.split(`
|
|
35562
35562
|
`).map((s) => s.trim()).filter(Boolean);
|
|
35563
35563
|
if (pids.length === 0)
|
|
@@ -35570,7 +35570,7 @@ async function resolveTmuxSupervisorPid(agentName3, execFileImpl) {
|
|
|
35570
35570
|
let rss = 0;
|
|
35571
35571
|
let comm = "";
|
|
35572
35572
|
try {
|
|
35573
|
-
const status =
|
|
35573
|
+
const status = readFileSync45(`/proc/${pid}/status`, "utf-8");
|
|
35574
35574
|
const rssLine = status.split(`
|
|
35575
35575
|
`).find((l) => l.startsWith("VmRSS:"));
|
|
35576
35576
|
if (rssLine) {
|
|
@@ -35582,7 +35582,7 @@ async function resolveTmuxSupervisorPid(agentName3, execFileImpl) {
|
|
|
35582
35582
|
continue;
|
|
35583
35583
|
}
|
|
35584
35584
|
try {
|
|
35585
|
-
comm =
|
|
35585
|
+
comm = readFileSync45(`/proc/${pid}/comm`, "utf-8").trim();
|
|
35586
35586
|
} catch {}
|
|
35587
35587
|
candidates.push({ pid, rss, comm });
|
|
35588
35588
|
}
|
|
@@ -35762,9 +35762,9 @@ async function probeQuota(claudeConfigDir, _agentDir, fetchImpl = fetch, opts =
|
|
|
35762
35762
|
let claudeDirForProbe = null;
|
|
35763
35763
|
for (const candidate of [
|
|
35764
35764
|
claudeConfigDir,
|
|
35765
|
-
|
|
35765
|
+
join49(claudeConfigDir, "accounts", "default")
|
|
35766
35766
|
]) {
|
|
35767
|
-
if (
|
|
35767
|
+
if (existsSync44(join49(candidate, ".oauth-token"))) {
|
|
35768
35768
|
claudeDirForProbe = candidate;
|
|
35769
35769
|
break;
|
|
35770
35770
|
}
|
|
@@ -35829,7 +35829,7 @@ async function probeHindsight(bankName, fetchImpl = fetch) {
|
|
|
35829
35829
|
}
|
|
35830
35830
|
function readContainerBootTimeMsForProbe() {
|
|
35831
35831
|
try {
|
|
35832
|
-
const stat1 =
|
|
35832
|
+
const stat1 = readFileSync45("/proc/1/stat", "utf8");
|
|
35833
35833
|
const lastParen = stat1.lastIndexOf(")");
|
|
35834
35834
|
if (lastParen < 0)
|
|
35835
35835
|
return null;
|
|
@@ -35837,7 +35837,7 @@ function readContainerBootTimeMsForProbe() {
|
|
|
35837
35837
|
const starttimeTicks = Number(after[19]);
|
|
35838
35838
|
if (!Number.isFinite(starttimeTicks))
|
|
35839
35839
|
return null;
|
|
35840
|
-
const procStat =
|
|
35840
|
+
const procStat = readFileSync45("/proc/stat", "utf8");
|
|
35841
35841
|
const btimeLine = procStat.split(`
|
|
35842
35842
|
`).find((l) => l.startsWith("btime "));
|
|
35843
35843
|
if (!btimeLine)
|
|
@@ -35935,7 +35935,7 @@ async function probeUds(label, socketPath, opts = {}) {
|
|
|
35935
35935
|
}
|
|
35936
35936
|
return withTimeout(label, (async () => {
|
|
35937
35937
|
if (!opts.connectImpl) {
|
|
35938
|
-
if (!
|
|
35938
|
+
if (!existsSync44(socketPath)) {
|
|
35939
35939
|
return {
|
|
35940
35940
|
status: "fail",
|
|
35941
35941
|
label,
|
|
@@ -35999,7 +35999,7 @@ async function probeSkills(agentDir, opts = {}) {
|
|
|
35999
35999
|
return withTimeout("Skills", (async () => {
|
|
36000
36000
|
const fs2 = opts.fs ?? realSkillsFs;
|
|
36001
36001
|
const max = opts.maxNamesShown ?? 3;
|
|
36002
|
-
const skillsDir =
|
|
36002
|
+
const skillsDir = join49(agentDir, ".claude", "skills");
|
|
36003
36003
|
if (!fs2.exists(skillsDir)) {
|
|
36004
36004
|
return { status: "ok", label: "Skills", detail: "no skills dir" };
|
|
36005
36005
|
}
|
|
@@ -36014,17 +36014,17 @@ async function probeSkills(agentDir, opts = {}) {
|
|
|
36014
36014
|
}
|
|
36015
36015
|
const dangling = [];
|
|
36016
36016
|
for (const name of entries) {
|
|
36017
|
-
const skillPath =
|
|
36017
|
+
const skillPath = join49(skillsDir, name);
|
|
36018
36018
|
if (!fs2.exists(skillPath)) {
|
|
36019
36019
|
dangling.push(name);
|
|
36020
36020
|
continue;
|
|
36021
36021
|
}
|
|
36022
|
-
const skillMd =
|
|
36022
|
+
const skillMd = join49(skillPath, "SKILL.md");
|
|
36023
36023
|
if (!fs2.exists(skillMd) && !fs2.exists(skillPath + ".md")) {
|
|
36024
36024
|
continue;
|
|
36025
36025
|
}
|
|
36026
36026
|
}
|
|
36027
|
-
const overlayDir = opts.overlaySkillsDir ??
|
|
36027
|
+
const overlayDir = opts.overlaySkillsDir ?? join49(agentDir, "skills.d");
|
|
36028
36028
|
const overlaySlugs = new Set;
|
|
36029
36029
|
if (fs2.exists(overlayDir)) {
|
|
36030
36030
|
let overlayEntries = [];
|
|
@@ -36066,8 +36066,8 @@ function renderBucketedSkills(switchroom, agent) {
|
|
|
36066
36066
|
}
|
|
36067
36067
|
async function probeConnections(agentDir, opts = {}) {
|
|
36068
36068
|
return withTimeout("Connections", (async () => {
|
|
36069
|
-
const path2 =
|
|
36070
|
-
const read = opts.readFileImpl ?? ((p) =>
|
|
36069
|
+
const path2 = join49(agentDir, ".claude", "connection-health.json");
|
|
36070
|
+
const read = opts.readFileImpl ?? ((p) => readFileSync45(p, "utf8"));
|
|
36071
36071
|
let issues = [];
|
|
36072
36072
|
try {
|
|
36073
36073
|
const parsed = JSON.parse(read(path2));
|
|
@@ -36098,24 +36098,24 @@ var init_boot_probes = __esm(() => {
|
|
|
36098
36098
|
execFile = promisify(execFileCb);
|
|
36099
36099
|
realProcFs = {
|
|
36100
36100
|
readdir: (p) => readdirSync10(p),
|
|
36101
|
-
readFile: (p) =>
|
|
36101
|
+
readFile: (p) => readFileSync45(p, "utf-8")
|
|
36102
36102
|
};
|
|
36103
36103
|
realSchedulerFs = {
|
|
36104
|
-
readFile: (p) =>
|
|
36104
|
+
readFile: (p) => readFileSync45(p, "utf-8"),
|
|
36105
36105
|
mtimeMs: (p) => {
|
|
36106
36106
|
const { statSync: statSync14 } = __require("fs");
|
|
36107
36107
|
return statSync14(p).mtimeMs;
|
|
36108
36108
|
},
|
|
36109
|
-
exists: (p) =>
|
|
36109
|
+
exists: (p) => existsSync44(p)
|
|
36110
36110
|
};
|
|
36111
36111
|
realSkillsFs = {
|
|
36112
36112
|
readdir: (p) => readdirSync10(p),
|
|
36113
|
-
exists: (p) =>
|
|
36113
|
+
exists: (p) => existsSync44(p)
|
|
36114
36114
|
};
|
|
36115
36115
|
});
|
|
36116
36116
|
|
|
36117
36117
|
// gateway/boot-issue-cache.ts
|
|
36118
|
-
import { existsSync as
|
|
36118
|
+
import { existsSync as existsSync45, readFileSync as readFileSync46, writeFileSync as writeFileSync38, mkdirSync as mkdirSync39, renameSync as renameSync19 } from "fs";
|
|
36119
36119
|
import { dirname as dirname16 } from "path";
|
|
36120
36120
|
function fingerprintProbe(key, r) {
|
|
36121
36121
|
if (r.status === "ok")
|
|
@@ -36195,11 +36195,11 @@ function diffProbes(probes, cache, opts = {}) {
|
|
|
36195
36195
|
return out;
|
|
36196
36196
|
}
|
|
36197
36197
|
function loadCache(path2, now = Date.now) {
|
|
36198
|
-
if (!
|
|
36198
|
+
if (!existsSync45(path2))
|
|
36199
36199
|
return { ...EMPTY_CACHE, probes: {} };
|
|
36200
36200
|
let raw;
|
|
36201
36201
|
try {
|
|
36202
|
-
raw =
|
|
36202
|
+
raw = readFileSync46(path2, "utf-8");
|
|
36203
36203
|
} catch {
|
|
36204
36204
|
return { ...EMPTY_CACHE, probes: {} };
|
|
36205
36205
|
}
|
|
@@ -36208,7 +36208,7 @@ function loadCache(path2, now = Date.now) {
|
|
|
36208
36208
|
parsed = JSON.parse(raw);
|
|
36209
36209
|
} catch {
|
|
36210
36210
|
try {
|
|
36211
|
-
|
|
36211
|
+
renameSync19(path2, `${path2}.corrupt-${now()}`);
|
|
36212
36212
|
} catch {}
|
|
36213
36213
|
return { ...EMPTY_CACHE, probes: {} };
|
|
36214
36214
|
}
|
|
@@ -36242,10 +36242,10 @@ function applyAndSave(path2, cache, diff) {
|
|
|
36242
36242
|
}
|
|
36243
36243
|
}
|
|
36244
36244
|
try {
|
|
36245
|
-
|
|
36245
|
+
mkdirSync39(dirname16(path2), { recursive: true });
|
|
36246
36246
|
const tmp = `${path2}.tmp`;
|
|
36247
|
-
|
|
36248
|
-
|
|
36247
|
+
writeFileSync38(tmp, JSON.stringify(next), { mode: 384 });
|
|
36248
|
+
renameSync19(tmp, path2);
|
|
36249
36249
|
} catch {}
|
|
36250
36250
|
return next;
|
|
36251
36251
|
}
|
|
@@ -36257,14 +36257,14 @@ var init_boot_issue_cache = __esm(() => {
|
|
|
36257
36257
|
});
|
|
36258
36258
|
|
|
36259
36259
|
// gateway/config-snapshot.ts
|
|
36260
|
-
import { createHash as
|
|
36261
|
-
import { existsSync as
|
|
36260
|
+
import { createHash as createHash5 } from "crypto";
|
|
36261
|
+
import { existsSync as existsSync46, readFileSync as readFileSync47, writeFileSync as writeFileSync39, mkdirSync as mkdirSync40, renameSync as renameSync20 } from "fs";
|
|
36262
36262
|
import { dirname as dirname17 } from "path";
|
|
36263
36263
|
function hashStringArray(items) {
|
|
36264
36264
|
if (!items || items.length === 0)
|
|
36265
36265
|
return null;
|
|
36266
36266
|
const sorted = [...items].sort();
|
|
36267
|
-
const raw =
|
|
36267
|
+
const raw = createHash5("sha256").update(sorted.join("\x00")).digest("hex");
|
|
36268
36268
|
return raw.slice(0, 12);
|
|
36269
36269
|
}
|
|
36270
36270
|
function normalizeModel(model) {
|
|
@@ -36323,11 +36323,11 @@ function renderConfigChangeDim(dim) {
|
|
|
36323
36323
|
}
|
|
36324
36324
|
}
|
|
36325
36325
|
function loadSnapshot(path2, now = Date.now) {
|
|
36326
|
-
if (!
|
|
36326
|
+
if (!existsSync46(path2))
|
|
36327
36327
|
return null;
|
|
36328
36328
|
let raw;
|
|
36329
36329
|
try {
|
|
36330
|
-
raw =
|
|
36330
|
+
raw = readFileSync47(path2, "utf-8");
|
|
36331
36331
|
} catch {
|
|
36332
36332
|
return null;
|
|
36333
36333
|
}
|
|
@@ -36336,7 +36336,7 @@ function loadSnapshot(path2, now = Date.now) {
|
|
|
36336
36336
|
parsed = JSON.parse(raw);
|
|
36337
36337
|
} catch {
|
|
36338
36338
|
try {
|
|
36339
|
-
|
|
36339
|
+
renameSync20(path2, `${path2}.corrupt-${now()}`);
|
|
36340
36340
|
} catch {}
|
|
36341
36341
|
return null;
|
|
36342
36342
|
}
|
|
@@ -36357,10 +36357,10 @@ function loadSnapshot(path2, now = Date.now) {
|
|
|
36357
36357
|
}
|
|
36358
36358
|
function persistSnapshot(path2, snapshot) {
|
|
36359
36359
|
try {
|
|
36360
|
-
|
|
36360
|
+
mkdirSync40(dirname17(path2), { recursive: true });
|
|
36361
36361
|
const tmp = `${path2}.tmp`;
|
|
36362
|
-
|
|
36363
|
-
|
|
36362
|
+
writeFileSync39(tmp, JSON.stringify(snapshot), { mode: 384 });
|
|
36363
|
+
renameSync20(tmp, path2);
|
|
36364
36364
|
} catch {}
|
|
36365
36365
|
}
|
|
36366
36366
|
var init_config_snapshot = __esm(() => {
|
|
@@ -36368,13 +36368,13 @@ var init_config_snapshot = __esm(() => {
|
|
|
36368
36368
|
});
|
|
36369
36369
|
|
|
36370
36370
|
// gateway/boot-card-msgid.ts
|
|
36371
|
-
import { readFileSync as
|
|
36371
|
+
import { readFileSync as readFileSync48, writeFileSync as writeFileSync40 } from "node:fs";
|
|
36372
36372
|
function bootCardChatKey(chatId, threadId) {
|
|
36373
36373
|
return `${chatId}:${threadId ?? ""}`;
|
|
36374
36374
|
}
|
|
36375
36375
|
function readStore(path2) {
|
|
36376
36376
|
try {
|
|
36377
|
-
const parsed = JSON.parse(
|
|
36377
|
+
const parsed = JSON.parse(readFileSync48(path2, "utf8"));
|
|
36378
36378
|
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
36379
36379
|
return parsed;
|
|
36380
36380
|
}
|
|
@@ -36393,7 +36393,7 @@ function saveBootCardMsgId(path2, chatKey3, messageId) {
|
|
|
36393
36393
|
if (store2[chatKey3] === messageId)
|
|
36394
36394
|
return;
|
|
36395
36395
|
store2[chatKey3] = messageId;
|
|
36396
|
-
|
|
36396
|
+
writeFileSync40(path2, JSON.stringify(store2), "utf8");
|
|
36397
36397
|
} catch {}
|
|
36398
36398
|
}
|
|
36399
36399
|
var init_boot_card_msgid = () => {};
|
|
@@ -36411,8 +36411,8 @@ __export(exports_boot_card, {
|
|
|
36411
36411
|
readRoutingMode: () => readRoutingMode,
|
|
36412
36412
|
containerBootStartMs: () => containerBootStartMs
|
|
36413
36413
|
});
|
|
36414
|
-
import { join as
|
|
36415
|
-
import { readFileSync as
|
|
36414
|
+
import { join as join50 } from "path";
|
|
36415
|
+
import { readFileSync as readFileSync49, statSync as statSync14 } from "fs";
|
|
36416
36416
|
function resolvePersonaName(slug, loadConfig3) {
|
|
36417
36417
|
try {
|
|
36418
36418
|
const config = loadConfig3 ? loadConfig3() : loadConfig();
|
|
@@ -36434,7 +36434,7 @@ function shouldSkipDuplicateBootCard(gate, site) {
|
|
|
36434
36434
|
}
|
|
36435
36435
|
return { skip: false };
|
|
36436
36436
|
}
|
|
36437
|
-
function containerBootStartMs(fsImpl = { readFileSync:
|
|
36437
|
+
function containerBootStartMs(fsImpl = { readFileSync: readFileSync49 }) {
|
|
36438
36438
|
try {
|
|
36439
36439
|
const btimeLine = fsImpl.readFileSync("/proc/stat", "utf-8").split(`
|
|
36440
36440
|
`).find((l) => l.startsWith("btime "));
|
|
@@ -36455,8 +36455,8 @@ function containerBootStartMs(fsImpl = { readFileSync: readFileSync48 }) {
|
|
|
36455
36455
|
return null;
|
|
36456
36456
|
}
|
|
36457
36457
|
}
|
|
36458
|
-
function readRoutingMode(agentDir, bootStartMs, fsImpl = { readFileSync:
|
|
36459
|
-
const path2 =
|
|
36458
|
+
function readRoutingMode(agentDir, bootStartMs, fsImpl = { readFileSync: readFileSync49, statSync: statSync14 }) {
|
|
36459
|
+
const path2 = join50(agentDir, ".routing-mode");
|
|
36460
36460
|
try {
|
|
36461
36461
|
const raw = fsImpl.readFileSync(path2, "utf-8");
|
|
36462
36462
|
const line = raw.split(`
|
|
@@ -36563,7 +36563,7 @@ function renderBootCard(opts) {
|
|
|
36563
36563
|
return stackCardLines(flatLines);
|
|
36564
36564
|
}
|
|
36565
36565
|
async function runAllProbes(opts) {
|
|
36566
|
-
const claudeDir =
|
|
36566
|
+
const claudeDir = join50(opts.agentDir, ".claude");
|
|
36567
36567
|
const probes = {};
|
|
36568
36568
|
const slug = opts.agentSlug ?? opts.agentName;
|
|
36569
36569
|
await Promise.allSettled([
|
|
@@ -37417,7 +37417,7 @@ __export(exports_tmux2, {
|
|
|
37417
37417
|
captureAgentPane: () => captureAgentPane2
|
|
37418
37418
|
});
|
|
37419
37419
|
import { execFileSync as execFileSync8 } from "node:child_process";
|
|
37420
|
-
import { chmodSync as chmodSync13, mkdirSync as
|
|
37420
|
+
import { chmodSync as chmodSync13, mkdirSync as mkdirSync48, readdirSync as readdirSync13, statSync as statSync19, unlinkSync as unlinkSync26, writeFileSync as writeFileSync49 } from "node:fs";
|
|
37421
37421
|
import { resolve as resolve12 } from "node:path";
|
|
37422
37422
|
function captureAgentPane2(opts) {
|
|
37423
37423
|
const { agentName: agentName3, agentDir, reason } = opts;
|
|
@@ -37429,7 +37429,7 @@ function captureAgentPane2(opts) {
|
|
|
37429
37429
|
const reasonSlug = sanitizeReason2(reason);
|
|
37430
37430
|
const outPath = resolve12(outDir, `${ts}-${reasonSlug}.txt`);
|
|
37431
37431
|
try {
|
|
37432
|
-
|
|
37432
|
+
mkdirSync48(outDir, { recursive: true, mode: 448 });
|
|
37433
37433
|
} catch (err) {
|
|
37434
37434
|
const msg = `mkdir crash-reports failed: ${err.message}`;
|
|
37435
37435
|
console.error(`[tmux-capture] ${agentName3}: ${msg}`);
|
|
@@ -37468,7 +37468,7 @@ function captureAgentPane2(opts) {
|
|
|
37468
37468
|
` + `
|
|
37469
37469
|
`;
|
|
37470
37470
|
try {
|
|
37471
|
-
|
|
37471
|
+
writeFileSync49(outPath, Buffer.concat([Buffer.from(header, "utf8"), body]), {
|
|
37472
37472
|
mode: 384
|
|
37473
37473
|
});
|
|
37474
37474
|
} catch (err) {
|
|
@@ -38348,7 +38348,7 @@ __export(exports_materialize_bot_token, {
|
|
|
38348
38348
|
materializeBotToken: () => materializeBotToken,
|
|
38349
38349
|
BotTokenMaterializeError: () => BotTokenMaterializeError
|
|
38350
38350
|
});
|
|
38351
|
-
import { existsSync as
|
|
38351
|
+
import { existsSync as existsSync55 } from "node:fs";
|
|
38352
38352
|
function pickConfiguredToken(config, agentName3) {
|
|
38353
38353
|
if (agentName3) {
|
|
38354
38354
|
const agent = config.agents?.[agentName3];
|
|
@@ -38362,7 +38362,7 @@ function tryDirectVaultRead4(ref, config, passphrase) {
|
|
|
38362
38362
|
if (!passphrase)
|
|
38363
38363
|
return null;
|
|
38364
38364
|
const vaultPath = resolvePath(config.vault?.path ?? "~/.switchroom/vault.enc");
|
|
38365
|
-
if (!
|
|
38365
|
+
if (!existsSync55(vaultPath))
|
|
38366
38366
|
return null;
|
|
38367
38367
|
try {
|
|
38368
38368
|
const secrets = openVault(passphrase, vaultPath);
|
|
@@ -38514,26 +38514,26 @@ var init_approvals_commands = __esm(() => {
|
|
|
38514
38514
|
// gateway/gateway.ts
|
|
38515
38515
|
var import_grammy16 = __toESM(require_mod(), 1);
|
|
38516
38516
|
var import_runner3 = __toESM(require_mod3(), 1);
|
|
38517
|
-
import { randomBytes as randomBytes10, createHash as
|
|
38517
|
+
import { randomBytes as randomBytes10, createHash as createHash6 } from "crypto";
|
|
38518
38518
|
import { execFileSync as execFileSync9, execSync as execSync2, spawn as spawn2 } from "child_process";
|
|
38519
38519
|
import {
|
|
38520
|
-
readFileSync as
|
|
38521
|
-
writeFileSync as
|
|
38522
|
-
mkdirSync as
|
|
38520
|
+
readFileSync as readFileSync60,
|
|
38521
|
+
writeFileSync as writeFileSync50,
|
|
38522
|
+
mkdirSync as mkdirSync49,
|
|
38523
38523
|
readdirSync as readdirSync14,
|
|
38524
38524
|
rmSync as rmSync6,
|
|
38525
38525
|
statSync as statSync20,
|
|
38526
|
-
renameSync as
|
|
38526
|
+
renameSync as renameSync23,
|
|
38527
38527
|
realpathSync as realpathSync4,
|
|
38528
38528
|
chmodSync as chmodSync14,
|
|
38529
38529
|
openSync as openSync12,
|
|
38530
38530
|
closeSync as closeSync12,
|
|
38531
|
-
existsSync as
|
|
38531
|
+
existsSync as existsSync56,
|
|
38532
38532
|
unlinkSync as unlinkSync27,
|
|
38533
|
-
appendFileSync as
|
|
38533
|
+
appendFileSync as appendFileSync9
|
|
38534
38534
|
} from "fs";
|
|
38535
38535
|
import { homedir as homedir20 } from "os";
|
|
38536
|
-
import { join as
|
|
38536
|
+
import { join as join62, sep as sep4, basename as basename15 } from "path";
|
|
38537
38537
|
|
|
38538
38538
|
// plugin-logger.ts
|
|
38539
38539
|
import { appendFileSync, mkdirSync, renameSync, statSync, existsSync } from "fs";
|
|
@@ -40819,6 +40819,141 @@ function forwardOriginDateIso(o) {
|
|
|
40819
40819
|
return new Date(o.date * 1000).toISOString();
|
|
40820
40820
|
}
|
|
40821
40821
|
|
|
40822
|
+
// gateway/rich-message-handler.ts
|
|
40823
|
+
var MAX_DEPTH = 32;
|
|
40824
|
+
function renderRichText(rt, depth = 0) {
|
|
40825
|
+
if (depth > MAX_DEPTH || rt == null)
|
|
40826
|
+
return "";
|
|
40827
|
+
if (typeof rt === "string")
|
|
40828
|
+
return rt;
|
|
40829
|
+
if (Array.isArray(rt))
|
|
40830
|
+
return rt.map((t) => renderRichText(t, depth + 1)).join("");
|
|
40831
|
+
if (typeof rt !== "object")
|
|
40832
|
+
return "";
|
|
40833
|
+
const node = rt;
|
|
40834
|
+
if (node.type === "custom_emoji")
|
|
40835
|
+
return node.alternative_text ?? "";
|
|
40836
|
+
if (node.type === "mathematical_expression") {
|
|
40837
|
+
return typeof node.expression === "string" ? node.expression : "";
|
|
40838
|
+
}
|
|
40839
|
+
if (node.type === "anchor")
|
|
40840
|
+
return "";
|
|
40841
|
+
if ("text" in node)
|
|
40842
|
+
return renderRichText(node.text, depth + 1);
|
|
40843
|
+
return "";
|
|
40844
|
+
}
|
|
40845
|
+
function renderCaption(caption, depth) {
|
|
40846
|
+
if (caption == null || typeof caption !== "object")
|
|
40847
|
+
return renderRichText(caption, depth);
|
|
40848
|
+
const c = caption;
|
|
40849
|
+
const text = renderRichText(c.text, depth);
|
|
40850
|
+
const credit = renderRichText(c.credit, depth);
|
|
40851
|
+
return [text, credit ? `\u2014 ${credit}` : ""].filter(Boolean).join(" ");
|
|
40852
|
+
}
|
|
40853
|
+
function renderBlocks(blocks, depth) {
|
|
40854
|
+
if (depth > MAX_DEPTH || !Array.isArray(blocks))
|
|
40855
|
+
return "";
|
|
40856
|
+
return blocks.map((b) => renderRichBlock(b, depth + 1)).filter((s) => s.length > 0).join(`
|
|
40857
|
+
`);
|
|
40858
|
+
}
|
|
40859
|
+
function renderRichBlock(block, depth = 0) {
|
|
40860
|
+
if (depth > MAX_DEPTH || block == null || typeof block !== "object")
|
|
40861
|
+
return "";
|
|
40862
|
+
const b = block;
|
|
40863
|
+
switch (b.type) {
|
|
40864
|
+
case "paragraph":
|
|
40865
|
+
case "heading":
|
|
40866
|
+
case "footer":
|
|
40867
|
+
return renderRichText(b.text, depth);
|
|
40868
|
+
case "pre": {
|
|
40869
|
+
const body = renderRichText(b.text, depth);
|
|
40870
|
+
return body.length > 0 ? `\`\`\`${b.language ?? ""}
|
|
40871
|
+
${body}
|
|
40872
|
+
\`\`\`` : "";
|
|
40873
|
+
}
|
|
40874
|
+
case "divider":
|
|
40875
|
+
return "---";
|
|
40876
|
+
case "mathematical_expression":
|
|
40877
|
+
return typeof b.expression === "string" ? b.expression : "";
|
|
40878
|
+
case "anchor":
|
|
40879
|
+
return "";
|
|
40880
|
+
case "list": {
|
|
40881
|
+
if (!Array.isArray(b.items))
|
|
40882
|
+
return "";
|
|
40883
|
+
return b.items.map((item) => {
|
|
40884
|
+
const body = renderBlocks(item?.blocks, depth);
|
|
40885
|
+
const check = item?.has_checkbox ? item.is_checked ? "[x] " : "[ ] " : "";
|
|
40886
|
+
const label = typeof item?.label === "string" && item.label.length > 0 ? item.label : "-";
|
|
40887
|
+
return body.length > 0 ? `${label} ${check}${body}` : "";
|
|
40888
|
+
}).filter((s) => s.length > 0).join(`
|
|
40889
|
+
`);
|
|
40890
|
+
}
|
|
40891
|
+
case "blockquote": {
|
|
40892
|
+
const body = renderBlocks(b.blocks, depth);
|
|
40893
|
+
const credit = renderRichText(b.credit, depth);
|
|
40894
|
+
const quoted = body.split(`
|
|
40895
|
+
`).map((line) => `> ${line}`).join(`
|
|
40896
|
+
`);
|
|
40897
|
+
return [quoted, credit ? `> \u2014 ${credit}` : ""].filter((s) => s.length > 0).join(`
|
|
40898
|
+
`);
|
|
40899
|
+
}
|
|
40900
|
+
case "pullquote": {
|
|
40901
|
+
const body = renderRichText(b.text, depth);
|
|
40902
|
+
const credit = renderRichText(b.credit, depth);
|
|
40903
|
+
return [body, credit ? `\u2014 ${credit}` : ""].filter(Boolean).join(" ");
|
|
40904
|
+
}
|
|
40905
|
+
case "details": {
|
|
40906
|
+
const summary = renderRichText(b.summary, depth);
|
|
40907
|
+
const body = renderBlocks(b.blocks, depth);
|
|
40908
|
+
return [summary, body].filter((s) => s.length > 0).join(`
|
|
40909
|
+
`);
|
|
40910
|
+
}
|
|
40911
|
+
case "collage":
|
|
40912
|
+
case "slideshow": {
|
|
40913
|
+
const body = renderBlocks(b.blocks, depth);
|
|
40914
|
+
const caption = renderCaption(b.caption, depth);
|
|
40915
|
+
return [body, caption].filter((s) => s.length > 0).join(`
|
|
40916
|
+
`);
|
|
40917
|
+
}
|
|
40918
|
+
case "table": {
|
|
40919
|
+
if (!Array.isArray(b.cells))
|
|
40920
|
+
return "";
|
|
40921
|
+
const rows = b.cells.map((row) => Array.isArray(row) ? row.map((cell) => renderRichText(cell?.text, depth)).join(" | ") : "").filter((s) => s.length > 0).join(`
|
|
40922
|
+
`);
|
|
40923
|
+
const caption = renderRichText(b.caption, depth);
|
|
40924
|
+
return [caption, rows].filter((s) => s.length > 0).join(`
|
|
40925
|
+
`);
|
|
40926
|
+
}
|
|
40927
|
+
case "map":
|
|
40928
|
+
case "animation":
|
|
40929
|
+
case "audio":
|
|
40930
|
+
case "photo":
|
|
40931
|
+
case "video":
|
|
40932
|
+
case "voice_note": {
|
|
40933
|
+
const caption = renderCaption(b.caption, depth);
|
|
40934
|
+
const tag = `[${b.type}]`;
|
|
40935
|
+
return caption.length > 0 ? `${tag} ${caption}` : tag;
|
|
40936
|
+
}
|
|
40937
|
+
case "thinking":
|
|
40938
|
+
return "";
|
|
40939
|
+
default: {
|
|
40940
|
+
const text = renderRichText(b.text, depth);
|
|
40941
|
+
if (text.length > 0)
|
|
40942
|
+
return text;
|
|
40943
|
+
return renderBlocks(b.blocks, depth);
|
|
40944
|
+
}
|
|
40945
|
+
}
|
|
40946
|
+
}
|
|
40947
|
+
function extractRichMessageText(rich) {
|
|
40948
|
+
if (rich == null || typeof rich !== "object")
|
|
40949
|
+
return;
|
|
40950
|
+
const blocks = rich.blocks;
|
|
40951
|
+
const rendered = renderBlocks(blocks, 0).replace(/\n{3,}/g, `
|
|
40952
|
+
|
|
40953
|
+
`).trim();
|
|
40954
|
+
return rendered.length > 0 ? rendered : undefined;
|
|
40955
|
+
}
|
|
40956
|
+
|
|
40822
40957
|
// gateway/unhandled-message.ts
|
|
40823
40958
|
var MESSAGE_ENVELOPE_KEYS = new Set([
|
|
40824
40959
|
"message_id",
|
|
@@ -40847,7 +40982,13 @@ var MESSAGE_ENVELOPE_KEYS = new Set([
|
|
|
40847
40982
|
"show_caption_above_media",
|
|
40848
40983
|
"entities",
|
|
40849
40984
|
"caption_entities",
|
|
40850
|
-
"paid_star_count"
|
|
40985
|
+
"paid_star_count",
|
|
40986
|
+
"forward_from",
|
|
40987
|
+
"forward_from_chat",
|
|
40988
|
+
"forward_from_message_id",
|
|
40989
|
+
"forward_signature",
|
|
40990
|
+
"forward_sender_name",
|
|
40991
|
+
"forward_date"
|
|
40851
40992
|
]);
|
|
40852
40993
|
var SERVICE_NOISE_KEYS = new Set([
|
|
40853
40994
|
"new_chat_members",
|
|
@@ -40892,7 +41033,7 @@ function planUnhandledMessage(msg) {
|
|
|
40892
41033
|
return { action: "log-only", contentKeys };
|
|
40893
41034
|
}
|
|
40894
41035
|
const contentType = contentKeys[0] ?? "unknown";
|
|
40895
|
-
const text = (typeof msg.text === "string" ? msg.text : undefined) ?? (typeof msg.caption === "string" ? msg.caption : undefined) ?? `(unhandled message content: ${contentType})`;
|
|
41036
|
+
const text = (typeof msg.text === "string" ? msg.text : undefined) ?? (typeof msg.caption === "string" ? msg.caption : undefined) ?? extractRichMessageText(msg.rich_message) ?? `(unhandled message content: ${contentType})`;
|
|
40896
41037
|
return { action: "turn", text, contentKeys };
|
|
40897
41038
|
}
|
|
40898
41039
|
var TAP_MAX_LINES_PER_MINUTE = 300;
|
|
@@ -41091,6 +41232,153 @@ async function handlePassportDataMessage(ctx, deps) {
|
|
|
41091
41232
|
await deps.handleRefusal(ctx, "passport_data", PASSPORT_REFUSAL_TEXT);
|
|
41092
41233
|
}
|
|
41093
41234
|
|
|
41235
|
+
// gateway/rich-message-handler.ts
|
|
41236
|
+
var RICH_MESSAGE_EMPTY_TEXT = "(rich message with no extractable text)";
|
|
41237
|
+
var MAX_DEPTH2 = 32;
|
|
41238
|
+
function renderRichText2(rt, depth = 0) {
|
|
41239
|
+
if (depth > MAX_DEPTH2 || rt == null)
|
|
41240
|
+
return "";
|
|
41241
|
+
if (typeof rt === "string")
|
|
41242
|
+
return rt;
|
|
41243
|
+
if (Array.isArray(rt))
|
|
41244
|
+
return rt.map((t) => renderRichText2(t, depth + 1)).join("");
|
|
41245
|
+
if (typeof rt !== "object")
|
|
41246
|
+
return "";
|
|
41247
|
+
const node = rt;
|
|
41248
|
+
if (node.type === "custom_emoji")
|
|
41249
|
+
return node.alternative_text ?? "";
|
|
41250
|
+
if (node.type === "mathematical_expression") {
|
|
41251
|
+
return typeof node.expression === "string" ? node.expression : "";
|
|
41252
|
+
}
|
|
41253
|
+
if (node.type === "anchor")
|
|
41254
|
+
return "";
|
|
41255
|
+
if ("text" in node)
|
|
41256
|
+
return renderRichText2(node.text, depth + 1);
|
|
41257
|
+
return "";
|
|
41258
|
+
}
|
|
41259
|
+
function renderCaption2(caption, depth) {
|
|
41260
|
+
if (caption == null || typeof caption !== "object")
|
|
41261
|
+
return renderRichText2(caption, depth);
|
|
41262
|
+
const c = caption;
|
|
41263
|
+
const text = renderRichText2(c.text, depth);
|
|
41264
|
+
const credit = renderRichText2(c.credit, depth);
|
|
41265
|
+
return [text, credit ? `\u2014 ${credit}` : ""].filter(Boolean).join(" ");
|
|
41266
|
+
}
|
|
41267
|
+
function renderBlocks2(blocks, depth) {
|
|
41268
|
+
if (depth > MAX_DEPTH2 || !Array.isArray(blocks))
|
|
41269
|
+
return "";
|
|
41270
|
+
return blocks.map((b) => renderRichBlock2(b, depth + 1)).filter((s) => s.length > 0).join(`
|
|
41271
|
+
`);
|
|
41272
|
+
}
|
|
41273
|
+
function renderRichBlock2(block, depth = 0) {
|
|
41274
|
+
if (depth > MAX_DEPTH2 || block == null || typeof block !== "object")
|
|
41275
|
+
return "";
|
|
41276
|
+
const b = block;
|
|
41277
|
+
switch (b.type) {
|
|
41278
|
+
case "paragraph":
|
|
41279
|
+
case "heading":
|
|
41280
|
+
case "footer":
|
|
41281
|
+
return renderRichText2(b.text, depth);
|
|
41282
|
+
case "pre": {
|
|
41283
|
+
const body = renderRichText2(b.text, depth);
|
|
41284
|
+
return body.length > 0 ? `\`\`\`${b.language ?? ""}
|
|
41285
|
+
${body}
|
|
41286
|
+
\`\`\`` : "";
|
|
41287
|
+
}
|
|
41288
|
+
case "divider":
|
|
41289
|
+
return "---";
|
|
41290
|
+
case "mathematical_expression":
|
|
41291
|
+
return typeof b.expression === "string" ? b.expression : "";
|
|
41292
|
+
case "anchor":
|
|
41293
|
+
return "";
|
|
41294
|
+
case "list": {
|
|
41295
|
+
if (!Array.isArray(b.items))
|
|
41296
|
+
return "";
|
|
41297
|
+
return b.items.map((item) => {
|
|
41298
|
+
const body = renderBlocks2(item?.blocks, depth);
|
|
41299
|
+
const check = item?.has_checkbox ? item.is_checked ? "[x] " : "[ ] " : "";
|
|
41300
|
+
const label = typeof item?.label === "string" && item.label.length > 0 ? item.label : "-";
|
|
41301
|
+
return body.length > 0 ? `${label} ${check}${body}` : "";
|
|
41302
|
+
}).filter((s) => s.length > 0).join(`
|
|
41303
|
+
`);
|
|
41304
|
+
}
|
|
41305
|
+
case "blockquote": {
|
|
41306
|
+
const body = renderBlocks2(b.blocks, depth);
|
|
41307
|
+
const credit = renderRichText2(b.credit, depth);
|
|
41308
|
+
const quoted = body.split(`
|
|
41309
|
+
`).map((line) => `> ${line}`).join(`
|
|
41310
|
+
`);
|
|
41311
|
+
return [quoted, credit ? `> \u2014 ${credit}` : ""].filter((s) => s.length > 0).join(`
|
|
41312
|
+
`);
|
|
41313
|
+
}
|
|
41314
|
+
case "pullquote": {
|
|
41315
|
+
const body = renderRichText2(b.text, depth);
|
|
41316
|
+
const credit = renderRichText2(b.credit, depth);
|
|
41317
|
+
return [body, credit ? `\u2014 ${credit}` : ""].filter(Boolean).join(" ");
|
|
41318
|
+
}
|
|
41319
|
+
case "details": {
|
|
41320
|
+
const summary = renderRichText2(b.summary, depth);
|
|
41321
|
+
const body = renderBlocks2(b.blocks, depth);
|
|
41322
|
+
return [summary, body].filter((s) => s.length > 0).join(`
|
|
41323
|
+
`);
|
|
41324
|
+
}
|
|
41325
|
+
case "collage":
|
|
41326
|
+
case "slideshow": {
|
|
41327
|
+
const body = renderBlocks2(b.blocks, depth);
|
|
41328
|
+
const caption = renderCaption2(b.caption, depth);
|
|
41329
|
+
return [body, caption].filter((s) => s.length > 0).join(`
|
|
41330
|
+
`);
|
|
41331
|
+
}
|
|
41332
|
+
case "table": {
|
|
41333
|
+
if (!Array.isArray(b.cells))
|
|
41334
|
+
return "";
|
|
41335
|
+
const rows = b.cells.map((row) => Array.isArray(row) ? row.map((cell) => renderRichText2(cell?.text, depth)).join(" | ") : "").filter((s) => s.length > 0).join(`
|
|
41336
|
+
`);
|
|
41337
|
+
const caption = renderRichText2(b.caption, depth);
|
|
41338
|
+
return [caption, rows].filter((s) => s.length > 0).join(`
|
|
41339
|
+
`);
|
|
41340
|
+
}
|
|
41341
|
+
case "map":
|
|
41342
|
+
case "animation":
|
|
41343
|
+
case "audio":
|
|
41344
|
+
case "photo":
|
|
41345
|
+
case "video":
|
|
41346
|
+
case "voice_note": {
|
|
41347
|
+
const caption = renderCaption2(b.caption, depth);
|
|
41348
|
+
const tag = `[${b.type}]`;
|
|
41349
|
+
return caption.length > 0 ? `${tag} ${caption}` : tag;
|
|
41350
|
+
}
|
|
41351
|
+
case "thinking":
|
|
41352
|
+
return "";
|
|
41353
|
+
default: {
|
|
41354
|
+
const text = renderRichText2(b.text, depth);
|
|
41355
|
+
if (text.length > 0)
|
|
41356
|
+
return text;
|
|
41357
|
+
return renderBlocks2(b.blocks, depth);
|
|
41358
|
+
}
|
|
41359
|
+
}
|
|
41360
|
+
}
|
|
41361
|
+
function extractRichMessageText2(rich) {
|
|
41362
|
+
if (rich == null || typeof rich !== "object")
|
|
41363
|
+
return;
|
|
41364
|
+
const blocks = rich.blocks;
|
|
41365
|
+
const rendered = renderBlocks2(blocks, 0).replace(/\n{3,}/g, `
|
|
41366
|
+
|
|
41367
|
+
`).trim();
|
|
41368
|
+
return rendered.length > 0 ? rendered : undefined;
|
|
41369
|
+
}
|
|
41370
|
+
async function handleRichMessageMessage(ctx, deps) {
|
|
41371
|
+
try {
|
|
41372
|
+
const text = extractRichMessageText2(ctx.message.rich_message) ?? RICH_MESSAGE_EMPTY_TEXT;
|
|
41373
|
+
deps.log(`telegram gateway: inbound rich_message from chat=${ctx.chat?.id ?? "?"} chars=${text.length}
|
|
41374
|
+
`);
|
|
41375
|
+
await deps.handleInbound(ctx, text, undefined);
|
|
41376
|
+
} catch (err) {
|
|
41377
|
+
deps.log(`telegram gateway: rich_message handler error: ${err.message}
|
|
41378
|
+
`);
|
|
41379
|
+
}
|
|
41380
|
+
}
|
|
41381
|
+
|
|
41094
41382
|
// gateway/stop-command.ts
|
|
41095
41383
|
function parseStopKeyword2(text) {
|
|
41096
41384
|
return /^stop[.!]?$/i.test(text.trim());
|
|
@@ -42712,6 +43000,8 @@ function buildForwardOriginMeta(origins) {
|
|
|
42712
43000
|
if (o.date != null) {
|
|
42713
43001
|
out[`forwarded_date${suffix}`] = fmtLocalStamp(o.date * 1000, resolveEnvTimezone());
|
|
42714
43002
|
}
|
|
43003
|
+
if (o.messageId != null)
|
|
43004
|
+
out[`forwarded_message_id${suffix}`] = String(o.messageId);
|
|
42715
43005
|
});
|
|
42716
43006
|
return out;
|
|
42717
43007
|
}
|
|
@@ -61243,7 +61533,7 @@ function prefixLines(text4, prefix) {
|
|
|
61243
61533
|
`);
|
|
61244
61534
|
}
|
|
61245
61535
|
function renderBlockquote(node2) {
|
|
61246
|
-
const inner =
|
|
61536
|
+
const inner = renderBlocks3(node2.children);
|
|
61247
61537
|
if (node2.expandable) {
|
|
61248
61538
|
const lines = inner.split(`
|
|
61249
61539
|
`);
|
|
@@ -61339,7 +61629,7 @@ function renderBlock(node2) {
|
|
|
61339
61629
|
function renderBlocksJoined(blocks, sep2) {
|
|
61340
61630
|
return blocks.map(renderBlock).join(sep2);
|
|
61341
61631
|
}
|
|
61342
|
-
function
|
|
61632
|
+
function renderBlocks3(blocks) {
|
|
61343
61633
|
return renderBlocksJoined(blocks, `
|
|
61344
61634
|
|
|
61345
61635
|
`);
|
|
@@ -74010,6 +74300,33 @@ function readDeliveredNonces(stateDir) {
|
|
|
74010
74300
|
} catch {}
|
|
74011
74301
|
return set;
|
|
74012
74302
|
}
|
|
74303
|
+
function isBackstopDeliveredEntry(e) {
|
|
74304
|
+
if (e.deliverySource === "sweep" || e.deliverySource === "flush")
|
|
74305
|
+
return true;
|
|
74306
|
+
if (e.deliverySource === "reply-tool" && e.replyAlreadyDeliveredThisTurn === false)
|
|
74307
|
+
return true;
|
|
74308
|
+
return false;
|
|
74309
|
+
}
|
|
74310
|
+
function backstopAlreadyDelivered(nonce, stateDir) {
|
|
74311
|
+
if (nonce == null || nonce === "")
|
|
74312
|
+
return false;
|
|
74313
|
+
const path2 = join28(resolveOutboxDir(stateDir), JOURNAL_FILE);
|
|
74314
|
+
if (!existsSync24(path2))
|
|
74315
|
+
return false;
|
|
74316
|
+
try {
|
|
74317
|
+
for (const line of readFileSync24(path2, "utf8").split(`
|
|
74318
|
+
`)) {
|
|
74319
|
+
if (!line)
|
|
74320
|
+
continue;
|
|
74321
|
+
try {
|
|
74322
|
+
const e = JSON.parse(line);
|
|
74323
|
+
if (e.turnNonce === nonce && isBackstopDeliveredEntry(e))
|
|
74324
|
+
return true;
|
|
74325
|
+
} catch {}
|
|
74326
|
+
}
|
|
74327
|
+
} catch {}
|
|
74328
|
+
return false;
|
|
74329
|
+
}
|
|
74013
74330
|
var JOURNAL_KEEP = 2000;
|
|
74014
74331
|
var JOURNAL_ROTATE_AT = 4000;
|
|
74015
74332
|
function appendDelivered(entry, stateDir) {
|
|
@@ -74053,10 +74370,13 @@ function decideOutboxSweep(input) {
|
|
|
74053
74370
|
routable,
|
|
74054
74371
|
routePrefix = "",
|
|
74055
74372
|
quietMs = OUTBOX_QUIET_MS,
|
|
74056
|
-
maxAgeMs = OUTBOX_MAX_AGE_MS
|
|
74373
|
+
maxAgeMs = OUTBOX_MAX_AGE_MS,
|
|
74374
|
+
shownLedgerHit = false
|
|
74057
74375
|
} = input;
|
|
74058
74376
|
if (deliveredNonces.has(record.turnNonce))
|
|
74059
74377
|
return { action: "skip-journaled" };
|
|
74378
|
+
if (shownLedgerHit)
|
|
74379
|
+
return { action: "skip-ephemeral-shown" };
|
|
74060
74380
|
const age = now - record.createdAt;
|
|
74061
74381
|
if (age < quietMs)
|
|
74062
74382
|
return { action: "skip-quiet" };
|
|
@@ -74089,6 +74409,149 @@ function extractTaskId(anchorContent) {
|
|
|
74089
74409
|
return m ? m[1] : null;
|
|
74090
74410
|
}
|
|
74091
74411
|
|
|
74412
|
+
// shown-ledger.ts
|
|
74413
|
+
import {
|
|
74414
|
+
existsSync as existsSync25,
|
|
74415
|
+
mkdirSync as mkdirSync26,
|
|
74416
|
+
readFileSync as readFileSync25,
|
|
74417
|
+
renameSync as renameSync9,
|
|
74418
|
+
writeFileSync as writeFileSync23,
|
|
74419
|
+
appendFileSync as appendFileSync5
|
|
74420
|
+
} from "node:fs";
|
|
74421
|
+
import { join as join29 } from "node:path";
|
|
74422
|
+
|
|
74423
|
+
// hooks/narration-classify.mjs
|
|
74424
|
+
import { createHash as createHash4 } from "node:crypto";
|
|
74425
|
+
var SUBSTANTIVE_MIN_CHARS = 200;
|
|
74426
|
+
var NARRATION_OPENER = /^(let me\b|lemme\b|i'?ll\b|i will\b|i am going to\b|i'?m going to\b|i'?m about to\b|going to\b|first,?\s+(?:let me|i'?ll|i will)\b|now,?\s+(?:let me|i'?ll|i will)\b|next,?\s+(?:let me|i'?ll|i will)\b|let'?s\b)/i;
|
|
74427
|
+
var NARRATION_TRAILER = /(?:\.{3}|\u2026|:)\s*$/;
|
|
74428
|
+
function isTrailingNarrationLine(block) {
|
|
74429
|
+
const t = typeof block === "string" ? block.trim() : "";
|
|
74430
|
+
if (t.length === 0 || t.length >= SUBSTANTIVE_MIN_CHARS)
|
|
74431
|
+
return false;
|
|
74432
|
+
if (t.includes(`
|
|
74433
|
+
`))
|
|
74434
|
+
return false;
|
|
74435
|
+
return NARRATION_TRAILER.test(t);
|
|
74436
|
+
}
|
|
74437
|
+
function isNarrationBlock(block) {
|
|
74438
|
+
const s = typeof block === "string" ? block : "";
|
|
74439
|
+
return NARRATION_OPENER.test(s.trimStart()) || isTrailingNarrationLine(s);
|
|
74440
|
+
}
|
|
74441
|
+
function isStructuralNarration(text4, followedByToolUse) {
|
|
74442
|
+
if (followedByToolUse !== true)
|
|
74443
|
+
return false;
|
|
74444
|
+
const t = typeof text4 === "string" ? text4.trim() : "";
|
|
74445
|
+
if (t.length === 0)
|
|
74446
|
+
return true;
|
|
74447
|
+
return isNarrationBlock(t) || t.length < SUBSTANTIVE_MIN_CHARS;
|
|
74448
|
+
}
|
|
74449
|
+
var EPHEMERAL_TOOLS = new Set([
|
|
74450
|
+
"react",
|
|
74451
|
+
"send_typing",
|
|
74452
|
+
"pin_message",
|
|
74453
|
+
"delete_message",
|
|
74454
|
+
"edit_message"
|
|
74455
|
+
]);
|
|
74456
|
+
function isEphemeralTool(name) {
|
|
74457
|
+
if (typeof name !== "string")
|
|
74458
|
+
return false;
|
|
74459
|
+
const suffix = name.replace(/^mcp__[^_].*?telegram__/, "");
|
|
74460
|
+
return EPHEMERAL_TOOLS.has(suffix);
|
|
74461
|
+
}
|
|
74462
|
+
function selectBackstopDelivery(blocks) {
|
|
74463
|
+
const nonEmpty = (Array.isArray(blocks) ? blocks : []).map((b) => ({
|
|
74464
|
+
text: typeof b?.text === "string" ? b.text.trim() : "",
|
|
74465
|
+
followedByToolUse: b?.followedByToolUse
|
|
74466
|
+
})).filter((b) => b.text.length > 0);
|
|
74467
|
+
if (nonEmpty.length === 0)
|
|
74468
|
+
return null;
|
|
74469
|
+
const run3 = [];
|
|
74470
|
+
for (let i = nonEmpty.length - 1;i >= 0; i--) {
|
|
74471
|
+
if (nonEmpty[i].followedByToolUse === true)
|
|
74472
|
+
break;
|
|
74473
|
+
run3.unshift(nonEmpty[i].text);
|
|
74474
|
+
}
|
|
74475
|
+
if (run3.length > 0)
|
|
74476
|
+
return { text: run3.join(`
|
|
74477
|
+
|
|
74478
|
+
`) };
|
|
74479
|
+
const last = nonEmpty[nonEmpty.length - 1];
|
|
74480
|
+
if (last.text.length >= SUBSTANTIVE_MIN_CHARS)
|
|
74481
|
+
return { text: last.text };
|
|
74482
|
+
return null;
|
|
74483
|
+
}
|
|
74484
|
+
function ledgerHashHex(text4) {
|
|
74485
|
+
return createHash4("sha256").update(String(text4 ?? "").trim(), "utf8").digest("hex");
|
|
74486
|
+
}
|
|
74487
|
+
|
|
74488
|
+
// shown-ledger.ts
|
|
74489
|
+
var SHOWN_LEDGER_FILE = "shown-ledger.jsonl";
|
|
74490
|
+
var SHOWN_LEDGER_KEEP = 2000;
|
|
74491
|
+
var SHOWN_LEDGER_ROTATE_AT = 4000;
|
|
74492
|
+
function shownLedgerPath(stateDir) {
|
|
74493
|
+
return join29(resolveOutboxDir(stateDir), SHOWN_LEDGER_FILE);
|
|
74494
|
+
}
|
|
74495
|
+
function appendShownBlock(turnNonce, text4, stateDir, now = Date.now()) {
|
|
74496
|
+
if (turnNonce == null || turnNonce === "")
|
|
74497
|
+
return;
|
|
74498
|
+
const trimmed = typeof text4 === "string" ? text4.trim() : "";
|
|
74499
|
+
if (trimmed.length === 0)
|
|
74500
|
+
return;
|
|
74501
|
+
const dir = resolveOutboxDir(stateDir);
|
|
74502
|
+
const path2 = shownLedgerPath(stateDir);
|
|
74503
|
+
try {
|
|
74504
|
+
mkdirSync26(dir, { recursive: true });
|
|
74505
|
+
const entry = { turnNonce, hash: ledgerHashHex(trimmed), ts: now };
|
|
74506
|
+
appendFileSync5(path2, JSON.stringify(entry) + `
|
|
74507
|
+
`, { mode: 384 });
|
|
74508
|
+
compactIfLarge(path2);
|
|
74509
|
+
} catch {}
|
|
74510
|
+
}
|
|
74511
|
+
function readShownHashes(turnNonce, stateDir) {
|
|
74512
|
+
const set = new Set;
|
|
74513
|
+
if (turnNonce == null || turnNonce === "")
|
|
74514
|
+
return set;
|
|
74515
|
+
const path2 = shownLedgerPath(stateDir);
|
|
74516
|
+
if (!existsSync25(path2))
|
|
74517
|
+
return set;
|
|
74518
|
+
try {
|
|
74519
|
+
for (const line of readFileSync25(path2, "utf8").split(`
|
|
74520
|
+
`)) {
|
|
74521
|
+
if (!line)
|
|
74522
|
+
continue;
|
|
74523
|
+
try {
|
|
74524
|
+
const e = JSON.parse(line);
|
|
74525
|
+
if (e.turnNonce === turnNonce && typeof e.hash === "string")
|
|
74526
|
+
set.add(e.hash);
|
|
74527
|
+
} catch {}
|
|
74528
|
+
}
|
|
74529
|
+
} catch {}
|
|
74530
|
+
return set;
|
|
74531
|
+
}
|
|
74532
|
+
function isShownBlock(turnNonce, text4, stateDir) {
|
|
74533
|
+
if (turnNonce == null || turnNonce === "")
|
|
74534
|
+
return false;
|
|
74535
|
+
const trimmed = typeof text4 === "string" ? text4.trim() : "";
|
|
74536
|
+
if (trimmed.length === 0)
|
|
74537
|
+
return false;
|
|
74538
|
+
return readShownHashes(turnNonce, stateDir).has(ledgerHashHex(trimmed));
|
|
74539
|
+
}
|
|
74540
|
+
function compactIfLarge(path2) {
|
|
74541
|
+
try {
|
|
74542
|
+
const lines = readFileSync25(path2, "utf8").split(`
|
|
74543
|
+
`).filter((l) => l.length > 0);
|
|
74544
|
+
if (lines.length <= SHOWN_LEDGER_ROTATE_AT)
|
|
74545
|
+
return;
|
|
74546
|
+
const kept = lines.slice(lines.length - SHOWN_LEDGER_KEEP);
|
|
74547
|
+
const tmp = `${path2}.${process.pid}.compact`;
|
|
74548
|
+
writeFileSync23(tmp, kept.join(`
|
|
74549
|
+
`) + `
|
|
74550
|
+
`, { mode: 384 });
|
|
74551
|
+
renameSync9(tmp, path2);
|
|
74552
|
+
} catch {}
|
|
74553
|
+
}
|
|
74554
|
+
|
|
74092
74555
|
// registry/subagents-schema.ts
|
|
74093
74556
|
function countRunningBackgroundSubagents(db2) {
|
|
74094
74557
|
const row = db2.prepare("SELECT count(*) AS n FROM subagents WHERE background = 1 AND status = 'running'").get();
|
|
@@ -74211,7 +74674,7 @@ function journalExternalDelivery(args, stateDir, now = Date.now()) {
|
|
|
74211
74674
|
textSha256: sha256Hex(args.text),
|
|
74212
74675
|
tgMessageId: args.tgMessageId,
|
|
74213
74676
|
ts: now,
|
|
74214
|
-
deliverySource: "reply-tool",
|
|
74677
|
+
deliverySource: args.deliverySource ?? "reply-tool",
|
|
74215
74678
|
...args.replyAlreadyDeliveredThisTurn == null ? {} : { replyAlreadyDeliveredThisTurn: args.replyAlreadyDeliveredThisTurn }
|
|
74216
74679
|
}, stateDir);
|
|
74217
74680
|
clearOutboxRecord(nonce, stateDir);
|
|
@@ -74606,8 +75069,8 @@ function monotonicNowMs2() {
|
|
|
74606
75069
|
}
|
|
74607
75070
|
|
|
74608
75071
|
// silent-end.ts
|
|
74609
|
-
import { existsSync as
|
|
74610
|
-
import { dirname as dirname11, join as
|
|
75072
|
+
import { existsSync as existsSync26, readFileSync as readFileSync26, writeFileSync as writeFileSync24, unlinkSync as unlinkSync13, mkdirSync as mkdirSync27 } from "node:fs";
|
|
75073
|
+
import { dirname as dirname11, join as join30 } from "node:path";
|
|
74611
75074
|
import { homedir as homedir11 } from "node:os";
|
|
74612
75075
|
var SILENT_END_MAX_RETRIES2 = 2;
|
|
74613
75076
|
var SILENT_END_STALE_RECORD_MAX_AGE_MS2 = 30 * 60000;
|
|
@@ -74622,10 +75085,10 @@ function resolveStateDir3(deps) {
|
|
|
74622
75085
|
if (env != null && env !== "")
|
|
74623
75086
|
return env;
|
|
74624
75087
|
const home2 = process.env.HOME ?? homedir11();
|
|
74625
|
-
return
|
|
75088
|
+
return join30(home2, ".claude", "channels", "telegram");
|
|
74626
75089
|
}
|
|
74627
75090
|
function resolveStatePath3(deps) {
|
|
74628
|
-
return
|
|
75091
|
+
return join30(resolveStateDir3(deps), "silent-end-pending.json");
|
|
74629
75092
|
}
|
|
74630
75093
|
function emitLog2(deps, line) {
|
|
74631
75094
|
if (deps?.log != null)
|
|
@@ -74637,8 +75100,8 @@ function writeSilentEndState2(args, deps) {
|
|
|
74637
75100
|
const statePath = resolveStatePath3(deps);
|
|
74638
75101
|
let retryCount = 0;
|
|
74639
75102
|
try {
|
|
74640
|
-
if (
|
|
74641
|
-
const prev = JSON.parse(
|
|
75103
|
+
if (existsSync26(statePath)) {
|
|
75104
|
+
const prev = JSON.parse(readFileSync26(statePath, "utf8"));
|
|
74642
75105
|
if (prev.turnKey === args.turnKey && typeof prev.retryCount === "number") {
|
|
74643
75106
|
retryCount = prev.retryCount;
|
|
74644
75107
|
}
|
|
@@ -74654,8 +75117,8 @@ function writeSilentEndState2(args, deps) {
|
|
|
74654
75117
|
timestamp: Date.now()
|
|
74655
75118
|
};
|
|
74656
75119
|
try {
|
|
74657
|
-
|
|
74658
|
-
|
|
75120
|
+
mkdirSync27(dirname11(statePath), { recursive: true });
|
|
75121
|
+
writeFileSync24(statePath, JSON.stringify(state3), "utf8");
|
|
74659
75122
|
emitLog2(deps, `silent-end: wrote state file turnKey=${args.turnKey} retryCount=${retryCount}
|
|
74660
75123
|
`);
|
|
74661
75124
|
} catch (err) {
|
|
@@ -74665,10 +75128,10 @@ function writeSilentEndState2(args, deps) {
|
|
|
74665
75128
|
}
|
|
74666
75129
|
function clearSilentEndState2(turnKey3, deps) {
|
|
74667
75130
|
const statePath = resolveStatePath3(deps);
|
|
74668
|
-
if (!
|
|
75131
|
+
if (!existsSync26(statePath))
|
|
74669
75132
|
return;
|
|
74670
75133
|
try {
|
|
74671
|
-
const prev = JSON.parse(
|
|
75134
|
+
const prev = JSON.parse(readFileSync26(statePath, "utf8"));
|
|
74672
75135
|
if (prev.turnKey != null && prev.turnKey !== turnKey3)
|
|
74673
75136
|
return;
|
|
74674
75137
|
unlinkSync13(statePath);
|
|
@@ -74690,6 +75153,12 @@ function decideCapturedProseDelivery(args, deps) {
|
|
|
74690
75153
|
const text4 = typeof state3.pendingText === "string" ? state3.pendingText : "";
|
|
74691
75154
|
if (text4.trim().length < minChars)
|
|
74692
75155
|
return { deliver: false, reason: "no-substantive-prose" };
|
|
75156
|
+
if (deps?.isBlockShown?.(state3.turnId, text4) === true) {
|
|
75157
|
+
return { deliver: false, reason: "ephemeral-shown" };
|
|
75158
|
+
}
|
|
75159
|
+
if (deps?.backstopDeliveredNonceHit?.(state3.turnId) === true) {
|
|
75160
|
+
return { deliver: false, reason: "already-delivered" };
|
|
75161
|
+
}
|
|
74693
75162
|
return { deliver: true, text: text4, reason: "captured-prose" };
|
|
74694
75163
|
}
|
|
74695
75164
|
function settleCapturedProseDelivery(outcome, effects) {
|
|
@@ -74702,10 +75171,10 @@ function settleCapturedProseDelivery(outcome, effects) {
|
|
|
74702
75171
|
}
|
|
74703
75172
|
function readSilentEndState2(deps) {
|
|
74704
75173
|
const statePath = resolveStatePath3(deps);
|
|
74705
|
-
if (!
|
|
75174
|
+
if (!existsSync26(statePath))
|
|
74706
75175
|
return null;
|
|
74707
75176
|
try {
|
|
74708
|
-
return JSON.parse(
|
|
75177
|
+
return JSON.parse(readFileSync26(statePath, "utf8"));
|
|
74709
75178
|
} catch {
|
|
74710
75179
|
return null;
|
|
74711
75180
|
}
|
|
@@ -75825,34 +76294,6 @@ function endsWithSilentMarker(text4) {
|
|
|
75825
76294
|
return false;
|
|
75826
76295
|
return isSilentFlushMarker(lines[lines.length - 1]);
|
|
75827
76296
|
}
|
|
75828
|
-
var FLUSH_SUBSTANTIVE_MIN_CHARS = 200;
|
|
75829
|
-
function selectFlushDeliveryText(blocks, followedByToolUse) {
|
|
75830
|
-
const candidates = blocks.map((b, i) => ({ text: b.trim(), followedByToolUse: followedByToolUse?.[i] })).filter((c) => c.text.length > 0);
|
|
75831
|
-
if (candidates.length === 0)
|
|
75832
|
-
return "";
|
|
75833
|
-
if (candidates.length === 1)
|
|
75834
|
-
return candidates[0].text;
|
|
75835
|
-
const answer = candidates[candidates.length - 1].text;
|
|
75836
|
-
const preceding = candidates.slice(0, -1);
|
|
75837
|
-
const allNarration = preceding.every((c) => c.followedByToolUse === true ? isNarrationBlock(c.text) || c.text.trim().length < FLUSH_SUBSTANTIVE_MIN_CHARS : c.followedByToolUse === false ? false : isNarrationBlock(c.text));
|
|
75838
|
-
return allNarration ? answer : candidates.map((c) => c.text).join(`
|
|
75839
|
-
|
|
75840
|
-
`);
|
|
75841
|
-
}
|
|
75842
|
-
var NARRATION_OPENER = /^(let me\b|lemme\b|i'?ll\b|i will\b|i am going to\b|i'?m going to\b|i'?m about to\b|going to\b|first,?\s+(?:let me|i'?ll|i will)\b|now,?\s+(?:let me|i'?ll|i will)\b|next,?\s+(?:let me|i'?ll|i will)\b|let'?s\b)/i;
|
|
75843
|
-
var NARRATION_TRAILER = /(?:\.{3}|\u2026|:)\s*$/;
|
|
75844
|
-
function isTrailingNarrationLine(block) {
|
|
75845
|
-
const t = block.trim();
|
|
75846
|
-
if (t.length === 0 || t.length >= FLUSH_SUBSTANTIVE_MIN_CHARS)
|
|
75847
|
-
return false;
|
|
75848
|
-
if (t.includes(`
|
|
75849
|
-
`))
|
|
75850
|
-
return false;
|
|
75851
|
-
return NARRATION_TRAILER.test(t);
|
|
75852
|
-
}
|
|
75853
|
-
function isNarrationBlock(block) {
|
|
75854
|
-
return NARRATION_OPENER.test(block.trimStart()) || isTrailingNarrationLine(block);
|
|
75855
|
-
}
|
|
75856
76297
|
function decideTurnFlush(input) {
|
|
75857
76298
|
const flushEnabled = input.flushEnabled !== false;
|
|
75858
76299
|
if (!flushEnabled)
|
|
@@ -75872,10 +76313,14 @@ function decideTurnFlush(input) {
|
|
|
75872
76313
|
return { kind: "skip", reason: "silent-marker" };
|
|
75873
76314
|
if (endsWithSilentMarker(joined))
|
|
75874
76315
|
return { kind: "skip", reason: "silent-marker" };
|
|
75875
|
-
|
|
75876
|
-
|
|
75877
|
-
|
|
75878
|
-
};
|
|
76316
|
+
const selected = selectBackstopDelivery(input.capturedText.map((text4, i) => ({
|
|
76317
|
+
text: text4,
|
|
76318
|
+
followedByToolUse: input.capturedBlockMeta?.[i]
|
|
76319
|
+
})));
|
|
76320
|
+
if (selected == null || selected.text.trim().length === 0) {
|
|
76321
|
+
return { kind: "skip", reason: "empty-text" };
|
|
76322
|
+
}
|
|
76323
|
+
return { kind: "flush", text: selected.text };
|
|
75879
76324
|
}
|
|
75880
76325
|
|
|
75881
76326
|
// answer-stream.ts
|
|
@@ -76265,20 +76710,20 @@ var INTERRUPTED_VIA = new Set([
|
|
|
76265
76710
|
init_rich_send();
|
|
76266
76711
|
|
|
76267
76712
|
// runtime-metrics.ts
|
|
76268
|
-
import { mkdirSync as
|
|
76269
|
-
import { dirname as dirname12, join as
|
|
76713
|
+
import { mkdirSync as mkdirSync29, appendFileSync as appendFileSync6 } from "node:fs";
|
|
76714
|
+
import { dirname as dirname12, join as join32 } from "node:path";
|
|
76270
76715
|
function resolveJsonlPath2() {
|
|
76271
76716
|
const override = process.env.SWITCHROOM_RUNTIME_METRICS_PATH;
|
|
76272
76717
|
if (override && override.trim() !== "")
|
|
76273
76718
|
return override.trim();
|
|
76274
76719
|
const base = process.env.SWITCHROOM_RUNTIME_STATE_DIR ?? "/state/agent";
|
|
76275
|
-
return
|
|
76720
|
+
return join32(base, "runtime-metrics.jsonl");
|
|
76276
76721
|
}
|
|
76277
76722
|
function appendJsonl2(line) {
|
|
76278
76723
|
const path2 = resolveJsonlPath2();
|
|
76279
76724
|
try {
|
|
76280
|
-
|
|
76281
|
-
|
|
76725
|
+
mkdirSync29(dirname12(path2), { recursive: true });
|
|
76726
|
+
appendFileSync6(path2, line + `
|
|
76282
76727
|
`, "utf-8");
|
|
76283
76728
|
} catch (err) {
|
|
76284
76729
|
process.stderr.write(`runtime-metrics: jsonl write failed: ${err.message}
|
|
@@ -76768,28 +77213,28 @@ function detectStatusSurfaceDegraded(t) {
|
|
|
76768
77213
|
// gateway/turn-active-marker.ts
|
|
76769
77214
|
import {
|
|
76770
77215
|
closeSync as closeSync5,
|
|
76771
|
-
existsSync as
|
|
76772
|
-
mkdirSync as
|
|
77216
|
+
existsSync as existsSync29,
|
|
77217
|
+
mkdirSync as mkdirSync30,
|
|
76773
77218
|
openSync as openSync5,
|
|
76774
|
-
readFileSync as
|
|
77219
|
+
readFileSync as readFileSync27,
|
|
76775
77220
|
statSync as statSync11,
|
|
76776
77221
|
unlinkSync as unlinkSync14,
|
|
76777
77222
|
utimesSync,
|
|
76778
|
-
writeFileSync as
|
|
77223
|
+
writeFileSync as writeFileSync25
|
|
76779
77224
|
} from "node:fs";
|
|
76780
|
-
import { join as
|
|
77225
|
+
import { join as join33 } from "node:path";
|
|
76781
77226
|
var TURN_ACTIVE_MARKER_FILE = "turn-active.json";
|
|
76782
77227
|
var TURN_ACTIVE_HARD_TTL_MS = 10 * 60000;
|
|
76783
77228
|
function writeTurnActiveMarker(stateDir, marker) {
|
|
76784
77229
|
try {
|
|
76785
|
-
|
|
76786
|
-
|
|
77230
|
+
mkdirSync30(stateDir, { recursive: true });
|
|
77231
|
+
writeFileSync25(join33(stateDir, TURN_ACTIVE_MARKER_FILE), JSON.stringify(marker, null, 2) + `
|
|
76787
77232
|
`, { mode: 384 });
|
|
76788
77233
|
} catch {}
|
|
76789
77234
|
}
|
|
76790
77235
|
function touchTurnActiveMarker(stateDir) {
|
|
76791
|
-
const path2 =
|
|
76792
|
-
if (!
|
|
77236
|
+
const path2 = join33(stateDir, TURN_ACTIVE_MARKER_FILE);
|
|
77237
|
+
if (!existsSync29(path2))
|
|
76793
77238
|
return;
|
|
76794
77239
|
const now = new Date;
|
|
76795
77240
|
try {
|
|
@@ -76803,11 +77248,11 @@ function touchTurnActiveMarker(stateDir) {
|
|
|
76803
77248
|
}
|
|
76804
77249
|
function removeTurnActiveMarker(stateDir) {
|
|
76805
77250
|
try {
|
|
76806
|
-
unlinkSync14(
|
|
77251
|
+
unlinkSync14(join33(stateDir, TURN_ACTIVE_MARKER_FILE));
|
|
76807
77252
|
} catch {}
|
|
76808
77253
|
}
|
|
76809
77254
|
function readTurnActiveMarkerAgeMs(stateDir, now) {
|
|
76810
|
-
const path2 =
|
|
77255
|
+
const path2 = join33(stateDir, TURN_ACTIVE_MARKER_FILE);
|
|
76811
77256
|
try {
|
|
76812
77257
|
const st = statSync11(path2);
|
|
76813
77258
|
return (now ?? Date.now()) - st.mtimeMs;
|
|
@@ -77229,7 +77674,10 @@ function handleSessionEvent(deps, ev) {
|
|
|
77229
77674
|
const turn = getCurrentTurn();
|
|
77230
77675
|
if (turn == null)
|
|
77231
77676
|
return;
|
|
77232
|
-
|
|
77677
|
+
if (!isEphemeralTool(ev.toolName)) {
|
|
77678
|
+
turn.capturedBlockMeta.fill(true);
|
|
77679
|
+
clearAnswerReadyFlushTimeout(turn);
|
|
77680
|
+
}
|
|
77233
77681
|
resolvePendingNarrativeOnTool(turn, ev.toolName, ev.input);
|
|
77234
77682
|
turn.toolCallCount++;
|
|
77235
77683
|
touchTurnActiveMarker(STATE_DIR);
|
|
@@ -77264,7 +77712,9 @@ function handleSessionEvent(deps, ev) {
|
|
|
77264
77712
|
const turn = getCurrentTurn();
|
|
77265
77713
|
if (turn == null)
|
|
77266
77714
|
return;
|
|
77267
|
-
|
|
77715
|
+
if (!isEphemeralTool(ev.toolName)) {
|
|
77716
|
+
clearAnswerReadyFlushTimeout(turn);
|
|
77717
|
+
}
|
|
77268
77718
|
resetOrphanedReplyTimeout();
|
|
77269
77719
|
if (isTelegramSurfaceTool(ev.toolName))
|
|
77270
77720
|
return;
|
|
@@ -77642,6 +78092,11 @@ function handleSessionEvent(deps, ev) {
|
|
|
77642
78092
|
}
|
|
77643
78093
|
} catch {}
|
|
77644
78094
|
}
|
|
78095
|
+
if (backstopAlreadyDelivered(turn.turnId, STATE_DIR)) {
|
|
78096
|
+
process.stderr.write(`telegram gateway: turn-flush skipped \u2014 turn ${turn.turnId} already delivered by a prior backstop (durable journal)
|
|
78097
|
+
`);
|
|
78098
|
+
return;
|
|
78099
|
+
}
|
|
77645
78100
|
if (!backstopLatchClaimed) {
|
|
77646
78101
|
process.stderr.write(`telegram gateway: turn-flush skipped \u2014 turn ${turn.turnId} already claimed the delivery latch
|
|
77647
78102
|
`);
|
|
@@ -77704,6 +78159,19 @@ function handleSessionEvent(deps, ev) {
|
|
|
77704
78159
|
chunkCount,
|
|
77705
78160
|
cardMessageId: backstopCardMessageId
|
|
77706
78161
|
});
|
|
78162
|
+
if (delivered) {
|
|
78163
|
+
try {
|
|
78164
|
+
journalExternalDelivery({
|
|
78165
|
+
turnNonce: turn.turnId,
|
|
78166
|
+
text: capturedText,
|
|
78167
|
+
tgMessageId: sentIds.length > 0 ? sentIds[0] : undefined,
|
|
78168
|
+
deliverySource: "flush"
|
|
78169
|
+
}, STATE_DIR);
|
|
78170
|
+
} catch (err) {
|
|
78171
|
+
process.stderr.write(`telegram gateway: turn-flush delivered but journal write failed (non-fatal): ${err.message}
|
|
78172
|
+
`);
|
|
78173
|
+
}
|
|
78174
|
+
}
|
|
77707
78175
|
if (OBLIGATION_LEDGER_ENABLED) {
|
|
77708
78176
|
if (delivered) {
|
|
77709
78177
|
obligationLedger.close(turn.turnId);
|
|
@@ -77764,6 +78232,9 @@ function handleSessionEvent(deps, ev) {
|
|
|
77764
78232
|
turnKey: tKey,
|
|
77765
78233
|
turnId: turn.turnId,
|
|
77766
78234
|
minChars: proseMinChars
|
|
78235
|
+
}, {
|
|
78236
|
+
isBlockShown: (nonce, text4) => isShownBlock(nonce ?? null, text4),
|
|
78237
|
+
backstopDeliveredNonceHit: (nonce) => backstopAlreadyDelivered(nonce ?? "", STATE_DIR)
|
|
77767
78238
|
}) : { deliver: false, reason: "no-state" };
|
|
77768
78239
|
if (proseDecision.deliver && proseDecision.text != null) {
|
|
77769
78240
|
process.stderr.write(`telegram gateway: captured-prose delivery engaged on first silent-end chat=${chatId} turnKey=${tKey} (#3227)
|
|
@@ -77903,6 +78374,7 @@ class NarrativeFlushController {
|
|
|
77903
78374
|
this.scheduler.disarm();
|
|
77904
78375
|
if (this.pending != null) {
|
|
77905
78376
|
this.effects.show(this.pending);
|
|
78377
|
+
this.markShown(this.pending);
|
|
77906
78378
|
}
|
|
77907
78379
|
this.pending = text4;
|
|
77908
78380
|
this.scheduler.arm(() => this.onTimerFire(), this.flushMs);
|
|
@@ -77927,6 +78399,7 @@ class NarrativeFlushController {
|
|
|
77927
78399
|
if (replyText != null && isDraftOfReply(pending, replyText))
|
|
77928
78400
|
return;
|
|
77929
78401
|
this.effects.show(pending);
|
|
78402
|
+
this.markShown(pending);
|
|
77930
78403
|
}
|
|
77931
78404
|
flushAtTurnEnd(lastReplyText) {
|
|
77932
78405
|
this.scheduler.disarm();
|
|
@@ -77945,6 +78418,13 @@ class NarrativeFlushController {
|
|
|
77945
78418
|
this.pending = null;
|
|
77946
78419
|
this.timerShown = null;
|
|
77947
78420
|
}
|
|
78421
|
+
markShown(text4) {
|
|
78422
|
+
if (this.effects.markDurableNarration == null)
|
|
78423
|
+
return;
|
|
78424
|
+
if (!isStructuralNarration(text4, true))
|
|
78425
|
+
return;
|
|
78426
|
+
this.effects.markDurableNarration(text4);
|
|
78427
|
+
}
|
|
77948
78428
|
maybeRetract(replyText) {
|
|
77949
78429
|
const shown = this.timerShown;
|
|
77950
78430
|
if (shown == null)
|
|
@@ -78096,7 +78576,12 @@ function createNarrativeLane(deps) {
|
|
|
78096
78576
|
let handle = null;
|
|
78097
78577
|
return new NarrativeFlushController({
|
|
78098
78578
|
show: (text4) => showNarrativeStep(turn, text4),
|
|
78099
|
-
retractShown: (text4) => retractNarrativeLine(turn, text4)
|
|
78579
|
+
retractShown: (text4) => retractNarrativeLine(turn, text4),
|
|
78580
|
+
markDurableNarration: (text4) => {
|
|
78581
|
+
if (turn.turnId == null)
|
|
78582
|
+
return;
|
|
78583
|
+
appendShownBlock(turn.turnId, text4);
|
|
78584
|
+
}
|
|
78100
78585
|
}, {
|
|
78101
78586
|
arm: (fn, ms) => {
|
|
78102
78587
|
if (handle != null)
|
|
@@ -78694,19 +79179,19 @@ function resolveAgentDirFromEnv() {
|
|
|
78694
79179
|
}
|
|
78695
79180
|
|
|
78696
79181
|
// active-reactions.ts
|
|
78697
|
-
import { readFileSync as
|
|
78698
|
-
import { join as
|
|
79182
|
+
import { readFileSync as readFileSync28, writeFileSync as writeFileSync26, renameSync as renameSync10, existsSync as existsSync30, unlinkSync as unlinkSync15 } from "node:fs";
|
|
79183
|
+
import { join as join34 } from "node:path";
|
|
78699
79184
|
var ACTIVE_REACTIONS_FILENAME = ".active-reactions.json";
|
|
78700
79185
|
function reactionsPath(agentDir) {
|
|
78701
|
-
return
|
|
79186
|
+
return join34(agentDir, ACTIVE_REACTIONS_FILENAME);
|
|
78702
79187
|
}
|
|
78703
79188
|
function readActiveReactions(agentDir) {
|
|
78704
79189
|
const p = reactionsPath(agentDir);
|
|
78705
|
-
if (!
|
|
79190
|
+
if (!existsSync30(p))
|
|
78706
79191
|
return [];
|
|
78707
79192
|
let raw;
|
|
78708
79193
|
try {
|
|
78709
|
-
raw =
|
|
79194
|
+
raw = readFileSync28(p, "utf-8");
|
|
78710
79195
|
} catch {
|
|
78711
79196
|
return [];
|
|
78712
79197
|
}
|
|
@@ -78738,9 +79223,9 @@ function writeActiveReactions(agentDir, reactions) {
|
|
|
78738
79223
|
}
|
|
78739
79224
|
const tmp = `${p}.tmp-${process.pid}-${Date.now()}`;
|
|
78740
79225
|
try {
|
|
78741
|
-
|
|
79226
|
+
writeFileSync26(tmp, JSON.stringify(reactions) + `
|
|
78742
79227
|
`, "utf-8");
|
|
78743
|
-
|
|
79228
|
+
renameSync10(tmp, p);
|
|
78744
79229
|
} catch {}
|
|
78745
79230
|
}
|
|
78746
79231
|
function addActiveReaction(agentDir, reaction) {
|
|
@@ -78762,19 +79247,19 @@ function clearActiveReactions(agentDir) {
|
|
|
78762
79247
|
}
|
|
78763
79248
|
|
|
78764
79249
|
// active-reactions.ts
|
|
78765
|
-
import { readFileSync as
|
|
78766
|
-
import { join as
|
|
79250
|
+
import { readFileSync as readFileSync29, writeFileSync as writeFileSync27, renameSync as renameSync11, existsSync as existsSync31, unlinkSync as unlinkSync16 } from "node:fs";
|
|
79251
|
+
import { join as join35 } from "node:path";
|
|
78767
79252
|
var ACTIVE_REACTIONS_FILENAME2 = ".active-reactions.json";
|
|
78768
79253
|
function reactionsPath2(agentDir) {
|
|
78769
|
-
return
|
|
79254
|
+
return join35(agentDir, ACTIVE_REACTIONS_FILENAME2);
|
|
78770
79255
|
}
|
|
78771
79256
|
function readActiveReactions2(agentDir) {
|
|
78772
79257
|
const p = reactionsPath2(agentDir);
|
|
78773
|
-
if (!
|
|
79258
|
+
if (!existsSync31(p))
|
|
78774
79259
|
return [];
|
|
78775
79260
|
let raw;
|
|
78776
79261
|
try {
|
|
78777
|
-
raw =
|
|
79262
|
+
raw = readFileSync29(p, "utf-8");
|
|
78778
79263
|
} catch {
|
|
78779
79264
|
return [];
|
|
78780
79265
|
}
|
|
@@ -79642,17 +80127,17 @@ async function approvalRecord(args, opts) {
|
|
|
79642
80127
|
}
|
|
79643
80128
|
|
|
79644
80129
|
// quota-check.ts
|
|
79645
|
-
import { readFileSync as
|
|
79646
|
-
import { join as
|
|
80130
|
+
import { readFileSync as readFileSync30, existsSync as existsSync32 } from "fs";
|
|
80131
|
+
import { join as join36 } from "path";
|
|
79647
80132
|
var OAUTH_BETA2 = "oauth-2025-04-20";
|
|
79648
80133
|
var DEFAULT_USER_AGENT2 = "claude-cli/1.0.0 (external, cli)";
|
|
79649
80134
|
var DEFAULT_PROBE_MODEL2 = "claude-haiku-4-5-20251001";
|
|
79650
80135
|
function readOauthToken2(claudeConfigDir) {
|
|
79651
|
-
const tokenFile =
|
|
79652
|
-
if (!
|
|
80136
|
+
const tokenFile = join36(claudeConfigDir, ".oauth-token");
|
|
80137
|
+
if (!existsSync32(tokenFile))
|
|
79653
80138
|
return null;
|
|
79654
80139
|
try {
|
|
79655
|
-
const raw =
|
|
80140
|
+
const raw = readFileSync30(tokenFile, "utf-8").trim();
|
|
79656
80141
|
return raw.length > 0 ? raw : null;
|
|
79657
80142
|
} catch {
|
|
79658
80143
|
return null;
|
|
@@ -80988,15 +81473,15 @@ async function menuWithBannerStatic(deps, banner) {
|
|
|
80988
81473
|
}
|
|
80989
81474
|
|
|
80990
81475
|
// gateway/session-model-file.ts
|
|
80991
|
-
import { readFileSync as
|
|
80992
|
-
import { join as
|
|
81476
|
+
import { readFileSync as readFileSync31, writeFileSync as writeFileSync28, renameSync as renameSync12, rmSync as rmSync4 } from "node:fs";
|
|
81477
|
+
import { join as join37 } from "node:path";
|
|
80993
81478
|
var SESSION_MODEL_FILE = ".session-model";
|
|
80994
81479
|
var CONFIGURED_DEFAULT_MODEL_FILE = ".configured-default-model";
|
|
80995
81480
|
var SESSION_MODEL_BOOT_ATTEMPTS_FILE = ".session-model-boot-attempts";
|
|
80996
81481
|
function atomicWrite(path2, content3) {
|
|
80997
81482
|
const tmp = `${path2}.tmp-${process.pid}-${Date.now()}`;
|
|
80998
|
-
|
|
80999
|
-
|
|
81483
|
+
writeFileSync28(tmp, content3, "utf8");
|
|
81484
|
+
renameSync12(tmp, path2);
|
|
81000
81485
|
}
|
|
81001
81486
|
function serializeSessionModel(rec) {
|
|
81002
81487
|
return `${JSON.stringify({
|
|
@@ -81011,28 +81496,28 @@ function writeSessionModelFile(agentDir, model, configuredDefaultAtWrite) {
|
|
|
81011
81496
|
throw new Error(`refusing to persist non-canonical session model token: ${JSON.stringify(model)}`);
|
|
81012
81497
|
}
|
|
81013
81498
|
try {
|
|
81014
|
-
rmSync4(
|
|
81499
|
+
rmSync4(join37(agentDir, SESSION_MODEL_BOOT_ATTEMPTS_FILE), { force: true });
|
|
81015
81500
|
} catch {}
|
|
81016
|
-
atomicWrite(
|
|
81501
|
+
atomicWrite(join37(agentDir, SESSION_MODEL_FILE), serializeSessionModel({ model, configuredDefaultAtWrite, ts: Date.now() }));
|
|
81017
81502
|
}
|
|
81018
81503
|
function readSessionModelFileRaw(agentDir) {
|
|
81019
81504
|
try {
|
|
81020
|
-
return
|
|
81505
|
+
return readFileSync31(join37(agentDir, SESSION_MODEL_FILE), "utf8");
|
|
81021
81506
|
} catch {
|
|
81022
81507
|
return null;
|
|
81023
81508
|
}
|
|
81024
81509
|
}
|
|
81025
81510
|
function clearSessionModelFile(agentDir) {
|
|
81026
81511
|
try {
|
|
81027
|
-
rmSync4(
|
|
81512
|
+
rmSync4(join37(agentDir, SESSION_MODEL_FILE), { force: true });
|
|
81028
81513
|
} catch {}
|
|
81029
81514
|
}
|
|
81030
81515
|
function consumeSessionModelCarrierOnHealthyBoot(agentDir) {
|
|
81031
81516
|
try {
|
|
81032
|
-
rmSync4(
|
|
81517
|
+
rmSync4(join37(agentDir, SESSION_MODEL_FILE), { force: true });
|
|
81033
81518
|
} catch {}
|
|
81034
81519
|
try {
|
|
81035
|
-
rmSync4(
|
|
81520
|
+
rmSync4(join37(agentDir, SESSION_MODEL_BOOT_ATTEMPTS_FILE), { force: true });
|
|
81036
81521
|
} catch {}
|
|
81037
81522
|
}
|
|
81038
81523
|
function restoreSessionModelFileRaw(agentDir, raw) {
|
|
@@ -81041,12 +81526,12 @@ function restoreSessionModelFileRaw(agentDir, raw) {
|
|
|
81041
81526
|
return;
|
|
81042
81527
|
}
|
|
81043
81528
|
try {
|
|
81044
|
-
atomicWrite(
|
|
81529
|
+
atomicWrite(join37(agentDir, SESSION_MODEL_FILE), raw);
|
|
81045
81530
|
} catch {}
|
|
81046
81531
|
}
|
|
81047
81532
|
function readConfiguredDefaultModel(agentDir) {
|
|
81048
81533
|
try {
|
|
81049
|
-
const v =
|
|
81534
|
+
const v = readFileSync31(join37(agentDir, CONFIGURED_DEFAULT_MODEL_FILE), "utf8").trim();
|
|
81050
81535
|
return v.length > 0 ? v : null;
|
|
81051
81536
|
} catch {
|
|
81052
81537
|
return null;
|
|
@@ -81058,12 +81543,12 @@ function writeSessionEffortFile(agentDir, level, configuredDefaultAtWrite) {
|
|
|
81058
81543
|
if (!EFFORT_LEVEL_RE.test(level)) {
|
|
81059
81544
|
throw new Error(`refusing to persist non-allowlisted effort level: ${JSON.stringify(level)}`);
|
|
81060
81545
|
}
|
|
81061
|
-
atomicWrite(
|
|
81546
|
+
atomicWrite(join37(agentDir, SESSION_EFFORT_FILE), `${JSON.stringify({ level, configuredDefaultAtWrite: configuredDefaultAtWrite ?? "", ts: Date.now() })}
|
|
81062
81547
|
`);
|
|
81063
81548
|
}
|
|
81064
81549
|
function clearSessionEffortFile(agentDir) {
|
|
81065
81550
|
try {
|
|
81066
|
-
rmSync4(
|
|
81551
|
+
rmSync4(join37(agentDir, SESSION_EFFORT_FILE), { force: true });
|
|
81067
81552
|
} catch {}
|
|
81068
81553
|
}
|
|
81069
81554
|
var PREMIUM_RECOVERY_FILE = ".premium-recovery";
|
|
@@ -81086,13 +81571,13 @@ function writePremiumRecoveryFile(agentDir, premiumModel, chats) {
|
|
|
81086
81571
|
if (clean.length === 0) {
|
|
81087
81572
|
throw new Error("refusing to persist premium-recovery marker with no chats to notify");
|
|
81088
81573
|
}
|
|
81089
|
-
atomicWrite(
|
|
81574
|
+
atomicWrite(join37(agentDir, PREMIUM_RECOVERY_FILE), `${JSON.stringify({ premiumModel, chats: clean, ts: Date.now() })}
|
|
81090
81575
|
`);
|
|
81091
81576
|
}
|
|
81092
81577
|
function readPremiumRecoveryFile(agentDir) {
|
|
81093
81578
|
let raw;
|
|
81094
81579
|
try {
|
|
81095
|
-
raw =
|
|
81580
|
+
raw = readFileSync31(join37(agentDir, PREMIUM_RECOVERY_FILE), "utf8");
|
|
81096
81581
|
} catch {
|
|
81097
81582
|
return null;
|
|
81098
81583
|
}
|
|
@@ -81105,7 +81590,7 @@ function readPremiumRecoveryFile(agentDir) {
|
|
|
81105
81590
|
}
|
|
81106
81591
|
function clearPremiumRecoveryFile(agentDir) {
|
|
81107
81592
|
try {
|
|
81108
|
-
rmSync4(
|
|
81593
|
+
rmSync4(join37(agentDir, PREMIUM_RECOVERY_FILE), { force: true });
|
|
81109
81594
|
} catch {}
|
|
81110
81595
|
}
|
|
81111
81596
|
|
|
@@ -81394,7 +81879,7 @@ async function discoverModels(agentName3, opts = {}) {
|
|
|
81394
81879
|
}
|
|
81395
81880
|
|
|
81396
81881
|
// ../src/agents/scaffold.ts
|
|
81397
|
-
import { dirname as dirname14, isAbsolute, join as
|
|
81882
|
+
import { dirname as dirname14, isAbsolute, join as join40, relative, resolve as resolve8 } from "node:path";
|
|
81398
81883
|
init_atomic();
|
|
81399
81884
|
|
|
81400
81885
|
// ../src/agents/agent-uid.ts
|
|
@@ -81411,7 +81896,7 @@ init_merge();
|
|
|
81411
81896
|
init_timezone();
|
|
81412
81897
|
|
|
81413
81898
|
// ../src/cli/agent-config.ts
|
|
81414
|
-
import { join as
|
|
81899
|
+
import { join as join38 } from "node:path";
|
|
81415
81900
|
import { homedir as homedir12 } from "node:os";
|
|
81416
81901
|
|
|
81417
81902
|
// ../src/cli/helpers.ts
|
|
@@ -81432,12 +81917,12 @@ var WEBKITE_VAULT_KEYS = new Set([
|
|
|
81432
81917
|
init_overlay_loader();
|
|
81433
81918
|
|
|
81434
81919
|
// ../src/cli/agent-config.ts
|
|
81435
|
-
var AUDIT_ROOT =
|
|
81920
|
+
var AUDIT_ROOT = join38(homedir12(), ".switchroom", "audit");
|
|
81436
81921
|
|
|
81437
81922
|
// ../src/agents/profiles.ts
|
|
81438
81923
|
var import_handlebars = __toESM(require_lib(), 1);
|
|
81439
|
-
import { readFileSync as
|
|
81440
|
-
import { resolve as resolve7, join as
|
|
81924
|
+
import { readFileSync as readFileSync32, writeFileSync as writeFileSync29, existsSync as existsSync33, readdirSync as readdirSync7, statSync as statSync12, copyFileSync, mkdirSync as mkdirSync31, realpathSync as realpathSync2 } from "node:fs";
|
|
81925
|
+
import { resolve as resolve7, join as join39, sep as pathSep } from "node:path";
|
|
81441
81926
|
function resolveProfilesRoot() {
|
|
81442
81927
|
const envOverride = process.env.SWITCHROOM_PROFILES_ROOT?.trim();
|
|
81443
81928
|
if (envOverride) {
|
|
@@ -81448,7 +81933,7 @@ function resolveProfilesRoot() {
|
|
|
81448
81933
|
resolve7(import.meta.dirname, "profiles")
|
|
81449
81934
|
];
|
|
81450
81935
|
for (const candidate of candidates) {
|
|
81451
|
-
if (
|
|
81936
|
+
if (existsSync33(candidate)) {
|
|
81452
81937
|
return candidate;
|
|
81453
81938
|
}
|
|
81454
81939
|
}
|
|
@@ -81464,9 +81949,9 @@ import_handlebars.default.registerHelper("isNumber", (value) => {
|
|
|
81464
81949
|
var SHARED_FRAGMENTS_DIR = resolve7(PROFILES_ROOT, "_shared");
|
|
81465
81950
|
var SHARED_FRAGMENTS = ["vault-protocol", "agent-self-service", "execution-discipline", "reply-discipline", "dev-protocol"];
|
|
81466
81951
|
for (const name of SHARED_FRAGMENTS) {
|
|
81467
|
-
const fragPath =
|
|
81468
|
-
if (
|
|
81469
|
-
import_handlebars.default.registerPartial(name,
|
|
81952
|
+
const fragPath = join39(SHARED_FRAGMENTS_DIR, `${name}.md.hbs`);
|
|
81953
|
+
if (existsSync33(fragPath)) {
|
|
81954
|
+
import_handlebars.default.registerPartial(name, readFileSync32(fragPath, "utf-8"));
|
|
81470
81955
|
}
|
|
81471
81956
|
}
|
|
81472
81957
|
|
|
@@ -82073,7 +82558,7 @@ init_overlay_loader();
|
|
|
82073
82558
|
init_merge();
|
|
82074
82559
|
init_timezone();
|
|
82075
82560
|
var import_yaml4 = __toESM(require_dist(), 1);
|
|
82076
|
-
import { readFileSync as
|
|
82561
|
+
import { readFileSync as readFileSync33, existsSync as existsSync34 } from "node:fs";
|
|
82077
82562
|
import { homedir as homedir13 } from "node:os";
|
|
82078
82563
|
import { resolve as resolve9 } from "node:path";
|
|
82079
82564
|
|
|
@@ -82149,7 +82634,7 @@ function findConfigFile2(startDir) {
|
|
|
82149
82634
|
resolve9(userDir, "clerk.yml")
|
|
82150
82635
|
].filter(Boolean);
|
|
82151
82636
|
for (const path2 of searchPaths) {
|
|
82152
|
-
if (
|
|
82637
|
+
if (existsSync34(path2)) {
|
|
82153
82638
|
return path2;
|
|
82154
82639
|
}
|
|
82155
82640
|
}
|
|
@@ -82157,12 +82642,12 @@ function findConfigFile2(startDir) {
|
|
|
82157
82642
|
}
|
|
82158
82643
|
function loadConfig2(configPath) {
|
|
82159
82644
|
const filePath = configPath ?? findConfigFile2();
|
|
82160
|
-
if (!
|
|
82645
|
+
if (!existsSync34(filePath)) {
|
|
82161
82646
|
throw new ConfigError2(`Config file not found: ${filePath}`);
|
|
82162
82647
|
}
|
|
82163
82648
|
let raw;
|
|
82164
82649
|
try {
|
|
82165
|
-
raw =
|
|
82650
|
+
raw = readFileSync33(filePath, "utf-8");
|
|
82166
82651
|
} catch (err) {
|
|
82167
82652
|
throw new ConfigError2(`Failed to read config file: ${filePath}`, [
|
|
82168
82653
|
` ${err.message}`
|
|
@@ -82692,15 +83177,15 @@ function topicForRecipient(args) {
|
|
|
82692
83177
|
}
|
|
82693
83178
|
|
|
82694
83179
|
// ../src/agents/perf.ts
|
|
82695
|
-
import { existsSync as
|
|
83180
|
+
import { existsSync as existsSync35, readFileSync as readFileSync34 } from "node:fs";
|
|
82696
83181
|
function readTurnUsages(jsonlPath, lastN) {
|
|
82697
|
-
if (!
|
|
83182
|
+
if (!existsSync35(jsonlPath))
|
|
82698
83183
|
return [];
|
|
82699
83184
|
if (lastN <= 0)
|
|
82700
83185
|
return [];
|
|
82701
83186
|
let raw;
|
|
82702
83187
|
try {
|
|
82703
|
-
raw =
|
|
83188
|
+
raw = readFileSync34(jsonlPath, "utf-8");
|
|
82704
83189
|
} catch {
|
|
82705
83190
|
return [];
|
|
82706
83191
|
}
|
|
@@ -82791,8 +83276,8 @@ function numField(obj, key) {
|
|
|
82791
83276
|
}
|
|
82792
83277
|
|
|
82793
83278
|
// gateway/context-occupancy.ts
|
|
82794
|
-
import { mkdirSync as
|
|
82795
|
-
import { join as
|
|
83279
|
+
import { mkdirSync as mkdirSync32, writeFileSync as writeFileSync30 } from "node:fs";
|
|
83280
|
+
import { join as join41 } from "node:path";
|
|
82796
83281
|
var CONTEXT_OCCUPANCY_FILENAME = "context-occupancy.json";
|
|
82797
83282
|
var TIGHT_FRACTION = 0.8;
|
|
82798
83283
|
function buildContextOccupancy(occupancy, cap, now) {
|
|
@@ -82815,9 +83300,9 @@ function buildContextOccupancy(occupancy, cap, now) {
|
|
|
82815
83300
|
}
|
|
82816
83301
|
function writeContextOccupancySnapshot(stateDir, snapshot, deps) {
|
|
82817
83302
|
try {
|
|
82818
|
-
const path2 =
|
|
82819
|
-
(deps?.mkdir ?? ((p, o) =>
|
|
82820
|
-
(deps?.writeFile ?? ((p, d) =>
|
|
83303
|
+
const path2 = join41(stateDir, CONTEXT_OCCUPANCY_FILENAME);
|
|
83304
|
+
(deps?.mkdir ?? ((p, o) => mkdirSync32(p, o)))(stateDir, { recursive: true });
|
|
83305
|
+
(deps?.writeFile ?? ((p, d) => writeFileSync30(p, d)))(path2, JSON.stringify(snapshot, null, 2) + `
|
|
82821
83306
|
`);
|
|
82822
83307
|
} catch {}
|
|
82823
83308
|
}
|
|
@@ -82971,7 +83456,7 @@ function nextCompactNotify(state6, ev) {
|
|
|
82971
83456
|
}
|
|
82972
83457
|
|
|
82973
83458
|
// gateway/hostd-dispatch.ts
|
|
82974
|
-
import { existsSync as
|
|
83459
|
+
import { existsSync as existsSync36 } from "node:fs";
|
|
82975
83460
|
import { randomBytes as randomBytes7 } from "node:crypto";
|
|
82976
83461
|
init_loader();
|
|
82977
83462
|
var _hostdEnabled2;
|
|
@@ -82995,13 +83480,13 @@ function hostdSocketPath2(agentName3) {
|
|
|
82995
83480
|
function hostdWillBeUsed2(agentName3) {
|
|
82996
83481
|
if (!isHostdEnabled2())
|
|
82997
83482
|
return false;
|
|
82998
|
-
return
|
|
83483
|
+
return existsSync36(hostdSocketPath2(agentName3));
|
|
82999
83484
|
}
|
|
83000
83485
|
async function tryHostdDispatch2(agentName3, req, timeoutMs = 5000) {
|
|
83001
83486
|
if (!isHostdEnabled2())
|
|
83002
83487
|
return "not-configured";
|
|
83003
83488
|
const sockPath = hostdSocketPath2(agentName3);
|
|
83004
|
-
if (!
|
|
83489
|
+
if (!existsSync36(sockPath))
|
|
83005
83490
|
return "not-configured";
|
|
83006
83491
|
try {
|
|
83007
83492
|
return await hostdRequest({ socketPath: sockPath, timeoutMs }, req);
|
|
@@ -83030,7 +83515,7 @@ async function pollHostdStatus(agentName3, targetRequestId, opts) {
|
|
|
83030
83515
|
if (!isHostdEnabled2())
|
|
83031
83516
|
return "not-configured";
|
|
83032
83517
|
const sockPath = hostdSocketPath2(agentName3);
|
|
83033
|
-
if (!
|
|
83518
|
+
if (!existsSync36(sockPath))
|
|
83034
83519
|
return "not-configured";
|
|
83035
83520
|
const now = opts.now ?? Date.now;
|
|
83036
83521
|
const sleep2 = opts.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
|
|
@@ -83149,7 +83634,7 @@ function createDmPinSweeper(deps) {
|
|
|
83149
83634
|
|
|
83150
83635
|
// gateway/webhook-ingest-server.ts
|
|
83151
83636
|
import net4 from "node:net";
|
|
83152
|
-
import { chmodSync as chmodSync10, existsSync as
|
|
83637
|
+
import { chmodSync as chmodSync10, existsSync as existsSync37, unlinkSync as unlinkSync17 } from "node:fs";
|
|
83153
83638
|
var MAX_REQUEST_BYTES = 1024 * 1024;
|
|
83154
83639
|
function fdOf(conn) {
|
|
83155
83640
|
const handle = conn._handle;
|
|
@@ -83161,7 +83646,7 @@ function startWebhookIngestServer(opts) {
|
|
|
83161
83646
|
const log = opts.log ?? ((s) => process.stderr.write(s));
|
|
83162
83647
|
const allowed = new Set(opts.allowedUids);
|
|
83163
83648
|
try {
|
|
83164
|
-
if (
|
|
83649
|
+
if (existsSync37(opts.socketPath))
|
|
83165
83650
|
unlinkSync17(opts.socketPath);
|
|
83166
83651
|
} catch (err) {
|
|
83167
83652
|
log(`webhook-ingest-server: could not unlink stale socket: ${err.message}
|
|
@@ -83254,7 +83739,7 @@ function startWebhookIngestServer(opts) {
|
|
|
83254
83739
|
server.close();
|
|
83255
83740
|
} catch {}
|
|
83256
83741
|
try {
|
|
83257
|
-
if (
|
|
83742
|
+
if (existsSync37(opts.socketPath))
|
|
83258
83743
|
unlinkSync17(opts.socketPath);
|
|
83259
83744
|
} catch {}
|
|
83260
83745
|
}
|
|
@@ -83262,20 +83747,20 @@ function startWebhookIngestServer(opts) {
|
|
|
83262
83747
|
}
|
|
83263
83748
|
|
|
83264
83749
|
// ../src/web/webhook-gateway-record.ts
|
|
83265
|
-
import { appendFileSync as
|
|
83266
|
-
import { join as
|
|
83750
|
+
import { appendFileSync as appendFileSync8, mkdirSync as mkdirSync35 } from "fs";
|
|
83751
|
+
import { join as join44 } from "path";
|
|
83267
83752
|
import { homedir as homedir15 } from "os";
|
|
83268
83753
|
|
|
83269
83754
|
// ../src/web/webhook-handler.ts
|
|
83270
|
-
import { appendFileSync as
|
|
83271
|
-
import { join as
|
|
83755
|
+
import { appendFileSync as appendFileSync7, existsSync as existsSync38, mkdirSync as mkdirSync33, readFileSync as readFileSync35, writeFileSync as writeFileSync31 } from "fs";
|
|
83756
|
+
import { join as join42 } from "path";
|
|
83272
83757
|
var DEDUP_MAX = 1000;
|
|
83273
83758
|
var DEDUP_TTL_MS = 24 * 60 * 60 * 1000;
|
|
83274
83759
|
function loadDedupFile(path2) {
|
|
83275
83760
|
try {
|
|
83276
|
-
if (!
|
|
83761
|
+
if (!existsSync38(path2))
|
|
83277
83762
|
return {};
|
|
83278
|
-
const raw = JSON.parse(
|
|
83763
|
+
const raw = JSON.parse(readFileSync35(path2, "utf-8"));
|
|
83279
83764
|
return typeof raw.deliveries === "object" && raw.deliveries !== null ? raw.deliveries : {};
|
|
83280
83765
|
} catch {
|
|
83281
83766
|
return {};
|
|
@@ -83289,7 +83774,7 @@ function saveDedupFile(path2, deliveries, now) {
|
|
|
83289
83774
|
}
|
|
83290
83775
|
const sorted = Object.entries(pruned).sort((a, b) => b[1] - a[1]).slice(0, DEDUP_MAX);
|
|
83291
83776
|
const final = Object.fromEntries(sorted);
|
|
83292
|
-
|
|
83777
|
+
writeFileSync31(path2, JSON.stringify({ deliveries: final }), {
|
|
83293
83778
|
mode: 384
|
|
83294
83779
|
});
|
|
83295
83780
|
}
|
|
@@ -83297,8 +83782,8 @@ var agentDedupCache = new Map;
|
|
|
83297
83782
|
function createFileDedupStore(resolveAgentDir) {
|
|
83298
83783
|
return {
|
|
83299
83784
|
check(agent, deliveryId, now) {
|
|
83300
|
-
const telegramDir =
|
|
83301
|
-
const filePath =
|
|
83785
|
+
const telegramDir = join42(resolveAgentDir(agent), "telegram");
|
|
83786
|
+
const filePath = join42(telegramDir, "webhook-dedup.json");
|
|
83302
83787
|
if (!agentDedupCache.has(agent)) {
|
|
83303
83788
|
agentDedupCache.set(agent, loadDedupFile(filePath));
|
|
83304
83789
|
}
|
|
@@ -83308,7 +83793,7 @@ function createFileDedupStore(resolveAgentDir) {
|
|
|
83308
83793
|
}
|
|
83309
83794
|
deliveries[deliveryId] = now;
|
|
83310
83795
|
try {
|
|
83311
|
-
|
|
83796
|
+
mkdirSync33(telegramDir, { recursive: true });
|
|
83312
83797
|
saveDedupFile(filePath, deliveries, now);
|
|
83313
83798
|
} catch {}
|
|
83314
83799
|
return;
|
|
@@ -83319,8 +83804,8 @@ var tokenBuckets = new Map;
|
|
|
83319
83804
|
var throttleIssueWindow = new Map;
|
|
83320
83805
|
|
|
83321
83806
|
// ../src/web/webhook-dispatch.ts
|
|
83322
|
-
import { existsSync as
|
|
83323
|
-
import { join as
|
|
83807
|
+
import { existsSync as existsSync39, mkdirSync as mkdirSync34, readFileSync as readFileSync36, writeFileSync as writeFileSync32 } from "fs";
|
|
83808
|
+
import { join as join43 } from "path";
|
|
83324
83809
|
import { homedir as homedir14 } from "os";
|
|
83325
83810
|
|
|
83326
83811
|
// ../src/agent-scheduler/ipc-client.ts
|
|
@@ -83619,9 +84104,9 @@ function cooldownKey(source, eventType, repo, number, ruleIndex) {
|
|
|
83619
84104
|
}
|
|
83620
84105
|
function loadCooldownFile(path2) {
|
|
83621
84106
|
try {
|
|
83622
|
-
if (!
|
|
84107
|
+
if (!existsSync39(path2))
|
|
83623
84108
|
return {};
|
|
83624
|
-
const raw = JSON.parse(
|
|
84109
|
+
const raw = JSON.parse(readFileSync36(path2, "utf-8"));
|
|
83625
84110
|
return typeof raw.dispatches === "object" && raw.dispatches !== null ? raw.dispatches : {};
|
|
83626
84111
|
} catch {
|
|
83627
84112
|
return {};
|
|
@@ -83629,7 +84114,7 @@ function loadCooldownFile(path2) {
|
|
|
83629
84114
|
}
|
|
83630
84115
|
function saveCooldownFile(path2, dispatches) {
|
|
83631
84116
|
try {
|
|
83632
|
-
|
|
84117
|
+
writeFileSync32(path2, JSON.stringify({ dispatches }), {
|
|
83633
84118
|
mode: 384
|
|
83634
84119
|
});
|
|
83635
84120
|
} catch {}
|
|
@@ -83640,8 +84125,8 @@ function createFileCooldownStore(resolveAgentDir) {
|
|
|
83640
84125
|
isCoolingDown(agent, key, cooldownMs, now) {
|
|
83641
84126
|
if (cooldownMs <= 0)
|
|
83642
84127
|
return false;
|
|
83643
|
-
const telegramDir =
|
|
83644
|
-
const filePath =
|
|
84128
|
+
const telegramDir = join43(resolveAgentDir(agent), "telegram");
|
|
84129
|
+
const filePath = join43(telegramDir, "webhook-cooldown.json");
|
|
83645
84130
|
if (!cache.has(agent)) {
|
|
83646
84131
|
cache.set(agent, loadCooldownFile(filePath));
|
|
83647
84132
|
}
|
|
@@ -83652,7 +84137,7 @@ function createFileCooldownStore(resolveAgentDir) {
|
|
|
83652
84137
|
}
|
|
83653
84138
|
dispatches[key] = now;
|
|
83654
84139
|
try {
|
|
83655
|
-
|
|
84140
|
+
mkdirSync34(telegramDir, { recursive: true });
|
|
83656
84141
|
saveCooldownFile(filePath, dispatches);
|
|
83657
84142
|
} catch {}
|
|
83658
84143
|
return false;
|
|
@@ -83698,9 +84183,9 @@ async function defaultInject(socketPath, agentName3, inbound) {
|
|
|
83698
84183
|
}
|
|
83699
84184
|
function injectWebhookInbound(agent, prompt, ctx, deps = {}) {
|
|
83700
84185
|
const log = deps.log ?? ((s) => process.stderr.write(s));
|
|
83701
|
-
const resolveAgentDir = deps.resolveAgentDir ?? ((a) =>
|
|
84186
|
+
const resolveAgentDir = deps.resolveAgentDir ?? ((a) => join43(homedir14(), ".switchroom", "agents", a));
|
|
83702
84187
|
const now = (deps.now ?? Date.now)();
|
|
83703
|
-
const socketPath =
|
|
84188
|
+
const socketPath = join43(resolveAgentDir(agent), "telegram", "gateway.sock");
|
|
83704
84189
|
const inbound = {
|
|
83705
84190
|
type: "inbound",
|
|
83706
84191
|
chatId: ctx.chatId,
|
|
@@ -83772,7 +84257,7 @@ function evaluateDispatch(args, deps = {}) {
|
|
|
83772
84257
|
const log = deps.log ?? ((s) => process.stderr.write(s));
|
|
83773
84258
|
const now = (deps.now ?? Date.now)();
|
|
83774
84259
|
const nowDate = deps.nowDate ?? (() => new Date(now));
|
|
83775
|
-
const resolveAgentDir = deps.resolveAgentDir ?? ((a) =>
|
|
84260
|
+
const resolveAgentDir = deps.resolveAgentDir ?? ((a) => join43(homedir14(), ".switchroom", "agents", a));
|
|
83776
84261
|
const cooldownStore = deps.cooldownStore ?? createFileCooldownStore(resolveAgentDir);
|
|
83777
84262
|
if (!DISPATCH_SOURCES.includes(args.source))
|
|
83778
84263
|
return 0;
|
|
@@ -83850,10 +84335,10 @@ var CONSOLIDATION_COMPLETED_EVENT = "consolidation.completed";
|
|
|
83850
84335
|
function recordWebhookEvent(rec, deps = {}) {
|
|
83851
84336
|
const log = deps.log ?? ((s) => process.stderr.write(s));
|
|
83852
84337
|
const now = rec.ts || (deps.now ?? Date.now)();
|
|
83853
|
-
const resolveAgentDir = deps.resolveAgentDir ?? ((a) =>
|
|
84338
|
+
const resolveAgentDir = deps.resolveAgentDir ?? ((a) => join44(homedir15(), ".switchroom", "agents", a));
|
|
83854
84339
|
const dedupStore = deps.dedupStore ?? createFileDedupStore(resolveAgentDir);
|
|
83855
84340
|
const agent = rec.agent;
|
|
83856
|
-
const telegramDir =
|
|
84341
|
+
const telegramDir = join44(resolveAgentDir(agent), "telegram");
|
|
83857
84342
|
if (rec.source === "github" && rec.delivery_id) {
|
|
83858
84343
|
const originalTs = dedupStore.check(agent, rec.delivery_id, now);
|
|
83859
84344
|
if (originalTs !== undefined) {
|
|
@@ -83862,9 +84347,9 @@ function recordWebhookEvent(rec, deps = {}) {
|
|
|
83862
84347
|
return { status: "deduped", ts: originalTs };
|
|
83863
84348
|
}
|
|
83864
84349
|
}
|
|
83865
|
-
const logPath =
|
|
84350
|
+
const logPath = join44(telegramDir, "webhook-events.jsonl");
|
|
83866
84351
|
try {
|
|
83867
|
-
|
|
84352
|
+
mkdirSync35(telegramDir, { recursive: true });
|
|
83868
84353
|
const record = {
|
|
83869
84354
|
ts: now,
|
|
83870
84355
|
source: rec.source,
|
|
@@ -83872,7 +84357,7 @@ function recordWebhookEvent(rec, deps = {}) {
|
|
|
83872
84357
|
rendered_text: rec.rendered_text,
|
|
83873
84358
|
payload: rec.payload
|
|
83874
84359
|
};
|
|
83875
|
-
|
|
84360
|
+
appendFileSync8(logPath, JSON.stringify(record) + `
|
|
83876
84361
|
`, { mode: 384 });
|
|
83877
84362
|
} catch (err) {
|
|
83878
84363
|
log(`webhook-gateway: agent='${agent}' source='${rec.source}' write failed: ${err.message}
|
|
@@ -83974,7 +84459,7 @@ function recordWebhookEvent(rec, deps = {}) {
|
|
|
83974
84459
|
|
|
83975
84460
|
// gateway/ipc-server.ts
|
|
83976
84461
|
init_format();
|
|
83977
|
-
import { renameSync as
|
|
84462
|
+
import { renameSync as renameSync14, unlinkSync as unlinkSync18, chmodSync as chmodSync11 } from "fs";
|
|
83978
84463
|
var MAX_BUFFER_SIZE = 1024 * 1024;
|
|
83979
84464
|
var VALID_OPERATOR_KINDS = new Set([
|
|
83980
84465
|
"credentials-expired",
|
|
@@ -84183,7 +84668,7 @@ function createIpcServer(options) {
|
|
|
84183
84668
|
heartbeatTimeoutMs = 30000
|
|
84184
84669
|
} = options;
|
|
84185
84670
|
try {
|
|
84186
|
-
|
|
84671
|
+
renameSync14(socketPath, socketPath + ".bak");
|
|
84187
84672
|
} catch {}
|
|
84188
84673
|
try {
|
|
84189
84674
|
unlinkSync18(socketPath + ".bak");
|
|
@@ -84573,7 +85058,7 @@ function createIpcServer(options) {
|
|
|
84573
85058
|
clientBySocketId.clear();
|
|
84574
85059
|
server.stop(true);
|
|
84575
85060
|
try {
|
|
84576
|
-
|
|
85061
|
+
renameSync14(socketPath, socketPath + ".bak");
|
|
84577
85062
|
} catch {}
|
|
84578
85063
|
}
|
|
84579
85064
|
};
|
|
@@ -88508,27 +88993,27 @@ function skillProposalKeyboard(id) {
|
|
|
88508
88993
|
// ../src/self-improve/skill-proposals.ts
|
|
88509
88994
|
import {
|
|
88510
88995
|
closeSync as closeSync7,
|
|
88511
|
-
existsSync as
|
|
88512
|
-
mkdirSync as
|
|
88996
|
+
existsSync as existsSync40,
|
|
88997
|
+
mkdirSync as mkdirSync36,
|
|
88513
88998
|
openSync as openSync7,
|
|
88514
|
-
readFileSync as
|
|
88999
|
+
readFileSync as readFileSync37,
|
|
88515
89000
|
writeSync as writeSync5
|
|
88516
89001
|
} from "node:fs";
|
|
88517
|
-
import { join as
|
|
89002
|
+
import { join as join45 } from "node:path";
|
|
88518
89003
|
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
88519
89004
|
var PROPOSALS_FILE2 = "skill-proposals.jsonl";
|
|
88520
89005
|
var REJECTED_FILE2 = "skill-proposals-rejected.jsonl";
|
|
88521
89006
|
var REJECTION_TTL_MS2 = 90 * 24 * 60 * 60 * 1000;
|
|
88522
89007
|
var PROPOSAL_SIM_THRESHOLD = 0.5;
|
|
88523
89008
|
function proposalsPath2(stateDir) {
|
|
88524
|
-
return
|
|
89009
|
+
return join45(stateDir, PROPOSALS_FILE2);
|
|
88525
89010
|
}
|
|
88526
89011
|
function rejectedPath2(stateDir) {
|
|
88527
|
-
return
|
|
89012
|
+
return join45(stateDir, REJECTED_FILE2);
|
|
88528
89013
|
}
|
|
88529
89014
|
function ensureDir3(stateDir) {
|
|
88530
|
-
if (!
|
|
88531
|
-
|
|
89015
|
+
if (!existsSync40(stateDir)) {
|
|
89016
|
+
mkdirSync36(stateDir, { recursive: true, mode: 493 });
|
|
88532
89017
|
}
|
|
88533
89018
|
}
|
|
88534
89019
|
function appendLine2(path2, obj) {
|
|
@@ -88541,11 +89026,11 @@ function appendLine2(path2, obj) {
|
|
|
88541
89026
|
}
|
|
88542
89027
|
}
|
|
88543
89028
|
function readLines2(path2, isValid2) {
|
|
88544
|
-
if (!
|
|
89029
|
+
if (!existsSync40(path2))
|
|
88545
89030
|
return [];
|
|
88546
89031
|
let raw;
|
|
88547
89032
|
try {
|
|
88548
|
-
raw =
|
|
89033
|
+
raw = readFileSync37(path2, "utf-8");
|
|
88549
89034
|
} catch {
|
|
88550
89035
|
return [];
|
|
88551
89036
|
}
|
|
@@ -89142,11 +89627,11 @@ function escapeBody2(s) {
|
|
|
89142
89627
|
}
|
|
89143
89628
|
|
|
89144
89629
|
// gateway/pid-file.ts
|
|
89145
|
-
import { writeFileSync as
|
|
89630
|
+
import { writeFileSync as writeFileSync33, readFileSync as readFileSync38, unlinkSync as unlinkSync19, renameSync as renameSync15 } from "node:fs";
|
|
89146
89631
|
function writePidFile(path2, record) {
|
|
89147
89632
|
const tmp = `${path2}.tmp-${process.pid}-${Date.now()}`;
|
|
89148
|
-
|
|
89149
|
-
|
|
89633
|
+
writeFileSync33(tmp, JSON.stringify(record), "utf-8");
|
|
89634
|
+
renameSync15(tmp, path2);
|
|
89150
89635
|
}
|
|
89151
89636
|
function clearPidFile(path2) {
|
|
89152
89637
|
try {
|
|
@@ -89161,10 +89646,10 @@ import {
|
|
|
89161
89646
|
writeFile as writeFileAsync,
|
|
89162
89647
|
readFile as readFileAsync
|
|
89163
89648
|
} from "node:fs/promises";
|
|
89164
|
-
import { readFileSync as
|
|
89649
|
+
import { readFileSync as readFileSync39 } from "node:fs";
|
|
89165
89650
|
function readCurrentBootId() {
|
|
89166
89651
|
try {
|
|
89167
|
-
const stat =
|
|
89652
|
+
const stat = readFileSync39("/proc/1/stat", "utf-8");
|
|
89168
89653
|
const lastParen = stat.lastIndexOf(")");
|
|
89169
89654
|
if (lastParen < 0)
|
|
89170
89655
|
return null;
|
|
@@ -89367,15 +89852,15 @@ function safeCount(fn) {
|
|
|
89367
89852
|
}
|
|
89368
89853
|
|
|
89369
89854
|
// gateway/session-marker.ts
|
|
89370
|
-
import { writeFileSync as
|
|
89855
|
+
import { writeFileSync as writeFileSync34, readFileSync as readFileSync40, renameSync as renameSync16, unlinkSync as unlinkSync20 } from "node:fs";
|
|
89371
89856
|
function writeSessionMarker(path2, marker) {
|
|
89372
89857
|
const tmp = `${path2}.tmp-${process.pid}-${Date.now()}`;
|
|
89373
|
-
|
|
89374
|
-
|
|
89858
|
+
writeFileSync34(tmp, JSON.stringify(marker), "utf-8");
|
|
89859
|
+
renameSync16(tmp, path2);
|
|
89375
89860
|
}
|
|
89376
89861
|
function readSessionMarker(path2) {
|
|
89377
89862
|
try {
|
|
89378
|
-
const raw =
|
|
89863
|
+
const raw = readFileSync40(path2, "utf-8");
|
|
89379
89864
|
const parsed = JSON.parse(raw);
|
|
89380
89865
|
if (typeof parsed.pid === "number" && typeof parsed.startedAtMs === "number" && Number.isFinite(parsed.pid) && Number.isFinite(parsed.startedAtMs)) {
|
|
89381
89866
|
return { pid: parsed.pid, startedAtMs: parsed.startedAtMs };
|
|
@@ -89397,16 +89882,16 @@ function shouldFireRestartBanner(input) {
|
|
|
89397
89882
|
}
|
|
89398
89883
|
|
|
89399
89884
|
// gateway/clean-shutdown-marker.ts
|
|
89400
|
-
import { writeFileSync as
|
|
89885
|
+
import { writeFileSync as writeFileSync35, readFileSync as readFileSync41, renameSync as renameSync17, unlinkSync as unlinkSync21 } from "node:fs";
|
|
89401
89886
|
var DEFAULT_MAX_AGE_MS = 60000;
|
|
89402
89887
|
function writeCleanShutdownMarker(path2, marker) {
|
|
89403
89888
|
const tmp = `${path2}.tmp-${process.pid}-${Date.now()}`;
|
|
89404
|
-
|
|
89405
|
-
|
|
89889
|
+
writeFileSync35(tmp, JSON.stringify(marker), "utf-8");
|
|
89890
|
+
renameSync17(tmp, path2);
|
|
89406
89891
|
}
|
|
89407
89892
|
function readCleanShutdownMarker(path2) {
|
|
89408
89893
|
try {
|
|
89409
|
-
const raw =
|
|
89894
|
+
const raw = readFileSync41(path2, "utf-8");
|
|
89410
89895
|
const parsed = JSON.parse(raw);
|
|
89411
89896
|
if (typeof parsed.ts === "number" && Number.isFinite(parsed.ts) && typeof parsed.signal === "string" && parsed.signal.length > 0) {
|
|
89412
89897
|
const out = { ts: parsed.ts, signal: parsed.signal };
|
|
@@ -89778,16 +90263,16 @@ function classifyAdminGate(text4, myAgentName) {
|
|
|
89778
90263
|
|
|
89779
90264
|
// subagent-watcher.ts
|
|
89780
90265
|
import {
|
|
89781
|
-
existsSync as
|
|
90266
|
+
existsSync as existsSync41,
|
|
89782
90267
|
openSync as openSync8,
|
|
89783
90268
|
readSync as readSync2,
|
|
89784
90269
|
statSync as statSync13,
|
|
89785
90270
|
closeSync as closeSync8,
|
|
89786
90271
|
watch,
|
|
89787
90272
|
readdirSync as readdirSync8,
|
|
89788
|
-
readFileSync as
|
|
90273
|
+
readFileSync as readFileSync42
|
|
89789
90274
|
} from "fs";
|
|
89790
|
-
import { join as
|
|
90275
|
+
import { join as join46 } from "path";
|
|
89791
90276
|
|
|
89792
90277
|
// session-tail.ts
|
|
89793
90278
|
function sanitizeCwdToProjectName2(cwd) {
|
|
@@ -90137,7 +90622,7 @@ function backfillJsonlAgentId(db3, jsonlPath, agentId, log) {
|
|
|
90137
90622
|
const metaPath = jsonlPath.replace(/\.jsonl$/, ".meta.json");
|
|
90138
90623
|
let meta;
|
|
90139
90624
|
try {
|
|
90140
|
-
const raw =
|
|
90625
|
+
const raw = readFileSync42(metaPath, "utf8");
|
|
90141
90626
|
meta = JSON.parse(raw);
|
|
90142
90627
|
} catch {
|
|
90143
90628
|
log?.(`subagent-watcher: backfill skip ${agentId} \u2014 meta.json not readable at ${metaPath}`);
|
|
@@ -90592,7 +91077,7 @@ function startSubagentWatcher(config) {
|
|
|
90592
91077
|
clearTimeout(ref.ref);
|
|
90593
91078
|
});
|
|
90594
91079
|
const fs2 = config.fs ?? {
|
|
90595
|
-
existsSync:
|
|
91080
|
+
existsSync: existsSync41,
|
|
90596
91081
|
readdirSync: readdirSync8,
|
|
90597
91082
|
statSync: statSync13,
|
|
90598
91083
|
openSync: openSync8,
|
|
@@ -91110,8 +91595,8 @@ function startSubagentWatcher(config) {
|
|
|
91110
91595
|
if (stopped)
|
|
91111
91596
|
return;
|
|
91112
91597
|
pruneVanishedDirWatchers();
|
|
91113
|
-
const claudeHome =
|
|
91114
|
-
const projectsRoot =
|
|
91598
|
+
const claudeHome = join46(agentDir, ".claude");
|
|
91599
|
+
const projectsRoot = join46(claudeHome, "projects");
|
|
91115
91600
|
if (!fs2.existsSync(projectsRoot))
|
|
91116
91601
|
return;
|
|
91117
91602
|
let projectDirs;
|
|
@@ -91145,7 +91630,7 @@ function startSubagentWatcher(config) {
|
|
|
91145
91630
|
continue;
|
|
91146
91631
|
}
|
|
91147
91632
|
warnedForeignSlugs.delete(pDir);
|
|
91148
|
-
const projectPath =
|
|
91633
|
+
const projectPath = join46(projectsRoot, pDir);
|
|
91149
91634
|
let sessionDirs;
|
|
91150
91635
|
try {
|
|
91151
91636
|
sessionDirs = fs2.readdirSync(projectPath);
|
|
@@ -91155,7 +91640,7 @@ function startSubagentWatcher(config) {
|
|
|
91155
91640
|
for (const sDir of sessionDirs) {
|
|
91156
91641
|
if (sDir.endsWith(".jsonl"))
|
|
91157
91642
|
continue;
|
|
91158
|
-
const subagentsPath =
|
|
91643
|
+
const subagentsPath = join46(projectPath, sDir, "subagents");
|
|
91159
91644
|
if (!fs2.existsSync(subagentsPath))
|
|
91160
91645
|
continue;
|
|
91161
91646
|
const watchAndScan = (dirPath) => {
|
|
@@ -91164,7 +91649,7 @@ function startSubagentWatcher(config) {
|
|
|
91164
91649
|
const w = fs2.watch(dirPath, (_event, filename) => {
|
|
91165
91650
|
if (!filename || !filename.toString().startsWith("agent-") || !filename.toString().endsWith(".jsonl"))
|
|
91166
91651
|
return;
|
|
91167
|
-
const filePath =
|
|
91652
|
+
const filePath = join46(dirPath, filename.toString());
|
|
91168
91653
|
if (!knownFiles.has(filePath)) {
|
|
91169
91654
|
scanSubagentsDir(dirPath);
|
|
91170
91655
|
}
|
|
@@ -91178,7 +91663,7 @@ function startSubagentWatcher(config) {
|
|
|
91178
91663
|
scanSubagentsDir(dirPath);
|
|
91179
91664
|
};
|
|
91180
91665
|
watchAndScan(subagentsPath);
|
|
91181
|
-
const workflowsPath =
|
|
91666
|
+
const workflowsPath = join46(subagentsPath, "workflows");
|
|
91182
91667
|
if (fs2.existsSync(workflowsPath)) {
|
|
91183
91668
|
let wfDirs;
|
|
91184
91669
|
try {
|
|
@@ -91188,7 +91673,7 @@ function startSubagentWatcher(config) {
|
|
|
91188
91673
|
}
|
|
91189
91674
|
for (const wfDir of wfDirs) {
|
|
91190
91675
|
try {
|
|
91191
|
-
const wfPath =
|
|
91676
|
+
const wfPath = join46(workflowsPath, wfDir);
|
|
91192
91677
|
if (!fs2.statSync(wfPath).isDirectory())
|
|
91193
91678
|
continue;
|
|
91194
91679
|
watchAndScan(wfPath);
|
|
@@ -91208,7 +91693,7 @@ function startSubagentWatcher(config) {
|
|
|
91208
91693
|
for (const e of entries) {
|
|
91209
91694
|
if (!e.startsWith("agent-") || !e.endsWith(".jsonl"))
|
|
91210
91695
|
continue;
|
|
91211
|
-
const filePath =
|
|
91696
|
+
const filePath = join46(subagentsPath, e);
|
|
91212
91697
|
if (knownFiles.has(filePath))
|
|
91213
91698
|
continue;
|
|
91214
91699
|
const agentId = e.slice("agent-".length, -".jsonl".length);
|
|
@@ -91336,37 +91821,37 @@ function startSubagentWatcher(config) {
|
|
|
91336
91821
|
|
|
91337
91822
|
// ../src/worktree/registry.ts
|
|
91338
91823
|
import {
|
|
91339
|
-
mkdirSync as
|
|
91340
|
-
writeFileSync as
|
|
91341
|
-
readFileSync as
|
|
91824
|
+
mkdirSync as mkdirSync37,
|
|
91825
|
+
writeFileSync as writeFileSync36,
|
|
91826
|
+
readFileSync as readFileSync43,
|
|
91342
91827
|
readdirSync as readdirSync9,
|
|
91343
91828
|
unlinkSync as unlinkSync22,
|
|
91344
|
-
existsSync as
|
|
91345
|
-
renameSync as
|
|
91829
|
+
existsSync as existsSync42,
|
|
91830
|
+
renameSync as renameSync18
|
|
91346
91831
|
} from "node:fs";
|
|
91347
|
-
import { join as
|
|
91832
|
+
import { join as join47, resolve as resolve10 } from "node:path";
|
|
91348
91833
|
import { homedir as homedir16 } from "node:os";
|
|
91349
91834
|
function registryDir() {
|
|
91350
|
-
return resolve10(process.env.SWITCHROOM_WORKTREE_DIR ??
|
|
91835
|
+
return resolve10(process.env.SWITCHROOM_WORKTREE_DIR ?? join47(homedir16(), ".switchroom", "worktrees"));
|
|
91351
91836
|
}
|
|
91352
91837
|
function recordPath(id) {
|
|
91353
|
-
return
|
|
91838
|
+
return join47(registryDir(), `${id}.json`);
|
|
91354
91839
|
}
|
|
91355
91840
|
function ensureDir4() {
|
|
91356
|
-
|
|
91841
|
+
mkdirSync37(registryDir(), { recursive: true });
|
|
91357
91842
|
}
|
|
91358
91843
|
function writeRecord(record) {
|
|
91359
91844
|
ensureDir4();
|
|
91360
91845
|
const target = recordPath(record.id);
|
|
91361
91846
|
const tmp = `${target}.tmp${process.pid}`;
|
|
91362
|
-
|
|
91847
|
+
writeFileSync36(tmp, JSON.stringify(record, null, 2) + `
|
|
91363
91848
|
`, { mode: 384 });
|
|
91364
|
-
|
|
91849
|
+
renameSync18(tmp, target);
|
|
91365
91850
|
}
|
|
91366
91851
|
function readRecord(id) {
|
|
91367
91852
|
const path2 = recordPath(id);
|
|
91368
91853
|
try {
|
|
91369
|
-
const raw =
|
|
91854
|
+
const raw = readFileSync43(path2, "utf8");
|
|
91370
91855
|
return JSON.parse(raw);
|
|
91371
91856
|
} catch {
|
|
91372
91857
|
return null;
|
|
@@ -91396,7 +91881,7 @@ function touchHeartbeat(id, onAfterRead) {
|
|
|
91396
91881
|
writeRecord({ ...rec, heartbeatAt: new Date().toISOString() });
|
|
91397
91882
|
}
|
|
91398
91883
|
function recordExists(id) {
|
|
91399
|
-
return
|
|
91884
|
+
return existsSync42(recordPath(id));
|
|
91400
91885
|
}
|
|
91401
91886
|
|
|
91402
91887
|
// worktree-watch-cwds.ts
|
|
@@ -91528,15 +92013,15 @@ function determineRestartReason(opts) {
|
|
|
91528
92013
|
init_boot_card();
|
|
91529
92014
|
|
|
91530
92015
|
// gateway/update-announce.ts
|
|
91531
|
-
import { existsSync as
|
|
91532
|
-
import { join as
|
|
92016
|
+
import { existsSync as existsSync47, mkdirSync as mkdirSync41, openSync as openSync9, closeSync as closeSync9, readFileSync as readFileSync50 } from "node:fs";
|
|
92017
|
+
import { join as join52 } from "node:path";
|
|
91533
92018
|
import { homedir as homedir18 } from "node:os";
|
|
91534
92019
|
|
|
91535
92020
|
// ../src/host-control/audit-reader.ts
|
|
91536
92021
|
import { homedir as homedir17 } from "node:os";
|
|
91537
|
-
import { join as
|
|
92022
|
+
import { join as join51 } from "node:path";
|
|
91538
92023
|
function defaultAuditLogPath(home2 = homedir17()) {
|
|
91539
|
-
return
|
|
92024
|
+
return join51(home2, ".switchroom", "host-control-audit.log");
|
|
91540
92025
|
}
|
|
91541
92026
|
function parseAuditLine(line) {
|
|
91542
92027
|
const trimmed = line.trim();
|
|
@@ -91659,8 +92144,8 @@ function readAndFilter(raw, filters, limit) {
|
|
|
91659
92144
|
var DEFAULT_LOOKBACK_MS = 10 * 60 * 1000;
|
|
91660
92145
|
function readLastTerminalUpdateAudit(opts = {}) {
|
|
91661
92146
|
const path2 = opts.auditLogPath ?? defaultAuditLogPath();
|
|
91662
|
-
const exists = opts.exists ??
|
|
91663
|
-
const readFile = opts.readFile ?? ((p) =>
|
|
92147
|
+
const exists = opts.exists ?? existsSync47;
|
|
92148
|
+
const readFile = opts.readFile ?? ((p) => readFileSync50(p, "utf-8"));
|
|
91664
92149
|
if (!exists(path2))
|
|
91665
92150
|
return null;
|
|
91666
92151
|
let raw;
|
|
@@ -91721,15 +92206,15 @@ function renderUpdateOutcomeLine(entry) {
|
|
|
91721
92206
|
`);
|
|
91722
92207
|
}
|
|
91723
92208
|
function claimUpdateAnnouncement(requestId, opts = {}) {
|
|
91724
|
-
const stateDir = opts.stateDir ?? process.env.TELEGRAM_STATE_DIR ??
|
|
91725
|
-
const dir =
|
|
92209
|
+
const stateDir = opts.stateDir ?? process.env.TELEGRAM_STATE_DIR ?? join52(homedir18(), ".switchroom");
|
|
92210
|
+
const dir = join52(stateDir, "update-announced");
|
|
91726
92211
|
try {
|
|
91727
|
-
|
|
92212
|
+
mkdirSync41(dir, { recursive: true });
|
|
91728
92213
|
} catch {
|
|
91729
92214
|
return false;
|
|
91730
92215
|
}
|
|
91731
92216
|
const safeId = requestId.replace(/[^A-Za-z0-9_.-]/g, "_").slice(0, 200);
|
|
91732
|
-
const path2 =
|
|
92217
|
+
const path2 = join52(dir, safeId);
|
|
91733
92218
|
try {
|
|
91734
92219
|
const fd = openSync9(path2, "wx");
|
|
91735
92220
|
closeSync9(fd);
|
|
@@ -91749,7 +92234,7 @@ function maybeRenderUpdateAnnouncement(opts = {}) {
|
|
|
91749
92234
|
|
|
91750
92235
|
// issues-card.ts
|
|
91751
92236
|
init_card_format();
|
|
91752
|
-
import { readFileSync as
|
|
92237
|
+
import { readFileSync as readFileSync51, writeFileSync as writeFileSync41 } from "node:fs";
|
|
91753
92238
|
var SEVERITY_EMOJI = {
|
|
91754
92239
|
info: "\u2139\ufe0f",
|
|
91755
92240
|
warn: "\u26a0\ufe0f",
|
|
@@ -91841,7 +92326,7 @@ function extractRetryAfterSecs2(err) {
|
|
|
91841
92326
|
var COOLDOWN_JITTER_MS2 = 500;
|
|
91842
92327
|
function readPersistedMessageId(path2, log) {
|
|
91843
92328
|
try {
|
|
91844
|
-
const raw =
|
|
92329
|
+
const raw = readFileSync51(path2, "utf8");
|
|
91845
92330
|
const parsed = JSON.parse(raw);
|
|
91846
92331
|
const v = parsed.messageId;
|
|
91847
92332
|
if (typeof v === "number" && Number.isInteger(v) && v > 0)
|
|
@@ -91857,7 +92342,7 @@ function readPersistedMessageId(path2, log) {
|
|
|
91857
92342
|
}
|
|
91858
92343
|
function writePersistedMessageId(path2, messageId, log) {
|
|
91859
92344
|
try {
|
|
91860
|
-
|
|
92345
|
+
writeFileSync41(path2, JSON.stringify({ messageId }) + `
|
|
91861
92346
|
`, { mode: 384 });
|
|
91862
92347
|
} catch (err) {
|
|
91863
92348
|
log(`issues-card: persist write failed (${err.message})`);
|
|
@@ -91950,24 +92435,24 @@ function createIssuesCardHandle(opts) {
|
|
|
91950
92435
|
}
|
|
91951
92436
|
|
|
91952
92437
|
// issues-watcher.ts
|
|
91953
|
-
import { existsSync as
|
|
91954
|
-
import { join as
|
|
92438
|
+
import { existsSync as existsSync49, statSync as statSync16 } from "node:fs";
|
|
92439
|
+
import { join as join54 } from "node:path";
|
|
91955
92440
|
|
|
91956
92441
|
// ../src/issues/store.ts
|
|
91957
92442
|
import {
|
|
91958
92443
|
closeSync as closeSync10,
|
|
91959
|
-
existsSync as
|
|
91960
|
-
mkdirSync as
|
|
92444
|
+
existsSync as existsSync48,
|
|
92445
|
+
mkdirSync as mkdirSync42,
|
|
91961
92446
|
openSync as openSync10,
|
|
91962
92447
|
readdirSync as readdirSync11,
|
|
91963
|
-
readFileSync as
|
|
91964
|
-
renameSync as
|
|
92448
|
+
readFileSync as readFileSync52,
|
|
92449
|
+
renameSync as renameSync21,
|
|
91965
92450
|
statSync as statSync15,
|
|
91966
92451
|
unlinkSync as unlinkSync23,
|
|
91967
|
-
writeFileSync as
|
|
92452
|
+
writeFileSync as writeFileSync42,
|
|
91968
92453
|
writeSync as writeSync6
|
|
91969
92454
|
} from "node:fs";
|
|
91970
|
-
import { join as
|
|
92455
|
+
import { join as join53 } from "node:path";
|
|
91971
92456
|
import { randomBytes as randomBytes8 } from "node:crypto";
|
|
91972
92457
|
import { execSync } from "node:child_process";
|
|
91973
92458
|
|
|
@@ -91986,12 +92471,12 @@ init_redact();
|
|
|
91986
92471
|
var ISSUES_FILE = "issues.jsonl";
|
|
91987
92472
|
var ISSUES_LOCK = "issues.lock";
|
|
91988
92473
|
function readAll(stateDir) {
|
|
91989
|
-
const path2 =
|
|
91990
|
-
if (!
|
|
92474
|
+
const path2 = join53(stateDir, ISSUES_FILE);
|
|
92475
|
+
if (!existsSync48(path2))
|
|
91991
92476
|
return [];
|
|
91992
92477
|
let raw;
|
|
91993
92478
|
try {
|
|
91994
|
-
raw =
|
|
92479
|
+
raw = readFileSync52(path2, "utf-8");
|
|
91995
92480
|
} catch {
|
|
91996
92481
|
return [];
|
|
91997
92482
|
}
|
|
@@ -92023,7 +92508,7 @@ function list2(stateDir, opts = {}) {
|
|
|
92023
92508
|
});
|
|
92024
92509
|
}
|
|
92025
92510
|
function resolve11(stateDir, fingerprint, nowFn = Date.now) {
|
|
92026
|
-
if (!
|
|
92511
|
+
if (!existsSync48(join53(stateDir, ISSUES_FILE)))
|
|
92027
92512
|
return 0;
|
|
92028
92513
|
return withLock(stateDir, () => {
|
|
92029
92514
|
const all2 = readAll(stateDir);
|
|
@@ -92041,14 +92526,14 @@ function resolve11(stateDir, fingerprint, nowFn = Date.now) {
|
|
|
92041
92526
|
});
|
|
92042
92527
|
}
|
|
92043
92528
|
function writeAll(stateDir, events) {
|
|
92044
|
-
const path2 =
|
|
92529
|
+
const path2 = join53(stateDir, ISSUES_FILE);
|
|
92045
92530
|
sweepOrphanTmpFiles(stateDir);
|
|
92046
92531
|
const tmp = `${path2}.tmp-${process.pid}-${randomBytes8(4).toString("hex")}`;
|
|
92047
92532
|
const body = events.length === 0 ? "" : events.map((e) => JSON.stringify(e)).join(`
|
|
92048
92533
|
`) + `
|
|
92049
92534
|
`;
|
|
92050
|
-
|
|
92051
|
-
|
|
92535
|
+
writeFileSync42(tmp, body, "utf-8");
|
|
92536
|
+
renameSync21(tmp, path2);
|
|
92052
92537
|
}
|
|
92053
92538
|
var ORPHAN_TMP_TTL_MS = 60000;
|
|
92054
92539
|
var TMP_PREFIX = `${ISSUES_FILE}.tmp-`;
|
|
@@ -92063,7 +92548,7 @@ function sweepOrphanTmpFiles(stateDir) {
|
|
|
92063
92548
|
for (const entry of entries) {
|
|
92064
92549
|
if (!entry.startsWith(TMP_PREFIX))
|
|
92065
92550
|
continue;
|
|
92066
|
-
const tmpPath2 =
|
|
92551
|
+
const tmpPath2 = join53(stateDir, entry);
|
|
92067
92552
|
try {
|
|
92068
92553
|
const stat = statSync15(tmpPath2);
|
|
92069
92554
|
if (stat.mtimeMs < cutoff) {
|
|
@@ -92075,7 +92560,7 @@ function sweepOrphanTmpFiles(stateDir) {
|
|
|
92075
92560
|
var LOCK_RETRY_MS = 25;
|
|
92076
92561
|
var LOCK_TIMEOUT_MS = 1e4;
|
|
92077
92562
|
function withLock(stateDir, fn) {
|
|
92078
|
-
const lockPath =
|
|
92563
|
+
const lockPath = join53(stateDir, ISSUES_LOCK);
|
|
92079
92564
|
const startedAt = Date.now();
|
|
92080
92565
|
let fd = null;
|
|
92081
92566
|
while (fd === null) {
|
|
@@ -92110,7 +92595,7 @@ function withLock(stateDir, fn) {
|
|
|
92110
92595
|
function tryStealStaleLock(lockPath) {
|
|
92111
92596
|
let pidStr;
|
|
92112
92597
|
try {
|
|
92113
|
-
pidStr =
|
|
92598
|
+
pidStr = readFileSync52(lockPath, "utf-8").trim();
|
|
92114
92599
|
} catch {
|
|
92115
92600
|
return true;
|
|
92116
92601
|
}
|
|
@@ -92160,7 +92645,7 @@ function isIssueEvent(v) {
|
|
|
92160
92645
|
// issues-watcher.ts
|
|
92161
92646
|
var DEFAULT_POLL_INTERVAL_MS2 = 2000;
|
|
92162
92647
|
function startIssuesWatcher(opts) {
|
|
92163
|
-
const path2 =
|
|
92648
|
+
const path2 = join54(opts.stateDir, ISSUES_FILE);
|
|
92164
92649
|
const log = opts.log ?? (() => {});
|
|
92165
92650
|
const intervalMs = opts.pollIntervalMs ?? DEFAULT_POLL_INTERVAL_MS2;
|
|
92166
92651
|
const setIntervalFn = opts.setInterval ?? setInterval;
|
|
@@ -92208,7 +92693,7 @@ function startIssuesWatcher(opts) {
|
|
|
92208
92693
|
};
|
|
92209
92694
|
}
|
|
92210
92695
|
function defaultSignatureProvider(path2) {
|
|
92211
|
-
if (!
|
|
92696
|
+
if (!existsSync49(path2))
|
|
92212
92697
|
return null;
|
|
92213
92698
|
try {
|
|
92214
92699
|
const stat = statSync16(path2);
|
|
@@ -92919,8 +93404,8 @@ function readBashCommand(inputPreview) {
|
|
|
92919
93404
|
}
|
|
92920
93405
|
|
|
92921
93406
|
// gateway/scoped-grant-store.ts
|
|
92922
|
-
import { readFileSync as
|
|
92923
|
-
import { join as
|
|
93407
|
+
import { readFileSync as readFileSync53, writeFileSync as writeFileSync43 } from "node:fs";
|
|
93408
|
+
import { join as join55 } from "node:path";
|
|
92924
93409
|
|
|
92925
93410
|
// scoped-approval.ts
|
|
92926
93411
|
var SCOPED_APPROVAL_DEFAULT_TTL_MS2 = 30 * 60 * 1000;
|
|
@@ -92962,11 +93447,11 @@ function scopedGrantPersistEnabled(env = process.env) {
|
|
|
92962
93447
|
return env.SWITCHROOM_SCOPED_GRANT_PERSIST !== "0";
|
|
92963
93448
|
}
|
|
92964
93449
|
function createScopedGrantStore(stateDir, env = process.env) {
|
|
92965
|
-
const filePath =
|
|
93450
|
+
const filePath = join55(stateDir, "scoped-grants.json");
|
|
92966
93451
|
const enabled7 = scopedGrantPersistEnabled(env);
|
|
92967
93452
|
function read() {
|
|
92968
93453
|
try {
|
|
92969
|
-
const raw =
|
|
93454
|
+
const raw = readFileSync53(filePath, "utf-8");
|
|
92970
93455
|
const parsed = JSON.parse(raw);
|
|
92971
93456
|
return Array.isArray(parsed) ? parsed : [];
|
|
92972
93457
|
} catch {
|
|
@@ -92984,7 +93469,7 @@ function createScopedGrantStore(stateDir, env = process.env) {
|
|
|
92984
93469
|
if (!enabled7)
|
|
92985
93470
|
return;
|
|
92986
93471
|
try {
|
|
92987
|
-
|
|
93472
|
+
writeFileSync43(filePath, JSON.stringify(serializeScopedGrants(store2)), {
|
|
92988
93473
|
encoding: "utf-8",
|
|
92989
93474
|
mode: 384
|
|
92990
93475
|
});
|
|
@@ -93335,8 +93820,8 @@ function isDiffPreApproved(agentName3, unifiedDiff, deps) {
|
|
|
93335
93820
|
|
|
93336
93821
|
// credits-watch.ts
|
|
93337
93822
|
init_card_format();
|
|
93338
|
-
import { readFileSync as
|
|
93339
|
-
import { join as
|
|
93823
|
+
import { readFileSync as readFileSync54, writeFileSync as writeFileSync44, existsSync as existsSync50, mkdirSync as mkdirSync43 } from "fs";
|
|
93824
|
+
import { join as join56 } from "path";
|
|
93340
93825
|
var STATE_FILE = "credits-watch.json";
|
|
93341
93826
|
var DEFAULT_CREDIT_FATAL_REASONS = new Set;
|
|
93342
93827
|
var KNOWN_CREDIT_REASONS = [
|
|
@@ -93358,12 +93843,12 @@ function emptyCreditState() {
|
|
|
93358
93843
|
return { lastNotifiedReason: null, lastNotifiedAt: 0 };
|
|
93359
93844
|
}
|
|
93360
93845
|
function readClaudeJsonOverage(claudeConfigDir) {
|
|
93361
|
-
const path2 =
|
|
93362
|
-
if (!
|
|
93846
|
+
const path2 = join56(claudeConfigDir, ".claude.json");
|
|
93847
|
+
if (!existsSync50(path2))
|
|
93363
93848
|
return null;
|
|
93364
93849
|
let raw;
|
|
93365
93850
|
try {
|
|
93366
|
-
raw =
|
|
93851
|
+
raw = readFileSync54(path2, "utf-8");
|
|
93367
93852
|
} catch {
|
|
93368
93853
|
return null;
|
|
93369
93854
|
}
|
|
@@ -93441,11 +93926,11 @@ function humanizeReason(reason) {
|
|
|
93441
93926
|
}
|
|
93442
93927
|
}
|
|
93443
93928
|
function loadCreditState(stateDir) {
|
|
93444
|
-
const path2 =
|
|
93445
|
-
if (!
|
|
93929
|
+
const path2 = join56(stateDir, STATE_FILE);
|
|
93930
|
+
if (!existsSync50(path2))
|
|
93446
93931
|
return emptyCreditState();
|
|
93447
93932
|
try {
|
|
93448
|
-
const raw =
|
|
93933
|
+
const raw = readFileSync54(path2, "utf-8");
|
|
93449
93934
|
const parsed = JSON.parse(raw);
|
|
93450
93935
|
if (parsed && typeof parsed === "object" && (parsed.lastNotifiedReason === null || typeof parsed.lastNotifiedReason === "string") && typeof parsed.lastNotifiedAt === "number" && Number.isFinite(parsed.lastNotifiedAt)) {
|
|
93451
93936
|
return {
|
|
@@ -93457,17 +93942,17 @@ function loadCreditState(stateDir) {
|
|
|
93457
93942
|
return emptyCreditState();
|
|
93458
93943
|
}
|
|
93459
93944
|
function saveCreditState(stateDir, state7) {
|
|
93460
|
-
|
|
93461
|
-
const path2 =
|
|
93462
|
-
|
|
93945
|
+
mkdirSync43(stateDir, { recursive: true });
|
|
93946
|
+
const path2 = join56(stateDir, STATE_FILE);
|
|
93947
|
+
writeFileSync44(path2, JSON.stringify(state7, null, 2) + `
|
|
93463
93948
|
`, { mode: 384 });
|
|
93464
93949
|
}
|
|
93465
93950
|
|
|
93466
93951
|
// quota-watch.ts
|
|
93467
93952
|
init_auth_snapshot_format();
|
|
93468
93953
|
init_card_format();
|
|
93469
|
-
import { readFileSync as
|
|
93470
|
-
import { join as
|
|
93954
|
+
import { readFileSync as readFileSync55, writeFileSync as writeFileSync45, existsSync as existsSync51, mkdirSync as mkdirSync44 } from "fs";
|
|
93955
|
+
import { join as join57 } from "path";
|
|
93471
93956
|
var STATE_FILE2 = "quota-watch.json";
|
|
93472
93957
|
function emptyQuotaWatchState() {
|
|
93473
93958
|
return {};
|
|
@@ -93705,11 +94190,11 @@ function buildRecoveryMessage(agentName3, snap) {
|
|
|
93705
94190
|
`);
|
|
93706
94191
|
}
|
|
93707
94192
|
function loadQuotaWatchState(stateDir) {
|
|
93708
|
-
const path2 =
|
|
93709
|
-
if (!
|
|
94193
|
+
const path2 = join57(stateDir, STATE_FILE2);
|
|
94194
|
+
if (!existsSync51(path2))
|
|
93710
94195
|
return emptyQuotaWatchState();
|
|
93711
94196
|
try {
|
|
93712
|
-
const raw =
|
|
94197
|
+
const raw = readFileSync55(path2, "utf-8");
|
|
93713
94198
|
const parsed = JSON.parse(raw);
|
|
93714
94199
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
93715
94200
|
return emptyQuotaWatchState();
|
|
@@ -93726,9 +94211,9 @@ function loadQuotaWatchState(stateDir) {
|
|
|
93726
94211
|
}
|
|
93727
94212
|
}
|
|
93728
94213
|
function saveQuotaWatchState(stateDir, state7) {
|
|
93729
|
-
|
|
93730
|
-
const path2 =
|
|
93731
|
-
|
|
94214
|
+
mkdirSync44(stateDir, { recursive: true });
|
|
94215
|
+
const path2 = join57(stateDir, STATE_FILE2);
|
|
94216
|
+
writeFileSync45(path2, JSON.stringify(state7, null, 2) + `
|
|
93732
94217
|
`, { mode: 384 });
|
|
93733
94218
|
}
|
|
93734
94219
|
function patchQuotaWatchState(current, accountLabel, accountState) {
|
|
@@ -93776,27 +94261,27 @@ init_auth_snapshot_format2();
|
|
|
93776
94261
|
// gateway/turn-active-marker.ts
|
|
93777
94262
|
import {
|
|
93778
94263
|
closeSync as closeSync11,
|
|
93779
|
-
existsSync as
|
|
93780
|
-
mkdirSync as
|
|
94264
|
+
existsSync as existsSync52,
|
|
94265
|
+
mkdirSync as mkdirSync45,
|
|
93781
94266
|
openSync as openSync11,
|
|
93782
|
-
readFileSync as
|
|
94267
|
+
readFileSync as readFileSync56,
|
|
93783
94268
|
statSync as statSync17,
|
|
93784
94269
|
unlinkSync as unlinkSync24,
|
|
93785
94270
|
utimesSync as utimesSync2,
|
|
93786
|
-
writeFileSync as
|
|
94271
|
+
writeFileSync as writeFileSync46
|
|
93787
94272
|
} from "node:fs";
|
|
93788
|
-
import { join as
|
|
94273
|
+
import { join as join58 } from "node:path";
|
|
93789
94274
|
var TURN_ACTIVE_MARKER_FILE2 = "turn-active.json";
|
|
93790
94275
|
var TURN_ACTIVE_HARD_TTL_MS2 = 10 * 60000;
|
|
93791
94276
|
var TURN_ACTIVE_IDLE_SWEEP_MS = 60000;
|
|
93792
94277
|
function removeTurnActiveMarker2(stateDir) {
|
|
93793
94278
|
try {
|
|
93794
|
-
unlinkSync24(
|
|
94279
|
+
unlinkSync24(join58(stateDir, TURN_ACTIVE_MARKER_FILE2));
|
|
93795
94280
|
} catch {}
|
|
93796
94281
|
}
|
|
93797
94282
|
function sweepStaleTurnActiveMarker(stateDir, opts) {
|
|
93798
|
-
const path2 =
|
|
93799
|
-
if (!
|
|
94283
|
+
const path2 = join58(stateDir, TURN_ACTIVE_MARKER_FILE2);
|
|
94284
|
+
if (!existsSync52(path2))
|
|
93800
94285
|
return false;
|
|
93801
94286
|
const now = opts.now ?? Date.now();
|
|
93802
94287
|
try {
|
|
@@ -93808,7 +94293,7 @@ function sweepStaleTurnActiveMarker(stateDir, opts) {
|
|
|
93808
94293
|
return false;
|
|
93809
94294
|
let payload = null;
|
|
93810
94295
|
try {
|
|
93811
|
-
payload =
|
|
94296
|
+
payload = readFileSync56(path2, "utf8");
|
|
93812
94297
|
} catch {}
|
|
93813
94298
|
unlinkSync24(path2);
|
|
93814
94299
|
if (opts.onRemove) {
|
|
@@ -93826,7 +94311,7 @@ function sweepStaleTurnActiveMarker(stateDir, opts) {
|
|
|
93826
94311
|
}
|
|
93827
94312
|
}
|
|
93828
94313
|
function readTurnActiveMarkerAgeMs2(stateDir, now) {
|
|
93829
|
-
const path2 =
|
|
94314
|
+
const path2 = join58(stateDir, TURN_ACTIVE_MARKER_FILE2);
|
|
93830
94315
|
try {
|
|
93831
94316
|
const st = statSync17(path2);
|
|
93832
94317
|
return (now ?? Date.now()) - st.mtimeMs;
|
|
@@ -93839,19 +94324,19 @@ function effectiveTurnAgeMs(markerAgeMs, turnStartedAt, now) {
|
|
|
93839
94324
|
}
|
|
93840
94325
|
|
|
93841
94326
|
// gateway/gateway-heartbeat.ts
|
|
93842
|
-
import { mkdirSync as
|
|
93843
|
-
import { join as
|
|
94327
|
+
import { mkdirSync as mkdirSync46, utimesSync as utimesSync3, writeFileSync as writeFileSync47 } from "node:fs";
|
|
94328
|
+
import { join as join59 } from "node:path";
|
|
93844
94329
|
var GATEWAY_HEARTBEAT_FILE = "gateway-heartbeat";
|
|
93845
94330
|
var GATEWAY_HEARTBEAT_INTERVAL_MS = 15000;
|
|
93846
94331
|
function touchGatewayHeartbeat(stateDir) {
|
|
93847
|
-
const path2 =
|
|
94332
|
+
const path2 = join59(stateDir, GATEWAY_HEARTBEAT_FILE);
|
|
93848
94333
|
const now = new Date;
|
|
93849
94334
|
try {
|
|
93850
94335
|
utimesSync3(path2, now, now);
|
|
93851
94336
|
} catch {
|
|
93852
94337
|
try {
|
|
93853
|
-
|
|
93854
|
-
|
|
94338
|
+
mkdirSync46(stateDir, { recursive: true });
|
|
94339
|
+
writeFileSync47(path2, `${Date.now()}
|
|
93855
94340
|
`, { mode: 384 });
|
|
93856
94341
|
} catch {}
|
|
93857
94342
|
}
|
|
@@ -93894,11 +94379,23 @@ async function sweepOutbox(deps) {
|
|
|
93894
94379
|
textAlreadyDelivered: resolved != null && deps.textAlreadyDelivered(resolved.chatId, resolved.threadId, record2.text),
|
|
93895
94380
|
routable: resolved != null,
|
|
93896
94381
|
routePrefix,
|
|
93897
|
-
quietMs: deps.quietMs ?? OUTBOX_QUIET_MS
|
|
94382
|
+
quietMs: deps.quietMs ?? OUTBOX_QUIET_MS,
|
|
94383
|
+
shownLedgerHit: isShownBlock(record2.turnNonce, record2.text, deps.stateDir)
|
|
93898
94384
|
});
|
|
93899
94385
|
if (decision.action !== "send" && decision.action !== "send-delayed") {
|
|
93900
94386
|
summary.skipped++;
|
|
93901
|
-
if (decision.action === "skip-
|
|
94387
|
+
if (decision.action === "skip-ephemeral-shown") {
|
|
94388
|
+
appendDelivered({
|
|
94389
|
+
turnNonce: record2.turnNonce,
|
|
94390
|
+
textSha256: record2.textSha256,
|
|
94391
|
+
ts: now,
|
|
94392
|
+
deliverySource: "sweep",
|
|
94393
|
+
replyAlreadyDeliveredThisTurn: record2.replyAlreadyDeliveredThisTurn === true
|
|
94394
|
+
}, deps.stateDir);
|
|
94395
|
+
clearOutboxRecord(record2.turnNonce, deps.stateDir);
|
|
94396
|
+
log(`outbox-sweep: suppressed ephemeral-shown nonce=${record2.turnNonce}
|
|
94397
|
+
`);
|
|
94398
|
+
} else if (decision.action === "skip-journaled") {
|
|
93902
94399
|
clearOutboxRecord(record2.turnNonce, deps.stateDir);
|
|
93903
94400
|
} else if (decision.action === "skip-dedup") {
|
|
93904
94401
|
appendDelivered({
|
|
@@ -93986,10 +94483,10 @@ function startOutboxSweep(deps) {
|
|
|
93986
94483
|
}
|
|
93987
94484
|
|
|
93988
94485
|
// ../src/build-info.ts
|
|
93989
|
-
var VERSION = "0.19.
|
|
93990
|
-
var COMMIT_SHA = "
|
|
93991
|
-
var COMMIT_DATE = "2026-07-
|
|
93992
|
-
var LATEST_PR =
|
|
94486
|
+
var VERSION = "0.19.15";
|
|
94487
|
+
var COMMIT_SHA = "20691874";
|
|
94488
|
+
var COMMIT_DATE = "2026-07-24T12:46:35+10:00";
|
|
94489
|
+
var LATEST_PR = 3518;
|
|
93993
94490
|
var COMMITS_AHEAD_OF_TAG = 0;
|
|
93994
94491
|
|
|
93995
94492
|
// gateway/boot-version.ts
|
|
@@ -94067,11 +94564,11 @@ init_peercred();
|
|
|
94067
94564
|
import * as net5 from "node:net";
|
|
94068
94565
|
import * as fs2 from "node:fs";
|
|
94069
94566
|
import { homedir as homedir19 } from "node:os";
|
|
94070
|
-
import { join as
|
|
94567
|
+
import { join as join60 } from "node:path";
|
|
94071
94568
|
var DEFAULT_TIMEOUT_MS4 = 2000;
|
|
94072
94569
|
var UNLOCK_TIMEOUT_MS = 30000;
|
|
94073
|
-
var LEGACY_SOCKET_PATH2 =
|
|
94074
|
-
var OPERATOR_SOCKET_PATH2 =
|
|
94570
|
+
var LEGACY_SOCKET_PATH2 = join60(homedir19(), ".switchroom", "vault-broker.sock");
|
|
94571
|
+
var OPERATOR_SOCKET_PATH2 = join60(homedir19(), ".switchroom", "broker-operator", "sock");
|
|
94075
94572
|
function defaultBrokerSocketPath2() {
|
|
94076
94573
|
if (fs2.existsSync(OPERATOR_SOCKET_PATH2))
|
|
94077
94574
|
return OPERATOR_SOCKET_PATH2;
|
|
@@ -94953,8 +95450,8 @@ function resolveVaultApprovalPosture(broker) {
|
|
|
94953
95450
|
}
|
|
94954
95451
|
|
|
94955
95452
|
// registry/turns-schema.ts
|
|
94956
|
-
import { chmodSync as chmodSync12, mkdirSync as
|
|
94957
|
-
import { join as
|
|
95453
|
+
import { chmodSync as chmodSync12, mkdirSync as mkdirSync47 } from "fs";
|
|
95454
|
+
import { join as join61 } from "path";
|
|
94958
95455
|
var DatabaseClass3 = null;
|
|
94959
95456
|
function loadDatabaseClass3() {
|
|
94960
95457
|
if (DatabaseClass3 != null)
|
|
@@ -95026,9 +95523,9 @@ function applySchema(db3) {
|
|
|
95026
95523
|
}
|
|
95027
95524
|
function openTurnsDb(agentDir) {
|
|
95028
95525
|
const Database = loadDatabaseClass3();
|
|
95029
|
-
const dir =
|
|
95030
|
-
|
|
95031
|
-
const path2 =
|
|
95526
|
+
const dir = join61(agentDir, "telegram");
|
|
95527
|
+
mkdirSync47(dir, { recursive: true, mode: 448 });
|
|
95528
|
+
const path2 = join61(dir, "registry.db");
|
|
95032
95529
|
const db3 = new Database(path2, { create: true });
|
|
95033
95530
|
applySchema(db3);
|
|
95034
95531
|
try {
|
|
@@ -95372,7 +95869,7 @@ function selectResumeBuilder(endedVia, opts) {
|
|
|
95372
95869
|
}
|
|
95373
95870
|
|
|
95374
95871
|
// gateway/bridge-dead-watchdog.ts
|
|
95375
|
-
import { readFileSync as
|
|
95872
|
+
import { readFileSync as readFileSync58, writeFileSync as writeFileSync48, renameSync as renameSync22, unlinkSync as unlinkSync25 } from "node:fs";
|
|
95376
95873
|
|
|
95377
95874
|
// gateway/cron-session.ts
|
|
95378
95875
|
var CRON_IDENTITY_SUFFIX2 = "-cron";
|
|
@@ -95405,7 +95902,7 @@ function readFreshCrashLogTail(path2, opts = {}) {
|
|
|
95405
95902
|
const nowMs3 = opts.nowMs ?? Date.now();
|
|
95406
95903
|
const freshWindowMs = opts.freshWindowMs ?? CRASH_LOG_FRESH_WINDOW_MS;
|
|
95407
95904
|
const maxLines = opts.maxLines ?? CRASH_LOG_TAIL_LINES;
|
|
95408
|
-
const readFile = opts.readFile ?? ((p) =>
|
|
95905
|
+
const readFile = opts.readFile ?? ((p) => readFileSync58(p, "utf8"));
|
|
95409
95906
|
let raw;
|
|
95410
95907
|
try {
|
|
95411
95908
|
raw = readFile(path2);
|
|
@@ -95426,13 +95923,13 @@ function readFreshCrashLogTail(path2, opts = {}) {
|
|
|
95426
95923
|
}
|
|
95427
95924
|
function writeBridgeDeadEscalationMarker(path2, marker) {
|
|
95428
95925
|
const tmp = `${path2}.tmp-${process.pid}-${Date.now()}`;
|
|
95429
|
-
|
|
95430
|
-
|
|
95926
|
+
writeFileSync48(tmp, JSON.stringify(marker), "utf8");
|
|
95927
|
+
renameSync22(tmp, path2);
|
|
95431
95928
|
}
|
|
95432
95929
|
function consumeBridgeDeadEscalationMarker(path2, nowMs3 = Date.now(), maxAgeMs = ESCALATION_MARKER_MAX_AGE_MS) {
|
|
95433
95930
|
let marker = null;
|
|
95434
95931
|
try {
|
|
95435
|
-
const parsed = JSON.parse(
|
|
95932
|
+
const parsed = JSON.parse(readFileSync58(path2, "utf8"));
|
|
95436
95933
|
if (typeof parsed.ts === "number" && Number.isFinite(parsed.ts) && typeof parsed.reason === "string") {
|
|
95437
95934
|
const age = nowMs3 - parsed.ts;
|
|
95438
95935
|
if (age >= 0 && age < maxAgeMs) {
|
|
@@ -95585,7 +96082,7 @@ function createBridgeDeadWatchdog(opts) {
|
|
|
95585
96082
|
}
|
|
95586
96083
|
|
|
95587
96084
|
// gateway/boot-probes.ts
|
|
95588
|
-
import { readFileSync as
|
|
96085
|
+
import { readFileSync as readFileSync59, readdirSync as readdirSync12, existsSync as existsSync54 } from "fs";
|
|
95589
96086
|
init_quota_cache();
|
|
95590
96087
|
init_quota_check();
|
|
95591
96088
|
import { execFile as execFileCb2 } from "child_process";
|
|
@@ -95593,7 +96090,7 @@ import { promisify as promisify2 } from "util";
|
|
|
95593
96090
|
var execFile2 = promisify2(execFileCb2);
|
|
95594
96091
|
var realProcFs2 = {
|
|
95595
96092
|
readdir: (p) => readdirSync12(p),
|
|
95596
|
-
readFile: (p) =>
|
|
96093
|
+
readFile: (p) => readFileSync59(p, "utf-8")
|
|
95597
96094
|
};
|
|
95598
96095
|
function findAgentProcessInContainer2(fs3 = realProcFs2) {
|
|
95599
96096
|
let entries;
|
|
@@ -95843,7 +96340,7 @@ if (isGatewayMain) {
|
|
|
95843
96340
|
shutdownAnalytics();
|
|
95844
96341
|
});
|
|
95845
96342
|
}
|
|
95846
|
-
var STATE_DIR = process.env.TELEGRAM_STATE_DIR ??
|
|
96343
|
+
var STATE_DIR = process.env.TELEGRAM_STATE_DIR ?? join62(homedir20(), ".claude", "channels", "telegram");
|
|
95847
96344
|
var permCardStore = createPermissionCardStore(STATE_DIR);
|
|
95848
96345
|
var BLOCKED_APPROVALS_DIR = process.env.SWITCHROOM_BLOCKED_APPROVALS_DIR ?? "/state/blocked-approvals";
|
|
95849
96346
|
var AGENT_NAME = process.env.SWITCHROOM_AGENT_NAME ?? "agent";
|
|
@@ -95882,7 +96379,7 @@ function alwaysAllowDrainDeps() {
|
|
|
95882
96379
|
return {
|
|
95883
96380
|
readConfigText: () => {
|
|
95884
96381
|
const cfgPath = process.env.SWITCHROOM_CONFIG ?? SWITCHROOM_CONFIG ?? findConfigFile2();
|
|
95885
|
-
return
|
|
96382
|
+
return readFileSync60(cfgPath, "utf8");
|
|
95886
96383
|
},
|
|
95887
96384
|
resolveAllowList: (_configText, agentName3) => {
|
|
95888
96385
|
const cfg = loadConfig2();
|
|
@@ -95943,11 +96440,11 @@ function scheduleAlwaysAllowPersistDrain() {
|
|
|
95943
96440
|
}, ALWAYS_ALLOW_DRAIN_INTERVAL_MS);
|
|
95944
96441
|
timer3.unref?.();
|
|
95945
96442
|
}
|
|
95946
|
-
var ACCESS_FILE =
|
|
95947
|
-
var APPROVED_DIR =
|
|
95948
|
-
var ENV_FILE =
|
|
95949
|
-
var INBOX_DIR =
|
|
95950
|
-
var PEOPLE_FILE =
|
|
96443
|
+
var ACCESS_FILE = join62(STATE_DIR, "access.json");
|
|
96444
|
+
var APPROVED_DIR = join62(STATE_DIR, "approved");
|
|
96445
|
+
var ENV_FILE = join62(STATE_DIR, ".env");
|
|
96446
|
+
var INBOX_DIR = join62(STATE_DIR, "inbox");
|
|
96447
|
+
var PEOPLE_FILE = join62(STATE_DIR, "people.json");
|
|
95951
96448
|
function triggerSelfRestart(targetAgent, reason, delayMs = 300) {
|
|
95952
96449
|
const isDocker = process.env.SWITCHROOM_RUNTIME === "docker";
|
|
95953
96450
|
const selfAgent = process.env.SWITCHROOM_AGENT_NAME;
|
|
@@ -96012,7 +96509,7 @@ function formatBootVersion() {
|
|
|
96012
96509
|
}
|
|
96013
96510
|
try {
|
|
96014
96511
|
chmodSync14(ENV_FILE, 384);
|
|
96015
|
-
for (const line of
|
|
96512
|
+
for (const line of readFileSync60(ENV_FILE, "utf8").split(`
|
|
96016
96513
|
`)) {
|
|
96017
96514
|
const m = line.match(/^(\w+)=(.*)$/);
|
|
96018
96515
|
if (m && process.env[m[1]] === undefined)
|
|
@@ -96033,7 +96530,7 @@ var bot;
|
|
|
96033
96530
|
var lastGetUpdatesHeartbeatMs = Date.now();
|
|
96034
96531
|
var GRAMMY_VERSION = (() => {
|
|
96035
96532
|
try {
|
|
96036
|
-
const raw =
|
|
96533
|
+
const raw = readFileSync60(new URL("../../node_modules/grammy/package.json", import.meta.url), "utf8");
|
|
96037
96534
|
return JSON.parse(raw).version ?? "unknown";
|
|
96038
96535
|
} catch {
|
|
96039
96536
|
return "unknown";
|
|
@@ -96096,7 +96593,7 @@ function assertSendable(f) {
|
|
|
96096
96593
|
} catch {
|
|
96097
96594
|
throw new Error(`refusing to send file \u2014 cannot resolve real path: ${f}`);
|
|
96098
96595
|
}
|
|
96099
|
-
const inbox =
|
|
96596
|
+
const inbox = join62(stateReal, "inbox");
|
|
96100
96597
|
if (real.startsWith(stateReal + sep4) && !real.startsWith(inbox + sep4)) {
|
|
96101
96598
|
throw new Error(`refusing to send channel state: ${f}`);
|
|
96102
96599
|
}
|
|
@@ -96115,7 +96612,7 @@ function assertSendable(f) {
|
|
|
96115
96612
|
}
|
|
96116
96613
|
function readAccessFile() {
|
|
96117
96614
|
try {
|
|
96118
|
-
const raw =
|
|
96615
|
+
const raw = readFileSync60(ACCESS_FILE, "utf8");
|
|
96119
96616
|
const parsed = JSON.parse(raw);
|
|
96120
96617
|
const allowFrom = validateStringArray("allowFrom", parsed.allowFrom ?? []);
|
|
96121
96618
|
const groups = {};
|
|
@@ -96155,7 +96652,7 @@ function readAccessFile() {
|
|
|
96155
96652
|
if (err.code === "ENOENT")
|
|
96156
96653
|
return defaultAccess();
|
|
96157
96654
|
try {
|
|
96158
|
-
|
|
96655
|
+
renameSync23(ACCESS_FILE, `${ACCESS_FILE}.corrupt-${Date.now()}`);
|
|
96159
96656
|
} catch {}
|
|
96160
96657
|
process.stderr.write(`telegram gateway: access.json is corrupt, moved aside. Starting fresh.
|
|
96161
96658
|
`);
|
|
@@ -96177,7 +96674,7 @@ function loadAccess() {
|
|
|
96177
96674
|
}
|
|
96178
96675
|
function readPeopleFile() {
|
|
96179
96676
|
try {
|
|
96180
|
-
const raw =
|
|
96677
|
+
const raw = readFileSync60(PEOPLE_FILE, "utf8");
|
|
96181
96678
|
const parsed = JSON.parse(raw);
|
|
96182
96679
|
if (!Array.isArray(parsed.entries))
|
|
96183
96680
|
return [];
|
|
@@ -96199,11 +96696,11 @@ function assertAllowedChat(chat_id) {
|
|
|
96199
96696
|
function saveAccess(a) {
|
|
96200
96697
|
if (STATIC)
|
|
96201
96698
|
return;
|
|
96202
|
-
|
|
96699
|
+
mkdirSync49(STATE_DIR, { recursive: true, mode: 448 });
|
|
96203
96700
|
const tmp = ACCESS_FILE + ".tmp";
|
|
96204
|
-
|
|
96701
|
+
writeFileSync50(tmp, JSON.stringify(a, null, 2) + `
|
|
96205
96702
|
`, { mode: 384 });
|
|
96206
|
-
|
|
96703
|
+
renameSync23(tmp, ACCESS_FILE);
|
|
96207
96704
|
}
|
|
96208
96705
|
function pruneExpired(a) {
|
|
96209
96706
|
const now = Date.now();
|
|
@@ -96221,7 +96718,7 @@ var HISTORY_ENABLED = HISTORY_ACCESS.historyEnabled !== false;
|
|
|
96221
96718
|
if (isGatewayMain && HISTORY_ENABLED) {
|
|
96222
96719
|
try {
|
|
96223
96720
|
initHistory(STATE_DIR, HISTORY_ACCESS.historyRetentionDays ?? 30);
|
|
96224
|
-
process.stderr.write(`telegram gateway: history capture enabled at ${
|
|
96721
|
+
process.stderr.write(`telegram gateway: history capture enabled at ${join62(STATE_DIR, "history.db")}
|
|
96225
96722
|
`);
|
|
96226
96723
|
} catch (err) {
|
|
96227
96724
|
process.stderr.write(`telegram gateway: history init failed (${err.message}) \u2014 capture disabled
|
|
@@ -96240,12 +96737,12 @@ if (isGatewayMain)
|
|
|
96240
96737
|
let markerTurnKey = null;
|
|
96241
96738
|
let markerAgeMs = null;
|
|
96242
96739
|
try {
|
|
96243
|
-
const markerPath =
|
|
96244
|
-
if (
|
|
96740
|
+
const markerPath = join62(STATE_DIR, TURN_ACTIVE_MARKER_FILE2);
|
|
96741
|
+
if (existsSync56(markerPath)) {
|
|
96245
96742
|
const st = statSync20(markerPath);
|
|
96246
96743
|
markerAgeMs = Date.now() - st.mtimeMs;
|
|
96247
96744
|
try {
|
|
96248
|
-
const payload = JSON.parse(
|
|
96745
|
+
const payload = JSON.parse(readFileSync60(markerPath, "utf8"));
|
|
96249
96746
|
if (typeof payload.turnKey === "string" && payload.turnKey.length > 0) {
|
|
96250
96747
|
markerTurnKey = payload.turnKey;
|
|
96251
96748
|
}
|
|
@@ -96265,10 +96762,10 @@ if (isGatewayMain)
|
|
|
96265
96762
|
process.stderr.write(`telegram gateway: turn-registry boot-reaper stamped ${reaped} orphaned turn(s)` + `${timeoutTurnKey ? ` (turnKey=${timeoutTurnKey} as 'timeout', markerAgeMs=${markerAgeMs})` : " as 'restart'"}
|
|
96266
96763
|
`);
|
|
96267
96764
|
} else {
|
|
96268
|
-
process.stderr.write(`telegram gateway: turn-registry initialized at ${
|
|
96765
|
+
process.stderr.write(`telegram gateway: turn-registry initialized at ${join62(agentDir, "telegram", "registry.db")}
|
|
96269
96766
|
`);
|
|
96270
96767
|
}
|
|
96271
|
-
const bridgeDeadMarker = consumeBridgeDeadEscalationMarker(
|
|
96768
|
+
const bridgeDeadMarker = consumeBridgeDeadEscalationMarker(join62(STATE_DIR, "bridge-dead-escalation.json"));
|
|
96272
96769
|
if (bridgeDeadMarker != null) {
|
|
96273
96770
|
bridgeDeadPriorStreak = bridgeDeadMarker.count ?? 1;
|
|
96274
96771
|
process.stderr.write(`telegram gateway: boot: prior restart was a bridge-dead escalation (reason=${bridgeDeadMarker.reason}` + `, consecutive=${bridgeDeadPriorStreak}` + `${bridgeDeadMarker.crashTail ? `, crashTail=${bridgeDeadMarker.crashTail}` : ""})
|
|
@@ -96281,7 +96778,7 @@ if (isGatewayMain)
|
|
|
96281
96778
|
const pending2 = findLatestTurnIfInterrupted(turnsDb);
|
|
96282
96779
|
const selfAgent = process.env.SWITCHROOM_AGENT_NAME ?? "";
|
|
96283
96780
|
if (pending2 != null && selfAgent) {
|
|
96284
|
-
const bootResumeMarkerPath = process.env.SWITCHROOM_GATEWAY_CLEAN_SHUTDOWN_MARKER ??
|
|
96781
|
+
const bootResumeMarkerPath = process.env.SWITCHROOM_GATEWAY_CLEAN_SHUTDOWN_MARKER ?? join62(STATE_DIR, "clean-shutdown.json");
|
|
96285
96782
|
const bootResumeCleanMarker = readCleanShutdownMarker(bootResumeMarkerPath);
|
|
96286
96783
|
const bootResumeForceAlways = process.env.SWITCHROOM_BOOT_RESUME_ALWAYS === "1";
|
|
96287
96784
|
const bootResumeMode = parseBootResumeMode(process.env.SWITCHROOM_BOOT_RESUME);
|
|
@@ -96394,7 +96891,7 @@ if (isGatewayMain)
|
|
|
96394
96891
|
`);
|
|
96395
96892
|
}
|
|
96396
96893
|
}
|
|
96397
|
-
const pendingEnvPath =
|
|
96894
|
+
const pendingEnvPath = join62(agentDir, ".pending-turn.env");
|
|
96398
96895
|
try {
|
|
96399
96896
|
if (pending2 != null) {
|
|
96400
96897
|
const lines = [
|
|
@@ -96408,13 +96905,13 @@ if (isGatewayMain)
|
|
|
96408
96905
|
pending2.interrupt_reason != null ? `SWITCHROOM_PENDING_INTERRUPT_REASON=${pending2.interrupt_reason}` : `SWITCHROOM_PENDING_INTERRUPT_REASON=`
|
|
96409
96906
|
];
|
|
96410
96907
|
const pendingEnvTmp = `${pendingEnvPath}.tmp-${process.pid}`;
|
|
96411
|
-
|
|
96908
|
+
writeFileSync50(pendingEnvTmp, lines.join(`
|
|
96412
96909
|
`) + `
|
|
96413
96910
|
`, { mode: 384 });
|
|
96414
|
-
|
|
96911
|
+
renameSync23(pendingEnvTmp, pendingEnvPath);
|
|
96415
96912
|
process.stderr.write(`telegram gateway: pending-turn env written to ${pendingEnvPath} turnKey=${pending2.turn_key} endedVia=${pending2.ended_via ?? "open"}
|
|
96416
96913
|
`);
|
|
96417
|
-
} else if (
|
|
96914
|
+
} else if (existsSync56(pendingEnvPath)) {
|
|
96418
96915
|
rmSync6(pendingEnvPath, { force: true });
|
|
96419
96916
|
process.stderr.write(`telegram gateway: pending-turn env cleared (clean previous shutdown)
|
|
96420
96917
|
`);
|
|
@@ -96522,7 +97019,7 @@ function checkApprovals() {
|
|
|
96522
97019
|
return;
|
|
96523
97020
|
}
|
|
96524
97021
|
for (const senderId of files) {
|
|
96525
|
-
const file =
|
|
97022
|
+
const file = join62(APPROVED_DIR, senderId);
|
|
96526
97023
|
bot.api.sendMessage(senderId, "Paired! Say hi to Claude.").then(() => rmSync6(file, { force: true }), (err) => {
|
|
96527
97024
|
process.stderr.write(`telegram gateway: failed to send approval confirm: ${err}
|
|
96528
97025
|
`);
|
|
@@ -96695,12 +97192,12 @@ function noteAgentOutputAt(key, ts) {
|
|
|
96695
97192
|
lastAgentOutputAt.delete(oldest);
|
|
96696
97193
|
}
|
|
96697
97194
|
}
|
|
96698
|
-
var OBLIGATION_STORE_PATH =
|
|
97195
|
+
var OBLIGATION_STORE_PATH = join62(STATE_DIR, "obligations.json");
|
|
96699
97196
|
var obligationStoreFs = {
|
|
96700
|
-
readFileSync: (p) =>
|
|
96701
|
-
writeFileSync: (p, d) =>
|
|
96702
|
-
renameSync: (a, b) =>
|
|
96703
|
-
existsSync: (p) =>
|
|
97197
|
+
readFileSync: (p) => readFileSync60(p, "utf8"),
|
|
97198
|
+
writeFileSync: (p, d) => writeFileSync50(p, d),
|
|
97199
|
+
renameSync: (a, b) => renameSync23(a, b),
|
|
97200
|
+
existsSync: (p) => existsSync56(p)
|
|
96704
97201
|
};
|
|
96705
97202
|
var obligationLedger = new ObligationLedger(OBLIGATION_REPRESENT_MAX, {
|
|
96706
97203
|
onChange: STATIC || !OBLIGATION_LEDGER_ENABLED ? undefined : (snapshot) => persistObligations(OBLIGATION_STORE_PATH, obligationStoreFs, snapshot)
|
|
@@ -97479,9 +97976,9 @@ function emitTurnRecord(turn, endedAt) {
|
|
|
97479
97976
|
return;
|
|
97480
97977
|
}
|
|
97481
97978
|
},
|
|
97482
|
-
rename: (from, to) =>
|
|
97979
|
+
rename: (from, to) => renameSync23(from, to)
|
|
97483
97980
|
});
|
|
97484
|
-
|
|
97981
|
+
appendFileSync9(turnsPath, rec);
|
|
97485
97982
|
} catch {}
|
|
97486
97983
|
}
|
|
97487
97984
|
function maybeProactiveCompact() {
|
|
@@ -98107,7 +98604,7 @@ function sweepStaleAlwaysAllowCorrelations(now = Date.now()) {
|
|
|
98107
98604
|
var MENTAL_MODEL_CORRELATION_TTL_MS = 720000;
|
|
98108
98605
|
var pendingMentalModelCorrelations = createSweepableStore((entry, now) => now - entry.createdAt > MENTAL_MODEL_CORRELATION_TTL_MS);
|
|
98109
98606
|
function mentalModelCorrelationKey(agentName3, unifiedDiff) {
|
|
98110
|
-
return `${agentName3}::${
|
|
98607
|
+
return `${agentName3}::${createHash6("sha256").update(unifiedDiff).digest("hex")}`;
|
|
98111
98608
|
}
|
|
98112
98609
|
function sweepStaleMentalModelCorrelations(now = Date.now()) {
|
|
98113
98610
|
pendingMentalModelCorrelations.sweep(now);
|
|
@@ -99043,28 +99540,28 @@ var statusPinState = new Map;
|
|
|
99043
99540
|
var statusPinChatIds = new Map;
|
|
99044
99541
|
var statusPinPinnedAt = new Map;
|
|
99045
99542
|
var statusPinRightsCache = new PinRightsCache2;
|
|
99046
|
-
var STATUS_PIN_STORE_PATH =
|
|
99543
|
+
var STATUS_PIN_STORE_PATH = join62(STATE_DIR, "status-pins.json");
|
|
99047
99544
|
var statusPinStoreFs = {
|
|
99048
|
-
readFileSync: (p) =>
|
|
99049
|
-
writeFileSync: (p, d) =>
|
|
99050
|
-
renameSync: (a, b) =>
|
|
99051
|
-
existsSync: (p) =>
|
|
99545
|
+
readFileSync: (p) => readFileSync60(p, "utf8"),
|
|
99546
|
+
writeFileSync: (p, d) => writeFileSync50(p, d),
|
|
99547
|
+
renameSync: (a, b) => renameSync23(a, b),
|
|
99548
|
+
existsSync: (p) => existsSync56(p)
|
|
99052
99549
|
};
|
|
99053
99550
|
var statusPinPersistEnabled = !STATIC && PIN_STATUS_WHILE_WORKING;
|
|
99054
|
-
var ACTIVITY_CARD_STORE_PATH =
|
|
99551
|
+
var ACTIVITY_CARD_STORE_PATH = join62(STATE_DIR, "activity-cards-pending.json");
|
|
99055
99552
|
var activityCardStoreFs = {
|
|
99056
|
-
readFileSync: (p) =>
|
|
99057
|
-
writeFileSync: (p, d) =>
|
|
99058
|
-
renameSync: (a, b) =>
|
|
99059
|
-
existsSync: (p) =>
|
|
99553
|
+
readFileSync: (p) => readFileSync60(p, "utf8"),
|
|
99554
|
+
writeFileSync: (p, d) => writeFileSync50(p, d),
|
|
99555
|
+
renameSync: (a, b) => renameSync23(a, b),
|
|
99556
|
+
existsSync: (p) => existsSync56(p)
|
|
99060
99557
|
};
|
|
99061
99558
|
var activityCardPersistEnabled = !STATIC;
|
|
99062
|
-
var QUEUED_CARD_STORE_PATH =
|
|
99559
|
+
var QUEUED_CARD_STORE_PATH = join62(STATE_DIR, "queued-cards-pending.json");
|
|
99063
99560
|
var queuedCardStoreFs = {
|
|
99064
|
-
readFileSync: (p) =>
|
|
99065
|
-
writeFileSync: (p, d) =>
|
|
99066
|
-
renameSync: (a, b) =>
|
|
99067
|
-
existsSync: (p) =>
|
|
99561
|
+
readFileSync: (p) => readFileSync60(p, "utf8"),
|
|
99562
|
+
writeFileSync: (p, d) => writeFileSync50(p, d),
|
|
99563
|
+
renameSync: (a, b) => renameSync23(a, b),
|
|
99564
|
+
existsSync: (p) => existsSync56(p)
|
|
99068
99565
|
};
|
|
99069
99566
|
var queuedCardPersistEnabled = !STATIC;
|
|
99070
99567
|
function persistQueuedCard(key, chatId, threadId, messageId) {
|
|
@@ -99437,12 +99934,12 @@ var getPinnedProgressCardMessageId = null;
|
|
|
99437
99934
|
var completeProgressCardTurn = null;
|
|
99438
99935
|
var subagentWatcher = null;
|
|
99439
99936
|
var workerActivityFeed = null;
|
|
99440
|
-
var SOCKET_PATH = process.env.SWITCHROOM_GATEWAY_SOCKET ??
|
|
99937
|
+
var SOCKET_PATH = process.env.SWITCHROOM_GATEWAY_SOCKET ?? join62(STATE_DIR, "gateway.sock");
|
|
99441
99938
|
if (isGatewayMain)
|
|
99442
|
-
|
|
99443
|
-
var GATEWAY_PID_PATH = process.env.SWITCHROOM_GATEWAY_PID_FILE ??
|
|
99444
|
-
var GATEWAY_SESSION_MARKER_PATH = process.env.SWITCHROOM_GATEWAY_SESSION_MARKER ??
|
|
99445
|
-
var GATEWAY_CLEAN_SHUTDOWN_MARKER_PATH = process.env.SWITCHROOM_GATEWAY_CLEAN_SHUTDOWN_MARKER ??
|
|
99939
|
+
mkdirSync49(STATE_DIR, { recursive: true, mode: 448 });
|
|
99940
|
+
var GATEWAY_PID_PATH = process.env.SWITCHROOM_GATEWAY_PID_FILE ?? join62(STATE_DIR, "gateway.pid.json");
|
|
99941
|
+
var GATEWAY_SESSION_MARKER_PATH = process.env.SWITCHROOM_GATEWAY_SESSION_MARKER ?? join62(STATE_DIR, "gateway-session.json");
|
|
99942
|
+
var GATEWAY_CLEAN_SHUTDOWN_MARKER_PATH = process.env.SWITCHROOM_GATEWAY_CLEAN_SHUTDOWN_MARKER ?? join62(STATE_DIR, "clean-shutdown.json");
|
|
99446
99943
|
var GATEWAY_STARTED_AT_MS = Date.now();
|
|
99447
99944
|
var BOOT_CARD_ENABLED = process.env.SWITCHROOM_BOOT_CARD !== "false";
|
|
99448
99945
|
var activeBootCard = null;
|
|
@@ -99471,7 +99968,7 @@ function ensureIssuesCard(chatId, threadId) {
|
|
|
99471
99968
|
bot: botApi,
|
|
99472
99969
|
log: (msg) => process.stderr.write(`telegram gateway: ${msg}
|
|
99473
99970
|
`),
|
|
99474
|
-
persistPath:
|
|
99971
|
+
persistPath: join62(stateDir, "issues-card.json")
|
|
99475
99972
|
});
|
|
99476
99973
|
activeIssuesWatcher = startIssuesWatcher({
|
|
99477
99974
|
stateDir,
|
|
@@ -99669,13 +100166,13 @@ if (isGatewayMain)
|
|
|
99669
100166
|
var inboundSpool;
|
|
99670
100167
|
if (isGatewayMain)
|
|
99671
100168
|
inboundSpool = STATIC ? undefined : createInboundSpool({
|
|
99672
|
-
path:
|
|
100169
|
+
path: join62(STATE_DIR, "inbound-spool.jsonl"),
|
|
99673
100170
|
fs: {
|
|
99674
|
-
appendFileSync: (p, d) =>
|
|
99675
|
-
readFileSync: (p) =>
|
|
99676
|
-
writeFileSync: (p, d) =>
|
|
99677
|
-
renameSync: (a, b) =>
|
|
99678
|
-
existsSync: (p) =>
|
|
100171
|
+
appendFileSync: (p, d) => appendFileSync9(p, d),
|
|
100172
|
+
readFileSync: (p) => readFileSync60(p, "utf8"),
|
|
100173
|
+
writeFileSync: (p, d) => writeFileSync50(p, d),
|
|
100174
|
+
renameSync: (a, b) => renameSync23(a, b),
|
|
100175
|
+
existsSync: (p) => existsSync56(p),
|
|
99679
100176
|
statSizeSync: (p) => statSync20(p).size
|
|
99680
100177
|
},
|
|
99681
100178
|
onDegraded: (info) => {
|
|
@@ -99737,13 +100234,13 @@ async function maybeRedeliverUndeliveredAnswer() {
|
|
|
99737
100234
|
let transcriptText;
|
|
99738
100235
|
try {
|
|
99739
100236
|
const projectsDir = getProjectsDirForCwd();
|
|
99740
|
-
const path2 =
|
|
99741
|
-
if (!
|
|
100237
|
+
const path2 = join62(projectsDir, `${sessionId}.jsonl`);
|
|
100238
|
+
if (!existsSync56(path2)) {
|
|
99742
100239
|
process.stderr.write(`telegram gateway: crash-redelivery \u2014 transcript not found for turnKey=${turn.turn_key} session=${sessionId} (${path2}); skipping
|
|
99743
100240
|
`);
|
|
99744
100241
|
return;
|
|
99745
100242
|
}
|
|
99746
|
-
transcriptText =
|
|
100243
|
+
transcriptText = readFileSync60(path2, "utf8");
|
|
99747
100244
|
} catch (err) {
|
|
99748
100245
|
process.stderr.write(`telegram gateway: crash-redelivery \u2014 transcript read failed turnKey=${turn.turn_key}: ${err.message}
|
|
99749
100246
|
`);
|
|
@@ -99902,8 +100399,8 @@ var bridgeDeadWatchdog = createBridgeDeadWatchdog({
|
|
|
99902
100399
|
isSessionAlive: () => findAgentProcessInContainer2()?.comm === "claude",
|
|
99903
100400
|
isShuttingDown: () => shuttingDown,
|
|
99904
100401
|
escalate: (reason) => triggerSelfRestart(process.env.SWITCHROOM_AGENT_NAME ?? "", reason, 1500),
|
|
99905
|
-
crashLogPath:
|
|
99906
|
-
markerPath:
|
|
100402
|
+
crashLogPath: join62(STATE_DIR, "bridge-crash.log"),
|
|
100403
|
+
markerPath: join62(STATE_DIR, "bridge-dead-escalation.json"),
|
|
99907
100404
|
log: (line) => process.stderr.write(`${line}
|
|
99908
100405
|
`),
|
|
99909
100406
|
priorStreak: bridgeDeadPriorStreak,
|
|
@@ -100009,8 +100506,8 @@ if (isGatewayMain)
|
|
|
100009
100506
|
probeQuotaViaBroker: (t) => probeQuotaForBootCard(agentSlug, t),
|
|
100010
100507
|
tmuxSupervisor: process.env.SWITCHROOM_TMUX_SUPERVISOR === "1",
|
|
100011
100508
|
dockerMode: process.env.SWITCHROOM_RUNTIME === "docker",
|
|
100012
|
-
configSnapshotPath:
|
|
100013
|
-
bootCardStatePath:
|
|
100509
|
+
configSnapshotPath: join62(resolvedAgentDirForCard, ".config-snapshot.json"),
|
|
100510
|
+
bootCardStatePath: join62(resolvedAgentDirForCard, ".boot-card-msgid.json"),
|
|
100014
100511
|
floodStatePath: FLOOD_STATE_PATH,
|
|
100015
100512
|
...updateOutcomeLine ? { updateOutcomeLine } : {}
|
|
100016
100513
|
}, ackMsgId).then((handle) => {
|
|
@@ -100692,7 +101189,7 @@ if (isGatewayMain)
|
|
|
100692
101189
|
const receiverUid = receiverUidRaw ? Number(receiverUidRaw) : NaN;
|
|
100693
101190
|
if (Number.isInteger(receiverUid))
|
|
100694
101191
|
allowedUids.push(receiverUid);
|
|
100695
|
-
const socketPath =
|
|
101192
|
+
const socketPath = join62(STATE_DIR, "webhook.sock");
|
|
100696
101193
|
const webhookInject = (agentName3, inbound) => {
|
|
100697
101194
|
const msg = inbound;
|
|
100698
101195
|
const delivered = ipcServer.sendToAgent(agentName3, msg);
|
|
@@ -100920,9 +101417,9 @@ function redactOutboundText(text5, site) {
|
|
|
100920
101417
|
var VOICE_OUT_DEFAULT_CHUNK_CHARS = 600;
|
|
100921
101418
|
var VOICE_OUT_HARD_CHUNK_CAP = 4096;
|
|
100922
101419
|
var voiceOnDemandCache = new VoiceOnDemandCache({
|
|
100923
|
-
persistPath:
|
|
101420
|
+
persistPath: join62(STATE_DIR, "voice-ondemand.json")
|
|
100924
101421
|
});
|
|
100925
|
-
var VOICE_CACHE_DIR =
|
|
101422
|
+
var VOICE_CACHE_DIR = join62(STATE_DIR, "voice-cache");
|
|
100926
101423
|
var voicePreSynthQueue = new PreSynthQueue({
|
|
100927
101424
|
runJob: async (job) => {
|
|
100928
101425
|
const sidecarToken = await materializeSidecarToken2();
|
|
@@ -101324,11 +101821,11 @@ async function executeSendGif(rawArgs) {
|
|
|
101324
101821
|
};
|
|
101325
101822
|
}
|
|
101326
101823
|
async function publishToTelegraph(text5, shortName, authorName) {
|
|
101327
|
-
const accountPath =
|
|
101824
|
+
const accountPath = join62(STATE_DIR, "telegraph-account.json");
|
|
101328
101825
|
let account = null;
|
|
101329
101826
|
try {
|
|
101330
|
-
if (
|
|
101331
|
-
const raw =
|
|
101827
|
+
if (existsSync56(accountPath)) {
|
|
101828
|
+
const raw = readFileSync60(accountPath, "utf-8");
|
|
101332
101829
|
const parsed = JSON.parse(raw);
|
|
101333
101830
|
if (parsed.shortName && parsed.accessToken) {
|
|
101334
101831
|
account = parsed;
|
|
@@ -101347,8 +101844,8 @@ async function publishToTelegraph(text5, shortName, authorName) {
|
|
|
101347
101844
|
}
|
|
101348
101845
|
account = created.value;
|
|
101349
101846
|
try {
|
|
101350
|
-
|
|
101351
|
-
|
|
101847
|
+
mkdirSync49(STATE_DIR, { recursive: true, mode: 448 });
|
|
101848
|
+
writeFileSync50(accountPath, JSON.stringify(account, null, 2), { mode: 384 });
|
|
101352
101849
|
} catch (err) {
|
|
101353
101850
|
process.stderr.write(`telegram gateway: telegraph cache write failed: ${err.message}
|
|
101354
101851
|
`);
|
|
@@ -101464,7 +101961,7 @@ _The secret was NOT saved. The agent can re-request with \`request_secret\`._`,
|
|
|
101464
101961
|
}
|
|
101465
101962
|
function readLiveSwitchroomConfigText() {
|
|
101466
101963
|
const cfgPath = process.env.SWITCHROOM_CONFIG ?? findConfigFile2();
|
|
101467
|
-
return
|
|
101964
|
+
return readFileSync60(cfgPath, "utf8");
|
|
101468
101965
|
}
|
|
101469
101966
|
async function executeReact(args) {
|
|
101470
101967
|
if (!args.chat_id)
|
|
@@ -101503,9 +102000,9 @@ async function executeDownloadAttachment(args) {
|
|
|
101503
102000
|
fileUniqueId: file.file_unique_id,
|
|
101504
102001
|
now: Date.now()
|
|
101505
102002
|
});
|
|
101506
|
-
|
|
102003
|
+
mkdirSync49(INBOX_DIR, { recursive: true, mode: 448 });
|
|
101507
102004
|
assertInsideInbox2(INBOX_DIR, dlPath);
|
|
101508
|
-
|
|
102005
|
+
writeFileSync50(dlPath, buf, { mode: 384 });
|
|
101509
102006
|
return { content: [{ type: "text", text: dlPath }] };
|
|
101510
102007
|
}
|
|
101511
102008
|
async function executeEditMessage(args) {
|
|
@@ -102865,14 +103362,14 @@ function restartMarkerPath() {
|
|
|
102865
103362
|
const agentDir = resolveAgentDirFromEnv();
|
|
102866
103363
|
if (!agentDir)
|
|
102867
103364
|
return null;
|
|
102868
|
-
return
|
|
103365
|
+
return join62(agentDir, "restart-pending.json");
|
|
102869
103366
|
}
|
|
102870
103367
|
function writeRestartMarker(marker) {
|
|
102871
103368
|
const p = restartMarkerPath();
|
|
102872
103369
|
if (!p)
|
|
102873
103370
|
return;
|
|
102874
103371
|
try {
|
|
102875
|
-
|
|
103372
|
+
writeFileSync50(p, JSON.stringify(marker));
|
|
102876
103373
|
lastPlannedRestartAt = Date.now();
|
|
102877
103374
|
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}
|
|
102878
103375
|
`);
|
|
@@ -102891,7 +103388,7 @@ function readRestartMarker() {
|
|
|
102891
103388
|
if (!p)
|
|
102892
103389
|
return null;
|
|
102893
103390
|
try {
|
|
102894
|
-
return JSON.parse(
|
|
103391
|
+
return JSON.parse(readFileSync60(p, "utf8"));
|
|
102895
103392
|
} catch {
|
|
102896
103393
|
return null;
|
|
102897
103394
|
}
|
|
@@ -103040,7 +103537,7 @@ var _dockerReachable;
|
|
|
103040
103537
|
function isDockerReachable() {
|
|
103041
103538
|
if (_dockerReachable !== undefined)
|
|
103042
103539
|
return _dockerReachable;
|
|
103043
|
-
if (!
|
|
103540
|
+
if (!existsSync56("/var/run/docker.sock")) {
|
|
103044
103541
|
_dockerReachable = false;
|
|
103045
103542
|
return _dockerReachable;
|
|
103046
103543
|
}
|
|
@@ -103057,12 +103554,12 @@ function _resetDockerReachableCache() {
|
|
|
103057
103554
|
}
|
|
103058
103555
|
function spawnSwitchroomDetached(args, onFailure) {
|
|
103059
103556
|
const fullArgs = SWITCHROOM_CONFIG ? ["--config", SWITCHROOM_CONFIG, ...args] : args;
|
|
103060
|
-
const logPath =
|
|
103557
|
+
const logPath = join62(STATE_DIR, "detached-spawn.log");
|
|
103061
103558
|
let outFd = null;
|
|
103062
103559
|
try {
|
|
103063
|
-
|
|
103560
|
+
mkdirSync49(STATE_DIR, { recursive: true });
|
|
103064
103561
|
outFd = openSync12(logPath, "a");
|
|
103065
|
-
|
|
103562
|
+
writeFileSync50(logPath, `
|
|
103066
103563
|
[${new Date().toISOString()}] spawn ${SWITCHROOM_CLI} ${fullArgs.join(" ")}
|
|
103067
103564
|
`, { flag: "a" });
|
|
103068
103565
|
} catch {}
|
|
@@ -103088,7 +103585,7 @@ function spawnSwitchroomDetached(args, onFailure) {
|
|
|
103088
103585
|
return;
|
|
103089
103586
|
let tail = "";
|
|
103090
103587
|
try {
|
|
103091
|
-
const full =
|
|
103588
|
+
const full = readFileSync60(logPath, "utf8");
|
|
103092
103589
|
tail = full.split(`
|
|
103093
103590
|
`).slice(-30).join(`
|
|
103094
103591
|
`).trim();
|
|
@@ -103350,10 +103847,10 @@ ${preBlock(formatSwitchroomOutput(detail))}`, { html: true });
|
|
|
103350
103847
|
}
|
|
103351
103848
|
function readRecentDenialsForAgent(agentName3, windowMs, limit) {
|
|
103352
103849
|
try {
|
|
103353
|
-
const auditPath =
|
|
103354
|
-
if (!
|
|
103850
|
+
const auditPath = join62(homedir20(), ".switchroom", "vault-audit.log");
|
|
103851
|
+
if (!existsSync56(auditPath))
|
|
103355
103852
|
return [];
|
|
103356
|
-
const raw =
|
|
103853
|
+
const raw = readFileSync60(auditPath, "utf8");
|
|
103357
103854
|
return recentDenialsFromAuditLog(raw, { agentName: agentName3, windowMs, limit });
|
|
103358
103855
|
} catch {
|
|
103359
103856
|
return [];
|
|
@@ -103404,7 +103901,7 @@ async function buildAgentMetadata(agentName3) {
|
|
|
103404
103901
|
try {
|
|
103405
103902
|
const agentDir = resolveAgentDirFromEnv();
|
|
103406
103903
|
if (agentDir) {
|
|
103407
|
-
const raw =
|
|
103904
|
+
const raw = readFileSync60(join62(agentDir, ".claude", ".claude.json"), "utf8");
|
|
103408
103905
|
claudeJson = JSON.parse(raw);
|
|
103409
103906
|
}
|
|
103410
103907
|
} catch {}
|
|
@@ -103533,7 +104030,7 @@ function buildModelDeps(restartCtx) {
|
|
|
103533
104030
|
try {
|
|
103534
104031
|
const agentDir = resolveAgentDirFromEnv();
|
|
103535
104032
|
if (agentDir) {
|
|
103536
|
-
const local = await fetchQuota2({ claudeConfigDir:
|
|
104033
|
+
const local = await fetchQuota2({ claudeConfigDir: join62(agentDir, ".claude") });
|
|
103537
104034
|
if (local.ok)
|
|
103538
104035
|
return formatQuotaLine2(local.data);
|
|
103539
104036
|
}
|
|
@@ -103779,9 +104276,9 @@ function effortMenuReplyMarkup(reply) {
|
|
|
103779
104276
|
function flushAgentHandoff(agentDir) {
|
|
103780
104277
|
let removed = 0;
|
|
103781
104278
|
for (const fname of [".handoff.md", ".handoff-topic"]) {
|
|
103782
|
-
const p =
|
|
104279
|
+
const p = join62(agentDir, fname);
|
|
103783
104280
|
try {
|
|
103784
|
-
if (
|
|
104281
|
+
if (existsSync56(p)) {
|
|
103785
104282
|
unlinkSync27(p);
|
|
103786
104283
|
removed++;
|
|
103787
104284
|
}
|
|
@@ -103837,7 +104334,7 @@ async function handleNewCommand(ctx) {
|
|
|
103837
104334
|
writeRestartMarker({ chat_id: chatId, thread_id: threadId ?? null, ack_message_id: ackId, ts: Date.now() });
|
|
103838
104335
|
if (agentDir != null) {
|
|
103839
104336
|
try {
|
|
103840
|
-
|
|
104337
|
+
writeFileSync50(join62(agentDir, ".force-fresh-session"), `${kind} at ${new Date().toISOString()}
|
|
103841
104338
|
`, "utf8");
|
|
103842
104339
|
} catch (err) {
|
|
103843
104340
|
process.stderr.write(`telegram gateway: failed to write force-fresh marker: ${err}
|
|
@@ -103950,16 +104447,16 @@ function buildFolderPickerDeps() {
|
|
|
103950
104447
|
};
|
|
103951
104448
|
}
|
|
103952
104449
|
var lockoutOps = {
|
|
103953
|
-
readFileSync: (p, enc) =>
|
|
103954
|
-
writeFileSync: (p, data, opts) =>
|
|
103955
|
-
existsSync: (p) =>
|
|
103956
|
-
mkdirSync: (p, opts) =>
|
|
103957
|
-
joinPath: (...parts) =>
|
|
104450
|
+
readFileSync: (p, enc) => readFileSync60(p, enc),
|
|
104451
|
+
writeFileSync: (p, data, opts) => writeFileSync50(p, data, opts),
|
|
104452
|
+
existsSync: (p) => existsSync56(p),
|
|
104453
|
+
mkdirSync: (p, opts) => mkdirSync49(p, opts),
|
|
104454
|
+
joinPath: (...parts) => join62(...parts)
|
|
103958
104455
|
};
|
|
103959
104456
|
var FLEET_FALLBACK_DEDUP_MS = 30000;
|
|
103960
104457
|
function isAuthBrokerSocketReachable() {
|
|
103961
104458
|
try {
|
|
103962
|
-
return
|
|
104459
|
+
return existsSync56(resolveAuthBrokerSocketPath2());
|
|
103963
104460
|
} catch {
|
|
103964
104461
|
return false;
|
|
103965
104462
|
}
|
|
@@ -104214,7 +104711,7 @@ async function runCreditWatch() {
|
|
|
104214
104711
|
if (!agentDir)
|
|
104215
104712
|
return;
|
|
104216
104713
|
const agentName3 = getMyAgentName();
|
|
104217
|
-
const claudeConfigDir =
|
|
104714
|
+
const claudeConfigDir = join62(agentDir, ".claude");
|
|
104218
104715
|
const stateDir = STATE_DIR;
|
|
104219
104716
|
const reason = readClaudeJsonOverage(claudeConfigDir);
|
|
104220
104717
|
const prev = loadCreditState(stateDir);
|
|
@@ -105970,7 +106467,7 @@ Send \`/auth ${parsed.provider} cancel\` to abort.`, { html: true });
|
|
|
105970
106467
|
await switchroomReply(ctx, "**/usage:** cannot resolve agent dir.", { html: true });
|
|
105971
106468
|
return;
|
|
105972
106469
|
}
|
|
105973
|
-
const result = await fetchQuota2({ claudeConfigDir:
|
|
106470
|
+
const result = await fetchQuota2({ claudeConfigDir: join62(agentDir, ".claude") });
|
|
105974
106471
|
if (!result.ok) {
|
|
105975
106472
|
await switchroomReply(ctx, `**/usage:** ${escapeHtmlForTg2(result.reason)}`, { html: true });
|
|
105976
106473
|
return;
|
|
@@ -106356,7 +106853,7 @@ ${interimLabel}` : interimLabel
|
|
|
106356
106853
|
const unifiedDiff = (() => {
|
|
106357
106854
|
try {
|
|
106358
106855
|
const cfgPath = process.env.SWITCHROOM_CONFIG ?? SWITCHROOM_CONFIG ?? findConfigFile2();
|
|
106359
|
-
const raw =
|
|
106856
|
+
const raw = readFileSync60(cfgPath, "utf8");
|
|
106360
106857
|
return synthesizeAllowRuleDiff({ agentName: agentName3, rule: chosen.rule, configText: raw });
|
|
106361
106858
|
} catch (err) {
|
|
106362
106859
|
process.stderr.write(`telegram gateway: always-allow diff synth failed: ${err.message}
|
|
@@ -106634,6 +107131,7 @@ ${labelWithResume}` : labelWithResume,
|
|
|
106634
107131
|
handleChecklistUpdate(ctx, "checklist_tasks_added", checklistHandlerDeps);
|
|
106635
107132
|
});
|
|
106636
107133
|
bot2.on("message:pinned_message", (ctx) => handlePinnedMessage(ctx, pinnedMessageHandlerDeps));
|
|
107134
|
+
bot2.on("message:rich_message", (ctx) => handleRichMessageMessage(ctx, mediaEnvelopeDeps));
|
|
106637
107135
|
installUnhandledMessageCatchAll(bot2, (ctx, text5) => routeInbound(ctx, text5, undefined, undefined, inboundRouterDeps), (line) => process.stderr.write(line));
|
|
106638
107136
|
bot2.on("message_reaction", (ctx) => {
|
|
106639
107137
|
handleMessageReaction(ctx);
|
|
@@ -107212,7 +107710,7 @@ async function startGateway() {
|
|
|
107212
107710
|
return;
|
|
107213
107711
|
}
|
|
107214
107712
|
})();
|
|
107215
|
-
const resolvedAgentDirForBootCard = agentDir ??
|
|
107713
|
+
const resolvedAgentDirForBootCard = agentDir ?? join62(homedir20(), ".switchroom", "agents", agentSlug);
|
|
107216
107714
|
const handle = await startBootCard(chatId, threadId, botApiForCard, {
|
|
107217
107715
|
agentName: agentDisplayName,
|
|
107218
107716
|
agentSlug,
|
|
@@ -107226,8 +107724,8 @@ async function startGateway() {
|
|
|
107226
107724
|
probeQuotaViaBroker: (t) => probeQuotaForBootCard(agentSlug, t),
|
|
107227
107725
|
tmuxSupervisor: process.env.SWITCHROOM_TMUX_SUPERVISOR === "1",
|
|
107228
107726
|
dockerMode: process.env.SWITCHROOM_RUNTIME === "docker",
|
|
107229
|
-
configSnapshotPath:
|
|
107230
|
-
bootCardStatePath:
|
|
107727
|
+
configSnapshotPath: join62(resolvedAgentDirForBootCard, ".config-snapshot.json"),
|
|
107728
|
+
bootCardStatePath: join62(resolvedAgentDirForBootCard, ".boot-card-msgid.json"),
|
|
107231
107729
|
floodStatePath: FLOOD_STATE_PATH,
|
|
107232
107730
|
...updateOutcomeLine ? { updateOutcomeLine } : {}
|
|
107233
107731
|
}, ackMsgId);
|
|
@@ -107258,10 +107756,10 @@ async function startGateway() {
|
|
|
107258
107756
|
try {
|
|
107259
107757
|
const smAgentDir = resolveAgentDirFromEnv();
|
|
107260
107758
|
if (smAgentDir) {
|
|
107261
|
-
const activePath =
|
|
107262
|
-
if (
|
|
107759
|
+
const activePath = join62(smAgentDir, ".active-session-model");
|
|
107760
|
+
if (existsSync56(activePath)) {
|
|
107263
107761
|
try {
|
|
107264
|
-
const launched =
|
|
107762
|
+
const launched = readFileSync60(activePath, "utf8").trim();
|
|
107265
107763
|
const configured = (() => {
|
|
107266
107764
|
const d = switchroomExecJson(["agent", "list"]);
|
|
107267
107765
|
const raw = d?.agents?.find((a) => a.name === getMyAgentName())?.model ?? null;
|
|
@@ -107294,24 +107792,24 @@ async function startGateway() {
|
|
|
107294
107792
|
deliverModelSwitchBootNotice({
|
|
107295
107793
|
...modelBootCardDeps,
|
|
107296
107794
|
confirmation,
|
|
107297
|
-
hasSessionModelAlert:
|
|
107795
|
+
hasSessionModelAlert: existsSync56(join62(smAgentDir, ".session-model-alert"))
|
|
107298
107796
|
});
|
|
107299
107797
|
}
|
|
107300
107798
|
} catch {}
|
|
107301
107799
|
}
|
|
107302
|
-
const activeEffortPath =
|
|
107303
|
-
if (
|
|
107800
|
+
const activeEffortPath = join62(smAgentDir, ".active-session-effort");
|
|
107801
|
+
if (existsSync56(activeEffortPath)) {
|
|
107304
107802
|
try {
|
|
107305
|
-
const launchedEffort =
|
|
107803
|
+
const launchedEffort = readFileSync60(activeEffortPath, "utf8").trim();
|
|
107306
107804
|
const configuredEffort = getConfiguredEffortForPersist();
|
|
107307
107805
|
sessionEffortOverride = launchedEffort.length > 0 && launchedEffort !== configuredEffort ? launchedEffort : null;
|
|
107308
107806
|
} catch {}
|
|
107309
107807
|
}
|
|
107310
|
-
const alertPath =
|
|
107311
|
-
if (
|
|
107808
|
+
const alertPath = join62(smAgentDir, ".session-model-alert");
|
|
107809
|
+
if (existsSync56(alertPath)) {
|
|
107312
107810
|
let alertText = null;
|
|
107313
107811
|
try {
|
|
107314
|
-
alertText =
|
|
107812
|
+
alertText = readFileSync60(alertPath, "utf8").trim();
|
|
107315
107813
|
} catch {
|
|
107316
107814
|
alertText = null;
|
|
107317
107815
|
}
|