triflux 10.3.4 → 10.7.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.
Files changed (329) hide show
  1. package/LICENSE +21 -21
  2. package/bin/tfx-doctor-tui.mjs +1 -1
  3. package/bin/tfx-doctor.mjs +6 -1
  4. package/bin/tfx-profile.mjs +1 -1
  5. package/bin/tfx-setup-tui.mjs +1 -1
  6. package/bin/tfx-setup.mjs +6 -1
  7. package/bin/triflux.mjs +2396 -1140
  8. package/hooks/agent-route-guard.mjs +12 -8
  9. package/hooks/cross-review-tracker.mjs +21 -8
  10. package/hooks/error-context.mjs +19 -7
  11. package/hooks/hook-adaptive-collector.mjs +18 -16
  12. package/hooks/hook-manager.mjs +93 -32
  13. package/hooks/hook-orchestrator.mjs +108 -24
  14. package/hooks/hook-registry.json +11 -0
  15. package/hooks/keyword-rules.json +6 -10
  16. package/hooks/lib/resolve-root.mjs +1 -1
  17. package/hooks/mcp-config-watcher.mjs +6 -2
  18. package/hooks/pipeline-stop.mjs +3 -6
  19. package/hooks/safety-guard.mjs +99 -28
  20. package/hooks/session-start-fast.mjs +143 -0
  21. package/hooks/subagent-verifier.mjs +5 -4
  22. package/hub/account-broker.mjs +256 -60
  23. package/hub/adaptive-diagnostic.mjs +75 -48
  24. package/hub/adaptive-inject.mjs +95 -57
  25. package/hub/adaptive-memory.mjs +156 -42
  26. package/hub/adaptive.mjs +60 -31
  27. package/hub/assign-callbacks.mjs +67 -30
  28. package/hub/bridge.mjs +0 -1
  29. package/hub/cli-adapter-base.mjs +200 -48
  30. package/hub/codex-adapter.mjs +76 -96
  31. package/hub/codex-compat.mjs +3 -3
  32. package/hub/codex-preflight.mjs +63 -37
  33. package/hub/delegator/contracts.mjs +19 -23
  34. package/hub/delegator/index.mjs +3 -3
  35. package/hub/delegator/service.mjs +88 -64
  36. package/hub/delegator/tool-definitions.mjs +5 -5
  37. package/hub/fullcycle.mjs +33 -17
  38. package/hub/gemini-adapter.mjs +69 -94
  39. package/hub/hitl.mjs +89 -30
  40. package/hub/intent.mjs +161 -38
  41. package/hub/lib/cache-guard.mjs +43 -17
  42. package/hub/lib/mcp-response-cache.mjs +66 -32
  43. package/hub/lib/memory-store.mjs +285 -111
  44. package/hub/lib/path-utils.mjs +35 -37
  45. package/hub/lib/process-utils.mjs +106 -37
  46. package/hub/lib/spawn-trace.mjs +527 -0
  47. package/hub/lib/ssh-command.mjs +34 -4
  48. package/hub/lib/ssh-retry.mjs +5 -1
  49. package/hub/lib/uuidv7.mjs +4 -3
  50. package/hub/memory-doctor.mjs +266 -106
  51. package/hub/middleware/request-logger.mjs +61 -34
  52. package/hub/paths.mjs +9 -9
  53. package/hub/pipeline/gates/confidence.mjs +34 -15
  54. package/hub/pipeline/gates/consensus.mjs +27 -15
  55. package/hub/pipeline/gates/index.mjs +7 -3
  56. package/hub/pipeline/gates/selfcheck.mjs +57 -19
  57. package/hub/pipeline/index.mjs +77 -42
  58. package/hub/pipeline/state.mjs +10 -10
  59. package/hub/pipeline/transitions.mjs +40 -23
  60. package/hub/platform.mjs +57 -48
  61. package/hub/promote-penalties.mjs +25 -7
  62. package/hub/quality/deslop.mjs +70 -49
  63. package/hub/research.mjs +32 -25
  64. package/hub/router.mjs +240 -107
  65. package/hub/routing/complexity.mjs +132 -29
  66. package/hub/routing/index.mjs +17 -12
  67. package/hub/routing/q-learning.mjs +76 -28
  68. package/hub/server.mjs +4 -4
  69. package/hub/session-fingerprint.mjs +126 -60
  70. package/hub/state.mjs +84 -43
  71. package/hub/store-adapter.mjs +59 -26
  72. package/hub/store.mjs +356 -153
  73. package/hub/team/agent-map.json +22 -7
  74. package/hub/team/ansi.mjs +186 -122
  75. package/hub/team/backend.mjs +28 -10
  76. package/hub/team/cli/commands/attach.mjs +29 -9
  77. package/hub/team/cli/commands/control.mjs +29 -8
  78. package/hub/team/cli/commands/debug.mjs +32 -11
  79. package/hub/team/cli/commands/focus.mjs +38 -11
  80. package/hub/team/cli/commands/interrupt.mjs +18 -6
  81. package/hub/team/cli/commands/kill.mjs +16 -5
  82. package/hub/team/cli/commands/list.mjs +11 -4
  83. package/hub/team/cli/commands/send.mjs +19 -6
  84. package/hub/team/cli/commands/start/index.mjs +154 -31
  85. package/hub/team/cli/commands/start/parse-args.mjs +38 -11
  86. package/hub/team/cli/commands/start/start-headless.mjs +112 -36
  87. package/hub/team/cli/commands/start/start-in-process.mjs +12 -2
  88. package/hub/team/cli/commands/start/start-mux.mjs +70 -21
  89. package/hub/team/cli/commands/start/start-wt.mjs +29 -12
  90. package/hub/team/cli/commands/status.mjs +43 -14
  91. package/hub/team/cli/commands/stop.mjs +11 -4
  92. package/hub/team/cli/commands/task.mjs +8 -3
  93. package/hub/team/cli/commands/tasks.mjs +1 -1
  94. package/hub/team/cli/index.mjs +2 -2
  95. package/hub/team/cli/manifest.mjs +38 -8
  96. package/hub/team/cli/render.mjs +30 -8
  97. package/hub/team/cli/services/attach-fallback.mjs +31 -11
  98. package/hub/team/cli/services/hub-client.mjs +42 -14
  99. package/hub/team/cli/services/member-selector.mjs +11 -4
  100. package/hub/team/cli/services/native-control.mjs +48 -21
  101. package/hub/team/cli/services/runtime-mode.mjs +2 -1
  102. package/hub/team/cli/services/state-store.mjs +25 -8
  103. package/hub/team/cli/services/task-model.mjs +16 -6
  104. package/hub/team/conductor-mesh-bridge.mjs +24 -23
  105. package/hub/team/conductor.mjs +8 -4
  106. package/hub/team/dashboard-anchor.mjs +4 -5
  107. package/hub/team/dashboard-layout.mjs +3 -1
  108. package/hub/team/dashboard-open.mjs +41 -21
  109. package/hub/team/dashboard.mjs +76 -28
  110. package/hub/team/event-log.mjs +18 -10
  111. package/hub/team/handoff.mjs +31 -15
  112. package/hub/team/headless.mjs +2 -1
  113. package/hub/team/health-probe.mjs +69 -54
  114. package/hub/team/launcher-template.mjs +16 -13
  115. package/hub/team/native-supervisor.mjs +65 -21
  116. package/hub/team/native.mjs +74 -35
  117. package/hub/team/nativeProxy.mjs +184 -113
  118. package/hub/team/notify.mjs +119 -76
  119. package/hub/team/orchestrator.mjs +9 -4
  120. package/hub/team/pane.mjs +12 -7
  121. package/hub/team/process-cleanup.mjs +25 -16
  122. package/hub/team/psmux.mjs +491 -201
  123. package/hub/team/remote-probe.mjs +68 -52
  124. package/hub/team/remote-session.mjs +117 -59
  125. package/hub/team/remote-watcher.mjs +61 -33
  126. package/hub/team/routing.mjs +51 -25
  127. package/hub/team/runtime-strategy.mjs +3 -1
  128. package/hub/team/session.mjs +98 -34
  129. package/hub/team/staleState.mjs +72 -30
  130. package/hub/team/swarm-locks.mjs +15 -13
  131. package/hub/team/swarm-planner.mjs +32 -21
  132. package/hub/team/swarm-reconciler.mjs +48 -23
  133. package/hub/team/tui-lite.mjs +266 -68
  134. package/hub/team/tui-remote-adapter.mjs +14 -10
  135. package/hub/team/tui-viewer.mjs +99 -43
  136. package/hub/team/tui.mjs +708 -271
  137. package/hub/team/worktree-lifecycle.mjs +152 -58
  138. package/hub/team/wt-manager.mjs +24 -14
  139. package/hub/token-mode.mjs +71 -71
  140. package/hub/tray.mjs +66 -23
  141. package/hub/workers/claude-worker.mjs +162 -118
  142. package/hub/workers/codex-mcp.mjs +192 -141
  143. package/hub/workers/delegator-mcp.mjs +507 -333
  144. package/hub/workers/factory.mjs +8 -8
  145. package/hub/workers/gemini-worker.mjs +115 -84
  146. package/hub/workers/interface.mjs +6 -1
  147. package/hub/workers/worker-utils.mjs +21 -14
  148. package/hud/colors.mjs +27 -9
  149. package/hud/constants.mjs +162 -26
  150. package/hud/context-monitor.mjs +82 -41
  151. package/hud/hud-qos-status.mjs +129 -49
  152. package/hud/mission-board.mjs +6 -3
  153. package/hud/providers/claude.mjs +226 -115
  154. package/hud/providers/codex.mjs +62 -22
  155. package/hud/providers/gemini.mjs +168 -56
  156. package/hud/renderers.mjs +384 -119
  157. package/hud/terminal.mjs +101 -31
  158. package/hud/utils.mjs +78 -38
  159. package/mesh/index.mjs +11 -5
  160. package/mesh/mesh-budget.mjs +18 -9
  161. package/mesh/mesh-heartbeat.mjs +1 -1
  162. package/mesh/mesh-queue.mjs +3 -5
  163. package/mesh/mesh-router.mjs +5 -4
  164. package/package.json +2 -1
  165. package/scripts/__tests__/gen-skill-docs.test.mjs +36 -7
  166. package/scripts/__tests__/keyword-detector.test.mjs +77 -28
  167. package/scripts/__tests__/mcp-guard-engine.test.mjs +58 -20
  168. package/scripts/__tests__/remote-spawn-transfer.test.mjs +30 -19
  169. package/scripts/__tests__/remote-spawn.test.mjs +10 -4
  170. package/scripts/__tests__/session-start-fast.test.mjs +36 -0
  171. package/scripts/__tests__/skill-template.test.mjs +98 -50
  172. package/scripts/__tests__/smoke.test.mjs +1 -1
  173. package/scripts/__tests__/spawn-trace.test.mjs +102 -0
  174. package/scripts/__tests__/tfx-doctor-diagnose.test.mjs +48 -0
  175. package/scripts/cache-doctor.mjs +11 -4
  176. package/scripts/cache-warmup.mjs +96 -37
  177. package/scripts/claudemd-sync.mjs +27 -17
  178. package/scripts/codex-gateway-preflight.mjs +52 -37
  179. package/scripts/codex-mcp-gateway-sync.mjs +59 -39
  180. package/scripts/completions/tfx.bash +47 -47
  181. package/scripts/completions/tfx.fish +44 -44
  182. package/scripts/completions/tfx.zsh +83 -83
  183. package/scripts/config-audit.mjs +232 -0
  184. package/scripts/convert-to-tmpl.mjs +54 -0
  185. package/scripts/cross-review-gate.mjs +35 -12
  186. package/scripts/cross-review-tracker.mjs +21 -8
  187. package/scripts/demo.mjs +35 -17
  188. package/scripts/doctor-diagnose.mjs +284 -0
  189. package/scripts/gen-skill-docs.mjs +7 -2
  190. package/scripts/gen-skill-manifest.mjs +2 -1
  191. package/scripts/headless-guard.mjs +86 -48
  192. package/scripts/hub-ensure.mjs +45 -26
  193. package/scripts/keyword-detector.mjs +41 -20
  194. package/scripts/keyword-rules-expander.mjs +47 -30
  195. package/scripts/lib/claudemd-scanner.mjs +6 -1
  196. package/scripts/lib/context.mjs +3 -3
  197. package/scripts/lib/cross-review-utils.mjs +6 -3
  198. package/scripts/lib/env-probe.mjs +47 -28
  199. package/scripts/lib/gemini-profiles.mjs +44 -10
  200. package/scripts/lib/handoff.mjs +33 -17
  201. package/scripts/lib/hook-utils.mjs +8 -6
  202. package/scripts/lib/keyword-rules.mjs +43 -19
  203. package/scripts/lib/logger.mjs +24 -24
  204. package/scripts/lib/mcp-filter.mjs +377 -239
  205. package/scripts/lib/mcp-guard-engine.mjs +194 -79
  206. package/scripts/lib/mcp-manifest.mjs +23 -13
  207. package/scripts/lib/mcp-server-catalog.mjs +300 -63
  208. package/scripts/lib/psmux-info.mjs +11 -6
  209. package/scripts/lib/remote-spawn-transfer.mjs +44 -14
  210. package/scripts/lib/skill-template.mjs +30 -7
  211. package/scripts/mcp-check.mjs +58 -39
  212. package/scripts/mcp-gateway-config.mjs +83 -39
  213. package/scripts/mcp-gateway-ensure.mjs +43 -35
  214. package/scripts/mcp-gateway-integration-test.mjs +70 -58
  215. package/scripts/mcp-gateway-start.mjs +126 -60
  216. package/scripts/mcp-gateway-verify.mjs +24 -22
  217. package/scripts/mcp-safety-guard.mjs +44 -11
  218. package/scripts/notion-read.mjs +199 -84
  219. package/scripts/pack.mjs +94 -89
  220. package/scripts/preflight-cache.mjs +27 -10
  221. package/scripts/preinstall.mjs +42 -13
  222. package/scripts/remote-spawn.mjs +309 -94
  223. package/scripts/run.cjs +8 -5
  224. package/scripts/session-spawn-helper.mjs +130 -39
  225. package/scripts/session-stale-cleanup.mjs +123 -0
  226. package/scripts/setup.mjs +941 -492
  227. package/scripts/test-lock.mjs +20 -7
  228. package/scripts/test-tfx-route-no-claude-native.mjs +16 -12
  229. package/scripts/tfx-batch-stats.mjs +32 -11
  230. package/scripts/tfx-gate-activate.mjs +11 -4
  231. package/scripts/tfx-route-post.mjs +87 -20
  232. package/scripts/tfx-route-worker.mjs +57 -51
  233. package/scripts/tfx-route.sh +41 -124
  234. package/scripts/tmp-cleanup.mjs +21 -7
  235. package/scripts/token-snapshot.mjs +204 -85
  236. package/skills/.omc/state/agent-replay-8f0e10a9-9693-4410-96f5-a6b07e8ed995.jsonl +1 -0
  237. package/skills/.omc/state/idle-notif-cooldown.json +3 -0
  238. package/skills/.omc/state/last-tool-error.json +7 -0
  239. package/skills/.omc/state/subagent-tracking.json +7 -0
  240. package/skills/_templates/base.md +1 -6
  241. package/skills/merge-worktree/SKILL.md.tmpl +144 -0
  242. package/skills/shared/telemetry-segment.md +6 -0
  243. package/skills/star-prompt/SKILL.md.tmpl +222 -0
  244. package/skills/tfx-analysis/SKILL.md.tmpl +107 -0
  245. package/skills/tfx-analysis/skill.json +1 -6
  246. package/skills/tfx-auto/SKILL.md +1 -0
  247. package/skills/tfx-auto-codex/SKILL.md.tmpl +106 -0
  248. package/skills/tfx-auto-codex/skill.json +1 -3
  249. package/skills/tfx-autopilot/SKILL.md.tmpl +116 -0
  250. package/skills/tfx-autopilot/skill.json +1 -5
  251. package/skills/tfx-autoresearch/SKILL.md.tmpl +136 -0
  252. package/skills/tfx-autoroute/SKILL.md.tmpl +189 -0
  253. package/skills/tfx-autoroute/skill.json +1 -7
  254. package/skills/tfx-codex/SKILL.md +1 -0
  255. package/skills/tfx-codex/skill.json +1 -3
  256. package/skills/tfx-codex-swarm/SKILL.md.tmpl +16 -0
  257. package/skills/tfx-codex-swarm/evals/evals.json +1 -1
  258. package/skills/tfx-codex-swarm/skill.json +1 -4
  259. package/skills/tfx-codex-swarm-workspace/iteration-1/benchmark.json +54 -12
  260. package/skills/tfx-codex-swarm-workspace/iteration-1/full-swarm-all-prds/with_skill/grading.json +35 -7
  261. package/skills/tfx-codex-swarm-workspace/iteration-1/full-swarm-all-prds/without_skill/grading.json +35 -7
  262. package/skills/tfx-codex-swarm-workspace/iteration-1/implicit-swarm-no-keywords/with_skill/grading.json +25 -5
  263. package/skills/tfx-codex-swarm-workspace/iteration-1/implicit-swarm-no-keywords/without_skill/grading.json +25 -5
  264. package/skills/tfx-codex-swarm-workspace/iteration-1/selective-spawn-with-override/with_skill/grading.json +20 -4
  265. package/skills/tfx-codex-swarm-workspace/iteration-1/selective-spawn-with-override/without_skill/grading.json +16 -4
  266. package/skills/tfx-consensus/SKILL.md.tmpl +146 -0
  267. package/skills/tfx-debate/SKILL.md.tmpl +192 -0
  268. package/skills/tfx-debate/skill.json +1 -7
  269. package/skills/tfx-deep-analysis/SKILL.md.tmpl +228 -0
  270. package/skills/tfx-deep-analysis/skill.json +1 -5
  271. package/skills/tfx-deep-interview/SKILL.md.tmpl +203 -0
  272. package/skills/tfx-deep-plan/SKILL.md.tmpl +282 -0
  273. package/skills/tfx-deep-qa/SKILL.md.tmpl +165 -0
  274. package/skills/tfx-deep-qa/skill.json +1 -6
  275. package/skills/tfx-deep-research/SKILL.md.tmpl +217 -0
  276. package/skills/tfx-deep-review/SKILL.md.tmpl +179 -0
  277. package/skills/tfx-doctor/SKILL.md +21 -0
  278. package/skills/tfx-doctor/SKILL.md.tmpl +172 -0
  279. package/skills/tfx-doctor/skill.json +1 -3
  280. package/skills/tfx-find/SKILL.md +1 -0
  281. package/skills/tfx-forge/SKILL.md.tmpl +187 -0
  282. package/skills/tfx-fullcycle/SKILL.md.tmpl +286 -0
  283. package/skills/tfx-fullcycle/skill.json +1 -6
  284. package/skills/tfx-gemini/SKILL.md.tmpl +91 -0
  285. package/skills/tfx-gemini/skill.json +1 -3
  286. package/skills/tfx-hooks/SKILL.md.tmpl +216 -0
  287. package/skills/tfx-hooks/skill.json +1 -3
  288. package/skills/tfx-hub/SKILL.md.tmpl +212 -0
  289. package/skills/tfx-hub/skill.json +1 -3
  290. package/skills/tfx-index/SKILL.md +1 -0
  291. package/skills/tfx-index/skill.json +1 -6
  292. package/skills/tfx-interview/SKILL.md.tmpl +285 -0
  293. package/skills/tfx-multi/SKILL.md.tmpl +183 -0
  294. package/skills/tfx-multi/skill.json +1 -3
  295. package/skills/tfx-panel/SKILL.md.tmpl +189 -0
  296. package/skills/tfx-panel/skill.json +1 -7
  297. package/skills/tfx-persist/SKILL.md.tmpl +270 -0
  298. package/skills/tfx-persist/skill.json +1 -7
  299. package/skills/tfx-plan/SKILL.md +1 -0
  300. package/skills/tfx-plan/skill.json +1 -6
  301. package/skills/tfx-profile/SKILL.md.tmpl +239 -0
  302. package/skills/tfx-profile/skill.json +1 -3
  303. package/skills/tfx-prune/SKILL.md.tmpl +200 -0
  304. package/skills/tfx-prune/skill.json +1 -7
  305. package/skills/tfx-psmux-rules/SKILL.md.tmpl +326 -0
  306. package/skills/tfx-psmux-rules/skill.json +1 -4
  307. package/skills/tfx-qa/SKILL.md +1 -0
  308. package/skills/tfx-qa/skill.json +1 -6
  309. package/skills/tfx-ralph/SKILL.md.tmpl +28 -0
  310. package/skills/tfx-ralph/skill.json +1 -4
  311. package/skills/tfx-remote-setup/SKILL.md.tmpl +576 -0
  312. package/skills/tfx-remote-setup/skill.json +1 -3
  313. package/skills/tfx-remote-spawn/SKILL.md.tmpl +263 -0
  314. package/skills/tfx-remote-spawn/references/hosts.json +16 -0
  315. package/skills/tfx-remote-spawn/skill.json +1 -4
  316. package/skills/tfx-research/SKILL.md +1 -0
  317. package/skills/tfx-review/SKILL.md +1 -0
  318. package/skills/tfx-review/skill.json +1 -6
  319. package/skills/tfx-setup/SKILL.md.tmpl +504 -0
  320. package/skills/tfx-setup/skill.json +1 -3
  321. package/skills/tfx-swarm/SKILL.md +22 -0
  322. package/skills/tfx-swarm/SKILL.md.tmpl +218 -0
  323. package/tui/codex-profile.mjs +88 -33
  324. package/tui/core.mjs +45 -15
  325. package/tui/doctor.mjs +75 -28
  326. package/tui/gemini-profile.mjs +74 -29
  327. package/tui/monitor-data.mjs +8 -4
  328. package/tui/monitor.mjs +71 -27
  329. package/tui/setup.mjs +133 -42
