oh-my-codex 0.8.11 → 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 (162) hide show
  1. package/README.md +43 -35
  2. package/dist/agents/__tests__/definitions.test.js +1 -0
  3. package/dist/agents/__tests__/definitions.test.js.map +1 -1
  4. package/dist/agents/definitions.d.ts.map +1 -1
  5. package/dist/agents/definitions.js +11 -0
  6. package/dist/agents/definitions.js.map +1 -1
  7. package/dist/cli/__tests__/doctor-invalid-config.test.d.ts +2 -0
  8. package/dist/cli/__tests__/doctor-invalid-config.test.d.ts.map +1 -0
  9. package/dist/cli/__tests__/doctor-invalid-config.test.js +52 -0
  10. package/dist/cli/__tests__/doctor-invalid-config.test.js.map +1 -0
  11. package/dist/cli/__tests__/index.test.js +35 -3
  12. package/dist/cli/__tests__/index.test.js.map +1 -1
  13. package/dist/cli/__tests__/launch-fallback.test.d.ts +2 -0
  14. package/dist/cli/__tests__/launch-fallback.test.d.ts.map +1 -0
  15. package/dist/cli/__tests__/launch-fallback.test.js +60 -0
  16. package/dist/cli/__tests__/launch-fallback.test.js.map +1 -0
  17. package/dist/cli/__tests__/resume.test.d.ts +2 -0
  18. package/dist/cli/__tests__/resume.test.d.ts.map +1 -0
  19. package/dist/cli/__tests__/resume.test.js +78 -0
  20. package/dist/cli/__tests__/resume.test.js.map +1 -0
  21. package/dist/cli/__tests__/session-search-help.test.d.ts +2 -0
  22. package/dist/cli/__tests__/session-search-help.test.d.ts.map +1 -0
  23. package/dist/cli/__tests__/session-search-help.test.js +36 -0
  24. package/dist/cli/__tests__/session-search-help.test.js.map +1 -0
  25. package/dist/cli/__tests__/session-search.test.d.ts +2 -0
  26. package/dist/cli/__tests__/session-search.test.d.ts.map +1 -0
  27. package/dist/cli/__tests__/session-search.test.js +77 -0
  28. package/dist/cli/__tests__/session-search.test.js.map +1 -0
  29. package/dist/cli/__tests__/setup-prompts-overwrite.test.js +2 -0
  30. package/dist/cli/__tests__/setup-prompts-overwrite.test.js.map +1 -1
  31. package/dist/cli/__tests__/team-decompose.test.js +41 -15
  32. package/dist/cli/__tests__/team-decompose.test.js.map +1 -1
  33. package/dist/cli/__tests__/team.test.js +208 -3
  34. package/dist/cli/__tests__/team.test.js.map +1 -1
  35. package/dist/cli/doctor.d.ts.map +1 -1
  36. package/dist/cli/doctor.js +26 -0
  37. package/dist/cli/doctor.js.map +1 -1
  38. package/dist/cli/index.d.ts +4 -3
  39. package/dist/cli/index.d.ts.map +1 -1
  40. package/dist/cli/index.js +73 -27
  41. package/dist/cli/index.js.map +1 -1
  42. package/dist/cli/session-search.d.ts +8 -0
  43. package/dist/cli/session-search.d.ts.map +1 -0
  44. package/dist/cli/session-search.js +133 -0
  45. package/dist/cli/session-search.js.map +1 -0
  46. package/dist/cli/team.d.ts +13 -12
  47. package/dist/cli/team.d.ts.map +1 -1
  48. package/dist/cli/team.js +123 -39
  49. package/dist/cli/team.js.map +1 -1
  50. package/dist/hooks/__tests__/agents-overlay.test.js +33 -1
  51. package/dist/hooks/__tests__/agents-overlay.test.js.map +1 -1
  52. package/dist/hooks/__tests__/notify-fallback-watcher.test.js +219 -0
  53. package/dist/hooks/__tests__/notify-fallback-watcher.test.js.map +1 -1
  54. package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js +1 -0
  55. package/dist/hooks/__tests__/notify-hook-all-workers-idle.test.js.map +1 -1
  56. package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js +64 -1
  57. package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js.map +1 -1
  58. package/dist/hooks/__tests__/notify-hook-modules.test.js +7 -0
  59. package/dist/hooks/__tests__/notify-hook-modules.test.js.map +1 -1
  60. package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js +2 -1
  61. package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js.map +1 -1
  62. package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js +420 -5
  63. package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js.map +1 -1
  64. package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js +95 -0
  65. package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js.map +1 -1
  66. package/dist/hooks/__tests__/notify-hook-worker-idle.test.js +3 -0
  67. package/dist/hooks/__tests__/notify-hook-worker-idle.test.js.map +1 -1
  68. package/dist/hooks/__tests__/tmux-hook-engine.test.js +39 -1
  69. package/dist/hooks/__tests__/tmux-hook-engine.test.js.map +1 -1
  70. package/dist/hooks/agents-overlay.d.ts +6 -1
  71. package/dist/hooks/agents-overlay.d.ts.map +1 -1
  72. package/dist/hooks/agents-overlay.js +45 -4
  73. package/dist/hooks/agents-overlay.js.map +1 -1
  74. package/dist/mcp/team-server.js +1 -1
  75. package/dist/mcp/team-server.js.map +1 -1
  76. package/dist/session-history/__tests__/search.test.d.ts +2 -0
  77. package/dist/session-history/__tests__/search.test.d.ts.map +1 -0
  78. package/dist/session-history/__tests__/search.test.js +150 -0
  79. package/dist/session-history/__tests__/search.test.js.map +1 -0
  80. package/dist/session-history/search.d.ts +31 -0
  81. package/dist/session-history/search.d.ts.map +1 -0
  82. package/dist/session-history/search.js +326 -0
  83. package/dist/session-history/search.js.map +1 -0
  84. package/dist/team/__tests__/allocation-policy.test.d.ts +2 -0
  85. package/dist/team/__tests__/allocation-policy.test.d.ts.map +1 -0
  86. package/dist/team/__tests__/allocation-policy.test.js +39 -0
  87. package/dist/team/__tests__/allocation-policy.test.js.map +1 -0
  88. package/dist/team/__tests__/api-interop.test.js +140 -4
  89. package/dist/team/__tests__/api-interop.test.js.map +1 -1
  90. package/dist/team/__tests__/followup-planner.test.js +12 -0
  91. package/dist/team/__tests__/followup-planner.test.js.map +1 -1
  92. package/dist/team/__tests__/idle-nudge.test.js +6 -1
  93. package/dist/team/__tests__/idle-nudge.test.js.map +1 -1
  94. package/dist/team/__tests__/rebalance-policy.test.d.ts +2 -0
  95. package/dist/team/__tests__/rebalance-policy.test.d.ts.map +1 -0
  96. package/dist/team/__tests__/rebalance-policy.test.js +125 -0
  97. package/dist/team/__tests__/rebalance-policy.test.js.map +1 -0
  98. package/dist/team/__tests__/runtime.test.js +315 -12
  99. package/dist/team/__tests__/runtime.test.js.map +1 -1
  100. package/dist/team/__tests__/state.test.js +20 -1
  101. package/dist/team/__tests__/state.test.js.map +1 -1
  102. package/dist/team/__tests__/team-ops-contract.test.js +1 -0
  103. package/dist/team/__tests__/team-ops-contract.test.js.map +1 -1
  104. package/dist/team/__tests__/worker-bootstrap.test.js +20 -3
  105. package/dist/team/__tests__/worker-bootstrap.test.js.map +1 -1
  106. package/dist/team/allocation-policy.d.ts +23 -0
  107. package/dist/team/allocation-policy.d.ts.map +1 -0
  108. package/dist/team/allocation-policy.js +71 -0
  109. package/dist/team/allocation-policy.js.map +1 -0
  110. package/dist/team/api-interop.d.ts +1 -1
  111. package/dist/team/api-interop.d.ts.map +1 -1
  112. package/dist/team/api-interop.js +159 -0
  113. package/dist/team/api-interop.js.map +1 -1
  114. package/dist/team/idle-nudge.js +1 -1
  115. package/dist/team/idle-nudge.js.map +1 -1
  116. package/dist/team/rebalance-policy.d.ts +19 -0
  117. package/dist/team/rebalance-policy.d.ts.map +1 -0
  118. package/dist/team/rebalance-policy.js +48 -0
  119. package/dist/team/rebalance-policy.js.map +1 -0
  120. package/dist/team/runtime.d.ts.map +1 -1
  121. package/dist/team/runtime.js +132 -17
  122. package/dist/team/runtime.js.map +1 -1
  123. package/dist/team/state/types.d.ts +3 -0
  124. package/dist/team/state/types.d.ts.map +1 -1
  125. package/dist/team/state/types.js.map +1 -1
  126. package/dist/team/state.d.ts +8 -0
  127. package/dist/team/state.d.ts.map +1 -1
  128. package/dist/team/state.js +28 -12
  129. package/dist/team/state.js.map +1 -1
  130. package/dist/team/team-ops.d.ts +2 -1
  131. package/dist/team/team-ops.d.ts.map +1 -1
  132. package/dist/team/team-ops.js +1 -0
  133. package/dist/team/team-ops.js.map +1 -1
  134. package/dist/team/tmux-session.d.ts +5 -4
  135. package/dist/team/tmux-session.d.ts.map +1 -1
  136. package/dist/team/tmux-session.js +5 -67
  137. package/dist/team/tmux-session.js.map +1 -1
  138. package/dist/team/worker-bootstrap.d.ts +1 -0
  139. package/dist/team/worker-bootstrap.d.ts.map +1 -1
  140. package/dist/team/worker-bootstrap.js +9 -2
  141. package/dist/team/worker-bootstrap.js.map +1 -1
  142. package/package.json +2 -1
  143. package/prompts/team-executor.md +57 -0
  144. package/prompts/team-orchestrator.md +8 -0
  145. package/scripts/notify-fallback-watcher.js +295 -1
  146. package/scripts/notify-hook/auto-nudge.js +20 -4
  147. package/scripts/notify-hook/team-dispatch.js +11 -58
  148. package/scripts/notify-hook/team-leader-nudge.js +59 -12
  149. package/scripts/notify-hook/team-tmux-guard.js +28 -11
  150. package/scripts/notify-hook/team-worker.js +3 -1
  151. package/scripts/notify-hook/tmux-injection.js +12 -13
  152. package/scripts/tmux-hook-engine.js +56 -0
  153. package/skills/team/SKILL.md +14 -0
  154. package/templates/catalog-manifest.json +5 -0
  155. package/dist/rtk/__tests__/index.test.d.ts +0 -2
  156. package/dist/rtk/__tests__/index.test.d.ts.map +0 -1
  157. package/dist/rtk/__tests__/index.test.js +0 -104
  158. package/dist/rtk/__tests__/index.test.js.map +0 -1
  159. package/dist/rtk/index.d.ts +0 -130
  160. package/dist/rtk/index.d.ts.map +0 -1
  161. package/dist/rtk/index.js +0 -257
  162. package/dist/rtk/index.js.map +0 -1
