```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("");
  const frames: string[] = [];
  let pending = "";
  let i = 0;

  while (i < buffer.length) {
    if (buffer[i] === marker) {
      if (i + 1 < buffer.length && buffer[i + 1] === marker) {
        // Escaped marker, move past the second character
        frames.push(pending);
        pending = "";
        i += 2;
      } else {
        // Lone marker, end current frame and start new one
        if (pending !== "") {
          frames.push(pending);
          pending = "";
        }
        i++;
      }
    } else {
      // Regular character, add to current frame
      pending += buffer[i];
      i++;
    }
  }

  return { frames, pending };
}
```