aiterm-mcp 0.31.1 → 0.31.2

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 CHANGED
@@ -7,6 +7,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [0.31.2] - 2026-09-08
11
+
12
+ ### Fixed
13
+
14
+ - Grok/Composerの無人起動で公式`--trust`を使い、フォルダ信頼の確認画面に初回promptのEnterが消費される問題を修正した。確認画面はshellの`>`がscrollbackにあっても入力受付と判定しない。
15
+ - Grokの完了済みhook結果`[hooks: 成功/失敗]`を実行中表示と誤認し、入力待ちのまま初回送信や追加送信が停止する問題を修正した。判定はGrok専用アダプターが所有する。
16
+
17
+ ### Changed
18
+
19
+ - Grok/Composerのsandbox起動拒否について、日英README、DESIGN、AGENTS、文書地図、公開後smokeの説明を同期した。検出はGrok専用アダプターが所有し、共通処理はその呼出しだけを担うこと、promptなしの起動応答は入力受付完了を示さないことを明記した。
20
+
10
21
  ## [0.31.1] - 2026-09-06
11
22
 
12
23
  ### Fixed
@@ -1559,7 +1570,8 @@ prototype (preserved under `prototype/python/` as the porting source and referen
1559
1570
  `ubuntu-latest` for Node 18/20/22, publishing to npm on `v*` tags with
1560
1571
  provenance.
1561
1572
 
1562
- [Unreleased]: https://github.com/kitepon/aiterm-mcp/compare/v0.31.1...HEAD
1573
+ [Unreleased]: https://github.com/kitepon/aiterm-mcp/compare/v0.31.2...HEAD
1574
+ [0.31.2]: https://github.com/kitepon/aiterm-mcp/compare/v0.31.1...v0.31.2
1563
1575
  [0.31.1]: https://github.com/kitepon/aiterm-mcp/compare/v0.31.0...v0.31.1
1564
1576
  [0.31.0]: https://github.com/kitepon/aiterm-mcp/compare/v0.30.0...v0.31.0
1565
1577
  [0.30.0]: https://github.com/kitepon/aiterm-mcp/compare/v0.29.31...v0.30.0
package/README.ja.md CHANGED
@@ -153,7 +153,7 @@ runtime-error store は canonical dotagents config の `collection.enabled: true
153
153
  場合だけ収集し、既定OFF、network送信は行いません。tag起点CIのnpm provenance(OIDC Trusted
154
154
  Publishing)で公開し、GitHub Release が Official MCP Registry を再登録します。
155
155
 
156
- **状態:** 開発継続中 · 現行公開版 **v0.31.1** · 動作対象は Linux · WSL2 · macOS · Windows ネイティブ · MIT · [変更履歴](CHANGELOG.md)。
156
+ **状態:** 開発継続中 · 現行公開版 **v0.31.2** · 動作対象は Linux · WSL2 · macOS · Windows ネイティブ · MIT · [変更履歴](CHANGELOG.md)。
157
157
 
158
158
  ### 更新と巻き戻し
159
159
 
@@ -193,8 +193,12 @@ pty_read(id, { wait: true }) → 削減済みの出力を読む(完了
193
193
 
194
194
  `agent_launch`は任意の`write_scope`も受ける。Codex/Grokのread-onlyは`--sandbox read-only`、Cursorは公式`--mode ask`で実効化する。path説明は同等CLI引数がないためdeclaration-only。
195
195
 
196
+ Grok/Composerの無人起動は公式`--trust`で指定された作業フォルダを信頼登録し、確認画面を完了してから初回promptを送る。この登録はGrok CLIの信頼ストアへ保存され、フォルダ内のhook・MCP・LSPにも適用される。read-only sandboxの制限は維持する。画面に残る完了済みhookの結果は実行中と判定しない。
197
+
196
198
  Grok/Composerがread-only sandboxの適用を拒否した場合、prompt送信時に`GROK_SANDBOX_STARTUP_FAILED`とCLIの原因を返す。例えばhookのパスにシンボリックリンクがあるとGrok CLIは起動を拒否する。設定の管理元で原因を修正し、対象sessionを`pty_close`して起動し直す。Aitermはsandboxを解除したりhookをコピーしたりしない。
197
199
 
200
+ この判定はGrok専用アダプターが所有し、同じCLIを使うComposerにも適用する。初回prompt付きの`agent_launch`と通常の`pty_send`で、入力受付待ち中に拒否を検出すると未送信のエラーを返す。promptなしの`agent_launch`は起動要求を返すため、その応答だけでは入力受付済みと判断しない。実装の責務分担は[DESIGN](docs/DESIGN.md#failure-and-recovery)を参照。
201
+
198
202
  ```text
199
203
  agent_launch({ harness: "codex-cli", session_name: "codex1", cwd: "/repo",
200
204
  prompt: "port test/legacy.py to vitest",
package/README.md CHANGED
@@ -169,7 +169,7 @@ collection is off by default and performs no network I/O. It ships via
169
169
  tag-triggered CI with npm provenance (OIDC Trusted Publishing); the GitHub
170
170
  Release re-registers the Official MCP Registry entry.
171
171
 
172
- **Status:** actively maintained · current public release **v0.31.1** · 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).
172
+ **Status:** actively maintained · current public release **v0.31.2** · 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).
173
173
 
174
174
  ### Update and rollback
175
175
 
@@ -215,8 +215,12 @@ The human-readable launch text is accompanied by an `aiterm.agent-launch-result.
215
215
 
216
216
  `agent_launch` accepts an optional `write_scope`: either `"read-only"` or a human-readable description of writable paths. Codex/Grok use `--sandbox read-only`; Cursor uses its official read-only `--mode ask`. A path description remains declaration-only because these CLI launch surfaces provide no equivalent path allowlist flag.
217
217
 
218
+ Grok/Composerの無人起動は公式`--trust`で指定された作業フォルダを信頼登録し、確認画面を完了してから初回promptを送る。この登録はGrok CLIの信頼ストアへ保存され、フォルダ内のhook・MCP・LSPにも適用される。read-only sandboxの制限は維持する。画面に残る完了済みhookの結果は実行中と判定しない。
219
+
218
220
  Grok/Composerがread-only sandboxの適用を拒否した場合、prompt送信時に`GROK_SANDBOX_STARTUP_FAILED`とCLIの原因を返す。hookパスのシンボリックリンクなど、CLIが示した原因を設定の管理元で修正し、対象sessionを`pty_close`して起動し直す。Aitermはsandboxを解除したりhookをコピーしたりしない。
219
221
 
222
+ この判定はGrok専用アダプターが所有し、同じCLIを使うComposerにも適用する。初回prompt付きの`agent_launch`と通常の`pty_send`で、入力受付待ち中に拒否を検出すると未送信のエラーを返す。promptなしの`agent_launch`は起動要求を返すため、その応答だけでは入力受付済みと判断しない。実装の責務分担は[DESIGN](docs/DESIGN.md#failure-and-recovery)を参照。
223
+
220
224
  For a correlated Claude turn stopped at `Do you want to proceed?`, use `claude_approval(action: "inspect", ...)` to capture the active operation and SHA-256 screen digest, review the displayed command, then call `respond` with that exact digest and either `approve_once` or `deny`. The relay rechecks the operation and screen under the send lock, never exposes arbitrary input or permanent approval, keeps the active marker intact, and records a prompt-free owner-only receipt. `pty_send(force: true)` does not bypass this boundary.
221
225
 
222
226
  ```text
package/dist/core.js CHANGED
@@ -16,7 +16,7 @@ import * as rtk from "./rtk.js";
16
16
  import { AitermError, telemetryOwnedFailure, ownTelemetryFailure } from "./errors.js";
17
17
  import { isWin, SOCKDIR, tmuxCommand, sendPsmuxPayload, loadPtyBufferChunk, pasteBufferBaseArgs, TMUX_EMPTY_CONFIG, attachCommand, normalizePaneCommand, appendMarkSentinel, settlePaneLog, paneCwdArgument, } from "./tmux-runtime.js";
18
18
  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";
19
- import { GROK_MODEL_DEFAULTS, realGrokHome, resolveAndValidateGrokAuth, assertGrokModelAvailable, grokEventsTranscript, latestGrokCompletion, observeGrokDone, buildGrokAgentCmd, grokLaunchNote, grokEnvTokens, grokTuiReady, assertGrokSandboxNotRejected, GROK_COMPOSER_MARKER_RE, grokFooterHasConfiguration, grokTranscriptText, createGrokAgentMetadata, } from "./harnesses/grok.js";
19
+ import { GROK_MODEL_DEFAULTS, realGrokHome, resolveAndValidateGrokAuth, assertGrokModelAvailable, grokEventsTranscript, latestGrokCompletion, observeGrokDone, buildGrokAgentCmd, grokLaunchNote, grokEnvTokens, grokTuiReady, grokTuiBusy, grokLaunchBlockingDialog, assertGrokSandboxNotRejected, GROK_COMPOSER_MARKER_RE, grokFooterHasConfiguration, grokTranscriptText, createGrokAgentMetadata, } from "./harnesses/grok.js";
20
20
  import { bindCodexTranscriptSession, latestCodexCompletion, observeCodexDone, buildCodexAgentCmd, codexLaunchNote, codexTuiReady, codexLaunchBlockingDialog, CODEX_COMPOSER_MARKER_RE, codexModelChoice, codexEffortChoice, codexMoreReasoningChoice, codexTranscriptText, createCodexAgentMetadata, } from "./harnesses/codex.js";
21
21
  import { OPERATION_ID_RE, CLAUDE_RESULT_MAX_BYTES, CLAUDE_EFFORTS, agentManagedClaudeSettingsPath, agentClaudeResultPath, agentClaudeOperationPath, agentClaudeApprovalReceiptPath, agentClaudeDispatchReceiptPath, validateOperationId, readClaudeResultText, assertClaudeAuthenticationReady, buildClaudeAgentCmd, claudeLaunchNote, claudeTuiReady, CLAUDE_COMPOSER_MARKER_RE, createClaudeAgentMetadata, claudeSessionTranscriptPath, claudeApiErrorFromLine, } from "./harnesses/claude.js";
22
22
  import { bindCursorTranscriptSession, cursorTurnBoundary, latestCursorCompletion, observeCursorDone, cursorTranscriptText, assertCursorAuthenticationReady, assertCursorModelAvailable, buildCursorAgentCmd, cursorPromptWithLineage, createCursorAgentMetadata, cursorLaunchNote, cursorEffortNavigation, cursorTuiReady, CURSOR_SUBMIT_SEQUENCE, CURSOR_COMPOSER_CONTENT_MARKER_RE, validateCursorModelEffort, } from "./harnesses/cursor.js";
@@ -2486,11 +2486,7 @@ function isAgentTuiBusy(kind, screen) {
2486
2486
  if (kind === "codex" || kind === "claude")
2487
2487
  return /esc to interrupt/i.test(screen);
2488
2488
  if (kind === "grok" || kind === "composer") {
2489
- return screen.includes("Waiting for response")
2490
- || screen.includes("Responding…")
2491
- || screen.includes("Responding...")
2492
- || screen.includes("[stop]")
2493
- || /\[hooks:\s*\d+\/\d+\]/u.test(screen);
2489
+ return grokTuiBusy(screen);
2494
2490
  }
2495
2491
  return false;
2496
2492
  }
@@ -2504,6 +2500,8 @@ function isAgentTuiIdleReady(kind, screen) {
2504
2500
  // 起動側が明示応答すべき既知UI。ここで自動承認せず、ready timeoutを待たずに
2505
2501
  // `initial_prompt=not_sent`を返してsessionを生かしたままcallerへ制御を戻す。
2506
2502
  function isAgentTuiActionRequired(kind, screen) {
2503
+ if (kind === "grok" || kind === "composer")
2504
+ return grokLaunchBlockingDialog(screen) !== null;
2507
2505
  if (kind === "codex") {
2508
2506
  return codexLaunchBlockingDialog(screen) !== null
2509
2507
  || screen.includes("Hooks need review")
@@ -2823,7 +2821,8 @@ export async function sendInitialAgentPrompt(name, text, o = {}) {
2823
2821
  if (!ready.ready) {
2824
2822
  // ready失敗は成功形で返さず明示エラーにする(実被弾 2026-08-25: Codexのupdate確認ダイアログで
2825
2823
  // 未送信のまま成功形receiptが返り、呼び出し側が40分気づけなかった)。sessionは調査/復旧用に残る。
2826
- const dialog = meta.kind === "codex" ? codexLaunchBlockingDialog(ready.lastScreen) : null;
2824
+ const dialog = meta.kind === "codex" ? codexLaunchBlockingDialog(ready.lastScreen)
2825
+ : meta.kind === "grok" || meta.kind === "composer" ? grokLaunchBlockingDialog(ready.lastScreen) : null;
2827
2826
  const causeNote = dialog
2828
2827
  ? `${dialog}が入力を塞いでいます。pty_read(screen:true)で画面を確認し、pty_keyでダイアログに応答してから、pty_sendでpromptを送ってください。`
2829
2828
  : `pty_read(screen:true)で画面を確認し、入力受付になってからpty_sendでpromptを送ってください。`;
@@ -229,8 +229,9 @@ export function buildGrokAgentCmd(kind, bin, model, effort, prompt, meta) {
229
229
  const parts = [shq(bin)];
230
230
  // grok / composer は同じ grok CLI をモデル違いで起動する。
231
231
  parts.push("--no-auto-update");
232
+ // 無人起動の対象cwdはCLIの公式folder trust指定で登録し、確認画面にpromptを消費させない。
232
233
  if (meta?.kind === "grok" || meta?.kind === "composer")
233
- parts.push("--no-alt-screen");
234
+ parts.push("--no-alt-screen", "--trust");
234
235
  parts.push("--model", shq(model ?? GROK_MODEL_DEFAULTS[kind]));
235
236
  if (effort)
236
237
  parts.push("--reasoning-effort", shq(effort));
@@ -273,13 +274,34 @@ export function assertGrokSandboxNotRejected(screen) {
273
274
  `${warning?.[0] ?? ""}\n${failure[0]}\n` +
274
275
  "CLIが示した設定の問題を、その設定の管理元で修正してください。修正後はpty_closeで対象sessionを閉じ、agent_launchで起動し直してください。", 2);
275
276
  }
277
+ export function grokLaunchBlockingDialog(screen) {
278
+ const trustAt = screen.lastIndexOf("Do you trust the contents of this directory?");
279
+ if (trustAt < 0)
280
+ return null;
281
+ const afterTrust = screen.slice(trustAt);
282
+ if (!afterTrust.includes("Yes, proceed") || !afterTrust.includes("No, quit"))
283
+ return null;
284
+ // 古い確認画面より後に現在の入力欄がある場合は、scrollbackだけを根拠に停止しない。
285
+ if (/(?:^|\n)[ \t]*(?:│[ \t]*)?[❯>]/u.test(afterTrust))
286
+ return null;
287
+ return "folder trust確認ダイアログ";
288
+ }
276
289
  export function grokTuiReady(screen) {
290
+ if (grokLaunchBlockingDialog(screen))
291
+ return false;
277
292
  // Grok Build 0.2.117 は起動完了後に製品名を消し、model footerだけを残す。
278
293
  // Composerも同じfrontendでmodel名だけが異なるため、両方をharness UIの根拠にする。
279
294
  // Windows native grok.exe(1.0.4 実測)は入力欄markerを `❯` でなく `>` で描画するため両方を受ける。
280
295
  const grokFrontend = screen.includes("Grok Build") || /\b(?:Grok|Composer)\s+[\w.()-]+/.test(screen);
281
296
  return grokFrontend && /(^|\n|\s)[❯>]/.test(screen);
282
297
  }
298
+ export function grokTuiBusy(screen) {
299
+ // [hooks: 成功/失敗]は完了後も残る結果表示であり、実行中の根拠にはならない。
300
+ return screen.includes("Waiting for response")
301
+ || screen.includes("Responding…")
302
+ || screen.includes("Responding...")
303
+ || screen.includes("[stop]");
304
+ }
283
305
  // submit座礁観測のcomposer領域マーカー(Windows native描画の `>` も ready 判定と同様に受ける)。
284
306
  export const GROK_COMPOSER_MARKER_RE = /(^|\s)[❯>]/;
285
307
  export function grokFooterHasConfiguration(screen, model, effort) {
@@ -14,6 +14,9 @@ dotagentsは任意の工場統合を担うが、Aitermの製品正典や実行
14
14
  - [benchmarks](https://github.com/kitepon/aiterm-mcp/blob/main/docs/benchmarks.md): 出力削減の実測根拠。
15
15
  - [CHANGELOG](../CHANGELOG.md): 版別変更履歴。
16
16
 
17
+ Grok/Composerのsandbox起動拒否については、[DESIGNの失敗と復旧](DESIGN.md#failure-and-recovery)に
18
+ 検出の所有と適用範囲、[RELEASEの公開後smoke](RELEASE.md#公開後smoke)に検証条件を置く。
19
+
17
20
  ## 履歴と証拠
18
21
 
19
22
  - [`archive/`](https://github.com/kitepon/aiterm-mcp/tree/main/docs/archive): 完了・棄却・中断・失効・置換により現行制御から外れたsnapshot。
package/docs/DESIGN.md CHANGED
@@ -55,6 +55,21 @@ shell、接続先、各harnessの公式CLIが所有する。
55
55
  stale send lockは並行processとのABAを避けるため自動削除せず、公開APIでは対象sessionを`pty_close`して
56
56
  同じIDで再作成する。全session一括停止は公開しない。
57
57
 
58
+ Grok/Composerのread-only sandbox起動拒否は、`src/harnesses/grok.ts`の
59
+ `assertGrokSandboxNotRejected`がCLIのエラー表示から検出する。`src/core.ts`の共通入力受付待機は
60
+ Grok/Composerの場合だけこの判定を呼び、`GROK_SANDBOX_STARTUP_FAILED`で原因と未送信を返す。
61
+ 初回prompt付き起動と通常dispatchに適用され、他harnessの入力受付判定には適用しない。
62
+ promptなしの起動応答はPTYへの起動要求を示し、入力受付の確認は後続の送信時に行う。
63
+
64
+ hookパスのシンボリックリンク等を拒否する判断はGrok CLIが所有する。AitermはCLIが出した拒否を伝え、
65
+ hookのコピー、設定の置換、sandboxの解除は行わない。原因を設定の管理元で修正した後、対象sessionを
66
+ 閉じて起動し直す。検出の回帰試験は`test/grok-startup.test.mjs`に置く。
67
+
68
+ Grok/Composerのmanaged起動は公式`--trust`を渡し、指定cwdの信頼状態はGrok CLIが管理する。
69
+ `grokLaunchBlockingDialog`は信頼確認を入力受付から除外し、scrollbackのshell promptを取り違えない。
70
+ `grokTuiBusy`は応答中の表示だけを実行中の根拠にし、完了後も残る`[hooks: 成功/失敗]`を含めない。
71
+ これらのCLI固有判定は`src/harnesses/grok.ts`が所有し、共通処理は判定を呼び出す。
72
+
58
73
  ## Platform contract
59
74
 
60
75
  - macOS/Linux/WSL2: tmux。
package/docs/RELEASE.md CHANGED
@@ -39,6 +39,11 @@ Aitermのreleaseはこのrepositoryが所有する。`.github/workflows/product-
39
39
  公式npm packageを隔離またはglobal installし、変更に触れたharnessの起動、non-blocking dispatch、wait outcome、
40
40
  transcript回収、`pty_close`後の残骸ゼロを確認する。
41
41
 
42
+ Grok/Composerのsandbox起動拒否を変更した場合は、対象環境のCLIが拒否する設定で初回prompt付き起動と
43
+ 通常dispatchの未送信エラーを確認する。`GROK_SANDBOX_STARTUP_FAILED`がCLIの原因を保持し、入力受付の
44
+ timeoutや再送案内へ変わらないことを確認する。拒否を検証した結果は起動成功の証拠にはしない。
45
+ 設定の管理元による修理は別途確認し、smokeのためにsandbox解除やhookのコピーを行わない。
46
+
42
47
  ## 利用者の更新と巻き戻し
43
48
 
44
49
  global installはnpmの公開packageだけで完結する。
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aiterm-mcp",
3
- "version": "0.31.1",
3
+ "version": "0.31.2",
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": [