copilot-statusline 0.1.12 → 0.1.13

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
@@ -24,6 +24,8 @@
24
24
 
25
25
  > **Based on [ccstatusline](https://github.com/sirmalloc/ccstatusline)** by [@sirmalloc](https://github.com/sirmalloc) — the excellent customizable statusline for Claude Code CLI. This project adapts its architecture, TUI, and rendering engine for the GitHub Copilot CLI payload format. Huge thanks to Matthew Breedlove for the original work.
26
26
 
27
+ > **Requirements:** GitHub Copilot CLI **≥ 1.0.35** for live context widgets (`Context %`, `Context Bar`, `Context Length`, `Remaining Tokens`). Older versions miss the underlying `current_context_tokens` / `displayed_context_limit` fields and these widgets render blank.
28
+
27
29
  ---
28
30
 
29
31
  ## 📚 Table of Contents
@@ -52913,7 +52913,7 @@ import { execSync as execSync3 } from "child_process";
52913
52913
  import * as fs5 from "fs";
52914
52914
  import * as path4 from "path";
52915
52915
  var __dirname = "/Users/ts/workspace/active/statusline/copilot_statusline/src/utils";
52916
- var PACKAGE_VERSION = "0.1.12";
52916
+ var PACKAGE_VERSION = "0.1.13";
52917
52917
  function getPackageVersion() {
52918
52918
  if (/^\d+\.\d+\.\d+/.test(PACKAGE_VERSION)) {
52919
52919
  return PACKAGE_VERSION;
@@ -54074,14 +54074,18 @@ function getContextWindowMetrics(data) {
54074
54074
  const contextWindow = data?.context_window;
54075
54075
  const empty = {
54076
54076
  windowSize: null,
54077
+ displayedContextLimit: null,
54077
54078
  usedTokens: null,
54078
54079
  contextLengthTokens: null,
54080
+ currentContextTokens: null,
54081
+ currentContextUsedPercentage: null,
54079
54082
  usedPercentage: null,
54080
54083
  remainingPercentage: null,
54081
54084
  totalInputTokens: null,
54082
54085
  totalOutputTokens: null,
54083
54086
  cachedTokens: null,
54084
54087
  totalTokens: null,
54088
+ reasoningTokens: null,
54085
54089
  remainingTokens: null,
54086
54090
  lastCallInputTokens: null,
54087
54091
  lastCallOutputTokens: null,
@@ -54093,6 +54097,12 @@ function getContextWindowMetrics(data) {
54093
54097
  }
54094
54098
  const rawWindowSize = toFiniteNonNegativeNumber(contextWindow.context_window_size);
54095
54099
  const windowSize = rawWindowSize !== null && rawWindowSize > 0 ? rawWindowSize : null;
54100
+ const rawDisplayedLimit = toFiniteNonNegativeNumber(contextWindow.displayed_context_limit);
54101
+ const displayedContextLimit = rawDisplayedLimit !== null && rawDisplayedLimit > 0 ? rawDisplayedLimit : null;
54102
+ const currentContextTokens = toFiniteNonNegativeNumber(contextWindow.current_context_tokens);
54103
+ const rawCurrentPct = toFiniteNonNegativeNumber(contextWindow.current_context_used_percentage);
54104
+ const currentContextUsedPercentage = rawCurrentPct !== null ? clampPercentage(rawCurrentPct) : null;
54105
+ const reasoningTokens = toFiniteNonNegativeNumber(contextWindow.total_reasoning_tokens);
54096
54106
  const totalInputTokens = toFiniteNonNegativeNumber(contextWindow.total_input_tokens);
54097
54107
  const totalOutputTokens = toFiniteNonNegativeNumber(contextWindow.total_output_tokens);
54098
54108
  const cacheReadTokens = toFiniteNonNegativeNumber(contextWindow.total_cache_read_tokens);
@@ -54123,14 +54133,18 @@ function getContextWindowMetrics(data) {
54123
54133
  const contextLengthFromAuthoritative = usedTokensFromRemaining ?? usedTokensFromPercentage;
54124
54134
  return {
54125
54135
  windowSize,
54136
+ displayedContextLimit,
54126
54137
  usedTokens,
54127
54138
  contextLengthTokens: contextLengthFromAuthoritative ?? contextLengthTokens ?? usedTokens,
54139
+ currentContextTokens,
54140
+ currentContextUsedPercentage,
54128
54141
  usedPercentage,
54129
54142
  remainingPercentage,
54130
54143
  totalInputTokens,
54131
54144
  totalOutputTokens,
54132
54145
  cachedTokens,
54133
54146
  totalTokens,
54147
+ reasoningTokens,
54134
54148
  remainingTokens,
54135
54149
  lastCallInputTokens,
54136
54150
  lastCallOutputTokens,
@@ -54255,6 +54269,40 @@ class TokensCachedWidget {
54255
54269
  return true;
54256
54270
  }
54257
54271
  }
54272
+ // src/widgets/TokensReasoning.ts
54273
+ class TokensReasoningWidget {
54274
+ getDefaultColor() {
54275
+ return "magenta";
54276
+ }
54277
+ getDescription() {
54278
+ return "Shows total reasoning (thinking) tokens consumed this session";
54279
+ }
54280
+ getDisplayName() {
54281
+ return "Tokens Reasoning";
54282
+ }
54283
+ getCategory() {
54284
+ return "Tokens";
54285
+ }
54286
+ getEditorDisplay(_item) {
54287
+ return { displayText: this.getDisplayName() };
54288
+ }
54289
+ render(item, context, _settings) {
54290
+ if (context.isPreview) {
54291
+ return formatRawOrLabeledValue(item, "Reasoning: ", "1.2k");
54292
+ }
54293
+ const metrics = getContextWindowMetrics(context.data);
54294
+ if (metrics.reasoningTokens !== null) {
54295
+ return formatRawOrLabeledValue(item, "Reasoning: ", formatTokens(metrics.reasoningTokens));
54296
+ }
54297
+ return null;
54298
+ }
54299
+ supportsRawValue() {
54300
+ return true;
54301
+ }
54302
+ supportsColors(_item) {
54303
+ return true;
54304
+ }
54305
+ }
54258
54306
  // src/widgets/TokensTotal.ts
54259
54307
  class TokensTotalWidget {
54260
54308
  getDefaultColor() {
@@ -54295,7 +54343,7 @@ class ContextLengthWidget {
54295
54343
  return "brightBlack";
54296
54344
  }
54297
54345
  getDescription() {
54298
- return "Shows context window size";
54346
+ return "Shows current context length in tokens (live)";
54299
54347
  }
54300
54348
  getDisplayName() {
54301
54349
  return "Context Length";
@@ -54308,11 +54356,11 @@ class ContextLengthWidget {
54308
54356
  }
54309
54357
  render(item, context, settings) {
54310
54358
  if (context.isPreview) {
54311
- return formatRawOrLabeledValue(item, "Ctx: ", "200k");
54359
+ return formatRawOrLabeledValue(item, "Ctx: ", "33k");
54312
54360
  }
54313
54361
  const metrics = getContextWindowMetrics(context.data);
54314
- if (metrics.windowSize !== null) {
54315
- return formatRawOrLabeledValue(item, "Ctx: ", formatTokens(metrics.windowSize));
54362
+ if (metrics.currentContextTokens !== null) {
54363
+ return formatRawOrLabeledValue(item, "Ctx: ", formatTokens(metrics.currentContextTokens));
54316
54364
  }
54317
54365
  return null;
54318
54366
  }
@@ -54323,6 +54371,41 @@ class ContextLengthWidget {
54323
54371
  return true;
54324
54372
  }
54325
54373
  }
54374
+ // src/widgets/ContextWindow.ts
54375
+ class ContextWindowWidget {
54376
+ getDefaultColor() {
54377
+ return "brightBlack";
54378
+ }
54379
+ getDescription() {
54380
+ return "Shows the model's context window size (max tokens)";
54381
+ }
54382
+ getDisplayName() {
54383
+ return "Context Window";
54384
+ }
54385
+ getCategory() {
54386
+ return "Context";
54387
+ }
54388
+ getEditorDisplay(_item) {
54389
+ return { displayText: this.getDisplayName() };
54390
+ }
54391
+ render(item, context, _settings) {
54392
+ if (context.isPreview) {
54393
+ return formatRawOrLabeledValue(item, "Window: ", "1000k");
54394
+ }
54395
+ const metrics = getContextWindowMetrics(context.data);
54396
+ const size2 = metrics.displayedContextLimit ?? metrics.windowSize;
54397
+ if (size2 !== null) {
54398
+ return formatRawOrLabeledValue(item, "Window: ", formatTokens(size2));
54399
+ }
54400
+ return null;
54401
+ }
54402
+ supportsRawValue() {
54403
+ return true;
54404
+ }
54405
+ supportsColors(_item) {
54406
+ return true;
54407
+ }
54408
+ }
54326
54409
  // src/widgets/shared/editor-display.ts
54327
54410
  function makeModifierText(modifiers) {
54328
54411
  return modifiers.length > 0 ? `(${modifiers.join(", ")})` : undefined;
@@ -54388,8 +54471,9 @@ class ContextPercentageWidget {
54388
54471
  return formatRawOrLabeledValue(item, "Ctx: ", previewValue);
54389
54472
  }
54390
54473
  const metrics = getContextWindowMetrics(context.data);
54391
- if (metrics.usedPercentage !== null) {
54392
- const displayPercentage = isInverse ? 100 - metrics.usedPercentage : metrics.usedPercentage;
54474
+ if (metrics.currentContextUsedPercentage !== null) {
54475
+ const pct = metrics.currentContextUsedPercentage;
54476
+ const displayPercentage = isInverse ? 100 - pct : pct;
54393
54477
  return formatRawOrLabeledValue(item, "Ctx: ", `${displayPercentage.toFixed(1)}%`);
54394
54478
  }
54395
54479
  return null;
@@ -54406,36 +54490,13 @@ class ContextPercentageWidget {
54406
54490
  return true;
54407
54491
  }
54408
54492
  }
54409
- // src/utils/model-context.ts
54410
- var DEFAULT_CONTEXT_WINDOW_SIZE = 200000;
54411
- var USABLE_CONTEXT_RATIO = 0.8;
54412
- function toValidWindowSize(value) {
54413
- if (typeof value !== "number" || !Number.isFinite(value) || value <= 0) {
54414
- return null;
54415
- }
54416
- return value;
54417
- }
54418
- function getContextConfig(contextWindowSize) {
54419
- const statusWindowSize = toValidWindowSize(contextWindowSize);
54420
- if (statusWindowSize !== null) {
54421
- return {
54422
- maxTokens: statusWindowSize,
54423
- usableTokens: Math.floor(statusWindowSize * USABLE_CONTEXT_RATIO)
54424
- };
54425
- }
54426
- return {
54427
- maxTokens: DEFAULT_CONTEXT_WINDOW_SIZE,
54428
- usableTokens: Math.floor(DEFAULT_CONTEXT_WINDOW_SIZE * USABLE_CONTEXT_RATIO)
54429
- };
54430
- }
54431
-
54432
54493
  // src/widgets/ContextPercentageUsable.ts
54433
54494
  class ContextPercentageUsableWidget {
54434
54495
  getDefaultColor() {
54435
54496
  return "blue";
54436
54497
  }
54437
54498
  getDescription() {
54438
- return "Shows percentage of usable context window used or remaining (80% of total)";
54499
+ return "Shows percentage of usable context (current_context_tokens / displayed_context_limit)";
54439
54500
  }
54440
54501
  getDisplayName() {
54441
54502
  return "Context % (Usable)";
@@ -54459,9 +54520,8 @@ class ContextPercentageUsableWidget {
54459
54520
  return formatRawOrLabeledValue(item, "Usable: ", previewValue);
54460
54521
  }
54461
54522
  const metrics = getContextWindowMetrics(context.data);
54462
- if (metrics.usedTokens !== null && metrics.windowSize !== null) {
54463
- const contextConfig = getContextConfig(metrics.windowSize);
54464
- const usablePercent = Math.min(100, metrics.usedTokens / contextConfig.usableTokens * 100);
54523
+ if (metrics.currentContextTokens !== null && metrics.displayedContextLimit !== null && metrics.displayedContextLimit > 0) {
54524
+ const usablePercent = Math.min(100, metrics.currentContextTokens / metrics.displayedContextLimit * 100);
54465
54525
  const displayPercentage = isInverse ? 100 - usablePercent : usablePercent;
54466
54526
  return formatRawOrLabeledValue(item, "Usable: ", `${displayPercentage.toFixed(1)}%`);
54467
54527
  }
@@ -54544,8 +54604,8 @@ class ContextBarWidget {
54544
54604
  return item.rawValue ? previewDisplay : `Context: ${previewDisplay}`;
54545
54605
  }
54546
54606
  const contextWindowMetrics = getContextWindowMetrics(context.data);
54547
- const total = contextWindowMetrics.windowSize;
54548
- const used = contextWindowMetrics.contextLengthTokens;
54607
+ const total = contextWindowMetrics.displayedContextLimit ?? contextWindowMetrics.windowSize;
54608
+ const used = contextWindowMetrics.currentContextTokens;
54549
54609
  if (used === null || total === null || total <= 0) {
54550
54610
  return null;
54551
54611
  }
@@ -54810,7 +54870,7 @@ class RemainingTokensWidget {
54810
54870
  return "brightBlack";
54811
54871
  }
54812
54872
  getDescription() {
54813
- return "Shows absolute remaining context tokens";
54873
+ return "Shows remaining tokens in current context (displayed_context_limit − current_context_tokens)";
54814
54874
  }
54815
54875
  getDisplayName() {
54816
54876
  return "Remaining Tokens";
@@ -54826,8 +54886,10 @@ class RemainingTokensWidget {
54826
54886
  return formatRawOrLabeledValue(item, "Remaining: ", "164.8k");
54827
54887
  }
54828
54888
  const metrics = getContextWindowMetrics(context.data);
54829
- if (metrics.remainingTokens !== null) {
54830
- return formatRawOrLabeledValue(item, "Remaining: ", formatTokens(metrics.remainingTokens));
54889
+ const limit = metrics.displayedContextLimit ?? metrics.windowSize;
54890
+ if (limit !== null && metrics.currentContextTokens !== null) {
54891
+ const remaining = Math.max(0, limit - metrics.currentContextTokens);
54892
+ return formatRawOrLabeledValue(item, "Remaining: ", formatTokens(remaining));
54831
54893
  }
54832
54894
  return null;
54833
54895
  }
@@ -58151,8 +58213,10 @@ var WIDGET_MANIFEST = [
58151
58213
  { type: "tokens-input", create: () => new TokensInputWidget },
58152
58214
  { type: "tokens-output", create: () => new TokensOutputWidget },
58153
58215
  { type: "tokens-cached", create: () => new TokensCachedWidget },
58216
+ { type: "tokens-reasoning", create: () => new TokensReasoningWidget },
58154
58217
  { type: "tokens-total", create: () => new TokensTotalWidget },
58155
58218
  { type: "context-length", create: () => new ContextLengthWidget },
58219
+ { type: "context-window", create: () => new ContextWindowWidget },
58156
58220
  { type: "context-percentage", create: () => new ContextPercentageWidget },
58157
58221
  { type: "context-percentage-usable", create: () => new ContextPercentageUsableWidget },
58158
58222
  { type: "context-bar", create: () => new ContextBarWidget },
@@ -63422,6 +63486,7 @@ var CopilotPayloadSchema = exports_external.object({
63422
63486
  reasoning_effort: exports_external.string().nullable().optional()
63423
63487
  }).optional(),
63424
63488
  workspace: exports_external.object({ current_dir: exports_external.string().optional() }).optional(),
63489
+ remote: exports_external.object({ connected: exports_external.boolean().optional() }).optional(),
63425
63490
  version: exports_external.string().optional(),
63426
63491
  cost: exports_external.object({
63427
63492
  total_api_duration_ms: exports_external.number().optional(),
@@ -63436,12 +63501,16 @@ var CopilotPayloadSchema = exports_external.object({
63436
63501
  total_output_tokens: exports_external.number().optional(),
63437
63502
  total_cache_read_tokens: exports_external.number().optional(),
63438
63503
  total_cache_write_tokens: exports_external.number().optional(),
63504
+ total_reasoning_tokens: exports_external.number().optional(),
63439
63505
  total_tokens: exports_external.number().optional(),
63440
63506
  used_percentage: OptionalNumber,
63441
63507
  remaining_percentage: OptionalNumber,
63442
63508
  remaining_tokens: OptionalNumber,
63443
63509
  last_call_input_tokens: exports_external.number().optional(),
63444
63510
  last_call_output_tokens: exports_external.number().optional(),
63511
+ current_context_tokens: OptionalNumber,
63512
+ current_context_used_percentage: OptionalNumber,
63513
+ displayed_context_limit: OptionalNumber,
63445
63514
  current_usage: exports_external.object({
63446
63515
  input_tokens: exports_external.number().optional(),
63447
63516
  output_tokens: exports_external.number().optional(),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "copilot-statusline",
3
- "version": "0.1.12",
3
+ "version": "0.1.13",
4
4
  "description": "A customizable status line formatter for GitHub Copilot CLI — based on ccstatusline",
5
5
  "module": "src/copilot-statusline.ts",
6
6
  "type": "module",