Skip to content

Commit 425339f

Browse files
committed
reset message ids after /compact
Clear DCP message alias state when native compaction is detected so refs rebuild from the compacted conversation instead of continuing toward m9999.
1 parent 90d4089 commit 425339f

2 files changed

Lines changed: 94 additions & 0 deletions

File tree

lib/state/utils.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,11 @@ export function resetOnCompaction(state: SessionState): void {
280280
state.toolParameters.clear()
281281
state.prune.tools = new Map<string, number>()
282282
state.prune.messages = createPruneMessagesState()
283+
state.messageIds = {
284+
byRawId: new Map<string, string>(),
285+
byRef: new Map<string, string>(),
286+
nextRef: 1,
287+
}
283288
state.nudges = {
284289
contextLimitAnchors: new Set<string>(),
285290
turnNudgeAnchors: new Set<string>(),

tests/message-ids.test.ts

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import assert from "node:assert/strict"
2+
import test from "node:test"
3+
import { Logger } from "../lib/logger"
4+
import { assignMessageRefs } from "../lib/message-ids"
5+
import { checkSession, createSessionState, type WithParts } from "../lib/state"
6+
7+
function textPart(messageID: string, sessionID: string, id: string, text: string) {
8+
return {
9+
id,
10+
messageID,
11+
sessionID,
12+
type: "text" as const,
13+
text,
14+
}
15+
}
16+
17+
function buildCompactedMessages(sessionID: string): WithParts[] {
18+
return [
19+
{
20+
info: {
21+
id: "msg-assistant-summary",
22+
role: "assistant",
23+
sessionID,
24+
agent: "assistant",
25+
summary: true,
26+
time: { created: 2 },
27+
} as WithParts["info"],
28+
parts: [
29+
textPart(
30+
"msg-assistant-summary",
31+
sessionID,
32+
"msg-assistant-summary-part",
33+
"Compaction summary",
34+
),
35+
],
36+
},
37+
{
38+
info: {
39+
id: "msg-user-follow-up",
40+
role: "user",
41+
sessionID,
42+
agent: "assistant",
43+
model: {
44+
providerID: "anthropic",
45+
modelID: "claude-test",
46+
},
47+
time: { created: 3 },
48+
} as WithParts["info"],
49+
parts: [
50+
textPart(
51+
"msg-user-follow-up",
52+
sessionID,
53+
"msg-user-follow-up-part",
54+
"Continue after compaction",
55+
),
56+
],
57+
},
58+
]
59+
}
60+
61+
test("checkSession resets message id aliases after native compaction", async () => {
62+
const sessionID = `ses_message_ids_after_compaction_${Date.now()}`
63+
const messages = buildCompactedMessages(sessionID)
64+
const state = createSessionState()
65+
const logger = new Logger(false)
66+
67+
state.sessionId = sessionID
68+
state.messageIds.byRawId.set("old-message-9998", "m9998")
69+
state.messageIds.byRawId.set("old-message-9999", "m9999")
70+
state.messageIds.byRef.set("m9998", "old-message-9998")
71+
state.messageIds.byRef.set("m9999", "old-message-9999")
72+
state.messageIds.nextRef = 9999
73+
74+
await checkSession({} as any, state, logger, messages, false)
75+
76+
assert.equal(state.lastCompaction, 2)
77+
assert.equal(state.messageIds.byRawId.size, 0)
78+
assert.equal(state.messageIds.byRef.size, 0)
79+
assert.equal(state.messageIds.nextRef, 1)
80+
81+
const assigned = assignMessageRefs(state, messages)
82+
83+
assert.equal(assigned, 2)
84+
assert.equal(state.messageIds.byRawId.get("msg-assistant-summary"), "m0001")
85+
assert.equal(state.messageIds.byRawId.get("msg-user-follow-up"), "m0002")
86+
assert.equal(state.messageIds.byRef.get("m0001"), "msg-assistant-summary")
87+
assert.equal(state.messageIds.byRef.get("m0002"), "msg-user-follow-up")
88+
assert.equal(state.messageIds.nextRef, 3)
89+
})

0 commit comments

Comments
 (0)