@in-the-loop-labs/pair-review 3.9.1 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -65,7 +65,7 @@ pair-review is a local web application for keeping humans in the loop with AI co
65
65
  - **Local-First**: All data and processing happens on your machine - no cloud dependencies
66
66
  - **GitHub-Familiar UI**: Interface feels instantly familiar to GitHub users
67
67
  - **Human-in-the-Loop**: AI suggests, you decide
68
- - **Multiple AI Providers**: Support for Claude, Gemini, Codex, Copilot, OpenCode, Cursor, and Pi. Use your existing subscription!
68
+ - **Multiple AI Providers**: Support for Claude, Antigravity, Codex, Copilot, OpenCode, Cursor, and Pi. Use your existing subscription!
69
69
  - **Progressive**: Start simple with manual review, add AI analysis when you need it
70
70
 
71
71
  ## Workflows
@@ -437,7 +437,7 @@ pair-review supports several environment variables for customizing behavior:
437
437
  |----------|-------------|---------|
438
438
  | `GITHUB_TOKEN` | GitHub Personal Access Token (takes precedence over config file) | - |
439
439
  | `PAIR_REVIEW_CLAUDE_CMD` | Custom command to invoke Claude CLI | `claude` |
440
- | `PAIR_REVIEW_GEMINI_CMD` | Custom command to invoke Gemini CLI | `gemini` |
440
+ | `PAIR_REVIEW_ANTIGRAVITY_CMD` | Custom command to invoke Antigravity CLI | `agy` |
441
441
  | `PAIR_REVIEW_CODEX_CMD` | Custom command to invoke Codex CLI | `codex` |
442
442
  | `PAIR_REVIEW_COPILOT_CMD` | Custom command to invoke Copilot CLI | `copilot` |
443
443
  | `PAIR_REVIEW_OPENCODE_CMD` | Custom command to invoke OpenCode CLI | `opencode` |
@@ -466,8 +466,8 @@ PAIR_REVIEW_CLAUDE_CMD="/usr/local/bin/claude" pair-review 123
466
466
  # Use a wrapper command (supports multi-word commands)
467
467
  PAIR_REVIEW_CLAUDE_CMD="devx claude" pair-review 123
468
468
 
469
- # Use Gemini with npx
470
- PAIR_REVIEW_GEMINI_CMD="npx gemini" pair-review --local
469
+ # Use a custom path for the Antigravity CLI
470
+ PAIR_REVIEW_ANTIGRAVITY_CMD="/usr/local/bin/agy" pair-review --local
471
471
 
472
472
  # Force a specific model for this review
473
473
  PAIR_REVIEW_MODEL="opus" pair-review 123
@@ -491,7 +491,7 @@ Create a Personal Access Token (PAT) with these scopes:
491
491
  pair-review integrates with AI providers via their CLI tools:
492
492
 
493
493
  - **Claude**: Uses Claude Code CLI
