triflux 2.0.0 → 2.0.2

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.
@@ -655,19 +655,25 @@ function formatResetRemaining(isoOrUnix) {
655
655
  const d = typeof isoOrUnix === "string" ? new Date(isoOrUnix) : new Date(isoOrUnix * 1000);
656
656
  if (isNaN(d.getTime())) return "";
657
657
  const diffMs = d.getTime() - Date.now();
658
- if (diffMs <= 0) return "now";
658
+ if (diffMs <= 0) return "00h00m";
659
659
  const totalMinutes = Math.floor(diffMs / 60000);
660
660
  const totalHours = Math.floor(totalMinutes / 60);
661
661
  const minutes = totalMinutes % 60;
662
662
  return `${String(totalHours).padStart(2, "0")}h${String(minutes).padStart(2, "0")}m`;
663
663
  }
664
664
 
665
+ function isResetPast(isoOrUnix) {
666
+ if (!isoOrUnix) return false;
667
+ const d = typeof isoOrUnix === "string" ? new Date(isoOrUnix) : new Date(isoOrUnix * 1000);
668
+ return !isNaN(d.getTime()) && d.getTime() <= Date.now();
669
+ }
670
+
665
671
  function formatResetRemainingDayHour(isoOrUnix) {
666
672
  if (!isoOrUnix) return "";
667
673
  const d = typeof isoOrUnix === "string" ? new Date(isoOrUnix) : new Date(isoOrUnix * 1000);
668
674
  if (isNaN(d.getTime())) return "";
669
675
  const diffMs = d.getTime() - Date.now();
670
- if (diffMs <= 0) return "now";
676
+ if (diffMs <= 0) return "0d00h";
671
677
  const totalMinutes = Math.floor(diffMs / 60000);
672
678
  const days = Math.floor(totalMinutes / (60 * 24));
673
679
  const hours = Math.floor((totalMinutes % (60 * 24)) / 60);
@@ -1159,8 +1165,8 @@ function getProviderRow(provider, marker, markerColor, qosProfile, accountsConfi
1159
1165
  if (realQuota?.type === "codex") {
1160
1166
  const main = realQuota.buckets.codex || realQuota.buckets[Object.keys(realQuota.buckets)[0]];
1161
1167
  if (main) {
1162
- const fiveP = clampPercent(main.primary?.used_percent ?? 0);
1163
- const weekP = clampPercent(main.secondary?.used_percent ?? 0);
1168
+ const fiveP = isResetPast(main.primary?.resets_at) ? 0 : clampPercent(main.primary?.used_percent ?? 0);
1169
+ const weekP = isResetPast(main.secondary?.resets_at) ? 0 : clampPercent(main.secondary?.used_percent ?? 0);
1164
1170
  if (cols < 40) {
1165
1171
  return { prefix: minPrefix, left: `${colorByPercent(fiveP, `${fiveP}%`)}${dim("/")}${colorByPercent(weekP, `${weekP}%`)}${svCompact}`, right: "" };
1166
1172
  }
@@ -1185,8 +1191,8 @@ function getProviderRow(provider, marker, markerColor, qosProfile, accountsConfi
1185
1191
  if (realQuota?.type === "codex") {
1186
1192
  const main = realQuota.buckets.codex || realQuota.buckets[Object.keys(realQuota.buckets)[0]];
1187
1193
  if (main) {
1188
- const fiveP = clampPercent(main.primary?.used_percent ?? 0);
1189
- const weekP = clampPercent(main.secondary?.used_percent ?? 0);
1194
+ const fiveP = isResetPast(main.primary?.resets_at) ? 0 : clampPercent(main.primary?.used_percent ?? 0);
1195
+ const weekP = isResetPast(main.secondary?.resets_at) ? 0 : clampPercent(main.secondary?.used_percent ?? 0);
1190
1196
  quotaSection = `${dim("5h:")}${colorByPercent(fiveP, `${fiveP}%`)} ` +
1191
1197
  `${dim("1w:")}${colorByPercent(weekP, `${weekP}%`)}`;
1192
1198
  }
@@ -1211,8 +1217,8 @@ function getProviderRow(provider, marker, markerColor, qosProfile, accountsConfi
1211
1217
  if (realQuota?.type === "codex") {
1212
1218
  const main = realQuota.buckets.codex || realQuota.buckets[Object.keys(realQuota.buckets)[0]];
1213
1219
  if (main) {
1214
- const fiveP = clampPercent(main.primary?.used_percent ?? 0);
1215
- const weekP = clampPercent(main.secondary?.used_percent ?? 0);
1220
+ const fiveP = isResetPast(main.primary?.resets_at) ? 0 : clampPercent(main.primary?.used_percent ?? 0);
1221
+ const weekP = isResetPast(main.secondary?.resets_at) ? 0 : clampPercent(main.secondary?.used_percent ?? 0);
1216
1222
  const fiveReset = formatResetRemaining(main.primary?.resets_at) || "n/a";
1217
1223
  const weekReset = formatResetRemainingDayHour(main.secondary?.resets_at) || "n/a";
1218
1224
  quotaSection = `${dim("5h:")}${colorByPercent(fiveP, formatPercentCell(fiveP))} ` +
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "triflux",
3
- "version": "2.0.0",
3
+ "version": "2.0.2",
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": {
package/scripts/setup.mjs CHANGED
@@ -151,6 +151,33 @@ for (const name of staleFiles) {
151
151
  }
152
152
  }
153
153
 
154
+ // ── Windows bash PATH 자동 설정 ──
155
+ // Codex/Gemini가 cmd에는 있지만 bash에서 못 찾는 문제 해결
156
+
157
+ if (process.platform === "win32") {
158
+ const npmBin = join(process.env.APPDATA || "", "npm");
159
+ if (existsSync(npmBin)) {
160
+ const bashrcPath = join(homedir(), ".bashrc");
161
+ const pathExport = 'export PATH="$PATH:$APPDATA/npm"';
162
+ let needsUpdate = true;
163
+
164
+ if (existsSync(bashrcPath)) {
165
+ const content = readFileSync(bashrcPath, "utf8");
166
+ if (content.includes("APPDATA/npm") || content.includes("APPDATA\\npm")) {
167
+ needsUpdate = false;
168
+ }
169
+ }
170
+
171
+ if (needsUpdate) {
172
+ const line = `\n# triflux: Codex/Gemini CLI를 bash에서 사용하기 위한 PATH 설정\n${pathExport}\n`;
173
+ try {
174
+ writeFileSync(bashrcPath, (existsSync(bashrcPath) ? readFileSync(bashrcPath, "utf8") : "") + line, "utf8");
175
+ synced++;
176
+ } catch {}
177
+ }
178
+ }
179
+ }
180
+
154
181
  // ── MCP 인벤토리 백그라운드 갱신 ──
155
182
 
156
183
  import { spawn } from "child_process";