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,11 +1,26 @@
1
1
  {
2
- "executor": "codex", "build-fixer": "codex", "debugger": "codex", "deep-executor": "codex",
3
- "architect": "codex", "planner": "codex", "critic": "codex", "analyst": "codex",
4
- "code-reviewer": "codex", "security-reviewer": "codex", "quality-reviewer": "codex",
5
- "scientist": "codex", "scientist-deep": "codex", "document-specialist": "codex",
2
+ "executor": "codex",
3
+ "build-fixer": "codex",
4
+ "debugger": "codex",
5
+ "deep-executor": "codex",
6
+ "architect": "codex",
7
+ "planner": "codex",
8
+ "critic": "codex",
9
+ "analyst": "codex",
10
+ "code-reviewer": "codex",
11
+ "security-reviewer": "codex",
12
+ "quality-reviewer": "codex",
13
+ "scientist": "codex",
14
+ "scientist-deep": "codex",
15
+ "document-specialist": "codex",
6
16
  "spark": "codex",
7
- "designer": "gemini", "writer": "gemini",
17
+ "designer": "gemini",
18
+ "writer": "gemini",
8
19
  "explore": "claude",
9
- "verifier": "codex", "test-engineer": "codex", "qa-tester": "codex",
10
- "codex": "codex", "gemini": "gemini", "claude": "claude"
20
+ "verifier": "codex",
21
+ "test-engineer": "codex",
22
+ "qa-tester": "codex",
23
+ "codex": "codex",
24
+ "gemini": "gemini",
25
+ "claude": "claude"
11
26
  }
package/hub/team/ansi.mjs CHANGED
@@ -7,54 +7,60 @@
7
7
  export const ESC = "\x1b";
8
8
 
9
9
  // ── 화면 ──
10
- export const altScreenOn = `${ESC}[?1049h`;
10
+ export const altScreenOn = `${ESC}[?1049h`;
11
11
  export const altScreenOff = `${ESC}[?1049l`;
12
- export const clearScreen = `${ESC}[2J`;
13
- export const cursorHome = `${ESC}[H`;
14
- export const cursorHide = `${ESC}[?25l`;
15
- export const cursorShow = `${ESC}[?25h`;
12
+ export const clearScreen = `${ESC}[2J`;
13
+ export const cursorHome = `${ESC}[H`;
14
+ export const cursorHide = `${ESC}[?25l`;
15
+ export const cursorShow = `${ESC}[?25h`;
16
16
 
17
17
  // ── 커서 이동 ──
18
- export function moveTo(row, col) { return `${ESC}[${row};${col}H`; }
19
- export function moveUp(n = 1) { return `${ESC}[${n}A`; }
20
- export function moveDown(n = 1) { return `${ESC}[${n}B`; }
18
+ export function moveTo(row, col) {
19
+ return `${ESC}[${row};${col}H`;
20
+ }
21
+ export function moveUp(n = 1) {
22
+ return `${ESC}[${n}A`;
23
+ }
24
+ export function moveDown(n = 1) {
25
+ return `${ESC}[${n}B`;
26
+ }
21
27
 
22
28
  // ── 줄 제어 ──
23
- export const clearLine = `${ESC}[2K`;
24
- export const clearToEnd = `${ESC}[K`;
25
- export const eraseBelow = `${ESC}[J`;
29
+ export const clearLine = `${ESC}[2K`;
30
+ export const clearToEnd = `${ESC}[K`;
31
+ export const eraseBelow = `${ESC}[J`;
26
32
 
27
33
  // ── 색상 (triflux 디자인 시스템) ──
28
34
  export const RESET = `${ESC}[0m`;
29
- export const BOLD = `${ESC}[1m`;
30
- export const DIM = `${ESC}[2m`;
35
+ export const BOLD = `${ESC}[1m`;
36
+ export const DIM = `${ESC}[2m`;
31
37
 
