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
package/hud/constants.mjs CHANGED
@@ -6,24 +6,77 @@ import { join } from "node:path";
6
6
 
7
7
  export const VERSION = "2.0";
8
8
 
9
- export const QOS_PATH = join(homedir(), ".omc", "state", "cli_qos_profile.json");
10
- export const ACCOUNTS_CONFIG_PATH = join(homedir(), ".omc", "router", "accounts.json");
11
- export const ACCOUNTS_STATE_PATH = join(homedir(), ".omc", "state", "cli_accounts_state.json");
9
+ export const QOS_PATH = join(
10
+ homedir(),
11
+ ".omc",
12
+ "state",
13
+ "cli_qos_profile.json",
14
+ );
15
+ export const ACCOUNTS_CONFIG_PATH = join(
16
+ homedir(),
17
+ ".omc",
18
+ "router",
19
+ "accounts.json",
20
+ );
21
+ export const ACCOUNTS_STATE_PATH = join(
22
+ homedir(),
23
+ ".omc",
24
+ "state",
25
+ "cli_accounts_state.json",
26
+ );
12
27
 
13
28
  // tfx-multi 상태 (v2.2 HUD 통합)
14
- export const TEAM_STATE_PATH = join(homedir(), ".claude", "cache", "tfx-hub", "team-state.json");
15
- export const CONTEXT_MONITOR_CACHE_PATH = join(homedir(), ".claude", "cache", "tfx-hub", "context-monitor.json");
16
- export const CONTEXT_MONITOR_LEGACY_PATH = join(homedir(), ".omc", "state", "context-monitor.json");
29
+ export const TEAM_STATE_PATH = join(
30
+ homedir(),
31
+ ".claude",
32
+ "cache",
33
+ "tfx-hub",
34
+ "team-state.json",
35
+ );
36
+ export const CONTEXT_MONITOR_CACHE_PATH = join(
37
+ homedir(),
38
+ ".claude",
39
+ "cache",
40
+ "tfx-hub",
41
+ "context-monitor.json",
42
+ );
43
+ export const CONTEXT_MONITOR_LEGACY_PATH = join(
44
+ homedir(),
45
+ ".omc",
46
+ "state",
47
+ "context-monitor.json",
48
+ );
17
49
  export const CONTEXT_MONITOR_LOG_DIR = join(homedir(), ".omc", "logs");
18
50
 
19
51
  // 원격 프로브 캐시 (tfx-remote-spawn)
20
- export const REMOTE_ENV_CACHE_DIR = join(homedir(), ".claude", "cache", "tfx-hub", "remote-env");
52
+ export const REMOTE_ENV_CACHE_DIR = join(
53
+ homedir(),
54
+ ".claude",
55
+ "cache",
56
+ "tfx-hub",
57
+ "remote-env",
58
+ );
21
59
  export const REMOTE_ENV_CACHE_TTL_MS = 24 * 60 * 60 * 1000; // 24시간
22
60
 
23
61
  // Claude OAuth Usage API (api.anthropic.com/api/oauth/usage)
24
- export const CLAUDE_CREDENTIALS_PATH = join(homedir(), ".claude", ".credentials.json");
25
- export const CLAUDE_USAGE_CACHE_PATH = join(homedir(), ".claude", "cache", "claude-usage-cache.json");
26
- export const OMC_PLUGIN_USAGE_CACHE_PATH = join(homedir(), ".claude", "plugins", "oh-my-claudecode", ".usage-cache.json");
62
+ export const CLAUDE_CREDENTIALS_PATH = join(
63
+ homedir(),
64
+ ".claude",
65
+ ".credentials.json",
66
+ );
67
+ export const CLAUDE_USAGE_CACHE_PATH = join(
68
+ homedir(),
69
+ ".claude",
70
+ "cache",
71
+ "claude-usage-cache.json",
72
+ );
73
+ export const OMC_PLUGIN_USAGE_CACHE_PATH = join(
74
+ homedir(),
75
+ ".claude",
76
+ "plugins",
77
+ "oh-my-claudecode",
78
+ ".usage-cache.json",
79
+ );
27
80
  export const CLAUDE_USAGE_STALE_MS_SOLO = 5 * 60 * 1000; // OMC 없을 때: 5분 캐시
