Skip to content

Commit 87c231e

Browse files
committed
Sanitize leaked tool-call wire format in assistant text
1 parent 5887821 commit 87c231e

File tree

2 files changed

+22
-0
lines changed

2 files changed

+22
-0
lines changed

internal/adapter/openai/tool_history_sanitize.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,18 @@ import (
66

77
var leakedToolHistoryPattern = regexp.MustCompile(`(?is)\[TOOL_CALL_HISTORY\][\s\S]*?\[/TOOL_CALL_HISTORY\]|\[TOOL_RESULT_HISTORY\][\s\S]*?\[/TOOL_RESULT_HISTORY\]`)
88
var emptyJSONFencePattern = regexp.MustCompile("(?is)```json\\s*```")
9+
var leakedToolCallArrayPattern = regexp.MustCompile(`(?is)\[\{\s*"function"\s*:\s*\{[\s\S]*?\}\s*,\s*"id"\s*:\s*"call[^"]*"\s*,\s*"type"\s*:\s*"function"\s*}\]`)
10+
var leakedToolResultBlobPattern = regexp.MustCompile(`(?is)<\s*\|\s*tool\s*\|\s*>\s*\{[\s\S]*?"tool_call_id"\s*:\s*"call[^"]*"\s*}`)
11+
var leakedMetaMarkerPattern = regexp.MustCompile(`(?is)<\s*\|\s*(?:assistant|tool|end_of_sentence|end_of_thinking)\s*\|\s*>`)
912

1013
func sanitizeLeakedToolHistory(text string) string {
1114
if text == "" {
1215
return text
1316
}
1417
out := leakedToolHistoryPattern.ReplaceAllString(text, "")
1518
out = emptyJSONFencePattern.ReplaceAllString(out, "")
19+
out = leakedToolCallArrayPattern.ReplaceAllString(out, "")
20+
out = leakedToolResultBlobPattern.ReplaceAllString(out, "")
21+
out = leakedMetaMarkerPattern.ReplaceAllString(out, "")
1622
return out
1723
}

internal/adapter/openai/tool_history_sanitize_test.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,22 @@ func TestFlushToolSieveDropsToolResultHistoryLeak(t *testing.T) {
7777
}
7878
}
7979

80+
func TestSanitizeLeakedToolHistoryRemovesLeakedWireToolCallAndResult(t *testing.T) {
81+
raw := "开始\n[{\"function\":{\"arguments\":\"{\\\"command\\\":\\\"java -version\\\"}\",\"name\":\"exec\"},\"id\":\"callb9a321\",\"type\":\"function\"}]< | Tool | >{\"content\":\"openjdk version 21\",\"tool_call_id\":\"callb9a321\"}\n结束"
82+
got := sanitizeLeakedToolHistory(raw)
83+
if got != "开始\n\n结束" {
84+
t.Fatalf("unexpected sanitize result for leaked wire format: %q", got)
85+
}
86+
}
87+
88+
func TestSanitizeLeakedToolHistoryRemovesStandaloneMetaMarkers(t *testing.T) {
89+
raw := "A<| end_of_sentence |><| Assistant |>B<| end_of_thinking |>C"
90+
got := sanitizeLeakedToolHistory(raw)
91+
if got != "ABC" {
92+
t.Fatalf("unexpected sanitize result for meta markers: %q", got)
93+
}
94+
}
95+
8096
func TestProcessToolSieveChunkSplitsResultHistoryBoundary(t *testing.T) {
8197
var state toolStreamSieveState
8298
parts := []string{

0 commit comments

Comments
 (0)