aiterm-mcp 0.20.1 → 0.20.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 +9 -6
- package/README.md +12 -9
- package/dist/core.js +78 -1
- package/dist/index.js +1 -0
- package/package.json +3 -3
package/README.ja.md
CHANGED
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
>
|
|
24
24
|
> *MCP = Model Context Protocol — Claude Code のようなツールが AI に機能を差し込むためのオープン標準。*
|
|
25
25
|
|
|
26
|
-
kitepon.devを運営する[クオ(@QLyun35332)](https://x.com/QLyun35332)が
|
|
26
|
+
[kitepon.dev](https://kitepon.dev/)を運営する[クオ(@QLyun35332)](https://x.com/QLyun35332)が
|
|
27
27
|
開発・メンテナンスしています。
|
|
28
28
|
|
|
29
29
|
## MCPクライアントへ導入
|
|
@@ -87,14 +87,17 @@ claude mcp add --scope user --transport stdio aiterm -- npx -y aiterm-mcp
|
|
|
87
87
|
}
|
|
88
88
|
```
|
|
89
89
|
|
|
90
|
-
|
|
91
|
-
|
|
90
|
+
**所有境界:** 本repositoryは永続PTYと外部agent実行レーンを所有します。製品横断の導入と
|
|
91
|
+
host統合は、kitepon.devの製品開発を支える内部基盤
|
|
92
|
+
[dotagents](https://github.com/kitepon-rgb/dotagents)が担当します。
|
|
92
93
|
|
|
93
94
|
**言葉でなく実測で:** このリポジトリ自身の 203 テストで、`pty_read` はコンテキストに載るトークンを生ログの **約 7.1 分の 1** に減らす。しかも pass/fail の判定は畳んでも残る。→ [組み込みシェルツールとの使い分け](#組み込みシェルツールとの使い分け)
|
|
94
95
|
|
|
95
96
|
13 ツール: 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 を新しい端末の中に起動し、`claude_turn`がdurable caller向けの構造化issue/recoveryを、`claude_approval`がmanaged Claudeの相関済み承認UI中継を、`diagnostics`が安全なfactory readinessを返す。バックエンドは **tmux** なので、MCP サーバや AI クライアントが再起動してもセッションは生き残る。
|
|
96
97
|
|
|
97
|
-
**v0.20.
|
|
98
|
+
**v0.20.3では、壊れた認証から複数のmanaged Claude/Fable sessionが同時にloginへ流れる問題を修理。**
|
|
99
|
+
新規Claude起動はPTY作成前にvendor所有の共有認証を検証し、正常な認証は複数sessionから並行・反復利用できる。
|
|
100
|
+
v0.20では、待たずに一度だけ観測する
|
|
98
101
|
`aiterm-wait --timeout 0` の未完了を、実際に待って終わらなかった`timeout`と区別し、
|
|
99
102
|
`running`(exit 5)で返すようにしました。v0.19系では相関済みmanaged Claude approval中継を追加し、
|
|
100
103
|
複数行shell配送を維持し、native Windowsのfactory diagnosticsを拡張しました。
|
|
@@ -151,7 +154,7 @@ $ aiterm-wait --session codex1 --cursor <event_cursor> # exit 0=done / 3=timeo
|
|
|
151
154
|
| `grok_agent` | Grok Build(xAI、既定`grok-4.5`、`model?`で上書き) | `prompt?`, `model?`, `reasoning_effort?`は非対応(指定時は明示エラー), `cwd?`, `session_name?` |
|
|
152
155
|
| `composer_agent` | Grok Build(xAI、既定`grok-composer-2.5-fast`、`model?`で上書き) | `prompt?`, `model?`, `reasoning_effort?`は非対応(指定時は明示エラー), `cwd?`, `session_name?` |
|
|
153
156
|
|
|
154
|
-
各ベンダーの CLI が導入・認証済みであること(`claude_agent` は `claude`、`codex_agent` は `codex`、Grok 系は `grok`)。バイナリは `CLAUDE_BIN` / `CODEX_BIN` / `GROK_BIN`、各既定path、`PATH` の順で解決する。CLI不在・不正なmodel/effort・実在しない`cwd`はsession作成前に失敗し、残骸を残さない。Claudeは通常settingsを継承しないlaunch専用settingsとStop hookを使い、本文なしeventとowner-only bounded resultを分離する。`pty_read({ agent_transcript:true })`はdigestとbyte数を検証したresultだけを返し、Claude private transcriptを読まない。後着resultは同じsessionからprompt再送なしで回収できる。managed Claudeのactive turn中はC-c以外の`pty_key`と素送信を拒否する。Claudeが`Do you want to proceed?`を表示したら、`claude_approval(action:"inspect", ...)`で画面digestを取得し、表示内容を判断してから、そのdigestと`approve_once`または`deny`を`respond`へ渡す。同じoperation・同じ画面が維持されている時だけ入力し、任意文字列や恒久許可選択肢は中継しない。中断は`C-c`、解除は`pty_close`。
|
|
157
|
+
各ベンダーの CLI が導入・認証済みであること(`claude_agent` は `claude`、`codex_agent` は `codex`、Grok 系は `grok`)。バイナリは `CLAUDE_BIN` / `CODEX_BIN` / `GROK_BIN`、各既定path、`PATH` の順で解決する。CLI不在・不正なmodel/effort・実在しない`cwd`はsession作成前に失敗し、残骸を残さない。Claudeはさらに、PTY作成前に同じCLIの`auth status --json`が`loggedIn:true`を返すことを要求する。未認証・malformed・失敗exit・timeoutは残骸ゼロで失敗し、正常なvendor所有の共有認証は複数sessionから利用する。managed Claudeへのexact `/login`・`/logout`は通常dispatchとforce送信の双方で副作用前に拒否するため、認証は通常端末で一度だけ修理する。Claudeは通常settingsを継承しないlaunch専用settingsとStop hookを使い、本文なしeventとowner-only bounded resultを分離する。`pty_read({ agent_transcript:true })`はdigestとbyte数を検証したresultだけを返し、Claude private transcriptを読まない。後着resultは同じsessionからprompt再送なしで回収できる。managed Claudeのactive turn中はC-c以外の`pty_key`と素送信を拒否する。Claudeが`Do you want to proceed?`を表示したら、`claude_approval(action:"inspect", ...)`で画面digestを取得し、表示内容を判断してから、そのdigestと`approve_once`または`deny`を`respond`へ渡す。同じoperation・同じ画面が維持されている時だけ入力し、任意文字列や恒久許可選択肢は中継しない。中断は`C-c`、解除は`pty_close`。
|
|
155
158
|
|
|
156
159
|
エージェント間の隠れたプロトコルは無い。起動したClaude/Codex/Grok/Composerは利用者がattachできるもう1本の永続sessionであり、MCPクライアントが通常のPTY操作で駆動する。
|
|
157
160
|
|
|
@@ -353,7 +356,7 @@ consumer は `aiterm-runtime-errors snapshot` を読み、durable ingestion 後
|
|
|
353
356
|
| `grok_agent` | Grok Build(xAI、既定`grok-4.5`、`model?`で上書き) | `prompt?`, `model?`, `reasoning_effort?`は非対応(指定時は明示エラー), `cwd?`, `session_name?` |
|
|
354
357
|
| `composer_agent` | Grok Build(xAI、既定`grok-composer-2.5-fast`、`model?`で上書き) | `prompt?`, `model?`, `reasoning_effort?`は非対応(指定時は明示エラー), `cwd?`, `session_name?` |
|
|
355
358
|
|
|
356
|
-
対応するCLI(`claude` / `codex` / `grok`)の導入・認証が必要。解決順は`CLAUDE_BIN` / `CODEX_BIN` / `GROK_BIN`、既定path、`PATH`。前提違反はsession作成前に明示失敗する。4 launcherすべてが同じ非ブロックdispatch契約を使い、Claude/Codexの初回promptはready gate経由で送信される。Claudeはisolated managed settingsとhook-captured resultを使い、private transcriptへ依存しない。Claude/Codex/Grok/Composerのlive smokeはすべてgreenであり、fixtureによる検証とは区別して記録する。
|
|
359
|
+
対応するCLI(`claude` / `codex` / `grok`)の導入・認証が必要。解決順は`CLAUDE_BIN` / `CODEX_BIN` / `GROK_BIN`、既定path、`PATH`。前提違反はsession作成前に明示失敗する。ClaudeはPTY作成前に構造化認証statusも検証し、managed session内の`/login`・`/logout`を拒否する。4 launcherすべてが同じ非ブロックdispatch契約を使い、Claude/Codexの初回promptはready gate経由で送信される。Claudeはisolated managed settingsとhook-captured resultを使い、private transcriptへ依存しない。Claude/Codex/Grok/Composerのlive smokeはすべてgreenであり、fixtureによる検証とは区別して記録する。
|
|
357
360
|
|
|
358
361
|
エージェントの回答が画面 tailより長ければ、対話callerは`pty_read({ agent_transcript:true })`で再promptなしに全文回収する。Claudeはmanaged Stop hookがowner-only resultへ保存した本文をdigest/byte数で検証して返し、private transcriptを読まない。durable machine callerは`claude_turn`を使う。`issue`は一度だけ送信し、`recover`は決して再送せず、`pending`を破損やidentity不一致と区別する。検証済みの`completed`だけがexact `raw_output`を持ち、`unknown`は未dispatchと帰属不能を区別する。不一致・破損は成功statusへ丸めずtool errorのままにする。IDなしの対話turnも匿名markerで直列化するため、現在Stop待ちの間に古い回答を返さない。CodexはStop hookの`turn_id`で構造化transcriptへjoinし、Grok/Composerは最後の実user行より後ろのassistant行を採る。不在・非agent・抽出不能は明示エラー。
|
|
359
362
|
|
package/README.md
CHANGED
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
>
|
|
24
24
|
> *MCP = Model Context Protocol — the open standard that lets tools like Claude Code plug capabilities into an AI.*
|
|
25
25
|
|
|
26
|
-
Built and maintained by [Quo](https://x.com/QLyun35332) at kitepon.dev.
|
|
26
|
+
Built and maintained by [Quo](https://x.com/QLyun35332) at [kitepon.dev](https://kitepon.dev/en).
|
|
27
27
|
|
|
28
28
|
## Install in your MCP client
|
|
29
29
|
|
|
@@ -86,17 +86,20 @@ Save this as `.cursor/mcp.json` for the project, or `~/.cursor/mcp.json` globall
|
|
|
86
86
|
}
|
|
87
87
|
```
|
|
88
88
|
|
|
89
|
-
**
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
89
|
+
**Ownership boundary:** this repository owns the persistent PTY and external-agent
|
|
90
|
+
execution lane. Cross-product installation and host integration are handled by
|
|
91
|
+
[dotagents](https://github.com/kitepon-rgb/dotagents), the internal development
|
|
92
|
+
toolchain behind kitepon.dev's products.
|
|
93
93
|
|
|
94
94
|
**Measured, not claimed:** on this repo's own 203-test suite, 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)
|
|
95
95
|
|
|
96
96
|
Thirteen 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, `claude_turn` for durable structured issue/recovery, `claude_approval` for correlated managed-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.
|
|
97
97
|
|
|
98
|
-
**v0.20.
|
|
99
|
-
|
|
98
|
+
**v0.20.3 prevents concurrent managed Claude/Fable sessions from turning one broken
|
|
99
|
+
login into many competing login flows.** Every new Claude launch verifies the
|
|
100
|
+
vendor-owned shared credential store before creating a PTY, while healthy credentials
|
|
101
|
+
remain reusable across concurrent and repeated sessions. The v0.20 line also distinguishes
|
|
102
|
+
a non-blocking `aiterm-wait --timeout 0` observation (`running`, exit 5) from a real timed-out
|
|
100
103
|
wait. The v0.19 line added the correlated managed-Claude approval relay,
|
|
101
104
|
preserved multiline shell delivery, and extended factory diagnostics on native
|
|
102
105
|
Windows. As of v0.16/0.17 a parent agent never blocks on aiterm:
|
|
@@ -164,7 +167,7 @@ One call per model, so the tool name itself tells you which model you get:
|
|
|
164
167
|
| `grok_agent` | Grok Build, model `grok-4.5` by default (`model?` overrides) (xAI) | `prompt?`, `model?`, `reasoning_effort?` unsupported (an explicit value is an error; Grok CLI `--effort` is headless-only), `cwd?`, `session_name?` |
|
|
165
168
|
| `composer_agent` | Grok Build, model `grok-composer-2.5-fast` by default (`model?` overrides) (xAI) | `prompt?`, `model?`, `reasoning_effort?` unsupported (an explicit value is an error), `cwd?`, `session_name?` |
|
|
166
169
|
|
|
167
|
-
The vendor CLI must be installed and authenticated (`claude` for `claude_agent`; `codex` for `codex_agent`; `grok` for both Grok tools). aiterm resolves the binary via `CLAUDE_BIN` / `CODEX_BIN` / `GROK_BIN`, then `~/.local/bin/claude` / `~/.local/bin/codex` / `~/.grok/bin/grok`, then `PATH`. Prerequisites are checked **before** a session exists: empty `model` values and unsupported effort values are rejected up front; a missing CLI binary or a nonexistent `cwd` fails for all four.
|
|
170
|
+
The vendor CLI must be installed and authenticated (`claude` for `claude_agent`; `codex` for `codex_agent`; `grok` for both Grok tools). aiterm resolves the binary via `CLAUDE_BIN` / `CODEX_BIN` / `GROK_BIN`, then `~/.local/bin/claude` / `~/.local/bin/codex` / `~/.grok/bin/grok`, then `PATH`. Prerequisites are checked **before** a session exists: empty `model` values and unsupported effort values are rejected up front; a missing CLI binary or a nonexistent `cwd` fails for all four. Before creating a Claude session, aiterm also requires a successful structured `claude auth status --json` result with `loggedIn: true`; unavailable, malformed, or failed authentication leaves **zero leftover session**. Claude sessions share the vendor-owned credential store rather than copying credentials per launch, so multiple sessions can reuse one healthy login. Managed Claude rejects exact `/login` and `/logout` dispatches, including forced sends: repair authentication once in a normal terminal, then relaunch any stale unauthenticated sessions. Claude and Codex launchers forward `model` and `reasoning_effort` through their vendor CLI's public flags; Grok/Composer reject `reasoning_effort` because it is headless-only. Pass an absolute path for `cwd` — `~` is not expanded. Durable callers can make a promptless Claude launch exactly replayable by passing an explicit `session_name` and a `launch_operation_id` formatted as `sha256:<64 lowercase hex>`. Repeating the identical launch returns the same structured session receipt without starting the CLI twice; a different correlation ID or launch argument for that session fails explicitly. Claude uses launch-local managed settings containing only aiterm's Stop hook: normal user/project/local hooks are not inherited, the hook event contains no answer body, and the bounded owner-only result is returned by `pty_read({ agent_transcript:true })` without reading Claude's private transcript. A late result remains recoverable from the same session without re-sending the prompt. While a managed Claude turn is active, raw sends and non-interrupt keys are rejected. If Claude displays `Do you want to proceed?`, call `claude_approval(action:"inspect", ...)`, decide from the visible prompt, then call `respond` with the returned digest and either `approve_once` or `deny`. The response is accepted only while the same operation and screen digest remain current; arbitrary text and persistent-allow choices are never relayed. Use `pty_key("C-c")` to interrupt and `pty_close` to abandon the session. For unconstrained manual key-by-key driving, open a plain `pty_open` session and start the vendor CLI yourself. Codex uses a managed `CODEX_HOME`; Grok/Composer isolate their managed homes and pass validated OAuth state through `GROK_AUTH_PATH`. Before the first unbound dispatch, aiterm waits for the vendor TUI's input prompt and fails before sending if it is not ready. Managed completion requires POSIX filesystem semantics (Linux, WSL2, macOS).
|
|
168
171
|
|
|
169
172
|
The managed Codex home links authentication, privately snapshots `config.toml` and `agents/*.toml` custom-role definitions, and keeps sessions/caches isolated. A symlinked role definition is resolved into a regular-file snapshot rather than shared with the source home.
|
|
170
173
|
|
|
@@ -370,7 +373,7 @@ Each launcher starts a specific vendor's interactive coding-agent TUI inside a f
|
|
|
370
373
|
| `grok_agent` | Grok Build, model `grok-4.5` by default (`model?` overrides) (xAI) | `prompt?`, `model?`, `reasoning_effort?` unsupported (an explicit value is an error; Grok CLI `--effort` is headless-only), `cwd?`, `session_name?` |
|
|
371
374
|
| `composer_agent` | Grok Build, model `grok-composer-2.5-fast` by default (`model?` overrides) (xAI) | `prompt?`, `model?`, `reasoning_effort?` unsupported (an explicit value is an error), `cwd?`, `session_name?` |
|
|
372
375
|
|
|
373
|
-
The vendor CLI must be installed and authenticated (`claude` for `claude_agent`; `codex` for `codex_agent`; `grok` for both Grok tools). Binary resolution uses `CLAUDE_BIN` / `CODEX_BIN` / `GROK_BIN`, then each documented default location, then `PATH`. Missing binaries, invalid model/effort values, and nonexistent `cwd` fail before a session is created. All four share the same non-blocking dispatch contract for follow-up turns; `claude_agent`/`codex_agent` submit an initial `prompt` through the ready gate. Claude uses isolated managed settings and a hook-captured bounded result rather than private transcript access. Claude, Codex, Grok, and Composer live smokes are green; fixture coverage remains a separate claim. Native Windows can launch agents but managed completion is not supported yet.
|
|
376
|
+
The vendor CLI must be installed and authenticated (`claude` for `claude_agent`; `codex` for `codex_agent`; `grok` for both Grok tools). Binary resolution uses `CLAUDE_BIN` / `CODEX_BIN` / `GROK_BIN`, then each documented default location, then `PATH`. Missing binaries, invalid model/effort values, and nonexistent `cwd` fail before a session is created. Claude additionally requires a structured healthy authentication status before any PTY exists, and managed Claude rejects `/login` and `/logout`; repair authentication once in a normal terminal. All four share the same non-blocking dispatch contract for follow-up turns; `claude_agent`/`codex_agent` submit an initial `prompt` through the ready gate. Claude uses isolated managed settings and a hook-captured bounded result rather than private transcript access. Claude, Codex, Grok, and Composer live smokes are green; fixture coverage remains a separate claim. Native Windows can launch agents but managed completion is not supported yet.
|
|
374
377
|
|
|
375
378
|
When an agent's answer is longer than the on-screen tail (pane height ≈ 24 lines), callers recover it in full with `pty_read({ agent_transcript: true })`. It returns the most recently completed turn's final assistant message in plain text with no re-prompting. Claude reads the bounded owner-only result captured by the managed Stop hook and verifies its digest/byte count; it never reads Claude's private transcript. Durable machine callers should use `claude_turn`: `issue` sends once, `recover` never sends, `pending` is distinct from unsafe or malformed state, and only `completed` carries the exact verified `raw_output`. `unknown` distinguishes `operation_not_found` from a receipt whose result can no longer be attributed. Mismatch and corruption remain tool errors rather than being folded into a successful status. ID-less interactive Claude turns are still serialized by an anonymous marker, so an older answer is not returned while the current Stop is pending. Codex joins its structured transcript on the Stop hook `turn_id`; Grok/Composer take the assistant rows after the last real user row. A missing result/transcript, a non-agent session, or an unextractable message is an explicit error, never a silent empty.
|
|
376
379
|
|
package/dist/core.js
CHANGED
|
@@ -945,12 +945,23 @@ function prepareSendText(text, o) {
|
|
|
945
945
|
assertSendTextSize(text);
|
|
946
946
|
return text;
|
|
947
947
|
}
|
|
948
|
+
function assertManagedClaudeCredentialCommandNotSent(name, text) {
|
|
949
|
+
const meta = tryLoadAgentMetadata(name);
|
|
950
|
+
if (meta?.kind !== "claude")
|
|
951
|
+
return;
|
|
952
|
+
const normalized = text.replace(PASTE_MARKERS_RE, "").replace(ANSI_RE, "").replace(CTRL_RE, "").trim();
|
|
953
|
+
if (!/^\/(?:login|logout)$/i.test(normalized))
|
|
954
|
+
return;
|
|
955
|
+
throw new AitermError("managed Claude sessionでは共有認証を変更する /login と /logout を送信できません。" +
|
|
956
|
+
"認証操作は通常端末で一度だけ行い、必要ならこのsessionをcloseして起動し直してください。", 2);
|
|
957
|
+
}
|
|
948
958
|
export function send(name, text, o = {}) {
|
|
949
959
|
assertSessionName(name);
|
|
950
960
|
const enter = o.enter ?? true;
|
|
951
961
|
if (!sessionExists(name))
|
|
952
962
|
throw new AitermError(`session '${name}' が無い(open してください)`, 2);
|
|
953
963
|
assertInitialPromptNotPendingForSend(name, !!o.force);
|
|
964
|
+
assertManagedClaudeCredentialCommandNotSent(name, text);
|
|
954
965
|
text = prepareSendText(text, o);
|
|
955
966
|
if (o.mark) {
|
|
956
967
|
// mark の sentinel は POSIX シェル構文。前面が fish/csh/tcsh 等の非 POSIX 対話シェルだと "$?" が
|
|
@@ -2687,6 +2698,33 @@ function readClaudeResultText(meta, done, operationId) {
|
|
|
2687
2698
|
}
|
|
2688
2699
|
return result.text;
|
|
2689
2700
|
}
|
|
2701
|
+
const CLAUDE_COMPLETION_MARKER_SETTLE_TIMEOUT_MS = 1_000;
|
|
2702
|
+
function claudeCompletionWasPublishedAfterMarker(meta, marker) {
|
|
2703
|
+
let markerStat;
|
|
2704
|
+
let resultStat;
|
|
2705
|
+
try {
|
|
2706
|
+
markerStat = fs.lstatSync(agentClaudeOperationPath(meta.aiterm_session, meta.launch_id));
|
|
2707
|
+
resultStat = fs.lstatSync(meta.result_file ?? "");
|
|
2708
|
+
}
|
|
2709
|
+
catch {
|
|
2710
|
+
return false;
|
|
2711
|
+
}
|
|
2712
|
+
if (resultStat.mtimeMs < markerStat.mtimeMs)
|
|
2713
|
+
return false;
|
|
2714
|
+
const done = latestAgentDoneEvent(meta, marker.operationId);
|
|
2715
|
+
return done !== null && done.operation_id === marker.operationId;
|
|
2716
|
+
}
|
|
2717
|
+
async function settlePublishedClaudeCompletionMarker(meta, marker) {
|
|
2718
|
+
if (!claudeCompletionWasPublishedAfterMarker(meta, marker))
|
|
2719
|
+
return marker;
|
|
2720
|
+
const deadline = performance.now() + CLAUDE_COMPLETION_MARKER_SETTLE_TIMEOUT_MS;
|
|
2721
|
+
let active = marker;
|
|
2722
|
+
while (active && performance.now() < deadline) {
|
|
2723
|
+
await sleep(AGENT_DONE_POLL_MS);
|
|
2724
|
+
active = readClaudeOperationMarker(meta);
|
|
2725
|
+
}
|
|
2726
|
+
return active;
|
|
2727
|
+
}
|
|
2690
2728
|
/** agent vendor の構造化 transcript から直近完了ターンの最終回答を読む。 */
|
|
2691
2729
|
export async function readAgentTranscript(name, o = {}) {
|
|
2692
2730
|
const meta = loadAgentMetadata(name);
|
|
@@ -2695,7 +2733,9 @@ export async function readAgentTranscript(name, o = {}) {
|
|
|
2695
2733
|
throw new AitermError("operation_id付き回収はClaude agent sessionだけで使用できます", 2);
|
|
2696
2734
|
}
|
|
2697
2735
|
if (meta.kind === "claude") {
|
|
2698
|
-
|
|
2736
|
+
let active = readClaudeOperationMarker(meta);
|
|
2737
|
+
if (active)
|
|
2738
|
+
active = await settlePublishedClaudeCompletionMarker(meta, active);
|
|
2699
2739
|
if (active) {
|
|
2700
2740
|
const label = active.operationId ? `operation ${active.operationId}` : "operation_idなしのClaude turn";
|
|
2701
2741
|
throw new AitermError(`${label} はまだ完了していません。Stop完了後に同じsessionから再取得してください。${agentWaitGuide(name)}`, 2);
|
|
@@ -3189,6 +3229,7 @@ export function isAgentSession(name) {
|
|
|
3189
3229
|
export async function dispatchAgentTurn(name, text, o = {}) {
|
|
3190
3230
|
assertSessionName(name);
|
|
3191
3231
|
const meta = loadAgentMetadata(name);
|
|
3232
|
+
assertManagedClaudeCredentialCommandNotSent(name, text);
|
|
3192
3233
|
const operationId = o.operation_id == null ? null : validateOperationId(o.operation_id);
|
|
3193
3234
|
if (operationId && meta.kind !== "claude") {
|
|
3194
3235
|
throw new AitermError("operation_id はClaude agent sessionだけで使用できます", 2);
|
|
@@ -3326,6 +3367,40 @@ function resolveAgentBin(kind) {
|
|
|
3326
3367
|
}
|
|
3327
3368
|
return null;
|
|
3328
3369
|
}
|
|
3370
|
+
const CLAUDE_AUTH_STATUS_TIMEOUT_MS = 5_000;
|
|
3371
|
+
function assertClaudeAuthenticationReady(bin) {
|
|
3372
|
+
const result = spawnSync(bin, ["auth", "status", "--json"], {
|
|
3373
|
+
encoding: "utf8",
|
|
3374
|
+
timeout: CLAUDE_AUTH_STATUS_TIMEOUT_MS,
|
|
3375
|
+
maxBuffer: 64 * 1024,
|
|
3376
|
+
});
|
|
3377
|
+
let status = null;
|
|
3378
|
+
try {
|
|
3379
|
+
status = JSON.parse((result.stdout ?? "").trim());
|
|
3380
|
+
}
|
|
3381
|
+
catch {
|
|
3382
|
+
status = null;
|
|
3383
|
+
}
|
|
3384
|
+
if (result.error == null &&
|
|
3385
|
+
result.status === 0 &&
|
|
3386
|
+
status !== null &&
|
|
3387
|
+
typeof status === "object" &&
|
|
3388
|
+
!Array.isArray(status) &&
|
|
3389
|
+
status.loggedIn === true) {
|
|
3390
|
+
return;
|
|
3391
|
+
}
|
|
3392
|
+
if (status !== null &&
|
|
3393
|
+
typeof status === "object" &&
|
|
3394
|
+
!Array.isArray(status) &&
|
|
3395
|
+
status.loggedIn === false) {
|
|
3396
|
+
throw new AitermError("Claude Codeの認証を利用できません。sessionは作成していません。" +
|
|
3397
|
+
"通常端末で `claude doctor` を実行し、Keychain/credential storeを直してから一度だけ `claude auth login` を実行してください。" +
|
|
3398
|
+
"managed Claude session内で /login を繰り返さないでください。", 2);
|
|
3399
|
+
}
|
|
3400
|
+
const timedOut = result.error && result.error.code === "ETIMEDOUT";
|
|
3401
|
+
throw new AitermError(`Claude Codeの認証状態を起動前に確認できません${timedOut ? "(5秒でtimeout)" : ""}。sessionは作成していません。` +
|
|
3402
|
+
"`claude auth status --json` と `claude doctor` が成功することを通常端末で確認してください。", 2);
|
|
3403
|
+
}
|
|
3329
3404
|
function isUsableExecutableFile(candidate) {
|
|
3330
3405
|
try {
|
|
3331
3406
|
if (!fs.statSync(candidate).isFile())
|
|
@@ -3587,6 +3662,8 @@ export function openAgent(kind, opts = {}) {
|
|
|
3587
3662
|
requireMatchingClaudeLaunch(opts.session_name, launchOperationId, launchRequestDigest);
|
|
3588
3663
|
return existingAgentLaunchResult("claude", opts.session_name, model, effort);
|
|
3589
3664
|
}
|
|
3665
|
+
if (kind === "claude")
|
|
3666
|
+
assertClaudeAuthenticationReady(bin);
|
|
3590
3667
|
// Windows は起動コマンドが WSL 内 bash で走る(tmux ブリッジ)。bin/cwd を /mnt/c/... 形へ変換して
|
|
3591
3668
|
// 渡す(ログの toWslPath と対称・A1)。前提: Windows 側に CLI を導入(resolveAgentBin が Windows
|
|
3592
3669
|
// パスで解決)。toWslPath は session を作る前に呼ぶ=変換失敗(非ドライブパス)で残骸 session を残さない。
|
package/dist/index.js
CHANGED
|
@@ -483,6 +483,7 @@ function registerAgentTool(toolName, kind, desc) {
|
|
|
483
483
|
}
|
|
484
484
|
registerAgentTool("claude_agent", "claude", "【Claude Code (Anthropic)】の対話エージェントTUIを永続端末に起動する。`claude -p`ではなく、" +
|
|
485
485
|
"同じ利用者可視sessionへpty_sendで継続入力する。常にmanaged(isolated settingsのStop hook)で起動する。" +
|
|
486
|
+
"起動前に共有認証を構造化確認し、未認証ならsessionを作らない。managed session内の/login・/logoutは拒否する。" +
|
|
486
487
|
agentCompletionDesc +
|
|
487
488
|
"Claude の durable turn は claude_turn でも回収できる。");
|
|
488
489
|
registerAgentTool("codex_agent", "codex", "【Codex (OpenAI)】の対話エージェント TUI を永続端末に起動する。実装・レビュー・調査を対話で回す。" +
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aiterm-mcp",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.3",
|
|
4
4
|
"mcpName": "io.github.kitepon-rgb/aiterm-mcp",
|
|
5
5
|
"description": "Persistent tmux terminal MCP that lets Claude Code drive Codex CLI's interactive TUI, including slash commands and $imagegen. Also runs durable PTY sessions for SSH, containers, REPLs, and coding agents.",
|
|
6
6
|
"keywords": [
|
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
],
|
|
27
27
|
"license": "MIT",
|
|
28
28
|
"author": {
|
|
29
|
-
"name": "Quo / クオ
|
|
30
|
-
"url": "https://
|
|
29
|
+
"name": "Quo / クオ at kitepon.dev",
|
|
30
|
+
"url": "https://kitepon.dev/"
|
|
31
31
|
},
|
|
32
32
|
"repository": {
|
|
33
33
|
"type": "git",
|