aiterm-mcp 0.29.25 → 0.29.27
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 +15 -1
- package/README.ja.md +1 -1
- package/README.md +1 -1
- package/dist/core.js +73 -8
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,18 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.29.27] - 2026-09-02
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- Cursorが貼り付け反映後の最初のEnterを取り落とし、promptをcomposerへ残した場合だけEnterを一度再送してturnを開始する。
|
|
15
|
+
|
|
16
|
+
## [0.29.26] - 2026-09-02
|
|
17
|
+
|
|
18
|
+
### Fixed
|
|
19
|
+
|
|
20
|
+
- Cursorの冷間起動時は、貼り付けたpromptがcomposerへ反映されたことを確認してからEnterを送り、入力準備前の早送信による未配達を防ぐ。
|
|
21
|
+
|
|
10
22
|
## [0.29.25] - 2026-09-02
|
|
11
23
|
|
|
12
24
|
### Fixed
|
|
@@ -1500,7 +1512,9 @@ prototype (preserved under `prototype/python/` as the porting source and referen
|
|
|
1500
1512
|
`ubuntu-latest` for Node 18/20/22, publishing to npm on `v*` tags with
|
|
1501
1513
|
provenance.
|
|
1502
1514
|
|
|
1503
|
-
[Unreleased]: https://github.com/kitepon/aiterm-mcp/compare/v0.29.
|
|
1515
|
+
[Unreleased]: https://github.com/kitepon/aiterm-mcp/compare/v0.29.27...HEAD
|
|
1516
|
+
[0.29.27]: https://github.com/kitepon/aiterm-mcp/compare/v0.29.26...v0.29.27
|
|
1517
|
+
[0.29.26]: https://github.com/kitepon/aiterm-mcp/compare/v0.29.25...v0.29.26
|
|
1504
1518
|
[0.29.25]: https://github.com/kitepon/aiterm-mcp/compare/v0.29.24...v0.29.25
|
|
1505
1519
|
[0.29.24]: https://github.com/kitepon/aiterm-mcp/compare/v0.29.23...v0.29.24
|
|
1506
1520
|
[0.29.23]: https://github.com/kitepon/aiterm-mcp/compare/v0.29.22...v0.29.23
|
package/README.ja.md
CHANGED
|
@@ -153,7 +153,7 @@ runtime-error store は canonical dotagents config の `collection.enabled: true
|
|
|
153
153
|
場合だけ収集し、既定OFF、network送信は行いません。tag起点CIのnpm provenance(OIDC Trusted
|
|
154
154
|
Publishing)で公開し、GitHub Release が Official MCP Registry を再登録します。
|
|
155
155
|
|
|
156
|
-
**状態:** 開発継続中 · 現行公開版 **v0.29.
|
|
156
|
+
**状態:** 開発継続中 · 現行公開版 **v0.29.27** · 動作対象は Linux · WSL2 · macOS · Windows ネイティブ · MIT · [変更履歴](CHANGELOG.md)。
|
|
157
157
|
|
|
158
158
|
### 更新と巻き戻し
|
|
159
159
|
|
package/README.md
CHANGED
|
@@ -169,7 +169,7 @@ collection is off by default and performs no network I/O. It ships via
|
|
|
169
169
|
tag-triggered CI with npm provenance (OIDC Trusted Publishing); the GitHub
|
|
170
170
|
Release re-registers the Official MCP Registry entry.
|
|
171
171
|
|
|
172
|
-
**Status:** actively maintained · current public release **v0.29.
|
|
172
|
+
**Status:** actively maintained · current public release **v0.29.27** · 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).
|
|
173
173
|
|
|
174
174
|
### Update and rollback
|
|
175
175
|
|
package/dist/core.js
CHANGED
|
@@ -61,6 +61,8 @@ const AGENT_SUBMIT_RESIDUE_POLL_MS = 300;
|
|
|
61
61
|
const AGENT_SUBMIT_RESIDUE_MAX_SAMPLES = 5;
|
|
62
62
|
const AGENT_SUBMIT_RESIDUE_TAIL_CHARS = 32;
|
|
63
63
|
const AGENT_SUBMIT_RESIDUE_MIN_TAIL_CHARS = 8;
|
|
64
|
+
const CURSOR_PROMPT_VISIBLE_POLL_MS = 100;
|
|
65
|
+
const CURSOR_PROMPT_VISIBLE_MAX_SAMPLES = 50;
|
|
64
66
|
// 出力削減(RTK の CAP 思想を移植)
|
|
65
67
|
const MAX_LINES_BEFORE_ELIDE = 60;
|
|
66
68
|
const HEAD_LINES = 30;
|
|
@@ -2480,6 +2482,31 @@ async function detectAgentSubmitResidueImpl(kind, text, sample, sleepFn, opts =
|
|
|
2480
2482
|
async function detectAgentSubmitResidue(name, kind, text) {
|
|
2481
2483
|
return detectAgentSubmitResidueImpl(kind, text, () => captureScreen(name, AGENT_TUI_READY_LINES), sleep);
|
|
2482
2484
|
}
|
|
2485
|
+
async function retryCursorSubmitIfResidueImpl(kind, residue, submit, inspect) {
|
|
2486
|
+
if (kind !== "cursor" || residue.residue !== true)
|
|
2487
|
+
return residue;
|
|
2488
|
+
submit();
|
|
2489
|
+
return inspect();
|
|
2490
|
+
}
|
|
2491
|
+
async function retryCursorSubmitIfResidue(name, kind, text, residue) {
|
|
2492
|
+
return retryCursorSubmitIfResidueImpl(kind, residue, () => sendKey(name, "Enter", { preserveAgentOperation: true }), () => detectAgentSubmitResidue(name, kind, text));
|
|
2493
|
+
}
|
|
2494
|
+
async function waitCursorPromptVisibleImpl(text, sample, sleepFn, opts = {}) {
|
|
2495
|
+
const tail = agentSubmitResidueTail(text) ?? normalizeResidueText(text);
|
|
2496
|
+
const pollMs = opts.pollMs ?? CURSOR_PROMPT_VISIBLE_POLL_MS;
|
|
2497
|
+
const maxSamples = opts.maxSamples ?? CURSOR_PROMPT_VISIBLE_MAX_SAMPLES;
|
|
2498
|
+
for (let i = 0; i < maxSamples; i++) {
|
|
2499
|
+
if (agentSubmitResidueOnScreen("cursor", sample(), tail) === true) {
|
|
2500
|
+
return { visible: true, samples: i + 1 };
|
|
2501
|
+
}
|
|
2502
|
+
if (i < maxSamples - 1)
|
|
2503
|
+
await sleepFn(pollMs);
|
|
2504
|
+
}
|
|
2505
|
+
return { visible: false, samples: maxSamples };
|
|
2506
|
+
}
|
|
2507
|
+
async function waitCursorPromptVisible(name, text) {
|
|
2508
|
+
return waitCursorPromptVisibleImpl(text, () => captureScreen(name, AGENT_TUI_READY_LINES), sleep);
|
|
2509
|
+
}
|
|
2483
2510
|
export function agentSubmitResidueWarning(name, residue) {
|
|
2484
2511
|
if (residue !== true)
|
|
2485
2512
|
return "";
|
|
@@ -2558,13 +2585,28 @@ export async function __testDetectAgentSubmitResidue(kind, text, samples, opts =
|
|
|
2558
2585
|
}, opts);
|
|
2559
2586
|
return { ...result, sleeps };
|
|
2560
2587
|
}
|
|
2588
|
+
export async function __testWaitCursorPromptVisible(text, samples, opts = {}) {
|
|
2589
|
+
if (samples.length === 0)
|
|
2590
|
+
throw new AitermError("Cursor prompt反映待ちのtest samplesが空です", 2);
|
|
2591
|
+
let i = 0;
|
|
2592
|
+
const sleeps = [];
|
|
2593
|
+
const result = await waitCursorPromptVisibleImpl(text, () => samples[Math.min(i++, samples.length - 1)], async (ms) => {
|
|
2594
|
+
sleeps.push(ms);
|
|
2595
|
+
}, opts);
|
|
2596
|
+
return { ...result, sleeps };
|
|
2597
|
+
}
|
|
2598
|
+
export async function __testRetryCursorSubmitIfResidue(kind, first, second) {
|
|
2599
|
+
let submits = 0;
|
|
2600
|
+
const result = await retryCursorSubmitIfResidueImpl(kind, first, () => { submits++; }, async () => second);
|
|
2601
|
+
return { result, submits };
|
|
2602
|
+
}
|
|
2561
2603
|
export function __testSetAgentTuiReadyStableSamples(value) {
|
|
2562
2604
|
if (value !== null && (!Number.isInteger(value) || value < 1 || value > 1000)) {
|
|
2563
2605
|
throw new AitermError("test ready stable samplesが不正です", 2);
|
|
2564
2606
|
}
|
|
2565
2607
|
agentTuiReadyStableSamplesTestOverride = value;
|
|
2566
2608
|
}
|
|
2567
|
-
async function sendAgentPromptText(name, text) {
|
|
2609
|
+
async function sendAgentPromptText(name, text, kind) {
|
|
2568
2610
|
send(name, text, {
|
|
2569
2611
|
enter: false,
|
|
2570
2612
|
force: true,
|
|
@@ -2574,7 +2616,16 @@ async function sendAgentPromptText(name, text) {
|
|
|
2574
2616
|
preserveAgentOperation: true,
|
|
2575
2617
|
bracketedPaste: true,
|
|
2576
2618
|
});
|
|
2577
|
-
|
|
2619
|
+
if (kind === "cursor") {
|
|
2620
|
+
const visible = await waitCursorPromptVisible(name, text);
|
|
2621
|
+
if (!visible.visible) {
|
|
2622
|
+
throw new AitermError(`vendor=cursor session=${name}\n` +
|
|
2623
|
+
"送信promptがCursorのcomposerへ反映されたことを確認できないため、Enterは送信していません。", 2);
|
|
2624
|
+
}
|
|
2625
|
+
}
|
|
2626
|
+
else {
|
|
2627
|
+
await sleep(AGENT_SUBMIT_DELAY_MS);
|
|
2628
|
+
}
|
|
2578
2629
|
sendKey(name, "Enter", { preserveAgentOperation: true });
|
|
2579
2630
|
}
|
|
2580
2631
|
export async function sendInitialAgentPrompt(name, text, o = {}) {
|
|
@@ -2614,7 +2665,7 @@ export async function sendInitialAgentPrompt(name, text, o = {}) {
|
|
|
2614
2665
|
prepareSendText(text, { raw: false });
|
|
2615
2666
|
reserveAnonymousClaudeTurn(meta);
|
|
2616
2667
|
}
|
|
2617
|
-
await sendAgentPromptText(name, promptText);
|
|
2668
|
+
await sendAgentPromptText(name, promptText, meta.kind);
|
|
2618
2669
|
setInitialPromptState(meta, "pending");
|
|
2619
2670
|
}
|
|
2620
2671
|
catch (e) {
|
|
@@ -2751,12 +2802,12 @@ export async function configureAgent(name, opts) {
|
|
|
2751
2802
|
// Cursor TUIの `/model <base model>` はmodelを直接切り替える一方、flatten済みcatalog ID
|
|
2752
2803
|
// (例: gpt-5.6-luna-high)を渡すとno matchesのfilter画面へ入る。effortは標準model pickerの
|
|
2753
2804
|
// parameter editorで選び、同じsessionと会話contextを保つ。
|
|
2754
|
-
await sendAgentPromptText(name, `/model ${model}
|
|
2805
|
+
await sendAgentPromptText(name, `/model ${model}`, meta.kind);
|
|
2755
2806
|
const modelReady = await waitAgentTuiReady(name, meta, AGENT_TUI_READY_TIMEOUT_MS);
|
|
2756
2807
|
if (!modelReady.ready)
|
|
2757
2808
|
throw new AitermError("Cursorのmodel変更完了を確認できません", 2);
|
|
2758
2809
|
if (effort) {
|
|
2759
|
-
await sendAgentPromptText(name, "/model");
|
|
2810
|
+
await sendAgentPromptText(name, "/model", meta.kind);
|
|
2760
2811
|
await waitForScreenText(name, "Available models");
|
|
2761
2812
|
sendMenuChoice(name, "Tab");
|
|
2762
2813
|
const parameterScreen = await waitForScreenText(name, "Edit Parameters");
|
|
@@ -2895,10 +2946,24 @@ export async function dispatchAgentTurn(name, text, o = {}) {
|
|
|
2895
2946
|
preserveAgentOperation: meta.kind === "claude",
|
|
2896
2947
|
bracketedPaste: true,
|
|
2897
2948
|
});
|
|
2898
|
-
//
|
|
2899
|
-
|
|
2949
|
+
// Cursorの冷間起動ではbracketed pasteの反映が250msを超えることがある。本文がcomposerへ
|
|
2950
|
+
// 現れた実測をsubmit条件にし、未反映のままEnterだけを失う競合を作らない。
|
|
2951
|
+
if (meta.kind === "cursor") {
|
|
2952
|
+
const visible = await waitCursorPromptVisible(name, dispatchText);
|
|
2953
|
+
if (!visible.visible) {
|
|
2954
|
+
throw new AitermError(`vendor=cursor session=${name}\n` +
|
|
2955
|
+
"送信promptがCursorのcomposerへ反映されたことを確認できないため、Enterは送信していません。", 2);
|
|
2956
|
+
}
|
|
2957
|
+
}
|
|
2958
|
+
else {
|
|
2959
|
+
// Codex TUI は literal text 投入直後の Enter を取り落とすことがある。agent 経路だけ submit を分離する。
|
|
2960
|
+
await sleep(AGENT_SUBMIT_DELAY_MS);
|
|
2961
|
+
}
|
|
2900
2962
|
sendKey(name, "Enter", { preserveAgentOperation: meta.kind === "claude" });
|
|
2901
|
-
|
|
2963
|
+
let residue = await detectAgentSubmitResidue(name, meta.kind, dispatchText);
|
|
2964
|
+
// Cursorはcomposerへの貼付反映後でも最初のEnterを取り落とすことがある。本文残留を
|
|
2965
|
+
// 陽性観測した場合だけ同じEnterを一度再送し、再検査後も残る時は失敗として返す。
|
|
2966
|
+
residue = await retryCursorSubmitIfResidue(name, meta.kind, dispatchText, residue);
|
|
2902
2967
|
assertAgentSubmitDelivered(name, meta.kind, residue);
|
|
2903
2968
|
return {
|
|
2904
2969
|
schema: "aiterm.agent-dispatch.v1",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aiterm-mcp",
|
|
3
|
-
"version": "0.29.
|
|
3
|
+
"version": "0.29.27",
|
|
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": [
|