aiterm-mcp 0.19.3 → 0.20.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/README.md CHANGED
@@ -326,6 +326,8 @@ As of v0.16 a parent agent **never blocks** on aiterm — there is no wait param
326
326
  3. **The parent never runs the waiter in its own foreground.** Waiting is correct — but the waiter is a separate process, not the parent's turn. A harness that re-invokes its agent when a background task exits (Claude Code) runs the waiter **in the background** and gets woken with zero polling. So that this is not left to interpretation, aiterm reads `clientInfo.name` from the MCP `initialize` handshake and its receipts name the concrete invocation for the detected host — for Claude Code, literally `Bash(command: "aiterm-wait …", run_in_background: true)`. Unknown or undeclared hosts get the generic "start it as a process that does not block the parent's turn" wording; nothing else about the contract changes. Every receipt leads with the same rule: dispatch and let go, then go do something else or end the turn.
327
327
  4. Collect the result exactly as before: `pty_read(agent_transcript: true)`, or `claude_turn recover` for durable Claude operations. The waiter carries the signal, never the payload.
328
328
 
329
+ **If your host has no completion push** (no mechanism that re-invokes the agent when a background process exits), `--timeout 0` is a one-shot check instead of a wait: it scans the event file once and returns `running` (exit `5`) when the turn is still in flight, `done` (exit `0`) when it finished, `closed` (exit `4`) when the session is gone. It is deliberately absent from the receipts and tool descriptions — a host that *does* get pushed should be woken, not poll. An unknown session name is an error, never `running`, so a typo cannot masquerade as a child that is still working.
330
+
329
331
  `aiterm-wait` takes no locks, never writes session state, and never dispatches — any number can run beside the MCP server and each other, and `pty_close`/concurrent sends are unaffected.
330
332
 
331
333
  ### Token reduction
@@ -2,14 +2,16 @@
2
2
  // aiterm-wait — agent turn 完了eventの純リーダー観測CLI。
3
3
  // 完了/timeout/close を1行のJSON receiptで返してexitする。lock・PTY・dispatch状態には一切触れない。
4
4
  // 親AIホストのバックグラウンドタスクとして起動し、exitを「観測終了の通知」として使う。
5
- // exit≠完了: exit code は outcome を映す(0=done / 3=timeout=未完了 / 4=closed / 1=エラー)。
5
+ // exit≠完了: exit code は outcome を映す(0=done / 5=running=未完了 / 3=timeout=未完了 / 4=closed / 1=エラー)。
6
+ // --timeout 0 は待たずに一度だけ観測する照会で、未完了は running(timeout と混同させない)。
6
7
  // receipt の outcome が正で、done 以外は未完了。timeout の既定は core の DEFAULT_AGENT_DONE_TIMEOUT(600秒)。
7
8
  import { fileURLToPath } from "node:url";
8
9
  import * as fs from "node:fs";
9
10
  import { AitermError, observeAgentDone } from "./core.js";
10
11
  const SESSION_RE = /^[A-Za-z0-9_-]{1,64}$/;
11
12
  const OPERATION_RE = /^sha256:[0-9a-f]{64}$/;
12
- const USAGE = "usage: aiterm-wait --session <name> [--cursor <event_cursor>] [--operation sha256:<64hex>] [--timeout <sec>]";
13
+ const USAGE = "usage: aiterm-wait --session <name> [--cursor <event_cursor>] [--operation sha256:<64hex>] [--timeout <sec>]" +
14
+ "(--timeout 0 は待たずに一度だけ観測する照会で、未完了は outcome=running / exit 5)";
13
15
  export function parseArgs(argv) {
14
16
  let session = null;
15
17
  let operationId = null;
@@ -65,7 +67,14 @@ function emit(value) {
65
67
  process.stdout.write(JSON.stringify(value) + "\n");
66
68
  }
67
69
  // outcome → exit code。exit status しか見えないホストでも done とそれ以外を誤読できないようにする。
68
- const OUTCOME_EXIT_CODES = { done: 0, timeout: 3, closed: 4 };
70
+ // Record で全 outcome を型に強制する: 語を足して対応表を直し忘れると undefined→exit 0 になり、
71
+ // 「まだ終わっていない」が「完了」として親へ届く。その取りこぼしを compile error で止める。
72
+ const OUTCOME_EXIT_CODES = {
73
+ done: 0,
74
+ running: 5,
75
+ timeout: 3,
76
+ closed: 4,
77
+ };
69
78
  export async function main(argv) {
70
79
  const cmd = parseArgs(argv);
71
80
  const result = await observeAgentDone(cmd.session, {
package/dist/core.js CHANGED
@@ -2938,8 +2938,10 @@ export async function observeAgentDone(name, o = {}) {
2938
2938
  if (scanned.event)
2939
2939
  return observation("done", scanned.event);
2940
2940
  }
2941
+ // timeout=0 は「待たずに一度だけ見る」照会=未完了は失敗ではなく running。
2942
+ // 1秒以上を指定した待機の未完了は従来どおり timeout で、待ち方の意味は変えない。
2941
2943
  if (performance.now() >= deadline)
2942
- return observation("timeout");
2944
+ return observation(timeout === 0 ? "running" : "timeout");
2943
2945
  await sleep(AGENT_DONE_POLL_MS);
2944
2946
  }
2945
2947
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aiterm-mcp",
3
- "version": "0.19.3",
3
+ "version": "0.20.0",
4
4
  "mcpName": "io.github.kitepon-rgb/aiterm-mcp",
5
5
  "description": "AI-driven persistent terminal as a local stdio MCP server (tmux-backed). Holds one local PTY; SSH and containers are just commands you send into it. Also launches interactive Claude/Codex/Grok/Composer agent TUIs in a persistent terminal. Token-reducing reads.",
6
6
  "keywords": [