Skip to content

refactor: unify JSONL line reading across codex, grok, and preview #91

Description

@sorafujitani

Context

The non-trivial "read one JSONL line with a byte cap, skip oversize lines and keep scanning" logic is implemented three times, and the per-line byte caps silently disagree.

Current state (verified locations)

  • internal/codex/codex.go:424 scanJSONLLines + :440 readJSONLLine ([]byte variant), cap jsonlLineCap = 64 MiB at codex.go:25
  • internal/grok/grok.go:454 scanJSONLLines + :470 readJSONLLine — byte-for-byte identical to the codex copy, but cap jsonlLineCap = 16 MiB at grok.go:24
  • internal/preview/preview.go:447 readJSONLLine (string variant), cap previewLineCap = 16 MiB at preview.go:329 (with a good comment explaining why bufio.Scanner was abandoned)

Task

  1. Create a new package internal/jsonl with:
    • func ReadLine(r *bufio.Reader, max int) ([]byte, error) — copy the codex implementation.
    • func ScanLines(r io.Reader, max int, visit func([]byte)) error — copy the codex implementation, taking max as a parameter instead of the package constant.
    • Move the preview comment about bufio.Scanner/ErrBufferFull onto ReadLine so the rationale lives with the shared code.
  2. Migrate codex and grok to jsonl.ScanLines(r, jsonlLineCap, visit); keep each package's existing cap constant and value so behavior is unchanged. Delete the local copies.
  3. Migrate internal/preview to jsonl.ReadLine, converting with string(line) at the call site (loadMessages and anywhere else readJSONLLine is called). Delete the string variant.
  4. Move the line-reading unit tests (search each package's _test.go for oversize-line / buffer-full cases) into internal/jsonl and delete duplicates. Add cases: empty file, line exactly at cap, line over cap followed by a normal line, missing trailing newline.
  5. Do NOT unify the cap values in this issue — leave 64 MiB for codex and 16 MiB for grok/preview, but add a one-line comment at each constant noting the divergence is inherited (a follow-up can reconcile them).

Acceptance criteria

  • Only one implementation of the read/scan logic exists (internal/jsonl).
  • go test ./..., go vet ./..., golangci-lint run, gofmt -l . pass/clean.
  • go test -bench=. ./internal/codex ./internal/grok ./internal/preview shows no regression (±5%).

Metadata

Metadata

Assignees

No one assigned

    Labels

    impact: lowLower or indirect user-visible impactrefactorInternal restructuring with no behavior change

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions