aiterm-mcp 0.25.1 → 0.25.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.ja.md CHANGED
@@ -96,6 +96,11 @@ host統合は、kitepon.devの製品開発を支える内部基盤
96
96
 
97
97
  14 ツール: 6 つの **PTY ツール**(`pty_open` / `pty_send` / `pty_read` / `pty_key` / `pty_close` / `pty_list`)で 1 本の永続端末を開き・操作し・読む。加えて 4 つの **エージェント起動ツール**(`claude_agent` / `codex_agent` / `grok_agent` / `composer_agent`)が別のコーディングエージェントの TUI を新しい端末の中に起動し、`agent_configure`が起動中のClaude/Codex/Grok/Composerのmodel・effortを再起動なしで変更し、`claude_turn`がdurable caller向けの構造化issue/recoveryを、`claude_approval`が相関済みClaude承認UI中継を、`diagnostics`が安全なfactory readinessを返す。バックエンドは **tmux** なので、MCP サーバや AI クライアントが再起動してもセッションは生き残る。
98
98
 
99
+ **v0.25.2ではGrok 4.6を含む同一sessionの連続設定変更を安定化。** Grok Build 1.0.3で
100
+ `/model`の成功通知が再描画により消えても、変更前には無かった要求model/effortが常駐footerへ現れた
101
+ 最終状態を確認する。caller側のretry、再起動、失敗の成功丸めは不要で、`grok-4.6`は従来どおり
102
+ 明示`model`としてlive catalog照合後に起動・変更できる。
103
+
99
104
  **v0.25.0ではGrok/Composerへ共通launcher制御を同等実装。** 起動時`reasoning_effort`、
100
105
  `write_scope:"read-only"`の`--sandbox read-only`強制、`agent_configure`による同一session内の
101
106
  model/effort変更に対応した。明示したGrok/Composer modelとComposer既定modelはPTY作成前に
package/README.md CHANGED
@@ -96,6 +96,11 @@ toolchain behind kitepon.dev's products.
96
96
 
97
97
  Fourteen tools: six **PTY tools** — `pty_open` / `pty_send` / `pty_read` / `pty_key` / `pty_close` / `pty_list` — to open, drive, and read one persistent terminal, four **agent launchers** — `claude_agent` / `codex_agent` / `grok_agent` / `composer_agent` — that each start another coding agent's TUI inside a fresh one, `agent_configure` to change a running Claude/Codex/Grok/Composer session's model and effort without restarting it, `claude_turn` for durable structured issue/recovery, `claude_approval` for correlated Claude approval prompts, and `diagnostics` for safe factory readiness. The backend is **tmux**, so sessions survive even if the MCP server or the AI client restarts.
98
98
 
99
+ **v0.25.2 stabilizes repeated in-place configuration changes, including Grok 4.6.** If Grok Build
100
+ 1.0.3 redraws before its `/model` success notice can be observed, aiterm confirms the requested model/effort
101
+ from the persistent footer when that state was absent before the command. Callers do not retry, restart, or
102
+ round a failure into success; explicit `grok-4.6` launch and configuration still pass the live catalog check.
103
+
99
104
  **v0.25.0 gives Grok and Composer the same shared launcher controls.** Their launchers now pass
100
105
  `reasoning_effort`, enforce `write_scope: "read-only"` with `--sandbox read-only`, and support
101
106
  in-place model/effort changes through `agent_configure`. Before creating a PTY, aiterm checks an
