feat(telegram): wire replyToMode config, add forum topic support, fix messaging tool duplicates

Changes:
- Default replyToMode from "off" to "first" for better threading UX
- Add messageThreadId and replyToMessageId params for forum topic support
- Add messaging tool duplicate detection to suppress redundant block replies
- Add sendMessage action to telegram tool schema
- Add @grammyjs/types devDependency for proper TypeScript typing
- Remove @ts-nocheck and fix all type errors in send.ts
- Add comprehensive docs/telegram.md documentation
- Add PR-326-REVIEW.md with John Carmack-level code review

Test coverage:
- normalizeTextForComparison: 5 cases
- isMessagingToolDuplicate: 7 cases
- sendMessageTelegram thread params: 5 cases
- handleTelegramAction sendMessage: 4 cases
- Forum topic isolation: 4 cases

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
mneves75
2026-01-07 03:24:56 -03:00
committed by Peter Steinberger
parent 6cd32ec7f6
commit 33e2d53be3
18 changed files with 872 additions and 38 deletions

View File

@@ -5,6 +5,8 @@ import {
buildBootstrapContextFiles,
formatAssistantErrorText,
isContextOverflowError,
isMessagingToolDuplicate,
normalizeTextForComparison,
sanitizeGoogleTurnOrdering,
validateGeminiTurns,
} from "./pi-embedded-helpers.js";
@@ -247,3 +249,86 @@ describe("sanitizeGoogleTurnOrdering", () => {
expect(out).toBe(input);
});
});
describe("normalizeTextForComparison", () => {
it("lowercases text", () => {
expect(normalizeTextForComparison("Hello World")).toBe("hello world");
});
it("trims whitespace", () => {
expect(normalizeTextForComparison(" hello ")).toBe("hello");
});
it("collapses multiple spaces", () => {
expect(normalizeTextForComparison("hello world")).toBe("hello world");
});
it("strips emoji", () => {
expect(normalizeTextForComparison("Hello 👋 World 🌍")).toBe("hello world");
});
it("handles mixed normalization", () => {
expect(normalizeTextForComparison(" Hello 👋 WORLD 🌍 ")).toBe(
"hello world",
);
});
});
describe("isMessagingToolDuplicate", () => {
it("returns false for empty sentTexts", () => {
expect(isMessagingToolDuplicate("hello world", [])).toBe(false);
});
it("returns false for short texts", () => {
expect(isMessagingToolDuplicate("short", ["short"])).toBe(false);
});
it("detects exact duplicates", () => {
expect(
isMessagingToolDuplicate("Hello, this is a test message!", [
"Hello, this is a test message!",
]),
).toBe(true);
});
it("detects duplicates with different casing", () => {
expect(
isMessagingToolDuplicate("HELLO, THIS IS A TEST MESSAGE!", [
"hello, this is a test message!",
]),
).toBe(true);
});
it("detects duplicates with emoji variations", () => {
expect(
isMessagingToolDuplicate("Hello! 👋 This is a test message!", [
"Hello! This is a test message!",
]),
).toBe(true);
});
it("detects substring duplicates (LLM elaboration)", () => {
expect(
isMessagingToolDuplicate(
'I sent the message: "Hello, this is a test message!"',
["Hello, this is a test message!"],
),
).toBe(true);
});
it("detects when sent text contains block reply (reverse substring)", () => {
expect(
isMessagingToolDuplicate("Hello, this is a test message!", [
'I sent the message: "Hello, this is a test message!"',
]),
).toBe(true);
});
it("returns false for non-matching texts", () => {
expect(
isMessagingToolDuplicate("This is completely different content.", [
"Hello, this is a test message!",
]),
).toBe(false);
});
});