oh-my-codex 0.8.12 → 0.8.13

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.
Files changed (114) hide show
  1. package/README.md +43 -35
  2. package/dist/cli/__tests__/doctor-invalid-config.test.d.ts +2 -0
  3. package/dist/cli/__tests__/doctor-invalid-config.test.d.ts.map +1 -0
  4. package/dist/cli/__tests__/doctor-invalid-config.test.js +52 -0
  5. package/dist/cli/__tests__/doctor-invalid-config.test.js.map +1 -0
  6. package/dist/cli/__tests__/index.test.js +12 -0
  7. package/dist/cli/__tests__/index.test.js.map +1 -1
  8. package/dist/cli/__tests__/resume.test.d.ts +2 -0
  9. package/dist/cli/__tests__/resume.test.d.ts.map +1 -0
  10. package/dist/cli/__tests__/resume.test.js +78 -0
  11. package/dist/cli/__tests__/resume.test.js.map +1 -0
  12. package/dist/cli/__tests__/session-search-help.test.js +1 -0
  13. package/dist/cli/__tests__/session-search-help.test.js.map +1 -1
  14. package/dist/cli/__tests__/team-decompose.test.js +9 -5
  15. package/dist/cli/__tests__/team-decompose.test.js.map +1 -1
  16. package/dist/cli/__tests__/team.test.js +59 -1
  17. package/dist/cli/__tests__/team.test.js.map +1 -1
  18. package/dist/cli/doctor.d.ts.map +1 -1
  19. package/dist/cli/doctor.js +26 -0
  20. package/dist/cli/doctor.js.map +1 -1
  21. package/dist/cli/index.d.ts +1 -1
  22. package/dist/cli/index.d.ts.map +1 -1
  23. package/dist/cli/index.js +12 -4
  24. package/dist/cli/index.js.map +1 -1
  25. package/dist/cli/team.d.ts.map +1 -1
  26. package/dist/cli/team.js +32 -5
  27. package/dist/cli/team.js.map +1 -1
  28. package/dist/hooks/__tests__/notify-fallback-watcher.test.js +127 -0
  29. package/dist/hooks/__tests__/notify-fallback-watcher.test.js.map +1 -1
  30. package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js +1 -0
  31. package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js.map +1 -1
  32. package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js +64 -1
  33. package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js.map +1 -1
  34. package/dist/hooks/__tests__/notify-hook-modules.test.js +7 -0
  35. package/dist/hooks/__tests__/notify-hook-modules.test.js.map +1 -1
  36. package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js +2 -1
  37. package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js.map +1 -1
  38. package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js +195 -16
  39. package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js.map +1 -1
  40. package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js +95 -0
  41. package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js.map +1 -1
  42. package/dist/hooks/__tests__/notify-hook-worker-idle.test.js +3 -0
  43. package/dist/hooks/__tests__/notify-hook-worker-idle.test.js.map +1 -1
  44. package/dist/hooks/__tests__/tmux-hook-engine.test.js +39 -1
  45. package/dist/hooks/__tests__/tmux-hook-engine.test.js.map +1 -1
  46. package/dist/mcp/team-server.js +1 -1
  47. package/dist/mcp/team-server.js.map +1 -1
  48. package/dist/team/__tests__/allocation-policy.test.d.ts +2 -0
  49. package/dist/team/__tests__/allocation-policy.test.d.ts.map +1 -0
  50. package/dist/team/__tests__/allocation-policy.test.js +39 -0
  51. package/dist/team/__tests__/allocation-policy.test.js.map +1 -0
  52. package/dist/team/__tests__/idle-nudge.test.js +6 -1
  53. package/dist/team/__tests__/idle-nudge.test.js.map +1 -1
  54. package/dist/team/__tests__/rebalance-policy.test.d.ts +2 -0
  55. package/dist/team/__tests__/rebalance-policy.test.d.ts.map +1 -0
  56. package/dist/team/__tests__/rebalance-policy.test.js +125 -0
  57. package/dist/team/__tests__/rebalance-policy.test.js.map +1 -0
  58. package/dist/team/__tests__/runtime.test.js +315 -12
  59. package/dist/team/__tests__/runtime.test.js.map +1 -1
  60. package/dist/team/__tests__/state.test.js +20 -1
  61. package/dist/team/__tests__/state.test.js.map +1 -1
  62. package/dist/team/__tests__/team-ops-contract.test.js +1 -0
  63. package/dist/team/__tests__/team-ops-contract.test.js.map +1 -1
  64. package/dist/team/__tests__/worker-bootstrap.test.js +20 -3
  65. package/dist/team/__tests__/worker-bootstrap.test.js.map +1 -1
  66. package/dist/team/allocation-policy.d.ts +23 -0
  67. package/dist/team/allocation-policy.d.ts.map +1 -0
  68. package/dist/team/allocation-policy.js +71 -0
  69. package/dist/team/allocation-policy.js.map +1 -0
  70. package/dist/team/idle-nudge.js +1 -1
  71. package/dist/team/idle-nudge.js.map +1 -1
  72. package/dist/team/rebalance-policy.d.ts +19 -0
  73. package/dist/team/rebalance-policy.d.ts.map +1 -0
  74. package/dist/team/rebalance-policy.js +48 -0
  75. package/dist/team/rebalance-policy.js.map +1 -0
  76. package/dist/team/runtime.d.ts.map +1 -1
  77. package/dist/team/runtime.js +132 -17
  78. package/dist/team/runtime.js.map +1 -1
  79. package/dist/team/state/types.d.ts +3 -0
  80. package/dist/team/state/types.d.ts.map +1 -1
  81. package/dist/team/state/types.js.map +1 -1
  82. package/dist/team/state.d.ts +8 -0
  83. package/dist/team/state.d.ts.map +1 -1
  84. package/dist/team/state.js +28 -12
  85. package/dist/team/state.js.map +1 -1
  86. package/dist/team/team-ops.d.ts +2 -1
  87. package/dist/team/team-ops.d.ts.map +1 -1
  88. package/dist/team/team-ops.js +1 -0
  89. package/dist/team/team-ops.js.map +1 -1
  90. package/dist/team/tmux-session.d.ts +5 -4
  91. package/dist/team/tmux-session.d.ts.map +1 -1
  92. package/dist/team/tmux-session.js +5 -67
  93. package/dist/team/tmux-session.js.map +1 -1
  94. package/dist/team/worker-bootstrap.d.ts +1 -0
  95. package/dist/team/worker-bootstrap.d.ts.map +1 -1
  96. package/dist/team/worker-bootstrap.js +9 -2
  97. package/dist/team/worker-bootstrap.js.map +1 -1
  98. package/package.json +2 -1
  99. package/scripts/notify-fallback-watcher.js +120 -1
  100. package/scripts/notify-hook/auto-nudge.js +20 -4
  101. package/scripts/notify-hook/team-dispatch.js +11 -58
  102. package/scripts/notify-hook/team-leader-nudge.js +47 -14
  103. package/scripts/notify-hook/team-tmux-guard.js +28 -11
  104. package/scripts/notify-hook/team-worker.js +3 -1
  105. package/scripts/notify-hook/tmux-injection.js +12 -13
  106. package/scripts/tmux-hook-engine.js +56 -0
  107. package/dist/rtk/__tests__/index.test.d.ts +0 -2
  108. package/dist/rtk/__tests__/index.test.d.ts.map +0 -1
  109. package/dist/rtk/__tests__/index.test.js +0 -104
  110. package/dist/rtk/__tests__/index.test.js.map +0 -1
  111. package/dist/rtk/index.d.ts +0 -130
  112. package/dist/rtk/index.d.ts.map +0 -1
  113. package/dist/rtk/index.js +0 -257
  114. package/dist/rtk/index.js.map +0 -1
