Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions lib/messages/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,8 @@ import type { SessionState, WithParts } from "../state"
import type { UserMessage } from "@opencode-ai/sdk/v2"

const SUMMARY_ID_HASH_LENGTH = 16
const DCP_MESSAGE_ID_TAG_REGEX =
/<dcp-message-id(?=[\s>])[^>]*>(?:m\d+|b\d+|BLOCKED)<\/dcp-message-id>/g
const DCP_BLOCK_ID_TAG_REGEX = /(<dcp-message-id(?=[\s>])[^>]*>)b\d+(<\/dcp-message-id>)/g
const DCP_SYSTEM_REMINDER_REGEX =
/<dcp-system-reminder(?=[\s>])[^>]*>[\s\S]*?<\/dcp-system-reminder>/g
const DCP_ANY_TAG_REGEX = /<dcp[^>]*>[\s\S]*?<\/dcp[^>]*>/gi

const generateStableId = (prefix: string, seed: string): string => {
const hash = createHash("sha256").update(seed).digest("hex").slice(0, SUMMARY_ID_HASH_LENGTH)
Expand Down Expand Up @@ -174,7 +171,7 @@ export const replaceBlockIdsWithBlocked = (text: string): string => {
}

export const stripHallucinationsFromString = (text: string): string => {
return text.replace(DCP_SYSTEM_REMINDER_REGEX, "").replace(DCP_MESSAGE_ID_TAG_REGEX, "")
return text.replace(DCP_ANY_TAG_REGEX, "")
}

export const stripHallucinations = (messages: WithParts[]): void => {
Expand Down
29 changes: 18 additions & 11 deletions tests/message-priority.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -611,25 +611,32 @@ test("range-mode rendered compressed summaries keep block IDs", () => {
assert.doesNotMatch(summaryText, /<dcp-message-id>BLOCKED<\/dcp-message-id>/)
})

test("hallucination stripping removes exact metadata tags and preserves lookalikes", async () => {
test("hallucination stripping removes all dcp-prefixed XML tags including variants", async () => {
const text =
'alpha<dcp-message-id priority="high">m0007</dcp-message-id>' +
"<dcp-message-id>BLOCKED</dcp-message-id>" +
"alpha" +
'<dcp-message-id priority="low">m0008</dcp-message-id>' +
'<dcp-message-id-extra priority="high">m0008</dcp-message-id-extra>' +
'<dcp-system-reminder kind="nudge">remove this</dcp-system-reminder>' +
"<dcp-system-reminder-extra>keep this</dcp-system-reminder-extra>" +
"<dcp-system-reminder>strip this</dcp-system-reminder>" +
"<dcp-system-reminder-extra>strip this too</dcp-system-reminder-extra>" +
"omega"

assert.equal(
stripHallucinationsFromString(text),
'alpha<dcp-message-id-extra priority="high">m0008</dcp-message-id-extra><dcp-system-reminder-extra>keep this</dcp-system-reminder-extra>omega',
)
assert.equal(stripHallucinationsFromString(text), "alphaomega")

const handler = createTextCompleteHandler()
const output = { text }
await handler({ sessionID: "session", messageID: "message", partID: "part" }, output)
assert.equal(output.text, "alphaomega")
})

test("hallucination stripping removes colon and underscore dcp tag variants", async () => {
assert.equal(
stripHallucinationsFromString("before<dcp:message_id>m0074</dcp:message_id>after"),
"beforeafter",
)
assert.equal(
output.text,
'alpha<dcp-message-id-extra priority="high">m0008</dcp-message-id-extra><dcp-system-reminder-extra>keep this</dcp-system-reminder-extra>omega',
stripHallucinationsFromString(
'start<dcp-function_calls><invoke name="Bash"></invoke></dcp-function_calls>end',
),
"startend",
)
})
Loading