@in-the-loop-labs/pair-review 3.3.5 → 3.3.7

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.
@@ -23,31 +23,65 @@ const BIN_DIR = path.join(__dirname, '..', '..', 'bin');
23
23
  * Based on OpenAI Codex Models guide (developers.openai.com/codex/models)
24
24
  * - gpt-5.4-nano: Cheapest model ($0.20/$1.25 per MTok), good for surface scans
25
25
  * - gpt-5.4-mini: Fast with 400k context ($0.75/$4.50 per MTok)
26
- * - gpt-5.4: Flagship model combining coding, reasoning, and agentic workflows
27
26
  * - gpt-5.3-codex: Industry-leading coding model for complex engineering tasks
27
+ * - gpt-5.4 / gpt-5.5: Exposed only via -high / -xhigh reasoning variants so the
28
+ * selected effort level is always explicit.
29
+ *
30
+ * Reasoning-effort variants (-high / -xhigh) use `cli_model` to pass the base
31
+ * model ID to `codex exec -m` and add `-c model_reasoning_effort="..."` via
32
+ * extra_args so Codex picks up the effort level through its config override.
28
33
  *
29
34
  * Deprecated (April 2026): gpt-5.1-codex-mini, gpt-5.1-codex-max, gpt-5.1-codex
30
35
  */
