@llblab/pi-telegram 0.41.1 → 0.42.1
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/CHANGELOG.md +11 -0
- package/README.md +3 -3
- package/docs/architecture.md +3 -3
- package/docs/compact-matrix-literal.md +29 -23
- package/docs/outbound.md +12 -21
- package/docs/public-api.md +2 -2
- package/lib/outbound-buttons.ts +9 -8
- package/lib/outbound-markup.ts +218 -83
- package/lib/routing.ts +44 -28
- package/package.json +1 -1
- package/skills/generated-control-surface/SKILL.md +61 -207
- package/skills/generated-control-surface/references/capability-adapters.md +27 -0
- package/skills/generated-control-surface/references/layout-and-state.md +35 -0
- package/skills/telegram-bridge/SKILL.md +71 -110
- package/skills/telegram-bridge/references/configuration.md +15 -0
- package/skills/telegram-bridge/references/delivery-and-threads.md +27 -0
- package/skills/telegram-bridge/references/diagnosis.md +14 -0
package/lib/outbound-markup.ts
CHANGED
|
@@ -153,63 +153,158 @@ export function parseTopLevelTelegramComment(
|
|
|
153
153
|
};
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
-
function
|
|
156
|
+
function parseTolerantTelegramAttributes(
|
|
157
157
|
source: string,
|
|
158
|
+
names: readonly string[],
|
|
158
159
|
): Record<string, string> | undefined {
|
|
159
160
|
const attributes: Record<string, string> = {};
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
const value = match[2].trim();
|
|
167
|
-
if (value) attributes[match[1]] = value;
|
|
168
|
-
offset = pattern.lastIndex;
|
|
161
|
+
const namePattern = names.join("|");
|
|
162
|
+
const pattern = new RegExp(
|
|
163
|
+
`\\b(${namePattern})\\s*=\\s*(?:"([^"]*)"|'([^']*)'|([^\\s]+))`,
|
|
164
|
+
"gu",
|
|
165
|
+
);
|
|
166
|
+
for (const match of source.matchAll(pattern)) {
|
|
167
|
+
const value = (match[2] ?? match[3] ?? match[4] ?? "").trim();
|
|
168
|
+
if (value) attributes[match[1]!] = value;
|
|
169
169
|
}
|
|
170
170
|
return Object.keys(attributes).length > 0 ? attributes : undefined;
|
|
171
171
|
}
|
|
172
172
|
|
|
173
|
-
function getTelegramActionPayloadSource(
|
|
174
|
-
comment: TelegramTopLevelHtmlComment,
|
|
175
|
-
command: string,
|
|
176
|
-
): { source: string; hasBody: boolean } | undefined {
|
|
177
|
-
const parsed = parseTopLevelTelegramComment(comment, command);
|
|
178
|
-
if (!parsed || parsed.head.trimStart().startsWith(":")) return undefined;
|
|
179
|
-
const source = [parsed.head, parsed.body]
|
|
180
|
-
.filter((part): part is string => part !== undefined)
|
|
181
|
-
.join("\n")
|
|
182
|
-
.trim();
|
|
183
|
-
return source ? { source, hasBody: parsed.body !== undefined } : undefined;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
173
|
function isTelegramActionPayload(value: unknown): value is Record<string, unknown> {
|
|
187
174
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
188
175
|
}
|
|
189
176
|
|
|
177
|
+
function removeTelegramJsonTrailingCommas(source: string): string {
|
|
178
|
+
let normalized = "";
|
|
179
|
+
let inString = false;
|
|
180
|
+
let escaped = false;
|
|
181
|
+
for (let offset = 0; offset < source.length; offset += 1) {
|
|
182
|
+
const character = source[offset]!;
|
|
183
|
+
if (inString) {
|
|
184
|
+
normalized += character;
|
|
185
|
+
if (escaped) escaped = false;
|
|
186
|
+
else if (character === "\\") escaped = true;
|
|
187
|
+
else if (character === '"') inString = false;
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
if (character === '"') {
|
|
191
|
+
inString = true;
|
|
192
|
+
normalized += character;
|
|
193
|
+
continue;
|
|
194
|
+
}
|
|
195
|
+
if (character === ",") {
|
|
196
|
+
let next = offset + 1;
|
|
197
|
+
while (/\s/u.test(source[next] ?? "")) next += 1;
|
|
198
|
+
if (source[next] === "}" || source[next] === "]") continue;
|
|
199
|
+
}
|
|
200
|
+
normalized += character;
|
|
201
|
+
}
|
|
202
|
+
return normalized;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function parseTelegramJsonObjectCandidate(
|
|
206
|
+
source: string,
|
|
207
|
+
): Record<string, unknown> | undefined {
|
|
208
|
+
const normalized = removeTelegramJsonTrailingCommas(source);
|
|
209
|
+
for (const candidate of normalized === source ? [source] : [source, normalized]) {
|
|
210
|
+
try {
|
|
211
|
+
const value: unknown = JSON.parse(candidate);
|
|
212
|
+
if (isTelegramActionPayload(value)) return value;
|
|
213
|
+
} catch {
|
|
214
|
+
// Try the bounded trailing-comma normalization before rejecting JSON.
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
return undefined;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function looksLikeTelegramNamedJsonObject(
|
|
221
|
+
source: string,
|
|
222
|
+
offset: number,
|
|
223
|
+
): boolean {
|
|
224
|
+
return /^\{\s*"(?:[^"\\]|\\.)*"\s*:/u.test(source.slice(offset));
|
|
225
|
+
}
|
|
226
|
+
|
|
190
227
|
export function parseTelegramActionPayload(
|
|
191
228
|
comment: TelegramTopLevelHtmlComment,
|
|
192
229
|
command: string,
|
|
193
230
|
): Record<string, unknown> | undefined {
|
|
194
|
-
|
|
195
|
-
if (!
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
231
|
+
let content = comment.content.replace(/^\s+/, "").replace(/^!/, "");
|
|
232
|
+
if (!content.startsWith(command)) return undefined;
|
|
233
|
+
content = content.slice(command.length);
|
|
234
|
+
let attributeEnvelope = content;
|
|
235
|
+
for (let offset = 0; offset < content.length; offset += 1) {
|
|
236
|
+
if (content[offset] !== "{" && content[offset] !== "[") continue;
|
|
237
|
+
if (
|
|
238
|
+
content[offset] === "[" &&
|
|
239
|
+
!isPlausibleTelegramMatrixStart(content, offset)
|
|
240
|
+
) {
|
|
241
|
+
const noiseEnd = findTelegramStructuredPayloadEnd(content, offset);
|
|
242
|
+
if (noiseEnd !== undefined) {
|
|
243
|
+
attributeEnvelope = `${attributeEnvelope.slice(0, offset)}${" ".repeat(noiseEnd - offset)}${attributeEnvelope.slice(noiseEnd)}`;
|
|
244
|
+
offset = noiseEnd - 1;
|
|
245
|
+
}
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
if (content[offset] === "{") {
|
|
249
|
+
const parsed = parseTelegramAdaptiveActionPayloadRows(
|
|
250
|
+
content.slice(offset),
|
|
251
|
+
parseTelegramVoiceCompactActionPayload,
|
|
252
|
+
{ allowTrailing: true },
|
|
253
|
+
);
|
|
254
|
+
if (parsed) return parsed.rows[0]![0];
|
|
202
255
|
}
|
|
256
|
+
const end = findTelegramStructuredPayloadEnd(content, offset);
|
|
257
|
+
if (end === undefined) continue;
|
|
258
|
+
attributeEnvelope = `${attributeEnvelope.slice(0, offset)}${" ".repeat(end - offset)}${attributeEnvelope.slice(end)}`;
|
|
259
|
+
offset = end - 1;
|
|
203
260
|
}
|
|
204
|
-
|
|
205
|
-
|
|
261
|
+
return parseTolerantTelegramAttributes(attributeEnvelope, [
|
|
262
|
+
"text",
|
|
263
|
+
"value",
|
|
264
|
+
"lang",
|
|
265
|
+
"rate",
|
|
266
|
+
]);
|
|
206
267
|
}
|
|
207
268
|
|
|
208
269
|
const TELEGRAM_COMPACT_ACTION_CONTROL_PATTERN = /[\u0000-\u001f\u007f-\u009f]/u;
|
|
209
270
|
|
|
271
|
+
type TelegramCompactActionPayloadParser = (
|
|
272
|
+
atoms: readonly string[],
|
|
273
|
+
) => Record<string, unknown> | undefined;
|
|
274
|
+
|
|
275
|
+
function parseTelegramButtonCompactActionPayload(
|
|
276
|
+
atoms: readonly string[],
|
|
277
|
+
): Record<string, unknown> | undefined {
|
|
278
|
+
const [label, prompt, selectedStyle] = atoms;
|
|
279
|
+
if (atoms.length === 1) return label ? { value: label } : undefined;
|
|
280
|
+
if (!prompt) return undefined;
|
|
281
|
+
const action = label ? { label, prompt } : { prompt };
|
|
282
|
+
if (atoms.length === 2) return action;
|
|
283
|
+
if (
|
|
284
|
+
selectedStyle !== "primary" &&
|
|
285
|
+
selectedStyle !== "success" &&
|
|
286
|
+
selectedStyle !== "danger"
|
|
287
|
+
) return undefined;
|
|
288
|
+
return { ...action, selected_style: selectedStyle };
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
function parseTelegramVoiceCompactActionPayload(
|
|
292
|
+
atoms: readonly string[],
|
|
293
|
+
): Record<string, unknown> | undefined {
|
|
294
|
+
const [text, lang, rate] = atoms;
|
|
295
|
+
if (!text) return undefined;
|
|
296
|
+
if (atoms.length === 1) return { text };
|
|
297
|
+
if (!lang) return undefined;
|
|
298
|
+
if (atoms.length === 2) return { text, lang };
|
|
299
|
+
if (!rate) return undefined;
|
|
300
|
+
return { text, lang, rate };
|
|
301
|
+
}
|
|
302
|
+
|
|
210
303
|
function parseTelegramAdaptiveActionPayloadRows(
|
|
211
304
|
source: string,
|
|
212
|
-
|
|
305
|
+
parseCompactPayload: TelegramCompactActionPayloadParser,
|
|
306
|
+
options: { allowTrailing?: boolean } = {},
|
|
307
|
+
): { rows: Record<string, unknown>[][]; end: number } | undefined {
|
|
213
308
|
let offset = 0;
|
|
214
309
|
const isStructuralWhitespace = (character: string | undefined): boolean =>
|
|
215
310
|
character === " " ||
|
|
@@ -224,11 +319,11 @@ function parseTelegramAdaptiveActionPayloadRows(
|
|
|
224
319
|
if (source[offset] !== ",") return true;
|
|
225
320
|
offset += 1;
|
|
226
321
|
skipWhitespace();
|
|
227
|
-
return source[offset] !== ","
|
|
322
|
+
return source[offset] !== ",";
|
|
228
323
|
};
|
|
229
324
|
const normalizeAtom = (value: string): string | undefined => {
|
|
230
325
|
const normalized = value.trim();
|
|
231
|
-
return
|
|
326
|
+
return !TELEGRAM_COMPACT_ACTION_CONTROL_PATTERN.test(normalized)
|
|
232
327
|
? normalized
|
|
233
328
|
: undefined;
|
|
234
329
|
};
|
|
@@ -259,15 +354,7 @@ function parseTelegramAdaptiveActionPayloadRows(
|
|
|
259
354
|
normalizeAtom(atom.join("")),
|
|
260
355
|
);
|
|
261
356
|
if (atoms.some((atom) => atom === undefined)) return undefined;
|
|
262
|
-
|
|
263
|
-
if (atoms.length === 1) return { value: label };
|
|
264
|
-
if (atoms.length === 2) return { label, prompt };
|
|
265
|
-
if (
|
|
266
|
-
selectedStyle !== "primary" &&
|
|
267
|
-
selectedStyle !== "success" &&
|
|
268
|
-
selectedStyle !== "danger"
|
|
269
|
-
) return undefined;
|
|
270
|
-
return { label, prompt, selected_style: selectedStyle };
|
|
357
|
+
return parseCompactPayload(atoms as string[]);
|
|
271
358
|
}
|
|
272
359
|
atomSources.at(-1)!.push(character);
|
|
273
360
|
offset += 1;
|
|
@@ -304,14 +391,10 @@ function parseTelegramAdaptiveActionPayloadRows(
|
|
|
304
391
|
) return undefined;
|
|
305
392
|
if (stack.length > 0) continue;
|
|
306
393
|
const candidate = source.slice(start, index + 1);
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
return value;
|
|
312
|
-
} catch {
|
|
313
|
-
return undefined;
|
|
314
|
-
}
|
|
394
|
+
const value = parseTelegramJsonObjectCandidate(candidate);
|
|
395
|
+
if (!value) return undefined;
|
|
396
|
+
offset = index + 1;
|
|
397
|
+
return value;
|
|
315
398
|
}
|
|
316
399
|
return undefined;
|
|
317
400
|
};
|
|
@@ -320,6 +403,7 @@ function parseTelegramAdaptiveActionPayloadRows(
|
|
|
320
403
|
const jsonCell = parseJsonObjectCell();
|
|
321
404
|
if (jsonCell) return jsonCell;
|
|
322
405
|
offset = start;
|
|
406
|
+
if (looksLikeTelegramNamedJsonObject(source, start)) return undefined;
|
|
323
407
|
return parseCompactCell();
|
|
324
408
|
};
|
|
325
409
|
const parseRow = (): Record<string, unknown>[] | undefined => {
|
|
@@ -377,42 +461,92 @@ function parseTelegramAdaptiveActionPayloadRows(
|
|
|
377
461
|
}
|
|
378
462
|
if (!rows) return undefined;
|
|
379
463
|
skipWhitespace();
|
|
380
|
-
|
|
464
|
+
if (!options.allowTrailing && offset !== source.length) return undefined;
|
|
465
|
+
return { rows, end: offset };
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
function findTelegramStructuredPayloadEnd(
|
|
469
|
+
source: string,
|
|
470
|
+
start: number,
|
|
471
|
+
): number | undefined {
|
|
472
|
+
const stack: string[] = [source[start]!];
|
|
473
|
+
let inString = false;
|
|
474
|
+
let escaped = false;
|
|
475
|
+
for (let offset = start + 1; offset < source.length; offset += 1) {
|
|
476
|
+
const character = source[offset]!;
|
|
477
|
+
if (inString) {
|
|
478
|
+
if (escaped) escaped = false;
|
|
479
|
+
else if (character === "\\") escaped = true;
|
|
480
|
+
else if (character === '"') inString = false;
|
|
481
|
+
continue;
|
|
482
|
+
}
|
|
483
|
+
if (character === '"') {
|
|
484
|
+
inString = true;
|
|
485
|
+
continue;
|
|
486
|
+
}
|
|
487
|
+
if (character === "[" || character === "{") {
|
|
488
|
+
stack.push(character);
|
|
489
|
+
continue;
|
|
490
|
+
}
|
|
491
|
+
if (character !== "]" && character !== "}") continue;
|
|
492
|
+
const expected = character === "]" ? "[" : "{";
|
|
493
|
+
if (stack.at(-1) === expected) stack.pop();
|
|
494
|
+
if (stack.length === 0) return offset + 1;
|
|
495
|
+
}
|
|
496
|
+
return undefined;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
function isPlausibleTelegramMatrixStart(
|
|
500
|
+
source: string,
|
|
501
|
+
start: number,
|
|
502
|
+
): boolean {
|
|
503
|
+
let offset = start + 1;
|
|
504
|
+
while (/\s/u.test(source[offset] ?? "")) offset += 1;
|
|
505
|
+
return (
|
|
506
|
+
source[offset] === "{" ||
|
|
507
|
+
source[offset] === "[" ||
|
|
508
|
+
source[offset] === "]"
|
|
509
|
+
);
|
|
381
510
|
}
|
|
382
511
|
|
|
383
512
|
export function parseTelegramActionPayloadRows(
|
|
384
513
|
comment: TelegramTopLevelHtmlComment,
|
|
385
514
|
command: string,
|
|
386
515
|
): Record<string, unknown>[][] | undefined {
|
|
387
|
-
|
|
388
|
-
if (!
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
}
|
|
400
|
-
|
|
401
|
-
!Array.isArray(entry) ||
|
|
402
|
-
entry.length === 0 ||
|
|
403
|
-
!entry.every(isTelegramActionPayload)
|
|
404
|
-
) {
|
|
405
|
-
return undefined;
|
|
406
|
-
}
|
|
407
|
-
rows.push(entry);
|
|
516
|
+
let content = comment.content.replace(/^\s+/, "").replace(/^!/, "");
|
|
517
|
+
if (!content.startsWith(command)) return undefined;
|
|
518
|
+
content = content.slice(command.length);
|
|
519
|
+
let attributeEnvelope = content;
|
|
520
|
+
for (let offset = 0; offset < content.length; offset += 1) {
|
|
521
|
+
if (content[offset] !== "[" && content[offset] !== "{") continue;
|
|
522
|
+
if (
|
|
523
|
+
content[offset] === "[" &&
|
|
524
|
+
!isPlausibleTelegramMatrixStart(content, offset)
|
|
525
|
+
) {
|
|
526
|
+
const noiseEnd = findTelegramStructuredPayloadEnd(content, offset);
|
|
527
|
+
if (noiseEnd !== undefined) {
|
|
528
|
+
attributeEnvelope = `${attributeEnvelope.slice(0, offset)}${" ".repeat(noiseEnd - offset)}${attributeEnvelope.slice(noiseEnd)}`;
|
|
529
|
+
offset = noiseEnd - 1;
|
|
408
530
|
}
|
|
409
|
-
|
|
410
|
-
} catch {
|
|
411
|
-
return parseTelegramAdaptiveActionPayloadRows(payload.source);
|
|
531
|
+
continue;
|
|
412
532
|
}
|
|
533
|
+
const parsed = parseTelegramAdaptiveActionPayloadRows(
|
|
534
|
+
content.slice(offset),
|
|
535
|
+
parseTelegramButtonCompactActionPayload,
|
|
536
|
+
{ allowTrailing: true },
|
|
537
|
+
);
|
|
538
|
+
if (parsed) return parsed.rows;
|
|
539
|
+
const end = findTelegramStructuredPayloadEnd(content, offset);
|
|
540
|
+
if (end === undefined) continue;
|
|
541
|
+
attributeEnvelope = `${attributeEnvelope.slice(0, offset)}${" ".repeat(end - offset)}${attributeEnvelope.slice(end)}`;
|
|
542
|
+
offset = end - 1;
|
|
413
543
|
}
|
|
414
|
-
|
|
415
|
-
|
|
544
|
+
const attributes = parseTolerantTelegramAttributes(attributeEnvelope, [
|
|
545
|
+
"label",
|
|
546
|
+
"prompt",
|
|
547
|
+
"value",
|
|
548
|
+
"selected_style",
|
|
549
|
+
]);
|
|
416
550
|
return attributes ? [[attributes]] : undefined;
|
|
417
551
|
}
|
|
418
552
|
|
|
@@ -481,9 +615,10 @@ export function planTelegramVoiceReply(
|
|
|
481
615
|
let lang: string | undefined;
|
|
482
616
|
let rate: string | undefined;
|
|
483
617
|
const stripped = replaceTopLevelHtmlComments(markdown, (comment) => {
|
|
484
|
-
const command =
|
|
485
|
-
|
|
486
|
-
|
|
618
|
+
const command = "telegram_voice";
|
|
619
|
+
const normalizedContent = comment.content.replace(/^\s+/, "").replace(/^!/, "");
|
|
620
|
+
if (!normalizedContent.startsWith(command)) return comment.raw;
|
|
621
|
+
const payload = parseTelegramActionPayload(comment, command);
|
|
487
622
|
if (!payload) return "";
|
|
488
623
|
const text =
|
|
489
624
|
getTelegramActionString(payload, "text") ??
|
package/lib/routing.ts
CHANGED
|
@@ -759,6 +759,42 @@ export function createTelegramInboundRouteRuntime<
|
|
|
759
759
|
);
|
|
760
760
|
}
|
|
761
761
|
};
|
|
762
|
+
const resolveTelegramThreadLabel = (message: {
|
|
763
|
+
chat: { id: number };
|
|
764
|
+
message_thread_id?: number;
|
|
765
|
+
}): string | undefined => {
|
|
766
|
+
const chatId = message.chat.id;
|
|
767
|
+
const threadId = message.message_thread_id;
|
|
768
|
+
if (!threadId) return undefined;
|
|
769
|
+
const localLabel = deps.getLocalThreadLabelForTarget?.({ chatId, threadId });
|
|
770
|
+
if (localLabel) return localLabel;
|
|
771
|
+
if (!deps.threadStore) return undefined;
|
|
772
|
+
const records = deps.threadStore.list();
|
|
773
|
+
const currentInstanceId = deps.getCurrentInstanceId?.();
|
|
774
|
+
for (const record of records) {
|
|
775
|
+
if (
|
|
776
|
+
record.target.chatId !== chatId ||
|
|
777
|
+
record.target.threadId !== threadId
|
|
778
|
+
) {
|
|
779
|
+
continue;
|
|
780
|
+
}
|
|
781
|
+
if (
|
|
782
|
+
currentInstanceId &&
|
|
783
|
+
record.instanceId &&
|
|
784
|
+
record.instanceId !== currentInstanceId
|
|
785
|
+
) {
|
|
786
|
+
continue;
|
|
787
|
+
}
|
|
788
|
+
return record.threadName &&
|
|
789
|
+
Threads.isTelegramTopicThreadNameValidForSlot(
|
|
790
|
+
record.threadName,
|
|
791
|
+
record.slot,
|
|
792
|
+
)
|
|
793
|
+
? record.threadName
|
|
794
|
+
: getRestoredThreadName(record, record.slot ?? "");
|
|
795
|
+
}
|
|
796
|
+
return undefined;
|
|
797
|
+
};
|
|
762
798
|
const createAdmissionReceipts = (
|
|
763
799
|
queueKind: Queue.TelegramQueueItemKind,
|
|
764
800
|
sources: readonly unknown[],
|
|
@@ -1628,6 +1664,13 @@ export function createTelegramInboundRouteRuntime<
|
|
|
1628
1664
|
replyToMessageId: messageId,
|
|
1629
1665
|
queueOrder,
|
|
1630
1666
|
action,
|
|
1667
|
+
telegramPrefix: Turns.createTelegramTurnPrefix({
|
|
1668
|
+
thread: resolveTelegramThreadLabel({
|
|
1669
|
+
chat: { id: chatId },
|
|
1670
|
+
message_thread_id:
|
|
1671
|
+
buttonQuery.message?.message_thread_id,
|
|
1672
|
+
}),
|
|
1673
|
+
}),
|
|
1631
1674
|
}),
|
|
1632
1675
|
...(admissionReceipts.length > 0 ? { admissionReceipts } : {}),
|
|
1633
1676
|
};
|
|
@@ -1770,34 +1813,7 @@ export function createTelegramInboundRouteRuntime<
|
|
|
1770
1813
|
|
|
1771
1814
|
// Voice policy resolves missing, invalid, and legacy manual config to hidden.
|
|
1772
1815
|
getVoiceReplyMode: () => getTelegramVoiceReplyMode(deps.configStore.get()),
|
|
1773
|
-
getTelegramThreadLabel
|
|
1774
|
-
if (!deps.threadStore) return undefined;
|
|
1775
|
-
const chatId = message.chat.id;
|
|
1776
|
-
const threadId = message.message_thread_id;
|
|
1777
|
-
if (!threadId) return undefined;
|
|
1778
|
-
const localLabel = deps.getLocalThreadLabelForTarget?.({
|
|
1779
|
-
chatId,
|
|
1780
|
-
threadId,
|
|
1781
|
-
});
|
|
1782
|
-
if (localLabel) return localLabel;
|
|
1783
|
-
const records = deps.threadStore.list();
|
|
1784
|
-
const currentInstanceId = deps.getCurrentInstanceId?.();
|
|
1785
|
-
for (const r of records) {
|
|
1786
|
-
if (r.target.chatId !== chatId || r.target.threadId !== threadId)
|
|
1787
|
-
continue;
|
|
1788
|
-
if (
|
|
1789
|
-
currentInstanceId &&
|
|
1790
|
-
r.instanceId &&
|
|
1791
|
-
r.instanceId !== currentInstanceId
|
|
1792
|
-
)
|
|
1793
|
-
continue;
|
|
1794
|
-
return r.threadName &&
|
|
1795
|
-
Threads.isTelegramTopicThreadNameValidForSlot(r.threadName, r.slot)
|
|
1796
|
-
? r.threadName
|
|
1797
|
-
: getRestoredThreadName(r, r.slot ?? "");
|
|
1798
|
-
}
|
|
1799
|
-
return undefined;
|
|
1800
|
-
},
|
|
1816
|
+
getTelegramThreadLabel: resolveTelegramThreadLabel,
|
|
1801
1817
|
});
|
|
1802
1818
|
const enqueueContinueTurn = async (
|
|
1803
1819
|
message: TMessage,
|