@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.
- package/CHANGELOG.md +12 -0
- package/README.md +6 -0
- package/package.json +1 -1
- package/src/agent.prompts.lib.mjs +25 -37
- package/src/architecture-care.prompts.lib.mjs +11 -11
- package/src/claude.prompts.lib.mjs +31 -46
- package/src/codex.lib.mjs +481 -100
- package/src/codex.options.lib.mjs +52 -0
- package/src/codex.prompts.lib.mjs +84 -39
- package/src/experiments-examples.prompts.lib.mjs +7 -7
- package/src/hive.bootstrap.lib.mjs +32 -0
- package/src/hive.config.lib.mjs +3 -3
- package/src/hive.mjs +13 -20
- package/src/interactive-mode.lib.mjs +200 -265
- package/src/interactive-mode.shared.lib.mjs +133 -0
- package/src/lib.mjs +101 -4
- package/src/limits.lib.mjs +339 -2
- package/src/log-upload.lib.mjs +46 -3
- package/src/models/index.mjs +21 -12
- package/src/opencode.prompts.lib.mjs +26 -38
- package/src/queue-config.lib.mjs +6 -0
- package/src/solve.auto-continue.lib.mjs +1 -0
- package/src/solve.bootstrap.lib.mjs +39 -0
- package/src/solve.config.lib.mjs +11 -11
- package/src/solve.mjs +35 -40
- package/src/solve.progress-monitoring.lib.mjs +10 -2
- package/src/solve.restart-shared.lib.mjs +13 -1
- package/src/solve.results.lib.mjs +43 -5
- package/src/solve.validation.lib.mjs +1 -1
- package/src/telegram-bot.mjs +4 -2
- package/src/telegram-solve-queue.helpers.lib.mjs +151 -0
- package/src/telegram-solve-queue.lib.mjs +82 -181
- package/src/version-info.lib.mjs +8 -5
package/src/models/index.mjs
CHANGED
|
@@ -103,14 +103,19 @@ export const opencodeModels = {
|
|
|
103
103
|
// Codex models (OpenAI API)
|
|
104
104
|
export const codexModels = {
|
|
105
105
|
gpt5: 'gpt-5',
|
|
106
|
-
'
|
|
107
|
-
|
|
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
|
-
|
|
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
|
|
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-')
|
|
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: ['
|
|
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
|
|
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
|
|
125
|
+
return `You are an AI issue solver using OpenCode.
|
|
138
126
|
|
|
139
127
|
General guidelines.
|
|
140
|
-
- When you execute commands,
|
|
141
|
-
- When running commands,
|
|
142
|
-
- When running sudo commands
|
|
143
|
-
- When CI is failing,
|
|
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
|
|
135
|
+
- When you face something extremely hard, use divide and conquer.
|
|
148
136
|
${workspaceInstructions}
|
|
149
137
|
Initial research.
|
|
150
|
-
- When you start,
|
|
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
|
|
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
|
|
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,
|
|
164
|
-
- When you are fixing a bug and code does not have enough tracing
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
double-check that all changes in the pull request
|
|
209
|
-
|
|
210
|
-
|
|
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
|
|
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
|
|
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
|
|
package/src/queue-config.lib.mjs
CHANGED
|
@@ -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
|
+
}
|
package/src/solve.config.lib.mjs
CHANGED
|
@@ -229,13 +229,13 @@ export const SOLVE_OPTION_DEFINITIONS = {
|
|
|
229
229
|
},
|
|
230
230
|
think: {
|
|
231
231
|
type: 'string',
|
|
232
|
-
description: 'Thinking level
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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
|
|
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
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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
|
|
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
|
|
362
|
-
* and updating progress automatically.
|
|
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,
|