
























@@ -333,6 +333,8 @@ describe("telegram live qa runtime", () => {
333333"telegram-context-command",
334334"telegram-current-session-status-tool",
335335"telegram-mentioned-message-reply",
336+"telegram-long-final-reuses-preview",
337+"telegram-long-final-three-chunks",
336338"telegram-mention-gating",
337339]);
338340expect(scenarios.map((scenario) => scenario.id)).toEqual([
@@ -343,6 +345,8 @@ describe("telegram live qa runtime", () => {
343345"telegram-context-command",
344346"telegram-current-session-status-tool",
345347"telegram-mentioned-message-reply",
348+"telegram-long-final-reuses-preview",
349+"telegram-long-final-three-chunks",
346350"telegram-mention-gating",
347351]);
348352expect(
@@ -355,6 +359,25 @@ describe("telegram live qa runtime", () => {
355359.find((scenario) => scenario.id === "telegram-mentioned-message-reply")
356360?.buildRun("sut_bot").replyToLatestSutMessage,
357361).toBe(true);
362+expect(
363+scenarios
364+.find((scenario) => scenario.id === "telegram-long-final-reuses-preview")
365+?.buildRun("sut_bot"),
366+).toMatchObject({
367+expectedJoinedSutTextIncludes: ["TELEGRAM-LONG-FINAL-BEGIN", "TELEGRAM-LONG-FINAL-END"],
368+expectedSutMessageCount: 2,
369+});
370+expect(
371+scenarios
372+.find((scenario) => scenario.id === "telegram-long-final-three-chunks")
373+?.buildRun("sut_bot"),
374+).toMatchObject({
375+expectedJoinedSutTextIncludes: [
376+"TELEGRAM-LONG-FINAL-3CHUNK-BEGIN",
377+"TELEGRAM-LONG-FINAL-3CHUNK-END",
378+],
379+expectedSutMessageCount: 3,
380+});
358381});
359382360383it("keeps bot-to-bot plain mentions out of the default Telegram live set", () => {
@@ -382,6 +405,160 @@ describe("telegram live qa runtime", () => {
382405).toEqual(["allowlist-block", "top-level-reply-shape", "restart-resume"]);
383406});
384407408+it("asserts long Telegram final replies reuse the streamed preview message", () => {
409+expect(() =>
410+__testing.assertTelegramScenarioMessageSet({
411+expectedJoinedSutTextIncludes: ["TELEGRAM-LONG-FINAL-BEGIN", "TELEGRAM-LONG-FINAL-END"],
412+expectedSutMessageCount: 2,
413+groupId: "-100123",
414+scenarioId: "telegram-long-final-reuses-preview",
415+sutBotId: 99,
416+observedMessages: [
417+{
418+updateId: 1,
419+messageId: 10,
420+chatId: -100123,
421+senderId: 99,
422+senderIsBot: true,
423+scenarioId: "telegram-long-final-reuses-preview",
424+scenarioTitle: "Telegram long final reuses the preview message",
425+matchedScenario: true,
426+text: "TELEGRAM-LONG-FINAL-BEGIN part one ",
427+timestamp: 1_700_000_000_000,
428+inlineButtons: [],
429+mediaKinds: [],
430+},
431+{
432+updateId: 2,
433+messageId: 11,
434+chatId: -100123,
435+senderId: 99,
436+senderIsBot: true,
437+scenarioId: "telegram-long-final-reuses-preview",
438+scenarioTitle: "Telegram long final reuses the preview message",
439+matchedScenario: true,
440+text: "part two TELEGRAM-LONG-FINAL-END",
441+timestamp: 1_700_000_001_000,
442+inlineButtons: [],
443+mediaKinds: [],
444+},
445+],
446+}),
447+).not.toThrow();
448+449+expect(() =>
450+__testing.assertTelegramScenarioMessageSet({
451+expectedSutMessageCount: 2,
452+groupId: "-100123",
453+scenarioId: "telegram-long-final-reuses-preview",
454+sutBotId: 99,
455+observedMessages: [
456+{
457+updateId: 1,
458+messageId: 10,
459+chatId: -100123,
460+senderId: 99,
461+senderIsBot: true,
462+scenarioId: "telegram-long-final-reuses-preview",
463+scenarioTitle: "Telegram long final reuses the preview message",
464+matchedScenario: true,
465+text: "preview",
466+timestamp: 1_700_000_000_000,
467+inlineButtons: [],
468+mediaKinds: [],
469+},
470+{
471+updateId: 2,
472+messageId: 11,
473+chatId: -100123,
474+senderId: 99,
475+senderIsBot: true,
476+scenarioId: "telegram-long-final-reuses-preview",
477+scenarioTitle: "Telegram long final reuses the preview message",
478+matchedScenario: true,
479+text: "final chunk one",
480+timestamp: 1_700_000_001_000,
481+inlineButtons: [],
482+mediaKinds: [],
483+},
484+{
485+updateId: 3,
486+messageId: 12,
487+chatId: -100123,
488+senderId: 99,
489+senderIsBot: true,
490+scenarioId: "telegram-long-final-reuses-preview",
491+scenarioTitle: "Telegram long final reuses the preview message",
492+matchedScenario: true,
493+text: "final chunk two",
494+timestamp: 1_700_000_002_000,
495+inlineButtons: [],
496+mediaKinds: [],
497+},
498+],
499+}),
500+).toThrow("expected 2 SUT message(s), observed 3");
501+});
502+503+it("accepts legitimate three-chunk Telegram final replies", () => {
504+expect(() =>
505+__testing.assertTelegramScenarioMessageSet({
506+expectedJoinedSutTextIncludes: [
507+"TELEGRAM-LONG-FINAL-3CHUNK-BEGIN",
508+"TELEGRAM-LONG-FINAL-3CHUNK-END",
509+],
510+expectedSutMessageCount: 3,
511+groupId: "-100123",
512+scenarioId: "telegram-long-final-three-chunks",
513+sutBotId: 99,
514+observedMessages: [
515+{
516+updateId: 1,
517+messageId: 10,
518+chatId: -100123,
519+senderId: 99,
520+senderIsBot: true,
521+scenarioId: "telegram-long-final-three-chunks",
522+scenarioTitle: "Telegram three-chunk final keeps only final chunks",
523+matchedScenario: true,
524+text: "TELEGRAM-LONG-FINAL-3CHUNK-BEGIN part one ",
525+timestamp: 1_700_000_000_000,
526+inlineButtons: [],
527+mediaKinds: [],
528+},
529+{
530+updateId: 2,
531+messageId: 11,
532+chatId: -100123,
533+senderId: 99,
534+senderIsBot: true,
535+scenarioId: "telegram-long-final-three-chunks",
536+scenarioTitle: "Telegram three-chunk final keeps only final chunks",
537+matchedScenario: true,
538+text: "part two ",
539+timestamp: 1_700_000_001_000,
540+inlineButtons: [],
541+mediaKinds: [],
542+},
543+{
544+updateId: 3,
545+messageId: 12,
546+chatId: -100123,
547+senderId: 99,
548+senderIsBot: true,
549+scenarioId: "telegram-long-final-three-chunks",
550+scenarioTitle: "Telegram three-chunk final keeps only final chunks",
551+matchedScenario: true,
552+text: "part three TELEGRAM-LONG-FINAL-3CHUNK-END",
553+timestamp: 1_700_000_002_000,
554+inlineButtons: [],
555+mediaKinds: [],
556+},
557+],
558+}),
559+).not.toThrow();
560+});
561+385562it("matches scenario replies by thread or exact marker", () => {
386563expect(
387564__testing.matchesTelegramScenarioReply({
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。