aiterm-mcp 0.54.0 → 0.55.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 +23 -1
- package/README.ja.md +5 -2
- package/README.md +5 -2
- package/dist/core.js +15 -0
- package/dist/harnesses/claude.js +30 -1
- package/dist/index.js +8 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,27 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.55.0] - 2026-10-06
|
|
11
|
+
|
|
12
|
+
### 変更
|
|
13
|
+
|
|
14
|
+
- `agent_launch`は、起動時promptの開始を確認できなかった返り(`initial_prompt.status`が`submitted_unconfirmed`)に
|
|
15
|
+
`isError`を付けない(ADR 0093)。sessionは立ち、promptは入力欄を離れ、親への配送も登録済みなので、状態は
|
|
16
|
+
`initial_prompt`と本文で伝える。本文には「turnの開始は未確認(reason=…)。再送もagentの起動し直しもしない。
|
|
17
|
+
確かめる時は pty_observe」の案内が付く。誤りの印でこの状態を見分けていた呼び出し側は、`initial_prompt.status`を見る。
|
|
18
|
+
送信の途中で失敗した起動は、今までどおり誤りで返る。`remote`付きの起動は、現地が旧版で誤りを返しても同じ形で返す。
|
|
19
|
+
|
|
20
|
+
### 修正
|
|
21
|
+
|
|
22
|
+
- Claude Code親が起こした子の回答が、親へ届かない事があった。開始未確認の返りを誤りで返していて、Claude Codeは
|
|
23
|
+
誤りの返りでは受け口のhook(`PostToolUse`)を走らせない。配送は`sending`のまま残り、返りの本文は「回答は自動配送する。
|
|
24
|
+
回収は不要」と案内していた。上の変更で、受け口が出来て回答が届く。
|
|
25
|
+
- 動いているClaude Codeを、入力待ち(`idle`/`composer_ready`)と読む事があった。Claude Code(2.1.289〜2.1.291で確認)は、
|
|
26
|
+
複数行のprompt(貼り付けの形で入る)を送った後の約8秒、足元の行を`paste again to expand`へ置き換える。動作中の印に
|
|
27
|
+
していた`esc to interrupt`がその間は画面に無い。複数行のpromptを付けたClaudeの子の起動は毎回、開始未確認になり、
|
|
28
|
+
`pty_observe`もその間`idle`を返していた。動いている間は入力欄の上に進行行(`✶ Slithering… (3s · ↓ 225 tokens)`)が
|
|
29
|
+
出続けるので、それも動作中の印にする。Linux・Mac・Windowsの実画面で確かめた。Codex・Grok・Cursorの読み方は変えていない。
|
|
30
|
+
|
|
10
31
|
## [0.54.0] - 2026-10-06
|
|
11
32
|
|
|
12
33
|
### 変更
|
|
@@ -2235,7 +2256,8 @@ prototype (preserved under `prototype/python/` as the porting source and referen
|
|
|
2235
2256
|
`ubuntu-latest` for Node 18/20/22, publishing to npm on `v*` tags with
|
|
2236
2257
|
provenance.
|
|
2237
2258
|
|
|
2238
|
-
[Unreleased]: https://github.com/kitepon/aiterm-mcp/compare/v0.
|
|
2259
|
+
[Unreleased]: https://github.com/kitepon/aiterm-mcp/compare/v0.55.0...HEAD
|
|
2260
|
+
[0.55.0]: https://github.com/kitepon/aiterm-mcp/compare/v0.54.0...v0.55.0
|
|
2239
2261
|
[0.54.0]: https://github.com/kitepon/aiterm-mcp/compare/v0.53.2...v0.54.0
|
|
2240
2262
|
[0.53.2]: https://github.com/kitepon/aiterm-mcp/compare/v0.53.1...v0.53.2
|
|
2241
2263
|
[0.53.1]: https://github.com/kitepon/aiterm-mcp/compare/v0.53.0...v0.53.1
|
package/README.ja.md
CHANGED
|
@@ -209,7 +209,7 @@ runtime-error store は canonical dotagents config の `collection.enabled: true
|
|
|
209
209
|
場合だけ収集し、既定OFF、network送信は行いません。tag起点CIのnpm provenance(OIDC Trusted
|
|
210
210
|
Publishing)で公開し、GitHub Release が Official MCP Registry を再登録します。
|
|
211
211
|
|
|
212
|
-
**状態:** 開発継続中 · 現行公開版 **v0.
|
|
212
|
+
**状態:** 開発継続中 · 現行公開版 **v0.55.0** · 動作対象は Linux · WSL2 · macOS · Windows ネイティブ · MIT · [変更履歴](CHANGELOG.md)。
|
|
213
213
|
|
|
214
214
|
### 更新と巻き戻し
|
|
215
215
|
|
|
@@ -546,7 +546,10 @@ Claude Code初回起動の文字表示テーマ選択では、画面で選択済
|
|
|
546
546
|
それでも描かれなければ、今までと同じく未送信(`initial_prompt=not_sent`)で返り、sessionは残る。
|
|
547
547
|
WindowsのCodexもhook確認を認識し、npm shim経由の起動を一つのharnessとして識別する。
|
|
548
548
|
初手の`initial_prompt.status`は`not_requested`/`not_sent`/`submitted_unconfirmed`/`started`を区別する。
|
|
549
|
-
|
|
549
|
+
未送信の失敗もsession付きstructuredContentを保持する。
|
|
550
|
+
`submitted_unconfirmed`(promptは入力欄を離れたが、確認時間の内に開始を見られなかった)は誤りにしない。`isError`は付かず、
|
|
551
|
+
本文に未確認の案内が付く。sessionは立っていて、親への配送も登録済み。未確認のpromptを再送せず、agentも起動し直さず、
|
|
552
|
+
返ったcursorか`pty_observe`で観測する。
|
|
550
553
|
|
|
551
554
|
Codexの実行中承認は`agent_approval({ action: "inspect", session_id })`の`prompt`と`choices`を確認し、
|
|
552
555
|
`respond`へ`observed_prompt_digest`と`approval_choice`(`approve_once`/`deny`)を渡す。
|
package/README.md
CHANGED
|
@@ -223,7 +223,7 @@ collection is off by default and performs no network I/O. It ships via
|
|
|
223
223
|
tag-triggered CI with npm provenance (OIDC Trusted Publishing); the GitHub
|
|
224
224
|
Release re-registers the Official MCP Registry entry.
|
|
225
225
|
|
|
226
|
-
**Status:** actively maintained · current public release **v0.
|
|
226
|
+
**Status:** actively maintained · current public release **v0.55.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).
|
|
227
227
|
|
|
228
228
|
### Update and rollback
|
|
229
229
|
|
|
@@ -583,7 +583,10 @@ waits up to 50 seconds from startup. If nothing is drawn by then, it still retur
|
|
|
583
583
|
A prompt-free launch without this option retains `startup.status="not_checked"`. `initial_prompt.status` distinguishes
|
|
584
584
|
`not_requested`, `not_sent`, `submitted_unconfirmed`, and `started`. Failure responses retain structured session information.
|
|
585
585
|
WindowsのCodexもhook確認を認識し、npm shim経由の起動を一つのharnessとして識別する。
|
|
586
|
-
|
|
586
|
+
`submitted_unconfirmed` (the prompt left the composer, but the turn start was not observed within the confirmation window) is
|
|
587
|
+
not a tool error: `isError` is not set, the text carries an unconfirmed-start note, the session is alive and the parent
|
|
588
|
+
delivery stays registered. Do not resend an unconfirmed prompt or relaunch the agent; observe with `pty_observe` or wait
|
|
589
|
+
using its returned cursor.
|
|
587
590
|
|
|
588
591
|
For a live Codex approval, inspect with `agent_approval({ action: "inspect", session_id })`, review `prompt` and `choices`,
|
|
589
592
|
then respond with `observed_prompt_digest` and `approval_choice` (`approve_once` or `deny`). Unknown or changed dialogs return
|
package/dist/core.js
CHANGED
|
@@ -3323,6 +3323,20 @@ async function waitCursorPromptVisibleImpl(text, sample, sleepFn, opts = {}) {
|
|
|
3323
3323
|
async function waitCursorPromptVisible(name, text) {
|
|
3324
3324
|
return waitCursorPromptVisibleImpl(text, () => captureScreen(name, AGENT_TUI_READY_LINES), sleep);
|
|
3325
3325
|
}
|
|
3326
|
+
// 起動時promptは入力欄を離れたが、確認時間の内にturnの開始を見られなかった時の案内。この返りは誤り(isError)にしない。
|
|
3327
|
+
// 誤りで返すと、Claude Code親は受け口のhook(PostToolUse)を走らせず、登録済みの配送が届かない(ADR 0093)。
|
|
3328
|
+
// 親が同じ依頼で起動し直すと子が2つ動くので、再送も再起動もしない事を先に書く。
|
|
3329
|
+
export const INITIAL_PROMPT_UNCONFIRMED_MARK = "turnの開始は未確認";
|
|
3330
|
+
export function initialPromptUnconfirmedNote(name, reason) {
|
|
3331
|
+
return (`注意: ${INITIAL_PROMPT_UNCONFIRMED_MARK}(reason=${reason})。promptは入力欄を離れているので、再送もagentの起動し直しもしない。` +
|
|
3332
|
+
`開始していれば結果は上の方法で届く。確かめる時は pty_observe(${name}) で状態を見る。`);
|
|
3333
|
+
}
|
|
3334
|
+
// 起動そのものは普通に返り、初手の開始だけが未確認の返りか。送信の途中で失敗した起動も同じstatusを持つ
|
|
3335
|
+
// (その時のstartup.reasonは失敗の理由になる)ので、起動が普通に返った形(ready/composer_ready)と組で見る。
|
|
3336
|
+
export function launchStartUnconfirmed(structured) {
|
|
3337
|
+
return structured.initial_prompt?.status === "submitted_unconfirmed"
|
|
3338
|
+
&& structured.startup?.status === "ready" && structured.startup?.reason === "composer_ready";
|
|
3339
|
+
}
|
|
3326
3340
|
export function agentSubmitResidueWarning(name, residue) {
|
|
3327
3341
|
if (residue !== true)
|
|
3328
3342
|
return "";
|
|
@@ -3622,6 +3636,7 @@ async function sendInitialAgentPromptInLock(name, text, o) {
|
|
|
3622
3636
|
return {
|
|
3623
3637
|
text: `initial_prompt=pending vendor=${meta.kind} event_cursor=${startOffset} harness=${agentHarness(meta.kind)}\n` +
|
|
3624
3638
|
`起動時 prompt を送信した。${agentDispatchGuide(name, startOffset)}` +
|
|
3639
|
+
(delivery.status === "submitted_unconfirmed" ? `\n${initialPromptUnconfirmedNote(name, delivery.reason)}` : "") +
|
|
3625
3640
|
agentSubmitResidueWarning(name, residue.residue),
|
|
3626
3641
|
event_cursor: startOffset,
|
|
3627
3642
|
submit_residue: residue.residue,
|
package/dist/harnesses/claude.js
CHANGED
|
@@ -281,13 +281,42 @@ export function claudeTuiReady(screen) {
|
|
|
281
281
|
// その下に描画された現在のcomposerを優先する。
|
|
282
282
|
return !/^❯\s*(?:\d+\.|\[|Enable selected\b|No,\s*exit\b|Yes,\s*I trust this folder\b)/iu.test(lastMarker);
|
|
283
283
|
}
|
|
284
|
+
// Claude Codeは動いている間、入力欄の上へ進行行を出し続ける(2.1.291の実画面 2026-10-06)。
|
|
285
|
+
// ✻ Swirling… (running UserPromptSubmit hook · 0s)
|
|
286
|
+
// * Swirling…
|
|
287
|
+
// ✶ Slithering… (3s · ↓ 225 tokens · thought for 2s)
|
|
288
|
+
// ✢ コマンド実行中… (12s · ↓ 1.0k tokens · thinking) ← 作業の一覧を使う時は、進行中の項目の文になる
|
|
289
|
+
// ⎿ ◼ 下の命令を1回だけ動かす ← 一覧は進行行の下へ字下げで並ぶ
|
|
290
|
+
// 終わると同じ位置が「✻ Cogitated for 11s · done 4:45 AM」へ変わる(「…」が無く、「·」で区切る)。
|
|
291
|
+
const CLAUDE_PROGRESS_LINE_RE = /^[·✢✳✶✻✽*∗] [^·…\s][^·…]*…(?: \(.*\))?\s*$/u;
|
|
292
|
+
// 入力欄の上の罫線から上へ、空行と字下げの行を飛ばし、行頭から始まる最初の行が進行行かを見る。
|
|
293
|
+
// 会話欄の行(「●」の回答、「❯」の依頼文、字下げの道具の出力)は進行行の形にならない。
|
|
294
|
+
function claudeTurnProgress(screen) {
|
|
295
|
+
const lines = screen.split(/\r?\n/u);
|
|
296
|
+
let marker = lines.length - 1;
|
|
297
|
+
while (marker >= 0 && !CLAUDE_COMPOSER_MARKER_RE.test(lines[marker]))
|
|
298
|
+
marker--;
|
|
299
|
+
if (marker <= 0 || !/^\s*─{8,}\s*$/u.test(lines[marker - 1]))
|
|
300
|
+
return false;
|
|
301
|
+
for (let i = marker - 2; i >= 0; i--) {
|
|
302
|
+
if (lines[i].trim() === "" || /^\s/u.test(lines[i]))
|
|
303
|
+
continue;
|
|
304
|
+
return CLAUDE_PROGRESS_LINE_RE.test(lines[i]);
|
|
305
|
+
}
|
|
306
|
+
return false;
|
|
307
|
+
}
|
|
308
|
+
// 足元の「esc to interrupt」は、貼り付けの知らせ(paste again to expand)へ置き換わる間は出ない。複数行のpromptを
|
|
309
|
+
// 送った後の約8秒がそうで、その間は動いているのに入力待ちと読んでいた(2.1.291、2026-10-06)。進行行も動作中の印にする。
|
|
310
|
+
export function claudeTuiBusy(screen) {
|
|
311
|
+
return /esc to interrupt/i.test(screen.split("\n").slice(-32).join("\n")) || claudeTurnProgress(screen);
|
|
312
|
+
}
|
|
284
313
|
export function claudePaneObservation(screen) {
|
|
285
314
|
const tail = screen.split("\n").slice(-32).join("\n");
|
|
286
315
|
if (claudeLoginMethodMenu(screen))
|
|
287
316
|
return { state: "blocked", reason: "vendor_onboarding_required" };
|
|
288
317
|
if (/Do you want to proceed\?/.test(tail) && /(?:^|\n)\s*[❯>]?\s*\d+\.\s+(?:Yes|No)\s*$/m.test(tail))
|
|
289
318
|
return { state: "blocked", reason: "tool_approval" };
|
|
290
|
-
if (
|
|
319
|
+
if (claudeTuiBusy(screen))
|
|
291
320
|
return { state: "busy", reason: "turn_running" };
|
|
292
321
|
if (claudeTuiReady(screen))
|
|
293
322
|
return { state: "idle", reason: "composer_ready" };
|
package/dist/index.js
CHANGED
|
@@ -913,12 +913,17 @@ async function launchRemoteAgent(target, harness, args, extra) {
|
|
|
913
913
|
return fail(new Error(`別端末でagentは起動しましたが、回答配送を登録できませんでした(session_id=${structured.session_id}): ${e instanceof Error ? e.message : String(e)}`));
|
|
914
914
|
}
|
|
915
915
|
const waited = await remoteCompletionWait(delivery, target, structured.session_id, structured.event_cursor);
|
|
916
|
+
// 現地が開始未確認を誤りで返す版(0.54.0以前)でも、ここでは誤りにしない(ADR 0093)。案内が無ければ足す。
|
|
917
|
+
const unconfirmed = core.launchStartUnconfirmed(structured);
|
|
918
|
+
const noted = result.content.some(item => item.type === "text" && item.text.includes(core.INITIAL_PROMPT_UNCONFIRMED_MARK));
|
|
916
919
|
return {
|
|
917
920
|
content: [...result.content, remoteNote(target, result),
|
|
921
|
+
...(unconfirmed && !noted
|
|
922
|
+
? [{ type: "text", text: core.initialPromptUnconfirmedNote(structured.session_id, structured.initial_prompt.reason) }] : []),
|
|
918
923
|
{ type: "text", text: `以後このsessionを操作する時は、同じremoteを付けて呼ぶ。${deliveryIdLine(delivery)}` }],
|
|
919
924
|
structuredContent: { ...structured, ...waited, ...(delivery?.result() ? { parent_delivery: delivery.result() } : {}),
|
|
920
925
|
remote_host: remoteLabel(target), remote_version: result.remote_version },
|
|
921
|
-
...(result.isError ? { isError: true } : {}),
|
|
926
|
+
...(result.isError && !unconfirmed ? { isError: true } : {}),
|
|
922
927
|
};
|
|
923
928
|
}
|
|
924
929
|
async function launchAgent(kind, args, extra) {
|
|
@@ -967,10 +972,11 @@ async function launchAgent(kind, args, extra) {
|
|
|
967
972
|
}
|
|
968
973
|
: {}),
|
|
969
974
|
};
|
|
975
|
+
// 開始未確認(submitted_unconfirmed)は誤りにしない。sessionは立ち、promptは入力欄を離れ、配送も登録済み。
|
|
976
|
+
// 誤りで返すとClaude Code親は受け口のhookを走らせず、子の回答が届かない(ADR 0093)。状態はinitial_promptと本文で伝える。
|
|
970
977
|
return {
|
|
971
978
|
content: [{ type: "text", text: `session_id: ${sid}\n${hint}${deliveryIdLine(delivery)}` }],
|
|
972
979
|
structuredContent: structured,
|
|
973
|
-
...(initialDelivery.status === "submitted_unconfirmed" ? { isError: true } : {}),
|
|
974
980
|
};
|
|
975
981
|
}
|
|
976
982
|
catch (e) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aiterm-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.55.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": [
|