triflux 10.2.0 → 10.2.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.
package/hub/team/ansi.mjs CHANGED
@@ -163,7 +163,7 @@ export function box(lines, width, borderColor = "", options = {}) {
163
163
  const bot = botChars
164
164
  .map((glyph, col) => renderBorderChar(glyph, totalRows - 1, col, highlightCell, bc(totalRows - 1), highlightSeq))
165
165
  .join("");
166
- const mid = `${bc(Math.floor(totalRows / 2))}${BOX.ml}${BOX.h.repeat(width - 2)}${BOX.mr}${rst}`;
166
+ const mid = `${bc(Math.floor(totalRows / 2))}${BOX.ml}${BOX.h.repeat(Math.max(0, width - 2))}${BOX.mr}${rst}`;
167
167
  const body = lines.map((l, i) => {
168
168
  const row = i + 1;
169
169
  const content = options.titleFlashBg && i === 0
@@ -128,7 +128,7 @@ function buildHeader(width, names, workers, pipeline, startedAt) {
128
128
  else if (status === "running" || status === "in_progress") counts.running++;
129
129
  }
130
130
  const elapsed = Math.max(0, Math.round((Date.now() - startedAt) / 1000));
131
- const line1 = color(` triflux ${VERSION} `, FG.black, BG.header)
131
+ const line1 = color(` triflux ${VERSION} `, FG.white, BG.header)
132
132
  + ` ${bold(`phase ${pipeline.phase || "exec"}`)}`
133
133
  + ` ${dim(`+${elapsed}s`)} ${names.length} workers`;
134
134
  const line2 = `${color(`ok ${counts.ok}`, MOCHA.ok)} ${color(`partial ${counts.partial}`, MOCHA.partial)} ${color(`failed ${counts.failed}`, MOCHA.fail)} ${color(`running ${counts.running}`, MOCHA.executing)}`;
@@ -210,6 +210,7 @@ export function createLiteDashboard(opts = {}) {
210
210
  let focusTab = "log";
211
211
  let helpVisible = false;
212
212
  let prevFrame = [];
213
+ let prevWidth = 0;
213
214
  let inputAttached = false;
214
215
  let rawModeEnabled = false;
215
216
 
@@ -264,7 +265,14 @@ export function createLiteDashboard(opts = {}) {
264
265
  return;
265
266
  }
266
267
  if (key === "\r" || key === "\n") {
267
- triggerOpenSelected();
268
+ if (typeof onOpenSelectedWorker !== "function") {
269
+ // 콜백 없으면 탭 순환 (기본 동작)
270
+ const tabs = ["log", "detail", "files"];
271
+ focusTab = tabs[(tabs.indexOf(focusTab) + 1) % tabs.length];
272
+ } else {
273
+ triggerOpenSelected();
274
+ }
275
+ render();
268
276
  return;
269
277
  }
270
278
  if (key === "\x1b[13;2u" || key === "\x1b[27;13;2~" || key === "\x1b\r" || key === "\x1b\n") {
@@ -339,6 +347,13 @@ export function createLiteDashboard(opts = {}) {
339
347
  if (isTTY) {
340
348
  const width = viewportColumns();
341
349
  const padded = rowsOut.map((line) => padRight(String(line ?? ""), width));
350
+ // Full redraw on first frame or terminal resize to avoid artifacts
351
+ if (prevFrame.length === 0 || width !== prevWidth) {
352
+ prevWidth = width;
353
+ write(cursorHome + padded.map((l) => l + clearToEnd).join("\n") + eraseBelow);
354
+ prevFrame = padded;
355
+ return;
356
+ }
342
357
  // Diff-based rendering: only rewrite lines that actually changed
343
358
  let buf = "";
344
359
  for (let i = 0; i < padded.length; i++) {
@@ -361,6 +376,7 @@ export function createLiteDashboard(opts = {}) {
361
376
  if (rawModeEnabled && typeof input?.setRawMode === "function") input.setRawMode(false);
362
377
  if (inputAttached && typeof input?.pause === "function") input.pause();
363
378
  if (isTTY) write(cursorShow + altScreenOff);
379
+ prevFrame = [];
364
380
  closed = true;
365
381
  }
366
382
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "triflux",
3
- "version": "10.2.0",
3
+ "version": "10.2.1",
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": {