@@ -1,8 +1,11 @@
1
1
  import { DIM, RESET, WHITE } from "../../shared.mjs";
2
+ import { ok } from "../render.mjs";
2
3
  import { isTeamAlive } from "../services/runtime-mode.mjs";
3
4
  import { loadTeamState, saveTeamState } from "../services/state-store.mjs";
4
- import { normalizeTaskStatus, updateTaskStatus } from "../services/task-model.mjs";
5
- import { ok } from "../render.mjs";
5
+ import {
6
+ normalizeTaskStatus,
7
+ updateTaskStatus,
8
+ } from "../services/task-model.mjs";
6
9
 
7
10
  export function teamTaskUpdate(args = []) {
8
11
  const state = loadTeamState();
@@ -14,7 +17,9 @@ export function teamTaskUpdate(args = []) {
14
17
  const nextStatus = normalizeTaskStatus(args[0]);
15
18
  const taskId = String(args[1] || "").toUpperCase();
16
19
  if (!nextStatus || !taskId) {
17
- console.log(`\n 사용법: ${WHITE}tfx multi task <pending|progress|done> <T1>${RESET}\n`);
20
+ console.log(
21
+ `\n 사용법: ${WHITE}tfx multi task <pending|progress|done> <T1>${RESET}\n`,
22
+ );
18
23
  return;
19
24
  }
20
25
 
@@ -1,7 +1,7 @@
1
1
  import { DIM, RESET } from "../../shared.mjs";
2
+ import { renderTasks } from "../render.mjs";
2
3
  import { isTeamAlive } from "../services/runtime-mode.mjs";
3
4
  import { loadTeamState } from "../services/state-store.mjs";
4
- import { renderTasks } from "../render.mjs";
5
5
 
6
6
  export function teamTasks() {
7
7
  const state = loadTeamState();
@@ -1,5 +1,3 @@
1
- import { renderTeamHelp } from "./help.mjs";
2
- import { resolveTeamCommand } from "./manifest.mjs";
3
1
  import { teamAttach } from "./commands/attach.mjs";
4
2
  import { teamControl } from "./commands/control.mjs";
5
3
  import { teamDebug } from "./commands/debug.mjs";
@@ -13,6 +11,8 @@ import { teamStatus } from "./commands/status.mjs";
13
11
  import { teamStop } from "./commands/stop.mjs";
14
12
  import { teamTaskUpdate } from "./commands/task.mjs";
15
13
  import { teamTasks } from "./commands/tasks.mjs";
14
+ import { renderTeamHelp } from "./help.mjs";
15
+ import { resolveTeamCommand } from "./manifest.mjs";
16
16
 
17
17
  const handlers = {
18
18
  attach: teamAttach,
@@ -1,18 +1,46 @@
1
1
  export const TEAM_COMMANDS = [
2
2
  { name: "status", usage: "tfx multi status", desc: "현재 팀 상태" },
3
- { name: "debug", usage: "tfx multi debug [--lines 30]", desc: "강화 디버그 출력" },
3
+ {
4
+ name: "debug",
5
+ usage: "tfx multi debug [--lines 30]",
6
+ desc: "강화 디버그 출력",
7
+ },
4
8
  { name: "tasks", usage: "tfx multi tasks", desc: "공유 태스크 목록" },
5
- { name: "task", usage: "tfx multi task <pending|progress|done> <T1>", desc: "태스크 상태 갱신" },
9
+ {
10
+ name: "task",
11
+ usage: "tfx multi task <pending|progress|done> <T1>",
12
+ desc: "태스크 상태 갱신",
13
+ },
6
14
  { name: "attach", usage: "tfx multi attach [--wt]", desc: "세션 재연결" },
7
- { name: "focus", usage: "tfx multi focus <lead|이름|번호> [--wt]", desc: "특정 팀메이트 포커스" },
8
- { name: "send", usage: "tfx multi send <lead|이름|번호> \"msg\"", desc: "팀메이트에 메시지 주입" },
9
- { name: "interrupt", usage: "tfx multi interrupt <대상>", desc: "팀메이트 인터럽트(C-c)" },
10
- { name: "control", usage: "tfx multi control <대상> <cmd> [사유]", desc: "리드 제어명령 전송" },
15
+ {
16
+ name: "focus",
17
+ usage: "tfx multi focus <lead|이름|번호> [--wt]",
18
+ desc: "특정 팀메이트 포커스",
19
+ },
20
+ {
21
+ name: "send",
22
+ usage: 'tfx multi send <lead|이름|번호> "msg"',
23
+ desc: "팀메이트에 메시지 주입",
24
+ },
25
+ {
26
+ name: "interrupt",
27
+ usage: "tfx multi interrupt <대상>",
28
+ desc: "팀메이트 인터럽트(C-c)",
29
+ },
30
+ {
31
+ name: "control",
32
+ usage: "tfx multi control <대상> <cmd> [사유]",
33
+ desc: "리드 제어명령 전송",
34
+ },
11
35
  { name: "stop", usage: "tfx multi stop", desc: "graceful 종료" },
12
36
  { name: "kill", usage: "tfx multi kill", desc: "모든 팀 세션 강제 종료" },
13
37
  { name: "list", usage: "tfx multi list", desc: "활성 세션 목록" },
14
38
  { name: "help", usage: "tfx multi help", desc: "도움말" },
15
- { name: "start", usage: "tfx multi start [options]", desc: "새 팀 세션 시작 (기본 커맨드)" },
39
+ {
40
+ name: "start",
41
+ usage: "tfx multi start [options]",
42
+ desc: "새 팀 세션 시작 (기본 커맨드)",
43
+ },
16
44
  ];
17
45
 
18
46
  export const TEAM_COMMAND_ALIASES = new Map([
@@ -25,5 +53,7 @@ export const TEAM_SUBCOMMANDS = new Set(TEAM_COMMANDS.map(({ name }) => name));
25
53
  export function resolveTeamCommand(raw) {
26
54
  if (typeof raw !== "string") return null;
27
55
  const command = raw.toLowerCase();
28
- return TEAM_SUBCOMMANDS.has(command) ? command : (TEAM_COMMAND_ALIASES.get(command) || null);
56
+ return TEAM_SUBCOMMANDS.has(command)
57
+ ? command
58
+ : TEAM_COMMAND_ALIASES.get(command) || null;
29
59
  }
@@ -1,8 +1,24 @@
1
- import { AMBER, BOLD, DIM, GRAY, GREEN, RED, RESET, WHITE, YELLOW } from "../shared.mjs";
1
+ import {
2
+ AMBER,
3
+ BOLD,
4
+ DIM,
5
+ GRAY,
6
+ GREEN,
7
+ RED,
8
+ RESET,
9
+ WHITE,
10
+ YELLOW,
11
+ } from "../shared.mjs";
2
12
 
3
- export function ok(msg) { console.log(` ${GREEN}✓${RESET} ${msg}`); }
4
- export function warn(msg) { console.log(` ${YELLOW}⚠${RESET} ${msg}`); }
5
- export function fail(msg) { console.log(` ${RED}✗${RESET} ${msg}`); }
13
+ export function ok(msg) {
14
+ console.log(` ${GREEN}✓${RESET} ${msg}`);
15
+ }
16
+ export function warn(msg) {
17
+ console.log(` ${YELLOW}⚠${RESET} ${msg}`);
18
+ }
19
+ export function fail(msg) {
20
+ console.log(` ${RED}✗${RESET} ${msg}`);
21
+ }
6
22
 
7
23
  export function renderTasks(tasks = []) {
8
24
  if (!tasks.length) {
@@ -12,9 +28,13 @@ export function renderTasks(tasks = []) {
12
28
 
13
29
  console.log(`\n ${AMBER}${BOLD}⬡ Team Tasks${RESET}\n`);
14
30
  for (const task of tasks) {
15
- const dep = task.depends_on?.length ? ` ${DIM}(deps: ${task.depends_on.join(",")})${RESET}` : "";
31
+ const dep = task.depends_on?.length
32
+ ? ` ${DIM}(deps: ${task.depends_on.join(",")})${RESET}`
33
+ : "";
16
34
  const owner = task.owner ? ` ${GRAY}[${task.owner}]${RESET}` : "";
17
- console.log(` ${WHITE}${task.id}${RESET} ${String(task.status || "").padEnd(11)} ${task.title}${owner}${dep}`);
35
+ console.log(
36
+ ` ${WHITE}${task.id}${RESET} ${String(task.status || "").padEnd(11)} ${task.title}${owner}${dep}`,
37
+ );
18
38
  }
19
39
  console.log("");
20
40
  }
@@ -24,7 +44,9 @@ export function formatCompletionSuffix(member) {
24
44
  if (member.completionStatus === "abnormal") {
25
45
  return ` ${RED}[abnormal:${member.completionReason || "unknown"}]${RESET}`;
26
46
  }
27
- if (member.completionStatus === "normal") return ` ${GREEN}[route-ok]${RESET}`;
28
- if (member.completionStatus === "unchecked") return ` ${GRAY}[route-unchecked]${RESET}`;
47
+ if (member.completionStatus === "normal")
48
+ return ` ${GREEN}[route-ok]${RESET}`;
49
+ if (member.completionStatus === "unchecked")
50
+ return ` ${GRAY}[route-unchecked]${RESET}`;
29
51
  return "";
30
52
  }
@@ -19,11 +19,24 @@ export async function launchAttachInWindowsTerminal(sessionName) {
19
19
 
20
20
  const beforeAttached = getSessionAttachedCount(sessionName);
21
21
  try {
22
- const child = spawn("wt", ["-w", "0", "split-pane", "-V", "-d", PKG_ROOT, attachSpec.command, ...attachSpec.args], {
23
- detached: true,
24
- stdio: "ignore",
25
- windowsHide: false,
26
- });
22
+ const child = spawn(
23
+ "wt",
24
+ [
25
+ "-w",
26
+ "0",
27
+ "split-pane",
28
+ "-V",
29
+ "-d",
30
+ PKG_ROOT,
31
+ attachSpec.command,
32
+ ...attachSpec.args,
33
+ ],
34
+ {
35
+ detached: true,
36
+ stdio: "ignore",
37
+ windowsHide: false,
38
+ },
39
+ );
27
40
  child.unref();
28
41
 
29
42
  if (beforeAttached == null) return true;
@@ -31,7 +44,8 @@ export async function launchAttachInWindowsTerminal(sessionName) {
31
44
  while (Date.now() < deadline) {
32
45
  await new Promise((resolve) => setTimeout(resolve, 120));
33
46
  const nowAttached = getSessionAttachedCount(sessionName);
34
- if (typeof nowAttached === "number" && nowAttached > beforeAttached) return true;
47
+ if (typeof nowAttached === "number" && nowAttached > beforeAttached)
48
+ return true;
35
49
  }
36
50
  } catch {}
37
51
  return false;
@@ -40,15 +54,21 @@ export async function launchAttachInWindowsTerminal(sessionName) {
40
54
  export function buildManualAttachCommand(sessionName) {
41
55
  try {
42
56
  const spec = resolveAttachCommand(sessionName);
43
- return [spec.command, ...spec.args].map((value) => {
44
- const text = String(value);
45
- return /\s/.test(text) ? `"${text.replace(/"/g, '\\"')}"` : text;
46
- }).join(" ");
57
+ return [spec.command, ...spec.args]
58
+ .map((value) => {
59
+ const text = String(value);
60
+ return /\s/.test(text) ? `"${text.replace(/"/g, '\\"')}"` : text;
61
+ })
62
+ .join(" ");
47
63
  } catch {
48
64
  return `tmux attach-session -t ${sessionName}`;
49
65
  }
50
66
  }
51
67
 
52
68
  export function wantsWtAttachFallback(args = [], env = process.env) {
53
- return args.includes("--wt") || args.includes("--spawn-wt") || env.TFX_ATTACH_WT_AUTO === "1";
69
+ return (
70
+ args.includes("--wt") ||
71
+ args.includes("--spawn-wt") ||
72
+ env.TFX_ATTACH_WT_AUTO === "1"
73
+ );
54
74
  }
@@ -1,10 +1,20 @@
1
- import { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
2
- import { join } from "node:path";
3
1
  import { spawn } from "node:child_process";
2
+ import {
3
+ existsSync,
4
+ mkdirSync,
5
+ readFileSync,
6
+ unlinkSync,
7
+ writeFileSync,
8
+ } from "node:fs";
9
+ import { join } from "node:path";
4
10
 
5
11
  import { publishLeadControl as publishLeadControlBridge } from "../../lead-control.mjs";
6
- import { getTeamStatus as fetchTeamStatus, subscribeToLeadCommands as pullLeadCommands } from "../../session-sync.mjs";
12
+ import {
13
+ getTeamStatus as fetchTeamStatus,
14
+ subscribeToLeadCommands as pullLeadCommands,
15
+ } from "../../session-sync.mjs";
7
16
  import { HUB_PID_DIR, PKG_ROOT } from "./state-store.mjs";
17
+
8
18
  export { nativeGetStatus } from "./native-control.mjs";
9
19
 
10
20
  const HUB_PID_FILE = join(HUB_PID_DIR, "hub.pid");
@@ -67,7 +77,9 @@ export async function getHubInfo() {
67
77
  ...(status ? {} : { degraded: true }),
68
78
  };
69
79
  } catch {
70
- try { unlinkSync(HUB_PID_FILE); } catch {}
80
+ try {
81
+ unlinkSync(HUB_PID_FILE);
82
+ } catch {}
71
83
  }
72
84
  }
73
85
 
@@ -86,7 +98,10 @@ export async function getHubInfo() {
86
98
  if (Number.isFinite(recovered.pid) && recovered.pid > 0) {
87
99
  try {
88
100
  mkdirSync(HUB_PID_DIR, { recursive: true });
89
- writeFileSync(HUB_PID_FILE, JSON.stringify({ ...recovered, started: Date.now() }));
101
+ writeFileSync(
102
+ HUB_PID_FILE,
103
+ JSON.stringify({ ...recovered, started: Date.now() }),
104
+ );
90
105
  } catch {}
91
106
  }
92
107
  return recovered;
@@ -159,7 +174,9 @@ export async function ensureHubAlive(maxRetries = 3) {
159
174
  }
160
175
  }
161
176
 
162
- const error = new Error(`Hub 재시작 ${maxRetries}회 모두 실패${lastError ? `: ${lastError.message}` : ""}`);
177
+ const error = new Error(
178
+ `Hub 재시작 ${maxRetries}회 모두 실패${lastError ? `: ${lastError.message}` : ""}`,
179
+ );
163
180
  error.code = "HUB_RESTART_FAILED";
164
181
  error.cause = lastError;
165
182
  throw error;
@@ -178,16 +195,24 @@ export async function fetchHubTaskList(state) {
178
195
  signal: AbortSignal.timeout(2000),
179
196
  });
180
197
  const data = await res.json();
181
- return data?.ok ? (data.data?.tasks || []) : [];
198
+ return data?.ok ? data.data?.tasks || [] : [];
182
199
  } catch {
183
200
  return [];
184
201
  }
185
202
  }
186
203
 
187
- export async function publishLeadControl(state, targetMember, command, reason = "") {
204
+ export async function publishLeadControl(
205
+ state,
206
+ targetMember,
207
+ command,
208
+ reason = "",
209
+ ) {
188
210
  const hubBase = (state?.hubUrl || getDefaultHubUrl()).replace(/\/mcp$/, "");
189
- const leadAgent = (state?.members || []).find((member) => member.role === "lead")?.agentId || "lead";
190
- const targetAgent = typeof targetMember === "string" ? targetMember : targetMember?.agentId;
211
+ const leadAgent =
212
+ (state?.members || []).find((member) => member.role === "lead")?.agentId ||
213
+ "lead";
214
+ const targetAgent =
215
+ typeof targetMember === "string" ? targetMember : targetMember?.agentId;
191
216
 
192
217
  const result = await publishLeadControlBridge({
193
218
  hubUrl: hubBase,
@@ -206,10 +231,13 @@ export async function publishLeadControl(state, targetMember, command, reason =
206
231
 
207
232
  export async function subscribeToLeadCommands(state, member, options = {}) {
208
233
  const hubBase = (state?.hubUrl || getDefaultHubUrl()).replace(/\/mcp$/, "");
209
- const fallbackAgentId = (state?.members || []).find((candidate) => candidate.role === "lead")?.agentId || null;
210
- const agentId = typeof member === "string"
211
- ? member
212
- : member?.agentId || options?.agentId || fallbackAgentId;
234
+ const fallbackAgentId =
235
+ (state?.members || []).find((candidate) => candidate.role === "lead")
236
+ ?.agentId || null;
237
+ const agentId =
238
+ typeof member === "string"
239
+ ? member
240
+ : member?.agentId || options?.agentId || fallbackAgentId;
213
241
 
214
242
  return await pullLeadCommands({
215
243
  hubUrl: hubBase,
@@ -2,9 +2,12 @@ export function resolveMember(state, selector) {
2
2
  const members = state?.members || [];
3
3
  if (!selector) return null;
4
4
 
5
- const direct = members.find((member) => (
6
- member.name === selector || member.role === selector || member.agentId === selector
7
- ));
5
+ const direct = members.find(
6
+ (member) =>
7
+ member.name === selector ||
8
+ member.role === selector ||
9
+ member.agentId === selector,
10
+ );
8
11
  if (direct) return direct;
9
12
 
10
13
  const workerAlias = /^worker-(\d+)$/i.exec(selector);
@@ -16,7 +19,11 @@ export function resolveMember(state, selector) {
16
19
 
17
20
  const numeric = parseInt(selector, 10);
18
21
  if (!Number.isNaN(numeric)) {
19
- const byPane = members.find((member) => member.pane?.endsWith(`.${numeric}`) || member.pane?.endsWith(`:${numeric}`));
22
+ const byPane = members.find(
23
+ (member) =>
24
+ member.pane?.endsWith(`.${numeric}`) ||
25
+ member.pane?.endsWith(`:${numeric}`),
26
+ );
20
27
  if (byPane) return byPane;
21
28
  if (numeric >= 1 && numeric <= members.length) return members[numeric - 1];
22
29
  }
@@ -1,12 +1,10 @@
1
+ import { spawn } from "node:child_process";
1
2
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
2
3
  import { join } from "node:path";
3
- import { spawn } from "node:child_process";
4
-
4
+ import { buildExecArgs } from "../../../codex-adapter.mjs";
5
5
  import { buildLeadPrompt, buildPrompt } from "../../orchestrator.mjs";
6
6
  import { HUB_PID_DIR, PKG_ROOT } from "./state-store.mjs";
7
7
 
8
- import { buildExecArgs } from "../../../codex-adapter.mjs";
9
-
10
8
  export function buildNativeCliCommand(cli) {
11
9
  switch (cli) {
12
10
  case "codex":
@@ -20,9 +18,19 @@ export function buildNativeCliCommand(cli) {
20
18
  }
21
19
  }
22
20
 
23
- export async function startNativeSupervisor({ sessionId, task, lead, agents, subtasks, hubUrl }) {
21
+ export async function startNativeSupervisor({
22
+ sessionId,
23
+ task,
24
+ lead,
25
+ agents,
26
+ subtasks,
27
+ hubUrl,
28
+ }) {
24
29
  const configPath = join(HUB_PID_DIR, `team-native-${sessionId}.config.json`);
25
- const runtimePath = join(HUB_PID_DIR, `team-native-${sessionId}.runtime.json`);
30
+ const runtimePath = join(
31
+ HUB_PID_DIR,
32
+ `team-native-${sessionId}.runtime.json`,
33
+ );
26
34
  const logsDir = join(HUB_PID_DIR, "team-logs", sessionId);
27
35
  mkdirSync(logsDir, { recursive: true });
28
36
 
@@ -57,25 +65,44 @@ export async function startNativeSupervisor({ sessionId, task, lead, agents, sub
57
65
  },
58
66
  ...workers.map((worker) => ({
59
67
  ...worker,
60
- prompt: buildPrompt(worker.subtask, { cli: worker.cli, agentId: worker.agentId, hubUrl }),
68
+ prompt: buildPrompt(worker.subtask, {
69
+ cli: worker.cli,
70
+ agentId: worker.agentId,
71
+ hubUrl,
72
+ }),
61
73
  })),
62
74
  ];
63
75
 
64
- writeFileSync(configPath, JSON.stringify({
65
- sessionName: sessionId,
66
- hubUrl,
67
- startupDelayMs: 3000,
68
- logsDir,
69
- runtimeFile: runtimePath,
70
- members,
71
- }, null, 2) + "\n");
76
+ writeFileSync(
77
+ configPath,
78
+ JSON.stringify(
79
+ {
80
+ sessionName: sessionId,
81
+ hubUrl,
82
+ startupDelayMs: 3000,
83
+ logsDir,
84
+ runtimeFile: runtimePath,
85
+ members,
86
+ },
87
+ null,
88
+ 2,
89
+ ) + "\n",
90
+ );
72
91
 
73
- const child = spawn(process.execPath, [join(PKG_ROOT, "hub", "team", "native-supervisor.mjs"), "--config", configPath], {
74
- detached: true,
75
- stdio: "ignore",
76
- env: { ...process.env },
77
- windowsHide: true,
78
- });
92
+ const child = spawn(
93
+ process.execPath,
94
+ [
95
+ join(PKG_ROOT, "hub", "team", "native-supervisor.mjs"),
96
+ "--config",
97
+ configPath,
98
+ ],
99
+ {
100
+ detached: true,
101
+ stdio: "ignore",
102
+ env: { ...process.env },
103
+ windowsHide: true,
104
+ },
105
+ );
79
106
  child.unref();
80
107
 
81
108
  const deadline = Date.now() + 5000;
@@ -22,7 +22,8 @@ export function normalizeTeammateMode(mode = "auto") {
22
22
  export function normalizeLayout(layout = "2x2") {
23
23
  const raw = String(layout).toLowerCase();
24
24
  if (raw === "2x2" || raw === "grid") return "2x2";
25
- if (raw === "1xn" || raw === "1x3" || raw === "vertical" || raw === "columns") return "1xN";
25
+ if (raw === "1xn" || raw === "1x3" || raw === "vertical" || raw === "columns")
26
+ return "1xN";
26
27
  if (raw === "nx1" || raw === "horizontal" || raw === "rows") return "Nx1";
27
28
  return "2x2";
28
29
  }
@@ -1,13 +1,20 @@
1
- import { existsSync, readFileSync, unlinkSync, writeFileSync } from "node:fs";
2
- import { mkdirSync } from "node:fs";
3
- import { dirname, join } from "node:path";
1
+ import {
2
+ existsSync,
3
+ mkdirSync,
4
+ readFileSync,
5
+ unlinkSync,
6
+ writeFileSync,
7
+ } from "node:fs";
4
8
  import { homedir } from "node:os";
9
+ import { dirname, join } from "node:path";
5
10
  import { fileURLToPath } from "node:url";
6
11
 
7
12
  export const PKG_ROOT = fileURLToPath(new URL("../../../../", import.meta.url));
8
13
  export const HUB_PID_DIR = join(homedir(), ".claude", "cache", "tfx-hub");
9
14
  export const TEAM_PROFILE = (() => {
10
- const raw = String(process.env.TFX_TEAM_PROFILE || "team").trim().toLowerCase();
15
+ const raw = String(process.env.TFX_TEAM_PROFILE || "team")
16
+ .trim()
17
+ .toLowerCase();
11
18
  return raw === "codex-team" ? "codex-team" : "team";
12
19
  })();
13
20
 
@@ -15,21 +22,28 @@ export const SESSION_ID = process.env.CLAUDE_SESSION_ID || `s${Date.now()}`;
15
22
 
16
23
  function getStatePath(sessionId) {
17
24
  if (sessionId) return join(HUB_PID_DIR, `team-state-${sessionId}.json`);
18
- return join(HUB_PID_DIR, TEAM_PROFILE === "codex-team" ? "team-state-codex-team.json" : "team-state.json");
25
+ return join(
26
+ HUB_PID_DIR,
27
+ TEAM_PROFILE === "codex-team"
28
+ ? "team-state-codex-team.json"
29
+ : "team-state.json",
30
+ );
19
31
  }
20
32
 
21
33
  export function loadTeamState(sessionId) {
22
34
  const resolvedId = sessionId || SESSION_ID;
23
35
  const sessionPath = getStatePath(resolvedId);
24
36
  try {
25
- if (existsSync(sessionPath)) return JSON.parse(readFileSync(sessionPath, "utf8"));
37
+ if (existsSync(sessionPath))
38
+ return JSON.parse(readFileSync(sessionPath, "utf8"));
26
39
  } catch {
27
40
  return null;
28
41
  }
29
42
  // 세션별 파일 없으면 기존 team-state.json fallback
30
43
  const legacyPath = getStatePath(null);
31
44
  try {
32
- if (existsSync(legacyPath)) return JSON.parse(readFileSync(legacyPath, "utf8"));
45
+ if (existsSync(legacyPath))
46
+ return JSON.parse(readFileSync(legacyPath, "utf8"));
33
47
  } catch {
34
48
  return null;
35
49
  }
@@ -39,7 +53,10 @@ export function loadTeamState(sessionId) {
39
53
  export function saveTeamState(state, sessionId) {
40
54
  const path = getStatePath(sessionId || state.sessionId || SESSION_ID);
41
55
  mkdirSync(dirname(path), { recursive: true });
42
- writeFileSync(path, JSON.stringify({ ...state, profile: TEAM_PROFILE }, null, 2) + "\n");
56
+ writeFileSync(
57
+ path,
58
+ JSON.stringify({ ...state, profile: TEAM_PROFILE }, null, 2) + "\n",
59
+ );
43
60
  }
44
61
 
45
62
  export function clearTeamState(sessionId) {
@@ -10,21 +10,31 @@ export function buildTasks(subtasks, workers) {
10
10
 
11
11
  export function normalizeTaskStatus(action) {
12
12
  const value = String(action || "").toLowerCase();
13
- if (value === "done" || value === "complete" || value === "completed") return "completed";
14
- if (value === "progress" || value === "in-progress" || value === "in_progress") return "in_progress";
13
+ if (value === "done" || value === "complete" || value === "completed")
14
+ return "completed";
15
+ if (
16
+ value === "progress" ||
17
+ value === "in-progress" ||
18
+ value === "in_progress"
19
+ )
20
+ return "in_progress";
15
21
  if (value === "pending") return "pending";
16
22
  return null;
17
23
  }
18
24
 
19
25
  export function updateTaskStatus(tasks = [], taskId, nextStatus) {
20
26
  const normalizedId = String(taskId || "").toUpperCase();
21
- const target = tasks.find((task) => String(task.id).toUpperCase() === normalizedId);
27
+ const target = tasks.find(
28
+ (task) => String(task.id).toUpperCase() === normalizedId,
29
+ );
22
30
  if (!target) return { tasks, target: null };
23
31
 
24
32
  return {
25
33
  target: { ...target, status: nextStatus },
26
- tasks: tasks.map((task) => (
27
- String(task.id).toUpperCase() === normalizedId ? { ...task, status: nextStatus } : task
28
- )),
34
+ tasks: tasks.map((task) =>
35
+ String(task.id).toUpperCase() === normalizedId
36
+ ? { ...task, status: nextStatus }
37
+ : task,
38
+ ),
29
39
  };
30
40
  }
@@ -14,10 +14,7 @@ const BRIDGE_AGENT_ID = "conductor";
14
14
  * @returns {object} Bridge API
15
15
  */
16
16
  export function createConductorMeshBridge(conductor, registry, opts = {}) {
17
- const {
18
- bridgeAgentId = BRIDGE_AGENT_ID,
19
- onMessage,
20
- } = opts;
17
+ const { bridgeAgentId = BRIDGE_AGENT_ID, onMessage } = opts;
21
18
 
22
19
  const sessionAgentMap = new Map();
23
20
  let attached = false;
@@ -49,12 +46,13 @@ export function createConductorMeshBridge(conductor, registry, opts = {}) {
49
46
  }
50
47
 
51
48
  // Emit mesh event
52
- const msg = createMessage(
53
- MSG_TYPES.EVENT,
54
- bridgeAgentId,
55
- "*",
56
- { event: "stateChange", sessionId, from, to, reason },
57
- );
49
+ const msg = createMessage(MSG_TYPES.EVENT, bridgeAgentId, "*", {
50
+ event: "stateChange",
51
+ sessionId,
52
+ from,
53
+ to,
54
+ reason,
55
+ });
58
56
  emit(msg);
59
57
 
60
58
  // Unregister on terminal states
@@ -68,12 +66,10 @@ export function createConductorMeshBridge(conductor, registry, opts = {}) {
68
66
  * Handle conductor completed events.
69
67
  */
70
68
  function handleCompleted(event) {
71
- const msg = createMessage(
72
- MSG_TYPES.EVENT,
73
- bridgeAgentId,
74
- "*",
75
- { event: "completed", sessionId: event.sessionId },
76
- );
69
+ const msg = createMessage(MSG_TYPES.EVENT, bridgeAgentId, "*", {
70
+ event: "completed",
71
+ sessionId: event.sessionId,
72
+ });
77
73
  emit(msg);
78
74
  }
79
75
 
@@ -81,12 +77,11 @@ export function createConductorMeshBridge(conductor, registry, opts = {}) {
81
77
  * Handle conductor dead events.
82
78
  */
83
79
  function handleDead(event) {
84
- const msg = createMessage(
85
- MSG_TYPES.EVENT,
86
- bridgeAgentId,
87
- "*",
88
- { event: "dead", sessionId: event.sessionId, reason: event.reason },
89
- );
80
+ const msg = createMessage(MSG_TYPES.EVENT, bridgeAgentId, "*", {
81
+ event: "dead",
82
+ sessionId: event.sessionId,
83
+ reason: event.reason,
84
+ });
90
85
  emit(msg);
91
86
  }
92
87
 
@@ -117,5 +112,11 @@ export function createConductorMeshBridge(conductor, registry, opts = {}) {
117
112
  attached = false;
118
113
  }
119
114
 
120
- return { attach, detach, get isAttached() { return attached; } };
115
+ return {
116
+ attach,
117
+ detach,
118
+ get isAttached() {
119
+ return attached;
120
+ },
121
+ };
121
122
  }