copilot-statusline 0.1.13 → 0.1.15
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 +17 -8
- package/dist/copilot-statusline.js +340 -99
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -265,6 +265,7 @@ Copilot CLI spawns your status line command on every state change, passing sessi
|
|
|
265
265
|
| Tokens Input | `tokens-input` | Total input tokens |
|
|
266
266
|
| Tokens Output | `tokens-output` | Total output tokens |
|
|
267
267
|
| Tokens Cached | `tokens-cached` | Total cached tokens (read + write) |
|
|
268
|
+
| Tokens Reasoning | `tokens-reasoning` | Total reasoning (thinking) tokens consumed |
|
|
268
269
|
| Tokens Total | `tokens-total` | Total tokens |
|
|
269
270
|
| Last Call Input | `last-call-input` | Input tokens from most recent API call |
|
|
270
271
|
| Last Call Output | `last-call-output` | Output tokens from most recent API call |
|
|
@@ -274,11 +275,11 @@ Copilot CLI spawns your status line command on every state change, passing sessi
|
|
|
274
275
|
### Context
|
|
275
276
|
| Widget | Type | Description |
|
|
276
277
|
|--------|------|-------------|
|
|
277
|
-
| Context Length | `context-length` |
|
|
278
|
-
| Context
|
|
279
|
-
| Context %
|
|
280
|
-
| Context Bar | `context-bar` | Visual progress bar for context usage |
|
|
281
|
-
| Remaining Tokens | `remaining-tokens` |
|
|
278
|
+
| Context Length | `context-length` | Current context length in tokens (live, from `current_context_tokens`) |
|
|
279
|
+
| Context Window | `context-window` | Model's context window size (max tokens, from `displayed_context_limit ?? context_window_size`) |
|
|
280
|
+
| Context % | `context-percentage` | Live context % from Copilot (`current_context_used_percentage`) |
|
|
281
|
+
| Context Bar | `context-bar` | Visual progress bar for live context usage |
|
|
282
|
+
| Remaining Tokens | `remaining-tokens` | Live remaining tokens (`displayed_context_limit − current_context_tokens`) |
|
|
282
283
|
|
|
283
284
|
### Git
|
|
284
285
|
| Widget | Type | Description |
|
|
@@ -289,8 +290,12 @@ Copilot CLI spawns your status line command on every state change, passing sessi
|
|
|
289
290
|
| Git Deletions | `git-deletions` | Uncommitted deletions only |
|
|
290
291
|
| Git Status | `git-status` | Staged/unstaged/untracked/conflicts indicators |
|
|
291
292
|
| Git Staged | `git-staged` | Staged changes indicator |
|
|
293
|
+
| Git Staged Files | `git-staged-files` | Count of staged files (`S:3`, raw: `3`) |
|
|
292
294
|
| Git Unstaged | `git-unstaged` | Unstaged changes indicator |
|
|
295
|
+
| Git Unstaged Files | `git-unstaged-files` | Count of unstaged tracked files (`M:2`, raw: `2`) |
|
|
293
296
|
| Git Untracked | `git-untracked` | Untracked files indicator |
|
|
297
|
+
| Git Untracked Files | `git-untracked-files` | Count of untracked files (`?:1`, raw: `1`) |
|
|
298
|
+
| Git Clean Status | `git-clean-status` | Working tree clean/dirty status (`✓`/`✗`, raw: `clean`/`dirty`) |
|
|
294
299
|
| Git Conflicts | `git-conflicts` | Merge conflict count |
|
|
295
300
|
| Git Ahead/Behind | `git-ahead-behind` | Commits ahead/behind upstream |
|
|
296
301
|
| Git SHA | `git-sha` | Short commit hash |
|
|
@@ -303,6 +308,8 @@ Copilot CLI spawns your status line command on every state change, passing sessi
|
|
|
303
308
|
| Git Upstream Repo | `git-upstream-repo` | Upstream remote repo name |
|
|
304
309
|
| Git Upstream Owner/Repo | `git-upstream-owner-repo` | Upstream `owner/repo` |
|
|
305
310
|
| Git Is Fork | `git-is-fork` | Fork detection indicator |
|
|
311
|
+
| Git Worktree | `git-worktree` | Current git worktree name (probes `git rev-parse --git-dir`) |
|
|
312
|
+
| Git Worktree Mode | `git-worktree-mode` | `⎇` indicator when current dir is a linked worktree |
|
|
306
313
|
|
|
307
314
|
### System
|
|
308
315
|
| Widget | Type | Description |
|
|
@@ -339,7 +346,8 @@ These widgets are exclusive to copilot-statusline and not available in ccstatusl
|
|
|
339
346
|
| Premium Rate | `premium-rate` | Burn rate in requests/minute |
|
|
340
347
|
| Last Call Input | `last-call-input` | Input tokens from the most recent API call |
|
|
341
348
|
| Last Call Output | `last-call-output` | Output tokens from the most recent API call |
|
|
342
|
-
| Remaining Tokens | `remaining-tokens` |
|
|
349
|
+
| Remaining Tokens | `remaining-tokens` | Live remaining tokens (`displayed_context_limit − current_context_tokens`) |
|
|
350
|
+
| Tokens Reasoning | `tokens-reasoning` | Total reasoning (thinking) tokens consumed |
|
|
343
351
|
| Cache Read Tokens | `cache-read-tokens` | Total cache read tokens |
|
|
344
352
|
| Cache Write Tokens | `cache-write-tokens` | Total cache write tokens |
|
|
345
353
|
|
|
@@ -368,7 +376,8 @@ Widget-specific shortcuts:
|
|
|
368
376
|
| Git widgets | `h` | Toggle hide `no git` output |
|
|
369
377
|
| Git Branch | `l` | Toggle GitHub link |
|
|
370
378
|
| Context % widgets | `u` | Toggle used/remaining display |
|
|
371
|
-
| Context
|
|
379
|
+
| Context % widgets | `p` | Cycle numeric/short bar display |
|
|
380
|
+
| Context Bar | `p` | Cycle bar style (medium/full/short/short-only) |
|
|
372
381
|
| Current Working Dir | `h` | Toggle `~` home abbreviation |
|
|
373
382
|
| Current Working Dir | `s` | Edit segment limit |
|
|
374
383
|
| Current Working Dir | `f` | Toggle fish-style path |
|
|
@@ -620,4 +629,4 @@ This project includes substantial portions of code from [ccstatusline](https://g
|
|
|
620
629
|
[](https://www.npmjs.com/package/copilot-statusline)
|
|
621
630
|
[](LICENSE)
|
|
622
631
|
|
|
623
|
-
</div>
|
|
632
|
+
</div>
|
|
@@ -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.
|
|
52916
|
+
var PACKAGE_VERSION = "0.1.15";
|
|
52917
52917
|
function getPackageVersion() {
|
|
52918
52918
|
if (/^\d+\.\d+\.\d+/.test(PACKAGE_VERSION)) {
|
|
52919
52919
|
return PACKAGE_VERSION;
|
|
@@ -54075,18 +54075,13 @@ function getContextWindowMetrics(data) {
|
|
|
54075
54075
|
const empty = {
|
|
54076
54076
|
windowSize: null,
|
|
54077
54077
|
displayedContextLimit: null,
|
|
54078
|
-
usedTokens: null,
|
|
54079
|
-
contextLengthTokens: null,
|
|
54080
54078
|
currentContextTokens: null,
|
|
54081
54079
|
currentContextUsedPercentage: null,
|
|
54082
|
-
usedPercentage: null,
|
|
54083
|
-
remainingPercentage: null,
|
|
54084
54080
|
totalInputTokens: null,
|
|
54085
54081
|
totalOutputTokens: null,
|
|
54086
54082
|
cachedTokens: null,
|
|
54087
54083
|
totalTokens: null,
|
|
54088
54084
|
reasoningTokens: null,
|
|
54089
|
-
remainingTokens: null,
|
|
54090
54085
|
lastCallInputTokens: null,
|
|
54091
54086
|
lastCallOutputTokens: null,
|
|
54092
54087
|
cacheReadTokens: null,
|
|
@@ -54107,45 +54102,20 @@ function getContextWindowMetrics(data) {
|
|
|
54107
54102
|
const totalOutputTokens = toFiniteNonNegativeNumber(contextWindow.total_output_tokens);
|
|
54108
54103
|
const cacheReadTokens = toFiniteNonNegativeNumber(contextWindow.total_cache_read_tokens);
|
|
54109
54104
|
const cacheWriteTokens = toFiniteNonNegativeNumber(contextWindow.total_cache_write_tokens);
|
|
54110
|
-
const remainingTokens = toFiniteNonNegativeNumber(contextWindow.remaining_tokens);
|
|
54111
54105
|
const lastCallInputTokens = toFiniteNonNegativeNumber(contextWindow.last_call_input_tokens);
|
|
54112
54106
|
const lastCallOutputTokens = toFiniteNonNegativeNumber(contextWindow.last_call_output_tokens);
|
|
54113
54107
|
const cachedTokens = cacheReadTokens !== null || cacheWriteTokens !== null ? (cacheReadTokens ?? 0) + (cacheWriteTokens ?? 0) : null;
|
|
54114
|
-
|
|
54115
|
-
let contextLengthTokens = null;
|
|
54116
|
-
if (contextWindow.current_usage && typeof contextWindow.current_usage === "object") {
|
|
54117
|
-
const usage = contextWindow.current_usage;
|
|
54118
|
-
const inputTokens = toFiniteNonNegativeNumber(usage.input_tokens) ?? 0;
|
|
54119
|
-
const outputTokens = toFiniteNonNegativeNumber(usage.output_tokens) ?? 0;
|
|
54120
|
-
const cacheCreationTokens = toFiniteNonNegativeNumber(usage.cache_creation_input_tokens) ?? 0;
|
|
54121
|
-
const cacheReadInputTokens = toFiniteNonNegativeNumber(usage.cache_read_input_tokens) ?? 0;
|
|
54122
|
-
currentUsageTotalTokens = inputTokens + outputTokens + cacheCreationTokens + cacheReadInputTokens;
|
|
54123
|
-
contextLengthTokens = inputTokens + cacheCreationTokens + cacheReadInputTokens;
|
|
54124
|
-
}
|
|
54125
|
-
const rawUsedPercentage = toFiniteNonNegativeNumber(contextWindow.used_percentage);
|
|
54126
|
-
const rawRemainingPercentage = toFiniteNonNegativeNumber(contextWindow.remaining_percentage);
|
|
54127
|
-
const usedTokensFromRemaining = windowSize !== null && remainingTokens !== null ? windowSize - remainingTokens : null;
|
|
54128
|
-
const usedTokensFromPercentage = rawUsedPercentage !== null && windowSize !== null ? rawUsedPercentage / 100 * windowSize : null;
|
|
54129
|
-
const usedTokens = usedTokensFromRemaining ?? usedTokensFromPercentage ?? currentUsageTotalTokens;
|
|
54130
|
-
const usedPercentage = rawUsedPercentage !== null ? clampPercentage(rawUsedPercentage) : usedTokens !== null && windowSize !== null && windowSize > 0 ? clampPercentage(usedTokens / windowSize * 100) : null;
|
|
54131
|
-
const remainingPercentage = rawRemainingPercentage !== null ? clampPercentage(rawRemainingPercentage) : usedPercentage !== null ? 100 - usedPercentage : null;
|
|
54132
|
-
const totalTokens = currentUsageTotalTokens ?? toFiniteNonNegativeNumber(contextWindow.total_tokens) ?? (totalInputTokens !== null && totalOutputTokens !== null ? totalInputTokens + totalOutputTokens : null);
|
|
54133
|
-
const contextLengthFromAuthoritative = usedTokensFromRemaining ?? usedTokensFromPercentage;
|
|
54108
|
+
const totalTokens = toFiniteNonNegativeNumber(contextWindow.total_tokens) ?? (totalInputTokens !== null && totalOutputTokens !== null ? totalInputTokens + totalOutputTokens : null);
|
|
54134
54109
|
return {
|
|
54135
54110
|
windowSize,
|
|
54136
54111
|
displayedContextLimit,
|
|
54137
|
-
usedTokens,
|
|
54138
|
-
contextLengthTokens: contextLengthFromAuthoritative ?? contextLengthTokens ?? usedTokens,
|
|
54139
54112
|
currentContextTokens,
|
|
54140
54113
|
currentContextUsedPercentage,
|
|
54141
|
-
usedPercentage,
|
|
54142
|
-
remainingPercentage,
|
|
54143
54114
|
totalInputTokens,
|
|
54144
54115
|
totalOutputTokens,
|
|
54145
54116
|
cachedTokens,
|
|
54146
54117
|
totalTokens,
|
|
54147
54118
|
reasoningTokens,
|
|
54148
|
-
remainingTokens,
|
|
54149
54119
|
lastCallInputTokens,
|
|
54150
54120
|
lastCallOutputTokens,
|
|
54151
54121
|
cacheReadTokens,
|
|
@@ -54441,95 +54411,117 @@ function handleContextInverseAction(action, item) {
|
|
|
54441
54411
|
return toggleMetadataFlag(item, INVERSE_KEY);
|
|
54442
54412
|
}
|
|
54443
54413
|
|
|
54444
|
-
// src/widgets/
|
|
54445
|
-
|
|
54446
|
-
|
|
54447
|
-
|
|
54448
|
-
|
|
54449
|
-
|
|
54450
|
-
|
|
54451
|
-
|
|
54452
|
-
|
|
54453
|
-
|
|
54454
|
-
|
|
54455
|
-
|
|
54456
|
-
return "Context";
|
|
54414
|
+
// src/widgets/shared/context-slider.ts
|
|
54415
|
+
var SLIDER_WIDTH = 10;
|
|
54416
|
+
var SLIDER_TOGGLE_KEYBIND = { key: "p", label: "(p)rogress toggle", action: "toggle-slider" };
|
|
54417
|
+
function makeSliderBar(percent, width = SLIDER_WIDTH) {
|
|
54418
|
+
const clamped = Math.max(0, Math.min(100, percent));
|
|
54419
|
+
const filled = Math.round(clamped / 100 * width);
|
|
54420
|
+
return "▓".repeat(filled) + "░".repeat(width - filled);
|
|
54421
|
+
}
|
|
54422
|
+
function getContextSliderMode(item) {
|
|
54423
|
+
const mode = item.metadata?.display;
|
|
54424
|
+
if (mode === "slider" || mode === "slider-only") {
|
|
54425
|
+
return mode;
|
|
54457
54426
|
}
|
|
54458
|
-
|
|
54427
|
+
return "none";
|
|
54428
|
+
}
|
|
54429
|
+
function cycleContextSliderMode(item) {
|
|
54430
|
+
const currentMode = getContextSliderMode(item);
|
|
54431
|
+
const nextMode = currentMode === "none" ? "slider" : currentMode === "slider" ? "slider-only" : "none";
|
|
54432
|
+
if (nextMode === "none") {
|
|
54433
|
+
const nextMetadata = { ...item.metadata ?? {} };
|
|
54434
|
+
delete nextMetadata.display;
|
|
54459
54435
|
return {
|
|
54460
|
-
|
|
54461
|
-
|
|
54436
|
+
...item,
|
|
54437
|
+
metadata: Object.keys(nextMetadata).length > 0 ? nextMetadata : undefined
|
|
54462
54438
|
};
|
|
54463
54439
|
}
|
|
54464
|
-
|
|
54465
|
-
|
|
54466
|
-
|
|
54467
|
-
|
|
54468
|
-
|
|
54469
|
-
if (context.isPreview) {
|
|
54470
|
-
const previewValue = isInverse ? "90.7%" : "9.3%";
|
|
54471
|
-
return formatRawOrLabeledValue(item, "Ctx: ", previewValue);
|
|
54472
|
-
}
|
|
54473
|
-
const metrics = getContextWindowMetrics(context.data);
|
|
54474
|
-
if (metrics.currentContextUsedPercentage !== null) {
|
|
54475
|
-
const pct = metrics.currentContextUsedPercentage;
|
|
54476
|
-
const displayPercentage = isInverse ? 100 - pct : pct;
|
|
54477
|
-
return formatRawOrLabeledValue(item, "Ctx: ", `${displayPercentage.toFixed(1)}%`);
|
|
54440
|
+
return {
|
|
54441
|
+
...item,
|
|
54442
|
+
metadata: {
|
|
54443
|
+
...item.metadata ?? {},
|
|
54444
|
+
display: nextMode
|
|
54478
54445
|
}
|
|
54446
|
+
};
|
|
54447
|
+
}
|
|
54448
|
+
function renderContextSlider(mode, percent) {
|
|
54449
|
+
if (mode === "none") {
|
|
54479
54450
|
return null;
|
|
54480
54451
|
}
|
|
54481
|
-
|
|
54482
|
-
|
|
54483
|
-
|
|
54484
|
-
];
|
|
54452
|
+
const slider = makeSliderBar(percent);
|
|
54453
|
+
if (mode === "slider") {
|
|
54454
|
+
return `${slider} ${percent.toFixed(1)}%`;
|
|
54485
54455
|
}
|
|
54486
|
-
|
|
54487
|
-
|
|
54456
|
+
return slider;
|
|
54457
|
+
}
|
|
54458
|
+
function getContextSliderModifierText(item) {
|
|
54459
|
+
const mode = getContextSliderMode(item);
|
|
54460
|
+
if (mode === "slider") {
|
|
54461
|
+
return "(short bar)";
|
|
54488
54462
|
}
|
|
54489
|
-
|
|
54490
|
-
return
|
|
54463
|
+
if (mode === "slider-only") {
|
|
54464
|
+
return "(short bar only)";
|
|
54491
54465
|
}
|
|
54466
|
+
return;
|
|
54492
54467
|
}
|
|
54493
|
-
|
|
54494
|
-
|
|
54468
|
+
function getContextSliderKeybinds() {
|
|
54469
|
+
return [SLIDER_TOGGLE_KEYBIND];
|
|
54470
|
+
}
|
|
54471
|
+
|
|
54472
|
+
// src/widgets/ContextPercentage.ts
|
|
54473
|
+
class ContextPercentageWidget {
|
|
54495
54474
|
getDefaultColor() {
|
|
54496
54475
|
return "blue";
|
|
54497
54476
|
}
|
|
54498
54477
|
getDescription() {
|
|
54499
|
-
return "Shows percentage of
|
|
54478
|
+
return "Shows percentage of context window used or remaining";
|
|
54500
54479
|
}
|
|
54501
54480
|
getDisplayName() {
|
|
54502
|
-
return "Context %
|
|
54481
|
+
return "Context %";
|
|
54503
54482
|
}
|
|
54504
54483
|
getCategory() {
|
|
54505
54484
|
return "Context";
|
|
54506
54485
|
}
|
|
54507
54486
|
getEditorDisplay(item) {
|
|
54487
|
+
const modifiers = [
|
|
54488
|
+
getContextInverseModifierText(item),
|
|
54489
|
+
getContextSliderModifierText(item)
|
|
54490
|
+
].filter((modifier) => modifier !== undefined);
|
|
54508
54491
|
return {
|
|
54509
54492
|
displayText: this.getDisplayName(),
|
|
54510
|
-
modifierText:
|
|
54493
|
+
modifierText: modifiers.length > 0 ? `(${modifiers.map((modifier) => modifier.replace(/^\(|\)$/g, "")).join(", ")})` : undefined
|
|
54511
54494
|
};
|
|
54512
54495
|
}
|
|
54513
54496
|
handleEditorAction(action, item) {
|
|
54497
|
+
if (action === "toggle-slider") {
|
|
54498
|
+
return cycleContextSliderMode(item);
|
|
54499
|
+
}
|
|
54514
54500
|
return handleContextInverseAction(action, item);
|
|
54515
54501
|
}
|
|
54516
54502
|
render(item, context, settings) {
|
|
54517
54503
|
const isInverse = isContextInverse(item);
|
|
54504
|
+
const label = isInverse ? "Ctx Left: " : "Ctx Used: ";
|
|
54505
|
+
const sliderMode = getContextSliderMode(item);
|
|
54506
|
+
const formatPercentage = (displayPercentage) => {
|
|
54507
|
+
const sliderDisplay = renderContextSlider(sliderMode, displayPercentage);
|
|
54508
|
+
return formatRawOrLabeledValue(item, label, sliderDisplay ?? `${displayPercentage.toFixed(1)}%`);
|
|
54509
|
+
};
|
|
54518
54510
|
if (context.isPreview) {
|
|
54519
|
-
|
|
54520
|
-
return formatRawOrLabeledValue(item, "Usable: ", previewValue);
|
|
54511
|
+
return formatPercentage(isInverse ? 90.7 : 9.3);
|
|
54521
54512
|
}
|
|
54522
54513
|
const metrics = getContextWindowMetrics(context.data);
|
|
54523
|
-
if (metrics.
|
|
54524
|
-
const
|
|
54525
|
-
const displayPercentage = isInverse ? 100 -
|
|
54526
|
-
return
|
|
54514
|
+
if (metrics.currentContextUsedPercentage !== null) {
|
|
54515
|
+
const pct = metrics.currentContextUsedPercentage;
|
|
54516
|
+
const displayPercentage = isInverse ? 100 - pct : pct;
|
|
54517
|
+
return formatPercentage(displayPercentage);
|
|
54527
54518
|
}
|
|
54528
54519
|
return null;
|
|
54529
54520
|
}
|
|
54530
54521
|
getCustomKeybinds() {
|
|
54531
54522
|
return [
|
|
54532
|
-
{ key: "u", label: "(u)sed/remaining", action: "toggle-inverse" }
|
|
54523
|
+
{ key: "u", label: "(u)sed/remaining", action: "toggle-inverse" },
|
|
54524
|
+
...getContextSliderKeybinds()
|
|
54533
54525
|
];
|
|
54534
54526
|
}
|
|
54535
54527
|
supportsRawValue() {
|
|
@@ -54554,7 +54546,14 @@ function makeUsageProgressBar(percent, width = 15, powerlineMode = false) {
|
|
|
54554
54546
|
|
|
54555
54547
|
// src/widgets/ContextBar.ts
|
|
54556
54548
|
function getDisplayMode(item) {
|
|
54557
|
-
|
|
54549
|
+
const mode = item.metadata?.display;
|
|
54550
|
+
if (mode === "progress" || mode === "slider" || mode === "slider-only") {
|
|
54551
|
+
return mode;
|
|
54552
|
+
}
|
|
54553
|
+
return "progress-short";
|
|
54554
|
+
}
|
|
54555
|
+
function isSliderMode(mode) {
|
|
54556
|
+
return mode === "slider" || mode === "slider-only";
|
|
54558
54557
|
}
|
|
54559
54558
|
|
|
54560
54559
|
class ContextBarWidget {
|
|
@@ -54574,7 +54573,11 @@ class ContextBarWidget {
|
|
|
54574
54573
|
const mode = getDisplayMode(item);
|
|
54575
54574
|
const modifiers = [];
|
|
54576
54575
|
if (mode === "progress-short") {
|
|
54576
|
+
modifiers.push("medium bar");
|
|
54577
|
+
} else if (mode === "slider") {
|
|
54577
54578
|
modifiers.push("short bar");
|
|
54579
|
+
} else if (mode === "slider-only") {
|
|
54580
|
+
modifiers.push("short bar only");
|
|
54578
54581
|
}
|
|
54579
54582
|
return {
|
|
54580
54583
|
displayText: this.getDisplayName(),
|
|
@@ -54586,7 +54589,7 @@ class ContextBarWidget {
|
|
|
54586
54589
|
return null;
|
|
54587
54590
|
}
|
|
54588
54591
|
const currentMode = getDisplayMode(item);
|
|
54589
|
-
const nextMode = currentMode === "progress-short" ? "progress" : "progress-short";
|
|
54592
|
+
const nextMode = currentMode === "progress-short" ? "progress" : currentMode === "progress" ? "slider" : currentMode === "slider" ? "slider-only" : "progress-short";
|
|
54590
54593
|
return {
|
|
54591
54594
|
...item,
|
|
54592
54595
|
metadata: {
|
|
@@ -54600,19 +54603,29 @@ class ContextBarWidget {
|
|
|
54600
54603
|
const barWidth = displayMode === "progress" ? 32 : 16;
|
|
54601
54604
|
const powerlineMode = settings.powerline.enabled;
|
|
54602
54605
|
if (context.isPreview) {
|
|
54606
|
+
if (isSliderMode(displayMode)) {
|
|
54607
|
+
const slider = renderContextSlider("slider-only", 25);
|
|
54608
|
+
const sliderDisplay = displayMode === "slider" ? `${slider} 50k/200k (25%)` : slider;
|
|
54609
|
+
return item.rawValue ? sliderDisplay : `Context: ${sliderDisplay}`;
|
|
54610
|
+
}
|
|
54603
54611
|
const previewDisplay = `${makeUsageProgressBar(25, barWidth, powerlineMode)} 50k/200k (25%)`;
|
|
54604
54612
|
return item.rawValue ? previewDisplay : `Context: ${previewDisplay}`;
|
|
54605
54613
|
}
|
|
54606
54614
|
const contextWindowMetrics = getContextWindowMetrics(context.data);
|
|
54607
54615
|
const total = contextWindowMetrics.displayedContextLimit ?? contextWindowMetrics.windowSize;
|
|
54608
54616
|
const used = contextWindowMetrics.currentContextTokens;
|
|
54609
|
-
|
|
54617
|
+
const upstreamPct = contextWindowMetrics.currentContextUsedPercentage;
|
|
54618
|
+
if (used === null || total === null || total <= 0 || upstreamPct === null) {
|
|
54610
54619
|
return null;
|
|
54611
54620
|
}
|
|
54612
|
-
const
|
|
54613
|
-
const clampedPercent = Math.max(0, Math.min(100, percent));
|
|
54621
|
+
const clampedPercent = Math.max(0, Math.min(100, upstreamPct));
|
|
54614
54622
|
const usedK = Math.round(used / 1000);
|
|
54615
54623
|
const totalK = Math.round(total / 1000);
|
|
54624
|
+
if (isSliderMode(displayMode)) {
|
|
54625
|
+
const slider = renderContextSlider("slider-only", clampedPercent);
|
|
54626
|
+
const sliderDisplay = displayMode === "slider" ? `${slider} ${usedK}k/${totalK}k (${Math.round(clampedPercent)}%)` : slider;
|
|
54627
|
+
return item.rawValue ? sliderDisplay : `Context: ${sliderDisplay}`;
|
|
54628
|
+
}
|
|
54616
54629
|
const display = `${makeUsageProgressBar(clampedPercent, barWidth, powerlineMode)} ${usedK}k/${totalK}k (${Math.round(clampedPercent)}%)`;
|
|
54617
54630
|
return item.rawValue ? display : `Context: ${display}`;
|
|
54618
54631
|
}
|
|
@@ -55024,6 +55037,9 @@ function getGitChangeCounts(context) {
|
|
|
55024
55037
|
deletions: unstagedCounts.deletions + stagedCounts.deletions
|
|
55025
55038
|
};
|
|
55026
55039
|
}
|
|
55040
|
+
function hasRenameOrCopyStatus(line) {
|
|
55041
|
+
return line.startsWith("R") || line.startsWith("C") || line[1] === "R" || line[1] === "C";
|
|
55042
|
+
}
|
|
55027
55043
|
function getGitStatus(context) {
|
|
55028
55044
|
const output = runGit("--no-optional-locks status --porcelain -z", context);
|
|
55029
55045
|
if (!output) {
|
|
@@ -55048,13 +55064,39 @@ function getGitStatus(context) {
|
|
|
55048
55064
|
untracked = true;
|
|
55049
55065
|
if (staged && unstaged && untracked && conflicts)
|
|
55050
55066
|
break;
|
|
55051
|
-
|
|
55052
|
-
if (indexStatus === "R" || indexStatus === "C") {
|
|
55067
|
+
if (hasRenameOrCopyStatus(line)) {
|
|
55053
55068
|
index += 1;
|
|
55054
55069
|
}
|
|
55055
55070
|
}
|
|
55056
55071
|
return { staged, unstaged, untracked, conflicts };
|
|
55057
55072
|
}
|
|
55073
|
+
function getGitFileStatusCounts(context) {
|
|
55074
|
+
const output = runGit("--no-optional-locks status --porcelain -z", context);
|
|
55075
|
+
if (!output) {
|
|
55076
|
+
return { staged: 0, unstaged: 0, untracked: 0 };
|
|
55077
|
+
}
|
|
55078
|
+
let staged = 0;
|
|
55079
|
+
let unstaged = 0;
|
|
55080
|
+
let untracked = 0;
|
|
55081
|
+
const entries = output.split("\x00");
|
|
55082
|
+
for (let index = 0;index < entries.length; index += 1) {
|
|
55083
|
+
const line = entries[index];
|
|
55084
|
+
if (typeof line !== "string" || line.length < 2)
|
|
55085
|
+
continue;
|
|
55086
|
+
if (line.startsWith("??")) {
|
|
55087
|
+
untracked += 1;
|
|
55088
|
+
} else {
|
|
55089
|
+
if (/^[MADRCTU]/.test(line))
|
|
55090
|
+
staged += 1;
|
|
55091
|
+
if (/^.[MADRCTU]/.test(line))
|
|
55092
|
+
unstaged += 1;
|
|
55093
|
+
}
|
|
55094
|
+
if (hasRenameOrCopyStatus(line)) {
|
|
55095
|
+
index += 1;
|
|
55096
|
+
}
|
|
55097
|
+
}
|
|
55098
|
+
return { staged, unstaged, untracked };
|
|
55099
|
+
}
|
|
55058
55100
|
function getGitAheadBehind(context) {
|
|
55059
55101
|
const output = runGit("rev-list --left-right --count HEAD...@{upstream}", context);
|
|
55060
55102
|
if (!output)
|
|
@@ -55973,6 +56015,55 @@ class GitStagedWidget {
|
|
|
55973
56015
|
return true;
|
|
55974
56016
|
}
|
|
55975
56017
|
}
|
|
56018
|
+
// src/widgets/GitStagedFiles.ts
|
|
56019
|
+
class GitStagedFilesWidget {
|
|
56020
|
+
getDefaultColor() {
|
|
56021
|
+
return "green";
|
|
56022
|
+
}
|
|
56023
|
+
getDescription() {
|
|
56024
|
+
return "Shows count of staged files";
|
|
56025
|
+
}
|
|
56026
|
+
getDisplayName() {
|
|
56027
|
+
return "Git Staged Files";
|
|
56028
|
+
}
|
|
56029
|
+
getCategory() {
|
|
56030
|
+
return "Git";
|
|
56031
|
+
}
|
|
56032
|
+
getEditorDisplay(item) {
|
|
56033
|
+
return {
|
|
56034
|
+
displayText: this.getDisplayName(),
|
|
56035
|
+
modifierText: getHideNoGitModifierText(item)
|
|
56036
|
+
};
|
|
56037
|
+
}
|
|
56038
|
+
handleEditorAction(action, item) {
|
|
56039
|
+
return handleToggleNoGitAction(action, item);
|
|
56040
|
+
}
|
|
56041
|
+
render(item, context, _settings) {
|
|
56042
|
+
const hideNoGit = isHideNoGitEnabled(item);
|
|
56043
|
+
if (context.isPreview) {
|
|
56044
|
+
return item.rawValue ? "3" : "S:3";
|
|
56045
|
+
}
|
|
56046
|
+
if (!isInsideGitWorkTree(context)) {
|
|
56047
|
+
return hideNoGit ? null : "(no git)";
|
|
56048
|
+
}
|
|
56049
|
+
const count = getGitFileStatusCounts(context).staged;
|
|
56050
|
+
return item.rawValue ? count.toString() : `S:${count}`;
|
|
56051
|
+
}
|
|
56052
|
+
getCustomKeybinds() {
|
|
56053
|
+
return getHideNoGitKeybinds();
|
|
56054
|
+
}
|
|
56055
|
+
getNumericValue(context, _item) {
|
|
56056
|
+
if (!isInsideGitWorkTree(context))
|
|
56057
|
+
return null;
|
|
56058
|
+
return getGitFileStatusCounts(context).staged;
|
|
56059
|
+
}
|
|
56060
|
+
supportsRawValue() {
|
|
56061
|
+
return true;
|
|
56062
|
+
}
|
|
56063
|
+
supportsColors(_item) {
|
|
56064
|
+
return true;
|
|
56065
|
+
}
|
|
56066
|
+
}
|
|
55976
56067
|
// src/widgets/GitUnstaged.ts
|
|
55977
56068
|
var DEFAULT_SYMBOL2 = "*";
|
|
55978
56069
|
|
|
@@ -56032,6 +56123,55 @@ class GitUnstagedWidget {
|
|
|
56032
56123
|
return true;
|
|
56033
56124
|
}
|
|
56034
56125
|
}
|
|
56126
|
+
// src/widgets/GitUnstagedFiles.ts
|
|
56127
|
+
class GitUnstagedFilesWidget {
|
|
56128
|
+
getDefaultColor() {
|
|
56129
|
+
return "yellow";
|
|
56130
|
+
}
|
|
56131
|
+
getDescription() {
|
|
56132
|
+
return "Shows count of unstaged tracked files";
|
|
56133
|
+
}
|
|
56134
|
+
getDisplayName() {
|
|
56135
|
+
return "Git Unstaged Files";
|
|
56136
|
+
}
|
|
56137
|
+
getCategory() {
|
|
56138
|
+
return "Git";
|
|
56139
|
+
}
|
|
56140
|
+
getEditorDisplay(item) {
|
|
56141
|
+
return {
|
|
56142
|
+
displayText: this.getDisplayName(),
|
|
56143
|
+
modifierText: getHideNoGitModifierText(item)
|
|
56144
|
+
};
|
|
56145
|
+
}
|
|
56146
|
+
handleEditorAction(action, item) {
|
|
56147
|
+
return handleToggleNoGitAction(action, item);
|
|
56148
|
+
}
|
|
56149
|
+
render(item, context, _settings) {
|
|
56150
|
+
const hideNoGit = isHideNoGitEnabled(item);
|
|
56151
|
+
if (context.isPreview) {
|
|
56152
|
+
return item.rawValue ? "2" : "M:2";
|
|
56153
|
+
}
|
|
56154
|
+
if (!isInsideGitWorkTree(context)) {
|
|
56155
|
+
return hideNoGit ? null : "(no git)";
|
|
56156
|
+
}
|
|
56157
|
+
const count = getGitFileStatusCounts(context).unstaged;
|
|
56158
|
+
return item.rawValue ? count.toString() : `M:${count}`;
|
|
56159
|
+
}
|
|
56160
|
+
getCustomKeybinds() {
|
|
56161
|
+
return getHideNoGitKeybinds();
|
|
56162
|
+
}
|
|
56163
|
+
getNumericValue(context, _item) {
|
|
56164
|
+
if (!isInsideGitWorkTree(context))
|
|
56165
|
+
return null;
|
|
56166
|
+
return getGitFileStatusCounts(context).unstaged;
|
|
56167
|
+
}
|
|
56168
|
+
supportsRawValue() {
|
|
56169
|
+
return true;
|
|
56170
|
+
}
|
|
56171
|
+
supportsColors(_item) {
|
|
56172
|
+
return true;
|
|
56173
|
+
}
|
|
56174
|
+
}
|
|
56035
56175
|
// src/widgets/GitUntracked.ts
|
|
56036
56176
|
var DEFAULT_SYMBOL3 = "?";
|
|
56037
56177
|
|
|
@@ -56091,6 +56231,103 @@ class GitUntrackedWidget {
|
|
|
56091
56231
|
return true;
|
|
56092
56232
|
}
|
|
56093
56233
|
}
|
|
56234
|
+
// src/widgets/GitUntrackedFiles.ts
|
|
56235
|
+
class GitUntrackedFilesWidget {
|
|
56236
|
+
getDefaultColor() {
|
|
56237
|
+
return "red";
|
|
56238
|
+
}
|
|
56239
|
+
getDescription() {
|
|
56240
|
+
return "Shows count of untracked files";
|
|
56241
|
+
}
|
|
56242
|
+
getDisplayName() {
|
|
56243
|
+
return "Git Untracked Files";
|
|
56244
|
+
}
|
|
56245
|
+
getCategory() {
|
|
56246
|
+
return "Git";
|
|
56247
|
+
}
|
|
56248
|
+
getEditorDisplay(item) {
|
|
56249
|
+
return {
|
|
56250
|
+
displayText: this.getDisplayName(),
|
|
56251
|
+
modifierText: getHideNoGitModifierText(item)
|
|
56252
|
+
};
|
|
56253
|
+
}
|
|
56254
|
+
handleEditorAction(action, item) {
|
|
56255
|
+
return handleToggleNoGitAction(action, item);
|
|
56256
|
+
}
|
|
56257
|
+
render(item, context, _settings) {
|
|
56258
|
+
const hideNoGit = isHideNoGitEnabled(item);
|
|
56259
|
+
if (context.isPreview) {
|
|
56260
|
+
return item.rawValue ? "1" : "?:1";
|
|
56261
|
+
}
|
|
56262
|
+
if (!isInsideGitWorkTree(context)) {
|
|
56263
|
+
return hideNoGit ? null : "(no git)";
|
|
56264
|
+
}
|
|
56265
|
+
const count = getGitFileStatusCounts(context).untracked;
|
|
56266
|
+
return item.rawValue ? count.toString() : `?:${count}`;
|
|
56267
|
+
}
|
|
56268
|
+
getCustomKeybinds() {
|
|
56269
|
+
return getHideNoGitKeybinds();
|
|
56270
|
+
}
|
|
56271
|
+
getNumericValue(context, _item) {
|
|
56272
|
+
if (!isInsideGitWorkTree(context))
|
|
56273
|
+
return null;
|
|
56274
|
+
return getGitFileStatusCounts(context).untracked;
|
|
56275
|
+
}
|
|
56276
|
+
supportsRawValue() {
|
|
56277
|
+
return true;
|
|
56278
|
+
}
|
|
56279
|
+
supportsColors(_item) {
|
|
56280
|
+
return true;
|
|
56281
|
+
}
|
|
56282
|
+
}
|
|
56283
|
+
// src/widgets/GitCleanStatus.ts
|
|
56284
|
+
class GitCleanStatusWidget {
|
|
56285
|
+
getDefaultColor() {
|
|
56286
|
+
return "green";
|
|
56287
|
+
}
|
|
56288
|
+
getDescription() {
|
|
56289
|
+
return "Shows ✓ when the working tree is clean and ✗ when it is dirty";
|
|
56290
|
+
}
|
|
56291
|
+
getDisplayName() {
|
|
56292
|
+
return "Git Clean Status";
|
|
56293
|
+
}
|
|
56294
|
+
getCategory() {
|
|
56295
|
+
return "Git";
|
|
56296
|
+
}
|
|
56297
|
+
getEditorDisplay(item) {
|
|
56298
|
+
return {
|
|
56299
|
+
displayText: this.getDisplayName(),
|
|
56300
|
+
modifierText: getHideNoGitModifierText(item)
|
|
56301
|
+
};
|
|
56302
|
+
}
|
|
56303
|
+
handleEditorAction(action, item) {
|
|
56304
|
+
return handleToggleNoGitAction(action, item);
|
|
56305
|
+
}
|
|
56306
|
+
render(item, context, _settings) {
|
|
56307
|
+
const hideNoGit = isHideNoGitEnabled(item);
|
|
56308
|
+
if (context.isPreview) {
|
|
56309
|
+
return item.rawValue ? "clean" : "✓";
|
|
56310
|
+
}
|
|
56311
|
+
if (!isInsideGitWorkTree(context)) {
|
|
56312
|
+
return hideNoGit ? null : "(no git)";
|
|
56313
|
+
}
|
|
56314
|
+
const status = getGitStatus(context);
|
|
56315
|
+
const clean = !status.staged && !status.unstaged && !status.untracked && !status.conflicts;
|
|
56316
|
+
if (item.rawValue) {
|
|
56317
|
+
return clean ? "clean" : "dirty";
|
|
56318
|
+
}
|
|
56319
|
+
return clean ? "✓" : "✗";
|
|
56320
|
+
}
|
|
56321
|
+
getCustomKeybinds() {
|
|
56322
|
+
return getHideNoGitKeybinds();
|
|
56323
|
+
}
|
|
56324
|
+
supportsRawValue() {
|
|
56325
|
+
return true;
|
|
56326
|
+
}
|
|
56327
|
+
supportsColors(_item) {
|
|
56328
|
+
return true;
|
|
56329
|
+
}
|
|
56330
|
+
}
|
|
56094
56331
|
// src/widgets/GitAheadBehind.ts
|
|
56095
56332
|
class GitAheadBehindWidget {
|
|
56096
56333
|
getDefaultColor() {
|
|
@@ -58218,7 +58455,6 @@ var WIDGET_MANIFEST = [
|
|
|
58218
58455
|
{ type: "context-length", create: () => new ContextLengthWidget },
|
|
58219
58456
|
{ type: "context-window", create: () => new ContextWindowWidget },
|
|
58220
58457
|
{ type: "context-percentage", create: () => new ContextPercentageWidget },
|
|
58221
|
-
{ type: "context-percentage-usable", create: () => new ContextPercentageUsableWidget },
|
|
58222
58458
|
{ type: "context-bar", create: () => new ContextBarWidget },
|
|
58223
58459
|
{ type: "session-clock", create: () => new SessionClockWidget },
|
|
58224
58460
|
{ type: "premium-requests", create: () => new PremiumRequestsWidget },
|
|
@@ -58237,8 +58473,12 @@ var WIDGET_MANIFEST = [
|
|
|
58237
58473
|
{ type: "git-pr", create: () => new GitPrWidget },
|
|
58238
58474
|
{ type: "git-status", create: () => new GitStatusWidget },
|
|
58239
58475
|
{ type: "git-staged", create: () => new GitStagedWidget },
|
|
58476
|
+
{ type: "git-staged-files", create: () => new GitStagedFilesWidget },
|
|
58240
58477
|
{ type: "git-unstaged", create: () => new GitUnstagedWidget },
|
|
58478
|
+
{ type: "git-unstaged-files", create: () => new GitUnstagedFilesWidget },
|
|
58241
58479
|
{ type: "git-untracked", create: () => new GitUntrackedWidget },
|
|
58480
|
+
{ type: "git-untracked-files", create: () => new GitUntrackedFilesWidget },
|
|
58481
|
+
{ type: "git-clean-status", create: () => new GitCleanStatusWidget },
|
|
58242
58482
|
{ type: "git-ahead-behind", create: () => new GitAheadBehindWidget },
|
|
58243
58483
|
{ type: "git-conflicts", create: () => new GitConflictsWidget },
|
|
58244
58484
|
{ type: "git-sha", create: () => new GitShaWidget },
|
|
@@ -62107,8 +62347,8 @@ function advanceGlobalPowerlineThemeIndex(currentIndex, entries) {
|
|
|
62107
62347
|
// src/utils/context-percentage.ts
|
|
62108
62348
|
function calculateContextPercentage(context) {
|
|
62109
62349
|
const contextWindowMetrics = getContextWindowMetrics(context.data);
|
|
62110
|
-
if (contextWindowMetrics.
|
|
62111
|
-
return contextWindowMetrics.
|
|
62350
|
+
if (contextWindowMetrics.currentContextUsedPercentage !== null) {
|
|
62351
|
+
return contextWindowMetrics.currentContextUsedPercentage;
|
|
62112
62352
|
}
|
|
62113
62353
|
return 0;
|
|
62114
62354
|
}
|
|
@@ -62509,17 +62749,18 @@ function renderStatusLine(widgets, settings, context, preRenderedWidgets, preCal
|
|
|
62509
62749
|
if (!widget)
|
|
62510
62750
|
continue;
|
|
62511
62751
|
if (widget.type === "separator") {
|
|
62512
|
-
let
|
|
62752
|
+
let previousWidgetRenderedContent = false;
|
|
62513
62753
|
for (let j = i - 1;j >= 0; j--) {
|
|
62514
62754
|
const prevWidget = widgets[j];
|
|
62515
|
-
if (prevWidget
|
|
62516
|
-
|
|
62517
|
-
|
|
62518
|
-
|
|
62519
|
-
|
|
62755
|
+
if (prevWidget?.type === "separator" || prevWidget?.type === "flex-separator") {
|
|
62756
|
+
continue;
|
|
62757
|
+
}
|
|
62758
|
+
if (prevWidget) {
|
|
62759
|
+
previousWidgetRenderedContent = Boolean(preRenderedWidgets[j]?.content);
|
|
62760
|
+
break;
|
|
62520
62761
|
}
|
|
62521
62762
|
}
|
|
62522
|
-
if (!
|
|
62763
|
+
if (!previousWidgetRenderedContent)
|
|
62523
62764
|
continue;
|
|
62524
62765
|
const sepChar = widget.character ?? (settings.defaultSeparator ?? "|");
|
|
62525
62766
|
const formattedSep = formatSeparator(sepChar);
|
package/package.json
CHANGED