oh-my-codex 0.7.5 → 0.8.0
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/README.de.md +314 -0
- package/README.es.md +295 -17
- package/README.fr.md +314 -0
- package/README.it.md +314 -0
- package/README.ja.md +296 -18
- package/README.ko.md +295 -17
- package/README.md +68 -3
- package/README.pt.md +295 -17
- package/README.ru.md +295 -17
- package/README.tr.md +314 -0
- package/README.vi.md +296 -18
- package/README.zh.md +292 -17
- package/dist/catalog/__tests__/generator.test.js +2 -0
- package/dist/catalog/__tests__/generator.test.js.map +1 -1
- package/dist/catalog/__tests__/schema.test.js +7 -0
- package/dist/catalog/__tests__/schema.test.js.map +1 -1
- package/dist/cli/__tests__/ask.test.d.ts +2 -0
- package/dist/cli/__tests__/ask.test.d.ts.map +1 -0
- package/dist/cli/__tests__/ask.test.js +236 -0
- package/dist/cli/__tests__/ask.test.js.map +1 -0
- package/dist/cli/__tests__/doctor-warning-copy.test.d.ts +2 -0
- package/dist/cli/__tests__/doctor-warning-copy.test.d.ts.map +1 -0
- package/dist/cli/__tests__/doctor-warning-copy.test.js +45 -0
- package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -0
- package/dist/cli/__tests__/index.test.js +43 -1
- package/dist/cli/__tests__/index.test.js.map +1 -1
- package/dist/cli/__tests__/ralph-prd-deep-interview.test.d.ts +2 -0
- package/dist/cli/__tests__/ralph-prd-deep-interview.test.d.ts.map +1 -0
- package/dist/cli/__tests__/ralph-prd-deep-interview.test.js +15 -0
- package/dist/cli/__tests__/ralph-prd-deep-interview.test.js.map +1 -0
- package/dist/cli/__tests__/ralph.test.d.ts +2 -0
- package/dist/cli/__tests__/ralph.test.d.ts.map +1 -0
- package/dist/cli/__tests__/ralph.test.js +40 -0
- package/dist/cli/__tests__/ralph.test.js.map +1 -0
- package/dist/cli/__tests__/setup-scope.test.js +2 -0
- package/dist/cli/__tests__/setup-scope.test.js.map +1 -1
- package/dist/cli/__tests__/team-decompose.test.d.ts +2 -0
- package/dist/cli/__tests__/team-decompose.test.d.ts.map +1 -0
- package/dist/cli/__tests__/team-decompose.test.js +67 -0
- package/dist/cli/__tests__/team-decompose.test.js.map +1 -0
- package/dist/cli/__tests__/version.test.d.ts +2 -0
- package/dist/cli/__tests__/version.test.d.ts.map +1 -0
- package/dist/cli/__tests__/version.test.js +21 -0
- package/dist/cli/__tests__/version.test.js.map +1 -0
- package/dist/cli/ask.d.ts +13 -0
- package/dist/cli/ask.d.ts.map +1 -0
- package/dist/cli/ask.js +174 -0
- package/dist/cli/ask.js.map +1 -0
- package/dist/cli/constants.d.ts +10 -0
- package/dist/cli/constants.d.ts.map +1 -0
- package/dist/cli/constants.js +10 -0
- package/dist/cli/constants.js.map +1 -0
- package/dist/cli/doctor.js +16 -5
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/index.d.ts +7 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +117 -43
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/ralph.d.ts +4 -0
- package/dist/cli/ralph.d.ts.map +1 -1
- package/dist/cli/ralph.js +89 -13
- package/dist/cli/ralph.js.map +1 -1
- package/dist/cli/setup.js +1 -1
- package/dist/cli/setup.js.map +1 -1
- package/dist/cli/team.d.ts +18 -0
- package/dist/cli/team.d.ts.map +1 -1
- package/dist/cli/team.js +108 -16
- package/dist/cli/team.js.map +1 -1
- package/dist/config/generator.d.ts.map +1 -1
- package/dist/config/generator.js +8 -0
- package/dist/config/generator.js.map +1 -1
- package/dist/hooks/__tests__/deep-interview-contract.test.d.ts +2 -0
- package/dist/hooks/__tests__/deep-interview-contract.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/deep-interview-contract.test.js +55 -0
- package/dist/hooks/__tests__/deep-interview-contract.test.js.map +1 -0
- package/dist/hooks/__tests__/emulator.test.js +6 -0
- package/dist/hooks/__tests__/emulator.test.js.map +1 -1
- package/dist/hooks/__tests__/keyword-detector.test.js +44 -22
- package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-session-scope.test.js +59 -0
- package/dist/hooks/__tests__/notify-hook-session-scope.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js +88 -0
- package/dist/hooks/__tests__/notify-hook-team-dispatch.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js +199 -0
- package/dist/hooks/__tests__/notify-hook-tmux-heal.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-visual-verdict.test.d.ts +11 -0
- package/dist/hooks/__tests__/notify-hook-visual-verdict.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/notify-hook-visual-verdict.test.js +266 -0
- package/dist/hooks/__tests__/notify-hook-visual-verdict.test.js.map +1 -0
- package/dist/hooks/__tests__/openclaw-setup-contract.test.d.ts +2 -0
- package/dist/hooks/__tests__/openclaw-setup-contract.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/openclaw-setup-contract.test.js +51 -0
- package/dist/hooks/__tests__/openclaw-setup-contract.test.js.map +1 -0
- package/dist/hooks/__tests__/pre-context-gate-skills.test.d.ts +2 -0
- package/dist/hooks/__tests__/pre-context-gate-skills.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/pre-context-gate-skills.test.js +34 -0
- package/dist/hooks/__tests__/pre-context-gate-skills.test.js.map +1 -0
- package/dist/hooks/__tests__/tmux-hook-engine.test.js +36 -1
- package/dist/hooks/__tests__/tmux-hook-engine.test.js.map +1 -1
- package/dist/hooks/__tests__/visual-verdict-loop.test.d.ts +2 -0
- package/dist/hooks/__tests__/visual-verdict-loop.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/visual-verdict-loop.test.js +35 -0
- package/dist/hooks/__tests__/visual-verdict-loop.test.js.map +1 -0
- package/dist/hooks/agents-overlay.d.ts.map +1 -1
- package/dist/hooks/agents-overlay.js +18 -16
- package/dist/hooks/agents-overlay.js.map +1 -1
- package/dist/hooks/codebase-map.d.ts.map +1 -1
- package/dist/hooks/codebase-map.js +6 -2
- package/dist/hooks/codebase-map.js.map +1 -1
- package/dist/hooks/emulator.d.ts.map +1 -1
- package/dist/hooks/emulator.js +2 -0
- package/dist/hooks/emulator.js.map +1 -1
- package/dist/hooks/extensibility/sdk.d.ts.map +1 -1
- package/dist/hooks/extensibility/sdk.js +2 -1
- package/dist/hooks/extensibility/sdk.js.map +1 -1
- package/dist/hooks/keyword-registry.d.ts.map +1 -1
- package/dist/hooks/keyword-registry.js +6 -0
- package/dist/hooks/keyword-registry.js.map +1 -1
- package/dist/hud/index.d.ts.map +1 -1
- package/dist/hud/index.js +2 -24
- package/dist/hud/index.js.map +1 -1
- package/dist/mcp/__tests__/team-server-cleanup.test.d.ts +2 -0
- package/dist/mcp/__tests__/team-server-cleanup.test.d.ts.map +1 -0
- package/dist/mcp/__tests__/team-server-cleanup.test.js +219 -0
- package/dist/mcp/__tests__/team-server-cleanup.test.js.map +1 -0
- package/dist/mcp/bootstrap.d.ts +1 -1
- package/dist/mcp/bootstrap.d.ts.map +1 -1
- package/dist/mcp/bootstrap.js +1 -0
- package/dist/mcp/bootstrap.js.map +1 -1
- package/dist/mcp/code-intel-server.d.ts.map +1 -1
- package/dist/mcp/code-intel-server.js +18 -8
- package/dist/mcp/code-intel-server.js.map +1 -1
- package/dist/mcp/memory-server.js +72 -11
- package/dist/mcp/memory-server.js.map +1 -1
- package/dist/mcp/state-paths.d.ts.map +1 -1
- package/dist/mcp/state-paths.js +4 -1
- package/dist/mcp/state-paths.js.map +1 -1
- package/dist/mcp/state-server.d.ts.map +1 -1
- package/dist/mcp/state-server.js +18 -5
- package/dist/mcp/state-server.js.map +1 -1
- package/dist/mcp/team-server.d.ts +24 -0
- package/dist/mcp/team-server.d.ts.map +1 -0
- package/dist/mcp/team-server.js +425 -0
- package/dist/mcp/team-server.js.map +1 -0
- package/dist/mcp/trace-server.d.ts.map +1 -1
- package/dist/mcp/trace-server.js +8 -3
- package/dist/mcp/trace-server.js.map +1 -1
- package/dist/notifications/__tests__/verbosity.test.js +35 -0
- package/dist/notifications/__tests__/verbosity.test.js.map +1 -1
- package/dist/notifications/config.d.ts.map +1 -1
- package/dist/notifications/config.js +12 -3
- package/dist/notifications/config.js.map +1 -1
- package/dist/notifications/dispatcher.d.ts.map +1 -1
- package/dist/notifications/dispatcher.js +4 -4
- package/dist/notifications/dispatcher.js.map +1 -1
- package/dist/notifications/reply-listener.d.ts.map +1 -1
- package/dist/notifications/reply-listener.js +6 -2
- package/dist/notifications/reply-listener.js.map +1 -1
- package/dist/notifications/session-registry.d.ts.map +1 -1
- package/dist/notifications/session-registry.js +2 -2
- package/dist/notifications/session-registry.js.map +1 -1
- package/dist/notifications/tmux.d.ts.map +1 -1
- package/dist/notifications/tmux.js +13 -4
- package/dist/notifications/tmux.js.map +1 -1
- package/dist/notifications/types.d.ts +4 -0
- package/dist/notifications/types.d.ts.map +1 -1
- package/dist/openclaw/__tests__/index.test.js +40 -0
- package/dist/openclaw/__tests__/index.test.js.map +1 -1
- package/dist/openclaw/dispatcher.d.ts.map +1 -1
- package/dist/openclaw/dispatcher.js +5 -2
- package/dist/openclaw/dispatcher.js.map +1 -1
- package/dist/openclaw/index.d.ts.map +1 -1
- package/dist/openclaw/index.js +1 -0
- package/dist/openclaw/index.js.map +1 -1
- package/dist/openclaw/types.d.ts +2 -0
- package/dist/openclaw/types.d.ts.map +1 -1
- package/dist/ralph/__tests__/persistence.test.js +28 -1
- package/dist/ralph/__tests__/persistence.test.js.map +1 -1
- package/dist/ralph/persistence.d.ts +21 -0
- package/dist/ralph/persistence.d.ts.map +1 -1
- package/dist/ralph/persistence.js +85 -2
- package/dist/ralph/persistence.js.map +1 -1
- package/dist/state/paths.d.ts +3 -0
- package/dist/state/paths.d.ts.map +1 -0
- package/dist/state/paths.js +2 -0
- package/dist/state/paths.js.map +1 -0
- package/dist/team/__tests__/idle-nudge.test.d.ts +2 -0
- package/dist/team/__tests__/idle-nudge.test.d.ts.map +1 -0
- package/dist/team/__tests__/idle-nudge.test.js +225 -0
- package/dist/team/__tests__/idle-nudge.test.js.map +1 -0
- package/dist/team/__tests__/role-router.test.d.ts +2 -0
- package/dist/team/__tests__/role-router.test.d.ts.map +1 -0
- package/dist/team/__tests__/role-router.test.js +204 -0
- package/dist/team/__tests__/role-router.test.js.map +1 -0
- package/dist/team/__tests__/runtime-cli.test.d.ts +2 -0
- package/dist/team/__tests__/runtime-cli.test.d.ts.map +1 -0
- package/dist/team/__tests__/runtime-cli.test.js +72 -0
- package/dist/team/__tests__/runtime-cli.test.js.map +1 -0
- package/dist/team/__tests__/runtime.test.js +195 -9
- package/dist/team/__tests__/runtime.test.js.map +1 -1
- package/dist/team/__tests__/scaling.test.js +132 -2
- package/dist/team/__tests__/scaling.test.js.map +1 -1
- package/dist/team/__tests__/state-root.test.d.ts +2 -0
- package/dist/team/__tests__/state-root.test.d.ts.map +1 -0
- package/dist/team/__tests__/state-root.test.js +9 -0
- package/dist/team/__tests__/state-root.test.js.map +1 -0
- package/dist/team/__tests__/state.test.js +52 -17
- package/dist/team/__tests__/state.test.js.map +1 -1
- package/dist/team/__tests__/team-ops-contract.test.d.ts +2 -0
- package/dist/team/__tests__/team-ops-contract.test.d.ts.map +1 -0
- package/dist/team/__tests__/team-ops-contract.test.js +90 -0
- package/dist/team/__tests__/team-ops-contract.test.js.map +1 -0
- package/dist/team/__tests__/tmux-session.test.js +94 -7
- package/dist/team/__tests__/tmux-session.test.js.map +1 -1
- package/dist/team/__tests__/worker-bootstrap.test.js +59 -0
- package/dist/team/__tests__/worker-bootstrap.test.js.map +1 -1
- package/dist/team/__tests__/worktree.test.js +81 -2
- package/dist/team/__tests__/worktree.test.js.map +1 -1
- package/dist/team/idle-nudge.d.ts +53 -0
- package/dist/team/idle-nudge.d.ts.map +1 -0
- package/dist/team/idle-nudge.js +140 -0
- package/dist/team/idle-nudge.js.map +1 -0
- package/dist/team/mcp-comm.d.ts +1 -1
- package/dist/team/mcp-comm.d.ts.map +1 -1
- package/dist/team/mcp-comm.js +6 -2
- package/dist/team/mcp-comm.js.map +1 -1
- package/dist/team/orchestrator.d.ts +1 -10
- package/dist/team/orchestrator.d.ts.map +1 -1
- package/dist/team/orchestrator.js +8 -0
- package/dist/team/orchestrator.js.map +1 -1
- package/dist/team/role-router.d.ts +32 -0
- package/dist/team/role-router.d.ts.map +1 -0
- package/dist/team/role-router.js +137 -0
- package/dist/team/role-router.js.map +1 -0
- package/dist/team/runtime-cli.d.ts +18 -0
- package/dist/team/runtime-cli.d.ts.map +1 -0
- package/dist/team/runtime-cli.js +244 -0
- package/dist/team/runtime-cli.js.map +1 -0
- package/dist/team/runtime.d.ts +6 -1
- package/dist/team/runtime.d.ts.map +1 -1
- package/dist/team/runtime.js +148 -60
- package/dist/team/runtime.js.map +1 -1
- package/dist/team/scaling.d.ts +1 -0
- package/dist/team/scaling.d.ts.map +1 -1
- package/dist/team/scaling.js +74 -32
- package/dist/team/scaling.js.map +1 -1
- package/dist/team/state/approvals.d.ts +25 -0
- package/dist/team/state/approvals.d.ts.map +1 -0
- package/dist/team/state/approvals.js +31 -0
- package/dist/team/state/approvals.js.map +1 -0
- package/dist/team/state/config.d.ts +2 -0
- package/dist/team/state/config.d.ts.map +1 -0
- package/dist/team/state/config.js +2 -0
- package/dist/team/state/config.js.map +1 -0
- package/dist/team/state/dispatch-lock.d.ts +3 -0
- package/dist/team/state/dispatch-lock.d.ts.map +1 -0
- package/dist/team/state/dispatch-lock.js +81 -0
- package/dist/team/state/dispatch-lock.js.map +1 -0
- package/dist/team/state/dispatch.d.ts +61 -0
- package/dist/team/state/dispatch.d.ts.map +1 -0
- package/dist/team/state/dispatch.js +158 -0
- package/dist/team/state/dispatch.js.map +1 -0
- package/dist/team/state/events.d.ts +2 -0
- package/dist/team/state/events.d.ts.map +1 -0
- package/dist/team/state/events.js +2 -0
- package/dist/team/state/events.js.map +1 -0
- package/dist/team/state/index.d.ts +11 -0
- package/dist/team/state/index.d.ts.map +1 -0
- package/dist/team/state/index.js +11 -0
- package/dist/team/state/index.js.map +1 -0
- package/dist/team/state/io.d.ts +2 -0
- package/dist/team/state/io.d.ts.map +1 -0
- package/dist/team/state/io.js +2 -0
- package/dist/team/state/io.js.map +1 -0
- package/dist/team/state/locks.d.ts +16 -0
- package/dist/team/state/locks.d.ts.map +1 -0
- package/dist/team/state/locks.js +201 -0
- package/dist/team/state/locks.js.map +1 -0
- package/dist/team/state/mailbox.d.ts +39 -0
- package/dist/team/state/mailbox.d.ts.map +1 -0
- package/dist/team/state/mailbox.js +58 -0
- package/dist/team/state/mailbox.js.map +1 -0
- package/dist/team/state/monitor.d.ts +96 -0
- package/dist/team/state/monitor.d.ts.map +1 -0
- package/dist/team/state/monitor.js +163 -0
- package/dist/team/state/monitor.js.map +1 -0
- package/dist/team/state/shutdown.d.ts +2 -0
- package/dist/team/state/shutdown.d.ts.map +1 -0
- package/dist/team/state/shutdown.js +2 -0
- package/dist/team/state/shutdown.js.map +1 -0
- package/dist/team/state/summary.d.ts +2 -0
- package/dist/team/state/summary.d.ts.map +1 -0
- package/dist/team/state/summary.js +2 -0
- package/dist/team/state/summary.js.map +1 -0
- package/dist/team/state/tasks.d.ts +49 -0
- package/dist/team/state/tasks.d.ts.map +1 -0
- package/dist/team/state/tasks.js +182 -0
- package/dist/team/state/tasks.js.map +1 -0
- package/dist/team/state/types.d.ts +281 -0
- package/dist/team/state/types.d.ts.map +1 -0
- package/dist/team/state/types.js +3 -0
- package/dist/team/state/types.js.map +1 -0
- package/dist/team/state/workers.d.ts +2 -0
- package/dist/team/state/workers.d.ts.map +1 -0
- package/dist/team/state/workers.js +2 -0
- package/dist/team/state/workers.js.map +1 -0
- package/dist/team/state-root.d.ts +5 -0
- package/dist/team/state-root.d.ts.map +1 -0
- package/dist/team/state-root.js +8 -0
- package/dist/team/state-root.js.map +1 -0
- package/dist/team/state.d.ts +6 -2
- package/dist/team/state.d.ts.map +1 -1
- package/dist/team/state.js +200 -881
- package/dist/team/state.js.map +1 -1
- package/dist/team/tmux-session.d.ts +42 -2
- package/dist/team/tmux-session.d.ts.map +1 -1
- package/dist/team/tmux-session.js +229 -74
- package/dist/team/tmux-session.js.map +1 -1
- package/dist/team/worker-bootstrap.d.ts +2 -0
- package/dist/team/worker-bootstrap.d.ts.map +1 -1
- package/dist/team/worker-bootstrap.js +47 -20
- package/dist/team/worker-bootstrap.js.map +1 -1
- package/dist/team/worktree.d.ts +5 -1
- package/dist/team/worktree.d.ts.map +1 -1
- package/dist/team/worktree.js +71 -17
- package/dist/team/worktree.js.map +1 -1
- package/dist/utils/safe-json.d.ts +3 -0
- package/dist/utils/safe-json.d.ts.map +1 -0
- package/dist/utils/safe-json.js +19 -0
- package/dist/utils/safe-json.js.map +1 -0
- package/dist/utils/sleep.d.ts +3 -0
- package/dist/utils/sleep.d.ts.map +1 -0
- package/dist/utils/sleep.js +15 -0
- package/dist/utils/sleep.js.map +1 -0
- package/dist/visual/__tests__/verdict.test.d.ts +2 -0
- package/dist/visual/__tests__/verdict.test.d.ts.map +1 -0
- package/dist/visual/__tests__/verdict.test.js +81 -0
- package/dist/visual/__tests__/verdict.test.js.map +1 -0
- package/dist/visual/constants.d.ts +4 -0
- package/dist/visual/constants.d.ts.map +1 -0
- package/dist/visual/constants.js +3 -0
- package/dist/visual/constants.js.map +1 -0
- package/dist/visual/verdict.d.ts +17 -0
- package/dist/visual/verdict.d.ts.map +1 -0
- package/dist/visual/verdict.js +61 -0
- package/dist/visual/verdict.js.map +1 -0
- package/package.json +10 -3
- package/scripts/ask-claude.sh +17 -0
- package/scripts/ask-gemini.sh +14 -0
- package/scripts/fixtures/ask-advisor-stub.js +12 -0
- package/scripts/notify-hook/log.js +5 -0
- package/scripts/notify-hook/team-dispatch.js +56 -1
- package/scripts/notify-hook/tmux-injection.js +45 -4
- package/scripts/notify-hook/visual-verdict.js +158 -0
- package/scripts/notify-hook.js +27 -0
- package/scripts/run-provider-advisor.js +179 -0
- package/scripts/tmux-hook-engine.js +24 -0
- package/skills/ask-claude/SKILL.md +61 -0
- package/skills/ask-gemini/SKILL.md +61 -0
- package/skills/autopilot/SKILL.md +34 -4
- package/skills/configure-notifications/SKILL.md +1 -1
- package/skills/configure-openclaw/SKILL.md +154 -157
- package/skills/deep-interview/SKILL.md +247 -0
- package/skills/doctor/SKILL.md +1 -1
- package/skills/help/SKILL.md +3 -3
- package/skills/ralph/SKILL.md +42 -11
- package/skills/ralplan/SKILL.md +17 -0
- package/skills/skill/SKILL.md +32 -32
- package/skills/team/SKILL.md +60 -0
- package/skills/visual-verdict/SKILL.md +76 -0
- package/skills/web-clone/SKILL.md +366 -0
- package/skills/worker/SKILL.md +5 -4
- package/templates/AGENTS.md +9 -0
- package/templates/catalog-manifest.json +39 -2
package/dist/team/runtime.js
CHANGED
|
@@ -3,11 +3,14 @@ import { existsSync } from 'fs';
|
|
|
3
3
|
import { readdir, readFile } from 'fs/promises';
|
|
4
4
|
import { performance } from 'perf_hooks';
|
|
5
5
|
import { spawn } from 'child_process';
|
|
6
|
-
import { sanitizeTeamName, isTmuxAvailable, createTeamSession, buildWorkerProcessLaunchSpec, resolveTeamWorkerCli, resolveTeamWorkerCliPlan, resolveTeamWorkerLaunchMode, waitForWorkerReady, dismissTrustPromptIfPresent, sleepFractionalSeconds, sendToWorker,
|
|
7
|
-
import { teamInit as initTeamState, DEFAULT_MAX_WORKERS, teamReadConfig as readTeamConfig, teamWriteWorkerIdentity as writeWorkerIdentity, teamReadWorkerHeartbeat as readWorkerHeartbeat, teamReadWorkerStatus as readWorkerStatus, teamWriteWorkerInbox as writeWorkerInbox, teamCreateTask as createStateTask, teamReadTask as readTask, teamListTasks as listTasks, teamReadManifest as readTeamManifestV2, teamNormalizePolicy as normalizeTeamPolicy, teamClaimTask as claimTask, teamReleaseTaskClaim as releaseTaskClaim, teamAppendEvent as appendTeamEvent, teamReadTaskApproval as readTaskApproval, teamListMailbox as listMailboxMessages, teamMarkMessageNotified as markMessageNotified, teamEnqueueDispatchRequest as enqueueDispatchRequest, teamMarkDispatchRequestNotified as markDispatchRequestNotified, teamTransitionDispatchRequest as transitionDispatchRequest, teamReadDispatchRequest as readDispatchRequest, teamCleanup as cleanupTeamState, teamSaveConfig as saveTeamConfig, teamWriteShutdownRequest as writeShutdownRequest, teamReadShutdownAck as readShutdownAck, teamReadMonitorSnapshot as readMonitorSnapshot, teamWriteMonitorSnapshot as writeMonitorSnapshot, teamReadPhase as readTeamPhaseState, teamWritePhase as writeTeamPhaseState, } from './team-ops.js';
|
|
6
|
+
import { sanitizeTeamName, isTmuxAvailable, createTeamSession, buildWorkerProcessLaunchSpec, resolveTeamWorkerCli, resolveTeamWorkerCliPlan, resolveTeamWorkerLaunchMode, waitForWorkerReady, dismissTrustPromptIfPresent, sleepFractionalSeconds, sendToWorker, sendToLeaderPane, sendToWorkerStdin, isWorkerAlive, getWorkerPanePid, killWorkerByPaneIdAsync, teardownWorkerPanes, unregisterResizeHook, destroyTeamSession, listTeamSessions, } from './tmux-session.js';
|
|
7
|
+
import { teamInit as initTeamState, DEFAULT_MAX_WORKERS, teamReadConfig as readTeamConfig, teamWriteWorkerIdentity as writeWorkerIdentity, teamReadWorkerHeartbeat as readWorkerHeartbeat, teamReadWorkerStatus as readWorkerStatus, teamWriteWorkerInbox as writeWorkerInbox, teamCreateTask as createStateTask, teamReadTask as readTask, teamListTasks as listTasks, teamReadManifest as readTeamManifestV2, teamNormalizePolicy as normalizeTeamPolicy, teamClaimTask as claimTask, teamReleaseTaskClaim as releaseTaskClaim, teamAppendEvent as appendTeamEvent, teamReadTaskApproval as readTaskApproval, teamListMailbox as listMailboxMessages, teamMarkMessageDelivered as markMessageDelivered, teamMarkMessageNotified as markMessageNotified, teamEnqueueDispatchRequest as enqueueDispatchRequest, teamMarkDispatchRequestNotified as markDispatchRequestNotified, teamTransitionDispatchRequest as transitionDispatchRequest, teamReadDispatchRequest as readDispatchRequest, teamCleanup as cleanupTeamState, teamSaveConfig as saveTeamConfig, teamWriteShutdownRequest as writeShutdownRequest, teamReadShutdownAck as readShutdownAck, teamReadMonitorSnapshot as readMonitorSnapshot, teamWriteMonitorSnapshot as writeMonitorSnapshot, teamReadPhase as readTeamPhaseState, teamWritePhase as writeTeamPhaseState, } from './team-ops.js';
|
|
8
8
|
import { queueInboxInstruction, queueDirectMailboxMessage, queueBroadcastMailboxMessage, waitForDispatchReceipt, } from './mcp-comm.js';
|
|
9
9
|
import { generateWorkerOverlay, writeTeamWorkerInstructionsFile, removeTeamWorkerInstructionsFile, generateInitialInbox, generateTaskAssignmentInbox, generateShutdownInbox, generateTriggerMessage, generateMailboxTriggerMessage, } from './worker-bootstrap.js';
|
|
10
|
+
import { loadRolePrompt } from './role-router.js';
|
|
11
|
+
import { codexPromptsDir } from '../utils/paths.js';
|
|
10
12
|
import { isLowComplexityAgentType, resolveTeamWorkerLaunchArgs, TEAM_LOW_COMPLEXITY_DEFAULT_MODEL, resolveTeamLowComplexityDefaultModel, parseTeamWorkerLaunchArgs, splitWorkerLaunchArgs, } from './model-contract.js';
|
|
13
|
+
import { resolveCanonicalTeamStateRoot } from './state-root.js';
|
|
11
14
|
import { inferPhaseTargetFromTaskCounts, reconcilePhaseStateForMonitor } from './phase-controller.js';
|
|
12
15
|
import { getTeamTmuxSessions } from '../notifications/tmux.js';
|
|
13
16
|
import { hasStructuredVerificationEvidence } from '../verification/verifier.js';
|
|
@@ -83,7 +86,8 @@ function isPidAlive(pid) {
|
|
|
83
86
|
process.kill(pid, 0);
|
|
84
87
|
return true;
|
|
85
88
|
}
|
|
86
|
-
catch {
|
|
89
|
+
catch (err) {
|
|
90
|
+
process.stderr.write(`[team/runtime] operation failed: ${err}\n`);
|
|
87
91
|
return false;
|
|
88
92
|
}
|
|
89
93
|
}
|
|
@@ -100,8 +104,9 @@ async function waitForPidExit(pid, timeoutMs) {
|
|
|
100
104
|
}
|
|
101
105
|
async function teardownPromptWorker(teamName, workerName, fallbackPid, cwd, context) {
|
|
102
106
|
const handle = getPromptWorkerHandle(teamName, workerName);
|
|
103
|
-
const
|
|
104
|
-
|
|
107
|
+
const handlePid = handle?.pid;
|
|
108
|
+
const pid = (typeof handlePid === 'number' && Number.isFinite(handlePid))
|
|
109
|
+
? handlePid
|
|
105
110
|
: (Number.isFinite(fallbackPid) && (fallbackPid ?? 0) > 0 ? fallbackPid : null);
|
|
106
111
|
if (pid === null) {
|
|
107
112
|
removePromptWorkerHandle(teamName, workerName);
|
|
@@ -115,7 +120,8 @@ async function teardownPromptWorker(teamName, workerName, fallbackPid, cwd, cont
|
|
|
115
120
|
process.kill(pid, 'SIGTERM');
|
|
116
121
|
}
|
|
117
122
|
}
|
|
118
|
-
catch {
|
|
123
|
+
catch (err) {
|
|
124
|
+
process.stderr.write(`[team/runtime] operation failed: ${err}\n`);
|
|
119
125
|
// Best effort.
|
|
120
126
|
}
|
|
121
127
|
const exitedOnTerm = await waitForPidExit(pid, PROMPT_WORKER_SIGTERM_WAIT_MS);
|
|
@@ -136,7 +142,8 @@ async function teardownPromptWorker(teamName, workerName, fallbackPid, cwd, cont
|
|
|
136
142
|
process.kill(pid, 'SIGKILL');
|
|
137
143
|
}
|
|
138
144
|
}
|
|
139
|
-
catch {
|
|
145
|
+
catch (err) {
|
|
146
|
+
process.stderr.write(`[team/runtime] operation failed: ${err}\n`);
|
|
140
147
|
// Best effort.
|
|
141
148
|
}
|
|
142
149
|
const exitedOnKill = await waitForPidExit(pid, PROMPT_WORKER_SIGKILL_WAIT_MS);
|
|
@@ -166,14 +173,13 @@ function isPromptWorkerAlive(config, worker) {
|
|
|
166
173
|
process.kill(worker.pid, 0);
|
|
167
174
|
return true;
|
|
168
175
|
}
|
|
169
|
-
catch {
|
|
176
|
+
catch (err) {
|
|
177
|
+
process.stderr.write(`[team/runtime] operation failed: ${err}\n`);
|
|
170
178
|
return false;
|
|
171
179
|
}
|
|
172
180
|
}
|
|
173
181
|
export { TEAM_LOW_COMPLEXITY_DEFAULT_MODEL };
|
|
174
|
-
export
|
|
175
|
-
return resolve(join(leaderCwd, '.omx', 'state'));
|
|
176
|
-
}
|
|
182
|
+
export { resolveCanonicalTeamStateRoot };
|
|
177
183
|
function spawnPromptWorker(teamName, workerName, workerIndex, workerCwd, launchArgs, workerEnv, workerCli) {
|
|
178
184
|
const processSpec = buildWorkerProcessLaunchSpec(teamName, workerIndex, launchArgs, workerCwd, workerEnv, workerCli);
|
|
179
185
|
const child = spawn(processSpec.command, processSpec.args, {
|
|
@@ -401,11 +407,24 @@ export async function startTeam(teamName, task, agentType, workerCount, tasks, c
|
|
|
401
407
|
const workerWorkspace = workerWorkspaceByName.get(workerName) ?? { cwd: leaderCwd };
|
|
402
408
|
// Get tasks assigned to this worker
|
|
403
409
|
const workerTasks = allTasks.filter(t => t.owner === workerName);
|
|
410
|
+
// Resolve per-worker role from assigned task roles
|
|
411
|
+
const taskRoles = workerTasks.map(t => t.role).filter(Boolean);
|
|
412
|
+
const uniqueTaskRoles = new Set(taskRoles);
|
|
413
|
+
const workerRole = taskRoles.length > 0 && uniqueTaskRoles.size === 1
|
|
414
|
+
? taskRoles[0]
|
|
415
|
+
: agentType;
|
|
416
|
+
if (uniqueTaskRoles.size > 1) {
|
|
417
|
+
console.log(`[omx:team] ${workerName}: mixed task roles [${[...uniqueTaskRoles].join(', ')}], falling back to ${agentType}`);
|
|
418
|
+
}
|
|
419
|
+
// Load role-specific prompt content if role differs from default
|
|
420
|
+
const rolePromptContent = workerRole !== agentType
|
|
421
|
+
? await loadRolePrompt(workerRole, codexPromptsDir())
|
|
422
|
+
: null;
|
|
404
423
|
// Write worker identity
|
|
405
424
|
const identity = {
|
|
406
425
|
name: workerName,
|
|
407
426
|
index: i,
|
|
408
|
-
role:
|
|
427
|
+
role: workerRole,
|
|
409
428
|
worker_cli: workerCliPlan[i - 1],
|
|
410
429
|
assigned_tasks: workerTasks.map(t => t.id),
|
|
411
430
|
working_dir: workerWorkspace.cwd,
|
|
@@ -448,6 +467,8 @@ export async function startTeam(teamName, task, agentType, workerCount, tasks, c
|
|
|
448
467
|
const inbox = generateInitialInbox(workerName, sanitized, agentType, workerTasks, {
|
|
449
468
|
teamStateRoot,
|
|
450
469
|
leaderCwd,
|
|
470
|
+
workerRole,
|
|
471
|
+
rolePromptContent: rolePromptContent ?? undefined,
|
|
451
472
|
});
|
|
452
473
|
const trigger = generateTriggerMessage(workerName, sanitized);
|
|
453
474
|
const maxStartupDispatchRetries = 3;
|
|
@@ -524,15 +545,19 @@ export async function startTeam(teamName, task, agentType, workerCount, tasks, c
|
|
|
524
545
|
if (sessionName.includes(':')) {
|
|
525
546
|
for (const paneId of createdWorkerPaneIds) {
|
|
526
547
|
try {
|
|
527
|
-
|
|
548
|
+
await killWorkerByPaneIdAsync(paneId, createdLeaderPaneId);
|
|
549
|
+
}
|
|
550
|
+
catch (err) {
|
|
551
|
+
process.stderr.write(`[team/runtime] operation failed: ${err}\n`);
|
|
528
552
|
}
|
|
529
|
-
catch { /* ignore */ }
|
|
530
553
|
}
|
|
531
554
|
if (config?.hud_pane_id) {
|
|
532
555
|
try {
|
|
533
|
-
|
|
556
|
+
await killWorkerByPaneIdAsync(config.hud_pane_id, createdLeaderPaneId);
|
|
557
|
+
}
|
|
558
|
+
catch (err) {
|
|
559
|
+
process.stderr.write(`[team/runtime] operation failed: ${err}\n`);
|
|
534
560
|
}
|
|
535
|
-
catch { /* ignore */ }
|
|
536
561
|
}
|
|
537
562
|
}
|
|
538
563
|
else {
|
|
@@ -573,7 +598,9 @@ export async function startTeam(teamName, task, agentType, workerCount, tasks, c
|
|
|
573
598
|
}
|
|
574
599
|
if (provisionedWorktrees.length > 0) {
|
|
575
600
|
try {
|
|
576
|
-
await rollbackProvisionedWorktrees(provisionedWorktrees
|
|
601
|
+
await rollbackProvisionedWorktrees(provisionedWorktrees, {
|
|
602
|
+
skipBranchDeletion: options.ralph === true,
|
|
603
|
+
});
|
|
577
604
|
}
|
|
578
605
|
catch (cleanupError) {
|
|
579
606
|
rollbackErrors.push(`rollbackProvisionedWorktrees: ${String(cleanupError)}`);
|
|
@@ -691,6 +718,22 @@ export async function monitorTeam(teamName, cwd) {
|
|
|
691
718
|
const mailboxDeliveryStartMs = performance.now();
|
|
692
719
|
const mailboxNotifiedByMessageId = await deliverPendingMailboxMessages(sanitized, config, workers, previousSnapshot?.mailboxNotifiedByMessageId ?? {}, dispatchPolicy, cwd);
|
|
693
720
|
const mailboxDeliveryMs = performance.now() - mailboxDeliveryStartMs;
|
|
721
|
+
// Prune ephemeral status messages from leader mailbox (TTL: 60s)
|
|
722
|
+
try {
|
|
723
|
+
const leaderMailbox = await listMailboxMessages(sanitized, 'leader-fixed', cwd);
|
|
724
|
+
const now = Date.now();
|
|
725
|
+
for (const msg of leaderMailbox) {
|
|
726
|
+
if (msg.from_worker === 'system' && msg.created_at) {
|
|
727
|
+
const age = now - new Date(msg.created_at).getTime();
|
|
728
|
+
if (age > 60_000) {
|
|
729
|
+
await markMessageDelivered(sanitized, 'leader-fixed', msg.message_id, cwd);
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
catch (err) {
|
|
735
|
+
process.stderr.write(`[team/runtime] operation failed: ${err}\n`);
|
|
736
|
+
}
|
|
694
737
|
const updatedAt = new Date().toISOString();
|
|
695
738
|
const totalMs = performance.now() - monitorStartMs;
|
|
696
739
|
await writeMonitorSnapshot(sanitized, {
|
|
@@ -788,7 +831,7 @@ export async function assignTask(teamName, workerName, taskId, cwd) {
|
|
|
788
831
|
waitForWorkerReady(config.tmux_session, workerInfo.index, 15_000, workerInfo.pane_id);
|
|
789
832
|
}
|
|
790
833
|
else {
|
|
791
|
-
|
|
834
|
+
await new Promise(r => setTimeout(r, assignRetryDelayS * 1000));
|
|
792
835
|
}
|
|
793
836
|
}
|
|
794
837
|
}
|
|
@@ -805,7 +848,8 @@ export async function assignTask(teamName, workerName, taskId, cwd) {
|
|
|
805
848
|
try {
|
|
806
849
|
await writeWorkerInbox(sanitized, workerName, `# Assignment Cancelled\n\nTask ${taskId} was not dispatched due to ${reason}.\nDo not execute this task from prior inbox content.`, cwd);
|
|
807
850
|
}
|
|
808
|
-
catch {
|
|
851
|
+
catch (err) {
|
|
852
|
+
process.stderr.write(`[team/runtime] operation failed: ${err}\n`);
|
|
809
853
|
// best effort
|
|
810
854
|
}
|
|
811
855
|
if (!released.ok) {
|
|
@@ -827,6 +871,7 @@ export async function reassignTask(teamName, taskId, _fromWorker, toWorker, cwd)
|
|
|
827
871
|
*/
|
|
828
872
|
export async function shutdownTeam(teamName, cwd, options = {}) {
|
|
829
873
|
const force = options.force === true;
|
|
874
|
+
const ralph = options.ralph === true;
|
|
830
875
|
const sanitized = sanitizeTeamName(teamName);
|
|
831
876
|
const config = await readTeamConfig(sanitized, cwd);
|
|
832
877
|
if (!config) {
|
|
@@ -834,7 +879,9 @@ export async function shutdownTeam(teamName, cwd, options = {}) {
|
|
|
834
879
|
try {
|
|
835
880
|
destroyTeamSession(`omx-team-${sanitized}`);
|
|
836
881
|
}
|
|
837
|
-
catch {
|
|
882
|
+
catch (err) {
|
|
883
|
+
process.stderr.write(`[team/runtime] operation failed: ${err}\n`);
|
|
884
|
+
}
|
|
838
885
|
await cleanupTeamState(sanitized, cwd);
|
|
839
886
|
restoreTeamModelInstructionsFile(sanitized);
|
|
840
887
|
return;
|
|
@@ -854,10 +901,22 @@ export async function shutdownTeam(teamName, cwd, options = {}) {
|
|
|
854
901
|
await appendTeamEvent(sanitized, {
|
|
855
902
|
type: 'shutdown_gate',
|
|
856
903
|
worker: 'leader-fixed',
|
|
857
|
-
reason: `allowed=${gate.allowed} total=${gate.total} pending=${gate.pending} blocked=${gate.blocked} in_progress=${gate.in_progress} completed=${gate.completed} failed=${gate.failed}`,
|
|
904
|
+
reason: `allowed=${gate.allowed} total=${gate.total} pending=${gate.pending} blocked=${gate.blocked} in_progress=${gate.in_progress} completed=${gate.completed} failed=${gate.failed}${ralph ? ' policy=ralph' : ''}`,
|
|
858
905
|
}, cwd).catch(() => { });
|
|
859
906
|
if (!gate.allowed) {
|
|
860
|
-
|
|
907
|
+
const hasActiveWork = gate.pending > 0 || gate.blocked > 0 || gate.in_progress > 0;
|
|
908
|
+
if (ralph && !hasActiveWork) {
|
|
909
|
+
// Ralph policy: bypass on failure-only scenarios (no pending/blocked/in_progress tasks).
|
|
910
|
+
// This allows the ralph loop to retry rather than leaving stale team state.
|
|
911
|
+
await appendTeamEvent(sanitized, {
|
|
912
|
+
type: 'ralph_cleanup_policy',
|
|
913
|
+
worker: 'leader-fixed',
|
|
914
|
+
reason: `gate_bypassed:pending=${gate.pending},blocked=${gate.blocked},in_progress=${gate.in_progress},failed=${gate.failed}`,
|
|
915
|
+
}, cwd).catch(() => { });
|
|
916
|
+
}
|
|
917
|
+
else {
|
|
918
|
+
throw new Error(`shutdown_gate_blocked:pending=${gate.pending},blocked=${gate.blocked},in_progress=${gate.in_progress},failed=${gate.failed}`);
|
|
919
|
+
}
|
|
861
920
|
}
|
|
862
921
|
}
|
|
863
922
|
if (force) {
|
|
@@ -890,7 +949,9 @@ export async function shutdownTeam(teamName, cwd, options = {}) {
|
|
|
890
949
|
inboxCorrelationKey: `shutdown:${w.name}`,
|
|
891
950
|
});
|
|
892
951
|
}
|
|
893
|
-
catch {
|
|
952
|
+
catch (err) {
|
|
953
|
+
process.stderr.write(`[team/runtime] operation failed: ${err}\n`);
|
|
954
|
+
}
|
|
894
955
|
}
|
|
895
956
|
// 2. Wait up to 15s for workers to exit and collect acks
|
|
896
957
|
const deadline = Date.now() + 15_000;
|
|
@@ -954,25 +1015,21 @@ export async function shutdownTeam(teamName, cwd, options = {}) {
|
|
|
954
1015
|
if (resizeHookWarning) {
|
|
955
1016
|
console.warn(`[team shutdown] ${sanitized}: ${resizeHookWarning}; continuing teardown`);
|
|
956
1017
|
}
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
if (isWorkerAlive(sessionName, w.index, w.pane_id)) {
|
|
965
|
-
killWorker(sessionName, w.index, w.pane_id, leaderPaneId ?? undefined);
|
|
966
|
-
}
|
|
967
|
-
}
|
|
968
|
-
catch { /* ignore */ }
|
|
969
|
-
}
|
|
1018
|
+
const workerPaneIds = config.workers
|
|
1019
|
+
.map((w) => w.pane_id)
|
|
1020
|
+
.filter((paneId) => typeof paneId === 'string' && paneId.trim().length > 0);
|
|
1021
|
+
await teardownWorkerPanes(workerPaneIds, {
|
|
1022
|
+
leaderPaneId,
|
|
1023
|
+
hudPaneId,
|
|
1024
|
+
});
|
|
970
1025
|
// 4. Destroy tmux session
|
|
971
1026
|
if (!sessionName.includes(':')) {
|
|
972
1027
|
try {
|
|
973
1028
|
destroyTeamSession(sessionName);
|
|
974
1029
|
}
|
|
975
|
-
catch {
|
|
1030
|
+
catch (err) {
|
|
1031
|
+
process.stderr.write(`[team/runtime] operation failed: ${err}\n`);
|
|
1032
|
+
}
|
|
976
1033
|
}
|
|
977
1034
|
}
|
|
978
1035
|
else {
|
|
@@ -991,9 +1048,23 @@ export async function shutdownTeam(teamName, cwd, options = {}) {
|
|
|
991
1048
|
try {
|
|
992
1049
|
await removeTeamWorkerInstructionsFile(sanitized, cwd);
|
|
993
1050
|
}
|
|
994
|
-
catch {
|
|
1051
|
+
catch (err) {
|
|
1052
|
+
process.stderr.write(`[team/runtime] operation failed: ${err}\n`);
|
|
1053
|
+
}
|
|
995
1054
|
restoreTeamModelInstructionsFile(sanitized);
|
|
996
|
-
// 6.
|
|
1055
|
+
// 6. Ralph stricter completion logging
|
|
1056
|
+
if (ralph) {
|
|
1057
|
+
const finalTasks = await listTasks(sanitized, cwd).catch(() => []);
|
|
1058
|
+
const completed = finalTasks.filter((t) => t.status === 'completed').length;
|
|
1059
|
+
const failed = finalTasks.filter((t) => t.status === 'failed').length;
|
|
1060
|
+
const pending = finalTasks.filter((t) => t.status === 'pending').length;
|
|
1061
|
+
await appendTeamEvent(sanitized, {
|
|
1062
|
+
type: 'ralph_cleanup_summary',
|
|
1063
|
+
worker: 'leader-fixed',
|
|
1064
|
+
reason: `total=${finalTasks.length} completed=${completed} failed=${failed} pending=${pending} force=${force}`,
|
|
1065
|
+
}, cwd).catch(() => { });
|
|
1066
|
+
}
|
|
1067
|
+
// 7. Cleanup state
|
|
997
1068
|
await cleanupTeamState(sanitized, cwd);
|
|
998
1069
|
}
|
|
999
1070
|
/**
|
|
@@ -1016,7 +1087,8 @@ export async function resumeTeam(teamName, cwd) {
|
|
|
1016
1087
|
process.kill(worker.pid, 0);
|
|
1017
1088
|
return true;
|
|
1018
1089
|
}
|
|
1019
|
-
catch {
|
|
1090
|
+
catch (err) {
|
|
1091
|
+
process.stderr.write(`[team/runtime] operation failed: ${err}\n`);
|
|
1020
1092
|
return false;
|
|
1021
1093
|
}
|
|
1022
1094
|
})
|
|
@@ -1094,7 +1166,8 @@ async function resolveLeaderSessionId(cwd) {
|
|
|
1094
1166
|
if (typeof parsed.session_id === 'string' && parsed.session_id.trim() !== '')
|
|
1095
1167
|
return parsed.session_id.trim();
|
|
1096
1168
|
}
|
|
1097
|
-
catch {
|
|
1169
|
+
catch (err) {
|
|
1170
|
+
process.stderr.write(`[team/runtime] operation failed: ${err}\n`);
|
|
1098
1171
|
return '';
|
|
1099
1172
|
}
|
|
1100
1173
|
return '';
|
|
@@ -1144,7 +1217,7 @@ async function emitMonitorDerivedEvents(teamName, tasks, workers, previous, cwd)
|
|
|
1144
1217
|
}
|
|
1145
1218
|
}
|
|
1146
1219
|
}
|
|
1147
|
-
function notifyWorkerOutcome(config, workerIndex, message, workerPaneId) {
|
|
1220
|
+
async function notifyWorkerOutcome(config, workerIndex, message, workerPaneId) {
|
|
1148
1221
|
const worker = config.workers.find((candidate) => candidate.index === workerIndex);
|
|
1149
1222
|
if (!worker)
|
|
1150
1223
|
return { ok: false, transport: 'none', reason: 'worker_not_found' };
|
|
@@ -1168,7 +1241,7 @@ function notifyWorkerOutcome(config, workerIndex, message, workerPaneId) {
|
|
|
1168
1241
|
return { ok: false, transport: 'tmux_send_keys', reason: 'tmux_unavailable' };
|
|
1169
1242
|
}
|
|
1170
1243
|
try {
|
|
1171
|
-
sendToWorker(config.tmux_session, workerIndex, message, workerPaneId, worker.worker_cli);
|
|
1244
|
+
await sendToWorker(config.tmux_session, workerIndex, message, workerPaneId, worker.worker_cli);
|
|
1172
1245
|
return { ok: true, transport: 'tmux_send_keys', reason: 'tmux_send_keys_sent' };
|
|
1173
1246
|
}
|
|
1174
1247
|
catch (error) {
|
|
@@ -1240,7 +1313,7 @@ async function dispatchCriticalInboxInstruction(params) {
|
|
|
1240
1313
|
return { ok: true, transport: 'hook', reason: `hook_receipt_${receipt.status}`, request_id: queued.request_id };
|
|
1241
1314
|
}
|
|
1242
1315
|
if (receipt?.status === 'failed') {
|
|
1243
|
-
const fallback = notifyWorkerOutcome(config, workerIndex, triggerMessage, paneId);
|
|
1316
|
+
const fallback = await notifyWorkerOutcome(config, workerIndex, triggerMessage, paneId);
|
|
1244
1317
|
if (fallback.ok) {
|
|
1245
1318
|
await transitionDispatchRequest(teamName, queued.request_id, 'failed', 'failed', { last_reason: `fallback_confirmed_after_failed_receipt:${fallback.reason}` }, cwd).catch(() => { });
|
|
1246
1319
|
return {
|
|
@@ -1258,7 +1331,7 @@ async function dispatchCriticalInboxInstruction(params) {
|
|
|
1258
1331
|
request_id: queued.request_id,
|
|
1259
1332
|
};
|
|
1260
1333
|
}
|
|
1261
|
-
const fallback = notifyWorkerOutcome(config, workerIndex, triggerMessage, paneId);
|
|
1334
|
+
const fallback = await notifyWorkerOutcome(config, workerIndex, triggerMessage, paneId);
|
|
1262
1335
|
if (fallback.ok) {
|
|
1263
1336
|
const marked = await markDispatchRequestNotified(teamName, queued.request_id, { last_reason: `fallback_confirmed:${fallback.reason}` }, cwd);
|
|
1264
1337
|
if (!marked) {
|
|
@@ -1293,9 +1366,9 @@ async function finalizeHookPreferredMailboxDispatch(params) {
|
|
|
1293
1366
|
return { ok: true, transport: 'hook', reason: `hook_receipt_${receipt.status}`, request_id: requestId, message_id: messageId };
|
|
1294
1367
|
}
|
|
1295
1368
|
const fallback = fallbackNotify
|
|
1296
|
-
? fallbackNotify()
|
|
1369
|
+
? await fallbackNotify()
|
|
1297
1370
|
: (typeof workerIndex === 'number'
|
|
1298
|
-
? notifyWorkerOutcome(config, workerIndex, triggerMessage, paneId)
|
|
1371
|
+
? await notifyWorkerOutcome(config, workerIndex, triggerMessage, paneId)
|
|
1299
1372
|
: { ok: false, transport: 'none', reason: 'missing_worker_index' });
|
|
1300
1373
|
if (receipt?.status === 'failed') {
|
|
1301
1374
|
if (fallback.ok) {
|
|
@@ -1344,10 +1417,25 @@ async function finalizeHookPreferredMailboxDispatch(params) {
|
|
|
1344
1417
|
message_id: messageId,
|
|
1345
1418
|
};
|
|
1346
1419
|
}
|
|
1347
|
-
function
|
|
1420
|
+
async function notifyLeaderAsync(config, message, cwd) {
|
|
1421
|
+
// Primary: inject directly into the leader pane via tmux send-keys.
|
|
1422
|
+
// This is the fallback path when hook-based dispatch timed out, so the
|
|
1423
|
+
// leader needs a direct tmux notification to wake up. Fixes #437.
|
|
1424
|
+
if (config.leader_pane_id && isTmuxAvailable()) {
|
|
1425
|
+
try {
|
|
1426
|
+
await sendToLeaderPane(config.leader_pane_id, message);
|
|
1427
|
+
return true;
|
|
1428
|
+
}
|
|
1429
|
+
catch (err) {
|
|
1430
|
+
process.stderr.write(`[team/runtime] operation failed: ${err}\n`);
|
|
1431
|
+
// Fall through to mailbox
|
|
1432
|
+
}
|
|
1433
|
+
}
|
|
1434
|
+
// Fallback: write to leader mailbox (leader picks up on next hook cycle)
|
|
1348
1435
|
if (!config.tmux_session)
|
|
1349
1436
|
return false;
|
|
1350
|
-
|
|
1437
|
+
const { notifyLeaderMailboxAsync } = await import('./tmux-session.js');
|
|
1438
|
+
return notifyLeaderMailboxAsync(config.name, 'system', message, cwd);
|
|
1351
1439
|
}
|
|
1352
1440
|
async function deliverPendingMailboxMessages(teamName, config, workers, previousNotifications, dispatchPolicy, cwd) {
|
|
1353
1441
|
const nextNotifications = {};
|
|
@@ -1410,7 +1498,7 @@ async function deliverPendingMailboxMessages(teamName, config, workers, previous
|
|
|
1410
1498
|
});
|
|
1411
1499
|
}
|
|
1412
1500
|
else {
|
|
1413
|
-
const direct = notifyWorkerOutcome(config, workerInfo.index, triggerMessage, workerInfo.pane_id);
|
|
1501
|
+
const direct = await notifyWorkerOutcome(config, workerInfo.index, triggerMessage, workerInfo.pane_id);
|
|
1414
1502
|
outcome = { ...direct, request_id: queued.request.request_id, message_id: msg.message_id };
|
|
1415
1503
|
if (outcome.ok) {
|
|
1416
1504
|
await markMessageNotified(teamName, worker.name, msg.message_id, cwd).catch(() => false);
|
|
@@ -1451,9 +1539,9 @@ export async function sendWorkerMessage(teamName, fromWorker, toWorker, body, cw
|
|
|
1451
1539
|
cwd,
|
|
1452
1540
|
transportPreference: leaderTransportPreference,
|
|
1453
1541
|
fallbackAllowed: leaderTransportPreference === 'hook_preferred_with_fallback',
|
|
1454
|
-
notify: (_target, message) => (leaderTransportPreference === 'hook_preferred_with_fallback'
|
|
1542
|
+
notify: async (_target, message) => (leaderTransportPreference === 'hook_preferred_with_fallback'
|
|
1455
1543
|
? { ok: true, transport: 'hook', reason: 'queued_for_hook_dispatch' }
|
|
1456
|
-
: { ok:
|
|
1544
|
+
: { ok: await notifyLeaderAsync(config, message, cwd), transport: 'mailbox', reason: 'leader_mailbox_notified' }),
|
|
1457
1545
|
});
|
|
1458
1546
|
let finalOutcome = outcome;
|
|
1459
1547
|
const canLeaderFallbackDirectly = Boolean(config.leader_pane_id) && isTmuxAvailable();
|
|
@@ -1471,10 +1559,10 @@ export async function sendWorkerMessage(teamName, fromWorker, toWorker, body, cw
|
|
|
1471
1559
|
config,
|
|
1472
1560
|
dispatchPolicy,
|
|
1473
1561
|
cwd,
|
|
1474
|
-
fallbackNotify: () => ({
|
|
1475
|
-
ok:
|
|
1476
|
-
transport: '
|
|
1477
|
-
reason: '
|
|
1562
|
+
fallbackNotify: async () => ({
|
|
1563
|
+
ok: await notifyLeaderAsync(config, leaderTriggerMessage, cwd),
|
|
1564
|
+
transport: 'mailbox',
|
|
1565
|
+
reason: 'leader_mailbox_notified',
|
|
1478
1566
|
}),
|
|
1479
1567
|
});
|
|
1480
1568
|
}
|
|
@@ -1500,9 +1588,9 @@ export async function sendWorkerMessage(teamName, fromWorker, toWorker, body, cw
|
|
|
1500
1588
|
cwd,
|
|
1501
1589
|
transportPreference,
|
|
1502
1590
|
fallbackAllowed: transportPreference === 'hook_preferred_with_fallback',
|
|
1503
|
-
notify: (_target, message) => (transportPreference === 'hook_preferred_with_fallback'
|
|
1591
|
+
notify: async (_target, message) => (transportPreference === 'hook_preferred_with_fallback'
|
|
1504
1592
|
? { ok: true, transport: 'hook', reason: 'queued_for_hook_dispatch' }
|
|
1505
|
-
: notifyWorkerOutcome(config, recipient.index, message, recipient.pane_id)),
|
|
1593
|
+
: await notifyWorkerOutcome(config, recipient.index, message, recipient.pane_id)),
|
|
1506
1594
|
});
|
|
1507
1595
|
let finalOutcome = outcome;
|
|
1508
1596
|
if (transportPreference === 'hook_preferred_with_fallback') {
|
|
@@ -1544,10 +1632,10 @@ export async function broadcastWorkerMessage(teamName, fromWorker, body, cwd) {
|
|
|
1544
1632
|
triggerFor: (workerName) => generateMailboxTriggerMessage(workerName, sanitized, 1),
|
|
1545
1633
|
transportPreference,
|
|
1546
1634
|
fallbackAllowed: transportPreference === 'hook_preferred_with_fallback',
|
|
1547
|
-
notify: (target, message) => transportPreference === 'hook_preferred_with_fallback'
|
|
1635
|
+
notify: async (target, message) => transportPreference === 'hook_preferred_with_fallback'
|
|
1548
1636
|
? { ok: true, transport: 'hook', reason: 'queued_for_hook_dispatch' }
|
|
1549
1637
|
: (typeof target.workerIndex === 'number'
|
|
1550
|
-
? notifyWorkerOutcome(config, target.workerIndex, message, target.paneId)
|
|
1638
|
+
? await notifyWorkerOutcome(config, target.workerIndex, message, target.paneId)
|
|
1551
1639
|
: { ok: false, transport: 'none', reason: 'missing_worker_index' }),
|
|
1552
1640
|
});
|
|
1553
1641
|
const finalizedOutcomes = [];
|