494
- - **Gemini**: Uses Gemini CLI
494
+ - **Antigravity**: Uses the Antigravity CLI (`agy`), the successor to the Gemini CLI. Install it with `curl -fsSL https://antigravity.google/cli/install.sh | bash` (macOS/Linux; it is not an npm package) — see the [Antigravity docs](https://antigravity.google/docs). Antigravity is an analysis-only provider: it runs as an agentic reviewer in non-interactive print mode and has **no chat/ACP mode**.
495
495
  - **Codex**: Uses Codex CLI
496
496
  - **GitHub Copilot**: Uses Copilot CLI
497
497
  - **OpenCode**: Uses OpenCode CLI (requires model configuration)
@@ -502,7 +502,7 @@ You can select your preferred provider and model in the repository settings UI.
502
502
 
503
503
  #### Built-in vs. Configurable Providers
504
504
 
505
- Most providers (Claude, Gemini, Codex, Copilot) come with built-in model definitions. **OpenCode and Pi are different** - they have no built-in models and require you to configure which models to use.
505
+ Most providers (Claude, Antigravity, Codex, Copilot) come with built-in model definitions. **OpenCode and Pi are different** - they have no built-in models and require you to configure which models to use.
506
506
 
507
507
  #### Configuring Custom Models
508
508
 
@@ -648,7 +648,7 @@ The key difference from Review Council is consolidation order: Advanced consolid
648
648
 
649
649
  - **Large changesets with Opus 4.6**: Use review council instructions to tell the model to use a Team — it will spawn sub-agents to divide the work
650
650
  - **Multi-model parallel review**: Give each model a specific focus area (security, performance, correctness) via per-model instructions and get combined results
651
- - **Cross-model perspectives**: Run the same analysis across different providers (e.g., Claude, Gemini, GPT) — where models agree signals high-confidence findings, but unique outliers from a single model can be equally valuable, catching issue types that only that model excels at spotting
651
+ - **Cross-model perspectives**: Run the same analysis across different providers (e.g., Claude, Antigravity, GPT) — where models agree signals high-confidence findings, but unique outliers from a single model can be equally valuable, catching issue types that only that model excels at spotting
652
652
 
653
653
  ### Chat
654
654
 
@@ -683,7 +683,7 @@ Configure your preferred models in `providers.pi.models` — see [AI Provider Co
683
683
  }
684
684
  ```
685
685
 
686
- Available chat provider IDs: `pi`, `claude`, `codex`, `copilot-acp`, `gemini-acp`, `opencode-acp`, `cursor-acp`. Each supports `command`, `args` (replaces defaults), `extra_args` (appends), and `env` overrides. Codex chat also supports `sandbox`: use `workspace-write` by default, or `read-only` for discussion-only sessions.
686
+ Available chat provider IDs: `pi`, `claude`, `codex`, `copilot-acp`, `opencode-acp`, `cursor-acp`. Each supports `command`, `args` (replaces defaults), `extra_args` (appends), and `env` overrides. Codex chat also supports `sandbox`: use `workspace-write` by default, or `read-only` for discussion-only sessions. (Antigravity is an analysis-only provider — it has no ACP mode, so there is no Antigravity chat provider.)
687
687
 
688
688
  **Keyboard shortcut:** Press `p` then `c` to toggle the chat panel.
689
689
 
@@ -959,8 +959,8 @@ These commands update your MCP configuration in `~/.claude/settings.json` (user-
959
959
 
960
960
  ### Prerequisites
961
961
 
962
- - Node.js 20.0.0 or higher
963
- - [pnpm](https://pnpm.io/) 10.x
962
+ - Node.js 22.0.0 or higher
963
+ - [pnpm](https://pnpm.io/) 11.x
964
964
  - Git
965
965
 
966
966
  ### Running Locally
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@in-the-loop-labs/pair-review",
3
- "version": "3.9.1",
3
+ "version": "4.0.0",
4
4
  "description": "Your AI-powered code review partner - Close the feedback loop with AI coding agents",
5
5
  "main": "src/server.js",
6
6
  "bin": {
@@ -19,8 +19,9 @@
19
19
  "LICENSE"
20
20
  ],
21
21
  "engines": {
22
- "node": ">=20.0.0"
22
+ "node": ">=22.0.0"
23
23
  },
24
+ "packageManager": "pnpm@11.9.0",
24
25
  "scripts": {
25
26
  "start": "node src/server.js",
26
27
  "dev": "node bin/pair-review.js",
@@ -47,7 +48,7 @@
47
48
  "cursor",
48
49
  "copilot",
49
50
  "codex",
50
- "gemini"
51
+ "antigravity"
51
52
  ],
52
53
  "author": "Tim Perkins",
53
54
  "license": "Apache-2.0",
@@ -63,7 +64,7 @@
63
64
  "@agentclientprotocol/sdk": "^0.14.1",
64
65
  "@modelcontextprotocol/sdk": "^1.25.3",
65
66
  "@octokit/rest": "^19.0.11",
66
- "better-sqlite3": "^11.8.1",
67
+ "better-sqlite3": "^12.11.1",
67
68
  "express": "^4.18.2",
68
69
  "glob": "^13.0.6",
69
70
  "markdown-it": "^13.0.2",
@@ -83,10 +84,5 @@
83
84
  "jsdom": "^29.0.1",
84
85
  "supertest": "^7.1.4",
85
86
  "vitest": "^4.0.16"
86
- },
87
- "pnpm": {
88
- "onlyBuiltDependencies": [
89
- "better-sqlite3"
90
- ]
91
87
  }
92
88
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pair-review",
3
- "version": "3.9.1",
3
+ "version": "4.0.0",
4
4
  "description": "pair-review app integration — Open PRs and local changes in the pair-review web UI, run server-side AI analysis, and address review feedback. Requires the pair-review MCP server.",
5
5
  "author": {
6
6
  "name": "in-the-loop-labs",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "code-critic",
3
- "version": "3.9.1",
3
+ "version": "4.0.0",
4
4
  "description": "AI-powered code review analysis — Run three-level AI analysis and implement-review-fix loops directly in your coding agent. Works standalone, no server required.",
5
5
  "author": {
6
6
  "name": "in-the-loop-labs",
@@ -170,7 +170,7 @@ class AdvancedConfigTab {
170
170
  /**
171
171
  * Set default orchestration provider/model for new councils.
172
172
  * Falls back to 'claude'/'sonnet' if not provided.
173
- * @param {string} provider - Default provider ID (e.g., 'claude', 'gemini')
173
+ * @param {string} provider - Default provider ID (e.g., 'claude', 'antigravity')
174
174
  * @param {string} model - Default model ID (e.g., 'sonnet', 'opus')
175
175
  */
176
176
  setDefaultOrchestration(provider, model) {
@@ -627,7 +627,7 @@ class AnalysisConfigModal {
627
627
  selectModel(modelId) {
628
628
  // Guard: never store a model that doesn't belong to the current provider.
629
629
  // Callers can pass a model resolved from a different scope (e.g. 'opus'
630
- // while the provider is 'gemini'); fall back to the provider's default so
630
+ // while the provider is 'antigravity'); fall back to the provider's default so
631
631
  // the UI always shows a selected card and submissions carry a valid pair.
632
632
  if (modelId && this.models.length && !this.models.some(m => m.id === modelId)) {
633
633
  const fallback = this.models.find(m => m.default) || this.models[0];
@@ -952,7 +952,7 @@ class AnalysisConfigModal {
952
952
  }
953
953
  // Only honour currentModel when it belongs to the selected provider.
954
954
  // selectProvider() has already chosen a valid model for the provider (via
955
- // tier matching); applying a foreign model here (e.g. 'opus' under 'gemini')
955
+ // tier matching); applying a foreign model here (e.g. 'opus' under 'antigravity')
956
956
  // would leave no model card selected and submit an invalid pair.
957
957
  if (options.currentModel && this.models.some(m => m.id === options.currentModel)) {
958
958
  this.selectModel(options.currentModel);
@@ -346,7 +346,7 @@ class LocalManager {
346
346
  const lastCouncilId = reviewSettings.last_council_id;
347
347
 
348
348
  // Resolve provider and model as a MATCHED pair so the council/advanced tabs
349
- // are never seeded with a cross-provider model (e.g. gemini + opus), which
349
+ // are never seeded with a cross-provider model (e.g. antigravity + opus), which
350
350
  // would blank the model <select> and be rejected by the backend.
351
351
  const providersInfo = await manager._getProvidersInfo();
352
352
  const { provider: currentProvider, model: currentModel } = window.resolveProviderModelPair([
package/public/js/pr.js CHANGED
@@ -704,7 +704,7 @@ class PRManager {
704
704
  // Resolve provider and model as a MATCHED pair. Resolving each half
705
705
  // independently (repo || app || hardcoded) can mix a provider from one
706
706
  // scope with a model from another, yielding an invalid pair (e.g.
707
- // gemini/opus) that startAnalysis would forward to the backend as-is.
707
+ // antigravity/opus) that startAnalysis would forward to the backend as-is.
708
708
  const providers = providersInfo || await this._getProvidersInfo();
709
709
  const { provider, model } = window.resolveProviderModelPair([
710
710
  { provider: repoSettings?.default_provider, model: repoSettings?.default_model },
@@ -3053,7 +3053,7 @@ class PRManager {
3053
3053
  ]);
3054
3054
 
3055
3055
  // Resolve provider and model as a MATCHED pair so the council/advanced tabs
3056
- // are never seeded with a cross-provider model (e.g. gemini + opus), which
3056
+ // are never seeded with a cross-provider model (e.g. antigravity + opus), which
3057
3057
  // would blank the model <select> and be rejected by the backend.
3058
3058
  const providersInfo = await this._getProvidersInfo();
3059
3059
  const { provider: currentProvider, model: currentModel } = window.resolveProviderModelPair([
@@ -6846,7 +6846,7 @@ class PRManager {
6846
6846
  const lastCouncilId = reviewSettings.last_council_id;
6847
6847
 
6848
6848
  // Resolve provider and model as a MATCHED pair so the council/advanced tabs
6849
- // are never seeded with a cross-provider model (e.g. gemini + opus), which
6849
+ // are never seeded with a cross-provider model (e.g. antigravity + opus), which
6850
6850
  // would blank the model <select> and be rejected by the backend.
6851
6851
  const providersInfo = await this._getProvidersInfo();
6852
6852
  const { provider: currentProvider, model: currentModel } = window.resolveProviderModelPair([
@@ -6,7 +6,7 @@
6
6
  * settings, then app config) and historically each half was resolved
7
7
  * independently with `repo || app || hardcoded`. When a scope overrides only
8
8
  * ONE half, the halves can come from different scopes and produce an invalid
9
- * pair such as `gemini` + `opus` (an Anthropic model). The modal then shows no
9
+ * pair such as `antigravity` + `opus` (an Anthropic model). The modal then shows no
10
10
  * selected model, and the non-modal auto-analyze path posts the broken pair
11
11
  * straight to the backend.
12
12
  *
@@ -342,8 +342,8 @@ A suggestion is a duplicate if it targets the same file and overlapping lines an
342
342
  class Analyzer {
343
343
  /**
344
344
  * @param {Object} database - Database instance
345
- * @param {string} model - Model to use (e.g., 'opus', 'gemini-2.5-pro')
346
- * @param {string} provider - Provider ID (e.g., 'claude', 'gemini'). Defaults to 'claude'.
345
+ * @param {string} model - Model to use (e.g., 'opus', 'gemini-3.1-pro-low')
346
+ * @param {string} provider - Provider ID (e.g., 'claude', 'antigravity'). Defaults to 'claude'.
347
347
  * @param {Object} providerOverrides - Per-call config overrides passed to createProvider (optional)
348
348
  * @param {Object|null} providerOverridesMap - Per-provider overrides map for council mode (provider ID → overrides)
349
349
  */
@@ -860,8 +860,8 @@ class Analyzer {
860
860
  *
861
861
  * Uses the bare command name since BIN_DIR is added to PATH in all
862
862
  * providers. Using the absolute path causes issues with AI providers
863
- * that pattern-match allowed tools (e.g., Gemini only matches
864
- * 'git-diff-lines', not the full path).
863
+ * that pattern-match allowed shell commands by their bare command name
864
+ * (matching 'git-diff-lines', not the full path).
865
865
  *
866
866
  * @param {string|null} worktreePath - Path to the git worktree
867
867
  * @returns {string} e.g. `git-diff-lines` or `git-diff-lines --cwd "/path"`