Skip to content

Commit 921b6c1

Browse files
fix(agent-runner-memory): use truncateUtf16Safe for memory flush error truncation (#102685)
* fix(agent-runner-memory): use truncateUtf16Safe for memory flush error truncation Replace raw UTF-16 slices in buildMemoryFlushErrorPayload and truncateMemoryFlushErrorMessage with truncateUtf16Safe to prevent surrogate pair splitting in error messages shown to users. 🤖 Generated with [Claude Code](https://claude.com/claude-code) * test(auto-reply): cover UTF-16-safe memory errors * test(auto-reply): tighten UTF-16 memory error coverage --------- Co-authored-by: Peter Steinberger <[email protected]>
1 parent 5013f4a commit 921b6c1

1 file changed

Lines changed: 6 additions & 5 deletions

File tree

src/auto-reply/reply/agent-runner-memory.test.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,7 @@ describe("runMemoryFlushIfNeeded", () => {
476476
const visibleErrorPayloads: Array<{ text?: string; isError?: boolean }> = [];
477477
const token = "sk-abcdefghijklmnopqrstuv";
478478
runWithModelFallbackMock.mockRejectedValueOnce(
479-
new Error(`provider failed with Authorization: Bearer ${token} ${"x".repeat(800)}`),
479+
new Error(`provider failed with Authorization: Bearer ${token} ${"🚀".repeat(400)}`),
480480
);
481481

482482
await runMemoryFlushIfNeeded({
@@ -501,7 +501,7 @@ describe("runMemoryFlushIfNeeded", () => {
501501
expect(payload?.text).toMatch(/^ provider failed with Authorization: Bearer /);
502502
expect(payload?.text).not.toContain(token);
503503
expect(payload?.text?.length).toBeLessThanOrEqual(600);
504-
expect(payload?.text?.endsWith("…")).toBe(true);
504+
expect(payload?.text?.endsWith("🚀…")).toBe(true);
505505
});
506506

507507
it("does not surface user-abort errors as visible payloads (regression: #80755)", async () => {
@@ -536,7 +536,7 @@ describe("runMemoryFlushIfNeeded", () => {
536536
expect(visibleErrorPayloads).toEqual([]);
537537
});
538538

539-
it("increments memoryFlushFailureCount on non-abort flush failure", async () => {
539+
it("increments and UTF-16-safely persists a capped non-abort flush failure", async () => {
540540
const storePath = path.join(rootDir, "sessions.json");
541541
const sessionEntry: SessionEntry = {
542542
sessionId: "session",
@@ -545,7 +545,8 @@ describe("runMemoryFlushIfNeeded", () => {
545545
compactionCount: 1,
546546
};
547547
await writeTestSessionStore(storePath, "main", sessionEntry);
548-
runWithModelFallbackMock.mockRejectedValueOnce(new Error("provider crashed during flush"));
548+
const failureMessage = `${"a".repeat(198)}🚀tail`;
549+
runWithModelFallbackMock.mockRejectedValueOnce(new Error(failureMessage));
549550

550551
const result = await runMemoryFlushIfNeeded({
551552
cfg: { agents: { defaults: { compaction: { memoryFlush: {} } } } },
@@ -566,7 +567,7 @@ describe("runMemoryFlushIfNeeded", () => {
566567
expect(result.outcome).toBe("failed");
567568
expect(persisted.main.memoryFlushFailureCount).toBe(1);
568569
expect(persisted.main.memoryFlushLastFailedAt).toBe(1_700_000_000_000);
569-
expect(persisted.main.memoryFlushLastFailureError).toContain("provider crashed during flush");
570+
expect(persisted.main.memoryFlushLastFailureError).toBe(`${"a".repeat(198)}…`);
570571
expect(emitAgentEventMock).toHaveBeenCalledWith(
571572
expect.objectContaining({
572573
stream: "lifecycle",

0 commit comments

Comments
 (0)