28
81
  export const CLAUDE_USAGE_STALE_MS_WITH_OMC = 15 * 60 * 1000; // OMC 있을 때: 15분 (OMC가 30초마다 갱신)
29
82
  export const CLAUDE_USAGE_429_BACKOFF_MS = 10 * 60 * 1000; // 429 에러 시 10분 backoff
@@ -38,29 +91,105 @@ export const ONE_DAY_MS = 24 * 60 * 60 * 1000;
38
91
  export const DEFAULT_OAUTH_CLIENT_ID = "9d1c250a-e61b-44d9-88ed-5944d1962f5e";
39
92
 
40
93
  export const CODEX_AUTH_PATH = join(homedir(), ".codex", "auth.json");
41
- export const CODEX_QUOTA_CACHE_PATH = join(homedir(), ".claude", "cache", "codex-rate-limits-cache.json");
94
+ export const CODEX_QUOTA_CACHE_PATH = join(
95
+ homedir(),
96
+ ".claude",
97
+ "cache",
98
+ "codex-rate-limits-cache.json",
99
+ );
42
100
  export const CODEX_QUOTA_STALE_MS = 30 * 1000; // 30초
43
101
  export const CODEX_MIN_BUCKETS = 2;
44
102
 
45
103
  // Spawn lock (중복 refresh 방지)
46
- export const CODEX_REFRESH_LOCK_PATH = join(homedir(), ".claude", "cache", ".codex-refresh-lock");
47
- export const GEMINI_QUOTA_REFRESH_LOCK_PATH = join(homedir(), ".claude", "cache", ".gemini-quota-refresh-lock");
48
- export const GEMINI_SESSION_REFRESH_LOCK_PATH = join(homedir(), ".claude", "cache", ".gemini-session-refresh-lock");
104
+ export const CLAUDE_REFRESH_LOCK_PATH = join(
105
+ homedir(),
106
+ ".claude",
107
+ "cache",
108
+ ".claude-refresh-lock",
109
+ );
110
+ export const CODEX_REFRESH_LOCK_PATH = join(
111
+ homedir(),
112
+ ".claude",
113
+ "cache",
114
+ ".codex-refresh-lock",
115
+ );
116
+ export const GEMINI_QUOTA_REFRESH_LOCK_PATH = join(
117
+ homedir(),
118
+ ".claude",
119
+ "cache",
120
+ ".gemini-quota-refresh-lock",
121
+ );
122
+ export const GEMINI_SESSION_REFRESH_LOCK_PATH = join(
123
+ homedir(),
124
+ ".claude",
125
+ "cache",
126
+ ".gemini-session-refresh-lock",
127
+ );
49
128
  export const SPAWN_LOCK_TTL_MS = 30 * 1000; // 30초 spawn dedup
50
129
 
51
130
  // Gemini 쿼터 API 관련
52
131
  export const GEMINI_OAUTH_PATH = join(homedir(), ".gemini", "oauth_creds.json");
