ccstatusline 2.2.12 → 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.12";
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
@@ -57288,7 +57288,9 @@ function getUsagePercentCustomKeybinds(item) {
57288
57288
  }
57289
57289
  function getUsageTimerCustomKeybinds(item, options = {}) {
57290
57290
  const keybinds = [PROGRESS_TOGGLE_KEYBIND];
57291
- if (item && isUsageProgressMode(getUsageDisplayMode(item))) {
57291
+ const mode = item ? getUsageDisplayMode(item) : "time";
57292
+ const isBarMode = isUsageProgressMode(mode) || isUsageSliderMode(mode);
57293
+ if (item && isBarMode) {
57292
57294
  keybinds.push(INVERT_TOGGLE_KEYBIND);
57293
57295
  } else {
57294
57296
  keybinds.push(COMPACT_TOGGLE_KEYBIND);
@@ -57296,7 +57298,7 @@ function getUsageTimerCustomKeybinds(item, options = {}) {
57296
57298
  keybinds.push(DATE_TOGGLE_KEYBIND);
57297
57299
  }
57298
57300
  }
57299
- if (item && isUsageDateMode(item) && !isUsageProgressMode(getUsageDisplayMode(item))) {
57301
+ if (item && isUsageDateMode(item) && !isBarMode) {
57300
57302
  if (options.includeHourFormat) {
57301
57303
  keybinds.push(HOUR_FORMAT_TOGGLE_KEYBIND);
57302
57304
  }
@@ -59519,6 +59521,10 @@ function parseCachedUsageData(rawJson) {
59519
59521
  sessionResetAt: parsed.sessionResetAt ?? undefined,
59520
59522
  weeklyUsage: parsed.weeklyUsage ?? undefined,
59521
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,
59522
59528
  extraUsageEnabled: parsed.extraUsageEnabled ?? undefined,
59523
59529
  extraUsageLimit: parsed.extraUsageLimit ?? undefined,
59524
59530
  extraUsageUsed: parsed.extraUsageUsed ?? undefined,
@@ -59536,6 +59542,10 @@ function parseUsageApiResponse(rawJson) {
59536
59542
  sessionResetAt: parsed.five_hour?.resets_at ?? undefined,
59537
59543
  weeklyUsage: parsed.seven_day?.utilization ?? undefined,
59538
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,
59539
59549
  extraUsageEnabled: parsed.extra_usage?.is_enabled ?? undefined,
59540
59550
  extraUsageLimit: parsed.extra_usage?.monthly_limit ?? undefined,
59541
59551
  extraUsageUsed: parsed.extra_usage?.used_credits ?? undefined,
@@ -59560,9 +59570,12 @@ function cacheUsageData(data, now2) {
59560
59570
  usageErrorCacheMaxAge = LOCK_MAX_AGE;
59561
59571
  return data;
59562
59572
  }
59563
- 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 = []) {
59564
59577
  const stale = readStaleUsageCache();
59565
- if (stale && !stale.error) {
59578
+ if (stale && !stale.error && hasRequiredUsageFields(stale, requiredFields)) {
59566
59579
  return cacheUsageData(stale, now2);
59567
59580
  }
59568
59581
  return setCachedUsageError(error48, now2, errorCacheMaxAge);
@@ -59814,11 +59827,12 @@ async function fetchFromUsageApi(token) {
59814
59827
  request2.end();
59815
59828
  });
59816
59829
  }
59817
- async function fetchUsageData() {
59830
+ async function fetchUsageData(options = {}) {
59818
59831
  const now2 = Math.floor(Date.now() / 1000);
59832
+ const requiredFields = options.requiredFields ?? [];
59819
59833
  if (cachedUsageData) {
59820
59834
  const cacheAge = now2 - usageCacheTime;
59821
- if (!cachedUsageData.error && cacheAge < CACHE_MAX_AGE) {
59835
+ if (!cachedUsageData.error && cacheAge < CACHE_MAX_AGE && hasRequiredUsageFields(cachedUsageData, requiredFields)) {
59822
59836
  return cachedUsageData;
59823
59837
  }
59824
59838
  if (cachedUsageData.error && cacheAge < usageErrorCacheMaxAge) {
@@ -59830,35 +59844,35 @@ async function fetchUsageData() {
59830
59844
  const fileAge = now2 - Math.floor(stat.mtimeMs / 1000);
59831
59845
  if (fileAge < CACHE_MAX_AGE) {
59832
59846
  const fileData = parseCachedUsageData(fs3.readFileSync(CACHE_FILE, "utf8"));
59833
- if (fileData && !fileData.error) {
59847
+ if (fileData && !fileData.error && hasRequiredUsageFields(fileData, requiredFields)) {
59834
59848
  return cacheUsageData(fileData, now2);
59835
59849
  }
59836
59850
  }
59837
59851
  } catch {}
59838
59852
  const token = getUsageToken();
59839
59853
  if (!token) {
59840
- return getStaleUsageOrError("no-credentials", now2);
59854
+ return getStaleUsageOrError("no-credentials", now2, LOCK_MAX_AGE, requiredFields);
59841
59855
  }
59842
59856
  const activeLock = readActiveUsageLock(now2);
59843
59857
  if (activeLock) {
59844
- return getStaleUsageOrError(activeLock.error, now2, Math.max(1, activeLock.blockedUntil - now2));
59858
+ return getStaleUsageOrError(activeLock.error, now2, Math.max(1, activeLock.blockedUntil - now2), requiredFields);
59845
59859
  }
59846
59860
  writeUsageLock(now2 + LOCK_MAX_AGE, "timeout");
59847
59861
  try {
59848
59862
  const response = await fetchFromUsageApi(token);
59849
59863
  if (response.kind === "rate-limited") {
59850
59864
  writeUsageLock(now2 + response.retryAfterSeconds, "rate-limited");
59851
- return getStaleUsageOrError("rate-limited", now2, response.retryAfterSeconds);
59865
+ return getStaleUsageOrError("rate-limited", now2, response.retryAfterSeconds, requiredFields);
59852
59866
  }
59853
59867
  if (response.kind === "error") {
59854
- return getStaleUsageOrError("api-error", now2);
59868
+ return getStaleUsageOrError("api-error", now2, LOCK_MAX_AGE, requiredFields);
59855
59869
  }
59856
59870
  const usageData = parseUsageApiResponse(response.body);
59857
59871
  if (!usageData) {
59858
- return getStaleUsageOrError("parse-error", now2);
59872
+ return getStaleUsageOrError("parse-error", now2, LOCK_MAX_AGE, requiredFields);
59859
59873
  }
59860
59874
  if (usageData.sessionUsage === undefined && usageData.weeklyUsage === undefined) {
59861
- return getStaleUsageOrError("parse-error", now2);
59875
+ return getStaleUsageOrError("parse-error", now2, LOCK_MAX_AGE, requiredFields);
59862
59876
  }
59863
59877
  try {
59864
59878
  ensureCacheDirExists();
@@ -59866,10 +59880,10 @@ async function fetchUsageData() {
59866
59880
  } catch {}
59867
59881
  return cacheUsageData(usageData, now2);
59868
59882
  } catch {
59869
- return getStaleUsageOrError("parse-error", now2);
59883
+ return getStaleUsageOrError("parse-error", now2, LOCK_MAX_AGE, requiredFields);
59870
59884
  }
59871
59885
  }
59872
- 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;
59873
59887
  var init_usage_fetch = __esm(async () => {
59874
59888
  init_dist5();
59875
59889
  init_zod();
@@ -59890,12 +59904,20 @@ var init_usage_fetch = __esm(async () => {
59890
59904
  sessionResetAt: exports_external.string().nullable().optional(),
59891
59905
  weeklyUsage: exports_external.number().nullable().optional(),
59892
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(),
59893
59911
  extraUsageEnabled: exports_external.boolean().nullable().optional(),
59894
59912
  extraUsageLimit: exports_external.number().nullable().optional(),
59895
59913
  extraUsageUsed: exports_external.number().nullable().optional(),
59896
59914
  extraUsageUtilization: exports_external.number().nullable().optional(),
59897
59915
  error: exports_external.string().nullable().optional()
59898
59916
  });
59917
+ PerModelWeeklyBucketSchema = exports_external.object({
59918
+ utilization: exports_external.number().nullable().optional(),
59919
+ resets_at: exports_external.string().nullable().optional()
59920
+ }).nullable().optional();
59899
59921
  UsageApiResponseSchema = exports_external.object({
59900
59922
  five_hour: exports_external.object({
59901
59923
  utilization: exports_external.number().nullable().optional(),
@@ -59905,6 +59927,8 @@ var init_usage_fetch = __esm(async () => {
59905
59927
  utilization: exports_external.number().nullable().optional(),
59906
59928
  resets_at: exports_external.string().nullable().optional()
59907
59929
  }).optional(),
59930
+ seven_day_sonnet: PerModelWeeklyBucketSchema,
59931
+ seven_day_opus: PerModelWeeklyBucketSchema,
59908
59932
  extra_usage: exports_external.object({
59909
59933
  is_enabled: exports_external.boolean().nullable().optional(),
59910
59934
  monthly_limit: exports_external.number().nullable().optional(),
@@ -63173,6 +63197,12 @@ function getWeeklyUsageWindowFromResetAt(weeklyResetAt, nowMs = Date.now()) {
63173
63197
  function resolveWeeklyUsageWindow(usageData, nowMs = Date.now()) {
63174
63198
  return getWeeklyUsageWindowFromResetAt(usageData.weeklyResetAt, nowMs);
63175
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
+ }
63176
63206
  function formatUsageDuration(durationMs, compact2 = false, useDays = true) {
63177
63207
  const clampedMs = Math.max(0, durationMs);
63178
63208
  const totalHours = Math.floor(clampedMs / (1000 * 60 * 60));
@@ -63330,7 +63360,7 @@ class BlockTimerWidget {
63330
63360
  }
63331
63361
  handleEditorAction(action, item) {
63332
63362
  if (action === "toggle-progress") {
63333
- return cycleUsageDisplayMode(item, ["compact"]);
63363
+ return cycleUsageDisplayMode(item, ["compact"], true);
63334
63364
  }
63335
63365
  if (action === "toggle-invert") {
63336
63366
  return toggleUsageInverted(item);
@@ -63351,6 +63381,11 @@ class BlockTimerWidget {
63351
63381
  const progressBar = makeTimerProgressBar(previewPercent, barWidth);
63352
63382
  return formatRawOrLabeledValue(item, "Block ", `[${progressBar}] ${previewPercent.toFixed(1)}%`);
63353
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
+ }
63354
63389
  return formatRawOrLabeledValue(item, "Block: ", compact2 ? "3h45m" : "3hr 45m");
63355
63390
  }
63356
63391
  const usageData = context.usageData ?? {};
@@ -63361,6 +63396,11 @@ class BlockTimerWidget {
63361
63396
  const emptyBar = "░".repeat(barWidth);
63362
63397
  return formatRawOrLabeledValue(item, "Block ", `[${emptyBar}] 0.0%`);
63363
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
+ }
63364
63404
  return formatRawOrLabeledValue(item, "Block: ", compact2 ? "0h" : "0hr 0m");
63365
63405
  }
63366
63406
  if (isUsageProgressMode(displayMode)) {
@@ -63370,6 +63410,12 @@ class BlockTimerWidget {
63370
63410
  const percentage = percent.toFixed(1);
63371
63411
  return formatRawOrLabeledValue(item, "Block ", `[${progressBar}] ${percentage}%`);
63372
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
+ }
63373
63419
  const elapsedTime = formatUsageDuration(window2.elapsedMs, compact2);
63374
63420
  return formatRawOrLabeledValue(item, "Block: ", elapsedTime);
63375
63421
  }
@@ -63678,201 +63724,845 @@ class ClaudeSessionIdWidget {
63678
63724
  }
63679
63725
  }
63680
63726
 
63681
- // src/widgets/ClaudeAccountEmail.ts
63682
- 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
+ });
63683
63759
 
63684
- class ClaudeAccountEmailWidget {
63760
+ // src/widgets/JjBookmarks.ts
63761
+ class JjBookmarksWidget {
63685
63762
  getDefaultColor() {
63686
- return "blue";
63763
+ return "magenta";
63687
63764
  }
63688
63765
  getDescription() {
63689
- return "Displays the email of the currently logged-in Claude account";
63766
+ return "Shows the current jujutsu bookmark(s)";
63690
63767
  }
63691
63768
  getDisplayName() {
63692
- return "Claude Account Email";
63769
+ return "JJ Bookmarks";
63693
63770
  }
63694
63771
  getCategory() {
63695
- return "Session";
63772
+ return "Jujutsu";
63696
63773
  }
63697
63774
  getEditorDisplay(item) {
63698
- 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
+ };
63699
63784
  }
63700
- 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";
63701
63800
  if (context.isPreview) {
63702
- 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;
63703
63823
  }
63704
- try {
63705
- const content = fs8.readFileSync(getClaudeJsonPath(), "utf-8");
63706
- const data = JSON.parse(content);
63707
- const email3 = data.oauthAccount?.emailAddress;
63708
- if (typeof email3 !== "string" || email3.length === 0) {
63709
- return null;
63710
- }
63711
- return item.rawValue ? email3 : `Account: ${email3}`;
63712
- } catch {
63824
+ const bookmarks = output.split(/\s+/).filter(Boolean);
63825
+ if (bookmarks.length === 0) {
63713
63826
  return null;
63714
63827
  }
63828
+ return bookmarks.join(", ");
63829
+ }
63830
+ getCustomKeybinds() {
63831
+ return [
63832
+ { key: "h", label: "(h)ide 'no jj' message", action: "toggle-nojj" }
63833
+ ];
63715
63834
  }
63716
63835
  supportsRawValue() {
63717
63836
  return true;
63718
63837
  }
63719
- supportsColors(item) {
63838
+ supportsColors() {
63720
63839
  return true;
63721
63840
  }
63722
63841
  }
63723
- var init_ClaudeAccountEmail = __esm(async () => {
63724
- await init_claude_settings();
63842
+ var init_JjBookmarks = __esm(() => {
63843
+ init_jj();
63725
63844
  });
63726
63845
 
63727
- // src/utils/speed-metrics.ts
63728
- function calculateOutputSpeed(metrics) {
63729
- if (metrics.totalDurationMs === 0) {
63730
- return null;
63846
+ // src/widgets/JjWorkspace.ts
63847
+ class JjWorkspaceWidget {
63848
+ getDefaultColor() {
63849
+ return "blue";
63731
63850
  }
63732
- const seconds = metrics.totalDurationMs / 1000;
63733
- return metrics.outputTokens / seconds;
63734
- }
63735
- function calculateInputSpeed(metrics) {
63736
- if (metrics.totalDurationMs === 0) {
63737
- return null;
63851
+ getDescription() {
63852
+ return "Shows the current jujutsu workspace name";
63738
63853
  }
63739
- const seconds = metrics.totalDurationMs / 1000;
63740
- return metrics.inputTokens / seconds;
63741
- }
63742
- function calculateTotalSpeed(metrics) {
63743
- if (metrics.totalDurationMs === 0) {
63744
- return null;
63854
+ getDisplayName() {
63855
+ return "JJ Workspace";
63745
63856
  }
63746
- const seconds = metrics.totalDurationMs / 1000;
63747
- return metrics.totalTokens / seconds;
63748
- }
63749
- function formatSpeed(tokensPerSec) {
63750
- if (tokensPerSec === null) {
63751
- return "—";
63857
+ getCategory() {
63858
+ return "Jujutsu";
63752
63859
  }
63753
- if (tokensPerSec >= 1000) {
63754
- const kValue = tokensPerSec / 1000;
63755
- return `${kValue.toFixed(1)}k t/s`;
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
+ };
63756
63870
  }
63757
- return `${tokensPerSec.toFixed(1)} t/s`;
63758
- }
63759
-
63760
- // src/utils/speed-window.ts
63761
- function clampSpeedWindowSeconds(value) {
63762
- if (!Number.isFinite(value)) {
63763
- return DEFAULT_SPEED_WINDOW_SECONDS;
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
+ }
63882
+ return null;
63764
63883
  }
63765
- const normalized = Math.trunc(value);
63766
- if (normalized < MIN_SPEED_WINDOW_SECONDS) {
63767
- return MIN_SPEED_WINDOW_SECONDS;
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";
63768
63897
  }
63769
- if (normalized > MAX_SPEED_WINDOW_SECONDS) {
63770
- return MAX_SPEED_WINDOW_SECONDS;
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;
63771
63909
  }
63772
- return normalized;
63773
- }
63774
- function getWidgetSpeedWindowSeconds(item) {
63775
- const metadataValue = item.metadata?.[SPEED_WINDOW_METADATA_KEY];
63776
- if (!metadataValue) {
63777
- return DEFAULT_SPEED_WINDOW_SECONDS;
63910
+ getCustomKeybinds() {
63911
+ return [
63912
+ { key: "h", label: "(h)ide 'no jj' message", action: "toggle-nojj" }
63913
+ ];
63778
63914
  }
63779
- const parsed = Number.parseInt(metadataValue, 10);
63780
- if (!Number.isFinite(parsed)) {
63781
- return DEFAULT_SPEED_WINDOW_SECONDS;
63915
+ supportsRawValue() {
63916
+ return true;
63917
+ }
63918
+ supportsColors() {
63919
+ return true;
63782
63920
  }
63783
- return clampSpeedWindowSeconds(parsed);
63784
- }
63785
- function isWidgetSpeedWindowEnabled(item) {
63786
- return getWidgetSpeedWindowSeconds(item) > 0;
63787
- }
63788
- function withWidgetSpeedWindowSeconds(item, seconds) {
63789
- return {
63790
- ...item,
63791
- metadata: {
63792
- ...item.metadata ?? {},
63793
- [SPEED_WINDOW_METADATA_KEY]: clampSpeedWindowSeconds(seconds).toString()
63794
- }
63795
- };
63796
63921
  }
63797
- var SPEED_WINDOW_METADATA_KEY = "windowSeconds", DEFAULT_SPEED_WINDOW_SECONDS = 0, MIN_SPEED_WINDOW_SECONDS = 0, MAX_SPEED_WINDOW_SECONDS = 120;
63922
+ var CURRENT_WORKSPACE_TEMPLATE = `if(target.current_working_copy(), name ++ "
63923
+ ")`;
63924
+ var init_JjWorkspace = __esm(() => {
63925
+ init_jj();
63926
+ });
63798
63927
 
63799
- // src/widgets/shared/speed-widget.tsx
63800
- function getSpeedMetricsForWidget(item, context) {
63801
- if (!isWidgetSpeedWindowEnabled(item)) {
63802
- return context.speedMetrics ?? null;
63928
+ // src/widgets/JjRootDir.ts
63929
+ class JjRootDirWidget {
63930
+ getDefaultColor() {
63931
+ return "cyan";
63803
63932
  }
63804
- const windowSeconds = getWidgetSpeedWindowSeconds(item);
63805
- return context.windowedSpeedMetrics?.[windowSeconds.toString()] ?? null;
63806
- }
63807
- function calculateSpeed(kind, metrics) {
63808
- if (kind === "input") {
63809
- return calculateInputSpeed(metrics);
63933
+ getDescription() {
63934
+ return "Shows the jujutsu repository root directory name";
63810
63935
  }
63811
- if (kind === "output") {
63812
- return calculateOutputSpeed(metrics);
63936
+ getDisplayName() {
63937
+ return "JJ Root Dir";
63813
63938
  }
63814
- return calculateTotalSpeed(metrics);
63815
- }
63816
- function getSpeedWidgetDisplayName(kind) {
63817
- return SPEED_WIDGET_CONFIG[kind].displayName;
63818
- }
63819
- function getSpeedWidgetDescription(kind) {
63820
- return SPEED_WIDGET_CONFIG[kind].description;
63821
- }
63822
- function getSpeedWidgetEditorDisplay(kind, item) {
63823
- const windowSeconds = getWidgetSpeedWindowSeconds(item);
63824
- const modifiers = windowSeconds > 0 ? [`${windowSeconds}s window`] : ["session avg"];
63825
- return {
63826
- displayText: getSpeedWidgetDisplayName(kind),
63827
- modifierText: makeModifierText(modifiers)
63828
- };
63829
- }
63830
- function renderSpeedWidgetValue(kind, item, context) {
63831
- const config2 = SPEED_WIDGET_CONFIG[kind];
63832
- const previewValue = isWidgetSpeedWindowEnabled(item) ? config2.windowedPreview : config2.sessionPreview;
63833
- if (context.isPreview) {
63834
- return formatRawOrLabeledValue(item, config2.label, previewValue);
63939
+ getCategory() {
63940
+ return "Jujutsu";
63835
63941
  }
63836
- const metrics = getSpeedMetricsForWidget(item, context);
63837
- if (!metrics) {
63838
- return null;
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
+ };
63839
63952
  }
63840
- const speed = calculateSpeed(kind, metrics);
63841
- return formatRawOrLabeledValue(item, config2.label, formatSpeed(speed));
63842
- }
63843
- function getSpeedWidgetCustomKeybinds() {
63844
- return [{
63845
- key: "w",
63846
- label: "(w)indow",
63847
- action: WINDOW_EDITOR_ACTION
63848
- }];
63849
- }
63850
- function renderSpeedWidgetEditor(props) {
63851
- return /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(SpeedWindowEditor, {
63852
- ...props
63853
- }, undefined, false, undefined, this);
63854
- }
63855
- var import_react31, jsx_dev_runtime5, WINDOW_EDITOR_ACTION = "edit-window", SPEED_WIDGET_CONFIG, SpeedWindowEditor = ({ widget, onComplete, onCancel, action }) => {
63856
- const [windowInput, setWindowInput] = import_react31.useState(getWidgetSpeedWindowSeconds(widget).toString());
63857
- use_input_default((input, key) => {
63858
- if (action !== WINDOW_EDITOR_ACTION) {
63859
- return;
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
+ };
63860
63963
  }
63861
- if (key.return) {
63862
- const parsedWindow = Number.parseInt(windowInput, 10);
63863
- const nextWindow = Number.isFinite(parsedWindow) ? parsedWindow : DEFAULT_SPEED_WINDOW_SECONDS;
63864
- onComplete(withWidgetSpeedWindowSeconds(widget, nextWindow));
63865
- return;
63964
+ return null;
63965
+ }
63966
+ render(item, context, _settings) {
63967
+ const hideNoJj = item.metadata?.hideNoJj === "true";
63968
+ if (context.isPreview) {
63969
+ return "my-repo";
63866
63970
  }
63867
- if (key.escape) {
63868
- onCancel();
63869
- return;
63971
+ if (!isInsideJjRepo(context)) {
63972
+ return hideNoJj ? null : "no jj";
63870
63973
  }
63871
- if (key.backspace) {
63872
- setWindowInput(windowInput.slice(0, -1));
63873
- return;
63974
+ const rootDir = runJjArgs(["root"], context);
63975
+ if (rootDir) {
63976
+ return this.getRootDirName(rootDir);
63874
63977
  }
63875
- if (shouldInsertInput(input, key) && /\d/.test(input)) {
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
+ }
63998
+ }
63999
+ var init_JjRootDir = __esm(() => {
64000
+ init_jj();
64001
+ });
64002
+
64003
+ // src/widgets/JjChanges.ts
64004
+ class JjChangesWidget {
64005
+ getDefaultColor() {
64006
+ return "yellow";
64007
+ }
64008
+ getDescription() {
64009
+ return "Shows jujutsu changes count (+insertions, -deletions)";
64010
+ }
64011
+ getDisplayName() {
64012
+ return "JJ Changes";
64013
+ }
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);
64514
+ const modifiers = windowSeconds > 0 ? [`${windowSeconds}s window`] : ["session avg"];
64515
+ return {
64516
+ displayText: getSpeedWidgetDisplayName(kind),
64517
+ modifierText: makeModifierText(modifiers)
64518
+ };
64519
+ }
64520
+ function renderSpeedWidgetValue(kind, item, context) {
64521
+ const config2 = SPEED_WIDGET_CONFIG[kind];
64522
+ const previewValue = isWidgetSpeedWindowEnabled(item) ? config2.windowedPreview : config2.sessionPreview;
64523
+ if (context.isPreview) {
64524
+ return formatRawOrLabeledValue(item, config2.label, previewValue);
64525
+ }
64526
+ const metrics = getSpeedMetricsForWidget(item, context);
64527
+ if (!metrics) {
64528
+ return null;
64529
+ }
64530
+ const speed = calculateSpeed(kind, metrics);
64531
+ return formatRawOrLabeledValue(item, config2.label, formatSpeed(speed));
64532
+ }
64533
+ function getSpeedWidgetCustomKeybinds() {
64534
+ return [{
64535
+ key: "w",
64536
+ label: "(w)indow",
64537
+ action: WINDOW_EDITOR_ACTION
64538
+ }];
64539
+ }
64540
+ function renderSpeedWidgetEditor(props) {
64541
+ return /* @__PURE__ */ jsx_dev_runtime5.jsxDEV(SpeedWindowEditor, {
64542
+ ...props
64543
+ }, undefined, false, undefined, this);
64544
+ }
64545
+ var import_react31, jsx_dev_runtime5, WINDOW_EDITOR_ACTION = "edit-window", SPEED_WIDGET_CONFIG, SpeedWindowEditor = ({ widget, onComplete, onCancel, action }) => {
64546
+ const [windowInput, setWindowInput] = import_react31.useState(getWidgetSpeedWindowSeconds(widget).toString());
64547
+ use_input_default((input, key) => {
64548
+ if (action !== WINDOW_EDITOR_ACTION) {
64549
+ return;
64550
+ }
64551
+ if (key.return) {
64552
+ const parsedWindow = Number.parseInt(windowInput, 10);
64553
+ const nextWindow = Number.isFinite(parsedWindow) ? parsedWindow : DEFAULT_SPEED_WINDOW_SECONDS;
64554
+ onComplete(withWidgetSpeedWindowSeconds(widget, nextWindow));
64555
+ return;
64556
+ }
64557
+ if (key.escape) {
64558
+ onCancel();
64559
+ return;
64560
+ }
64561
+ if (key.backspace) {
64562
+ setWindowInput(windowInput.slice(0, -1));
64563
+ return;
64564
+ }
64565
+ if (shouldInsertInput(input, key) && /\d/.test(input)) {
63876
64566
  setWindowInput(windowInput + input);
63877
64567
  }
63878
64568
  });
@@ -64208,19 +64898,207 @@ function makeTimerProgressBar2(percent, width, options) {
64208
64898
  bar += "░";
64209
64899
  }
64210
64900
  }
64211
- return bar;
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
+ }
64212
65086
  }
65087
+ var init_WeeklyUsage = __esm(async () => {
65088
+ init_usage_display();
65089
+ await init_usage();
65090
+ });
64213
65091
 
64214
- // src/widgets/SessionUsage.ts
64215
- class SessionUsageWidget {
65092
+ // src/widgets/WeeklySonnetUsage.ts
65093
+ class WeeklySonnetUsageWidget {
64216
65094
  getDefaultColor() {
64217
65095
  return "brightBlue";
64218
65096
  }
64219
65097
  getDescription() {
64220
- return "Shows daily/session API usage percentage";
65098
+ return "Shows weekly Sonnet API usage percentage";
64221
65099
  }
64222
65100
  getDisplayName() {
64223
- return "Session Usage";
65101
+ return "Weekly Sonnet Usage";
64224
65102
  }
64225
65103
  getCategory() {
64226
65104
  return "Usage";
@@ -64248,47 +65126,47 @@ class SessionUsageWidget {
64248
65126
  const inverted = isUsageInverted(item);
64249
65127
  const showCursor = isUsageCursorEnabled(item);
64250
65128
  if (context.isPreview) {
64251
- const previewPercent = 20;
65129
+ const previewPercent = 8;
64252
65130
  const renderedPercent2 = inverted ? 100 - previewPercent : previewPercent;
64253
65131
  if (isUsageProgressMode(displayMode)) {
64254
65132
  const width = getUsageProgressBarWidth(displayMode);
64255
65133
  const progressBar = makeTimerProgressBar2(renderedPercent2, width, showCursor ? { cursorPercent: 50 } : undefined);
64256
65134
  const progressDisplay = `[${progressBar}] ${renderedPercent2.toFixed(1)}%`;
64257
- return formatRawOrLabeledValue(item, "Session: ", progressDisplay);
65135
+ return formatRawOrLabeledValue(item, LABEL, progressDisplay);
64258
65136
  }
64259
65137
  if (isUsageSliderMode(displayMode)) {
64260
65138
  const slider = makeSliderBar(renderedPercent2, undefined, showCursor ? { cursorPercent: 50 } : undefined);
64261
65139
  const sliderDisplay = displayMode === "slider" ? `${slider} ${renderedPercent2.toFixed(1)}%` : slider;
64262
- return formatRawOrLabeledValue(item, "Session: ", sliderDisplay);
65140
+ return formatRawOrLabeledValue(item, LABEL, sliderDisplay);
64263
65141
  }
64264
- return formatRawOrLabeledValue(item, "Session: ", `${previewPercent.toFixed(1)}%`);
65142
+ return formatRawOrLabeledValue(item, LABEL, `${previewPercent.toFixed(1)}%`);
64265
65143
  }
64266
65144
  const data = context.usageData ?? {};
64267
65145
  if (data.error)
64268
65146
  return getUsageErrorMessage(data.error);
64269
- if (data.sessionUsage === undefined)
65147
+ if (data.weeklySonnetUsage === undefined)
64270
65148
  return null;
64271
- const percent = Math.max(0, Math.min(100, data.sessionUsage));
65149
+ const percent = Math.max(0, Math.min(100, data.weeklySonnetUsage));
64272
65150
  const renderedPercent = inverted ? 100 - percent : percent;
64273
65151
  const getCursorOptions = () => {
64274
65152
  if (!showCursor) {
64275
65153
  return;
64276
65154
  }
64277
- const window2 = resolveUsageWindowWithFallback(data, context.blockMetrics);
65155
+ const window2 = resolveWeeklySonnetUsageWindow(data);
64278
65156
  return window2 ? { cursorPercent: window2.elapsedPercent } : undefined;
64279
65157
  };
64280
65158
  if (isUsageProgressMode(displayMode)) {
64281
65159
  const width = getUsageProgressBarWidth(displayMode);
64282
65160
  const progressBar = makeTimerProgressBar2(renderedPercent, width, getCursorOptions());
64283
65161
  const progressDisplay = `[${progressBar}] ${renderedPercent.toFixed(1)}%`;
64284
- return formatRawOrLabeledValue(item, "Session: ", progressDisplay);
65162
+ return formatRawOrLabeledValue(item, LABEL, progressDisplay);
64285
65163
  }
64286
65164
  if (isUsageSliderMode(displayMode)) {
64287
65165
  const slider = makeSliderBar(renderedPercent, undefined, getCursorOptions());
64288
65166
  const sliderDisplay = displayMode === "slider" ? `${slider} ${renderedPercent.toFixed(1)}%` : slider;
64289
- return formatRawOrLabeledValue(item, "Session: ", sliderDisplay);
65167
+ return formatRawOrLabeledValue(item, LABEL, sliderDisplay);
64290
65168
  }
64291
- return formatRawOrLabeledValue(item, "Session: ", `${percent.toFixed(1)}%`);
65169
+ return formatRawOrLabeledValue(item, LABEL, `${percent.toFixed(1)}%`);
64292
65170
  }
64293
65171
  getCustomKeybinds(item) {
64294
65172
  return getUsagePercentCustomKeybinds(item);
@@ -64300,21 +65178,22 @@ class SessionUsageWidget {
64300
65178
  return true;
64301
65179
  }
64302
65180
  }
64303
- var init_SessionUsage = __esm(async () => {
65181
+ var LABEL = "Weekly Sonnet: ";
65182
+ var init_WeeklySonnetUsage = __esm(async () => {
64304
65183
  init_usage_display();
64305
65184
  await init_usage();
64306
65185
  });
64307
65186
 
64308
- // src/widgets/WeeklyUsage.ts
64309
- class WeeklyUsageWidget {
65187
+ // src/widgets/WeeklyOpusUsage.ts
65188
+ class WeeklyOpusUsageWidget {
64310
65189
  getDefaultColor() {
64311
65190
  return "brightBlue";
64312
65191
  }
64313
65192
  getDescription() {
64314
- return "Shows weekly API usage percentage";
65193
+ return "Shows weekly Opus API usage percentage";
64315
65194
  }
64316
65195
  getDisplayName() {
64317
- return "Weekly Usage";
65196
+ return "Weekly Opus Usage";
64318
65197
  }
64319
65198
  getCategory() {
64320
65199
  return "Usage";
@@ -64342,47 +65221,47 @@ class WeeklyUsageWidget {
64342
65221
  const inverted = isUsageInverted(item);
64343
65222
  const showCursor = isUsageCursorEnabled(item);
64344
65223
  if (context.isPreview) {
64345
- const previewPercent = 12;
65224
+ const previewPercent = 4;
64346
65225
  const renderedPercent2 = inverted ? 100 - previewPercent : previewPercent;
64347
65226
  if (isUsageProgressMode(displayMode)) {
64348
65227
  const width = getUsageProgressBarWidth(displayMode);
64349
65228
  const progressBar = makeTimerProgressBar2(renderedPercent2, width, showCursor ? { cursorPercent: 50 } : undefined);
64350
65229
  const progressDisplay = `[${progressBar}] ${renderedPercent2.toFixed(1)}%`;
64351
- return formatRawOrLabeledValue(item, "Weekly: ", progressDisplay);
65230
+ return formatRawOrLabeledValue(item, LABEL2, progressDisplay);
64352
65231
  }
64353
65232
  if (isUsageSliderMode(displayMode)) {
64354
65233
  const slider = makeSliderBar(renderedPercent2, undefined, showCursor ? { cursorPercent: 50 } : undefined);
64355
65234
  const sliderDisplay = displayMode === "slider" ? `${slider} ${renderedPercent2.toFixed(1)}%` : slider;
64356
- return formatRawOrLabeledValue(item, "Weekly: ", sliderDisplay);
65235
+ return formatRawOrLabeledValue(item, LABEL2, sliderDisplay);
64357
65236
  }
64358
- return formatRawOrLabeledValue(item, "Weekly: ", `${previewPercent.toFixed(1)}%`);
65237
+ return formatRawOrLabeledValue(item, LABEL2, `${previewPercent.toFixed(1)}%`);
64359
65238
  }
64360
65239
  const data = context.usageData ?? {};
64361
65240
  if (data.error)
64362
65241
  return getUsageErrorMessage(data.error);
64363
- if (data.weeklyUsage === undefined)
65242
+ if (data.weeklyOpusUsage === undefined)
64364
65243
  return null;
64365
- const percent = Math.max(0, Math.min(100, data.weeklyUsage));
65244
+ const percent = Math.max(0, Math.min(100, data.weeklyOpusUsage));
64366
65245
  const renderedPercent = inverted ? 100 - percent : percent;
64367
65246
  const getCursorOptions = () => {
64368
65247
  if (!showCursor) {
64369
65248
  return;
64370
65249
  }
64371
- const window2 = resolveWeeklyUsageWindow(data);
65250
+ const window2 = resolveWeeklyOpusUsageWindow(data);
64372
65251
  return window2 ? { cursorPercent: window2.elapsedPercent } : undefined;
64373
65252
  };
64374
65253
  if (isUsageProgressMode(displayMode)) {
64375
65254
  const width = getUsageProgressBarWidth(displayMode);
64376
65255
  const progressBar = makeTimerProgressBar2(renderedPercent, width, getCursorOptions());
64377
65256
  const progressDisplay = `[${progressBar}] ${renderedPercent.toFixed(1)}%`;
64378
- return formatRawOrLabeledValue(item, "Weekly: ", progressDisplay);
65257
+ return formatRawOrLabeledValue(item, LABEL2, progressDisplay);
64379
65258
  }
64380
65259
  if (isUsageSliderMode(displayMode)) {
64381
65260
  const slider = makeSliderBar(renderedPercent, undefined, getCursorOptions());
64382
65261
  const sliderDisplay = displayMode === "slider" ? `${slider} ${renderedPercent.toFixed(1)}%` : slider;
64383
- return formatRawOrLabeledValue(item, "Weekly: ", sliderDisplay);
65262
+ return formatRawOrLabeledValue(item, LABEL2, sliderDisplay);
64384
65263
  }
64385
- return formatRawOrLabeledValue(item, "Weekly: ", `${percent.toFixed(1)}%`);
65264
+ return formatRawOrLabeledValue(item, LABEL2, `${percent.toFixed(1)}%`);
64386
65265
  }
64387
65266
  getCustomKeybinds(item) {
64388
65267
  return getUsagePercentCustomKeybinds(item);
@@ -64394,7 +65273,8 @@ class WeeklyUsageWidget {
64394
65273
  return true;
64395
65274
  }
64396
65275
  }
64397
- var init_WeeklyUsage = __esm(async () => {
65276
+ var LABEL2 = "Weekly Opus: ";
65277
+ var init_WeeklyOpusUsage = __esm(async () => {
64398
65278
  init_usage_display();
64399
65279
  await init_usage();
64400
65280
  });
@@ -64879,7 +65759,7 @@ class BlockResetTimerWidget {
64879
65759
  }
64880
65760
  handleEditorAction(action, item) {
64881
65761
  if (action === "toggle-progress") {
64882
- return cycleUsageDisplayMode(item, ["compact", "absolute"]);
65762
+ return cycleUsageDisplayMode(item, ["compact", "absolute"], true);
64883
65763
  }
64884
65764
  if (action === "toggle-invert") {
64885
65765
  return toggleUsageInverted(item);
@@ -64907,6 +65787,11 @@ class BlockResetTimerWidget {
64907
65787
  const progressBar = makeTimerProgressBar3(previewPercent, barWidth);
64908
65788
  return formatRawOrLabeledValue(item, "Reset ", `[${progressBar}] ${previewPercent.toFixed(1)}%`);
64909
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
+ }
64910
65795
  if (dateMode) {
64911
65796
  const resetAt = formatUsageResetAt(BLOCK_RESET_PREVIEW_AT, compact2, getUsageTimezone(item), getUsageLocale(item), isUsage12HourClock(item));
64912
65797
  return formatRawOrLabeledValue(item, "Reset: ", resetAt ?? (compact2 ? "03-12 08:30Z" : "2026-03-12 08:30 UTC"));
@@ -64928,6 +65813,12 @@ class BlockResetTimerWidget {
64928
65813
  const percentage = percent.toFixed(1);
64929
65814
  return formatRawOrLabeledValue(item, "Reset ", `[${progressBar}] ${percentage}%`);
64930
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
+ }
64931
65822
  if (dateMode) {
64932
65823
  const timezone = getUsageTimezone(item);
64933
65824
  const locale = getUsageLocale(item);
@@ -64989,16 +65880,21 @@ function toggleWeeklyResetHoursOnly(item) {
64989
65880
  function getWeeklyResetModifierText(item) {
64990
65881
  const displayMode = getUsageDisplayMode(item);
64991
65882
  const dateMode = isUsageDateMode(item);
65883
+ const isBarMode = isUsageProgressMode(displayMode) || isUsageSliderMode(displayMode);
64992
65884
  const modifiers = [];
64993
65885
  if (displayMode === "progress") {
64994
65886
  modifiers.push("long bar");
64995
65887
  } else if (displayMode === "progress-short") {
64996
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");
64997
65893
  }
64998
65894
  if (isUsageInverted(item)) {
64999
65895
  modifiers.push("inverted");
65000
65896
  }
65001
- if (!isUsageProgressMode(displayMode)) {
65897
+ if (!isBarMode) {
65002
65898
  if (isUsageCompact(item)) {
65003
65899
  modifiers.push("compact");
65004
65900
  }
@@ -65012,11 +65908,11 @@ function getWeeklyResetModifierText(item) {
65012
65908
  }
65013
65909
  }
65014
65910
  const timezoneModifier = getUsageTimezoneModifier(item);
65015
- if (!isUsageProgressMode(displayMode) && dateMode && timezoneModifier) {
65911
+ if (!isBarMode && dateMode && timezoneModifier) {
65016
65912
  modifiers.push(timezoneModifier);
65017
65913
  }
65018
65914
  const localeModifier = getUsageLocaleModifier(item);
65019
- if (!isUsageProgressMode(displayMode) && dateMode && localeModifier) {
65915
+ if (!isBarMode && dateMode && localeModifier) {
65020
65916
  modifiers.push(localeModifier);
65021
65917
  }
65022
65918
  return makeModifierText(modifiers);
@@ -65043,7 +65939,7 @@ class WeeklyResetTimerWidget {
65043
65939
  }
65044
65940
  handleEditorAction(action, item) {
65045
65941
  if (action === "toggle-progress") {
65046
- return cycleUsageDisplayMode(item, ["compact", "hours", "absolute"]);
65942
+ return cycleUsageDisplayMode(item, ["compact", "hours", "absolute"], true);
65047
65943
  }
65048
65944
  if (action === "toggle-invert") {
65049
65945
  return toggleUsageInverted(item);
@@ -65075,6 +65971,11 @@ class WeeklyResetTimerWidget {
65075
65971
  const progressBar = makeTimerProgressBar4(previewPercent, barWidth);
65076
65972
  return formatRawOrLabeledValue(item, "Weekly Reset ", `[${progressBar}] ${previewPercent.toFixed(1)}%`);
65077
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
+ }
65078
65979
  if (dateMode) {
65079
65980
  const resetAt = formatUsageResetAt(WEEKLY_RESET_PREVIEW_AT, compact2, getUsageTimezone(item), getUsageLocale(item), isUsage12HourClock(item));
65080
65981
  return formatRawOrLabeledValue(item, "Weekly Reset: ", resetAt ?? (compact2 ? "03-15 08:30Z" : "2026-03-15 08:30 UTC"));
@@ -65096,6 +65997,12 @@ class WeeklyResetTimerWidget {
65096
65997
  const percentage = percent.toFixed(1);
65097
65998
  return formatRawOrLabeledValue(item, "Weekly Reset ", `[${progressBar}] ${percentage}%`);
65098
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
+ }
65099
66006
  if (dateMode) {
65100
66007
  const timezone = getUsageTimezone(item);
65101
66008
  const locale = getUsageLocale(item);
@@ -65114,7 +66021,9 @@ class WeeklyResetTimerWidget {
65114
66021
  includeLocale: true,
65115
66022
  includeTimezone: true
65116
66023
  });
65117
- 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)) {
65118
66027
  keybinds.push({ key: "h", label: "(h)ours only", action: "toggle-hours" });
65119
66028
  }
65120
66029
  return keybinds;
@@ -66109,6 +67018,141 @@ var init_CompactionCounter = __esm(() => {
66109
67018
  FORMATS2 = ["icon-space-number", "text-and-number", "number"];
66110
67019
  });
66111
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
+
66112
67156
  // src/widgets/index.ts
66113
67157
  var init_widgets = __esm(async () => {
66114
67158
  init_GitBranch();
@@ -66139,6 +67183,14 @@ var init_widgets = __esm(async () => {
66139
67183
  init_ContextPercentage();
66140
67184
  init_ContextPercentageUsable();
66141
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();
66142
67194
  init_FreeMemory();
66143
67195
  init_SessionName();
66144
67196
  init_VimMode();
@@ -66161,12 +67213,15 @@ var init_widgets = __esm(async () => {
66161
67213
  init_TotalSpeed(),
66162
67214
  init_SessionUsage(),
66163
67215
  init_WeeklyUsage(),
67216
+ init_WeeklySonnetUsage(),
67217
+ init_WeeklyOpusUsage(),
66164
67218
  init_BlockResetTimer(),
66165
67219
  init_WeeklyResetTimer(),
66166
67220
  init_ContextBar(),
66167
67221
  init_Link(),
66168
67222
  init_Skills(),
66169
- init_ThinkingEffort()
67223
+ init_ThinkingEffort(),
67224
+ init_VoiceStatus()
66170
67225
  ]);
66171
67226
  });
66172
67227
 
@@ -66202,6 +67257,14 @@ var init_widget_manifest = __esm(async () => {
66202
67257
  { type: "git-upstream-repo", create: () => new GitUpstreamRepoWidget },
66203
67258
  { type: "git-upstream-owner-repo", create: () => new GitUpstreamOwnerRepoWidget },
66204
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 },
66205
67268
  { type: "current-working-dir", create: () => new CurrentWorkingDirWidget },
66206
67269
  { type: "tokens-input", create: () => new TokensInputWidget },
66207
67270
  { type: "tokens-output", create: () => new TokensOutputWidget },
@@ -66229,12 +67292,15 @@ var init_widget_manifest = __esm(async () => {
66229
67292
  { type: "free-memory", create: () => new FreeMemoryWidget },
66230
67293
  { type: "session-usage", create: () => new SessionUsageWidget },
66231
67294
  { type: "weekly-usage", create: () => new WeeklyUsageWidget },
67295
+ { type: "weekly-sonnet-usage", create: () => new WeeklySonnetUsageWidget },
67296
+ { type: "weekly-opus-usage", create: () => new WeeklyOpusUsageWidget },
66232
67297
  { type: "reset-timer", create: () => new BlockResetTimerWidget },
66233
67298
  { type: "weekly-reset-timer", create: () => new WeeklyResetTimerWidget },
66234
67299
  { type: "context-bar", create: () => new ContextBarWidget },
66235
67300
  { type: "skills", create: () => new SkillsWidget },
66236
67301
  { type: "thinking-effort", create: () => new ThinkingEffortWidget },
66237
67302
  { type: "vim-mode", create: () => new VimModeWidget },
67303
+ { type: "voice-status", create: () => new VoiceStatusWidget },
66238
67304
  { type: "worktree-mode", create: () => new GitWorktreeModeWidget },
66239
67305
  { type: "worktree-name", create: () => new GitWorktreeNameWidget },
66240
67306
  { type: "worktree-branch", create: () => new GitWorktreeBranchWidget },
@@ -66346,6 +67412,9 @@ __export(exports_hooks, {
66346
67412
  syncWidgetHooks: () => syncWidgetHooks,
66347
67413
  removeManagedHooks: () => removeManagedHooks
66348
67414
  });
67415
+ function hasWidgetHooks(widget) {
67416
+ return Boolean(widget && "getHooks" in widget && typeof widget.getHooks === "function");
67417
+ }
66349
67418
  function stripManagedHooks(hooks) {
66350
67419
  for (const event of Object.keys(hooks)) {
66351
67420
  hooks[event] = (hooks[event] ?? []).filter((entry) => entry._tag !== HOOK_TAG);
@@ -66360,7 +67429,7 @@ function getActiveHookDefs(settings) {
66360
67429
  for (const line of settings.lines) {
66361
67430
  for (const item of line) {
66362
67431
  const widget = getWidget(item.type);
66363
- if (!widget?.getHooks) {
67432
+ if (!hasWidgetHooks(widget)) {
66364
67433
  continue;
66365
67434
  }
66366
67435
  for (const hook of widget.getHooks()) {
@@ -66787,8 +67856,53 @@ async function setRefreshInterval(interval) {
66787
67856
  }
66788
67857
  await saveClaudeSettings(settings);
66789
67858
  }
66790
- 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;
66791
67904
  var init_claude_settings = __esm(async () => {
67905
+ init_zod();
66792
67906
  init_Settings();
66793
67907
  await init_config();
66794
67908
  readFile4 = fs11.promises.readFile;
@@ -66799,6 +67913,7 @@ var init_claude_settings = __esm(async () => {
66799
67913
  BUNX: "bunx -y ccstatusline@latest",
66800
67914
  SELF_MANAGED: "ccstatusline"
66801
67915
  };
67916
+ VoiceConfigSchema = exports_external.object({ enabled: exports_external.boolean().optional() });
66802
67917
  });
66803
67918
 
66804
67919
  // node_modules/pluralize/pluralize.js
@@ -72919,7 +74034,9 @@ var StatusJSONSchema = exports_external.looseObject({
72919
74034
  }).nullable().optional(),
72920
74035
  rate_limits: exports_external.object({
72921
74036
  five_hour: RateLimitPeriodSchema.optional(),
72922
- seven_day: RateLimitPeriodSchema.optional()
74037
+ seven_day: RateLimitPeriodSchema.optional(),
74038
+ seven_day_sonnet: RateLimitPeriodSchema.nullable().optional(),
74039
+ seven_day_opus: RateLimitPeriodSchema.nullable().optional()
72923
74040
  }).nullable().optional()
72924
74041
  });
72925
74042
 
@@ -73035,11 +74152,11 @@ function saveCompactionState(sessionId, state) {
73035
74152
 
73036
74153
  // src/ccstatusline.ts
73037
74154
  init_context_percentage();
73038
- await __promiseAll([
73039
- init_config(),
73040
- init_jsonl()
73041
- ]);
73042
- 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";
73043
74160
 
73044
74161
  // src/utils/skills.ts
73045
74162
  import * as fs14 from "fs";
@@ -73087,18 +74204,83 @@ function getSkillsMetrics(sessionId) {
73087
74204
  return EMPTY;
73088
74205
  }
73089
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();
73090
74247
  // src/utils/usage-prefetch.ts
73091
74248
  await init_usage();
73092
74249
  var USAGE_WIDGET_TYPES = new Set([
73093
74250
  "session-usage",
73094
74251
  "weekly-usage",
74252
+ "weekly-sonnet-usage",
74253
+ "weekly-opus-usage",
73095
74254
  "block-timer",
73096
74255
  "reset-timer",
73097
74256
  "weekly-reset-timer"
73098
74257
  ]);
74258
+ var PER_MODEL_USAGE_WIDGET_TYPES = new Set([
74259
+ "weekly-sonnet-usage",
74260
+ "weekly-opus-usage"
74261
+ ]);
73099
74262
  function hasUsageDependentWidgets(lines) {
73100
74263
  return lines.some((line) => line.some((item) => USAGE_WIDGET_TYPES.has(item.type)));
73101
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
+ }
73102
74284
  function epochSecondsToIsoString(epochSeconds) {
73103
74285
  if (epochSeconds === null || epochSeconds === undefined || !Number.isFinite(epochSeconds)) {
73104
74286
  return;
@@ -73113,23 +74295,56 @@ function extractUsageDataFromRateLimits(rateLimits) {
73113
74295
  const sessionResetAt = epochSecondsToIsoString(rateLimits.five_hour?.resets_at);
73114
74296
  const weeklyUsage = rateLimits.seven_day?.used_percentage ?? undefined;
73115
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);
73116
74302
  if (sessionUsage === undefined && weeklyUsage === undefined) {
73117
74303
  return null;
73118
74304
  }
73119
- 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;
73120
74327
  }
73121
- function hasCompleteRateLimitsUsageData(usageData) {
73122
- 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;
73123
74337
  }
73124
74338
  async function prefetchUsageDataIfNeeded(lines, data) {
73125
74339
  if (!hasUsageDependentWidgets(lines)) {
73126
74340
  return null;
73127
74341
  }
73128
74342
  const rateLimitsData = extractUsageDataFromRateLimits(data?.rate_limits);
73129
- if (hasCompleteRateLimitsUsageData(rateLimitsData)) {
74343
+ const perModelRequirements = getPerModelUsageRequirements(lines);
74344
+ if (hasCompleteRateLimitsUsageData(rateLimitsData, perModelRequirements)) {
73130
74345
  return rateLimitsData;
73131
74346
  }
73132
- return fetchUsageData();
74347
+ return fetchUsageData({ requiredFields: getRequiredUsageFields(perModelRequirements) });
73133
74348
  }
73134
74349
 
73135
74350
  // src/ccstatusline.ts
@@ -73164,8 +74379,8 @@ async function ensureWindowsUtf8CodePage() {
73164
74379
  return;
73165
74380
  }
73166
74381
  try {
73167
- const { execFileSync: execFileSync4 } = await import("child_process");
73168
- execFileSync4("chcp.com", ["65001"], { stdio: "ignore" });
74382
+ const { execFileSync: execFileSync5 } = await import("child_process");
74383
+ execFileSync5("chcp.com", ["65001"], { stdio: "ignore" });
73169
74384
  } catch {}
73170
74385
  }
73171
74386
  async function renderMultipleLines(data) {
@@ -73291,44 +74506,7 @@ function parseConfigArg() {
73291
74506
  }
73292
74507
  async function handleHook() {
73293
74508
  const input = await readStdin();
73294
- if (!input) {
73295
- console.log("{}");
73296
- return;
73297
- }
73298
- try {
73299
- const data = JSON.parse(input);
73300
- const sessionId = data.session_id;
73301
- if (!sessionId) {
73302
- console.log("{}");
73303
- return;
73304
- }
73305
- let skillName = "";
73306
- if (data.hook_event_name === "PreToolUse" && data.tool_name === "Skill") {
73307
- skillName = data.tool_input?.skill ?? "";
73308
- } else if (data.hook_event_name === "UserPromptSubmit") {
73309
- const match = /^\/([a-zA-Z0-9_:-]+)(?:\s|$)/.exec(data.prompt ?? "");
73310
- if (match) {
73311
- skillName = match[1] ?? "";
73312
- }
73313
- }
73314
- if (!skillName) {
73315
- console.log("{}");
73316
- return;
73317
- }
73318
- const filePath = getSkillsFilePath(sessionId);
73319
- const fs15 = await import("fs");
73320
- const path12 = await import("path");
73321
- fs15.mkdirSync(path12.dirname(filePath), { recursive: true });
73322
- const entry = JSON.stringify({
73323
- timestamp: new Date().toISOString(),
73324
- session_id: sessionId,
73325
- skill: skillName,
73326
- source: data.hook_event_name
73327
- });
73328
- fs15.appendFileSync(filePath, entry + `
73329
- `);
73330
- } catch {}
73331
- console.log("{}");
74509
+ handleHookInput(input);
73332
74510
  }
73333
74511
  async function main() {
73334
74512
  initConfigPath(parseConfigArg());