aiterm-mcp 0.40.3 → 0.41.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 +8 -1
- package/README.ja.md +5 -5
- package/README.md +6 -6
- package/dist/agent-resolver.js +1 -1
- package/dist/agent-shared.js +6 -8
- package/dist/core.js +31 -33
- package/dist/cursor-parent-receiver.js +1 -1
- package/dist/grok-stop-hook.js +2 -2
- package/dist/harnesses/grok.js +11 -15
- package/dist/index.js +6 -15
- package/dist/parent-delivery.js +1 -1
- package/dist/setup-integrations.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.41.0] - 2026-09-27
|
|
11
|
+
|
|
12
|
+
### 削除
|
|
13
|
+
|
|
14
|
+
- 旧互換alias `composer_agent` と、agent種別の`composer`を削除した。ComposerはCursorのmodelの一つで、現行のGrok CLIにはComposerが無いため、このaliasは常にcatalogエラーで起動できなかった。Composerは`agent_launch(harness=cursor-cli, model=composer-2.5-fast)`で起動する。`provider`/`vendor`の列挙から`composer`を外し、Claudeの親hookのmatcherからも`composer_agent`を外した。
|
|
15
|
+
|
|
10
16
|
## [0.40.3] - 2026-09-27
|
|
11
17
|
|
|
12
18
|
### 文書
|
|
@@ -1804,7 +1810,8 @@ prototype (preserved under `prototype/python/` as the porting source and referen
|
|
|
1804
1810
|
`ubuntu-latest` for Node 18/20/22, publishing to npm on `v*` tags with
|
|
1805
1811
|
provenance.
|
|
1806
1812
|
|
|
1807
|
-
[Unreleased]: https://github.com/kitepon/aiterm-mcp/compare/v0.
|
|
1813
|
+
[Unreleased]: https://github.com/kitepon/aiterm-mcp/compare/v0.41.0...HEAD
|
|
1814
|
+
[0.41.0]: https://github.com/kitepon/aiterm-mcp/compare/v0.40.3...v0.41.0
|
|
1808
1815
|
[0.40.3]: https://github.com/kitepon/aiterm-mcp/compare/v0.40.2...v0.40.3
|
|
1809
1816
|
[0.40.2]: https://github.com/kitepon/aiterm-mcp/compare/v0.40.1...v0.40.2
|
|
1810
1817
|
[0.40.1]: https://github.com/kitepon/aiterm-mcp/compare/v0.40.0...v0.40.1
|
package/README.ja.md
CHANGED
|
@@ -143,9 +143,9 @@ diagnostics、recovery、update、releaseを所有します。このREADMEと[
|
|
|
143
143
|
|
|
144
144
|
**言葉でなく実測で:** 記録済み203テストのベンチマークでは、`pty_read` はコンテキストに載るトークンを生ログの **約 7.1 分の 1** に減らす。しかも pass/fail の判定は畳んでも残る。→ [組み込みシェルツールとの使い分け](#組み込みシェルツールとの使い分け)
|
|
145
145
|
|
|
146
|
-
|
|
146
|
+
16ツール: 7つのPTYツール、正規のagent起動入口`agent_launch`、移行用の旧3alias、`agent_configure`、`agent_approval`、`claude_turn`、`claude_approval`、`diagnostics`。backendはPOSIXのtmux/Windows nativeのpsmuxなので、MCPサーバやAIクライアントが再起動してもsessionは生き残る。
|
|
147
147
|
|
|
148
|
-
**v0.28.0では実行基盤harnessとmodelを分離した。** harnessはagent loop・認証・hook・session・transcriptを所有し、modelはその上で選ぶ。Cursor Agent CLIでGPT/Claude/Grokを選んでも完了契約はCursor方式のまま。ComposerはCursorのmodelの一つで、harnessでもGrokのmodelでもない。`harness:"cursor-cli", model:"composer-2.5-fast"`(または`composer-2.5
|
|
148
|
+
**v0.28.0では実行基盤harnessとmodelを分離した。** harnessはagent loop・認証・hook・session・transcriptを所有し、modelはその上で選ぶ。Cursor Agent CLIでGPT/Claude/Grokを選んでも完了契約はCursor方式のまま。ComposerはCursorのmodelの一つで、harnessでもGrokのmodelでもない。`harness:"cursor-cli", model:"composer-2.5-fast"`(または`composer-2.5`)で表す。旧起動ツールは同じ実装へ流れる互換alias。
|
|
149
149
|
|
|
150
150
|
**v0.25.2ではGrok 4.6を含む同一sessionの連続設定変更を安定化。** Grok Build 1.0.3で
|
|
151
151
|
`/model`の成功通知が再描画により消えても、変更前には無かった要求model/effortが常駐footerへ現れた
|
|
@@ -203,7 +203,7 @@ runtime-error store は canonical dotagents config の `collection.enabled: true
|
|
|
203
203
|
場合だけ収集し、既定OFF、network送信は行いません。tag起点CIのnpm provenance(OIDC Trusted
|
|
204
204
|
Publishing)で公開し、GitHub Release が Official MCP Registry を再登録します。
|
|
205
205
|
|
|
206
|
-
**状態:** 開発継続中 · 現行公開版 **v0.
|
|
206
|
+
**状態:** 開発継続中 · 現行公開版 **v0.41.0** · 動作対象は Linux · WSL2 · macOS · Windows ネイティブ · MIT · [変更履歴](CHANGELOG.md)。
|
|
207
207
|
|
|
208
208
|
### 更新と巻き戻し
|
|
209
209
|
|
|
@@ -406,7 +406,7 @@ MCP クライアントが aiterm を stdio 越しにプログラムから駆動
|
|
|
406
406
|
|
|
407
407
|
```mermaid
|
|
408
408
|
flowchart LR
|
|
409
|
-
AI["AI / MCP client<br/>(the orchestrator)"] -->|"pty_send · pty_observe · agent_launch · agent_configure · agent_approval · claude_turn · claude_approval<br/>旧launcher alias · diagnostics"| S["aiterm-mcp<br/>stdio MCP ·
|
|
409
|
+
AI["AI / MCP client<br/>(the orchestrator)"] -->|"pty_send · pty_observe · agent_launch · agent_configure · agent_approval · claude_turn · claude_approval<br/>旧launcher alias · diagnostics"| S["aiterm-mcp<br/>stdio MCP · 16 tools"]
|
|
410
410
|
S -->|"pty_read<br/>token-reduced"| AI
|
|
411
411
|
S -->|"tmux / psmux<br/>send · capture"| P["persistent PTYs<br/>再起動を跨ぐ"]
|
|
412
412
|
P -->|"ssh · docker · repl"| R["nested<br/>remote · container · REPL"]
|
|
@@ -523,7 +523,7 @@ Claudeの相関済み承認は既存の`claude_approval`を使う。
|
|
|
523
523
|
| `pty_observe` | pane/harnessの生存、native process identity、状態と活動 | `session_id`, `cursor?` |
|
|
524
524
|
| `agent_launch` | harnessとmodelを別軸で選ぶ正規agent起動入口 | `harness`, `prompt?`, `model?`, `reasoning_effort?`, `cwd?`, `write_scope?`, `trust_project?`, `env_vars?`, `throughline_source_session?`, `throughline_supplement_file?` |
|
|
525
525
|
| `agent_approval` | Codexの現在の承認を検査し、単発許可・拒否を送る | `action`, `session_id`, `approval_choice?`, `observed_prompt_digest?` |
|
|
526
|
-
| `claude_agent` / `codex_agent` / `grok_agent`
|
|
526
|
+
| `claude_agent` / `codex_agent` / `grok_agent` | deprecated互換alias(`composer_agent`は0.41.0で削除。Composerは`agent_launch`の`cursor-cli`で使う) | 旧launcher引数 |
|
|
527
527
|
| `agent_configure` | 起動中のClaude/Codex/Grok/Cursorを再起動せずmodel/effort変更 | `session_id`, `model?`, `reasoning_effort?` |
|
|
528
528
|
| `claude_turn` | 相関済みClaude operationをdispatch(issue)または回収(recover) | `action`, `session_id`, `operation_id`, `text?` |
|
|
529
529
|
| `claude_approval` | 現在表示中の相関済みClaude承認UIを検査または応答 | `action`, `session_id`, `operation_id?`, `approval_choice?`, `observed_prompt_digest?` |
|
package/README.md
CHANGED
|
@@ -145,9 +145,9 @@ Aiterm and is not a runtime dependency.
|
|
|
145
145
|
|
|
146
146
|
**Measured, not claimed:** in the recorded 203-test benchmark, a `pty_read` puts **~7.1× fewer tokens** in your context than the raw log — and the pass/fail verdict survives the fold. → [When to reach for it vs. the built-in shell](#when-to-reach-for-it-vs-the-built-in-shell)
|
|
147
147
|
|
|
148
|
-
|
|
148
|
+
Sixteen tools: seven **PTY tools** — `pty_open` / `pty_send` / `pty_read` / `pty_key` / `pty_close` / `pty_list` / `pty_observe` — to open, drive, read, and observe one persistent terminal; one canonical **agent launcher**, `agent_launch`, which selects `claude-code`, `codex-cli`, `grok-cli`, or `cursor-cli` as the execution harness; three deprecated launcher aliases kept for migration; `agent_configure`; `agent_approval`; `claude_turn`; `claude_approval`; and `diagnostics`. The backend is **tmux on POSIX and psmux on native Windows**, so sessions survive even if the MCP server or the AI client restarts.
|
|
149
149
|
|
|
150
|
-
**v0.28.0 separates the execution harness from the model.** The harness owns the agent loop, authentication, hooks, session, and transcript; `model` is what that harness runs. Cursor Agent CLI can therefore select GPT, Claude, or Grok without changing the completion contract from Cursor hooks to another harness's. Composer is one of Cursor's models, not a harness and not a Grok model: use `harness: "cursor-cli", model: "composer-2.5-fast"` (or `composer-2.5`). The old
|
|
150
|
+
**v0.28.0 separates the execution harness from the model.** The harness owns the agent loop, authentication, hooks, session, and transcript; `model` is what that harness runs. Cursor Agent CLI can therefore select GPT, Claude, or Grok without changing the completion contract from Cursor hooks to another harness's. Composer is one of Cursor's models, not a harness and not a Grok model: use `harness: "cursor-cli", model: "composer-2.5-fast"` (or `composer-2.5`). The old launcher tools are thin compatibility aliases over the same implementation.
|
|
151
151
|
|
|
152
152
|
**v0.25.2 stabilizes repeated in-place configuration changes, including Grok 4.6.** If Grok Build
|
|
153
153
|
1.0.3 redraws before its `/model` success notice can be observed, aiterm confirms the requested model/effort
|
|
@@ -217,7 +217,7 @@ collection is off by default and performs no network I/O. It ships via
|
|
|
217
217
|
tag-triggered CI with npm provenance (OIDC Trusted Publishing); the GitHub
|
|
218
218
|
Release re-registers the Official MCP Registry entry.
|
|
219
219
|
|
|
220
|
-
**Status:** actively maintained · current public release **v0.
|
|
220
|
+
**Status:** actively maintained · current public release **v0.41.0** · runs on Linux · WSL2 · macOS · native Windows (tmux on POSIX, the tmux-CLI-compatible [psmux](https://github.com/psmux/psmux) on native Windows — no WSL required) · MIT · see the [CHANGELOG](CHANGELOG.md).
|
|
221
221
|
|
|
222
222
|
### Update and rollback
|
|
223
223
|
|
|
@@ -394,7 +394,7 @@ The only edits to the captures above are the two `⋮` lines (a long head/tail r
|
|
|
394
394
|
`aiterm-setup --json`が`ready`になったら、利用するMCP clientを再起動して接続を確認する。Claude Codeの場合:
|
|
395
395
|
|
|
396
396
|
```bash
|
|
397
|
-
/mcp # aiterm should show as connected, exposing
|
|
397
|
+
/mcp # aiterm should show as connected, exposing 16 tools
|
|
398
398
|
```
|
|
399
399
|
|
|
400
400
|
Your first session — four calls, one persistent terminal:
|
|
@@ -435,7 +435,7 @@ The terminal is real and shared, so a human *can* jump in ([A human can watch](#
|
|
|
435
435
|
|
|
436
436
|
```mermaid
|
|
437
437
|
flowchart LR
|
|
438
|
-
AI["AI / MCP client<br/>(the orchestrator)"] -->|"pty_send · pty_observe · agent_launch · agent_configure · agent_approval · claude_turn · claude_approval<br/>legacy launcher aliases · diagnostics"| S["aiterm-mcp<br/>stdio MCP ·
|
|
438
|
+
AI["AI / MCP client<br/>(the orchestrator)"] -->|"pty_send · pty_observe · agent_launch · agent_configure · agent_approval · claude_turn · claude_approval<br/>legacy launcher aliases · diagnostics"| S["aiterm-mcp<br/>stdio MCP · 16 tools"]
|
|
439
439
|
S -->|"pty_read<br/>token-reduced"| AI
|
|
440
440
|
S -->|"tmux / psmux<br/>send · capture"| P["persistent PTYs<br/>survive restarts"]
|
|
441
441
|
P -->|"ssh · docker · repl"| R["nested<br/>remote · container · REPL"]
|
|
@@ -556,7 +556,7 @@ continue to use `claude_approval`.
|
|
|
556
556
|
| `pty_observe` | Pane/harness liveness, native process identity, state, and activity | `session_id`, `cursor?` |
|
|
557
557
|
| `agent_launch` | Canonical agent launch; harness and model are independent | `harness`, `prompt?`, `model?`, `reasoning_effort?`, `cwd?`, `write_scope?`, `trust_project?`, `env_vars?`, `throughline_source_session?`, `throughline_supplement_file?` |
|
|
558
558
|
| `agent_approval` | Inspect a Codex approval and submit a one-time approval or denial | `action`, `session_id`, `approval_choice?`, `observed_prompt_digest?` |
|
|
559
|
-
| `claude_agent` / `codex_agent` / `grok_agent`
|
|
559
|
+
| `claude_agent` / `codex_agent` / `grok_agent` | Deprecated compatibility aliases (`composer_agent` was removed in 0.41.0; run Composer with `agent_launch` on `cursor-cli`) | legacy launcher arguments |
|
|
560
560
|
| `agent_configure` | Change model/effort in a running Claude, Codex, Grok, or Cursor session without restarting it | `session_id`, `model?`, `reasoning_effort?` |
|
|
561
561
|
| `claude_turn` | Issue (dispatch-only) or recover one correlated Claude operation | `action`, `session_id`, `operation_id`, `text?` |
|
|
562
562
|
| `claude_approval` | Inspect or answer the current correlated Claude approval prompt | `action`, `session_id`, `operation_id?`, `approval_choice?`, `observed_prompt_digest?` |
|
package/dist/agent-resolver.js
CHANGED
|
@@ -29,7 +29,7 @@ export function isWindowsNativeExecutable(candidate) {
|
|
|
29
29
|
// Windows の bin 受入: native 実行ファイル(.exe/.cmd/.bat)に加え、pane shell
|
|
30
30
|
// (Git Bash)が shebang で実行できる script も実在すれば受け入れる。旧 WSL 側
|
|
31
31
|
// バイナリ検査への黙ったフォールバックは廃止(別 HOME・別 auth の subagent を
|
|
32
|
-
// 作るため)。native 実行ファイルの強制が要る harness(grok
|
|
32
|
+
// 作るため)。native 実行ファイルの強制が要る harness(grok の実効
|
|
33
33
|
// sandbox 等)は openAgent 側の専用ゲートが明示エラーで担う。
|
|
34
34
|
export function isUsableAgentExecutableFile(candidate) {
|
|
35
35
|
if (!isWin)
|
package/dist/agent-shared.js
CHANGED
|
@@ -177,13 +177,11 @@ export function writeAgentMetadata(meta) {
|
|
|
177
177
|
export function agentLabel(kind) {
|
|
178
178
|
return kind === "claude"
|
|
179
179
|
? "Claude Code"
|
|
180
|
-
: kind === "
|
|
181
|
-
? "Grok Build(
|
|
182
|
-
: kind === "
|
|
183
|
-
? "
|
|
184
|
-
:
|
|
185
|
-
? "Cursor Agent CLI"
|
|
186
|
-
: "Codex";
|
|
180
|
+
: kind === "grok"
|
|
181
|
+
? "Grok Build(Grok)"
|
|
182
|
+
: kind === "cursor"
|
|
183
|
+
? "Cursor Agent CLI"
|
|
184
|
+
: "Codex";
|
|
187
185
|
}
|
|
188
186
|
export function agentHarness(kind) {
|
|
189
187
|
return kind === "claude"
|
|
@@ -223,7 +221,7 @@ export function writeScopeLaunchNote(kind, writeScope) {
|
|
|
223
221
|
? ""
|
|
224
222
|
: kind === "cursor" && writeScope === "read-only"
|
|
225
223
|
? `\n能力宣言: write_scope=${JSON.stringify(writeScope)}。Cursor Agent CLIへ --mode ask を付与し、書込みを実効禁止。`
|
|
226
|
-
: (kind === "codex" || kind === "grok"
|
|
224
|
+
: (kind === "codex" || kind === "grok") && writeScope === "read-only"
|
|
227
225
|
? `\n能力宣言: write_scope=${JSON.stringify(writeScope)}。${agentLabel(kind)} CLIへ --sandbox read-only を付与し、書込みを実効禁止。` +
|
|
228
226
|
(kind === "codex" ? "" : "MCPツール許可は --always-approve で自動承認(sandbox内のため能力拡大なし)。")
|
|
229
227
|
: `\n能力宣言: write_scope=${JSON.stringify(writeScope)}。パス単位のsandbox allowlistに対応するCLI引数がないため宣言の記録のみ(構造的unsupported)。`;
|
package/dist/core.js
CHANGED
|
@@ -18,7 +18,7 @@ import { readRuntimeProcesses, processSubtree, parentProcess, processIdentity, b
|
|
|
18
18
|
import { AitermError, telemetryOwnedFailure, ownTelemetryFailure } from "./errors.js";
|
|
19
19
|
import { isWin, SOCKDIR, tmuxCommand, sendPsmuxPayload, loadPtyBufferChunk, pasteBufferBaseArgs, TMUX_EMPTY_CONFIG, attachCommand, normalizePaneCommand, atomicShellMultiline, appendMarkSentinel, markShellCommand, settlePaneLog, paneCwdArgument, sessionEnvironmentLaunch, } from "./tmux-runtime.js";
|
|
20
20
|
import { sleep, currentUid, runtimeStateBase, safeStatSize, readFileRange, writeJson0600, createEmpty0600, shq, LAUNCH_ID_RE, AGENT_DONE_POLL_MS, AGENT_EVENT_MAX_BYTES, assertSessionName, agentsDir, agentEventPath, agentMetadataPath, writeAgentMetadata, AGENT_EVENT_TAIL_BYTES, agentLabel, agentHarness, subagentInstruction, agentLineageFields, } from "./agent-shared.js";
|
|
21
|
-
import {
|
|
21
|
+
import { realGrokHome, resolveAndValidateGrokAuth, assertGrokModelAvailable, grokEventsTranscript, latestGrokCompletion, observeGrokDone, buildGrokAgentCmd, grokLaunchNote, grokEnvTokens, grokTuiReady, grokTuiBusy, grokPaneObservation, grokRateLimitDialog, grokStartupAction, grokLaunchBlockingDialog, assertGrokSandboxNotRejected, GROK_COMPOSER_MARKER_RE, grokFooterHasConfiguration, grokTranscriptText, createGrokAgentMetadata, } from "./harnesses/grok.js";
|
|
22
22
|
import { bindCodexTranscriptSession, latestCodexCompletion, observeCodexDone, buildCodexAgentCmd, codexLaunchNote, codexTuiReady, codexPaneObservation, codexRateLimitModelSwitchDialog, codexApprovalDialog, codexStartupAction, CODEX_COMPOSER_MARKER_RE, codexModelChoice, codexEffortChoice, codexMoreReasoningChoice, codexTranscriptText, createCodexAgentMetadata, } from "./harnesses/codex.js";
|
|
23
23
|
import { OPERATION_ID_RE, CLAUDE_RESULT_MAX_BYTES, CLAUDE_EFFORTS, agentManagedClaudeSettingsPath, agentClaudeResultPath, agentClaudeOperationPath, agentClaudeApprovalReceiptPath, agentClaudeDispatchReceiptPath, validateOperationId, readClaudeResultText, assertClaudeAuthenticationReady, buildClaudeAgentCmd, claudeLaunchNote, claudeTuiReady, claudePaneObservation, claudeStartupAction, claudeLoginMethodMenu, CLAUDE_COMPOSER_MARKER_RE, createClaudeAgentMetadata, claudeSessionTranscriptPath, claudeApiErrorFromLine, } from "./harnesses/claude.js";
|
|
24
24
|
import { bindCursorTranscriptSession, cursorTurnBoundary, latestCursorCompletion, observeCursorDone, cursorTranscriptText, assertCursorAuthenticationReady, assertCursorModelAvailable, buildCursorAgentCmd, cursorAgentArgv, cursorPwshLaunchLine, cursorPromptWithLineage, createCursorAgentMetadata, cursorLaunchNote, cursorEffortNavigation, cursorTuiReady, cursorPaneObservation, cursorPromptHooksRunning, cursorUsageLimit, CURSOR_SUBMIT_SEQUENCE, CURSOR_COMPOSER_CONTENT_MARKER_RE, validateCursorModelEffort, } from "./harnesses/cursor.js";
|
|
@@ -121,7 +121,6 @@ const AGENT_COMMAND_PATTERNS = {
|
|
|
121
121
|
codex: /(^|[\s/])codex([\s]|$)/,
|
|
122
122
|
claude: /(^|[\s/])claude([\s]|$)/,
|
|
123
123
|
grok: /(^|[\s/])grok(-[^\s/]+)?([\s]|$)/,
|
|
124
|
-
composer: /(^|[\s/])(composer|grok(-[^\s/]+)?)([\s]|$)/,
|
|
125
124
|
cursor: /(^|[\s/])(cursor-agent|agent)([\s]|$)/,
|
|
126
125
|
};
|
|
127
126
|
/**
|
|
@@ -1134,7 +1133,7 @@ export function observeSession(name, cursor) {
|
|
|
1134
1133
|
const screen = captured.stdout;
|
|
1135
1134
|
result.token_hint = meta ? paneTokenHint(screen) : null;
|
|
1136
1135
|
if (meta && agent) {
|
|
1137
|
-
const observation = meta.kind === "grok"
|
|
1136
|
+
const observation = meta.kind === "grok" ? grokPaneObservation(screen)
|
|
1138
1137
|
: meta.kind === "codex" ? codexPaneObservation(screen)
|
|
1139
1138
|
: meta.kind === "claude" ? claudePaneObservation(screen) : cursorPaneObservation(screen);
|
|
1140
1139
|
result.state = observation.state;
|
|
@@ -1933,7 +1932,7 @@ function loadAgentMetadata(name) {
|
|
|
1933
1932
|
throw new AitermError(`agent metadata を読めません: ${e.message}`, 2);
|
|
1934
1933
|
}
|
|
1935
1934
|
const m = raw;
|
|
1936
|
-
if ((m.kind !== "claude" && m.kind !== "codex" && m.kind !== "grok" && m.kind !== "
|
|
1935
|
+
if ((m.kind !== "claude" && m.kind !== "codex" && m.kind !== "grok" && m.kind !== "cursor") ||
|
|
1937
1936
|
m.aiterm_session !== name ||
|
|
1938
1937
|
typeof m.launch_id !== "string" ||
|
|
1939
1938
|
!LAUNCH_ID_RE.test(m.launch_id)) {
|
|
@@ -2191,7 +2190,7 @@ function bindCompletedInitialPrompt(meta) {
|
|
|
2191
2190
|
setInitialPromptState(meta, "done");
|
|
2192
2191
|
return;
|
|
2193
2192
|
}
|
|
2194
|
-
if (
|
|
2193
|
+
if (meta.kind === "grok" && meta.completion_route === "grok_transcript") {
|
|
2195
2194
|
if (!latestGrokCompletion(meta, readTranscriptLines)) {
|
|
2196
2195
|
throw new AitermError(`agent session '${meta.aiterm_session}' は起動時 prompt の完了待ちです。${agentWaitGuide(meta.aiterm_session)}`, 2);
|
|
2197
2196
|
}
|
|
@@ -2231,7 +2230,7 @@ function latestAgentDoneEvent(meta, expectedOperationId = null) {
|
|
|
2231
2230
|
if (meta.kind === "cursor" && meta.completion_route === "cursor_transcript") {
|
|
2232
2231
|
return latestCursorCompletion(meta, readTranscriptLines);
|
|
2233
2232
|
}
|
|
2234
|
-
if (
|
|
2233
|
+
if (meta.kind === "grok" && meta.completion_route === "grok_transcript") {
|
|
2235
2234
|
return latestGrokCompletion(meta, readTranscriptLines);
|
|
2236
2235
|
}
|
|
2237
2236
|
const size = safeStatSize(meta.event_file);
|
|
@@ -2323,7 +2322,7 @@ function recoverAgentHarnessSession(meta) {
|
|
|
2323
2322
|
writeAgentMetadata(meta);
|
|
2324
2323
|
}
|
|
2325
2324
|
function agentCompletionCursor(meta) {
|
|
2326
|
-
if (
|
|
2325
|
+
if (meta.kind === "grok" && meta.completion_route === "grok_transcript") {
|
|
2327
2326
|
const transcript = grokEventsTranscript(meta);
|
|
2328
2327
|
return transcript ? safeStatSize(transcript) : 0;
|
|
2329
2328
|
}
|
|
@@ -2409,7 +2408,7 @@ export async function readAgentTranscriptResult(name, o = {}) {
|
|
|
2409
2408
|
throw new AitermError(`agent session '${name}' はまだターンが完了していません。agent_done 完了後に再取得してください。${agentWaitGuide(name)}`, 2);
|
|
2410
2409
|
}
|
|
2411
2410
|
const done = latestAgentDoneEvent(meta, operationId);
|
|
2412
|
-
if (o.completion && meta.kind !== "codex" && meta.kind !== "grok"
|
|
2411
|
+
if (o.completion && meta.kind !== "codex" && meta.kind !== "grok"
|
|
2413
2412
|
&& (!done || done.turn_id !== o.completion.turn_id || done.operation_id !== o.completion.operation_id)) {
|
|
2414
2413
|
throw new AitermError("回収対象の完了情報が置換されました。別の回答は配送しません", 2);
|
|
2415
2414
|
}
|
|
@@ -2607,7 +2606,7 @@ export function agentWaitGuide(session) {
|
|
|
2607
2606
|
const cmd = `aiterm-wait --session ${session ?? "<session_id>"} --cursor 0`;
|
|
2608
2607
|
return `完了通知は ${agentWaitLaunchForm(cmd)} で受ける(親はここで待たない・polling 不要)。receipt の outcome=done を確認してから再取得する。`;
|
|
2609
2608
|
}
|
|
2610
|
-
// harness別の利用上限観測。Grok
|
|
2609
|
+
// harness別の利用上限観測。Grokは現在の質問カード、Cursorは現在の画面、他harnessは既存logを使う。
|
|
2611
2610
|
// 出典(2026-08-22): grok は live 実バナーで検証、codex/claude はインストール済み実バイナリの
|
|
2612
2611
|
// 埋込文字列から抽出(codex: "You've hit your usage limit for" / claude: "Usage limit reached ·
|
|
2613
2612
|
// continuing automatically when it resets"。Claude Code はリセット時に自動継続する設計なので、
|
|
@@ -2619,7 +2618,7 @@ const AGENT_RATE_LIMIT_PATTERNS = {
|
|
|
2619
2618
|
const AGENT_RATE_LIMIT_SCAN_BYTES = 16 * 1024;
|
|
2620
2619
|
// pane log の末尾から上限バナーを探す。読めない・無い・対象 harness でないは全て null(誤検知より取りこぼし側へ倒す)。
|
|
2621
2620
|
export function detectAgentRateLimit(kind, aitermSession) {
|
|
2622
|
-
if (kind === "grok"
|
|
2621
|
+
if (kind === "grok") {
|
|
2623
2622
|
return grokRateLimitDialog(captureScreen(aitermSession, 0))?.message ?? null;
|
|
2624
2623
|
}
|
|
2625
2624
|
if (kind === "cursor")
|
|
@@ -2671,7 +2670,7 @@ export async function observeAgentDone(name, o = {}) {
|
|
|
2671
2670
|
if (meta.kind === "cursor" && meta.completion_route === "cursor_transcript") {
|
|
2672
2671
|
return observeCursorDone(meta, timeout, o.cursor, detectAgentRateLimit, (session) => captureScreen(session, 0), o.signal);
|
|
2673
2672
|
}
|
|
2674
|
-
if (
|
|
2673
|
+
if (meta.kind === "grok" && meta.completion_route === "grok_transcript") {
|
|
2675
2674
|
return observeGrokDone(meta, timeout, o.cursor, detectAgentRateLimit, o.signal);
|
|
2676
2675
|
}
|
|
2677
2676
|
const metadataFile = agentMetadataPath(meta.aiterm_session, meta.launch_id);
|
|
@@ -2769,13 +2768,13 @@ function isAgentTuiReady(kind, screen) {
|
|
|
2769
2768
|
// Codex/Claude は実行中に「(esc to interrupt)」、Cursor は「Working」+
|
|
2770
2769
|
// 「ctrl+c to stop」を表示する(いずれも実機採取)。startup 側の処理(MCP initialize 等)が
|
|
2771
2770
|
// 走ったまま古い composer がscrollbackに残る画面は入力受付とみなさない。
|
|
2772
|
-
// Grok
|
|
2771
|
+
// Grok は実機で `Waiting for response` / `Responding…` / `[stop]` を表示する。
|
|
2773
2772
|
function isAgentTuiBusy(kind, screen) {
|
|
2774
2773
|
if (kind === "cursor")
|
|
2775
2774
|
return /ctrl\+c to stop/i.test(screen);
|
|
2776
2775
|
if (kind === "codex" || kind === "claude")
|
|
2777
2776
|
return /esc to interrupt/i.test(screen);
|
|
2778
|
-
if (kind === "grok"
|
|
2777
|
+
if (kind === "grok") {
|
|
2779
2778
|
return grokTuiBusy(screen);
|
|
2780
2779
|
}
|
|
2781
2780
|
return false;
|
|
@@ -2783,7 +2782,7 @@ function isAgentTuiBusy(kind, screen) {
|
|
|
2783
2782
|
// ready gate 用: 入力欄マーカーがあっても busy 表示中は ready と数えない。
|
|
2784
2783
|
// frontend 推定(inferAgentFrontend)は「agent TUI が前面か」を見るだけなので isAgentTuiReady のまま。
|
|
2785
2784
|
function isAgentTuiIdleReady(kind, screen) {
|
|
2786
|
-
const observation = kind === "grok"
|
|
2785
|
+
const observation = kind === "grok" ? grokPaneObservation(screen)
|
|
2787
2786
|
: kind === "codex" ? codexPaneObservation(screen)
|
|
2788
2787
|
: kind === "claude" ? claudePaneObservation(screen) : cursorPaneObservation(screen);
|
|
2789
2788
|
return observation.state === "idle";
|
|
@@ -2791,7 +2790,7 @@ function isAgentTuiIdleReady(kind, screen) {
|
|
|
2791
2790
|
// 起動側が明示応答すべき既知UI。ここで自動承認せず、ready timeoutを待たずに
|
|
2792
2791
|
// `initial_prompt=not_sent`を返してsessionを生かしたままcallerへ制御を戻す。
|
|
2793
2792
|
function isAgentTuiActionRequired(kind, screen) {
|
|
2794
|
-
if (kind === "grok"
|
|
2793
|
+
if (kind === "grok")
|
|
2795
2794
|
return grokLaunchBlockingDialog(screen) !== null;
|
|
2796
2795
|
if (kind === "codex") {
|
|
2797
2796
|
return codexPaneObservation(screen).state === "blocked";
|
|
@@ -2830,7 +2829,7 @@ async function waitAgentTuiReadyImpl(kind, sample, sleepFn, opts = {}) {
|
|
|
2830
2829
|
for (;;) {
|
|
2831
2830
|
lastScreen = sample();
|
|
2832
2831
|
samples++;
|
|
2833
|
-
if (kind === "grok"
|
|
2832
|
+
if (kind === "grok")
|
|
2834
2833
|
assertGrokSandboxNotRejected(lastScreen);
|
|
2835
2834
|
if (isAgentTuiIdleReady(kind, lastScreen)) {
|
|
2836
2835
|
readyStreak++;
|
|
@@ -2873,7 +2872,7 @@ function agentSubmitResidueOnScreen(kind, screen, tail) {
|
|
|
2873
2872
|
const lines = screen.split("\n");
|
|
2874
2873
|
// 入力欄マーカーは ready 判定と同じ記号を行頭基準で探す。submit 済みの transcript echo は
|
|
2875
2874
|
// マーカー行より上に出るため、最後のマーカー行以降だけを composer 領域として見る。
|
|
2876
|
-
// grok
|
|
2875
|
+
// grok は Windows native 描画(`>`・実測 1.0.4)も ready 判定と同様に受ける。
|
|
2877
2876
|
const markerRe = kind === "codex"
|
|
2878
2877
|
? CODEX_COMPOSER_MARKER_RE
|
|
2879
2878
|
: kind === "claude"
|
|
@@ -3118,7 +3117,7 @@ async function prepareAgentInput(name, meta, options) {
|
|
|
3118
3117
|
while (!ready.ready) {
|
|
3119
3118
|
const action = meta.kind === "codex" ? codexStartupAction(ready.lastScreen, options.trust_project === true)
|
|
3120
3119
|
: meta.kind === "claude" ? claudeStartupAction(ready.lastScreen, options.trust_project === true)
|
|
3121
|
-
: meta.kind === "grok"
|
|
3120
|
+
: meta.kind === "grok" ? grokStartupAction(ready.lastScreen, options.trust_project === true) : null;
|
|
3122
3121
|
if (!action || handled.has(action.kind))
|
|
3123
3122
|
break;
|
|
3124
3123
|
handled.add(action.kind);
|
|
@@ -3145,7 +3144,7 @@ async function prepareAgentInput(name, meta, options) {
|
|
|
3145
3144
|
ready = await waitAgentTuiReady(name, meta, options.ready_timeout ?? AGENT_TUI_READY_TIMEOUT_MS);
|
|
3146
3145
|
}
|
|
3147
3146
|
if (!ready.ready) {
|
|
3148
|
-
const state = meta.kind === "grok"
|
|
3147
|
+
const state = meta.kind === "grok" ? grokPaneObservation(ready.lastScreen)
|
|
3149
3148
|
: meta.kind === "codex" ? codexPaneObservation(ready.lastScreen)
|
|
3150
3149
|
: meta.kind === "claude" ? claudePaneObservation(ready.lastScreen) : cursorPaneObservation(ready.lastScreen);
|
|
3151
3150
|
return { status: "blocked", reason: state.reason };
|
|
@@ -3217,7 +3216,7 @@ export async function sendInitialAgentPrompt(name, text, o = {}) {
|
|
|
3217
3216
|
let screen = "";
|
|
3218
3217
|
do {
|
|
3219
3218
|
screen = captureScreen(name, AGENT_TUI_READY_LINES);
|
|
3220
|
-
const state = meta.kind === "grok"
|
|
3219
|
+
const state = meta.kind === "grok" ? grokPaneObservation(screen)
|
|
3221
3220
|
: meta.kind === "codex" ? codexPaneObservation(screen)
|
|
3222
3221
|
: meta.kind === "claude" ? claudePaneObservation(screen) : cursorPaneObservation(screen);
|
|
3223
3222
|
if (state.state === "busy") {
|
|
@@ -3415,7 +3414,7 @@ export async function configureAgent(name, opts) {
|
|
|
3415
3414
|
reasoning_effort: effort,
|
|
3416
3415
|
};
|
|
3417
3416
|
}
|
|
3418
|
-
if (meta.kind === "grok"
|
|
3417
|
+
if (meta.kind === "grok") {
|
|
3419
3418
|
if (model) {
|
|
3420
3419
|
const bin = resolveAgentBin(meta.kind);
|
|
3421
3420
|
if (!bin)
|
|
@@ -3551,8 +3550,8 @@ export async function dispatchAgentTurn(name, text, o = {}) {
|
|
|
3551
3550
|
throw new AitermError("operation_id はClaude agent sessionだけで使用できます", 2);
|
|
3552
3551
|
}
|
|
3553
3552
|
bindCompletedInitialPrompt(meta);
|
|
3554
|
-
// Codex/Grok
|
|
3555
|
-
// Grok
|
|
3553
|
+
// Codex/Grokはbind済みのfollow-upでも毎回idleを確認してからtranscript境界を切る。
|
|
3554
|
+
// Grokはsession IDが起動前から既知でも、共有MCPの初期化完了前には送信しない。
|
|
3556
3555
|
// 同じcursorへ複数turnを帰属させる余地や、初期化中TUIへの早送信を作らない。
|
|
3557
3556
|
// Claudeはsession IDを起動時に採番するため「bind済み」では初回を区別できず、起動直後の
|
|
3558
3557
|
// dispatchがready gateを素通りしていた。composer描画前に貼付とEnterが届くと起動時の一塊の
|
|
@@ -3563,7 +3562,7 @@ export async function dispatchAgentTurn(name, text, o = {}) {
|
|
|
3563
3562
|
&& readClaudeOperationMarker(meta) === null;
|
|
3564
3563
|
const paneInputRecovery = o.pane_input_recovery ?? await ensureAgentOwnsPaneInput(name, meta.kind);
|
|
3565
3564
|
let codexRateLimitModelSwitch = false;
|
|
3566
|
-
const limitDialog = meta.kind === "grok"
|
|
3565
|
+
const limitDialog = meta.kind === "grok"
|
|
3567
3566
|
? grokRateLimitDialog(captureScreen(name, 0)) : null;
|
|
3568
3567
|
if (limitDialog) {
|
|
3569
3568
|
const live = observeSession(name);
|
|
@@ -3736,7 +3735,7 @@ async function steerRunningTurn(name, meta, text, o) {
|
|
|
3736
3735
|
sendKey(name, "Enter", { preserveAgentOperation });
|
|
3737
3736
|
// GrokとCursorは実行中の送信を待ち行列へ入れる。そのままだと現在turnの完了後に別turnとして動き、
|
|
3738
3737
|
// 完了通知が差し込み前の回答で届いてしまう。待ち行列へ入ったことを確かめ、標準の「今すぐ送る」で現在turnへ移す。
|
|
3739
|
-
const queued = meta.kind === "grok"
|
|
3738
|
+
const queued = meta.kind === "grok" ? grokSteerQueued
|
|
3740
3739
|
: meta.kind === "cursor" ? cursorSteerQueued : null;
|
|
3741
3740
|
if (queued) {
|
|
3742
3741
|
const label = meta.kind === "cursor" ? "Cursor" : "Grok";
|
|
@@ -3820,7 +3819,7 @@ function inspectClaudeOperation(meta, operationId, action) {
|
|
|
3820
3819
|
const rawOutput = readClaudeResultText(meta, done, operationId, transcriptUnavailable);
|
|
3821
3820
|
return { ...base, status: "completed", raw_output: rawOutput, reason: null };
|
|
3822
3821
|
}
|
|
3823
|
-
// ── 対話型エージェント起動(Claude / Codex / Grok Build
|
|
3822
|
+
// ── 対話型エージェント起動(Claude / Codex / Grok Build / Cursor)──────
|
|
3824
3823
|
// aiterm の永続端末に、指定モデルの対話エージェント TUI を起動する。以後は pty_read で画面を
|
|
3825
3824
|
// 読み、pty_send で操作する=aiterm の対話パラダイムそのもの。モデルはツールごとに固定し、
|
|
3826
3825
|
// reasoning effort は引数で渡す。CLI 未導入環境は明示エラー(動くフリをしない)。
|
|
@@ -4063,21 +4062,20 @@ export function openAgent(kind, opts = {}) {
|
|
|
4063
4062
|
// 未検証リスク: npm グローバル導入の codex.cmd/.bat シムの対話 TUI 描画は実 Windows でしか確認
|
|
4064
4063
|
// できない(CI 非対象。docs/03_audit-sweep-2026-07.md 参照)。native .exe の TUI 描画は
|
|
4065
4064
|
// grok.exe で実測済み(2026-08-15)。
|
|
4066
|
-
// Windows の grok
|
|
4065
|
+
// Windows の grok は Windows native の grok.exe だけを起動する(オーナー裁定 2026-08-15:
|
|
4067
4066
|
// WindowsネイティブはWindowsネイティブで完結させ、WSL2へ持ち込まない)。WSL 側 grok を起動すると
|
|
4068
4067
|
// harness 実体が WSL process になり、auth・session 記録(events/chat_history)が WSL home 側へ分裂して
|
|
4069
4068
|
// transcript/completion を回収できない(実被弾: 2026-08-15 olc-plan-review-grok2)。
|
|
4070
|
-
if (isWin &&
|
|
4069
|
+
if (isWin && kind === "grok" && !isWindowsNativeExecutable(bin)) {
|
|
4071
4070
|
ownTelemetryFailure("AITERM.VENDOR_LAUNCHER_FAILED", new AitermError(`Windows の ${label} launcher は Windows native の grok.exe だけを起動できます(現在の解決先: ${bin})。` +
|
|
4072
4071
|
"Windows 版 Grok CLI を導入するか、GROK_BIN に grok.exe の絶対パスを指定してください。", 2), 2);
|
|
4073
4072
|
}
|
|
4074
4073
|
const binForCmd = agentBinForPaneShell(bin);
|
|
4075
4074
|
const cwdForCmd = cwd ? paneCwdArgument(cwd) : cwd;
|
|
4076
|
-
const grokAuthPath = agentDone &&
|
|
4077
|
-
if (kind === "grok"
|
|
4078
|
-
|
|
4079
|
-
|
|
4080
|
-
assertGrokModelAvailable(bin, cwd ?? process.cwd(), requestedModel);
|
|
4075
|
+
const grokAuthPath = agentDone && kind === "grok" ? resolveAndValidateGrokAuth(realGrokHome()) : null;
|
|
4076
|
+
if (kind === "grok") {
|
|
4077
|
+
if (model)
|
|
4078
|
+
assertGrokModelAvailable(bin, cwd ?? process.cwd(), model);
|
|
4081
4079
|
}
|
|
4082
4080
|
if (kind === "cursor" && model) {
|
|
4083
4081
|
assertCursorModelAvailable(bin, cwd ?? process.cwd(), model, effort);
|
|
@@ -11,7 +11,7 @@ export const cursorParentSchema = z.object({
|
|
|
11
11
|
}).strict();
|
|
12
12
|
const deliveryIdSchema = z.string().uuid();
|
|
13
13
|
const dispatchTools = new Set([
|
|
14
|
-
"agent_launch", "claude_agent", "codex_agent", "grok_agent", "
|
|
14
|
+
"agent_launch", "claude_agent", "codex_agent", "grok_agent", "pty_send", "claude_turn",
|
|
15
15
|
]);
|
|
16
16
|
export class CursorDeliveryError extends AitermError {
|
|
17
17
|
delivery_code;
|
package/dist/grok-stop-hook.js
CHANGED
|
@@ -64,8 +64,8 @@ async function main() {
|
|
|
64
64
|
const kind = process.env.AITERM_AGENT_KIND;
|
|
65
65
|
const session = process.env.AITERM_SESSION_ID || process.env.AITERM_AGENT_SESSION_ID || "";
|
|
66
66
|
const launchId = process.env.AITERM_AGENT_LAUNCH_ID || "";
|
|
67
|
-
if (kind !== "grok"
|
|
68
|
-
fail(`AITERM_AGENT_KIND が grok
|
|
67
|
+
if (kind !== "grok")
|
|
68
|
+
fail(`AITERM_AGENT_KIND が grok ではありません: ${kind ?? ""}`);
|
|
69
69
|
if (!SESSION_RE.test(session))
|
|
70
70
|
fail(`session id が不正です: ${session}`);
|
|
71
71
|
if (!LAUNCH_ID_RE.test(launchId))
|
package/dist/harnesses/grok.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
// Grok 固有の制御。
|
|
2
|
-
//
|
|
3
|
-
// 現行Grok CLIには無い(2026-09-27 grok 1.0.41 実測)。
|
|
1
|
+
// Grok 固有の制御。Composer は Cursor の model の一つであり、Grok CLI では扱わない
|
|
2
|
+
// (2026-09-27 grok 1.0.41 実測でcatalogに無い)。
|
|
4
3
|
// core 所有のサービス(transcript 行読取・rate limit 検知)は引数で注入し、
|
|
5
4
|
// 依存方向を core → harnesses → agent-shared の一方向に保つ。
|
|
6
5
|
import * as fs from "node:fs";
|
|
@@ -17,7 +16,6 @@ const GROK_MODELS_TIMEOUT_MS = 15_000;
|
|
|
17
16
|
// 製品既定は検証済みGrok catalog世代へ固定する。callerの明示modelはlive catalogで別途照合する。
|
|
18
17
|
export const GROK_MODEL_DEFAULTS = {
|
|
19
18
|
grok: "grok-4.6",
|
|
20
|
-
composer: "grok-composer-2.5-fast",
|
|
21
19
|
};
|
|
22
20
|
export function realGrokHome() {
|
|
23
21
|
return path.resolve(process.env.GROK_HOME || path.join(process.env.HOME ?? os.homedir(), ".grok"));
|
|
@@ -71,7 +69,7 @@ export function assertGrokModelAvailable(bin, cwd, model) {
|
|
|
71
69
|
}
|
|
72
70
|
}
|
|
73
71
|
export function grokSessionDirectory(meta) {
|
|
74
|
-
if (
|
|
72
|
+
if (meta.kind !== "grok" || !meta.grok_home || !meta.vendor_session_id)
|
|
75
73
|
return null;
|
|
76
74
|
// Grok CLIは起動cwdをOSの絶対パスへ正規化して保存する。
|
|
77
75
|
const cwd = path.resolve(meta.cwd ?? process.cwd());
|
|
@@ -82,7 +80,7 @@ export function grokEventsTranscript(meta) {
|
|
|
82
80
|
return dir ? path.join(dir, "events.jsonl") : null;
|
|
83
81
|
}
|
|
84
82
|
export function grokCompletionEvent(meta, record) {
|
|
85
|
-
if (
|
|
83
|
+
if (meta.kind !== "grok" ||
|
|
86
84
|
record?.type !== "turn_ended" ||
|
|
87
85
|
(record?.outcome !== "completed" && record?.outcome !== "cancelled" && record?.outcome !== "error"))
|
|
88
86
|
return null;
|
|
@@ -240,24 +238,23 @@ export async function observeGrokDone(meta, timeout, requestedCursor, detectRate
|
|
|
240
238
|
}
|
|
241
239
|
export function buildGrokAgentCmd(kind, bin, model, effort, prompt, meta) {
|
|
242
240
|
const parts = [shq(bin)];
|
|
243
|
-
// grok / composer は同じ grok CLI をモデル違いで起動する。
|
|
244
241
|
parts.push("--no-auto-update");
|
|
245
242
|
// 無人起動の対象cwdはCLIの公式folder trust指定で登録し、確認画面にpromptを消費させない。
|
|
246
|
-
if (meta?.kind === "grok"
|
|
243
|
+
if (meta?.kind === "grok")
|
|
247
244
|
parts.push("--no-alt-screen", "--trust");
|
|
248
245
|
parts.push("--model", shq(model ?? GROK_MODEL_DEFAULTS[kind]));
|
|
249
246
|
if (effort)
|
|
250
247
|
parts.push("--reasoning-effort", shq(effort));
|
|
251
|
-
if (
|
|
248
|
+
if (meta?.kind === "grok" && meta.write_scope === "read-only") {
|
|
252
249
|
// read-only は sandbox が実効書込み禁止を作るため、MCP ツール許可ダイアログの自動承認を
|
|
253
250
|
// 付けても能力は増えない。無人 subagent が初回 MCP 使用の許可待ちで停止する実障害への対処。
|
|
254
251
|
// read-only 以外の launch には付けない=権限拡大しない。
|
|
255
252
|
parts.push("--sandbox", "read-only", "--always-approve");
|
|
256
253
|
}
|
|
257
|
-
if (
|
|
254
|
+
if (meta?.kind === "grok" && meta.hook_route === "shared_grok_home") {
|
|
258
255
|
parts.push("--session-id", shq(meta.vendor_session_id ?? ""), "--rules", shq(subagentInstruction(meta)));
|
|
259
256
|
}
|
|
260
|
-
if (
|
|
257
|
+
if (meta?.kind === "grok" && prompt)
|
|
261
258
|
parts.push("--verbatim");
|
|
262
259
|
if (prompt)
|
|
263
260
|
parts.push(shq(prompt)); // 初手プロンプト(任意)
|
|
@@ -268,7 +265,7 @@ export function grokLaunchNote(kind, model, effort, meta) {
|
|
|
268
265
|
return (`起動設定: model=${model ?? GROK_MODEL_DEFAULTS[kind]}(${model ? "引数" : "ツール既定"})。` +
|
|
269
266
|
`effort=${effort ?? "CLI/model既定"}。` + writeScopeNote);
|
|
270
267
|
}
|
|
271
|
-
// grok
|
|
268
|
+
// grok: 検証済み auth 正本をそのままの path 形で渡す。Windows では native 強制により
|
|
272
269
|
// harness は Windows process なので、Windows ドライブパスが正しい形(WSL 形への変換はしない)。
|
|
273
270
|
export function grokEnvTokens(meta) {
|
|
274
271
|
return [
|
|
@@ -304,9 +301,8 @@ export function grokTuiReady(screen) {
|
|
|
304
301
|
if (grokLaunchBlockingDialog(screen))
|
|
305
302
|
return false;
|
|
306
303
|
// Grok Build 0.2.117 は起動完了後に製品名を消し、model footerだけを残す。
|
|
307
|
-
// Composerも同じfrontendでmodel名だけが異なるため、両方をharness UIの根拠にする。
|
|
308
304
|
// Windows native grok.exe(1.0.4 実測)は入力欄markerを `❯` でなく `>` で描画するため両方を受ける。
|
|
309
|
-
const grokFrontend = screen.includes("Grok Build") || /\
|
|
305
|
+
const grokFrontend = screen.includes("Grok Build") || /\bGrok\s+[\w.()-]+/.test(screen);
|
|
310
306
|
return grokFrontend && /(^|\n|\s)[❯>]/.test(screen);
|
|
311
307
|
}
|
|
312
308
|
export function grokTuiBusy(screen) {
|
|
@@ -334,7 +330,7 @@ export function grokRateLimitDialog(screen) {
|
|
|
334
330
|
return { message: "You hit your weekly limit.", dismissKey: "X" };
|
|
335
331
|
}
|
|
336
332
|
function grokFramedComposer(screen) {
|
|
337
|
-
return /^[ \t]*│[ \t]*[❯>][^\n]*\n(?:[ \t]*│[^\n]*\n)*[ \t]*╰[^\n]*\
|
|
333
|
+
return /^[ \t]*│[ \t]*[❯>][^\n]*\n(?:[ \t]*│[^\n]*\n)*[ \t]*╰[^\n]*\bGrok\s+[\w.()-]+[^\n]*╯[ \t]*(?:\n|$)/mu.test(screen);
|
|
338
334
|
}
|
|
339
335
|
export function grokPaneObservation(screen) {
|
|
340
336
|
// 通信失敗後もWaitingが残る実画面を、稼働中として返さない。
|
package/dist/index.js
CHANGED
|
@@ -122,7 +122,7 @@ async function factoryDiagnostics() {
|
|
|
122
122
|
grok: {
|
|
123
123
|
status: grok,
|
|
124
124
|
optional: true,
|
|
125
|
-
required_for: ["grok_agent"
|
|
125
|
+
required_for: ["grok_agent"],
|
|
126
126
|
},
|
|
127
127
|
cursor: {
|
|
128
128
|
status: cursor,
|
|
@@ -292,7 +292,7 @@ registerRemoteAwareTool("pty_send", {
|
|
|
292
292
|
wait_process: waitProcessOutputSchema,
|
|
293
293
|
parent_delivery: parentDeliveryOutputSchema.optional(),
|
|
294
294
|
launch_id: z.string().nullable(),
|
|
295
|
-
vendor: z.enum(["claude", "codex", "grok", "
|
|
295
|
+
vendor: z.enum(["claude", "codex", "grok", "cursor"]).nullable(),
|
|
296
296
|
harness: z.enum(["claude-code", "codex-cli", "grok-cli", "cursor-cli"]).nullable(),
|
|
297
297
|
// dispatch後のsubmit座礁観測(additive)。true=composerに送信textの残存を確認(submit未成立の疑い)/
|
|
298
298
|
// false=残存を観測せず(成立の保証ではない)/ null=通常送信・判定不能。
|
|
@@ -426,7 +426,7 @@ registerRemoteAwareTool("pty_read", {
|
|
|
426
426
|
mode: z.enum(["terminal", "agent_transcript"]),
|
|
427
427
|
session_id: z.string(),
|
|
428
428
|
text: z.string(),
|
|
429
|
-
vendor: z.enum(["claude", "codex", "grok", "
|
|
429
|
+
vendor: z.enum(["claude", "codex", "grok", "cursor"]).nullable(),
|
|
430
430
|
turn_id: z.string().nullable(),
|
|
431
431
|
harness: z.enum(["claude-code", "codex-cli", "grok-cli", "cursor-cli"]).nullable(),
|
|
432
432
|
raw_chars: z.number().int().nonnegative().nullable(),
|
|
@@ -726,7 +726,7 @@ registerRemoteAwareTool("agent_configure", {
|
|
|
726
726
|
outputSchema: {
|
|
727
727
|
schema: z.literal("aiterm.agent-configure-result.v1"),
|
|
728
728
|
session_id: z.string().regex(/^[A-Za-z0-9_-]{1,64}$/),
|
|
729
|
-
provider: z.enum(["claude", "codex", "grok", "
|
|
729
|
+
provider: z.enum(["claude", "codex", "grok", "cursor"]),
|
|
730
730
|
harness: z.enum(["claude-code", "codex-cli", "grok-cli", "cursor-cli"]),
|
|
731
731
|
model: z.string().nullable(),
|
|
732
732
|
reasoning_effort: z.string().nullable(),
|
|
@@ -752,10 +752,7 @@ const agentModelDesc = (kind) => kind === "claude"
|
|
|
752
752
|
"(端末側のピンがそのまま効く。実効値は起動応答に明示される)"
|
|
753
753
|
: kind === "cursor"
|
|
754
754
|
? "Cursor Agent CLIで選ぶbase model(例: gpt-5.6-luna)。GPT/Claude/Grok等を選べ、effortは別指定。省略時はCursor既定"
|
|
755
|
-
:
|
|
756
|
-
(kind === "composer"
|
|
757
|
-
? "既定/explicit modelを起動前にlive catalogへ照合し、不在ならfallbackせずエラー"
|
|
758
|
-
: "explicit modelを起動前にlive catalogへ照合し、不在ならfallbackせずエラー");
|
|
755
|
+
: "起動モデル。省略時は grok-4.6。explicit modelを起動前にlive catalogへ照合し、不在ならfallbackせずエラー";
|
|
759
756
|
const agentEffortDesc = (kind) => kind === "claude"
|
|
760
757
|
? "Claude Code reasoning effort。low/medium/high/xhigh/max。省略時はCLI既定"
|
|
761
758
|
: kind === "codex"
|
|
@@ -965,7 +962,7 @@ server.registerTool("agent_launch", {
|
|
|
965
962
|
remote_host: z.string().optional().describe("別端末で起動した時の接続先"),
|
|
966
963
|
remote_version: z.string().nullable().optional().describe("別端末のAiterm版"),
|
|
967
964
|
harness: z.enum(["claude-code", "codex-cli", "grok-cli", "cursor-cli"]),
|
|
968
|
-
provider: z.enum(["claude", "codex", "grok", "
|
|
965
|
+
provider: z.enum(["claude", "codex", "grok", "cursor"]).describe("旧互換field。新規連携はharnessを使う"),
|
|
969
966
|
session_id: z.string().regex(/^[A-Za-z0-9_-]{1,64}$/),
|
|
970
967
|
managed_completion: z.boolean(),
|
|
971
968
|
event_cursor: z.number().int().nullable(),
|
|
@@ -1006,12 +1003,6 @@ registerAgentTool("grok_agent", "grok", "【旧互換alias。新規連携は age
|
|
|
1006
1003
|
"turn は pty_send で送る(自動で非ブロック dispatch になる)。" +
|
|
1007
1004
|
agentCompletionDesc +
|
|
1008
1005
|
"model/reasoning_effortを引数で指定可。read-only sandboxとagent_configureに対応。");
|
|
1009
|
-
registerAgentTool("composer_agent", "composer", "【旧互換alias・起動不能。ComposerはCursorのmodelの一つなので agent_launch(harness=cursor-cli, model=composer-2.5-fast) を使う】旧Grok CLIのComposer presetを起動しようとする。現行Grok CLIにComposerは無く、常にcatalogエラーになる。" +
|
|
1010
|
-
agentEnvironmentDesc +
|
|
1011
|
-
"turn は pty_send で送る(自動で非ブロック dispatch になる)。" +
|
|
1012
|
-
agentCompletionDesc +
|
|
1013
|
-
"model/reasoning_effortを引数で指定可。live catalogにComposer modelがなければGrokへfallbackせず明示エラー。" +
|
|
1014
|
-
"read-only sandboxとagent_configureに対応。");
|
|
1015
1006
|
async function main() {
|
|
1016
1007
|
// 親ホストを initialize の clientInfo.name から確定させ、receipt の完了待ちコマンドを
|
|
1017
1008
|
// そのホストの実際の起動形で名指しする(実測: claude-code は initialize → notifications/initialized
|
package/dist/parent-delivery.js
CHANGED
|
@@ -21,7 +21,7 @@ const recordSchema = z.object({
|
|
|
21
21
|
boundary: z.object({
|
|
22
22
|
session_id: z.string().regex(/^[A-Za-z0-9_-]{1,64}$/),
|
|
23
23
|
launch_id: z.string().regex(/^[0-9a-f]{32}$/),
|
|
24
|
-
vendor: z.enum(["claude", "codex", "grok", "
|
|
24
|
+
vendor: z.enum(["claude", "codex", "grok", "cursor"]),
|
|
25
25
|
harness: z.enum(["claude-code", "codex-cli", "grok-cli", "cursor-cli"]),
|
|
26
26
|
event_cursor: z.number().int().nonnegative(), operation_id: z.string().nullable(),
|
|
27
27
|
// 別端末の子。remote用の保存場所にだけ書き、旧版のreaderへ渡さない。
|
|
@@ -58,7 +58,7 @@ export function mergeJsonMcp(file, registration) {
|
|
|
58
58
|
}
|
|
59
59
|
export function claudeParentHookEntries(registration) {
|
|
60
60
|
const command = { type: "command", command: registration.command, args: [join(dirname(registration.args[0]), "claude-parent-hook.js")] };
|
|
61
|
-
const matcher = "^mcp__aiterm__(agent_launch|claude_agent|codex_agent|grok_agent|
|
|
61
|
+
const matcher = "^mcp__aiterm__(agent_launch|claude_agent|codex_agent|grok_agent|pty_send|claude_turn)$";
|
|
62
62
|
return {
|
|
63
63
|
PreToolUse: [{ matcher, hooks: [{ ...command, timeout: 15 }] }],
|
|
64
64
|
PostToolUse: [{ matcher, hooks: [{ ...command, asyncRewake: true, timeout: 86400 }] }],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aiterm-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.41.0",
|
|
4
4
|
"mcpName": "io.github.kitepon/aiterm-mcp",
|
|
5
5
|
"description": "Persistent terminal MCP with one harness-based launcher for Claude Code, Codex CLI, Grok CLI, and Cursor Agent CLI, plus durable PTYs for SSH, containers, and REPLs.",
|
|
6
6
|
"keywords": [
|