lumira 1.7.0 → 1.8.0

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/README.md CHANGED
@@ -26,7 +26,7 @@ Interactive wizard — preset, theme, icons — previewed live before write.
26
26
 
27
27
  > 3,400+ monthly downloads, zero marketing. Try it for one session — `npx lumira install`.
28
28
 
29
- > **What's new in v1.7.0:** added-dirs badge (`+N dirs`, orange at ≥5) and worktree origin-branch breadcrumb (`↳ <branch>`) both togglable via `display.addedDirs` / `display.worktreeBreadcrumb`, on by default in `full`/`balanced`. Combined with the [`lumira stats` CLI](#stats-cli) (v1.5), `API N%` latency widget (v1.4.0), 7-day quota projection warning (v1.3.0), and auto-compact proximity glyph ⚠ (v1.4.1), recent releases add several diagnostic signals to the session.
29
+ > **What's new in v1.8.0:** compaction counter (`⊙ N` on line 2) tracks how many times the session has been compacted, pairing with the auto-compact proximity glyph ⚠. Togglable via `display.compactionCount`, on by default in `full`/`balanced`. Combined with the added-dirs badge and worktree breadcrumb (v1.7.0), [`lumira stats` CLI](#stats-cli) (v1.5), `API N%` latency widget (v1.4.0), 7-day quota projection warning (v1.3.0), and auto-compact proximity glyph ⚠ (v1.4.1), recent releases add several diagnostic signals to the session.
30
30
 
31
31
  ## Table of contents
32
32
 
@@ -288,6 +288,7 @@ Create `~/.config/lumira/config.json`:
288
288
  "linesChanged": true,
289
289
  "memory": true,
290
290
  "agents": true,
291
+ "compactionCount": true,
291
292
  "health": false,
292
293
  "contextWarningThreshold": 70,
293
294
  "contextCriticalThreshold": 85
package/dist/config.js CHANGED
@@ -293,6 +293,7 @@ const PRESET_DEFS = {
293
293
  apiLatency: false,
294
294
  addedDirs: false,
295
295
  worktreeBreadcrumb: false,
296
+ compactionCount: false,
296
297
  },
297
298
  },
298
299
  };
@@ -124,7 +124,7 @@ export function extractToolTarget(toolName, input) {
124
124
  // same canonicalisation and allow-list semantics. See `path.ts` for caveats
125
125
  // about the string-level (non-symlink-following) nature of the check.
126
126
  export async function parseTranscript(transcriptPath) {
127
- const result = { ...EMPTY_TRANSCRIPT, tools: [], agents: [], todos: [] };
127
+ const result = { ...EMPTY_TRANSCRIPT, tools: [], agents: [], todos: [], compactionCount: 0 };
128
128
  if (!transcriptPath || !existsSync(transcriptPath)) {
129
129
  if (log.enabled)
130
130
  log('skip — transcript path missing or nonexistent:', transcriptPath || '(empty)');
@@ -185,6 +185,8 @@ export async function parseTranscript(transcriptPath) {
185
185
  const entry = JSON.parse(line);
186
186
  if (!result.sessionStart && entry.timestamp)
187
187
  result.sessionStart = new Date(entry.timestamp);
188
+ if (entry.type === 'system' && entry.subtype === 'compact_boundary')
189
+ result.compactionCount++;
188
190
  const effortMatch = Array.isArray(entry.message?.content)
189
191
  ? entry.message.content
190
192
  .filter((b) => b.type === 'text')
@@ -25,7 +25,7 @@ export function formatCountdown(resetsAt) {
25
25
  return `${s}s`;
26
26
  }
27
27
  export function renderLine2(ctx, c) {
28
- const { input, tokenSpeed, transcript: { thinkingEffort }, config: { display }, cols, memory, mcp, icons } = ctx;
28
+ const { input, tokenSpeed, transcript: { thinkingEffort, compactionCount }, config: { display }, cols, memory, mcp, icons } = ctx;
29
29
  const leftParts = [];
30
30
  const rightParts = [];
31
31
  // Track context slots pushed so critical rate-limit segments anchor after
@@ -56,6 +56,11 @@ export function renderLine2(ctx, c) {
56
56
  contextSlotCount++;
57
57
  }
58
58
  }
59
+ // Compaction counter — how many times this session has been compacted.
60
+ // Self-gating: renders nothing at count 0. Paired with the context bar.
61
+ if (display.compactionCount && compactionCount > 0) {
62
+ leftParts.push(c.dim(`⊙ ${compactionCount}`));
63
+ }
59
64
  // Tokens
60
65
  if (display.tokens) {
61
66
  const inTokens = input.tokens.input;
@@ -44,7 +44,7 @@ function getApiLatencyBg(pct, palette) {
44
44
  // urgency channels the user actually needs at a glance. Decision rationale
45
45
  // recorded against PR #47.
46
46
  function buildSegments(ctx, palette, c) {
47
- const { input, config: { display }, icons, mcp, transcript: { thinkingEffort } } = ctx;
47
+ const { input, config: { display }, icons, mcp, transcript: { thinkingEffort, compactionCount } } = ctx;
48
48
  const segments = [];
49
49
  // Context bar — always highest priority. plain=true so the bar cells inherit
50
50
  // the powerline segment bg; only %/icon/hint emit color escapes.
@@ -72,6 +72,11 @@ function buildSegments(ctx, palette, c) {
72
72
  segments.push({ text: `${formatTokens(used)}/${formatTokens(capacity)}`, bg: palette.dirBg, fg: palette.fg, priority: 90 });
73
73
  }
74
74
  }
75
+ // Compaction counter — self-gating at 0; priority 88 keeps it adjacent to
76
+ // the context family (contextBar=100, contextTokens=90).
77
+ if (display.compactionCount && compactionCount > 0) {
78
+ segments.push({ text: `⊙ ${compactionCount}`, bg: palette.dirBg, fg: palette.fg, priority: 88 });
79
+ }
75
80
  // 7d projection — computed once, surfaced inside the 7d segment when the
76
81
  // badge is visible (≥50%), or as a standalone segment when it isn't. Mirrors
77
82
  // classic line2: badge filter hides noise, projection surfaces signal.
package/dist/types.js CHANGED
@@ -11,6 +11,7 @@ export const EMPTY_TRANSCRIPT = Object.freeze({
11
11
  todos: Object.freeze([]),
12
12
  thinkingEffort: '',
13
13
  sessionStart: null,
14
+ compactionCount: 0,
14
15
  });
15
16
  /** Hard cap on per-command wall time (ms). */
16
17
  export const CUSTOM_COMMAND_MAX_TIMEOUT_MS = 2000;
@@ -106,6 +107,7 @@ export const DEFAULT_DISPLAY = {
106
107
  apiLatency: true,
107
108
  addedDirs: true,
108
109
  worktreeBreadcrumb: true,
110
+ compactionCount: true,
109
111
  contextWarningThreshold: DEFAULT_CONTEXT_WARNING_THRESHOLD,
110
112
  contextCriticalThreshold: DEFAULT_CONTEXT_CRITICAL_THRESHOLD,
111
113
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lumira",
3
- "version": "1.7.0",
3
+ "version": "1.8.0",
4
4
  "description": "Real-time statusline HUD for Claude Code and Qwen Code. Includes session analytics CLI, API latency overhead widget, 7d quota projection, auto-compact proximity warnings, themes, and powerline. Zero deps.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",