@@ -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
  }
@@ -200,6 +200,20 @@ Follow this exact lifecycle when running `$team`:
200
200
  Do not run `shutdown` while workers are actively writing updates unless user explicitly requested abort/cancel.
201
201
  Do not treat ad-hoc pane typing as primary control flow when runtime/state evidence is available.
202
202
 
203
+ ### Active leader monitoring rule
204
+
205
+ While a team is **ON/running**, the leader must not go blind. Keep checking live team state until terminal completion.
206
+
207
+ Minimum acceptable loop:
208
+
209
+ ```bash
210
+ sleep 30 && omx team status <team-name>
211
+ ```
212
+
213
+ Repeat that check while the team stays active, or use `omx team await <team-name> --timeout-ms 30000 --json` when event-driven waiting is a better fit.
214
+
215
+ If the leader gets a stale/team-stalled nudge, immediately run `omx team status <team-name>` before taking any manual intervention.
216
+
203
217
  ## Message Dispatch Policy (CLI-first, state-first)
204
218
 
205
219
  To avoid brittle behavior, **message/task delivery must not be driven by ad-hoc tmux typing**.
@@ -327,6 +327,11 @@
327
327
  "category": "build",
328
328
  "status": "active"
329
329
  },
330
+ {
331
+ "name": "team-executor",
332
+ "category": "build",
333
+ "status": "internal"
334
+ },
330
335
  {
331
336
  "name": "verifier",
332
337
  "category": "build",
@@ -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"}