switchroom 0.14.41 → 0.14.42
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
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.42";
|
|
49466
|
+
var COMMIT_SHA = "6da4313d";
|
|
49467
49467
|
|
|
49468
49468
|
// src/cli/agent.ts
|
|
49469
49469
|
init_source();
|
package/package.json
CHANGED
|
@@ -44777,6 +44777,12 @@ function resolveOutboundTopic(config, event) {
|
|
|
44777
44777
|
return aliasToId(cfg, ADMIN_ALIAS) ?? cfg.default_topic_id;
|
|
44778
44778
|
}
|
|
44779
44779
|
}
|
|
44780
|
+
function topicForRecipient(args) {
|
|
44781
|
+
const { recipientChatId, resolvedTopic, supergroupChatId } = args;
|
|
44782
|
+
if (resolvedTopic == null || supergroupChatId == null)
|
|
44783
|
+
return;
|
|
44784
|
+
return String(recipientChatId) === String(supergroupChatId) ? resolvedTopic : undefined;
|
|
44785
|
+
}
|
|
44780
44786
|
|
|
44781
44787
|
// ../src/agents/perf.ts
|
|
44782
44788
|
import { existsSync as existsSync18, readFileSync as readFileSync14 } from "node:fs";
|
|
@@ -51865,10 +51871,10 @@ function sweepStaleTurnActiveMarker(stateDir, opts) {
|
|
|
51865
51871
|
}
|
|
51866
51872
|
|
|
51867
51873
|
// ../src/build-info.ts
|
|
51868
|
-
var VERSION = "0.14.
|
|
51869
|
-
var COMMIT_SHA = "
|
|
51870
|
-
var COMMIT_DATE = "2026-06-
|
|
51871
|
-
var LATEST_PR =
|
|
51874
|
+
var VERSION = "0.14.42";
|
|
51875
|
+
var COMMIT_SHA = "6da4313d";
|
|
51876
|
+
var COMMIT_DATE = "2026-06-02T22:14:58Z";
|
|
51877
|
+
var LATEST_PR = 2097;
|
|
51872
51878
|
var COMMITS_AHEAD_OF_TAG = 0;
|
|
51873
51879
|
|
|
51874
51880
|
// gateway/boot-version.ts
|
|
@@ -53361,14 +53367,18 @@ function postPermissionResumeMessage(opts) {
|
|
|
53361
53367
|
timeoutMinutes: opts.timeoutMinutes
|
|
53362
53368
|
});
|
|
53363
53369
|
const turn = currentTurn;
|
|
53364
|
-
const targets = turn != null ? [{ chatId: turn.sessionChatId, threadId: turn.sessionThreadId }] :
|
|
53365
|
-
|
|
53366
|
-
|
|
53370
|
+
const targets = turn != null ? [{ chatId: turn.sessionChatId, threadId: turn.sessionThreadId }] : (() => {
|
|
53371
|
+
const sg = resolveAgentSupergroupChatId();
|
|
53372
|
+
const topic = resolveAgentOutboundTopic({
|
|
53367
53373
|
kind: "permission",
|
|
53368
53374
|
turnInitiated: false,
|
|
53369
53375
|
originThreadId: undefined
|
|
53370
|
-
})
|
|
53371
|
-
|
|
53376
|
+
});
|
|
53377
|
+
return loadAccess().allowFrom.map((chatId) => ({
|
|
53378
|
+
chatId,
|
|
53379
|
+
threadId: topicForRecipient({ recipientChatId: chatId, resolvedTopic: topic, supergroupChatId: sg })
|
|
53380
|
+
}));
|
|
53381
|
+
})();
|
|
53372
53382
|
for (const { chatId, threadId } of targets) {
|
|
53373
53383
|
swallowingApiCall(() => bot.api.sendMessage(chatId, text, {
|
|
53374
53384
|
parse_mode: "HTML",
|
|
@@ -54479,11 +54489,13 @@ var ipcServer = createIpcServer({
|
|
|
54479
54489
|
turnInitiated: activeTurn != null,
|
|
54480
54490
|
originThreadId: activeTurn?.sessionThreadId
|
|
54481
54491
|
});
|
|
54492
|
+
const permSupergroup = resolveAgentSupergroupChatId();
|
|
54482
54493
|
for (const chat_id of access.allowFrom) {
|
|
54494
|
+
const permThread = topicForRecipient({ recipientChatId: chat_id, resolvedTopic: permTopic, supergroupChatId: permSupergroup });
|
|
54483
54495
|
bot.api.sendMessage(chat_id, text, {
|
|
54484
54496
|
parse_mode: "HTML",
|
|
54485
54497
|
reply_markup: keyboard,
|
|
54486
|
-
...
|
|
54498
|
+
...permThread != null ? { message_thread_id: permThread } : {}
|
|
54487
54499
|
}).catch((e) => {
|
|
54488
54500
|
process.stderr.write(`telegram gateway: permission_request send to ${chat_id} failed: ${e}
|
|
54489
54501
|
`);
|
|
@@ -54547,9 +54559,13 @@ var ipcServer = createIpcServer({
|
|
|
54547
54559
|
if (operator === undefined)
|
|
54548
54560
|
return null;
|
|
54549
54561
|
const activeTurn = currentTurn;
|
|
54550
|
-
const driveTopic =
|
|
54551
|
-
|
|
54552
|
-
|
|
54562
|
+
const driveTopic = topicForRecipient({
|
|
54563
|
+
recipientChatId: operator,
|
|
54564
|
+
resolvedTopic: resolveAgentOutboundTopic({
|
|
54565
|
+
kind: "hostd-approval",
|
|
54566
|
+
originThreadId: activeTurn?.sessionThreadId
|
|
54567
|
+
}),
|
|
54568
|
+
supergroupChatId: resolveAgentSupergroupChatId()
|
|
54553
54569
|
});
|
|
54554
54570
|
return {
|
|
54555
54571
|
chatId: operator,
|
|
@@ -54605,9 +54621,13 @@ var ipcServer = createIpcServer({
|
|
|
54605
54621
|
if (operator === undefined)
|
|
54606
54622
|
return null;
|
|
54607
54623
|
const activeTurn = currentTurn;
|
|
54608
|
-
const ms365Topic =
|
|
54609
|
-
|
|
54610
|
-
|
|
54624
|
+
const ms365Topic = topicForRecipient({
|
|
54625
|
+
recipientChatId: operator,
|
|
54626
|
+
resolvedTopic: resolveAgentOutboundTopic({
|
|
54627
|
+
kind: "hostd-approval",
|
|
54628
|
+
originThreadId: activeTurn?.sessionThreadId
|
|
54629
|
+
}),
|
|
54630
|
+
supergroupChatId: resolveAgentSupergroupChatId()
|
|
54611
54631
|
});
|
|
54612
54632
|
return {
|
|
54613
54633
|
chatId: operator,
|
|
@@ -54662,9 +54682,13 @@ var ipcServer = createIpcServer({
|
|
|
54662
54682
|
if (operator === undefined)
|
|
54663
54683
|
return null;
|
|
54664
54684
|
const activeTurn = currentTurn;
|
|
54665
|
-
const cfgTopic =
|
|
54666
|
-
|
|
54667
|
-
|
|
54685
|
+
const cfgTopic = topicForRecipient({
|
|
54686
|
+
recipientChatId: operator,
|
|
54687
|
+
resolvedTopic: resolveAgentOutboundTopic({
|
|
54688
|
+
kind: "hostd-approval",
|
|
54689
|
+
originThreadId: activeTurn?.sessionThreadId
|
|
54690
|
+
}),
|
|
54691
|
+
supergroupChatId: resolveAgentSupergroupChatId()
|
|
54668
54692
|
});
|
|
54669
54693
|
return {
|
|
54670
54694
|
chatId: operator,
|
|
@@ -58229,6 +58253,22 @@ function resolveAgentOutboundTopic(event) {
|
|
|
58229
58253
|
return;
|
|
58230
58254
|
}
|
|
58231
58255
|
}
|
|
58256
|
+
function resolveAgentSupergroupChatId() {
|
|
58257
|
+
const agentName3 = process.env.SWITCHROOM_AGENT_NAME;
|
|
58258
|
+
if (!agentName3)
|
|
58259
|
+
return;
|
|
58260
|
+
try {
|
|
58261
|
+
const cfg = loadConfig2();
|
|
58262
|
+
const rawAgent = cfg.agents?.[agentName3];
|
|
58263
|
+
if (!rawAgent)
|
|
58264
|
+
return;
|
|
58265
|
+
const resolved = resolveAgentConfig2(cfg.defaults, cfg.profiles, rawAgent);
|
|
58266
|
+
const tg = resolved.channels?.telegram;
|
|
58267
|
+
return tg?.chat_id != null ? String(tg.chat_id) : undefined;
|
|
58268
|
+
} catch {
|
|
58269
|
+
return;
|
|
58270
|
+
}
|
|
58271
|
+
}
|
|
58232
58272
|
function stampUserRestartReason(reason) {
|
|
58233
58273
|
try {
|
|
58234
58274
|
writeCleanShutdownMarker(GATEWAY_CLEAN_SHUTDOWN_MARKER_PATH, {
|
|
@@ -251,7 +251,7 @@ import { handleInjectCommand } from './inject-handler.js'
|
|
|
251
251
|
import { type BannerState } from '../slot-banner.js'
|
|
252
252
|
import { refreshBanner } from '../slot-banner-driver.js'
|
|
253
253
|
import { loadConfig as loadSwitchroomConfig, findConfigFile as findSwitchroomConfigFile } from '../../src/config/loader.js'; import { resolveAgentConfig } from '../../src/config/merge.js'
|
|
254
|
-
import { resolveOutboundTopic as resolveOutboundTopicHelper, type TopicRouterConfig as _OutboundRouterConfig } from '../../src/telegram/topic-router.js'
|
|
254
|
+
import { resolveOutboundTopic as resolveOutboundTopicHelper, topicForRecipient, type TopicRouterConfig as _OutboundRouterConfig } from '../../src/telegram/topic-router.js'
|
|
255
255
|
import { readTurnUsages } from '../../src/agents/perf.js'
|
|
256
256
|
import { decideProactiveCompact, initialCompactState, type CompactState } from './proactive-compact.js'
|
|
257
257
|
import { nextCompactNotify, idleCompactNotifyState, type CompactNotifyState } from './compact-notify.js'
|
|
@@ -2273,14 +2273,20 @@ function postPermissionResumeMessage(opts: {
|
|
|
2273
2273
|
const targets: Array<{ chatId: string; threadId: number | undefined }> =
|
|
2274
2274
|
turn != null
|
|
2275
2275
|
? [{ chatId: turn.sessionChatId, threadId: turn.sessionThreadId }]
|
|
2276
|
-
:
|
|
2277
|
-
|
|
2278
|
-
|
|
2276
|
+
: (() => {
|
|
2277
|
+
const sg = resolveAgentSupergroupChatId()
|
|
2278
|
+
const topic = resolveAgentOutboundTopic({
|
|
2279
2279
|
kind: 'permission',
|
|
2280
2280
|
turnInitiated: false,
|
|
2281
2281
|
originThreadId: undefined,
|
|
2282
|
-
})
|
|
2283
|
-
|
|
2282
|
+
})
|
|
2283
|
+
// allowFrom is normally operator DMs — attach the topic only to a
|
|
2284
|
+
// recipient that owns it (the supergroup), never a DM (marko wedge).
|
|
2285
|
+
return loadAccess().allowFrom.map(chatId => ({
|
|
2286
|
+
chatId,
|
|
2287
|
+
threadId: topicForRecipient({ recipientChatId: chatId, resolvedTopic: topic, supergroupChatId: sg }),
|
|
2288
|
+
}))
|
|
2289
|
+
})()
|
|
2284
2290
|
for (const { chatId, threadId } of targets) {
|
|
2285
2291
|
// allow-raw-bot-api: wrapped in swallowingApiCall (retry policy); thread-aware send
|
|
2286
2292
|
void swallowingApiCall(
|
|
@@ -4664,16 +4670,20 @@ const ipcServer: IpcServer = createIpcServer({
|
|
|
4664
4670
|
turnInitiated: activeTurn != null,
|
|
4665
4671
|
originThreadId: activeTurn?.sessionThreadId,
|
|
4666
4672
|
})
|
|
4673
|
+
const permSupergroup = resolveAgentSupergroupChatId()
|
|
4667
4674
|
for (const chat_id of access.allowFrom) {
|
|
4668
4675
|
// parse_mode=HTML pairs with formatPermissionCardBody (#1790)
|
|
4669
4676
|
// so the <b>/<i> tags render as formatting.
|
|
4670
|
-
//
|
|
4671
|
-
//
|
|
4677
|
+
// The resolved topic is valid only in the agent's supergroup — attach
|
|
4678
|
+
// it ONLY when this recipient IS that supergroup. allowFrom DMs get the
|
|
4679
|
+
// card thread-less; attaching a topic to a DM yields 400 "message thread
|
|
4680
|
+
// not found" → card never arrives → auto-deny → wedge (marko 2026-06-02).
|
|
4681
|
+
const permThread = topicForRecipient({ recipientChatId: chat_id, resolvedTopic: permTopic, supergroupChatId: permSupergroup })
|
|
4672
4682
|
// allow-raw-bot-api: permission-request keyboard fan-out; topic-aware opts
|
|
4673
4683
|
void bot.api.sendMessage(chat_id, text, {
|
|
4674
4684
|
parse_mode: 'HTML',
|
|
4675
4685
|
reply_markup: keyboard,
|
|
4676
|
-
...(
|
|
4686
|
+
...(permThread != null ? { message_thread_id: permThread } : {}),
|
|
4677
4687
|
}).catch(e => {
|
|
4678
4688
|
process.stderr.write(`telegram gateway: permission_request send to ${chat_id} failed: ${e}\n`)
|
|
4679
4689
|
})
|
|
@@ -4811,9 +4821,15 @@ const ipcServer: IpcServer = createIpcServer({
|
|
|
4811
4821
|
// topic. Drive approval cards follow the originating turn
|
|
4812
4822
|
// (operator-initiated tool call), admin alias fallback.
|
|
4813
4823
|
const activeTurn = currentTurn
|
|
4814
|
-
|
|
4815
|
-
|
|
4816
|
-
|
|
4824
|
+
// Attach the topic only when `operator` IS the agent's supergroup —
|
|
4825
|
+
// operator DMs have no topics (marko brevo wedge, 2026-06-02).
|
|
4826
|
+
const driveTopic = topicForRecipient({
|
|
4827
|
+
recipientChatId: operator,
|
|
4828
|
+
resolvedTopic: resolveAgentOutboundTopic({
|
|
4829
|
+
kind: 'hostd-approval',
|
|
4830
|
+
originThreadId: activeTurn?.sessionThreadId,
|
|
4831
|
+
}),
|
|
4832
|
+
supergroupChatId: resolveAgentSupergroupChatId(),
|
|
4817
4833
|
})
|
|
4818
4834
|
return {
|
|
4819
4835
|
chatId: operator,
|
|
@@ -4884,9 +4900,14 @@ const ipcServer: IpcServer = createIpcServer({
|
|
|
4884
4900
|
// alias fallback for background cases. Same shape as hostd /
|
|
4885
4901
|
// drive approvals below.
|
|
4886
4902
|
const activeTurn = currentTurn
|
|
4887
|
-
|
|
4888
|
-
|
|
4889
|
-
|
|
4903
|
+
// Topic valid only in the agent's supergroup — never on the operator DM.
|
|
4904
|
+
const ms365Topic = topicForRecipient({
|
|
4905
|
+
recipientChatId: operator,
|
|
4906
|
+
resolvedTopic: resolveAgentOutboundTopic({
|
|
4907
|
+
kind: 'hostd-approval',
|
|
4908
|
+
originThreadId: activeTurn?.sessionThreadId,
|
|
4909
|
+
}),
|
|
4910
|
+
supergroupChatId: resolveAgentSupergroupChatId(),
|
|
4890
4911
|
})
|
|
4891
4912
|
return {
|
|
4892
4913
|
chatId: operator,
|
|
@@ -4963,9 +4984,14 @@ const ipcServer: IpcServer = createIpcServer({
|
|
|
4963
4984
|
// returns undefined for non-supergroup agents → behavior
|
|
4964
4985
|
// unchanged.
|
|
4965
4986
|
const activeTurn = currentTurn
|
|
4966
|
-
|
|
4967
|
-
|
|
4968
|
-
|
|
4987
|
+
// Topic valid only in the agent's supergroup — never on the operator DM.
|
|
4988
|
+
const cfgTopic = topicForRecipient({
|
|
4989
|
+
recipientChatId: operator,
|
|
4990
|
+
resolvedTopic: resolveAgentOutboundTopic({
|
|
4991
|
+
kind: 'hostd-approval',
|
|
4992
|
+
originThreadId: activeTurn?.sessionThreadId,
|
|
4993
|
+
}),
|
|
4994
|
+
supergroupChatId: resolveAgentSupergroupChatId(),
|
|
4969
4995
|
})
|
|
4970
4996
|
return {
|
|
4971
4997
|
chatId: operator,
|
|
@@ -11067,6 +11093,30 @@ function resolveAgentOutboundTopic(
|
|
|
11067
11093
|
}
|
|
11068
11094
|
}
|
|
11069
11095
|
|
|
11096
|
+
/**
|
|
11097
|
+
* The agent's supergroup chat id (`channels.telegram.chat_id`) when it is in
|
|
11098
|
+
* supergroup-owned mode, else undefined. A forum topic id resolved by
|
|
11099
|
+
* {@link resolveAgentOutboundTopic} is valid ONLY in this chat — used by
|
|
11100
|
+
* {@link topicForRecipient} to decide whether an approval/permission card sent
|
|
11101
|
+
* to a given recipient (operator DMs vs the supergroup itself) may carry a
|
|
11102
|
+
* `message_thread_id`. Attaching a topic to a DM is the marko brevo wedge
|
|
11103
|
+
* (2026-06-02): the card fails with "message thread not found" and auto-denies.
|
|
11104
|
+
*/
|
|
11105
|
+
function resolveAgentSupergroupChatId(): string | undefined {
|
|
11106
|
+
const agentName = process.env.SWITCHROOM_AGENT_NAME
|
|
11107
|
+
if (!agentName) return undefined
|
|
11108
|
+
try {
|
|
11109
|
+
const cfg = loadSwitchroomConfig()
|
|
11110
|
+
const rawAgent = cfg.agents?.[agentName]
|
|
11111
|
+
if (!rawAgent) return undefined
|
|
11112
|
+
const resolved = resolveAgentConfig(cfg.defaults, cfg.profiles, rawAgent)
|
|
11113
|
+
const tg = resolved.channels?.telegram as { chat_id?: string | number } | undefined
|
|
11114
|
+
return tg?.chat_id != null ? String(tg.chat_id) : undefined
|
|
11115
|
+
} catch {
|
|
11116
|
+
return undefined
|
|
11117
|
+
}
|
|
11118
|
+
}
|
|
11119
|
+
|
|
11070
11120
|
/**
|
|
11071
11121
|
* Stamp a user-facing restart reason into the clean-shutdown marker
|
|
11072
11122
|
* (same file the SIGTERM handler writes to and the next session greeting
|