diff --git a/fs/handlers_agent.go b/fs/handlers_agent.go index 17377b8..a97455a 100644 --- a/fs/handlers_agent.go +++ b/fs/handlers_agent.go @@ -139,12 +139,12 @@ func streamAgentChatText(ctx HandlerCtx, cctx context.Context, base string) ([]b } } -// stripMarkers removes [[[...]]] marker lines and source fence lines from raw -// chat data. Partial lines (no trailing \n) are always passed through — they -// are streaming content, never markers. +// stripMarkers removes [[[...]]] marker lines and source fence delimiter lines +// from raw chat data. Content inside fences is preserved — only the ``` lines +// themselves are stripped. Partial lines (no trailing \n) are always passed +// through — they are streaming content, never markers. func stripMarkers(data []byte) []byte { var out []byte - inFence := false for len(data) > 0 { // Find next newline nl := bytes.IndexByte(data, '\n') @@ -162,28 +162,15 @@ func stripMarkers(data []byte) []byte { continue } - // Drop fence open/close lines (``` with optional language suffix) + // Drop bare fence delimiter lines (``` or ```lang). + // These are the source fences wrapping tool output. + // Keep fences with 4+ backticks (````), those are user/assistant markdown. stripped := bytes.TrimSpace(trimmed) - if bytes.HasPrefix(stripped, []byte("```")) { - if inFence { - inFence = false - continue - } - // Opening fence — only drop if it's a source fence (tool output), - // not markdown fences in assistant prose. Tool fences follow - // immediately after a marker line, so if we just dropped a marker - // and this is the next line, it's a source fence. - // Simplification: drop all bare ``` lines (no content on the line). - // Keep fences that are part of assistant markdown (they have text before/after). - if len(stripped) == 3 || (len(stripped) > 3 && stripped[3] != '`') { - inFence = true - continue - } + if bytes.HasPrefix(stripped, []byte("```")) && !bytes.HasPrefix(stripped, []byte("````")) { + continue } - if !inFence { - out = append(out, line...) - } + out = append(out, line...) } return out }