@ekkos/cli 1.2.12 → 1.2.14

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.
@@ -1081,72 +1081,50 @@ async function launchDashboard(initialSessionName, jsonlPath, refreshMs) {
1081
1081
  let header = '';
1082
1082
  let separator = '';
1083
1083
  let rows = [];
1084
- // Responsive table layouts keep headers visible even in very narrow panes.
1085
- if (w >= 60) {
1086
- // Full mode: Turn, Model, Context, Cache Rd, Cache Wr, Output, Cost
1087
- const colNum = 4;
1088
- const colM = 7;
1089
- const colCtx = 7;
1090
- const colCost = 8;
1091
- const nDividers = 6;
1092
- const fixedW = colNum + colM + colCtx + colCost;
1093
- const flexTotal = w - fixedW - nDividers;
1094
- const rdW = Math.max(10, Math.floor(flexTotal * 0.35));
1095
- const wrW = Math.max(11, Math.floor(flexTotal * 0.30));
1096
- const outW = Math.max(6, flexTotal - rdW - wrW);
1097
- header = `${pad('Turn', colNum)}${div}${rpad('Model', colM)}${div}${rpad('Contex', colCtx)}${div}${rpad('Cache Read', rdW)}${div}${rpad('Cache Write', wrW)}${div}${rpad('Output', outW)}${div}${rpad('Cost', colCost)}`;
1098
- separator = `${'─'.repeat(colNum)}┼${'─'.repeat(colM)}┼${'─'.repeat(colCtx)}┼${'─'.repeat(rdW)}┼${'─'.repeat(wrW)}┼${'─'.repeat(outW)}┼${'─'.repeat(colCost)}`;
1099
- rows = turns.map(t => {
1100
- const mTag = modelTag(t.routedModel);
1101
- const mColor = t.routedModel.includes('haiku') ? 'green' : t.routedModel.includes('sonnet') ? 'blue' : 'magenta';
1102
- const costFlag = t.cost > 1.0 ? '{red-fg}' : t.cost > 0.5 ? '{yellow-fg}' : '{white-fg}';
1103
- const costEnd = t.cost > 1.0 ? '{/red-fg}' : t.cost > 0.5 ? '{/yellow-fg}' : '{/white-fg}';
1104
- return (pad(String(t.turn), colNum) + div +
1105
- `{${mColor}-fg}${cpad(mTag, colM)}{/${mColor}-fg}` + div +
1106
- rpad(`${t.contextPct.toFixed(0)}%`, colCtx) + div +
1107
- `{green-fg}${rpad(fmtK(t.cacheRead), rdW)}{/green-fg}` + div +
1108
- `{yellow-fg}${rpad(fmtK(t.cacheCreate), wrW)}{/yellow-fg}` + div +
1109
- `{cyan-fg}${rpad(fmtK(t.output), outW)}{/cyan-fg}` + div +
1110
- costFlag + rpad(`$${t.cost.toFixed(2)}`, colCost) + costEnd);
1111
- });
1112
- }
1113
- else if (w >= 30) {
1114
- // Compact mode: drop cache split columns to preserve readable headers.
1115
- const colNum = 4;
1116
- const colM = 6;
1117
- const colCtx = 6;
1118
- const colCost = 6;
1119
- const nDividers = 4;
1120
- const outW = Math.max(4, w - (colNum + colM + colCtx + colCost + nDividers));
1121
- header = `${pad('Turn', colNum)}${div}${rpad('Model', colM)}${div}${rpad('Context', colCtx)}${div}${rpad('Output', outW)}${div}${rpad('Cost', colCost)}`;
1122
- separator = `${'─'.repeat(colNum)}┼${'─'.repeat(colM)}┼${'─'.repeat(colCtx)}┼${'─'.repeat(outW)}┼${'─'.repeat(colCost)}`;
1123
- rows = turns.map(t => {
1124
- const mTag = modelTag(t.routedModel);
1125
- const mColor = t.routedModel.includes('haiku') ? 'green' : t.routedModel.includes('sonnet') ? 'blue' : 'magenta';
1126
- const costFlag = t.cost > 1.0 ? '{red-fg}' : t.cost > 0.5 ? '{yellow-fg}' : '{white-fg}';
1127
- const costEnd = t.cost > 1.0 ? '{/red-fg}' : t.cost > 0.5 ? '{/yellow-fg}' : '{/white-fg}';
1128
- return (pad(String(t.turn), colNum) + div +
1129
- `{${mColor}-fg}${cpad(mTag, colM)}{/${mColor}-fg}` + div +
1130
- rpad(`${t.contextPct.toFixed(0)}%`, colCtx) + div +
1131
- `{cyan-fg}${rpad(fmtK(t.output), outW)}{/cyan-fg}` + div +
1132
- costFlag + rpad(`$${t.cost.toFixed(2)}`, colCost) + costEnd);
1133
- });
1134
- }
1135
- else {
1136
- // Minimal mode: guaranteed no-wrap fallback.
1137
- const colNum = 4;
1138
- const colCtx = 6;
1139
- const colCost = 6;
1140
- header = `${pad('Turn', colNum)}${div}${rpad('Context', colCtx)}${div}${rpad('Cost', colCost)}`;
1141
- separator = `${'─'.repeat(colNum)}┼${'─'.repeat(colCtx)}┼${'─'.repeat(colCost)}`;
1142
- rows = turns.map(t => {
1143
- const costFlag = t.cost > 1.0 ? '{red-fg}' : t.cost > 0.5 ? '{yellow-fg}' : '{white-fg}';
1144
- const costEnd = t.cost > 1.0 ? '{/red-fg}' : t.cost > 0.5 ? '{/yellow-fg}' : '{/white-fg}';
1145
- return (pad(String(t.turn), colNum) + div +
1146
- rpad(`${t.contextPct.toFixed(0)}%`, colCtx) + div +
1147
- costFlag + rpad(`$${t.cost.toFixed(2)}`, colCost) + costEnd);
1148
- });
1084
+ // Always show all 7 columns: Turn, Model, Context, Cache Rd, Cache Wr, Output, Cost
1085
+ // Shrink flex columns to fit narrow panes instead of dropping them.
1086
+ const colNum = 4;
1087
+ const colM = 7;
1088
+ const colCtx = 7;
1089
+ const colCost = 8;
1090
+ const nDividers = 6;
1091
+ const fixedW = colNum + colM + colCtx + colCost;
1092
+ const flexTotal = Math.max(0, w - fixedW - nDividers);
1093
+ let rdW = Math.max(5, Math.floor(flexTotal * 0.35));
1094
+ let wrW = Math.max(5, Math.floor(flexTotal * 0.30));
1095
+ let outW = Math.max(6, flexTotal - rdW - wrW);
1096
+ // Trim flex columns if they overflow available width
1097
+ let totalW = fixedW + nDividers + rdW + wrW + outW;
1098
+ if (totalW > w) {
1099
+ let overflow = totalW - w;
1100
+ const trimOut = Math.min(overflow, Math.max(0, outW - 4));
1101
+ outW -= trimOut;
1102
+ overflow -= trimOut;
1103
+ if (overflow > 0) {
1104
+ const trimWr = Math.min(overflow, Math.max(0, wrW - 4));
1105
+ wrW -= trimWr;
1106
+ overflow -= trimWr;
1107
+ }
1108
+ if (overflow > 0) {
1109
+ const trimRd = Math.min(overflow, Math.max(0, rdW - 4));
1110
+ rdW -= trimRd;
1111
+ }
1149
1112
  }
1113
+ header = `{bold}${pad('Turn', colNum)}${div}${pad('Model', colM)}${div}${pad('Context', colCtx)}${div}${rpad('Cache Rd', rdW)}${div}${rpad('Cache Wr', wrW)}${div}${rpad('Output', outW)}${div}${rpad('Cost', colCost)}{/bold}`;
1114
+ separator = `{gray-fg}${'─'.repeat(colNum)}┼${'─'.repeat(colM)}┼${'─'.repeat(colCtx)}┼${'─'.repeat(rdW)}┼${'─'.repeat(wrW)}┼${'─'.repeat(outW)}┼${'─'.repeat(colCost)}{/gray-fg}`;
1115
+ rows = turns.map(t => {
1116
+ const mTag = modelTag(t.routedModel);
1117
+ const mColor = t.routedModel.includes('haiku') ? 'green' : t.routedModel.includes('sonnet') ? 'blue' : 'magenta';
1118
+ const costFlag = t.cost > 1.0 ? '{red-fg}' : t.cost > 0.5 ? '{yellow-fg}' : '{white-fg}';
1119
+ const costEnd = t.cost > 1.0 ? '{/red-fg}' : t.cost > 0.5 ? '{/yellow-fg}' : '{/white-fg}';
1120
+ return (pad(String(t.turn), colNum) + div +
1121
+ `{${mColor}-fg}${pad(mTag, colM)}{/${mColor}-fg}` + div +
1122
+ pad(`${t.contextPct.toFixed(0)}%`, colCtx) + div +
1123
+ `{green-fg}${rpad(fmtK(t.cacheRead), rdW)}{/green-fg}` + div +
1124
+ `{yellow-fg}${rpad(fmtK(t.cacheCreate), wrW)}{/yellow-fg}` + div +
1125
+ `{cyan-fg}${rpad(fmtK(t.output), outW)}{/cyan-fg}` + div +
1126
+ costFlag + rpad(`$${t.cost.toFixed(2)}`, colCost) + costEnd);
1127
+ });
1150
1128
  const lines = [header, separator, ...rows];
1151
1129
  turnBox.setContent(lines.join('\n'));
1152
1130
  // Restore scroll position AFTER content update
@@ -1137,10 +1137,7 @@ async function run(options) {
1137
1137
  // ══════════════════════════════════════════════════════════════════════════
1138
1138
  // STARTUP BANNER WITH COLOR PULSE ANIMATION
1139
1139
  // ══════════════════════════════════════════════════════════════════════════
1140
- // Skip cursor-manipulation animations on Windows ConPTY + cmd /c can't handle rapid
1141
- // cursor repositioning (\x1B[6A, \b, etc.), leaving the terminal in a dirty state that
1142
- // causes Ink rendering artifacts in Claude Code. Use a clean static banner instead.
1143
- const skipFancyIntro = isWindows || process.env.EKKOS_REMOTE_SESSION === '1' || process.env.EKKOS_NO_SPLASH === '1';
1140
+ const skipFancyIntro = process.env.EKKOS_REMOTE_SESSION === '1' || process.env.EKKOS_NO_SPLASH === '1';
1144
1141
  if (!skipFancyIntro) {
1145
1142
  const logoLines = [
1146
1143
  ' ▄▄▄▄▄ ▄▄▄▄▄▄▄ ▄▄▄ ▄▄ ▄▄',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ekkos/cli",
3
- "version": "1.2.12",
3
+ "version": "1.2.14",
4
4
  "description": "Setup ekkOS memory for AI coding assistants (Claude Code, Cursor, Windsurf)",
5
5
  "main": "dist/index.js",
6
6
  "bin": {