aiterm-mcp 0.28.4 → 0.29.1

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/dist/core.js CHANGED
@@ -16,7 +16,7 @@ import { AitermError, telemetryOwnedFailure, ownTelemetryFailure } from "./error
16
16
  import { isWin, SOCKDIR, tmuxCommand, loadPtyBufferChunk, pasteBufferBaseArgs, TMUX_EMPTY_CONFIG, attachCommand, normalizePaneCommand, appendMarkSentinel, settlePaneLog, paneCwdArgument, } from "./tmux-runtime.js";
17
17
  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";
18
18
  import { GROK_MODEL_DEFAULTS, realGrokHome, resolveAndValidateGrokAuth, assertGrokModelAvailable, grokEventsTranscript, latestGrokCompletion, grokInitializationComplete, observeGrokDone, buildGrokAgentCmd, grokLaunchNote, grokEnvTokens, grokTuiReady, GROK_COMPOSER_MARKER_RE, grokFooterHasConfiguration, grokTranscriptText, createGrokAgentMetadata, } from "./harnesses/grok.js";
19
- import { bindCodexTranscriptSession, latestCodexCompletion, observeCodexDone, buildCodexAgentCmd, codexLaunchNote, codexTuiReady, CODEX_COMPOSER_MARKER_RE, codexModelChoice, codexEffortChoice, codexMoreReasoningChoice, codexTranscriptText, createCodexAgentMetadata, } from "./harnesses/codex.js";
19
+ import { bindCodexTranscriptSession, latestCodexCompletion, observeCodexDone, buildCodexAgentCmd, codexLaunchNote, codexTuiReady, codexLaunchBlockingDialog, CODEX_COMPOSER_MARKER_RE, codexModelChoice, codexEffortChoice, codexMoreReasoningChoice, codexTranscriptText, createCodexAgentMetadata, } from "./harnesses/codex.js";
20
20
  import { OPERATION_ID_RE, CLAUDE_RESULT_MAX_BYTES, CLAUDE_EFFORTS, agentManagedClaudeSettingsPath, agentClaudeResultPath, agentClaudeOperationPath, agentClaudeApprovalReceiptPath, agentClaudeDispatchReceiptPath, validateOperationId, readClaudeResultText, assertClaudeAuthenticationReady, buildClaudeAgentCmd, claudeLaunchNote, claudeTuiReady, CLAUDE_COMPOSER_MARKER_RE, createClaudeAgentMetadata, } from "./harnesses/claude.js";
21
21
  import { bindCursorTranscriptSession, cursorTurnBoundary, latestCursorCompletion, observeCursorDone, cursorTranscriptText, assertCursorAuthenticationReady, assertCursorModelAvailable, buildCursorAgentCmd, createCursorAgentMetadata, cursorLaunchNote, cursorEffortNavigation, cursorTuiReady, CURSOR_COMPOSER_MARKER_RE, validateCursorModelEffort, } from "./harnesses/cursor.js";
22
22
  import { resolveAgentBin, resolveThroughlineBin, runThroughlineHandoffContext, isWindowsNativeExecutable, agentBinForPaneShell, resolveWinPaneShell } from "./agent-resolver.js";
@@ -2309,6 +2309,23 @@ function isAgentTuiIdleReady(kind, screen) {
2309
2309
  return false;
2310
2310
  return !isAgentTuiBusy(kind, screen);
2311
2311
  }
