Skip to content

Feat/ai orchestrator token opt#23

Merged
afewyards merged 21 commits into
mainfrom
feat/ai-orchestrator-token-opt
May 13, 2026
Merged

Feat/ai orchestrator token opt#23
afewyards merged 21 commits into
mainfrom
feat/ai-orchestrator-token-opt

Conversation

@afewyards

Copy link
Copy Markdown
Owner

Reduces AI review token usage and introduces a new :CodeReviewPlan command that reuses the same orchestration. Also fixes #22.

:CodeReviewPlan (new)

  • New entrypoint and :CodeReviewPlan user command for AI-generated implementation plans from a branch diff.
  • Shared orchestrator extracted from plan/review so both code paths share file filtering, batching, progress, and provider plumbing.
  • Git branch utilities + prompt module + integration tests.

Token optimization

  • Batching: files are packed into a single AI call up to a configurable token budget instead of one call per file.
  • Cache-friendly prompt order with Anthropic cache_control markers so prompt prefixes stay cacheable across runs.
  • Dropped per-file Branch Context and the Phase 1 summary — both were redundant under the new prompt structure.
  • Skip rules: lockfiles, generated, vendored, and binary diffs are skipped by default.
  • Configurable ai_skip_patterns via .codereview.nvim dotfile, parsed in auth and merged into orchestrator + review init. Shared helper in file_filter.
  • Per-file progress for CLI providers so long batched calls remain visible.

Bug fixes

  • fix(api): JSON null from GitLab (e.g. empty MR description) now decodes to Lua nil instead of vim.NIL userdata, fixing the attempt to concatenate a userdata value crash when opening :CodeReview on a repo with several MRs. Fixes Opening CodeReview on repository with several merge requests fails with formatting #22.
  • fix(ai): URL encoding and glob pattern matching bugs in skip-pattern handling.
  • fix(ai): filtered-files spinner state, progress race, and parser fallback (from earlier code-review pass).
  • fix(plan): handle nil paths and limit concurrent AI calls.

afewyards added 21 commits May 13, 2026 20:48
- Add spinner.start/stop aliases for plan module compatibility
- Extract path from diff --git line as fallback in git parser
- Defensive nil handling for file paths in prompt builder
- Limit to max 10 concurrent AI calls with queue-based processing
Adds a tmp-file-backed progress tracker that CLI agents append to as they
finish each file. The orchestrator polls every 250ms and emits on_progress(done,
total) so plan and review spinners reflect real-time per-file progress.
HTTP providers (anthropic, openai, ollama) are unaffected and continue using
the existing per-batch on_batch_complete counter.
Pack diffs into batches by char budget (default 80 000 chars / 15 files)
before sending to the AI provider. Amortises instruction overhead across
files, cutting AI calls on large MRs to a fraction of the old per-file
count. Review uses a tighter per-spec budget (40 000 / 8) because full
file content is included alongside diffs.

- Add lua/codereview/ai/batch.lua: M.build(diffs, opts) greedy packer
- Add ai.batch_char_budget (80 000) and ai.batch_max_files (15) defaults
- Orchestrator: replace 1-file-per-batch loop with batch.build(); per-spec
  overrides (spec.batch_char_budget / spec.batch_max_files) take priority
- plan/prompt: add build_batch_plan_prompt(files, opts)
- ai/prompt: add build_batch_review_prompt(review, files, contents, opts)
- plan/init: swap build_prompt to batch variant; spinner counts files not batches
- review/init: swap to batch variant; pre-fetch content per file in batch;
  ai_file_done() called N times (once per file in batch)
- Tests: batch_spec (TDD), orchestrator_spec updated, integration_spec asserts
  5 small files → 1 batch
- gitlab.lua: properly URL-encode file paths with spaces/special chars
- file_filter.lua: fix glob_to_pat null-byte placeholder corruption

The glob pattern `\0DBL\0` placeholder was interpreted by Lua's gsub
as matching every position, corrupting patterns like `*.json` into
garbage. Replaced with `<<<DBL>>>` string placeholder.
GitLab returns `description: null` for MRs with no description. By
default `vim.json.decode` maps JSON null to `vim.NIL` (userdata), which
is truthy — so existing `or ""` guards in `types.normalize_review` and
`format_mr_preview` passed it through unchanged, causing
`attempt to concatenate a userdata value` when the picker rendered the
preview.

Pass `{ luanil = { object = true, array = true } }` to all
`vim.json.decode` call sites so null becomes nil throughout. Existing
`~= vim.NIL` checks in github.lua remain correct (nil ~= vim.NIL).

Fixes #22
@afewyards afewyards merged commit 22ceaa3 into main May 13, 2026
3 checks passed
@afewyards afewyards deleted the feat/ai-orchestrator-token-opt branch May 13, 2026 19:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Opening CodeReview on repository with several merge requests fails with formatting

1 participant