feat: human error states, operator toasts and a queue/origin view in the omp UI

- classify transport and API failures into a short state with the next step
- count undelivered messages and show them next to the sent counter
- toast on owner paired, connection recovered and reply not delivered (throttled)
- second status line previews the next queued turns
- host spinner names the Telegram prompt while its turn runs
- sanitize every Telegram-controlled string that reaches the widget
This commit is contained in:
evandrodevbr committed 2026-10-01 17:33:37 -03:00
1 parent 9435ff709b
commit 057281a3bb
19 files changed
+862 -22

No files matched your search

+23
View File
@@ -683,6 +683,29 @@ test("Telegram config pairing runtime binds config and status ports", async () =
assert.deepEqual(events, ["set:7", "persist", "status:ctx"]);
});
test("Telegram config pairing runtime reports the new owner only after persisting", async () => {
const events: string[] = [];
let allowedUserId: number | undefined;
const runtime = createTelegramUserPairingRuntime({
getAllowedUserId: () => allowedUserId,
setAllowedUserId: (userId) => {
allowedUserId = userId;
},
persistConfig: async () => {
events.push("persist");
},
updateStatus: () => {
events.push("status");
},
onPaired: (userId, ctx: string) => {
events.push(`paired:${userId}:${ctx}`);
},
});
assert.equal(await runtime.pairIfNeeded(7, "ctx"), true);
assert.equal(await runtime.pairIfNeeded(8, "ctx"), false);
assert.deepEqual(events, ["persist", "status", "paired:7:ctx"]);
});
test("Bot token input prefers stored config over env vars", () => {
const value = getTelegramBotTokenInputDefault(
{