@@ -4,7 +4,14 @@ import { dirname, join, resolve } from 'path';
4
4
  import { safeString } from './utils.js';
5
5
  import { runProcess } from './process-runner.js';
6
6
  import { resolvePaneTarget } from './tmux-injection.js';
7
- import { buildCapturePaneArgv, buildPaneInModeArgv, buildSendKeysArgv } from '../tmux-hook-engine.js';
7
+ import {
8
+ buildCapturePaneArgv,
9
+ buildPaneInModeArgv,
10
+ buildSendKeysArgv,
11
+ normalizeTmuxCapture,
12
+ paneHasActiveTask,
13
+ paneLooksReady,
14
+ } from '../tmux-hook-engine.js';
8
15
 
9
16
  function readJson(path, fallback) {
10
17
  return readFile(path, 'utf8')
@@ -260,18 +267,14 @@ function resolveWorkerCliForRequest(request, config) {
260
267
  return 'codex';
261
268
  }
262
269
 
263
- function normalizeCaptureText(value) {
264
- return safeString(value).replace(/\r/g, '').replace(/\s+/g, ' ').trim();
265
- }
266
-
267
270
  function capturedPaneContainsTrigger(captured, trigger) {
268
271
  if (!captured || !trigger) return false;
269
- return normalizeCaptureText(captured).includes(normalizeCaptureText(trigger));
272
+ return normalizeTmuxCapture(captured).includes(normalizeTmuxCapture(trigger));
270
273
  }
271
274
 
272
275
  function capturedPaneContainsTriggerNearTail(captured, trigger, nonEmptyTailLines = 24) {
273
276
  if (!captured || !trigger) return false;
274
- const normalizedTrigger = normalizeCaptureText(trigger);
277
+ const normalizedTrigger = normalizeTmuxCapture(trigger);
275
278
  if (!normalizedTrigger) return false;
276
279
  const lines = safeString(captured)
277
280
  .split('\n')
@@ -279,57 +282,7 @@ function capturedPaneContainsTriggerNearTail(captured, trigger, nonEmptyTailLine
279
282
  .filter((line) => line.length > 0);
280
283
  if (lines.length === 0) return false;
281
284
  const tail = lines.slice(-Math.max(1, nonEmptyTailLines)).join(' ');
282
- return normalizeCaptureText(tail).includes(normalizedTrigger);
283
- }
284
-
285
- // Ported from src/team/tmux-session.ts:949-963 — detects active CLI task indicators.
286
- function paneHasActiveTask(captured) {
287
- const lines = safeString(captured)
288
- .split('\n')
289
- .map((line) => line.replace(/\r/g, '').trim())
290
- .filter((line) => line.length > 0);
291
- const tail = lines.slice(-40);
292
- if (tail.some((line) => /\b\d+\s+background terminal running\b/i.test(line))) return true;
293
- if (tail.some((line) => /esc to interrupt/i.test(line))) return true;
294
- if (tail.some((line) => /\bbackground terminal running\b/i.test(line))) return true;
295
- if (tail.some((line) => /^•\s.+\(.+•\s*esc to interrupt\)$/i.test(line))) return true;
296
- // Claude active generation lines
297
- if (tail.some((line) => /^[·✻]\s+[A-Za-z][A-Za-z0-9''-]*(?:\s+[A-Za-z][A-Za-z0-9''-]*){0,3}(?:…|\.{3})$/u.test(line))) return true;
298
- return false;
299
- }
300
-
301
- function paneIsBootstrapping(captured) {
302
- const lines = safeString(captured)
303
- .split('\n')
304
- .map((line) => line.replace(/\r/g, '').trim())
305
- .filter((line) => line.length > 0);
306
- return lines.some((line) =>
307
- /\b(loading|initializing|starting up)\b/i.test(line)
308
- || /\bmodel:\s*loading\b/i.test(line)
309
- || /\bconnecting\s+to\b/i.test(line),
310
- );
311
- }
312
-
313
- function paneLooksReady(captured) {
314
- const content = safeString(captured).trimEnd();
315
- if (content === '') return false;
316
-
317
- const lines = content
318
- .split('\n')
319
- .map((line) => line.replace(/\r/g, ''))
320
- .map((line) => line.trimEnd())
321
- .filter((line) => line.trim() !== '');
322
-
323
- if (paneIsBootstrapping(content)) return false;
324
-
325
- const lastLine = lines.length > 0 ? lines[lines.length - 1] : '';
326
- if (/^\s*[›>❯]\s*/u.test(lastLine)) return true;
327
-
328
- const hasCodexPromptLine = lines.some((line) => /^\s*›\s*/u.test(line));
329
- const hasClaudePromptLine = lines.some((line) => /^\s*❯\s*/u.test(line));
330
- if (hasCodexPromptLine || hasClaudePromptLine) return true;
331
-
332
- return false;
285
+ return normalizeTmuxCapture(tail).includes(normalizedTrigger);
333
286
  }
334
287
 
335
288
  const INJECT_VERIFY_DELAY_MS = 250;
@@ -53,10 +53,38 @@ export function resolveLeaderProgressStallThresholdMs() {
53
53
  return 120_000;
54
54
  }
55
55
 
56
- function buildStatusCheckReminder(teamName, { keepPolling = false } = {}) {
57
- return keepPolling
58
- ? `Check: omx team status ${teamName}; keep polling.`
59
- : `Check: omx team status ${teamName}.`;
56
+ function buildStatusCheckReminder(teamName) {
57
+ return `Next: check messages; keep orchestrating; if done, gracefully shut down: omx team shutdown ${teamName}.`;
58
+ }
59
+
60
+ function buildMailboxCheckReminder(teamName) {
61
+ return `Next: read messages; keep orchestrating; if done, gracefully shut down: omx team shutdown ${teamName}.`;
62
+ }
63
+
64
+ function buildWorkerStartEvidenceReminder(teamName, workerName) {
65
+ return `Next: check ${workerName} msg/output, confirm task in omx team status ${teamName}, then reassign/nudge.`;
66
+ }
67
+
68
+ function buildLeaderActionGuidance(teamName, {
69
+ allWorkersIdle = false,
70
+ workerPanesAlive = false,
71
+ taskCounts = {},
72
+ } = {}) {
73
+ const pending = Number.isFinite(taskCounts.pending) ? taskCounts.pending : 0;
74
+ const blocked = Number.isFinite(taskCounts.blocked) ? taskCounts.blocked : 0;
75
+ const inProgress = Number.isFinite(taskCounts.in_progress) ? taskCounts.in_progress : 0;
76
+ const tasksComplete = pending === 0 && blocked === 0 && inProgress === 0;
77
+ const pendingFollowUpTasks = allWorkersIdle && pending > 0 && blocked === 0 && inProgress === 0;
78
+
79
+ if (pendingFollowUpTasks) {
80
+ return workerPanesAlive
81
+ ? 'Next: assign the next follow-up task to this idle team.'
82
+ : 'Next: launch a new team for the next task set.';
83
+ }
84
+ if (allWorkersIdle && tasksComplete) {
85
+ return `Next: omx team shutdown ${teamName}.`;
86
+ }
87
+ return buildStatusCheckReminder(teamName);
60
88
  }
61
89
 
62
90
  export async function checkWorkerPanesAlive(tmuxTarget, workerPaneIds = []) {
@@ -498,6 +526,11 @@ export async function maybeNudgeTeamLeader({ cwd, stateDir, logsDir, preComputed
498
526
  : [];
499
527
  const allWorkersIdle = workerStates.length > 0 && workerStates.every((state) => state === 'idle' || state === 'done');
500
528
  const progressSnapshot = await readTeamProgressSnapshot(stateDir, teamName, workerNames);
529
+ const leaderActionGuidance = buildLeaderActionGuidance(teamName, {
530
+ allWorkersIdle,
531
+ workerPanesAlive: paneStatus.alive,
532
+ taskCounts: progressSnapshot.taskCounts,
533
+ });
501
534
  const prevProgress = nudgeState.progress_by_team[teamName] && typeof nudgeState.progress_by_team[teamName] === 'object'
502
535
  ? nudgeState.progress_by_team[teamName]
503
536
  : {};
@@ -562,37 +595,37 @@ export async function maybeNudgeTeamLeader({ cwd, stateDir, logsDir, preComputed
562
595
  if (shouldSendAllIdleNudge) {
563
596
  nudgeReason = 'all_workers_idle';
564
597
  const N = workerNames.length;
565
- text = `[OMX] All ${N} worker${N === 1 ? '' : 's'} idle. Ready for next instructions.`;
598
+ text = `[OMX] All ${N} worker${N === 1 ? '' : 's'} idle. ${leaderActionGuidance}`;
566
599
  } else if (ackWithoutStartEvidence) {
567
600
  nudgeReason = ACK_WITHOUT_START_EVIDENCE_REASON;
568
601
  text =
569
602
  `Team ${teamName}: ${ackWithoutStartEvidence.worker} said "${ackWithoutStartEvidence.body}" `
570
- + `but has no work-start evidence yet (status: ${ackWithoutStartEvidence.statusState}, no owned in_progress task). `
571
- + buildStatusCheckReminder(teamName);
603
+ + `but has no start evidence (status: ${ackWithoutStartEvidence.statusState}). `
604
+ + buildWorkerStartEvidenceReminder(teamName, ackWithoutStartEvidence.worker);
572
605
  } else if (stalledTeamNudge) {
573
606
  nudgeReason = stalledTeamReason;
574
607
  const { pending, in_progress, blocked } = progressSnapshot.taskCounts;
575
608
  const missingSignals = progressSnapshot.missingSignalWorkers > 0
576
- ? `; ${progressSnapshot.missingSignalWorkers} worker signal${progressSnapshot.missingSignalWorkers === 1 ? '' : 's'} missing`
609
+ ? `; ${progressSnapshot.missingSignalWorkers} signal${progressSnapshot.missingSignalWorkers === 1 ? '' : 's'} missing`
577
610
  : '';
578
611
  const stallPrefix = leaderStale ? 'leader stale, ' : 'worker panes stalled, ';
579
612
  text =
580
- `Team ${teamName}: ${stallPrefix}no team progress for ${formatDurationMs(stalledForMs)}. `
581
- + `${buildStatusCheckReminder(teamName, { keepPolling: true })} `
582
- + `(pending:${pending} in_progress:${in_progress} blocked:${blocked}${missingSignals})`;
613
+ `Team ${teamName}: ${stallPrefix}no progress ${formatDurationMs(stalledForMs)}. `
614
+ + `${leaderActionGuidance} `
615
+ + `(p:${pending} ip:${in_progress} b:${blocked}${missingSignals})`;
583
616
  } else if (stalePanesNudge && hasNewMessage) {
584
617
  nudgeReason = 'stale_leader_with_messages';
585
618
  text =
586
619
  `Team ${teamName}: leader stale, ${paneStatus.paneCount} pane(s) active, ${messages.length} msg(s) pending. `
587
- + buildStatusCheckReminder(teamName, { keepPolling: true });
620
+ + buildMailboxCheckReminder(teamName);
588
621
  } else if (staleFollowupDue) {
589
622
  nudgeReason = 'stale_leader_panes_alive';
590
623
  text =
591
624
  `Team ${teamName}: leader stale, ${paneStatus.paneCount} worker pane(s) still active. `
592
- + buildStatusCheckReminder(teamName, { keepPolling: true });
625
+ + leaderActionGuidance;
593
626
  } else if (hasNewMessage) {
594
627
  nudgeReason = 'new_mailbox_message';
595
- text = `Team ${teamName}: ${messages.length} msg(s) for leader. ${buildStatusCheckReminder(teamName)}`;
628
+ text = `Team ${teamName}: ${messages.length} msg(s) for leader. ${buildMailboxCheckReminder(teamName)}`;
596
629
  } else {
597
630
  continue;
598
631
  }
@@ -1,31 +1,48 @@
1
1
  import { safeString } from './utils.js';
2
2
  import { runProcess } from './process-runner.js';
3
- import { buildPaneCurrentCommandArgv, isPaneRunningShell } from '../tmux-hook-engine.js';
3
+ import {
4
+ buildCapturePaneArgv,
5
+ buildPaneCurrentCommandArgv,
6
+ isPaneRunningShell,
7
+ paneHasActiveTask,
8
+ paneLooksReady,
9
+ } from '../tmux-hook-engine.js';
4
10
 
5
11
  export async function checkPaneReadyForTeamSendKeys(paneTarget) {
6
12
  const target = safeString(paneTarget).trim();
7
13
  if (!target) {
8
- return { ok: false, reason: 'missing_pane_target', paneCurrentCommand: '' };
14
+ return { ok: false, reason: 'missing_pane_target', paneCurrentCommand: '', paneCapture: '' };
9
15
  }
10
16
 
17
+ let paneCurrentCommand = '';
11
18
  try {
12
19
  const result = await runProcess('tmux', buildPaneCurrentCommandArgv(target), 1000);
13
- const paneCurrentCommand = safeString(result.stdout).trim();
20
+ paneCurrentCommand = safeString(result.stdout).trim();
14
21
  if (isPaneRunningShell(paneCurrentCommand)) {
15
22
  return {
16
23
  ok: false,
17
24
  reason: 'pane_running_shell',
18
25
  paneCurrentCommand,
26
+ paneCapture: '',
19
27
  };
20
28
  }
21
- return {
22
- ok: true,
23
- paneCurrentCommand,
24
- };
25
29
  } catch {
26
- return {
27
- ok: true,
28
- paneCurrentCommand: '',
29
- };
30
+ paneCurrentCommand = '';
31
+ }
32
+
33
+ try {
34
+ const capture = await runProcess('tmux', buildCapturePaneArgv(target), 1000);
35
+ const paneCapture = safeString(capture.stdout);
36
+ if (paneCapture.trim() !== '') {
37
+ if (paneHasActiveTask(paneCapture)) {
38
+ return { ok: false, reason: 'pane_has_active_task', paneCurrentCommand, paneCapture };
39
+ }
40
+ if (!paneLooksReady(paneCapture)) {
41
+ return { ok: false, reason: 'pane_not_ready', paneCurrentCommand, paneCapture };
42
+ }
43
+ }
44
+ return { ok: true, paneCurrentCommand, paneCapture };
45
+ } catch {
46
+ return { ok: true, paneCurrentCommand, paneCapture: '' };
30
47
  }
31
48
  }
@@ -386,7 +386,8 @@ export async function maybeNotifyLeaderAllWorkersIdle({ cwd, stateDir, logsDir,
386
386
  }
387
387
 
388
388
  const N = workers.length;
389
- const message = `[OMX] All ${N} worker${N === 1 ? '' : 's'} idle. Ready for next instructions. ${DEFAULT_MARKER}`;
389
+ const nextAction = `Next: run omx team status ${teamName}, check unread worker messages, then assign the next concrete task or shut the team down.`;
390
+ const message = `[OMX] All ${N} worker${N === 1 ? '' : 's'} idle. ${nextAction} ${DEFAULT_MARKER}`;
390
391
  const tmuxTarget = leaderPaneId;
391
392
  const paneGuard = await checkPaneReadyForTeamSendKeys(tmuxTarget);
392
393
  if (!paneGuard.ok) {
@@ -591,6 +592,7 @@ export async function maybeNotifyLeaderWorkerIdle({ cwd, stateDir, logsDir, pars
591
592
  if (prevState && prevState !== 'unknown') parts.push(`(was: ${prevState})`);
592
593
  if (currentTaskId) parts.push(`task: ${currentTaskId}`);
593
594
  if (currentReason) parts.push(`reason: ${currentReason}`);
595
+ parts.push(`Next: read ${workerName}'s latest message/output, then assign the next concrete step or mark the task complete.`);
594
596
  const message = `${parts.join('. ')}. ${DEFAULT_MARKER}`;
595
597
 
596
598
  try {
@@ -16,14 +16,13 @@ import {
16
16
  } from './state-io.js';
17
17
  import { runProcess } from './process-runner.js';
18
18
  import { logTmuxHookEvent } from './log.js';
19
+ import { checkPaneReadyForTeamSendKeys } from './team-tmux-guard.js';
19
20
  import {
20
21
  normalizeTmuxHookConfig,
21
22
  pickActiveMode,
22
23
  evaluateInjectionGuards,
23
24
  buildSendKeysArgv,
24
25
  buildPaneInModeArgv,
25
- buildPaneCurrentCommandArgv,
26
- isPaneRunningShell,
27
26
  } from '../tmux-hook-engine.js';
28
27
 
29
28
  export async function resolveSessionToPane(sessionName) {
@@ -373,28 +372,28 @@ export async function handleTmuxInjection({
373
372
  }
374
373
  }
375
374
 
376
- // Shell-detection guard: skip injection when the agent process has exited
377
- // and the pane has returned to an interactive shell (zsh, bash, etc.).
378
- // Sending the inject marker to a shell causes glob errors like
379
- // "zsh: no matches found: [OMX_TMUX_INJECT]". See #441.
375
+ // Shared pane-state guard: skip injection when the target pane has returned
376
+ // to a shell, is still bootstrapping, or is visibly busy with active work.
380
377
  try {
381
- const cmdResult = await runProcess('tmux', buildPaneCurrentCommandArgv(paneTarget), 1000);
382
- const currentCmd = safeString(cmdResult.stdout).trim();
383
- if (isPaneRunningShell(currentCmd)) {
384
- state.last_reason = 'agent_not_running';
378
+ const paneGuard = await checkPaneReadyForTeamSendKeys(paneTarget);
379
+ if (!paneGuard.ok) {
380
+ const reason = paneGuard.reason === 'pane_running_shell'
381
+ ? 'agent_not_running'
382
+ : paneGuard.reason;
383
+ state.last_reason = reason;
385
384
  state.last_event_at = nowIso;
386
385
  await writeFile(hookStatePath, JSON.stringify(state, null, 2)).catch(() => {});
387
386
  await logTmuxHookEvent(logsDir, {
388
387
  ...baseLog,
389
388
  event: 'injection_skipped',
390
- reason: 'agent_not_running',
389
+ reason,
391
390
  pane_target: paneTarget,
392
- pane_current_command: currentCmd,
391
+ pane_current_command: paneGuard.paneCurrentCommand || undefined,
393
392
  });
394
393
  return;
395
394
  }
396
395
  } catch {
397
- // Non-fatal: if querying pane command fails, proceed with injection.
396
+ // Non-fatal: if querying pane state fails, proceed with injection.
398
397
  }
399
398
 
400
399
  if (config.dry_run) {
@@ -178,6 +178,62 @@ export function isPaneRunningShell(paneCurrentCommand) {
178
178
  return SHELL_COMMANDS.has(base);
179
179
  }
180
180
 
181
+ export function normalizeTmuxCapture(value) {
182
+ return String(value ?? '')
183
+ .replace(/\r/g, '')
184
+ .replace(/\s+/g, ' ')
185
+ .trim();
186
+ }
187
+
188
+ function normalizePaneLines(capturedOrLines) {
189
+ if (Array.isArray(capturedOrLines)) {
190
+ return capturedOrLines
191
+ .map((line) => String(line ?? '').replace(/\r/g, '').trimEnd())
192
+ .filter((line) => line.trim() !== '');
193
+ }
194
+
195
+ return String(capturedOrLines ?? '')
196
+ .split('\n')
197
+ .map((line) => line.replace(/\r/g, '').trimEnd())
198
+ .filter((line) => line.trim() !== '');
199
+ }
200
+
201
+ export function paneIsBootstrapping(capturedOrLines) {
202
+ const lines = normalizePaneLines(capturedOrLines);
203
+ return lines.some((line) =>
204
+ /\b(loading|initializing|starting up)\b/i.test(line)
205
+ || /\bmodel:\s*loading\b/i.test(line)
206
+ || /\bconnecting\s+to\b/i.test(line)
207
+ );
208
+ }
209
+
210
+ export function paneLooksReady(captured) {
211
+ const content = String(captured ?? '').trimEnd();
212
+ if (content === '') return false;
213
+
214
+ const lines = normalizePaneLines(content);
215
+
216
+ if (paneIsBootstrapping(lines)) return false;
217
+
218
+ const lastLine = lines.length > 0 ? lines[lines.length - 1] : '';
219
+ if (/^\s*[›>❯]\s*/u.test(lastLine)) return true;
220
+
221
+ const hasCodexPromptLine = lines.some((line) => /^\s*›\s*/u.test(line));
222
+ const hasClaudePromptLine = lines.some((line) => /^\s*❯\s*/u.test(line));
223
+ if (hasCodexPromptLine || hasClaudePromptLine) return true;
224
+
225
+ return lines.some((line) => /^\s*(?:[›>❯]\s*)?[A-Z][A-Z0-9]+-\d+\s+only(?:\s*(?:…|\.{3}))?\s*$/iu.test(line));
226
+ }
227
+
228
+ export function paneHasActiveTask(captured) {
229
+ const tail = normalizePaneLines(captured).map((line) => line.trim()).slice(-40);
230
+ if (tail.some((line) => /\b\d+\s+background terminal running\b/i.test(line))) return true;
231
+ if (tail.some((line) => /esc to interrupt/i.test(line))) return true;
232
+ if (tail.some((line) => /\bbackground terminal running\b/i.test(line))) return true;
233
+ if (tail.some((line) => /^•\s.+\(.+•\s*esc to interrupt\)$/i.test(line))) return true;
234
+ return tail.some((line) => /^[·✻]\s+[A-Za-z][A-Za-z0-9'’-]*(?:\s+[A-Za-z][A-Za-z0-9'’-]*){0,3}(?:…|\.{3})$/u.test(line));
235
+ }
236
+
181
237
  export function buildCapturePaneArgv(paneTarget, tailLines = 80) {
182
238
  return ['capture-pane', '-t', paneTarget, '-p', '-S', `-${tailLines}`];
183
239
  }
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=index.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.test.d.ts","sourceRoot":"","sources":["../../../src/rtk/__tests__/index.test.ts"],"names":[],"mappings":""}
@@ -1,104 +0,0 @@
1
- import { afterEach, beforeEach, describe, it } from "node:test";
2
- import assert from "node:assert/strict";
3
- import { chmod, mkdir, mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
4
- import { join } from "node:path";
5
- import { tmpdir } from "node:os";
6
- import { buildRtkAliasesScript, isRtkEnabled, omxRuntimeConfigPath, readRtkEnabledSetting, resolveRtkBashEnv, resolveRtkExecutable, rtkAliasesPath, syncRtkRuntimeConfig, writeRtkAliasesFile, } from "../index.js";
7
- describe("rtk integration helpers", () => {
8
- let tempDir;
9
- let originalHome;
10
- let originalCodexHome;
11
- let originalPath;
12
- beforeEach(async () => {
13
- tempDir = await mkdtemp(join(tmpdir(), "omx-rtk-"));
14
- originalHome = process.env.HOME;
15
- originalCodexHome = process.env.CODEX_HOME;
16
- originalPath = process.env.PATH;
17
- process.env.HOME = tempDir;
18
- process.env.CODEX_HOME = join(tempDir, ".codex");
19
- process.env.PATH = "";
20
- await mkdir(process.env.CODEX_HOME, { recursive: true });
21
- });
22
- afterEach(async () => {
23
- if (typeof originalHome === "string")
24
- process.env.HOME = originalHome;
25
- else
26
- delete process.env.HOME;
27
- if (typeof originalCodexHome === "string")
28
- process.env.CODEX_HOME = originalCodexHome;
29
- else
30
- delete process.env.CODEX_HOME;
31
- if (typeof originalPath === "string")
32
- process.env.PATH = originalPath;
33
- else
34
- delete process.env.PATH;
35
- await rm(tempDir, { recursive: true, force: true });
36
- });
37
- async function writeRuntimeConfig(config) {
38
- await writeFile(omxRuntimeConfigPath(), JSON.stringify(config, null, 2));
39
- }
40
- async function createFakeRtkBinary(dirName = "bin") {
41
- const binDir = join(tempDir, dirName);
42
- const binaryPath = join(binDir, "rtk");
43
- await mkdir(binDir, { recursive: true });
44
- await writeFile(binaryPath, "#!/bin/sh\nif [ \"$1\" = \"--version\" ]; then echo 'rtk 0.27.1'; exit 0; fi\necho ok\n");
45
- await chmod(binaryPath, 0o755);
46
- process.env.PATH = `${binDir}`;
47
- return binaryPath;
48
- }
49
- it("reads rtk.enabled from .omx-config.json", async () => {
50
- await writeRuntimeConfig({ rtk: { enabled: false } });
51
- assert.equal(readRtkEnabledSetting(), false);
52
- });
53
- it("defaults rtk.enabled to installed state when config is absent", async () => {
54
- assert.equal(isRtkEnabled(), false);
55
- await createFakeRtkBinary();
56
- assert.equal(isRtkEnabled(), true);
57
- });
58
- it("respects explicit opt-out even when rtk is installed", async () => {
59
- await createFakeRtkBinary();
60
- await writeRuntimeConfig({ rtk: { enabled: false } });
61
- assert.equal(isRtkEnabled(), false);
62
- });
63
- it("writes alias file for supported commands", async () => {
64
- const binaryPath = await createFakeRtkBinary();
65
- const changed = await writeRtkAliasesFile(binaryPath);
66
- assert.equal(changed, true);
67
- const content = await readFile(rtkAliasesPath(), "utf-8");
68
- assert.match(content, /alias git='"\$RTK_BIN" git'/);
69
- assert.match(content, /alias cat='"\$RTK_BIN" read'/);
70
- assert.match(content, /alias rg='"\$RTK_BIN" grep'/);
71
- assert.match(content, new RegExp(`RTK_BIN="${binaryPath.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}"`));
72
- });
73
- it("seeds rtk.enabled into runtime config when missing and preserves other keys", async () => {
74
- await writeRuntimeConfig({ notifications: { enabled: true } });
75
- const changed = await syncRtkRuntimeConfig(process.env.CODEX_HOME, true);
76
- assert.equal(changed, true);
77
- const raw = JSON.parse(await readFile(omxRuntimeConfigPath(), "utf-8"));
78
- assert.equal(raw.notifications.enabled, true);
79
- assert.equal(raw.rtk.enabled, true);
80
- });
81
- it("does not override explicit rtk.enabled when already present", async () => {
82
- await writeRuntimeConfig({ rtk: { enabled: false } });
83
- const changed = await syncRtkRuntimeConfig(process.env.CODEX_HOME, true);
84
- assert.equal(changed, false);
85
- assert.equal(readRtkEnabledSetting(), false);
86
- });
87
- it("resolves BASH_ENV only when enabled and aliases exist", async () => {
88
- const binaryPath = await createFakeRtkBinary();
89
- assert.equal(resolveRtkExecutable(), binaryPath);
90
- assert.equal(resolveRtkBashEnv(), undefined);
91
- await writeRtkAliasesFile(binaryPath);
92
- assert.equal(resolveRtkBashEnv(), rtkAliasesPath());
93
- await writeRuntimeConfig({ rtk: { enabled: false } });
94
- assert.equal(resolveRtkBashEnv(), undefined);
95
- });
96
- it("builds deterministic alias script content", async () => {
97
- const binaryPath = await createFakeRtkBinary();
98
- const script = buildRtkAliasesScript(binaryPath);
99
- assert.match(script, /^# Generated by omx setup/m);
100
- assert.match(script, /alias docker='"\$RTK_BIN" docker'/);
101
- assert.match(script, /alias kubectl='"\$RTK_BIN" kubectl'/);
102
- });
103
- });
104
- //# sourceMappingURL=index.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../../../src/rtk/__tests__/index.test.ts"],"names":[],"mappings":"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"}
@@ -1,130 +0,0 @@
1
- export interface RtkConfigBlock {
2
- enabled?: boolean;
3
- }
4
- export interface EnsureRtkOptions {
5
- dryRun?: boolean;
6
- verbose?: boolean;
7
- }
8
- export interface EnsureRtkResult {
9
- aliasesPath: string;
10
- aliasFileWritten: boolean;
11
- executablePath?: string;
12
- installed: boolean;
13
- installMethod: "existing" | "cargo" | "brew" | "dry-run" | "unavailable";
14
- }
15
- export declare const RTK_ALIAS_DEFINITIONS: readonly [{
16
- readonly name: "aws";
17
- readonly target: "aws";
18
- }, {
19
- readonly name: "biome";
20
- readonly target: "lint";
21
- }, {
22
- readonly name: "cargo";
23
- readonly target: "cargo";
24
- }, {
25
- readonly name: "cat";
26
- readonly target: "read";
27
- }, {
28
- readonly name: "curl";
29
- readonly target: "curl";
30
- }, {
31
- readonly name: "diff";
32
- readonly target: "diff";
33
- }, {
34
- readonly name: "docker";
35
- readonly target: "docker";
36
- }, {
37
- readonly name: "eslint";
38
- readonly target: "lint";
39
- }, {
40
- readonly name: "find";
41
- readonly target: "find";
42
- }, {
43
- readonly name: "gh";
44
- readonly target: "gh";
45
- }, {
46
- readonly name: "git";
47
- readonly target: "git";
48
- }, {
49
- readonly name: "go";
50
- readonly target: "go";
51
- }, {
52
- readonly name: "golangci-lint";
53
- readonly target: "golangci-lint";
54
- }, {
55
- readonly name: "grep";
56
- readonly target: "grep";
57
- }, {
58
- readonly name: "kubectl";
59
- readonly target: "kubectl";
60
- }, {
61
- readonly name: "ls";
62
- readonly target: "ls";
63
- }, {
64
- readonly name: "mypy";
65
- readonly target: "mypy";
66
- }, {
67
- readonly name: "next";
68
- readonly target: "next";
69
- }, {
70
- readonly name: "npm";
71
- readonly target: "npm";
72
- }, {
73
- readonly name: "npx";
74
- readonly target: "npx";
75
- }, {
76
- readonly name: "pip";
77
- readonly target: "pip";
78
- }, {
79
- readonly name: "playwright";
80
- readonly target: "playwright";
81
- }, {
82
- readonly name: "pnpm";
83
- readonly target: "pnpm";
84
- }, {
85
- readonly name: "prettier";
86
- readonly target: "prettier";
87
- }, {
88
- readonly name: "prisma";
89
- readonly target: "prisma";
90
- }, {
91
- readonly name: "psql";
92
- readonly target: "psql";
93
- }, {
94
- readonly name: "pytest";
95
- readonly target: "pytest";
96
- }, {
97
- readonly name: "rg";
98
- readonly target: "grep";
99
- }, {
100
- readonly name: "ruff";
101
- readonly target: "ruff";
102
- }, {
103
- readonly name: "tree";
104
- readonly target: "tree";
105
- }, {
106
- readonly name: "tsc";
107
- readonly target: "tsc";
108
- }, {
109
- readonly name: "vitest";
110
- readonly target: "vitest";
111
- }, {
112
- readonly name: "wc";
113
- readonly target: "wc";
114
- }, {
115
- readonly name: "wget";
116
- readonly target: "wget";
117
- }];
118
- export declare function omxRuntimeConfigPath(codexHomeOverride?: string): string;
119
- export declare function readRtkEnabledSetting(codexHomeOverride?: string): boolean | undefined;
120
- export declare function resolveRtkExecutable(env?: NodeJS.ProcessEnv): string | undefined;
121
- export declare function isRtkInstalled(env?: NodeJS.ProcessEnv): boolean;
122
- export declare function isRtkEnabled(codexHomeOverride?: string, env?: NodeJS.ProcessEnv): boolean;
123
- export declare function rtkAliasesPath(): string;
124
- export declare function buildRtkAliasesScript(executablePath: string): string;
125
- export declare function writeRtkAliasesFile(executablePath: string, options?: EnsureRtkOptions): Promise<boolean>;
126
- export declare function ensureRtkInstalledAndAliases(options?: EnsureRtkOptions): Promise<EnsureRtkResult>;
127
- export declare function syncRtkRuntimeConfig(codexHomeDir: string, defaultEnabled: boolean, options?: EnsureRtkOptions): Promise<boolean>;
128
- export declare function resolveRtkBashEnv(codexHomeOverride?: string, env?: NodeJS.ProcessEnv): string | undefined;
129
- export declare function withRtkBashEnv(baseEnv: NodeJS.ProcessEnv, codexHomeOverride?: string): NodeJS.ProcessEnv;
130
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/rtk/index.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,cAAc;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAOD,MAAM,WAAW,gBAAgB;IAC/B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,EAAE,UAAU,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,GAAG,aAAa,CAAC;CAC1E;AAED,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAmCxB,CAAC;AAIX,wBAAgB,oBAAoB,CAAC,iBAAiB,CAAC,EAAE,MAAM,GAAG,MAAM,CAEvE;AAmBD,wBAAgB,qBAAqB,CACnC,iBAAiB,CAAC,EAAE,MAAM,GACzB,OAAO,GAAG,SAAS,CAIrB;AAoCD,wBAAgB,oBAAoB,CAClC,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,GAAG,SAAS,CASpB;AAED,wBAAgB,cAAc,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAE5E;AAED,wBAAgB,YAAY,CAC1B,iBAAiB,CAAC,EAAE,MAAM,EAC1B,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,OAAO,CAGT;AAED,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAMD,wBAAgB,qBAAqB,CAAC,cAAc,EAAE,MAAM,GAAG,MAAM,CAkBpE;AAED,wBAAsB,mBAAmB,CACvC,cAAc,EAAE,MAAM,EACtB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,OAAO,CAAC,CAalB;AAqBD,wBAAsB,4BAA4B,CAChD,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,eAAe,CAAC,CAkD1B;AAED,wBAAsB,oBAAoB,CACxC,YAAY,EAAE,MAAM,EACpB,cAAc,EAAE,OAAO,EACvB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,OAAO,CAAC,CA6BlB;AAED,wBAAgB,iBAAiB,CAC/B,iBAAiB,CAAC,EAAE,MAAM,EAC1B,GAAG,GAAE,MAAM,CAAC,UAAwB,GACnC,MAAM,GAAG,SAAS,CAKpB;AAED,wBAAgB,cAAc,CAC5B,OAAO,EAAE,MAAM,CAAC,UAAU,EAC1B,iBAAiB,CAAC,EAAE,MAAM,GACzB,MAAM,CAAC,UAAU,CAInB"}