fix: wrap telegram reasoning italics per line (#2181)
Landed PR #2181. Thanks @YuriNachos! Co-authored-by: YuriNachos <YuriNachos@users.noreply.github.com>
This commit is contained in:
@@ -37,6 +37,7 @@ Status: unreleased.
|
||||
- macOS: keep custom SSH usernames in remote target. (#2046) Thanks @algal.
|
||||
|
||||
### Fixes
|
||||
- Telegram: wrap reasoning italics per line to avoid raw underscores. (#2181) Thanks @YuriNachos.
|
||||
- Security: harden Tailscale Serve auth by validating identity via local tailscaled before trusting headers.
|
||||
- Build: align memory-core peer dependency with lockfile.
|
||||
- Security: add mDNS discovery mode with minimal default to reduce information disclosure. (#1882) Thanks @orlyjamie.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { AssistantMessage } from "@mariozechner/pi-ai";
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { extractAssistantText } from "./pi-embedded-utils.js";
|
||||
import { extractAssistantText, formatReasoningMessage } from "./pi-embedded-utils.js";
|
||||
|
||||
describe("extractAssistantText", () => {
|
||||
it("strips Minimax tool invocation XML from text", () => {
|
||||
@@ -508,3 +508,41 @@ File contents here`,
|
||||
expect(result).toBe("StartMiddleEnd");
|
||||
});
|
||||
});
|
||||
|
||||
describe("formatReasoningMessage", () => {
|
||||
it("returns empty string for empty input", () => {
|
||||
expect(formatReasoningMessage("")).toBe("");
|
||||
});
|
||||
|
||||
it("returns empty string for whitespace-only input", () => {
|
||||
expect(formatReasoningMessage(" \n \t ")).toBe("");
|
||||
});
|
||||
|
||||
it("wraps single line in italics", () => {
|
||||
expect(formatReasoningMessage("Single line of reasoning")).toBe(
|
||||
"Reasoning:\n_Single line of reasoning_",
|
||||
);
|
||||
});
|
||||
|
||||
it("wraps each line separately for multiline text (Telegram fix)", () => {
|
||||
expect(formatReasoningMessage("Line one\nLine two\nLine three")).toBe(
|
||||
"Reasoning:\n_Line one_\n_Line two_\n_Line three_",
|
||||
);
|
||||
});
|
||||
|
||||
it("preserves empty lines between reasoning text", () => {
|
||||
expect(formatReasoningMessage("First block\n\nSecond block")).toBe(
|
||||
"Reasoning:\n_First block_\n\n_Second block_",
|
||||
);
|
||||
});
|
||||
|
||||
it("handles mixed empty and non-empty lines", () => {
|
||||
expect(formatReasoningMessage("A\n\nB\nC")).toBe("Reasoning:\n_A_\n\n_B_\n_C_");
|
||||
});
|
||||
|
||||
it("trims leading/trailing whitespace", () => {
|
||||
expect(formatReasoningMessage(" \n Reasoning here \n ")).toBe(
|
||||
"Reasoning:\n_Reasoning here_",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -211,7 +211,13 @@ export function formatReasoningMessage(text: string): string {
|
||||
if (!trimmed) return "";
|
||||
// Show reasoning in italics (cursive) for markdown-friendly surfaces (Discord, etc.).
|
||||
// Keep the plain "Reasoning:" prefix so existing parsing/detection keeps working.
|
||||
return `Reasoning:\n_${trimmed}_`;
|
||||
// Note: Underscore markdown cannot span multiple lines on Telegram, so we wrap
|
||||
// each non-empty line separately.
|
||||
const italicLines = trimmed
|
||||
.split("\n")
|
||||
.map((line) => (line ? `_${line}_` : line))
|
||||
.join("\n");
|
||||
return `Reasoning:\n${italicLines}`;
|
||||
}
|
||||
|
||||
type ThinkTaggedSplitBlock =
|
||||
|
||||
@@ -10,7 +10,7 @@ const {
|
||||
disableTailscaleServe,
|
||||
ensureFunnel,
|
||||
} = tailscale;
|
||||
const tailscaleBin = expect.stringMatching(/tailscale$/);
|
||||
const tailscaleBin = expect.stringMatching(/tailscale$/i);
|
||||
|
||||
describe("tailscale helpers", () => {
|
||||
afterEach(() => {
|
||||
|
||||
Reference in New Issue
Block a user