53
- export const GEMINI_QUOTA_CACHE_PATH = join(homedir(), ".claude", "cache", "gemini-quota-cache.json");
54
- export const GEMINI_PROJECT_CACHE_PATH = join(homedir(), ".claude", "cache", "gemini-project-id.json");
55
- export const GEMINI_SESSION_CACHE_PATH = join(homedir(), ".claude", "cache", "gemini-session-cache.json");
56
- export const GEMINI_RPM_TRACKER_PATH = join(homedir(), ".claude", "cache", "gemini-rpm-tracker.json");
57
- export const SV_ACCUMULATOR_PATH = join(homedir(), ".claude", "cache", "sv-accumulator.json");
132
+ export const GEMINI_QUOTA_CACHE_PATH = join(
133
+ homedir(),
134
+ ".claude",
135
+ "cache",
136
+ "gemini-quota-cache.json",
137
+ );
138
+ export const GEMINI_PROJECT_CACHE_PATH = join(
139
+ homedir(),
140
+ ".claude",
141
+ "cache",
142
+ "gemini-project-id.json",
143
+ );
144
+ export const GEMINI_SESSION_CACHE_PATH = join(
145
+ homedir(),
146
+ ".claude",
147
+ "cache",
148
+ "gemini-session-cache.json",
149
+ );
150
+ export const GEMINI_RPM_TRACKER_PATH = join(
151
+ homedir(),
152
+ ".claude",
153
+ "cache",
154
+ "gemini-rpm-tracker.json",
155
+ );
156
+ export const SV_ACCUMULATOR_PATH = join(
157
+ homedir(),
158
+ ".claude",
159
+ "cache",
160
+ "sv-accumulator.json",
161
+ );
58
162
  // 이전 .omc/ 경로 fallback (기존 환경 호환)
59
- export const LEGACY_GEMINI_QUOTA_CACHE = join(homedir(), ".omc", "state", "gemini_quota_cache.json");
60
- export const LEGACY_GEMINI_PROJECT_CACHE = join(homedir(), ".omc", "state", "gemini_project_id.json");
61
- export const LEGACY_GEMINI_SESSION_CACHE = join(homedir(), ".omc", "state", "gemini_session_tokens_cache.json");
62
- export const LEGACY_GEMINI_RPM_TRACKER = join(homedir(), ".omc", "state", "gemini_rpm_tracker.json");
63
- export const LEGACY_SV_ACCUMULATOR = join(homedir(), ".omc", "state", "sv-accumulator.json");
163
+ export const LEGACY_GEMINI_QUOTA_CACHE = join(
164
+ homedir(),
165
+ ".omc",
166
+ "state",
167
+ "gemini_quota_cache.json",
168
+ );
169
+ export const LEGACY_GEMINI_PROJECT_CACHE = join(
170
+ homedir(),
171
+ ".omc",
172
+ "state",
173
+ "gemini_project_id.json",
174
+ );
175
+ export const LEGACY_GEMINI_SESSION_CACHE = join(
176
+ homedir(),
177
+ ".omc",
178
+ "state",
179
+ "gemini_session_tokens_cache.json",
180
+ );
181
+ export const LEGACY_GEMINI_RPM_TRACKER = join(
182
+ homedir(),
183
+ ".omc",
184
+ "state",
185
+ "gemini_rpm_tracker.json",
186
+ );
187
+ export const LEGACY_SV_ACCUMULATOR = join(
188
+ homedir(),
189
+ ".omc",
190
+ "state",
191
+ "sv-accumulator.json",
192
+ );
64
193
 
65
194
  export const GEMINI_RPM_WINDOW_MS = 60 * 1000; // 60초 슬라이딩 윈도우
66
195
  export const GEMINI_QUOTA_STALE_MS = 5 * 60 * 1000; // 5분
@@ -90,5 +219,12 @@ export const ROWS_BUDGET_MEDIUM = 28;
90
219
  export const ROWS_BUDGET_SMALL = 22;
91
220
 
92
221
  // Gemini Pro 풀 공유 그룹: 같은 remainingFraction을 공유하는 모델 ID들
93
- export const GEMINI_PRO_POOL = new Set(["gemini-2.5-pro", "gemini-3-pro-preview", "gemini-3.1-pro-preview"]);
94
- export const GEMINI_FLASH_POOL = new Set(["gemini-2.5-flash", "gemini-3-flash-preview"]);
222
+ export const GEMINI_PRO_POOL = new Set([
223
+ "gemini-2.5-pro",
224
+ "gemini-3-pro-preview",
225
+ "gemini-3.1-pro-preview",
226
+ ]);
227
+ export const GEMINI_FLASH_POOL = new Set([
228
+ "gemini-2.5-flash",
229
+ "gemini-3-flash-preview",
230
+ ]);
@@ -1,7 +1,6 @@
1
+ import { randomUUID } from "node:crypto";
1
2
  import { mkdirSync, writeFileSync } from "node:fs";
