aiterm-mcp 0.61.16 → 0.61.17
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 +9 -1
- package/README.ja.md +2 -12
- package/README.md +4 -16
- package/dist/core.js +8 -0
- package/dist/execution-immediate-stop.js +8 -2
- package/dist/execution-native-server.js +29 -7
- package/dist/execution-native-setup.js +20 -25
- package/docs/DESIGN.md +17 -126
- package/docs/RELEASE.md +8 -7
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.61.17] - 2026-10-24
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- Ordinary MCP delivery and parent-return hooks no longer enter the shared execution tracking dispatcher, participant enrollment or writer mutex. The legacy native MCP entry provides the standard delivery handlers plus direct leaf-first stop; hosts must remove mandatory ExecutionBridge registration.
|
|
15
|
+
- Stop forwarding reads existing agent parent relationships and sends normal interruption keys without shared graph access or writes. A lineage read failure still forwards the explicit root command. Native hook setup migrates back to the standard parent hook scripts.
|
|
16
|
+
|
|
10
17
|
## [0.61.16] - 2026-10-24
|
|
11
18
|
|
|
12
19
|
### Fixed
|
|
@@ -2854,7 +2861,8 @@ prototype (preserved under `prototype/python/` as the porting source and referen
|
|
|
2854
2861
|
`ubuntu-latest` for Node 18/20/22, publishing to npm on `v*` tags with
|
|
2855
2862
|
provenance.
|
|
2856
2863
|
|
|
2857
|
-
[Unreleased]: https://github.com/kitepon/aiterm-mcp/compare/v0.61.
|
|
2864
|
+
[Unreleased]: https://github.com/kitepon/aiterm-mcp/compare/v0.61.17...HEAD
|
|
2865
|
+
[0.61.17]: https://github.com/kitepon/aiterm-mcp/compare/v0.61.16...v0.61.17
|
|
2858
2866
|
[0.61.16]: https://github.com/kitepon/aiterm-mcp/compare/v0.61.15...v0.61.16
|
|
2859
2867
|
[0.61.15]: https://github.com/kitepon/aiterm-mcp/compare/v0.61.14...v0.61.15
|
|
2860
2868
|
[0.61.14]: https://github.com/kitepon/aiterm-mcp/compare/v0.61.13...v0.61.14
|
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.61.
|
|
212
|
+
**状態:** 開発継続中 · 現行公開版 **v0.61.17** · 動作対象は Linux · WSL2 · macOS · Windows ネイティブ · MIT · [変更履歴](CHANGELOG.md)。
|
|
213
213
|
|
|
214
214
|
### 更新と巻き戻し
|
|
215
215
|
|
|
@@ -742,20 +742,10 @@ agent_launch({ "harness": "codex-cli", "remote": { "host": "rabbit" }, "cwd": "/
|
|
|
742
742
|
|
|
743
743
|
BellTeamのmodel・effort・fast変更も、既存session世代に結合したnative管理要求で受け付ける。途中で世代・受付枠・停止状態が変われば、それ以降の打鍵を止める。途中まで変更した結果は作用不明のまま保持し、自動でやり直さない。
|
|
744
744
|
|
|
745
|
-
POSIXの明示native入口でも、`agent_auth`の名前なし開始、認証済みで何も起こさない開始、既存v1の確認・初回案内・取消を受け付ける。認証PTYは実際の作成元nativeと世代へ結合する。BellTeamの参照なし入力・キーは、この証拠がある認証PTYにだけ許可し、通常agentの本文には配送参照を引き続き必要とする。作成証拠のない旧認証metadataを自動登録しない。
|
|
746
|
-
|
|
747
|
-
この明示入口では `agent_execution` の `reconcile_launch` に元の `request` と正確な `target: {session_id, launch_id}` を渡し、結果不明の空起動を既存世代へ結合できる。保存したnative/serverと現在のmanaged世代、raw状態で初期promptなし、生存して入力待ちのharnessをmetadata受付内で照合し、該当するunknown launch枠だけを解放する。受付済みでも本文未発行なら、照合を繰り返すたびに現在世代・入力待ち・競合操作なしを再確認する。保存した受付結果だけで後の世代を確認済みとしない。起動・打鍵・close・本文再送は行わない。issuedのRPC、入力状態不明、世代交代や世代未確認は拒否する。後続本文は元参照で通常のsend受付を通して一度だけ発行する。照合成功は失われた元RPC receiptの回収を意味しない。
|
|
748
|
-
|
|
749
|
-
CLIが終了した結果不明の空起動には、BellTeam native入口の `agent_execution({action: "close_launch", request, target: {session_id, launch_id}})` を明示的に使う。元requestと期待世代を受付内とnative close直前で照合し、原native/server・managed世代一致、raw初期prompt `none`・初期配送なし・send未発行・現在CLI終了の正規probeがすべて必要になる。Claude CodeとCodexで同じ証明条件を使う。生存・issued・送信済み・欠測・世代交代は拒否し、sessionだけのcloseへの代用や自動再起動・再送はしない。旧版は新actionを拒否する。
|
|
750
|
-
|
|
751
|
-
成功時の `structuredContent` は応答するSDKの別管理requestのExecutionRecordで、元unknown recordは変えない。`_meta["aiterm/closed_launch"]` に厳密なreceiptを返す。固定項目は `schema: "aiterm.closed-launch.v1"`、`version: 1`、`action: "close_launch"`、`outcome: "closed"`、元 `request`、正確な `target`、`management_ref`(応答SDKのMCP request、`tool: "pty_close"`)。`evidence` は原 `native` binding、`initial_prompt: "none"`、`initial_prompt_delivery: null`、`harness_alive: false`、`absence_confirmed: true`、`metadata_committed: true` を持つ。実close・不在確認・slot解放commitが揃った場合だけ返し、失敗や結果不明には返さない。本体が不明を解除する際は元pending操作と自身のstop/versionも照合する。過去receiptで後発の不明を解除しない。
|
|
752
|
-
|
|
753
|
-
同じ明示入口で、返却済みunknown launchのCLIが終了している場合は、元native/server・managed世代とraw初期promptなし・本文未発行・harness終了を同期検証できた時だけ通常の`pty_close`で対象席を閉じられる。成功と不在を確認して該当枠だけを外し、元unknown requestを保持する。発行中RPC、生存harness、入力や世代の欠測は拒否する。旧requestを再実行せず、必要な後続は新しい通常要求として行う。
|
|
754
|
-
|
|
755
745
|
|
|
756
746
|
## 人が覗く
|
|
757
747
|
|
|
758
|
-
|
|
748
|
+
通常の配送と親への返答は、実行追跡用の共有lockを取得も待機もしない。旧native入口も通常配送と末端優先の`agent_stop`を提供し、`agent_execution`登録を要求しない。この入口を使う本体もExecutionBridgeの先行登録を外す。記録の失敗で配送を止めない。
|
|
759
749
|
|
|
760
750
|
セッションは共有tmux socket(Windows nativeはpsmux namespace)上にある。`pty_open`/`agent_launch`の戻り値に表示されるattachコマンドで、人間がClaude/Codex/Grok/Cursor harnessの同じ端末へ入り、途中でキーボードを引き取れる。
|
|
761
751
|
POSIXでは、tmuxのソケットがまだ無くても最初の`agent_launch`でserverを起動できる。Aitermは作成したsessionとserverを実際のreceiptから照合して受付を確定し、不明な結果を入力の再送で補わない。
|
package/README.md
CHANGED
|
@@ -227,7 +227,7 @@ collection is off by default and performs no network I/O. It ships via
|
|
|
227
227
|
tag-triggered CI with npm provenance (OIDC Trusted Publishing); the GitHub
|
|
228
228
|
Release re-registers the Official MCP Registry entry.
|
|
229
229
|
|
|
230
|
-
**Status:** actively maintained · current public release **v0.61.
|
|
230
|
+
**Status:** actively maintained · current public release **v0.61.17** · 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).
|
|
231
231
|
|
|
232
232
|
### Update and rollback
|
|
233
233
|
|
|
@@ -791,22 +791,14 @@ agent_launch({ "harness": "codex-cli", "remote": { "host": "rabbit" }, "cwd": "/
|
|
|
791
791
|
|
|
792
792
|
### Input and output
|
|
793
793
|
|
|
794
|
+
Ordinary delivery and parent-return hooks do not acquire or wait for the shared execution tracking lock. The legacy native entry now serves ordinary delivery plus leaf-first `agent_stop`, without `agent_execution` registration. Hosts using that entry must remove mandatory ExecutionBridge registration; recording failure must not prevent delivery.
|
|
795
|
+
|
|
794
796
|
`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.
|
|
795
797
|
|
|
796
|
-
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 wrap the whole text once in `ESC[200~/201~` and stream the wrapped text in the same chunks, so the agent TUI sees one paste (an image path is never split across pastes), 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.
|
|
798
|
+
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 wrap the whole text once in `ESC[200~/201~` and stream the wrapped text in the same chunks, so the agent TUI sees one paste (an image path is never split across pastes), 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.
|
|
797
799
|
|
|
798
800
|
## A human can watch
|
|
799
801
|
|
|
800
|
-
In the opt-in POSIX native execution entry, an ordinary message arriving at a verified caller can overlap that caller's outgoing send. It does not replace the caller's generation or clear either request's slot. A newly connected participant also waits within the existing bounded metadata admission to commit its declared roles before its first asynchronous request; that wait never replays input. Agent paste/submit segments wait for metadata mutex contention before input; uncertain operations, generation changes and stops still prevent input. BellTeam may explicitly recreate a closed session with a promptless management `agent_launch`; sending a prompt still requires its original execution reference.
|
|
801
|
-
|
|
802
|
-
An explicit `agent_execution` action `reconcile_launch` can bind an existing empty launch after a lost launch result in this opt-in entry. Supply the original `request` and exact `target: {session_id, launch_id}`. The server checks the original native/server identity, current managed generation, raw no-prompt state and a live ready harness under metadata admission, then releases only that unknown launch slot. Repeating an accepted empty launch before its send also rechecks the current generation, readiness and absence of competing session operations; a saved acceptance alone cannot confirm a later generation. It never launches, types, closes or resends. `issued` RPCs, unknown input and changed or unverified generations remain blocked. Any subsequent body uses the original reference through normal send admission once; a successful reconciliation does not prove the lost RPC receipt.
|
|
803
|
-
|
|
804
|
-
For an empty unknown launch whose harness has exited, the BellTeam native entry accepts `agent_execution({action: "close_launch", request, target: {session_id, launch_id}})`. The original request and generation are atomic expectations, checked within admission and immediately before the native close. Raw initial prompt must be `none`, initial delivery absent, send unissued, and the original native/server and managed identity must match. The private runtime proof covers Claude Code and Codex; live, issued, sent, missing or replaced targets remain refused. No session-only close fallback or automatic relaunch/send occurs. Older servers reject this action.
|
|
805
|
-
|
|
806
|
-
Success retains the original unknown record and returns the serving SDK's distinct management execution record in `structuredContent`. `_meta["aiterm/closed_launch"]` is a strict receipt with `schema: "aiterm.closed-launch.v1"`, `version: 1`, `action: "close_launch"`, `outcome: "closed"`, the original `request`, exact `target`, and `management_ref` (the serving MCP request, `tool: "pty_close"`). Its `evidence` contains original `native` binding, `initial_prompt: "none"`, `initial_prompt_delivery: null`, `harness_alive: false`, `absence_confirmed: true`, and `metadata_committed: true`. Only confirmed close, absence and committed slot release produce this receipt. Errors or lost/uncertain results do not. Hosts must match the original pending operation and local stop/version state before clearing its uncertainty; historical receipts cannot clear later uncertainty.
|
|
807
|
-
|
|
808
|
-
For a returned unknown launch whose harness has exited, the same native entry admits explicit `pty_close` only after synchronous proof of the original native/server and managed generation, raw no-initial-prompt state, an unissued body send and an exited harness. It releases the failed launch slot after successful close and confirmed absence, preserving the original unknown record. Issued RPCs, live harnesses and missing input or generation evidence remain blocked. The old request is never replayed; a later ordinary request may create a fresh generation.
|
|
809
|
-
|
|
810
802
|
|
|
811
803
|
On native Windows, non-raw commands sent to a PowerShell shell use UTF-8 for Console input/output and native pipelines. Runtime additions to the caller PATH are passed to new panes; raw PTY input is unchanged.
|
|
812
804
|
Agent launches use a PowerShell 7 pane and pass the harness argv directly; accepted shebang wrappers use noninteractive Git Bash in that same pane. The owned startup script is sent as one ASCII line, while agent TUI bodies retain their literal text.
|
|
@@ -814,10 +806,6 @@ Agent launches use a PowerShell 7 pane and pass the harness argv directly; accep
|
|
|
814
806
|
Sessions live on a shared tmux socket on POSIX or a shared psmux namespace on native Windows. The attach line printed by `pty_open` and `agent_launch` lets a human attach to the same terminal and intervene, including a Claude/Codex/Grok/Cursor harness session: `tmux -S … attach -t <id>` on POSIX, or `psmux -L <namespace> attach -t <id>` on native Windows.
|
|
815
807
|
On POSIX, the first `agent_launch` can create the tmux server when its socket does not yet exist. Aiterm verifies the exact created session and server before accepting that launch; an uncertain result is reported without retrying the input.
|
|
816
808
|
|
|
817
|
-
BellTeam model, effort and fast changes use a native management request bound to the existing session generation. Later stages stop if that generation, its admission slot or stop state changes. A partial change remains an uncertain effect and must not be blindly repeated.
|
|
818
|
-
|
|
819
|
-
In the opt-in POSIX native entry, `agent_auth` also supports omitted session names, authenticated no-op starts and the normal v1 status/onboarding/cancel receipts. Authentication PTYs are bound to their actual native creator and generation. Ref-less BellTeam input or keys are allowed only for those proven authentication PTYs; ordinary agent messages still require their delivery reference. Legacy authentication metadata without creator proof is not automatically enrolled.
|
|
820
|
-
|
|
821
809
|
## Requirements
|
|
822
810
|
|
|
823
811
|
- **Node.js >= 18**
|
package/dist/core.js
CHANGED
|
@@ -1805,6 +1805,14 @@ export function listSessions(result = listSessionsResult()) {
|
|
|
1805
1805
|
}
|
|
1806
1806
|
return "(セッション無し)";
|
|
1807
1807
|
}
|
|
1808
|
+
/** Existing agent lineage is enough to forward a stop from leaves to parent.
|
|
1809
|
+
* This reads ordinary session metadata and never opens the execution graph. */
|
|
1810
|
+
export function agentSessionChildren() {
|
|
1811
|
+
return listSessionsResult().sessions.flatMap(({ session_id }) => {
|
|
1812
|
+
const parent = tryLoadAgentMetadata(session_id)?.parent_session_id;
|
|
1813
|
+
return parent ? [{ parent, child: session_id }] : [];
|
|
1814
|
+
});
|
|
1815
|
+
}
|
|
1808
1816
|
/**
|
|
1809
1817
|
* `pty_list` 相当を read-only に照会し、内容を返さず session 件数だけを返す。
|
|
1810
1818
|
* session 名・前面コマンド・PTY 出力を診断応答へ持ち出さないため、factory が安全に readiness を
|
|
@@ -12,9 +12,12 @@ export const immediateStopResultSchema = z.object({
|
|
|
12
12
|
}).strict();
|
|
13
13
|
export function interruptKnownSessions(input, dependencies) {
|
|
14
14
|
const args = immediateStopInputSchema.parse(input), roots = [...new Set(args.session_ids ?? [args.session_id])];
|
|
15
|
-
let relations = [], graphUnavailable = false;
|
|
15
|
+
let relations = [], children = [], graphUnavailable = false;
|
|
16
16
|
try {
|
|
17
|
-
|
|
17
|
+
if (dependencies.children)
|
|
18
|
+
children = dependencies.children();
|
|
19
|
+
else if (dependencies.relations)
|
|
20
|
+
relations = unfinishedExecutionRelations(dependencies.relations());
|
|
18
21
|
}
|
|
19
22
|
catch {
|
|
20
23
|
graphUnavailable = true;
|
|
@@ -25,6 +28,9 @@ export function interruptKnownSessions(input, dependencies) {
|
|
|
25
28
|
if (visited.has(key))
|
|
26
29
|
return;
|
|
27
30
|
visited.add(key);
|
|
31
|
+
for (const child of children)
|
|
32
|
+
if (child.parent === name)
|
|
33
|
+
visit(child.child);
|
|
28
34
|
for (const edge of relations)
|
|
29
35
|
if (edge.source?.launch.session_id === name
|
|
30
36
|
&& (!launchId || edge.source.launch.launch_id === launchId) && edge.target)
|
|
@@ -14,6 +14,28 @@ import { AITERM_PROFILE } from "./steer-profile.js";
|
|
|
14
14
|
import { EXECUTION_SOURCE_ENV_NAMES, EXECUTION_SCOPE_ENV_NAMES } from "./execution-runtime.js";
|
|
15
15
|
import { observeExecutionActor } from "./process-runtime.js";
|
|
16
16
|
import { ExecutionError } from "./execution-wire.js";
|
|
17
|
+
import { createAitermServer } from "./index.js";
|
|
18
|
+
import { immediateStopInputSchema, immediateStopResultSchema } from "./execution-immediate-stop.js";
|
|
19
|
+
/** Ordinary delivery and leaf-first cancel keys have no execution-store
|
|
20
|
+
* registration, participant gate, shared transaction or graph write. */
|
|
21
|
+
export function createNativeDeliveryServer(dependencies = {}) {
|
|
22
|
+
const server = createAitermServer();
|
|
23
|
+
server.registerTool("agent_stop", {
|
|
24
|
+
description: "指定sessionとその呼出先へ末端から通常の停止キーを送る。sentはキー送信結果であり終了の証明ではない。",
|
|
25
|
+
inputSchema: immediateStopInputSchema.shape,
|
|
26
|
+
outputSchema: immediateStopResultSchema.shape,
|
|
27
|
+
}, async (args) => {
|
|
28
|
+
const result = interruptKnownSessions(args, {
|
|
29
|
+
children: dependencies.children ?? core.agentSessionChildren,
|
|
30
|
+
currentLaunchId: dependencies.currentLaunchId ?? core.interruptionLaunchId,
|
|
31
|
+
sendKey: dependencies.sendKey ?? core.interruptSessionNow,
|
|
32
|
+
});
|
|
33
|
+
return { content: [{ type: "text", text: JSON.stringify(result) }], structuredContent: result };
|
|
34
|
+
});
|
|
35
|
+
return server;
|
|
36
|
+
}
|
|
37
|
+
/** Historical injected tracking composition. Normal CLI delivery does not
|
|
38
|
+
* construct this participant or register its execution controls. */
|
|
17
39
|
export function createNativeExecutionServer(input) {
|
|
18
40
|
if (input.interruptCurrentRun !== true || !input.expectedScope || !path.isAbsolute(input.expectedScope.state_root)
|
|
19
41
|
|| input.expectedScope.multiplexer?.kind !== "socket" || !path.isAbsolute(input.expectedScope.multiplexer.key))
|
|
@@ -90,6 +112,7 @@ function nativeParentDependencies(provider, profile) {
|
|
|
90
112
|
},
|
|
91
113
|
processes: readProcessIdentities, exists: nativeProcessExists, now: () => performance.now(), wall: () => Date.now() };
|
|
92
114
|
}
|
|
115
|
+
/** Historical injected worker; normal parent-hook CLI no longer uses it. */
|
|
93
116
|
export function createNativeExecutionWorker(input) {
|
|
94
117
|
if (input.interruptCurrentRun !== true || !input.expectedScope || !path.isAbsolute(input.expectedScope.state_root)
|
|
95
118
|
|| input.expectedScope.multiplexer?.kind !== "socket" || !path.isAbsolute(input.expectedScope.multiplexer.key))
|
|
@@ -116,23 +139,22 @@ export function parseNativeExecutionArguments(args) {
|
|
|
116
139
|
}
|
|
117
140
|
async function main() {
|
|
118
141
|
const options = parseNativeExecutionArguments(process.argv.slice(2));
|
|
119
|
-
const provider = await import(pathToFileURL(options.providerFile).href);
|
|
120
142
|
if (options.mode === "mcp") {
|
|
121
|
-
|
|
122
|
-
await participant.server.connect(new StdioServerTransport());
|
|
143
|
+
await createNativeDeliveryServer().connect(new StdioServerTransport());
|
|
123
144
|
}
|
|
124
145
|
else {
|
|
146
|
+
const provider = await import(pathToFileURL(options.providerFile).href);
|
|
125
147
|
const method = options.mode === "claude-hook" ? "runClaudeHookMain" : options.mode === "cursor-hook" ? "runCursorHookMain" : "runCodexHookMain";
|
|
126
148
|
const hookProvider = provider;
|
|
127
149
|
if (typeof hookProvider[method] !== "function")
|
|
128
150
|
throw new ExecutionError("EXECUTION_UNSUPPORTED");
|
|
129
|
-
const
|
|
151
|
+
const profile = { ...AITERM_PROFILE, state_root: () => options.expectedScope.state_root };
|
|
130
152
|
if (options.mode === "claude-hook")
|
|
131
|
-
await hookProvider.runClaudeHookMain(
|
|
153
|
+
await hookProvider.runClaudeHookMain(profile, path.join(options.expectedScope.state_root, "claude-parent-hooks"));
|
|
132
154
|
else if (options.mode === "cursor-hook")
|
|
133
|
-
await hookProvider.runCursorHookMain(
|
|
155
|
+
await hookProvider.runCursorHookMain(profile, path.join(options.expectedScope.state_root, "cursor-parent-hooks"));
|
|
134
156
|
else
|
|
135
|
-
await hookProvider.runCodexHookMain(
|
|
157
|
+
await hookProvider.runCodexHookMain(profile, options.hookDirectory);
|
|
136
158
|
}
|
|
137
159
|
}
|
|
138
160
|
let entry = false;
|
|
@@ -5,60 +5,55 @@ import { pathToFileURL } from "node:url";
|
|
|
5
5
|
import { parseNativeExecutionArguments } from "./execution-native-server.js";
|
|
6
6
|
import { AITERM_PROFILE } from "./steer-profile.js";
|
|
7
7
|
import { ExecutionError } from "./execution-wire.js";
|
|
8
|
+
import { codexHookCommand } from "./setup-codex-hooks.js";
|
|
8
9
|
export async function configureNativeExecutionHooks(home, options) {
|
|
9
10
|
if (process.platform === "win32" || !path.isAbsolute(home) || !path.isAbsolute(options.registration.command)
|
|
10
11
|
|| !path.isAbsolute(options.registration.args[0] ?? "") || path.basename(options.registration.args[0]) !== "execution-native-server.js")
|
|
11
12
|
throw new ExecutionError("EXECUTION_INVALID");
|
|
12
|
-
const
|
|
13
|
-
const parsed = parseNativeExecutionArguments(
|
|
13
|
+
const previousRegistration = structuredClone(options.registration), scope = structuredClone(options.expectedScope);
|
|
14
|
+
const parsed = parseNativeExecutionArguments(previousRegistration.args.slice(1));
|
|
14
15
|
if (parsed.mode !== "mcp" || JSON.stringify(parsed.expectedScope) !== JSON.stringify(scope)
|
|
15
16
|
|| path.resolve(parsed.providerFile) !== path.resolve(options.providerFile))
|
|
16
17
|
throw new ExecutionError("EXECUTION_CONFLICT");
|
|
17
18
|
const provider = options.provider ?? await import(pathToFileURL(options.providerFile).href);
|
|
18
|
-
if (provider.DELIVERY_ADMISSION_CONTRACT?.native_hook_args !== true)
|
|
19
|
-
throw new ExecutionError("EXECUTION_UNSUPPORTED");
|
|
20
19
|
const clients = [...new Set(options.clients ?? ["claude", "cursor", "codex"])];
|
|
21
20
|
if (clients.some(client => !["claude", "cursor", "codex"].includes(client))
|
|
22
21
|
|| (clients.includes("codex") && (!options.codexBinary || !path.isAbsolute(options.codexBinary))))
|
|
23
22
|
throw new ExecutionError("EXECUTION_INVALID");
|
|
23
|
+
const dist = path.dirname(previousRegistration.args[0]);
|
|
24
|
+
const registration = { command: previousRegistration.command, args: [path.join(dist, "index.js")] };
|
|
24
25
|
const profile = { ...AITERM_PROFILE, state_root: () => scope.state_root,
|
|
25
|
-
config_root: () => path.join(home, ".config", "aiterm-mcp")
|
|
26
|
-
|
|
26
|
+
config_root: () => path.join(home, ".config", "aiterm-mcp") };
|
|
27
|
+
const previousProfile = { ...profile, hooks: {
|
|
28
|
+
claude: path.basename(previousRegistration.args[0]), cursor: path.basename(previousRegistration.args[0]), codex: path.basename(previousRegistration.args[0]),
|
|
27
29
|
} };
|
|
28
|
-
|
|
29
|
-
// non-secret scope roots before Node loads its native constants; preserve
|
|
30
|
-
// the caller's dynamic source/launch env instead of stamping a setup-time ID.
|
|
31
|
-
const prefix = ["AITERM_STATE_BASE=" + path.dirname(scope.state_root),
|
|
32
|
-
"TMPDIR=" + path.dirname(path.dirname(scope.multiplexer.key)), registration.command, registration.args[0],
|
|
33
|
-
"--execution-interrupt", "--state-root", scope.state_root, "--socket", scope.multiplexer.key,
|
|
34
|
-
"--steer-provider", options.providerFile];
|
|
35
|
-
const hook = (mode, extra = []) => ({ command: "/usr/bin/env", script: prefix[0], args: [...prefix.slice(1), "--mode", mode, ...extra] });
|
|
30
|
+
const hook = (file) => ({ command: registration.command, script: path.join(dist, file) });
|
|
36
31
|
const quote = (word) => "'" + word.replace(/'/g, "'\"'\"'") + "'";
|
|
37
|
-
const command = (
|
|
32
|
+
const command = (file) => [registration.command, path.join(dist, file)].map(quote).join(" ");
|
|
38
33
|
const result = {}, commands = {};
|
|
39
34
|
if (clients.includes("claude")) {
|
|
40
35
|
const file = path.join(home, ".claude", "settings.json");
|
|
41
|
-
const removed = provider.removeClaudeParentHooks(
|
|
42
|
-
result.claude = provider.mergeClaudeParentHooks(profile, file, hook(
|
|
36
|
+
const removed = provider.removeClaudeParentHooks(previousProfile, file);
|
|
37
|
+
result.claude = provider.mergeClaudeParentHooks(profile, file, hook(profile.hooks.claude));
|
|
43
38
|
if (removed === "removed" && result.claude === "unchanged")
|
|
44
39
|
result.claude = "configured";
|
|
45
|
-
commands.claude = "exec " + command(
|
|
40
|
+
commands.claude = "exec " + command(profile.hooks.claude);
|
|
46
41
|
}
|
|
47
42
|
if (clients.includes("cursor")) {
|
|
48
43
|
const file = path.join(home, ".cursor", "hooks.json");
|
|
49
|
-
const removed = provider.removeCursorParentHooks(
|
|
50
|
-
result.cursor = provider.mergeCursorParentHooks(profile, file, hook(
|
|
44
|
+
const removed = provider.removeCursorParentHooks(previousProfile, file);
|
|
45
|
+
result.cursor = provider.mergeCursorParentHooks(profile, file, hook(profile.hooks.cursor));
|
|
51
46
|
if (removed === "removed" && result.cursor === "unchanged")
|
|
52
47
|
result.cursor = "configured";
|
|
53
|
-
commands.cursor = command(
|
|
48
|
+
commands.cursor = command(profile.hooks.cursor);
|
|
54
49
|
}
|
|
55
50
|
if (clients.includes("codex")) {
|
|
56
51
|
const directory = path.join(home, ".config", "aiterm-mcp", "codex-parent-hooks"), codexHome = path.join(home, ".codex");
|
|
57
|
-
const
|
|
52
|
+
const hookFile = path.join(dist, profile.hooks.codex);
|
|
58
53
|
const runtime = { ...options.codexRuntime, directory, codex_home: codexHome, node: registration.command,
|
|
59
|
-
hook:
|
|
54
|
+
hook: hookFile, findBinary: () => options.codexBinary };
|
|
60
55
|
result.codex = await provider.configureCodexSteer(profile, "enable", runtime);
|
|
61
|
-
commands.codex =
|
|
56
|
+
commands.codex = codexHookCommand(registration.command, hookFile, directory);
|
|
62
57
|
}
|
|
63
|
-
return { results: result, commands, registration, relation_scope: "
|
|
58
|
+
return { results: result, commands, registration, relation_scope: "untracked" };
|
|
64
59
|
}
|
package/docs/DESIGN.md
CHANGED
|
@@ -1,93 +1,22 @@
|
|
|
1
1
|
# Aiterm design
|
|
2
2
|
|
|
3
|
-
##
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
serving producerは最初のawait前にnative decoder/session/tool/ownerを元requestへ固定し、欠測を後で補完しない。Claude ownerは同じharness PID/startで、別のMCP/hook descendantを代用しない。source入力のnative受理/turn aliasではない。
|
|
21
|
-
別processのhookは同じscopeと既存delivery bindingを照合し、callback欠測時に旧配送へfallbackしない。
|
|
22
|
-
processごとのrequired profile factoryは隔離実装中であり、static profileや稼働hookへは未接続。
|
|
23
|
-
scope一致やhook返却だけで全参加者の被覆・native turn alias・終了fenceを証明したことにはしない。
|
|
24
|
-
Claudeのproducerは実PreToolUse owner/tool/sessionと配送bindingを作用直前にも確認する隔離factoryを持つ。
|
|
25
|
-
既存parent returnが未解決なら局所doneのfenceを閉じず、元dispatch receiptの遅着は入力を再送せずmetadataだけを待つ。
|
|
26
|
-
native emit直前に照合したhook参照は既存deliveryへ保存する。CodexのStop/PostToolUse、Claudeのtool、Cursorのconversationを
|
|
27
|
-
受取executionの完了と同一視せず、canonical cursorを作らない。受取番の対応と終了fenceの証拠は別に必要。
|
|
28
|
-
POSIXのraw tty回復もnative作用であり、tmux打鍵と同じ受付を通す。ttyは正確なsession selectorで読み、
|
|
29
|
-
実stty直前にも同じdeviceを確認する。停止や世代/tty交代後に古いdeviceへ回復を発行しない。
|
|
30
|
-
一つのRPCが複数のnative作用を発行するときも、各回に同じissued slotとsource/target世代・停止を再確認する。
|
|
31
|
-
agentの貼付け・Enterの同期区間は、既存metadata mutexを非同期に取得してから実行する。
|
|
32
|
-
native作成後に再開する起動準備も同じ非同期取得を通す。pane所有検査、fg/stty回復、
|
|
33
|
-
起動メニューの各キーを短い同期区間で実行し、待機後の停止・世代・slot検査を省略しない。
|
|
34
|
-
mutexをawait中へ持ち越さず、同じ同期stack内の各gateが発行記録を永続化してからnative作用へ進む。
|
|
35
|
-
検証済みsourceと同世代への通常sendがissuedである間も、そのsourceの送信先が別ならoutgoing RPCは継続できる。
|
|
36
|
-
incomingのslotを解放・書換・成功扱いせず、unknown・管理操作・世代不一致は従来どおり拒否する。
|
|
37
|
-
incomingの完了待ちをoutgoingへ課して相互送信を循環待ちにしない(ADR 0127)。
|
|
38
|
-
BellTeamのpromptなし明示管理launchは、管理close同様にserving process/request identityへ結合する。
|
|
39
|
-
promptやThroughline読出しを含む未登録送信、auto-name、remoteはこの管理例外へ含めない。
|
|
40
|
-
BellTeamのrefなしagent_configureも同じnative process/request identityの管理RPCとして受ける。
|
|
41
|
-
model/effort/fastの各stageは同じ既存世代・slot・source・停止のgateを通り、途中で変われば続きの打鍵を拒否する。
|
|
42
|
-
発行後の途中失敗はpossible/unknownを保持する。CLI結果待ち後のfast metadata書込も同じ準備受付で再検査する(ADR 0129)。
|
|
43
|
-
新launchは、既存POSIX serverのnative owner、またはserver未作成の完全な空観測を受付時と発行直前に確認する。
|
|
44
|
-
冷間時は最初のnew-session自身でserverを作り、その実receiptのnative IDとserver PIDを、作成後の安定したnative一覧とprocess開始識別子で照合する。
|
|
45
|
-
既存server時も冷間時も、作成したsessionのnative ID・server owner・core内部のlaunch世代を同じ要求slotへ段階結合する。
|
|
46
|
-
物理shell準備はnative IDへ固定し、未結合の同名世代を採用しない。冷間起動のための補助sessionや再送は作らない。
|
|
47
|
-
作成時のnative ID/server ownerをmanaged metadataへ保存し、private runtimeの世代読取と期待closeでも再照合する。
|
|
48
|
-
古いmetadataの欠測を現観測で補わず、既存席の自動登録は行わない。
|
|
49
|
-
証拠の無い新server起動、Windows固有のserver作成、一般のauto-name/通常PTY等はまだunsupported。認証専用PTYはADR 0130の限定経路で受け付ける。
|
|
50
|
-
実18 toolsのhandlerを作るconstructorは、private dispatcher/親execution callbackを明示注入して隔離SDKで検証できる。
|
|
51
|
-
通常のstdio mainは注入せず、全参加process/全core作用口・native fenceが揃うまで公開有効化しない。
|
|
52
|
-
private participant factoryはproducer/service/dispatcher/同process用worker profileを同じscopeとnative actorで組む。
|
|
53
|
-
source環境の既存8名は一度だけ読み、必要な値だけを固定してproducerとdispatcherへ渡す。
|
|
54
|
-
呼出側のprovider/profile/runtime methodの差替えは構築済みparticipantへ混入させず、現在のscope/actorの変化は作用前に拒否する。
|
|
55
|
-
親managerの保存先とownerも同じscope/actorへ照合する。別processのhookはactorを流用せず、自分のworker factoryで接続する。
|
|
56
|
-
native runtimeの自己actorは、現在実行中のprocessのPIDと開始identityを一度だけOSで確定して保持する。
|
|
57
|
-
同processの生存中に開始identityは変わらないため、scope確認ごとの自己PID照会を行わない。
|
|
58
|
-
初回の欠測・失敗は確定値として保持せず、返すobjectも複製する。注入runtimeのactor、他process・server・
|
|
59
|
-
source/target世代の観測は保持せず、従来どおり各受付で再照合する。
|
|
60
|
-
注入runtimeへ欠けたparent依存を既定OS処理で補わず、完全なfake依存を要求する。このfactoryも通常mainには未注入。
|
|
61
|
-
同producer serviceの停止closeは、既存のissued close slotを持つ間だけ同期の期待世代primitiveへ渡す。
|
|
62
|
-
実killの直前にもruntimeの同期世代読取を通し、scope/actor/期待launchの交代を拒否する。
|
|
63
|
-
注入runtimeのclose欠測をcore既定処理で補わず、作用後の応答欠測は消失観測があってもunknown slotを保持する。
|
|
64
|
-
完了の照会点は固定し、終了fenceの非同期応答後にも現在世代を確認する。実受取番/終了fenceの証拠adapterは未了。
|
|
65
|
-
通常のcompletion終了確認は元request/Pointを共有lock内で固定し、native/transcript観測をlock外で行う。
|
|
66
|
-
反映時に同じrecord全体・issued/unknown・元slot・親作用を再照合し、途中変更があれば反映しない。
|
|
67
|
-
親返却のpending判定は反映時のstateで行い、元unknownの解除や送信の再実行には使わない。
|
|
68
|
-
実行登録も同じrequestの既存予約を短い共有lock内で確認してから、source/targetの非同期観測をlock外で行う。
|
|
69
|
-
登録反映時に同じ予約・取消・source/targetの受付条件を再確認し、実作用直前の同期世代gateは維持する。
|
|
70
|
-
launch/sendの返却結果は元issued slotを固定してlock外で世代観測し、同じslotとissued状態だけに結合する。
|
|
71
|
-
途中のunknown化・slot交代・観測した世代の不一致はpossibleとして保持し、元作用を再実行しない。
|
|
72
|
-
遅延した要求取消は本物の受付結果を消さず、共有lock内へ非同期の観測待ちを戻さない。
|
|
73
|
-
private producer/worker factoryを構築したprocessではnative effect scopeを必須にする。
|
|
74
|
-
coreの公開変更入口も、打鍵や設定・認証・lock/metadata準備に入る前に対象のrequest contextを要求する。
|
|
75
|
-
この入口確認はissuedへの昇格ではない。実作用時には既存の同期受付を別に通す。
|
|
76
|
-
通常stdio mainはprivate factoryを使わず既定挙動を維持する。別processの未登録参加者や非同期準備中の全metadata作用を
|
|
77
|
-
この入口だけで覆ったとはしない。全参加者inventoryと各実作用の接続を確認するまでcoverage incompleteを維持する。
|
|
78
|
-
deferred frameには既存requestと期待世代を再照合する同期の準備callbackを渡す。
|
|
79
|
-
core入口の再確認と、managed metadata/hook生成・設定model保存は同じsource/target/slot条件を使う。
|
|
80
|
-
準備callbackは短い共有metadata lock内で動き、execution graphはread-onlyのまま、preparingをissuedへ変えない。
|
|
81
|
-
native作用やawaitをcallbackへ入れず、停止・世代/actor/scope交代・RPC終了後の遅着を拒否する。
|
|
82
|
-
これらの明示接続以外の設定復元や親配送metadata経路はまだ未了であり、既定mainへの有効化条件を満たさない。
|
|
83
|
-
private factoryは同scopeの共有stateへ既存PID/開始identityと役割を宣言し、各受付の同じlock内で欠測を拒否する。
|
|
84
|
-
遅延登録する参加者の最初の非同期要求は、既存の上限付きmetadata受付内で宣言を保存してから進む。
|
|
85
|
-
待機後にもscope/actorを照合し、read-only要求でも宣言だけは独立して保存する。
|
|
86
|
-
同期入口の即時拒否、登録削除後の拒否、停止snapshotの登録不要条件は変えず、入力や要求を再送しない。
|
|
87
|
-
MCP/parent-effectの既存参照とnative identityを読むinventoryはread-onlyで、役割やenvから世代・終了を補完しない。
|
|
88
|
-
開始identity交代や未登録actorを示しても旧slotを消さず、parent受付だけで参照を退役させない。
|
|
89
|
-
全行のidentity一致でも参加者の全発見/native終了fence/全経路の接続を証明せず、coverage incompleteを維持する。
|
|
90
|
-
作用後のmetadata受付欠測では成功receiptとpossibleを保ち、issued slotを再構築や消失観測で再実行可能へ変えない。
|
|
3
|
+
## 通常配送と停止
|
|
4
|
+
|
|
5
|
+
通常MCPの18 toolsは既存のterminal/harnessへ直接渡す。execution graphへの登録、participant宣言、
|
|
6
|
+
shared writer lockの取得・待機を配送条件にしない。記録の欠測や旧lock fileで本文を拒否しない。
|
|
7
|
+
旧execution-native-serverのMCP互換入口も標準の配送handlerを使い、agent_stopだけを追加する。
|
|
8
|
+
agent_executionとagent_execution_rootsをこの入口へ登録しない。本体は旧ExecutionBridgeの先行登録を要求しない。
|
|
9
|
+
|
|
10
|
+
親hookのClaude/Cursor/Codex入口は通常providerを直接呼ぶ。execution workerやdelivery_admissionを渡さない。
|
|
11
|
+
旧native hook設定は通常のparent-hook scriptへ移行し、他製品のhook・履歴を保持する。
|
|
12
|
+
|
|
13
|
+
agent_stopは指定sessionと既存agent metadataのparent_session_idを使い、末端から通常の中断キーを送る。
|
|
14
|
+
共有execution graphの読書き、writer lock、fsync、journal、記録整合性の確認待ちは行わない。
|
|
15
|
+
親子情報を読めなくても指定rootへはキーを送る。各宛先の送信結果を返し、キー受付を終了証明にしない。
|
|
16
|
+
会話をclose/killせず、本文の自動再送や追跡記録の未送信化を行わない。
|
|
17
|
+
|
|
18
|
+
旧共有受付の設計は撤回した履歴として
|
|
19
|
+
[archive](https://github.com/kitepon/aiterm-mcp/blob/main/docs/archive/20261024-retired-shared-execution-admission.md)へ移した。
|
|
91
20
|
|
|
92
21
|
## 目的と所有
|
|
93
22
|
|
|
@@ -499,44 +428,6 @@ ADR 0074(repositoryの`docs/adr/0074-agent-model-catalog.md`)。
|
|
|
499
428
|
境界失敗は明示errorにする。retry、別model、別harness、別backendへ自動fallbackしない。
|
|
500
429
|
stale send lockは並行processとのABAを避けるため自動削除せず、公開APIでは対象sessionを`pty_close`して
|
|
501
430
|
同じIDで再作成する。全session一括停止は公開しない。
|
|
502
|
-
実行ラッパーの要求参照の検証とMCP receipt整形は`execution-tools.ts`、native作用の進行は
|
|
503
|
-
`execution-invocation.ts`が所有する。実行・保存の判断は既存`ExecutionService`へ委ねる。
|
|
504
|
-
receiptの観測は、通常経路ではbody返却直後、deferred経路ではnative frameの正常返却後に行う。
|
|
505
|
-
その後の結合失敗でも観測済みreceiptを保持し、frame内のnative拒否を成功へ変換しない。
|
|
506
|
-
native一覧は終了コード1・空stdout・単独の`server exited unexpectedly`だけを20ms間隔、最長500msで再観測する。
|
|
507
|
-
再観測は呼出元の同じissued枠と世代検査の中で行う。不在の証拠は既存の同socket・終了コード1・空stdoutの
|
|
508
|
-
厳密な診断に限定し、正常一覧は従来のnative/server識別検査を通す。上限・別error・曖昧な一覧はunknownを保つ。
|
|
509
|
-
close・送信・その他native作用は再実行しない(ADR 0133)。
|
|
510
|
-
POSIXの明示native execution構成では、返却済みsendのunknown枠が対象席の管理closeまで
|
|
511
|
-
永久に拒否しないよう、通常`pty_close`だけを同じ期待launch/native IDで受付できる。
|
|
512
|
-
unknown send枠を保持したまま既存core closeへ進み、native close成功と席の不在を確認した後だけ
|
|
513
|
-
該当send枠を解放する。元recordのphase/completion/sendはunknownのまま残し、再送や成功化をしない。
|
|
514
|
-
旧callbackは未知/消失した元slotで拒否され、同IDの新launchへnative作用を発行できない。
|
|
515
|
-
issued、管理close自体のunknown、親作用のslot、世代/native/serverの不明・交代は対象外。
|
|
516
|
-
既存の送信・待機lockの拒否も維持し、他席やissuerの停止を復旧条件へ追加しない。
|
|
517
|
-
返却済みunknown launchも、元native/server・managed世代が一致し、raw initial_prompt:none・初期配送なし・
|
|
518
|
-
send:not_issuedで、harnessの終了を現在の同期primitiveが証明できる場合だけ、同じ明示管理closeを許す(ADR 0131)。
|
|
519
|
-
受付時とnative作用直前にこの証拠を検査し、closeと不在確認後に該当slotを外す。元unknown recordを保ち、
|
|
520
|
-
旧requestのlaunch/sendは再実行しない。生存harnessはreconcile_launchの対象として維持する。
|
|
521
|
-
本体からの明示復旧には既存agent_executionのclose_launch actionを使う(ADR 0132)。元requestと
|
|
522
|
-
target(session_id,launch_id)を原子的な期待条件として受付と作用直前に照合し、応答SDK自身の管理refで
|
|
523
|
-
既存close primitiveへ進む。呼出元がobserveしたsessionだけをcloseする手順で代用しない。
|
|
524
|
-
close・不在確認・metadata commit後だけ_meta["aiterm/closed_launch"]のversion1 receiptを返す。
|
|
525
|
-
structuredContentは別管理requestのrecord、元unknown recordは不変。結果不明や保存失敗にはclosed証明なし。
|
|
526
|
-
本体は元pending操作・stop/versionを別途照合し、後発不明を過去receiptで解除しない。
|
|
527
|
-
非同期launcherはCLIの検証をgraph mutex外で行い、実create→metadata公開→世代結合→CLI入力の同期区間を
|
|
528
|
-
一度のnative admission内で通す。起動準備のawaitをmutex内に持ち込まず、待機後には通常の世代・停止・slot検査を行う。
|
|
529
|
-
空起動の結果不明は明示 `agent_execution/reconcile_launch` で既存世代へ結合できる(ADR 0128)。
|
|
530
|
-
対象は返却済みunknown launch、send:not_issued、元native/server stamp付きの単独slotだけ。
|
|
531
|
-
同じmetadata transaction内のprivate同期primitiveで現在のnative/managed世代、生のinitial_prompt:none・初期配送なし、
|
|
532
|
-
harness生存とidleを照合する。既存recordのlaunchをaccepted、targetを当該世代へ結合し、該当slotだけを外す。
|
|
533
|
-
これは現在世代の明示採用で、失われたRPC receiptの復元ではない。本文・初期prompt・claim・nativeには作用しない。
|
|
534
|
-
同じaccepted targetへの再照合もsend:not_issuedなら現在のmanaged世代・生の未入力状態・入力待ちを再確認し、
|
|
535
|
-
同じsessionへの競合slotや親の未確定作用があれば拒否する。保存済みacceptedを後の世代の不明解除の証拠にしない。
|
|
536
|
-
issued、入力済み・不明、停止、別slot、世代/native/serverの不一致は拒否。後続sendは元source世代を含め通常受付を通る。
|
|
537
|
-
遅着した元callbackはまだ所有するissued stage/slotがある時だけunknownを書け、照合後や別stageを上書きしない。
|
|
538
|
-
native handlerのisErrorは元の本文を保持し、`aiterm/execution_error`のcode/effectを併記する。
|
|
539
|
-
native作用後の不明はpossibleのままで、原因説明を再送可否や成功receiptへ変換しない。
|
|
540
431
|
agent sessionへの送信1本を守る`<name>.agent-send.lock`は持つ時間が長いので、持ち主が終了した残骸を次の送信が片付ける。消す役を`<name>.agent-send.lock.reap`の排他作成で1つに絞り、
|
|
541
432
|
その中でもう一度確かめてから消すので、確かめた後で別のlockに入れ替わらない。消す役の印そのものが残った時だけは自動で消さず、`pty_close`を案内する。
|
|
542
433
|
終了した持ち主のpidを別のprocessが使い回すと、pidだけでは生きて見える。生きて見える持ち主は、processが始まってからの経過とlockを作ってからの時間を比べ、
|
package/docs/RELEASE.md
CHANGED
|
@@ -117,10 +117,11 @@ dotagentsの導入・更新は不要である。
|
|
|
117
117
|
利用環境は直前の正常npm versionを明示installして戻す。公開済みtagは動かさず、npm packageは上書きしない。
|
|
118
118
|
state schemaやmigrationを変更するreleaseでは、旧versionへ戻せる条件をCHANGELOGへ明記してから公開する。
|
|
119
119
|
|
|
120
|
-
###
|
|
121
|
-
|
|
122
|
-
The
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
120
|
+
### Ordinary delivery and historical graph fixtures
|
|
121
|
+
|
|
122
|
+
The normal MCP entry and parent hooks do not construct the shared execution
|
|
123
|
+
tracking runtime. The legacy native CLI serves ordinary delivery plus direct
|
|
124
|
+
leaf-first stop, without graph registration or writer-lock admission.
|
|
125
|
+
The retained experimental graph/checkpoint fixtures are historical POSIX-only
|
|
126
|
+
library tests, not ordinary delivery or stop requirements. Their Windows skips
|
|
127
|
+
do not establish native Windows interrupt support.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aiterm-mcp",
|
|
3
|
-
"version": "0.61.
|
|
3
|
+
"version": "0.61.17",
|
|
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": [
|