@link-assistant/hive-mind 1.50.8 → 1.50.10

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.
@@ -103,14 +103,19 @@ export const opencodeModels = {
103
103
  // Codex models (OpenAI API)
104
104
  export const codexModels = {
105
105
  gpt5: 'gpt-5',
106
- 'gpt5-codex': 'gpt-5-codex',
107
- o3: 'o3',
106
+ 'gpt-5': 'gpt-5',
107
+ 'gpt-5.4': 'gpt-5.4',
108
+ 'gpt-5.4-mini': 'gpt-5.4-mini',
109
+ 'gpt-5.4-nano': 'gpt-5.4-nano',
110
+ 'gpt-5.2-codex': 'gpt-5.2-codex',
111
+ 'gpt-5.3-codex': 'gpt-5.3-codex',
112
+ 'gpt-5.3-codex-spark': 'gpt-5.3-codex-spark',
113
+ 'gpt-5.1-codex-max': 'gpt-5.1-codex-max',
108
114
  'o3-mini': 'o3-mini',
109
115
  gpt4: 'gpt-4',
116
+ 'gpt-4': 'gpt-4',
110
117
  gpt4o: 'gpt-4o',
111
- claude: 'claude-3-5-sonnet',
112
- sonnet: 'claude-3-5-sonnet',
113
- opus: 'claude-3-opus',
118
+ 'gpt-4o': 'gpt-4o',
114
119
  };
115
120
 
116
121
  // Default model for each tool (Issue #1473: centralized to avoid scattered hardcoded defaults)
@@ -118,7 +123,7 @@ export const defaultModels = {
118
123
  claude: 'sonnet',
119
124
  agent: 'nemotron-3-super-free', // Issue #1563: changed from qwen3.6-plus-free (free promotion ended) per agent PR #243
120
125
  opencode: 'grok-code-fast-1',
121
- codex: 'gpt-5',
126
+ codex: 'gpt-5.4',
122
127
  };
123
128
 
124
129
  // Models that support 1M token context window via [1m] suffix (Issue #1221, Issue #1238, Issue #1329)
@@ -180,11 +185,15 @@ export const OPENCODE_MODELS = {
180
185
  export const CODEX_MODELS = {
181
186
  ...codexModels,
182
187
  'gpt-5': 'gpt-5',
183
- 'gpt-5-codex': 'gpt-5-codex',
188
+ 'gpt-5.4': 'gpt-5.4',
189
+ 'gpt-5.4-mini': 'gpt-5.4-mini',
190
+ 'gpt-5.4-nano': 'gpt-5.4-nano',
191
+ 'gpt-5.2-codex': 'gpt-5.2-codex',
192
+ 'gpt-5.3-codex': 'gpt-5.3-codex',
193
+ 'gpt-5.3-codex-spark': 'gpt-5.3-codex-spark',
194
+ 'gpt-5.1-codex-max': 'gpt-5.1-codex-max',
184
195
  'gpt-4': 'gpt-4',
185
196
  'gpt-4o': 'gpt-4o',
186
- 'claude-3-5-sonnet': 'claude-3-5-sonnet',
187
- 'claude-3-opus': 'claude-3-opus',
188
197
  };
189
198
 
190
199
  export const AGENT_MODELS = {
@@ -273,7 +282,7 @@ export const isModelCompatibleWithTool = (tool, model) => {
273
282
  case 'opencode':
274
283
  return mappedModel.includes('/') || Object.keys(opencodeModels).includes(model);
275
284
  case 'codex':
276
- return Object.keys(codexModels).includes(model) || mappedModel.startsWith('gpt-') || mappedModel.startsWith('o3') || mappedModel.startsWith('claude-');
285
+ return Object.keys(codexModels).includes(model) || mappedModel.startsWith('gpt-');
277
286
  default:
278
287
  return true;
279
288
  }
@@ -304,7 +313,7 @@ export const getValidModelsForTool = tool => {
304
313
  export const primaryModelNames = {
305
314
  claude: ['opus', 'sonnet', 'haiku', 'opusplan'],
306
315
  opencode: ['grok', 'gpt4o'],
307
- codex: ['gpt5', 'gpt5-codex', 'o3'],
316
+ codex: ['gpt-5.4', 'gpt-5.4-mini', 'gpt-5.3-codex', 'gpt-5.3-codex-spark', 'gpt-5.2-codex'],
308
317
  agent: ['nemotron-3-super-free', 'minimax-m2.5-free', 'big-pickle', 'gpt-5-nano', 'glm-5-free', 'deepseek-r1-free'],
309
318
  };
310
319
 
@@ -375,7 +384,7 @@ export const getAvailableModelNames = tool => {
375
384
  // - Full model IDs with slashes (e.g., 'openai/gpt-4')
376
385
  // - Long claude-prefixed model IDs (e.g., 'claude-sonnet-4-5-20250929')
377
386
  // - Full gpt- prefixed IDs that are ONLY version numbers (e.g., 'gpt-4', 'gpt-4o', 'gpt-5')
378
- // But keep descriptive aliases like 'gpt-5-nano', 'gpt-5-codex', 'o3', 'o3-mini', 'gpt5', etc.
387
+ // But keep descriptive aliases like 'gpt-5-nano', 'gpt-5.3-codex', 'o3-mini', 'gpt5', etc.
379
388
  // Issue #1185: Updated regex to not filter out gpt-5-nano (a valid short alias)
380
389
  if (key.includes('/')) return false;
381
390
  if (key.match(/^claude-.*-\d{8}$/)) return false; // Full claude model IDs with date
@@ -87,18 +87,6 @@ export const buildSystemPrompt = params => {
87
87
  // When in fork mode, screenshots are pushed to the fork, not the original repo
88
88
  const screenshotRepoPath = argv?.fork && forkedRepo ? forkedRepo : `${owner}/${repo}`;
89
89
 
90
- // Build thinking instruction based on --think level
91
- let thinkLine = '';
92
- if (argv && argv.think) {
93
- const thinkMessages = {
94
- low: 'You always think on every step.',
95
- medium: 'You always think hard on every step.',
96
- high: 'You always think harder on every step.',
97
- max: 'You always ultrathink on every step.',
98
- };
99
- thinkLine = `\n${thinkMessages[argv.think]}\n`;
100
- }
101
-
102
90
  // Build workspace-specific instructions and examples
103
91
  let workspaceInstructions = '';
104
92
  if (workspaceTmpDir) {
@@ -134,22 +122,22 @@ CI investigation with workspace tmp directory.
134
122
  `;
135
123
  }
136
124
 
137
- return `You are AI issue solver using OpenCode.${thinkLine}
125
+ return `You are an AI issue solver using OpenCode.
138
126
 
139
127
  General guidelines.
140
- - When you execute commands, always save their logs to files for easier reading if the output becomes large.
141
- - When running commands, do not set a timeout yourself let them run as long as needed.
142
- - When running sudo commands (especially package installations), always run them in the background to avoid timeout issues.
143
- - When CI is failing, make sure you download the logs locally and carefully investigate them.
128
+ - When you execute commands and the output becomes large, save the logs to files for easier review.
129
+ - When running commands, avoid setting a timeout yourself. Let them run as long as needed.
130
+ - When running sudo commands, especially package installations, run them in the background to avoid timeout issues.
131
+ - When CI is failing, download the logs locally and investigate them carefully.
144
132
  - When a code or log file has more than 1500 lines, read it in chunks of 1500 lines.
145
133
  - When facing a complex problem, do as much tracing as possible and turn on all verbose modes.
146
134
  ${getExperimentsExamplesSubPrompt(argv)}
147
- - When you face something extremely hard, use divide and conquer — it always helps.
135
+ - When you face something extremely hard, use divide and conquer.
148
136
  ${workspaceInstructions}
149
137
  Initial research.
150
- - When you start, make sure you create detailed plan for yourself and follow your todo list step by step, make sure that as many points from these guidelines are added to your todo list to keep track of everything that can help you solve the issue with highest possible quality.
151
- - When you read issue, read all details and comments thoroughly.
152
- - When you see screenshots or images in issue descriptions, pull request descriptions, comments, or discussions, download the image to a local file first, then use Read tool to view and analyze it. Before reading downloaded images with the Read tool, verify the file is a valid image (not HTML) using a CLI tool like the 'file' command to check the actual file format. When corrupted or non-image files (like GitHub's "Not Found" pages saved as .png) are read, they can cause "Could not process image" errors and crash the AI solver process. When the file command shows "HTML", "text", or "ASCII text", the download failed do not call Read on this file. Instead: (1) When images are from GitHub issues/PRs (URLs containing "github.com/user-attachments"), these require authentication — retry with: curl -L -H "Authorization: token $(gh auth token)" -o <filename> "<url>" (2) When the retry still fails, skip the image and note it was unavailable.
138
+ - When you start, create a detailed plan for yourself and follow your todo list step by step. Add as many relevant points from these guidelines to the todo list as practical so you can track the work clearly.
139
+ - When you read the issue, read all details and comments thoroughly.
140
+ - When you see screenshots or images in issue descriptions, pull request descriptions, comments, or discussions, download the image to a local file first, then use the Read tool to view and analyze it. Before reading downloaded images with the Read tool, verify that the file is a valid image rather than HTML by using a CLI tool such as the 'file' command. When corrupted or non-image files, such as GitHub "Not Found" pages saved as `.png`, are read, they can cause "Could not process image" errors and crash the AI solver process. When the file command shows "HTML", "text", or "ASCII text", the download failed, so do not call Read on that file. Instead: (1) when images are from GitHub issues or PRs, such as URLs containing "github.com/user-attachments", retry with: curl -L -H "Authorization: token $(gh auth token)" -o <filename> "<url>" (2) when the retry still fails, skip the image and note that it was unavailable.
153
141
  - When you need issue details, use gh issue view https://github.com/${owner}/${repo}/issues/${issueNumber}.
154
142
  - When you need related code, use gh search code --owner ${owner} [keywords].
155
143
  - When you need repo context, read files in your working directory.${
@@ -158,21 +146,21 @@ Initial research.
158
146
  - When you study related work, study the most recent related pull requests.`
159
147
  : ''
160
148
  }
161
- - When issue is not defined enough, write a comment to ask clarifying questions.
149
+ - When the issue is not defined clearly enough, write a comment with clarifying questions.
162
150
  - When accessing GitHub Gists, use gh gist view command instead of direct URL fetching.
163
- - When you are fixing a bug, please make sure you first find the actual root cause, do as many experiments as needed.
164
- - When you are fixing a bug and code does not have enough tracing/logs, add them and make sure they stay in the code, but are switched off by default.
151
+ - When you are fixing a bug, find the actual root cause first and run as many experiments as needed.
152
+ - When you are fixing a bug and the code does not have enough tracing or logs, add them and keep them in the code with the default state switched off.
165
153
  - When you need comments on a pull request, note that GitHub has three different comment types with different API endpoints:
166
154
  1. PR review comments (inline code comments): gh api repos/${owner}/${repo}/pulls/${prNumber}/comments --paginate
167
155
  2. PR conversation comments (general discussion): gh api repos/${owner}/${repo}/issues/${prNumber}/comments --paginate
168
156
  3. PR reviews (approve/request changes): gh api repos/${owner}/${repo}/pulls/${prNumber}/reviews --paginate
169
157
  Note: The command "gh pr view --json comments" only returns conversation comments and misses review comments.
170
- - When you need latest comments on issue, use gh api repos/${owner}/${repo}/issues/${issueNumber}/comments --paginate.
158
+ - When you need the latest comments on the issue, use gh api repos/${owner}/${repo}/issues/${issueNumber}/comments --paginate.
171
159
 
172
160
  Solution development and testing.
173
161
  - When issue is solvable, first create a test that reproduces the problem, then implement the fix.
174
162
  - When implementing features, search for similar existing implementations in the codebase and use them as examples instead of implementing everything from scratch.
175
- - When coding, each atomic step that can be useful by itself should be committed to the pull request's branch, meaning if work will be interrupted by any reason parts of solution will still be kept intact and safe in pull request.
163
+ - When coding, commit each atomic step that is useful on its own to the pull request branch so interrupted work remains preserved in the pull request.
176
164
  - When you test:
177
165
  start from testing of small functions using separate scripts;
178
166
  write unit tests with mocks for easy and quick start.
@@ -180,7 +168,7 @@ Solution development and testing.
180
168
  - When you test solution draft, include automated checks in pr.
181
169
  - When you write or modify tests, consider setting reasonable timeouts at test, suite, and CI job levels so failures surface quickly instead of hanging.
182
170
  - When you see repeated test timeout patterns in CI, investigate the root cause rather than increasing timeouts.
183
- - When issue is unclear, write comment on issue asking questions.
171
+ - When the issue is unclear, write a comment on the issue with questions.
184
172
  - When you encounter any problems that you are unable to solve yourself, write a comment to the pull request asking for help.
185
173
  - When you need human help, use gh pr comment ${prNumber} --body "your message" to comment on existing PR.
186
174
 
@@ -188,9 +176,9 @@ Reproducible testing.
188
176
  - When fixing a bug, create a test that reproduces the problem before implementing the fix. When you cannot reproduce the problem, you cannot verify the fix.
189
177
  - When encountering logic bugs, write an automated test that fails due to the bug, then implement the fix to make it pass.
190
178
  - When encountering UI bugs, capture a screenshot showing the problem state, then create a visual regression test or manual verification screenshot after the fix.
191
- - When creating tests, prefer minimum reproducible examples - the simplest test case that demonstrates the issue.
179
+ - When creating tests, prefer minimum reproducible examples, meaning the simplest test case that demonstrates the issue.
192
180
  - When submitting a fix, include in the PR description: (1) how to reproduce the issue, (2) the automated test that verifies the fix, (3) before/after screenshots for UI issues.
193
- - When a bug fix doesn't have a reproducing test, the fix is incomplete - regressions can silently occur later.
181
+ - When a bug fix does not have a reproducing test, treat the fix as incomplete because regressions can occur later without notice.
194
182
 
195
183
  Preparing pull request.
196
184
  - When you code, follow contributing guidelines.
@@ -200,14 +188,14 @@ Preparing pull request.
200
188
  - When there is a package with version and GitHub Actions workflows for automatic release, update the version in your pull request to prepare for next release.
201
189
  - When you update existing pr ${prNumber}, use gh pr edit to modify title and description.
202
190
  - When you finalize the pull request:
203
- check that pull request title and description are updated (the PR may start with a [WIP] prefix and placeholder description that should be replaced with actual title and description of the changes),
191
+ check that the pull request title and description are updated (the PR may start with a [WIP] prefix and a placeholder description that should be replaced with the actual title and description of the changes),
204
192
  follow style from merged prs for code, title, and description,
205
- make sure no uncommitted changes corresponding to the original requirements are left behind,
206
- make sure the default branch is merged to the pull request's branch,
207
- make sure all CI checks passing if they exist before you finish,
208
- double-check that all changes in the pull request answer to original requirements of the issue,
209
- make sure no new bugs are introduced in pull request by carefully reading gh pr diff,
210
- make sure no previously existing features were removed without an explicit request from users via the issue description, issue comments, and/or pull request comments.
193
+ check that no uncommitted changes corresponding to the original requirements are left behind,
194
+ check that the default branch is merged into the pull request branch,
195
+ check that all CI checks are passing if they exist before you finish,
196
+ double-check that all changes in the pull request address the original requirements of the issue,
197
+ check for newly introduced bugs in the pull request by carefully reading gh pr diff,
198
+ check that no previously existing features were removed without an explicit request in the issue description, issue comments, or pull request comments.
211
199
  - When you finish implementation, use gh pr ready ${prNumber}.
212
200
 
213
201
  Workflow and collaboration.
@@ -220,7 +208,7 @@ Workflow and collaboration.
220
208
  - When you contribute, keep repository history forward-moving with regular commits, pushes, and reverts if needed.
221
209
  - When you face conflict that you cannot resolve yourself, ask for help.
222
210
  - When you collaborate, respect branch protections by working only on ${branchName}.
223
- - When you mention result, include pull request url or comment url.
211
+ - When you mention a result, include the pull request URL or comment URL.
224
212
  - When you need to create pr, remember pr ${prNumber} already exists for this branch.
225
213
 
226
214
  Self review.
@@ -229,7 +217,7 @@ Self review.
229
217
  - When you finalize, confirm code, tests, and description are consistent.${
230
218
  argv && argv.promptEnsureAllRequirementsAreMet
231
219
  ? `
232
- - When no explicit feedback or requirements are provided, ensure all changes are correct, consistent, validated, tested, logged and fully meet all discussed requirements (check issue description and all comments in issue and in pull request). Ensure all CI/CD checks pass.`
220
+ - When no explicit feedback or requirements are provided, ensure all changes are correct, consistent, validated, tested, logged, and aligned with all discussed requirements by checking the issue description and all comments on the issue and pull request. Check that all CI or CD checks are passing.`
233
221
  : ''
234
222
  }
235
223
 
@@ -246,6 +246,8 @@ export const QUEUE_CONFIG = {
246
246
  disk: getThresholdConfig('disk', 'HIVE_MIND_DISK_THRESHOLD', 'HIVE_MIND_DISK_STRATEGY', 0.9, 'reject'),
247
247
  claude5Hour: getThresholdConfig('claude5Hour', 'HIVE_MIND_CLAUDE_5_HOUR_SESSION_THRESHOLD', 'HIVE_MIND_CLAUDE_5_HOUR_SESSION_STRATEGY', 0.65, 'dequeue-one-at-a-time'),
248
248
  claudeWeekly: getThresholdConfig('claudeWeekly', 'HIVE_MIND_CLAUDE_WEEKLY_THRESHOLD', 'HIVE_MIND_CLAUDE_WEEKLY_STRATEGY', 0.97, 'dequeue-one-at-a-time'),
249
+ codex5Hour: getThresholdConfig('codex5Hour', 'HIVE_MIND_CODEX_5_HOUR_SESSION_THRESHOLD', 'HIVE_MIND_CODEX_5_HOUR_SESSION_STRATEGY', 0.65, 'dequeue-one-at-a-time'),
250
+ codexWeekly: getThresholdConfig('codexWeekly', 'HIVE_MIND_CODEX_WEEKLY_THRESHOLD', 'HIVE_MIND_CODEX_WEEKLY_STRATEGY', 0.97, 'dequeue-one-at-a-time'),
249
251
  githubApi: getThresholdConfig('githubApi', 'HIVE_MIND_GITHUB_API_THRESHOLD', 'HIVE_MIND_GITHUB_API_STRATEGY', 0.75, 'enqueue'),
250
252
  },
251
253
 
@@ -256,6 +258,8 @@ export const QUEUE_CONFIG = {
256
258
  DISK_THRESHOLD: getThresholdConfig('disk', 'HIVE_MIND_DISK_THRESHOLD', 'HIVE_MIND_DISK_STRATEGY', 0.9, 'reject').value,
257
259
  CLAUDE_5_HOUR_SESSION_THRESHOLD: getThresholdConfig('claude5Hour', 'HIVE_MIND_CLAUDE_5_HOUR_SESSION_THRESHOLD', 'HIVE_MIND_CLAUDE_5_HOUR_SESSION_STRATEGY', 0.65, 'dequeue-one-at-a-time').value,
258
260
  CLAUDE_WEEKLY_THRESHOLD: getThresholdConfig('claudeWeekly', 'HIVE_MIND_CLAUDE_WEEKLY_THRESHOLD', 'HIVE_MIND_CLAUDE_WEEKLY_STRATEGY', 0.97, 'dequeue-one-at-a-time').value,
261
+ CODEX_5_HOUR_SESSION_THRESHOLD: getThresholdConfig('codex5Hour', 'HIVE_MIND_CODEX_5_HOUR_SESSION_THRESHOLD', 'HIVE_MIND_CODEX_5_HOUR_SESSION_STRATEGY', 0.65, 'dequeue-one-at-a-time').value,
262
+ CODEX_WEEKLY_THRESHOLD: getThresholdConfig('codexWeekly', 'HIVE_MIND_CODEX_WEEKLY_THRESHOLD', 'HIVE_MIND_CODEX_WEEKLY_STRATEGY', 0.97, 'dequeue-one-at-a-time').value,
259
263
  GITHUB_API_THRESHOLD: getThresholdConfig('githubApi', 'HIVE_MIND_GITHUB_API_THRESHOLD', 'HIVE_MIND_GITHUB_API_STRATEGY', 0.75, 'enqueue').value,
260
264
 
261
265
  // Timing
@@ -290,6 +294,8 @@ export const DISPLAY_THRESHOLDS = {
290
294
  DISK: thresholdToPercent(QUEUE_CONFIG.DISK_THRESHOLD),
291
295
  CLAUDE_5_HOUR_SESSION: thresholdToPercent(QUEUE_CONFIG.CLAUDE_5_HOUR_SESSION_THRESHOLD),
292
296
  CLAUDE_WEEKLY: thresholdToPercent(QUEUE_CONFIG.CLAUDE_WEEKLY_THRESHOLD),
297
+ CODEX_5_HOUR_SESSION: thresholdToPercent(QUEUE_CONFIG.CODEX_5_HOUR_SESSION_THRESHOLD),
298
+ CODEX_WEEKLY: thresholdToPercent(QUEUE_CONFIG.CODEX_WEEKLY_THRESHOLD),
293
299
  GITHUB_API: thresholdToPercent(QUEUE_CONFIG.GITHUB_API_THRESHOLD),
294
300
  };
295
301
 
@@ -160,6 +160,7 @@ export const autoContinueWhenLimitResets = async (issueUrl, sessionId, argv, sho
160
160
  resumeArgs.push('--session-type', sessionType);
161
161
 
162
162
  // Preserve other flags from original invocation
163
+ if (argv.tool && argv.tool !== 'claude') resumeArgs.push('--tool', argv.tool);
163
164
  if (argv.model !== 'sonnet') resumeArgs.push('--model', argv.model);
164
165
  if (argv.verbose) resumeArgs.push('--verbose');
165
166
  if (argv.fork) resumeArgs.push('--fork');
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Handle lightweight early-exit paths before solve loads its full dependency graph.
5
+ *
6
+ * @param {string[]} earlyArgs - Raw CLI args without the node/script prefix
7
+ * @returns {Promise<void>}
8
+ */
9
+ export async function handleSolveEarlyExit(earlyArgs) {
10
+ if (earlyArgs.includes('--version')) {
11
+ const { getVersion } = await import('./version.lib.mjs');
12
+ try {
13
+ console.log(await getVersion());
14
+ } catch {
15
+ console.error('Error: Unable to determine version');
16
+ process.exit(1);
17
+ }
18
+ process.exit(0);
19
+ }
20
+
21
+ if (earlyArgs.includes('--help') || earlyArgs.includes('-h')) {
22
+ // Load minimal modules needed for help output.
23
+ const { use } = eval(await (await fetch('https://unpkg.com/use-m/use.js')).text());
24
+ globalThis.use = use;
25
+ const { initializeConfig, createYargsConfig } = await import('./solve.config.lib.mjs');
26
+ const { yargs, hideBin } = await initializeConfig(use);
27
+ const rawArgs = hideBin(process.argv);
28
+ const argsWithoutHelp = rawArgs.filter(arg => arg !== '--help' && arg !== '-h');
29
+ createYargsConfig(yargs(argsWithoutHelp)).showHelp();
30
+ process.exit(0);
31
+ }
32
+
33
+ if (earlyArgs.length === 0) {
34
+ console.error('Usage: solve.mjs <issue-url> [options]');
35
+ console.error('\nError: Missing required github issue or pull request URL');
36
+ console.error('\nRun "solve.mjs --help" for more information');
37
+ process.exit(1);
38
+ }
39
+ }
@@ -229,13 +229,13 @@ export const SOLVE_OPTION_DEFINITIONS = {
229
229
  },
230
230
  think: {
231
231
  type: 'string',
232
- description: 'Thinking level for Claude. Translated to --thinking-budget for Claude Code >= 2.1.12 (off=0, low=~8000, medium=~16000, high=~24000, max=31999). For older versions, uses thinking keywords.',
232
+ description: 'Thinking level hint. For Claude, translated to --thinking-budget for Claude Code >= 2.1.12 (off=0, low=~8000, medium=~16000, high=~24000, max=31999). For Codex, mapped to reasoning effort (off=none, low=low, medium=medium, high=high, max=xhigh).',
233
233
  choices: ['off', 'low', 'medium', 'high', 'max'],
234
234
  default: undefined,
235
235
  },
236
236
  'thinking-budget': {
237
237
  type: 'number',
238
- description: 'Thinking token budget for Claude Code (0-31999). Controls MAX_THINKING_TOKENS. Default: 0 (thinking disabled). For older Claude Code versions, translated back to --think level.',
238
+ description: 'Thinking token budget. For Claude Code, controls MAX_THINKING_TOKENS (0-31999 by default). For Codex, enables finer reasoning-effort mapping including minimal/low/medium/high/xhigh.',
239
239
  default: undefined,
240
240
  },
241
241
  'thinking-budget-claude-minimum-version': {
@@ -250,7 +250,7 @@ export const SOLVE_OPTION_DEFINITIONS = {
250
250
  },
251
251
  'prompt-plan-sub-agent': {
252
252
  type: 'boolean',
253
- description: 'Encourage AI to use Plan sub-agent for initial planning (only works with --tool claude)',
253
+ description: 'Encourage AI to use a planning sub-agent or planning workflow for initial planning. Supported for --tool claude and --tool codex.',
254
254
  default: false,
255
255
  },
256
256
  'base-branch': {
@@ -326,27 +326,27 @@ export const SOLVE_OPTION_DEFINITIONS = {
326
326
  },
327
327
  'interactive-mode': {
328
328
  type: 'boolean',
329
- description: '[EXPERIMENTAL] Post Claude output as PR comments in real-time. Only supported for --tool claude.',
329
+ description: '[EXPERIMENTAL] Post tool output as PR comments in real-time. Supported for --tool claude and --tool codex.',
330
330
  default: false,
331
331
  },
332
332
  'prompt-explore-sub-agent': {
333
333
  type: 'boolean',
334
- description: 'Encourage Claude to use Explore sub-agent for codebase exploration. Only supported for --tool claude.',
334
+ description: 'Encourage AI to use Explore-style sub-agent workflow for codebase exploration. Supported for --tool claude and --tool codex.',
335
335
  default: false,
336
336
  },
337
337
  'prompt-general-purpose-sub-agent': {
338
338
  type: 'boolean',
339
- description: 'Prompt AI to use general-purpose sub agents for processing large tasks with multiple files/folders. Only supported for --tool claude.',
339
+ description: 'Prompt AI to use general-purpose sub agents for processing large tasks with multiple files/folders. Supported for --tool claude and --tool codex.',
340
340
  default: false,
341
341
  },
342
342
  'tokens-budget-stats': {
343
343
  type: 'boolean',
344
- description: '[EXPERIMENTAL] Show detailed token budget statistics including context window usage and ratios. Only supported for --tool claude.',
344
+ description: '[EXPERIMENTAL] Show detailed token budget statistics including context window usage and ratios. Supported for --tool claude, --tool codex, and any tool that returns detailed token usage.',
345
345
  default: false,
346
346
  },
347
347
  'prompt-issue-reporting': {
348
348
  type: 'boolean',
349
- description: 'Enable automatic issue creation for spotted bugs/errors not related to main task. Issues will include reproducible examples, workarounds, and fix suggestions. Works for both current and third-party repositories. Only supported for --tool claude.',
349
+ description: 'Enable automatic issue creation for spotted bugs/errors not related to main task. Issues will include reproducible examples, workarounds, and fix suggestions. Works for both current and third-party repositories. Supported for --tool claude and --tool codex.',
350
350
  default: false,
351
351
  },
352
352
  'prompt-architecture-care': {
@@ -356,12 +356,12 @@ export const SOLVE_OPTION_DEFINITIONS = {
356
356
  },
357
357
  'prompt-case-studies': {
358
358
  type: 'boolean',
359
- description: 'Create comprehensive case study documentation for the issue including logs, analysis, timeline, root cause investigation, and proposed solutions. Organizes findings into ./docs/case-studies/issue-{id}/ directory. Only supported for --tool claude.',
359
+ description: 'Create comprehensive case study documentation for the issue including logs, analysis, timeline, root cause investigation, and proposed solutions. Organizes findings into ./docs/case-studies/issue-{id}/ directory. Supported for --tool claude and --tool codex.',
360
360
  default: false,
361
361
  },
362
362
  'prompt-playwright-mcp': {
363
363
  type: 'boolean',
364
- description: 'Enable Playwright MCP browser automation hints in system prompt (enabled by default, only takes effect if Playwright MCP is installed). Use --no-prompt-playwright-mcp to disable. Only supported for --tool claude.',
364
+ description: 'Enable Playwright MCP browser automation hints in system prompt (enabled by default, only takes effect if Playwright MCP is installed). Use --no-prompt-playwright-mcp to disable. Supported for --tool claude and --tool codex.',
365
365
  default: true,
366
366
  },
367
367
  'prompt-check-sibling-pull-requests': {
@@ -391,7 +391,7 @@ export const SOLVE_OPTION_DEFINITIONS = {
391
391
  },
392
392
  'prompt-subagents-via-agent-commander': {
393
393
  type: 'boolean',
394
- description: 'Guide Claude to use agent-commander CLI (start-agent) instead of native Task tool for subagent delegation. Allows using any supported agent type (claude, opencode, codex, agent) with unified API. Only works with --tool claude and requires agent-commander to be installed.',
394
+ description: 'Guide AI to use agent-commander CLI (start-agent) instead of native tool-specific delegation for subagent work. Allows using any supported agent type (claude, opencode, codex, agent) with a unified API. Supported for --tool claude and --tool codex and requires agent-commander to be installed.',
395
395
  default: false,
396
396
  },
397
397
  'auto-init-repository': {
package/src/solve.mjs CHANGED
@@ -1,39 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  // Import Sentry instrumentation first (must be before other imports)
3
3
  import './instrument.mjs';
4
- // Early exit paths - handle these before loading all modules to speed up testing
5
4
  const earlyArgs = process.argv.slice(2);
6
- if (earlyArgs.includes('--version')) {
7
- const { getVersion } = await import('./version.lib.mjs');
8
- try {
9
- const version = await getVersion();
10
- console.log(version);
11
- } catch {
12
- console.error('Error: Unable to determine version');
13
- process.exit(1);
14
- }
15
- process.exit(0);
16
- }
17
- if (earlyArgs.includes('--help') || earlyArgs.includes('-h')) {
18
- // Load minimal modules needed for help
19
- const { use } = eval(await (await fetch('https://unpkg.com/use-m/use.js')).text());
20
- globalThis.use = use;
21
- const config = await import('./solve.config.lib.mjs');
22
- const { initializeConfig, createYargsConfig } = config;
23
- const { yargs, hideBin } = await initializeConfig(use);
24
- const rawArgs = hideBin(process.argv);
25
- // Filter out help flags to avoid duplicate display
26
- const argsWithoutHelp = rawArgs.filter(arg => arg !== '--help' && arg !== '-h');
27
- createYargsConfig(yargs(argsWithoutHelp)).showHelp();
28
- process.exit(0);
29
- }
30
- if (earlyArgs.length === 0) {
31
- console.error('Usage: solve.mjs <issue-url> [options]');
32
- console.error('\nError: Missing required github issue or pull request URL');
33
- console.error('\nRun "solve.mjs --help" for more information');
34
- process.exit(1);
35
- }
36
- // Now load all modules for normal operation
5
+ const { handleSolveEarlyExit } = await import('./solve.bootstrap.lib.mjs');
6
+ await handleSolveEarlyExit(earlyArgs);
7
+
37
8
  const { use } = eval(await (await fetch('https://unpkg.com/use-m/use.js')).text());
38
9
  globalThis.use = use;
39
10
  const { $ } = await use('command-stream');
@@ -58,9 +29,9 @@ const { processAutoContinueForIssue } = autoContinue;
58
29
  const repository = await import('./solve.repository.lib.mjs');
59
30
  const { setupTempDirectory, cleanupTempDirectory } = repository;
60
31
  const results = await import('./solve.results.lib.mjs');
61
- const { cleanupClaudeFile, showSessionSummary, verifyResults, buildClaudeResumeCommand, checkForAiCreatedComments, attachSolutionSummary } = results;
32
+ const { cleanupClaudeFile, showSessionSummary, verifyResults, buildClaudeResumeCommand, buildSolveResumeCommand, checkForAiCreatedComments, attachSolutionSummary } = results;
62
33
  const claudeLib = await import('./claude.lib.mjs');
63
- const { executeClaude } = claudeLib;
34
+ const { executeClaude, checkPlaywrightMcpAvailability } = claudeLib;
64
35
 
65
36
  const githubLinking = await import('./github-linking.lib.mjs');
66
37
  const { extractLinkedIssueNumber } = githubLinking;
@@ -769,9 +740,21 @@ try {
769
740
  });
770
741
  } else if (argv.tool === 'codex') {
771
742
  const codexLib = await import('./codex.lib.mjs');
772
- const { executeCodex } = codexLib;
743
+ const { executeCodex, checkPlaywrightMcpAvailability } = codexLib;
773
744
  const codexPath = process.env.CODEX_PATH || 'codex';
774
745
 
746
+ if (argv.promptPlaywrightMcp) {
747
+ const playwrightMcpAvailable = await checkPlaywrightMcpAvailability();
748
+ if (playwrightMcpAvailable) {
749
+ await log('🎭 Playwright MCP detected - enabling browser automation hints', { verbose: true });
750
+ } else {
751
+ await log('ℹ️ Playwright MCP not detected - browser automation hints will be disabled', { verbose: true });
752
+ argv.promptPlaywrightMcp = false;
753
+ }
754
+ } else {
755
+ await log('ℹ️ Playwright MCP explicitly disabled via --no-prompt-playwright-mcp', { verbose: true });
756
+ }
757
+
775
758
  toolResult = await executeCodex({
776
759
  issueUrl,
777
760
  issueNumber,
@@ -831,7 +814,6 @@ try {
831
814
  if (argv.tool === 'claude' || !argv.tool) {
832
815
  // If flag is true (default), check if Playwright MCP is actually available
833
816
  if (argv.promptPlaywrightMcp) {
834
- const { checkPlaywrightMcpAvailability } = claudeLib;
835
817
  const playwrightMcpAvailable = await checkPlaywrightMcpAvailability();
836
818
  if (playwrightMcpAvailable) {
837
819
  await log('🎭 Playwright MCP detected - enabling browser automation hints', { verbose: true });
@@ -927,6 +909,12 @@ try {
927
909
  await log('');
928
910
  await log(` ${claudeResumeCmd}`);
929
911
  await log('');
912
+ } else if (argv.url) {
913
+ const solveResumeCmd = buildSolveResumeCommand({ issueUrl: argv.url, sessionId, tool: toolForResume, model: argv.model, tempDir });
914
+ await log(`💡 To continue this ${toolForResume} session with solve:`);
915
+ await log('');
916
+ await log(` ${solveResumeCmd}`);
917
+ await log('');
930
918
  }
931
919
  }
932
920
 
@@ -936,7 +924,7 @@ try {
936
924
  try {
937
925
  // Build Claude CLI resume command
938
926
  const tool = argv.tool || 'claude';
939
- const resumeCommand = tool === 'claude' ? buildClaudeResumeCommand({ tempDir, sessionId, model: argv.model }) : null;
927
+ const resumeCommand = tool === 'claude' ? buildClaudeResumeCommand({ tempDir, sessionId, model: argv.model }) : sessionId ? buildSolveResumeCommand({ issueUrl: argv.url, sessionId, tool, model: argv.model, tempDir }) : null;
940
928
  const logUploadSuccess = await attachLogToGitHub({
941
929
  logFile: getLogFile(),
942
930
  targetType: 'pr',
@@ -974,7 +962,7 @@ try {
974
962
  const resetTime = global.limitResetTime;
975
963
  // Build Claude CLI resume command
976
964
  const tool = argv.tool || 'claude';
977
- const resumeCmd = tool === 'claude' ? buildClaudeResumeCommand({ tempDir, sessionId, model: argv.model }) : null;
965
+ const resumeCmd = tool === 'claude' ? buildClaudeResumeCommand({ tempDir, sessionId, model: argv.model }) : sessionId ? buildSolveResumeCommand({ issueUrl: argv.url, sessionId, tool, model: argv.model, tempDir }) : null;
978
966
  const resumeSection = resumeCmd ? `To resume after the limit resets, use:\n\`\`\`bash\n${resumeCmd}\n\`\`\`` : `Session ID: \`${sessionId}\``;
979
967
  // Format the reset time with relative time and UTC conversion if available
980
968
  const timezone = global.limitTimezone || null;
@@ -1002,7 +990,7 @@ try {
1002
990
  try {
1003
991
  // Build Claude CLI resume command (only for logging, not shown to users when auto-resume is enabled)
1004
992
  const tool = argv.tool || 'claude';
1005
- const resumeCommand = tool === 'claude' ? buildClaudeResumeCommand({ tempDir, sessionId, model: argv.model }) : null;
993
+ const resumeCommand = tool === 'claude' ? buildClaudeResumeCommand({ tempDir, sessionId, model: argv.model }) : sessionId ? buildSolveResumeCommand({ issueUrl: argv.url, sessionId, tool, model: argv.model, tempDir }) : null;
1006
994
  const logUploadSuccess = await attachLogToGitHub({
1007
995
  logFile: getLogFile(),
1008
996
  targetType: 'pr',
@@ -1090,6 +1078,13 @@ try {
1090
1078
  await log('');
1091
1079
  await log(` ${claudeResumeCmd}`);
1092
1080
  await log('');
1081
+ } else if (sessionId && argv.url) {
1082
+ const solveResumeCmd = buildSolveResumeCommand({ issueUrl: argv.url, sessionId, tool: toolForFailure, model: argv.model, tempDir });
1083
+ await log('');
1084
+ await log(`💡 To continue this ${toolForFailure} session with solve:`);
1085
+ await log('');
1086
+ await log(` ${solveResumeCmd}`);
1087
+ await log('');
1093
1088
  }
1094
1089
 
1095
1090
  // Attach failure logs before exiting (Issues #1212, #1462: fall back to issue if no PR)
@@ -1104,7 +1099,7 @@ try {
1104
1099
  try {
1105
1100
  // Build Claude CLI resume command
1106
1101
  const tool = argv.tool || 'claude';
1107
- const resumeCommand = sessionId && tool === 'claude' ? buildClaudeResumeCommand({ tempDir, sessionId, model: argv.model }) : null;
1102
+ const resumeCommand = sessionId ? (tool === 'claude' ? buildClaudeResumeCommand({ tempDir, sessionId, model: argv.model }) : buildSolveResumeCommand({ issueUrl: argv.url, sessionId, tool, model: argv.model, tempDir })) : null;
1108
1103
  const logUploadSuccess = await attachLogToGitHub({
1109
1104
  logFile: getLogFile(),
1110
1105
  targetType: logTargetType,
@@ -358,8 +358,8 @@ export const createProgressMonitor = ({ owner, repo, prNumber, $, log, verbose =
358
358
  };
359
359
 
360
360
  /**
361
- * Process a Claude CLI stream event, detecting TodoWrite tool calls
362
- * and updating progress automatically. Call this for each parsed NDJSON event.
361
+ * Process a tool stream event, detecting Claude TodoWrite or Codex todo_list
362
+ * updates and updating progress automatically.
363
363
  *
364
364
  * @param {Object} data - Parsed JSON event from Claude CLI stream
365
365
  * @param {boolean} force - Force update even if within rate limit interval
@@ -381,6 +381,14 @@ export const createProgressMonitor = ({ owner, repo, prNumber, $, log, verbose =
381
381
  if (data.type === 'user' && data.tool_use_result?.newTodos) {
382
382
  updated = await updateProgress(data.tool_use_result.newTodos, force);
383
383
  }
384
+ // Pattern 3: Codex item event with todo_list payload
385
+ if ((data.type === 'item.started' || data.type === 'item.updated' || data.type === 'item.completed') && data.item?.type === 'todo_list' && Array.isArray(data.item.items)) {
386
+ const todos = data.item.items.map(todo => ({
387
+ status: todo?.completed ? 'completed' : 'pending',
388
+ content: todo?.text || '',
389
+ }));
390
+ updated = await updateProgress(todos, force);
391
+ }
384
392
  return updated;
385
393
  };
386
394
 
@@ -208,9 +208,21 @@ export const executeToolIteration = async params => {
208
208
  } else if (argv.tool === 'codex') {
209
209
  // Use Codex
210
210
  const codexExecLib = await import('./codex.lib.mjs');
211
- const { executeCodex } = codexExecLib;
211
+ const { executeCodex, checkPlaywrightMcpAvailability } = codexExecLib;
212
212
  const codexPath = argv.codexPath || 'codex';
213
213
 
214
+ if (argv.promptPlaywrightMcp) {
215
+ const playwrightMcpAvailable = await checkPlaywrightMcpAvailability();
216
+ if (playwrightMcpAvailable) {
217
+ await log('🎭 Playwright MCP detected - enabling browser automation hints', { verbose: true });
218
+ } else {
219
+ await log('ℹ️ Playwright MCP not detected - browser automation hints will be disabled', { verbose: true });
220
+ argv.promptPlaywrightMcp = false;
221
+ }
222
+ } else {
223
+ await log('ℹ️ Playwright MCP explicitly disabled via --no-prompt-playwright-mcp', { verbose: true });
224
+ }
225
+
214
226
  toolResult = await executeCodex({
215
227
  issueUrl,
216
228
  issueNumber,