```ts
/** Cut a chunked stream into frames at a marker, doubled to escape it. */
export function drainFrames(chunks: string[], marker: string): { frames: string[]; pending: string } {
  if (typeof marker !== "string" || marker.length !== 1) {
    throw new Error("marker must be a single character");
  }
  const buffer = chunks.join("");
  let frame = "";
  let pending = "";
  for (let i = 0; i < buffer.length; i++) {
    if (buffer[i] === marker) {
      if (i + 1 < buffer.length && buffer[i + 1] === marker) {
        // Double marker, fold into one literal marker
        frame += marker;
        i++;
      } else {
        // End of a frame
        frames.push(frame);
        frame = "";
      }
    } else {
      // Add to current frame
      frame += buffer[i];
    }
  }
  pending = frame; // Remaining text after the last frame or dangling marker
  return { frames, pending };
}
```