@triflux/core 10.88.0 → 10.88.1

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.
@@ -54,7 +54,12 @@ import {
54
54
  } from "./renderers.mjs";
55
55
  import { sessionStatus } from "./session-status.mjs";
56
56
  import { selectTier } from "./terminal.mjs";
57
- import { formatTimeCell, formatTimeCellDH, readStdinJson } from "./utils.mjs";
57
+ import {
58
+ formatTimeCell,
59
+ formatTimeCellDH,
60
+ readStdinJson,
61
+ stripAnsi,
62
+ } from "./utils.mjs";
58
63
 
59
64
  async function main() {
60
65
  if (process.argv.includes(CLAUDE_REFRESH_FLAG)) {
@@ -78,6 +83,8 @@ async function main() {
78
83
  const codexSession = stdin?.product === "codex";
79
84
  const cacheOnly = process.argv.includes("--cache-only");
80
85
  const status = await sessionStatus(stdin);
86
+ const currentMarker = agySession ? "a" : codexSession ? "x" : "c";
87
+ const jevMarker = codexSession ? "c" : "x";
81
88
  if (agySession || codexSession) {
82
89
  if (stdin.terminal_width > 0)
83
90
  process.env.COLUMNS = String(stdin.terminal_width);
@@ -138,24 +145,22 @@ async function main() {
138
145
  codexLoggedOut,
139
146
  showAntigravity: antigravityAllowed,
140
147
  antigravityQuota,
148
+ sessionStatus: status,
149
+ currentMarker,
150
+ jevMarker,
141
151
  });
142
152
  const header = bandMode ? `${BAND_HEADER}\n` : "";
143
- process.stdout.write(`${header}\x1b[0m${microLine}\n${status}\n`);
153
+ process.stdout.write(`${header}\x1b[0m${microLine}\n`);
144
154
  return;
145
155
  }
146
156
 
147
157
  const rows =
148
158
  bandState === "claude"
149
159
  ? []
150
- : getClaudeRows(
151
- currentTier,
152
- agySession || codexSession ? null : contextView,
153
- claudeUsage,
154
- {
155
- accountName: getClaudeEmail(),
156
- promptCache: stdin?.prompt_cache,
157
- },
158
- );
160
+ : getClaudeRows(currentTier, null, claudeUsage, {
161
+ accountName: getClaudeEmail(),
162
+ promptCache: stdin?.prompt_cache,
163
+ });
159
164
  let codexRowIndex = -1;
160
165
  if (showCodex) {
161
166
  codexRowIndex = rows.length;
@@ -180,11 +185,20 @@ async function main() {
180
185
  geminiBlue,
181
186
  antigravityQuota,
182
187
  getAntigravityAccountLabel(),
183
- { contextView: agySession ? contextView : null },
184
188
  ),
185
189
  );
186
190
  }
187
191
 
192
+ for (const row of rows) {
193
+ const marker = stripAnsi(row.prefix);
194
+ const extra =
195
+ marker === `${currentMarker}:`
196
+ ? status.context
197
+ : marker === `${jevMarker}:`
198
+ ? status.jev
199
+ : "";
200
+ if (extra) row.right = [row.right, extra].filter(Boolean).join(" ");
201
+ }
188
202
  const outputLines = renderAlignedRows(rows);
189
203
  if (outputLines[codexRowIndex] != null && codexLoggedOut) {
190
204
  outputLines[codexRowIndex] = `${DIM}${outputLines[codexRowIndex]}${RESET}`;
@@ -200,14 +214,12 @@ async function main() {
200
214
  const resetLines = outputLines.map((line) => `\x1b[0m${line}`);
201
215
  // band 는 첫 줄 표지로 이 HUD 가 --band 를 아는지 확인한다.
202
216
  const header = bandMode ? `${BAND_HEADER}\n` : "";
203
- process.stdout.write(
204
- `${header}${leadingBreaks}${resetLines.join("\n")}\n${status}\n`,
205
- );
217
+ process.stdout.write(`${header}${leadingBreaks}${resetLines.join("\n")}\n`);
206
218
  }
207
219
 
208
220
  main().catch(() => {
209
221
  process.stdout.write(
210
- `\x1b[0m${bold(claudeOrange("c"))}: ${dim(`5h:--% ${formatTimeCell("")} 1w:--% ${formatTimeCellDH("")} | ctx:--%`)}\n`,
222
+ `\x1b[0m${bold(claudeOrange("c"))}: ${dim(`5h:--% ${formatTimeCell("")} 1w:--% ${formatTimeCellDH("")} | ctx:--`)}\n`,
211
223
  );
212
224
  });
213
225
 
package/hud/renderers.mjs CHANGED
@@ -24,7 +24,6 @@ import {
24
24
  SEVEN_DAY_MS,
25
25
  TIME_CELL_INNER_WIDTH,
26
26
  } from "./constants.mjs";
27
- import { buildContextUsageView } from "./context-monitor.mjs";
28
27
  import { cacheGap, claudePromptCache } from "./prompt-cache.mjs";
29
28
  import { getTerminalColumns, tierBar, tierDimBar } from "./terminal.mjs";
30
29
  import {
@@ -91,7 +90,7 @@ export function getMicroLine(
91
90
  showAntigravity = true,
92
91
  codexLoggedOut = false,
93
92
  } = options;
94
- const ctxView = contextView || buildContextUsageView({});
93
+
95
94
  // Claude 5h/1w
96
95
  const cF =
97
96
  claudeUsage?.fiveHourPercent != null
@@ -144,7 +143,18 @@ export function getMicroLine(
144
143
  : agyText;
145
144
  segments.push(`${marker}${dim(":")}${agyValue}`);
146
145
  }
147
- segments.push(`${dim("ctx:")}${contextPercentText(ctxView)}`);
146
+ if (options.sessionStatus) {
147
+ for (let index = 0; index < segments.length; index += 1) {
148
+ const marker = stripAnsi(segments[index]).split(":")[0];
149
+ const extra =
150
+ marker === options.currentMarker
151
+ ? options.sessionStatus.context
152
+ : marker === options.jevMarker
153
+ ? options.sessionStatus.jev
154
+ : "";
155
+ if (extra) segments[index] += ` ${extra}`;
156
+ }
157
+ }
148
158
  return truncateAnsi(segments.join(" "), cols);
149
159
  }
150
160
 
@@ -1,17 +1,16 @@
1
1
  import { buildContextUsageView } from "./context-monitor.mjs";
2
- import { clampPercent, formatTokenCount } from "./utils.mjs";
2
+ import { clampPercent } from "./utils.mjs";
3
3
 
4
4
  export async function sessionStatus(stdin, env = process.env) {
5
- let jev = "Jev ?";
5
+ let jev = "";
6
6
  try {
7
7
  const { isJevEnabled } = await import("../hub/lib/jev-addon.mjs");
8
- jev = isJevEnabled({ env }) ? "Jev ON" : "Jev OFF";
8
+ jev = isJevEnabled({ env }) ? "j" : "";
9
9
  } catch {
10
10
  // 설정을 판정하지 못한 것은 런타임 호출 실패의 증거가 아니다.
11
11
  }
12
12
  const window = stdin?.context_window;
13
13
  const view = buildContextUsageView(stdin);
14
- let remaining = "미확인";
15
14
  const usageValues = Object.entries(window?.current_usage || {})
16
15
  .filter(([key]) =>
17
16
  [
@@ -22,21 +21,26 @@ export async function sessionStatus(stdin, env = process.env) {
22
21
  ].includes(key),
23
22
  )
24
23
  .map(([, value]) => value);
25
- const knownZero =
24
+ const hasUsage =
26
25
  usageValues.length > 0 &&
27
- usageValues.every((value) => value === 0) &&
26
+ usageValues.every((value) => Number.isFinite(value) && value >= 0);
27
+ const hasWindow =
28
28
  Number.isFinite(window?.context_window_size) &&
29
29
  window.context_window_size > 0;
30
- if (knownZero) {
31
- remaining = `${formatTokenCount(window.context_window_size).replace("K", "k")} 남음`;
32
- } else if (view.source === "stdin.tokens") {
33
- remaining = `${formatTokenCount(Math.max(0, view.limitTokens - view.usedTokens)).replace("K", "k")} 남음`;
34
- } else {
35
- const value =
36
- window?.remaining_percentage ??
37
- (window?.used_percentage == null ? null : 100 - window.used_percentage);
38
- if (typeof value === "number" && Number.isFinite(value))
39
- remaining = `${clampPercent(value)}% 남음`;
30
+ const knownZero = hasUsage && usageValues.every((value) => value === 0);
31
+ let context = "ctx:--";
32
+ if (hasWindow && hasUsage && (knownZero || view.source === "stdin.tokens")) {
33
+ const used = knownZero ? 0 : view.usedTokens;
34
+ context = `ctx:${clampPercent((used / window.context_window_size) * 100)}%`;
35
+ } else if (
36
+ !(stdin?.product === "antigravity" && window?.context_window_size === 0)
37
+ ) {
38
+ const used = Number.isFinite(window?.used_percentage)
39
+ ? clampPercent(window.used_percentage)
40
+ : Number.isFinite(window?.remaining_percentage)
41
+ ? 100 - clampPercent(window.remaining_percentage)
42
+ : null;
43
+ if (used != null) context = `ctx:${used}%`;
40
44
  }
41
- return `${jev} | 문맥 ${remaining}`;
45
+ return { context, jev };
42
46
  }
@@ -56,12 +56,14 @@ export async function configureCodexHud(runTmux, target, env = process.env) {
56
56
  .join(" ")
57
57
  .replace(/#/g, "##");
58
58
  for (const [key, value] of [
59
- ["status", "4"],
59
+ ["status", "3"],
60
60
  ["status-interval", "5"],
61
61
  ["status-format[0]", `#(${command} #{client_width})`],
62
- ...[1, 2, 3].map((n) => [`status-format[${n}]`, `#{@tfx_hud_${n}}`]),
62
+ ...[1, 2].map((n) => [`status-format[${n}]`, `#{@tfx_hud_${n}}`]),
63
63
  ])
64
64
  await runTmux(null, ["set-option", "-t", target, key, value]);
65
+ for (const key of ["status-format[3]", "@tfx_hud_3"])
66
+ await runTmux(null, ["set-option", "-u", "-t", target, key]);
65
67
  }
66
68
 
67
69
  export async function updateTmuxHud(session, pane, columns) {
@@ -111,8 +113,7 @@ export async function updateTmuxHud(session, pane, columns) {
111
113
  rendering.child.stdin.end(JSON.stringify(input));
112
114
  const { stdout } = await rendering;
113
115
  const lines = stripAnsi(stdout).trim().split("\n");
114
- const status = lines.pop();
115
- for (let n = 1; n <= 3; n += 1) {
116
+ for (let n = 0; n < 3; n += 1) {
116
117
  await exec(
117
118
  "tmux",
118
119
  [
@@ -120,12 +121,12 @@ export async function updateTmuxHud(session, pane, columns) {
120
121
  "-t",
121
122
  session,
122
123
  `@tfx_hud_${n}`,
123
- (lines[n - 1] || "").replace(/#/g, "##"),
124
+ (lines[n] || "").replace(/#/g, "##"),
124
125
  ],
125
126
  { timeout: 2000 },
126
127
  );
127
128
  }
128
- return status;
129
+ return lines[0] || "";
129
130
  }
130
131
 
131
132
  if (process.argv[1] === fileURLToPath(import.meta.url)) {
@@ -134,6 +135,6 @@ if (process.argv[1] === fileURLToPath(import.meta.url)) {
134
135
  process.stdout.write(`${status}\n`);
135
136
  })
136
137
  .catch(() => {
137
- process.stdout.write("Jev ? | 문맥 미확인\n");
138
+ process.stdout.write("c: ctx:--\n");
138
139
  });
139
140
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@triflux/core",
3
- "version": "10.88.0",
3
+ "version": "10.88.1",
4
4
  "description": "triflux core — CLI routing, adapters. Zero native dependencies.",
5
5
  "type": "module",
6
6
  "main": "hub/index.mjs",