2312
+ // 起動側が明示応答すべき既知UI。ここで自動承認せず、ready timeoutを待たずに
2313
+ // `initial_prompt=not_sent`を返してsessionを生かしたままcallerへ制御を戻す。
2314
+ function isAgentTuiActionRequired(kind, screen) {
2315
+ if (kind === "codex") {
2316
+ return screen.includes("Update available!")
2317
+ || screen.includes("Do you trust the contents of this directory?")
2318
+ || screen.includes("Hooks need review")
2319
+ || screen.includes("Allow the room MCP server to run tool")
2320
+ || screen.includes("Would you like to run the following command?");
2321
+ }
2322
+ if (kind === "claude") {
2323
+ return /new MCP servers? found in this project/iu.test(screen)
2324
+ || screen.includes("Is this a project you created or one you trust")
2325
+ || screen.includes("trust this folder");
2326
+ }
2327
+ return false;
2328
+ }
2312
2329
  async function waitAgentTuiReadyImpl(kind, sample, sleepFn, opts = {}) {
2313
2330
  const timeoutMs = opts.timeoutMs ?? AGENT_TUI_READY_TIMEOUT_MS;
2314
2331
  const pollMs = opts.pollMs ?? AGENT_TUI_READY_POLL_MS;
@@ -2320,6 +2337,8 @@ async function waitAgentTuiReadyImpl(kind, sample, sleepFn, opts = {}) {
2320
2337
  for (;;) {
2321
2338
  lastScreen = sample();
2322
2339
  samples++;
2340
+ if (isAgentTuiActionRequired(kind, lastScreen))
2341
+ return { ready: false, samples, lastScreen };
2323
2342
  if (isAgentTuiIdleReady(kind, lastScreen)) {
2324
2343
  readyStreak++;
2325
2344
  if (readyStreak >= stableSamples)
@@ -2508,12 +2527,14 @@ export async function sendInitialAgentPrompt(name, text, o = {}) {
2508
2527
  setInitialPromptState(meta, "not_sent");
2509
2528
  const ready = await waitAgentTuiReady(name, meta, o.ready_timeout ?? AGENT_TUI_READY_TIMEOUT_MS);
2510
2529
  if (!ready.ready) {
2511
- return {
2512
- text: `initial_prompt=not_sent vendor=${meta.kind} ready=false samples=${ready.samples} harness=${agentHarness(meta.kind)}\n` +
2513
- `agent session '${name}' の ${agentLabel(meta.kind)} TUI が入力受付状態になりません。prompt は送信していません。`,
2514
- event_cursor: null,
2515
- submit_residue: null,
2516
- };
2530
+ // ready失敗は成功形で返さず明示エラーにする(実被弾 2026-08-25: Codexのupdate確認ダイアログで
2531
+ // 未送信のまま成功形receiptが返り、呼び出し側が40分気づけなかった)。sessionは調査/復旧用に残る。
2532
+ const dialog = meta.kind === "codex" ? codexLaunchBlockingDialog(ready.lastScreen) : null;
2533
+ const causeNote = dialog
2534
+ ? `${dialog}が入力を塞いでいます。pty_read(screen:true)で画面を確認し、pty_keyでダイアログに応答してから、pty_sendでpromptを送ってください。`
2535
+ : `pty_read(screen:true)で画面を確認し、入力受付になってからpty_sendでpromptを送ってください。`;
2536
+ throw new AitermError(`initial_prompt=not_sent vendor=${meta.kind} ready=false samples=${ready.samples} harness=${agentHarness(meta.kind)}\n` +
2537
+ `agent session '${name}' の ${agentLabel(meta.kind)} TUI が入力受付状態にならず、prompt は送信していません。${causeNote}`, 2);
2517
2538
  }
2518
2539
  const startOffset = agentCompletionCursor(meta);
2519
2540
  try {
@@ -381,6 +381,20 @@ export function codexTuiReady(screen) {
381
381
  }
382
382
  // submit座礁観測のcomposer領域マーカー(ready判定と同じ記号を行頭基準で探す)。
383
383
  export const CODEX_COMPOSER_MARKER_RE = /^\s*[›>]/;
384
+ // Codexの起動前modalダイアログ検知。表示中はheader/footerが描かれず codexTuiReady が
385
+ // 恒久falseになるため、ready gate失敗の原因究明用に画面から種別を特定する
386
+ // (実被弾 2026-08-25: update確認で初手prompt未送信のまま30秒timeout→40分停滞)。
387
+ // 文字列は実機captureの逐語。既知2種に一致しない「Press enter to continue」も
388
+ // 同型のmodalとして拾う(種別不明のまま握りつぶさない)。
389
+ export function codexLaunchBlockingDialog(screen) {
390
+ if (screen.includes("Update available!"))
391
+ return "update確認ダイアログ";
392
+ if (screen.includes("Do you trust the contents of this directory"))
393
+ return "directory trust確認ダイアログ";
394
+ if (screen.includes("Press enter to continue"))
395
+ return "起動時ダイアログ(種別未特定)";
396
+ return null;
397
+ }
384
398
  export function codexModelChoice(screen, model) {
385
399
  for (const line of screen.slice(screen.lastIndexOf("Select Model and Effort")).split("\n")) {
386
400
  const match = line.match(/^\s*(?:›\s*)?(\d+)\.\s+(\S+)/);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aiterm-mcp",
3
- "version": "0.28.4",
3
+ "version": "0.29.1",
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": [