triflux 2.4.4 → 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";
@@ -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.4",
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))