triflux 2.4.3 → 2.4.6

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.
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
  // tfx-doctor — triflux doctor 바로가기
3
3
  import { dirname } from "path";
4
4
  import { fileURLToPath } from "url";
package/bin/tfx-setup.mjs CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
  // tfx-setup — triflux setup 바로가기
3
3
  import { dirname } from "path";
4
4
  import { fileURLToPath } from "url";
package/bin/triflux.mjs CHANGED
@@ -296,11 +296,18 @@ function cmdDoctor(options = {}) {
296
296
  const hudScript = join(CLAUDE_DIR, "hud", "hud-qos-status.mjs");
297
297
  if (existsSync(hudScript)) {
298
298
  try {
299
- execSync(`"${process.execPath}" "${hudScript}" --refresh-gemini`, { timeout: 15000, stdio: "ignore" });
299
+ execSync(`"${process.execPath}" "${hudScript}" --refresh-claude-usage`, { timeout: 20000, stdio: "ignore" });
300
+ ok("Claude 사용량 캐시 재생성됨");
301
+ } catch { warn("Claude 사용량 캐시 재생성 실패 — 다음 API 호출 시 자동 생성"); }
302
+ try {
303
+ execSync(`"${process.execPath}" "${hudScript}" --refresh-codex-rate-limits`, { timeout: 15000, stdio: "ignore" });
304
+ ok("Codex 레이트 리밋 캐시 재생성됨");
305
+ } catch { warn("Codex 레이트 리밋 캐시 재생성 실패"); }
306
+ try {
307
+ execSync(`"${process.execPath}" "${hudScript}" --refresh-gemini-quota`, { timeout: 15000, stdio: "ignore" });
300
308
  ok("Gemini 쿼터 캐시 재생성됨");
301
309
  } catch { warn("Gemini 쿼터 캐시 재생성 실패"); }
302
310
  }
303
- info("Claude/Codex 캐시는 다음 사용 시 자동 생성됩니다");
304
311
  console.log(`\n ${LINE}`);
305
312
  console.log(` ${GREEN_BRIGHT}${BOLD}✓ 캐시 초기화 + 재생성 완료${RESET}\n`);
306
313
  return;
@@ -302,7 +302,7 @@ function selectTier(stdin, claudeUsage = null) {
302
302
  let indicatorRows = 1; // bypass permissions (거의 항상 표시)
303
303
  indicatorRows += 1; // 선행 개행 가드 (알림 배너 우회용 빈 줄)
304
304
  const contextPercent = getContextPercent(stdin);
305
- if (contextPercent >= 85) indicatorRows += 1; // "Context low" 배너
305
+ // "Context low" 배너 공간은 출력부(leadingBreaks)에서 \n\n으로 처리 티어 선택에서 예약 불필요
306
306
  // Claude Code 사용량 경고 (노란색 배너: "You've used X% of your ... limit")
307
307
  const weeklyPct = claudeUsage?.weeklyPercent ?? 0;
308
308
  const fiveHourPct = claudeUsage?.fiveHourPercent ?? 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "triflux",
3
- "version": "2.4.3",
3
+ "version": "2.4.6",
4
4
  "description": "CLI-first multi-model orchestrator for Claude Code — route tasks to Codex, Gemini, and Claude",
5
5
  "type": "module",
6
6
  "bin": {
@@ -527,31 +527,62 @@ get_gemini_mcp_filter() {
527
527
  extract_tokens() {
528
528
  local raw="$1"
529
529
  local cli_type="$2"
530
-
531
- if [[ "$cli_type" != "codex" ]] || [[ -z "$raw" ]]; then
530
+ local stderr_file="$3"
531
+
532
+ if [[ "$cli_type" == "codex" ]]; then
533
+ # Codex CLI: stderr에 "tokens used\n76,239" 형식으로 토큰 출력
534
+ if [[ -f "$stderr_file" ]]; then
535
+ local total
536
+ total=$(grep -A1 "tokens used" "$stderr_file" 2>/dev/null | tail -1 | tr -d ',' | tr -d ' ')
537
+ if [[ -n "$total" && "$total" =~ ^[0-9]+$ && "$total" -gt 0 ]]; then
538
+ echo "$total 0"
539
+ return
540
+ fi
541
+ fi
532
542
  echo "0 0"
533
543
  return
534
544
  fi
535
545
 
536
- local result
537
- result=$(echo "$raw" | python3 -c "
538
- import sys, json
539
- inp, out = 0, 0
540
- for line in sys.stdin:
541
- line = line.strip()
542
- if not line:
543
- continue
544
- try:
545
- obj = json.loads(line)
546
- u = obj.get('usage', {})
547
- if u:
548
- inp = max(inp, u.get('input_tokens', 0))
549
- out = max(out, u.get('output_tokens', 0))
550
- except:
551
- pass
546
+ if [[ "$cli_type" == "gemini" ]]; then
547
+ # Gemini CLI: ~/.gemini/tmp/*/chats/session-*.json에서 최신 세션 토큰 추출
548
+ local gemini_tmp="${HOME}/.gemini/tmp"
549
+ if [[ -d "$gemini_tmp" ]]; then
550
+ local latest
551
+ latest=$(find "$gemini_tmp" -name "session-*.json" -path "*/chats/*" -newer "$stderr_file" 2>/dev/null \
552
+ | head -1)
553
+ # stderr보다 새 파일 없으면 가장 최근 파일 사용
554
+ if [[ -z "$latest" ]]; then
555
+ latest=$(find "$gemini_tmp" -name "session-*.json" -path "*/chats/*" -printf '%T@ %p\n' 2>/dev/null \
556
+ | sort -rn | head -1 | cut -d' ' -f2-)
557
+ # Windows Git Bash: -printf 미지원 시 ls fallback
558
+ if [[ -z "$latest" ]]; then
559
+ latest=$(find "$gemini_tmp" -name "session-*.json" -path "*/chats/*" 2>/dev/null \
560
+ | xargs ls -t 2>/dev/null | head -1)
561
+ fi
562
+ fi
563
+ if [[ -n "$latest" && -f "$latest" ]]; then
564
+ local result
565
+ result=$(python3 -c "
566
+ import json, sys
567
+ data = json.load(open(sys.argv[1]))
568
+ inp = sum(m.get('tokens',{}).get('input',0) for m in data.get('messages',[]))
569
+ out = sum(m.get('tokens',{}).get('output',0) for m in data.get('messages',[]))
552
570
  print(f'{inp} {out}')
553
- " 2>/dev/null) || result="0 0"
554
- echo "$result"
571
+ " "$latest" 2>/dev/null) || result="0 0"
572
+ local inp out
573
+ inp=$(echo "$result" | awk '{print $1}')
574
+ out=$(echo "$result" | awk '{print $2}')
575
+ if [[ $((inp + out)) -gt 0 ]]; then
576
+ echo "$inp $out"
577
+ return
578
+ fi
579
+ fi
580
+ fi
581
+ echo "0 0"
582
+ return
583
+ fi
584
+
585
+ echo "0 0"
555
586
  }
556
587
 
557
588
  # ── Codex JSON-line 출력 파서 ──
@@ -634,7 +665,7 @@ accumulate_tokens() {
634
665
  # node로 JSON 읽기/수정/쓰기 (jq 의존성 없이)
635
666
  node -e '
636
667
  const fs = require("fs");
637
- const [,, file, cliType, inp, out] = process.argv;
668
+ const [, file, cliType, inp, out] = process.argv;
638
669
  let data;
639
670
  try { data = JSON.parse(fs.readFileSync(file, "utf-8")); } catch { data = {}; }
640
671
  if (!data.codex) data.codex = { tokens: 0, calls: 0 };
@@ -860,7 +891,7 @@ main() {
860
891
 
861
892
  # 토큰 추출
862
893
  local token_info input_tokens output_tokens total_tokens
863
- token_info=$(extract_tokens "$raw_output" "$CLI_TYPE") || token_info="0 0"
894
+ token_info=$(extract_tokens "$raw_output" "$CLI_TYPE" "$STDERR_LOG") || token_info="0 0"
864
895
  input_tokens=$(echo "$token_info" | awk '{print $1}')
865
896
  output_tokens=$(echo "$token_info" | awk '{print $2}')
866
897
  total_tokens=$((input_tokens + output_tokens))