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.
- package/LICENSE +21 -21
- package/bin/tfx-doctor-tui.mjs +1 -1
- package/bin/tfx-doctor.mjs +6 -1
- package/bin/tfx-profile.mjs +1 -1
- package/bin/tfx-setup-tui.mjs +1 -1
- package/bin/tfx-setup.mjs +6 -1
- package/bin/triflux.mjs +2396 -1140
- package/hooks/agent-route-guard.mjs +12 -8
- package/hooks/cross-review-tracker.mjs +21 -8
- package/hooks/error-context.mjs +19 -7
- package/hooks/hook-adaptive-collector.mjs +18 -16
- package/hooks/hook-manager.mjs +93 -32
- package/hooks/hook-orchestrator.mjs +108 -24
- package/hooks/hook-registry.json +11 -0
- package/hooks/keyword-rules.json +6 -10
- package/hooks/lib/resolve-root.mjs +1 -1
- package/hooks/mcp-config-watcher.mjs +6 -2
- package/hooks/pipeline-stop.mjs +3 -6
- package/hooks/safety-guard.mjs +99 -28
- package/hooks/session-start-fast.mjs +143 -0
- package/hooks/subagent-verifier.mjs +5 -4
- package/hub/account-broker.mjs +256 -60
- package/hub/adaptive-diagnostic.mjs +75 -48
- package/hub/adaptive-inject.mjs +95 -57
- package/hub/adaptive-memory.mjs +156 -42
- package/hub/adaptive.mjs +60 -31
- package/hub/assign-callbacks.mjs +67 -30
- package/hub/bridge.mjs +0 -1
- package/hub/cli-adapter-base.mjs +200 -48
- package/hub/codex-adapter.mjs +76 -96
- package/hub/codex-compat.mjs +3 -3
- package/hub/codex-preflight.mjs +63 -37
- package/hub/delegator/contracts.mjs +19 -23
- package/hub/delegator/index.mjs +3 -3
- package/hub/delegator/service.mjs +88 -64
- package/hub/delegator/tool-definitions.mjs +5 -5
- package/hub/fullcycle.mjs +33 -17
- package/hub/gemini-adapter.mjs +69 -94
- package/hub/hitl.mjs +89 -30
- package/hub/intent.mjs +161 -38
- package/hub/lib/cache-guard.mjs +43 -17
- package/hub/lib/mcp-response-cache.mjs +66 -32
- package/hub/lib/memory-store.mjs +285 -111
- package/hub/lib/path-utils.mjs +35 -37
- package/hub/lib/process-utils.mjs +106 -37
- package/hub/lib/spawn-trace.mjs +527 -0
- package/hub/lib/ssh-command.mjs +34 -4
- package/hub/lib/ssh-retry.mjs +5 -1
- package/hub/lib/uuidv7.mjs +4 -3
- package/hub/memory-doctor.mjs +266 -106
- package/hub/middleware/request-logger.mjs +61 -34
- package/hub/paths.mjs +9 -9
- package/hub/pipeline/gates/confidence.mjs +34 -15
- package/hub/pipeline/gates/consensus.mjs +27 -15
- package/hub/pipeline/gates/index.mjs +7 -3
- package/hub/pipeline/gates/selfcheck.mjs +57 -19
- package/hub/pipeline/index.mjs +77 -42
- package/hub/pipeline/state.mjs +10 -10
- package/hub/pipeline/transitions.mjs +40 -23
- package/hub/platform.mjs +57 -48
- package/hub/promote-penalties.mjs +25 -7
- package/hub/quality/deslop.mjs +70 -49
- package/hub/research.mjs +32 -25
- package/hub/router.mjs +240 -107
- package/hub/routing/complexity.mjs +132 -29
- package/hub/routing/index.mjs +17 -12
- package/hub/routing/q-learning.mjs +76 -28
- package/hub/server.mjs +4 -4
- package/hub/session-fingerprint.mjs +126 -60
- package/hub/state.mjs +84 -43
- package/hub/store-adapter.mjs +59 -26
- package/hub/store.mjs +356 -153
- package/hub/team/agent-map.json +22 -7
- package/hub/team/ansi.mjs +186 -122
- package/hub/team/backend.mjs +28 -10
- package/hub/team/cli/commands/attach.mjs +29 -9
- package/hub/team/cli/commands/control.mjs +29 -8
- package/hub/team/cli/commands/debug.mjs +32 -11
- package/hub/team/cli/commands/focus.mjs +38 -11
- package/hub/team/cli/commands/interrupt.mjs +18 -6
- package/hub/team/cli/commands/kill.mjs +16 -5
- package/hub/team/cli/commands/list.mjs +11 -4
- package/hub/team/cli/commands/send.mjs +19 -6
- package/hub/team/cli/commands/start/index.mjs +154 -31
- package/hub/team/cli/commands/start/parse-args.mjs +38 -11
- package/hub/team/cli/commands/start/start-headless.mjs +112 -36
- package/hub/team/cli/commands/start/start-in-process.mjs +12 -2
- package/hub/team/cli/commands/start/start-mux.mjs +70 -21
- package/hub/team/cli/commands/start/start-wt.mjs +29 -12
- package/hub/team/cli/commands/status.mjs +43 -14
- package/hub/team/cli/commands/stop.mjs +11 -4
- package/hub/team/cli/commands/task.mjs +8 -3
- package/hub/team/cli/commands/tasks.mjs +1 -1
- package/hub/team/cli/index.mjs +2 -2
- package/hub/team/cli/manifest.mjs +38 -8
- package/hub/team/cli/render.mjs +30 -8
- package/hub/team/cli/services/attach-fallback.mjs +31 -11
- package/hub/team/cli/services/hub-client.mjs +42 -14
- package/hub/team/cli/services/member-selector.mjs +11 -4
- package/hub/team/cli/services/native-control.mjs +48 -21
- package/hub/team/cli/services/runtime-mode.mjs +2 -1
- package/hub/team/cli/services/state-store.mjs +25 -8
- package/hub/team/cli/services/task-model.mjs +16 -6
- package/hub/team/conductor-mesh-bridge.mjs +24 -23
- package/hub/team/conductor.mjs +8 -4
- package/hub/team/dashboard-anchor.mjs +4 -5
- package/hub/team/dashboard-layout.mjs +3 -1
- package/hub/team/dashboard-open.mjs +41 -21
- package/hub/team/dashboard.mjs +76 -28
- package/hub/team/event-log.mjs +18 -10
- package/hub/team/handoff.mjs +31 -15
- package/hub/team/headless.mjs +2 -1
- package/hub/team/health-probe.mjs +69 -54
- package/hub/team/launcher-template.mjs +16 -13
- package/hub/team/native-supervisor.mjs +65 -21
- package/hub/team/native.mjs +74 -35
- package/hub/team/nativeProxy.mjs +184 -113
- package/hub/team/notify.mjs +119 -76
- package/hub/team/orchestrator.mjs +9 -4
- package/hub/team/pane.mjs +12 -7
- package/hub/team/process-cleanup.mjs +25 -16
- package/hub/team/psmux.mjs +491 -201
- package/hub/team/remote-probe.mjs +68 -52
- package/hub/team/remote-session.mjs +117 -59
- package/hub/team/remote-watcher.mjs +61 -33
- package/hub/team/routing.mjs +51 -25
- package/hub/team/runtime-strategy.mjs +3 -1
- package/hub/team/session.mjs +98 -34
- package/hub/team/staleState.mjs +72 -30
- package/hub/team/swarm-locks.mjs +15 -13
- package/hub/team/swarm-planner.mjs +32 -21
- package/hub/team/swarm-reconciler.mjs +48 -23
- package/hub/team/tui-lite.mjs +266 -68
- package/hub/team/tui-remote-adapter.mjs +14 -10
- package/hub/team/tui-viewer.mjs +99 -43
- package/hub/team/tui.mjs +708 -271
- package/hub/team/worktree-lifecycle.mjs +152 -58
- package/hub/team/wt-manager.mjs +24 -14
- package/hub/token-mode.mjs +71 -71
- package/hub/tray.mjs +66 -23
- package/hub/workers/claude-worker.mjs +162 -118
- package/hub/workers/codex-mcp.mjs +192 -141
- package/hub/workers/delegator-mcp.mjs +507 -333
- package/hub/workers/factory.mjs +8 -8
- package/hub/workers/gemini-worker.mjs +115 -84
- package/hub/workers/interface.mjs +6 -1
- package/hub/workers/worker-utils.mjs +21 -14
- package/hud/colors.mjs +27 -9
- package/hud/constants.mjs +162 -26
- package/hud/context-monitor.mjs +82 -41
- package/hud/hud-qos-status.mjs +129 -49
- package/hud/mission-board.mjs +6 -3
- package/hud/providers/claude.mjs +226 -115
- package/hud/providers/codex.mjs +62 -22
- package/hud/providers/gemini.mjs +168 -56
- package/hud/renderers.mjs +384 -119
- package/hud/terminal.mjs +101 -31
- package/hud/utils.mjs +78 -38
- package/mesh/index.mjs +11 -5
- package/mesh/mesh-budget.mjs +18 -9
- package/mesh/mesh-heartbeat.mjs +1 -1
- package/mesh/mesh-queue.mjs +3 -5
- package/mesh/mesh-router.mjs +5 -4
- package/package.json +2 -1
- package/scripts/__tests__/gen-skill-docs.test.mjs +36 -7
- package/scripts/__tests__/keyword-detector.test.mjs +77 -28
- package/scripts/__tests__/mcp-guard-engine.test.mjs +58 -20
- package/scripts/__tests__/remote-spawn-transfer.test.mjs +30 -19
- package/scripts/__tests__/remote-spawn.test.mjs +10 -4
- package/scripts/__tests__/session-start-fast.test.mjs +36 -0
- package/scripts/__tests__/skill-template.test.mjs +98 -50
- package/scripts/__tests__/smoke.test.mjs +1 -1
- package/scripts/__tests__/spawn-trace.test.mjs +102 -0
- package/scripts/__tests__/tfx-doctor-diagnose.test.mjs +48 -0
- package/scripts/cache-doctor.mjs +11 -4
- package/scripts/cache-warmup.mjs +96 -37
- package/scripts/claudemd-sync.mjs +27 -17
- package/scripts/codex-gateway-preflight.mjs +52 -37
- package/scripts/codex-mcp-gateway-sync.mjs +59 -39
- package/scripts/completions/tfx.bash +47 -47
- package/scripts/completions/tfx.fish +44 -44
- package/scripts/completions/tfx.zsh +83 -83
- package/scripts/config-audit.mjs +232 -0
- package/scripts/convert-to-tmpl.mjs +54 -0
- package/scripts/cross-review-gate.mjs +35 -12
- package/scripts/cross-review-tracker.mjs +21 -8
- package/scripts/demo.mjs +35 -17
- package/scripts/doctor-diagnose.mjs +284 -0
- package/scripts/gen-skill-docs.mjs +7 -2
- package/scripts/gen-skill-manifest.mjs +2 -1
- package/scripts/headless-guard.mjs +86 -48
- package/scripts/hub-ensure.mjs +45 -26
- package/scripts/keyword-detector.mjs +41 -20
- package/scripts/keyword-rules-expander.mjs +47 -30
- package/scripts/lib/claudemd-scanner.mjs +6 -1
- package/scripts/lib/context.mjs +3 -3
- package/scripts/lib/cross-review-utils.mjs +6 -3
- package/scripts/lib/env-probe.mjs +47 -28
- package/scripts/lib/gemini-profiles.mjs +44 -10
- package/scripts/lib/handoff.mjs +33 -17
- package/scripts/lib/hook-utils.mjs +8 -6
- package/scripts/lib/keyword-rules.mjs +43 -19
- package/scripts/lib/logger.mjs +24 -24
- package/scripts/lib/mcp-filter.mjs +377 -239
- package/scripts/lib/mcp-guard-engine.mjs +194 -79
- package/scripts/lib/mcp-manifest.mjs +23 -13
- package/scripts/lib/mcp-server-catalog.mjs +300 -63
- package/scripts/lib/psmux-info.mjs +11 -6
- package/scripts/lib/remote-spawn-transfer.mjs +44 -14
- package/scripts/lib/skill-template.mjs +30 -7
- package/scripts/mcp-check.mjs +58 -39
- package/scripts/mcp-gateway-config.mjs +83 -39
- package/scripts/mcp-gateway-ensure.mjs +43 -35
- package/scripts/mcp-gateway-integration-test.mjs +70 -58
- package/scripts/mcp-gateway-start.mjs +126 -60
- package/scripts/mcp-gateway-verify.mjs +24 -22
- package/scripts/mcp-safety-guard.mjs +44 -11
- package/scripts/notion-read.mjs +199 -84
- package/scripts/pack.mjs +94 -89
- package/scripts/preflight-cache.mjs +27 -10
- package/scripts/preinstall.mjs +42 -13
- package/scripts/remote-spawn.mjs +309 -94
- package/scripts/run.cjs +8 -5
- package/scripts/session-spawn-helper.mjs +130 -39
- package/scripts/session-stale-cleanup.mjs +123 -0
- package/scripts/setup.mjs +941 -492
- package/scripts/test-lock.mjs +20 -7
- package/scripts/test-tfx-route-no-claude-native.mjs +16 -12
- package/scripts/tfx-batch-stats.mjs +32 -11
- package/scripts/tfx-gate-activate.mjs +11 -4
- package/scripts/tfx-route-post.mjs +87 -20
- package/scripts/tfx-route-worker.mjs +57 -51
- package/scripts/tfx-route.sh +41 -124
- package/scripts/tmp-cleanup.mjs +21 -7
- package/scripts/token-snapshot.mjs +204 -85
- package/skills/.omc/state/agent-replay-8f0e10a9-9693-4410-96f5-a6b07e8ed995.jsonl +1 -0
- package/skills/.omc/state/idle-notif-cooldown.json +3 -0
- package/skills/.omc/state/last-tool-error.json +7 -0
- package/skills/.omc/state/subagent-tracking.json +7 -0
- package/skills/_templates/base.md +1 -6
- package/skills/merge-worktree/SKILL.md.tmpl +144 -0
- package/skills/shared/telemetry-segment.md +6 -0
- package/skills/star-prompt/SKILL.md.tmpl +222 -0
- package/skills/tfx-analysis/SKILL.md.tmpl +107 -0
- package/skills/tfx-analysis/skill.json +1 -6
- package/skills/tfx-auto/SKILL.md +1 -0
- package/skills/tfx-auto-codex/SKILL.md.tmpl +106 -0
- package/skills/tfx-auto-codex/skill.json +1 -3
- package/skills/tfx-autopilot/SKILL.md.tmpl +116 -0
- package/skills/tfx-autopilot/skill.json +1 -5
- package/skills/tfx-autoresearch/SKILL.md.tmpl +136 -0
- package/skills/tfx-autoroute/SKILL.md.tmpl +189 -0
- package/skills/tfx-autoroute/skill.json +1 -7
- package/skills/tfx-codex/SKILL.md +1 -0
- package/skills/tfx-codex/skill.json +1 -3
- package/skills/tfx-codex-swarm/SKILL.md.tmpl +16 -0
- package/skills/tfx-codex-swarm/evals/evals.json +1 -1
- package/skills/tfx-codex-swarm/skill.json +1 -4
- package/skills/tfx-codex-swarm-workspace/iteration-1/benchmark.json +54 -12
- package/skills/tfx-codex-swarm-workspace/iteration-1/full-swarm-all-prds/with_skill/grading.json +35 -7
- package/skills/tfx-codex-swarm-workspace/iteration-1/full-swarm-all-prds/without_skill/grading.json +35 -7
- package/skills/tfx-codex-swarm-workspace/iteration-1/implicit-swarm-no-keywords/with_skill/grading.json +25 -5
- package/skills/tfx-codex-swarm-workspace/iteration-1/implicit-swarm-no-keywords/without_skill/grading.json +25 -5
- package/skills/tfx-codex-swarm-workspace/iteration-1/selective-spawn-with-override/with_skill/grading.json +20 -4
- package/skills/tfx-codex-swarm-workspace/iteration-1/selective-spawn-with-override/without_skill/grading.json +16 -4
- package/skills/tfx-consensus/SKILL.md.tmpl +146 -0
- package/skills/tfx-debate/SKILL.md.tmpl +192 -0
- package/skills/tfx-debate/skill.json +1 -7
- package/skills/tfx-deep-analysis/SKILL.md.tmpl +228 -0
- package/skills/tfx-deep-analysis/skill.json +1 -5
- package/skills/tfx-deep-interview/SKILL.md.tmpl +203 -0
- package/skills/tfx-deep-plan/SKILL.md.tmpl +282 -0
- package/skills/tfx-deep-qa/SKILL.md.tmpl +165 -0
- package/skills/tfx-deep-qa/skill.json +1 -6
- package/skills/tfx-deep-research/SKILL.md.tmpl +217 -0
- package/skills/tfx-deep-review/SKILL.md.tmpl +179 -0
- package/skills/tfx-doctor/SKILL.md +21 -0
- package/skills/tfx-doctor/SKILL.md.tmpl +172 -0
- package/skills/tfx-doctor/skill.json +1 -3
- package/skills/tfx-find/SKILL.md +1 -0
- package/skills/tfx-forge/SKILL.md.tmpl +187 -0
- package/skills/tfx-fullcycle/SKILL.md.tmpl +286 -0
- package/skills/tfx-fullcycle/skill.json +1 -6
- package/skills/tfx-gemini/SKILL.md.tmpl +91 -0
- package/skills/tfx-gemini/skill.json +1 -3
- package/skills/tfx-hooks/SKILL.md.tmpl +216 -0
- package/skills/tfx-hooks/skill.json +1 -3
- package/skills/tfx-hub/SKILL.md.tmpl +212 -0
- package/skills/tfx-hub/skill.json +1 -3
- package/skills/tfx-index/SKILL.md +1 -0
- package/skills/tfx-index/skill.json +1 -6
- package/skills/tfx-interview/SKILL.md.tmpl +285 -0
- package/skills/tfx-multi/SKILL.md.tmpl +183 -0
- package/skills/tfx-multi/skill.json +1 -3
- package/skills/tfx-panel/SKILL.md.tmpl +189 -0
- package/skills/tfx-panel/skill.json +1 -7
- package/skills/tfx-persist/SKILL.md.tmpl +270 -0
- package/skills/tfx-persist/skill.json +1 -7
- package/skills/tfx-plan/SKILL.md +1 -0
- package/skills/tfx-plan/skill.json +1 -6
- package/skills/tfx-profile/SKILL.md.tmpl +239 -0
- package/skills/tfx-profile/skill.json +1 -3
- package/skills/tfx-prune/SKILL.md.tmpl +200 -0
- package/skills/tfx-prune/skill.json +1 -7
- package/skills/tfx-psmux-rules/SKILL.md.tmpl +326 -0
- package/skills/tfx-psmux-rules/skill.json +1 -4
- package/skills/tfx-qa/SKILL.md +1 -0
- package/skills/tfx-qa/skill.json +1 -6
- package/skills/tfx-ralph/SKILL.md.tmpl +28 -0
- package/skills/tfx-ralph/skill.json +1 -4
- package/skills/tfx-remote-setup/SKILL.md.tmpl +576 -0
- package/skills/tfx-remote-setup/skill.json +1 -3
- package/skills/tfx-remote-spawn/SKILL.md.tmpl +263 -0
- package/skills/tfx-remote-spawn/references/hosts.json +16 -0
- package/skills/tfx-remote-spawn/skill.json +1 -4
- package/skills/tfx-research/SKILL.md +1 -0
- package/skills/tfx-review/SKILL.md +1 -0
- package/skills/tfx-review/skill.json +1 -6
- package/skills/tfx-setup/SKILL.md.tmpl +504 -0
- package/skills/tfx-setup/skill.json +1 -3
- package/skills/tfx-swarm/SKILL.md +22 -0
- package/skills/tfx-swarm/SKILL.md.tmpl +218 -0
- package/tui/codex-profile.mjs +88 -33
- package/tui/core.mjs +45 -15
- package/tui/doctor.mjs +75 -28
- package/tui/gemini-profile.mjs +74 -29
- package/tui/monitor-data.mjs +8 -4
- package/tui/monitor.mjs +71 -27
- package/tui/setup.mjs +133 -42
package/hub/token-mode.mjs
CHANGED
|
@@ -8,78 +8,78 @@
|
|
|
8
8
|
*/
|
|
9
9
|
export const COMPACT_RULES = [
|
|
10
10
|
// ── 심볼 치환 (긴 매칭 우선 정렬) ──
|
|
11
|
-
{ from: [
|
|
12
|
-
{ from: [
|
|
13
|
-
{ from: [
|
|
14
|
-
{ from: [
|
|
15
|
-
{ from: [
|
|
16
|
-
{ from: [
|
|
17
|
-
{ from: [
|
|
18
|
-
{ from: [
|
|
19
|
-
{ from: [
|
|
20
|
-
{ from: [
|
|
21
|
-
{ from: [
|
|
22
|
-
{ from: [
|
|
23
|
-
{ from: [
|
|
24
|
-
{ from: [
|
|
11
|
+
{ from: ["greater than or equal"], to: "≥", type: "symbol" },
|
|
12
|
+
{ from: ["less than or equal"], to: "≤", type: "symbol" },
|
|
13
|
+
{ from: ["results in", "결과적으로"], to: "→", type: "symbol" },
|
|
14
|
+
{ from: ["therefore", "따라서"], to: "∴", type: "symbol" },
|
|
15
|
+
{ from: ["because", "왜냐하면"], to: "∵", type: "symbol" },
|
|
16
|
+
{ from: ["approximately", "대략"], to: "≈", type: "symbol" },
|
|
17
|
+
{ from: ["not equal", "같지 않"], to: "≠", type: "symbol" },
|
|
18
|
+
{ from: ["in progress", "진행 중"], to: "⏳", type: "symbol" },
|
|
19
|
+
{ from: ["completed", "완료"], to: "✓", type: "symbol" },
|
|
20
|
+
{ from: ["success", "성공"], to: "✓", type: "symbol" },
|
|
21
|
+
{ from: ["failure", "실패"], to: "✗", type: "symbol" },
|
|
22
|
+
{ from: ["warning", "경고"], to: "⚠", type: "symbol" },
|
|
23
|
+
{ from: ["error", "에러"], to: "✗", type: "symbol" },
|
|
24
|
+
{ from: ["pending", "대기"], to: "⏸", type: "symbol" },
|
|
25
25
|
|
|
26
26
|
// ── 약어 (긴 매칭 우선 정렬) ──
|
|
27
|
-
{ from: [
|
|
28
|
-
{ from: [
|
|
29
|
-
{ from: [
|
|
30
|
-
{ from: [
|
|
31
|
-
{ from: [
|
|
32
|
-
{ from: [
|
|
33
|
-
{ from: [
|
|
34
|
-
{ from: [
|
|
35
|
-
{ from: [
|
|
36
|
-
{ from: [
|
|
27
|
+
{ from: ["configuration", "설정"], to: "cfg", type: "abbrev" },
|
|
28
|
+
{ from: ["implementation", "구현"], to: "impl", type: "abbrev" },
|
|
29
|
+
{ from: ["architecture", "아키텍처"], to: "arch", type: "abbrev" },
|
|
30
|
+
{ from: ["dependency", "의존성"], to: "dep", type: "abbrev" },
|
|
31
|
+
{ from: ["function", "함수"], to: "fn", type: "abbrev" },
|
|
32
|
+
{ from: ["parameter", "파라미터"], to: "param", type: "abbrev" },
|
|
33
|
+
{ from: ["repository", "저장소"], to: "repo", type: "abbrev" },
|
|
34
|
+
{ from: ["environment", "환경"], to: "env", type: "abbrev" },
|
|
35
|
+
{ from: ["variable", "변수"], to: "var", type: "abbrev" },
|
|
36
|
+
{ from: ["directory", "디렉토리"], to: "dir", type: "abbrev" },
|
|
37
37
|
|
|
38
38
|
// ── 한국어 동사/명령형 약어 ──
|
|
39
|
-
{ from: [
|
|
40
|
-
{ from: [
|
|
41
|
-
{ from: [
|
|
42
|
-
{ from: [
|
|
43
|
-
{ from: [
|
|
44
|
-
{ from: [
|
|
45
|
-
{ from: [
|
|
46
|
-
{ from: [
|
|
39
|
+
{ from: ["구현해"], to: "impl", type: "abbrev" },
|
|
40
|
+
{ from: ["확인해"], to: "check", type: "abbrev" },
|
|
41
|
+
{ from: ["수정해"], to: "fix", type: "abbrev" },
|
|
42
|
+
{ from: ["테스트"], to: "test", type: "abbrev" },
|
|
43
|
+
{ from: ["리뷰"], to: "review", type: "abbrev" },
|
|
44
|
+
{ from: ["분석"], to: "analyze", type: "abbrev" },
|
|
45
|
+
{ from: ["설계"], to: "design", type: "abbrev" },
|
|
46
|
+
{ from: ["문서화"], to: "docs", type: "abbrev" },
|
|
47
47
|
];
|
|
48
48
|
|
|
49
49
|
/** @type {Array<{ from: string[], to: string, type: 'symbol'|'abbrev' }>} */
|
|
50
50
|
export const REVIEW_RULES = [
|
|
51
|
-
{ from: [
|
|
52
|
-
{ from: [
|
|
53
|
-
{ from: [
|
|
54
|
-
{ from: [
|
|
55
|
-
{ from: [
|
|
56
|
-
{ from: [
|
|
57
|
-
{ from: [
|
|
58
|
-
{ from: [
|
|
51
|
+
{ from: ["looks good to me", "lgtm"], to: "✓lgtm", type: "abbrev" },
|
|
52
|
+
{ from: ["needs changes", "수정 필요"], to: "✗chg", type: "abbrev" },
|
|
53
|
+
{ from: ["nitpick", "사소한"], to: "nit", type: "abbrev" },
|
|
54
|
+
{ from: ["blocking", "블로킹"], to: "blk", type: "abbrev" },
|
|
55
|
+
{ from: ["suggestion", "제안"], to: "sug", type: "abbrev" },
|
|
56
|
+
{ from: ["question", "질문"], to: "q", type: "abbrev" },
|
|
57
|
+
{ from: ["approved", "승인"], to: "✓apv", type: "abbrev" },
|
|
58
|
+
{ from: ["request changes", "변경 요청"], to: "✗req", type: "abbrev" },
|
|
59
59
|
];
|
|
60
60
|
|
|
61
61
|
/** @type {Array<{ from: string[], to: string, type: 'symbol'|'abbrev' }>} */
|
|
62
62
|
export const DESIGN_RULES = [
|
|
63
|
-
{ from: [
|
|
64
|
-
{ from: [
|
|
65
|
-
{ from: [
|
|
66
|
-
{ from: [
|
|
67
|
-
{ from: [
|
|
68
|
-
{ from: [
|
|
69
|
-
{ from: [
|
|
70
|
-
{ from: [
|
|
63
|
+
{ from: ["component", "컴포넌트"], to: "cmp", type: "abbrev" },
|
|
64
|
+
{ from: ["interface", "인터페이스"], to: "iface", type: "abbrev" },
|
|
65
|
+
{ from: ["abstraction", "추상화"], to: "abs", type: "abbrev" },
|
|
66
|
+
{ from: ["pattern", "패턴"], to: "ptn", type: "abbrev" },
|
|
67
|
+
{ from: ["dependency injection", "의존성 주입"], to: "di", type: "abbrev" },
|
|
68
|
+
{ from: ["single responsibility", "단일 책임"], to: "srp", type: "abbrev" },
|
|
69
|
+
{ from: ["open closed", "개방 폐쇄"], to: "ocp", type: "abbrev" },
|
|
70
|
+
{ from: ["inheritance", "상속"], to: "inh", type: "abbrev" },
|
|
71
71
|
];
|
|
72
72
|
|
|
73
73
|
/** @type {Array<{ from: string[], to: string, type: 'symbol'|'abbrev' }>} */
|
|
74
74
|
export const DOCS_RULES = [
|
|
75
|
-
{ from: [
|
|
76
|
-
{ from: [
|
|
77
|
-
{ from: [
|
|
78
|
-
{ from: [
|
|
79
|
-
{ from: [
|
|
80
|
-
{ from: [
|
|
81
|
-
{ from: [
|
|
82
|
-
{ from: [
|
|
75
|
+
{ from: ["description", "설명"], to: "desc", type: "abbrev" },
|
|
76
|
+
{ from: ["example", "예시"], to: "ex", type: "abbrev" },
|
|
77
|
+
{ from: ["reference", "참조"], to: "ref", type: "abbrev" },
|
|
78
|
+
{ from: ["introduction", "소개"], to: "intro", type: "abbrev" },
|
|
79
|
+
{ from: ["deprecated", "사용 중단"], to: "dep", type: "abbrev" },
|
|
80
|
+
{ from: ["optional", "선택적"], to: "opt", type: "abbrev" },
|
|
81
|
+
{ from: ["required", "필수"], to: "req", type: "abbrev" },
|
|
82
|
+
{ from: ["returns", "반환"], to: "ret", type: "abbrev" },
|
|
83
83
|
];
|
|
84
84
|
|
|
85
85
|
// ── 프로필 맵 ──
|
|
@@ -87,9 +87,9 @@ export const DOCS_RULES = [
|
|
|
87
87
|
/** @type {Record<string, Array<{ from: string[], to: string, type: 'symbol'|'abbrev' }>>} */
|
|
88
88
|
const PROFILE_MAP = {
|
|
89
89
|
default: COMPACT_RULES,
|
|
90
|
-
review:
|
|
91
|
-
design:
|
|
92
|
-
docs:
|
|
90
|
+
review: [...COMPACT_RULES, ...REVIEW_RULES],
|
|
91
|
+
design: [...COMPACT_RULES, ...DESIGN_RULES],
|
|
92
|
+
docs: [...COMPACT_RULES, ...DOCS_RULES],
|
|
93
93
|
};
|
|
94
94
|
|
|
95
95
|
// ── 내부: 정렬된 치환 쌍 빌드 헬퍼 ──
|
|
@@ -135,7 +135,7 @@ const CODE_BLOCK_RE = /```[\s\S]*?```/g;
|
|
|
135
135
|
*/
|
|
136
136
|
function withCodeProtection(text, transform) {
|
|
137
137
|
const blocks = [];
|
|
138
|
-
const placeholder =
|
|
138
|
+
const placeholder = "\x00CB";
|
|
139
139
|
let idx = 0;
|
|
140
140
|
const masked = text.replace(CODE_BLOCK_RE, (match) => {
|
|
141
141
|
blocks.push(match);
|
|
@@ -146,7 +146,7 @@ function withCodeProtection(text, transform) {
|
|
|
146
146
|
|
|
147
147
|
// 플레이스홀더 복원
|
|
148
148
|
return transformed.replace(
|
|
149
|
-
new RegExp(`${placeholder}(\\d+)${placeholder}`,
|
|
149
|
+
new RegExp(`${placeholder}(\\d+)${placeholder}`, "g"),
|
|
150
150
|
(_, i) => blocks[Number(i)],
|
|
151
151
|
);
|
|
152
152
|
}
|
|
@@ -170,14 +170,14 @@ export function isCompactMode() {
|
|
|
170
170
|
* @returns {string}
|
|
171
171
|
*/
|
|
172
172
|
export function compactify(text) {
|
|
173
|
-
if (!text || typeof text !==
|
|
173
|
+
if (!text || typeof text !== "string") return text ?? "";
|
|
174
174
|
_compactMode = true;
|
|
175
175
|
|
|
176
176
|
return withCodeProtection(text, (segment) => {
|
|
177
177
|
let result = segment;
|
|
178
178
|
for (const { pattern, to } of _compactPairs) {
|
|
179
|
-
const escaped = pattern.replace(/[.*+?^${}()|[\]\\]/g,
|
|
180
|
-
const re = new RegExp(escaped,
|
|
179
|
+
const escaped = pattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
180
|
+
const re = new RegExp(escaped, "gi");
|
|
181
181
|
result = result.replace(re, to);
|
|
182
182
|
}
|
|
183
183
|
return result;
|
|
@@ -190,8 +190,8 @@ export function compactify(text) {
|
|
|
190
190
|
* @param {'default'|'review'|'design'|'docs'} [profile='default'] — 도메인 프로필
|
|
191
191
|
* @returns {string}
|
|
192
192
|
*/
|
|
193
|
-
export function applyCompactRules(text, profile =
|
|
194
|
-
if (!text || typeof text !==
|
|
193
|
+
export function applyCompactRules(text, profile = "default") {
|
|
194
|
+
if (!text || typeof text !== "string") return text ?? "";
|
|
195
195
|
|
|
196
196
|
const rules = PROFILE_MAP[profile] ?? COMPACT_RULES;
|
|
197
197
|
const pairs = buildCompactPairs(rules);
|
|
@@ -199,8 +199,8 @@ export function applyCompactRules(text, profile = 'default') {
|
|
|
199
199
|
return withCodeProtection(text, (segment) => {
|
|
200
200
|
let result = segment;
|
|
201
201
|
for (const { pattern, to } of pairs) {
|
|
202
|
-
const escaped = pattern.replace(/[.*+?^${}()|[\]\\]/g,
|
|
203
|
-
const re = new RegExp(escaped,
|
|
202
|
+
const escaped = pattern.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
203
|
+
const re = new RegExp(escaped, "gi");
|
|
204
204
|
result = result.replace(re, to);
|
|
205
205
|
}
|
|
206
206
|
return result;
|
|
@@ -213,14 +213,14 @@ export function applyCompactRules(text, profile = 'default') {
|
|
|
213
213
|
* @returns {string}
|
|
214
214
|
*/
|
|
215
215
|
export function expand(text) {
|
|
216
|
-
if (!text || typeof text !==
|
|
216
|
+
if (!text || typeof text !== "string") return text ?? "";
|
|
217
217
|
_compactMode = false;
|
|
218
218
|
|
|
219
219
|
return withCodeProtection(text, (segment) => {
|
|
220
220
|
let result = segment;
|
|
221
221
|
for (const { symbol, restore } of _expandPairs) {
|
|
222
|
-
const escaped = symbol.replace(/[.*+?^${}()|[\]\\]/g,
|
|
223
|
-
const re = new RegExp(escaped,
|
|
222
|
+
const escaped = symbol.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
223
|
+
const re = new RegExp(escaped, "g");
|
|
224
224
|
result = result.replace(re, restore);
|
|
225
225
|
}
|
|
226
226
|
return result;
|
package/hub/tray.mjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
import _SysTrayModule from "systray2";
|
|
4
|
+
|
|
4
5
|
const SysTray = _SysTrayModule.default || _SysTrayModule;
|
|
6
|
+
|
|
5
7
|
import { exec } from "node:child_process";
|
|
6
8
|
import { existsSync, readFileSync } from "node:fs";
|
|
7
9
|
import { homedir } from "node:os";
|
|
@@ -13,7 +15,8 @@ const HUB_PID_FILE = join(homedir(), ".claude", "cache", "tfx-hub", "hub.pid");
|
|
|
13
15
|
const DEFAULT_HUB_PORT = "27888";
|
|
14
16
|
|
|
15
17
|
function getHubBaseUrl() {
|
|
16
|
-
if (process.env.TFX_HUB_URL)
|
|
18
|
+
if (process.env.TFX_HUB_URL)
|
|
19
|
+
return process.env.TFX_HUB_URL.replace(/\/+$/, "");
|
|
17
20
|
try {
|
|
18
21
|
const info = JSON.parse(readFileSync(HUB_PID_FILE, "utf8"));
|
|
19
22
|
if (info.port) return `http://${info.host || "127.0.0.1"}:${info.port}`;
|
|
@@ -42,7 +45,8 @@ const CODEX_RATE_LIMITS_FILE = join(CACHE_DIR, "codex-rate-limits-cache.json");
|
|
|
42
45
|
const GEMINI_QUOTA_FILE = join(CACHE_DIR, "gemini-quota-cache.json");
|
|
43
46
|
const CLAUDE_USAGE_FILE = join(CACHE_DIR, "claude-usage-cache.json");
|
|
44
47
|
|
|
45
|
-
const TRAY_ICON_BASE64 =
|
|
48
|
+
const TRAY_ICON_BASE64 =
|
|
49
|
+
"AAABAAEAICAAAAEAIAADAQAAFgAAAIlQTkcNChoKAAAADUlIRFIAAAAgAAAAIAgGAAAAc3p69AAAAMpJREFUeJzV1UEKgzAQheEcwnXP4a17gl6n6yy7U1IIqDSTeW/m0TYwK8X/E6OW8m9rWW5Pa74SlWLYeBgRDcOQ7V42a+SIGSALkwKIQKDnroJQmy4bAgO8EDnAA4EBkV3do7VWeAOfAO0Cx/EC+vnMG2QCLND12Pp4vUcK+DQ9fBxqI47uDI23oV7F2fNVxF2A64zCTBwCWGE2Pv0WzKKp8ba8wWg4DIiGKUBWdBjP+i+E4z8BUCJccRUCimdC6HAGIiWOYiRR5doBauXshzcEs0UAAAAASUVORK5CYII=";
|
|
46
50
|
|
|
47
51
|
function clampPercent(value) {
|
|
48
52
|
if (!Number.isFinite(Number(value))) return null;
|
|
@@ -96,8 +100,10 @@ function getAimdBatchSize(now = Date.now()) {
|
|
|
96
100
|
|
|
97
101
|
function getCodexPercent() {
|
|
98
102
|
const data = readJson(CODEX_RATE_LIMITS_FILE);
|
|
99
|
-
const buckets =
|
|
100
|
-
|
|
103
|
+
const buckets =
|
|
104
|
+
data?.buckets && typeof data.buckets === "object" ? data.buckets : null;
|
|
105
|
+
const primaryBucket =
|
|
106
|
+
buckets?.codex ?? Object.values(buckets ?? {})[0] ?? null;
|
|
101
107
|
return clampPercent(primaryBucket?.primary?.used_percent);
|
|
102
108
|
}
|
|
103
109
|
|
|
@@ -117,7 +123,10 @@ function pickGeminiBucket(data) {
|
|
|
117
123
|
if (match) return match;
|
|
118
124
|
}
|
|
119
125
|
|
|
120
|
-
return
|
|
126
|
+
return (
|
|
127
|
+
buckets.find((bucket) => String(bucket?.modelId ?? "").includes("flash")) ??
|
|
128
|
+
buckets[0]
|
|
129
|
+
);
|
|
121
130
|
}
|
|
122
131
|
|
|
123
132
|
function getGeminiPercent() {
|
|
@@ -140,8 +149,11 @@ async function getHubStatusLabel() {
|
|
|
140
149
|
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
141
150
|
|
|
142
151
|
const data = await response.json();
|
|
143
|
-
const state =
|
|
144
|
-
|
|
152
|
+
const state =
|
|
153
|
+
typeof data?.hub?.state === "string" ? data.hub.state : "connected";
|
|
154
|
+
const sessions = Number.isFinite(Number(data?.sessions))
|
|
155
|
+
? Number(data.sessions)
|
|
156
|
+
: null;
|
|
145
157
|
return sessions == null ? `Hub: ${state}` : `Hub: ${state} | S:${sessions}`;
|
|
146
158
|
} catch {
|
|
147
159
|
return "Hub 미연결";
|
|
@@ -167,12 +179,32 @@ function buildUsageTitle(snapshot) {
|
|
|
167
179
|
|
|
168
180
|
function findChromePath() {
|
|
169
181
|
const candidates = [
|
|
170
|
-
join(
|
|
171
|
-
|
|
172
|
-
|
|
182
|
+
join(
|
|
183
|
+
process.env.ProgramFiles || "",
|
|
184
|
+
"Google",
|
|
185
|
+
"Chrome",
|
|
186
|
+
"Application",
|
|
187
|
+
"chrome.exe",
|
|
188
|
+
),
|
|
189
|
+
join(
|
|
190
|
+
process.env["ProgramFiles(x86)"] || "",
|
|
191
|
+
"Google",
|
|
192
|
+
"Chrome",
|
|
193
|
+
"Application",
|
|
194
|
+
"chrome.exe",
|
|
195
|
+
),
|
|
196
|
+
join(
|
|
197
|
+
process.env.LOCALAPPDATA || "",
|
|
198
|
+
"Google",
|
|
199
|
+
"Chrome",
|
|
200
|
+
"Application",
|
|
201
|
+
"chrome.exe",
|
|
202
|
+
),
|
|
173
203
|
];
|
|
174
204
|
for (const p of candidates) {
|
|
175
|
-
try {
|
|
205
|
+
try {
|
|
206
|
+
if (existsSync(p)) return p;
|
|
207
|
+
} catch {}
|
|
176
208
|
}
|
|
177
209
|
return null;
|
|
178
210
|
}
|
|
@@ -183,11 +215,15 @@ function openDashboard() {
|
|
|
183
215
|
const chrome = findChromePath();
|
|
184
216
|
if (chrome) {
|
|
185
217
|
// Chrome --app: 주소바/탭 없는 앱 윈도우로 열기
|
|
186
|
-
exec(
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
218
|
+
exec(
|
|
219
|
+
`start "" "${chrome}" "--app=${url}"`,
|
|
220
|
+
{ shell, windowsHide: true },
|
|
221
|
+
(err) => {
|
|
222
|
+
if (err) {
|
|
223
|
+
exec(`start "" "${url}"`, { shell, windowsHide: true }, () => {});
|
|
224
|
+
}
|
|
225
|
+
},
|
|
226
|
+
);
|
|
191
227
|
} else {
|
|
192
228
|
exec(`start "" "${url}"`, { shell, windowsHide: true }, () => {});
|
|
193
229
|
}
|
|
@@ -277,17 +313,22 @@ async function refreshMenu() {
|
|
|
277
313
|
await systray.sendAction({ type: "update-item", item: aimdItem });
|
|
278
314
|
await systray.sendAction({ type: "update-item", item: quotaItem });
|
|
279
315
|
await systray.sendAction({ type: "update-item", item: hubItem });
|
|
280
|
-
await systray.sendAction({
|
|
316
|
+
await systray.sendAction({
|
|
317
|
+
type: "update-item-and-title",
|
|
318
|
+
item: { title: buildTooltip(snapshot) },
|
|
319
|
+
});
|
|
281
320
|
}
|
|
282
321
|
}
|
|
283
322
|
|
|
284
323
|
function scheduleRefresh() {
|
|
285
324
|
if (refreshPromise) return refreshPromise;
|
|
286
|
-
refreshPromise = refreshMenu()
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
325
|
+
refreshPromise = refreshMenu()
|
|
326
|
+
.catch((error) => {
|
|
327
|
+
console.error(`[tfx-tray] refresh failed: ${error.message}`);
|
|
328
|
+
})
|
|
329
|
+
.finally(() => {
|
|
330
|
+
refreshPromise = null;
|
|
331
|
+
});
|
|
291
332
|
return refreshPromise;
|
|
292
333
|
}
|
|
293
334
|
|
|
@@ -366,7 +407,9 @@ export async function startTray() {
|
|
|
366
407
|
};
|
|
367
408
|
}
|
|
368
409
|
|
|
369
|
-
const selfRun =
|
|
410
|
+
const selfRun =
|
|
411
|
+
process.argv[1] &&
|
|
412
|
+
resolve(process.argv[1]) === resolve(fileURLToPath(import.meta.url));
|
|
370
413
|
|
|
371
414
|
if (selfRun) {
|
|
372
415
|
startTray().catch((error) => {
|