2
3
  import { dirname, join } from "node:path";
3
- import { randomUUID } from "node:crypto";
4
- import { homedir } from "node:os";
5
4
 
6
5
  import {
7
6
  CONTEXT_MONITOR_CACHE_PATH,
@@ -72,21 +71,24 @@ function normalizeUsage(usage) {
72
71
  const input = Number(usage.input_tokens ?? usage.inputTokens ?? 0);
73
72
  const output = Number(usage.output_tokens ?? usage.outputTokens ?? 0);
74
73
  const cacheCreation = Number(
75
- usage.cache_creation_input_tokens
76
- ?? usage.cacheCreationInputTokens
77
- ?? usage.cache_creation_tokens
78
- ?? 0,
74
+ usage.cache_creation_input_tokens ??
75
+ usage.cacheCreationInputTokens ??
76
+ usage.cache_creation_tokens ??
77
+ 0,
79
78
  );
80
79
  const cacheRead = Number(
81
- usage.cache_read_input_tokens
82
- ?? usage.cacheReadInputTokens
83
- ?? usage.cache_read_tokens
84
- ?? 0,
80
+ usage.cache_read_input_tokens ??
81
+ usage.cacheReadInputTokens ??
82
+ usage.cache_read_tokens ??
83
+ 0,
84
+ );
85
+ const totalCandidate = Number(
86
+ usage.total_tokens ?? usage.totalTokens ?? Number.NaN,
85
87
  );
86
- const totalCandidate = Number(usage.total_tokens ?? usage.totalTokens ?? Number.NaN);
87
- const total = Number.isFinite(totalCandidate) && totalCandidate > 0
88
- ? totalCandidate
89
- : input + output + cacheCreation + cacheRead;
88
+ const total =
89
+ Number.isFinite(totalCandidate) && totalCandidate > 0
90
+ ? totalCandidate
91
+ : input + output + cacheCreation + cacheRead;
90
92
  if (!Number.isFinite(total) || total <= 0) return null;
91
93
  return {
92
94
  input: Math.max(0, Math.round(input)),
@@ -159,7 +161,10 @@ function extractFileKeys(args) {
159
161
  function detectSkillHints(payloadText) {
160
162
  if (!payloadText) return [];
161
163
  const matches = payloadText.match(/\$[a-z0-9_-]+/gi) || [];
162
- return Array.from(new Set(matches.map((m) => m.replace(/^\$/, "")))).slice(0, 5);
164
+ return Array.from(new Set(matches.map((m) => m.replace(/^\$/, "")))).slice(
165
+ 0,
166
+ 5,
167
+ );
163
168
  }
164
169
 
165
170
  export function estimateTokens(input) {
@@ -172,21 +177,34 @@ export function parseUsageFromPayload(payload) {
172
177
 
173
178
  export function classifyContextThreshold(percent) {
174
179
  const p = clampThresholdPercent(percent);
175
- if (p >= WARNING_LEVELS.critical.min) return { level: "critical", message: WARNING_LEVELS.critical.message };
176
- if (p >= WARNING_LEVELS.warn.min) return { level: "warn", message: WARNING_LEVELS.warn.message };
177
- if (p >= WARNING_LEVELS.info.min) return { level: "info", message: WARNING_LEVELS.info.message };
180
+ if (p >= WARNING_LEVELS.critical.min)
181
+ return { level: "critical", message: WARNING_LEVELS.critical.message };
182
+ if (p >= WARNING_LEVELS.warn.min)
183
+ return { level: "warn", message: WARNING_LEVELS.warn.message };
184
+ if (p >= WARNING_LEVELS.info.min)
185
+ return { level: "info", message: WARNING_LEVELS.info.message };
178
186
  return { level: "ok", message: "" };
179
187
  }
180
188
 
181
189
  export function formatContextUsage(usedTokens, limitTokens, percent = null) {
182
190
  const used = Math.max(0, Math.round(Number(usedTokens) || 0));
183
- const limit = Math.max(1, Math.round(Number(limitTokens) || DEFAULT_CONTEXT_LIMIT));
184
- const pct = percent == null ? clampPercent((used / limit) * 100) : clampPercent(percent);
191
+ const limit = Math.max(
192
+ 1,
193
+ Math.round(Number(limitTokens) || DEFAULT_CONTEXT_LIMIT),
194
+ );
195
+ const pct =
196
+ percent == null
197
+ ? clampPercent((used / limit) * 100)
198
+ : clampPercent(percent);
185
199
  return `${formatTokenCount(used)}/${formatTokenCount(limit)} (${pct}%)`;
186
200
  }
187
201
 
188
202
  export function readContextMonitorSnapshot() {
189
- return readJsonMigrate(CONTEXT_MONITOR_CACHE_PATH, CONTEXT_MONITOR_LEGACY_PATH, null);
203
+ return readJsonMigrate(
204
+ CONTEXT_MONITOR_CACHE_PATH,
205
+ CONTEXT_MONITOR_LEGACY_PATH,
206
+ null,
207
+ );
190
208
  }
191
209
 
192
210
  function getStdinContextUsage(stdin) {
@@ -194,9 +212,10 @@ function getStdinContextUsage(stdin) {
194
212
  const nativePercent = Number(stdin?.context_window?.used_percentage);
195
213
  const usage = stdin?.context_window?.current_usage || {};
196
214
  const explicitUsed = Number(usage.total_tokens || 0);
197
- const calculatedUsed = Number(usage.input_tokens || 0)
198
- + Number(usage.cache_creation_input_tokens || 0)
199
- + Number(usage.cache_read_input_tokens || 0);
215
+ const calculatedUsed =
216
+ Number(usage.input_tokens || 0) +
217
+ Number(usage.cache_creation_input_tokens || 0) +
218
+ Number(usage.cache_read_input_tokens || 0);
200
219
  const usedTokens = explicitUsed > 0 ? explicitUsed : calculatedUsed;
201
220
 
202
221
  if (limitTokens > 0 && usedTokens > 0) {
@@ -225,12 +244,11 @@ export function buildContextUsageView(stdin, snapshot = null) {
225
244
  const monitor = snapshot || readContextMonitorSnapshot();
226
245
  const fallbackLimit = Number(monitor?.limitTokens || DEFAULT_CONTEXT_LIMIT);
227
246
 
228
- const usedTokens = stdinUsage?.usedTokens
229
- ?? Number(monitor?.usedTokens || 0);
230
- const limitTokens = stdinUsage?.limitTokens
231
- ?? Math.max(1, fallbackLimit);
232
- const percent = stdinUsage?.percent
233
- ?? (limitTokens > 0 ? clampPercent((usedTokens / limitTokens) * 100) : 0);
247
+ const usedTokens = stdinUsage?.usedTokens ?? Number(monitor?.usedTokens || 0);
248
+ const limitTokens = stdinUsage?.limitTokens ?? Math.max(1, fallbackLimit);
249
+ const percent =
250
+ stdinUsage?.percent ??
251
+ (limitTokens > 0 ? clampPercent((usedTokens / limitTokens) * 100) : 0);
234
252
 
235
253
  const warning = classifyContextThreshold(percent);
236
254
  return {
@@ -240,10 +258,14 @@ export function buildContextUsageView(stdin, snapshot = null) {
240
258
  display: formatContextUsage(usedTokens, limitTokens, percent),
241
259
  warningLevel: warning.level,
242
260
  warningMessage: warning.message,
243
- warningTag: warning.level === "warn" ? "⚠ 압축 권장"
244
- : warning.level === "critical" ? "‼ 분할 권장"
245
- : warning.level === "info" ? " 절반 이상 사용"
246
- : "",
261
+ warningTag:
262
+ warning.level === "warn"
263
+ ? " 압축 권장"
264
+ : warning.level === "critical"
265
+ ? "‼ 분할 권장"
266
+ : warning.level === "info"
267
+ ? "ℹ 절반 이상 사용"
268
+ : "",
247
269
  source: stdinUsage?.source || (monitor ? "monitor" : "none"),
248
270
  };
249
271
  }
@@ -295,7 +317,10 @@ export function createContextMonitor(options = {}) {
295
317
  const percent = clampPercent((state.usedTokens / state.limitTokens) * 100);
296
318
  const warning = classifyContextThreshold(percent);
297
319
  const ts = new Date().toISOString().replace(/[:.]/g, "-");
298
- const reportPath = join(logsDir, `context-usage-${state.sessionId}-${ts}.json`);
320
+ const reportPath = join(
321
+ logsDir,
322
+ `context-usage-${state.sessionId}-${ts}.json`,
323
+ );
299
324
  safeWriteJson(reportPath, {
300
325
  sessionId: state.sessionId,
301
326
  reason,
@@ -329,17 +354,31 @@ export function createContextMonitor(options = {}) {
329
354
  toolName = "",
330
355
  } = {}) => {
331
356
  const started = process.hrtime.bigint();
332
- const reqObj = typeof requestBody === "object" ? requestBody : safeJsonParse(String(requestBody || ""));
333
- const resObj = typeof responseBody === "object" ? responseBody : safeJsonParse(String(responseBody || ""));
357
+ const reqObj =
358
+ typeof requestBody === "object"
359
+ ? requestBody
360
+ : safeJsonParse(String(requestBody || ""));
361
+ const resObj =
362
+ typeof responseBody === "object"
363
+ ? responseBody
364
+ : safeJsonParse(String(responseBody || ""));
334
365
 
335
366
  const usage = parseUsageFromPayload(resObj);
336
- const requestTokens = requestBytes > 0 ? toTokenEstimate(requestBytes) : toTokenEstimate(requestBody);
337
- const responseTokens = usage?.total ?? (responseBytes > 0 ? toTokenEstimate(responseBytes) : toTokenEstimate(responseBody));
367
+ const requestTokens =
368
+ requestBytes > 0
369
+ ? toTokenEstimate(requestBytes)
370
+ : toTokenEstimate(requestBody);
371
+ const responseTokens =
372
+ usage?.total ??
373
+ (responseBytes > 0
374
+ ? toTokenEstimate(responseBytes)
375
+ : toTokenEstimate(responseBody));
338
376
  const totalTokens = Math.max(0, requestTokens + responseTokens);
339
377
 
340
378
  const method = reqObj?.method || reqObj?.params?.name || "";
341
379
  const name = toolName || reqObj?.params?.name || reqObj?.tool || "";
342
- const args = reqObj?.params?.arguments || reqObj?.arguments || reqObj?.params || {};
380
+ const args =
381
+ reqObj?.params?.arguments || reqObj?.arguments || reqObj?.params || {};
343
382
  const payloadText = normalizeText(requestBody).slice(0, MAX_CAPTURE_BYTES);
344
383
  const skills = detectSkillHints(payloadText);
345
384
  const files = extractFileKeys(args);
@@ -383,7 +422,9 @@ export function createContextMonitor(options = {}) {
383
422
 
384
423
  if (registerExitHooks) {
385
424
  const flushOnExit = () => {
386
- try { flush("process.exit"); } catch {}
425
+ try {
426
+ flush("process.exit");
427
+ } catch {}
387
428
  };
388
429
  process.once("exit", flushOnExit);
389
430
  process.once("SIGINT", flushOnExit);