Skip to content

Commit c0d7015

Browse files
fix(active-memory): bound timeout partials safely
Co-authored-by: 张贵萍0668001030 <[email protected]>
1 parent 98ae0ec commit c0d7015

2 files changed

Lines changed: 49 additions & 8 deletions

File tree

extensions/active-memory/index.test.ts

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3201,6 +3201,47 @@ describe("active-memory plugin", () => {
32013201
expect(readFileSpy).not.toHaveBeenCalled();
32023202
});
32033203

3204+
it("keeps partial assistant transcript caps UTF-16 safe", async () => {
3205+
const sessionFile = path.join(stateDir, "surrogate-timeout-transcript.jsonl");
3206+
await writeTranscriptJsonl(sessionFile, [
3207+
{
3208+
type: "message",
3209+
message: {
3210+
role: "assistant",
3211+
content: `${"a".repeat(38)}🎉TAILWORD`,
3212+
},
3213+
},
3214+
]);
3215+
3216+
const result = await testing.readPartialAssistantText(sessionFile, {
3217+
maxChars: 39,
3218+
maxLines: 10,
3219+
});
3220+
3221+
expect(result).toBe("a".repeat(38));
3222+
});
3223+
3224+
it("keeps joined partial assistant transcript caps UTF-16 safe", async () => {
3225+
const sessionFile = path.join(stateDir, "joined-surrogate-timeout-transcript.jsonl");
3226+
await writeTranscriptJsonl(sessionFile, [
3227+
{
3228+
type: "message",
3229+
message: { role: "assistant", content: "a".repeat(37) },
3230+
},
3231+
{
3232+
type: "message",
3233+
message: { role: "assistant", content: "🎉TAILWORD" },
3234+
},
3235+
]);
3236+
3237+
const result = await testing.readPartialAssistantText(sessionFile, {
3238+
maxChars: 39,
3239+
maxLines: 10,
3240+
});
3241+
3242+
expect(result).toBe("a".repeat(37));
3243+
});
3244+
32043245
it("skips malformed JSONL lines when reading partial assistant transcripts", async () => {
32053246
const sessionFile = path.join(stateDir, "malformed-timeout-transcript.jsonl");
32063247
await fs.mkdir(path.dirname(sessionFile), { recursive: true });

extensions/active-memory/index.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2251,20 +2251,20 @@ async function readPartialAssistantText(
22512251
if (remaining <= 0) {
22522252
return true;
22532253
}
2254-
const nextText = text.slice(0, remaining);
2254+
const nextText = truncateUtf16Safe(text, remaining);
2255+
if (!nextText) {
2256+
return true;
2257+
}
22552258
texts.push(nextText);
22562259
collectedChars += separatorChars + nextText.length;
2257-
return collectedChars >= resolvedLimits.maxChars;
2260+
// A surrogate backoff leaves spare code units; stop instead of skipping ahead.
2261+
return nextText.length < text.length || collectedChars >= resolvedLimits.maxChars;
22582262
}
22592263
return false;
22602264
},
22612265
});
2262-
const joined = texts
2263-
.map((text) => text.trim())
2264-
.filter(Boolean)
2265-
.join("\n")
2266-
.slice(0, resolvedLimits.maxChars)
2267-
.trim();
2266+
// Accepted chunks and separators are charged before append, so the join is already bounded.
2267+
const joined = texts.join("\n").trim();
22682268
return joined || null;
22692269
}
22702270

0 commit comments

Comments
 (0)