aiterm-mcp 0.37.8 → 0.37.9
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 +3 -1
- package/README.md +3 -1
- package/dist/aiterm-wait-cli.js +2 -2
- package/dist/core.js +22 -4
- package/dist/harnesses/grok.js +28 -3
- package/docs/00_overview.md +4 -0
- package/docs/DESIGN.md +13 -0
- 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.37.9] - 2026-09-21
|
|
11
|
+
|
|
12
|
+
### 修正
|
|
13
|
+
|
|
14
|
+
- Grok/Composerで前のターンのweekly-limitパネルが残っていても、通常の`pty_send`が一度閉じて今回の本文を送れるようにした。同じsessionを保ち、解除記録をreceiptへ返す。
|
|
15
|
+
- Grokの利用上限は現在の画面から判定する。古い上限logによる新しいターンの待機打切りと、入力欄に重なったprivacy案内による誤停止を修正した。
|
|
16
|
+
|
|
10
17
|
## [0.37.8] - 2026-09-19
|
|
11
18
|
|
|
12
19
|
### 修正
|
|
@@ -1719,7 +1726,8 @@ prototype (preserved under `prototype/python/` as the porting source and referen
|
|
|
1719
1726
|
`ubuntu-latest` for Node 18/20/22, publishing to npm on `v*` tags with
|
|
1720
1727
|
provenance.
|
|
1721
1728
|
|
|
1722
|
-
[Unreleased]: https://github.com/kitepon/aiterm-mcp/compare/v0.37.
|
|
1729
|
+
[Unreleased]: https://github.com/kitepon/aiterm-mcp/compare/v0.37.9...HEAD
|
|
1730
|
+
[0.37.9]: https://github.com/kitepon/aiterm-mcp/compare/v0.37.8...v0.37.9
|
|
1723
1731
|
[0.37.8]: https://github.com/kitepon/aiterm-mcp/compare/v0.37.7...v0.37.8
|
|
1724
1732
|
[0.37.7]: https://github.com/kitepon/aiterm-mcp/compare/v0.37.6...v0.37.7
|
|
1725
1733
|
[0.37.6]: https://github.com/kitepon/aiterm-mcp/compare/v0.37.5...v0.37.6
|
package/README.ja.md
CHANGED
|
@@ -202,7 +202,7 @@ runtime-error store は canonical dotagents config の `collection.enabled: true
|
|
|
202
202
|
場合だけ収集し、既定OFF、network送信は行いません。tag起点CIのnpm provenance(OIDC Trusted
|
|
203
203
|
Publishing)で公開し、GitHub Release が Official MCP Registry を再登録します。
|
|
204
204
|
|
|
205
|
-
**状態:** 開発継続中 · 現行公開版 **v0.37.
|
|
205
|
+
**状態:** 開発継続中 · 現行公開版 **v0.37.9** · 動作対象は Linux · WSL2 · macOS · Windows ネイティブ · MIT · [変更履歴](CHANGELOG.md)。
|
|
206
206
|
|
|
207
207
|
### 更新と巻き戻し
|
|
208
208
|
|
|
@@ -244,6 +244,8 @@ pty_read(id, { wait: true }) → 削減済みの出力を読む(完了
|
|
|
244
244
|
|
|
245
245
|
Grok/Composerの無人起動は公式`--trust`で指定された作業フォルダを信頼登録し、確認画面を完了してから初回promptを送る。この登録はGrok CLIの信頼ストアへ保存され、フォルダ内のhook・MCP・LSPにも適用される。read-only sandboxの制限は維持する。画面に残る完了済みhookの結果は実行中と判定しない。
|
|
246
246
|
|
|
247
|
+
Grok/Composerで終了済みターンのweekly-limitパネルが残っている場合、次の通常`pty_send`が`Shift+X`で一度閉じ、入力受付を確認して今回の本文を送る。同じsessionと会話を保ち、receiptの`pane_input_recovery`に`grok_rate_limit_dialog_dismissed`を記録する。ターン未終了・harness不在は`GROK_RATE_LIMIT_RECOVERY_BLOCKED`、解除後の入力受付失敗は`GROK_RATE_LIMIT_RECOVERY_FAILED`となり、本文は未送信。上限の継続は`rate_limited`として返し、過去promptは再送しない。Grokの上限観測には現在の画面だけを使う。
|
|
248
|
+
|
|
247
249
|
Grok/Composerがread-only sandboxの適用を拒否した場合、prompt送信時に`GROK_SANDBOX_STARTUP_FAILED`とCLIの原因を返す。例えばhookのパスにシンボリックリンクがあるとGrok CLIは起動を拒否する。設定の管理元で原因を修正し、対象sessionを`pty_close`して起動し直す。Aitermはsandboxを解除したりhookをコピーしたりしない。
|
|
248
250
|
|
|
249
251
|
この判定はGrok専用アダプターが所有し、同じCLIを使うComposerにも適用する。初回prompt付きの`agent_launch`と通常の`pty_send`で、入力受付待ち中に拒否を検出すると未送信のエラーを返す。promptなし・`trust_project`指定なしの起動応答は入力受付を保証しない。`trust_project:true`では入力受付まで確認し、`startup.status`を返す。Grokのprivacy notice起動設定も同アダプターが所有する。実装の責務分担は[DESIGN](docs/DESIGN.md#failure-and-recovery)を参照。
|
package/README.md
CHANGED
|
@@ -216,7 +216,7 @@ collection is off by default and performs no network I/O. It ships via
|
|
|
216
216
|
tag-triggered CI with npm provenance (OIDC Trusted Publishing); the GitHub
|
|
217
217
|
Release re-registers the Official MCP Registry entry.
|
|
218
218
|
|
|
219
|
-
**Status:** actively maintained · current public release **v0.37.
|
|
219
|
+
**Status:** actively maintained · current public release **v0.37.9** · 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).
|
|
220
220
|
|
|
221
221
|
### Update and rollback
|
|
222
222
|
|
|
@@ -264,6 +264,8 @@ The same primitive hosts another agent's TUI. `agent_launch` starts a selected e
|
|
|
264
264
|
|
|
265
265
|
Grok/Composerの無人起動は公式`--trust`で指定された作業フォルダを信頼登録し、確認画面を完了してから初回promptを送る。この登録はGrok CLIの信頼ストアへ保存され、フォルダ内のhook・MCP・LSPにも適用される。read-only sandboxの制限は維持する。画面に残る完了済みhookの結果は実行中と判定しない。
|
|
266
266
|
|
|
267
|
+
Grok/Composerで終了済みターンのweekly-limitパネルが残っている場合、次の通常`pty_send`が`Shift+X`で一度閉じ、入力受付を確認して今回の本文を送る。同じsessionと会話を保ち、receiptの`pane_input_recovery`に`grok_rate_limit_dialog_dismissed`を記録する。ターン未終了・harness不在は`GROK_RATE_LIMIT_RECOVERY_BLOCKED`、解除後の入力受付失敗は`GROK_RATE_LIMIT_RECOVERY_FAILED`となり、本文は未送信。上限の継続は`rate_limited`として返し、過去promptは再送しない。Grokの上限観測には現在の画面だけを使う。
|
|
268
|
+
|
|
267
269
|
Grok/Composerがread-only sandboxの適用を拒否した場合、prompt送信時に`GROK_SANDBOX_STARTUP_FAILED`とCLIの原因を返す。hookパスのシンボリックリンクなど、CLIが示した原因を設定の管理元で修正し、対象sessionを`pty_close`して起動し直す。Aitermはsandboxを解除したりhookをコピーしたりしない。
|
|
268
270
|
|
|
269
271
|
この判定はGrok専用アダプターが所有し、同じCLIを使うComposerにも適用する。初回prompt付きの`agent_launch`と通常の`pty_send`で、入力受付待ち中に拒否を検出すると未送信のエラーを返す。promptなし・`trust_project`指定なしの起動応答は入力受付を保証しない。`trust_project:true`では入力受付まで確認し、`startup.status`を返す。Grokのprivacy notice起動設定も同アダプターが所有する。実装の責務分担は[DESIGN](docs/DESIGN.md#failure-and-recovery)を参照。
|
package/dist/aiterm-wait-cli.js
CHANGED
|
@@ -89,8 +89,8 @@ export async function main(argv) {
|
|
|
89
89
|
}
|
|
90
90
|
catch (e) {
|
|
91
91
|
// Grok は利用上限に達すると auth 正本を自壊させることがあり(2026-08-22 実測)、
|
|
92
|
-
// metadata
|
|
93
|
-
//
|
|
92
|
+
// metadata検証が認証不在で止まる。現在のviewportに上限パネルがある場合だけ
|
|
93
|
+
// rate_limitedとして返し、古いlogで現在の認証エラーを置き換えない。
|
|
94
94
|
if (e instanceof AitermError && /Grok 認証正本/.test(e.message)) {
|
|
95
95
|
const limited = detectAgentRateLimit("grok", cmd.session);
|
|
96
96
|
if (limited) {
|
package/dist/core.js
CHANGED
|
@@ -18,7 +18,7 @@ import { readRuntimeProcesses, processSubtree, processIdentity, backgroundProces
|
|
|
18
18
|
import { AitermError, telemetryOwnedFailure, ownTelemetryFailure } from "./errors.js";
|
|
19
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
|
-
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";
|
|
21
|
+
import { GROK_MODEL_DEFAULTS, realGrokHome, resolveAndValidateGrokAuth, assertGrokModelAvailable, grokEventsTranscript, latestGrokCompletion, observeGrokDone, buildGrokAgentCmd, grokLaunchNote, grokEnvTokens, grokTuiReady, grokTuiBusy, grokPaneObservation, grokRateLimitDialog, 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";
|
|
23
23
|
import { OPERATION_ID_RE, CLAUDE_RESULT_MAX_BYTES, CLAUDE_EFFORTS, agentManagedClaudeSettingsPath, agentClaudeResultPath, agentClaudeOperationPath, agentClaudeApprovalReceiptPath, agentClaudeDispatchReceiptPath, validateOperationId, readClaudeResultText, assertClaudeAuthenticationReady, buildClaudeAgentCmd, claudeLaunchNote, claudeTuiReady, claudePaneObservation, claudeStartupAction, CLAUDE_COMPOSER_MARKER_RE, createClaudeAgentMetadata, claudeSessionTranscriptPath, claudeApiErrorFromLine, } from "./harnesses/claude.js";
|
|
24
24
|
import { bindCursorTranscriptSession, cursorTurnBoundary, latestCursorCompletion, observeCursorDone, cursorTranscriptText, assertCursorAuthenticationReady, assertCursorModelAvailable, buildCursorAgentCmd, cursorPromptWithLineage, createCursorAgentMetadata, cursorLaunchNote, cursorEffortNavigation, cursorTuiReady, cursorPaneObservation, CURSOR_SUBMIT_SEQUENCE, CURSOR_COMPOSER_CONTENT_MARKER_RE, validateCursorModelEffort, } from "./harnesses/cursor.js";
|
|
@@ -2590,20 +2590,21 @@ export function agentWaitGuide(session) {
|
|
|
2590
2590
|
const cmd = `aiterm-wait --session ${session ?? "<session_id>"} --cursor 0`;
|
|
2591
2591
|
return `完了通知は ${agentWaitLaunchForm(cmd)} で受ける(親はここで待たない・polling 不要)。receipt の outcome=done を確認してから再取得する。`;
|
|
2592
2592
|
}
|
|
2593
|
-
// harness
|
|
2593
|
+
// harness別の利用上限観測。Grok/Composerは現在の質問カード、他harnessは既存logを使う。
|
|
2594
2594
|
// 出典(2026-08-22): grok は live 実バナーで検証、codex/claude はインストール済み実バイナリの
|
|
2595
2595
|
// 埋込文字列から抽出(codex: "You've hit your usage limit for" / claude: "Usage limit reached ·
|
|
2596
2596
|
// continuing automatically when it resets"。Claude Code はリセット時に自動継続する設計なので、
|
|
2597
2597
|
// この報告は「今は上限で止まっている」の観測であり恒久停止を意味しない)。
|
|
2598
2598
|
const AGENT_RATE_LIMIT_PATTERNS = {
|
|
2599
|
-
grok: [/You hit your weekly limit/i, /Weekly limit left:\s*0%/i],
|
|
2600
|
-
composer: [/You hit your weekly limit/i, /Weekly limit left:\s*0%/i],
|
|
2601
2599
|
codex: [/You'?ve hit your usage limit/i],
|
|
2602
2600
|
claude: [/Usage limit reached/i],
|
|
2603
2601
|
};
|
|
2604
2602
|
const AGENT_RATE_LIMIT_SCAN_BYTES = 16 * 1024;
|
|
2605
2603
|
// pane log の末尾から上限バナーを探す。読めない・無い・対象 harness でないは全て null(誤検知より取りこぼし側へ倒す)。
|
|
2606
2604
|
export function detectAgentRateLimit(kind, aitermSession) {
|
|
2605
|
+
if (kind === "grok" || kind === "composer") {
|
|
2606
|
+
return grokRateLimitDialog(captureScreen(aitermSession, 0))?.message ?? null;
|
|
2607
|
+
}
|
|
2607
2608
|
const patterns = AGENT_RATE_LIMIT_PATTERNS[kind];
|
|
2608
2609
|
if (!patterns)
|
|
2609
2610
|
return null;
|
|
@@ -3440,13 +3441,30 @@ export async function dispatchAgentTurn(name, text, o = {}) {
|
|
|
3440
3441
|
&& agentCompletionCursor(meta) === 0
|
|
3441
3442
|
&& readClaudeOperationMarker(meta) === null;
|
|
3442
3443
|
const paneInputRecovery = await ensureAgentOwnsPaneInput(name, meta.kind);
|
|
3444
|
+
const limitDialog = meta.kind === "grok" || meta.kind === "composer"
|
|
3445
|
+
? grokRateLimitDialog(captureScreen(name, 0)) : null;
|
|
3446
|
+
if (limitDialog) {
|
|
3447
|
+
const live = observeSession(name);
|
|
3448
|
+
const done = latestAgentDoneEvent(meta);
|
|
3449
|
+
if (live.harness_alive !== true || done?.done_status !== "turn_error") {
|
|
3450
|
+
const reason = live.harness_alive !== true ? live.reason : "latest_turn_not_error";
|
|
3451
|
+
throw new AitermError(`GROK_RATE_LIMIT_RECOVERY_BLOCKED: ${reason}。終了済み上限パネルと確認できません。今回の文字列は送信していません。`, 2);
|
|
3452
|
+
}
|
|
3453
|
+
sendKey(name, limitDialog.dismissKey);
|
|
3454
|
+
}
|
|
3443
3455
|
if (meta.kind !== "claude" || claudeColdStart) {
|
|
3444
3456
|
const ready = await waitAgentTuiReady(name, meta, o.ready_timeout ?? AGENT_TUI_READY_TIMEOUT_MS);
|
|
3445
3457
|
if (!ready.ready) {
|
|
3458
|
+
if (limitDialog) {
|
|
3459
|
+
const reason = grokPaneObservation(ready.lastScreen).reason;
|
|
3460
|
+
throw new AitermError(`GROK_RATE_LIMIT_RECOVERY_FAILED: ${reason}。上限パネル解除後の入力受付を確認できません。今回の文字列は送信していません。`, 2);
|
|
3461
|
+
}
|
|
3446
3462
|
throw new AitermError(`agent session '${name}' の ${agentLabel(meta.kind)} TUI が入力受付状態になりません。文字列は送信していません。` +
|
|
3447
3463
|
"少し後で pty_read(screen:true) を確認し、TUI が起動済みなら再度 pty_send してください。", 2);
|
|
3448
3464
|
}
|
|
3449
3465
|
}
|
|
3466
|
+
if (limitDialog)
|
|
3467
|
+
paneInputRecovery.push("grok_rate_limit_dialog_dismissed");
|
|
3450
3468
|
const startOffset = agentCompletionCursor(meta);
|
|
3451
3469
|
// promptなしで起動したCursorは、最初のdispatch時点ではtranscriptとの相関markerをまだ持たない。
|
|
3452
3470
|
// その1回だけlaunch contextを加え、以後はbind済みconversationへ通常textだけを送る。
|
package/dist/harnesses/grok.js
CHANGED
|
@@ -210,8 +210,11 @@ export async function observeGrokDone(meta, timeout, requestedCursor, detectRate
|
|
|
210
210
|
}
|
|
211
211
|
try {
|
|
212
212
|
const done = grokCompletionEvent(meta, JSON.parse(line));
|
|
213
|
-
if (done)
|
|
214
|
-
|
|
213
|
+
if (done) {
|
|
214
|
+
const limited = done.done_status === "turn_error"
|
|
215
|
+
? detectRateLimit(meta.kind, meta.aiterm_session) : null;
|
|
216
|
+
return observation(limited ? "rate_limited" : done.done_status === "turn_error" ? "error" : "done", done, limited);
|
|
217
|
+
}
|
|
215
218
|
}
|
|
216
219
|
catch {
|
|
217
220
|
malformedEvents++;
|
|
@@ -307,12 +310,34 @@ export function grokTuiBusy(screen) {
|
|
|
307
310
|
|| screen.includes("Responding...")
|
|
308
311
|
|| screen.includes("[stop]");
|
|
309
312
|
}
|
|
313
|
+
// 現在の質問カードだけを認識する。選択肢が空でも操作欄は残る。
|
|
314
|
+
// footer後に描画があれば過去のカードなので、会話履歴からキー操作を起こさない。
|
|
315
|
+
export function grokRateLimitDialog(screen) {
|
|
316
|
+
const clean = screen.replace(/\x1b\[[0-?]*[ -/]*[@-~]/g, "");
|
|
317
|
+
const headings = [...clean.matchAll(/^[ \t]*[┃│]?[ \t]*You hit your weekly limit\.[ \t]*[┃│]?[ \t]*$/gm)];
|
|
318
|
+
const heading = headings.at(-1);
|
|
319
|
+
if (!heading)
|
|
320
|
+
return null;
|
|
321
|
+
const afterHeading = clean.slice(heading.index + heading[0].length);
|
|
322
|
+
const footer = /Tab\s*:\s*next\s+answer\s*[│┃]?\s*Esc\s*:\s*scrollback\s*[│┃]?\s*Shift\+x\s*:\s*dismiss/i.exec(afterHeading);
|
|
323
|
+
if (!footer || afterHeading.slice(footer.index + footer[0].length).trim())
|
|
324
|
+
return null;
|
|
325
|
+
const body = afterHeading.slice(0, footer.index);
|
|
326
|
+
if (grokTuiBusy(body) || /(?:^|\n)[ \t]*(?:│[ \t]*)?[❯>]/u.test(body))
|
|
327
|
+
return null;
|
|
328
|
+
return { message: "You hit your weekly limit.", dismissKey: "X" };
|
|
329
|
+
}
|
|
330
|
+
function grokFramedComposer(screen) {
|
|
331
|
+
return /^[ \t]*│[ \t]*[❯>][^\n]*\n(?:[ \t]*│[^\n]*\n)*[ \t]*╰[^\n]*\b(?:Grok|Composer)\s+[\w.()-]+[^\n]*╯[ \t]*(?:\n|$)/mu.test(screen);
|
|
332
|
+
}
|
|
310
333
|
export function grokPaneObservation(screen) {
|
|
311
334
|
// 通信失敗後もWaitingが残る実画面を、稼働中として返さない。
|
|
312
335
|
const tail = screen.split("\n").slice(-32).join("\n");
|
|
313
336
|
if (/Connection failed|reqwest error stream|Check your network and try again/i.test(tail))
|
|
314
337
|
return { state: "blocked", reason: "connection_failed" };
|
|
315
|
-
if (
|
|
338
|
+
if (grokRateLimitDialog(tail))
|
|
339
|
+
return { state: "blocked", reason: "rate_limited" };
|
|
340
|
+
if (/Help improve Grok/.test(tail) && !grokFramedComposer(tail.slice(tail.lastIndexOf("Help improve Grok"))))
|
|
316
341
|
return { state: "blocked", reason: "privacy_choice" };
|
|
317
342
|
if (grokLaunchBlockingDialog(tail))
|
|
318
343
|
return { state: "blocked", reason: "startup_dialog" };
|
package/docs/00_overview.md
CHANGED
|
@@ -20,6 +20,10 @@ Grok/Composerのsandbox起動拒否については、[DESIGNの失敗と復旧
|
|
|
20
20
|
Codex親への回答の自動配送は[DESIGN](DESIGN.md#codex親への自動配送)に、対応範囲と失敗時の状態を置く。
|
|
21
21
|
Claude Code親の非同期hookによる受信は[DESIGN](DESIGN.md#claude-code親への自動配送)を参照する。
|
|
22
22
|
|
|
23
|
+
## 実装待ちの設計
|
|
24
|
+
|
|
25
|
+
- [Grokの過去の利用上限表示からの復帰](https://github.com/kitepon/aiterm-mcp/blob/main/docs/grok-rate-limit-recovery-plan.md): 設計完了・実装未着手。通常dispatchでのパネル解除、現在の画面による上限観測、試験と実機受入を定める。
|
|
26
|
+
|
|
23
27
|
## 履歴と証拠
|
|
24
28
|
|
|
25
29
|
- [`archive/`](https://github.com/kitepon/aiterm-mcp/tree/main/docs/archive): 完了・棄却・中断・失効・置換により現行制御から外れたsnapshot。
|
package/docs/DESIGN.md
CHANGED
|
@@ -200,6 +200,19 @@ Grok/Composerのmanaged起動は公式`--trust`を渡し、指定cwdの信頼
|
|
|
200
200
|
`grokTuiBusy`は応答中の表示だけを実行中の根拠にし、完了後も残る`[hooks: 成功/失敗]`を含めない。
|
|
201
201
|
これらのCLI固有判定は`src/harnesses/grok.ts`が所有し、共通処理は判定を呼び出す。
|
|
202
202
|
|
|
203
|
+
Grok/Composerの終了済みerrorターンにweekly-limit質問カードが残る場合、通常dispatchだけが
|
|
204
|
+
現在のviewportを読み、harness生存と最新turnのエラー完了を確かめて`X`を一回送る。
|
|
205
|
+
既存の入力受付待機を通した後に完了cursorを取得し、今回の本文だけを送る。
|
|
206
|
+
実施した解除は既存receiptの`pane_input_recovery`に`grok_rate_limit_dialog_dismissed`として載る。
|
|
207
|
+
解除条件の不成立は`GROK_RATE_LIMIT_RECOVERY_BLOCKED`、解除後の入力受付失敗は
|
|
208
|
+
`GROK_RATE_LIMIT_RECOVERY_FAILED`で未送信を返す。読取・観測・設定・steerはこの解除を行わない。
|
|
209
|
+
|
|
210
|
+
`grokRateLimitDialog`が見出しと操作footerの組を所有し、過去logや後続UIのあるカードは採用しない。
|
|
211
|
+
privacy案内は現在の枠付きcomposerとmodel footerが見える場合だけ入力受付を妨げない。
|
|
212
|
+
完了観測は成功eventを優先し、今回のerror eventと現在のカードが揃えばturn情報付きの`rate_limited`を返す。
|
|
213
|
+
新turnの完了前に古いlogだけで上限を返さない。購入・再認証・過去prompt再送・定期再試行は行わない。
|
|
214
|
+
画面判定と模擬CLIの実PTY試験は`test/grok-rate-limit.test.mjs`に置く。
|
|
215
|
+
|
|
203
216
|
## Platform contract
|
|
204
217
|
|
|
205
218
|
- macOS/Linux/WSL2: tmux。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "aiterm-mcp",
|
|
3
|
-
"version": "0.37.
|
|
3
|
+
"version": "0.37.9",
|
|
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": [
|