/** * Strip opencode-dcp plugin tags (`mNNNN`) that * the @tarquinen/opencode-dcp plugin appends to assistant text and which * otherwise render as literal text in the UI. * * Why a streaming stripper and not a per-chunk `.replace()`: opencode streams * assistant text token-by-token, so the tag arrives SPLIT across many SSE deltas * (``, `m0019`, `` content. */ const DCP_TAG_RE = /[^<]*<\/dcp-message-id>/g; const OPEN = ''; const CLOSE = ''; /** One-shot strip of COMPLETE tags. Safe for non-streaming / final content. */ export function stripDcpTags(s: string): string { return s.replace(DCP_TAG_RE, ''); } /** * Could `tail` (a substring starting at a `<`) still grow into a complete dcp * tag on a future chunk? If so the caller must hold it back rather than emit it. * Returns false for unrelated `<` content (`
`, ``, …) so those stream * normally. */ function isPartialDcp(tail: string): boolean { // A prefix of the opening marker: '<', '`). for (let i = buf.indexOf('<'); i !== -1; i = buf.indexOf('<', i + 1)) { if (isPartialDcp(buf.slice(i))) { const emit = buf.slice(0, i); buf = buf.slice(i); return emit; } } const emit = buf; buf = ''; return emit; }, flush(): string { const out = stripDcpTags(buf); buf = ''; return out; }, }; }