switchroom 0.14.48 → 0.14.50
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 +2 -2
- package/package.json +1 -1
- package/telegram-plugin/dist/gateway/gateway.js +154 -76
- package/telegram-plugin/gateway/boot-card-msgid.ts +70 -0
- package/telegram-plugin/gateway/boot-card.ts +81 -14
- package/telegram-plugin/gateway/gateway.ts +31 -6
- package/telegram-plugin/gateway/inbound-delivery-confirm.ts +26 -0
- package/telegram-plugin/gateway/resume-inbound-builder.ts +27 -2
- package/telegram-plugin/tests/boot-card-edit-in-place.test.ts +139 -0
- package/telegram-plugin/tests/boot-card-msgid.test.ts +88 -0
- package/telegram-plugin/tests/inbound-delivery-confirm.test.ts +61 -0
- package/telegram-plugin/tests/resume-inbound-builder.test.ts +33 -0
package/dist/cli/switchroom.js
CHANGED
|
@@ -49462,8 +49462,8 @@ var {
|
|
|
49462
49462
|
} = import__.default;
|
|
49463
49463
|
|
|
49464
49464
|
// src/build-info.ts
|
|
49465
|
-
var VERSION = "0.14.
|
|
49466
|
-
var COMMIT_SHA = "
|
|
49465
|
+
var VERSION = "0.14.50";
|
|
49466
|
+
var COMMIT_SHA = "07e8b692";
|
|
49467
49467
|
|
|
49468
49468
|
// src/cli/agent.ts
|
|
49469
49469
|
init_source();
|
package/package.json
CHANGED
|
@@ -29493,6 +29493,37 @@ function persistSnapshot(path, snapshot) {
|
|
|
29493
29493
|
}
|
|
29494
29494
|
var init_config_snapshot = () => {};
|
|
29495
29495
|
|
|
29496
|
+
// gateway/boot-card-msgid.ts
|
|
29497
|
+
import { readFileSync as readFileSync27, writeFileSync as writeFileSync17 } from "node:fs";
|
|
29498
|
+
function bootCardChatKey(chatId, threadId) {
|
|
29499
|
+
return `${chatId}:${threadId ?? ""}`;
|
|
29500
|
+
}
|
|
29501
|
+
function readStore(path) {
|
|
29502
|
+
try {
|
|
29503
|
+
const parsed = JSON.parse(readFileSync27(path, "utf8"));
|
|
29504
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
29505
|
+
return parsed;
|
|
29506
|
+
}
|
|
29507
|
+
} catch {}
|
|
29508
|
+
return {};
|
|
29509
|
+
}
|
|
29510
|
+
function loadBootCardMsgId(path, chatKey3) {
|
|
29511
|
+
const id = readStore(path)[chatKey3];
|
|
29512
|
+
return typeof id === "number" && Number.isFinite(id) && id > 0 ? id : null;
|
|
29513
|
+
}
|
|
29514
|
+
function saveBootCardMsgId(path, chatKey3, messageId) {
|
|
29515
|
+
if (!(Number.isFinite(messageId) && messageId > 0))
|
|
29516
|
+
return;
|
|
29517
|
+
try {
|
|
29518
|
+
const store2 = readStore(path);
|
|
29519
|
+
if (store2[chatKey3] === messageId)
|
|
29520
|
+
return;
|
|
29521
|
+
store2[chatKey3] = messageId;
|
|
29522
|
+
writeFileSync17(path, JSON.stringify(store2), "utf8");
|
|
29523
|
+
} catch {}
|
|
29524
|
+
}
|
|
29525
|
+
var init_boot_card_msgid = () => {};
|
|
29526
|
+
|
|
29496
29527
|
// gateway/boot-card.ts
|
|
29497
29528
|
var exports_boot_card = {};
|
|
29498
29529
|
__export(exports_boot_card, {
|
|
@@ -29640,22 +29671,46 @@ async function startBootCard(chatId, threadId, bot, opts, ackMessageId, log) {
|
|
|
29640
29671
|
...opts.updateOutcomeLine ? { updateOutcomeLine: opts.updateOutcomeLine } : {}
|
|
29641
29672
|
});
|
|
29642
29673
|
const silentBootCard = true;
|
|
29643
|
-
|
|
29644
|
-
|
|
29645
|
-
|
|
29646
|
-
|
|
29647
|
-
|
|
29648
|
-
|
|
29649
|
-
|
|
29650
|
-
|
|
29651
|
-
|
|
29652
|
-
|
|
29653
|
-
|
|
29674
|
+
const chatKey3 = bootCardChatKey(chatId, threadId);
|
|
29675
|
+
const reuseId = ackMessageId == null && opts.bootCardStatePath != null && bot.editMessageTextStrict != null ? loadBootCardMsgId(opts.bootCardStatePath, chatKey3) : null;
|
|
29676
|
+
let messageId = -1;
|
|
29677
|
+
if (reuseId != null && bot.editMessageTextStrict != null) {
|
|
29678
|
+
try {
|
|
29679
|
+
const outcome = await bot.editMessageTextStrict(chatId, reuseId, ackText, {
|
|
29680
|
+
parse_mode: "HTML",
|
|
29681
|
+
link_preview_options: { is_disabled: true },
|
|
29682
|
+
...threadId != null ? { message_thread_id: threadId } : {}
|
|
29683
|
+
});
|
|
29684
|
+
if (outcome === "edited") {
|
|
29685
|
+
messageId = reuseId;
|
|
29686
|
+
logger2(`telegram gateway: boot-card: reused msgId=${messageId} chatId=${chatId} reason=${opts.restartReason ?? "-"} reason_detail=${opts.restartReasonDetail ?? "-"} edit_in_place=true notify=none
|
|
29654
29687
|
`);
|
|
29655
|
-
|
|
29656
|
-
|
|
29688
|
+
}
|
|
29689
|
+
} catch (err) {
|
|
29690
|
+
logger2(`telegram gateway: boot-card: edit-in-place probe failed (${err?.message ?? String(err)}) \u2014 sending fresh
|
|
29657
29691
|
`);
|
|
29658
|
-
|
|
29692
|
+
}
|
|
29693
|
+
}
|
|
29694
|
+
if (messageId < 0) {
|
|
29695
|
+
try {
|
|
29696
|
+
const sent = await bot.sendMessage(chatId, ackText, {
|
|
29697
|
+
parse_mode: "HTML",
|
|
29698
|
+
link_preview_options: { is_disabled: true },
|
|
29699
|
+
...threadId != null ? { message_thread_id: threadId } : {},
|
|
29700
|
+
...ackMessageId != null ? { reply_parameters: { message_id: ackMessageId } } : {},
|
|
29701
|
+
...silentBootCard ? { disable_notification: true } : {}
|
|
29702
|
+
});
|
|
29703
|
+
messageId = sent.message_id;
|
|
29704
|
+
logger2(`telegram gateway: boot-card: posted msgId=${messageId} chatId=${chatId} reason=${opts.restartReason ?? "-"} reason_detail=${opts.restartReasonDetail ?? "-"} silent=${silentBootCard}
|
|
29705
|
+
`);
|
|
29706
|
+
} catch (err) {
|
|
29707
|
+
logger2(`telegram gateway: boot-card: failed to post ack: ${err?.message ?? String(err)}
|
|
29708
|
+
`);
|
|
29709
|
+
return { messageId: -1, complete: () => {} };
|
|
29710
|
+
}
|
|
29711
|
+
}
|
|
29712
|
+
if (opts.bootCardStatePath != null && messageId > 0) {
|
|
29713
|
+
saveBootCardMsgId(opts.bootCardStatePath, chatKey3, messageId);
|
|
29659
29714
|
}
|
|
29660
29715
|
const liveWindowMs = opts.agentLiveWindowMs ?? AGENT_LIVE_WINDOW_MS;
|
|
29661
29716
|
setTimeoutFn(() => {
|
|
@@ -29822,6 +29877,7 @@ var init_boot_card = __esm(() => {
|
|
|
29822
29877
|
init_boot_probes();
|
|
29823
29878
|
init_boot_issue_cache();
|
|
29824
29879
|
init_config_snapshot();
|
|
29880
|
+
init_boot_card_msgid();
|
|
29825
29881
|
init_loader();
|
|
29826
29882
|
init_merge();
|
|
29827
29883
|
DOT = {
|
|
@@ -30211,8 +30267,8 @@ var init_flock = () => {};
|
|
|
30211
30267
|
// ../src/vault/vault.ts
|
|
30212
30268
|
import { randomBytes as randomBytes5, scryptSync, createCipheriv, createDecipheriv } from "node:crypto";
|
|
30213
30269
|
import {
|
|
30214
|
-
readFileSync as
|
|
30215
|
-
writeFileSync as
|
|
30270
|
+
readFileSync as readFileSync35,
|
|
30271
|
+
writeFileSync as writeFileSync23,
|
|
30216
30272
|
existsSync as existsSync36,
|
|
30217
30273
|
renameSync as renameSync11,
|
|
30218
30274
|
mkdirSync as mkdirSync23,
|
|
@@ -30256,7 +30312,7 @@ function openVault(passphrase, vaultPath) {
|
|
|
30256
30312
|
}
|
|
30257
30313
|
let vaultFile;
|
|
30258
30314
|
try {
|
|
30259
|
-
vaultFile = JSON.parse(
|
|
30315
|
+
vaultFile = JSON.parse(readFileSync35(vaultPath, "utf8"));
|
|
30260
30316
|
} catch {
|
|
30261
30317
|
throw new VaultError(`Failed to read vault file: ${vaultPath}`);
|
|
30262
30318
|
}
|
|
@@ -30637,7 +30693,7 @@ __export(exports_tmux, {
|
|
|
30637
30693
|
captureAgentPane: () => captureAgentPane
|
|
30638
30694
|
});
|
|
30639
30695
|
import { execFileSync as execFileSync4 } from "node:child_process";
|
|
30640
|
-
import { mkdirSync as mkdirSync25, readdirSync as readdirSync6, statSync as statSync12, unlinkSync as unlinkSync13, writeFileSync as
|
|
30696
|
+
import { mkdirSync as mkdirSync25, readdirSync as readdirSync6, statSync as statSync12, unlinkSync as unlinkSync13, writeFileSync as writeFileSync24 } from "node:fs";
|
|
30641
30697
|
import { resolve as resolve7 } from "node:path";
|
|
30642
30698
|
function captureAgentPane(opts) {
|
|
30643
30699
|
const { agentName: agentName3, agentDir, reason } = opts;
|
|
@@ -30683,7 +30739,7 @@ function captureAgentPane(opts) {
|
|
|
30683
30739
|
` + `
|
|
30684
30740
|
`;
|
|
30685
30741
|
try {
|
|
30686
|
-
|
|
30742
|
+
writeFileSync24(outPath, Buffer.concat([Buffer.from(header, "utf8"), body]), {
|
|
30687
30743
|
mode: 420
|
|
30688
30744
|
});
|
|
30689
30745
|
} catch (err) {
|
|
@@ -31259,8 +31315,8 @@ var import_runner2 = __toESM(require_mod3(), 1);
|
|
|
31259
31315
|
import { randomBytes as randomBytes6 } from "crypto";
|
|
31260
31316
|
import { execFileSync as execFileSync5, execSync as execSync2, spawn as spawn2 } from "child_process";
|
|
31261
31317
|
import {
|
|
31262
|
-
readFileSync as
|
|
31263
|
-
writeFileSync as
|
|
31318
|
+
readFileSync as readFileSync36,
|
|
31319
|
+
writeFileSync as writeFileSync25,
|
|
31264
31320
|
mkdirSync as mkdirSync26,
|
|
31265
31321
|
readdirSync as readdirSync7,
|
|
31266
31322
|
rmSync as rmSync4,
|
|
@@ -47320,6 +47376,9 @@ function shouldTrackDelivery(input) {
|
|
|
47320
47376
|
return false;
|
|
47321
47377
|
return true;
|
|
47322
47378
|
}
|
|
47379
|
+
function isTrackableResumeSynthetic(meta) {
|
|
47380
|
+
return meta?.source === "resume_interrupted" && meta.message_id != null && meta.message_id !== "";
|
|
47381
|
+
}
|
|
47323
47382
|
|
|
47324
47383
|
// gateway/pending-permission-decisions.ts
|
|
47325
47384
|
var DEFAULT_PENDING_PERMISSION_CAP = 32;
|
|
@@ -50439,7 +50498,7 @@ function determineRestartReason(opts) {
|
|
|
50439
50498
|
init_boot_card();
|
|
50440
50499
|
|
|
50441
50500
|
// gateway/update-announce.ts
|
|
50442
|
-
import { existsSync as existsSync29, mkdirSync as mkdirSync17, openSync as openSync3, closeSync as closeSync3, readFileSync as
|
|
50501
|
+
import { existsSync as existsSync29, mkdirSync as mkdirSync17, openSync as openSync3, closeSync as closeSync3, readFileSync as readFileSync28 } from "node:fs";
|
|
50443
50502
|
import { join as join26 } from "node:path";
|
|
50444
50503
|
import { homedir as homedir12 } from "node:os";
|
|
50445
50504
|
|
|
@@ -50554,7 +50613,7 @@ var DEFAULT_LOOKBACK_MS = 10 * 60 * 1000;
|
|
|
50554
50613
|
function readLastTerminalUpdateAudit(opts = {}) {
|
|
50555
50614
|
const path = opts.auditLogPath ?? defaultAuditLogPath();
|
|
50556
50615
|
const exists = opts.exists ?? existsSync29;
|
|
50557
|
-
const readFile = opts.readFile ?? ((p) =>
|
|
50616
|
+
const readFile = opts.readFile ?? ((p) => readFileSync28(p, "utf-8"));
|
|
50558
50617
|
if (!exists(path))
|
|
50559
50618
|
return null;
|
|
50560
50619
|
let raw;
|
|
@@ -50642,7 +50701,7 @@ function maybeRenderUpdateAnnouncement(opts = {}) {
|
|
|
50642
50701
|
}
|
|
50643
50702
|
|
|
50644
50703
|
// issues-card.ts
|
|
50645
|
-
import { readFileSync as
|
|
50704
|
+
import { readFileSync as readFileSync29, writeFileSync as writeFileSync18 } from "node:fs";
|
|
50646
50705
|
var SEVERITY_EMOJI = {
|
|
50647
50706
|
info: "\u2139\ufe0f",
|
|
50648
50707
|
warn: "\u26a0\ufe0f",
|
|
@@ -50734,7 +50793,7 @@ function extractRetryAfterSecs2(err) {
|
|
|
50734
50793
|
var COOLDOWN_JITTER_MS2 = 500;
|
|
50735
50794
|
function readPersistedMessageId(path, log) {
|
|
50736
50795
|
try {
|
|
50737
|
-
const raw =
|
|
50796
|
+
const raw = readFileSync29(path, "utf8");
|
|
50738
50797
|
const parsed = JSON.parse(raw);
|
|
50739
50798
|
const v = parsed.messageId;
|
|
50740
50799
|
if (typeof v === "number" && Number.isInteger(v) && v > 0)
|
|
@@ -50750,7 +50809,7 @@ function readPersistedMessageId(path, log) {
|
|
|
50750
50809
|
}
|
|
50751
50810
|
function writePersistedMessageId(path, messageId, log) {
|
|
50752
50811
|
try {
|
|
50753
|
-
|
|
50812
|
+
writeFileSync18(path, JSON.stringify({ messageId }) + `
|
|
50754
50813
|
`, { mode: 384 });
|
|
50755
50814
|
} catch (err) {
|
|
50756
50815
|
log(`issues-card: persist write failed (${err.message})`);
|
|
@@ -50853,11 +50912,11 @@ import {
|
|
|
50853
50912
|
mkdirSync as mkdirSync18,
|
|
50854
50913
|
openSync as openSync4,
|
|
50855
50914
|
readdirSync as readdirSync5,
|
|
50856
|
-
readFileSync as
|
|
50915
|
+
readFileSync as readFileSync30,
|
|
50857
50916
|
renameSync as renameSync10,
|
|
50858
50917
|
statSync as statSync7,
|
|
50859
50918
|
unlinkSync as unlinkSync10,
|
|
50860
|
-
writeFileSync as
|
|
50919
|
+
writeFileSync as writeFileSync19,
|
|
50861
50920
|
writeSync
|
|
50862
50921
|
} from "node:fs";
|
|
50863
50922
|
import { join as join27 } from "node:path";
|
|
@@ -50884,7 +50943,7 @@ function readAll(stateDir) {
|
|
|
50884
50943
|
return [];
|
|
50885
50944
|
let raw;
|
|
50886
50945
|
try {
|
|
50887
|
-
raw =
|
|
50946
|
+
raw = readFileSync30(path, "utf-8");
|
|
50888
50947
|
} catch {
|
|
50889
50948
|
return [];
|
|
50890
50949
|
}
|
|
@@ -50940,7 +50999,7 @@ function writeAll(stateDir, events) {
|
|
|
50940
50999
|
const body = events.length === 0 ? "" : events.map((e) => JSON.stringify(e)).join(`
|
|
50941
51000
|
`) + `
|
|
50942
51001
|
`;
|
|
50943
|
-
|
|
51002
|
+
writeFileSync19(tmp, body, "utf-8");
|
|
50944
51003
|
renameSync10(tmp, path);
|
|
50945
51004
|
}
|
|
50946
51005
|
var ORPHAN_TMP_TTL_MS = 60000;
|
|
@@ -51003,7 +51062,7 @@ function withLock(stateDir, fn) {
|
|
|
51003
51062
|
function tryStealStaleLock(lockPath) {
|
|
51004
51063
|
let pidStr;
|
|
51005
51064
|
try {
|
|
51006
|
-
pidStr =
|
|
51065
|
+
pidStr = readFileSync30(lockPath, "utf-8").trim();
|
|
51007
51066
|
} catch {
|
|
51008
51067
|
return true;
|
|
51009
51068
|
}
|
|
@@ -51781,7 +51840,7 @@ function extractFlowItems(line) {
|
|
|
51781
51840
|
}
|
|
51782
51841
|
|
|
51783
51842
|
// credits-watch.ts
|
|
51784
|
-
import { readFileSync as
|
|
51843
|
+
import { readFileSync as readFileSync31, writeFileSync as writeFileSync20, existsSync as existsSync32, mkdirSync as mkdirSync19 } from "fs";
|
|
51785
51844
|
import { join as join29 } from "path";
|
|
51786
51845
|
var STATE_FILE = "credits-watch.json";
|
|
51787
51846
|
var FATAL_REASONS = new Set([
|
|
@@ -51799,7 +51858,7 @@ function readClaudeJsonOverage(claudeConfigDir) {
|
|
|
51799
51858
|
return null;
|
|
51800
51859
|
let raw;
|
|
51801
51860
|
try {
|
|
51802
|
-
raw =
|
|
51861
|
+
raw = readFileSync31(path, "utf-8");
|
|
51803
51862
|
} catch {
|
|
51804
51863
|
return null;
|
|
51805
51864
|
}
|
|
@@ -51883,7 +51942,7 @@ function loadCreditState(stateDir) {
|
|
|
51883
51942
|
if (!existsSync32(path))
|
|
51884
51943
|
return emptyCreditState();
|
|
51885
51944
|
try {
|
|
51886
|
-
const raw =
|
|
51945
|
+
const raw = readFileSync31(path, "utf-8");
|
|
51887
51946
|
const parsed = JSON.parse(raw);
|
|
51888
51947
|
if (parsed && typeof parsed === "object" && (parsed.lastNotifiedReason === null || typeof parsed.lastNotifiedReason === "string") && typeof parsed.lastNotifiedAt === "number" && Number.isFinite(parsed.lastNotifiedAt)) {
|
|
51889
51948
|
return {
|
|
@@ -51897,12 +51956,12 @@ function loadCreditState(stateDir) {
|
|
|
51897
51956
|
function saveCreditState(stateDir, state4) {
|
|
51898
51957
|
mkdirSync19(stateDir, { recursive: true });
|
|
51899
51958
|
const path = join29(stateDir, STATE_FILE);
|
|
51900
|
-
|
|
51959
|
+
writeFileSync20(path, JSON.stringify(state4, null, 2) + `
|
|
51901
51960
|
`, { mode: 384 });
|
|
51902
51961
|
}
|
|
51903
51962
|
|
|
51904
51963
|
// quota-watch.ts
|
|
51905
|
-
import { readFileSync as
|
|
51964
|
+
import { readFileSync as readFileSync32, writeFileSync as writeFileSync21, existsSync as existsSync33, mkdirSync as mkdirSync20 } from "fs";
|
|
51906
51965
|
import { join as join30 } from "path";
|
|
51907
51966
|
var STATE_FILE2 = "quota-watch.json";
|
|
51908
51967
|
function emptyQuotaWatchState() {
|
|
@@ -51997,7 +52056,7 @@ function loadQuotaWatchState(stateDir) {
|
|
|
51997
52056
|
if (!existsSync33(path))
|
|
51998
52057
|
return emptyQuotaWatchState();
|
|
51999
52058
|
try {
|
|
52000
|
-
const raw =
|
|
52059
|
+
const raw = readFileSync32(path, "utf-8");
|
|
52001
52060
|
const parsed = JSON.parse(raw);
|
|
52002
52061
|
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
52003
52062
|
return emptyQuotaWatchState();
|
|
@@ -52016,7 +52075,7 @@ function loadQuotaWatchState(stateDir) {
|
|
|
52016
52075
|
function saveQuotaWatchState(stateDir, state4) {
|
|
52017
52076
|
mkdirSync20(stateDir, { recursive: true });
|
|
52018
52077
|
const path = join30(stateDir, STATE_FILE2);
|
|
52019
|
-
|
|
52078
|
+
writeFileSync21(path, JSON.stringify(state4, null, 2) + `
|
|
52020
52079
|
`, { mode: 384 });
|
|
52021
52080
|
}
|
|
52022
52081
|
function patchQuotaWatchState(current, accountLabel, accountState) {
|
|
@@ -52032,18 +52091,18 @@ import {
|
|
|
52032
52091
|
existsSync as existsSync34,
|
|
52033
52092
|
mkdirSync as mkdirSync21,
|
|
52034
52093
|
openSync as openSync5,
|
|
52035
|
-
readFileSync as
|
|
52094
|
+
readFileSync as readFileSync33,
|
|
52036
52095
|
statSync as statSync9,
|
|
52037
52096
|
unlinkSync as unlinkSync11,
|
|
52038
52097
|
utimesSync as utimesSync2,
|
|
52039
|
-
writeFileSync as
|
|
52098
|
+
writeFileSync as writeFileSync22
|
|
52040
52099
|
} from "node:fs";
|
|
52041
52100
|
import { join as join31 } from "node:path";
|
|
52042
52101
|
var TURN_ACTIVE_MARKER_FILE2 = "turn-active.json";
|
|
52043
52102
|
function writeTurnActiveMarker(stateDir, marker) {
|
|
52044
52103
|
try {
|
|
52045
52104
|
mkdirSync21(stateDir, { recursive: true });
|
|
52046
|
-
|
|
52105
|
+
writeFileSync22(join31(stateDir, TURN_ACTIVE_MARKER_FILE2), JSON.stringify(marker, null, 2) + `
|
|
52047
52106
|
`, { mode: 384 });
|
|
52048
52107
|
} catch {}
|
|
52049
52108
|
}
|
|
@@ -52080,7 +52139,7 @@ function sweepStaleTurnActiveMarker(stateDir, opts) {
|
|
|
52080
52139
|
return false;
|
|
52081
52140
|
let payload = null;
|
|
52082
52141
|
try {
|
|
52083
|
-
payload =
|
|
52142
|
+
payload = readFileSync33(path, "utf8");
|
|
52084
52143
|
} catch {}
|
|
52085
52144
|
unlinkSync11(path);
|
|
52086
52145
|
if (opts.onRemove) {
|
|
@@ -52099,10 +52158,10 @@ function sweepStaleTurnActiveMarker(stateDir, opts) {
|
|
|
52099
52158
|
}
|
|
52100
52159
|
|
|
52101
52160
|
// ../src/build-info.ts
|
|
52102
|
-
var VERSION = "0.14.
|
|
52103
|
-
var COMMIT_SHA = "
|
|
52104
|
-
var COMMIT_DATE = "2026-06-
|
|
52105
|
-
var LATEST_PR =
|
|
52161
|
+
var VERSION = "0.14.50";
|
|
52162
|
+
var COMMIT_SHA = "07e8b692";
|
|
52163
|
+
var COMMIT_DATE = "2026-06-03T10:08:18Z";
|
|
52164
|
+
var LATEST_PR = 2124;
|
|
52106
52165
|
var COMMITS_AHEAD_OF_TAG = 0;
|
|
52107
52166
|
|
|
52108
52167
|
// gateway/boot-version.ts
|
|
@@ -52617,15 +52676,18 @@ function promptClause(turn) {
|
|
|
52617
52676
|
function buildResumeInterruptedInbound(ctx) {
|
|
52618
52677
|
const ts = ctx.nowMs ?? Date.now();
|
|
52619
52678
|
const elapsed = humanizeElapsed(ts - ctx.turn.started_at);
|
|
52679
|
+
const threadId = threadIdNum(ctx.turn);
|
|
52620
52680
|
const meta = {
|
|
52621
52681
|
source: "resume_interrupted",
|
|
52682
|
+
chat_id: ctx.turn.chat_id,
|
|
52683
|
+
...threadId != null ? { message_thread_id: String(threadId) } : {},
|
|
52684
|
+
message_id: String(ts),
|
|
52622
52685
|
resume_turn_key: ctx.turn.turn_key,
|
|
52623
52686
|
interrupted_via: ctx.turn.ended_via ?? "restart",
|
|
52624
52687
|
started_at: String(ctx.turn.started_at)
|
|
52625
52688
|
};
|
|
52626
52689
|
if (ctx.turn.user_prompt_preview)
|
|
52627
52690
|
meta.original_prompt = ctx.turn.user_prompt_preview;
|
|
52628
|
-
const threadId = threadIdNum(ctx.turn);
|
|
52629
52691
|
return {
|
|
52630
52692
|
type: "inbound",
|
|
52631
52693
|
chatId: ctx.turn.chat_id,
|
|
@@ -52643,8 +52705,11 @@ function buildResumeWatchdogReportInbound(ctx) {
|
|
|
52643
52705
|
const idle = humanizeElapsed(ctx.idleMs);
|
|
52644
52706
|
const since = humanizeElapsed(ts - ctx.turn.started_at);
|
|
52645
52707
|
const toolClause = ctx.turn.tool_call_count != null && ctx.turn.tool_call_count > 0 ? ` You'd run ${ctx.turn.tool_call_count} tool call${ctx.turn.tool_call_count === 1 ? "" : "s"} before it stalled.` : "";
|
|
52708
|
+
const threadId = threadIdNum(ctx.turn);
|
|
52646
52709
|
const meta = {
|
|
52647
52710
|
source: "resume_watchdog_timeout",
|
|
52711
|
+
chat_id: ctx.turn.chat_id,
|
|
52712
|
+
...threadId != null ? { message_thread_id: String(threadId) } : {},
|
|
52648
52713
|
resume_turn_key: ctx.turn.turn_key,
|
|
52649
52714
|
interrupted_via: "timeout",
|
|
52650
52715
|
idle_ms: String(ctx.idleMs),
|
|
@@ -52654,7 +52719,6 @@ function buildResumeWatchdogReportInbound(ctx) {
|
|
|
52654
52719
|
meta.tool_call_count = String(ctx.turn.tool_call_count);
|
|
52655
52720
|
if (ctx.turn.user_prompt_preview)
|
|
52656
52721
|
meta.original_prompt = ctx.turn.user_prompt_preview;
|
|
52657
|
-
const threadId = threadIdNum(ctx.turn);
|
|
52658
52722
|
return {
|
|
52659
52723
|
type: "inbound",
|
|
52660
52724
|
chatId: ctx.turn.chat_id,
|
|
@@ -52849,7 +52913,7 @@ function formatBootVersion() {
|
|
|
52849
52913
|
}
|
|
52850
52914
|
try {
|
|
52851
52915
|
chmodSync6(ENV_FILE, 384);
|
|
52852
|
-
for (const line of
|
|
52916
|
+
for (const line of readFileSync36(ENV_FILE, "utf8").split(`
|
|
52853
52917
|
`)) {
|
|
52854
52918
|
const m = line.match(/^(\w+)=(.*)$/);
|
|
52855
52919
|
if (m && process.env[m[1]] === undefined)
|
|
@@ -52902,7 +52966,7 @@ installTgPostLogger(bot);
|
|
|
52902
52966
|
var _rawSendMessageDraft = bot.api.raw.sendMessageDraft;
|
|
52903
52967
|
var GRAMMY_VERSION = (() => {
|
|
52904
52968
|
try {
|
|
52905
|
-
const raw =
|
|
52969
|
+
const raw = readFileSync36(new URL("../../node_modules/grammy/package.json", import.meta.url), "utf8");
|
|
52906
52970
|
return JSON.parse(raw).version ?? "unknown";
|
|
52907
52971
|
} catch {
|
|
52908
52972
|
return "unknown";
|
|
@@ -52994,7 +53058,7 @@ function assertSendable(f) {
|
|
|
52994
53058
|
}
|
|
52995
53059
|
function readAccessFile() {
|
|
52996
53060
|
try {
|
|
52997
|
-
const raw =
|
|
53061
|
+
const raw = readFileSync36(ACCESS_FILE, "utf8");
|
|
52998
53062
|
const parsed = JSON.parse(raw);
|
|
52999
53063
|
const allowFrom = validateStringArray("allowFrom", parsed.allowFrom ?? []);
|
|
53000
53064
|
const groups = {};
|
|
@@ -53064,7 +53128,7 @@ function saveAccess(a) {
|
|
|
53064
53128
|
return;
|
|
53065
53129
|
mkdirSync26(STATE_DIR, { recursive: true, mode: 448 });
|
|
53066
53130
|
const tmp = ACCESS_FILE + ".tmp";
|
|
53067
|
-
|
|
53131
|
+
writeFileSync25(tmp, JSON.stringify(a, null, 2) + `
|
|
53068
53132
|
`, { mode: 384 });
|
|
53069
53133
|
renameSync12(tmp, ACCESS_FILE);
|
|
53070
53134
|
}
|
|
@@ -53105,7 +53169,7 @@ try {
|
|
|
53105
53169
|
const st = statSync13(markerPath);
|
|
53106
53170
|
markerAgeMs = Date.now() - st.mtimeMs;
|
|
53107
53171
|
try {
|
|
53108
|
-
const payload = JSON.parse(
|
|
53172
|
+
const payload = JSON.parse(readFileSync36(markerPath, "utf8"));
|
|
53109
53173
|
if (typeof payload.turnKey === "string" && payload.turnKey.length > 0) {
|
|
53110
53174
|
markerTurnKey = payload.turnKey;
|
|
53111
53175
|
}
|
|
@@ -53176,7 +53240,7 @@ try {
|
|
|
53176
53240
|
pending2.interrupt_reason != null ? `SWITCHROOM_PENDING_INTERRUPT_REASON=${pending2.interrupt_reason}` : `SWITCHROOM_PENDING_INTERRUPT_REASON=`
|
|
53177
53241
|
];
|
|
53178
53242
|
const pendingEnvTmp = `${pendingEnvPath}.tmp-${process.pid}`;
|
|
53179
|
-
|
|
53243
|
+
writeFileSync25(pendingEnvTmp, lines.join(`
|
|
53180
53244
|
`) + `
|
|
53181
53245
|
`, { mode: 384 });
|
|
53182
53246
|
renameSync12(pendingEnvTmp, pendingEnvPath);
|
|
@@ -53798,7 +53862,18 @@ function wrapBootCardApi(threadId) {
|
|
|
53798
53862
|
const sent = await robustApiCall(() => lockedBot.api.sendMessage(cid, text, sendOpts), opts(cid));
|
|
53799
53863
|
return sent;
|
|
53800
53864
|
},
|
|
53801
|
-
editMessageText: (cid, mid, text, editOpts) => robustApiCall(() => lockedBot.api.editMessageText(cid, mid, text, editOpts), opts(cid))
|
|
53865
|
+
editMessageText: (cid, mid, text, editOpts) => robustApiCall(() => lockedBot.api.editMessageText(cid, mid, text, editOpts), opts(cid)),
|
|
53866
|
+
editMessageTextStrict: async (cid, mid, text, editOpts) => {
|
|
53867
|
+
try {
|
|
53868
|
+
await lockedBot.api.editMessageText(cid, mid, text, editOpts);
|
|
53869
|
+
return "edited";
|
|
53870
|
+
} catch (err) {
|
|
53871
|
+
const desc = err instanceof import_grammy9.GrammyError ? err.description : err instanceof Error ? err.message : String(err);
|
|
53872
|
+
if (typeof desc === "string" && desc.toLowerCase().includes("not modified"))
|
|
53873
|
+
return "edited";
|
|
53874
|
+
return "gone";
|
|
53875
|
+
}
|
|
53876
|
+
}
|
|
53802
53877
|
};
|
|
53803
53878
|
}
|
|
53804
53879
|
function wrapIssuesCardApi(threadId) {
|
|
@@ -54434,7 +54509,8 @@ _deliveryMachineTick.unref?.();
|
|
|
54434
54509
|
function trackRedeliveredInbound(merged) {
|
|
54435
54510
|
if (!DELIVERY_CONFIRM_ENABLED)
|
|
54436
54511
|
return;
|
|
54437
|
-
|
|
54512
|
+
const isTrackableResume = isTrackableResumeSynthetic(merged.meta);
|
|
54513
|
+
if (!isTrackableResume && !shouldTrackDelivery({
|
|
54438
54514
|
isSteering: false,
|
|
54439
54515
|
isInterrupt: false,
|
|
54440
54516
|
hasSource: merged.meta?.source != null,
|
|
@@ -54496,8 +54572,8 @@ var inboundSpool = STATIC ? undefined : createInboundSpool({
|
|
|
54496
54572
|
path: join35(STATE_DIR, "inbound-spool.jsonl"),
|
|
54497
54573
|
fs: {
|
|
54498
54574
|
appendFileSync: (p, d) => appendFileSync5(p, d),
|
|
54499
|
-
readFileSync: (p) =>
|
|
54500
|
-
writeFileSync: (p, d) =>
|
|
54575
|
+
readFileSync: (p) => readFileSync36(p, "utf8"),
|
|
54576
|
+
writeFileSync: (p, d) => writeFileSync25(p, d),
|
|
54501
54577
|
renameSync: (a, b) => renameSync12(a, b),
|
|
54502
54578
|
existsSync: (p) => existsSync38(p),
|
|
54503
54579
|
statSizeSync: (p) => statSync13(p).size
|
|
@@ -54642,6 +54718,7 @@ var ipcServer = createIpcServer({
|
|
|
54642
54718
|
tmuxSupervisor: process.env.SWITCHROOM_TMUX_SUPERVISOR === "1",
|
|
54643
54719
|
dockerMode: process.env.SWITCHROOM_RUNTIME === "docker",
|
|
54644
54720
|
configSnapshotPath: join35(resolvedAgentDirForCard, ".config-snapshot.json"),
|
|
54721
|
+
bootCardStatePath: join35(resolvedAgentDirForCard, ".boot-card-msgid.json"),
|
|
54645
54722
|
...updateOutcomeLine ? { updateOutcomeLine } : {}
|
|
54646
54723
|
}, ackMsgId).then((handle) => {
|
|
54647
54724
|
activeBootCard = handle;
|
|
@@ -56081,7 +56158,7 @@ async function publishToTelegraph(text, shortName, authorName) {
|
|
|
56081
56158
|
let account = null;
|
|
56082
56159
|
try {
|
|
56083
56160
|
if (existsSync38(accountPath)) {
|
|
56084
|
-
const raw =
|
|
56161
|
+
const raw = readFileSync36(accountPath, "utf-8");
|
|
56085
56162
|
const parsed = JSON.parse(raw);
|
|
56086
56163
|
if (parsed.shortName && parsed.accessToken) {
|
|
56087
56164
|
account = parsed;
|
|
@@ -56101,7 +56178,7 @@ async function publishToTelegraph(text, shortName, authorName) {
|
|
|
56101
56178
|
account = created.value;
|
|
56102
56179
|
try {
|
|
56103
56180
|
mkdirSync26(STATE_DIR, { recursive: true, mode: 448 });
|
|
56104
|
-
|
|
56181
|
+
writeFileSync25(accountPath, JSON.stringify(account, null, 2), { mode: 384 });
|
|
56105
56182
|
} catch (err) {
|
|
56106
56183
|
process.stderr.write(`telegram gateway: telegraph cache write failed: ${err.message}
|
|
56107
56184
|
`);
|
|
@@ -56575,7 +56652,7 @@ async function executeDownloadAttachment(args) {
|
|
|
56575
56652
|
});
|
|
56576
56653
|
mkdirSync26(INBOX_DIR, { recursive: true, mode: 448 });
|
|
56577
56654
|
assertInsideInbox(INBOX_DIR, dlPath);
|
|
56578
|
-
|
|
56655
|
+
writeFileSync25(dlPath, buf, { mode: 384 });
|
|
56579
56656
|
return { content: [{ type: "text", text: dlPath }] };
|
|
56580
56657
|
}
|
|
56581
56658
|
async function executeEditMessage(args) {
|
|
@@ -58464,7 +58541,7 @@ function writeRestartMarker(marker) {
|
|
|
58464
58541
|
if (!p)
|
|
58465
58542
|
return;
|
|
58466
58543
|
try {
|
|
58467
|
-
|
|
58544
|
+
writeFileSync25(p, JSON.stringify(marker));
|
|
58468
58545
|
lastPlannedRestartAt = Date.now();
|
|
58469
58546
|
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}
|
|
58470
58547
|
`);
|
|
@@ -58483,7 +58560,7 @@ function readRestartMarker() {
|
|
|
58483
58560
|
if (!p)
|
|
58484
58561
|
return null;
|
|
58485
58562
|
try {
|
|
58486
|
-
return JSON.parse(
|
|
58563
|
+
return JSON.parse(readFileSync36(p, "utf8"));
|
|
58487
58564
|
} catch {
|
|
58488
58565
|
return null;
|
|
58489
58566
|
}
|
|
@@ -58620,7 +58697,7 @@ function spawnSwitchroomDetached(args, onFailure) {
|
|
|
58620
58697
|
try {
|
|
58621
58698
|
mkdirSync26(STATE_DIR, { recursive: true });
|
|
58622
58699
|
outFd = openSync8(logPath, "a");
|
|
58623
|
-
|
|
58700
|
+
writeFileSync25(logPath, `
|
|
58624
58701
|
[${new Date().toISOString()}] spawn ${SWITCHROOM_CLI} ${fullArgs.join(" ")}
|
|
58625
58702
|
`, { flag: "a" });
|
|
58626
58703
|
} catch {}
|
|
@@ -58646,7 +58723,7 @@ function spawnSwitchroomDetached(args, onFailure) {
|
|
|
58646
58723
|
return;
|
|
58647
58724
|
let tail = "";
|
|
58648
58725
|
try {
|
|
58649
|
-
const full =
|
|
58726
|
+
const full = readFileSync36(logPath, "utf8");
|
|
58650
58727
|
tail = full.split(`
|
|
58651
58728
|
`).slice(-30).join(`
|
|
58652
58729
|
`).trim();
|
|
@@ -58991,7 +59068,7 @@ function readRecentDenialsForAgent(agentName3, windowMs, limit) {
|
|
|
58991
59068
|
const auditPath = join35(homedir14(), ".switchroom", "vault-audit.log");
|
|
58992
59069
|
if (!existsSync38(auditPath))
|
|
58993
59070
|
return [];
|
|
58994
|
-
const raw =
|
|
59071
|
+
const raw = readFileSync36(auditPath, "utf8");
|
|
58995
59072
|
return recentDenialsFromAuditLog(raw, { agentName: agentName3, windowMs, limit });
|
|
58996
59073
|
} catch {
|
|
58997
59074
|
return [];
|
|
@@ -59042,7 +59119,7 @@ async function buildAgentMetadata(agentName3) {
|
|
|
59042
59119
|
try {
|
|
59043
59120
|
const agentDir = resolveAgentDirFromEnv();
|
|
59044
59121
|
if (agentDir) {
|
|
59045
|
-
const raw =
|
|
59122
|
+
const raw = readFileSync36(join35(agentDir, ".claude", ".claude.json"), "utf8");
|
|
59046
59123
|
claudeJson = JSON.parse(raw);
|
|
59047
59124
|
}
|
|
59048
59125
|
} catch {}
|
|
@@ -59314,7 +59391,7 @@ async function handleNewOrResetCommand(ctx, kind) {
|
|
|
59314
59391
|
writeRestartMarker({ chat_id: chatId, thread_id: threadId ?? null, ack_message_id: ackId, ts: Date.now() });
|
|
59315
59392
|
if (agentDir != null) {
|
|
59316
59393
|
try {
|
|
59317
|
-
|
|
59394
|
+
writeFileSync25(join35(agentDir, ".force-fresh-session"), `${kind} at ${new Date().toISOString()}
|
|
59318
59395
|
`, "utf8");
|
|
59319
59396
|
} catch (err) {
|
|
59320
59397
|
process.stderr.write(`telegram gateway: failed to write force-fresh marker: ${err}
|
|
@@ -59678,8 +59755,8 @@ bot.command("interrupt", async (ctx) => {
|
|
|
59678
59755
|
await runSwitchroomCommand(ctx, ["agent", "interrupt", name], `interrupt ${name}`);
|
|
59679
59756
|
});
|
|
59680
59757
|
var lockoutOps = {
|
|
59681
|
-
readFileSync: (p, enc) =>
|
|
59682
|
-
writeFileSync: (p, data, opts) =>
|
|
59758
|
+
readFileSync: (p, enc) => readFileSync36(p, enc),
|
|
59759
|
+
writeFileSync: (p, data, opts) => writeFileSync25(p, data, opts),
|
|
59683
59760
|
existsSync: (p) => existsSync38(p),
|
|
59684
59761
|
mkdirSync: (p, opts) => mkdirSync26(p, opts),
|
|
59685
59762
|
joinPath: (...parts) => join35(...parts)
|
|
@@ -60054,7 +60131,7 @@ async function handleVaultRecentDenialCallback(ctx, data) {
|
|
|
60054
60131
|
const tokenPath = join35(homedir14(), ".switchroom", "agents", agentName3, ".vault-token");
|
|
60055
60132
|
try {
|
|
60056
60133
|
mkdirSync26(join35(homedir14(), ".switchroom", "agents", agentName3), { recursive: true });
|
|
60057
|
-
|
|
60134
|
+
writeFileSync25(tokenPath, token, { mode: 384 });
|
|
60058
60135
|
} catch (err) {
|
|
60059
60136
|
await switchroomReply(ctx, `<b>Grant created (${escapeHtmlForTg(id)}) but token write failed:</b> ${escapeHtmlForTg(String(err))}
|
|
60060
60137
|
<i>Recover with: <code>switchroom vault grant ${escapeHtmlForTg(agentName3)} --keys ${escapeHtmlForTg(keyName)} --duration 30d</code> on the host.</i>`, { html: true });
|
|
@@ -60133,7 +60210,7 @@ async function performVaultAccessApproval(ctx, pending2, stageId, senderId, atte
|
|
|
60133
60210
|
const tokenPath = join35(homedir14(), ".switchroom", "agents", pending2.agent, ".vault-token");
|
|
60134
60211
|
try {
|
|
60135
60212
|
mkdirSync26(join35(homedir14(), ".switchroom", "agents", pending2.agent), { recursive: true });
|
|
60136
|
-
|
|
60213
|
+
writeFileSync25(tokenPath, token, { mode: 384 });
|
|
60137
60214
|
} catch (err) {
|
|
60138
60215
|
await switchroomReply(ctx, `<b>Grant created (${escapeHtmlForTg(id)}) but token write failed:</b> ${escapeHtmlForTg(String(err))}
|
|
60139
60216
|
<i>Recover with: <code>switchroom vault grant ${escapeHtmlForTg(pending2.agent)} --keys ${escapeHtmlForTg(pending2.key)} --duration ${Math.round(pending2.ttl_seconds / 86400)}d</code> on the host.</i>`, { html: true });
|
|
@@ -60637,7 +60714,7 @@ async function executeGrantWizard(ctx, chatId, state4) {
|
|
|
60637
60714
|
const tokenPath = join35(homedir14(), ".switchroom", "agents", state4.agent, ".vault-token");
|
|
60638
60715
|
try {
|
|
60639
60716
|
mkdirSync26(join35(homedir14(), ".switchroom", "agents", state4.agent), { recursive: true });
|
|
60640
|
-
|
|
60717
|
+
writeFileSync25(tokenPath, token, { mode: 384 });
|
|
60641
60718
|
} catch (err) {
|
|
60642
60719
|
await switchroomReply(ctx, `<b>Grant created but token write failed:</b> ${escapeHtmlForTg(String(err))}`, { html: true });
|
|
60643
60720
|
return;
|
|
@@ -61933,7 +62010,7 @@ ${preBlock(formatSwitchroomOutput(err.message ?? "unknown error"))}`, { html: tr
|
|
|
61933
62010
|
const unifiedDiff = (() => {
|
|
61934
62011
|
try {
|
|
61935
62012
|
const cfgPath = process.env.SWITCHROOM_CONFIG ?? SWITCHROOM_CONFIG ?? findConfigFile2();
|
|
61936
|
-
const raw =
|
|
62013
|
+
const raw = readFileSync36(cfgPath, "utf8");
|
|
61937
62014
|
return synthesizeAllowRuleDiff({ agentName: agentName3, rule: chosen.rule, configText: raw });
|
|
61938
62015
|
} catch (err) {
|
|
61939
62016
|
process.stderr.write(`telegram gateway: always-allow diff synth failed: ${err.message}
|
|
@@ -62081,7 +62158,7 @@ bot.on("message:photo", async (ctx) => {
|
|
|
62081
62158
|
});
|
|
62082
62159
|
mkdirSync26(INBOX_DIR, { recursive: true, mode: 448 });
|
|
62083
62160
|
assertInsideInbox(INBOX_DIR, dlPath);
|
|
62084
|
-
|
|
62161
|
+
writeFileSync25(dlPath, buf, { mode: 384 });
|
|
62085
62162
|
return dlPath;
|
|
62086
62163
|
} catch (err) {
|
|
62087
62164
|
const msg = err instanceof Error ? err.message : "unknown error";
|
|
@@ -62122,7 +62199,7 @@ async function maybeTranscribeVoice(fileId, mimeType, language) {
|
|
|
62122
62199
|
try {
|
|
62123
62200
|
const path = __require("path").join(__require("os").homedir(), ".switchroom", "openai-api-key");
|
|
62124
62201
|
if (existsSync38(path)) {
|
|
62125
|
-
apiKey =
|
|
62202
|
+
apiKey = readFileSync36(path, "utf-8").trim();
|
|
62126
62203
|
}
|
|
62127
62204
|
} catch (err) {
|
|
62128
62205
|
process.stderr.write(`telegram gateway: voice-in: failed to read api key: ${err.message}
|
|
@@ -62992,6 +63069,7 @@ var didOneTimeSetup = false;
|
|
|
62992
63069
|
tmuxSupervisor: process.env.SWITCHROOM_TMUX_SUPERVISOR === "1",
|
|
62993
63070
|
dockerMode: process.env.SWITCHROOM_RUNTIME === "docker",
|
|
62994
63071
|
configSnapshotPath: join35(resolvedAgentDirForBootCard, ".config-snapshot.json"),
|
|
63072
|
+
bootCardStatePath: join35(resolvedAgentDirForBootCard, ".boot-card-msgid.json"),
|
|
62995
63073
|
...updateOutcomeLine ? { updateOutcomeLine } : {}
|
|
62996
63074
|
}, ackMsgId);
|
|
62997
63075
|
activeBootCard = handle;
|