32
38
  export const FG = {
33
- white: `${ESC}[97m`,
34
- black: `${ESC}[30m`,
35
- red: `${ESC}[31m`,
36
- green: `${ESC}[32m`,
37
- yellow: `${ESC}[33m`,
38
- blue: `${ESC}[34m`,
39
- magenta: `${ESC}[35m`,
40
- cyan: `${ESC}[36m`,
41
- gray: `${ESC}[90m`,
39
+ white: `${ESC}[97m`,
40
+ black: `${ESC}[30m`,
41
+ red: `${ESC}[31m`,
42
+ green: `${ESC}[32m`,
43
+ yellow: `${ESC}[33m`,
44
+ blue: `${ESC}[34m`,
45
+ magenta: `${ESC}[35m`,
46
+ cyan: `${ESC}[36m`,
47
+ gray: `${ESC}[90m`,
42
48
  // triflux 브랜드
43
- codex: `${ESC}[38;2;16;163;127m`, // #10a37f codex green
44
- gemini: `${ESC}[38;5;39m`, // blue
45
- claude: `${ESC}[38;2;232;112;64m`, // orange
46
- triflux: `${ESC}[38;5;214m`, // amber
47
- accent: `${ESC}[38;5;75m`, // light blue (Catppuccin blue)
48
- muted: `${ESC}[38;5;245m`, // gray
49
+ codex: `${ESC}[38;2;16;163;127m`, // #10a37f codex green
50
+ gemini: `${ESC}[38;5;39m`, // blue
51
+ claude: `${ESC}[38;2;232;112;64m`, // orange
52
+ triflux: `${ESC}[38;5;214m`, // amber
53
+ accent: `${ESC}[38;5;75m`, // light blue (Catppuccin blue)
54
+ muted: `${ESC}[38;5;245m`, // gray
49
55
  };
50
56
 
51
57
  export const BG = {
52
- black: `${ESC}[40m`,
53
- red: `${ESC}[41m`,
54
- green: `${ESC}[42m`,
55
- yellow: `${ESC}[43m`,
56
- blue: `${ESC}[44m`,
57
- header: `${ESC}[48;5;236m`, // dark gray
58
+ black: `${ESC}[40m`,
59
+ red: `${ESC}[41m`,
60
+ green: `${ESC}[42m`,
61
+ yellow: `${ESC}[43m`,
62
+ blue: `${ESC}[44m`,
63
+ header: `${ESC}[48;5;236m`, // dark gray
58
64
  };
59
65
 
60
66
  // ── 색상 헬퍼 ──
@@ -63,8 +69,12 @@ export function color(text, fg, bg) {
63
69
  return prefix ? `${prefix}${text}${RESET}` : text;
64
70
  }
65
71
 
66
- export function bold(text) { return `${BOLD}${text}${RESET}`; }
67
- export function dim(text) { return `${DIM}${text}${RESET}`; }
72
+ export function bold(text) {
73
+ return `${BOLD}${text}${RESET}`;
74
+ }
75
+ export function dim(text) {
76
+ return `${DIM}${text}${RESET}`;
77
+ }
68
78
 
