metheus-governance-mcp-cli 0.2.249 → 0.2.250
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/cli.mjs +75 -18
- package/lib/runner-delivery.mjs +17 -0
- package/lib/runner-helpers.mjs +90 -0
- package/lib/runner-orchestration.mjs +60 -8
- package/lib/runner-runtime.mjs +53 -1
- package/lib/selftest-runner-scenarios.mjs +157 -0
- package/lib/selftest-telegram-e2e.mjs +45 -11
- package/package.json +1 -1
package/cli.mjs
CHANGED
|
@@ -140,6 +140,7 @@ import {
|
|
|
140
140
|
buildRunnerRouteStateFromComment,
|
|
141
141
|
buildProcessableArchiveLogicalKey,
|
|
142
142
|
findEarlierProcessableArchiveDuplicate,
|
|
143
|
+
findRecentTelegramMessageEnvelope,
|
|
143
144
|
isInboundArchiveKind,
|
|
144
145
|
normalizeTelegramMessageEnvelope as normalizeRunnerTelegramMessageEnvelope,
|
|
145
146
|
normalizeArchiveCommentRecord,
|
|
@@ -1989,6 +1990,7 @@ function mergeRunnerStateRecords(preferred, fallback) {
|
|
|
1989
1990
|
last_followup_source_message_envelope: pickObjectField("last_followup_source_message_envelope"),
|
|
1990
1991
|
last_followup_last_reply_message_envelope: pickObjectField("last_followup_last_reply_message_envelope"),
|
|
1991
1992
|
last_followup_attempted_delivery_envelope: pickObjectField("last_followup_attempted_delivery_envelope"),
|
|
1993
|
+
recent_local_inbound_envelopes: pickObjectField("recent_local_inbound_envelopes"),
|
|
1992
1994
|
last_contract_validation_targets: pickArrayField("last_contract_validation_targets", normalizeTelegramMentionUsername),
|
|
1993
1995
|
last_normalized_execution_contract_targets: pickArrayField("last_normalized_execution_contract_targets", normalizeTelegramMentionUsername),
|
|
1994
1996
|
last_normalized_execution_next_responders: pickArrayField("last_normalized_execution_next_responders", normalizeTelegramMentionUsername),
|
|
@@ -2642,6 +2644,42 @@ function normalizeRunnerReplyChainContext(rawContext) {
|
|
|
2642
2644
|
return normalized;
|
|
2643
2645
|
}
|
|
2644
2646
|
|
|
2647
|
+
function findRunnerRouteLocalInboundEnvelope(routeStateRaw, parsedArchiveRaw) {
|
|
2648
|
+
const routeState = safeObject(routeStateRaw);
|
|
2649
|
+
const parsedArchive = safeObject(parsedArchiveRaw);
|
|
2650
|
+
const chatID = String(parsedArchive.chatID || parsedArchive.chatId || "").trim();
|
|
2651
|
+
const messageID = intFromRawAllowZero(parsedArchive.messageID, 0);
|
|
2652
|
+
if (!chatID || !(messageID > 0)) {
|
|
2653
|
+
return {};
|
|
2654
|
+
}
|
|
2655
|
+
return findRecentTelegramMessageEnvelope(routeState.recent_local_inbound_envelopes, {
|
|
2656
|
+
chatID,
|
|
2657
|
+
messageID,
|
|
2658
|
+
});
|
|
2659
|
+
}
|
|
2660
|
+
|
|
2661
|
+
function buildRunnerSourceMessageEnvelope({
|
|
2662
|
+
routeState = {},
|
|
2663
|
+
routeKey = "",
|
|
2664
|
+
normalizedRoute = null,
|
|
2665
|
+
parsedArchive = null,
|
|
2666
|
+
}) {
|
|
2667
|
+
const localEnvelope = findRunnerRouteLocalInboundEnvelope(routeState, parsedArchive);
|
|
2668
|
+
if (String(localEnvelope.source_origin || "").trim().toLowerCase() === "local_telegram_inbound") {
|
|
2669
|
+
return localEnvelope;
|
|
2670
|
+
}
|
|
2671
|
+
const fallbackBotSelector = normalizeTelegramMentionUsername(
|
|
2672
|
+
normalizedRoute?.botName
|
|
2673
|
+
|| normalizedRoute?.serverBotName
|
|
2674
|
+
|| "",
|
|
2675
|
+
);
|
|
2676
|
+
return buildRunnerTelegramMessageEnvelopeFromParsedArchive(parsedArchive, {
|
|
2677
|
+
source_origin: "archive_reconstructed",
|
|
2678
|
+
source_route_key: String(routeKey || "").trim(),
|
|
2679
|
+
source_bot_username: fallbackBotSelector,
|
|
2680
|
+
});
|
|
2681
|
+
}
|
|
2682
|
+
|
|
2645
2683
|
function normalizeBotRunnerRequests(rawRequests, nowMs = Date.now()) {
|
|
2646
2684
|
const normalized = {};
|
|
2647
2685
|
for (const [requestKeyRaw, entryRaw] of Object.entries(safeObject(rawRequests))) {
|
|
@@ -2676,6 +2714,7 @@ function normalizeBotRunnerRequests(rawRequests, nowMs = Date.now()) {
|
|
|
2676
2714
|
body: entry.source_message_body || entry.sourceMessageBody,
|
|
2677
2715
|
sender: "human",
|
|
2678
2716
|
sender_is_bot: false,
|
|
2717
|
+
source_origin: "archive_reconstructed",
|
|
2679
2718
|
}
|
|
2680
2719
|
: {}),
|
|
2681
2720
|
),
|
|
@@ -4408,9 +4447,10 @@ async function claimRunnerRequestForHumanComment({
|
|
|
4408
4447
|
reason: "non_human_comment_cannot_create_request",
|
|
4409
4448
|
};
|
|
4410
4449
|
}
|
|
4411
|
-
const currentState = loadBotRunnerState();
|
|
4412
|
-
const
|
|
4413
|
-
|
|
4450
|
+
const currentState = loadBotRunnerState();
|
|
4451
|
+
const currentRouteState = safeObject(safeObject(currentState.routes)[String(routeKey || "").trim()]);
|
|
4452
|
+
const replyChainResolution = await resolveRunnerReplyChainConversationContextWithServerFallback({
|
|
4453
|
+
state: currentState,
|
|
4414
4454
|
normalizedRoute,
|
|
4415
4455
|
selectedRecord,
|
|
4416
4456
|
runtime,
|
|
@@ -4530,14 +4570,19 @@ async function claimRunnerRequestForHumanComment({
|
|
|
4530
4570
|
};
|
|
4531
4571
|
}
|
|
4532
4572
|
const nowISO = new Date().toISOString();
|
|
4533
|
-
const { requests: nextRequests, request } = upsertRunnerRequest(stateForClaim, requestKey, {
|
|
4573
|
+
const { requests: nextRequests, request } = upsertRunnerRequest(stateForClaim, requestKey, {
|
|
4534
4574
|
project_id: String(normalizedRoute?.projectID || "").trim(),
|
|
4535
4575
|
provider: String(normalizedRoute?.provider || "").trim(),
|
|
4536
4576
|
chat_id: String(parsed.chatID || parsed.chatId || "").trim(),
|
|
4537
4577
|
source_message_id: intFromRawAllowZero(parsed.messageID, 0) || undefined,
|
|
4538
4578
|
source_message_thread_id: intFromRawAllowZero(parsed.messageThreadID, 0) || undefined,
|
|
4539
4579
|
source_message_body: String(parsed.body || "").trim(),
|
|
4540
|
-
source_message_envelope:
|
|
4580
|
+
source_message_envelope: buildRunnerSourceMessageEnvelope({
|
|
4581
|
+
routeState: currentRouteState,
|
|
4582
|
+
routeKey,
|
|
4583
|
+
normalizedRoute,
|
|
4584
|
+
parsedArchive: parsed,
|
|
4585
|
+
}),
|
|
4541
4586
|
root_comment_id: String(selectedRecord?.id || "").trim(),
|
|
4542
4587
|
root_comment_kind: commentKind,
|
|
4543
4588
|
conversation_id: resolvedConversationID,
|
|
@@ -7552,11 +7597,11 @@ function parseArchivedChatComment(rawBody) {
|
|
|
7552
7597
|
.filter(Boolean),
|
|
7553
7598
|
}
|
|
7554
7599
|
: null;
|
|
7555
|
-
return {
|
|
7556
|
-
kind,
|
|
7557
|
-
header,
|
|
7558
|
-
metadata,
|
|
7559
|
-
body,
|
|
7600
|
+
return {
|
|
7601
|
+
kind,
|
|
7602
|
+
header,
|
|
7603
|
+
metadata,
|
|
7604
|
+
body,
|
|
7560
7605
|
chatID: String(metadata.chat_id || "").trim(),
|
|
7561
7606
|
chatType: String(metadata.chat_type || "").trim().toLowerCase(),
|
|
7562
7607
|
messageID: intFromRawAllowZero(metadata.message_id, 0),
|
|
@@ -7569,8 +7614,11 @@ function parseArchivedChatComment(rawBody) {
|
|
|
7569
7614
|
.split(",")
|
|
7570
7615
|
.map((value) => normalizeTelegramMentionUsername(value))
|
|
7571
7616
|
.filter(Boolean),
|
|
7572
|
-
occurredAt: String(metadata.occurred_at || "").trim(),
|
|
7573
|
-
|
|
7617
|
+
occurredAt: String(metadata.occurred_at || "").trim(),
|
|
7618
|
+
sourceOrigin: String(metadata.source_origin || "").trim().toLowerCase(),
|
|
7619
|
+
sourceRouteKey: String(metadata.source_route_key || "").trim(),
|
|
7620
|
+
sourceBotUsername: normalizeTelegramMentionUsername(metadata.source_bot_username || ""),
|
|
7621
|
+
replyToMessageID: intFromRawAllowZero(metadata.reply_to_message_id, 0),
|
|
7574
7622
|
replyToSender: String(metadata.reply_to_sender || "").trim(),
|
|
7575
7623
|
replyToUsername: String(metadata.reply_to_telegram_username || "").trim(),
|
|
7576
7624
|
replyToSenderIsBot: boolFromRaw(metadata.reply_to_sender_is_bot, false),
|
|
@@ -7886,18 +7934,27 @@ function buildArchivedInboundMessageKey(chatID, messageID) {
|
|
|
7886
7934
|
return `${String(chatID || "").trim()}:${intFromRawAllowZero(messageID, 0)}`;
|
|
7887
7935
|
}
|
|
7888
7936
|
|
|
7889
|
-
function formatTelegramInboundArchiveComment(normalized) {
|
|
7890
|
-
const headerLines = [
|
|
7937
|
+
function formatTelegramInboundArchiveComment(normalized) {
|
|
7938
|
+
const headerLines = [
|
|
7891
7939
|
`[Telegram ${normalized.eventName === "telegram.message.updated" ? "edited" : "message"}]`,
|
|
7892
7940
|
`chat_id: ${normalized.chatID || "<missing>"}`,
|
|
7893
7941
|
`chat_type: ${normalized.chatType || "unknown"}`,
|
|
7894
7942
|
`message_id: ${normalized.messageID || "<missing>"}`,
|
|
7895
7943
|
`occurred_at: ${normalized.occurredAt || new Date().toISOString()}`,
|
|
7896
7944
|
`sender_id: ${normalized.fromID || "<missing>"}`,
|
|
7897
|
-
`sender: ${normalized.fromName || normalized.fromUsername || normalized.fromID || "unknown"}`,
|
|
7898
|
-
`sender_is_bot: ${normalized.fromIsBot ? "true" : "false"}`,
|
|
7899
|
-
];
|
|
7900
|
-
if (normalized.
|
|
7945
|
+
`sender: ${normalized.fromName || normalized.fromUsername || normalized.fromID || "unknown"}`,
|
|
7946
|
+
`sender_is_bot: ${normalized.fromIsBot ? "true" : "false"}`,
|
|
7947
|
+
];
|
|
7948
|
+
if (String(normalized.sourceOrigin || "").trim()) {
|
|
7949
|
+
headerLines.push(`source_origin: ${String(normalized.sourceOrigin || "").trim()}`);
|
|
7950
|
+
}
|
|
7951
|
+
if (String(normalized.sourceRouteKey || "").trim()) {
|
|
7952
|
+
headerLines.push(`source_route_key: ${String(normalized.sourceRouteKey || "").trim()}`);
|
|
7953
|
+
}
|
|
7954
|
+
if (String(normalized.sourceBotUsername || "").trim()) {
|
|
7955
|
+
headerLines.push(`source_bot_username: @${String(normalized.sourceBotUsername || "").trim().replace(/^@+/, "")}`);
|
|
7956
|
+
}
|
|
7957
|
+
if (normalized.fromUsername) {
|
|
7901
7958
|
headerLines.push(`telegram_username: @${normalized.fromUsername.replace(/^@+/, "")}`);
|
|
7902
7959
|
}
|
|
7903
7960
|
if (normalized.mentionUsernames.length > 0) {
|
package/lib/runner-delivery.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { deliverLocalProviderMessage } from "./provider-local-transport.mjs";
|
|
2
2
|
import { normalizeBotProviderName } from "./provider-support.mjs";
|
|
3
|
+
import { normalizeTelegramMessageEnvelope } from "./runner-helpers.mjs";
|
|
3
4
|
|
|
4
5
|
function safeObject(value) {
|
|
5
6
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
@@ -71,6 +72,12 @@ function normalizeArchiveCommentRecord(rawComment, parseArchivedChatComment) {
|
|
|
71
72
|
};
|
|
72
73
|
}
|
|
73
74
|
|
|
75
|
+
function telegramReplySourceEnvelopeIsLocal(rawEnvelope) {
|
|
76
|
+
const envelope = normalizeTelegramMessageEnvelope(rawEnvelope);
|
|
77
|
+
return String(envelope.source_origin || "").trim().toLowerCase() === "local_telegram_inbound"
|
|
78
|
+
&& intFromRawAllowZero(envelope.message_id, 0) > 0;
|
|
79
|
+
}
|
|
80
|
+
|
|
74
81
|
function normalizeExecutionContractForArchive(rawContract) {
|
|
75
82
|
const contract = safeObject(rawContract);
|
|
76
83
|
if (!Object.keys(contract).length) {
|
|
@@ -274,6 +281,7 @@ export async function performLocalBotDelivery({
|
|
|
274
281
|
disableWebPagePreview,
|
|
275
282
|
messageThreadID,
|
|
276
283
|
replyToMessageID,
|
|
284
|
+
sourceMessageEnvelope = {},
|
|
277
285
|
archiveReplies = true,
|
|
278
286
|
archiveDedupeOutbound = true,
|
|
279
287
|
archiveThreadID = "",
|
|
@@ -295,6 +303,7 @@ export async function performLocalBotDelivery({
|
|
|
295
303
|
const parseArchivedChatComment = requireDependency(deps, "parseArchivedChatComment");
|
|
296
304
|
|
|
297
305
|
const normalizedProvider = normalizeBotProviderName(provider, "telegram");
|
|
306
|
+
const normalizedSourceMessageEnvelope = normalizeTelegramMessageEnvelope(sourceMessageEnvelope);
|
|
298
307
|
const destinations = await listProjectChatDestinations({
|
|
299
308
|
siteBaseURL,
|
|
300
309
|
projectID,
|
|
@@ -332,6 +341,14 @@ export async function performLocalBotDelivery({
|
|
|
332
341
|
replySupported: normalizedProvider === "telegram",
|
|
333
342
|
};
|
|
334
343
|
} else {
|
|
344
|
+
if (
|
|
345
|
+
normalizedProvider === "telegram"
|
|
346
|
+
&& intFromRawAllowZero(replyToMessageID, 0) > 0
|
|
347
|
+
&& !telegramReplySourceEnvelopeIsLocal(normalizedSourceMessageEnvelope)
|
|
348
|
+
) {
|
|
349
|
+
const origin = String(normalizedSourceMessageEnvelope.source_origin || "unknown").trim() || "unknown";
|
|
350
|
+
throw new Error(`telegram reply anchor is not local to this route (${origin})`);
|
|
351
|
+
}
|
|
335
352
|
delivery = await deliverLocalProviderMessage({
|
|
336
353
|
provider: normalizedProvider,
|
|
337
354
|
token: providerEnv.token,
|
package/lib/runner-helpers.mjs
CHANGED
|
@@ -68,6 +68,21 @@ export function normalizeTelegramMessageEnvelope(rawEnvelope) {
|
|
|
68
68
|
|| rawSenderIsBot === "1"
|
|
69
69
|
|| kind === "bot_reply";
|
|
70
70
|
const body = String(envelope.body || envelope.text || "").trim();
|
|
71
|
+
const sourceOrigin = String(
|
|
72
|
+
envelope.source_origin
|
|
73
|
+
|| envelope.sourceOrigin
|
|
74
|
+
|| "",
|
|
75
|
+
).trim().toLowerCase();
|
|
76
|
+
const sourceRouteKey = String(
|
|
77
|
+
envelope.source_route_key
|
|
78
|
+
|| envelope.sourceRouteKey
|
|
79
|
+
|| "",
|
|
80
|
+
).trim();
|
|
81
|
+
const sourceBotUsername = normalizeMentionSelector(
|
|
82
|
+
envelope.source_bot_username
|
|
83
|
+
|| envelope.sourceBotUsername
|
|
84
|
+
|| "",
|
|
85
|
+
);
|
|
71
86
|
if (
|
|
72
87
|
!chatID
|
|
73
88
|
&& !(messageID > 0)
|
|
@@ -77,6 +92,9 @@ export function normalizeTelegramMessageEnvelope(rawEnvelope) {
|
|
|
77
92
|
&& !sender
|
|
78
93
|
&& !senderUsername
|
|
79
94
|
&& !body
|
|
95
|
+
&& !sourceOrigin
|
|
96
|
+
&& !sourceRouteKey
|
|
97
|
+
&& !sourceBotUsername
|
|
80
98
|
) {
|
|
81
99
|
return {};
|
|
82
100
|
}
|
|
@@ -90,6 +108,9 @@ export function normalizeTelegramMessageEnvelope(rawEnvelope) {
|
|
|
90
108
|
...(senderUsername ? { sender_username: senderUsername } : {}),
|
|
91
109
|
sender_is_bot: senderIsBot === true,
|
|
92
110
|
...(body ? { body } : {}),
|
|
111
|
+
...(sourceOrigin ? { source_origin: sourceOrigin } : {}),
|
|
112
|
+
...(sourceRouteKey ? { source_route_key: sourceRouteKey } : {}),
|
|
113
|
+
...(sourceBotUsername ? { source_bot_username: sourceBotUsername } : {}),
|
|
93
114
|
};
|
|
94
115
|
}
|
|
95
116
|
|
|
@@ -119,6 +140,21 @@ export function buildTelegramMessageEnvelopeFromParsedArchive(parsedArchiveRaw,
|
|
|
119
140
|
]),
|
|
120
141
|
sender_is_bot: overrides.sender_is_bot ?? parsedArchive.senderIsBot,
|
|
121
142
|
body: firstNonEmptyString([overrides.body, parsedArchive.body]),
|
|
143
|
+
source_origin: firstNonEmptyString([
|
|
144
|
+
overrides.source_origin,
|
|
145
|
+
parsedArchive.sourceOrigin,
|
|
146
|
+
parsedArchive.metadata?.source_origin,
|
|
147
|
+
]),
|
|
148
|
+
source_route_key: firstNonEmptyString([
|
|
149
|
+
overrides.source_route_key,
|
|
150
|
+
parsedArchive.sourceRouteKey,
|
|
151
|
+
parsedArchive.metadata?.source_route_key,
|
|
152
|
+
]),
|
|
153
|
+
source_bot_username: firstNonEmptyString([
|
|
154
|
+
overrides.source_bot_username,
|
|
155
|
+
parsedArchive.sourceBotUsername,
|
|
156
|
+
parsedArchive.metadata?.source_bot_username,
|
|
157
|
+
]),
|
|
122
158
|
});
|
|
123
159
|
}
|
|
124
160
|
|
|
@@ -155,6 +191,60 @@ export function buildTelegramBotReplyEnvelope({
|
|
|
155
191
|
});
|
|
156
192
|
}
|
|
157
193
|
|
|
194
|
+
export function buildTelegramMessageEnvelopeKey(rawEnvelopeOrChatID, rawMessageID = undefined) {
|
|
195
|
+
const envelope = rawMessageID === undefined
|
|
196
|
+
? normalizeTelegramMessageEnvelope(rawEnvelopeOrChatID)
|
|
197
|
+
: normalizeTelegramMessageEnvelope({
|
|
198
|
+
chat_id: rawEnvelopeOrChatID,
|
|
199
|
+
message_id: rawMessageID,
|
|
200
|
+
});
|
|
201
|
+
const chatID = String(envelope.chat_id || "").trim();
|
|
202
|
+
const messageID = intFromRawAllowZero(envelope.message_id, 0);
|
|
203
|
+
if (!chatID || !(messageID > 0)) {
|
|
204
|
+
return "";
|
|
205
|
+
}
|
|
206
|
+
return `${chatID}:${messageID}`;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export function findRecentTelegramMessageEnvelope(rawMap, { chatID = "", messageID = 0 } = {}) {
|
|
210
|
+
const envelopeKey = buildTelegramMessageEnvelopeKey(chatID, messageID);
|
|
211
|
+
if (!envelopeKey) {
|
|
212
|
+
return {};
|
|
213
|
+
}
|
|
214
|
+
return normalizeTelegramMessageEnvelope(safeObject(safeObject(rawMap)[envelopeKey]));
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
export function mergeRecentTelegramMessageEnvelopes(rawMap, incomingEnvelopes, limit = 128) {
|
|
218
|
+
const merged = new Map();
|
|
219
|
+
for (const [key, value] of Object.entries(safeObject(rawMap))) {
|
|
220
|
+
const normalized = normalizeTelegramMessageEnvelope(value);
|
|
221
|
+
const normalizedKey = buildTelegramMessageEnvelopeKey(normalized) || String(key || "").trim();
|
|
222
|
+
if (!normalizedKey || !Object.keys(normalized).length) {
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
merged.set(normalizedKey, normalized);
|
|
226
|
+
}
|
|
227
|
+
for (const rawEnvelope of ensureArray(incomingEnvelopes)) {
|
|
228
|
+
const normalized = normalizeTelegramMessageEnvelope(rawEnvelope);
|
|
229
|
+
const normalizedKey = buildTelegramMessageEnvelopeKey(normalized);
|
|
230
|
+
if (!normalizedKey || !Object.keys(normalized).length) {
|
|
231
|
+
continue;
|
|
232
|
+
}
|
|
233
|
+
if (merged.has(normalizedKey)) {
|
|
234
|
+
merged.delete(normalizedKey);
|
|
235
|
+
}
|
|
236
|
+
merged.set(normalizedKey, normalized);
|
|
237
|
+
}
|
|
238
|
+
while (merged.size > Math.max(1, intFromRawAllowZero(limit, 128))) {
|
|
239
|
+
const oldestKey = merged.keys().next().value;
|
|
240
|
+
if (!oldestKey) {
|
|
241
|
+
break;
|
|
242
|
+
}
|
|
243
|
+
merged.delete(oldestKey);
|
|
244
|
+
}
|
|
245
|
+
return Object.fromEntries(merged.entries());
|
|
246
|
+
}
|
|
247
|
+
|
|
158
248
|
function normalizePendingSelectionOptions(rawOptions) {
|
|
159
249
|
const options = safeObject(rawOptions);
|
|
160
250
|
const maxPendingAgeMs = intFromRawAllowZero(options.maxPendingAgeMs, 0);
|
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
buildRunnerRouteStateFromComment,
|
|
8
8
|
compareArchiveCommentRecords,
|
|
9
9
|
dedupeProcessableArchiveComments,
|
|
10
|
+
findRecentTelegramMessageEnvelope,
|
|
10
11
|
isInboundArchiveKind,
|
|
11
12
|
normalizeTelegramMessageEnvelope,
|
|
12
13
|
selectPendingArchiveComments,
|
|
@@ -376,11 +377,54 @@ function normalizeBoundaryViolations(rawViolations) {
|
|
|
376
377
|
.filter(Boolean);
|
|
377
378
|
}
|
|
378
379
|
|
|
379
|
-
function normalizeMentionSelector(value) {
|
|
380
|
-
return String(value || "").trim().replace(/^@+/, "").toLowerCase();
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
function
|
|
380
|
+
function normalizeMentionSelector(value) {
|
|
381
|
+
return String(value || "").trim().replace(/^@+/, "").toLowerCase();
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
function resolveRunnerDeliverySourceMessageEnvelope({
|
|
385
|
+
routeState,
|
|
386
|
+
persistedRequest,
|
|
387
|
+
selectedRecord,
|
|
388
|
+
routeKey,
|
|
389
|
+
currentBotSelector,
|
|
390
|
+
}) {
|
|
391
|
+
const archiveEnvelope = buildTelegramMessageEnvelopeFromParsedArchive(selectedRecord?.parsedArchive, {
|
|
392
|
+
source_origin: "archive_reconstructed",
|
|
393
|
+
source_route_key: String(routeKey || "").trim(),
|
|
394
|
+
source_bot_username: currentBotSelector,
|
|
395
|
+
});
|
|
396
|
+
const archiveChatID = String(archiveEnvelope.chat_id || "").trim();
|
|
397
|
+
const archiveMessageID = intFromRawAllowZero(archiveEnvelope.message_id, 0);
|
|
398
|
+
const routeLocalEnvelope = findRecentTelegramMessageEnvelope(
|
|
399
|
+
safeObject(routeState).recent_local_inbound_envelopes,
|
|
400
|
+
{
|
|
401
|
+
chatID: archiveChatID,
|
|
402
|
+
messageID: archiveMessageID,
|
|
403
|
+
},
|
|
404
|
+
);
|
|
405
|
+
if (String(routeLocalEnvelope.source_origin || "").trim().toLowerCase() === "local_telegram_inbound") {
|
|
406
|
+
return routeLocalEnvelope;
|
|
407
|
+
}
|
|
408
|
+
const persistedSourceEnvelope = normalizeTelegramMessageEnvelope(
|
|
409
|
+
safeObject(persistedRequest).source_message_envelope
|
|
410
|
+
|| safeObject(persistedRequest).sourceMessageEnvelope,
|
|
411
|
+
);
|
|
412
|
+
const persistedOrigin = String(persistedSourceEnvelope.source_origin || "").trim().toLowerCase();
|
|
413
|
+
const persistedChatID = String(persistedSourceEnvelope.chat_id || "").trim();
|
|
414
|
+
const persistedMessageID = intFromRawAllowZero(persistedSourceEnvelope.message_id, 0);
|
|
415
|
+
if (
|
|
416
|
+
persistedOrigin === "local_telegram_inbound"
|
|
417
|
+
&& archiveChatID
|
|
418
|
+
&& archiveChatID === persistedChatID
|
|
419
|
+
&& archiveMessageID > 0
|
|
420
|
+
&& archiveMessageID === persistedMessageID
|
|
421
|
+
) {
|
|
422
|
+
return persistedSourceEnvelope;
|
|
423
|
+
}
|
|
424
|
+
return archiveEnvelope;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
function escapeRegExp(text) {
|
|
384
428
|
return String(text || "").replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
385
429
|
}
|
|
386
430
|
|
|
@@ -4720,10 +4764,18 @@ export async function processRunnerSelectedRecord({
|
|
|
4720
4764
|
safeObject(persistedHumanIntentRequest).reply_chain_context
|
|
4721
4765
|
|| safeObject(persistedHumanIntentRequest).replyChainContext,
|
|
4722
4766
|
);
|
|
4723
|
-
const
|
|
4767
|
+
const currentBotSelector = normalizeMentionSelector(bot?.username || bot?.name);
|
|
4768
|
+
const sourceMessageEnvelope = resolveRunnerDeliverySourceMessageEnvelope({
|
|
4769
|
+
routeState,
|
|
4770
|
+
persistedRequest: persistedHumanIntentRequest,
|
|
4771
|
+
selectedRecord,
|
|
4772
|
+
routeKey,
|
|
4773
|
+
currentBotSelector,
|
|
4774
|
+
});
|
|
4724
4775
|
const replyMessageThreadID = intFromRawAllowZero(sourceMessageEnvelope.message_thread_id, 0);
|
|
4725
4776
|
const replyToMessageID = intFromRawAllowZero(sourceMessageEnvelope.message_id, 0);
|
|
4726
|
-
const replyAnchorSource =
|
|
4777
|
+
const replyAnchorSource = String(sourceMessageEnvelope.source_origin || "").trim()
|
|
4778
|
+
|| (replyToMessageID > 0 ? "source_message_envelope" : "");
|
|
4727
4779
|
const normalizedPrecomputedHumanIntentContext = safeObject(precomputedHumanIntentContext);
|
|
4728
4780
|
const validateWorkspaceArtifacts = typeof executionDeps.validateWorkspaceArtifacts === "function"
|
|
4729
4781
|
? executionDeps.validateWorkspaceArtifacts
|
|
@@ -4734,7 +4786,6 @@ export async function processRunnerSelectedRecord({
|
|
|
4734
4786
|
const resolveInformationalQueryReply = typeof executionDeps.resolveInformationalQueryReply === "function"
|
|
4735
4787
|
? executionDeps.resolveInformationalQueryReply
|
|
4736
4788
|
: null;
|
|
4737
|
-
const currentBotSelector = normalizeMentionSelector(bot?.username || bot?.name);
|
|
4738
4789
|
const triggerDecision = safeObject(precomputedTriggerDecision);
|
|
4739
4790
|
const effectiveTriggerDecision = typeof triggerDecision.shouldRespond === "boolean"
|
|
4740
4791
|
? triggerDecision
|
|
@@ -5592,6 +5643,7 @@ export async function processRunnerSelectedRecord({
|
|
|
5592
5643
|
disableWebPagePreview: true,
|
|
5593
5644
|
messageThreadID: replyMessageThreadID,
|
|
5594
5645
|
replyToMessageID,
|
|
5646
|
+
sourceMessageEnvelope: sourceMessageEnvelope,
|
|
5595
5647
|
archiveReplies: normalizedRoute.archivePolicy.mirrorReplies,
|
|
5596
5648
|
archiveDedupeOutbound: normalizedRoute.archivePolicy.dedupeOutbound,
|
|
5597
5649
|
archiveThreadID: archiveThread.threadID,
|
package/lib/runner-runtime.mjs
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import {
|
|
2
|
+
mergeRecentTelegramMessageEnvelopes,
|
|
3
|
+
normalizeTelegramMessageEnvelope,
|
|
4
|
+
} from "./runner-helpers.mjs";
|
|
5
|
+
|
|
1
6
|
function safeObject(value) {
|
|
2
7
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
3
8
|
return {};
|
|
@@ -198,6 +203,40 @@ function mergeRunnerSharedInboxUpdates(existingUpdates, incomingUpdates) {
|
|
|
198
203
|
.slice(-500);
|
|
199
204
|
}
|
|
200
205
|
|
|
206
|
+
const RUNNER_RECENT_LOCAL_INBOUND_ENVELOPE_LIMIT = 200;
|
|
207
|
+
|
|
208
|
+
function buildRunnerRecentLocalInboundEnvelopes(routeStateRaw, updates, routeKey, bot, destination) {
|
|
209
|
+
const routeState = safeObject(routeStateRaw);
|
|
210
|
+
const currentBotSelector = normalizeMentionSelector(
|
|
211
|
+
bot?.username
|
|
212
|
+
|| bot?.name
|
|
213
|
+
|| "",
|
|
214
|
+
);
|
|
215
|
+
const relevantEnvelopes = ensureArray(updates)
|
|
216
|
+
.filter((update) => String(update.chatID || "").trim() === String(destination?.chatID || "").trim())
|
|
217
|
+
.filter((update) => String(update.text || "").trim())
|
|
218
|
+
.map((update) => normalizeTelegramMessageEnvelope({
|
|
219
|
+
chat_id: update.chatID,
|
|
220
|
+
message_id: update.messageID,
|
|
221
|
+
message_thread_id: update.messageThreadID,
|
|
222
|
+
reply_to_message_id: update.replyToMessageID,
|
|
223
|
+
kind: update.fromIsBot ? "bot_reply" : "telegram_message",
|
|
224
|
+
sender: update.fromName,
|
|
225
|
+
sender_username: update.fromUsername,
|
|
226
|
+
sender_is_bot: update.fromIsBot === true,
|
|
227
|
+
body: update.text,
|
|
228
|
+
source_origin: "local_telegram_inbound",
|
|
229
|
+
source_route_key: String(routeKey || "").trim(),
|
|
230
|
+
source_bot_username: currentBotSelector,
|
|
231
|
+
}))
|
|
232
|
+
.filter((envelope) => Object.keys(envelope).length > 0);
|
|
233
|
+
return mergeRecentTelegramMessageEnvelopes(
|
|
234
|
+
routeState.recent_local_inbound_envelopes,
|
|
235
|
+
relevantEnvelopes,
|
|
236
|
+
RUNNER_RECENT_LOCAL_INBOUND_ENVELOPE_LIMIT,
|
|
237
|
+
);
|
|
238
|
+
}
|
|
239
|
+
|
|
201
240
|
const RUNNER_INBOUND_ARCHIVE_RESERVATION_TTL_MS = 10 * 60 * 1000;
|
|
202
241
|
const runnerInboundArchiveReservations = new Map();
|
|
203
242
|
|
|
@@ -470,6 +509,13 @@ export async function archiveLocalTelegramMessagesForRoute({
|
|
|
470
509
|
.sort((left, right) => intFromRawAllowZero(left.updateID, 0) - intFromRawAllowZero(right.updateID, 0));
|
|
471
510
|
let handledUpdateID = lastUpdateID;
|
|
472
511
|
const mergedSharedUpdates = mergeRunnerSharedInboxUpdates(sharedInbox.updates, updates);
|
|
512
|
+
const recentLocalInboundEnvelopes = buildRunnerRecentLocalInboundEnvelopes(
|
|
513
|
+
routeState,
|
|
514
|
+
mergedSharedUpdates,
|
|
515
|
+
routeKey,
|
|
516
|
+
bot,
|
|
517
|
+
destination,
|
|
518
|
+
);
|
|
473
519
|
|
|
474
520
|
const persistPollingProgress = (remainingSharedUpdates = []) => {
|
|
475
521
|
if (sharedInboxKey && saveBotRunnerState) {
|
|
@@ -489,6 +535,7 @@ export async function archiveLocalTelegramMessagesForRoute({
|
|
|
489
535
|
local_telegram_polling_ready: true,
|
|
490
536
|
last_provider_update_id: handledUpdateID,
|
|
491
537
|
last_local_poll_at: new Date().toISOString(),
|
|
538
|
+
recent_local_inbound_envelopes: recentLocalInboundEnvelopes,
|
|
492
539
|
});
|
|
493
540
|
};
|
|
494
541
|
|
|
@@ -564,7 +611,12 @@ export async function archiveLocalTelegramMessagesForRoute({
|
|
|
564
611
|
timeoutSeconds: runtime.timeoutSeconds,
|
|
565
612
|
threadID: archiveThread.threadID,
|
|
566
613
|
actorUserID: runtime.actor.user_id,
|
|
567
|
-
body: formatTelegramInboundArchiveComment(
|
|
614
|
+
body: formatTelegramInboundArchiveComment({
|
|
615
|
+
...update,
|
|
616
|
+
sourceOrigin: "local_telegram_inbound",
|
|
617
|
+
sourceRouteKey: String(routeKey || "").trim(),
|
|
618
|
+
sourceBotUsername: normalizeMentionSelector(bot?.username || bot?.name),
|
|
619
|
+
}),
|
|
568
620
|
});
|
|
569
621
|
} catch (err) {
|
|
570
622
|
releaseRunnerInboundArchiveMessageReservation(reservation.reservationKey);
|
|
@@ -12829,6 +12829,163 @@ export async function runSelftestRunnerScenarios(push, deps) {
|
|
|
12829
12829
|
push("runner_delivery_failure_after_generation_records_ai_state_without_execution_error", false, String(err?.message || err));
|
|
12830
12830
|
}
|
|
12831
12831
|
|
|
12832
|
+
try {
|
|
12833
|
+
let capturedReplyToMessageID = 0;
|
|
12834
|
+
let capturedMessageThreadID = 0;
|
|
12835
|
+
let capturedSourceMessageEnvelope = {};
|
|
12836
|
+
const processed = await processRunnerSelectedRecord({
|
|
12837
|
+
routeKey: "delivery-prefers-route-local-inbound-envelope-key",
|
|
12838
|
+
normalizedRoute: normalizeRunnerRoute({
|
|
12839
|
+
name: "telegram-monitor-delivery-prefers-route-local-inbound-envelope",
|
|
12840
|
+
project_id: selftestProjectID,
|
|
12841
|
+
provider: "telegram",
|
|
12842
|
+
role: "monitor",
|
|
12843
|
+
role_profile: "monitor",
|
|
12844
|
+
destination_id: "dest-1",
|
|
12845
|
+
destination_label: "Main Room",
|
|
12846
|
+
server_bot_name: "RyoAI_bot",
|
|
12847
|
+
server_bot_id: "bot-1",
|
|
12848
|
+
trigger_policy: {
|
|
12849
|
+
mentions_only: true,
|
|
12850
|
+
direct_messages: true,
|
|
12851
|
+
reply_to_bot_messages: true,
|
|
12852
|
+
},
|
|
12853
|
+
archive_policy: {
|
|
12854
|
+
mirror_replies: true,
|
|
12855
|
+
dedupe_inbound: true,
|
|
12856
|
+
dedupe_outbound: true,
|
|
12857
|
+
skip_bot_messages: true,
|
|
12858
|
+
},
|
|
12859
|
+
dry_run_delivery: false,
|
|
12860
|
+
}),
|
|
12861
|
+
routeState: {
|
|
12862
|
+
recent_local_inbound_envelopes: {
|
|
12863
|
+
"-100123:128": {
|
|
12864
|
+
chat_id: "-100123",
|
|
12865
|
+
message_id: 128,
|
|
12866
|
+
message_thread_id: 912,
|
|
12867
|
+
reply_to_message_id: 127,
|
|
12868
|
+
kind: "telegram_message",
|
|
12869
|
+
sender: "human",
|
|
12870
|
+
sender_is_bot: false,
|
|
12871
|
+
body: "@RyoAI_bot hi",
|
|
12872
|
+
source_origin: "local_telegram_inbound",
|
|
12873
|
+
source_route_key: "delivery-prefers-route-local-inbound-envelope-key",
|
|
12874
|
+
source_bot_username: "ryoai_bot",
|
|
12875
|
+
},
|
|
12876
|
+
},
|
|
12877
|
+
},
|
|
12878
|
+
selectedRecord: {
|
|
12879
|
+
id: "comment-delivery-prefers-route-local-inbound-envelope",
|
|
12880
|
+
createdAt: "2026-03-27T00:00:00.000Z",
|
|
12881
|
+
parsedArchive: {
|
|
12882
|
+
kind: "telegram_message",
|
|
12883
|
+
chatID: "-100123",
|
|
12884
|
+
chatType: "supergroup",
|
|
12885
|
+
body: "@RyoAI_bot hi",
|
|
12886
|
+
messageID: 128,
|
|
12887
|
+
messageThreadID: 912,
|
|
12888
|
+
replyToMessageID: 127,
|
|
12889
|
+
sender: "human",
|
|
12890
|
+
senderIsBot: false,
|
|
12891
|
+
mentionUsernames: ["ryoai_bot"],
|
|
12892
|
+
},
|
|
12893
|
+
},
|
|
12894
|
+
pendingOrdered: [],
|
|
12895
|
+
bot: {
|
|
12896
|
+
id: "bot-1",
|
|
12897
|
+
name: "RyoAI_bot",
|
|
12898
|
+
username: "RyoAI_bot",
|
|
12899
|
+
role: "monitor",
|
|
12900
|
+
provider: "telegram",
|
|
12901
|
+
},
|
|
12902
|
+
destination: {
|
|
12903
|
+
id: "dest-1",
|
|
12904
|
+
label: "Main Room",
|
|
12905
|
+
provider: "telegram",
|
|
12906
|
+
chatID: "-100123",
|
|
12907
|
+
},
|
|
12908
|
+
archiveThread: {
|
|
12909
|
+
threadID: "thread-1",
|
|
12910
|
+
workItemID: "work-item-1",
|
|
12911
|
+
},
|
|
12912
|
+
executionPlan: {
|
|
12913
|
+
mode: "role_profile",
|
|
12914
|
+
roleProfileName: "monitor",
|
|
12915
|
+
roleProfile: {
|
|
12916
|
+
client: "sample",
|
|
12917
|
+
model: "",
|
|
12918
|
+
permissionMode: "read_only",
|
|
12919
|
+
reasoningEffort: "low",
|
|
12920
|
+
},
|
|
12921
|
+
workspaceDir: "",
|
|
12922
|
+
workspaceSource: "selftest",
|
|
12923
|
+
usedCommandFallback: false,
|
|
12924
|
+
},
|
|
12925
|
+
runtime: {
|
|
12926
|
+
baseURL: "https://example.test",
|
|
12927
|
+
token: "selftest-token",
|
|
12928
|
+
timeoutSeconds: 30,
|
|
12929
|
+
actor: { user_id: "user-1" },
|
|
12930
|
+
},
|
|
12931
|
+
deps: {
|
|
12932
|
+
saveRunnerRouteState: () => {},
|
|
12933
|
+
startRunnerTypingHeartbeat: () => ({ async stop() {} }),
|
|
12934
|
+
runRunnerAIExecution: async () => ({
|
|
12935
|
+
skip: false,
|
|
12936
|
+
reply: "Hello from RyoAI_bot.",
|
|
12937
|
+
}),
|
|
12938
|
+
performLocalBotDelivery: async ({ replyToMessageID, messageThreadID, sourceMessageEnvelope }) => {
|
|
12939
|
+
capturedReplyToMessageID = Number(replyToMessageID || 0);
|
|
12940
|
+
capturedMessageThreadID = Number(messageThreadID || 0);
|
|
12941
|
+
capturedSourceMessageEnvelope = safeObject(sourceMessageEnvelope);
|
|
12942
|
+
return {
|
|
12943
|
+
delivery: {
|
|
12944
|
+
dryRun: false,
|
|
12945
|
+
body: {
|
|
12946
|
+
result: {
|
|
12947
|
+
message_id: 9001,
|
|
12948
|
+
message_thread_id: Number(messageThreadID || 0) || undefined,
|
|
12949
|
+
},
|
|
12950
|
+
},
|
|
12951
|
+
},
|
|
12952
|
+
archive: {},
|
|
12953
|
+
};
|
|
12954
|
+
},
|
|
12955
|
+
serializeRunnerTriggerPolicy: (value) => value,
|
|
12956
|
+
serializeRunnerArchivePolicy: (value) => value,
|
|
12957
|
+
buildRunnerExecutionDeps: () => ({
|
|
12958
|
+
validateWorkspaceArtifacts,
|
|
12959
|
+
analyzeHumanConversationIntentWithAI: async () => ({
|
|
12960
|
+
mode: "single_bot",
|
|
12961
|
+
lead_bot: "ryoai_bot",
|
|
12962
|
+
participants: ["ryoai_bot"],
|
|
12963
|
+
initial_responders: ["ryoai_bot"],
|
|
12964
|
+
allowed_responders: ["ryoai_bot"],
|
|
12965
|
+
summary_bot: "",
|
|
12966
|
+
allow_bot_to_bot: false,
|
|
12967
|
+
reply_expectation: "informational",
|
|
12968
|
+
intent_type: "small_talk",
|
|
12969
|
+
}),
|
|
12970
|
+
}),
|
|
12971
|
+
buildRunnerDeliveryDeps: () => ({}),
|
|
12972
|
+
buildRunnerRuntimeDeps: () => ({}),
|
|
12973
|
+
resolveConversationPeerBots: () => [],
|
|
12974
|
+
},
|
|
12975
|
+
});
|
|
12976
|
+
push(
|
|
12977
|
+
"runner_delivery_prefers_route_local_inbound_provenance_envelope",
|
|
12978
|
+
processed.kind === "replied"
|
|
12979
|
+
&& capturedReplyToMessageID === 128
|
|
12980
|
+
&& capturedMessageThreadID === 912
|
|
12981
|
+
&& String(capturedSourceMessageEnvelope.source_origin || "") === "local_telegram_inbound"
|
|
12982
|
+
&& Number(capturedSourceMessageEnvelope.message_id || 0) === 128,
|
|
12983
|
+
`kind=${String(processed.kind || "(none)")} reply_to=${String(capturedReplyToMessageID || 0)} thread=${String(capturedMessageThreadID || 0)} origin=${String(capturedSourceMessageEnvelope.source_origin || "(none)")} message=${String(capturedSourceMessageEnvelope.message_id || "(none)")}`,
|
|
12984
|
+
);
|
|
12985
|
+
} catch (err) {
|
|
12986
|
+
push("runner_delivery_prefers_route_local_inbound_provenance_envelope", false, String(err?.message || err));
|
|
12987
|
+
}
|
|
12988
|
+
|
|
12832
12989
|
try {
|
|
12833
12990
|
const workspaceDir = fs.mkdtempSync(path.join(os.tmpdir(), "metheus-runner-selftest-observed-artifacts-"));
|
|
12834
12991
|
const scriptDir = path.join(workspaceDir, ".metheus", "runner-runtime", "local-ai-scratch");
|
|
@@ -503,17 +503,51 @@ export async function runSelftestTelegramE2E(push, deps) {
|
|
|
503
503
|
dryRun: true,
|
|
504
504
|
deps: buildRunnerDeliveryDeps(),
|
|
505
505
|
});
|
|
506
|
-
push(
|
|
507
|
-
"telegram_delivery_dry_run_skips_send_and_archive",
|
|
508
|
-
Boolean(dryRunResult.delivery?.dryRun)
|
|
509
|
-
&& String(dryRunResult.archive?.reason || "") === "dry_run_delivery"
|
|
510
|
-
&& telegramE2EServer.state.sentMessages.length === sentCountBeforeDryRun
|
|
511
|
-
&& telegramE2EServer.state.comments.length === commentCountBeforeDryRun,
|
|
512
|
-
`dry_run=${String(dryRunResult.delivery?.dryRun || false)} sent=${telegramE2EServer.state.sentMessages.length} comments=${telegramE2EServer.state.comments.length}`,
|
|
513
|
-
);
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
506
|
+
push(
|
|
507
|
+
"telegram_delivery_dry_run_skips_send_and_archive",
|
|
508
|
+
Boolean(dryRunResult.delivery?.dryRun)
|
|
509
|
+
&& String(dryRunResult.archive?.reason || "") === "dry_run_delivery"
|
|
510
|
+
&& telegramE2EServer.state.sentMessages.length === sentCountBeforeDryRun
|
|
511
|
+
&& telegramE2EServer.state.comments.length === commentCountBeforeDryRun,
|
|
512
|
+
`dry_run=${String(dryRunResult.delivery?.dryRun || false)} sent=${telegramE2EServer.state.sentMessages.length} comments=${telegramE2EServer.state.comments.length}`,
|
|
513
|
+
);
|
|
514
|
+
const sentCountBeforeUnsafeAnchor = telegramE2EServer.state.sentMessages.length;
|
|
515
|
+
let unsafeAnchorError = "";
|
|
516
|
+
try {
|
|
517
|
+
await performLocalBotDelivery({
|
|
518
|
+
siteBaseURL: telegramE2EServer.baseURL,
|
|
519
|
+
token: e2eToken,
|
|
520
|
+
timeoutSeconds: 10,
|
|
521
|
+
actorUserID: e2eActorUserID,
|
|
522
|
+
bot: e2eBot,
|
|
523
|
+
projectID: selftestProjectID,
|
|
524
|
+
provider: "telegram",
|
|
525
|
+
destinationSelectors: {
|
|
526
|
+
destinationLabel: e2eDestination.label,
|
|
527
|
+
},
|
|
528
|
+
text: "unsafe archive anchor",
|
|
529
|
+
replyToMessageID: 41,
|
|
530
|
+
sourceMessageEnvelope: {
|
|
531
|
+
chat_id: e2eDestination.chat_id,
|
|
532
|
+
message_id: 41,
|
|
533
|
+
source_origin: "archive_reconstructed",
|
|
534
|
+
},
|
|
535
|
+
archiveReplies: false,
|
|
536
|
+
dryRun: false,
|
|
537
|
+
deps: buildRunnerDeliveryDeps(),
|
|
538
|
+
});
|
|
539
|
+
} catch (err) {
|
|
540
|
+
unsafeAnchorError = String(err?.message || err);
|
|
541
|
+
}
|
|
542
|
+
push(
|
|
543
|
+
"telegram_delivery_rejects_archive_reconstructed_reply_anchor",
|
|
544
|
+
/telegram reply anchor is not local to this route/i.test(unsafeAnchorError)
|
|
545
|
+
&& telegramE2EServer.state.sentMessages.length === sentCountBeforeUnsafeAnchor,
|
|
546
|
+
`error=${unsafeAnchorError || "(none)"} sent=${telegramE2EServer.state.sentMessages.length}`,
|
|
547
|
+
);
|
|
548
|
+
|
|
549
|
+
telegramE2EServer.state.comments = [];
|
|
550
|
+
telegramE2EServer.state.updates = [
|
|
517
551
|
{
|
|
518
552
|
update_id: 201,
|
|
519
553
|
message: {
|