@reedchan/statusline 1.9.0 → 1.10.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/README.md CHANGED
@@ -7,7 +7,7 @@ English | [中文](README_CN.md)
7
7
  Replaces pi's footer with a labelled two-row one. Every value carries a word, so nothing has to be
8
8
  decoded from a symbol or remembered from a legend.
9
9
 
10
- ```
10
+ ```text
11
11
  Context █████████▍░░░░░░░░░░ 47% 471k / 1.0M Input 194k · Output 89k | Cache hit 99.9% | Cost $0.229 · Today $1.63
12
12
  ~/.pi (master) deepseek-flash · Effort high | TTFT 482ms · Avg TTFT 612ms | Last 729 tok/s · Avg 512 tok/s
13
13
  LSP Active: typescript
package/README_CN.md CHANGED
@@ -6,7 +6,7 @@
6
6
 
7
7
  替换 pi 的 footer,改成带文字标签的两行。每个值都带一个词,不需要靠符号猜、也不需要记图例。
8
8
 
9
- ```
9
+ ```text
10
10
  Context █████████▍░░░░░░░░░░ 47% 471k / 1.0M Input 194k · Output 89k | Cache hit 99.9% | Cost $0.229 · Today $1.63
11
11
  ~/.pi (master) deepseek-flash · Effort high | TTFT 482ms · Avg TTFT 612ms | Last 729 tok/s · Avg 512 tok/s
12
12
  LSP Active: typescript
@@ -521,33 +521,28 @@ export default function (pi: ExtensionAPI) {
521
521
  const separator = theme.fg('dim', ' · ')
522
522
  const wall = theme.fg('dim', ' | ')
523
523
  const identity = [theme.fg('accent', model)]
524
- if (ctx.thinkingLevel) identity.push(pair(theme, 'Effort', ctx.thinkingLevel, 'muted'))
524
+ if (ctx.thinkingLevel) identity.push(pair(theme, 'Effort', ctx.thinkingLevel))
525
525
 
526
526
  const ttft: string[] = []
527
527
  const waiting = ttftDisplay(requestAt, firstTokenAt, Date.now())
528
528
  if (waiting !== null) {
529
529
  // The clock is running: this wait has no reading yet, so the previous turn's
530
530
  // numbers would only be mistaken for the current one.
531
- ttft.push(pair(theme, 'TTFT', waiting.text, 'muted'))
531
+ ttft.push(pair(theme, 'TTFT', waiting.text))
532
532
  } else if (reading) {
533
533
  if (reading.ttftMs !== null)
534
- ttft.push(pair(theme, 'TTFT', formatLatency(reading.ttftMs), 'muted'))
534
+ ttft.push(pair(theme, 'TTFT', formatLatency(reading.ttftMs)))
535
535
  }
536
536
  const avgTtft = avgMs(totalTtftMs, ttftCount)
537
- if (avgTtft !== null) ttft.push(pair(theme, 'Avg TTFT', formatLatency(avgTtft), 'muted'))
537
+ if (avgTtft !== null) ttft.push(pair(theme, 'Avg TTFT', formatLatency(avgTtft)))
538
538
 
539
539
  const throughput: string[] = []
540
540
  if (reading) {
541
541
  throughput.push(
542
- pair(
543
- theme,
544
- 'Last',
545
- `${reading.exact ? '' : '~'}${formatTps(reading.rate)} tok/s`,
546
- reading.exact ? 'success' : 'dim',
547
- ),
542
+ pair(theme, 'Last', `${reading.exact ? '' : '~'}${formatTps(reading.rate)} tok/s`),
548
543
  )
549
544
  }
550
- if (avg !== null) throughput.push(pair(theme, 'Avg', `${formatTps(avg)} tok/s`, 'muted'))
545
+ if (avg !== null) throughput.push(pair(theme, 'Avg', `${formatTps(avg)} tok/s`))
551
546
 
552
547
  const row2Right = [identity, ttft, throughput]
553
548
  .filter((group) => group.length > 0)
@@ -711,6 +706,10 @@ export default function (pi: ExtensionAPI) {
711
706
  ttftCount += 1
712
707
  persist(ctx.sessionManager.getSessionFile() ?? null)
713
708
  publish((tokens / decodeMs) * 1000, output > 0, measured)
709
+ } else if (measured !== null && decodeMs > 0) {
710
+ // The frozen Last must be this message's whole-message rate, never the last live
711
+ // sliding-window sample: a buffered burst of chunks mid-stream reads triple.
712
+ publish((tokens / decodeMs) * 1000, output > 0, measured)
714
713
  }
715
714
  // Null it with the stream: a request that has produced its message is no longer in flight, and
716
715
  // a stale anchor would let the live branch count against nothing until the next turn.
@@ -41,7 +41,9 @@ export const ANSI = /\u001b\[[0-9;]*m/g
41
41
  * an unrelated extension that happens to use the same words is left alone.
42
42
  */
43
43
  export const QUIET_STATUS: ReadonlyArray<readonly [string, RegExp]> = [
44
- ['pi-lens-lsp', /^LSP Inactive$/i],
44
+ // pi-lens reports language-server health here. Useful when diagnostics break; permanent
45
+ // noise once they work, so the whole LSP line stays out of the footer.
46
+ ['pi-lens-lsp', /^LSP/i],
45
47
  ]
46
48
 
47
49
  export function formatTokens(count: number): string {
@@ -63,7 +65,9 @@ export function formatLatency(ms: number): string {
63
65
  const clamped = Math.max(0, ms)
64
66
  if (clamped < 1000) return `${Math.round(clamped)}ms`
65
67
  const seconds = clamped / 1000
66
- return `${seconds < 10 ? Math.round(seconds * 10) / 10 : Math.round(seconds)}s`
68
+ // Fixed one decimal under 10s: dropping the ".0" costs two columns, and the whole row would
69
+ // twitch every time a ticking count crossed an integer.
70
+ return `${seconds < 10 ? seconds.toFixed(1) : Math.round(seconds)}s`
67
71
  }
68
72
 
69
73
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@reedchan/statusline",
3
- "version": "1.9.0",
3
+ "version": "1.10.1",
4
4
  "description": "Replaces pi's footer with a labelled two-row status line: context pressure as a fixed-size meter, cache and cost, the model and effort level, and the latest turn's TTFT and decode throughput in tokens/second.",
5
5
  "keywords": [
6
6
  "bun",