@link-assistant/hive-mind 2.1.9 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/README.hi.md +1 -1
- package/README.md +10 -10
- package/README.ru.md +1 -1
- package/README.zh.md +4 -4
- package/package.json +1 -1
- package/src/agent-commander.lib.mjs +7 -2
- package/src/claude.lib.mjs +5 -5
- package/src/codex.lib.mjs +5 -2
- package/src/codex.options.lib.mjs +34 -3
- package/src/config.lib.mjs +8 -2
- package/src/isolation-runner.lib.mjs +33 -4
- package/src/locales/en.lino +1 -1
- package/src/locales/hi.lino +1 -1
- package/src/locales/ru.lino +1 -1
- package/src/locales/zh.lino +1 -1
- package/src/models/index.mjs +6 -3
- package/src/solve.config.lib.mjs +8 -3
- package/src/thinking-prompt.lib.mjs +1 -0
- package/src/tool-retry.lib.mjs +7 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @link-assistant/hive-mind
|
|
2
2
|
|
|
3
|
+
## 2.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- d3b7c97: Default `--tool codex` to `gpt-5.6-sol` and make the `--think` levels map predictably to Codex reasoning efforts (`off`→`none`, `low`/`medium`/`high`/`xhigh`/`ultra`/`max` as an identity mapping). GPT-5.6 Sol's multi-agent `ultra` mode is always paired with a `rollout_token_budget` cap (default `500000`, overridable via `--rollout-token-budget`), and budget-derived effort stays capped at `xhigh`. Align `--tool claude` by adding the matching `ultra` level (equivalent to `ultracode`). By default both tools run the model as-is with no thinking level enforced.
|
|
8
|
+
|
|
9
|
+
## 2.1.11
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- 208e123: Fix false-positive npm releases (issue #2028). `setup-npm.mjs` now pins npm to the 11.x line and validates the result instead of installing `npm@latest` (which pulled in npm 12.0.0, whose sigstore regression crashes provenance publishes — npm/cli#9722). `publish-to-npm.mjs` no longer trusts the publish command's exit status alone: it observes the real exit code, scans output for failure patterns, and verifies the version is actually live on npm before reporting success, so a failed publish can no longer be reported as a successful release. Added `sanitize-npm-userconfig.mjs` to remove the deprecated `always-auth` npm warning from release logs.
|
|
14
|
+
|
|
15
|
+
## 2.1.10
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- 9964e69: Retry Claude stream-json sessions with `--resume` when the stream ends without a terminal result event after tool output.
|
|
20
|
+
- afbc353: Avoid fetching `use-m` at isolation-runner import time when tests only use pure helper exports.
|
|
21
|
+
|
|
3
22
|
## 2.1.9
|
|
4
23
|
|
|
5
24
|
### Patch Changes
|
package/README.hi.md
CHANGED
|
@@ -39,7 +39,7 @@ Hive Mind एक **सामान्यवादी AI** (मिनी-AGI) ह
|
|
|
39
39
|
| सदस्यता | `--tool` के साथ | डिफ़ॉल्ट मॉडल | किसके लिए बेहतर है |
|
|
40
40
|
| ---------------------------------------------------------------- | ------------------- | ------------- | ------------------------------------------------- |
|
|
41
41
|
| **Anthropic Claude MAX** (~$200/माह, अक्सर 50% छूट = $400 मूल्य) | `claude` (डिफ़ॉल्ट) | Sonnet/Haiku | उच्चतम रचनात्मकता, मजबूत सामान्य कोड रीजनिंग |
|
|
42
|
-
| **OpenAI ChatGPT Pro** ($200/माह, Codex शामिल) | `codex` | `gpt-5.
|
|
42
|
+
| **OpenAI ChatGPT Pro** ($200/माह, Codex शामिल) | `codex` | `gpt-5.6-sol` | भरोसेमंद deterministic refactors और तेज iteration |
|
|
43
43
|
|
|
44
44
|
दोनों टूल एक ही hive में साथ उपयोग किए जा सकते हैं। Worker अलग-अलग टूल समानांतर चला सकते हैं, और `/codex` या `/solve --tool codex` कार्यों को ChatGPT Pro पर भेजता है जबकि डिफ़ॉल्ट Claude MAX पर जाता है। किसी एक को चुनना आवश्यक नहीं है: किसी भी एक सदस्यता से संचालन संभव है, और दोनों का उपयोग per-tool/model concurrency mode (#1474) खोलता है।
|
|
45
45
|
|
package/README.md
CHANGED
|
@@ -39,7 +39,7 @@ Hive Mind is a **generalist AI** (mini-AGI) capable of working on a wide range o
|
|
|
39
39
|
| Subscription | Pairs with `--tool` | Default model | Best for |
|
|
40
40
|
| ------------------------------------------------------------------ | ------------------- | ------------- | ------------------------------------------------------- |
|
|
41
41
|
| **Anthropic Claude MAX** (~$200/month, often 50% off = $400 value) | `claude` (default) | Sonnet/Haiku | Highest creativity, strongest general code reasoning |
|
|
42
|
-
| **OpenAI ChatGPT Pro** ($200/month, includes Codex) | `codex` | `gpt-5.
|
|
42
|
+
| **OpenAI ChatGPT Pro** ($200/month, includes Codex) | `codex` | `gpt-5.6-sol` | Strong deterministic refactors and fast iteration loops |
|
|
43
43
|
|
|
44
44
|
Both tools can be combined in the same hive. Workers can run different tools in parallel, and `/codex` or `/solve --tool codex` routes tasks to ChatGPT Pro while the default routes to Claude MAX. There is no requirement to pick one: either single subscription is enough to operate, and using both unlocks per-tool/model concurrency mode (#1474).
|
|
45
45
|
|
|
@@ -507,15 +507,15 @@ Free Models via Kilo Gateway (with --tool agent):
|
|
|
507
507
|
|
|
508
508
|
Current tool defaults in Hive Mind:
|
|
509
509
|
|
|
510
|
-
| Tool | Default model
|
|
511
|
-
| ---------- |
|
|
512
|
-
| `claude` | `sonnet`
|
|
513
|
-
| `codex` | `gpt-5.
|
|
514
|
-
| `opencode` | `grok-code-fast-1`
|
|
515
|
-
| `agent` | `nemotron-3-super-free`
|
|
516
|
-
| `gemini` | `flash`
|
|
517
|
-
| `qwen` | `qwen3-coder-plus`
|
|
518
|
-
| `gemini` | `gemini-2.5-flash`
|
|
510
|
+
| Tool | Default model | Default reasoning behavior |
|
|
511
|
+
| ---------- | --------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- |
|
|
512
|
+
| `claude` | `sonnet` | No extra thinking is requested unless you pass `--think` or `--thinking-budget` |
|
|
513
|
+
| `codex` | `gpt-5.6-sol` preferred, with runtime fallback to local catalog (`gpt-5.5`) | Codex runs with `reasoning_effort=none` unless you pass `--think` or `--thinking-budget` |
|
|
514
|
+
| `opencode` | `grok-code-fast-1` | No extra thinking prompt is added for the default model |
|
|
515
|
+
| `agent` | `nemotron-3-super-free` | No extra thinking prompt is added for the default model |
|
|
516
|
+
| `gemini` | `flash` | No extra thinking prompt is added for the default model |
|
|
517
|
+
| `qwen` | `qwen3-coder-plus` | No extra thinking prompt is added for the default model |
|
|
518
|
+
| `gemini` | `gemini-2.5-flash` | No extra thinking prompt is added for the default model |
|
|
519
519
|
|
|
520
520
|
See [docs/CONFIGURATION.md](./docs/CONFIGURATION.md) for the full per-tool defaults and reasoning mappings.
|
|
521
521
|
|
package/README.ru.md
CHANGED
|
@@ -39,7 +39,7 @@ Hive Mind — это **универсальный ИИ** (мини-AGI), спо
|
|
|
39
39
|
| Подписка | Используется с `--tool` | Модель по умолчанию | Лучше всего подходит для |
|
|
40
40
|
| ----------------------------------------------------------------- | ----------------------- | ------------------- | ---------------------------------------------------------- |
|
|
41
41
|
| **Anthropic Claude MAX** (~$200 в месяц, часто скидка 50% = $400) | `claude` (по умолчанию) | Sonnet/Haiku | Максимальная креативность и сильное общее кодовое мышление |
|
|
42
|
-
| **OpenAI ChatGPT Pro** ($200 в месяц, включает Codex) | `codex` | `gpt-5.
|
|
42
|
+
| **OpenAI ChatGPT Pro** ($200 в месяц, включает Codex) | `codex` | `gpt-5.6-sol` | Надёжные детерминированные рефакторинги и быстрые итерации |
|
|
43
43
|
|
|
44
44
|
Оба инструмента можно сочетать в одном hive. Воркеры могут параллельно запускать разные инструменты, а `/codex` или `/solve --tool codex` направляет задачи в ChatGPT Pro, тогда как маршрут по умолчанию идёт в Claude MAX. Выбирать только один вариант не требуется: любой одной подписки достаточно для работы, а использование обеих открывает режим параллелизма по инструментам/моделям (#1474).
|
|
45
45
|
|
package/README.zh.md
CHANGED
|
@@ -36,10 +36,10 @@ Hive Mind 是一款**通用 AI**(迷你 AGI),能够处理广泛的任务
|
|
|
36
36
|
|
|
37
37
|
**费用**:Hive Mind 支持两种 $200/月订阅作为功能完整、近乎“无限”的选项:
|
|
38
38
|
|
|
39
|
-
| 订阅 | 搭配 `--tool` | 默认模型
|
|
40
|
-
| ---------------------------------------------------------------- | ---------------- |
|
|
41
|
-
| **Anthropic Claude MAX**(约 $200/月,常有五折优惠 = 价值 $400) | `claude`(默认) | Sonnet/Haiku
|
|
42
|
-
| **OpenAI ChatGPT Pro**($200/月,包含 Codex) | `codex` | `gpt-5.
|
|
39
|
+
| 订阅 | 搭配 `--tool` | 默认模型 | 最适合场景 |
|
|
40
|
+
| ---------------------------------------------------------------- | ---------------- | ------------- | ---------------------------- |
|
|
41
|
+
| **Anthropic Claude MAX**(约 $200/月,常有五折优惠 = 价值 $400) | `claude`(默认) | Sonnet/Haiku | 最高创造力、最强通用代码推理 |
|
|
42
|
+
| **OpenAI ChatGPT Pro**($200/月,包含 Codex) | `codex` | `gpt-5.6-sol` | 稳定确定性的重构和快速迭代 |
|
|
43
43
|
|
|
44
44
|
两个工具可以在同一个 hive 中组合使用。Worker 可以并行运行不同工具,`/codex` 或 `/solve --tool codex` 会将任务路由到 ChatGPT Pro,而默认路由到 Claude MAX。无需二选一:任意单一订阅都足以运行,同时使用两者可解锁按工具/模型划分的并发模式(#1474)。
|
|
45
45
|
|
package/package.json
CHANGED
|
@@ -62,8 +62,13 @@ const buildClaudeToolOptions = (argv = {}) => {
|
|
|
62
62
|
|
|
63
63
|
const buildCodexToolOptions = (argv = {}) => {
|
|
64
64
|
const options = {};
|
|
65
|
-
const { reasoningEffort } = resolveCodexReasoningEffort(argv);
|
|
66
|
-
|
|
65
|
+
const { reasoningEffort, rolloutTokenBudget } = resolveCodexReasoningEffort(argv);
|
|
66
|
+
const reasoningArgs = ['-c', `model_reasoning_effort=${reasoningEffort}`, '-c', 'model_reasoning_summary=auto'];
|
|
67
|
+
// Issue #2027: pair GPT-5.6 Sol's multi-agent `ultra` effort with a rollout token budget cap.
|
|
68
|
+
if (rolloutTokenBudget) {
|
|
69
|
+
reasoningArgs.push('-c', `rollout_token_budget=${rolloutTokenBudget}`);
|
|
70
|
+
}
|
|
71
|
+
appendExtraArgs(options, reasoningArgs);
|
|
67
72
|
|
|
68
73
|
appendExtraArgs(options, buildCodexDisable1mContextConfigArgs(!!argv.disable1mContext));
|
|
69
74
|
try {
|
package/src/claude.lib.mjs
CHANGED
|
@@ -1163,6 +1163,11 @@ export const executeClaudeCommand = async params => {
|
|
|
1163
1163
|
queuedFeedback,
|
|
1164
1164
|
};
|
|
1165
1165
|
}
|
|
1166
|
+
if (shouldFailClaudeStreamWithoutResult({ commandFailed, streamingInput, resultEventReceived })) {
|
|
1167
|
+
commandFailed = true;
|
|
1168
|
+
lastMessage = buildMissingClaudeResultMessage({ lastToolResultError, lastMessage });
|
|
1169
|
+
await log(`\n\n❌ Command failed: ${lastMessage}`, { level: 'error' });
|
|
1170
|
+
}
|
|
1166
1171
|
const retryableLastError = classifyRetryableError(lastMessage);
|
|
1167
1172
|
// Issue #1834: Corrupted extended-thinking blocks → try to resume the session first, then fall
|
|
1168
1173
|
// back to a fresh restart (PR #1835 feedback). When both caps are reached, tryThinkingBlockRecovery
|
|
@@ -1291,11 +1296,6 @@ export const executeClaudeCommand = async params => {
|
|
|
1291
1296
|
.join('\n');
|
|
1292
1297
|
await log(`\n\n❌ Command failed: No messages processed and errors detected in stderr\nStderr errors:\n${errorsPreview}`, { level: 'error' });
|
|
1293
1298
|
}
|
|
1294
|
-
if (shouldFailClaudeStreamWithoutResult({ commandFailed, streamingInput, resultEventReceived })) {
|
|
1295
|
-
commandFailed = true;
|
|
1296
|
-
lastMessage = buildMissingClaudeResultMessage({ lastToolResultError, lastMessage });
|
|
1297
|
-
await log(`\n\n❌ Command failed: ${lastMessage}`, { level: 'error' });
|
|
1298
|
-
}
|
|
1299
1299
|
if (commandFailed) {
|
|
1300
1300
|
// Take resource snapshot after failure
|
|
1301
1301
|
const resourcesAfter = await getResourceSnapshot();
|
package/src/codex.lib.mjs
CHANGED
|
@@ -804,7 +804,7 @@ export const executeCodexCommand = async params => {
|
|
|
804
804
|
|
|
805
805
|
let execCommand;
|
|
806
806
|
const mappedModel = mapModelToId(argv.model);
|
|
807
|
-
const { reasoningEffort, source: reasoningEffortSource } = resolveCodexReasoningEffort(argv);
|
|
807
|
+
const { reasoningEffort, source: reasoningEffortSource, rolloutTokenBudget } = resolveCodexReasoningEffort(argv);
|
|
808
808
|
const isResumeMode = !!argv.resume;
|
|
809
809
|
const codexEnv = getCodexExecEnv(argv.verbose);
|
|
810
810
|
|
|
@@ -839,7 +839,10 @@ export const executeCodexCommand = async params => {
|
|
|
839
839
|
for (const arg of codexPlaywrightMcpDisableConfigArgs) {
|
|
840
840
|
codexArgs += ` ${shellQuote(arg)}`;
|
|
841
841
|
}
|
|
842
|
-
codexArgs += ` --json --skip-git-repo-check -o ${shellQuote(lastMessageFile)} -c ${shellQuote(`model_reasoning_effort=${reasoningEffort}`)} -c ${shellQuote('model_reasoning_summary=auto')}
|
|
842
|
+
codexArgs += ` --json --skip-git-repo-check -o ${shellQuote(lastMessageFile)} -c ${shellQuote(`model_reasoning_effort=${reasoningEffort}`)} -c ${shellQuote('model_reasoning_summary=auto')}`;
|
|
843
|
+
// Issue #2027: pair GPT-5.6 Sol's multi-agent `ultra` effort with a rollout token budget cap so it stays predictable and does not run away on cost.
|
|
844
|
+
if (rolloutTokenBudget) codexArgs += ` -c ${shellQuote(`rollout_token_budget=${rolloutTokenBudget}`)}`;
|
|
845
|
+
codexArgs += ' --dangerously-bypass-approvals-and-sandbox';
|
|
843
846
|
|
|
844
847
|
// Issue #1706: Append --disable-1m-context and --sub-session-size as Codex -c overrides.
|
|
845
848
|
let parsedSubSessionSize;
|
|
@@ -4,13 +4,34 @@ import { codexModels } from './models/index.mjs';
|
|
|
4
4
|
|
|
5
5
|
export const mapModelToId = model => codexModels[model] || model;
|
|
6
6
|
|
|
7
|
+
// Issue #2027: Map the shared hive-mind --think levels to Codex `model_reasoning_effort`
|
|
8
|
+
// values. GPT-5.6 Sol (the default Codex model) keeps the full ladder inherited from the
|
|
9
|
+
// GPT-5.5/GPT-5.4 generation — low/medium/high/xhigh — and adds `max` *above* xhigh for the
|
|
10
|
+
// deepest single-agent reasoning, plus a multi-agent `ultra` mode. Because every hive level
|
|
11
|
+
// has a same-named Codex reasoning effort, the mapping is a predictable identity: `xhigh`
|
|
12
|
+
// stays `xhigh` (natively supported per `codex debug models`), `ultra` selects GPT-5.6's
|
|
13
|
+
// multi-agent ultra mode (the counterpart of Claude's "ultracode"), and `max` selects the
|
|
14
|
+
// deepest single-agent effort. `off` disables reasoning (`none`). See docs/case-studies/issue-2027.
|
|
7
15
|
const THINK_LEVEL_TO_CODEX_REASONING = {
|
|
8
16
|
off: 'none',
|
|
9
17
|
low: 'low',
|
|
10
18
|
medium: 'medium',
|
|
11
19
|
high: 'high',
|
|
12
20
|
xhigh: 'xhigh',
|
|
13
|
-
|
|
21
|
+
ultra: 'ultra',
|
|
22
|
+
max: 'max',
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
// Issue #2027: GPT-5.6 Sol's multi-agent `ultra` mode spawns subagents and consumes far more
|
|
26
|
+
// tokens per turn than single-agent reasoning. OpenAI's guidance is explicit: never use `ultra`
|
|
27
|
+
// reasoning effort without a `rollout_token_budget` cap, or it can run away on cost. We pair
|
|
28
|
+
// every `ultra` selection with this budget (their recommended default) so `--think ultra` stays
|
|
29
|
+
// predictable. Override with `--rollout-token-budget`.
|
|
30
|
+
export const CODEX_ULTRA_ROLLOUT_TOKEN_BUDGET = 500000;
|
|
31
|
+
|
|
32
|
+
const resolveUltraRolloutTokenBudget = argv => {
|
|
33
|
+
const override = argv?.rolloutTokenBudget;
|
|
34
|
+
return Number.isFinite(override) && override > 0 ? override : CODEX_ULTRA_ROLLOUT_TOKEN_BUDGET;
|
|
14
35
|
};
|
|
15
36
|
|
|
16
37
|
export const resolveCodexReasoningEffort = argv => {
|
|
@@ -26,6 +47,10 @@ export const resolveCodexReasoningEffort = argv => {
|
|
|
26
47
|
}
|
|
27
48
|
|
|
28
49
|
const ratio = Math.min(1, thinkingBudget / maxBudget);
|
|
50
|
+
// Issue #2027: the budget-derived effort caps at `xhigh` — the deepest tier every Codex
|
|
51
|
+
// model (including the gpt-5.5 runtime fallback) supports. `max` is GPT-5.6-only and `ultra`
|
|
52
|
+
// needs a paired rollout token budget, so both require an explicit `--think max`/`--think ultra`
|
|
53
|
+
// to stay predictable rather than being reached implicitly through a token budget.
|
|
29
54
|
const reasoningEffort = ratio <= 0.2 ? 'minimal' : ratio <= 0.4 ? 'low' : ratio <= 0.6 ? 'medium' : ratio <= 0.8 ? 'high' : 'xhigh';
|
|
30
55
|
|
|
31
56
|
return {
|
|
@@ -35,10 +60,15 @@ export const resolveCodexReasoningEffort = argv => {
|
|
|
35
60
|
}
|
|
36
61
|
|
|
37
62
|
if (argv?.think && THINK_LEVEL_TO_CODEX_REASONING[argv.think]) {
|
|
38
|
-
|
|
39
|
-
|
|
63
|
+
const reasoningEffort = THINK_LEVEL_TO_CODEX_REASONING[argv.think];
|
|
64
|
+
const result = {
|
|
65
|
+
reasoningEffort,
|
|
40
66
|
source: `--think ${argv.think}`,
|
|
41
67
|
};
|
|
68
|
+
if (reasoningEffort === 'ultra') {
|
|
69
|
+
result.rolloutTokenBudget = resolveUltraRolloutTokenBudget(argv);
|
|
70
|
+
}
|
|
71
|
+
return result;
|
|
42
72
|
}
|
|
43
73
|
|
|
44
74
|
return {
|
|
@@ -50,4 +80,5 @@ export const resolveCodexReasoningEffort = argv => {
|
|
|
50
80
|
export default {
|
|
51
81
|
mapModelToId,
|
|
52
82
|
resolveCodexReasoningEffort,
|
|
83
|
+
CODEX_ULTRA_ROLLOUT_TOKEN_BUDGET,
|
|
53
84
|
};
|
package/src/config.lib.mjs
CHANGED
|
@@ -397,6 +397,7 @@ export const getThinkingLevelToTokens = (maxBudget = DEFAULT_MAX_THINKING_BUDGET
|
|
|
397
397
|
medium: Math.floor(maxBudget / 2), // ~16000 for default 31999
|
|
398
398
|
high: Math.floor((maxBudget * 3) / 4), // ~24000 for default 31999
|
|
399
399
|
xhigh: maxBudget, // same as max when represented as MAX_THINKING_TOKENS
|
|
400
|
+
ultra: maxBudget, // Issue #2027: ultra is max-class in token terms for Claude
|
|
400
401
|
max: maxBudget, // 31999 by default
|
|
401
402
|
});
|
|
402
403
|
|
|
@@ -482,10 +483,13 @@ export const OPUS_46_EFFORT_LEVELS = ['low', 'medium', 'high', 'max'];
|
|
|
482
483
|
export const OPUS_47_EFFORT_LEVELS = ['low', 'medium', 'high', 'xhigh', 'max'];
|
|
483
484
|
|
|
484
485
|
/**
|
|
485
|
-
* Convert thinking level to effort level (Issue #1238, Issue #1620)
|
|
486
|
+
* Convert thinking level to effort level (Issue #1238, Issue #1620, Issue #2027)
|
|
486
487
|
* Models with max support keep max as max. Opus 4.7 keeps xhigh as xhigh.
|
|
487
488
|
* Models with effort but without max support use high for max/xhigh.
|
|
488
|
-
*
|
|
489
|
+
* `ultra` (Issue #2027) requests Claude "ultracode"-class reasoning; Claude Code has no
|
|
490
|
+
* distinct `ultra`/`ultracode` effort value, so it clamps to the highest supported effort
|
|
491
|
+
* (max, else xhigh, else high).
|
|
492
|
+
* @param {string|undefined} thinkLevel - The thinking level (off/low/medium/high/xhigh/ultra/max)
|
|
489
493
|
* @param {Object} [options] - Options
|
|
490
494
|
* @param {boolean} [options.isOpus47] - Backward-compatible shorthand for supportsXHigh
|
|
491
495
|
* @param {boolean} [options.supportsXHigh] - Whether the model supports xhigh effort
|
|
@@ -509,6 +513,8 @@ export const thinkLevelToEffortLevel = (thinkLevel, options = {}) => {
|
|
|
509
513
|
return 'high';
|
|
510
514
|
case 'xhigh':
|
|
511
515
|
return supportsXHigh ? 'xhigh' : supportsMax ? 'max' : 'high';
|
|
516
|
+
case 'ultra':
|
|
517
|
+
return supportsMax ? 'max' : supportsXHigh ? 'xhigh' : 'high';
|
|
512
518
|
case 'max':
|
|
513
519
|
return supportsMax ? 'max' : 'high';
|
|
514
520
|
default:
|
|
@@ -20,11 +20,26 @@ import os from 'node:os';
|
|
|
20
20
|
import path from 'node:path';
|
|
21
21
|
import { isExecutingSessionStatus, isTerminalSessionStatus } from './session-status.lib.mjs';
|
|
22
22
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
let commandStreamDollarPromise = null;
|
|
24
|
+
|
|
25
|
+
async function getCommandStreamDollar() {
|
|
26
|
+
if (!commandStreamDollarPromise) {
|
|
27
|
+
commandStreamDollarPromise = (async () => {
|
|
28
|
+
if (typeof globalThis.use === 'undefined') {
|
|
29
|
+
await ensureUseM();
|
|
30
|
+
}
|
|
31
|
+
const { $ } = await globalThis.use('command-stream');
|
|
32
|
+
return $;
|
|
33
|
+
})();
|
|
34
|
+
}
|
|
26
35
|
|
|
27
|
-
|
|
36
|
+
try {
|
|
37
|
+
return await commandStreamDollarPromise;
|
|
38
|
+
} catch (error) {
|
|
39
|
+
commandStreamDollarPromise = null;
|
|
40
|
+
throw error;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
28
43
|
|
|
29
44
|
// Re-export the shared status predicates so existing callers that reach them via
|
|
30
45
|
// the isolation-runner module (e.g. session-monitor's `runner.isExecutingSessionStatus`)
|
|
@@ -516,6 +531,7 @@ export function readSessionExitFromLog(logPath, options = {}) {
|
|
|
516
531
|
*/
|
|
517
532
|
async function findStartCommandBinary() {
|
|
518
533
|
try {
|
|
534
|
+
const $ = await getCommandStreamDollar();
|
|
519
535
|
const result = await $({ mirror: false })`which $`;
|
|
520
536
|
const path = result.stdout?.toString().trim() || '';
|
|
521
537
|
return path || null;
|
|
@@ -677,6 +693,7 @@ export async function querySessionStatus(sessionId, verbose = false) {
|
|
|
677
693
|
}
|
|
678
694
|
|
|
679
695
|
try {
|
|
696
|
+
const $ = await getCommandStreamDollar();
|
|
680
697
|
const result = await $({ mirror: false })`${binPath} --status ${sessionId} --output-format json`;
|
|
681
698
|
|
|
682
699
|
const stdout = result.stdout?.toString().trim() || '';
|
|
@@ -755,6 +772,7 @@ export async function listIsolationSessions(verbose = false) {
|
|
|
755
772
|
return [];
|
|
756
773
|
}
|
|
757
774
|
try {
|
|
775
|
+
const $ = await getCommandStreamDollar();
|
|
758
776
|
const result = await $({ mirror: false })`${binPath} --list --output-format json`;
|
|
759
777
|
const stdout = result.stdout?.toString().trim() || '';
|
|
760
778
|
const sessions = parseSessionListOutput(stdout);
|
|
@@ -791,6 +809,7 @@ export async function stopIsolatedSession(sessionId, verbose = false) {
|
|
|
791
809
|
}
|
|
792
810
|
|
|
793
811
|
try {
|
|
812
|
+
const $ = await getCommandStreamDollar();
|
|
794
813
|
const result = await $({ mirror: false })`${binPath} --stop ${sessionId}`;
|
|
795
814
|
const stdout = result.stdout?.toString() || '';
|
|
796
815
|
const stderr = result.stderr?.toString() || '';
|
|
@@ -827,6 +846,7 @@ export async function stopIsolatedSession(sessionId, verbose = false) {
|
|
|
827
846
|
*/
|
|
828
847
|
export async function checkScreenSessionRunning(sessionName, verbose = false) {
|
|
829
848
|
try {
|
|
849
|
+
const $ = await getCommandStreamDollar();
|
|
830
850
|
const result = await $({ mirror: false })`screen -ls`;
|
|
831
851
|
const output = result.stdout?.toString() || '';
|
|
832
852
|
const exists = output.includes(sessionName);
|
|
@@ -857,6 +877,7 @@ export async function checkScreenSessionRunning(sessionName, verbose = false) {
|
|
|
857
877
|
*/
|
|
858
878
|
export async function checkDockerContainerRunning(containerName, verbose = false) {
|
|
859
879
|
try {
|
|
880
|
+
const $ = await getCommandStreamDollar();
|
|
860
881
|
const result = await $({ mirror: false })`docker inspect -f ${'{{.State.Running}}'} ${containerName}`;
|
|
861
882
|
const running = (result.stdout?.toString() || '').trim() === 'true';
|
|
862
883
|
if (verbose) {
|
|
@@ -890,6 +911,7 @@ export function parseDockerContainerWritableLayerSizeOutput(output) {
|
|
|
890
911
|
export async function getDockerContainerWritableLayerSize(containerName, verbose = false) {
|
|
891
912
|
if (!containerName) return null;
|
|
892
913
|
try {
|
|
914
|
+
const $ = await getCommandStreamDollar();
|
|
893
915
|
const result = await $({ mirror: false })`docker inspect --size -f ${'{{.SizeRw}}'} ${containerName}`;
|
|
894
916
|
const bytes = parseDockerContainerWritableLayerSizeOutput(result.stdout?.toString() || '');
|
|
895
917
|
if (verbose) {
|
|
@@ -922,6 +944,7 @@ export async function releaseDockerContainerStartGate(containerName, verbose = f
|
|
|
922
944
|
|
|
923
945
|
for (let attempt = 1; attempt <= 5; attempt++) {
|
|
924
946
|
try {
|
|
947
|
+
const $ = await getCommandStreamDollar();
|
|
925
948
|
await $({ mirror: false })`docker exec ${containerName} sh -c ${releaseCommand}`;
|
|
926
949
|
if (verbose) {
|
|
927
950
|
console.log(`[VERBOSE] isolation-runner: released docker start gate for '${containerName}'`);
|
|
@@ -960,6 +983,7 @@ export async function removeDockerContainer(containerName, verbose = false) {
|
|
|
960
983
|
}
|
|
961
984
|
|
|
962
985
|
try {
|
|
986
|
+
const $ = await getCommandStreamDollar();
|
|
963
987
|
const result = await $({ mirror: false })`docker rm -f ${containerName}`;
|
|
964
988
|
const stdout = result.stdout?.toString() || '';
|
|
965
989
|
const stderr = result.stderr?.toString() || '';
|
|
@@ -992,6 +1016,7 @@ export async function removeDockerContainer(containerName, verbose = false) {
|
|
|
992
1016
|
*/
|
|
993
1017
|
export async function checkTmuxSessionRunning(sessionName, verbose = false) {
|
|
994
1018
|
try {
|
|
1019
|
+
const $ = await getCommandStreamDollar();
|
|
995
1020
|
await $({ mirror: false })`tmux has-session -t ${sessionName}`;
|
|
996
1021
|
if (verbose) console.log(`[VERBOSE] isolation-runner: tmux has-session '${sessionName}': running`);
|
|
997
1022
|
return true;
|
|
@@ -1035,6 +1060,7 @@ export async function checkBackendSessionAlive(sessionId, backend, verbose = fal
|
|
|
1035
1060
|
*/
|
|
1036
1061
|
export async function checkDockerImagePresent(image, verbose = false) {
|
|
1037
1062
|
try {
|
|
1063
|
+
const $ = await getCommandStreamDollar();
|
|
1038
1064
|
await $({ mirror: false })`docker image inspect ${image}`;
|
|
1039
1065
|
if (verbose) console.log(`[VERBOSE] isolation-runner: docker image inspect '${image}': present`);
|
|
1040
1066
|
return true;
|
|
@@ -1062,6 +1088,7 @@ export async function checkDockerImagePresent(image, verbose = false) {
|
|
|
1062
1088
|
*/
|
|
1063
1089
|
export async function checkDockerStorageDriver(verbose = false) {
|
|
1064
1090
|
try {
|
|
1091
|
+
const $ = await getCommandStreamDollar();
|
|
1065
1092
|
const result = await $({ mirror: false })`docker info --format ${'{{.Driver}}'}`;
|
|
1066
1093
|
const driver = (result.stdout?.toString() || '').trim().toLowerCase() || null;
|
|
1067
1094
|
if (verbose) console.log(`[VERBOSE] isolation-runner: docker storage driver: ${driver || '(unknown)'}`);
|
|
@@ -1091,6 +1118,7 @@ export async function checkDockerDiskSpace(verbose = false) {
|
|
|
1091
1118
|
try {
|
|
1092
1119
|
let dataRoot = '/var/lib/docker';
|
|
1093
1120
|
try {
|
|
1121
|
+
const $ = await getCommandStreamDollar();
|
|
1094
1122
|
const info = await $({ mirror: false })`docker info --format ${'{{.DockerRootDir}}'}`;
|
|
1095
1123
|
const root = (info.stdout?.toString() || '').trim();
|
|
1096
1124
|
if (root) dataRoot = root;
|
|
@@ -1099,6 +1127,7 @@ export async function checkDockerDiskSpace(verbose = false) {
|
|
|
1099
1127
|
// fails on it (e.g. the path does not exist) we return null below.
|
|
1100
1128
|
}
|
|
1101
1129
|
|
|
1130
|
+
const $ = await getCommandStreamDollar();
|
|
1102
1131
|
const df = await $({ mirror: false })`df -Pk ${dataRoot}`;
|
|
1103
1132
|
// `df -P` guarantees one logical line per filesystem (no wrapping). The last
|
|
1104
1133
|
// line is the data row: Filesystem 1024-blocks Used Available Capacity Mount
|
package/src/locales/en.lino
CHANGED
|
@@ -578,7 +578,7 @@ en
|
|
|
578
578
|
branch
|
|
579
579
|
option "• `--base-branch <branch>` or `-b` - Target branch for PR (default: repo default branch)"
|
|
580
580
|
think
|
|
581
|
-
option "• `--think <level>` - Thinking level (off/low/medium/high/xhigh/max) | `--thinking-budget <num>` - Token budget (0-63999)"
|
|
581
|
+
option "• `--think <level>` - Thinking level (off/low/medium/high/xhigh/ultra/max) | `--thinking-budget <num>` - Token budget (0-63999)"
|
|
582
582
|
verbose
|
|
583
583
|
option "• `--verbose` or `-v` - Verbose output | `--attach-logs` - Attach logs to PR"
|
|
584
584
|
show
|
package/src/locales/hi.lino
CHANGED
|
@@ -578,7 +578,7 @@ hi
|
|
|
578
578
|
branch
|
|
579
579
|
option "• `--base-branch <branch>` या `-b` - PR के लिए target branch (default: repo default branch)"
|
|
580
580
|
think
|
|
581
|
-
option "• `--think <level>` - thinking level (off/low/medium/high/xhigh/max) | `--thinking-budget <num>` - token budget (0-63999)"
|
|
581
|
+
option "• `--think <level>` - thinking level (off/low/medium/high/xhigh/ultra/max) | `--thinking-budget <num>` - token budget (0-63999)"
|
|
582
582
|
verbose
|
|
583
583
|
option "• `--verbose` या `-v` - verbose output | `--attach-logs` - logs को PR से attach करें"
|
|
584
584
|
show
|
package/src/locales/ru.lino
CHANGED
|
@@ -578,7 +578,7 @@ ru
|
|
|
578
578
|
branch
|
|
579
579
|
option "• `--base-branch <branch>` или `-b` - Целевая ветка для PR (по умолчанию ветка репозитория)"
|
|
580
580
|
think
|
|
581
|
-
option "• `--think <level>` - уровень размышления (off/low/medium/high/xhigh/max) | `--thinking-budget <num>` - бюджет токенов (0-63999)"
|
|
581
|
+
option "• `--think <level>` - уровень размышления (off/low/medium/high/xhigh/ultra/max) | `--thinking-budget <num>` - бюджет токенов (0-63999)"
|
|
582
582
|
verbose
|
|
583
583
|
option "• `--verbose` или `-v` - подробный вывод | `--attach-logs` - прикрепить логи к PR"
|
|
584
584
|
show
|
package/src/locales/zh.lino
CHANGED
|
@@ -578,7 +578,7 @@ zh
|
|
|
578
578
|
branch
|
|
579
579
|
option "• `--base-branch <branch>` 或 `-b` - PR 目标分支(默认:仓库默认分支)"
|
|
580
580
|
think
|
|
581
|
-
option "• `--think <level>` - 思考级别(off/low/medium/high/xhigh/max)| `--thinking-budget <num>` - token 预算(0-63999)"
|
|
581
|
+
option "• `--think <level>` - 思考级别(off/low/medium/high/xhigh/ultra/max)| `--thinking-budget <num>` - token 预算(0-63999)"
|
|
582
582
|
verbose
|
|
583
583
|
option "• `--verbose` 或 `-v` - 详细输出 | `--attach-logs` - 将日志附加到 PR"
|
|
584
584
|
show
|
package/src/models/index.mjs
CHANGED
|
@@ -192,7 +192,7 @@ export const defaultModels = {
|
|
|
192
192
|
claude: 'sonnet',
|
|
193
193
|
agent: 'nemotron-3-super-free', // Issue #1563: changed from qwen3.6-plus-free (free promotion ended) per agent PR #243
|
|
194
194
|
opencode: 'grok-code-fast-1',
|
|
195
|
-
codex: 'gpt-5.
|
|
195
|
+
codex: 'gpt-5.6-sol', // Issue #2027: GPT-5.6 Sol is the released Codex flagship; runtime falls back to gpt-5.5 when Sol is not in the local catalog
|
|
196
196
|
qwen: 'qwen3-coder-plus',
|
|
197
197
|
gemini: 'flash',
|
|
198
198
|
};
|
|
@@ -366,7 +366,10 @@ export const getDefaultModelForTool = tool => {
|
|
|
366
366
|
};
|
|
367
367
|
|
|
368
368
|
let cachedInstalledCodexModelsPromise = null;
|
|
369
|
-
|
|
369
|
+
// Issue #2027: With gpt-5.6-sol as the preferred default, the fallback chain is only
|
|
370
|
+
// consulted when Sol is absent from the local catalog. Prefer the previous stable
|
|
371
|
+
// default (gpt-5.5) first, then the remaining GPT-5.6 preview tiers, then older models.
|
|
372
|
+
const CODEX_DEFAULT_FALLBACK_CHAIN = ['gpt-5.5', 'openai.gpt-5.5', 'gpt-5.6-terra', 'gpt-5.6-luna', 'openai.gpt-5.6-sol', 'openai.gpt-5.6-terra', 'openai.gpt-5.6-luna', 'gpt-5.4', 'openai.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'];
|
|
370
373
|
|
|
371
374
|
export const getInstalledCodexModels = async () => {
|
|
372
375
|
if (!cachedInstalledCodexModelsPromise) {
|
|
@@ -490,7 +493,7 @@ export const getValidModelsForTool = tool => {
|
|
|
490
493
|
export const primaryModelNames = {
|
|
491
494
|
claude: ['opus', 'sonnet', 'haiku', 'opusplan', 'fable'],
|
|
492
495
|
opencode: ['grok', 'gpt4o'],
|
|
493
|
-
codex: ['gpt-5.
|
|
496
|
+
codex: ['gpt-5.6-sol', 'gpt-5.5', 'gpt-5.6-terra', 'gpt-5.6-luna', 'gpt-5.4', 'gpt-5.4-mini', 'gpt-5.3-codex-spark'],
|
|
494
497
|
agent: ['nemotron-3-super-free', 'minimax-m2.5-free', 'big-pickle', 'gpt-5-nano', 'glm-5-free', 'deepseek-r1-free'],
|
|
495
498
|
qwen: ['qwen3-coder-plus', 'qwen3-coder', 'qwen3-coder-flash'],
|
|
496
499
|
gemini: ['flash', 'pro', 'flash-lite', 'auto'],
|
package/src/solve.config.lib.mjs
CHANGED
|
@@ -299,13 +299,18 @@ export const SOLVE_OPTION_DEFINITIONS = {
|
|
|
299
299
|
},
|
|
300
300
|
think: {
|
|
301
301
|
type: 'string',
|
|
302
|
-
description: 'Thinking level hint. For Claude, translated to --thinking-budget for Claude Code >= 2.1.12 (off=0, low=~8000, medium=~16000, high=~24000, xhigh/max=31999) and to CLAUDE_CODE_EFFORT_LEVEL when supported. Fable 5/Mythos 5/Sonnet 5/Opus 4.8/4.7 support xhigh and max; Opus 4.6/Sonnet 4.6/Mythos Preview support max; Opus 4.5 uses high for xhigh/max. For Codex, mapped to reasoning effort (off=none, low=low, medium=medium, high=high, xhigh
|
|
303
|
-
choices: ['off', 'low', 'medium', 'high', 'xhigh', 'max'],
|
|
302
|
+
description: 'Thinking level hint. For Claude, translated to --thinking-budget for Claude Code >= 2.1.12 (off=0, low=~8000, medium=~16000, high=~24000, xhigh/ultra/max=31999) and to CLAUDE_CODE_EFFORT_LEVEL when supported. Fable 5/Mythos 5/Sonnet 5/Opus 4.8/4.7 support xhigh and max; Opus 4.6/Sonnet 4.6/Mythos Preview support max; Opus 4.5 uses high for xhigh/max. `ultra` maps to the highest supported Claude effort (Claude "ultracode"-class reasoning). For Codex (GPT-5.6 Sol), mapped 1:1 to reasoning effort (off=none, low=low, medium=medium, high=high, xhigh=xhigh, ultra=ultra, max=max); GPT-5.6 keeps xhigh and adds max above it, and ultra runs the multi-agent mode paired with a rollout token budget cap. Default: no thinking level is enforced (models run as-is).',
|
|
303
|
+
choices: ['off', 'low', 'medium', 'high', 'xhigh', 'ultra', 'max'],
|
|
304
304
|
default: undefined,
|
|
305
305
|
},
|
|
306
306
|
'thinking-budget': {
|
|
307
307
|
type: 'number',
|
|
308
|
-
description: 'Thinking token budget. For Claude Code, controls MAX_THINKING_TOKENS (0-31999 by default). For Codex, enables finer reasoning-effort mapping
|
|
308
|
+
description: 'Thinking token budget. For Claude Code, controls MAX_THINKING_TOKENS (0-31999 by default). For Codex, enables finer reasoning-effort mapping (minimal/low/medium/high) capped at xhigh; the deepest single-agent `max` and the multi-agent `ultra` effort must be requested explicitly via --think max / --think ultra.',
|
|
309
|
+
default: undefined,
|
|
310
|
+
},
|
|
311
|
+
'rollout-token-budget': {
|
|
312
|
+
type: 'number',
|
|
313
|
+
description: "Codex rollout token budget (turn-level cap) paired with the multi-agent `--think ultra` effort so GPT-5.6 Sol's ultra mode stays predictable and does not run away on cost. Default: 500000. Only applied when --think ultra selects the ultra reasoning effort.",
|
|
309
314
|
default: undefined,
|
|
310
315
|
},
|
|
311
316
|
'thinking-budget-claude-minimum-version': {
|
package/src/tool-retry.lib.mjs
CHANGED
|
@@ -59,6 +59,13 @@ export const classifyRetryableError = value => {
|
|
|
59
59
|
return { message, isRetryable: true, isCapacity: false, label: 'Stream disconnected before completion' };
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
+
// Issue #2023: Claude Code can close a stream-json process after tool output
|
|
63
|
+
// (for example "Exit code 144") without emitting the terminal result event.
|
|
64
|
+
// The session is still resumable; failing immediately loses in-progress work.
|
|
65
|
+
if (lower.includes('claude stream ended without a terminal result event')) {
|
|
66
|
+
return { message, isRetryable: true, isCapacity: false, label: 'Claude stream ended without terminal result' };
|
|
67
|
+
}
|
|
68
|
+
|
|
62
69
|
// Issue #1937: Stream idle timeout. When the Anthropic streaming response stalls
|
|
63
70
|
// (no bytes for the SDK's idle window) after the model has already emitted part of
|
|
64
71
|
// its answer, the Claude CLI aborts the turn and surfaces a synthetic assistant /
|