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
|
@@ -17,13 +17,13 @@ import {
|
|
|
17
17
|
} from './state-io.js';
|
|
18
18
|
import { runProcess } from './process-runner.js';
|
|
19
19
|
import { logTmuxHookEvent } from './log.js';
|
|
20
|
+
import { resolveManagedCurrentPane, resolveManagedSessionContext, verifyManagedPaneTarget } from './managed-tmux.js';
|
|
20
21
|
import { evaluatePaneInjectionReadiness, mapPaneInjectionReadinessReason, sendPaneInput } from './team-tmux-guard.js';
|
|
21
22
|
import {
|
|
22
23
|
normalizeTmuxHookConfig,
|
|
23
24
|
pickActiveMode,
|
|
24
25
|
evaluateInjectionGuards,
|
|
25
26
|
buildSendKeysArgv,
|
|
26
|
-
resolveCodexPane,
|
|
27
27
|
} from '../tmux-hook-engine.js';
|
|
28
28
|
|
|
29
29
|
function isHudPaneStartCommand(startCommand: any): boolean {
|
|
@@ -96,6 +96,25 @@ async function resolveCanonicalPaneFromPaneTarget(paneTarget: any, expectedCwd:
|
|
|
96
96
|
return finalizeResolvedPane(healedPaneId, 'healed_hud_pane_target', expectedCwd);
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
+
async function resolvePreferredModePane(stateDir: string, allowedModes: string[]): Promise<{ mode: string; state: any; pane: string } | null> {
|
|
100
|
+
const scopedDirs = await getScopedStateDirsForCurrentSession(stateDir).catch(() => [stateDir]);
|
|
101
|
+
const dirs = [...scopedDirs];
|
|
102
|
+
if (!dirs.map((dir) => resolvePath(dir)).includes(resolvePath(stateDir))) {
|
|
103
|
+
dirs.push(stateDir);
|
|
104
|
+
}
|
|
105
|
+
for (const dir of dirs) {
|
|
106
|
+
for (const mode of allowedModes || []) {
|
|
107
|
+
const path = join(dir, `${mode}-state.json`);
|
|
108
|
+
const parsed = await readJsonIfExists(path, null);
|
|
109
|
+
const pane = safeString(parsed?.tmux_pane_id || '').trim();
|
|
110
|
+
if (parsed?.active && pane) {
|
|
111
|
+
return { mode, state: parsed, pane };
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
|
|
99
118
|
export async function resolveSessionToPane(sessionName: any): Promise<string | null> {
|
|
100
119
|
const result = await runProcess('tmux', ['list-panes', '-t', sessionName, '-F', '#{pane_id}\t#{pane_active}\t#{pane_current_command}\t#{pane_start_command}']);
|
|
101
120
|
const rows = result.stdout
|
|
@@ -128,27 +147,35 @@ export async function resolveSessionToPane(sessionName: any): Promise<string | n
|
|
|
128
147
|
return nonHudRows[0]?.paneId || null;
|
|
129
148
|
}
|
|
130
149
|
|
|
131
|
-
export async function resolvePaneTarget(target: any,
|
|
132
|
-
const
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
}
|
|
150
|
+
export async function resolvePaneTarget(target: any, expectedCwd: any, modePane: any, cwd: string, payload: any): Promise<any> {
|
|
151
|
+
const requiresManagedOwnership = safeString(cwd).trim() !== '' && safeString(payload?.session_id || payload?.['session-id'] || process.env.OMX_SESSION_ID || '').trim() !== '';
|
|
152
|
+
const managedContext = requiresManagedOwnership
|
|
153
|
+
? await resolveManagedSessionContext(cwd, payload, { allowTeamWorker: false })
|
|
154
|
+
: { managed: false, reason: 'not_required', invocationSessionId: '', sessionState: null, expectedTmuxSessionName: '', currentTmuxSessionName: '' };
|
|
155
|
+
if (requiresManagedOwnership && !managedContext.managed) {
|
|
156
|
+
return { paneTarget: null, reason: managedContext.reason || 'unmanaged_session' };
|
|
139
157
|
}
|
|
140
158
|
|
|
141
|
-
|
|
159
|
+
const canonicalModePane = safeString(modePane).trim();
|
|
160
|
+
if (canonicalModePane) {
|
|
142
161
|
try {
|
|
143
|
-
const resolved = await resolveCanonicalPaneFromPaneTarget(
|
|
162
|
+
const resolved = await resolveCanonicalPaneFromPaneTarget(canonicalModePane, expectedCwd);
|
|
144
163
|
if (resolved.paneTarget) {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
164
|
+
const ownership = requiresManagedOwnership
|
|
165
|
+
? await verifyManagedPaneTarget(resolved.paneTarget, cwd, payload, { allowTeamWorker: false })
|
|
166
|
+
: { ok: true };
|
|
167
|
+
if (ownership.ok) {
|
|
168
|
+
return {
|
|
169
|
+
...resolved,
|
|
170
|
+
reason: resolved.reason === 'ok' ? 'fallback_mode_state_pane' : resolved.reason,
|
|
171
|
+
source: 'mode_state',
|
|
172
|
+
healTarget: true,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
return { paneTarget: null, reason: ownership.reason || 'pane_not_managed_session' };
|
|
149
176
|
}
|
|
150
177
|
} catch {
|
|
151
|
-
// Fall through to config
|
|
178
|
+
// Fall through to explicit config target
|
|
152
179
|
}
|
|
153
180
|
}
|
|
154
181
|
|
|
@@ -157,20 +184,52 @@ export async function resolvePaneTarget(target: any, fallbackPane: any, expected
|
|
|
157
184
|
if (target.type === 'pane') {
|
|
158
185
|
try {
|
|
159
186
|
const resolved = await resolveCanonicalPaneFromPaneTarget(target.value, expectedCwd);
|
|
160
|
-
if (resolved.paneTarget)
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
187
|
+
if (resolved.paneTarget) {
|
|
188
|
+
const ownership = requiresManagedOwnership
|
|
189
|
+
? await verifyManagedPaneTarget(resolved.paneTarget, cwd, payload, { allowTeamWorker: false })
|
|
190
|
+
: { ok: true };
|
|
191
|
+
if (ownership.ok) {
|
|
192
|
+
return {
|
|
193
|
+
...resolved,
|
|
194
|
+
reason: resolved.reason === 'ok' ? 'explicit_pane_target' : resolved.reason,
|
|
195
|
+
source: 'explicit_target',
|
|
196
|
+
healTarget: true,
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
return { paneTarget: null, reason: ownership.reason || 'pane_not_managed_session' };
|
|
200
|
+
}
|
|
168
201
|
} catch {
|
|
169
202
|
// Fall through
|
|
170
203
|
}
|
|
204
|
+
return { paneTarget: null, reason: 'target_not_found' };
|
|
171
205
|
}
|
|
172
206
|
|
|
173
|
-
|
|
207
|
+
try {
|
|
208
|
+
if (!requiresManagedOwnership) return { paneTarget: null, reason: 'target_session_requires_managed_context' };
|
|
209
|
+
const explicitSessionTarget = safeString(target.value).trim();
|
|
210
|
+
const expectedSessionTarget = safeString(managedContext.expectedTmuxSessionName).trim();
|
|
211
|
+
const sessionIdTarget = safeString(managedContext.invocationSessionId).trim();
|
|
212
|
+
const stateSessionTarget = safeString(managedContext.sessionState?.session_id).trim();
|
|
213
|
+
const allowedSessionTargets = new Set([expectedSessionTarget, sessionIdTarget, stateSessionTarget].filter(Boolean));
|
|
214
|
+
if (!allowedSessionTargets.has(explicitSessionTarget)) {
|
|
215
|
+
return { paneTarget: null, reason: 'target_session_not_managed' };
|
|
216
|
+
}
|
|
217
|
+
const paneId = await resolveSessionToPane(expectedSessionTarget);
|
|
218
|
+
if (!paneId) return { paneTarget: null, reason: 'target_not_found' };
|
|
219
|
+
const resolved = await finalizeResolvedPane(paneId, 'managed_session_target', expectedCwd);
|
|
220
|
+
if (!resolved.paneTarget) return resolved;
|
|
221
|
+
const ownership = await verifyManagedPaneTarget(resolved.paneTarget, cwd, payload, { allowTeamWorker: false });
|
|
222
|
+
if (!ownership.ok) {
|
|
223
|
+
return { paneTarget: null, reason: ownership.reason || 'pane_not_managed_session' };
|
|
224
|
+
}
|
|
225
|
+
return {
|
|
226
|
+
...resolved,
|
|
227
|
+
source: 'explicit_target',
|
|
228
|
+
healTarget: true,
|
|
229
|
+
};
|
|
230
|
+
} catch {
|
|
231
|
+
return { paneTarget: null, reason: 'target_not_found' };
|
|
232
|
+
}
|
|
174
233
|
}
|
|
175
234
|
|
|
176
235
|
export async function handleTmuxInjection({
|
|
@@ -202,7 +261,6 @@ export async function handleTmuxInjection({
|
|
|
202
261
|
const activeModes: string[] = [];
|
|
203
262
|
const activeModeStates: Record<string, any> = {};
|
|
204
263
|
const scannedStateDirs = new Set<string>();
|
|
205
|
-
const payloadSessionId = safeString(payload.session_id || payload['session-id'] || '');
|
|
206
264
|
const scanActiveModeStateDirs = async (dirs: string[], preserveExisting = false) => {
|
|
207
265
|
for (const scopedDir of dirs) {
|
|
208
266
|
const resolvedScopedDir = resolvePath(scopedDir);
|
|
@@ -225,7 +283,7 @@ export async function handleTmuxInjection({
|
|
|
225
283
|
}
|
|
226
284
|
};
|
|
227
285
|
try {
|
|
228
|
-
const scopedDirs = await getScopedStateDirsForCurrentSession(stateDir
|
|
286
|
+
const scopedDirs = await getScopedStateDirsForCurrentSession(stateDir);
|
|
229
287
|
await scanActiveModeStateDirs(scopedDirs);
|
|
230
288
|
|
|
231
289
|
if (!pickActiveMode(activeModes, config.allowed_modes) && !scannedStateDirs.has(resolvePath(stateDir))) {
|
|
@@ -235,9 +293,10 @@ export async function handleTmuxInjection({
|
|
|
235
293
|
// Non-fatal
|
|
236
294
|
}
|
|
237
295
|
|
|
238
|
-
const
|
|
239
|
-
const
|
|
240
|
-
const
|
|
296
|
+
const preferredModePane = await resolvePreferredModePane(stateDir, config.allowed_modes).catch(() => null);
|
|
297
|
+
const mode = preferredModePane?.mode || pickActiveMode(activeModes, config.allowed_modes);
|
|
298
|
+
const modeState = preferredModePane?.state || (mode ? (activeModeStates[mode] || {}) : {});
|
|
299
|
+
const modePane = preferredModePane?.pane || safeString(modeState.tmux_pane_id || '');
|
|
241
300
|
const preGuard = evaluateInjectionGuards({
|
|
242
301
|
config,
|
|
243
302
|
mode,
|
|
@@ -280,8 +339,19 @@ export async function handleTmuxInjection({
|
|
|
280
339
|
turnId,
|
|
281
340
|
timestamp: nowIso,
|
|
282
341
|
}), sourceText);
|
|
283
|
-
const
|
|
284
|
-
|
|
342
|
+
const preferredPaneTarget = modePane || await resolveManagedCurrentPane(cwd, payload, { allowTeamWorker: false });
|
|
343
|
+
let resolution = preferredModePane
|
|
344
|
+
? await resolveCanonicalPaneFromPaneTarget(preferredModePane.pane, cwd).then((resolved) => (
|
|
345
|
+
resolved.paneTarget
|
|
346
|
+
? { ...resolved, reason: 'fallback_mode_state_pane', source: 'mode_state', healTarget: true }
|
|
347
|
+
: resolved
|
|
348
|
+
))
|
|
349
|
+
: preferredPaneTarget
|
|
350
|
+
? await resolvePaneTarget({ type: 'pane', value: preferredPaneTarget }, cwd, '', cwd, payload)
|
|
351
|
+
: await resolvePaneTarget(config.target, cwd, modePane, cwd, payload);
|
|
352
|
+
if (!resolution.paneTarget && preferredPaneTarget) {
|
|
353
|
+
resolution = await resolvePaneTarget(config.target, cwd, modePane, cwd, payload);
|
|
354
|
+
}
|
|
285
355
|
if (!resolution.paneTarget) {
|
|
286
356
|
state.last_reason = resolution.reason;
|
|
287
357
|
state.last_event_at = nowIso;
|
|
@@ -319,7 +389,7 @@ export async function handleTmuxInjection({
|
|
|
319
389
|
}
|
|
320
390
|
|
|
321
391
|
// Pane-canonical healing: persist resolved pane target so routing stops depending on session names or stale pane ids.
|
|
322
|
-
if (config.target && (config.target.type !== 'pane' || safeString(config.target.value).trim() !== paneTarget)) {
|
|
392
|
+
if (resolution.healTarget && config.target && (config.target.type !== 'pane' || safeString(config.target.value).trim() !== paneTarget)) {
|
|
323
393
|
try {
|
|
324
394
|
const healed = {
|
|
325
395
|
...(rawConfig && typeof rawConfig === 'object' ? rawConfig : {}),
|
|
@@ -39,6 +39,10 @@ import { isLeaderStale, resolveLeaderStalenessThresholdMs, maybeNudgeTeamLeader
|
|
|
39
39
|
import { drainPendingTeamDispatch } from './notify-hook/team-dispatch.js';
|
|
40
40
|
import { handleTmuxInjection } from './notify-hook/tmux-injection.js';
|
|
41
41
|
import { maybeAutoNudge, resolveNudgePaneTarget, isDeepInterviewStateActive } from './notify-hook/auto-nudge.js';
|
|
42
|
+
import { isManagedOmxSession } from './notify-hook/managed-tmux.js';
|
|
43
|
+
import { logNotifyHookEvent } from './notify-hook/log.js';
|
|
44
|
+
import { reconcileRalphSessionResume } from './notify-hook/ralph-session-resume.js';
|
|
45
|
+
import { sendPaneInput } from './notify-hook/team-tmux-guard.js';
|
|
42
46
|
import {
|
|
43
47
|
buildOperationalContext,
|
|
44
48
|
deriveAssistantSignalEvents,
|
|
@@ -68,6 +72,79 @@ const RALPH_ACTIVE_PROGRESS_PHASES = new Set([
|
|
|
68
72
|
'fixing',
|
|
69
73
|
]);
|
|
70
74
|
|
|
75
|
+
const IDLE_NOTIFICATION_SUMMARY_MAX_LENGTH = 240;
|
|
76
|
+
|
|
77
|
+
function summarizeIdleNotificationMessage(message: unknown): string {
|
|
78
|
+
const source = safeString(message)
|
|
79
|
+
.split('\n')
|
|
80
|
+
.map((line) => line.trim())
|
|
81
|
+
.filter(Boolean);
|
|
82
|
+
const preferred = source.at(-1) || '';
|
|
83
|
+
const normalized = preferred.replace(/\s+/g, ' ').trim();
|
|
84
|
+
if (!normalized) return '';
|
|
85
|
+
return normalized.length > IDLE_NOTIFICATION_SUMMARY_MAX_LENGTH
|
|
86
|
+
? `${normalized.slice(0, IDLE_NOTIFICATION_SUMMARY_MAX_LENGTH - 1)}…`
|
|
87
|
+
: normalized;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function classifyIdleNotificationPhase(message: unknown): 'idle' | 'progress' | 'finished' | 'failed' {
|
|
91
|
+
const lower = safeString(message).toLowerCase();
|
|
92
|
+
if (!lower) return 'idle';
|
|
93
|
+
|
|
94
|
+
if (/(error|failed|exception|invalid|timed out|timeout)/i.test(lower)) {
|
|
95
|
+
return 'failed';
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
if ([
|
|
99
|
+
'all tests pass',
|
|
100
|
+
'build succeeded',
|
|
101
|
+
'completed',
|
|
102
|
+
'complete',
|
|
103
|
+
'done',
|
|
104
|
+
'final summary',
|
|
105
|
+
'summary',
|
|
106
|
+
].some((pattern) => lower.includes(pattern))) {
|
|
107
|
+
return 'finished';
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if ([
|
|
111
|
+
'verify',
|
|
112
|
+
'verified',
|
|
113
|
+
'verification',
|
|
114
|
+
'review',
|
|
115
|
+
'reviewed',
|
|
116
|
+
'diagnostic',
|
|
117
|
+
'typecheck',
|
|
118
|
+
'test',
|
|
119
|
+
'implement',
|
|
120
|
+
'implemented',
|
|
121
|
+
'apply patch',
|
|
122
|
+
'change',
|
|
123
|
+
'fix',
|
|
124
|
+
'update',
|
|
125
|
+
'refactor',
|
|
126
|
+
'resume',
|
|
127
|
+
'resumed',
|
|
128
|
+
'progress',
|
|
129
|
+
'continue',
|
|
130
|
+
'continued',
|
|
131
|
+
].some((pattern) => lower.includes(pattern))) {
|
|
132
|
+
return 'progress';
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return 'idle';
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function buildIdleNotificationFingerprint(payload: Record<string, unknown>): string {
|
|
139
|
+
const lastAssistantMessage = safeString(payload['last-assistant-message'] || payload.last_assistant_message || '');
|
|
140
|
+
const summary = summarizeIdleNotificationMessage(lastAssistantMessage);
|
|
141
|
+
const phase = classifyIdleNotificationPhase(lastAssistantMessage);
|
|
142
|
+
return JSON.stringify({
|
|
143
|
+
phase,
|
|
144
|
+
...(summary ? { summary } : {}),
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
|
|
71
148
|
async function main() {
|
|
72
149
|
const rawPayload = process.argv[process.argv.length - 1];
|
|
73
150
|
if (!rawPayload || rawPayload.startsWith('-')) {
|
|
@@ -83,6 +160,9 @@ async function main() {
|
|
|
83
160
|
|
|
84
161
|
const cwd = payload.cwd || payload['cwd'] || process.cwd();
|
|
85
162
|
const payloadSessionId = safeString(payload.session_id || payload['session-id'] || '');
|
|
163
|
+
const payloadThreadId = safeString(payload['thread-id'] || payload.thread_id || '');
|
|
164
|
+
const inputMessages = normalizeInputMessages(payload);
|
|
165
|
+
const latestUserInput = safeString(inputMessages.length > 0 ? inputMessages[inputMessages.length - 1] : '');
|
|
86
166
|
|
|
87
167
|
// Team worker detection via environment variable
|
|
88
168
|
const teamWorkerEnv = process.env.OMX_TEAM_WORKER; // e.g., "fix-ts/worker-1"
|
|
@@ -94,6 +174,7 @@ async function main() {
|
|
|
94
174
|
: join(cwd, '.omx', 'state');
|
|
95
175
|
const logsDir = join(cwd, '.omx', 'logs');
|
|
96
176
|
const omxDir = join(cwd, '.omx');
|
|
177
|
+
let currentOmxSessionId = '';
|
|
97
178
|
|
|
98
179
|
// Ensure directories exist
|
|
99
180
|
await mkdir(logsDir, { recursive: true }).catch(() => {});
|
|
@@ -158,11 +239,45 @@ async function main() {
|
|
|
158
239
|
const logFile = join(logsDir, `turns-${new Date().toISOString().split('T')[0]}.jsonl`);
|
|
159
240
|
await appendFile(logFile, JSON.stringify(logEntry) + '\n').catch(() => {});
|
|
160
241
|
|
|
242
|
+
// Reconcile Ralph ownership for same-Codex-session continuation before
|
|
243
|
+
// lifecycle counters or injection read the active scope.
|
|
244
|
+
if (!isTeamWorker) {
|
|
245
|
+
try {
|
|
246
|
+
const resumeResult = await reconcileRalphSessionResume({
|
|
247
|
+
stateDir,
|
|
248
|
+
payloadSessionId,
|
|
249
|
+
payloadThreadId,
|
|
250
|
+
});
|
|
251
|
+
currentOmxSessionId = resumeResult.currentOmxSessionId;
|
|
252
|
+
if (resumeResult.resumed || resumeResult.updatedCurrentOwner) {
|
|
253
|
+
await logNotifyHookEvent(logsDir, {
|
|
254
|
+
timestamp: new Date().toISOString(),
|
|
255
|
+
type: 'ralph_session_resume',
|
|
256
|
+
reason: resumeResult.reason,
|
|
257
|
+
current_omx_session_id: resumeResult.currentOmxSessionId || null,
|
|
258
|
+
payload_codex_session_id: payloadSessionId || null,
|
|
259
|
+
source_path: resumeResult.sourcePath || null,
|
|
260
|
+
target_path: resumeResult.targetPath || null,
|
|
261
|
+
owner_updated: resumeResult.updatedCurrentOwner,
|
|
262
|
+
resumed: resumeResult.resumed,
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
} catch (error) {
|
|
266
|
+
await logNotifyHookEvent(logsDir, {
|
|
267
|
+
timestamp: new Date().toISOString(),
|
|
268
|
+
level: 'warn',
|
|
269
|
+
type: 'ralph_session_resume_failure',
|
|
270
|
+
payload_codex_session_id: payloadSessionId || null,
|
|
271
|
+
error: error instanceof Error ? error.message : String(error),
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
161
276
|
// 2. Update active mode state (increment iteration)
|
|
162
277
|
// GUARD: Skip when running inside a team worker to prevent state corruption
|
|
163
278
|
if (!isTeamWorker) {
|
|
164
279
|
try {
|
|
165
|
-
const scopedDirs = await getScopedStateDirsForCurrentSession(stateDir
|
|
280
|
+
const scopedDirs = await getScopedStateDirsForCurrentSession(stateDir);
|
|
166
281
|
for (const scopedDir of scopedDirs) {
|
|
167
282
|
const stateFiles = await readdir(scopedDir).catch(() => []);
|
|
168
283
|
for (const f of stateFiles) {
|
|
@@ -298,7 +413,9 @@ async function main() {
|
|
|
298
413
|
if (existsSync(hudStatePath)) {
|
|
299
414
|
hudState = JSON.parse(await readFile(hudStatePath, 'utf-8'));
|
|
300
415
|
}
|
|
301
|
-
|
|
416
|
+
const nowIso = new Date().toISOString();
|
|
417
|
+
hudState.last_turn_at = nowIso;
|
|
418
|
+
(hudState as any).last_progress_at = nowIso;
|
|
302
419
|
hudState.turn_count = (hudState.turn_count || 0) + 1;
|
|
303
420
|
(hudState as any).last_agent_output = (payload['last-assistant-message'] || payload.last_assistant_message || '')
|
|
304
421
|
.slice(0, 100);
|
|
@@ -323,14 +440,12 @@ async function main() {
|
|
|
323
440
|
// 4.45. Skill activation tracking: update skill-active-state.json before any nudge logic.
|
|
324
441
|
try {
|
|
325
442
|
const { recordSkillActivation } = await import('../hooks/keyword-detector.js');
|
|
326
|
-
const inputMessages = normalizeInputMessages(payload);
|
|
327
|
-
const latestUserInput = safeString(inputMessages.length > 0 ? inputMessages[inputMessages.length - 1] : '');
|
|
328
443
|
if (latestUserInput) {
|
|
329
444
|
await recordSkillActivation({
|
|
330
445
|
stateDir,
|
|
331
446
|
text: latestUserInput,
|
|
332
447
|
sessionId: payloadSessionId,
|
|
333
|
-
threadId:
|
|
448
|
+
threadId: payloadThreadId,
|
|
334
449
|
turnId: safeString(payload['turn-id'] || payload.turn_id || ''),
|
|
335
450
|
});
|
|
336
451
|
}
|
|
@@ -443,19 +558,20 @@ async function main() {
|
|
|
443
558
|
const { notifyLifecycle } = await import('../notifications/index.js');
|
|
444
559
|
const { shouldSendIdleNotification, recordIdleNotificationSent } = await import('../notifications/idle-cooldown.js');
|
|
445
560
|
const sessionJsonPath = join(stateDir, 'session.json');
|
|
561
|
+
const idleFingerprint = buildIdleNotificationFingerprint(payload);
|
|
446
562
|
let notifySessionId = '';
|
|
447
563
|
try {
|
|
448
564
|
const sessionData = JSON.parse(await readFile(sessionJsonPath, 'utf-8'));
|
|
449
565
|
notifySessionId = safeString(sessionData && sessionData.session_id ? sessionData.session_id : '');
|
|
450
566
|
} catch { /* no session file */ }
|
|
451
567
|
|
|
452
|
-
if (notifySessionId && shouldSendIdleNotification(stateDir, notifySessionId)) {
|
|
568
|
+
if (notifySessionId && shouldSendIdleNotification(stateDir, notifySessionId, idleFingerprint)) {
|
|
453
569
|
const idleResult = await notifyLifecycle('session-idle', {
|
|
454
570
|
sessionId: notifySessionId,
|
|
455
571
|
projectPath: cwd,
|
|
456
572
|
});
|
|
457
573
|
if (idleResult && idleResult.anySuccess) {
|
|
458
|
-
recordIdleNotificationSent(stateDir, notifySessionId);
|
|
574
|
+
recordIdleNotificationSent(stateDir, notifySessionId, idleFingerprint);
|
|
459
575
|
}
|
|
460
576
|
try {
|
|
461
577
|
const { buildNativeHookEvent } = await import('../hooks/extensibility/events.js');
|
|
@@ -506,7 +622,7 @@ async function main() {
|
|
|
506
622
|
payload,
|
|
507
623
|
stateDir,
|
|
508
624
|
logsDir,
|
|
509
|
-
sessionId: payloadSessionId,
|
|
625
|
+
sessionId: currentOmxSessionId || payloadSessionId,
|
|
510
626
|
turnId: safeString(payload['turn-id'] || payload.turn_id || ''),
|
|
511
627
|
});
|
|
512
628
|
} catch (err) {
|
|
@@ -531,23 +647,36 @@ async function main() {
|
|
|
531
647
|
const { processCodeSimplifier } = await import('../hooks/code-simplifier/index.js');
|
|
532
648
|
const csResult = processCodeSimplifier(cwd, stateDir);
|
|
533
649
|
if (csResult.triggered) {
|
|
534
|
-
const
|
|
535
|
-
if (
|
|
536
|
-
const csText = `${csResult.message} ${DEFAULT_MARKER}`;
|
|
537
|
-
const { runProcess } = await import('./notify-hook/process-runner.js');
|
|
538
|
-
await runProcess('tmux', ['send-keys', '-t', csPaneId, '-l', csText], 3000);
|
|
539
|
-
await new Promise(r => setTimeout(r, 100));
|
|
540
|
-
await runProcess('tmux', ['send-keys', '-t', csPaneId, 'C-m'], 3000);
|
|
541
|
-
await new Promise(r => setTimeout(r, 100));
|
|
542
|
-
await runProcess('tmux', ['send-keys', '-t', csPaneId, 'C-m'], 3000);
|
|
543
|
-
|
|
650
|
+
const managedSession = await isManagedOmxSession(cwd, payload, { allowTeamWorker: false });
|
|
651
|
+
if (!managedSession) {
|
|
544
652
|
const { logTmuxHookEvent } = await import('./notify-hook/log.js');
|
|
545
653
|
await logTmuxHookEvent(logsDir, {
|
|
546
654
|
timestamp: new Date().toISOString(),
|
|
547
|
-
type: '
|
|
548
|
-
|
|
549
|
-
file_count: csResult.message.split('\n').filter(l => l.trimStart().startsWith('- ')).length,
|
|
655
|
+
type: 'code_simplifier_skipped',
|
|
656
|
+
reason: 'unmanaged_session',
|
|
550
657
|
});
|
|
658
|
+
} else {
|
|
659
|
+
const csPaneId = await resolveNudgePaneTarget(stateDir, cwd, payload);
|
|
660
|
+
if (csPaneId) {
|
|
661
|
+
const csText = `${csResult.message} ${DEFAULT_MARKER}`;
|
|
662
|
+
const sendResult = await sendPaneInput({
|
|
663
|
+
paneTarget: csPaneId,
|
|
664
|
+
prompt: csText,
|
|
665
|
+
submitKeyPresses: 2,
|
|
666
|
+
submitDelayMs: 100,
|
|
667
|
+
});
|
|
668
|
+
if (!sendResult.ok) {
|
|
669
|
+
throw new Error(sendResult.error || sendResult.reason || 'send_failed');
|
|
670
|
+
}
|
|
671
|
+
|
|
672
|
+
const { logTmuxHookEvent } = await import('./notify-hook/log.js');
|
|
673
|
+
await logTmuxHookEvent(logsDir, {
|
|
674
|
+
timestamp: new Date().toISOString(),
|
|
675
|
+
type: 'code_simplifier_triggered',
|
|
676
|
+
pane_id: csPaneId,
|
|
677
|
+
file_count: csResult.message.split('\n').filter(l => l.trimStart().startsWith('- ')).length,
|
|
678
|
+
});
|
|
679
|
+
}
|
|
551
680
|
}
|
|
552
681
|
}
|
|
553
682
|
} catch {
|
|
@@ -59,7 +59,8 @@ function ensureBinary(binary: string): void {
|
|
|
59
59
|
const probe = spawnSync(binary, ['--version'], {
|
|
60
60
|
stdio: 'ignore',
|
|
61
61
|
encoding: 'utf8',
|
|
62
|
-
|
|
62
|
+
windowsHide: true,
|
|
63
|
+
});
|
|
63
64
|
|
|
64
65
|
if (probe.error && (probe.error as NodeJS.ErrnoException).code === 'ENOENT') {
|
|
65
66
|
const verify = `${binary} --version`;
|
|
@@ -153,7 +154,8 @@ async function main(): Promise<void> {
|
|
|
153
154
|
const run = spawnSync(binary, ['-p', prompt], {
|
|
154
155
|
encoding: 'utf8',
|
|
155
156
|
maxBuffer: 10 * 1024 * 1024,
|
|
156
|
-
|
|
157
|
+
windowsHide: true,
|
|
158
|
+
});
|
|
157
159
|
|
|
158
160
|
const stdout = run.stdout || '';
|
|
159
161
|
const stderr = run.stderr || '';
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
import { readdirSync, statSync } from 'node:fs';
|
|
3
|
+
import { join, resolve } from 'node:path';
|
|
4
|
+
|
|
5
|
+
function collectTests(path: string, out: string[]): void {
|
|
6
|
+
let stats;
|
|
7
|
+
try {
|
|
8
|
+
stats = statSync(path);
|
|
9
|
+
} catch {
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (stats.isDirectory()) {
|
|
14
|
+
for (const entry of readdirSync(path)) {
|
|
15
|
+
collectTests(join(path, entry), out);
|
|
16
|
+
}
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (stats.isFile() && path.endsWith('.test.js')) {
|
|
21
|
+
out.push(path);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const roots = process.argv.slice(2);
|
|
26
|
+
const targets = roots.length > 0 ? roots : ['dist'];
|
|
27
|
+
const files: string[] = [];
|
|
28
|
+
for (const target of targets) {
|
|
29
|
+
collectTests(resolve(target), files);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
files.sort();
|
|
33
|
+
|
|
34
|
+
if (files.length === 0) {
|
|
35
|
+
console.error(`No test files found under: ${targets.join(', ')}`);
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const result = spawnSync(process.execPath, ['--test', ...files], {
|
|
40
|
+
stdio: 'inherit',
|
|
41
|
+
env: process.env,
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
if (typeof result.status === 'number') {
|
|
45
|
+
process.exit(result.status);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
process.exit(1);
|
|
@@ -80,6 +80,10 @@ export function normalizeTmuxHookConfig(raw: any): any {
|
|
|
80
80
|
};
|
|
81
81
|
}
|
|
82
82
|
|
|
83
|
+
export function tmuxHookExplicitlyDisablesInjection(raw: any): boolean {
|
|
84
|
+
return Boolean(raw && typeof raw === 'object' && raw.enabled === false);
|
|
85
|
+
}
|
|
86
|
+
|
|
83
87
|
export function pickActiveMode(activeModes: any, allowedModes: any): string | null {
|
|
84
88
|
const activeSet = new Set((activeModes || []).filter((mode: any) => typeof mode === 'string'));
|
|
85
89
|
for (const mode of allowedModes || []) {
|
|
@@ -223,6 +227,7 @@ export function resolveCodexPane(): string {
|
|
|
223
227
|
try {
|
|
224
228
|
const sessionName = execFileSync('tmux', ['display-message', '-t', envPane, '-p', '#S'], {
|
|
225
229
|
encoding: 'utf-8', timeout: 2000,
|
|
230
|
+
windowsHide: true,
|
|
226
231
|
}).trim();
|
|
227
232
|
if (!sessionName) return '';
|
|
228
233
|
|
|
@@ -297,6 +302,17 @@ export function paneLooksReady(captured: any): boolean {
|
|
|
297
302
|
return lines.some((line) => /^\s*(?:[›>❯]\s*)?[A-Z][A-Z0-9]+-\d+\s+only(?:\s*(?:…|\.{3}))?\s*$/iu.test(line));
|
|
298
303
|
}
|
|
299
304
|
|
|
305
|
+
export function paneShowsCodexViewport(captured: any): boolean {
|
|
306
|
+
const lines = normalizePaneLines(captured);
|
|
307
|
+
if (lines.length === 0) return false;
|
|
308
|
+
if (paneIsBootstrapping(lines)) return false;
|
|
309
|
+
|
|
310
|
+
const hasCodexBanner = lines.some((line) => /\bOpenAI Codex\b/i.test(line));
|
|
311
|
+
if (!hasCodexBanner) return false;
|
|
312
|
+
|
|
313
|
+
return lines.some((line) => /(?:^|\s)(?:model|directory):/i.test(line));
|
|
314
|
+
}
|
|
315
|
+
|
|
300
316
|
export function paneHasActiveTask(captured: any): boolean {
|
|
301
317
|
const tail = normalizePaneLines(captured).map((line) => line.trim()).slice(-40);
|
|
302
318
|
if (tail.some((line) => /\b\d+\s+background terminal running\b/i.test(line))) return true;
|