aiterm-mcp 0.12.2 → 0.15.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.ja.md +31 -23
- package/README.md +63 -22
- package/dist/aiterm-wait-cli.js +94 -0
- package/dist/claude-stop-hook.js +237 -0
- package/dist/core.js +1027 -149
- package/dist/index.js +133 -28
- package/dist/runtime-error-store.js +15 -7
- package/package.json +4 -3
package/dist/index.js
CHANGED
|
@@ -33,6 +33,7 @@ function fail(e) {
|
|
|
33
33
|
*/
|
|
34
34
|
async function factoryDiagnostics() {
|
|
35
35
|
const ptyList = core.readOnlyPtyListDiagnostic();
|
|
36
|
+
const claude = core.vendorLauncherDiagnostic("claude");
|
|
36
37
|
const codex = core.vendorLauncherDiagnostic("codex");
|
|
37
38
|
const grok = core.vendorLauncherDiagnostic("grok");
|
|
38
39
|
const runtimeErrors = await runtimeErrorStoreDiagnostic();
|
|
@@ -45,6 +46,11 @@ async function factoryDiagnostics() {
|
|
|
45
46
|
pty_list: { access: "read_only", ...ptyList },
|
|
46
47
|
runtime_error_store: runtimeErrors,
|
|
47
48
|
vendor_dependencies: {
|
|
49
|
+
claude: {
|
|
50
|
+
status: claude,
|
|
51
|
+
optional: true,
|
|
52
|
+
required_for: ["claude_agent"],
|
|
53
|
+
},
|
|
48
54
|
codex: {
|
|
49
55
|
status: codex,
|
|
50
56
|
optional: true,
|
|
@@ -81,18 +87,26 @@ server.registerTool("pty_open", {
|
|
|
81
87
|
});
|
|
82
88
|
server.registerTool("pty_send", {
|
|
83
89
|
description: "セッションへテキスト(コマンド)を送る。通常は送信だけ行い、出力は pty_read で取得する。" +
|
|
84
|
-
"agent_done:true で起動した Codex/Grok/Composer セッションは wait:'agent_done' で Stop hook まで待てる。"
|
|
90
|
+
"agent_done:true で起動した Claude/Codex/Grok/Composer セッションは wait:'agent_done' で Stop hook まで待てる。" +
|
|
91
|
+
"managed Claude sessionはturn相関のためwait:'agent_done'を必須とし、通常送信を拒否する。",
|
|
85
92
|
inputSchema: {
|
|
86
93
|
session_id: z.string(),
|
|
87
|
-
text: z
|
|
94
|
+
text: z
|
|
95
|
+
.string()
|
|
96
|
+
.describe("送る文字列(コマンド)。UTF-8で最大64KiB"),
|
|
88
97
|
enter: z.boolean().default(true).describe("末尾で Enter を送る"),
|
|
89
98
|
wait: z
|
|
90
99
|
.enum(["none", "agent_done"])
|
|
91
100
|
.default("none")
|
|
92
|
-
.describe("none
|
|
101
|
+
.describe("none=従来通り送信のみ(managed Claudeでは拒否)。agent_done=agent Stop hook まで待って最終画面を返す"),
|
|
93
102
|
timeout: z.number().default(600).describe("wait:'agent_done' の最大待ち秒数"),
|
|
94
103
|
screen: z.boolean().default(true).describe("wait:'agent_done' の返り値を描画済みスクリーンにする"),
|
|
95
104
|
lines: z.number().int().nullish().describe("wait:'agent_done' で返す末尾 N 行"),
|
|
105
|
+
operation_id: z
|
|
106
|
+
.string()
|
|
107
|
+
.regex(/^sha256:[0-9a-f]{64}$/)
|
|
108
|
+
.nullish()
|
|
109
|
+
.describe("Claudeのdurable caller operation ID。wait:'agent_done'時だけ指定し、timeout後の同一結果回収へ使う"),
|
|
96
110
|
mark: z
|
|
97
111
|
.boolean()
|
|
98
112
|
.default(false)
|
|
@@ -106,7 +120,7 @@ server.registerTool("pty_send", {
|
|
|
106
120
|
rtk: z.boolean().default(false).describe("既知コマンドを rtk 形へ委譲して送る(rtk 不在なら素通し)"),
|
|
107
121
|
raw: z.boolean().default(false).describe("送信前サニタイズを無効化"),
|
|
108
122
|
},
|
|
109
|
-
}, async ({ session_id, text, enter, wait, timeout, screen, lines, mark, force, rtk, raw }) => {
|
|
123
|
+
}, async ({ session_id, text, enter, wait, timeout, screen, lines, operation_id, mark, force, rtk, raw }) => {
|
|
110
124
|
try {
|
|
111
125
|
if (wait === "agent_done") {
|
|
112
126
|
return ok(await core.sendAndWaitAgentDone(session_id, text, {
|
|
@@ -118,8 +132,11 @@ server.registerTool("pty_send", {
|
|
|
118
132
|
timeout,
|
|
119
133
|
screen,
|
|
120
134
|
lines: lines ?? null,
|
|
135
|
+
operation_id: operation_id ?? null,
|
|
121
136
|
}));
|
|
122
137
|
}
|
|
138
|
+
if (operation_id != null)
|
|
139
|
+
throw new Error("operation_idはwait:'agent_done'時だけ指定できます");
|
|
123
140
|
return ok(core.send(session_id, text, { enter, mark, force, rtk, raw }));
|
|
124
141
|
}
|
|
125
142
|
catch (e) {
|
|
@@ -129,7 +146,7 @@ server.registerTool("pty_send", {
|
|
|
129
146
|
server.registerTool("pty_read", {
|
|
130
147
|
description: "セッションの出力をトークン削減して読む(既定は前回読取位置からの増分)。" +
|
|
131
148
|
"削減: 制御文字除去 / 反復圧縮 / head+tail 折りたたみ+復元ヒント+メタ併記。" +
|
|
132
|
-
"agent_transcript:true は agent session の直近完了ターンの最終 assistant
|
|
149
|
+
"agent_transcript:true は agent session の直近完了ターンの最終 assistant メッセージを公開されたvendor記録から平文で返す。" +
|
|
133
150
|
"長い回答が screen tail で切れた時の回収用。",
|
|
134
151
|
inputSchema: {
|
|
135
152
|
session_id: z.string(),
|
|
@@ -155,16 +172,26 @@ server.registerTool("pty_read", {
|
|
|
155
172
|
agent_transcript: z
|
|
156
173
|
.boolean()
|
|
157
174
|
.default(false)
|
|
158
|
-
.describe("agent session の直近完了ターンの最終 assistant
|
|
175
|
+
.describe("agent session の直近完了ターンの最終 assistant メッセージを返す。Claudeはmanaged Stop hook result、他vendorはtranscriptを使う。長い回答がscreen tailで切れた時の回収用"),
|
|
176
|
+
operation_id: z
|
|
177
|
+
.string()
|
|
178
|
+
.regex(/^sha256:[0-9a-f]{64}$/)
|
|
179
|
+
.nullish()
|
|
180
|
+
.describe("Claude operationの期待ID。agent_transcript:true時だけ指定し、古い別operationの結果を拒否する"),
|
|
159
181
|
},
|
|
160
|
-
}, async ({ session_id, wait, until, until_regex, timeout, screen, full, lines, line_range, raw, rtk, agent_transcript }) => {
|
|
182
|
+
}, async ({ session_id, wait, until, until_regex, timeout, screen, full, lines, line_range, raw, rtk, agent_transcript, operation_id }) => {
|
|
161
183
|
try {
|
|
162
184
|
if (agent_transcript) {
|
|
163
185
|
if (screen || full || rtk || wait || line_range != null) {
|
|
164
186
|
throw new Error("agent_transcript:true は screen / full / rtk / line_range / wait と併用できません。lines のみ指定できます。");
|
|
165
187
|
}
|
|
166
|
-
return ok(await core.readAgentTranscript(session_id, {
|
|
188
|
+
return ok(await core.readAgentTranscript(session_id, {
|
|
189
|
+
lines: lines ?? null,
|
|
190
|
+
operation_id: operation_id ?? null,
|
|
191
|
+
}));
|
|
167
192
|
}
|
|
193
|
+
if (operation_id != null)
|
|
194
|
+
throw new Error("operation_idはagent_transcript:true時だけ指定できます");
|
|
168
195
|
let range = null;
|
|
169
196
|
if (line_range) {
|
|
170
197
|
const idx = line_range.indexOf(":");
|
|
@@ -199,7 +226,7 @@ server.registerTool("pty_read", {
|
|
|
199
226
|
}
|
|
200
227
|
});
|
|
201
228
|
server.registerTool("pty_key", {
|
|
202
|
-
description: "制御キーを送る(C-c, C-d, Enter, Tab, Up, Down... の別名に対応)。",
|
|
229
|
+
description: "制御キーを送る(C-c, C-d, Enter, Tab, Up, Down... の別名に対応)。managed Claude sessionではturn相関を守るためC-cだけを許可する。",
|
|
203
230
|
inputSchema: {
|
|
204
231
|
session_id: z.string(),
|
|
205
232
|
key: z.string().describe('キー名(例 "C-c", "Enter", "Up")'),
|
|
@@ -213,11 +240,21 @@ server.registerTool("pty_key", {
|
|
|
213
240
|
}
|
|
214
241
|
});
|
|
215
242
|
server.registerTool("pty_close", {
|
|
216
|
-
description: "
|
|
243
|
+
description: "セッションを閉じ、ログ/読取位置を破棄する。同じsession_idへの再試行は安全で、" +
|
|
244
|
+
"closed/already_closedのstructured receiptを返す。",
|
|
217
245
|
inputSchema: { session_id: z.string() },
|
|
246
|
+
outputSchema: {
|
|
247
|
+
schema: z.literal("aiterm.pty-close-result.v1"),
|
|
248
|
+
session_id: z.string().regex(/^[A-Za-z0-9_-]{1,64}$/),
|
|
249
|
+
outcome: z.enum(["closed", "already_closed"]),
|
|
250
|
+
},
|
|
218
251
|
}, async ({ session_id }) => {
|
|
219
252
|
try {
|
|
220
|
-
|
|
253
|
+
const result = core.closeSessionResult(session_id);
|
|
254
|
+
return {
|
|
255
|
+
content: [{ type: "text", text: `closed ${session_id}` }],
|
|
256
|
+
structuredContent: { ...result },
|
|
257
|
+
};
|
|
221
258
|
}
|
|
222
259
|
catch (e) {
|
|
223
260
|
return fail(e);
|
|
@@ -234,20 +271,61 @@ server.registerTool("pty_list", {
|
|
|
234
271
|
return fail(e);
|
|
235
272
|
}
|
|
236
273
|
});
|
|
274
|
+
server.registerTool("claude_turn", {
|
|
275
|
+
description: "managed Claude sessionのdurable operationを構造化issue/recoverするmachine-caller専用面。" +
|
|
276
|
+
"pending/unknown/completedを人間向けerror文字列の解析なしで返し、Observer固有ロジックは持たない。",
|
|
277
|
+
inputSchema: {
|
|
278
|
+
action: z.enum(["issue", "recover"]),
|
|
279
|
+
session_id: z.string(),
|
|
280
|
+
operation_id: z.string().regex(/^sha256:[0-9a-f]{64}$/),
|
|
281
|
+
text: z.string().optional().describe("issueだけに指定するbounded turn本文"),
|
|
282
|
+
timeout: z.number().min(0).max(3600).optional().describe("issueだけに指定するStop待ち秒数"),
|
|
283
|
+
},
|
|
284
|
+
outputSchema: {
|
|
285
|
+
schema: z.literal("aiterm.claude-operation-result.v1"),
|
|
286
|
+
action: z.enum(["issue", "recover"]),
|
|
287
|
+
status: z.enum(["accepted", "pending", "completed", "unknown"]),
|
|
288
|
+
session_id: z.string(),
|
|
289
|
+
operation_id: z.string().regex(/^sha256:[0-9a-f]{64}$/),
|
|
290
|
+
raw_output: z.string().nullable(),
|
|
291
|
+
reason: z.enum(["operation_not_found", "result_unknown"]).nullable(),
|
|
292
|
+
},
|
|
293
|
+
}, async ({ action, session_id, operation_id, text, timeout }) => {
|
|
294
|
+
try {
|
|
295
|
+
const result = await core.runClaudeOperation({
|
|
296
|
+
action,
|
|
297
|
+
session_id,
|
|
298
|
+
operation_id,
|
|
299
|
+
text: text ?? undefined,
|
|
300
|
+
timeout,
|
|
301
|
+
});
|
|
302
|
+
return {
|
|
303
|
+
content: [{ type: "text", text: JSON.stringify(result) }],
|
|
304
|
+
structuredContent: { ...result },
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
catch (e) {
|
|
308
|
+
return fail(e);
|
|
309
|
+
}
|
|
310
|
+
});
|
|
237
311
|
// 対話型エージェント起動ツール(モデルごとに1つ=ツール名/説明でどのモデルか一目で分かる)。
|
|
238
312
|
// いずれも永続端末に TUI を起動し session_id を返す。以後 pty_read/pty_send で対話操作する。
|
|
239
|
-
const agentModelDesc = (kind) => kind === "
|
|
240
|
-
? "起動モデル(例:
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
313
|
+
const agentModelDesc = (kind) => kind === "claude"
|
|
314
|
+
? "起動モデル(例: claude-sonnet-4-6)。省略時はClaude CLI既定"
|
|
315
|
+
: kind === "codex"
|
|
316
|
+
? "起動モデル(例: gpt-5.6-sol / gpt-5.6-terra / gpt-5.6-luna)。省略時は端末 config/CLI 既定を継承" +
|
|
317
|
+
"(端末側のピンがそのまま効く。実効値は起動応答に明示される)"
|
|
318
|
+
: `起動モデル。省略時は ${kind === "grok" ? "grok-4.5" : "grok-composer-2.5-fast"}`;
|
|
319
|
+
const agentEffortDesc = (kind) => kind === "claude"
|
|
320
|
+
? "Claude Code reasoning effort。low/medium/high/xhigh/max。省略時はCLI既定"
|
|
321
|
+
: kind === "grok" || kind === "composer"
|
|
322
|
+
? "指定不可(grok CLI の --effort は headless 専用で、対話 TUI では警告の上無視される。" +
|
|
323
|
+
"composer は effort 自体非対応)。指定すると起動前にエラーを返す"
|
|
324
|
+
: "reasoning effort(思考レベル)。low/medium/high/xhigh/max/ultra(CLI 版依存)。" +
|
|
325
|
+
"ultra は max 推論+proactive 自動委譲 ON=使用量急増注意(明示要求時のみ)。省略時は端末 config/CLI 既定。";
|
|
326
|
+
function registerAgentTool(toolName, kind, desc) {
|
|
249
327
|
const initialPromptWaitSchema = {};
|
|
250
|
-
if (kind === "codex") {
|
|
328
|
+
if (kind === "codex" || kind === "claude") {
|
|
251
329
|
initialPromptWaitSchema.wait = z
|
|
252
330
|
.enum(["none", "agent_done"])
|
|
253
331
|
.default("none")
|
|
@@ -256,6 +334,14 @@ function registerAgentTool(toolName, kind, desc, grokLike) {
|
|
|
256
334
|
initialPromptWaitSchema.screen = z.boolean().default(true).describe("wait:'agent_done' の返り値を描画済みスクリーンにする");
|
|
257
335
|
initialPromptWaitSchema.lines = z.number().int().nullish().describe("wait:'agent_done' で返す末尾 N 行");
|
|
258
336
|
}
|
|
337
|
+
const correlatedLaunchSchema = {};
|
|
338
|
+
if (kind === "claude") {
|
|
339
|
+
correlatedLaunchSchema.launch_operation_id = z
|
|
340
|
+
.string()
|
|
341
|
+
.regex(/^sha256:[0-9a-f]{64}$/)
|
|
342
|
+
.optional()
|
|
343
|
+
.describe("promptless managed launchのexact replay相関ID。session_nameとagent_done:trueが必須");
|
|
344
|
+
}
|
|
259
345
|
server.registerTool(toolName, {
|
|
260
346
|
description: desc,
|
|
261
347
|
inputSchema: {
|
|
@@ -263,16 +349,23 @@ function registerAgentTool(toolName, kind, desc, grokLike) {
|
|
|
263
349
|
model: z.string().nullish().describe(agentModelDesc(kind)),
|
|
264
350
|
// grok/composer の effort は対話 TUI で無効(headless 専用)=core 側が起動前に明示エラーで拒否。
|
|
265
351
|
// codex は CLI 側の値集合が版で変わるため縛らない(core 側も同方針)。
|
|
266
|
-
reasoning_effort: z.string().nullish().describe(agentEffortDesc(
|
|
352
|
+
reasoning_effort: z.string().nullish().describe(agentEffortDesc(kind)),
|
|
267
353
|
cwd: z.string().nullish().describe("作業ディレクトリ(対象リポのルート等・任意)"),
|
|
268
354
|
session_name: z.string().nullish().describe("セッション名(省略で自動採番)"),
|
|
269
355
|
agent_done: z
|
|
270
356
|
.boolean()
|
|
271
357
|
.default(false)
|
|
272
358
|
.describe("managed Stop hook を有効化し、pty_send(wait:'agent_done') を使えるようにする"),
|
|
359
|
+
...correlatedLaunchSchema,
|
|
273
360
|
...initialPromptWaitSchema,
|
|
274
361
|
},
|
|
275
|
-
|
|
362
|
+
outputSchema: {
|
|
363
|
+
schema: z.literal("aiterm.agent-launch-result.v1"),
|
|
364
|
+
provider: z.literal(kind),
|
|
365
|
+
session_id: z.string().regex(/^[A-Za-z0-9_-]{1,64}$/),
|
|
366
|
+
managed_completion: z.boolean(),
|
|
367
|
+
},
|
|
368
|
+
}, async ({ prompt, model, reasoning_effort, cwd, session_name, agent_done, launch_operation_id, wait, timeout, screen, lines }) => {
|
|
276
369
|
try {
|
|
277
370
|
const [sid, hint] = await core.openAgentWithInitialPrompt(kind, {
|
|
278
371
|
prompt: prompt ?? undefined,
|
|
@@ -281,25 +374,37 @@ function registerAgentTool(toolName, kind, desc, grokLike) {
|
|
|
281
374
|
cwd: cwd ?? undefined,
|
|
282
375
|
session_name: session_name ?? undefined,
|
|
283
376
|
agent_done: agent_done ?? false,
|
|
377
|
+
launch_operation_id: launch_operation_id ?? undefined,
|
|
284
378
|
wait: wait ?? "none",
|
|
285
379
|
timeout,
|
|
286
380
|
screen,
|
|
287
381
|
lines,
|
|
288
382
|
});
|
|
289
|
-
|
|
383
|
+
const structured = {
|
|
384
|
+
schema: "aiterm.agent-launch-result.v1",
|
|
385
|
+
provider: kind,
|
|
386
|
+
session_id: sid,
|
|
387
|
+
managed_completion: agent_done ?? false,
|
|
388
|
+
};
|
|
389
|
+
return {
|
|
390
|
+
content: [{ type: "text", text: `session_id: ${sid}\n${hint}` }],
|
|
391
|
+
structuredContent: structured,
|
|
392
|
+
};
|
|
290
393
|
}
|
|
291
394
|
catch (e) {
|
|
292
395
|
return fail(e);
|
|
293
396
|
}
|
|
294
397
|
});
|
|
295
398
|
}
|
|
399
|
+
registerAgentTool("claude_agent", "claude", "【Claude Code (Anthropic)】の対話エージェントTUIを永続端末に起動する。`claude -p`ではなく、" +
|
|
400
|
+
"同じ利用者可視sessionへpty_sendで継続入力する。agent_done:trueではisolated settingsのmanaged Stop hookで完了と結果を回収する。");
|
|
296
401
|
registerAgentTool("codex_agent", "codex", "【Codex (OpenAI)】の対話エージェント TUI を永続端末に起動する。実装・レビュー・調査を対話で回す。" +
|
|
297
402
|
"起動後は pty_read で画面を読み pty_send で操作する。model / reasoning_effort を引数で指定可" +
|
|
298
|
-
"(省略時は端末 config/CLI 既定を継承。実効値は起動応答に明示)。"
|
|
403
|
+
"(省略時は端末 config/CLI 既定を継承。実効値は起動応答に明示)。");
|
|
299
404
|
registerAgentTool("grok_agent", "grok", "【Grok Build の Grok モデル (既定 grok-4.5)】の対話エージェント TUI を永続端末に起動する。" +
|
|
300
|
-
"起動後は pty_read/pty_send で対話操作。model を引数で指定可。reasoning_effort は対話 TUI 非対応(指定はエラー)。"
|
|
405
|
+
"起動後は pty_read/pty_send で対話操作。model を引数で指定可。reasoning_effort は対話 TUI 非対応(指定はエラー)。");
|
|
301
406
|
registerAgentTool("composer_agent", "composer", "【Grok Build の Composer モデル (既定 grok-composer-2.5-fast)】の対話エージェント TUI を永続端末に起動する。" +
|
|
302
|
-
"起動後は pty_read/pty_send で対話操作。model を引数で指定可。reasoning_effort は非対応(指定はエラー)。"
|
|
407
|
+
"起動後は pty_read/pty_send で対話操作。model を引数で指定可。reasoning_effort は非対応(指定はエラー)。");
|
|
303
408
|
async function main() {
|
|
304
409
|
const transport = new StdioServerTransport();
|
|
305
410
|
await server.connect(transport);
|
|
@@ -31,6 +31,11 @@ const RECORD_KEYS = [
|
|
|
31
31
|
const DIAGNOSTIC_KEYS = ["status", "collection", "record_count", "unacknowledged_count"];
|
|
32
32
|
const ARCHES = new Set(["x64", "arm64", "arm", "ia32"]);
|
|
33
33
|
const EMPTY_STATE = () => ({ schema_version: STORE_SCHEMA, cursor: 0, acknowledged_cursor: 0, records: [] });
|
|
34
|
+
// readLock と queue scan の内部だけで使う。entry 本文など外部入力の Error message で
|
|
35
|
+
// disappearance を判定しないため、公開せず型そのものを識別子にする。
|
|
36
|
+
class LockDisappearedOrReplacedError extends Error {
|
|
37
|
+
constructor() { super("runtime error store lock が消滅または置換されました"); }
|
|
38
|
+
}
|
|
34
39
|
function isObject(value) {
|
|
35
40
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
36
41
|
}
|
|
@@ -426,6 +431,10 @@ export class RuntimeErrorStore {
|
|
|
426
431
|
}
|
|
427
432
|
else {
|
|
428
433
|
const before = fs.lstatSync(lock);
|
|
434
|
+
// APFS の高競合では readdir snapshot 後、正当に unlink 済みの entry が pre-open
|
|
435
|
+
// lstat で nlink=0 と観測される。これは置換/消滅として caller の既存 skip 経路へ渡す。
|
|
436
|
+
if (before.nlink === 0)
|
|
437
|
+
throw new LockDisappearedOrReplacedError();
|
|
429
438
|
if (!before.isFile() || before.isSymbolicLink() || before.nlink < 1 || before.nlink > 2
|
|
430
439
|
|| before.uid !== process.getuid() || (before.mode & 0o777) !== 0o600 || before.size > 4096) {
|
|
431
440
|
throw new Error("runtime error store lock が不正です");
|
|
@@ -433,9 +442,10 @@ export class RuntimeErrorStore {
|
|
|
433
442
|
const fd = fs.openSync(lock, fs.constants.O_RDONLY | fs.constants.O_NONBLOCK | (fs.constants.O_NOFOLLOW ?? 0));
|
|
434
443
|
try {
|
|
435
444
|
const after = fs.fstatSync(fd);
|
|
436
|
-
if (before.dev !== after.dev || before.ino !== after.ino || after.nlink
|
|
437
|
-
throw new
|
|
438
|
-
|
|
445
|
+
if (before.dev !== after.dev || before.ino !== after.ino || after.nlink === 0)
|
|
446
|
+
throw new LockDisappearedOrReplacedError();
|
|
447
|
+
if (after.nlink < 1 || after.nlink > 2)
|
|
448
|
+
throw new Error("runtime error store lock が不正です");
|
|
439
449
|
text = fs.readFileSync(fd, "utf8");
|
|
440
450
|
}
|
|
441
451
|
finally {
|
|
@@ -532,8 +542,7 @@ export class RuntimeErrorStore {
|
|
|
532
542
|
current = this.readLock(currentPath);
|
|
533
543
|
}
|
|
534
544
|
catch (error) {
|
|
535
|
-
if (error.code === "ENOENT"
|
|
536
|
-
|| (error instanceof Error && error.message.includes("置換されました")))
|
|
545
|
+
if (error.code === "ENOENT" || error instanceof LockDisappearedOrReplacedError)
|
|
537
546
|
continue;
|
|
538
547
|
throw error;
|
|
539
548
|
}
|
|
@@ -568,8 +577,7 @@ export class RuntimeErrorStore {
|
|
|
568
577
|
current = this.readLock(currentPath);
|
|
569
578
|
}
|
|
570
579
|
catch (error) {
|
|
571
|
-
if (error.code === "ENOENT"
|
|
572
|
-
|| (error instanceof Error && error.message.includes("置換されました")))
|
|
580
|
+
if (error.code === "ENOENT" || error instanceof LockDisappearedOrReplacedError)
|
|
573
581
|
continue;
|
|
574
582
|
throw error;
|
|
575
583
|
}
|
package/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aiterm-mcp",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"mcpName": "io.github.kitepon-rgb/aiterm-mcp",
|
|
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 Codex/Grok/Composer agent TUIs in a persistent terminal. Token-reducing reads.",
|
|
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": [
|
|
7
7
|
"mcp",
|
|
8
8
|
"mcp-server",
|
|
@@ -33,7 +33,8 @@
|
|
|
33
33
|
"type": "module",
|
|
34
34
|
"bin": {
|
|
35
35
|
"aiterm-mcp": "dist/index.js",
|
|
36
|
-
"aiterm-runtime-errors": "dist/runtime-errors-cli.js"
|
|
36
|
+
"aiterm-runtime-errors": "dist/runtime-errors-cli.js",
|
|
37
|
+
"aiterm-wait": "dist/aiterm-wait-cli.js"
|
|
37
38
|
},
|
|
38
39
|
"files": [
|
|
39
40
|
"dist",
|