switchroom 0.14.44 → 0.14.45
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/agent-scheduler/index.js +80 -80
- package/dist/auth-broker/index.js +80 -80
- package/dist/cli/drive-write-pretool.mjs +10 -10
- package/dist/cli/notion-write-pretool.mjs +82 -82
- package/dist/cli/skill-validate-pretool.mjs +72 -72
- package/dist/cli/switchroom.js +357 -357
- package/dist/host-control/main.js +148 -148
- package/dist/vault/approvals/kernel-server.js +82 -82
- package/dist/vault/broker/server.js +83 -83
- package/package.json +1 -1
- package/telegram-plugin/dist/bridge/bridge.js +112 -112
- package/telegram-plugin/dist/gateway/gateway.js +198 -195
- package/telegram-plugin/dist/server.js +160 -160
- package/telegram-plugin/gateway/gateway.ts +21 -4
- package/telegram-plugin/hooks/tool-label-pretool.mjs +38 -6
|
@@ -3537,18 +3537,24 @@ function emitGatewayOperatorEvent(event: OperatorEvent): void {
|
|
|
3537
3537
|
// Fleet-shared / DM agents see `undefined` → no `message_thread_id`
|
|
3538
3538
|
// is added to the broadcast opts → behavior unchanged.
|
|
3539
3539
|
const opEventTopic = resolveAgentOutboundTopic({ kind: 'compact-watchdog' })
|
|
3540
|
+
const opEventSupergroup = resolveAgentSupergroupChatId()
|
|
3540
3541
|
|
|
3541
3542
|
process.stderr.write(
|
|
3542
3543
|
`telegram gateway: operator-event posting agent=${agent} kind=${kind} to ${access.allowFrom.length} chat(s)` +
|
|
3543
3544
|
(opEventTopic != null ? ` topic=${opEventTopic}` : '') + '\n',
|
|
3544
3545
|
)
|
|
3545
3546
|
for (const chat_id of access.allowFrom) {
|
|
3547
|
+
// The resolved topic is valid ONLY in the agent's supergroup — attaching
|
|
3548
|
+
// it to an operator DM recipient yields 400 "message thread not found" and
|
|
3549
|
+
// the event silently fails to deliver (the marko #2096 class). Guard it:
|
|
3550
|
+
// DM recipients get a thread-less send; the supergroup owner gets the lane.
|
|
3551
|
+
const opEventThread = topicForRecipient({ recipientChatId: chat_id, resolvedTopic: opEventTopic, supergroupChatId: opEventSupergroup })
|
|
3546
3552
|
// grammy's Other<...> opts type is generated and stricter than our
|
|
3547
3553
|
// call shape; runtime accepts both. Cast through unknown.
|
|
3548
3554
|
const opts = {
|
|
3549
3555
|
parse_mode: 'HTML' as const,
|
|
3550
3556
|
...(renderedKeyboard ? { reply_markup: renderedKeyboard } : {}),
|
|
3551
|
-
...(
|
|
3557
|
+
...(opEventThread != null ? { message_thread_id: opEventThread } : {}),
|
|
3552
3558
|
}
|
|
3553
3559
|
// Comment-only context for the reader; the lint marker on the
|
|
3554
3560
|
// very next line is what unlocks the raw bot.api call.
|
|
@@ -10159,7 +10165,14 @@ async function handleInbound(
|
|
|
10159
10165
|
// No staged entry to act on — fall through to normal handling.
|
|
10160
10166
|
}
|
|
10161
10167
|
|
|
10162
|
-
|
|
10168
|
+
// Typing indicator in the ORIGINATING topic — on a supergroup-topic inbound,
|
|
10169
|
+
// an un-threaded sendChatAction shows "typing" in General, not the topic the
|
|
10170
|
+
// user is in. messageThreadId is the inbound's thread (undefined in a DM).
|
|
10171
|
+
void bot.api.sendChatAction(
|
|
10172
|
+
chat_id,
|
|
10173
|
+
'typing',
|
|
10174
|
+
messageThreadId != null ? { message_thread_id: messageThreadId } : {},
|
|
10175
|
+
).catch(() => {})
|
|
10163
10176
|
|
|
10164
10177
|
// Parse explicit prefixes first. `/steer ` / `/s ` opts IN to steering;
|
|
10165
10178
|
// `/queue ` / `/q ` are legacy aliases that opt in to the new default (queued).
|
|
@@ -11088,10 +11101,14 @@ function resolveBootChatId(
|
|
|
11088
11101
|
// → behavior unchanged (lands at chat-root as today). PR4b of
|
|
11089
11102
|
// supergroup-mode rollout (docs/rfcs/supergroup-mode.md).
|
|
11090
11103
|
const supergroupBootTopic = resolveAgentOutboundTopic({ kind: 'boot' })
|
|
11104
|
+
const bootSupergroup = resolveAgentSupergroupChatId()
|
|
11105
|
+
// The boot topic is valid only in the agent's supergroup — attach it per
|
|
11106
|
+
// recipient so a DM owner doesn't 400 (marko #2096 class); the supergroup
|
|
11107
|
+
// owner gets the boot/alerts lane, a DM gets a thread-less boot card.
|
|
11091
11108
|
|
|
11092
11109
|
// 2. Env var
|
|
11093
11110
|
const envChat = process.env.SUBAGENT_OWNER_CHAT_ID
|
|
11094
|
-
if (envChat) return { chatId: envChat, threadId: supergroupBootTopic, ackMsgId: undefined }
|
|
11111
|
+
if (envChat) return { chatId: envChat, threadId: topicForRecipient({ recipientChatId: envChat, resolvedTopic: supergroupBootTopic, supergroupChatId: bootSupergroup }), ackMsgId: undefined }
|
|
11095
11112
|
// 3. Most-recent inbound from history
|
|
11096
11113
|
if (HISTORY_ENABLED) {
|
|
11097
11114
|
try {
|
|
@@ -11099,7 +11116,7 @@ function resolveBootChatId(
|
|
|
11099
11116
|
const ownerChatId = access.allowFrom[0]
|
|
11100
11117
|
if (ownerChatId) {
|
|
11101
11118
|
const recent = queryHistory({ chat_id: ownerChatId, limit: 1 })
|
|
11102
|
-
if (recent.length > 0) return { chatId: ownerChatId, threadId: supergroupBootTopic, ackMsgId: undefined }
|
|
11119
|
+
if (recent.length > 0) return { chatId: ownerChatId, threadId: topicForRecipient({ recipientChatId: ownerChatId, resolvedTopic: supergroupBootTopic, supergroupChatId: bootSupergroup }), ackMsgId: undefined }
|
|
11103
11120
|
}
|
|
11104
11121
|
} catch {}
|
|
11105
11122
|
}
|
|
@@ -133,8 +133,9 @@ export function computeLabel(toolName, input) {
|
|
|
133
133
|
}
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
-
// MCP
|
|
136
|
+
// MCP tools.
|
|
137
137
|
if (typeof toolName === 'string' && toolName.startsWith('mcp__')) {
|
|
138
|
+
// Explicit labels / suppressions for the built-in servers.
|
|
138
139
|
switch (toolName) {
|
|
139
140
|
case 'mcp__switchroom-telegram__reply':
|
|
140
141
|
case 'mcp__switchroom-telegram__stream_reply':
|
|
@@ -150,15 +151,46 @@ export function computeLabel(toolName, input) {
|
|
|
150
151
|
return 'Searching memory'
|
|
151
152
|
case 'mcp__hindsight__retain':
|
|
152
153
|
return 'Saving memory'
|
|
153
|
-
// Explicit suppressions — return null so we don't emit a sidecar
|
|
154
|
-
// line at all. (Falling through to the default below produces the
|
|
155
|
-
// same effect, but listing these makes the intent obvious.)
|
|
154
|
+
// Explicit suppressions — return null so we don't emit a sidecar line.
|
|
156
155
|
case 'mcp__switchroom-telegram__send_typing':
|
|
157
156
|
case 'mcp__hindsight__sync_retain':
|
|
158
157
|
return null
|
|
159
158
|
}
|
|
160
|
-
//
|
|
161
|
-
|
|
159
|
+
// Generic fallback for ANY other MCP tool (operator-configured servers
|
|
160
|
+
// — perplexity, webkite, gdrive, notion, …). These previously returned
|
|
161
|
+
// null → invisible in the live activity feed, so a research turn driven
|
|
162
|
+
// entirely by MCP tools read as pure silence (only a typing dot + the
|
|
163
|
+
// 👀 reaction) — the "I can't see what it's doing" report. Mirror the
|
|
164
|
+
// gateway's describeToolUse: friendly per-server labels, else a
|
|
165
|
+
// model-authored field, else a humanized tool name. NEVER label
|
|
166
|
+
// switchroom-telegram surface/control tools (they ARE the conversation).
|
|
167
|
+
const m = /^mcp__(.+?)__(.+)$/.exec(toolName)
|
|
168
|
+
if (!m) return null
|
|
169
|
+
const server = m[1].toLowerCase()
|
|
170
|
+
const tool = m[2].toLowerCase()
|
|
171
|
+
if (server === 'switchroom-telegram') return null
|
|
172
|
+
if (server === 'hindsight') return 'Working with memory'
|
|
173
|
+
if (server === 'google-workspace' || server === 'claude_ai_google_calendar')
|
|
174
|
+
return 'Checking your calendar'
|
|
175
|
+
if (server === 'claude_ai_gmail') return 'Checking your email'
|
|
176
|
+
if (server === 'claude_ai_google_drive' || server === 'gdrive')
|
|
177
|
+
return 'Looking through your files'
|
|
178
|
+
if (server === 'notion' || server === 'claude_ai_notion') return 'Checking your notes'
|
|
179
|
+
if (server === 'perplexity') {
|
|
180
|
+
const q = clip(String(i.query ?? i.description ?? ''), 60).trim()
|
|
181
|
+
return q ? `Searching the web for ${q}` : 'Searching the web'
|
|
182
|
+
}
|
|
183
|
+
if (server === 'webkite') {
|
|
184
|
+
const u = clip(urlHostPath(i.url ?? ''), 60).trim()
|
|
185
|
+
return u ? `Reading ${u}` : 'Reading the web'
|
|
186
|
+
}
|
|
187
|
+
// Unknown MCP server: prefer a model-authored field, else humanized tool.
|
|
188
|
+
const desc =
|
|
189
|
+
clip(String(i.description ?? ''), 60).trim() ||
|
|
190
|
+
clip(String(i.query ?? ''), 50).trim() ||
|
|
191
|
+
clip(String(i.title ?? ''), 50).trim()
|
|
192
|
+
if (desc) return desc
|
|
193
|
+
return `Using ${tool.replace(/[-_]+/g, ' ')}`
|
|
162
194
|
}
|
|
163
195
|
|
|
164
196
|
return null
|