aiterm-mcp 0.37.5 → 0.37.6
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 +8 -1
- package/README.ja.md +2 -2
- package/README.md +2 -2
- package/dist/core.js +3 -21
- package/dist/psmux-send-worker.js +2 -1
- package/dist/tmux-runtime.js +16 -0
- package/docs/DESIGN.md +6 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.37.6] - 2026-09-19
|
|
11
|
+
|
|
12
|
+
### 修正
|
|
13
|
+
|
|
14
|
+
- WindowsのPowerShellへ複数行を送ると、改行が`Ctrl+Enter`として解釈されて行順が反転し、完了印が処理より先に出る問題を修正した。POSIX shellと同じくscript全体を一括で渡し、現在のshellの変数・作業場所とEnterによる実行開始を保持する。
|
|
15
|
+
|
|
10
16
|
## [0.37.5] - 2026-09-19
|
|
11
17
|
|
|
12
18
|
### 修正
|
|
@@ -1700,7 +1706,8 @@ prototype (preserved under `prototype/python/` as the porting source and referen
|
|
|
1700
1706
|
`ubuntu-latest` for Node 18/20/22, publishing to npm on `v*` tags with
|
|
1701
1707
|
provenance.
|
|
1702
1708
|
|
|
1703
|
-
[Unreleased]: https://github.com/kitepon/aiterm-mcp/compare/v0.37.
|
|
1709
|
+
[Unreleased]: https://github.com/kitepon/aiterm-mcp/compare/v0.37.6...HEAD
|
|
1710
|
+
[0.37.6]: https://github.com/kitepon/aiterm-mcp/compare/v0.37.5...v0.37.6
|
|
1704
1711
|
[0.37.5]: https://github.com/kitepon/aiterm-mcp/compare/v0.37.4...v0.37.5
|
|
1705
1712
|
[0.37.4]: https://github.com/kitepon/aiterm-mcp/compare/v0.37.3...v0.37.4
|
|
1706
1713
|
[0.37.3]: https://github.com/kitepon/aiterm-mcp/compare/v0.37.2...v0.37.3
|
package/README.ja.md
CHANGED
|
@@ -200,7 +200,7 @@ runtime-error store は canonical dotagents config の `collection.enabled: true
|
|
|
200
200
|
場合だけ収集し、既定OFF、network送信は行いません。tag起点CIのnpm provenance(OIDC Trusted
|
|
201
201
|
Publishing)で公開し、GitHub Release が Official MCP Registry を再登録します。
|
|
202
202
|
|
|
203
|
-
**状態:** 開発継続中 · 現行公開版 **v0.37.
|
|
203
|
+
**状態:** 開発継続中 · 現行公開版 **v0.37.6** · 動作対象は Linux · WSL2 · macOS · Windows ネイティブ · MIT · [変更履歴](CHANGELOG.md)。
|
|
204
204
|
|
|
205
205
|
### 更新と巻き戻し
|
|
206
206
|
|
|
@@ -571,7 +571,7 @@ Claudeをリンク経由の`cwd`から起動した場合も、実体パスに対
|
|
|
571
571
|
|
|
572
572
|
`pty_send` はコマンドやpromptの意味を判定せず、指定された本文を端末へ送る。既定ではESC・ブラケットペースト終端などをサニタイズし、`pty_read`も制御文字を無害化して返す(`raw: true`はそのまま扱う)。コマンドの許可・拒否はshell、接続先、起動したharnessが所有する。
|
|
573
573
|
|
|
574
|
-
1回の `pty_send` が受理する本文はUTF-8で最大64KiB。同一sessionへの送信はaiterm processをまたいで直列化し、chunk同士の混線を防ぐ。全OSで長いPTY入力の欠落を避けるためplatformのmultiplexerへUTF-8境界を壊さない256-byte単位でpasteし、chunk間に10msのdrain間隔を置く。POSIX shellが前面にいる時のsanitize
|
|
574
|
+
1回の `pty_send` が受理する本文はUTF-8で最大64KiB。同一sessionへの送信はaiterm processをまたいで直列化し、chunk同士の混線を防ぐ。全OSで長いPTY入力の欠落を避けるためplatformのmultiplexerへUTF-8境界を壊さない256-byte単位でpasteし、chunk間に10msのdrain間隔を置く。POSIX shellまたはPowerShellが前面にいる時のsanitize済み複数行は、改行を含まない単一入力へ符号化する。POSIXは`eval`、PowerShellはUTF-8のBase64を復元したscriptblockのdot-sourceを使い、変数と作業場所を現在のshellに保つ。shellがscript全体を所有してから先頭行を実行するため、途中で起動したpager/REPLが後続行を対話キーとして奪わない。単一行、`raw:true`、非shell前面は従来どおり直接PTYへpasteする。agent dispatchはtmux互換のbracketed paste操作(`paste-buffer -p`)を使う: bracketed paste modeを要求しているpaneへは各chunkを`ESC[200~/201~`で包んで届け、chunk投入中のキー解釈による語中文字化け・submit取り落としを抑える。途中chunkが失敗した場合は部分送信済みであることを明示し、自動でEnterを押さない。送信processの異常終了でlockが残った場合は送信前にfail-closedする。`pty_list`で対象sessionを確認し、`pty_close`で閉じてから同じsession IDを作り直す。公開の一括停止toolは存在しない。
|
|
575
575
|
|
|
576
576
|
## 人が覗く
|
|
577
577
|
|
package/README.md
CHANGED
|
@@ -214,7 +214,7 @@ collection is off by default and performs no network I/O. It ships via
|
|
|
214
214
|
tag-triggered CI with npm provenance (OIDC Trusted Publishing); the GitHub
|
|
215
215
|
Release re-registers the Official MCP Registry entry.
|
|
216
216
|
|
|
217
|
-
**Status:** actively maintained · current public release **v0.37.
|
|
217
|
+
**Status:** actively maintained · current public release **v0.37.6** · 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).
|
|
218
218
|
|
|
219
219
|
### Update and rollback
|
|
220
220
|
|
|
@@ -616,7 +616,7 @@ Claudeをリンク経由の`cwd`から起動した場合も、実体パスに対
|
|
|
616
616
|
|
|
617
617
|
`pty_send` does not interpret command or prompt meaning; it delivers the requested text to the terminal. By default it sanitizes ESC and bracketed-paste terminators, while `pty_read` neutralizes control characters in returned output (`raw: true` keeps them unchanged). The shell, remote endpoint, or launched harness owns command authorization.
|
|
618
618
|
|
|
619
|
-
Each `pty_send` accepts at most 64 KiB of UTF-8 text. Sends to the same session are serialized across aiterm processes so chunks cannot interleave. Every OS pastes through its multiplexer in UTF-8-safe 256-byte chunks with a 10 ms drain interval; macOS, Linux, and WSL2 have all demonstrated silent middle/trailing loss when a long input is pushed without that boundary. Sanitized multiline text sent while a POSIX shell is in the foreground is encoded as one newline-free `eval`
|
|
619
|
+
Each `pty_send` accepts at most 64 KiB of UTF-8 text. Sends to the same session are serialized across aiterm processes so chunks cannot interleave. Every OS pastes through its multiplexer in UTF-8-safe 256-byte chunks with a 10 ms drain interval; macOS, Linux, and WSL2 have all demonstrated silent middle/trailing loss when a long input is pushed without that boundary. Sanitized multiline text sent while a POSIX shell or PowerShell is in the foreground is encoded as one newline-free input (`eval` for POSIX shells; a dot-sourced, UTF-8 Base64-decoded scriptblock for PowerShell): the shell receives the complete script before it runs the first line, so a pager or REPL started mid-script cannot consume later lines as interactive keystrokes. Single-line input, `raw:true`, and non-shell frontends remain direct PTY pastes. Agent dispatches additionally use the tmux-compatible bracketed-paste operation (`paste-buffer -p`): panes that requested bracketed-paste mode receive each chunk wrapped in `ESC[200~/201~`, hardening prompt injection against mid-word key-interpretation corruption and dropped submits. If a later chunk fails, aiterm reports the partial-send state and does not press Enter automatically. A lock left by a terminated sender fails closed before sending; use `pty_list` to confirm the affected session, close it with `pty_close`, then recreate the same session ID. There is no public kill-all tool.
|
|
620
620
|
|
|
621
621
|
## A human can watch
|
|
622
622
|
|
package/dist/core.js
CHANGED
|
@@ -16,7 +16,7 @@ import * as rtk from "./rtk.js";
|
|
|
16
16
|
import { paneTokenHint } from "./harnesses/pane-tokens.js";
|
|
17
17
|
import { readRuntimeProcesses, processSubtree, processIdentity, backgroundProcesses } from "./process-runtime.js";
|
|
18
18
|
import { AitermError, telemetryOwnedFailure, ownTelemetryFailure } from "./errors.js";
|
|
19
|
-
import { isWin, SOCKDIR, tmuxCommand, sendPsmuxPayload, loadPtyBufferChunk, pasteBufferBaseArgs, TMUX_EMPTY_CONFIG, attachCommand, normalizePaneCommand, appendMarkSentinel, markShellCommand, settlePaneLog, paneCwdArgument, sessionEnvironmentLaunch, } from "./tmux-runtime.js";
|
|
19
|
+
import { isWin, SOCKDIR, tmuxCommand, sendPsmuxPayload, loadPtyBufferChunk, pasteBufferBaseArgs, TMUX_EMPTY_CONFIG, attachCommand, normalizePaneCommand, atomicShellMultiline, appendMarkSentinel, markShellCommand, settlePaneLog, paneCwdArgument, sessionEnvironmentLaunch, } from "./tmux-runtime.js";
|
|
20
20
|
import { sleep, currentUid, runtimeStateBase, safeStatSize, readFileRange, writeJson0600, createEmpty0600, shq, LAUNCH_ID_RE, AGENT_DONE_POLL_MS, AGENT_EVENT_MAX_BYTES, assertSessionName, agentsDir, agentEventPath, agentMetadataPath, writeAgentMetadata, AGENT_EVENT_TAIL_BYTES, agentLabel, agentHarness, subagentInstruction, agentLineageFields, } from "./agent-shared.js";
|
|
21
21
|
import { GROK_MODEL_DEFAULTS, realGrokHome, resolveAndValidateGrokAuth, assertGrokModelAvailable, grokEventsTranscript, latestGrokCompletion, observeGrokDone, buildGrokAgentCmd, grokLaunchNote, grokEnvTokens, grokTuiReady, grokTuiBusy, grokPaneObservation, grokStartupAction, grokLaunchBlockingDialog, assertGrokSandboxNotRejected, GROK_COMPOSER_MARKER_RE, grokFooterHasConfiguration, grokTranscriptText, createGrokAgentMetadata, } from "./harnesses/grok.js";
|
|
22
22
|
import { bindCodexTranscriptSession, latestCodexCompletion, observeCodexDone, buildCodexAgentCmd, codexLaunchNote, codexTuiReady, codexPaneObservation, codexApprovalDialog, codexStartupAction, CODEX_COMPOSER_MARKER_RE, codexModelChoice, codexEffortChoice, codexMoreReasoningChoice, codexTranscriptText, createCodexAgentMetadata, } from "./harnesses/codex.js";
|
|
@@ -31,11 +31,6 @@ export const DEFAULT_TIMEOUT = 10.0;
|
|
|
31
31
|
const POLL = 0.25;
|
|
32
32
|
const STABLE_POLLS = 2; // 連続でログサイズ不変ならば静止とみなす回数
|
|
33
33
|
const SHELLS = new Set(["bash", "sh", "zsh", "fish", "dash"]);
|
|
34
|
-
// 通常PTYへ複数行をそのままpasteすると、途中で起動したpager/REPLが後続行を
|
|
35
|
-
// キー入力として消費する。POSIX shell前面では改行を持たないeval 1行へ包み、
|
|
36
|
-
// script全体をshell内部へ取り込んでから実行する。fish等の非POSIX shellや
|
|
37
|
-
// ssh/REPL前面は従来の生pasteを維持する。
|
|
38
|
-
const ATOMIC_MULTILINE_SHELLS = new Set(["bash", "sh", "zsh", "dash"]);
|
|
39
34
|
// mark の sentinel は POSIX シェル構文(; と "$?")に依存する。これらの非 POSIX 対話シェルが
|
|
40
35
|
// 前面のときは "$?" が正しく展開されず sentinel が壊れるので mark を拒否する(B8)。ssh/docker で
|
|
41
36
|
// リモート POSIX シェルに入っている場合は前面が "ssh"/"docker" 等で本集合に含まれず=許可される。
|
|
@@ -270,19 +265,6 @@ function splitPtyText(text) {
|
|
|
270
265
|
chunks.push(chunk);
|
|
271
266
|
return chunks;
|
|
272
267
|
}
|
|
273
|
-
function quoteForPrintfB(text) {
|
|
274
|
-
return text
|
|
275
|
-
.replace(/\\/g, "\\\\")
|
|
276
|
-
.replace(/\n/g, "\\n")
|
|
277
|
-
.replace(/\r/g, "\\r")
|
|
278
|
-
.replace(/\t/g, "\\t")
|
|
279
|
-
.replace(/'/g, `'"'"'`);
|
|
280
|
-
}
|
|
281
|
-
function atomicShellMultiline(text) {
|
|
282
|
-
// POSIX printf %bで元の改行・backslashを復元し、evalは現在shell内で実行する。
|
|
283
|
-
// command substitutionが末尾LFを落とす点は、pty_sendのsubmitを担うEnterと同値。
|
|
284
|
-
return `eval "$(command printf '%b' '${quoteForPrintfB(text)}')"`;
|
|
285
|
-
}
|
|
286
268
|
function assertSendTextSize(text, context = "送信文字列") {
|
|
287
269
|
const bytes = Buffer.byteLength(text, "utf8");
|
|
288
270
|
if (bytes > MAX_SEND_BYTES) {
|
|
@@ -792,8 +774,8 @@ export function send(name, text, o = {}) {
|
|
|
792
774
|
text = appendMarkSentinel(text, fg);
|
|
793
775
|
assertSendTextSize(text, o.rtk || o.mark ? "変換後の送信文字列" : "送信文字列");
|
|
794
776
|
const reportedText = text;
|
|
795
|
-
if (!o.raw && text.includes("\n")
|
|
796
|
-
text = atomicShellMultiline(text);
|
|
777
|
+
if (!o.raw && text.includes("\n")) {
|
|
778
|
+
text = atomicShellMultiline(text, fg || paneCurrentCommand(name));
|
|
797
779
|
}
|
|
798
780
|
if (o.mark) {
|
|
799
781
|
try {
|
|
@@ -2,7 +2,8 @@ import * as fs from "node:fs";
|
|
|
2
2
|
import * as net from "node:net";
|
|
3
3
|
import * as os from "node:os";
|
|
4
4
|
import * as path from "node:path";
|
|
5
|
-
|
|
5
|
+
// 公開本文64KiBをPowerShellの一括入力へBase64化した長さと構文・paste markerを含む。
|
|
6
|
+
const MAX_PAYLOAD_BYTES = Math.ceil(64 * 1024 / 3) * 4 + 128;
|
|
6
7
|
const PTY_CHUNK_BYTES = 256;
|
|
7
8
|
const MAX_FINAL_DRAIN_MS = 3_000;
|
|
8
9
|
const SESSION_BASE_RE = /^[A-Za-z0-9_-]{1,160}$/;
|
package/dist/tmux-runtime.js
CHANGED
|
@@ -217,6 +217,22 @@ export function normalizePaneCommand(cmd) {
|
|
|
217
217
|
}
|
|
218
218
|
// 完了マーカーの方言は実効shellで決める。SSH先のshellはhost OSやsshのprocess名と異なる。
|
|
219
219
|
const POWERSHELL_COMMANDS = new Set(["powershell", "pwsh"]);
|
|
220
|
+
const POSIX_ATOMIC_SHELLS = new Set(["bash", "sh", "zsh", "dash"]);
|
|
221
|
+
// shellにscript全体を取り込ませてから現在のscopeで実行する。生LFはWindowsの
|
|
222
|
+
// Console.ReadKeyでCtrl+Enterとなり、PSReadLineでは行が逆順に挿入される。
|
|
223
|
+
// OSで仕組みを変えず、同じ一括入力を各shellの構文へ適合させる。
|
|
224
|
+
export function atomicShellMultiline(text, foreground) {
|
|
225
|
+
if (POWERSHELL_COMMANDS.has(foreground)) {
|
|
226
|
+
const encoded = Buffer.from(text, "utf8").toString("base64");
|
|
227
|
+
return `. ([scriptblock]::Create([Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('${encoded}'))))`;
|
|
228
|
+
}
|
|
229
|
+
if (!POSIX_ATOMIC_SHELLS.has(foreground))
|
|
230
|
+
return text;
|
|
231
|
+
const quoted = text.replace(/\\/g, "\\\\").replace(/\n/g, "\\n")
|
|
232
|
+
.replace(/\r/g, "\\r").replace(/\t/g, "\\t").replace(/'/g, `'"'"'`);
|
|
233
|
+
// printf %bで本文を復元する。末尾LFの除去はpty_sendのsubmit Enterと同値。
|
|
234
|
+
return `eval "$(command printf '%b' '${quoted}')"`;
|
|
235
|
+
}
|
|
220
236
|
export function markShellCommand(foreground, screen) {
|
|
221
237
|
if (POWERSHELL_COMMANDS.has(foreground))
|
|
222
238
|
return foreground;
|
package/docs/DESIGN.md
CHANGED
|
@@ -22,6 +22,12 @@ Claude/CursorのJSONは参照先を原子的に更新して変更前backupを
|
|
|
22
22
|
SSHやcontainerを別toolにせず、PTY内で実行するcommandとして扱う。sessionはPOSIXではtmux、
|
|
23
23
|
Windows nativeではpsmux 3.3.8以上に保存され、MCP serverやclientの再起動をまたぐ。
|
|
24
24
|
|
|
25
|
+
sanitize済みの複数行は、POSIX shellでもPowerShellでもscript全体を取り込んでから記述順に実行する。
|
|
26
|
+
`src/tmux-runtime.ts`が改行を持たない1回の入力へ適合させ、POSIXは`eval`、PowerShellは
|
|
27
|
+
UTF-8のBase64を復元したscriptblockのdot-sourceを使う。変数と作業場所は現在のshellに残す。
|
|
28
|
+
生LFをPowerShellへキー入力として流さないため、Windowsの`Ctrl+Enter`による行順の反転を防ぐ。
|
|
29
|
+
単一行、`raw:true`、非shell前面は直接PTYへ送る。`enter:false`では後続のEnterまで実行しない。
|
|
30
|
+
|
|
25
31
|
`pty_read`は制御文字除去、反復圧縮、head+tail、command別reducerでcontext量を減らす。
|
|
26
32
|
完了はprocess exit、shell sentinel、literal/regex `until`、shell復帰を伴うquiescence、timeoutを区別する。
|
|
27
33
|
要求されたsentinel/untilを静止判定より優先し、nested shellで証拠がない状態を完了へ丸めない。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aiterm-mcp",
|
|
3
|
-
"version": "0.37.
|
|
3
|
+
"version": "0.37.6",
|
|
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": [
|