oh-my-codex 0.11.11 → 0.11.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.
- package/Cargo.lock +5 -5
- package/Cargo.toml +1 -1
- package/README.de.md +12 -6
- package/README.el.md +223 -0
- package/README.es.md +12 -6
- package/README.fr.md +11 -5
- package/README.it.md +12 -6
- package/README.ja.md +12 -6
- package/README.ko.md +12 -6
- package/README.md +56 -28
- package/README.pl.md +216 -0
- package/README.pt.md +12 -6
- package/README.ru.md +12 -6
- package/README.tr.md +12 -6
- package/README.vi.md +148 -183
- package/README.zh-TW.md +14 -17
- package/README.zh.md +12 -6
- package/crates/omx-runtime-core/src/engine.rs +122 -4
- package/crates/omx-runtime-core/src/lib.rs +17 -0
- package/dist/autoresearch/contracts.d.ts.map +1 -1
- package/dist/autoresearch/contracts.js +1 -0
- package/dist/autoresearch/contracts.js.map +1 -1
- package/dist/autoresearch/runtime.d.ts.map +1 -1
- package/dist/autoresearch/runtime.js +7 -1
- package/dist/autoresearch/runtime.js.map +1 -1
- package/dist/cli/__tests__/agents.test.js +24 -1
- package/dist/cli/__tests__/agents.test.js.map +1 -1
- package/dist/cli/__tests__/autoresearch.test.js +11 -0
- package/dist/cli/__tests__/autoresearch.test.js.map +1 -1
- package/dist/cli/__tests__/cleanup.test.js +117 -4
- package/dist/cli/__tests__/cleanup.test.js.map +1 -1
- package/dist/cli/__tests__/doctor-warning-copy.test.js +33 -3
- package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
- package/dist/cli/__tests__/error-handling-warnings.test.js +13 -0
- package/dist/cli/__tests__/error-handling-warnings.test.js.map +1 -1
- package/dist/cli/__tests__/exec.test.js +6 -0
- package/dist/cli/__tests__/exec.test.js.map +1 -1
- package/dist/cli/__tests__/index.test.js +101 -1
- package/dist/cli/__tests__/index.test.js.map +1 -1
- package/dist/cli/__tests__/launch-fallback.test.js +3 -0
- package/dist/cli/__tests__/launch-fallback.test.js.map +1 -1
- package/dist/cli/__tests__/package-bin-contract.test.js +10 -0
- package/dist/cli/__tests__/package-bin-contract.test.js.map +1 -1
- package/dist/cli/__tests__/packaged-script-resolution.test.js +4 -3
- package/dist/cli/__tests__/packaged-script-resolution.test.js.map +1 -1
- package/dist/cli/__tests__/resume.test.js +6 -0
- package/dist/cli/__tests__/resume.test.js.map +1 -1
- package/dist/cli/__tests__/setup-refresh.test.js +29 -12
- package/dist/cli/__tests__/setup-refresh.test.js.map +1 -1
- package/dist/cli/__tests__/setup-scope.test.js +1 -1
- package/dist/cli/__tests__/setup-scope.test.js.map +1 -1
- package/dist/cli/__tests__/star-prompt.test.js +16 -0
- package/dist/cli/__tests__/star-prompt.test.js.map +1 -1
- package/dist/cli/__tests__/uninstall.test.js +112 -1
- package/dist/cli/__tests__/uninstall.test.js.map +1 -1
- package/dist/cli/__tests__/windows-popup-loop-contract.test.d.ts +2 -0
- package/dist/cli/__tests__/windows-popup-loop-contract.test.d.ts.map +1 -0
- package/dist/cli/__tests__/windows-popup-loop-contract.test.js +30 -0
- package/dist/cli/__tests__/windows-popup-loop-contract.test.js.map +1 -0
- package/dist/cli/agents.d.ts.map +1 -1
- package/dist/cli/agents.js +9 -3
- package/dist/cli/agents.js.map +1 -1
- package/dist/cli/autoresearch-guided.d.ts.map +1 -1
- package/dist/cli/autoresearch-guided.js +9 -3
- package/dist/cli/autoresearch-guided.js.map +1 -1
- package/dist/cli/autoresearch.d.ts.map +1 -1
- package/dist/cli/autoresearch.js +8 -2
- package/dist/cli/autoresearch.js.map +1 -1
- package/dist/cli/cleanup.d.ts +2 -0
- package/dist/cli/cleanup.d.ts.map +1 -1
- package/dist/cli/cleanup.js +27 -1
- package/dist/cli/cleanup.js.map +1 -1
- package/dist/cli/doctor.js +7 -0
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/index.d.ts +9 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +171 -55
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +18 -15
- package/dist/cli/setup.js.map +1 -1
- package/dist/cli/star-prompt.d.ts.map +1 -1
- package/dist/cli/star-prompt.js +2 -0
- package/dist/cli/star-prompt.js.map +1 -1
- package/dist/cli/team.d.ts.map +1 -1
- package/dist/cli/team.js +5 -1
- package/dist/cli/team.js.map +1 -1
- package/dist/cli/tmux-hook.d.ts.map +1 -1
- package/dist/cli/tmux-hook.js +4 -1
- package/dist/cli/tmux-hook.js.map +1 -1
- package/dist/cli/uninstall.d.ts.map +1 -1
- package/dist/cli/uninstall.js +26 -0
- package/dist/cli/uninstall.js.map +1 -1
- package/dist/cli/update.d.ts.map +1 -1
- package/dist/cli/update.js +1 -0
- package/dist/cli/update.js.map +1 -1
- package/dist/compat/__tests__/rust-runtime-compat.test.js +84 -1
- package/dist/compat/__tests__/rust-runtime-compat.test.js.map +1 -1
- package/dist/config/__tests__/generator-idempotent.test.js +4 -4
- package/dist/config/__tests__/generator-idempotent.test.js.map +1 -1
- package/dist/config/__tests__/mcp-registry.test.js +13 -16
- package/dist/config/__tests__/mcp-registry.test.js.map +1 -1
- package/dist/config/mcp-registry.d.ts +1 -0
- package/dist/config/mcp-registry.d.ts.map +1 -1
- package/dist/config/mcp-registry.js +4 -4
- package/dist/config/mcp-registry.js.map +1 -1
- package/dist/config/models.d.ts +1 -0
- package/dist/config/models.d.ts.map +1 -1
- package/dist/config/models.js +39 -1
- package/dist/config/models.js.map +1 -1
- package/dist/hooks/__tests__/keyword-detector.test.js +12 -1
- package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-fallback-watcher.test.js +554 -18
- package/dist/hooks/__tests__/notify-fallback-watcher.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js +347 -16
- package/dist/hooks/__tests__/notify-hook-auto-nudge.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-modules.test.js +5 -0
- package/dist/hooks/__tests__/notify-hook-modules.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-ralph-resume.test.d.ts +2 -0
- package/dist/hooks/__tests__/notify-hook-ralph-resume.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/notify-hook-ralph-resume.test.js +597 -0
- package/dist/hooks/__tests__/notify-hook-ralph-resume.test.js.map +1 -0
- package/dist/hooks/__tests__/notify-hook-regression-205.test.js +19 -1
- package/dist/hooks/__tests__/notify-hook-regression-205.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-session-scope.test.js +73 -53
- package/dist/hooks/__tests__/notify-hook-session-scope.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js +193 -2
- package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js +183 -0
- package/dist/hooks/__tests__/notify-hook-team-leader-nudge.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js +255 -97
- package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-tmux-scrollback.test.js +0 -0
- package/dist/hooks/__tests__/notify-hook-tmux-scrollback.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-worker-idle.test.js +46 -0
- package/dist/hooks/__tests__/notify-hook-worker-idle.test.js.map +1 -1
- package/dist/hooks/__tests__/prompt-team-routing.test.js +34 -0
- package/dist/hooks/__tests__/prompt-team-routing.test.js.map +1 -1
- package/dist/hooks/__tests__/tmux-hook-engine.test.js +32 -1
- package/dist/hooks/__tests__/tmux-hook-engine.test.js.map +1 -1
- package/dist/hooks/code-simplifier/index.d.ts.map +1 -1
- package/dist/hooks/code-simplifier/index.js +1 -0
- package/dist/hooks/code-simplifier/index.js.map +1 -1
- package/dist/hooks/codebase-map.d.ts.map +1 -1
- package/dist/hooks/codebase-map.js +1 -0
- package/dist/hooks/codebase-map.js.map +1 -1
- package/dist/hooks/extensibility/sdk/tmux.d.ts.map +1 -1
- package/dist/hooks/extensibility/sdk/tmux.js +3 -1
- package/dist/hooks/extensibility/sdk/tmux.js.map +1 -1
- package/dist/hooks/keyword-detector.d.ts +1 -0
- package/dist/hooks/keyword-detector.d.ts.map +1 -1
- package/dist/hooks/keyword-detector.js +48 -0
- package/dist/hooks/keyword-detector.js.map +1 -1
- package/dist/hooks/prompt-guidance-contract.d.ts.map +1 -1
- package/dist/hooks/prompt-guidance-contract.js +6 -0
- package/dist/hooks/prompt-guidance-contract.js.map +1 -1
- package/dist/hooks/session.d.ts.map +1 -1
- package/dist/hooks/session.js +1 -0
- package/dist/hooks/session.js.map +1 -1
- package/dist/hud/__tests__/state.test.js +70 -1
- package/dist/hud/__tests__/state.test.js.map +1 -1
- package/dist/hud/authority.d.ts.map +1 -1
- package/dist/hud/authority.js +1 -0
- package/dist/hud/authority.js.map +1 -1
- package/dist/hud/state.d.ts.map +1 -1
- package/dist/hud/state.js +52 -0
- package/dist/hud/state.js.map +1 -1
- package/dist/mcp/state-server.d.ts.map +1 -1
- package/dist/mcp/state-server.js +5 -0
- package/dist/mcp/state-server.js.map +1 -1
- package/dist/modes/__tests__/base-session-scope.test.js +46 -0
- package/dist/modes/__tests__/base-session-scope.test.js.map +1 -1
- package/dist/modes/base.d.ts.map +1 -1
- package/dist/modes/base.js +4 -0
- package/dist/modes/base.js.map +1 -1
- package/dist/notifications/__tests__/custom-alias-enablement.test.d.ts +2 -0
- package/dist/notifications/__tests__/custom-alias-enablement.test.d.ts.map +1 -0
- package/dist/notifications/__tests__/custom-alias-enablement.test.js +84 -0
- package/dist/notifications/__tests__/custom-alias-enablement.test.js.map +1 -0
- package/dist/notifications/__tests__/idle-cooldown.test.js +55 -0
- package/dist/notifications/__tests__/idle-cooldown.test.js.map +1 -1
- package/dist/notifications/idle-cooldown.d.ts +8 -6
- package/dist/notifications/idle-cooldown.d.ts.map +1 -1
- package/dist/notifications/idle-cooldown.js +53 -22
- package/dist/notifications/idle-cooldown.js.map +1 -1
- package/dist/notifications/notifier.js +1 -1
- package/dist/notifications/notifier.js.map +1 -1
- package/dist/notifications/reply-listener.d.ts.map +1 -1
- package/dist/notifications/reply-listener.js +1 -0
- package/dist/notifications/reply-listener.js.map +1 -1
- package/dist/notifications/tmux.d.ts.map +1 -1
- package/dist/notifications/tmux.js +4 -0
- package/dist/notifications/tmux.js.map +1 -1
- package/dist/openclaw/config.js +2 -2
- package/dist/openclaw/config.js.map +1 -1
- package/dist/runtime/bridge.d.ts +2 -0
- package/dist/runtime/bridge.d.ts.map +1 -1
- package/dist/runtime/bridge.js +8 -0
- package/dist/runtime/bridge.js.map +1 -1
- package/dist/scripts/notify-fallback-watcher.js +103 -53
- package/dist/scripts/notify-fallback-watcher.js.map +1 -1
- package/dist/scripts/notify-hook/auto-nudge.d.ts +2 -1
- package/dist/scripts/notify-hook/auto-nudge.d.ts.map +1 -1
- package/dist/scripts/notify-hook/auto-nudge.js +90 -104
- package/dist/scripts/notify-hook/auto-nudge.js.map +1 -1
- package/dist/scripts/notify-hook/managed-tmux.d.ts +19 -0
- package/dist/scripts/notify-hook/managed-tmux.d.ts.map +1 -0
- package/dist/scripts/notify-hook/managed-tmux.js +320 -0
- package/dist/scripts/notify-hook/managed-tmux.js.map +1 -0
- package/dist/scripts/notify-hook/operational-events.d.ts.map +1 -1
- package/dist/scripts/notify-hook/operational-events.js +2 -0
- package/dist/scripts/notify-hook/operational-events.js.map +1 -1
- package/dist/scripts/notify-hook/ralph-session-resume.d.ts +22 -0
- package/dist/scripts/notify-hook/ralph-session-resume.d.ts.map +1 -0
- package/dist/scripts/notify-hook/ralph-session-resume.js +277 -0
- package/dist/scripts/notify-hook/ralph-session-resume.js.map +1 -0
- package/dist/scripts/notify-hook/state-io.d.ts +1 -1
- package/dist/scripts/notify-hook/state-io.d.ts.map +1 -1
- package/dist/scripts/notify-hook/state-io.js +2 -10
- package/dist/scripts/notify-hook/state-io.js.map +1 -1
- package/dist/scripts/notify-hook/team-dispatch.d.ts +1 -1
- package/dist/scripts/notify-hook/team-dispatch.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-dispatch.js +123 -72
- package/dist/scripts/notify-hook/team-dispatch.js.map +1 -1
- package/dist/scripts/notify-hook/team-leader-nudge.d.ts +2 -1
- package/dist/scripts/notify-hook/team-leader-nudge.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-leader-nudge.js +13 -5
- package/dist/scripts/notify-hook/team-leader-nudge.js.map +1 -1
- package/dist/scripts/notify-hook/team-tmux-guard.d.ts.map +1 -1
- package/dist/scripts/notify-hook/team-tmux-guard.js +1 -19
- package/dist/scripts/notify-hook/team-tmux-guard.js.map +1 -1
- package/dist/scripts/notify-hook/team-worker.js +4 -4
- package/dist/scripts/notify-hook/team-worker.js.map +1 -1
- package/dist/scripts/notify-hook/tmux-injection.d.ts +1 -1
- package/dist/scripts/notify-hook/tmux-injection.d.ts.map +1 -1
- package/dist/scripts/notify-hook/tmux-injection.js +102 -35
- package/dist/scripts/notify-hook/tmux-injection.js.map +1 -1
- package/dist/scripts/notify-hook.js +144 -20
- package/dist/scripts/notify-hook.js.map +1 -1
- package/dist/scripts/run-provider-advisor.js +2 -0
- package/dist/scripts/run-provider-advisor.js.map +1 -1
- package/dist/scripts/run-test-files.d.ts +2 -0
- package/dist/scripts/run-test-files.d.ts.map +1 -0
- package/dist/scripts/run-test-files.js +41 -0
- package/dist/scripts/run-test-files.js.map +1 -0
- package/dist/scripts/tmux-hook-engine.d.ts +2 -0
- package/dist/scripts/tmux-hook-engine.d.ts.map +1 -1
- package/dist/scripts/tmux-hook-engine.js +15 -0
- package/dist/scripts/tmux-hook-engine.js.map +1 -1
- package/dist/team/__tests__/api-interop.test.js +136 -4
- package/dist/team/__tests__/api-interop.test.js.map +1 -1
- package/dist/team/__tests__/leader-activity.test.js +107 -2
- package/dist/team/__tests__/leader-activity.test.js.map +1 -1
- package/dist/team/__tests__/runtime-cli.test.js +32 -0
- package/dist/team/__tests__/runtime-cli.test.js.map +1 -1
- package/dist/team/__tests__/runtime.test.js +148 -0
- package/dist/team/__tests__/runtime.test.js.map +1 -1
- package/dist/team/__tests__/shutdown-fallback.test.js +13 -0
- package/dist/team/__tests__/shutdown-fallback.test.js.map +1 -1
- package/dist/team/__tests__/state-root.test.js +11 -1
- package/dist/team/__tests__/state-root.test.js.map +1 -1
- package/dist/team/__tests__/state.test.js +237 -0
- package/dist/team/__tests__/state.test.js.map +1 -1
- package/dist/team/__tests__/tmux-session.test.js +521 -2
- package/dist/team/__tests__/tmux-session.test.js.map +1 -1
- package/dist/team/api-interop.d.ts.map +1 -1
- package/dist/team/api-interop.js +41 -31
- package/dist/team/api-interop.js.map +1 -1
- package/dist/team/commit-hygiene.d.ts +60 -0
- package/dist/team/commit-hygiene.d.ts.map +1 -0
- package/dist/team/commit-hygiene.js +232 -0
- package/dist/team/commit-hygiene.js.map +1 -0
- package/dist/team/leader-activity.d.ts.map +1 -1
- package/dist/team/leader-activity.js +56 -4
- package/dist/team/leader-activity.js.map +1 -1
- package/dist/team/runtime-cli.d.ts +9 -1
- package/dist/team/runtime-cli.d.ts.map +1 -1
- package/dist/team/runtime-cli.js +15 -6
- package/dist/team/runtime-cli.js.map +1 -1
- package/dist/team/runtime.d.ts +7 -2
- package/dist/team/runtime.d.ts.map +1 -1
- package/dist/team/runtime.js +392 -171
- package/dist/team/runtime.js.map +1 -1
- package/dist/team/scaling.d.ts.map +1 -1
- package/dist/team/scaling.js +6 -2
- package/dist/team/scaling.js.map +1 -1
- package/dist/team/state/dispatch.d.ts +2 -0
- package/dist/team/state/dispatch.d.ts.map +1 -1
- package/dist/team/state/dispatch.js +86 -40
- package/dist/team/state/dispatch.js.map +1 -1
- package/dist/team/state/mailbox.d.ts +3 -0
- package/dist/team/state/mailbox.d.ts.map +1 -1
- package/dist/team/state/mailbox.js +93 -19
- package/dist/team/state/mailbox.js.map +1 -1
- package/dist/team/state-root.d.ts +1 -1
- package/dist/team/state-root.d.ts.map +1 -1
- package/dist/team/state-root.js +8 -3
- package/dist/team/state-root.js.map +1 -1
- package/dist/team/state.d.ts.map +1 -1
- package/dist/team/state.js +96 -2
- package/dist/team/state.js.map +1 -1
- package/dist/team/tmux-session.d.ts.map +1 -1
- package/dist/team/tmux-session.js +81 -29
- package/dist/team/tmux-session.js.map +1 -1
- package/dist/team/worker-bootstrap.d.ts.map +1 -1
- package/dist/team/worker-bootstrap.js +4 -0
- package/dist/team/worker-bootstrap.js.map +1 -1
- package/dist/team/worktree.d.ts.map +1 -1
- package/dist/team/worktree.js +9 -0
- package/dist/team/worktree.js.map +1 -1
- package/dist/utils/__tests__/paths.test.js +98 -11
- package/dist/utils/__tests__/paths.test.js.map +1 -1
- package/dist/utils/__tests__/platform-command.test.js +101 -2
- package/dist/utils/__tests__/platform-command.test.js.map +1 -1
- package/dist/utils/git-layout.d.ts +8 -0
- package/dist/utils/git-layout.d.ts.map +1 -0
- package/dist/utils/git-layout.js +58 -0
- package/dist/utils/git-layout.js.map +1 -0
- package/dist/utils/paths.d.ts +3 -0
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js +14 -4
- package/dist/utils/paths.js.map +1 -1
- package/dist/utils/platform-command.d.ts.map +1 -1
- package/dist/utils/platform-command.js +35 -3
- package/dist/utils/platform-command.js.map +1 -1
- package/package.json +9 -5
- package/src/scripts/notify-fallback-watcher.ts +103 -53
- package/src/scripts/notify-hook/auto-nudge.ts +97 -103
- package/src/scripts/notify-hook/managed-tmux.ts +324 -0
- package/src/scripts/notify-hook/operational-events.ts +2 -0
- package/src/scripts/notify-hook/ralph-session-resume.ts +337 -0
- package/src/scripts/notify-hook/state-io.ts +2 -10
- package/src/scripts/notify-hook/team-dispatch.ts +131 -66
- package/src/scripts/notify-hook/team-leader-nudge.ts +19 -5
- package/src/scripts/notify-hook/team-tmux-guard.ts +0 -20
- package/src/scripts/notify-hook/team-worker.ts +4 -4
- package/src/scripts/notify-hook/tmux-injection.ts +103 -33
- package/src/scripts/notify-hook.ts +150 -21
- package/src/scripts/run-provider-advisor.ts +4 -2
- package/src/scripts/run-test-files.ts +48 -0
- package/src/scripts/tmux-hook-engine.ts +16 -0
- package/templates/AGENTS.md +51 -43
|
@@ -3,10 +3,10 @@ import assert from 'node:assert/strict';
|
|
|
3
3
|
import fs from 'node:fs';
|
|
4
4
|
import { syncBuiltinESMExports } from 'node:module';
|
|
5
5
|
import { PassThrough } from 'node:stream';
|
|
6
|
-
import { mkdtemp, readFile, rm, writeFile
|
|
6
|
+
import { chmod, mkdir, mkdtemp, readFile, rm, writeFile } from 'fs/promises';
|
|
7
7
|
import { join } from 'path';
|
|
8
8
|
import { tmpdir } from 'os';
|
|
9
|
-
import { buildClientAttachedReconcileHookName, assertTeamWorkerCliBinaryAvailable, buildWorkerProcessLaunchSpec, buildReconcileHudResizeArgs, buildRegisterClientAttachedReconcileArgs, buildRegisterResizeHookArgs, buildResizeHookName, buildResizeHookTarget, buildScheduleDelayedHudResizeArgs, buildUnregisterClientAttachedReconcileArgs, buildUnregisterResizeHookArgs, buildWorkerStartupCommand, buildHudPaneTarget, chooseTeamLeaderPaneId, createTeamSession, enableMouseScrolling, isMsysOrGitBash, isNativeWindows, isTmuxAvailable, translatePathForMsys, isWsl2, isWorkerAlive, killWorker, killWorkerByPaneId, teardownWorkerPanes, listTeamSessions, resolveTeamWorkerCli, resolveTeamWorkerLaunchMode, resolveWorkerCliForSend, resolveTeamWorkerCliPlan, buildWorkerSubmitPlan, sanitizeTeamName, shouldAttemptAdaptiveRetry, sendToWorker, sendToWorkerStdin, sleepFractionalSeconds, translateWorkerLaunchArgsForCli, waitForWorkerReady, paneIsBootstrapping, dismissTrustPromptIfPresent, } from '../tmux-session.js';
|
|
9
|
+
import { buildClientAttachedReconcileHookName, assertTeamWorkerCliBinaryAvailable, buildWorkerProcessLaunchSpec, buildReconcileHudResizeArgs, buildRegisterClientAttachedReconcileArgs, buildRegisterResizeHookArgs, buildResizeHookName, buildResizeHookTarget, buildScheduleDelayedHudResizeArgs, buildUnregisterClientAttachedReconcileArgs, buildUnregisterResizeHookArgs, buildWorkerStartupCommand, buildHudPaneTarget, chooseTeamLeaderPaneId, createTeamSession, enableMouseScrolling, isMsysOrGitBash, isNativeWindows, isTmuxAvailable, restoreStandaloneHudPane, translatePathForMsys, isWsl2, isWorkerAlive, killWorker, killWorkerByPaneId, teardownWorkerPanes, listTeamSessions, resolveTeamWorkerCli, resolveTeamWorkerLaunchMode, resolveWorkerCliForSend, resolveTeamWorkerCliPlan, buildWorkerSubmitPlan, sanitizeTeamName, shouldAttemptAdaptiveRetry, sendToWorker, sendToWorkerStdin, sleepFractionalSeconds, translateWorkerLaunchArgsForCli, waitForWorkerReady, paneIsBootstrapping, dismissTrustPromptIfPresent, } from '../tmux-session.js';
|
|
10
10
|
import { HUD_RESIZE_RECONCILE_DELAY_SECONDS, HUD_TMUX_TEAM_HEIGHT_LINES } from '../../hud/constants.js';
|
|
11
11
|
import * as tmuxSessionModule from '../tmux-session.js';
|
|
12
12
|
function withEmptyPath(fn) {
|
|
@@ -51,6 +51,17 @@ const READY_HELPER_CAPTURE = `╭───────────────
|
|
|
51
51
|
╰────────────────────────────────────────────╯
|
|
52
52
|
|
|
53
53
|
How can I help you today?`;
|
|
54
|
+
const VIEWPORT_WITHOUT_VISIBLE_PROMPT_CAPTURE = `╭────────────────────────────────────────────╮
|
|
55
|
+
│ >_ OpenAI Codex (v0.118.0) │
|
|
56
|
+
│ │
|
|
57
|
+
│ model: gpt-5.4 high /model to change │
|
|
58
|
+
│ directory: ~/Workspace/demo │
|
|
59
|
+
╰────────────────────────────────────────────╯
|
|
60
|
+
|
|
61
|
+
⚠ MCP startup incomplete (failed: hf request)`;
|
|
62
|
+
const VIEWPORT_SCROLLBACK_READY_CAPTURE = `${VIEWPORT_WITHOUT_VISIBLE_PROMPT_CAPTURE}
|
|
63
|
+
|
|
64
|
+
› support lane on multi-image attach`;
|
|
54
65
|
async function withMockTmuxFixture(dirPrefix, tmuxScript, run) {
|
|
55
66
|
const fakeBinDir = await mkdtemp(join(tmpdir(), dirPrefix));
|
|
56
67
|
const logPath = join(fakeBinDir, 'tmux.log');
|
|
@@ -179,6 +190,71 @@ describe('HUD resize hook command builders', () => {
|
|
|
179
190
|
assert.equal(args.join(' ').includes('split-window'), false);
|
|
180
191
|
assert.deepEqual(args, ['run-shell', `tmux resize-pane -t %7 -y ${HUD_TMUX_TEAM_HEIGHT_LINES} >/dev/null 2>&1 || true`]);
|
|
181
192
|
});
|
|
193
|
+
it('resolves the tmux executable for win32 hook shell snippets', async () => {
|
|
194
|
+
const fakeBin = await mkdtemp(join(tmpdir(), 'omx-win32-hook-tmux-'));
|
|
195
|
+
const prevPath = process.env.PATH;
|
|
196
|
+
const prevPathext = process.env.PATHEXT;
|
|
197
|
+
const origPlatform = Object.getOwnPropertyDescriptor(process, 'platform');
|
|
198
|
+
try {
|
|
199
|
+
const tmuxPath = join(fakeBin, 'tmux.exe');
|
|
200
|
+
await writeFile(tmuxPath, '');
|
|
201
|
+
process.env.PATH = fakeBin;
|
|
202
|
+
process.env.PATHEXT = '.EXE';
|
|
203
|
+
Object.defineProperty(process, 'platform', { value: 'win32', configurable: true });
|
|
204
|
+
const resizeArgs = buildRegisterResizeHookArgs('my-session:0', 'omx_resize_team_session_0_1', '%1');
|
|
205
|
+
const delayedArgs = buildScheduleDelayedHudResizeArgs('%1');
|
|
206
|
+
const reconcileArgs = buildReconcileHudResizeArgs('%1');
|
|
207
|
+
assert.match(resizeArgs[4] ?? '', new RegExp(escapeRegExp(tmuxPath)));
|
|
208
|
+
assert.doesNotMatch(resizeArgs[4] ?? '', /^run-shell -b 'tmux resize-pane/);
|
|
209
|
+
assert.match(delayedArgs[2] ?? '', new RegExp(escapeRegExp(tmuxPath)));
|
|
210
|
+
assert.doesNotMatch(delayedArgs[2] ?? '', /sleep \d+; tmux resize-pane/);
|
|
211
|
+
assert.match(reconcileArgs[1] ?? '', new RegExp(escapeRegExp(tmuxPath)));
|
|
212
|
+
assert.doesNotMatch(reconcileArgs[1] ?? '', /^tmux resize-pane/);
|
|
213
|
+
}
|
|
214
|
+
finally {
|
|
215
|
+
if (origPlatform)
|
|
216
|
+
Object.defineProperty(process, 'platform', origPlatform);
|
|
217
|
+
if (typeof prevPath === 'string')
|
|
218
|
+
process.env.PATH = prevPath;
|
|
219
|
+
else
|
|
220
|
+
delete process.env.PATH;
|
|
221
|
+
if (typeof prevPathext === 'string')
|
|
222
|
+
process.env.PATHEXT = prevPathext;
|
|
223
|
+
else
|
|
224
|
+
delete process.env.PATHEXT;
|
|
225
|
+
await rm(fakeBin, { recursive: true, force: true });
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
it('resolves the tmux executable twice for win32 client-attached one-shot hooks', async () => {
|
|
229
|
+
const fakeBin = await mkdtemp(join(tmpdir(), 'omx-win32-attached-hook-'));
|
|
230
|
+
const prevPath = process.env.PATH;
|
|
231
|
+
const prevPathext = process.env.PATHEXT;
|
|
232
|
+
const origPlatform = Object.getOwnPropertyDescriptor(process, 'platform');
|
|
233
|
+
try {
|
|
234
|
+
const tmuxPath = join(fakeBin, 'tmux.exe');
|
|
235
|
+
await writeFile(tmuxPath, '');
|
|
236
|
+
process.env.PATH = fakeBin;
|
|
237
|
+
process.env.PATHEXT = '.EXE';
|
|
238
|
+
Object.defineProperty(process, 'platform', { value: 'win32', configurable: true });
|
|
239
|
+
const args = buildRegisterClientAttachedReconcileArgs('my-session:0', 'omx_attached_team_session_0_1', '%1');
|
|
240
|
+
const matches = (args[4] ?? '').match(new RegExp(escapeRegExp(tmuxPath), 'g')) || [];
|
|
241
|
+
assert.equal(matches.length, 2, 'client-attached hook should resolve tmux for both resize and unregister commands');
|
|
242
|
+
assert.doesNotMatch(args[4] ?? '', /; tmux set-hook -u -t my-session:0 client-attached/);
|
|
243
|
+
}
|
|
244
|
+
finally {
|
|
245
|
+
if (origPlatform)
|
|
246
|
+
Object.defineProperty(process, 'platform', origPlatform);
|
|
247
|
+
if (typeof prevPath === 'string')
|
|
248
|
+
process.env.PATH = prevPath;
|
|
249
|
+
else
|
|
250
|
+
delete process.env.PATH;
|
|
251
|
+
if (typeof prevPathext === 'string')
|
|
252
|
+
process.env.PATHEXT = prevPathext;
|
|
253
|
+
else
|
|
254
|
+
delete process.env.PATHEXT;
|
|
255
|
+
await rm(fakeBin, { recursive: true, force: true });
|
|
256
|
+
}
|
|
257
|
+
});
|
|
182
258
|
});
|
|
183
259
|
describe('sendToWorker validation', () => {
|
|
184
260
|
it('rejects text over 200 chars', async () => {
|
|
@@ -1105,6 +1181,212 @@ describe('team worker launch mode helpers', () => {
|
|
|
1105
1181
|
delete process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT;
|
|
1106
1182
|
}
|
|
1107
1183
|
});
|
|
1184
|
+
it('buildWorkerProcessLaunchSpec injects the active provider env_key from CODEX_HOME config.toml', async () => {
|
|
1185
|
+
const prevBypass = process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT;
|
|
1186
|
+
const prevCodexHome = process.env.CODEX_HOME;
|
|
1187
|
+
const prevProviderEnv = process.env.CUSTOM_PROVIDER_API_KEY;
|
|
1188
|
+
const codexHome = await mkdtemp(join(tmpdir(), 'omx-team-provider-env-'));
|
|
1189
|
+
process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT = '0';
|
|
1190
|
+
process.env.CODEX_HOME = codexHome;
|
|
1191
|
+
process.env.CUSTOM_PROVIDER_API_KEY = 'test-secret';
|
|
1192
|
+
try {
|
|
1193
|
+
await writeFile(join(codexHome, 'config.toml'), [
|
|
1194
|
+
'model_provider = "custom_provider"',
|
|
1195
|
+
'',
|
|
1196
|
+
'[model_providers.custom_provider]',
|
|
1197
|
+
'name = "custom_provider"',
|
|
1198
|
+
'base_url = "http://localhost:3000/v1"',
|
|
1199
|
+
'wire_api = "responses"',
|
|
1200
|
+
'requires_openai_auth = true',
|
|
1201
|
+
'env_key = "CUSTOM_PROVIDER_API_KEY"',
|
|
1202
|
+
'',
|
|
1203
|
+
].join('\n'));
|
|
1204
|
+
const spec = buildWorkerProcessLaunchSpec('gamma-team', 1, [], '/tmp/workspace', {}, 'codex');
|
|
1205
|
+
assert.equal(spec.env.CUSTOM_PROVIDER_API_KEY, 'test-secret');
|
|
1206
|
+
}
|
|
1207
|
+
finally {
|
|
1208
|
+
if (typeof prevBypass === 'string')
|
|
1209
|
+
process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT = prevBypass;
|
|
1210
|
+
else
|
|
1211
|
+
delete process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT;
|
|
1212
|
+
if (typeof prevCodexHome === 'string')
|
|
1213
|
+
process.env.CODEX_HOME = prevCodexHome;
|
|
1214
|
+
else
|
|
1215
|
+
delete process.env.CODEX_HOME;
|
|
1216
|
+
if (typeof prevProviderEnv === 'string')
|
|
1217
|
+
process.env.CUSTOM_PROVIDER_API_KEY = prevProviderEnv;
|
|
1218
|
+
else
|
|
1219
|
+
delete process.env.CUSTOM_PROVIDER_API_KEY;
|
|
1220
|
+
await rm(codexHome, { recursive: true, force: true });
|
|
1221
|
+
}
|
|
1222
|
+
});
|
|
1223
|
+
it('buildWorkerProcessLaunchSpec does not inject the active provider env_key for non-codex workers', async () => {
|
|
1224
|
+
const prevBypass = process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT;
|
|
1225
|
+
const prevCodexHome = process.env.CODEX_HOME;
|
|
1226
|
+
const prevProviderEnv = process.env.CUSTOM_PROVIDER_API_KEY;
|
|
1227
|
+
const codexHome = await mkdtemp(join(tmpdir(), 'omx-team-provider-env-'));
|
|
1228
|
+
process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT = '0';
|
|
1229
|
+
process.env.CODEX_HOME = codexHome;
|
|
1230
|
+
process.env.CUSTOM_PROVIDER_API_KEY = 'test-secret';
|
|
1231
|
+
try {
|
|
1232
|
+
await writeFile(join(codexHome, 'config.toml'), [
|
|
1233
|
+
'model_provider = "custom_provider"',
|
|
1234
|
+
'',
|
|
1235
|
+
'[model_providers.custom_provider]',
|
|
1236
|
+
'name = "custom_provider"',
|
|
1237
|
+
'base_url = "http://localhost:3000/v1"',
|
|
1238
|
+
'wire_api = "responses"',
|
|
1239
|
+
'requires_openai_auth = true',
|
|
1240
|
+
'env_key = "CUSTOM_PROVIDER_API_KEY"',
|
|
1241
|
+
'',
|
|
1242
|
+
].join('\n'));
|
|
1243
|
+
const spec = buildWorkerProcessLaunchSpec('delta-team', 1, [], '/tmp/workspace', {}, 'claude');
|
|
1244
|
+
assert.equal(spec.workerCli, 'claude');
|
|
1245
|
+
assert.equal(spec.env.CUSTOM_PROVIDER_API_KEY, undefined);
|
|
1246
|
+
}
|
|
1247
|
+
finally {
|
|
1248
|
+
if (typeof prevBypass === 'string')
|
|
1249
|
+
process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT = prevBypass;
|
|
1250
|
+
else
|
|
1251
|
+
delete process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT;
|
|
1252
|
+
if (typeof prevCodexHome === 'string')
|
|
1253
|
+
process.env.CODEX_HOME = prevCodexHome;
|
|
1254
|
+
else
|
|
1255
|
+
delete process.env.CODEX_HOME;
|
|
1256
|
+
if (typeof prevProviderEnv === 'string')
|
|
1257
|
+
process.env.CUSTOM_PROVIDER_API_KEY = prevProviderEnv;
|
|
1258
|
+
else
|
|
1259
|
+
delete process.env.CUSTOM_PROVIDER_API_KEY;
|
|
1260
|
+
await rm(codexHome, { recursive: true, force: true });
|
|
1261
|
+
}
|
|
1262
|
+
});
|
|
1263
|
+
it('buildWorkerProcessLaunchSpec reads provider env from worker CODEX_HOME override', async () => {
|
|
1264
|
+
const prevBypass = process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT;
|
|
1265
|
+
const prevCodexHome = process.env.CODEX_HOME;
|
|
1266
|
+
const prevPrimaryProviderEnv = process.env.PRIMARY_PROVIDER_API_KEY;
|
|
1267
|
+
const prevWorkerProviderEnv = process.env.WORKER_PROVIDER_API_KEY;
|
|
1268
|
+
const leaderCodexHome = await mkdtemp(join(tmpdir(), 'omx-team-provider-env-leader-'));
|
|
1269
|
+
const workerCodexHome = await mkdtemp(join(tmpdir(), 'omx-team-provider-env-worker-'));
|
|
1270
|
+
process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT = '0';
|
|
1271
|
+
process.env.CODEX_HOME = leaderCodexHome;
|
|
1272
|
+
process.env.PRIMARY_PROVIDER_API_KEY = 'leader-secret';
|
|
1273
|
+
process.env.WORKER_PROVIDER_API_KEY = 'worker-secret';
|
|
1274
|
+
try {
|
|
1275
|
+
await writeFile(join(leaderCodexHome, 'config.toml'), [
|
|
1276
|
+
'model_provider = "primary_provider"',
|
|
1277
|
+
'',
|
|
1278
|
+
'[model_providers.primary_provider]',
|
|
1279
|
+
'name = "primary_provider"',
|
|
1280
|
+
'base_url = "http://localhost:3000/v1"',
|
|
1281
|
+
'wire_api = "responses"',
|
|
1282
|
+
'requires_openai_auth = true',
|
|
1283
|
+
'env_key = "PRIMARY_PROVIDER_API_KEY"',
|
|
1284
|
+
'',
|
|
1285
|
+
].join('\n'));
|
|
1286
|
+
await writeFile(join(workerCodexHome, 'config.toml'), [
|
|
1287
|
+
'model_provider = "worker_provider"',
|
|
1288
|
+
'',
|
|
1289
|
+
'[model_providers.worker_provider]',
|
|
1290
|
+
'name = "worker_provider"',
|
|
1291
|
+
'base_url = "http://localhost:4000/v1"',
|
|
1292
|
+
'wire_api = "responses"',
|
|
1293
|
+
'requires_openai_auth = true',
|
|
1294
|
+
'env_key = "WORKER_PROVIDER_API_KEY"',
|
|
1295
|
+
'',
|
|
1296
|
+
].join('\n'));
|
|
1297
|
+
const spec = buildWorkerProcessLaunchSpec('epsilon-team', 1, [], '/tmp/workspace', { CODEX_HOME: workerCodexHome }, 'codex');
|
|
1298
|
+
assert.equal(spec.env.CODEX_HOME, workerCodexHome);
|
|
1299
|
+
assert.equal(spec.env.WORKER_PROVIDER_API_KEY, 'worker-secret');
|
|
1300
|
+
assert.equal(spec.env.PRIMARY_PROVIDER_API_KEY, undefined);
|
|
1301
|
+
}
|
|
1302
|
+
finally {
|
|
1303
|
+
if (typeof prevBypass === 'string')
|
|
1304
|
+
process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT = prevBypass;
|
|
1305
|
+
else
|
|
1306
|
+
delete process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT;
|
|
1307
|
+
if (typeof prevCodexHome === 'string')
|
|
1308
|
+
process.env.CODEX_HOME = prevCodexHome;
|
|
1309
|
+
else
|
|
1310
|
+
delete process.env.CODEX_HOME;
|
|
1311
|
+
if (typeof prevPrimaryProviderEnv === 'string')
|
|
1312
|
+
process.env.PRIMARY_PROVIDER_API_KEY = prevPrimaryProviderEnv;
|
|
1313
|
+
else
|
|
1314
|
+
delete process.env.PRIMARY_PROVIDER_API_KEY;
|
|
1315
|
+
if (typeof prevWorkerProviderEnv === 'string')
|
|
1316
|
+
process.env.WORKER_PROVIDER_API_KEY = prevWorkerProviderEnv;
|
|
1317
|
+
else
|
|
1318
|
+
delete process.env.WORKER_PROVIDER_API_KEY;
|
|
1319
|
+
await rm(leaderCodexHome, { recursive: true, force: true });
|
|
1320
|
+
await rm(workerCodexHome, { recursive: true, force: true });
|
|
1321
|
+
}
|
|
1322
|
+
});
|
|
1323
|
+
it('buildWorkerProcessLaunchSpec resolves relative worker CODEX_HOME against the worker cwd', async () => {
|
|
1324
|
+
const prevBypass = process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT;
|
|
1325
|
+
const prevCodexHome = process.env.CODEX_HOME;
|
|
1326
|
+
const prevLeaderProviderEnv = process.env.LEADER_PROVIDER_API_KEY;
|
|
1327
|
+
const prevWorkerProviderEnv = process.env.WORKER_PROVIDER_API_KEY;
|
|
1328
|
+
const originalCwd = process.cwd();
|
|
1329
|
+
const leaderCwd = await mkdtemp(join(tmpdir(), 'omx-team-provider-relative-leader-'));
|
|
1330
|
+
const workerCwd = await mkdtemp(join(tmpdir(), 'omx-team-provider-relative-worker-'));
|
|
1331
|
+
const leaderCodexHome = join(leaderCwd, '.codex');
|
|
1332
|
+
const workerCodexHome = join(workerCwd, '.codex');
|
|
1333
|
+
process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT = '0';
|
|
1334
|
+
process.env.CODEX_HOME = leaderCodexHome;
|
|
1335
|
+
process.env.LEADER_PROVIDER_API_KEY = 'leader-secret';
|
|
1336
|
+
process.env.WORKER_PROVIDER_API_KEY = 'worker-secret';
|
|
1337
|
+
try {
|
|
1338
|
+
await mkdir(leaderCodexHome, { recursive: true });
|
|
1339
|
+
await mkdir(workerCodexHome, { recursive: true });
|
|
1340
|
+
await writeFile(join(leaderCodexHome, 'config.toml'), [
|
|
1341
|
+
'model_provider = "leader_provider"',
|
|
1342
|
+
'',
|
|
1343
|
+
'[model_providers.leader_provider]',
|
|
1344
|
+
'name = "leader_provider"',
|
|
1345
|
+
'base_url = "http://localhost:3000/v1"',
|
|
1346
|
+
'wire_api = "responses"',
|
|
1347
|
+
'requires_openai_auth = true',
|
|
1348
|
+
'env_key = "LEADER_PROVIDER_API_KEY"',
|
|
1349
|
+
'',
|
|
1350
|
+
].join('\n'));
|
|
1351
|
+
await writeFile(join(workerCodexHome, 'config.toml'), [
|
|
1352
|
+
'model_provider = "worker_provider"',
|
|
1353
|
+
'',
|
|
1354
|
+
'[model_providers.worker_provider]',
|
|
1355
|
+
'name = "worker_provider"',
|
|
1356
|
+
'base_url = "http://localhost:4000/v1"',
|
|
1357
|
+
'wire_api = "responses"',
|
|
1358
|
+
'requires_openai_auth = true',
|
|
1359
|
+
'env_key = "WORKER_PROVIDER_API_KEY"',
|
|
1360
|
+
'',
|
|
1361
|
+
].join('\n'));
|
|
1362
|
+
process.chdir(leaderCwd);
|
|
1363
|
+
const spec = buildWorkerProcessLaunchSpec('zeta-team', 1, [], workerCwd, { CODEX_HOME: '.codex' }, 'codex');
|
|
1364
|
+
assert.equal(spec.env.CODEX_HOME, '.codex');
|
|
1365
|
+
assert.equal(spec.env.WORKER_PROVIDER_API_KEY, 'worker-secret');
|
|
1366
|
+
assert.equal(spec.env.LEADER_PROVIDER_API_KEY, undefined);
|
|
1367
|
+
}
|
|
1368
|
+
finally {
|
|
1369
|
+
process.chdir(originalCwd);
|
|
1370
|
+
if (typeof prevBypass === 'string')
|
|
1371
|
+
process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT = prevBypass;
|
|
1372
|
+
else
|
|
1373
|
+
delete process.env.OMX_BYPASS_DEFAULT_SYSTEM_PROMPT;
|
|
1374
|
+
if (typeof prevCodexHome === 'string')
|
|
1375
|
+
process.env.CODEX_HOME = prevCodexHome;
|
|
1376
|
+
else
|
|
1377
|
+
delete process.env.CODEX_HOME;
|
|
1378
|
+
if (typeof prevLeaderProviderEnv === 'string')
|
|
1379
|
+
process.env.LEADER_PROVIDER_API_KEY = prevLeaderProviderEnv;
|
|
1380
|
+
else
|
|
1381
|
+
delete process.env.LEADER_PROVIDER_API_KEY;
|
|
1382
|
+
if (typeof prevWorkerProviderEnv === 'string')
|
|
1383
|
+
process.env.WORKER_PROVIDER_API_KEY = prevWorkerProviderEnv;
|
|
1384
|
+
else
|
|
1385
|
+
delete process.env.WORKER_PROVIDER_API_KEY;
|
|
1386
|
+
await rm(leaderCwd, { recursive: true, force: true });
|
|
1387
|
+
await rm(workerCwd, { recursive: true, force: true });
|
|
1388
|
+
}
|
|
1389
|
+
});
|
|
1108
1390
|
});
|
|
1109
1391
|
describe('sendToWorkerStdin', () => {
|
|
1110
1392
|
it('writes a newline-terminated trigger message to worker stdin', () => {
|
|
@@ -1186,6 +1468,56 @@ esac
|
|
|
1186
1468
|
assert.equal(waitForWorkerReady('omx-team-x', 1, 1_000), true);
|
|
1187
1469
|
});
|
|
1188
1470
|
});
|
|
1471
|
+
it('waitForWorkerReady falls back to recent scrollback when a live Codex viewport pushes the prompt below the visible slice', async () => {
|
|
1472
|
+
await withMockTmuxFixture('omx-tmux-worker-ready-scrollback-fallback-', (logPath) => `#!/bin/sh
|
|
1473
|
+
set -eu
|
|
1474
|
+
printf '%s\n' "$*" >> "${logPath}"
|
|
1475
|
+
case "$1" in
|
|
1476
|
+
capture-pane)
|
|
1477
|
+
if printf '%s\n' "$*" | grep -q -- ' -S -80'; then
|
|
1478
|
+
cat <<'EOF'
|
|
1479
|
+
${VIEWPORT_SCROLLBACK_READY_CAPTURE}
|
|
1480
|
+
EOF
|
|
1481
|
+
else
|
|
1482
|
+
cat <<'EOF'
|
|
1483
|
+
${VIEWPORT_WITHOUT_VISIBLE_PROMPT_CAPTURE}
|
|
1484
|
+
EOF
|
|
1485
|
+
fi
|
|
1486
|
+
exit 0
|
|
1487
|
+
;;
|
|
1488
|
+
*)
|
|
1489
|
+
exit 0
|
|
1490
|
+
;;
|
|
1491
|
+
esac
|
|
1492
|
+
`, async ({ logPath }) => {
|
|
1493
|
+
assert.equal(waitForWorkerReady('omx-team-x', 1, 1_000), true);
|
|
1494
|
+
const log = await readFile(logPath, 'utf-8');
|
|
1495
|
+
assert.match(log, /capture-pane -t omx-team-x:1 -p/);
|
|
1496
|
+
assert.match(log, /capture-pane -t omx-team-x:1 -p -S -80/);
|
|
1497
|
+
});
|
|
1498
|
+
});
|
|
1499
|
+
it('waitForWorkerReady does not consult scrollback when the visible slice is only status text', async () => {
|
|
1500
|
+
await withMockTmuxFixture('omx-tmux-worker-ready-no-scrollback-status-', (logPath) => `#!/bin/sh
|
|
1501
|
+
set -eu
|
|
1502
|
+
printf '%s\n' "$*" >> "${logPath}"
|
|
1503
|
+
case "$1" in
|
|
1504
|
+
capture-pane)
|
|
1505
|
+
cat <<'EOF'
|
|
1506
|
+
gpt-5 50% left
|
|
1507
|
+
EOF
|
|
1508
|
+
exit 0
|
|
1509
|
+
;;
|
|
1510
|
+
*)
|
|
1511
|
+
exit 0
|
|
1512
|
+
;;
|
|
1513
|
+
esac
|
|
1514
|
+
`, async ({ logPath }) => {
|
|
1515
|
+
assert.equal(waitForWorkerReady('omx-team-x', 1, 250), false);
|
|
1516
|
+
const log = await readFile(logPath, 'utf-8');
|
|
1517
|
+
assert.match(log, /capture-pane -t omx-team-x:1 -p/);
|
|
1518
|
+
assert.doesNotMatch(log, /capture-pane -t omx-team-x:1 -p -S -80/);
|
|
1519
|
+
});
|
|
1520
|
+
});
|
|
1189
1521
|
it('waitForWorkerReady auto-accepts the Claude bypass prompt', async () => {
|
|
1190
1522
|
await withMockTmuxFixture('omx-tmux-claude-bypass-ready-', (logPath) => `#!/bin/sh
|
|
1191
1523
|
set -eu
|
|
@@ -1259,6 +1591,193 @@ esac
|
|
|
1259
1591
|
});
|
|
1260
1592
|
});
|
|
1261
1593
|
});
|
|
1594
|
+
describe('native Windows HUD reconciliation', () => {
|
|
1595
|
+
it('avoids nested tmux run-shell hooks during team HUD startup on native Windows', async () => {
|
|
1596
|
+
const cwd = await mkdtemp(join(tmpdir(), 'omx-team-win32-hud-'));
|
|
1597
|
+
const prevTmux = process.env.TMUX;
|
|
1598
|
+
const prevTmuxPane = process.env.TMUX_PANE;
|
|
1599
|
+
const prevWorkerCli = process.env.OMX_TEAM_WORKER_CLI;
|
|
1600
|
+
const prevMsystem = process.env.MSYSTEM;
|
|
1601
|
+
const prevOstype = process.env.OSTYPE;
|
|
1602
|
+
const prevWsl = process.env.WSL_DISTRO_NAME;
|
|
1603
|
+
const prevWslInterop = process.env.WSL_INTEROP;
|
|
1604
|
+
const origPlatform = Object.getOwnPropertyDescriptor(process, 'platform');
|
|
1605
|
+
try {
|
|
1606
|
+
await withMockTmuxFixture('omx-tmux-win32-hud-reconcile-', (logPath) => `#!/bin/sh
|
|
1607
|
+
set -eu
|
|
1608
|
+
printf '%s\\n' "$*" >> "${logPath}"
|
|
1609
|
+
case "\${1:-}" in
|
|
1610
|
+
-V)
|
|
1611
|
+
echo "tmux 3.4"
|
|
1612
|
+
exit 0
|
|
1613
|
+
;;
|
|
1614
|
+
display-message)
|
|
1615
|
+
case "$*" in
|
|
1616
|
+
*"#{window_width}"*)
|
|
1617
|
+
echo "120"
|
|
1618
|
+
;;
|
|
1619
|
+
*)
|
|
1620
|
+
echo "leader:0 %1"
|
|
1621
|
+
;;
|
|
1622
|
+
esac
|
|
1623
|
+
exit 0
|
|
1624
|
+
;;
|
|
1625
|
+
list-panes)
|
|
1626
|
+
printf "%%1\\tnode\\t'codex'\\n"
|
|
1627
|
+
exit 0
|
|
1628
|
+
;;
|
|
1629
|
+
split-window)
|
|
1630
|
+
case "$*" in
|
|
1631
|
+
*" -h "*)
|
|
1632
|
+
echo "%2"
|
|
1633
|
+
;;
|
|
1634
|
+
*)
|
|
1635
|
+
echo "%3"
|
|
1636
|
+
;;
|
|
1637
|
+
esac
|
|
1638
|
+
exit 0
|
|
1639
|
+
;;
|
|
1640
|
+
resize-pane|select-layout|set-window-option|select-pane|kill-pane)
|
|
1641
|
+
exit 0
|
|
1642
|
+
;;
|
|
1643
|
+
set-hook|run-shell)
|
|
1644
|
+
exit 0
|
|
1645
|
+
;;
|
|
1646
|
+
*)
|
|
1647
|
+
exit 0
|
|
1648
|
+
;;
|
|
1649
|
+
esac
|
|
1650
|
+
`, async ({ logPath }) => {
|
|
1651
|
+
const fakeBinDir = join(logPath, '..');
|
|
1652
|
+
const geminiPath = join(fakeBinDir, 'gemini');
|
|
1653
|
+
await writeFile(geminiPath, '#!/bin/sh\nexit 0\n');
|
|
1654
|
+
await chmod(geminiPath, 0o755);
|
|
1655
|
+
process.env.TMUX = 'leader-session,stub,0';
|
|
1656
|
+
process.env.TMUX_PANE = '%1';
|
|
1657
|
+
process.env.OMX_TEAM_WORKER_CLI = 'gemini';
|
|
1658
|
+
delete process.env.MSYSTEM;
|
|
1659
|
+
delete process.env.OSTYPE;
|
|
1660
|
+
delete process.env.WSL_DISTRO_NAME;
|
|
1661
|
+
delete process.env.WSL_INTEROP;
|
|
1662
|
+
Object.defineProperty(process, 'platform', { value: 'win32', configurable: true });
|
|
1663
|
+
const session = createTeamSession('Windows Team', 1, cwd);
|
|
1664
|
+
assert.equal(session.hudPaneId, '%3');
|
|
1665
|
+
assert.equal(session.resizeHookName, null);
|
|
1666
|
+
assert.equal(session.resizeHookTarget, null);
|
|
1667
|
+
const tmuxLog = await readFile(logPath, 'utf-8');
|
|
1668
|
+
assert.match(tmuxLog, new RegExp(`resize-pane -t %3 -y ${HUD_TMUX_TEAM_HEIGHT_LINES}`));
|
|
1669
|
+
assert.doesNotMatch(tmuxLog, /set-hook -t leader:0 client-resized\[\d+\]/);
|
|
1670
|
+
assert.doesNotMatch(tmuxLog, /set-hook -t leader:0 client-attached\[\d+\]/);
|
|
1671
|
+
assert.doesNotMatch(tmuxLog, /run-shell -b sleep \d+; tmux resize-pane -t %3 -y \d+ >/);
|
|
1672
|
+
assert.doesNotMatch(tmuxLog, /run-shell tmux resize-pane -t %3 -y \d+ >/);
|
|
1673
|
+
});
|
|
1674
|
+
}
|
|
1675
|
+
finally {
|
|
1676
|
+
if (origPlatform)
|
|
1677
|
+
Object.defineProperty(process, 'platform', origPlatform);
|
|
1678
|
+
if (typeof prevTmux === 'string')
|
|
1679
|
+
process.env.TMUX = prevTmux;
|
|
1680
|
+
else
|
|
1681
|
+
delete process.env.TMUX;
|
|
1682
|
+
if (typeof prevTmuxPane === 'string')
|
|
1683
|
+
process.env.TMUX_PANE = prevTmuxPane;
|
|
1684
|
+
else
|
|
1685
|
+
delete process.env.TMUX_PANE;
|
|
1686
|
+
if (typeof prevWorkerCli === 'string')
|
|
1687
|
+
process.env.OMX_TEAM_WORKER_CLI = prevWorkerCli;
|
|
1688
|
+
else
|
|
1689
|
+
delete process.env.OMX_TEAM_WORKER_CLI;
|
|
1690
|
+
if (typeof prevMsystem === 'string')
|
|
1691
|
+
process.env.MSYSTEM = prevMsystem;
|
|
1692
|
+
else
|
|
1693
|
+
delete process.env.MSYSTEM;
|
|
1694
|
+
if (typeof prevOstype === 'string')
|
|
1695
|
+
process.env.OSTYPE = prevOstype;
|
|
1696
|
+
else
|
|
1697
|
+
delete process.env.OSTYPE;
|
|
1698
|
+
if (typeof prevWsl === 'string')
|
|
1699
|
+
process.env.WSL_DISTRO_NAME = prevWsl;
|
|
1700
|
+
else
|
|
1701
|
+
delete process.env.WSL_DISTRO_NAME;
|
|
1702
|
+
if (typeof prevWslInterop === 'string')
|
|
1703
|
+
process.env.WSL_INTEROP = prevWslInterop;
|
|
1704
|
+
else
|
|
1705
|
+
delete process.env.WSL_INTEROP;
|
|
1706
|
+
await rm(cwd, { recursive: true, force: true });
|
|
1707
|
+
}
|
|
1708
|
+
});
|
|
1709
|
+
it('restores standalone HUD panes with direct resize on native Windows', async () => {
|
|
1710
|
+
const cwd = await mkdtemp(join(tmpdir(), 'omx-standalone-win32-hud-'));
|
|
1711
|
+
const prevLeaderNodePath = process.env.OMX_LEADER_NODE_PATH;
|
|
1712
|
+
const prevMsystem = process.env.MSYSTEM;
|
|
1713
|
+
const prevOstype = process.env.OSTYPE;
|
|
1714
|
+
const prevWsl = process.env.WSL_DISTRO_NAME;
|
|
1715
|
+
const prevWslInterop = process.env.WSL_INTEROP;
|
|
1716
|
+
const origPlatform = Object.getOwnPropertyDescriptor(process, 'platform');
|
|
1717
|
+
try {
|
|
1718
|
+
await withMockTmuxFixture('omx-tmux-win32-standalone-hud-', (logPath) => `#!/bin/sh
|
|
1719
|
+
set -eu
|
|
1720
|
+
printf '%s\\n' "$*" >> "${logPath}"
|
|
1721
|
+
case "\${1:-}" in
|
|
1722
|
+
split-window)
|
|
1723
|
+
echo "%44"
|
|
1724
|
+
exit 0
|
|
1725
|
+
;;
|
|
1726
|
+
resize-pane|select-pane)
|
|
1727
|
+
exit 0
|
|
1728
|
+
;;
|
|
1729
|
+
set-hook|run-shell)
|
|
1730
|
+
exit 0
|
|
1731
|
+
;;
|
|
1732
|
+
*)
|
|
1733
|
+
exit 0
|
|
1734
|
+
;;
|
|
1735
|
+
esac
|
|
1736
|
+
`, async ({ logPath }) => {
|
|
1737
|
+
delete process.env.MSYSTEM;
|
|
1738
|
+
delete process.env.OSTYPE;
|
|
1739
|
+
delete process.env.WSL_DISTRO_NAME;
|
|
1740
|
+
delete process.env.WSL_INTEROP;
|
|
1741
|
+
process.env.OMX_LEADER_NODE_PATH = 'C:\\Program Files\\nodejs\\node.exe';
|
|
1742
|
+
Object.defineProperty(process, 'platform', { value: 'win32', configurable: true });
|
|
1743
|
+
const paneId = restoreStandaloneHudPane('%11', cwd);
|
|
1744
|
+
assert.equal(paneId, '%44');
|
|
1745
|
+
const tmuxLog = await readFile(logPath, 'utf-8');
|
|
1746
|
+
assert.match(tmuxLog, /'C:\\Program Files\\nodejs\\node\.exe'/);
|
|
1747
|
+
assert.match(tmuxLog, new RegExp(`resize-pane -t %44 -y ${HUD_TMUX_TEAM_HEIGHT_LINES}`));
|
|
1748
|
+
assert.match(tmuxLog, /select-pane -t %11/);
|
|
1749
|
+
assert.doesNotMatch(tmuxLog, /run-shell -b sleep \d+; tmux resize-pane -t %44 -y \d+ >/);
|
|
1750
|
+
assert.doesNotMatch(tmuxLog, /run-shell tmux resize-pane -t %44 -y \d+ >/);
|
|
1751
|
+
assert.doesNotMatch(tmuxLog, /set-hook -t /);
|
|
1752
|
+
});
|
|
1753
|
+
}
|
|
1754
|
+
finally {
|
|
1755
|
+
if (origPlatform)
|
|
1756
|
+
Object.defineProperty(process, 'platform', origPlatform);
|
|
1757
|
+
if (typeof prevLeaderNodePath === 'string')
|
|
1758
|
+
process.env.OMX_LEADER_NODE_PATH = prevLeaderNodePath;
|
|
1759
|
+
else
|
|
1760
|
+
delete process.env.OMX_LEADER_NODE_PATH;
|
|
1761
|
+
if (typeof prevMsystem === 'string')
|
|
1762
|
+
process.env.MSYSTEM = prevMsystem;
|
|
1763
|
+
else
|
|
1764
|
+
delete process.env.MSYSTEM;
|
|
1765
|
+
if (typeof prevOstype === 'string')
|
|
1766
|
+
process.env.OSTYPE = prevOstype;
|
|
1767
|
+
else
|
|
1768
|
+
delete process.env.OSTYPE;
|
|
1769
|
+
if (typeof prevWsl === 'string')
|
|
1770
|
+
process.env.WSL_DISTRO_NAME = prevWsl;
|
|
1771
|
+
else
|
|
1772
|
+
delete process.env.WSL_DISTRO_NAME;
|
|
1773
|
+
if (typeof prevWslInterop === 'string')
|
|
1774
|
+
process.env.WSL_INTEROP = prevWslInterop;
|
|
1775
|
+
else
|
|
1776
|
+
delete process.env.WSL_INTEROP;
|
|
1777
|
+
await rm(cwd, { recursive: true, force: true });
|
|
1778
|
+
}
|
|
1779
|
+
});
|
|
1780
|
+
});
|
|
1262
1781
|
describe('dismissTrustPromptIfPresent capture shape', () => {
|
|
1263
1782
|
it('uses visible capture-pane argv without tail flags', async () => {
|
|
1264
1783
|
const previousAutoTrust = process.env.OMX_TEAM_AUTO_TRUST;
|