69
79
  export function lerpRgb(a, b, t) {
70
80
  return {
@@ -83,9 +93,10 @@ function brightenRgb(rgb, amount = 0.3) {
83
93
  }
84
94
 
85
95
  function parseRgbSeq(seq) {
86
- const match = typeof seq === "string"
87
- ? seq.match(/\x1b\[(?:38|48);2;(\d+);(\d+);(\d+)m/)
88
- : null;
96
+ const match =
97
+ typeof seq === "string"
98
+ ? seq.match(/\x1b\[(?:38|48);2;(\d+);(\d+);(\d+)m/)
99
+ : null;
89
100
  if (!match) return null;
90
101
  return {
91
102
  r: Number.parseInt(match[1], 10),
@@ -100,7 +111,16 @@ function reapplyBackground(text, bgSeq) {
100
111
  }
101
112
 
102
113
  // ── 박스 그리기 (유니코드 테두리) ──
103
- const BOX = { tl: "┌", tr: "┐", bl: "└", br: "┘", h: "─", v: "│", ml: "├", mr: "┤" };
114
+ const BOX = {
115
+ tl: "┌",
116
+ tr: "┐",
117
+ bl: "└",
118
+ br: "┘",
119
+ h: "─",
120
+ v: "│",
121
+ ml: "├",
122
+ mr: "┤",
123
+ };
104
124
 
105
125
  function borderHighlightCell(width, totalRows, highlightPos) {
106
126
  if (!Number.isFinite(highlightPos)) return null;
@@ -118,7 +138,14 @@ function borderHighlightCell(width, totalRows, highlightPos) {
118
138
  return { row: totalRows - 1 - pos, col: 0 };
119
139
  }
120
140
 
121
- function renderBorderChar(glyph, row, col, highlightCell, borderSeq, highlightSeq) {
141
+ function renderBorderChar(
142
+ glyph,
143
+ row,
144
+ col,
145
+ highlightCell,
146
+ borderSeq,
147
+ highlightSeq,
148
+ ) {
122
149
  if (highlightCell && highlightCell.row === row && highlightCell.col === col) {
123
150
  return `${highlightSeq}${glyph}${RESET}`;
124
151
  }
@@ -128,7 +155,11 @@ function renderBorderChar(glyph, row, col, highlightCell, borderSeq, highlightSe
128
155
  export function box(lines, width, borderColor = "", options = {}) {
129
156
  const isFn = typeof borderColor === "function";
130
157
  const totalRows = lines.length + 2;
131
- const highlightCell = borderHighlightCell(width, totalRows, options.highlightPos);
158
+ const highlightCell = borderHighlightCell(
159
+ width,
160
+ totalRows,
161
+ options.highlightPos,
162
+ );
132
163
 
133
164
  // Fast path: static border, no highlight — batch border chars (~13x less output)
134
165
  if (!highlightCell && !isFn) {
@@ -139,9 +170,10 @@ export function box(lines, width, borderColor = "", options = {}) {
139
170
  const bot = `${bc}${BOX.bl}${hLine}${BOX.br}${rst}`;
140
171
  const mid = `${bc}${BOX.ml}${hLine}${BOX.mr}${rst}`;
141
172
  const body = lines.map((l, i) => {
142
- const content = options.titleFlashBg && i === 0
143
- ? reapplyBackground(padRight(l, width - 4), options.titleFlashBg)
144
- : padRight(l, width - 4);
173
+ const content =
174
+ options.titleFlashBg && i === 0
175
+ ? reapplyBackground(padRight(l, width - 4), options.titleFlashBg)
176
+ : padRight(l, width - 4);
145
177
  return `${bc}${BOX.v}${rst} ${content} ${bc}${BOX.v}${rst}`;
146
178
  });
147
179
  return { top, body, bot, mid };
@@ -149,26 +181,49 @@ export function box(lines, width, borderColor = "", options = {}) {
149
181
 
150
182
  // Slow path: per-character rendering for highlight animation
151
183
  const bc = isFn ? (row) => borderColor(row, totalRows) : () => borderColor;
152
- const rst = (isFn || borderColor) ? RESET : "";
153
- const highlightSeq = options.highlightColor
154
- || (() => {
155
- const parsed = parseRgbSeq(typeof borderColor === "string" ? borderColor : "");
184
+ const rst = isFn || borderColor ? RESET : "";
185
+ const highlightSeq =
186
+ options.highlightColor ||
187
+ (() => {
188
+ const parsed = parseRgbSeq(
189
+ typeof borderColor === "string" ? borderColor : "",
190
+ );
156
191
  return parsed ? rgbSeq(brightenRgb(parsed, 0.45)) : `${BOLD}${FG.white}`;
157
192
  })();
158
- const topChars = [BOX.tl, ...Array.from({ length: width - 2 }, () => BOX.h), BOX.tr];
159
- const botChars = [BOX.bl, ...Array.from({ length: width - 2 }, () => BOX.h), BOX.br];
193
+ const topChars = [
194
+ BOX.tl,
195
+ ...Array.from({ length: width - 2 }, () => BOX.h),
196
+ BOX.tr,
197
+ ];
198
+ const botChars = [
199
+ BOX.bl,
200
+ ...Array.from({ length: width - 2 }, () => BOX.h),
201
+ BOX.br,
202
+ ];
160
203
  const top = topChars
161
- .map((glyph, col) => renderBorderChar(glyph, 0, col, highlightCell, bc(0), highlightSeq))
204
+ .map((glyph, col) =>
205
+ renderBorderChar(glyph, 0, col, highlightCell, bc(0), highlightSeq),
206
+ )
162
207
  .join("");
163
208
  const bot = botChars
164
- .map((glyph, col) => renderBorderChar(glyph, totalRows - 1, col, highlightCell, bc(totalRows - 1), highlightSeq))
209
+ .map((glyph, col) =>
210
+ renderBorderChar(
211
+ glyph,
212
+ totalRows - 1,
213
+ col,
214
+ highlightCell,
215
+ bc(totalRows - 1),
216
+ highlightSeq,
217
+ ),
218
+ )
165
219
  .join("");
166
220
  const mid = `${bc(Math.floor(totalRows / 2))}${BOX.ml}${BOX.h.repeat(Math.max(0, width - 2))}${BOX.mr}${rst}`;
167
221
  const body = lines.map((l, i) => {
168
222
  const row = i + 1;
169
- const content = options.titleFlashBg && i === 0
170
- ? reapplyBackground(padRight(l, width - 4), options.titleFlashBg)
171
- : padRight(l, width - 4);
223
+ const content =
224
+ options.titleFlashBg && i === 0
225
+ ? reapplyBackground(padRight(l, width - 4), options.titleFlashBg)
226
+ : padRight(l, width - 4);
172
227
  return `${renderBorderChar(BOX.v, row, 0, highlightCell, bc(row), highlightSeq)} ${content} ${renderBorderChar(BOX.v, row, width - 1, highlightCell, bc(row), highlightSeq)}`;
173
228
  });
174
229
  return { top, body, bot, mid };
@@ -179,50 +234,53 @@ export function box(lines, width, borderColor = "", options = {}) {
179
234
  function charWidth(cp) {
180
235
  // combining / zero-width 범위
181
236
  if (
182
- cp === 0 || cp === 0xAD ||
183
- (cp >= 0x0300 && cp <= 0x036F) || // Combining Diacritical Marks
184
- (cp >= 0x0610 && cp <= 0x061A) ||
185
- (cp >= 0x064B && cp <= 0x065F) ||
186
- (cp >= 0x1AB0 && cp <= 0x1AFF) ||
187
- (cp >= 0x1DC0 && cp <= 0x1DFF) ||
188
- (cp >= 0x20D0 && cp <= 0x20FF) || // Combining Diacritical Marks for Symbols
189
- (cp >= 0xFE20 && cp <= 0xFE2F) // Combining Half Marks
190
- ) return 0;
237
+ cp === 0 ||
238
+ cp === 0xad ||
239
+ (cp >= 0x0300 && cp <= 0x036f) || // Combining Diacritical Marks
240
+ (cp >= 0x0610 && cp <= 0x061a) ||
241
+ (cp >= 0x064b && cp <= 0x065f) ||
242
+ (cp >= 0x1ab0 && cp <= 0x1aff) ||
243
+ (cp >= 0x1dc0 && cp <= 0x1dff) ||
244
+ (cp >= 0x20d0 && cp <= 0x20ff) || // Combining Diacritical Marks for Symbols
245
+ (cp >= 0xfe20 && cp <= 0xfe2f) // Combining Half Marks
246
+ )
247
+ return 0;
191
248
 
192
249
  // Wide: CJK Unified Ideographs, Hangul, Fullwidth, emoji 주요 블록
193
250
  if (
194
- (cp >= 0x1100 && cp <= 0x115F) || // Hangul Jamo
195
- (cp >= 0x2E80 && cp <= 0x2EFF) || // CJK Radicals Supplement
196
- (cp >= 0x2F00 && cp <= 0x2FFF) ||
197
- (cp >= 0x3000 && cp <= 0x303F) || // CJK Symbols and Punctuation
198
- (cp >= 0x3040 && cp <= 0x309F) || // Hiragana
199
- (cp >= 0x30A0 && cp <= 0x30FF) || // Katakana
200
- (cp >= 0x3100 && cp <= 0x312F) ||
201
- (cp >= 0x3130 && cp <= 0x318F) || // Hangul Compatibility Jamo
202
- (cp >= 0x3190 && cp <= 0x319F) ||
203
- (cp >= 0x31C0 && cp <= 0x31EF) ||
204
- (cp >= 0x3200 && cp <= 0x32FF) ||
205
- (cp >= 0x3300 && cp <= 0x33FF) ||
206
- (cp >= 0x3400 && cp <= 0x4DBF) ||
207
- (cp >= 0x4E00 && cp <= 0x9FFF) || // CJK Unified Ideographs
208
- (cp >= 0xA000 && cp <= 0xA48F) ||
209
- (cp >= 0xA490 && cp <= 0xA4CF) ||
210
- (cp >= 0xA960 && cp <= 0xA97F) ||
211
- (cp >= 0xAC00 && cp <= 0xD7AF) || // Hangul Syllables
212
- (cp >= 0xF900 && cp <= 0xFAFF) || // CJK Compatibility Ideographs
213
- (cp >= 0xFE10 && cp <= 0xFE1F) ||
214
- (cp >= 0xFE30 && cp <= 0xFE4F) ||
215
- (cp >= 0xFF00 && cp <= 0xFF60) || // Fullwidth Forms
216
- (cp >= 0xFFE0 && cp <= 0xFFE6) ||
217
- (cp >= 0x1B000 && cp <= 0x1B0FF) ||
218
- (cp >= 0x1F004 && cp <= 0x1F0CF) ||
219
- (cp >= 0x1F200 && cp <= 0x1F2FF) ||
220
- (cp >= 0x1F300 && cp <= 0x1F64F) || // Misc Symbols, Emoticons
221
- (cp >= 0x1F680 && cp <= 0x1F6FF) || // Transport & Map
222
- (cp >= 0x1F900 && cp <= 0x1FAFF) || // Supplemental Symbols
223
- (cp >= 0x20000 && cp <= 0x2FFFD) ||
224
- (cp >= 0x30000 && cp <= 0x3FFFD)
225
- ) return 2;
251
+ (cp >= 0x1100 && cp <= 0x115f) || // Hangul Jamo
252
+ (cp >= 0x2e80 && cp <= 0x2eff) || // CJK Radicals Supplement
253
+ (cp >= 0x2f00 && cp <= 0x2fff) ||
254
+ (cp >= 0x3000 && cp <= 0x303f) || // CJK Symbols and Punctuation
255
+ (cp >= 0x3040 && cp <= 0x309f) || // Hiragana
256
+ (cp >= 0x30a0 && cp <= 0x30ff) || // Katakana
257
+ (cp >= 0x3100 && cp <= 0x312f) ||
258
+ (cp >= 0x3130 && cp <= 0x318f) || // Hangul Compatibility Jamo
259
+ (cp >= 0x3190 && cp <= 0x319f) ||
260
+ (cp >= 0x31c0 && cp <= 0x31ef) ||
261
+ (cp >= 0x3200 && cp <= 0x32ff) ||
262
+ (cp >= 0x3300 && cp <= 0x33ff) ||
263
+ (cp >= 0x3400 && cp <= 0x4dbf) ||
264
+ (cp >= 0x4e00 && cp <= 0x9fff) || // CJK Unified Ideographs
265
+ (cp >= 0xa000 && cp <= 0xa48f) ||
266
+ (cp >= 0xa490 && cp <= 0xa4cf) ||
267
+ (cp >= 0xa960 && cp <= 0xa97f) ||
268
+ (cp >= 0xac00 && cp <= 0xd7af) || // Hangul Syllables
269
+ (cp >= 0xf900 && cp <= 0xfaff) || // CJK Compatibility Ideographs
270
+ (cp >= 0xfe10 && cp <= 0xfe1f) ||
271
+ (cp >= 0xfe30 && cp <= 0xfe4f) ||
272
+ (cp >= 0xff00 && cp <= 0xff60) || // Fullwidth Forms
273
+ (cp >= 0xffe0 && cp <= 0xffe6) ||
274
+ (cp >= 0x1b000 && cp <= 0x1b0ff) ||
275
+ (cp >= 0x1f004 && cp <= 0x1f0cf) ||
276
+ (cp >= 0x1f200 && cp <= 0x1f2ff) ||
277
+ (cp >= 0x1f300 && cp <= 0x1f64f) || // Misc Symbols, Emoticons
278
+ (cp >= 0x1f680 && cp <= 0x1f6ff) || // Transport & Map
279
+ (cp >= 0x1f900 && cp <= 0x1faff) || // Supplemental Symbols
280
+ (cp >= 0x20000 && cp <= 0x2fffd) ||
281
+ (cp >= 0x30000 && cp <= 0x3fffd)
282
+ )
283
+ return 2;
226
284
 
227
285
  return 1;
228
286
  }
@@ -257,7 +315,7 @@ function ansiSlice(str, maxWidth) {
257
315
  let i = 0;
258
316
 
259
317
  while (i < str.length) {
260
- if (str.charCodeAt(i) === 0x1B) {
318
+ if (str.charCodeAt(i) === 0x1b) {
261
319
  const rest = str.slice(i);
262
320
  const m = rest.match(/^(\x1b(?:\[[0-9;]*[a-zA-Z]|\].*?(?:\x07|\x1b\\)))/);
263
321
  if (m) {
@@ -269,7 +327,7 @@ function ansiSlice(str, maxWidth) {
269
327
  }
270
328
 
271
329
  const cp = str.codePointAt(i);
272
- const charLen = cp > 0xFFFF ? 2 : 1;
330
+ const charLen = cp > 0xffff ? 2 : 1;
273
331
  const cw = charWidth(cp);
274
332
 
275
333
  if (visWidth + cw > maxWidth) break;
@@ -302,25 +360,25 @@ export function clip(str, width) {
302
360
 
303
361
  // ── Catppuccin Mocha 색상 상수 ──
304
362
  export const MOCHA = {
305
- ok: `${ESC}[38;5;114m`, // #a6e3a1 green
306
- partial: `${ESC}[38;5;216m`, // #fab387 peach
307
- fail: `${ESC}[38;5;210m`, // #f38ba8 red
308
- thinking: `${ESC}[38;5;183m`, // #cba6f7 mauve
309
- executing: `${ESC}[38;5;117m`, // #74c7ec sky
310
- border: `${ESC}[38;5;238m`, // #45475a surface1
311
- text: `${ESC}[38;2;205;214;244m`, // #cdd6f4 catppuccin text
312
- subtext: `${ESC}[38;2;166;173;200m`, // #a6adc8 subtext0
313
- overlay: `${ESC}[38;2;108;112;134m`, // #6c7086 overlay0
314
- blue: `${ESC}[38;2;137;180;250m`, // #89b4fa blue
315
- yellow: `${ESC}[38;2;249;226;175m`, // #f9e2af yellow
316
- red: `${ESC}[38;2;243;139;168m`, // #f38ba8 red (truecolor)
317
- surface0: `${ESC}[38;2;49;50;68m`, // #313244 surface0
363
+ ok: `${ESC}[38;5;114m`, // #a6e3a1 green
364
+ partial: `${ESC}[38;5;216m`, // #fab387 peach
365
+ fail: `${ESC}[38;5;210m`, // #f38ba8 red
366
+ thinking: `${ESC}[38;5;183m`, // #cba6f7 mauve
367
+ executing: `${ESC}[38;5;117m`, // #74c7ec sky
368
+ border: `${ESC}[38;5;238m`, // #45475a surface1
369
+ text: `${ESC}[38;2;205;214;244m`, // #cdd6f4 catppuccin text
370
+ subtext: `${ESC}[38;2;166;173;200m`, // #a6adc8 subtext0
371
+ overlay: `${ESC}[38;2;108;112;134m`, // #6c7086 overlay0
372
+ blue: `${ESC}[38;2;137;180;250m`, // #89b4fa blue
373
+ yellow: `${ESC}[38;2;249;226;175m`, // #f9e2af yellow
374
+ red: `${ESC}[38;2;243;139;168m`, // #f38ba8 red (truecolor)
375
+ surface0: `${ESC}[38;2;49;50;68m`, // #313244 surface0
318
376
  };
319
377
 
320
378
  const MOCHA_RGB = {
321
- ok: { r: 166, g: 227, b: 161 },
322
- partial: { r: 250, g: 179, b: 135 },
323
- fail: { r: 243, g: 139, b: 168 },
379
+ ok: { r: 166, g: 227, b: 161 },
380
+ partial: { r: 250, g: 179, b: 135 },
381
+ fail: { r: 243, g: 139, b: 168 },
324
382
  };
325
383
 
326
384
  // ── badge 헬퍼 ──
@@ -354,7 +412,12 @@ export function progressBar(percent, width = 20, time) {
354
412
  const ratio = Math.max(0, Math.min(100, percent)) / 100;
355
413
  const filled = Math.round(ratio * width);
356
414
  const empty = width - filled;
357
- const fillRgb = percent >= 100 ? MOCHA_RGB.ok : percent >= 50 ? MOCHA_RGB.partial : MOCHA_RGB.fail;
415
+ const fillRgb =
416
+ percent >= 100
417
+ ? MOCHA_RGB.ok
418
+ : percent >= 50
419
+ ? MOCHA_RGB.partial
420
+ : MOCHA_RGB.fail;
358
421
  const fillColor = rgbSeq(fillRgb);
359
422
  let fillText = "█".repeat(filled);
360
423
 
@@ -365,13 +428,14 @@ export function progressBar(percent, width = 20, time) {
365
428
  );
366
429
  const shineColor = rgbSeq(brightenRgb(fillRgb, 0.3));
367
430
  fillText = Array.from({ length: filled }, (_, idx) =>
368
- idx === shinePos ? `${shineColor}█${RESET}` : `${fillColor}█${RESET}`
431
+ idx === shinePos ? `${shineColor}█${RESET}` : `${fillColor}█${RESET}`,
369
432
  ).join("");
370
433
  } else if (filled > 0) {
371
434
  fillText = `${fillColor}${fillText}${RESET}`;
372
435
  }
373
436
 
374
- const emptyText = empty > 0 ? `${MOCHA.border}${"░".repeat(empty)}${RESET}` : "";
437
+ const emptyText =
438
+ empty > 0 ? `${MOCHA.border}${"░".repeat(empty)}${RESET}` : "";
375
439
  return `${fillText}${emptyText}`;
376
440
  }
377
441
 
@@ -395,14 +459,14 @@ export function animatedProgressBar(percent, width = 20, tick = 0) {
395
459
 
396
460
  // ── 상태 아이콘 ──
397
461
  export const STATUS_ICON = {
398
- running: `${MOCHA.partial}⏳${RESET}`,
462
+ running: `${MOCHA.partial}⏳${RESET}`,
399
463
  completed: `${MOCHA.ok}✓${RESET}`,
400
- failed: `${MOCHA.fail}✗${RESET}`,
401
- pending: `${FG.gray}⏸${RESET}`,
464
+ failed: `${MOCHA.fail}✗${RESET}`,
465
+ pending: `${FG.gray}⏸${RESET}`,
402
466
  };
403
467
 
404
468
  export const CLI_ICON = {
405
- codex: `${FG.codex}⚪${RESET}`,
469
+ codex: `${FG.codex}⚪${RESET}`,
406
470
  gemini: `${FG.gemini}🔵${RESET}`,
407
471
  claude: `${FG.claude}🟠${RESET}`,
408
472
  };
@@ -10,8 +10,12 @@ const _require = createRequire(import.meta.url);
10
10
  // ── 백엔드 클래스 ──────────────────────────────────────────────────────────
11
11
 
12
12
  export class CodexBackend {
13
- name() { return "codex"; }
14
- command() { return "codex"; }
13
+ name() {
14
+ return "codex";
15
+ }
16
+ command() {
17
+ return "codex";
18
+ }
15
19
 
16
20
  /**
17
21
  * @param {string} prompt — 프롬프트 (프롬프트 파일 경로가 아닌 PowerShell 표현식)
@@ -23,36 +27,50 @@ export class CodexBackend {
23
27
  return buildExecArgs({ prompt, resultFile, ...opts });
24
28
  }
25
29
 
26
- env() { return {}; }
30
+ env() {
31
+ return {};
32
+ }
27
33
  }
28
34
 
29
35
  export class GeminiBackend {
30
- name() { return "gemini"; }
31
- command() { return "gemini"; }
36
+ name() {
37
+ return "gemini";
38
+ }
39
+ command() {
40
+ return "gemini";
41
+ }
32
42
 
33
43
  buildArgs(prompt, resultFile, opts = {}) {
34
44
  return `gemini --prompt ${prompt} --output-format text > '${resultFile}' 2>'${resultFile}.err'`;
35
45
  }
36
46
 
37
- env() { return {}; }
47
+ env() {
48
+ return {};
49
+ }
38
50
  }
39
51
 
40
52
  export class ClaudeBackend {
41
- name() { return "claude"; }
42
- command() { return "claude"; }
53
+ name() {
54
+ return "claude";
55
+ }
56
+ command() {
57
+ return "claude";
58
+ }
43
59
 
44
60
  buildArgs(prompt, resultFile, opts = {}) {
45
61
  return `claude --print ${prompt} --output-format text > '${resultFile}' 2>&1`;
46
62
  }
47
63
 
48
- env() { return {}; }
64
+ env() {
65
+ return {};
66
+ }
49
67
  }
50
68
 
51
69
  // ── 레지스트리 ─────────────────────────────────────────────────────────────
52
70
 
53
71
  /** @type {Map<string, CodexBackend|GeminiBackend|ClaudeBackend>} */
54
72
  const backends = new Map([
55
- ["codex", new CodexBackend()],
73
+ ["codex", new CodexBackend()],
56
74
  ["gemini", new GeminiBackend()],
57
75
  ["claude", new ClaudeBackend()],
58
76
  ]);
@@ -1,9 +1,17 @@
1
1
  import { attachSession } from "../../session.mjs";
2
2
  import { DIM, RESET } from "../../shared.mjs";
3
- import { buildManualAttachCommand, launchAttachInWindowsTerminal, wantsWtAttachFallback } from "../services/attach-fallback.mjs";
4
- import { isNativeMode, isTeamAlive, isWtMode } from "../services/runtime-mode.mjs";
5
- import { loadTeamState } from "../services/state-store.mjs";
6
3
  import { fail, ok, warn } from "../render.mjs";
4
+ import {
5
+ buildManualAttachCommand,
6
+ launchAttachInWindowsTerminal,
7
+ wantsWtAttachFallback,
8
+ } from "../services/attach-fallback.mjs";
9
+ import {
10
+ isNativeMode,
11
+ isTeamAlive,
12
+ isWtMode,
13
+ } from "../services/runtime-mode.mjs";
14
+ import { loadTeamState } from "../services/state-store.mjs";
7
15
 
8
16
  export async function teamAttach(args = []) {
9
17
  const state = loadTeamState();
@@ -12,11 +20,15 @@ export async function teamAttach(args = []) {
12
20
  return;
13
21
  }
14
22
  if (isNativeMode(state)) {
15
- console.log(`\n ${DIM}in-process 모드는 별도 attach가 없습니다.${RESET}\n ${DIM}상태 확인: tfx multi status${RESET}\n`);
23
+ console.log(
24
+ `\n ${DIM}in-process 모드는 별도 attach가 없습니다.${RESET}\n ${DIM}상태 확인: tfx multi status${RESET}\n`,
25
+ );
16
26
  return;
17
27
  }
18
28
  if (isWtMode(state)) {
19
- console.log(`\n ${DIM}wt 모드는 attach 개념이 없습니다 (Windows Terminal pane가 독립 실행됨).${RESET}\n ${DIM}재실행/정리는: tfx multi stop${RESET}\n`);
29
+ console.log(
30
+ `\n ${DIM}wt 모드는 attach 개념이 없습니다 (Windows Terminal pane가 독립 실행됨).${RESET}\n ${DIM}재실행/정리는: tfx multi stop${RESET}\n`,
31
+ );
20
32
  return;
21
33
  }
22
34
 
@@ -24,14 +36,22 @@ export async function teamAttach(args = []) {
24
36
  attachSession(state.sessionName);
25
37
  } catch (error) {
26
38
  const allowWt = wantsWtAttachFallback(args);
27
- if (allowWt && await launchAttachInWindowsTerminal(state.sessionName)) {
39
+ if (allowWt && (await launchAttachInWindowsTerminal(state.sessionName))) {
28
40
  warn(`현재 터미널에서 attach 실패: ${error.message}`);
29
41
  ok("Windows Terminal split-pane로 attach 재시도 창을 열었습니다.");
30
- console.log(` ${DIM}수동 attach 명령: ${buildManualAttachCommand(state.sessionName)}${RESET}\n`);
42
+ console.log(
43
+ ` ${DIM}수동 attach 명령: ${buildManualAttachCommand(state.sessionName)}${RESET}\n`,
44
+ );
31
45
  return;
32
46
  }
33
47
  fail(`attach 실패: ${error.message}`);
34
- warn(allowWt ? "WT 분할창 attach 자동 검증 실패 (session_attached 증가 없음)" : "자동 WT 분할은 기본 비활성입니다. 필요 시 --wt 옵션으로 실행하세요.");
35
- console.log(` ${DIM}수동 attach 명령: ${buildManualAttachCommand(state.sessionName)}${RESET}\n`);
48
+ warn(
49
+ allowWt
50
+ ? "WT 분할창 attach 자동 검증 실패 (session_attached 증가 없음)"
51
+ : "자동 WT 분할은 기본 비활성입니다. 필요 시 --wt 옵션으로 실행하세요.",
52
+ );
53
+ console.log(
54
+ ` ${DIM}수동 attach 명령: ${buildManualAttachCommand(state.sessionName)}${RESET}\n`,
55
+ );
36
56
  }
37
57
  }