@link-assistant/hive-mind 1.62.1 → 1.64.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 +12 -0
- package/README.hi.md +5 -2
- package/README.md +20 -15
- package/README.ru.md +5 -2
- package/README.zh.md +18 -15
- package/package.json +2 -2
- package/src/agent-commander.lib.mjs +361 -0
- package/src/bidirectional-interactive.lib.mjs +1 -1
- package/src/claude.prompts.lib.mjs +2 -2
- package/src/codex.prompts.lib.mjs +2 -2
- package/src/config.lib.mjs +1 -0
- package/src/gemini.lib.mjs +611 -0
- package/src/gemini.prompts.lib.mjs +236 -0
- package/src/hive.config.lib.mjs +1 -1
- package/src/interactive-mode.lib.mjs +1 -1
- package/src/models/index.mjs +58 -11
- package/src/qwen.prompts.lib.mjs +2 -2
- package/src/solve.config.lib.mjs +11 -5
- package/src/solve.mjs +39 -74
- package/src/solve.restart-shared.lib.mjs +75 -2
- package/src/solve.results.lib.mjs +1 -1
- package/src/solve.validation.lib.mjs +20 -1
- package/src/task.config.lib.mjs +1 -1
- package/src/task.mjs +1 -1
- package/src/telegram-bot.mjs +4 -4
- package/src/telegram-solve-command.lib.mjs +1 -0
- package/src/telegram-solve-queue-command.lib.mjs +1 -1
- package/src/telegram-solve-queue.helpers.lib.mjs +12 -1
- package/src/telegram-solve-queue.lib.mjs +37 -20
- package/src/tool-connection-validation.lib.mjs +3 -0
- package/src/usage-limit.lib.mjs +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @link-assistant/hive-mind
|
|
2
2
|
|
|
3
|
+
## 1.64.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 2ffb808: Add experimental `--use-agent-commander` option to delegate supported tool execution to the agent-commander library, including Claude, Codex, OpenCode, Agent, Qwen, and Gemini.
|
|
8
|
+
|
|
9
|
+
## 1.63.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- b7b0721: Add direct Google Gemini CLI support for solve, hive, queueing, model validation, structured stream JSON parsing, and Telegram `/gemini` aliases.
|
|
14
|
+
|
|
3
15
|
## 1.62.1
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/README.hi.md
CHANGED
|
@@ -343,7 +343,7 @@ solve <issue-url> [options]
|
|
|
343
343
|
|
|
344
344
|
| विकल्प | संक्षिप्त | विवरण | डिफ़ॉल्ट |
|
|
345
345
|
| ------------------------ | --------- | ----------------------------------------------------------- | -------- |
|
|
346
|
-
| `--tool` | | AI टूल (claude, opencode, codex, agent, qwen)
|
|
346
|
+
| `--tool` | | AI टूल (claude, opencode, codex, agent, qwen, gemini) | claude |
|
|
347
347
|
| `--verbose` | `-v` | विस्तृत लॉगिंग सक्षम करें | false |
|
|
348
348
|
| `--attach-logs` | | PR में लॉग संलग्न करें (⚠️ संवेदनशील डेटा उजागर हो सकता है) | false |
|
|
349
349
|
| `--auto-init-repository` | | खाली रेपो स्वतः-आरंभ करें (README.md बनाता है) | false |
|
|
@@ -370,7 +370,7 @@ hive <github-url> [options]
|
|
|
370
370
|
|
|
371
371
|
| विकल्प | संक्षिप्त | विवरण | डिफ़ॉल्ट |
|
|
372
372
|
| ------------------------ | --------- | ----------------------------------------------------------- | -------- |
|
|
373
|
-
| `--tool` | | AI टूल (claude, opencode, codex, agent, qwen)
|
|
373
|
+
| `--tool` | | AI टूल (claude, opencode, codex, agent, qwen, gemini) | claude |
|
|
374
374
|
| `--concurrency` | `-c` | समानांतर वर्कर की संख्या | 2 |
|
|
375
375
|
| `--skip-issues-with-prs` | `-s` | मौजूदा PR वाले इश्यू छोड़ें | false |
|
|
376
376
|
| `--verbose` | `-v` | विस्तृत लॉगिंग सक्षम करें | false |
|
|
@@ -463,12 +463,15 @@ Aliases:
|
|
|
463
463
|
/opencode /solve --tool opencode के बराबर है
|
|
464
464
|
/agent /solve --tool agent के बराबर है
|
|
465
465
|
/qwen /solve --tool qwen के बराबर है
|
|
466
|
+
/gemini /solve --tool gemini के बराबर है
|
|
466
467
|
|
|
467
468
|
Tool alias examples:
|
|
468
469
|
/codex https://github.com/owner/repo/issues/123 --model gpt-5.5
|
|
469
470
|
/opencode https://github.com/owner/repo/issues/123 --model grok-code-fast-1
|
|
470
471
|
/agent https://github.com/owner/repo/issues/123 --model nemotron-3-super-free
|
|
472
|
+
/gemini https://github.com/owner/repo/issues/123 --model flash
|
|
471
473
|
/qwen https://github.com/owner/repo/issues/123 --model qwen3-coder-plus
|
|
474
|
+
/gemini https://github.com/owner/repo/issues/123 --model gemini-2.5-flash
|
|
472
475
|
|
|
473
476
|
Free Models (with --tool agent):
|
|
474
477
|
/solve https://github.com/owner/repo/issues/123 --tool agent --model nemotron-3-super-free
|
package/README.md
CHANGED
|
@@ -350,13 +350,13 @@ solve <issue-url> [options]
|
|
|
350
350
|
|
|
351
351
|
**Other useful options:**
|
|
352
352
|
|
|
353
|
-
| Option | Alias | Description
|
|
354
|
-
| ------------------------ | ----- |
|
|
355
|
-
| `--tool` | | AI tool (claude, opencode, codex, agent, qwen)
|
|
356
|
-
| `--verbose` | `-v` | Enable verbose logging
|
|
357
|
-
| `--attach-logs` | | Attach logs to PR (⚠️ may expose sensitive data)
|
|
358
|
-
| `--auto-init-repository` | | Auto-initialize empty repos (creates README.md)
|
|
359
|
-
| `--help` | `-h` | Show all available options
|
|
353
|
+
| Option | Alias | Description | Default |
|
|
354
|
+
| ------------------------ | ----- | ------------------------------------------------------ | ------- |
|
|
355
|
+
| `--tool` | | AI tool (claude, opencode, codex, agent, qwen, gemini) | claude |
|
|
356
|
+
| `--verbose` | `-v` | Enable verbose logging | false |
|
|
357
|
+
| `--attach-logs` | | Attach logs to PR (⚠️ may expose sensitive data) | false |
|
|
358
|
+
| `--auto-init-repository` | | Auto-initialize empty repos (creates README.md) | false |
|
|
359
|
+
| `--help` | `-h` | Show all available options | - |
|
|
360
360
|
|
|
361
361
|
> **📖 Full options list**: See [docs/CONFIGURATION.md](./docs/CONFIGURATION.md#solve-options) for all available options including forking, auto-continue, watch mode, and experimental features.
|
|
362
362
|
|
|
@@ -377,14 +377,14 @@ hive <github-url> [options]
|
|
|
377
377
|
|
|
378
378
|
**Other useful options:**
|
|
379
379
|
|
|
380
|
-
| Option | Alias | Description
|
|
381
|
-
| ------------------------ | ----- |
|
|
382
|
-
| `--tool` | | AI tool (claude, opencode, codex, agent, qwen)
|
|
383
|
-
| `--concurrency` | `-c` | Number of parallel workers
|
|
384
|
-
| `--skip-issues-with-prs` | `-s` | Skip issues with existing PRs
|
|
385
|
-
| `--verbose` | `-v` | Enable verbose logging
|
|
386
|
-
| `--attach-logs` | | Attach logs to PRs (⚠️ may expose sensitive data)
|
|
387
|
-
| `--help` | `-h` | Show all available options
|
|
380
|
+
| Option | Alias | Description | Default |
|
|
381
|
+
| ------------------------ | ----- | ------------------------------------------------------ | ------- |
|
|
382
|
+
| `--tool` | | AI tool (claude, opencode, codex, agent, qwen, gemini) | claude |
|
|
383
|
+
| `--concurrency` | `-c` | Number of parallel workers | 2 |
|
|
384
|
+
| `--skip-issues-with-prs` | `-s` | Skip issues with existing PRs | false |
|
|
385
|
+
| `--verbose` | `-v` | Enable verbose logging | false |
|
|
386
|
+
| `--attach-logs` | | Attach logs to PRs (⚠️ may expose sensitive data) | false |
|
|
387
|
+
| `--help` | `-h` | Show all available options | - |
|
|
388
388
|
|
|
389
389
|
> **📖 Full options list**: See [docs/CONFIGURATION.md](./docs/CONFIGURATION.md#hive-options) for all available options including project monitoring, YouTrack integration, and experimental features.
|
|
390
390
|
|
|
@@ -470,12 +470,15 @@ Aliases:
|
|
|
470
470
|
/opencode is equivalent to /solve --tool opencode
|
|
471
471
|
/agent is equivalent to /solve --tool agent
|
|
472
472
|
/qwen is equivalent to /solve --tool qwen
|
|
473
|
+
/gemini is equivalent to /solve --tool gemini
|
|
473
474
|
|
|
474
475
|
Tool alias examples:
|
|
475
476
|
/codex https://github.com/owner/repo/issues/123 --model gpt-5.5
|
|
476
477
|
/opencode https://github.com/owner/repo/issues/123 --model grok-code-fast-1
|
|
477
478
|
/agent https://github.com/owner/repo/issues/123 --model nemotron-3-super-free
|
|
479
|
+
/gemini https://github.com/owner/repo/issues/123 --model flash
|
|
478
480
|
/qwen https://github.com/owner/repo/issues/123 --model qwen3-coder-plus
|
|
481
|
+
/gemini https://github.com/owner/repo/issues/123 --model gemini-2.5-flash
|
|
479
482
|
|
|
480
483
|
Free Models (with --tool agent):
|
|
481
484
|
/solve https://github.com/owner/repo/issues/123 --tool agent --model nemotron-3-super-free
|
|
@@ -497,7 +500,9 @@ Current tool defaults in Hive Mind:
|
|
|
497
500
|
| `codex` | `gpt-5.5` preferred, with runtime fallback to local catalog | Codex runs with `reasoning_effort=none` unless you pass `--think` or `--thinking-budget` |
|
|
498
501
|
| `opencode` | `grok-code-fast-1` | No extra thinking prompt is added for the default model |
|
|
499
502
|
| `agent` | `nemotron-3-super-free` | No extra thinking prompt is added for the default model |
|
|
503
|
+
| `gemini` | `flash` | No extra thinking prompt is added for the default model |
|
|
500
504
|
| `qwen` | `qwen3-coder-plus` | No extra thinking prompt is added for the default model |
|
|
505
|
+
| `gemini` | `gemini-2.5-flash` | No extra thinking prompt is added for the default model |
|
|
501
506
|
|
|
502
507
|
See [docs/CONFIGURATION.md](./docs/CONFIGURATION.md) for the full per-tool defaults and reasoning mappings.
|
|
503
508
|
|
package/README.ru.md
CHANGED
|
@@ -343,7 +343,7 @@ solve <issue-url> [options]
|
|
|
343
343
|
|
|
344
344
|
| Параметр | Сокр. | Описание | По умолчанию |
|
|
345
345
|
| ------------------------ | ----- | --------------------------------------------------------------------- | ------------ |
|
|
346
|
-
| `--tool` | | Инструмент ИИ (claude, opencode, codex, agent, qwen)
|
|
346
|
+
| `--tool` | | Инструмент ИИ (claude, opencode, codex, agent, qwen, gemini) | claude |
|
|
347
347
|
| `--verbose` | `-v` | Включить подробное логирование | false |
|
|
348
348
|
| `--attach-logs` | | Прикрепить логи к PR (⚠️ может раскрыть конфиденциальные данные) | false |
|
|
349
349
|
| `--auto-init-repository` | | Автоматически инициализировать пустые репозитории (создаёт README.md) | false |
|
|
@@ -370,7 +370,7 @@ hive <github-url> [options]
|
|
|
370
370
|
|
|
371
371
|
| Параметр | Сокр. | Описание | По умолчанию |
|
|
372
372
|
| ------------------------ | ----- | ----------------------------------------------------------------- | ------------ |
|
|
373
|
-
| `--tool` | | Инструмент ИИ (claude, opencode, codex, agent, qwen)
|
|
373
|
+
| `--tool` | | Инструмент ИИ (claude, opencode, codex, agent, qwen, gemini) | claude |
|
|
374
374
|
| `--concurrency` | `-c` | Количество параллельных воркеров | 2 |
|
|
375
375
|
| `--skip-issues-with-prs` | `-s` | Пропускать задачи с существующими PR | false |
|
|
376
376
|
| `--verbose` | `-v` | Включить подробное логирование | false |
|
|
@@ -464,12 +464,15 @@ Aliases:
|
|
|
464
464
|
/opencode эквивалентна /solve --tool opencode
|
|
465
465
|
/agent эквивалентна /solve --tool agent
|
|
466
466
|
/qwen эквивалентна /solve --tool qwen
|
|
467
|
+
/gemini эквивалентна /solve --tool gemini
|
|
467
468
|
|
|
468
469
|
Tool alias examples:
|
|
469
470
|
/codex https://github.com/owner/repo/issues/123 --model gpt-5.5
|
|
470
471
|
/opencode https://github.com/owner/repo/issues/123 --model grok-code-fast-1
|
|
471
472
|
/agent https://github.com/owner/repo/issues/123 --model nemotron-3-super-free
|
|
473
|
+
/gemini https://github.com/owner/repo/issues/123 --model flash
|
|
472
474
|
/qwen https://github.com/owner/repo/issues/123 --model qwen3-coder-plus
|
|
475
|
+
/gemini https://github.com/owner/repo/issues/123 --model gemini-2.5-flash
|
|
473
476
|
|
|
474
477
|
Free Models (with --tool agent):
|
|
475
478
|
/solve https://github.com/owner/repo/issues/123 --tool agent --model nemotron-3-super-free
|
package/README.zh.md
CHANGED
|
@@ -341,13 +341,13 @@ solve <issue-url> [options]
|
|
|
341
341
|
|
|
342
342
|
**其他常用选项:**
|
|
343
343
|
|
|
344
|
-
| 选项 | 简写 | 描述
|
|
345
|
-
| ------------------------ | ---- |
|
|
346
|
-
| `--tool` | | AI 工具(claude、opencode、codex、agent、qwen) | claude |
|
|
347
|
-
| `--verbose` | `-v` | 启用详细日志
|
|
348
|
-
| `--attach-logs` | | 将日志附加到 PR(⚠️ 可能暴露敏感数据)
|
|
349
|
-
| `--auto-init-repository` | | 自动初始化空仓库(创建 README.md)
|
|
350
|
-
| `--help` | `-h` | 显示所有可用选项
|
|
344
|
+
| 选项 | 简写 | 描述 | 默认值 |
|
|
345
|
+
| ------------------------ | ---- | ------------------------------------------------------- | ------ |
|
|
346
|
+
| `--tool` | | AI 工具(claude、opencode、codex、agent、qwen、gemini) | claude |
|
|
347
|
+
| `--verbose` | `-v` | 启用详细日志 | false |
|
|
348
|
+
| `--attach-logs` | | 将日志附加到 PR(⚠️ 可能暴露敏感数据) | false |
|
|
349
|
+
| `--auto-init-repository` | | 自动初始化空仓库(创建 README.md) | false |
|
|
350
|
+
| `--help` | `-h` | 显示所有可用选项 | - |
|
|
351
351
|
|
|
352
352
|
> **📖 完整选项列表**:包含 Fork、自动续行、监视模式及实验性功能在内的所有可用选项,请参见 [docs/CONFIGURATION.zh.md](./docs/CONFIGURATION.zh.md#solve-options)。
|
|
353
353
|
|
|
@@ -368,14 +368,14 @@ hive <github-url> [options]
|
|
|
368
368
|
|
|
369
369
|
**其他常用选项:**
|
|
370
370
|
|
|
371
|
-
| 选项 | 简写 | 描述
|
|
372
|
-
| ------------------------ | ---- |
|
|
373
|
-
| `--tool` | | AI 工具(claude、opencode、codex、agent、qwen) | claude |
|
|
374
|
-
| `--concurrency` | `-c` | 并行工作进程数量
|
|
375
|
-
| `--skip-issues-with-prs` | `-s` | 跳过已有 PR 的 Issue
|
|
376
|
-
| `--verbose` | `-v` | 启用详细日志
|
|
377
|
-
| `--attach-logs` | | 将日志附加到 PR(⚠️ 可能暴露敏感数据)
|
|
378
|
-
| `--help` | `-h` | 显示所有可用选项
|
|
371
|
+
| 选项 | 简写 | 描述 | 默认值 |
|
|
372
|
+
| ------------------------ | ---- | ------------------------------------------------------- | ------ |
|
|
373
|
+
| `--tool` | | AI 工具(claude、opencode、codex、agent、qwen、gemini) | claude |
|
|
374
|
+
| `--concurrency` | `-c` | 并行工作进程数量 | 2 |
|
|
375
|
+
| `--skip-issues-with-prs` | `-s` | 跳过已有 PR 的 Issue | false |
|
|
376
|
+
| `--verbose` | `-v` | 启用详细日志 | false |
|
|
377
|
+
| `--attach-logs` | | 将日志附加到 PR(⚠️ 可能暴露敏感数据) | false |
|
|
378
|
+
| `--help` | `-h` | 显示所有可用选项 | - |
|
|
379
379
|
|
|
380
380
|
> **📖 完整选项列表**:包含项目监控、YouTrack 集成及实验性功能在内的所有可用选项,请参见 [docs/CONFIGURATION.zh.md](./docs/CONFIGURATION.zh.md#hive-options)。
|
|
381
381
|
|
|
@@ -460,12 +460,15 @@ Aliases:
|
|
|
460
460
|
/opencode 等同于 /solve --tool opencode
|
|
461
461
|
/agent 等同于 /solve --tool agent
|
|
462
462
|
/qwen 等同于 /solve --tool qwen
|
|
463
|
+
/gemini 等同于 /solve --tool gemini
|
|
463
464
|
|
|
464
465
|
Tool alias examples:
|
|
465
466
|
/codex https://github.com/owner/repo/issues/123 --model gpt-5.5
|
|
466
467
|
/opencode https://github.com/owner/repo/issues/123 --model grok-code-fast-1
|
|
467
468
|
/agent https://github.com/owner/repo/issues/123 --model nemotron-3-super-free
|
|
469
|
+
/gemini https://github.com/owner/repo/issues/123 --model flash
|
|
468
470
|
/qwen https://github.com/owner/repo/issues/123 --model qwen3-coder-plus
|
|
471
|
+
/gemini https://github.com/owner/repo/issues/123 --model gemini-2.5-flash
|
|
469
472
|
|
|
470
473
|
Free Models (with --tool agent):
|
|
471
474
|
/solve https://github.com/owner/repo/issues/123 --tool agent --model nemotron-3-super-free
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@link-assistant/hive-mind",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.64.0",
|
|
4
4
|
"description": "AI-powered issue solver and hive mind for collaborative problem solving",
|
|
5
5
|
"main": "src/hive.mjs",
|
|
6
6
|
"type": "module",
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
"@secretlint/secretlint-rule-preset-recommend": "^11.2.5",
|
|
73
73
|
"@sentry/node": "^10.15.0",
|
|
74
74
|
"@sentry/profiling-node": "^10.15.0",
|
|
75
|
-
"agent-commander": "^0.
|
|
75
|
+
"agent-commander": "^0.6.1",
|
|
76
76
|
"dayjs": "^1.11.19",
|
|
77
77
|
"decimal.js-light": "^2.5.1",
|
|
78
78
|
"lino-arguments": "^0.3.0",
|
|
@@ -0,0 +1,361 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Experimental agent-commander execution adapter.
|
|
4
|
+
*
|
|
5
|
+
* This module is only used when solve is called with --use-agent-commander.
|
|
6
|
+
* Default tool execution remains in claude.lib.mjs, codex.lib.mjs,
|
|
7
|
+
* opencode.lib.mjs, and agent.lib.mjs.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { resolveCodexReasoningEffort } from './codex.options.lib.mjs';
|
|
11
|
+
import { mapModelForTool } from './models/index.mjs';
|
|
12
|
+
import { buildCodexDisable1mContextConfigArgs, buildCodexSubSessionSizeConfigArgs, parseSubSessionSize } from './sub-session-size.lib.mjs';
|
|
13
|
+
import { detectUsageLimit } from './usage-limit.lib.mjs';
|
|
14
|
+
|
|
15
|
+
export const AGENT_COMMANDER_TOOLS = new Set(['claude', 'codex', 'opencode', 'agent', 'qwen', 'gemini']);
|
|
16
|
+
|
|
17
|
+
const TOOL_EXECUTABLE_CONFIG = {
|
|
18
|
+
claude: { argvKey: 'claudePath', envKey: 'CLAUDE_PATH' },
|
|
19
|
+
codex: { argvKey: 'codexPath', envKey: 'CODEX_PATH' },
|
|
20
|
+
opencode: { argvKey: 'opencodePath', envKey: 'OPENCODE_PATH' },
|
|
21
|
+
agent: { argvKey: 'agentPath', envKey: 'AGENT_PATH' },
|
|
22
|
+
qwen: { argvKey: 'qwenPath', envKey: 'QWEN_PATH' },
|
|
23
|
+
gemini: { argvKey: 'geminiPath', envKey: 'GEMINI_PATH' },
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const getConfiguredExecutable = (argv = {}, tool) => {
|
|
27
|
+
const config = TOOL_EXECUTABLE_CONFIG[tool];
|
|
28
|
+
if (!config) return null;
|
|
29
|
+
return argv[config.argvKey] || process.env[config.envKey] || null;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
const appendExtraArgs = (options, args) => {
|
|
33
|
+
if (!Array.isArray(args) || args.length === 0) return;
|
|
34
|
+
options.extraArgs = [...(options.extraArgs || []), ...args];
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const appendExtraEnv = (options, env) => {
|
|
38
|
+
const entries = Object.entries(env || {}).filter(([, value]) => value !== undefined && value !== null && value !== false);
|
|
39
|
+
if (entries.length === 0) return;
|
|
40
|
+
options.extraEnv = {
|
|
41
|
+
...(options.extraEnv || {}),
|
|
42
|
+
...Object.fromEntries(entries.map(([key, value]) => [key, String(value)])),
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const buildClaudeToolOptions = (argv = {}) => {
|
|
47
|
+
const options = {};
|
|
48
|
+
options.verbose = !!argv.verbose;
|
|
49
|
+
if (argv.fallbackModel) options.fallbackModel = argv.fallbackModel;
|
|
50
|
+
|
|
51
|
+
const extraEnv = {};
|
|
52
|
+
if (argv.thinkingBudget !== undefined) extraEnv.MAX_THINKING_TOKENS = argv.thinkingBudget;
|
|
53
|
+
if (argv.disable1mContext) extraEnv.CLAUDE_CODE_DISABLE_1M_CONTEXT = '1';
|
|
54
|
+
if (argv.showThinkingContent) extraEnv.CLAUDE_CODE_SHOW_THINKING = '1';
|
|
55
|
+
if (argv.planModel) extraEnv.ANTHROPIC_DEFAULT_OPUS_MODEL = argv.planModel;
|
|
56
|
+
appendExtraEnv(options, extraEnv);
|
|
57
|
+
|
|
58
|
+
return options;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const buildCodexToolOptions = (argv = {}) => {
|
|
62
|
+
const options = {};
|
|
63
|
+
const { reasoningEffort } = resolveCodexReasoningEffort(argv);
|
|
64
|
+
appendExtraArgs(options, ['-c', `model_reasoning_effort=${reasoningEffort}`, '-c', 'model_reasoning_summary=auto']);
|
|
65
|
+
|
|
66
|
+
appendExtraArgs(options, buildCodexDisable1mContextConfigArgs(!!argv.disable1mContext));
|
|
67
|
+
try {
|
|
68
|
+
appendExtraArgs(options, buildCodexSubSessionSizeConfigArgs(parseSubSessionSize(argv.subSessionSize)));
|
|
69
|
+
} catch {
|
|
70
|
+
// The embedded Codex path logs parse warnings later. Keep agent-commander
|
|
71
|
+
// command construction permissive so validation can still run.
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
return options;
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const defaultLog = async (message, options = {}) => {
|
|
78
|
+
if (options.verbose && !global.verboseMode) return;
|
|
79
|
+
if (options.level === 'error') {
|
|
80
|
+
console.error(message);
|
|
81
|
+
} else if (options.level === 'warning' || options.level === 'warn') {
|
|
82
|
+
console.warn(message);
|
|
83
|
+
} else {
|
|
84
|
+
console.log(message);
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const getAgentCommander = async () => {
|
|
89
|
+
try {
|
|
90
|
+
return await import('agent-commander');
|
|
91
|
+
} catch (error) {
|
|
92
|
+
throw new Error(`agent-commander is not installed or cannot be loaded. Install it with: npm install agent-commander\nOriginal error: ${error.message}`);
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
export const isAgentCommanderAvailable = async () => {
|
|
97
|
+
try {
|
|
98
|
+
await getAgentCommander();
|
|
99
|
+
return true;
|
|
100
|
+
} catch {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
export const getAgentCommanderToolName = (argv = {}) => argv.tool || 'claude';
|
|
106
|
+
|
|
107
|
+
const resolveAgentCommanderModel = (tool, model) => (model ? mapModelForTool(tool, model) : model);
|
|
108
|
+
|
|
109
|
+
export const buildAgentCommanderToolOptions = (argv = {}, tool = getAgentCommanderToolName(argv)) => {
|
|
110
|
+
const options = tool === 'claude' ? buildClaudeToolOptions(argv) : tool === 'codex' ? buildCodexToolOptions(argv) : {};
|
|
111
|
+
|
|
112
|
+
const executable = getConfiguredExecutable(argv, tool);
|
|
113
|
+
if (executable) {
|
|
114
|
+
options.executable = executable;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
if (tool === 'gemini' && argv.verbose) options.debug = true;
|
|
118
|
+
|
|
119
|
+
return options;
|
|
120
|
+
};
|
|
121
|
+
|
|
122
|
+
export const buildAgentCommanderControllerOptions = ({ tool, tempDir, prompt, systemPrompt, argv = {} }) => ({
|
|
123
|
+
tool,
|
|
124
|
+
workingDirectory: tempDir,
|
|
125
|
+
prompt,
|
|
126
|
+
systemPrompt,
|
|
127
|
+
model: resolveAgentCommanderModel(tool, argv.model),
|
|
128
|
+
json: tool !== 'agent',
|
|
129
|
+
resume: argv.resume,
|
|
130
|
+
toolOptions: buildAgentCommanderToolOptions(argv, tool),
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
export const validateAgentCommanderConnection = async ({ tool, model, log = defaultLog, agentCommanderModule = null }) => {
|
|
134
|
+
try {
|
|
135
|
+
const module = agentCommanderModule || (await getAgentCommander());
|
|
136
|
+
const { agent, isToolSupported } = module;
|
|
137
|
+
const toolName = tool || 'claude';
|
|
138
|
+
|
|
139
|
+
if (!AGENT_COMMANDER_TOOLS.has(toolName) || !isToolSupported({ toolName })) {
|
|
140
|
+
await log(`[agent-commander] Tool '${toolName}' is not supported`, { level: 'error' });
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const controller = agent({
|
|
145
|
+
tool: toolName,
|
|
146
|
+
workingDirectory: process.cwd(),
|
|
147
|
+
prompt: 'connection check',
|
|
148
|
+
model: resolveAgentCommanderModel(toolName, model),
|
|
149
|
+
json: toolName !== 'agent',
|
|
150
|
+
toolOptions: buildAgentCommanderToolOptions({ model }, toolName),
|
|
151
|
+
});
|
|
152
|
+
await controller.start({ dryRun: true, attached: false });
|
|
153
|
+
await log(`[agent-commander] ${toolName} command construction validated`, { verbose: true });
|
|
154
|
+
return true;
|
|
155
|
+
} catch (error) {
|
|
156
|
+
await log(`[agent-commander] Connection validation failed: ${error.message}`, { level: 'error' });
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
const getPromptModule = async tool => {
|
|
162
|
+
if (tool === 'claude') return await import('./claude.prompts.lib.mjs');
|
|
163
|
+
if (tool === 'codex') return await import('./codex.prompts.lib.mjs');
|
|
164
|
+
if (tool === 'opencode') return await import('./opencode.prompts.lib.mjs');
|
|
165
|
+
if (tool === 'agent') return await import('./agent.prompts.lib.mjs');
|
|
166
|
+
if (tool === 'qwen') return await import('./qwen.prompts.lib.mjs');
|
|
167
|
+
if (tool === 'gemini') return await import('./gemini.prompts.lib.mjs');
|
|
168
|
+
throw new Error(`Unsupported tool for agent-commander: ${tool}`);
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
export const getPlaywrightMcpAvailabilityCheck = async tool => {
|
|
172
|
+
if (tool === 'opencode') return (await import('./opencode.lib.mjs')).checkPlaywrightMcpAvailability;
|
|
173
|
+
if (tool === 'codex') return (await import('./codex.lib.mjs')).checkPlaywrightMcpAvailability;
|
|
174
|
+
if (tool === 'agent') return (await import('./agent.lib.mjs')).checkPlaywrightMcpAvailability;
|
|
175
|
+
if (tool === 'qwen') return (await import('./qwen.lib.mjs')).checkPlaywrightMcpAvailability;
|
|
176
|
+
if (tool === 'gemini') return (await import('./gemini.lib.mjs')).checkPlaywrightMcpAvailability;
|
|
177
|
+
return (await import('./claude.lib.mjs')).checkPlaywrightMcpAvailability;
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
export const resolvePlaywrightMcpForAgentCommander = async ({ argv, log = defaultLog, tool = getAgentCommanderToolName(argv) }) => {
|
|
181
|
+
if (argv.playwrightMcp === false) return;
|
|
182
|
+
if (!argv.promptPlaywrightMcp) {
|
|
183
|
+
await log('ℹ️ Playwright MCP explicitly disabled via --no-prompt-playwright-mcp', { verbose: true });
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
const checkFn = await getPlaywrightMcpAvailabilityCheck(tool);
|
|
188
|
+
const available = await checkFn();
|
|
189
|
+
if (available) {
|
|
190
|
+
await log('🎭 Playwright MCP detected - enabling browser automation hints', { verbose: true });
|
|
191
|
+
} else {
|
|
192
|
+
await log('ℹ️ Playwright MCP not detected - browser automation hints will be disabled', { verbose: true });
|
|
193
|
+
argv.promptPlaywrightMcp = false;
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
const getParsedMessages = result => {
|
|
198
|
+
const parsed = result?.output?.parsed;
|
|
199
|
+
if (Array.isArray(parsed)) return parsed;
|
|
200
|
+
if (parsed && typeof parsed === 'object') return [parsed];
|
|
201
|
+
return [];
|
|
202
|
+
};
|
|
203
|
+
|
|
204
|
+
const extractResultSummary = (messages, plainOutput) => {
|
|
205
|
+
for (const message of [...messages].reverse()) {
|
|
206
|
+
if (typeof message?.result === 'string' && message.result.trim()) return message.result.trim();
|
|
207
|
+
if (typeof message?.summary === 'string' && message.summary.trim()) return message.summary.trim();
|
|
208
|
+
if (typeof message?.text === 'string' && message.text.trim()) return message.text.trim();
|
|
209
|
+
if (typeof message?.message === 'string' && message.message.trim()) return message.message.trim();
|
|
210
|
+
if (typeof message?.item?.content === 'string' && message.item.content.trim()) return message.item.content.trim();
|
|
211
|
+
if (Array.isArray(message?.item?.content)) {
|
|
212
|
+
const text = message.item.content
|
|
213
|
+
.map(part => part?.text || '')
|
|
214
|
+
.join('')
|
|
215
|
+
.trim();
|
|
216
|
+
if (text) return text;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
return plainOutput?.trim() ? plainOutput.trim().slice(-4000) : null;
|
|
221
|
+
};
|
|
222
|
+
|
|
223
|
+
const hasErrorMessage = messages => messages.some(message => message?.is_error === true || message?.type === 'error' || message?.type === 'step_error' || message?.error);
|
|
224
|
+
|
|
225
|
+
export const summarizeAgentCommanderResult = ({ result, tool }) => {
|
|
226
|
+
const plainOutput = result?.output?.plain || '';
|
|
227
|
+
if (result?.metadata && typeof result.metadata === 'object') {
|
|
228
|
+
const metadata = result.metadata;
|
|
229
|
+
return {
|
|
230
|
+
success: metadata.success === true,
|
|
231
|
+
sessionId: metadata.sessionId || result.sessionId || null,
|
|
232
|
+
limitReached: !!metadata.limitReached,
|
|
233
|
+
limitResetTime: metadata.limitResetTime || null,
|
|
234
|
+
limitTimezone: metadata.limitTimezone || null,
|
|
235
|
+
anthropicTotalCostUSD: metadata.anthropicTotalCostUSD ?? null,
|
|
236
|
+
publicPricingEstimate: metadata.publicPricingEstimate ?? metadata.pricingInfo?.totalCostUSD ?? null,
|
|
237
|
+
pricingInfo: metadata.pricingInfo || null,
|
|
238
|
+
resultSummary: metadata.resultSummary || null,
|
|
239
|
+
resultModelUsage: metadata.resultModelUsage || null,
|
|
240
|
+
streamTokenUsage: metadata.streamTokenUsage || result.usage || null,
|
|
241
|
+
subAgentCalls: metadata.subAgentCalls || null,
|
|
242
|
+
errorDuringExecution: metadata.errorDuringExecution === true || result?.exitCode !== 0,
|
|
243
|
+
result: plainOutput,
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const messages = getParsedMessages(result);
|
|
248
|
+
const usageLimit = detectUsageLimit(plainOutput);
|
|
249
|
+
const usage = result?.usage || null;
|
|
250
|
+
const resultMessage = [...messages].reverse().find(message => message?.type === 'result') || null;
|
|
251
|
+
const totalCost = typeof resultMessage?.total_cost_usd === 'number' ? resultMessage.total_cost_usd : null;
|
|
252
|
+
const publicPricingEstimate = tool === 'agent' && typeof usage?.totalCost === 'number' ? usage.totalCost : null;
|
|
253
|
+
|
|
254
|
+
return {
|
|
255
|
+
success: result?.exitCode === 0 && !usageLimit.isUsageLimit && !hasErrorMessage(messages),
|
|
256
|
+
sessionId: result?.sessionId || resultMessage?.session_id || null,
|
|
257
|
+
limitReached: usageLimit.isUsageLimit,
|
|
258
|
+
limitResetTime: usageLimit.resetTime,
|
|
259
|
+
limitTimezone: usageLimit.timezone,
|
|
260
|
+
anthropicTotalCostUSD: tool === 'claude' ? totalCost : null,
|
|
261
|
+
publicPricingEstimate,
|
|
262
|
+
pricingInfo: publicPricingEstimate !== null ? { totalCostUSD: publicPricingEstimate, source: 'agent-commander' } : null,
|
|
263
|
+
resultSummary: extractResultSummary(messages, plainOutput),
|
|
264
|
+
resultModelUsage: null,
|
|
265
|
+
streamTokenUsage: usage,
|
|
266
|
+
subAgentCalls: null,
|
|
267
|
+
errorDuringExecution: result?.exitCode !== 0 || hasErrorMessage(messages),
|
|
268
|
+
result: plainOutput,
|
|
269
|
+
};
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
export const executeWithAgentCommander = async params => {
|
|
273
|
+
const { agentCommanderModule = null, promptModule = null, log = defaultLog, argv, tempDir, workspaceTmpDir, ...promptParams } = params;
|
|
274
|
+
const tool = getAgentCommanderToolName(argv);
|
|
275
|
+
const module = agentCommanderModule || (await getAgentCommander());
|
|
276
|
+
|
|
277
|
+
if (!AGENT_COMMANDER_TOOLS.has(tool) || !module.isToolSupported({ toolName: tool })) {
|
|
278
|
+
throw new Error(`agent-commander does not support tool '${tool}'`);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
const prompts = promptModule || (await getPromptModule(tool));
|
|
282
|
+
const promptBuilderParams = { ...promptParams, tempDir, workspaceTmpDir, argv };
|
|
283
|
+
const prompt = prompts.buildUserPrompt(promptBuilderParams);
|
|
284
|
+
const systemPrompt = prompts.buildSystemPrompt(promptBuilderParams);
|
|
285
|
+
const controllerOptions = buildAgentCommanderControllerOptions({ tool, tempDir, prompt, systemPrompt, argv });
|
|
286
|
+
|
|
287
|
+
if (argv.verbose) {
|
|
288
|
+
await log('\n[agent-commander] Final prompt structure:', { verbose: true });
|
|
289
|
+
await log(` Tool: ${tool}`, { verbose: true });
|
|
290
|
+
await log(` User prompt characters: ${prompt.length}`, { verbose: true });
|
|
291
|
+
await log(` System prompt characters: ${systemPrompt.length}`, { verbose: true });
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
const controller = module.agent(controllerOptions);
|
|
295
|
+
const dryRun = !!(argv.dryRun || argv.onlyPrepareCommand);
|
|
296
|
+
await log(`\n[agent-commander] Starting ${tool} execution${dryRun ? ' (dry-run)' : ''}...`);
|
|
297
|
+
await controller.start({
|
|
298
|
+
dryRun,
|
|
299
|
+
attached: true,
|
|
300
|
+
onOutput: chunk => {
|
|
301
|
+
if (chunk.type === 'stderr') process.stderr.write(chunk.data);
|
|
302
|
+
else process.stdout.write(chunk.data);
|
|
303
|
+
},
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
if (dryRun) {
|
|
307
|
+
return {
|
|
308
|
+
success: true,
|
|
309
|
+
sessionId: null,
|
|
310
|
+
limitReached: false,
|
|
311
|
+
limitResetTime: null,
|
|
312
|
+
limitTimezone: null,
|
|
313
|
+
anthropicTotalCostUSD: null,
|
|
314
|
+
publicPricingEstimate: null,
|
|
315
|
+
pricingInfo: null,
|
|
316
|
+
resultSummary: null,
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
const result = await controller.stop();
|
|
321
|
+
await log(`[agent-commander] ${tool} exited with code ${result.exitCode}`);
|
|
322
|
+
return summarizeAgentCommanderResult({ result, tool });
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
export const checkForUncommittedChanges = async (tempDir, owner, repo, branchName, $, log = defaultLog, autoCommit = false, autoRestartEnabled = true) => {
|
|
326
|
+
await log('\n🔍 Checking for uncommitted changes...');
|
|
327
|
+
const gitStatusResult = await $({ cwd: tempDir })`git status --porcelain 2>&1`;
|
|
328
|
+
const statusOutput = gitStatusResult.stdout?.toString().trim() || '';
|
|
329
|
+
|
|
330
|
+
if (!statusOutput) {
|
|
331
|
+
await log('✅ No uncommitted changes found');
|
|
332
|
+
return false;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
await log('📝 Found uncommitted changes');
|
|
336
|
+
await log('Changes:');
|
|
337
|
+
for (const line of statusOutput.split('\n')) await log(` ${line}`);
|
|
338
|
+
|
|
339
|
+
if (autoCommit) {
|
|
340
|
+
await log('💾 Auto-committing changes (--auto-commit-uncommitted-changes is enabled)...');
|
|
341
|
+
const addResult = await $({ cwd: tempDir })`git add -A`;
|
|
342
|
+
if (addResult.code === 0) {
|
|
343
|
+
const commitResult = await $({ cwd: tempDir })`git commit -m ${'Auto-commit: Changes made through agent-commander during problem-solving session'}`;
|
|
344
|
+
if (commitResult.code === 0) {
|
|
345
|
+
const pushResult = await $({ cwd: tempDir })`git push origin ${branchName} 2>&1`;
|
|
346
|
+
await log(pushResult.code === 0 ? '✅ Changes pushed successfully' : `⚠️ Warning: Could not push changes: ${pushResult.stderr?.toString().trim() || pushResult.stdout?.toString().trim()}`, { level: pushResult.code === 0 ? 'info' : 'warning' });
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
return false;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
if (autoRestartEnabled) {
|
|
353
|
+
await log('\n⚠️ IMPORTANT: Uncommitted changes detected!');
|
|
354
|
+
await log(' The agent-commander controlled tool made changes that were not committed.');
|
|
355
|
+
await log('\n🔄 AUTO-RESTART: Restarting the tool to handle uncommitted changes...\n');
|
|
356
|
+
return true;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
await log('\n⚠️ Uncommitted changes detected but auto-restart is disabled.');
|
|
360
|
+
return false;
|
|
361
|
+
};
|
|
@@ -851,7 +851,7 @@ export const createBidirectionalHandler = options => {
|
|
|
851
851
|
/**
|
|
852
852
|
* Check if bidirectional interactive mode is supported for the given tool
|
|
853
853
|
*
|
|
854
|
-
* @param {string} tool - Tool name (claude, opencode, codex)
|
|
854
|
+
* @param {string} tool - Tool name (claude, opencode, codex, agent, gemini)
|
|
855
855
|
* @returns {boolean} Whether bidirectional interactive mode is supported
|
|
856
856
|
*/
|
|
857
857
|
export const isBidirectionalModeSupported = tool => {
|
|
@@ -294,13 +294,13 @@ Plan sub-agent usage.
|
|
|
294
294
|
|
|
295
295
|
Agent Commander usage (unified subagent delegation).
|
|
296
296
|
- When you need to delegate tasks to subagents, use the agent-commander CLI tool (start-agent) instead of the native Task tool.
|
|
297
|
-
- Agent Commander provides a unified API for different agent types (claude, opencode, codex, agent, qwen) and supports various isolation modes.
|
|
297
|
+
- Agent Commander provides a unified API for different agent types (claude, opencode, codex, agent, qwen, gemini) and supports various isolation modes.
|
|
298
298
|
- To delegate a task, use the Bash tool to run start-agent with appropriate parameters:
|
|
299
299
|
\`\`\`bash
|
|
300
300
|
start-agent --tool claude --working-directory "$(pwd)" --prompt "Your task description here"
|
|
301
301
|
\`\`\`
|
|
302
302
|
- Common start-agent parameters:
|
|
303
|
-
--tool <name>: Agent to use (claude, opencode, codex, agent, qwen)
|
|
303
|
+
--tool <name>: Agent to use (claude, opencode, codex, agent, qwen, gemini)
|
|
304
304
|
--working-directory <path>: Execution directory (use current directory for context)
|
|
305
305
|
--prompt <text>: The task to delegate
|
|
306
306
|
--model <name>: Model to use (${[...new Set(Object.values(primaryModelNames).flat())].slice(0, 5).join(', ')}, etc.)
|
|
@@ -277,13 +277,13 @@ Planning workflow usage.
|
|
|
277
277
|
|
|
278
278
|
Agent Commander usage (unified subagent delegation).
|
|
279
279
|
- When you need to delegate tasks to subagents, use the agent-commander CLI tool (start-agent) instead of relying only on native Codex collaboration.
|
|
280
|
-
- Agent Commander provides a unified API for different agent types (claude, opencode, codex, agent, qwen) and supports various isolation modes.
|
|
280
|
+
- Agent Commander provides a unified API for different agent types (claude, opencode, codex, agent, qwen, gemini) and supports various isolation modes.
|
|
281
281
|
- To delegate a task, use a command like:
|
|
282
282
|
\`\`\`bash
|
|
283
283
|
start-agent --tool codex --working-directory "$(pwd)" --prompt "Your task description here"
|
|
284
284
|
\`\`\`
|
|
285
285
|
- Common start-agent parameters:
|
|
286
|
-
--tool <name>: Agent to use (claude, opencode, codex, agent, qwen)
|
|
286
|
+
--tool <name>: Agent to use (claude, opencode, codex, agent, qwen, gemini)
|
|
287
287
|
--working-directory <path>: Execution directory (use the current directory for context)
|
|
288
288
|
--prompt <text>: The task to delegate
|
|
289
289
|
--model <name>: Model to use
|
package/src/config.lib.mjs
CHANGED
|
@@ -51,6 +51,7 @@ const parseFloatWithDefault = (envVar, defaultValue) => {
|
|
|
51
51
|
export const timeouts = {
|
|
52
52
|
claudeCli: parseIntWithDefault('HIVE_MIND_CLAUDE_TIMEOUT_SECONDS', 60) * 1000,
|
|
53
53
|
opencodeCli: parseIntWithDefault('HIVE_MIND_OPENCODE_TIMEOUT_SECONDS', 60) * 1000,
|
|
54
|
+
geminiCli: parseIntWithDefault('HIVE_MIND_GEMINI_TIMEOUT_SECONDS', 60) * 1000,
|
|
54
55
|
codexCli: parseIntWithDefault('HIVE_MIND_CODEX_TIMEOUT_SECONDS', 60) * 1000,
|
|
55
56
|
qwenCli: parseIntWithDefault('HIVE_MIND_QWEN_TIMEOUT_SECONDS', 60) * 1000,
|
|
56
57
|
githubApiDelay: parseIntWithDefault('HIVE_MIND_GITHUB_API_DELAY_MS', 5000),
|