@link-assistant/hive-mind 1.56.1 → 1.56.3
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 +27 -0
- package/README.hi.md +1 -1
- package/README.md +20 -4
- package/README.ru.md +1 -1
- package/README.zh.md +1 -1
- package/package.json +1 -1
- package/src/codex.lib.mjs +2 -1
- package/src/hive-screens.lib.mjs +71 -17
- package/src/hive.mjs +2 -2
- package/src/models/index.mjs +59 -2
- package/src/solve.config.lib.mjs +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
# @link-assistant/hive-mind
|
|
2
2
|
|
|
3
|
+
## 1.56.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 86da037: Support `gpt-5.5` for the Codex tool, prefer it as the default model, accept forward-compatible `gpt-5.5-mini` and `gpt-5.5-nano` aliases, and document per-tool model and reasoning defaults.
|
|
8
|
+
|
|
9
|
+
## 1.56.2
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- d39f08f: fix(hive-screens): make `--list` default to `--all`, print log/issue after `--enter` exits, and actually close sessions on `--close`
|
|
14
|
+
|
|
15
|
+
Addresses issue #1654:
|
|
16
|
+
- `hive-screens --list` now defaults to `--all` so a bare `--list` lists every
|
|
17
|
+
match, matching user expectations. `--enter` and `--close` keep `--oldest` as
|
|
18
|
+
their default because they are destructive.
|
|
19
|
+
- `hive-screens --enter` now prints `Log:` and `Issue:` lines **after** the
|
|
20
|
+
user detaches from the screen session, so the information is not wiped by
|
|
21
|
+
`screen -r` swapping to the alternate buffer.
|
|
22
|
+
- `hive-screens --close` now spawns `screen -X stuff exit\n` directly (with
|
|
23
|
+
the newline as a literal argv element) instead of shelling out with bash
|
|
24
|
+
ANSI-C quoting (`$'exit\n'`). The legacy form relied on `/bin/sh` being
|
|
25
|
+
bash, but on Debian/Ubuntu it is `dash`, which does not understand
|
|
26
|
+
`$'...'` — so the previous command sent the literal string `$exit\n` into
|
|
27
|
+
each session and never actually closed it.
|
|
28
|
+
- Adds a `--verbose` / `-v` flag that prints scanning diagnostics to stderr.
|
|
29
|
+
|
|
3
30
|
## 1.56.1
|
|
4
31
|
|
|
5
32
|
### Patch Changes
|
package/README.hi.md
CHANGED
|
@@ -452,7 +452,7 @@ Aliases:
|
|
|
452
452
|
/agent /solve --tool agent के बराबर है
|
|
453
453
|
|
|
454
454
|
Tool alias examples:
|
|
455
|
-
/codex https://github.com/owner/repo/issues/123 --model gpt-5.
|
|
455
|
+
/codex https://github.com/owner/repo/issues/123 --model gpt-5.5
|
|
456
456
|
/opencode https://github.com/owner/repo/issues/123 --model grok-code-fast-1
|
|
457
457
|
/agent https://github.com/owner/repo/issues/123 --model nemotron-3-super-free
|
|
458
458
|
|
package/README.md
CHANGED
|
@@ -461,7 +461,7 @@ Aliases:
|
|
|
461
461
|
/agent is equivalent to /solve --tool agent
|
|
462
462
|
|
|
463
463
|
Tool alias examples:
|
|
464
|
-
/codex https://github.com/owner/repo/issues/123 --model gpt-5.
|
|
464
|
+
/codex https://github.com/owner/repo/issues/123 --model gpt-5.5
|
|
465
465
|
/opencode https://github.com/owner/repo/issues/123 --model grok-code-fast-1
|
|
466
466
|
/agent https://github.com/owner/repo/issues/123 --model nemotron-3-super-free
|
|
467
467
|
|
|
@@ -477,6 +477,17 @@ Free Models via Kilo Gateway (with --tool agent):
|
|
|
477
477
|
/solve https://github.com/owner/repo/issues/123 --tool agent --model kilo/deepseek-r1-free
|
|
478
478
|
```
|
|
479
479
|
|
|
480
|
+
Current tool defaults in Hive Mind:
|
|
481
|
+
|
|
482
|
+
| Tool | Default model | Default reasoning behavior |
|
|
483
|
+
| ---------- | ----------------------------------------------------------- | ---------------------------------------------------------------------------------------- |
|
|
484
|
+
| `claude` | `sonnet` | No extra thinking is requested unless you pass `--think` or `--thinking-budget` |
|
|
485
|
+
| `codex` | `gpt-5.5` preferred, with runtime fallback to local catalog | Codex runs with `reasoning_effort=none` unless you pass `--think` or `--thinking-budget` |
|
|
486
|
+
| `opencode` | `grok-code-fast-1` | No extra thinking prompt is added for the default model |
|
|
487
|
+
| `agent` | `nemotron-3-super-free` | No extra thinking prompt is added for the default model |
|
|
488
|
+
|
|
489
|
+
See [docs/CONFIGURATION.md](./docs/CONFIGURATION.md) for the full per-tool defaults and reasoning mappings.
|
|
490
|
+
|
|
480
491
|
> **📖 Free Models Guide**: See [docs/FREE_MODELS.md](./docs/FREE_MODELS.md) for comprehensive information about all free models including OpenCode Zen and Kilo Gateway providers.
|
|
481
492
|
|
|
482
493
|
#### `/hive` - Run Hive Orchestration
|
|
@@ -831,7 +842,7 @@ you see under `--list` is guaranteed to be the same set `--close` will act on
|
|
|
831
842
|
|
|
832
843
|
```bash
|
|
833
844
|
# Safe preview — show every finished, mergeable solve session.
|
|
834
|
-
hive-screens --list
|
|
845
|
+
hive-screens --list
|
|
835
846
|
|
|
836
847
|
# Close the oldest finished session (same as the legacy script's default).
|
|
837
848
|
hive-screens --close
|
|
@@ -841,10 +852,15 @@ hive-screens --enter --newest
|
|
|
841
852
|
|
|
842
853
|
# Close every finished session.
|
|
843
854
|
hive-screens --close --all
|
|
855
|
+
|
|
856
|
+
# Print diagnostic output while scanning (useful when matching fails).
|
|
857
|
+
hive-screens --list --verbose
|
|
844
858
|
```
|
|
845
859
|
|
|
846
|
-
|
|
847
|
-
|
|
860
|
+
`--list` defaults to `--all` so a bare `hive-screens --list` shows every match.
|
|
861
|
+
`--enter` and `--close` default to `--oldest` because they are destructive.
|
|
862
|
+
Supply `--oldest`, `--newest`, or `--all` to override. Run
|
|
863
|
+
`hive-screens --help` for the full option list.
|
|
848
864
|
|
|
849
865
|
### Reboot server.
|
|
850
866
|
|
package/README.ru.md
CHANGED
|
@@ -452,7 +452,7 @@ Aliases:
|
|
|
452
452
|
/agent эквивалентна /solve --tool agent
|
|
453
453
|
|
|
454
454
|
Tool alias examples:
|
|
455
|
-
/codex https://github.com/owner/repo/issues/123 --model gpt-5.
|
|
455
|
+
/codex https://github.com/owner/repo/issues/123 --model gpt-5.5
|
|
456
456
|
/opencode https://github.com/owner/repo/issues/123 --model grok-code-fast-1
|
|
457
457
|
/agent https://github.com/owner/repo/issues/123 --model nemotron-3-super-free
|
|
458
458
|
|
package/README.zh.md
CHANGED
|
@@ -452,7 +452,7 @@ Aliases:
|
|
|
452
452
|
/agent 等同于 /solve --tool agent
|
|
453
453
|
|
|
454
454
|
Tool alias examples:
|
|
455
|
-
/codex https://github.com/owner/repo/issues/123 --model gpt-5.
|
|
455
|
+
/codex https://github.com/owner/repo/issues/123 --model gpt-5.5
|
|
456
456
|
/opencode https://github.com/owner/repo/issues/123 --model grok-code-fast-1
|
|
457
457
|
/agent https://github.com/owner/repo/issues/123 --model nemotron-3-super-free
|
|
458
458
|
|
package/package.json
CHANGED
package/src/codex.lib.mjs
CHANGED
|
@@ -23,6 +23,7 @@ import { createInteractiveHandler } from './interactive-mode.lib.mjs';
|
|
|
23
23
|
import { initProgressMonitoring } from './solve.progress-monitoring.lib.mjs';
|
|
24
24
|
import { getCodexPlaywrightMcpDisableConfigArgs } from './playwright-mcp.lib.mjs';
|
|
25
25
|
import { fetchModelInfo } from './model-info.lib.mjs';
|
|
26
|
+
import { defaultModels } from './models/index.mjs';
|
|
26
27
|
import Decimal from 'decimal.js-light';
|
|
27
28
|
|
|
28
29
|
const CODEX_USAGE_FIELD_NAMES = ['input_tokens', 'cached_input_tokens', 'output_tokens', 'cache_write_tokens', 'cache_creation_input_tokens', 'reasoning_tokens', 'input_tokens_details.cached_tokens', 'input_tokens_details.cache_read_tokens', 'input_tokens_details.cache_write_tokens', 'input_tokens_details.cache_creation_tokens', 'input_tokens_details.cache_creation_input_tokens', 'output_tokens_details.reasoning_tokens'];
|
|
@@ -408,7 +409,7 @@ export const calculateCodexPricing = async (modelId, tokenUsage) => {
|
|
|
408
409
|
};
|
|
409
410
|
|
|
410
411
|
// Function to validate Codex CLI connection
|
|
411
|
-
export const validateCodexConnection = async (model =
|
|
412
|
+
export const validateCodexConnection = async (model = defaultModels.codex, verbose = false) => {
|
|
412
413
|
// Map model alias to full ID
|
|
413
414
|
const mappedModel = mapModelToId(model);
|
|
414
415
|
|
package/src/hive-screens.lib.mjs
CHANGED
|
@@ -18,7 +18,7 @@ import { promisify } from 'node:util';
|
|
|
18
18
|
|
|
19
19
|
const execAsync = promisify(execCallback);
|
|
20
20
|
|
|
21
|
-
export const HIVE_SCREENS_HELP = `Usage: hive-screens (--list | --enter | --close) [--oldest|--newest|--all]
|
|
21
|
+
export const HIVE_SCREENS_HELP = `Usage: hive-screens (--list | --enter | --close) [--oldest|--newest|--all] [--verbose]
|
|
22
22
|
|
|
23
23
|
Scan detached GNU screen sessions for completed solve runs and either list,
|
|
24
24
|
enter, or close them. A session matches when its scrollback contains both
|
|
@@ -30,21 +30,24 @@ Actions (one required):
|
|
|
30
30
|
--enter Attach to the selected match (blocking)
|
|
31
31
|
--close Send \`exit\\n\` to the selected match so it terminates
|
|
32
32
|
|
|
33
|
-
Selection (optional
|
|
34
|
-
--oldest Act on the oldest match (default)
|
|
33
|
+
Selection (optional):
|
|
34
|
+
--oldest Act on the oldest match (default for --enter/--close)
|
|
35
35
|
--newest Act on the newest match
|
|
36
|
-
--all Act on every match
|
|
36
|
+
--all Act on every match (default for --list)
|
|
37
37
|
|
|
38
38
|
Options:
|
|
39
|
+
-v, --verbose Print diagnostic output to stderr while scanning
|
|
39
40
|
-h, --help Show this help and exit
|
|
40
41
|
|
|
41
42
|
Examples:
|
|
42
|
-
hive-screens --list #
|
|
43
|
-
hive-screens --list --
|
|
44
|
-
hive-screens --close
|
|
43
|
+
hive-screens --list # list every match (default is --all)
|
|
44
|
+
hive-screens --list --oldest # preview only the oldest match
|
|
45
|
+
hive-screens --close # close the oldest finished run
|
|
45
46
|
hive-screens --enter --newest # attach to the newest finished run
|
|
46
47
|
|
|
47
|
-
|
|
48
|
+
References:
|
|
49
|
+
https://github.com/link-assistant/hive-mind/issues/1649
|
|
50
|
+
https://github.com/link-assistant/hive-mind/issues/1654
|
|
48
51
|
`;
|
|
49
52
|
|
|
50
53
|
const ACTION_FLAGS = new Set(['--enter', '--close', '--list']);
|
|
@@ -61,6 +64,7 @@ export const parseHiveScreensArgs = argv => {
|
|
|
61
64
|
close: false,
|
|
62
65
|
list: false,
|
|
63
66
|
selection: null,
|
|
67
|
+
verbose: false,
|
|
64
68
|
help: false,
|
|
65
69
|
error: null,
|
|
66
70
|
};
|
|
@@ -70,6 +74,10 @@ export const parseHiveScreensArgs = argv => {
|
|
|
70
74
|
result.help = true;
|
|
71
75
|
continue;
|
|
72
76
|
}
|
|
77
|
+
if (arg === '--verbose' || arg === '-v') {
|
|
78
|
+
result.verbose = true;
|
|
79
|
+
continue;
|
|
80
|
+
}
|
|
73
81
|
if (ACTION_FLAGS.has(arg)) {
|
|
74
82
|
if (arg === '--enter') result.enter = true;
|
|
75
83
|
else if (arg === '--close') result.close = true;
|
|
@@ -100,7 +108,10 @@ export const parseHiveScreensArgs = argv => {
|
|
|
100
108
|
return result;
|
|
101
109
|
}
|
|
102
110
|
|
|
103
|
-
|
|
111
|
+
// --list is a safe preview so default to showing every match. --enter and
|
|
112
|
+
// --close are destructive, so their default stays --oldest (mirrors the
|
|
113
|
+
// legacy hive-screens.sh behaviour).
|
|
114
|
+
if (!result.selection) result.selection = result.list ? 'all' : 'oldest';
|
|
104
115
|
return result;
|
|
105
116
|
};
|
|
106
117
|
|
|
@@ -212,7 +223,12 @@ export const selectMatches = (matches, selection) => {
|
|
|
212
223
|
return [matches[0]];
|
|
213
224
|
};
|
|
214
225
|
|
|
215
|
-
|
|
226
|
+
/**
|
|
227
|
+
* Print the Session / Log / Issue triple for one match. Shared by --list,
|
|
228
|
+
* --enter (after leaving), and --close so every action surfaces the same
|
|
229
|
+
* human-readable context the legacy hive-screens.sh script showed.
|
|
230
|
+
*/
|
|
231
|
+
const printSessionInfo = ({ session, logPath, issueUrl }, { log }) => {
|
|
216
232
|
log(`Session: ${session}`);
|
|
217
233
|
log(logPath ? `Log: ${logPath}` : 'Log: (not found)');
|
|
218
234
|
log(issueUrl ? `Issue: ${issueUrl}` : 'Issue: (not found)');
|
|
@@ -220,13 +236,32 @@ const printSession = ({ session, logPath, issueUrl }, { log }) => {
|
|
|
220
236
|
|
|
221
237
|
const SEPARATOR = '-----------------------------------';
|
|
222
238
|
|
|
239
|
+
/**
|
|
240
|
+
* Send `exit\n` to a detached screen session so its login shell terminates
|
|
241
|
+
* and the session is destroyed. Uses `spawn` with an argv array instead of
|
|
242
|
+
* `exec` with a shell string so we do not depend on the invoking shell
|
|
243
|
+
* understanding bash ANSI-C quoting (`$'exit\n'`), which `/bin/sh` on
|
|
244
|
+
* Debian/Ubuntu is dash and does not support. See issue #1654.
|
|
245
|
+
*/
|
|
246
|
+
export const closeScreenSession = async (session, { spawn } = {}) => {
|
|
247
|
+
const spawnFn = spawn || (await import('node:child_process')).spawn;
|
|
248
|
+
return new Promise((resolve, reject) => {
|
|
249
|
+
const child = spawnFn('screen', ['-S', session, '-X', 'stuff', 'exit\n'], { stdio: 'ignore' });
|
|
250
|
+
child.on('error', reject);
|
|
251
|
+
child.on('exit', code => {
|
|
252
|
+
if (code === 0) resolve();
|
|
253
|
+
else reject(new Error(`screen -X stuff exited with code ${code}`));
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
};
|
|
257
|
+
|
|
223
258
|
/**
|
|
224
259
|
* Top-level orchestrator used by the bin. `deps` is injected so tests can
|
|
225
260
|
* stub `exec`, `fs`, stdio, and process spawning without touching real
|
|
226
261
|
* screen sessions.
|
|
227
262
|
*/
|
|
228
263
|
export const runHiveScreens = async (argv, deps = {}) => {
|
|
229
|
-
const { exec = execAsync, fsModule = fs, tmpDir = os.tmpdir(), log = (...args) => console.log(...args), error = (...args) => console.error(...args), spawnScreen, captureOptions } = deps;
|
|
264
|
+
const { exec = execAsync, fsModule = fs, tmpDir = os.tmpdir(), log = (...args) => console.log(...args), error = (...args) => console.error(...args), spawnScreen, closeScreen, captureOptions } = deps;
|
|
230
265
|
|
|
231
266
|
const args = parseHiveScreensArgs(argv);
|
|
232
267
|
if (args.help) {
|
|
@@ -238,8 +273,12 @@ export const runHiveScreens = async (argv, deps = {}) => {
|
|
|
238
273
|
return 1;
|
|
239
274
|
}
|
|
240
275
|
|
|
276
|
+
const debug = args.verbose ? (...parts) => error('[hive-screens]', ...parts) : () => {};
|
|
277
|
+
|
|
241
278
|
const order = args.selection === 'newest' ? 'newest' : 'oldest';
|
|
279
|
+
debug(`scanning detached sessions in ${order}-first order`);
|
|
242
280
|
const matches = await findMatchingSessions({ exec, fsModule, tmpDir, order, captureOptions });
|
|
281
|
+
debug(`found ${matches.length} matching session(s)`);
|
|
243
282
|
|
|
244
283
|
if (!matches.length) {
|
|
245
284
|
log('No matching sessions');
|
|
@@ -247,10 +286,15 @@ export const runHiveScreens = async (argv, deps = {}) => {
|
|
|
247
286
|
}
|
|
248
287
|
|
|
249
288
|
const selected = selectMatches(matches, args.selection);
|
|
289
|
+
debug(`selection=${args.selection} -> acting on ${selected.length} session(s)`);
|
|
250
290
|
|
|
251
291
|
for (const match of selected) {
|
|
252
|
-
printSession(match, { log });
|
|
253
292
|
if (args.enter) {
|
|
293
|
+
// Print the session name up-front so the user knows which one they
|
|
294
|
+
// are about to attach to, then print the Log/Issue context AFTER
|
|
295
|
+
// control returns — otherwise `screen -r` swaps to the alternate
|
|
296
|
+
// buffer and wipes any context we printed beforehand.
|
|
297
|
+
log(`Session: ${match.session}`);
|
|
254
298
|
log(`Entering ${match.session}`);
|
|
255
299
|
if (spawnScreen) {
|
|
256
300
|
await spawnScreen(match.session);
|
|
@@ -258,13 +302,23 @@ export const runHiveScreens = async (argv, deps = {}) => {
|
|
|
258
302
|
await attachScreen(match.session);
|
|
259
303
|
}
|
|
260
304
|
log(`Left ${match.session}`);
|
|
261
|
-
|
|
262
|
-
|
|
305
|
+
log(match.logPath ? `Log: ${match.logPath}` : 'Log: (not found)');
|
|
306
|
+
log(match.issueUrl ? `Issue: ${match.issueUrl}` : 'Issue: (not found)');
|
|
307
|
+
} else if (args.close) {
|
|
308
|
+
printSessionInfo(match, { log });
|
|
263
309
|
log(`Closing ${match.session}`);
|
|
264
|
-
|
|
265
|
-
|
|
310
|
+
debug(`sending 'exit\\n' to ${match.session} via screen -X stuff`);
|
|
311
|
+
try {
|
|
312
|
+
if (closeScreen) {
|
|
313
|
+
await closeScreen(match.session);
|
|
314
|
+
} else {
|
|
315
|
+
await closeScreenSession(match.session);
|
|
316
|
+
}
|
|
317
|
+
} catch (err) {
|
|
266
318
|
error(`Failed to send exit to ${match.session}: ${err.message}`);
|
|
267
|
-
}
|
|
319
|
+
}
|
|
320
|
+
} else {
|
|
321
|
+
printSessionInfo(match, { log });
|
|
268
322
|
}
|
|
269
323
|
log(SEPARATOR);
|
|
270
324
|
}
|
package/src/hive.mjs
CHANGED
|
@@ -86,7 +86,7 @@ if (isRunningDirectly) {
|
|
|
86
86
|
const { validateClaudeConnection } = claudeLib;
|
|
87
87
|
// Import model validation library
|
|
88
88
|
const modelValidation = await import('./models/index.mjs');
|
|
89
|
-
const { validateAndExitOnInvalidModel, defaultModels } = modelValidation;
|
|
89
|
+
const { validateAndExitOnInvalidModel, defaultModels, resolveRuntimeDefaultModel } = modelValidation;
|
|
90
90
|
const githubLib = await import('./github.lib.mjs');
|
|
91
91
|
const { checkGitHubPermissions, fetchAllIssuesWithPagination, fetchProjectIssues, isRateLimitError, batchCheckPullRequestsForIssues, parseGitHubUrl, batchCheckArchivedRepositories } = githubLib;
|
|
92
92
|
// Import YouTrack-related functions
|
|
@@ -458,7 +458,7 @@ if (isRunningDirectly) {
|
|
|
458
458
|
|
|
459
459
|
const modelExplicitlyProvided = rawArgs.includes('--model') || rawArgs.includes('-m') || rawArgs.includes('--worker-model');
|
|
460
460
|
if (argv.tool && !modelExplicitlyProvided && defaultModels[argv.tool]) {
|
|
461
|
-
argv.model =
|
|
461
|
+
argv.model = await resolveRuntimeDefaultModel(argv.tool);
|
|
462
462
|
}
|
|
463
463
|
|
|
464
464
|
// Validate model names EARLY (simple string check, always runs)
|
package/src/models/index.mjs
CHANGED
|
@@ -12,6 +12,9 @@
|
|
|
12
12
|
* @see https://github.com/link-assistant/hive-mind/issues/1473
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
+
import { execFile } from 'node:child_process';
|
|
16
|
+
import { promisify } from 'node:util';
|
|
17
|
+
|
|
15
18
|
// Check if use is already defined (when imported from solve.mjs)
|
|
16
19
|
// If not, fetch it (when running standalone)
|
|
17
20
|
if (typeof globalThis.use === 'undefined') {
|
|
@@ -20,6 +23,8 @@ if (typeof globalThis.use === 'undefined') {
|
|
|
20
23
|
|
|
21
24
|
import { log } from '../lib.mjs';
|
|
22
25
|
|
|
26
|
+
const execFileAsync = promisify(execFile);
|
|
27
|
+
|
|
23
28
|
// ─── MODEL DATA ──────────────────────────────────────────────────────────────
|
|
24
29
|
|
|
25
30
|
// Claude models (Anthropic API)
|
|
@@ -106,9 +111,13 @@ export const opencodeModels = {
|
|
|
106
111
|
export const codexModels = {
|
|
107
112
|
gpt5: 'gpt-5',
|
|
108
113
|
'gpt-5': 'gpt-5',
|
|
114
|
+
'gpt-5.5': 'gpt-5.5',
|
|
115
|
+
'gpt-5.5-mini': 'gpt-5.5-mini',
|
|
116
|
+
'gpt-5.5-nano': 'gpt-5.5-nano',
|
|
109
117
|
'gpt-5.4': 'gpt-5.4',
|
|
110
118
|
'gpt-5.4-mini': 'gpt-5.4-mini',
|
|
111
119
|
'gpt-5.4-nano': 'gpt-5.4-nano',
|
|
120
|
+
'gpt-5.2': 'gpt-5.2',
|
|
112
121
|
'gpt-5.2-codex': 'gpt-5.2-codex',
|
|
113
122
|
'gpt-5.3-codex': 'gpt-5.3-codex',
|
|
114
123
|
'gpt-5.3-codex-spark': 'gpt-5.3-codex-spark',
|
|
@@ -125,7 +134,7 @@ export const defaultModels = {
|
|
|
125
134
|
claude: 'sonnet',
|
|
126
135
|
agent: 'nemotron-3-super-free', // Issue #1563: changed from qwen3.6-plus-free (free promotion ended) per agent PR #243
|
|
127
136
|
opencode: 'grok-code-fast-1',
|
|
128
|
-
codex: 'gpt-5.
|
|
137
|
+
codex: 'gpt-5.5',
|
|
129
138
|
};
|
|
130
139
|
|
|
131
140
|
// Models that support 1M token context window via [1m] suffix (Issue #1221, Issue #1238, Issue #1329)
|
|
@@ -190,9 +199,13 @@ export const OPENCODE_MODELS = {
|
|
|
190
199
|
export const CODEX_MODELS = {
|
|
191
200
|
...codexModels,
|
|
192
201
|
'gpt-5': 'gpt-5',
|
|
202
|
+
'gpt-5.5': 'gpt-5.5',
|
|
203
|
+
'gpt-5.5-mini': 'gpt-5.5-mini',
|
|
204
|
+
'gpt-5.5-nano': 'gpt-5.5-nano',
|
|
193
205
|
'gpt-5.4': 'gpt-5.4',
|
|
194
206
|
'gpt-5.4-mini': 'gpt-5.4-mini',
|
|
195
207
|
'gpt-5.4-nano': 'gpt-5.4-nano',
|
|
208
|
+
'gpt-5.2': 'gpt-5.2',
|
|
196
209
|
'gpt-5.2-codex': 'gpt-5.2-codex',
|
|
197
210
|
'gpt-5.3-codex': 'gpt-5.3-codex',
|
|
198
211
|
'gpt-5.3-codex-spark': 'gpt-5.3-codex-spark',
|
|
@@ -249,6 +262,50 @@ export const getDefaultModelForTool = tool => {
|
|
|
249
262
|
return defaultModels[tool] || defaultModels.claude;
|
|
250
263
|
};
|
|
251
264
|
|
|
265
|
+
let cachedInstalledCodexModelsPromise = null;
|
|
266
|
+
const CODEX_DEFAULT_FALLBACK_CHAIN = ['gpt-5.4', 'gpt-5.5-mini', 'gpt-5.4-mini', 'gpt-5.3-codex', 'gpt-5.3-codex-spark', 'gpt-5.2', 'gpt-5.2-codex', 'gpt-5.5-nano', 'gpt-5.4-nano'];
|
|
267
|
+
|
|
268
|
+
export const getInstalledCodexModels = async () => {
|
|
269
|
+
if (!cachedInstalledCodexModelsPromise) {
|
|
270
|
+
cachedInstalledCodexModelsPromise = (async () => {
|
|
271
|
+
try {
|
|
272
|
+
const { stdout } = await execFileAsync('codex', ['debug', 'models'], {
|
|
273
|
+
encoding: 'utf8',
|
|
274
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
275
|
+
});
|
|
276
|
+
const parsed = JSON.parse(stdout);
|
|
277
|
+
const modelSlugs = parsed?.models?.map(model => model?.slug).filter(Boolean);
|
|
278
|
+
return Array.isArray(modelSlugs) ? [...new Set(modelSlugs)] : null;
|
|
279
|
+
} catch {
|
|
280
|
+
return null;
|
|
281
|
+
}
|
|
282
|
+
})();
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
return cachedInstalledCodexModelsPromise;
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
export const resolveRuntimeDefaultModel = async (tool, options = {}) => {
|
|
289
|
+
const toolName = (tool || 'claude').toString().toLowerCase();
|
|
290
|
+
const preferredDefault = defaultModels[toolName] || defaultModels.claude;
|
|
291
|
+
|
|
292
|
+
if (toolName !== 'codex') {
|
|
293
|
+
return preferredDefault;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
const availableCodexModels = options.availableCodexModels === undefined ? await getInstalledCodexModels() : options.availableCodexModels;
|
|
297
|
+
|
|
298
|
+
if (!Array.isArray(availableCodexModels) || availableCodexModels.length === 0) {
|
|
299
|
+
return preferredDefault;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
if (availableCodexModels.includes(preferredDefault)) {
|
|
303
|
+
return preferredDefault;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
return CODEX_DEFAULT_FALLBACK_CHAIN.find(model => availableCodexModels.includes(model)) || preferredDefault;
|
|
307
|
+
};
|
|
308
|
+
|
|
252
309
|
/**
|
|
253
310
|
* Map model name to full model ID for a specific tool
|
|
254
311
|
* @param {string} tool - The tool name (claude, agent, opencode, codex)
|
|
@@ -318,7 +375,7 @@ export const getValidModelsForTool = tool => {
|
|
|
318
375
|
export const primaryModelNames = {
|
|
319
376
|
claude: ['opus', 'sonnet', 'haiku', 'opusplan'],
|
|
320
377
|
opencode: ['grok', 'gpt4o'],
|
|
321
|
-
codex: ['gpt-5.
|
|
378
|
+
codex: ['gpt-5.5', 'gpt-5.4', 'gpt-5.4-mini', 'gpt-5.3-codex', 'gpt-5.3-codex-spark'],
|
|
322
379
|
agent: ['nemotron-3-super-free', 'minimax-m2.5-free', 'big-pickle', 'gpt-5-nano', 'glm-5-free', 'deepseek-r1-free'],
|
|
323
380
|
};
|
|
324
381
|
|
package/src/solve.config.lib.mjs
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
// This approach was adopted per issue #482 feedback to minimize custom code maintenance
|
|
9
9
|
|
|
10
10
|
import { enhanceErrorMessage, detectMalformedFlags } from './option-suggestions.lib.mjs';
|
|
11
|
-
import { defaultModels, buildModelOptionDescription } from './models/index.mjs';
|
|
11
|
+
import { defaultModels, buildModelOptionDescription, resolveRuntimeDefaultModel } from './models/index.mjs';
|
|
12
12
|
import { validateBranchName } from './solve.branch.lib.mjs';
|
|
13
13
|
|
|
14
14
|
// Re-export for use by telegram-bot.mjs (avoids extra import lines there)
|
|
@@ -678,7 +678,7 @@ export const parseArguments = async (yargs, hideBin) => {
|
|
|
678
678
|
if (argv.tool && !modelExplicitlyProvided && defaultModels[argv.tool]) {
|
|
679
679
|
// User did not explicitly provide --model, so use the correct default for the tool
|
|
680
680
|
// (Issue #1473: centralized in models/index.mjs)
|
|
681
|
-
argv.model =
|
|
681
|
+
argv.model = await resolveRuntimeDefaultModel(argv.tool);
|
|
682
682
|
}
|
|
683
683
|
|
|
684
684
|
// Validate mutual exclusivity of --claude-file and --gitkeep-file
|