aiterm-mcp 0.29.9 → 0.29.11
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 +16 -1
- package/README.ja.md +6 -5
- package/README.md +6 -5
- package/dist/core.js +41 -3
- package/dist/harnesses/grok.js +5 -4
- package/dist/index.js +65 -3
- package/docs/DESIGN.md +1 -0
- package/docs/RELEASE.md +2 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.29.11] - 2026-09-01
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Add `agent_steer` to inject an additional message into a running Codex or Grok turn. Idle sessions return `delivery=idle` without sending text so callers can queue a new turn explicitly.
|
|
15
|
+
|
|
16
|
+
## [0.29.10] - 2026-08-31
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- Return `pty_read(agent_transcript:true)` answer text separately as `aiterm.pty-read-result.v1` structured content while preserving the existing human-readable diagnostic suffix.
|
|
21
|
+
- For Grok and Composer, return only the last non-empty assistant message after the last real user row instead of joining tool-use preambles with the final answer.
|
|
22
|
+
|
|
10
23
|
## [0.29.9] - 2026-08-31
|
|
11
24
|
|
|
12
25
|
### Fixed
|
|
@@ -1401,7 +1414,9 @@ prototype (preserved under `prototype/python/` as the porting source and referen
|
|
|
1401
1414
|
`ubuntu-latest` for Node 18/20/22, publishing to npm on `v*` tags with
|
|
1402
1415
|
provenance.
|
|
1403
1416
|
|
|
1404
|
-
[Unreleased]: https://github.com/kitepon/aiterm-mcp/compare/v0.29.
|
|
1417
|
+
[Unreleased]: https://github.com/kitepon/aiterm-mcp/compare/v0.29.11...HEAD
|
|
1418
|
+
[0.29.11]: https://github.com/kitepon/aiterm-mcp/compare/v0.29.10...v0.29.11
|
|
1419
|
+
[0.29.10]: https://github.com/kitepon/aiterm-mcp/compare/v0.29.9...v0.29.10
|
|
1405
1420
|
[0.29.9]: https://github.com/kitepon/aiterm-mcp/compare/v0.29.8...v0.29.9
|
|
1406
1421
|
[0.29.8]: https://github.com/kitepon/aiterm-mcp/compare/v0.29.7...v0.29.8
|
|
1407
1422
|
[0.29.7]: https://github.com/kitepon/aiterm-mcp/compare/v0.29.6...v0.29.7
|
package/README.ja.md
CHANGED
|
@@ -94,7 +94,7 @@ diagnostics、recovery、update、releaseを所有します。このREADMEと[
|
|
|
94
94
|
|
|
95
95
|
**言葉でなく実測で:** 記録済み203テストのベンチマークでは、`pty_read` はコンテキストに載るトークンを生ログの **約 7.1 分の 1** に減らす。しかも pass/fail の判定は畳んでも残る。→ [組み込みシェルツールとの使い分け](#組み込みシェルツールとの使い分け)
|
|
96
96
|
|
|
97
|
-
|
|
97
|
+
16ツール: 6つのPTYツール、正規のagent起動入口`agent_launch`、実行中のCodex/Grokを誘導する`agent_steer`、移行用の旧4alias、`agent_configure`、`claude_turn`、`claude_approval`、`diagnostics`。backendはPOSIXのtmux/Windows nativeのpsmuxなので、MCPサーバやAIクライアントが再起動してもsessionは生き残る。
|
|
98
98
|
|
|
99
99
|
**v0.28.0では実行基盤harnessとmodelを分離した。** harnessはagent loop・認証・hook・session・transcriptを所有し、modelはその上で選ぶ。Cursor Agent CLIでGPT/Claude/Grokを選んでも完了契約はCursor方式のまま。Composerは別harnessではなく、`harness:"grok-cli", model:"grok-composer-2.5-fast"`で表す。旧4起動ツールは同じ実装へ流れる互換alias。
|
|
100
100
|
|
|
@@ -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.29.
|
|
156
|
+
**状態:** 開発継続中 · 現行公開版 **v0.29.11** · 動作対象は Linux · WSL2 · macOS · Windows ネイティブ · MIT · [変更履歴](CHANGELOG.md)。
|
|
157
157
|
|
|
158
158
|
### 更新と巻き戻し
|
|
159
159
|
|
|
@@ -287,7 +287,7 @@ Throughline自体が不要である。
|
|
|
287
287
|
Claude Code を再起動して、接続を確認:
|
|
288
288
|
|
|
289
289
|
```bash
|
|
290
|
-
/mcp # aiterm が connected・
|
|
290
|
+
/mcp # aiterm が connected・16 ツール公開、と出る
|
|
291
291
|
```
|
|
292
292
|
|
|
293
293
|
最初のセッション——4 回の呼び出しで、1 個の永続端末:
|
|
@@ -328,7 +328,7 @@ MCP クライアントが aiterm を stdio 越しにプログラムから駆動
|
|
|
328
328
|
|
|
329
329
|
```mermaid
|
|
330
330
|
flowchart LR
|
|
331
|
-
AI["AI / MCP client<br/>(the orchestrator)"] -->|"pty_send · agent_launch · agent_configure · claude_turn · claude_approval<br/>旧launcher alias · diagnostics"| S["aiterm-mcp<br/>stdio MCP ·
|
|
331
|
+
AI["AI / MCP client<br/>(the orchestrator)"] -->|"pty_send · agent_launch · agent_steer · agent_configure · claude_turn · claude_approval<br/>旧launcher alias · diagnostics"| S["aiterm-mcp<br/>stdio MCP · 16 tools"]
|
|
332
332
|
S -->|"pty_read<br/>token-reduced"| AI
|
|
333
333
|
S -->|"tmux / psmux<br/>send · capture"| P["persistent PTYs<br/>再起動を跨ぐ"]
|
|
334
334
|
P -->|"ssh · docker · repl"| R["nested<br/>remote · container · REPL"]
|
|
@@ -409,6 +409,7 @@ aiterm は同じ核心の洞察——端末を出会いの場にする——を
|
|
|
409
409
|
| `pty_close` | 冪等に閉じ、`closed` / `already_closed`を返す | `session_id` |
|
|
410
410
|
| `pty_list` | セッション一覧(agent行は正規`harness=<id>`と互換`agent=<kind>`を含む) | (なし) |
|
|
411
411
|
| `agent_launch` | harnessとmodelを別軸で選ぶ正規agent起動入口 | `harness`, `prompt?`, `model?`, `reasoning_effort?`, `cwd?`, `write_scope?` |
|
|
412
|
+
| `agent_steer` | 実行中のCodex/Grok turnへtextを差し込む。idleなら送信せず`idle`を返す | `session_id`, `text` |
|
|
412
413
|
| `claude_agent` / `codex_agent` / `grok_agent` / `composer_agent` | deprecated互換alias | 旧launcher引数 |
|
|
413
414
|
| `agent_configure` | 起動中のClaude/Codex/Grok/Composer/Cursorを再起動せずmodel/effort変更 | `session_id`, `model?`, `reasoning_effort?` |
|
|
414
415
|
| `claude_turn` | 相関済みClaude operationをdispatch(issue)または回収(recover) | `action`, `session_id`, `operation_id`, `text?` |
|
|
@@ -443,7 +444,7 @@ handoff contextを前置きできる。この任意経路は`throughline >= 0.9.
|
|
|
443
444
|
`launch_operation_id`とは併用不可で、元sessionのDB所属を変更しない。Throughlineは
|
|
444
445
|
`THROUGHLINE_BIN`、次に`PATH`から解決し、不在・不正・空のexportはPTY作成前に明示失敗する。
|
|
445
446
|
|
|
446
|
-
エージェントの回答が画面tailより長ければ、`pty_read({ agent_transcript:true })`で再prompt
|
|
447
|
+
エージェントの回答が画面tailより長ければ、`pty_read({ agent_transcript:true })`で再promptなしに全文回収する。既存の人間向けcontentは診断suffixを維持し、機械呼出し側は`aiterm.pty-read-result.v1`の`structuredContent.text`から回答本文だけを取得する。Claudeはlaunch相関Stop hook、Codexは通常rollout、Grokは最後の実user行以後の最後の空でないassistantメッセージだけ、Cursorはlaunch IDでbindした通常agent transcriptから同じturnを回収する。
|
|
447
448
|
|
|
448
449
|
### 完了検出(5 層)
|
|
449
450
|
|
package/README.md
CHANGED
|
@@ -96,7 +96,7 @@ Aiterm and is not a runtime dependency.
|
|
|
96
96
|
|
|
97
97
|
**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)
|
|
98
98
|
|
|
99
|
-
|
|
99
|
+
Sixteen tools: six **PTY tools** — `pty_open` / `pty_send` / `pty_read` / `pty_key` / `pty_close` / `pty_list` — to open, drive, and read one persistent terminal; one canonical **agent launcher**, `agent_launch`, which selects `claude-code`, `codex-cli`, `grok-cli`, or `cursor-cli` as the execution harness; `agent_steer` for an active Codex or Grok turn; four deprecated launcher aliases kept for migration; `agent_configure`; `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.
|
|
100
100
|
|
|
101
101
|
**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. Grok Composer is a Grok CLI model preset, not another harness: use `harness: "grok-cli", model: "grok-composer-2.5-fast"`. The old four launcher tools are thin compatibility aliases over the same implementation.
|
|
102
102
|
|
|
@@ -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.29.
|
|
172
|
+
**Status:** actively maintained · current public release **v0.29.11** · 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
|
|
|
@@ -316,7 +316,7 @@ The only edits to the captures above are the two `⋮` lines (a long head/tail r
|
|
|
316
316
|
Restart Claude Code, then verify the connection:
|
|
317
317
|
|
|
318
318
|
```bash
|
|
319
|
-
/mcp # aiterm should show as connected, exposing
|
|
319
|
+
/mcp # aiterm should show as connected, exposing 16 tools
|
|
320
320
|
```
|
|
321
321
|
|
|
322
322
|
Your first session — four calls, one persistent terminal:
|
|
@@ -357,7 +357,7 @@ The terminal is real and shared, so a human *can* jump in ([A human can watch](#
|
|
|
357
357
|
|
|
358
358
|
```mermaid
|
|
359
359
|
flowchart LR
|
|
360
|
-
AI["AI / MCP client<br/>(the orchestrator)"] -->|"pty_send · agent_launch · agent_configure · claude_turn · claude_approval<br/>legacy launcher aliases · diagnostics"| S["aiterm-mcp<br/>stdio MCP ·
|
|
360
|
+
AI["AI / MCP client<br/>(the orchestrator)"] -->|"pty_send · agent_launch · agent_steer · agent_configure · claude_turn · claude_approval<br/>legacy launcher aliases · diagnostics"| S["aiterm-mcp<br/>stdio MCP · 16 tools"]
|
|
361
361
|
S -->|"pty_read<br/>token-reduced"| AI
|
|
362
362
|
S -->|"tmux / psmux<br/>send · capture"| P["persistent PTYs<br/>survive restarts"]
|
|
363
363
|
P -->|"ssh · docker · repl"| R["nested<br/>remote · container · REPL"]
|
|
@@ -440,6 +440,7 @@ On top of that sits a productized layer a raw tmux bridge doesn't have: **token-
|
|
|
440
440
|
| `pty_close` | Close idempotently; return `closed` / `already_closed` | `session_id` |
|
|
441
441
|
| `pty_list` | List sessions (agent rows carry canonical `harness=<id>` plus compatibility `agent=<kind>`) | (none) |
|
|
442
442
|
| `agent_launch` | Canonical agent launch; harness and model are independent | `harness`, `prompt?`, `model?`, `reasoning_effort?`, `cwd?`, `write_scope?` |
|
|
443
|
+
| `agent_steer` | Inject text into the active Codex or Grok turn; return `idle` without sending when no turn is active | `session_id`, `text` |
|
|
443
444
|
| `claude_agent` / `codex_agent` / `grok_agent` / `composer_agent` | Deprecated compatibility aliases | legacy launcher arguments |
|
|
444
445
|
| `agent_configure` | Change model/effort in a running Claude, Codex, Grok, Composer, or Cursor session without restarting it | `session_id`, `model?`, `reasoning_effort?` |
|
|
445
446
|
| `claude_turn` | Issue (dispatch-only) or recover one correlated Claude operation | `action`, `session_id`, `operation_id`, `text?` |
|
|
@@ -475,7 +476,7 @@ cannot be combined with `launch_operation_id`, and leaves the source session's d
|
|
|
475
476
|
unchanged. Throughline is resolved through `THROUGHLINE_BIN` and then `PATH`; a missing or invalid
|
|
476
477
|
export fails before the PTY exists instead of silently launching clean.
|
|
477
478
|
|
|
478
|
-
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 launch-correlated 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`. Codex uses the normal rollout transcript's `task_complete.turn_id`; Grok/Composer
|
|
479
|
+
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. The existing human-readable content keeps its diagnostic suffix; machine callers read the answer alone from `structuredContent.text` in `aiterm.pty-read-result.v1`. Claude reads the bounded owner-only result captured by the launch-correlated 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`. Codex uses the normal rollout transcript's `task_complete.turn_id`; Grok/Composer return the last non-empty assistant message after the last real user row, excluding tool-use preambles; Cursor uses the normal agent transcript bound to the launch ID and current turn. Missing or ambiguous attribution remains an explicit error.
|
|
479
480
|
|
|
480
481
|
### Completion detection (5 layers)
|
|
481
482
|
|
package/dist/core.js
CHANGED
|
@@ -1994,8 +1994,8 @@ async function settlePublishedClaudeCompletionMarker(meta, marker) {
|
|
|
1994
1994
|
}
|
|
1995
1995
|
return active;
|
|
1996
1996
|
}
|
|
1997
|
-
/** agent harness の構造化 transcript
|
|
1998
|
-
export async function
|
|
1997
|
+
/** agent harness の構造化 transcript から直近完了ターンの最終回答と相関情報を読む。 */
|
|
1998
|
+
export async function readAgentTranscriptResult(name, o = {}) {
|
|
1999
1999
|
const meta = loadAgentMetadata(name);
|
|
2000
2000
|
const operationId = o.operation_id == null ? null : validateOperationId(o.operation_id);
|
|
2001
2001
|
if (operationId && meta.kind !== "claude") {
|
|
@@ -2050,7 +2050,18 @@ export async function readAgentTranscript(name, o = {}) {
|
|
|
2050
2050
|
done?.operation_id ? `operation_id=${done.operation_id}` : null,
|
|
2051
2051
|
`raw_chars=${rawChars}`,
|
|
2052
2052
|
].filter(Boolean).join(" ");
|
|
2053
|
-
return
|
|
2053
|
+
return {
|
|
2054
|
+
text: body,
|
|
2055
|
+
display: `${body}\n${outputMeta} [${transcriptMeta}]`,
|
|
2056
|
+
vendor: meta.kind,
|
|
2057
|
+
turn_id: turnId,
|
|
2058
|
+
harness: agentHarness(meta.kind),
|
|
2059
|
+
raw_chars: rawChars,
|
|
2060
|
+
};
|
|
2061
|
+
}
|
|
2062
|
+
/** 人間向け互換表示を維持する。機械利用は readAgentTranscriptResult の text を使う。 */
|
|
2063
|
+
export async function readAgentTranscript(name, o = {}) {
|
|
2064
|
+
return (await readAgentTranscriptResult(name, o)).display;
|
|
2054
2065
|
}
|
|
2055
2066
|
function inferAgentFrontend(name, meta, screen) {
|
|
2056
2067
|
const fg = paneCurrentCommand(name);
|
|
@@ -2837,6 +2848,33 @@ export async function dispatchAgentTurn(name, text, o = {}) {
|
|
|
2837
2848
|
submit_residue: residue.residue,
|
|
2838
2849
|
};
|
|
2839
2850
|
}
|
|
2851
|
+
export async function steerAgentTurn(name, text) {
|
|
2852
|
+
assertSessionName(name);
|
|
2853
|
+
const meta = loadAgentMetadata(name);
|
|
2854
|
+
if (!["codex", "grok", "composer"].includes(meta.kind)) {
|
|
2855
|
+
throw new AitermError("agent_steer はCodex/Grok agent sessionだけで使用できます", 2);
|
|
2856
|
+
}
|
|
2857
|
+
const receipt = {
|
|
2858
|
+
schema: "aiterm.agent-steer.v1",
|
|
2859
|
+
session_id: meta.aiterm_session,
|
|
2860
|
+
launch_id: meta.launch_id,
|
|
2861
|
+
vendor: meta.kind,
|
|
2862
|
+
harness: agentHarness(meta.kind),
|
|
2863
|
+
};
|
|
2864
|
+
if (!isAgentTuiBusy(meta.kind, captureScreen(name, AGENT_TUI_READY_LINES)))
|
|
2865
|
+
return { ...receipt, delivery: "idle" };
|
|
2866
|
+
send(name, text, {
|
|
2867
|
+
enter: false,
|
|
2868
|
+
force: true,
|
|
2869
|
+
raw: false,
|
|
2870
|
+
mark: false,
|
|
2871
|
+
rtk: false,
|
|
2872
|
+
bracketedPaste: true,
|
|
2873
|
+
});
|
|
2874
|
+
await sleep(AGENT_SUBMIT_DELAY_MS);
|
|
2875
|
+
sendKey(name, "Enter");
|
|
2876
|
+
return { ...receipt, delivery: "steered" };
|
|
2877
|
+
}
|
|
2840
2878
|
export async function runClaudeOperation({ session_id: name, action, operation_id: operationIdInput, text, }) {
|
|
2841
2879
|
assertSessionName(name);
|
|
2842
2880
|
if (action !== "issue" && action !== "recover") {
|
package/dist/harnesses/grok.js
CHANGED
|
@@ -283,7 +283,7 @@ export function grokFooterHasConfiguration(screen, model, effort) {
|
|
|
283
283
|
return modelLabel !== null || effort !== null;
|
|
284
284
|
});
|
|
285
285
|
}
|
|
286
|
-
// 最後のuser
|
|
286
|
+
// 最後のuser発話以降に確定した最後のassistantメッセージをchat_history.jsonlから抽出する。
|
|
287
287
|
export function grokTranscriptText(meta, readTranscriptLines, transcriptUnavailable) {
|
|
288
288
|
if (!meta.grok_home || !meta.vendor_session_id)
|
|
289
289
|
transcriptUnavailable();
|
|
@@ -307,11 +307,12 @@ export function grokTranscriptText(meta, readTranscriptLines, transcriptUnavaila
|
|
|
307
307
|
// 外部 transcript の壊れた1行は残りの完結行を読む妨げにしない。
|
|
308
308
|
}
|
|
309
309
|
}
|
|
310
|
-
|
|
310
|
+
const replies = records
|
|
311
311
|
.slice(lastUser + 1)
|
|
312
312
|
.filter((record) => record?.type === "assistant" && typeof record?.content === "string")
|
|
313
|
-
.map((record) => record.content)
|
|
314
|
-
.
|
|
313
|
+
.map((record) => record.content.trim())
|
|
314
|
+
.filter(Boolean);
|
|
315
|
+
return replies.at(-1) ?? "";
|
|
315
316
|
}
|
|
316
317
|
export function createGrokAgentMetadata(kind, name, cwd, initialPrompt, authPath, writeScope, lineageContext) {
|
|
317
318
|
const launchId = randomBytes(16).toString("hex");
|
package/dist/index.js
CHANGED
|
@@ -203,6 +203,33 @@ server.registerTool("pty_send", {
|
|
|
203
203
|
return fail(e);
|
|
204
204
|
}
|
|
205
205
|
});
|
|
206
|
+
server.registerTool("agent_steer", {
|
|
207
|
+
description: "実行中のCodex/Grok agentへ追加メッセージを差し込み、現在のターンを誘導する。" +
|
|
208
|
+
"独立した次ターンを始める用途ではなく、idle時は文字を送らずdelivery=idleを返す。",
|
|
209
|
+
inputSchema: {
|
|
210
|
+
session_id: z.string(),
|
|
211
|
+
text: z.string().describe("現在のターンへ追加する文字列。UTF-8で最大64KiB"),
|
|
212
|
+
},
|
|
213
|
+
outputSchema: {
|
|
214
|
+
schema: z.literal("aiterm.agent-steer.v1"),
|
|
215
|
+
session_id: z.string(),
|
|
216
|
+
launch_id: z.string(),
|
|
217
|
+
vendor: z.enum(["codex", "grok", "composer"]),
|
|
218
|
+
harness: z.enum(["codex-cli", "grok-cli"]),
|
|
219
|
+
delivery: z.enum(["steered", "idle"]),
|
|
220
|
+
},
|
|
221
|
+
}, async ({ session_id, text }) => {
|
|
222
|
+
try {
|
|
223
|
+
const receipt = await core.steerAgentTurn(session_id, text);
|
|
224
|
+
return {
|
|
225
|
+
content: [{ type: "text", text: `${receipt.delivery} ${receipt.session_id}` }],
|
|
226
|
+
structuredContent: receipt,
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
catch (e) {
|
|
230
|
+
return fail(e);
|
|
231
|
+
}
|
|
232
|
+
});
|
|
206
233
|
server.registerTool("pty_read", {
|
|
207
234
|
description: "セッションの出力をトークン削減して読む(既定は前回読取位置からの増分)。" +
|
|
208
235
|
"削減: 制御文字除去 / 反復圧縮 / head+tail 折りたたみ+復元ヒント+メタ併記。" +
|
|
@@ -239,16 +266,39 @@ server.registerTool("pty_read", {
|
|
|
239
266
|
.nullish()
|
|
240
267
|
.describe("Claude operationの期待ID。agent_transcript:true時だけ指定し、古い別operationの結果を拒否する"),
|
|
241
268
|
},
|
|
269
|
+
outputSchema: {
|
|
270
|
+
schema: z.literal("aiterm.pty-read-result.v1"),
|
|
271
|
+
mode: z.enum(["terminal", "agent_transcript"]),
|
|
272
|
+
session_id: z.string(),
|
|
273
|
+
text: z.string(),
|
|
274
|
+
vendor: z.enum(["claude", "codex", "grok", "composer", "cursor"]).nullable(),
|
|
275
|
+
turn_id: z.string().nullable(),
|
|
276
|
+
harness: z.enum(["claude-code", "codex-cli", "grok-cli", "cursor-cli"]).nullable(),
|
|
277
|
+
raw_chars: z.number().int().nonnegative().nullable(),
|
|
278
|
+
},
|
|
242
279
|
}, async ({ session_id, wait, until, until_regex, timeout, screen, full, lines, line_range, raw, rtk, agent_transcript, operation_id }) => {
|
|
243
280
|
try {
|
|
244
281
|
if (agent_transcript) {
|
|
245
282
|
if (screen || full || rtk || wait || line_range != null) {
|
|
246
283
|
throw new Error("agent_transcript:true は screen / full / rtk / line_range / wait と併用できません。lines のみ指定できます。");
|
|
247
284
|
}
|
|
248
|
-
|
|
285
|
+
const result = await core.readAgentTranscriptResult(session_id, {
|
|
249
286
|
lines: lines ?? null,
|
|
250
287
|
operation_id: operation_id ?? null,
|
|
251
|
-
})
|
|
288
|
+
});
|
|
289
|
+
return {
|
|
290
|
+
content: [{ type: "text", text: result.display }],
|
|
291
|
+
structuredContent: {
|
|
292
|
+
schema: "aiterm.pty-read-result.v1",
|
|
293
|
+
mode: "agent_transcript",
|
|
294
|
+
session_id,
|
|
295
|
+
text: result.text,
|
|
296
|
+
vendor: result.vendor,
|
|
297
|
+
turn_id: result.turn_id,
|
|
298
|
+
harness: result.harness,
|
|
299
|
+
raw_chars: result.raw_chars,
|
|
300
|
+
},
|
|
301
|
+
};
|
|
252
302
|
}
|
|
253
303
|
if (operation_id != null)
|
|
254
304
|
throw new Error("operation_idはagent_transcript:true時だけ指定できます");
|
|
@@ -279,7 +329,19 @@ server.registerTool("pty_read", {
|
|
|
279
329
|
raw,
|
|
280
330
|
rtk,
|
|
281
331
|
});
|
|
282
|
-
return
|
|
332
|
+
return {
|
|
333
|
+
content: [{ type: "text", text: out }],
|
|
334
|
+
structuredContent: {
|
|
335
|
+
schema: "aiterm.pty-read-result.v1",
|
|
336
|
+
mode: "terminal",
|
|
337
|
+
session_id,
|
|
338
|
+
text: out,
|
|
339
|
+
vendor: null,
|
|
340
|
+
turn_id: null,
|
|
341
|
+
harness: null,
|
|
342
|
+
raw_chars: null,
|
|
343
|
+
},
|
|
344
|
+
};
|
|
283
345
|
}
|
|
284
346
|
catch (e) {
|
|
285
347
|
return fail(e);
|
package/docs/DESIGN.md
CHANGED
|
@@ -25,6 +25,7 @@ project/user環境を置換せず、launch相関と完了回収に必要なsta
|
|
|
25
25
|
agent turnは常に非ブロックdispatchである。receiptの`event_cursor`がturn境界、`wait_process`が
|
|
26
26
|
platform nativeな別process起動情報を返す。waiterは純readerで、親のforeground turnを塞がない。
|
|
27
27
|
回答はharness所有transcriptから同じturnへ相関して回収し、欠落・曖昧・timeout時にpromptを再送しない。
|
|
28
|
+
`agent_steer`は実行中のCodex/Grok turnへ追加textを差し込み、idleなら送信せず状態を返す。
|
|
28
29
|
|
|
29
30
|
## Layer ownership
|
|
30
31
|
|
package/docs/RELEASE.md
CHANGED
|
@@ -26,7 +26,7 @@ npm pack --dry-run
|
|
|
26
26
|
npm run mcpb:build
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
-
MCPBのstaged serverでversion、
|
|
29
|
+
MCPBのstaged serverでversion、16 tools、stderr 0、必要なruntime JavaScriptの同梱を確認する。
|
|
30
30
|
|
|
31
31
|
## Mainと公開
|
|
32
32
|
|
|
@@ -44,7 +44,7 @@ CI callerは同じrepositoryの`./.github/workflows/product-full-ci.yml`だけ
|
|
|
44
44
|
公式npm packageを隔離またはglobal installし、次を確認する。
|
|
45
45
|
|
|
46
46
|
- `aiterm-mcp`、`aiterm-wait`、`aiterm-runtime-errors`の3 bins。
|
|
47
|
-
- MCP initializeのversion、
|
|
47
|
+
- MCP initializeのversion、16 tools、stderr 0。
|
|
48
48
|
- POSIXはtmux、Windows nativeはpsmux 3.3.8以上とPowerShell 7。
|
|
49
49
|
- 変更に触れたharnessの起動、non-blocking dispatch、wait outcome、transcript回収、`pty_close`後の残骸ゼロ。
|
|
50
50
|
- Official Registryが`io.github.kitepon/aiterm-mcp`の同じversionをactive/latestとして返す。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aiterm-mcp",
|
|
3
|
-
"version": "0.29.
|
|
3
|
+
"version": "0.29.11",
|
|
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": [
|