fix(runtime): duplicate messages, share singleton state across bundled chunks (#43683)

* Tests: add fresh module import helper

* Process: share command queue runtime state

* Agents: share embedded run runtime state

* Reply: share followup queue runtime state

* Reply: share followup drain callback state

* Reply: share queued message dedupe state

* Reply: share inbound dedupe state

* Tests: cover shared command queue runtime state

* Tests: cover shared embedded run runtime state

* Tests: cover shared followup queue runtime state

* Tests: cover shared inbound dedupe state

* Tests: cover shared Slack thread participation state

* Slack: share sent thread participation state

* Tests: document fresh import helper

* Telegram: share draft stream runtime state

* Tests: cover shared Telegram draft stream state

* Telegram: share sent message cache state

* Tests: cover shared Telegram sent message cache

* Telegram: share thread binding runtime state

* Tests: cover shared Telegram thread binding state

* Tests: avoid duplicate shared queue reset

* refactor(runtime): centralize global singleton access

* refactor(runtime): preserve undefined global singleton values

* test(runtime): cover undefined global singleton values

---------

Co-authored-by: Nimrod Gutman <nimrod.gutman@gmail.com>
This commit is contained in:
Vincent Koc
2026-03-12 14:59:27 -04:00
committed by GitHub
parent 08aa57a3de
commit 4ca84acf24
21 changed files with 569 additions and 38 deletions

View File

@@ -1,6 +1,7 @@
import type { Bot } from "grammy";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import { createTelegramDraftStream } from "./draft-stream.js";
import { importFreshModule } from "../../test/helpers/import-fresh.js";
import { __testing, createTelegramDraftStream } from "./draft-stream.js";
type TelegramDraftStreamParams = Parameters<typeof createTelegramDraftStream>[0];
@@ -65,6 +66,10 @@ function createForceNewMessageHarness(params: { throttleMs?: number } = {}) {
}
describe("createTelegramDraftStream", () => {
afterEach(() => {
__testing.resetTelegramDraftStreamForTests();
});
it("sends stream preview message with message_thread_id when provided", async () => {
const api = createMockDraftApi();
const stream = createForumDraftStream(api);
@@ -355,6 +360,46 @@ describe("createTelegramDraftStream", () => {
expect(api.editMessageText).not.toHaveBeenCalled();
});
it("shares draft-id allocation across distinct module instances", async () => {
const draftA = await importFreshModule<typeof import("./draft-stream.js")>(
import.meta.url,
"./draft-stream.js?scope=shared-a",
);
const draftB = await importFreshModule<typeof import("./draft-stream.js")>(
import.meta.url,
"./draft-stream.js?scope=shared-b",
);
const apiA = createMockDraftApi();
const apiB = createMockDraftApi();
draftA.__testing.resetTelegramDraftStreamForTests();
try {
const streamA = draftA.createTelegramDraftStream({
api: apiA as unknown as Bot["api"],
chatId: 123,
thread: { id: 42, scope: "dm" },
previewTransport: "draft",
});
const streamB = draftB.createTelegramDraftStream({
api: apiB as unknown as Bot["api"],
chatId: 123,
thread: { id: 42, scope: "dm" },
previewTransport: "draft",
});
streamA.update("Message A");
await streamA.flush();
streamB.update("Message B");
await streamB.flush();
expect(apiA.sendMessageDraft.mock.calls[0]?.[1]).toBe(1);
expect(apiB.sendMessageDraft.mock.calls[0]?.[1]).toBe(2);
} finally {
draftA.__testing.resetTelegramDraftStreamForTests();
}
});
it("creates new message after forceNewMessage is called", async () => {
const { api, stream } = createForceNewMessageHarness();