package/dist/core.js CHANGED
@@ -1625,7 +1625,11 @@ function resolveAndValidateGrokAuth(srcHome) {
1625
1625
  try {
1626
1626
  fd = fs.openSync(authPath, fs.constants.O_RDONLY | fs.constants.O_NOFOLLOW | fs.constants.O_NONBLOCK);
1627
1627
  const st = fs.fstatSync(fd);
1628
- if (!st.isFile() || st.nlink !== 1 || st.uid !== currentUid() || (st.mode & 0o077) !== 0 || st.size > GROK_AUTH_MAX_BYTES) {
1628
+ // Windows の fs.Stats.mode は POSIX permission bit を持たず、常に 666/777 相当を報告する
1629
+ // (NTFS ACL は別体系)。currentUid と同じ既知制約の明示的受容として、Windows では
1630
+ // group/other bit 検証を行わない。isFile・nlink・owner・size・O_NOFOLLOW・realpath 検証は共通に維持する。
1631
+ const worldAccessible = !isWin && (st.mode & 0o077) !== 0;
1632
+ if (!st.isFile() || st.nlink !== 1 || st.uid !== currentUid() || worldAccessible || st.size > GROK_AUTH_MAX_BYTES) {
1629
1633
  throw new AitermError("Grok 認証正本の安全検証に失敗しました", 2);
1630
1634
  }
1631
1635
  const value = JSON.parse(fs.readFileSync(fd, "utf8"));
@@ -1643,7 +1647,8 @@ function resolveAndValidateGrokAuth(srcHome) {
1643
1647
  // /tmp のような root 所有 + sticky の共有 directory は、本人所有の private な
1644
1648
  // 直下 directory を他 UID が rename/unlink できないため許可する。sticky 無しの
1645
1649
  // group/other writable 祖先は path swap が可能なので従来どおり拒否する。
1646
- const writableByOthers = (dirSt.mode & 0o022) !== 0;
1650
+ // Windows は directory も mode bit を持たない(常に 777 相当)ため、同じ受容で除外する。
1651
+ const writableByOthers = !isWin && (dirSt.mode & 0o022) !== 0;
1647
1652
  const protectedSharedRoot = dirSt.uid === 0 && (dirSt.mode & 0o1000) !== 0;
1648
1653
  if (!dirSt.isDirectory()
1649
1654
  || dirSt.isSymbolicLink()
@@ -3629,8 +3634,24 @@ function lineCounts(screen) {
3629
3634
  }
3630
3635
  return counts;
3631
3636
  }
3632
- async function waitForGrokConfigurationResult(name, before, timeoutMs = 3_000) {
3637
+ function grokFooterHasConfiguration(screen, model, effort) {
3638
+ const modelMatch = model?.match(/^grok-(\d+(?:\.\d+)*)$/) ?? null;
3639
+ if (model && !modelMatch)
3640
+ return false;
3641
+ const modelLabel = modelMatch ? `Grok ${modelMatch[1]}` : null;
3642
+ return screen.split("\n").some((line) => {
3643
+ if (!line.includes("·"))
3644
+ return false;
3645
+ if (modelLabel && !line.includes(`${modelLabel} (`))
3646
+ return false;
3647
+ if (effort && !line.includes(`(${effort})`))
3648
+ return false;
3649
+ return modelLabel !== null || effort !== null;
3650
+ });
3651
+ }
3652
+ async function waitForGrokConfigurationResult(name, before, model, effort, timeoutMs = 3_000) {
3633
3653
  const beforeCounts = lineCounts(before);
3654
+ const footerAlreadyMatched = grokFooterHasConfiguration(before, model, effort);
3634
3655
  const deadline = performance.now() + timeoutMs;
3635
3656
  do {
3636
3657
  const screen = captureScreen(name, AGENT_TUI_READY_LINES);
@@ -3647,6 +3668,10 @@ async function waitForGrokConfigurationResult(name, before, timeoutMs = 3_000) {
3647
3668
  throw new AitermError(`Grokの設定変更に失敗しました: ${error}`, 2);
3648
3669
  if (added.some((line) => /^(?:Switched to |✓?\s*Default model:)/.test(line)))
3649
3670
  return;
3671
+ // Grok Build 1.0.3では成功通知が次の再描画で消えることがある。変更前には無かった
3672
+ // target model/effortが常駐footerへ現れた場合も、vendor自身の最終状態として受理する。
3673
+ if (!footerAlreadyMatched && grokFooterHasConfiguration(screen, model, effort))
3674
+ return;
3650
3675
  await sleep(100);
3651
3676
  } while (performance.now() < deadline);
3652
3677
  throw new AitermError(`${agentLabel(loadAgentMetadata(name).kind)} の設定変更完了を確認できません`, 2);
@@ -3740,7 +3765,7 @@ export async function configureAgent(name, opts) {
3740
3765
  : `/effort ${effort}`;
3741
3766
  const before = captureScreen(name, AGENT_TUI_READY_LINES);
3742
3767
  await sendAgentPromptText(name, command);
3743
- await waitForGrokConfigurationResult(name, before);
3768
+ await waitForGrokConfigurationResult(name, before, model, effort);
3744
3769
  return {
3745
3770
  schema: "aiterm.agent-configure-result.v1",
3746
3771
  session_id: name,
@@ -4214,8 +4239,13 @@ function agentEnvPrefix(meta, sid, envVars = []) {
4214
4239
  if (meta.kind === "codex") {
4215
4240
  return common.join(" ") + " ";
4216
4241
  }
4242
+ // Windows では起動コマンドが WSL 内 bash で走るため、検証済み auth 正本の Windows ドライブパスを
4243
+ // bin/cwd と同じく /mnt/c/... 形へ変換して渡す。変換しないと WSL 側 grok が正本を開けず接続で停止する。
4244
+ const grokAuthForCmd = meta.grok_auth_path && isWin && isWindowsDrivePath(meta.grok_auth_path)
4245
+ ? toWslPath(meta.grok_auth_path)
4246
+ : meta.grok_auth_path;
4217
4247
  return [
4218
- ...(meta.grok_auth_path ? [`GROK_AUTH_PATH=${shq(meta.grok_auth_path)}`] : []),
4248
+ ...(grokAuthForCmd ? [`GROK_AUTH_PATH=${shq(grokAuthForCmd)}`] : []),
4219
4249
  "GROK_DISABLE_AUTOUPDATER=1",
4220
4250
  ...common,
4221
4251
  ].join(" ") + " ";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aiterm-mcp",
3
- "version": "0.25.1",
3
+ "version": "0.25.3",
4
4
  "mcpName": "io.github.kitepon/aiterm-mcp",
5
5
  "description": "Persistent tmux terminal MCP for launching and driving Claude, Codex, Grok, or Composer from any MCP client, cross-vendor or same-vendor. Also runs durable PTY sessions for SSH, containers, and REPLs.",
6
6
  "keywords": [