ccstatusline 2.2.11 → 2.2.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.
@@ -56136,7 +56136,7 @@ function getTerminalWidth() {
56136
56136
  function canDetectTerminalWidth() {
56137
56137
  return probeTerminalWidth() !== null;
56138
56138
  }
56139
- var __dirname = "/Users/sirmalloc/Projects/Personal/ccstatusline/src/utils", PACKAGE_VERSION = "2.2.11";
56139
+ var __dirname = "/Users/sirmalloc/Projects/Personal/ccstatusline/src/utils", PACKAGE_VERSION = "2.2.13";
56140
56140
  var init_terminal = () => {};
56141
56141
 
56142
56142
  // src/utils/renderer.ts
@@ -57127,11 +57127,21 @@ function isUsageProgressMode(mode) {
57127
57127
  function isUsageSliderMode(mode) {
57128
57128
  return mode === "slider" || mode === "slider-only";
57129
57129
  }
57130
- function makeSliderBar(percent, width = SLIDER_WIDTH) {
57130
+ function makeSliderBar(percent, width = SLIDER_WIDTH, options) {
57131
57131
  const clamped = Math.max(0, Math.min(100, percent));
57132
57132
  const filled = Math.round(clamped / 100 * width);
57133
- const empty = width - filled;
57134
- return "▓".repeat(filled) + "".repeat(empty);
57133
+ const cursorPos = options?.cursorPercent !== undefined ? Math.min(Math.floor(Math.max(0, Math.min(100, options.cursorPercent)) / 100 * width), width - 1) : -1;
57134
+ let bar = "";
57135
+ for (let i = 0;i < width; i++) {
57136
+ if (i === cursorPos) {
57137
+ bar += "│";
57138
+ } else if (i < filled) {
57139
+ bar += "▓";
57140
+ } else {
57141
+ bar += "░";
57142
+ }
57143
+ }
57144
+ return bar;
57135
57145
  }
57136
57146
  function getUsageProgressBarWidth(mode) {
57137
57147
  return mode === "progress" ? 32 : 16;
@@ -57142,6 +57152,12 @@ function isUsageInverted(item) {
57142
57152
  function isUsageCompact(item) {
57143
57153
  return isMetadataFlagEnabled(item, "compact");
57144
57154
  }
57155
+ function isUsageCursorEnabled(item) {
57156
+ return isMetadataFlagEnabled(item, "cursor");
57157
+ }
57158
+ function toggleUsageCursor(item) {
57159
+ return toggleMetadataFlag(item, "cursor");
57160
+ }
57145
57161
  function isUsageDateMode(item) {
57146
57162
  return isMetadataFlagEnabled(item, "absolute");
57147
57163
  }
@@ -57213,6 +57229,9 @@ function getUsageDisplayModifierText(item, options = {}) {
57213
57229
  if (isUsageInverted(item)) {
57214
57230
  modifiers.push("inverted");
57215
57231
  }
57232
+ if (isUsageCursorEnabled(item) && (isUsageProgressMode(mode) || isUsageSliderMode(mode))) {
57233
+ modifiers.push("time cursor");
57234
+ }
57216
57235
  if (options.includeCompact && !isUsageProgressMode(mode) && isUsageCompact(item)) {
57217
57236
  modifiers.push("compact");
57218
57237
  }
@@ -57240,7 +57259,8 @@ function cycleUsageDisplayMode(item, disabledInProgressKeys = [], includeSlider
57240
57259
  } else {
57241
57260
  nextMode = currentMode === "time" ? "progress" : currentMode === "progress" ? "progress-short" : "time";
57242
57261
  }
57243
- const nextItem = removeMetadataKeys(item, nextMode === "time" ? ["invert"] : disabledInProgressKeys);
57262
+ const keysToRemove = nextMode === "time" ? ["invert", "cursor"] : disabledInProgressKeys;
57263
+ const nextItem = removeMetadataKeys(item, keysToRemove);
57244
57264
  const nextMetadata = {
57245
57265
  ...nextItem.metadata ?? {},
57246
57266
  display: nextMode
@@ -57260,12 +57280,17 @@ function getUsagePercentCustomKeybinds(item) {
57260
57280
  if (isUsageProgressMode(mode) || isUsageSliderMode(mode)) {
57261
57281
  keybinds.push(INVERT_TOGGLE_KEYBIND);
57262
57282
  }
57283
+ if (isUsageProgressMode(mode) || isUsageSliderMode(mode)) {
57284
+ keybinds.push(CURSOR_TOGGLE_KEYBIND);
57285
+ }
57263
57286
  }
57264
57287
  return keybinds;
57265
57288
  }
57266
57289
  function getUsageTimerCustomKeybinds(item, options = {}) {
57267
57290
  const keybinds = [PROGRESS_TOGGLE_KEYBIND];
57268
- if (item && isUsageProgressMode(getUsageDisplayMode(item))) {
57291
+ const mode = item ? getUsageDisplayMode(item) : "time";
57292
+ const isBarMode = isUsageProgressMode(mode) || isUsageSliderMode(mode);
57293
+ if (item && isBarMode) {
57269
57294
  keybinds.push(INVERT_TOGGLE_KEYBIND);
57270
57295
  } else {
57271
57296
  keybinds.push(COMPACT_TOGGLE_KEYBIND);
@@ -57273,7 +57298,7 @@ function getUsageTimerCustomKeybinds(item, options = {}) {
57273
57298
  keybinds.push(DATE_TOGGLE_KEYBIND);
57274
57299
  }
57275
57300
  }
57276
- if (item && isUsageDateMode(item) && !isUsageProgressMode(getUsageDisplayMode(item))) {
57301
+ if (item && isUsageDateMode(item) && !isBarMode) {
57277
57302
  if (options.includeHourFormat) {
57278
57303
  keybinds.push(HOUR_FORMAT_TOGGLE_KEYBIND);
57279
57304
  }
@@ -57286,12 +57311,13 @@ function getUsageTimerCustomKeybinds(item, options = {}) {
57286
57311
  }
57287
57312
  return keybinds;
57288
57313
  }
57289
- var SLIDER_WIDTH = 10, PROGRESS_TOGGLE_KEYBIND, INVERT_TOGGLE_KEYBIND, COMPACT_TOGGLE_KEYBIND, DATE_TOGGLE_KEYBIND, HOUR_FORMAT_TOGGLE_KEYBIND, TIMEZONE_KEYBIND, LOCALE_KEYBIND;
57314
+ var SLIDER_WIDTH = 10, PROGRESS_TOGGLE_KEYBIND, INVERT_TOGGLE_KEYBIND, COMPACT_TOGGLE_KEYBIND, CURSOR_TOGGLE_KEYBIND, DATE_TOGGLE_KEYBIND, HOUR_FORMAT_TOGGLE_KEYBIND, TIMEZONE_KEYBIND, LOCALE_KEYBIND;
57290
57315
  var init_usage_display = __esm(() => {
57291
57316
  init_locales2();
57292
57317
  PROGRESS_TOGGLE_KEYBIND = { key: "p", label: "(p)rogress toggle", action: "toggle-progress" };
57293
57318
  INVERT_TOGGLE_KEYBIND = { key: "v", label: "in(v)ert fill", action: "toggle-invert" };
57294
57319
  COMPACT_TOGGLE_KEYBIND = { key: "s", label: "(s)hort time", action: "toggle-compact" };
57320
+ CURSOR_TOGGLE_KEYBIND = { key: "t", label: "(t)ime cursor", action: "toggle-cursor" };
57295
57321
  DATE_TOGGLE_KEYBIND = { key: "t", label: "(t)imestamp", action: "toggle-date" };
57296
57322
  HOUR_FORMAT_TOGGLE_KEYBIND = { key: "h", label: "12/24 (h)our", action: "toggle-hour-format" };
57297
57323
  TIMEZONE_KEYBIND = { key: "z", label: "time(z)one", action: "edit-timezone" };
@@ -57386,23 +57412,19 @@ class ContextPercentageWidget {
57386
57412
  }
57387
57413
  render(item, context, settings) {
57388
57414
  const isInverse = isContextInverse(item);
57415
+ const label = isInverse ? "Ctx Left: " : "Ctx Used: ";
57389
57416
  const sliderMode = getContextSliderMode(item);
57390
57417
  const contextPercentageMetrics = calculateContextPercentageMetrics(context);
57418
+ const formatContextPercentage = (displayPercentage) => {
57419
+ const sliderResult = renderContextSlider(sliderMode, displayPercentage);
57420
+ return formatRawOrLabeledValue(item, label, sliderResult ?? `${displayPercentage.toFixed(1)}%`);
57421
+ };
57391
57422
  if (context.isPreview) {
57392
- const previewPercent = isInverse ? 90.7 : 9.3;
57393
- const sliderResult = renderContextSlider(sliderMode, previewPercent);
57394
- if (sliderResult !== null) {
57395
- return formatRawOrLabeledValue(item, "Ctx: ", sliderResult);
57396
- }
57397
- return formatRawOrLabeledValue(item, "Ctx: ", `${previewPercent.toFixed(1)}%`);
57423
+ return formatContextPercentage(isInverse ? 90.7 : 9.3);
57398
57424
  }
57399
57425
  if (contextPercentageMetrics !== null) {
57400
57426
  const displayPercentage = isInverse ? 100 - contextPercentageMetrics.usedPercentage : contextPercentageMetrics.usedPercentage;
57401
- const sliderResult = renderContextSlider(sliderMode, displayPercentage);
57402
- if (sliderResult !== null) {
57403
- return formatRawOrLabeledValue(item, "Ctx: ", sliderResult);
57404
- }
57405
- return formatRawOrLabeledValue(item, "Ctx: ", `${displayPercentage.toFixed(1)}%`);
57427
+ return formatContextPercentage(displayPercentage);
57406
57428
  }
57407
57429
  return null;
57408
57430
  }
@@ -57457,35 +57479,27 @@ class ContextPercentageUsableWidget {
57457
57479
  }
57458
57480
  render(item, context, settings) {
57459
57481
  const isInverse = isContextInverse(item);
57482
+ const label = isInverse ? "Ctx(u) Left: " : "Ctx(u) Used: ";
57460
57483
  const sliderMode = getContextSliderMode(item);
57461
57484
  const modelIdentifier = getModelContextIdentifier(context.data?.model);
57462
57485
  const contextWindowMetrics = getContextWindowMetrics(context.data);
57463
57486
  const contextConfig = getContextConfig(modelIdentifier, contextWindowMetrics.windowSize);
57487
+ const formatContextPercentage = (displayPercentage) => {
57488
+ const sliderResult = renderContextSlider(sliderMode, displayPercentage);
57489
+ return formatRawOrLabeledValue(item, label, sliderResult ?? `${displayPercentage.toFixed(1)}%`);
57490
+ };
57464
57491
  if (context.isPreview) {
57465
- const previewPercent = isInverse ? 88.4 : 11.6;
57466
- const sliderResult = renderContextSlider(sliderMode, previewPercent);
57467
- if (sliderResult !== null) {
57468
- return formatRawOrLabeledValue(item, "Ctx(u): ", sliderResult);
57469
- }
57470
- return formatRawOrLabeledValue(item, "Ctx(u): ", `${previewPercent.toFixed(1)}%`);
57492
+ return formatContextPercentage(isInverse ? 88.4 : 11.6);
57471
57493
  }
57472
57494
  if (contextWindowMetrics.contextLengthTokens !== null) {
57473
57495
  const usedPercentage = Math.min(100, contextWindowMetrics.contextLengthTokens / contextConfig.usableTokens * 100);
57474
57496
  const displayPercentage = isInverse ? 100 - usedPercentage : usedPercentage;
57475
- const sliderResult = renderContextSlider(sliderMode, displayPercentage);
57476
- if (sliderResult !== null) {
57477
- return formatRawOrLabeledValue(item, "Ctx(u): ", sliderResult);
57478
- }
57479
- return formatRawOrLabeledValue(item, "Ctx(u): ", `${displayPercentage.toFixed(1)}%`);
57497
+ return formatContextPercentage(displayPercentage);
57480
57498
  }
57481
57499
  if (context.tokenMetrics) {
57482
57500
  const usedPercentage = Math.min(100, context.tokenMetrics.contextLength / contextConfig.usableTokens * 100);
57483
57501
  const displayPercentage = isInverse ? 100 - usedPercentage : usedPercentage;
57484
- const sliderResult = renderContextSlider(sliderMode, displayPercentage);
57485
- if (sliderResult !== null) {
57486
- return formatRawOrLabeledValue(item, "Ctx(u): ", sliderResult);
57487
- }
57488
- return formatRawOrLabeledValue(item, "Ctx(u): ", `${displayPercentage.toFixed(1)}%`);
57502
+ return formatContextPercentage(displayPercentage);
57489
57503
  }
57490
57504
  return null;
57491
57505
  }
@@ -59507,6 +59521,10 @@ function parseCachedUsageData(rawJson) {
59507
59521
  sessionResetAt: parsed.sessionResetAt ?? undefined,
59508
59522
  weeklyUsage: parsed.weeklyUsage ?? undefined,
59509
59523
  weeklyResetAt: parsed.weeklyResetAt ?? undefined,
59524
+ weeklySonnetUsage: parsed.weeklySonnetUsage ?? undefined,
59525
+ weeklySonnetResetAt: parsed.weeklySonnetResetAt ?? undefined,
59526
+ weeklyOpusUsage: parsed.weeklyOpusUsage ?? undefined,
59527
+ weeklyOpusResetAt: parsed.weeklyOpusResetAt ?? undefined,
59510
59528
  extraUsageEnabled: parsed.extraUsageEnabled ?? undefined,
59511
59529
  extraUsageLimit: parsed.extraUsageLimit ?? undefined,
59512
59530
  extraUsageUsed: parsed.extraUsageUsed ?? undefined,
@@ -59524,6 +59542,10 @@ function parseUsageApiResponse(rawJson) {
59524
59542
  sessionResetAt: parsed.five_hour?.resets_at ?? undefined,
59525
59543
  weeklyUsage: parsed.seven_day?.utilization ?? undefined,
59526
59544
  weeklyResetAt: parsed.seven_day?.resets_at ?? undefined,
59545
+ weeklySonnetUsage: parsed.seven_day_sonnet === null ? 0 : parsed.seven_day_sonnet?.utilization ?? undefined,
59546
+ weeklySonnetResetAt: parsed.seven_day_sonnet?.resets_at ?? undefined,
59547
+ weeklyOpusUsage: parsed.seven_day_opus === null ? 0 : parsed.seven_day_opus?.utilization ?? undefined,
59548
+ weeklyOpusResetAt: parsed.seven_day_opus?.resets_at ?? undefined,
59527
59549
  extraUsageEnabled: parsed.extra_usage?.is_enabled ?? undefined,
59528
59550
  extraUsageLimit: parsed.extra_usage?.monthly_limit ?? undefined,
59529
59551
  extraUsageUsed: parsed.extra_usage?.used_credits ?? undefined,
@@ -59548,9 +59570,12 @@ function cacheUsageData(data, now2) {
59548
59570
  usageErrorCacheMaxAge = LOCK_MAX_AGE;
59549
59571
  return data;
59550
59572
  }
59551
- function getStaleUsageOrError(error48, now2, errorCacheMaxAge = LOCK_MAX_AGE) {
59573
+ function hasRequiredUsageFields(data, requiredFields = []) {
59574
+ return requiredFields.every((field) => data[field] !== undefined);
59575
+ }
59576
+ function getStaleUsageOrError(error48, now2, errorCacheMaxAge = LOCK_MAX_AGE, requiredFields = []) {
59552
59577
  const stale = readStaleUsageCache();
59553
- if (stale && !stale.error) {
59578
+ if (stale && !stale.error && hasRequiredUsageFields(stale, requiredFields)) {
59554
59579
  return cacheUsageData(stale, now2);
59555
59580
  }
59556
59581
  return setCachedUsageError(error48, now2, errorCacheMaxAge);
@@ -59802,11 +59827,12 @@ async function fetchFromUsageApi(token) {
59802
59827
  request2.end();
59803
59828
  });
59804
59829
  }
59805
- async function fetchUsageData() {
59830
+ async function fetchUsageData(options = {}) {
59806
59831
  const now2 = Math.floor(Date.now() / 1000);
59832
+ const requiredFields = options.requiredFields ?? [];
59807
59833
  if (cachedUsageData) {
59808
59834
  const cacheAge = now2 - usageCacheTime;
59809
- if (!cachedUsageData.error && cacheAge < CACHE_MAX_AGE) {
59835
+ if (!cachedUsageData.error && cacheAge < CACHE_MAX_AGE && hasRequiredUsageFields(cachedUsageData, requiredFields)) {
59810
59836
  return cachedUsageData;
59811
59837
  }
59812
59838
  if (cachedUsageData.error && cacheAge < usageErrorCacheMaxAge) {
@@ -59818,35 +59844,35 @@ async function fetchUsageData() {
59818
59844
  const fileAge = now2 - Math.floor(stat.mtimeMs / 1000);
59819
59845
  if (fileAge < CACHE_MAX_AGE) {
59820
59846
  const fileData = parseCachedUsageData(fs3.readFileSync(CACHE_FILE, "utf8"));
59821
- if (fileData && !fileData.error) {
59847
+ if (fileData && !fileData.error && hasRequiredUsageFields(fileData, requiredFields)) {
59822
59848
  return cacheUsageData(fileData, now2);
59823
59849
  }
59824
59850
  }
59825
59851
  } catch {}
59826
59852
  const token = getUsageToken();
59827
59853
  if (!token) {
59828
- return getStaleUsageOrError("no-credentials", now2);
59854
+ return getStaleUsageOrError("no-credentials", now2, LOCK_MAX_AGE, requiredFields);
59829
59855
  }
59830
59856
  const activeLock = readActiveUsageLock(now2);
59831
59857
  if (activeLock) {
59832
- return getStaleUsageOrError(activeLock.error, now2, Math.max(1, activeLock.blockedUntil - now2));
59858
+ return getStaleUsageOrError(activeLock.error, now2, Math.max(1, activeLock.blockedUntil - now2), requiredFields);
59833
59859
  }
59834
59860
  writeUsageLock(now2 + LOCK_MAX_AGE, "timeout");
59835
59861
  try {
59836
59862
  const response = await fetchFromUsageApi(token);
59837
59863
  if (response.kind === "rate-limited") {
59838
59864
  writeUsageLock(now2 + response.retryAfterSeconds, "rate-limited");
59839
- return getStaleUsageOrError("rate-limited", now2, response.retryAfterSeconds);
59865
+ return getStaleUsageOrError("rate-limited", now2, response.retryAfterSeconds, requiredFields);
59840
59866
  }
59841
59867
  if (response.kind === "error") {
59842
- return getStaleUsageOrError("api-error", now2);
59868
+ return getStaleUsageOrError("api-error", now2, LOCK_MAX_AGE, requiredFields);
59843
59869
  }
59844
59870
  const usageData = parseUsageApiResponse(response.body);
59845
59871
  if (!usageData) {
59846
- return getStaleUsageOrError("parse-error", now2);
59872
+ return getStaleUsageOrError("parse-error", now2, LOCK_MAX_AGE, requiredFields);
59847
59873
  }
59848
59874
  if (usageData.sessionUsage === undefined && usageData.weeklyUsage === undefined) {
59849
- return getStaleUsageOrError("parse-error", now2);
59875
+ return getStaleUsageOrError("parse-error", now2, LOCK_MAX_AGE, requiredFields);
59850
59876
  }
59851
59877
  try {
59852
59878
  ensureCacheDirExists();
@@ -59854,10 +59880,10 @@ async function fetchUsageData() {
59854
59880
  } catch {}
59855
59881
  return cacheUsageData(usageData, now2);
59856
59882
  } catch {
59857
- return getStaleUsageOrError("parse-error", now2);
59883
+ return getStaleUsageOrError("parse-error", now2, LOCK_MAX_AGE, requiredFields);
59858
59884
  }
59859
59885
  }
59860
- var CACHE_DIR, CACHE_FILE, LOCK_FILE, CACHE_MAX_AGE = 180, LOCK_MAX_AGE = 30, DEFAULT_RATE_LIMIT_BACKOFF = 300, MACOS_USAGE_CREDENTIALS_SERVICE = "Claude Code-credentials", MACOS_SECURITY_DUMP_MAX_BUFFER, UsageCredentialsSchema, UsageLockErrorSchema, UsageLockSchema, CachedUsageDataSchema, UsageApiResponseSchema, cachedUsageData = null, usageCacheTime = 0, usageErrorCacheMaxAge, USAGE_API_HOST = "api.anthropic.com", USAGE_API_PATH = "/api/oauth/usage", USAGE_API_TIMEOUT_MS = 5000;
59886
+ var CACHE_DIR, CACHE_FILE, LOCK_FILE, CACHE_MAX_AGE = 180, LOCK_MAX_AGE = 30, DEFAULT_RATE_LIMIT_BACKOFF = 300, MACOS_USAGE_CREDENTIALS_SERVICE = "Claude Code-credentials", MACOS_SECURITY_DUMP_MAX_BUFFER, UsageCredentialsSchema, UsageLockErrorSchema, UsageLockSchema, CachedUsageDataSchema, PerModelWeeklyBucketSchema, UsageApiResponseSchema, cachedUsageData = null, usageCacheTime = 0, usageErrorCacheMaxAge, USAGE_API_HOST = "api.anthropic.com", USAGE_API_PATH = "/api/oauth/usage", USAGE_API_TIMEOUT_MS = 5000;
59861
59887
  var init_usage_fetch = __esm(async () => {
59862
59888
  init_dist5();
59863
59889
  init_zod();
@@ -59878,12 +59904,20 @@ var init_usage_fetch = __esm(async () => {
59878
59904
  sessionResetAt: exports_external.string().nullable().optional(),
59879
59905
  weeklyUsage: exports_external.number().nullable().optional(),
59880
59906
  weeklyResetAt: exports_external.string().nullable().optional(),
59907
+ weeklySonnetUsage: exports_external.number().nullable().optional(),
59908
+ weeklySonnetResetAt: exports_external.string().nullable().optional(),
59909
+ weeklyOpusUsage: exports_external.number().nullable().optional(),
59910
+ weeklyOpusResetAt: exports_external.string().nullable().optional(),
59881
59911
  extraUsageEnabled: exports_external.boolean().nullable().optional(),
59882
59912
  extraUsageLimit: exports_external.number().nullable().optional(),
59883
59913
  extraUsageUsed: exports_external.number().nullable().optional(),
59884
59914
  extraUsageUtilization: exports_external.number().nullable().optional(),
59885
59915
  error: exports_external.string().nullable().optional()
59886
59916
  });
59917
+ PerModelWeeklyBucketSchema = exports_external.object({
59918
+ utilization: exports_external.number().nullable().optional(),
59919
+ resets_at: exports_external.string().nullable().optional()
59920
+ }).nullable().optional();
59887
59921
  UsageApiResponseSchema = exports_external.object({
59888
59922
  five_hour: exports_external.object({
59889
59923
  utilization: exports_external.number().nullable().optional(),
@@ -59893,6 +59927,8 @@ var init_usage_fetch = __esm(async () => {
59893
59927
  utilization: exports_external.number().nullable().optional(),
59894
59928
  resets_at: exports_external.string().nullable().optional()
59895
59929
  }).optional(),
59930
+ seven_day_sonnet: PerModelWeeklyBucketSchema,
59931
+ seven_day_opus: PerModelWeeklyBucketSchema,
59896
59932
  extra_usage: exports_external.object({
59897
59933
  is_enabled: exports_external.boolean().nullable().optional(),
59898
59934
  monthly_limit: exports_external.number().nullable().optional(),
@@ -63161,6 +63197,12 @@ function getWeeklyUsageWindowFromResetAt(weeklyResetAt, nowMs = Date.now()) {
63161
63197
  function resolveWeeklyUsageWindow(usageData, nowMs = Date.now()) {
63162
63198
  return getWeeklyUsageWindowFromResetAt(usageData.weeklyResetAt, nowMs);
63163
63199
  }
63200
+ function resolveWeeklySonnetUsageWindow(usageData, nowMs = Date.now()) {
63201
+ return getWeeklyUsageWindowFromResetAt(usageData.weeklySonnetResetAt ?? usageData.weeklyResetAt, nowMs);
63202
+ }
63203
+ function resolveWeeklyOpusUsageWindow(usageData, nowMs = Date.now()) {
63204
+ return getWeeklyUsageWindowFromResetAt(usageData.weeklyOpusResetAt ?? usageData.weeklyResetAt, nowMs);
63205
+ }
63164
63206
  function formatUsageDuration(durationMs, compact2 = false, useDays = true) {
63165
63207
  const clampedMs = Math.max(0, durationMs);
63166
63208
  const totalHours = Math.floor(clampedMs / (1000 * 60 * 60));
@@ -63318,7 +63360,7 @@ class BlockTimerWidget {
63318
63360
  }
63319
63361
  handleEditorAction(action, item) {
63320
63362
  if (action === "toggle-progress") {
63321
- return cycleUsageDisplayMode(item, ["compact"]);
63363
+ return cycleUsageDisplayMode(item, ["compact"], true);
63322
63364
  }
63323
63365
  if (action === "toggle-invert") {
63324
63366
  return toggleUsageInverted(item);
@@ -63339,6 +63381,11 @@ class BlockTimerWidget {
63339
63381
  const progressBar = makeTimerProgressBar(previewPercent, barWidth);
63340
63382
  return formatRawOrLabeledValue(item, "Block ", `[${progressBar}] ${previewPercent.toFixed(1)}%`);
63341
63383
  }
63384
+ if (isUsageSliderMode(displayMode)) {
63385
+ const slider = makeSliderBar(previewPercent);
63386
+ const sliderDisplay = displayMode === "slider" ? `${slider} ${previewPercent.toFixed(1)}%` : slider;
63387
+ return formatRawOrLabeledValue(item, "Block ", sliderDisplay);
63388
+ }
63342
63389
  return formatRawOrLabeledValue(item, "Block: ", compact2 ? "3h45m" : "3hr 45m");
63343
63390
  }
63344
63391
  const usageData = context.usageData ?? {};
@@ -63349,6 +63396,11 @@ class BlockTimerWidget {
63349
63396
  const emptyBar = "░".repeat(barWidth);
63350
63397
  return formatRawOrLabeledValue(item, "Block ", `[${emptyBar}] 0.0%`);
63351
63398
  }
63399
+ if (isUsageSliderMode(displayMode)) {
63400
+ const emptySlider = makeSliderBar(0);
63401
+ const sliderDisplay = displayMode === "slider" ? `${emptySlider} 0.0%` : emptySlider;
63402
+ return formatRawOrLabeledValue(item, "Block ", sliderDisplay);
63403
+ }
63352
63404
  return formatRawOrLabeledValue(item, "Block: ", compact2 ? "0h" : "0hr 0m");
63353
63405
  }
63354
63406
  if (isUsageProgressMode(displayMode)) {
@@ -63358,6 +63410,12 @@ class BlockTimerWidget {
63358
63410
  const percentage = percent.toFixed(1);
63359
63411
  return formatRawOrLabeledValue(item, "Block ", `[${progressBar}] ${percentage}%`);
63360
63412
  }
63413
+ if (isUsageSliderMode(displayMode)) {
63414
+ const percent = inverted ? window2.remainingPercent : window2.elapsedPercent;
63415
+ const slider = makeSliderBar(percent);
63416
+ const sliderDisplay = displayMode === "slider" ? `${slider} ${percent.toFixed(1)}%` : slider;
63417
+ return formatRawOrLabeledValue(item, "Block ", sliderDisplay);
63418
+ }
63361
63419
  const elapsedTime = formatUsageDuration(window2.elapsedMs, compact2);
63362
63420
  return formatRawOrLabeledValue(item, "Block: ", elapsedTime);
63363
63421
  }
@@ -63666,149 +63724,793 @@ class ClaudeSessionIdWidget {
63666
63724
  }
63667
63725
  }
63668
63726
 
63669
- // src/widgets/ClaudeAccountEmail.ts
63670
- import * as fs8 from "fs";
63727
+ // src/utils/jj.ts
63728
+ import { execFileSync as execFileSync4 } from "child_process";
63729
+ function runJjArgs(args, context, allowEmpty = false) {
63730
+ try {
63731
+ const cwd2 = resolveGitCwd(context);
63732
+ const output = execFileSync4("jj", args, {
63733
+ encoding: "utf8",
63734
+ stdio: ["pipe", "pipe", "ignore"],
63735
+ ...cwd2 ? { cwd: cwd2 } : {}
63736
+ }).trimEnd();
63737
+ return allowEmpty || output.length > 0 ? output : null;
63738
+ } catch {
63739
+ return null;
63740
+ }
63741
+ }
63742
+ function isInsideJjRepo(context) {
63743
+ return runJjArgs(["root"], context) !== null;
63744
+ }
63745
+ function parseDiffStat(stat2) {
63746
+ const insertMatch = /(\d+)\s+insertions?/.exec(stat2);
63747
+ const deleteMatch = /(\d+)\s+deletions?/.exec(stat2);
63748
+ return {
63749
+ insertions: insertMatch?.[1] ? parseInt(insertMatch[1], 10) : 0,
63750
+ deletions: deleteMatch?.[1] ? parseInt(deleteMatch[1], 10) : 0
63751
+ };
63752
+ }
63753
+ function getJjChangeCounts(context) {
63754
+ return parseDiffStat(runJjArgs(["diff", "--stat"], context) ?? "");
63755
+ }
63756
+ var init_jj = __esm(() => {
63757
+ init_git();
63758
+ });
63671
63759
 
63672
- class ClaudeAccountEmailWidget {
63760
+ // src/widgets/JjBookmarks.ts
63761
+ class JjBookmarksWidget {
63673
63762
  getDefaultColor() {
63674
- return "blue";
63763
+ return "magenta";
63675
63764
  }
63676
63765
  getDescription() {
63677
- return "Displays the email of the currently logged-in Claude account";
63766
+ return "Shows the current jujutsu bookmark(s)";
63678
63767
  }
63679
63768
  getDisplayName() {
63680
- return "Claude Account Email";
63769
+ return "JJ Bookmarks";
63681
63770
  }
63682
63771
  getCategory() {
63683
- return "Session";
63772
+ return "Jujutsu";
63684
63773
  }
63685
63774
  getEditorDisplay(item) {
63686
- return { displayText: this.getDisplayName() };
63775
+ const hideNoJj = item.metadata?.hideNoJj === "true";
63776
+ const modifiers = [];
63777
+ if (hideNoJj) {
63778
+ modifiers.push("hide 'no jj'");
63779
+ }
63780
+ return {
63781
+ displayText: this.getDisplayName(),
63782
+ modifierText: modifiers.length > 0 ? `(${modifiers.join(", ")})` : undefined
63783
+ };
63687
63784
  }
63688
- render(item, context, settings) {
63785
+ handleEditorAction(action, item) {
63786
+ if (action === "toggle-nojj") {
63787
+ const currentState = item.metadata?.hideNoJj === "true";
63788
+ return {
63789
+ ...item,
63790
+ metadata: {
63791
+ ...item.metadata,
63792
+ hideNoJj: (!currentState).toString()
63793
+ }
63794
+ };
63795
+ }
63796
+ return null;
63797
+ }
63798
+ render(item, context, _settings) {
63799
+ const hideNoJj = item.metadata?.hideNoJj === "true";
63689
63800
  if (context.isPreview) {
63690
- return item.rawValue ? "you@example.com" : "Account: you@example.com";
63801
+ return item.rawValue ? "main" : "\uD83D\uDD16 main";
63802
+ }
63803
+ if (!isInsideJjRepo(context)) {
63804
+ return hideNoJj ? null : "\uD83D\uDD16 no jj";
63805
+ }
63806
+ const bookmarks = this.getJjBookmarks(context);
63807
+ if (bookmarks) {
63808
+ return item.rawValue ? bookmarks : `\uD83D\uDD16 ${bookmarks}`;
63809
+ }
63810
+ return hideNoJj ? null : "\uD83D\uDD16 (none)";
63811
+ }
63812
+ getJjBookmarks(context) {
63813
+ const output = runJjArgs([
63814
+ "log",
63815
+ "--no-graph",
63816
+ "-r",
63817
+ "heads(::@ & bookmarks())",
63818
+ "--template",
63819
+ "bookmarks"
63820
+ ], context);
63821
+ if (!output) {
63822
+ return null;
63691
63823
  }
63692
- try {
63693
- const content = fs8.readFileSync(getClaudeJsonPath(), "utf-8");
63694
- const data = JSON.parse(content);
63695
- const email3 = data.oauthAccount?.emailAddress;
63696
- if (typeof email3 !== "string" || email3.length === 0) {
63697
- return null;
63698
- }
63699
- return item.rawValue ? email3 : `Account: ${email3}`;
63700
- } catch {
63824
+ const bookmarks = output.split(/\s+/).filter(Boolean);
63825
+ if (bookmarks.length === 0) {
63701
63826
  return null;
63702
63827
  }
63828
+ return bookmarks.join(", ");
63829
+ }
63830
+ getCustomKeybinds() {
63831
+ return [
63832
+ { key: "h", label: "(h)ide 'no jj' message", action: "toggle-nojj" }
63833
+ ];
63703
63834
  }
63704
63835
  supportsRawValue() {
63705
63836
  return true;
63706
63837
  }
63707
- supportsColors(item) {
63838
+ supportsColors() {
63708
63839
  return true;
63709
63840
  }
63710
63841
  }
63711
- var init_ClaudeAccountEmail = __esm(async () => {
63712
- await init_claude_settings();
63842
+ var init_JjBookmarks = __esm(() => {
63843
+ init_jj();
63713
63844
  });
63714
63845
 
63715
- // src/utils/speed-metrics.ts
63716
- function calculateOutputSpeed(metrics) {
63717
- if (metrics.totalDurationMs === 0) {
63718
- return null;
63846
+ // src/widgets/JjWorkspace.ts
63847
+ class JjWorkspaceWidget {
63848
+ getDefaultColor() {
63849
+ return "blue";
63719
63850
  }
63720
- const seconds = metrics.totalDurationMs / 1000;
63721
- return metrics.outputTokens / seconds;
63722
- }
63723
- function calculateInputSpeed(metrics) {
63724
- if (metrics.totalDurationMs === 0) {
63725
- return null;
63851
+ getDescription() {
63852
+ return "Shows the current jujutsu workspace name";
63726
63853
  }
63727
- const seconds = metrics.totalDurationMs / 1000;
63728
- return metrics.inputTokens / seconds;
63729
- }
63730
- function calculateTotalSpeed(metrics) {
63731
- if (metrics.totalDurationMs === 0) {
63854
+ getDisplayName() {
63855
+ return "JJ Workspace";
63856
+ }
63857
+ getCategory() {
63858
+ return "Jujutsu";
63859
+ }
63860
+ getEditorDisplay(item) {
63861
+ const hideNoJj = item.metadata?.hideNoJj === "true";
63862
+ const modifiers = [];
63863
+ if (hideNoJj) {
63864
+ modifiers.push("hide 'no jj'");
63865
+ }
63866
+ return {
63867
+ displayText: this.getDisplayName(),
63868
+ modifierText: modifiers.length > 0 ? `(${modifiers.join(", ")})` : undefined
63869
+ };
63870
+ }
63871
+ handleEditorAction(action, item) {
63872
+ if (action === "toggle-nojj") {
63873
+ const currentState = item.metadata?.hideNoJj === "true";
63874
+ return {
63875
+ ...item,
63876
+ metadata: {
63877
+ ...item.metadata,
63878
+ hideNoJj: (!currentState).toString()
63879
+ }
63880
+ };
63881
+ }
63732
63882
  return null;
63733
63883
  }
63734
- const seconds = metrics.totalDurationMs / 1000;
63735
- return metrics.totalTokens / seconds;
63736
- }
63737
- function formatSpeed(tokensPerSec) {
63738
- if (tokensPerSec === null) {
63739
- return "—";
63884
+ render(item, context, _settings) {
63885
+ const hideNoJj = item.metadata?.hideNoJj === "true";
63886
+ if (context.isPreview) {
63887
+ return item.rawValue ? "default" : "◆ default";
63888
+ }
63889
+ if (!isInsideJjRepo(context)) {
63890
+ return hideNoJj ? null : "◆ no jj";
63891
+ }
63892
+ const workspace = this.getJjWorkspace(context);
63893
+ if (workspace) {
63894
+ return item.rawValue ? workspace : `◆ ${workspace}`;
63895
+ }
63896
+ return hideNoJj ? null : "◆ no jj";
63740
63897
  }
63741
- if (tokensPerSec >= 1000) {
63742
- const kValue = tokensPerSec / 1000;
63743
- return `${kValue.toFixed(1)}k t/s`;
63898
+ getJjWorkspace(context) {
63899
+ const output = runJjArgs([
63900
+ "workspace",
63901
+ "list",
63902
+ "--template",
63903
+ CURRENT_WORKSPACE_TEMPLATE
63904
+ ], context);
63905
+ if (!output) {
63906
+ return null;
63907
+ }
63908
+ return output.split(/\r?\n/).map((workspace) => workspace.trim()).find(Boolean) ?? null;
63909
+ }
63910
+ getCustomKeybinds() {
63911
+ return [
63912
+ { key: "h", label: "(h)ide 'no jj' message", action: "toggle-nojj" }
63913
+ ];
63914
+ }
63915
+ supportsRawValue() {
63916
+ return true;
63917
+ }
63918
+ supportsColors() {
63919
+ return true;
63744
63920
  }
63745
- return `${tokensPerSec.toFixed(1)} t/s`;
63746
63921
  }
63922
+ var CURRENT_WORKSPACE_TEMPLATE = `if(target.current_working_copy(), name ++ "
63923
+ ")`;
63924
+ var init_JjWorkspace = __esm(() => {
63925
+ init_jj();
63926
+ });
63747
63927
 
63748
- // src/utils/speed-window.ts
63749
- function clampSpeedWindowSeconds(value) {
63750
- if (!Number.isFinite(value)) {
63751
- return DEFAULT_SPEED_WINDOW_SECONDS;
63928
+ // src/widgets/JjRootDir.ts
63929
+ class JjRootDirWidget {
63930
+ getDefaultColor() {
63931
+ return "cyan";
63752
63932
  }
63753
- const normalized = Math.trunc(value);
63754
- if (normalized < MIN_SPEED_WINDOW_SECONDS) {
63755
- return MIN_SPEED_WINDOW_SECONDS;
63933
+ getDescription() {
63934
+ return "Shows the jujutsu repository root directory name";
63756
63935
  }
63757
- if (normalized > MAX_SPEED_WINDOW_SECONDS) {
63758
- return MAX_SPEED_WINDOW_SECONDS;
63936
+ getDisplayName() {
63937
+ return "JJ Root Dir";
63759
63938
  }
63760
- return normalized;
63761
- }
63762
- function getWidgetSpeedWindowSeconds(item) {
63763
- const metadataValue = item.metadata?.[SPEED_WINDOW_METADATA_KEY];
63764
- if (!metadataValue) {
63765
- return DEFAULT_SPEED_WINDOW_SECONDS;
63939
+ getCategory() {
63940
+ return "Jujutsu";
63766
63941
  }
63767
- const parsed = Number.parseInt(metadataValue, 10);
63768
- if (!Number.isFinite(parsed)) {
63769
- return DEFAULT_SPEED_WINDOW_SECONDS;
63942
+ getEditorDisplay(item) {
63943
+ const hideNoJj = item.metadata?.hideNoJj === "true";
63944
+ const modifiers = [];
63945
+ if (hideNoJj) {
63946
+ modifiers.push("hide 'no jj'");
63947
+ }
63948
+ return {
63949
+ displayText: this.getDisplayName(),
63950
+ modifierText: modifiers.length > 0 ? `(${modifiers.join(", ")})` : undefined
63951
+ };
63770
63952
  }
63771
- return clampSpeedWindowSeconds(parsed);
63772
- }
63773
- function isWidgetSpeedWindowEnabled(item) {
63774
- return getWidgetSpeedWindowSeconds(item) > 0;
63775
- }
63776
- function withWidgetSpeedWindowSeconds(item, seconds) {
63777
- return {
63778
- ...item,
63779
- metadata: {
63780
- ...item.metadata ?? {},
63781
- [SPEED_WINDOW_METADATA_KEY]: clampSpeedWindowSeconds(seconds).toString()
63953
+ handleEditorAction(action, item) {
63954
+ if (action === "toggle-nojj") {
63955
+ const currentState = item.metadata?.hideNoJj === "true";
63956
+ return {
63957
+ ...item,
63958
+ metadata: {
63959
+ ...item.metadata,
63960
+ hideNoJj: (!currentState).toString()
63961
+ }
63962
+ };
63782
63963
  }
63783
- };
63964
+ return null;
63965
+ }
63966
+ render(item, context, _settings) {
63967
+ const hideNoJj = item.metadata?.hideNoJj === "true";
63968
+ if (context.isPreview) {
63969
+ return "my-repo";
63970
+ }
63971
+ if (!isInsideJjRepo(context)) {
63972
+ return hideNoJj ? null : "no jj";
63973
+ }
63974
+ const rootDir = runJjArgs(["root"], context);
63975
+ if (rootDir) {
63976
+ return this.getRootDirName(rootDir);
63977
+ }
63978
+ return hideNoJj ? null : "no jj";
63979
+ }
63980
+ getRootDirName(rootDir) {
63981
+ const trimmedRootDir = rootDir.replace(/[\\/]+$/, "");
63982
+ const normalizedRootDir = trimmedRootDir.length > 0 ? trimmedRootDir : rootDir;
63983
+ const parts = normalizedRootDir.split(/[\\/]/).filter(Boolean);
63984
+ const lastPart = parts[parts.length - 1];
63985
+ return lastPart && lastPart.length > 0 ? lastPart : normalizedRootDir;
63986
+ }
63987
+ getCustomKeybinds() {
63988
+ return [
63989
+ { key: "h", label: "(h)ide 'no jj' message", action: "toggle-nojj" }
63990
+ ];
63991
+ }
63992
+ supportsRawValue() {
63993
+ return false;
63994
+ }
63995
+ supportsColors() {
63996
+ return true;
63997
+ }
63784
63998
  }
63785
- var SPEED_WINDOW_METADATA_KEY = "windowSeconds", DEFAULT_SPEED_WINDOW_SECONDS = 0, MIN_SPEED_WINDOW_SECONDS = 0, MAX_SPEED_WINDOW_SECONDS = 120;
63999
+ var init_JjRootDir = __esm(() => {
64000
+ init_jj();
64001
+ });
63786
64002
 
63787
- // src/widgets/shared/speed-widget.tsx
63788
- function getSpeedMetricsForWidget(item, context) {
63789
- if (!isWidgetSpeedWindowEnabled(item)) {
63790
- return context.speedMetrics ?? null;
64003
+ // src/widgets/JjChanges.ts
64004
+ class JjChangesWidget {
64005
+ getDefaultColor() {
64006
+ return "yellow";
63791
64007
  }
63792
- const windowSeconds = getWidgetSpeedWindowSeconds(item);
63793
- return context.windowedSpeedMetrics?.[windowSeconds.toString()] ?? null;
63794
- }
63795
- function calculateSpeed(kind, metrics) {
63796
- if (kind === "input") {
63797
- return calculateInputSpeed(metrics);
64008
+ getDescription() {
64009
+ return "Shows jujutsu changes count (+insertions, -deletions)";
63798
64010
  }
63799
- if (kind === "output") {
63800
- return calculateOutputSpeed(metrics);
64011
+ getDisplayName() {
64012
+ return "JJ Changes";
63801
64013
  }
63802
- return calculateTotalSpeed(metrics);
63803
- }
63804
- function getSpeedWidgetDisplayName(kind) {
63805
- return SPEED_WIDGET_CONFIG[kind].displayName;
63806
- }
63807
- function getSpeedWidgetDescription(kind) {
63808
- return SPEED_WIDGET_CONFIG[kind].description;
63809
- }
63810
- function getSpeedWidgetEditorDisplay(kind, item) {
63811
- const windowSeconds = getWidgetSpeedWindowSeconds(item);
64014
+ getCategory() {
64015
+ return "Jujutsu";
64016
+ }
64017
+ getEditorDisplay(item) {
64018
+ const hideNoJj = item.metadata?.hideNoJj === "true";
64019
+ const modifiers = [];
64020
+ if (hideNoJj) {
64021
+ modifiers.push("hide 'no jj'");
64022
+ }
64023
+ return {
64024
+ displayText: this.getDisplayName(),
64025
+ modifierText: modifiers.length > 0 ? `(${modifiers.join(", ")})` : undefined
64026
+ };
64027
+ }
64028
+ handleEditorAction(action, item) {
64029
+ if (action === "toggle-nojj") {
64030
+ const currentState = item.metadata?.hideNoJj === "true";
64031
+ return {
64032
+ ...item,
64033
+ metadata: {
64034
+ ...item.metadata,
64035
+ hideNoJj: (!currentState).toString()
64036
+ }
64037
+ };
64038
+ }
64039
+ return null;
64040
+ }
64041
+ render(item, context, _settings) {
64042
+ const hideNoJj = item.metadata?.hideNoJj === "true";
64043
+ if (context.isPreview) {
64044
+ return "(+42,-10)";
64045
+ }
64046
+ if (!isInsideJjRepo(context)) {
64047
+ return hideNoJj ? null : "(no jj)";
64048
+ }
64049
+ const changes = this.getJjChanges(context);
64050
+ if (changes) {
64051
+ return `(+${changes.insertions},-${changes.deletions})`;
64052
+ }
64053
+ return hideNoJj ? null : "(no jj)";
64054
+ }
64055
+ getJjChanges(context) {
64056
+ const stat2 = runJjArgs(["diff", "--stat"], context);
64057
+ let totalInsertions = 0;
64058
+ let totalDeletions = 0;
64059
+ if (stat2) {
64060
+ const lines = stat2.split(`
64061
+ `);
64062
+ const summaryLine = lines[lines.length - 1];
64063
+ if (summaryLine) {
64064
+ const insertMatch = /(\d+) insertion/.exec(summaryLine);
64065
+ const deleteMatch = /(\d+) deletion/.exec(summaryLine);
64066
+ totalInsertions += insertMatch?.[1] ? parseInt(insertMatch[1], 10) : 0;
64067
+ totalDeletions += deleteMatch?.[1] ? parseInt(deleteMatch[1], 10) : 0;
64068
+ }
64069
+ }
64070
+ return { insertions: totalInsertions, deletions: totalDeletions };
64071
+ }
64072
+ getCustomKeybinds() {
64073
+ return [
64074
+ { key: "h", label: "(h)ide 'no jj' message", action: "toggle-nojj" }
64075
+ ];
64076
+ }
64077
+ supportsRawValue() {
64078
+ return false;
64079
+ }
64080
+ supportsColors() {
64081
+ return true;
64082
+ }
64083
+ }
64084
+ var init_JjChanges = __esm(() => {
64085
+ init_jj();
64086
+ });
64087
+
64088
+ // src/widgets/JjInsertions.ts
64089
+ class JjInsertionsWidget {
64090
+ getDefaultColor() {
64091
+ return "green";
64092
+ }
64093
+ getDescription() {
64094
+ return "Shows jujutsu insertions count";
64095
+ }
64096
+ getDisplayName() {
64097
+ return "JJ Insertions";
64098
+ }
64099
+ getCategory() {
64100
+ return "Jujutsu";
64101
+ }
64102
+ getEditorDisplay(item) {
64103
+ const hideNoJj = item.metadata?.hideNoJj === "true";
64104
+ const modifiers = [];
64105
+ if (hideNoJj) {
64106
+ modifiers.push("hide 'no jj'");
64107
+ }
64108
+ return {
64109
+ displayText: this.getDisplayName(),
64110
+ modifierText: modifiers.length > 0 ? `(${modifiers.join(", ")})` : undefined
64111
+ };
64112
+ }
64113
+ handleEditorAction(action, item) {
64114
+ if (action === "toggle-nojj") {
64115
+ const currentState = item.metadata?.hideNoJj === "true";
64116
+ return {
64117
+ ...item,
64118
+ metadata: {
64119
+ ...item.metadata,
64120
+ hideNoJj: (!currentState).toString()
64121
+ }
64122
+ };
64123
+ }
64124
+ return null;
64125
+ }
64126
+ render(item, context, _settings) {
64127
+ const hideNoJj = item.metadata?.hideNoJj === "true";
64128
+ if (context.isPreview) {
64129
+ return "+42";
64130
+ }
64131
+ if (!isInsideJjRepo(context)) {
64132
+ return hideNoJj ? null : "(no jj)";
64133
+ }
64134
+ const changes = getJjChangeCounts(context);
64135
+ return `+${changes.insertions}`;
64136
+ }
64137
+ getCustomKeybinds() {
64138
+ return [
64139
+ { key: "h", label: "(h)ide 'no jj' message", action: "toggle-nojj" }
64140
+ ];
64141
+ }
64142
+ supportsRawValue() {
64143
+ return false;
64144
+ }
64145
+ supportsColors(item) {
64146
+ return true;
64147
+ }
64148
+ }
64149
+ var init_JjInsertions = __esm(() => {
64150
+ init_jj();
64151
+ });
64152
+
64153
+ // src/widgets/JjDeletions.ts
64154
+ class JjDeletionsWidget {
64155
+ getDefaultColor() {
64156
+ return "red";
64157
+ }
64158
+ getDescription() {
64159
+ return "Shows jujutsu deletions count";
64160
+ }
64161
+ getDisplayName() {
64162
+ return "JJ Deletions";
64163
+ }
64164
+ getCategory() {
64165
+ return "Jujutsu";
64166
+ }
64167
+ getEditorDisplay(item) {
64168
+ const hideNoJj = item.metadata?.hideNoJj === "true";
64169
+ const modifiers = [];
64170
+ if (hideNoJj) {
64171
+ modifiers.push("hide 'no jj'");
64172
+ }
64173
+ return {
64174
+ displayText: this.getDisplayName(),
64175
+ modifierText: modifiers.length > 0 ? `(${modifiers.join(", ")})` : undefined
64176
+ };
64177
+ }
64178
+ handleEditorAction(action, item) {
64179
+ if (action === "toggle-nojj") {
64180
+ const currentState = item.metadata?.hideNoJj === "true";
64181
+ return {
64182
+ ...item,
64183
+ metadata: {
64184
+ ...item.metadata,
64185
+ hideNoJj: (!currentState).toString()
64186
+ }
64187
+ };
64188
+ }
64189
+ return null;
64190
+ }
64191
+ render(item, context, _settings) {
64192
+ const hideNoJj = item.metadata?.hideNoJj === "true";
64193
+ if (context.isPreview) {
64194
+ return "-10";
64195
+ }
64196
+ if (!isInsideJjRepo(context)) {
64197
+ return hideNoJj ? null : "(no jj)";
64198
+ }
64199
+ const changes = getJjChangeCounts(context);
64200
+ return `-${changes.deletions}`;
64201
+ }
64202
+ getCustomKeybinds() {
64203
+ return [
64204
+ { key: "h", label: "(h)ide 'no jj' message", action: "toggle-nojj" }
64205
+ ];
64206
+ }
64207
+ supportsRawValue() {
64208
+ return false;
64209
+ }
64210
+ supportsColors(item) {
64211
+ return true;
64212
+ }
64213
+ }
64214
+ var init_JjDeletions = __esm(() => {
64215
+ init_jj();
64216
+ });
64217
+
64218
+ // src/widgets/JjDescription.ts
64219
+ class JjDescriptionWidget {
64220
+ getDefaultColor() {
64221
+ return "white";
64222
+ }
64223
+ getDescription() {
64224
+ return "Shows the current jujutsu change description";
64225
+ }
64226
+ getDisplayName() {
64227
+ return "JJ Description";
64228
+ }
64229
+ getCategory() {
64230
+ return "Jujutsu";
64231
+ }
64232
+ getEditorDisplay(item) {
64233
+ const hideNoJj = item.metadata?.hideNoJj === "true";
64234
+ const modifiers = [];
64235
+ if (hideNoJj) {
64236
+ modifiers.push("hide 'no jj'");
64237
+ }
64238
+ return {
64239
+ displayText: this.getDisplayName(),
64240
+ modifierText: modifiers.length > 0 ? `(${modifiers.join(", ")})` : undefined
64241
+ };
64242
+ }
64243
+ handleEditorAction(action, item) {
64244
+ if (action === "toggle-nojj") {
64245
+ const currentState = item.metadata?.hideNoJj === "true";
64246
+ return {
64247
+ ...item,
64248
+ metadata: {
64249
+ ...item.metadata,
64250
+ hideNoJj: (!currentState).toString()
64251
+ }
64252
+ };
64253
+ }
64254
+ return null;
64255
+ }
64256
+ render(item, context, _settings) {
64257
+ const hideNoJj = item.metadata?.hideNoJj === "true";
64258
+ if (context.isPreview) {
64259
+ return "(no description)";
64260
+ }
64261
+ if (!isInsideJjRepo(context)) {
64262
+ return hideNoJj ? null : "no jj";
64263
+ }
64264
+ const description = runJjArgs([
64265
+ "log",
64266
+ "--no-graph",
64267
+ "-r",
64268
+ "@",
64269
+ "-T",
64270
+ "description.first_line()"
64271
+ ], context, true);
64272
+ if (description === null) {
64273
+ return hideNoJj ? null : "no jj";
64274
+ }
64275
+ return description.length > 0 ? description : "(no description)";
64276
+ }
64277
+ getCustomKeybinds() {
64278
+ return [
64279
+ { key: "h", label: "(h)ide 'no jj' message", action: "toggle-nojj" }
64280
+ ];
64281
+ }
64282
+ supportsRawValue() {
64283
+ return false;
64284
+ }
64285
+ supportsColors(item) {
64286
+ return true;
64287
+ }
64288
+ }
64289
+ var init_JjDescription = __esm(() => {
64290
+ init_jj();
64291
+ });
64292
+
64293
+ // src/widgets/JjRevision.ts
64294
+ class JjRevisionWidget {
64295
+ getDefaultColor() {
64296
+ return "green";
64297
+ }
64298
+ getDescription() {
64299
+ return "Shows the current jujutsu change ID (short)";
64300
+ }
64301
+ getDisplayName() {
64302
+ return "JJ Revision";
64303
+ }
64304
+ getCategory() {
64305
+ return "Jujutsu";
64306
+ }
64307
+ getEditorDisplay(item) {
64308
+ const hideNoJj = item.metadata?.hideNoJj === "true";
64309
+ const modifiers = [];
64310
+ if (hideNoJj) {
64311
+ modifiers.push("hide 'no jj'");
64312
+ }
64313
+ return {
64314
+ displayText: this.getDisplayName(),
64315
+ modifierText: modifiers.length > 0 ? `(${modifiers.join(", ")})` : undefined
64316
+ };
64317
+ }
64318
+ handleEditorAction(action, item) {
64319
+ if (action === "toggle-nojj") {
64320
+ const currentState = item.metadata?.hideNoJj === "true";
64321
+ return {
64322
+ ...item,
64323
+ metadata: {
64324
+ ...item.metadata,
64325
+ hideNoJj: (!currentState).toString()
64326
+ }
64327
+ };
64328
+ }
64329
+ return null;
64330
+ }
64331
+ render(item, context, _settings) {
64332
+ const hideNoJj = item.metadata?.hideNoJj === "true";
64333
+ if (context.isPreview) {
64334
+ return item.rawValue ? "kkmpptxz" : " kkmpptxz";
64335
+ }
64336
+ if (!isInsideJjRepo(context)) {
64337
+ return hideNoJj ? null : " no jj";
64338
+ }
64339
+ const changeId = this.getJjRevision(context);
64340
+ if (changeId) {
64341
+ return item.rawValue ? changeId : ` ${changeId}`;
64342
+ }
64343
+ return hideNoJj ? null : " no jj";
64344
+ }
64345
+ getJjRevision(context) {
64346
+ return runJjArgs([
64347
+ "log",
64348
+ "--no-graph",
64349
+ "-r",
64350
+ "@",
64351
+ "-T",
64352
+ "change_id.shortest()"
64353
+ ], context);
64354
+ }
64355
+ getCustomKeybinds() {
64356
+ return [
64357
+ { key: "h", label: "(h)ide 'no jj' message", action: "toggle-nojj" }
64358
+ ];
64359
+ }
64360
+ supportsRawValue() {
64361
+ return true;
64362
+ }
64363
+ supportsColors() {
64364
+ return true;
64365
+ }
64366
+ }
64367
+ var init_JjRevision = __esm(() => {
64368
+ init_jj();
64369
+ });
64370
+
64371
+ // src/widgets/ClaudeAccountEmail.ts
64372
+ import * as fs8 from "fs";
64373
+
64374
+ class ClaudeAccountEmailWidget {
64375
+ getDefaultColor() {
64376
+ return "blue";
64377
+ }
64378
+ getDescription() {
64379
+ return "Displays the email of the currently logged-in Claude account";
64380
+ }
64381
+ getDisplayName() {
64382
+ return "Claude Account Email";
64383
+ }
64384
+ getCategory() {
64385
+ return "Session";
64386
+ }
64387
+ getEditorDisplay(item) {
64388
+ return { displayText: this.getDisplayName() };
64389
+ }
64390
+ render(item, context, settings) {
64391
+ if (context.isPreview) {
64392
+ return item.rawValue ? "you@example.com" : "Account: you@example.com";
64393
+ }
64394
+ try {
64395
+ const content = fs8.readFileSync(getClaudeJsonPath(), "utf-8");
64396
+ const data = JSON.parse(content);
64397
+ const email3 = data.oauthAccount?.emailAddress;
64398
+ if (typeof email3 !== "string" || email3.length === 0) {
64399
+ return null;
64400
+ }
64401
+ return item.rawValue ? email3 : `Account: ${email3}`;
64402
+ } catch {
64403
+ return null;
64404
+ }
64405
+ }
64406
+ supportsRawValue() {
64407
+ return true;
64408
+ }
64409
+ supportsColors(item) {
64410
+ return true;
64411
+ }
64412
+ }
64413
+ var init_ClaudeAccountEmail = __esm(async () => {
64414
+ await init_claude_settings();
64415
+ });
64416
+
64417
+ // src/utils/speed-metrics.ts
64418
+ function calculateOutputSpeed(metrics) {
64419
+ if (metrics.totalDurationMs === 0) {
64420
+ return null;
64421
+ }
64422
+ const seconds = metrics.totalDurationMs / 1000;
64423
+ return metrics.outputTokens / seconds;
64424
+ }
64425
+ function calculateInputSpeed(metrics) {
64426
+ if (metrics.totalDurationMs === 0) {
64427
+ return null;
64428
+ }
64429
+ const seconds = metrics.totalDurationMs / 1000;
64430
+ return metrics.inputTokens / seconds;
64431
+ }
64432
+ function calculateTotalSpeed(metrics) {
64433
+ if (metrics.totalDurationMs === 0) {
64434
+ return null;
64435
+ }
64436
+ const seconds = metrics.totalDurationMs / 1000;
64437
+ return metrics.totalTokens / seconds;
64438
+ }
64439
+ function formatSpeed(tokensPerSec) {
64440
+ if (tokensPerSec === null) {
64441
+ return "—";
64442
+ }
64443
+ if (tokensPerSec >= 1000) {
64444
+ const kValue = tokensPerSec / 1000;
64445
+ return `${kValue.toFixed(1)}k t/s`;
64446
+ }
64447
+ return `${tokensPerSec.toFixed(1)} t/s`;
64448
+ }
64449
+
64450
+ // src/utils/speed-window.ts
64451
+ function clampSpeedWindowSeconds(value) {
64452
+ if (!Number.isFinite(value)) {
64453
+ return DEFAULT_SPEED_WINDOW_SECONDS;
64454
+ }
64455
+ const normalized = Math.trunc(value);
64456
+ if (normalized < MIN_SPEED_WINDOW_SECONDS) {
64457
+ return MIN_SPEED_WINDOW_SECONDS;
64458
+ }
64459
+ if (normalized > MAX_SPEED_WINDOW_SECONDS) {
64460
+ return MAX_SPEED_WINDOW_SECONDS;
64461
+ }
64462
+ return normalized;
64463
+ }
64464
+ function getWidgetSpeedWindowSeconds(item) {
64465
+ const metadataValue = item.metadata?.[SPEED_WINDOW_METADATA_KEY];
64466
+ if (!metadataValue) {
64467
+ return DEFAULT_SPEED_WINDOW_SECONDS;
64468
+ }
64469
+ const parsed = Number.parseInt(metadataValue, 10);
64470
+ if (!Number.isFinite(parsed)) {
64471
+ return DEFAULT_SPEED_WINDOW_SECONDS;
64472
+ }
64473
+ return clampSpeedWindowSeconds(parsed);
64474
+ }
64475
+ function isWidgetSpeedWindowEnabled(item) {
64476
+ return getWidgetSpeedWindowSeconds(item) > 0;
64477
+ }
64478
+ function withWidgetSpeedWindowSeconds(item, seconds) {
64479
+ return {
64480
+ ...item,
64481
+ metadata: {
64482
+ ...item.metadata ?? {},
64483
+ [SPEED_WINDOW_METADATA_KEY]: clampSpeedWindowSeconds(seconds).toString()
64484
+ }
64485
+ };
64486
+ }
64487
+ var SPEED_WINDOW_METADATA_KEY = "windowSeconds", DEFAULT_SPEED_WINDOW_SECONDS = 0, MIN_SPEED_WINDOW_SECONDS = 0, MAX_SPEED_WINDOW_SECONDS = 120;
64488
+
64489
+ // src/widgets/shared/speed-widget.tsx
64490
+ function getSpeedMetricsForWidget(item, context) {
64491
+ if (!isWidgetSpeedWindowEnabled(item)) {
64492
+ return context.speedMetrics ?? null;
64493
+ }
64494
+ const windowSeconds = getWidgetSpeedWindowSeconds(item);
64495
+ return context.windowedSpeedMetrics?.[windowSeconds.toString()] ?? null;
64496
+ }
64497
+ function calculateSpeed(kind, metrics) {
64498
+ if (kind === "input") {
64499
+ return calculateInputSpeed(metrics);
64500
+ }
64501
+ if (kind === "output") {
64502
+ return calculateOutputSpeed(metrics);
64503
+ }
64504
+ return calculateTotalSpeed(metrics);
64505
+ }
64506
+ function getSpeedWidgetDisplayName(kind) {
64507
+ return SPEED_WIDGET_CONFIG[kind].displayName;
64508
+ }
64509
+ function getSpeedWidgetDescription(kind) {
64510
+ return SPEED_WIDGET_CONFIG[kind].description;
64511
+ }
64512
+ function getSpeedWidgetEditorDisplay(kind, item) {
64513
+ const windowSeconds = getWidgetSpeedWindowSeconds(item);
63812
64514
  const modifiers = windowSeconds > 0 ? [`${windowSeconds}s window`] : ["session avg"];
63813
64515
  return {
63814
64516
  displayText: getSpeedWidgetDisplayName(kind),
@@ -64181,16 +64883,222 @@ class SessionNameWidget {
64181
64883
  }
64182
64884
  var init_SessionName = () => {};
64183
64885
 
64184
- // src/widgets/SessionUsage.ts
64185
- class SessionUsageWidget {
64886
+ // src/widgets/shared/progress-bar.ts
64887
+ function makeTimerProgressBar2(percent, width, options) {
64888
+ const clampedPercent = Math.max(0, Math.min(100, percent));
64889
+ const filledWidth = Math.round(clampedPercent / 100 * width);
64890
+ const cursorPos = options?.cursorPercent !== undefined ? Math.min(Math.floor(Math.max(0, Math.min(100, options.cursorPercent)) / 100 * width), width - 1) : -1;
64891
+ let bar = "";
64892
+ for (let i = 0;i < width; i++) {
64893
+ if (i === cursorPos) {
64894
+ bar += "│";
64895
+ } else if (i < filledWidth) {
64896
+ bar += "█";
64897
+ } else {
64898
+ bar += "░";
64899
+ }
64900
+ }
64901
+ return bar;
64902
+ }
64903
+
64904
+ // src/widgets/SessionUsage.ts
64905
+ class SessionUsageWidget {
64906
+ getDefaultColor() {
64907
+ return "brightBlue";
64908
+ }
64909
+ getDescription() {
64910
+ return "Shows daily/session API usage percentage";
64911
+ }
64912
+ getDisplayName() {
64913
+ return "Session Usage";
64914
+ }
64915
+ getCategory() {
64916
+ return "Usage";
64917
+ }
64918
+ getEditorDisplay(item) {
64919
+ return {
64920
+ displayText: this.getDisplayName(),
64921
+ modifierText: getUsageDisplayModifierText(item)
64922
+ };
64923
+ }
64924
+ handleEditorAction(action, item) {
64925
+ if (action === "toggle-progress") {
64926
+ return cycleUsageDisplayMode(item, [], true);
64927
+ }
64928
+ if (action === "toggle-invert") {
64929
+ return toggleUsageInverted(item);
64930
+ }
64931
+ if (action === "toggle-cursor") {
64932
+ return toggleUsageCursor(item);
64933
+ }
64934
+ return null;
64935
+ }
64936
+ render(item, context, settings) {
64937
+ const displayMode = getUsageDisplayMode(item);
64938
+ const inverted = isUsageInverted(item);
64939
+ const showCursor = isUsageCursorEnabled(item);
64940
+ if (context.isPreview) {
64941
+ const previewPercent = 20;
64942
+ const renderedPercent2 = inverted ? 100 - previewPercent : previewPercent;
64943
+ if (isUsageProgressMode(displayMode)) {
64944
+ const width = getUsageProgressBarWidth(displayMode);
64945
+ const progressBar = makeTimerProgressBar2(renderedPercent2, width, showCursor ? { cursorPercent: 50 } : undefined);
64946
+ const progressDisplay = `[${progressBar}] ${renderedPercent2.toFixed(1)}%`;
64947
+ return formatRawOrLabeledValue(item, "Session: ", progressDisplay);
64948
+ }
64949
+ if (isUsageSliderMode(displayMode)) {
64950
+ const slider = makeSliderBar(renderedPercent2, undefined, showCursor ? { cursorPercent: 50 } : undefined);
64951
+ const sliderDisplay = displayMode === "slider" ? `${slider} ${renderedPercent2.toFixed(1)}%` : slider;
64952
+ return formatRawOrLabeledValue(item, "Session: ", sliderDisplay);
64953
+ }
64954
+ return formatRawOrLabeledValue(item, "Session: ", `${previewPercent.toFixed(1)}%`);
64955
+ }
64956
+ const data = context.usageData ?? {};
64957
+ if (data.error)
64958
+ return getUsageErrorMessage(data.error);
64959
+ if (data.sessionUsage === undefined)
64960
+ return null;
64961
+ const percent = Math.max(0, Math.min(100, data.sessionUsage));
64962
+ const renderedPercent = inverted ? 100 - percent : percent;
64963
+ const getCursorOptions = () => {
64964
+ if (!showCursor) {
64965
+ return;
64966
+ }
64967
+ const window2 = resolveUsageWindowWithFallback(data, context.blockMetrics);
64968
+ return window2 ? { cursorPercent: window2.elapsedPercent } : undefined;
64969
+ };
64970
+ if (isUsageProgressMode(displayMode)) {
64971
+ const width = getUsageProgressBarWidth(displayMode);
64972
+ const progressBar = makeTimerProgressBar2(renderedPercent, width, getCursorOptions());
64973
+ const progressDisplay = `[${progressBar}] ${renderedPercent.toFixed(1)}%`;
64974
+ return formatRawOrLabeledValue(item, "Session: ", progressDisplay);
64975
+ }
64976
+ if (isUsageSliderMode(displayMode)) {
64977
+ const slider = makeSliderBar(renderedPercent, undefined, getCursorOptions());
64978
+ const sliderDisplay = displayMode === "slider" ? `${slider} ${renderedPercent.toFixed(1)}%` : slider;
64979
+ return formatRawOrLabeledValue(item, "Session: ", sliderDisplay);
64980
+ }
64981
+ return formatRawOrLabeledValue(item, "Session: ", `${percent.toFixed(1)}%`);
64982
+ }
64983
+ getCustomKeybinds(item) {
64984
+ return getUsagePercentCustomKeybinds(item);
64985
+ }
64986
+ supportsRawValue() {
64987
+ return true;
64988
+ }
64989
+ supportsColors(item) {
64990
+ return true;
64991
+ }
64992
+ }
64993
+ var init_SessionUsage = __esm(async () => {
64994
+ init_usage_display();
64995
+ await init_usage();
64996
+ });
64997
+
64998
+ // src/widgets/WeeklyUsage.ts
64999
+ class WeeklyUsageWidget {
65000
+ getDefaultColor() {
65001
+ return "brightBlue";
65002
+ }
65003
+ getDescription() {
65004
+ return "Shows weekly API usage percentage";
65005
+ }
65006
+ getDisplayName() {
65007
+ return "Weekly Usage";
65008
+ }
65009
+ getCategory() {
65010
+ return "Usage";
65011
+ }
65012
+ getEditorDisplay(item) {
65013
+ return {
65014
+ displayText: this.getDisplayName(),
65015
+ modifierText: getUsageDisplayModifierText(item)
65016
+ };
65017
+ }
65018
+ handleEditorAction(action, item) {
65019
+ if (action === "toggle-progress") {
65020
+ return cycleUsageDisplayMode(item, [], true);
65021
+ }
65022
+ if (action === "toggle-invert") {
65023
+ return toggleUsageInverted(item);
65024
+ }
65025
+ if (action === "toggle-cursor") {
65026
+ return toggleUsageCursor(item);
65027
+ }
65028
+ return null;
65029
+ }
65030
+ render(item, context, settings) {
65031
+ const displayMode = getUsageDisplayMode(item);
65032
+ const inverted = isUsageInverted(item);
65033
+ const showCursor = isUsageCursorEnabled(item);
65034
+ if (context.isPreview) {
65035
+ const previewPercent = 12;
65036
+ const renderedPercent2 = inverted ? 100 - previewPercent : previewPercent;
65037
+ if (isUsageProgressMode(displayMode)) {
65038
+ const width = getUsageProgressBarWidth(displayMode);
65039
+ const progressBar = makeTimerProgressBar2(renderedPercent2, width, showCursor ? { cursorPercent: 50 } : undefined);
65040
+ const progressDisplay = `[${progressBar}] ${renderedPercent2.toFixed(1)}%`;
65041
+ return formatRawOrLabeledValue(item, "Weekly: ", progressDisplay);
65042
+ }
65043
+ if (isUsageSliderMode(displayMode)) {
65044
+ const slider = makeSliderBar(renderedPercent2, undefined, showCursor ? { cursorPercent: 50 } : undefined);
65045
+ const sliderDisplay = displayMode === "slider" ? `${slider} ${renderedPercent2.toFixed(1)}%` : slider;
65046
+ return formatRawOrLabeledValue(item, "Weekly: ", sliderDisplay);
65047
+ }
65048
+ return formatRawOrLabeledValue(item, "Weekly: ", `${previewPercent.toFixed(1)}%`);
65049
+ }
65050
+ const data = context.usageData ?? {};
65051
+ if (data.error)
65052
+ return getUsageErrorMessage(data.error);
65053
+ if (data.weeklyUsage === undefined)
65054
+ return null;
65055
+ const percent = Math.max(0, Math.min(100, data.weeklyUsage));
65056
+ const renderedPercent = inverted ? 100 - percent : percent;
65057
+ const getCursorOptions = () => {
65058
+ if (!showCursor) {
65059
+ return;
65060
+ }
65061
+ const window2 = resolveWeeklyUsageWindow(data);
65062
+ return window2 ? { cursorPercent: window2.elapsedPercent } : undefined;
65063
+ };
65064
+ if (isUsageProgressMode(displayMode)) {
65065
+ const width = getUsageProgressBarWidth(displayMode);
65066
+ const progressBar = makeTimerProgressBar2(renderedPercent, width, getCursorOptions());
65067
+ const progressDisplay = `[${progressBar}] ${renderedPercent.toFixed(1)}%`;
65068
+ return formatRawOrLabeledValue(item, "Weekly: ", progressDisplay);
65069
+ }
65070
+ if (isUsageSliderMode(displayMode)) {
65071
+ const slider = makeSliderBar(renderedPercent, undefined, getCursorOptions());
65072
+ const sliderDisplay = displayMode === "slider" ? `${slider} ${renderedPercent.toFixed(1)}%` : slider;
65073
+ return formatRawOrLabeledValue(item, "Weekly: ", sliderDisplay);
65074
+ }
65075
+ return formatRawOrLabeledValue(item, "Weekly: ", `${percent.toFixed(1)}%`);
65076
+ }
65077
+ getCustomKeybinds(item) {
65078
+ return getUsagePercentCustomKeybinds(item);
65079
+ }
65080
+ supportsRawValue() {
65081
+ return true;
65082
+ }
65083
+ supportsColors(item) {
65084
+ return true;
65085
+ }
65086
+ }
65087
+ var init_WeeklyUsage = __esm(async () => {
65088
+ init_usage_display();
65089
+ await init_usage();
65090
+ });
65091
+
65092
+ // src/widgets/WeeklySonnetUsage.ts
65093
+ class WeeklySonnetUsageWidget {
64186
65094
  getDefaultColor() {
64187
65095
  return "brightBlue";
64188
65096
  }
64189
65097
  getDescription() {
64190
- return "Shows daily/session API usage percentage";
65098
+ return "Shows weekly Sonnet API usage percentage";
64191
65099
  }
64192
65100
  getDisplayName() {
64193
- return "Session Usage";
65101
+ return "Weekly Sonnet Usage";
64194
65102
  }
64195
65103
  getCategory() {
64196
65104
  return "Usage";
@@ -64208,44 +65116,57 @@ class SessionUsageWidget {
64208
65116
  if (action === "toggle-invert") {
64209
65117
  return toggleUsageInverted(item);
64210
65118
  }
65119
+ if (action === "toggle-cursor") {
65120
+ return toggleUsageCursor(item);
65121
+ }
64211
65122
  return null;
64212
65123
  }
64213
65124
  render(item, context, settings) {
64214
65125
  const displayMode = getUsageDisplayMode(item);
64215
65126
  const inverted = isUsageInverted(item);
65127
+ const showCursor = isUsageCursorEnabled(item);
64216
65128
  if (context.isPreview) {
64217
- const previewPercent = 20;
65129
+ const previewPercent = 8;
64218
65130
  const renderedPercent2 = inverted ? 100 - previewPercent : previewPercent;
64219
65131
  if (isUsageProgressMode(displayMode)) {
64220
65132
  const width = getUsageProgressBarWidth(displayMode);
64221
- const progressDisplay = `${makeUsageProgressBar(renderedPercent2, width)} ${renderedPercent2.toFixed(1)}%`;
64222
- return formatRawOrLabeledValue(item, "Session: ", progressDisplay);
65133
+ const progressBar = makeTimerProgressBar2(renderedPercent2, width, showCursor ? { cursorPercent: 50 } : undefined);
65134
+ const progressDisplay = `[${progressBar}] ${renderedPercent2.toFixed(1)}%`;
65135
+ return formatRawOrLabeledValue(item, LABEL, progressDisplay);
64223
65136
  }
64224
65137
  if (isUsageSliderMode(displayMode)) {
64225
- const slider = makeSliderBar(renderedPercent2);
65138
+ const slider = makeSliderBar(renderedPercent2, undefined, showCursor ? { cursorPercent: 50 } : undefined);
64226
65139
  const sliderDisplay = displayMode === "slider" ? `${slider} ${renderedPercent2.toFixed(1)}%` : slider;
64227
- return formatRawOrLabeledValue(item, "Session: ", sliderDisplay);
65140
+ return formatRawOrLabeledValue(item, LABEL, sliderDisplay);
64228
65141
  }
64229
- return formatRawOrLabeledValue(item, "Session: ", `${previewPercent.toFixed(1)}%`);
65142
+ return formatRawOrLabeledValue(item, LABEL, `${previewPercent.toFixed(1)}%`);
64230
65143
  }
64231
65144
  const data = context.usageData ?? {};
64232
65145
  if (data.error)
64233
65146
  return getUsageErrorMessage(data.error);
64234
- if (data.sessionUsage === undefined)
65147
+ if (data.weeklySonnetUsage === undefined)
64235
65148
  return null;
64236
- const percent = Math.max(0, Math.min(100, data.sessionUsage));
65149
+ const percent = Math.max(0, Math.min(100, data.weeklySonnetUsage));
64237
65150
  const renderedPercent = inverted ? 100 - percent : percent;
65151
+ const getCursorOptions = () => {
65152
+ if (!showCursor) {
65153
+ return;
65154
+ }
65155
+ const window2 = resolveWeeklySonnetUsageWindow(data);
65156
+ return window2 ? { cursorPercent: window2.elapsedPercent } : undefined;
65157
+ };
64238
65158
  if (isUsageProgressMode(displayMode)) {
64239
65159
  const width = getUsageProgressBarWidth(displayMode);
64240
- const progressDisplay = `${makeUsageProgressBar(renderedPercent, width)} ${renderedPercent.toFixed(1)}%`;
64241
- return formatRawOrLabeledValue(item, "Session: ", progressDisplay);
65160
+ const progressBar = makeTimerProgressBar2(renderedPercent, width, getCursorOptions());
65161
+ const progressDisplay = `[${progressBar}] ${renderedPercent.toFixed(1)}%`;
65162
+ return formatRawOrLabeledValue(item, LABEL, progressDisplay);
64242
65163
  }
64243
65164
  if (isUsageSliderMode(displayMode)) {
64244
- const slider = makeSliderBar(renderedPercent);
65165
+ const slider = makeSliderBar(renderedPercent, undefined, getCursorOptions());
64245
65166
  const sliderDisplay = displayMode === "slider" ? `${slider} ${renderedPercent.toFixed(1)}%` : slider;
64246
- return formatRawOrLabeledValue(item, "Session: ", sliderDisplay);
65167
+ return formatRawOrLabeledValue(item, LABEL, sliderDisplay);
64247
65168
  }
64248
- return formatRawOrLabeledValue(item, "Session: ", `${percent.toFixed(1)}%`);
65169
+ return formatRawOrLabeledValue(item, LABEL, `${percent.toFixed(1)}%`);
64249
65170
  }
64250
65171
  getCustomKeybinds(item) {
64251
65172
  return getUsagePercentCustomKeybinds(item);
@@ -64257,21 +65178,22 @@ class SessionUsageWidget {
64257
65178
  return true;
64258
65179
  }
64259
65180
  }
64260
- var init_SessionUsage = __esm(async () => {
65181
+ var LABEL = "Weekly Sonnet: ";
65182
+ var init_WeeklySonnetUsage = __esm(async () => {
64261
65183
  init_usage_display();
64262
65184
  await init_usage();
64263
65185
  });
64264
65186
 
64265
- // src/widgets/WeeklyUsage.ts
64266
- class WeeklyUsageWidget {
65187
+ // src/widgets/WeeklyOpusUsage.ts
65188
+ class WeeklyOpusUsageWidget {
64267
65189
  getDefaultColor() {
64268
65190
  return "brightBlue";
64269
65191
  }
64270
65192
  getDescription() {
64271
- return "Shows weekly API usage percentage";
65193
+ return "Shows weekly Opus API usage percentage";
64272
65194
  }
64273
65195
  getDisplayName() {
64274
- return "Weekly Usage";
65196
+ return "Weekly Opus Usage";
64275
65197
  }
64276
65198
  getCategory() {
64277
65199
  return "Usage";
@@ -64289,44 +65211,57 @@ class WeeklyUsageWidget {
64289
65211
  if (action === "toggle-invert") {
64290
65212
  return toggleUsageInverted(item);
64291
65213
  }
65214
+ if (action === "toggle-cursor") {
65215
+ return toggleUsageCursor(item);
65216
+ }
64292
65217
  return null;
64293
65218
  }
64294
65219
  render(item, context, settings) {
64295
65220
  const displayMode = getUsageDisplayMode(item);
64296
65221
  const inverted = isUsageInverted(item);
65222
+ const showCursor = isUsageCursorEnabled(item);
64297
65223
  if (context.isPreview) {
64298
- const previewPercent = 12;
65224
+ const previewPercent = 4;
64299
65225
  const renderedPercent2 = inverted ? 100 - previewPercent : previewPercent;
64300
65226
  if (isUsageProgressMode(displayMode)) {
64301
65227
  const width = getUsageProgressBarWidth(displayMode);
64302
- const progressDisplay = `${makeUsageProgressBar(renderedPercent2, width)} ${renderedPercent2.toFixed(1)}%`;
64303
- return formatRawOrLabeledValue(item, "Weekly: ", progressDisplay);
65228
+ const progressBar = makeTimerProgressBar2(renderedPercent2, width, showCursor ? { cursorPercent: 50 } : undefined);
65229
+ const progressDisplay = `[${progressBar}] ${renderedPercent2.toFixed(1)}%`;
65230
+ return formatRawOrLabeledValue(item, LABEL2, progressDisplay);
64304
65231
  }
64305
65232
  if (isUsageSliderMode(displayMode)) {
64306
- const slider = makeSliderBar(renderedPercent2);
65233
+ const slider = makeSliderBar(renderedPercent2, undefined, showCursor ? { cursorPercent: 50 } : undefined);
64307
65234
  const sliderDisplay = displayMode === "slider" ? `${slider} ${renderedPercent2.toFixed(1)}%` : slider;
64308
- return formatRawOrLabeledValue(item, "Weekly: ", sliderDisplay);
65235
+ return formatRawOrLabeledValue(item, LABEL2, sliderDisplay);
64309
65236
  }
64310
- return formatRawOrLabeledValue(item, "Weekly: ", `${previewPercent.toFixed(1)}%`);
65237
+ return formatRawOrLabeledValue(item, LABEL2, `${previewPercent.toFixed(1)}%`);
64311
65238
  }
64312
65239
  const data = context.usageData ?? {};
64313
65240
  if (data.error)
64314
65241
  return getUsageErrorMessage(data.error);
64315
- if (data.weeklyUsage === undefined)
65242
+ if (data.weeklyOpusUsage === undefined)
64316
65243
  return null;
64317
- const percent = Math.max(0, Math.min(100, data.weeklyUsage));
65244
+ const percent = Math.max(0, Math.min(100, data.weeklyOpusUsage));
64318
65245
  const renderedPercent = inverted ? 100 - percent : percent;
65246
+ const getCursorOptions = () => {
65247
+ if (!showCursor) {
65248
+ return;
65249
+ }
65250
+ const window2 = resolveWeeklyOpusUsageWindow(data);
65251
+ return window2 ? { cursorPercent: window2.elapsedPercent } : undefined;
65252
+ };
64319
65253
  if (isUsageProgressMode(displayMode)) {
64320
65254
  const width = getUsageProgressBarWidth(displayMode);
64321
- const progressDisplay = `${makeUsageProgressBar(renderedPercent, width)} ${renderedPercent.toFixed(1)}%`;
64322
- return formatRawOrLabeledValue(item, "Weekly: ", progressDisplay);
65255
+ const progressBar = makeTimerProgressBar2(renderedPercent, width, getCursorOptions());
65256
+ const progressDisplay = `[${progressBar}] ${renderedPercent.toFixed(1)}%`;
65257
+ return formatRawOrLabeledValue(item, LABEL2, progressDisplay);
64323
65258
  }
64324
65259
  if (isUsageSliderMode(displayMode)) {
64325
- const slider = makeSliderBar(renderedPercent);
65260
+ const slider = makeSliderBar(renderedPercent, undefined, getCursorOptions());
64326
65261
  const sliderDisplay = displayMode === "slider" ? `${slider} ${renderedPercent.toFixed(1)}%` : slider;
64327
- return formatRawOrLabeledValue(item, "Weekly: ", sliderDisplay);
65262
+ return formatRawOrLabeledValue(item, LABEL2, sliderDisplay);
64328
65263
  }
64329
- return formatRawOrLabeledValue(item, "Weekly: ", `${percent.toFixed(1)}%`);
65264
+ return formatRawOrLabeledValue(item, LABEL2, `${percent.toFixed(1)}%`);
64330
65265
  }
64331
65266
  getCustomKeybinds(item) {
64332
65267
  return getUsagePercentCustomKeybinds(item);
@@ -64338,7 +65273,8 @@ class WeeklyUsageWidget {
64338
65273
  return true;
64339
65274
  }
64340
65275
  }
64341
- var init_WeeklyUsage = __esm(async () => {
65276
+ var LABEL2 = "Weekly Opus: ";
65277
+ var init_WeeklyOpusUsage = __esm(async () => {
64342
65278
  init_usage_display();
64343
65279
  await init_usage();
64344
65280
  });
@@ -64795,7 +65731,7 @@ var init_timezone_editor = __esm(async () => {
64795
65731
  });
64796
65732
 
64797
65733
  // src/widgets/BlockResetTimer.ts
64798
- function makeTimerProgressBar2(percent, width) {
65734
+ function makeTimerProgressBar3(percent, width) {
64799
65735
  const clampedPercent = Math.max(0, Math.min(100, percent));
64800
65736
  const filledWidth = Math.floor(clampedPercent / 100 * width);
64801
65737
  const emptyWidth = width - filledWidth;
@@ -64823,7 +65759,7 @@ class BlockResetTimerWidget {
64823
65759
  }
64824
65760
  handleEditorAction(action, item) {
64825
65761
  if (action === "toggle-progress") {
64826
- return cycleUsageDisplayMode(item, ["compact", "absolute"]);
65762
+ return cycleUsageDisplayMode(item, ["compact", "absolute"], true);
64827
65763
  }
64828
65764
  if (action === "toggle-invert") {
64829
65765
  return toggleUsageInverted(item);
@@ -64848,9 +65784,14 @@ class BlockResetTimerWidget {
64848
65784
  const previewPercent = inverted ? 90 : 10;
64849
65785
  if (isUsageProgressMode(displayMode)) {
64850
65786
  const barWidth = getUsageProgressBarWidth(displayMode);
64851
- const progressBar = makeTimerProgressBar2(previewPercent, barWidth);
65787
+ const progressBar = makeTimerProgressBar3(previewPercent, barWidth);
64852
65788
  return formatRawOrLabeledValue(item, "Reset ", `[${progressBar}] ${previewPercent.toFixed(1)}%`);
64853
65789
  }
65790
+ if (isUsageSliderMode(displayMode)) {
65791
+ const slider = makeSliderBar(previewPercent);
65792
+ const sliderDisplay = displayMode === "slider" ? `${slider} ${previewPercent.toFixed(1)}%` : slider;
65793
+ return formatRawOrLabeledValue(item, "Reset ", sliderDisplay);
65794
+ }
64854
65795
  if (dateMode) {
64855
65796
  const resetAt = formatUsageResetAt(BLOCK_RESET_PREVIEW_AT, compact2, getUsageTimezone(item), getUsageLocale(item), isUsage12HourClock(item));
64856
65797
  return formatRawOrLabeledValue(item, "Reset: ", resetAt ?? (compact2 ? "03-12 08:30Z" : "2026-03-12 08:30 UTC"));
@@ -64868,10 +65809,16 @@ class BlockResetTimerWidget {
64868
65809
  if (isUsageProgressMode(displayMode)) {
64869
65810
  const barWidth = getUsageProgressBarWidth(displayMode);
64870
65811
  const percent = inverted ? window2.remainingPercent : window2.elapsedPercent;
64871
- const progressBar = makeTimerProgressBar2(percent, barWidth);
65812
+ const progressBar = makeTimerProgressBar3(percent, barWidth);
64872
65813
  const percentage = percent.toFixed(1);
64873
65814
  return formatRawOrLabeledValue(item, "Reset ", `[${progressBar}] ${percentage}%`);
64874
65815
  }
65816
+ if (isUsageSliderMode(displayMode)) {
65817
+ const percent = inverted ? window2.remainingPercent : window2.elapsedPercent;
65818
+ const slider = makeSliderBar(percent);
65819
+ const sliderDisplay = displayMode === "slider" ? `${slider} ${percent.toFixed(1)}%` : slider;
65820
+ return formatRawOrLabeledValue(item, "Reset ", sliderDisplay);
65821
+ }
64875
65822
  if (dateMode) {
64876
65823
  const timezone = getUsageTimezone(item);
64877
65824
  const locale = getUsageLocale(item);
@@ -64918,7 +65865,7 @@ var init_BlockResetTimer = __esm(async () => {
64918
65865
  });
64919
65866
 
64920
65867
  // src/widgets/WeeklyResetTimer.ts
64921
- function makeTimerProgressBar3(percent, width) {
65868
+ function makeTimerProgressBar4(percent, width) {
64922
65869
  const clampedPercent = Math.max(0, Math.min(100, percent));
64923
65870
  const filledWidth = Math.floor(clampedPercent / 100 * width);
64924
65871
  const emptyWidth = width - filledWidth;
@@ -64933,16 +65880,21 @@ function toggleWeeklyResetHoursOnly(item) {
64933
65880
  function getWeeklyResetModifierText(item) {
64934
65881
  const displayMode = getUsageDisplayMode(item);
64935
65882
  const dateMode = isUsageDateMode(item);
65883
+ const isBarMode = isUsageProgressMode(displayMode) || isUsageSliderMode(displayMode);
64936
65884
  const modifiers = [];
64937
65885
  if (displayMode === "progress") {
64938
65886
  modifiers.push("long bar");
64939
65887
  } else if (displayMode === "progress-short") {
64940
65888
  modifiers.push("medium bar");
65889
+ } else if (displayMode === "slider") {
65890
+ modifiers.push("short bar");
65891
+ } else if (displayMode === "slider-only") {
65892
+ modifiers.push("short bar only");
64941
65893
  }
64942
65894
  if (isUsageInverted(item)) {
64943
65895
  modifiers.push("inverted");
64944
65896
  }
64945
- if (!isUsageProgressMode(displayMode)) {
65897
+ if (!isBarMode) {
64946
65898
  if (isUsageCompact(item)) {
64947
65899
  modifiers.push("compact");
64948
65900
  }
@@ -64956,11 +65908,11 @@ function getWeeklyResetModifierText(item) {
64956
65908
  }
64957
65909
  }
64958
65910
  const timezoneModifier = getUsageTimezoneModifier(item);
64959
- if (!isUsageProgressMode(displayMode) && dateMode && timezoneModifier) {
65911
+ if (!isBarMode && dateMode && timezoneModifier) {
64960
65912
  modifiers.push(timezoneModifier);
64961
65913
  }
64962
65914
  const localeModifier = getUsageLocaleModifier(item);
64963
- if (!isUsageProgressMode(displayMode) && dateMode && localeModifier) {
65915
+ if (!isBarMode && dateMode && localeModifier) {
64964
65916
  modifiers.push(localeModifier);
64965
65917
  }
64966
65918
  return makeModifierText(modifiers);
@@ -64987,7 +65939,7 @@ class WeeklyResetTimerWidget {
64987
65939
  }
64988
65940
  handleEditorAction(action, item) {
64989
65941
  if (action === "toggle-progress") {
64990
- return cycleUsageDisplayMode(item, ["compact", "hours", "absolute"]);
65942
+ return cycleUsageDisplayMode(item, ["compact", "hours", "absolute"], true);
64991
65943
  }
64992
65944
  if (action === "toggle-invert") {
64993
65945
  return toggleUsageInverted(item);
@@ -65016,9 +65968,14 @@ class WeeklyResetTimerWidget {
65016
65968
  const previewPercent = inverted ? 90 : 10;
65017
65969
  if (isUsageProgressMode(displayMode)) {
65018
65970
  const barWidth = getUsageProgressBarWidth(displayMode);
65019
- const progressBar = makeTimerProgressBar3(previewPercent, barWidth);
65971
+ const progressBar = makeTimerProgressBar4(previewPercent, barWidth);
65020
65972
  return formatRawOrLabeledValue(item, "Weekly Reset ", `[${progressBar}] ${previewPercent.toFixed(1)}%`);
65021
65973
  }
65974
+ if (isUsageSliderMode(displayMode)) {
65975
+ const slider = makeSliderBar(previewPercent);
65976
+ const sliderDisplay = displayMode === "slider" ? `${slider} ${previewPercent.toFixed(1)}%` : slider;
65977
+ return formatRawOrLabeledValue(item, "Weekly Reset ", sliderDisplay);
65978
+ }
65022
65979
  if (dateMode) {
65023
65980
  const resetAt = formatUsageResetAt(WEEKLY_RESET_PREVIEW_AT, compact2, getUsageTimezone(item), getUsageLocale(item), isUsage12HourClock(item));
65024
65981
  return formatRawOrLabeledValue(item, "Weekly Reset: ", resetAt ?? (compact2 ? "03-15 08:30Z" : "2026-03-15 08:30 UTC"));
@@ -65036,10 +65993,16 @@ class WeeklyResetTimerWidget {
65036
65993
  if (isUsageProgressMode(displayMode)) {
65037
65994
  const barWidth = getUsageProgressBarWidth(displayMode);
65038
65995
  const percent = inverted ? window2.remainingPercent : window2.elapsedPercent;
65039
- const progressBar = makeTimerProgressBar3(percent, barWidth);
65996
+ const progressBar = makeTimerProgressBar4(percent, barWidth);
65040
65997
  const percentage = percent.toFixed(1);
65041
65998
  return formatRawOrLabeledValue(item, "Weekly Reset ", `[${progressBar}] ${percentage}%`);
65042
65999
  }
66000
+ if (isUsageSliderMode(displayMode)) {
66001
+ const percent = inverted ? window2.remainingPercent : window2.elapsedPercent;
66002
+ const slider = makeSliderBar(percent);
66003
+ const sliderDisplay = displayMode === "slider" ? `${slider} ${percent.toFixed(1)}%` : slider;
66004
+ return formatRawOrLabeledValue(item, "Weekly Reset ", sliderDisplay);
66005
+ }
65043
66006
  if (dateMode) {
65044
66007
  const timezone = getUsageTimezone(item);
65045
66008
  const locale = getUsageLocale(item);
@@ -65058,7 +66021,9 @@ class WeeklyResetTimerWidget {
65058
66021
  includeLocale: true,
65059
66022
  includeTimezone: true
65060
66023
  });
65061
- if (!item || !isUsageProgressMode(getUsageDisplayMode(item)) && !isUsageDateMode(item)) {
66024
+ const mode = item ? getUsageDisplayMode(item) : "time";
66025
+ const isBarMode = isUsageProgressMode(mode) || isUsageSliderMode(mode);
66026
+ if (!item || !isBarMode && !isUsageDateMode(item)) {
65062
66027
  keybinds.push({ key: "h", label: "(h)ours only", action: "toggle-hours" });
65063
66028
  }
65064
66029
  return keybinds;
@@ -66053,6 +67018,141 @@ var init_CompactionCounter = __esm(() => {
66053
67018
  FORMATS2 = ["icon-space-number", "text-and-number", "number"];
66054
67019
  });
66055
67020
 
67021
+ // src/widgets/VoiceStatus.ts
67022
+ function getFormat3(item) {
67023
+ const f = item.metadata?.format;
67024
+ return FORMATS3.includes(f ?? "") ? f : DEFAULT_FORMAT3;
67025
+ }
67026
+ function setFormat3(item, format) {
67027
+ if (format === DEFAULT_FORMAT3) {
67028
+ const { format: removedFormat, ...restMetadata } = item.metadata ?? {};
67029
+ return {
67030
+ ...item,
67031
+ metadata: Object.keys(restMetadata).length > 0 ? restMetadata : undefined
67032
+ };
67033
+ }
67034
+ return {
67035
+ ...item,
67036
+ metadata: {
67037
+ ...item.metadata ?? {},
67038
+ format
67039
+ }
67040
+ };
67041
+ }
67042
+ function isNerdFontEnabled3(item) {
67043
+ return item.metadata?.[NERD_FONT_METADATA_KEY3] === "true";
67044
+ }
67045
+ function toggleNerdFont3(item) {
67046
+ if (!isNerdFontEnabled3(item)) {
67047
+ return {
67048
+ ...item,
67049
+ metadata: {
67050
+ ...item.metadata ?? {},
67051
+ [NERD_FONT_METADATA_KEY3]: "true"
67052
+ }
67053
+ };
67054
+ }
67055
+ const { [NERD_FONT_METADATA_KEY3]: removedNerdFont, ...restMetadata } = item.metadata ?? {};
67056
+ return {
67057
+ ...item,
67058
+ metadata: Object.keys(restMetadata).length > 0 ? restMetadata : undefined
67059
+ };
67060
+ }
67061
+ function formatStatus(enabled, format, nerdFont) {
67062
+ const stateText = enabled ? "on" : "off";
67063
+ const stateDot = enabled ? STATE_DOT_ON : STATE_DOT_OFF;
67064
+ const icon = nerdFont ? enabled ? MIC_NERD_FONT : MIC_SLASH_NERD_FONT : MIC_EMOJI;
67065
+ switch (format) {
67066
+ case "icon":
67067
+ return nerdFont ? icon : `${icon} ${stateDot}`;
67068
+ case "icon-text":
67069
+ return `${icon} ${stateText}`;
67070
+ case "text":
67071
+ return stateText;
67072
+ case "word":
67073
+ return `voice ${stateText}`;
67074
+ }
67075
+ }
67076
+ function resolveVoiceConfigCwd(context) {
67077
+ const candidates = [
67078
+ context.data?.workspace?.project_dir,
67079
+ context.data?.cwd,
67080
+ context.data?.workspace?.current_dir
67081
+ ];
67082
+ return candidates.find((candidate) => typeof candidate === "string" && candidate.trim().length > 0);
67083
+ }
67084
+
67085
+ class VoiceStatusWidget {
67086
+ getDefaultColor() {
67087
+ return "magenta";
67088
+ }
67089
+ getDescription() {
67090
+ return "Shows whether Claude Code voice input is enabled";
67091
+ }
67092
+ getDisplayName() {
67093
+ return "Voice Status";
67094
+ }
67095
+ getCategory() {
67096
+ return "Core";
67097
+ }
67098
+ getEditorDisplay(item) {
67099
+ const modifiers = [getFormat3(item)];
67100
+ if (isNerdFontEnabled3(item)) {
67101
+ modifiers.push("nerd font");
67102
+ }
67103
+ return {
67104
+ displayText: this.getDisplayName(),
67105
+ modifierText: `(${modifiers.join(", ")})`
67106
+ };
67107
+ }
67108
+ handleEditorAction(action, item) {
67109
+ if (action === CYCLE_FORMAT_ACTION3) {
67110
+ const currentFormat = getFormat3(item);
67111
+ const nextFormat = FORMATS3[(FORMATS3.indexOf(currentFormat) + 1) % FORMATS3.length] ?? DEFAULT_FORMAT3;
67112
+ return setFormat3(item, nextFormat);
67113
+ }
67114
+ if (action === TOGGLE_NERD_FONT_ACTION3) {
67115
+ return toggleNerdFont3(item);
67116
+ }
67117
+ return null;
67118
+ }
67119
+ render(item, context, _settings) {
67120
+ const format = getFormat3(item);
67121
+ const nerdFont = isNerdFontEnabled3(item);
67122
+ if (context.isPreview) {
67123
+ if (item.rawValue) {
67124
+ return "on";
67125
+ }
67126
+ return formatStatus(true, format, nerdFont);
67127
+ }
67128
+ const config2 = getVoiceConfig(resolveVoiceConfigCwd(context));
67129
+ if (config2 === null) {
67130
+ return null;
67131
+ }
67132
+ if (item.rawValue) {
67133
+ return config2.enabled ? "on" : "off";
67134
+ }
67135
+ return formatStatus(config2.enabled, format, nerdFont);
67136
+ }
67137
+ getCustomKeybinds() {
67138
+ return [
67139
+ { key: "f", label: "(f)ormat", action: CYCLE_FORMAT_ACTION3 },
67140
+ { key: "n", label: "(n)erd font", action: TOGGLE_NERD_FONT_ACTION3 }
67141
+ ];
67142
+ }
67143
+ supportsRawValue() {
67144
+ return true;
67145
+ }
67146
+ supportsColors(_item) {
67147
+ return true;
67148
+ }
67149
+ }
67150
+ var MIC_EMOJI = "\uD83C\uDFA4", MIC_NERD_FONT = "", MIC_SLASH_NERD_FONT = "", STATE_DOT_OFF = "○", STATE_DOT_ON = "◉", FORMATS3, DEFAULT_FORMAT3 = "icon", CYCLE_FORMAT_ACTION3 = "cycle-format", TOGGLE_NERD_FONT_ACTION3 = "toggle-nerd-font", NERD_FONT_METADATA_KEY3 = "nerdFont";
67151
+ var init_VoiceStatus = __esm(async () => {
67152
+ await init_claude_settings();
67153
+ FORMATS3 = ["icon", "icon-text", "text", "word"];
67154
+ });
67155
+
66056
67156
  // src/widgets/index.ts
66057
67157
  var init_widgets = __esm(async () => {
66058
67158
  init_GitBranch();
@@ -66083,6 +67183,14 @@ var init_widgets = __esm(async () => {
66083
67183
  init_ContextPercentage();
66084
67184
  init_ContextPercentageUsable();
66085
67185
  init_TerminalWidth();
67186
+ init_JjBookmarks();
67187
+ init_JjWorkspace();
67188
+ init_JjRootDir();
67189
+ init_JjChanges();
67190
+ init_JjInsertions();
67191
+ init_JjDeletions();
67192
+ init_JjDescription();
67193
+ init_JjRevision();
66086
67194
  init_FreeMemory();
66087
67195
  init_SessionName();
66088
67196
  init_VimMode();
@@ -66105,12 +67213,15 @@ var init_widgets = __esm(async () => {
66105
67213
  init_TotalSpeed(),
66106
67214
  init_SessionUsage(),
66107
67215
  init_WeeklyUsage(),
67216
+ init_WeeklySonnetUsage(),
67217
+ init_WeeklyOpusUsage(),
66108
67218
  init_BlockResetTimer(),
66109
67219
  init_WeeklyResetTimer(),
66110
67220
  init_ContextBar(),
66111
67221
  init_Link(),
66112
67222
  init_Skills(),
66113
- init_ThinkingEffort()
67223
+ init_ThinkingEffort(),
67224
+ init_VoiceStatus()
66114
67225
  ]);
66115
67226
  });
66116
67227
 
@@ -66146,6 +67257,14 @@ var init_widget_manifest = __esm(async () => {
66146
67257
  { type: "git-upstream-repo", create: () => new GitUpstreamRepoWidget },
66147
67258
  { type: "git-upstream-owner-repo", create: () => new GitUpstreamOwnerRepoWidget },
66148
67259
  { type: "git-is-fork", create: () => new GitIsForkWidget },
67260
+ { type: "jj-bookmarks", create: () => new JjBookmarksWidget },
67261
+ { type: "jj-workspace", create: () => new JjWorkspaceWidget },
67262
+ { type: "jj-root-dir", create: () => new JjRootDirWidget },
67263
+ { type: "jj-changes", create: () => new JjChangesWidget },
67264
+ { type: "jj-insertions", create: () => new JjInsertionsWidget },
67265
+ { type: "jj-deletions", create: () => new JjDeletionsWidget },
67266
+ { type: "jj-description", create: () => new JjDescriptionWidget },
67267
+ { type: "jj-revision", create: () => new JjRevisionWidget },
66149
67268
  { type: "current-working-dir", create: () => new CurrentWorkingDirWidget },
66150
67269
  { type: "tokens-input", create: () => new TokensInputWidget },
66151
67270
  { type: "tokens-output", create: () => new TokensOutputWidget },
@@ -66173,12 +67292,15 @@ var init_widget_manifest = __esm(async () => {
66173
67292
  { type: "free-memory", create: () => new FreeMemoryWidget },
66174
67293
  { type: "session-usage", create: () => new SessionUsageWidget },
66175
67294
  { type: "weekly-usage", create: () => new WeeklyUsageWidget },
67295
+ { type: "weekly-sonnet-usage", create: () => new WeeklySonnetUsageWidget },
67296
+ { type: "weekly-opus-usage", create: () => new WeeklyOpusUsageWidget },
66176
67297
  { type: "reset-timer", create: () => new BlockResetTimerWidget },
66177
67298
  { type: "weekly-reset-timer", create: () => new WeeklyResetTimerWidget },
66178
67299
  { type: "context-bar", create: () => new ContextBarWidget },
66179
67300
  { type: "skills", create: () => new SkillsWidget },
66180
67301
  { type: "thinking-effort", create: () => new ThinkingEffortWidget },
66181
67302
  { type: "vim-mode", create: () => new VimModeWidget },
67303
+ { type: "voice-status", create: () => new VoiceStatusWidget },
66182
67304
  { type: "worktree-mode", create: () => new GitWorktreeModeWidget },
66183
67305
  { type: "worktree-name", create: () => new GitWorktreeNameWidget },
66184
67306
  { type: "worktree-branch", create: () => new GitWorktreeBranchWidget },
@@ -66290,6 +67412,9 @@ __export(exports_hooks, {
66290
67412
  syncWidgetHooks: () => syncWidgetHooks,
66291
67413
  removeManagedHooks: () => removeManagedHooks
66292
67414
  });
67415
+ function hasWidgetHooks(widget) {
67416
+ return Boolean(widget && "getHooks" in widget && typeof widget.getHooks === "function");
67417
+ }
66293
67418
  function stripManagedHooks(hooks) {
66294
67419
  for (const event of Object.keys(hooks)) {
66295
67420
  hooks[event] = (hooks[event] ?? []).filter((entry) => entry._tag !== HOOK_TAG);
@@ -66304,7 +67429,7 @@ function getActiveHookDefs(settings) {
66304
67429
  for (const line of settings.lines) {
66305
67430
  for (const item of line) {
66306
67431
  const widget = getWidget(item.type);
66307
- if (!widget?.getHooks) {
67432
+ if (!hasWidgetHooks(widget)) {
66308
67433
  continue;
66309
67434
  }
66310
67435
  for (const hook of widget.getHooks()) {
@@ -66731,8 +67856,53 @@ async function setRefreshInterval(interval) {
66731
67856
  }
66732
67857
  await saveClaudeSettings(settings);
66733
67858
  }
66734
- var readFile4, writeFile2, mkdir2, CCSTATUSLINE_COMMANDS;
67859
+ function getVoiceConfigCandidatePathsByPriority(cwd2) {
67860
+ const userDir = getClaudeConfigDir();
67861
+ const projectDir = path8.join(cwd2, ".claude");
67862
+ const candidates = [
67863
+ path8.join(projectDir, "settings.local.json"),
67864
+ path8.join(projectDir, "settings.json"),
67865
+ path8.join(userDir, "settings.local.json"),
67866
+ path8.join(userDir, "settings.json")
67867
+ ];
67868
+ return Array.from(new Set(candidates));
67869
+ }
67870
+ function tryReadVoiceLayer(filePath) {
67871
+ let content;
67872
+ try {
67873
+ content = fs11.readFileSync(filePath, "utf-8");
67874
+ } catch (error48) {
67875
+ const isMissing = error48.code === "ENOENT";
67876
+ return { fileExisted: !isMissing, enabled: undefined };
67877
+ }
67878
+ try {
67879
+ const parsed = JSON.parse(content);
67880
+ const voice = parsed.voice;
67881
+ if (voice === undefined || voice === null) {
67882
+ return { fileExisted: true, enabled: undefined };
67883
+ }
67884
+ const result2 = VoiceConfigSchema.safeParse(voice);
67885
+ return { fileExisted: true, enabled: result2.success ? result2.data.enabled : undefined };
67886
+ } catch {
67887
+ return { fileExisted: true, enabled: undefined };
67888
+ }
67889
+ }
67890
+ function getVoiceConfig(cwd2 = process.cwd()) {
67891
+ let anyFileExisted = false;
67892
+ for (const filePath of getVoiceConfigCandidatePathsByPriority(cwd2)) {
67893
+ const layer = tryReadVoiceLayer(filePath);
67894
+ if (layer.fileExisted) {
67895
+ anyFileExisted = true;
67896
+ }
67897
+ if (layer.enabled !== undefined) {
67898
+ return { enabled: layer.enabled };
67899
+ }
67900
+ }
67901
+ return anyFileExisted ? { enabled: false } : null;
67902
+ }
67903
+ var readFile4, writeFile2, mkdir2, CCSTATUSLINE_COMMANDS, VoiceConfigSchema;
66735
67904
  var init_claude_settings = __esm(async () => {
67905
+ init_zod();
66736
67906
  init_Settings();
66737
67907
  await init_config();
66738
67908
  readFile4 = fs11.promises.readFile;
@@ -66743,6 +67913,7 @@ var init_claude_settings = __esm(async () => {
66743
67913
  BUNX: "bunx -y ccstatusline@latest",
66744
67914
  SELF_MANAGED: "ccstatusline"
66745
67915
  };
67916
+ VoiceConfigSchema = exports_external.object({ enabled: exports_external.boolean().optional() });
66746
67917
  });
66747
67918
 
66748
67919
  // node_modules/pluralize/pluralize.js
@@ -70855,7 +72026,7 @@ var PowerlineSeparatorEditor = ({
70855
72026
  newInvertBgs[selectedIndex] = isLeftFacing;
70856
72027
  }
70857
72028
  updateSeparators(newSeparators, mode === "separator" ? newInvertBgs : undefined);
70858
- } else if ((input === "a" || input === "A") && (mode === "separator" || separators.length < 3)) {
72029
+ } else if (input === "a" || input === "A") {
70859
72030
  const newSeparators = [...separators];
70860
72031
  const newInvertBgs = mode === "separator" ? [...invertBgs] : [];
70861
72032
  const defaultChar = presetSeparators[0]?.char ?? "";
@@ -70875,7 +72046,7 @@ var PowerlineSeparatorEditor = ({
70875
72046
  updateSeparators(newSeparators, newInvertBgs);
70876
72047
  setSelectedIndex(selectedIndex + 1);
70877
72048
  }
70878
- } else if ((input === "i" || input === "I") && (mode === "separator" || separators.length < 3)) {
72049
+ } else if (input === "i" || input === "I") {
70879
72050
  const newSeparators = [...separators];
70880
72051
  const newInvertBgs = mode === "separator" ? [...invertBgs] : [];
70881
72052
  const defaultChar = presetSeparators[0]?.char ?? "";
@@ -70927,7 +72098,6 @@ var PowerlineSeparatorEditor = ({
70927
72098
  return "Powerline End Cap Configuration";
70928
72099
  }
70929
72100
  };
70930
- const canAdd = mode === "separator" || separators.length < 3;
70931
72101
  const canDelete = mode !== "separator" || separators.length > 1;
70932
72102
  return /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Box_default, {
70933
72103
  flexDirection: "column",
@@ -70979,7 +72149,7 @@ var PowerlineSeparatorEditor = ({
70979
72149
  /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Box_default, {
70980
72150
  children: /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Text, {
70981
72151
  dimColor: true,
70982
- children: `↑↓ select, ← → cycle${canAdd ? ", (a)dd, (i)nsert" : ""}${canDelete ? ", (d)elete" : ""}, (c)lear, (h)ex${mode === "separator" ? ", (t)oggle invert" : ""}, ESC back`
72152
+ children: `↑↓ select, ← → cycle, (a)dd, (i)nsert${canDelete ? ", (d)elete" : ""}, (c)lear, (h)ex${mode === "separator" ? ", (t)oggle invert" : ""}, ESC back`
70983
72153
  }, undefined, false, undefined, this)
70984
72154
  }, undefined, false, undefined, this),
70985
72155
  /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Box_default, {
@@ -72864,7 +74034,9 @@ var StatusJSONSchema = exports_external.looseObject({
72864
74034
  }).nullable().optional(),
72865
74035
  rate_limits: exports_external.object({
72866
74036
  five_hour: RateLimitPeriodSchema.optional(),
72867
- seven_day: RateLimitPeriodSchema.optional()
74037
+ seven_day: RateLimitPeriodSchema.optional(),
74038
+ seven_day_sonnet: RateLimitPeriodSchema.nullable().optional(),
74039
+ seven_day_opus: RateLimitPeriodSchema.nullable().optional()
72868
74040
  }).nullable().optional()
72869
74041
  });
72870
74042
 
@@ -72980,11 +74152,11 @@ function saveCompactionState(sessionId, state) {
72980
74152
 
72981
74153
  // src/ccstatusline.ts
72982
74154
  init_context_percentage();
72983
- await __promiseAll([
72984
- init_config(),
72985
- init_jsonl()
72986
- ]);
72987
- await init_renderer2();
74155
+ await init_config();
74156
+
74157
+ // src/utils/hook-handler.ts
74158
+ import * as fs15 from "fs";
74159
+ import * as path12 from "path";
72988
74160
 
72989
74161
  // src/utils/skills.ts
72990
74162
  import * as fs14 from "fs";
@@ -73032,18 +74204,83 @@ function getSkillsMetrics(sessionId) {
73032
74204
  return EMPTY;
73033
74205
  }
73034
74206
  }
74207
+
74208
+ // src/utils/hook-handler.ts
74209
+ function handleHookInput(input) {
74210
+ if (!input) {
74211
+ return;
74212
+ }
74213
+ try {
74214
+ const data = JSON.parse(input);
74215
+ const sessionId = data.session_id;
74216
+ if (!sessionId) {
74217
+ return;
74218
+ }
74219
+ let skillName = "";
74220
+ if (data.hook_event_name === "PreToolUse" && data.tool_name === "Skill") {
74221
+ skillName = data.tool_input?.skill ?? "";
74222
+ } else if (data.hook_event_name === "UserPromptSubmit") {
74223
+ const match = /^\/([a-zA-Z0-9_:-]+)(?:\s|$)/.exec(data.prompt ?? "");
74224
+ if (match) {
74225
+ skillName = match[1] ?? "";
74226
+ }
74227
+ }
74228
+ if (!skillName) {
74229
+ return;
74230
+ }
74231
+ const filePath = getSkillsFilePath(sessionId);
74232
+ fs15.mkdirSync(path12.dirname(filePath), { recursive: true });
74233
+ const entry = JSON.stringify({
74234
+ timestamp: new Date().toISOString(),
74235
+ session_id: sessionId,
74236
+ skill: skillName,
74237
+ source: data.hook_event_name
74238
+ });
74239
+ fs15.appendFileSync(filePath, entry + `
74240
+ `);
74241
+ } catch {}
74242
+ }
74243
+
74244
+ // src/ccstatusline.ts
74245
+ await init_jsonl();
74246
+ await init_renderer2();
73035
74247
  // src/utils/usage-prefetch.ts
73036
74248
  await init_usage();
73037
74249
  var USAGE_WIDGET_TYPES = new Set([
73038
74250
  "session-usage",
73039
74251
  "weekly-usage",
74252
+ "weekly-sonnet-usage",
74253
+ "weekly-opus-usage",
73040
74254
  "block-timer",
73041
74255
  "reset-timer",
73042
74256
  "weekly-reset-timer"
73043
74257
  ]);
74258
+ var PER_MODEL_USAGE_WIDGET_TYPES = new Set([
74259
+ "weekly-sonnet-usage",
74260
+ "weekly-opus-usage"
74261
+ ]);
73044
74262
  function hasUsageDependentWidgets(lines) {
73045
74263
  return lines.some((line) => line.some((item) => USAGE_WIDGET_TYPES.has(item.type)));
73046
74264
  }
74265
+ function getPerModelUsageRequirements(lines) {
74266
+ const requirements = {
74267
+ opus: false,
74268
+ sonnet: false
74269
+ };
74270
+ for (const line of lines) {
74271
+ for (const item of line) {
74272
+ if (!PER_MODEL_USAGE_WIDGET_TYPES.has(item.type)) {
74273
+ continue;
74274
+ }
74275
+ if (item.type === "weekly-sonnet-usage") {
74276
+ requirements.sonnet = true;
74277
+ } else if (item.type === "weekly-opus-usage") {
74278
+ requirements.opus = true;
74279
+ }
74280
+ }
74281
+ }
74282
+ return requirements;
74283
+ }
73047
74284
  function epochSecondsToIsoString(epochSeconds) {
73048
74285
  if (epochSeconds === null || epochSeconds === undefined || !Number.isFinite(epochSeconds)) {
73049
74286
  return;
@@ -73058,23 +74295,56 @@ function extractUsageDataFromRateLimits(rateLimits) {
73058
74295
  const sessionResetAt = epochSecondsToIsoString(rateLimits.five_hour?.resets_at);
73059
74296
  const weeklyUsage = rateLimits.seven_day?.used_percentage ?? undefined;
73060
74297
  const weeklyResetAt = epochSecondsToIsoString(rateLimits.seven_day?.resets_at);
74298
+ const weeklySonnetUsage = rateLimits.seven_day_sonnet === null ? 0 : rateLimits.seven_day_sonnet?.used_percentage ?? undefined;
74299
+ const weeklySonnetResetAt = epochSecondsToIsoString(rateLimits.seven_day_sonnet?.resets_at);
74300
+ const weeklyOpusUsage = rateLimits.seven_day_opus === null ? 0 : rateLimits.seven_day_opus?.used_percentage ?? undefined;
74301
+ const weeklyOpusResetAt = epochSecondsToIsoString(rateLimits.seven_day_opus?.resets_at);
73061
74302
  if (sessionUsage === undefined && weeklyUsage === undefined) {
73062
74303
  return null;
73063
74304
  }
73064
- return { sessionUsage, sessionResetAt, weeklyUsage, weeklyResetAt };
74305
+ return {
74306
+ sessionUsage,
74307
+ sessionResetAt,
74308
+ weeklyUsage,
74309
+ weeklyResetAt,
74310
+ weeklySonnetUsage,
74311
+ weeklySonnetResetAt,
74312
+ weeklyOpusUsage,
74313
+ weeklyOpusResetAt
74314
+ };
74315
+ }
74316
+ function hasCompleteRateLimitsUsageData(usageData, perModelRequirements) {
74317
+ if (usageData?.sessionUsage === undefined || usageData.sessionResetAt === undefined || usageData.weeklyUsage === undefined || usageData.weeklyResetAt === undefined) {
74318
+ return false;
74319
+ }
74320
+ if (perModelRequirements.sonnet && usageData.weeklySonnetUsage === undefined) {
74321
+ return false;
74322
+ }
74323
+ if (perModelRequirements.opus && usageData.weeklyOpusUsage === undefined) {
74324
+ return false;
74325
+ }
74326
+ return true;
73065
74327
  }
73066
- function hasCompleteRateLimitsUsageData(usageData) {
73067
- return usageData?.sessionUsage !== undefined && usageData.sessionResetAt !== undefined && usageData.weeklyUsage !== undefined && usageData.weeklyResetAt !== undefined;
74328
+ function getRequiredUsageFields(perModelRequirements) {
74329
+ const requiredFields = [];
74330
+ if (perModelRequirements.sonnet) {
74331
+ requiredFields.push("weeklySonnetUsage");
74332
+ }
74333
+ if (perModelRequirements.opus) {
74334
+ requiredFields.push("weeklyOpusUsage");
74335
+ }
74336
+ return requiredFields;
73068
74337
  }
73069
74338
  async function prefetchUsageDataIfNeeded(lines, data) {
73070
74339
  if (!hasUsageDependentWidgets(lines)) {
73071
74340
  return null;
73072
74341
  }
73073
74342
  const rateLimitsData = extractUsageDataFromRateLimits(data?.rate_limits);
73074
- if (hasCompleteRateLimitsUsageData(rateLimitsData)) {
74343
+ const perModelRequirements = getPerModelUsageRequirements(lines);
74344
+ if (hasCompleteRateLimitsUsageData(rateLimitsData, perModelRequirements)) {
73075
74345
  return rateLimitsData;
73076
74346
  }
73077
- return fetchUsageData();
74347
+ return fetchUsageData({ requiredFields: getRequiredUsageFields(perModelRequirements) });
73078
74348
  }
73079
74349
 
73080
74350
  // src/ccstatusline.ts
@@ -73109,8 +74379,8 @@ async function ensureWindowsUtf8CodePage() {
73109
74379
  return;
73110
74380
  }
73111
74381
  try {
73112
- const { execFileSync: execFileSync4 } = await import("child_process");
73113
- execFileSync4("chcp.com", ["65001"], { stdio: "ignore" });
74382
+ const { execFileSync: execFileSync5 } = await import("child_process");
74383
+ execFileSync5("chcp.com", ["65001"], { stdio: "ignore" });
73114
74384
  } catch {}
73115
74385
  }
73116
74386
  async function renderMultipleLines(data) {
@@ -73236,44 +74506,7 @@ function parseConfigArg() {
73236
74506
  }
73237
74507
  async function handleHook() {
73238
74508
  const input = await readStdin();
73239
- if (!input) {
73240
- console.log("{}");
73241
- return;
73242
- }
73243
- try {
73244
- const data = JSON.parse(input);
73245
- const sessionId = data.session_id;
73246
- if (!sessionId) {
73247
- console.log("{}");
73248
- return;
73249
- }
73250
- let skillName = "";
73251
- if (data.hook_event_name === "PreToolUse" && data.tool_name === "Skill") {
73252
- skillName = data.tool_input?.skill ?? "";
73253
- } else if (data.hook_event_name === "UserPromptSubmit") {
73254
- const match = /^\/([a-zA-Z0-9_:-]+)(?:\s|$)/.exec(data.prompt ?? "");
73255
- if (match) {
73256
- skillName = match[1] ?? "";
73257
- }
73258
- }
73259
- if (!skillName) {
73260
- console.log("{}");
73261
- return;
73262
- }
73263
- const filePath = getSkillsFilePath(sessionId);
73264
- const fs15 = await import("fs");
73265
- const path12 = await import("path");
73266
- fs15.mkdirSync(path12.dirname(filePath), { recursive: true });
73267
- const entry = JSON.stringify({
73268
- timestamp: new Date().toISOString(),
73269
- session_id: sessionId,
73270
- skill: skillName,
73271
- source: data.hook_event_name
73272
- });
73273
- fs15.appendFileSync(filePath, entry + `
73274
- `);
73275
- } catch {}
73276
- console.log("{}");
74509
+ handleHookInput(input);
73277
74510
  }
73278
74511
  async function main() {
73279
74512
  initConfigPath(parseConfigArg());