31
36
  const CODEX_MODELS = [
32
37
  {
33
- id: 'gpt-5.4-nano',
34
- name: 'GPT-5.4 Nano',
35
- tier: 'fast',
36
- tagline: 'Cheapest',
37
- description: 'Ultra-low-cost surface scans for style issues, obvious bugs, and lint-level feedback.',
38
- badge: 'Cheapest',
39
- badgeClass: 'badge-speed'
40
- },
41
- {
42
- id: 'gpt-5.4-mini',
43
- name: 'GPT-5.4 Mini',
44
- tier: 'balanced',
45
- tagline: 'Best Balance',
46
- description: 'Fast reviews with 400k context—good balance of speed and capability for everyday PR review.',
38
+ id: 'gpt-5.4-high',
39
+ // Alias keeps results/councils saved under the previous bare `gpt-5.4`
40
+ // model ID resolving to the now-explicit high-effort variant.
41
+ aliases: ['gpt-5.4'],
42
+ cli_model: 'gpt-5.4',
43
+ extra_args: ['-c', 'model_reasoning_effort="high"'],
44
+ name: 'GPT-5.4 High',
45
+ tier: 'thorough',
46
+ tagline: 'Deep Review',
47
+ description: 'GPT-5.4 with high reasoning effort for complex multi-file reviews, architectural consistency, and subtle behavioral regressions.',
47
48
  badge: 'Recommended',
48
49
  badgeClass: 'badge-recommended',
49
50
  default: true
50
51
  },
52
+ {
53
+ id: 'gpt-5.4-xhigh',
54
+ cli_model: 'gpt-5.4',
55
+ extra_args: ['-c', 'model_reasoning_effort="xhigh"'],
56
+ name: 'GPT-5.4 XHigh',
57
+ tier: 'thorough',
58
+ tagline: 'Max Depth',
59
+ description: 'GPT-5.4 with extra-high reasoning effort for difficult reviews that need broad context, careful tradeoff analysis, and deeper issue validation.',
60
+ badge: 'Extra High',
61
+ badgeClass: 'badge-power'
62
+ },
63
+ {
64
+ id: 'gpt-5.5-high',
65
+ cli_model: 'gpt-5.5',
66
+ extra_args: ['-c', 'model_reasoning_effort="high"'],
67
+ name: 'GPT-5.5 High',
68
+ tier: 'thorough',
69
+ tagline: 'Latest Deep',
70
+ description: 'Latest-generation GPT model with high reasoning effort for demanding PR reviews, strong code understanding, and careful cross-file analysis.',
71
+ badge: 'High Effort',
72
+ badgeClass: 'badge-power'
73
+ },
74
+ {
75
+ id: 'gpt-5.5-xhigh',
76
+ cli_model: 'gpt-5.5',
77
+ extra_args: ['-c', 'model_reasoning_effort="xhigh"'],
78
+ name: 'GPT-5.5 XHigh',
79
+ tier: 'thorough',
80
+ tagline: 'Frontier Depth',
81
+ description: 'GPT-5.5 with extra-high reasoning effort for the hardest reviews: architecture, concurrency, security-sensitive changes, and large codebase context.',
82
+ badge: 'Max Reasoning',
83
+ badgeClass: 'badge-power'
84
+ },
51
85
  {
52
86
  id: 'gpt-5.3-codex',
53
87
  name: 'GPT-5.3 Codex',
@@ -58,13 +92,22 @@ const CODEX_MODELS = [
58
92
  badgeClass: 'badge-power'
59
93
  },
60
94
  {
61
- id: 'gpt-5.4',
62
- name: 'GPT-5.4',
63
- tier: 'thorough',
64
- tagline: 'Latest Gen',
65
- description: 'Flagship model combining coding, reasoning, and agentic workflows for complex architectural reviews.',
66
- badge: 'Most Thorough',
67
- badgeClass: 'badge-power'
95
+ id: 'gpt-5.4-mini',
96
+ name: 'GPT-5.4 Mini',
97
+ tier: 'balanced',
98
+ tagline: 'Best Balance',
99
+ description: 'Fast reviews with 400k context—good balance of speed and capability for everyday PR review.',
100
+ badge: 'Fast',
101
+ badgeClass: 'badge-speed'
102
+ },
103
+ {
104
+ id: 'gpt-5.4-nano',
105
+ name: 'GPT-5.4 Nano',
106
+ tier: 'fast',
107
+ tagline: 'Cheapest',
108
+ description: 'Ultra-low-cost surface scans for style issues, obvious bugs, and lint-level feedback.',
109
+ badge: 'Cheapest',
110
+ badgeClass: 'badge-speed'
68
111
  }
69
112
  ];
70
113
 
@@ -78,7 +121,7 @@ class CodexProvider extends AIProvider {
78
121
  * @param {Object} configOverrides.env - Additional environment variables
79
122
  * @param {Object[]} configOverrides.models - Custom model definitions
80
123
  */
81
- constructor(model = 'gpt-5.4-mini', configOverrides = {}) {
124
+ constructor(model = 'gpt-5.4-high', configOverrides = {}) {
82
125
  super(model);
83
126
 
84
127
  // Command precedence: ENV > config > default
@@ -127,27 +170,70 @@ class CodexProvider extends AIProvider {
127
170
  // same two-tier pattern as chat-providers.js: args replaces, extra_args appends.
128
171
  const defaultShellEnvArgs = ['-c', 'allow_login_shell=false', '-c', 'shell_environment_policy.include_only=["PATH","HOME","USER","GH_TOKEN","GITHUB_TOKEN"]'];
129
172
  const configArgs = configOverrides.args || defaultShellEnvArgs;
130
- const baseArgs = ['exec', '-m', model, '--json', ...sandboxArgs, ...configArgs, '-'];
131
- const providerArgs = configOverrides.extra_args || [];
132
- const modelConfig = configOverrides.models?.find(m => m.id === model);
133
- const modelArgs = modelConfig?.extra_args || [];
134
173
 
135
- // Merge env: provider env + model env
136
- this.extraEnv = {
137
- ...(configOverrides.env || {}),
138
- ...(modelConfig?.env || {})
139
- };
174
+ // Resolve cli_model + extra_args + env from built-in model, provider config,
175
+ // and per-model config. This is what lets reasoning variants like
176
+ // gpt-5.4-high pass `-m gpt-5.4` plus `-c model_reasoning_effort="high"`.
177
+ const { cliModel, extraArgs, env } = this._resolveModelConfig(model);
178
+
179
+ // IMPORTANT: `-` (stdin marker) must come LAST, after any extra_args.
180
+ // Reasoning variants contribute `-c model_reasoning_effort="..."` via
181
+ // extraArgs; if '-' were placed inside baseArgs those flags would land
182
+ // after the positional stdin marker and be ignored. `buildArgsForModel`
183
+ // enforces the same invariant for the extraction path.
184
+ const baseArgs = ['exec', '-m', cliModel, '--json', ...sandboxArgs, ...configArgs];
185
+
186
+ this.extraEnv = env;
140
187
 
141
188
  if (this.useShell) {
142
189
  // In shell mode, build full command string with args
143
- this.command = `${codexCmd} ${quoteShellArgs([...baseArgs, ...providerArgs, ...modelArgs]).join(' ')}`;
190
+ this.command = `${codexCmd} ${quoteShellArgs([...baseArgs, ...extraArgs, '-']).join(' ')}`;
144
191
  this.args = [];
145
192
  } else {
146
193
  this.command = codexCmd;
147
- this.args = [...baseArgs, ...providerArgs, ...modelArgs];
194
+ this.args = [...baseArgs, ...extraArgs, '-'];
148
195
  }
149
196
  }
150
197
 
198
+ /**
199
+ * Resolve model configuration by looking up built-in and config override definitions.
200
+ * Produces the CLI model ID (for `-m`), merged extra_args, and merged env.
201
+ *
202
+ * Precedence for cli_model: config model > built-in model > modelId.
203
+ * `cli_model` lets reasoning-effort variants (e.g. `gpt-5.4-high`) pass the
204
+ * base model (`gpt-5.4`) to `codex exec -m` while adding reasoning overrides
205
+ * via extra_args.
206
+ *
207
+ * @param {string} modelId
208
+ * @returns {{ builtIn: Object|undefined, configModel: Object|undefined, cliModel: string, extraArgs: string[], env: Object }}
209
+ * @private
210
+ */
211
+ _resolveModelConfig(modelId) {
212
+ const configOverrides = this.configOverrides || {};
213
+
214
+ const builtIn = CODEX_MODELS.find(m => m.id === modelId || (m.aliases && m.aliases.includes(modelId)));
215
+ const configModel = configOverrides.models?.find(m => m.id === modelId);
216
+
217
+ const cliModel = configModel?.cli_model !== undefined
218
+ ? configModel.cli_model
219
+ : (builtIn?.cli_model !== undefined ? builtIn.cli_model : modelId);
220
+
221
+ // Three-way merge for extra_args: built-in model → provider config → per-model config
222
+ const builtInArgs = builtIn?.extra_args || [];
223
+ const providerArgs = configOverrides.extra_args || [];
224
+ const configModelArgs = configModel?.extra_args || [];
225
+ const extraArgs = [...builtInArgs, ...providerArgs, ...configModelArgs];
226
+
227
+ // Three-way merge for env: built-in model → provider config → per-model config
228
+ const env = {
229
+ ...(builtIn?.env || {}),
230
+ ...(configOverrides.env || {}),
231
+ ...(configModel?.env || {})
232
+ };
233
+
234
+ return { builtIn, configModel, cliModel, extraArgs, env };
235
+ }
236
+
151
237
  /**
152
238
  * Execute Codex CLI with a prompt
153
239
  * @param {string} prompt - The prompt to send to Codex
@@ -572,17 +658,16 @@ class CodexProvider extends AIProvider {
572
658
  * @returns {string[]} Complete args array for the CLI
573
659
  */
574
660
  buildArgsForModel(model) {
661
+ // Resolve cli_model + merged extra_args so reasoning-effort variants behave
662
+ // the same for extraction as they do for the main analysis call.
663
+ const { cliModel, extraArgs } = this._resolveModelConfig(model);
664
+
575
665
  // Base args for extraction (read-only sandbox, no shell access needed)
576
666
  // Note: '-' (stdin marker) must come LAST, after any extra_args
577
- const baseArgs = ['exec', '-m', model, '--json', '--sandbox', 'read-only', '--full-auto'];
578
- // Provider-level extra_args (from configOverrides)
579
- const providerArgs = this.configOverrides?.extra_args || [];
580
- // Model-specific extra_args (from the model config for the given model)
581
- const modelConfig = this.configOverrides?.models?.find(m => m.id === model);
582
- const modelArgs = modelConfig?.extra_args || [];
667
+ const baseArgs = ['exec', '-m', cliModel, '--json', '--sandbox', 'read-only', '--full-auto'];
583
668
 
584
669
  // Append stdin marker '-' at the end after all other args
585
- return [...baseArgs, ...providerArgs, ...modelArgs, '-'];
670
+ return [...baseArgs, ...extraArgs, '-'];
586
671
  }
587
672
 
588
673
  /**
@@ -598,20 +683,25 @@ class CodexProvider extends AIProvider {
598
683
 
599
684
  // Build args consistently using the shared method, applying provider and model extra_args
600
685
  const args = this.buildArgsForModel(model);
686
+ // Surface merged env (built-in + provider + per-model) so the extraction
687
+ // spawn matches the contract used by other providers.
688
+ const { env } = this._resolveModelConfig(model);
601
689
 
602
690
  if (useShell) {
603
691
  return {
604
692
  command: `${codexCmd} ${quoteShellArgs(args).join(' ')}`,
605
693
  args: [],
606
694
  useShell: true,
607
- promptViaStdin: true
695
+ promptViaStdin: true,
696
+ env
608
697
  };
609
698
  }
610
699
  return {
611
700
  command: codexCmd,
612
701
  args,
613
702
  useShell: false,
614
- promptViaStdin: true
703
+ promptViaStdin: true,
704
+ env
615
705
  };
616
706
  }
617
707
 
@@ -700,7 +790,7 @@ class CodexProvider extends AIProvider {
700
790
  }
701
791
 
702
792
  static getDefaultModel() {
703
- return 'gpt-5.4-mini';
793
+ return 'gpt-5.4-high';
704
794
  }
705
795
 
706
796
  static getInstallInstructions() {
package/src/ai/index.js CHANGED
@@ -21,7 +21,8 @@ const {
21
21
  inferModelDefaults,
22
22
  resolveDefaultModel,
23
23
  prettifyModelId,
24
- createAliasedProviderClass
24
+ createAliasedProviderClass,
25
+ getTierForModel
25
26
  } = require('./provider');
26
27
 
27
28
  // Load the availability checking module
@@ -73,6 +74,7 @@ module.exports = {
73
74
  inferModelDefaults,
74
75
  resolveDefaultModel,
75
76
  prettifyModelId,
77
+ getTierForModel,
76
78
 
77
79
  // Provider factories
78
80
  createExecutableProviderClass,