ccstatusline 2.2.23 → 2.2.25

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.
@@ -53003,13 +53003,14 @@ var init_Widget = __esm(() => {
53003
53003
  });
53004
53004
 
53005
53005
  // src/types/Settings.ts
53006
- var CURRENT_VERSION = 3, InstallationMetadataSchema, SettingsSchema_v1, SettingsSchema, DEFAULT_SETTINGS;
53006
+ var CURRENT_VERSION = 3, DefaultPaddingSideSchema, InstallationMetadataSchema, SettingsSchema_v1, SettingsSchema, DEFAULT_SETTINGS;
53007
53007
  var init_Settings = __esm(() => {
53008
53008
  init_zod();
53009
53009
  init_ColorLevel();
53010
53010
  init_FlexMode();
53011
53011
  init_PowerlineConfig();
53012
53012
  init_Widget();
53013
+ DefaultPaddingSideSchema = exports_external.enum(["both", "left", "right"]);
53013
53014
  InstallationMetadataSchema = exports_external.discriminatedUnion("method", [
53014
53015
  exports_external.object({
53015
53016
  method: exports_external.literal("auto-update"),
@@ -53060,6 +53061,7 @@ var init_Settings = __esm(() => {
53060
53061
  colorLevel: ColorLevelSchema.default(2),
53061
53062
  defaultSeparator: exports_external.string().optional(),
53062
53063
  defaultPadding: exports_external.string().optional(),
53064
+ defaultPaddingSide: DefaultPaddingSideSchema.default("both"),
53063
53065
  inheritSeparatorColors: exports_external.boolean().default(false),
53064
53066
  overrideBackgroundColor: exports_external.string().optional(),
53065
53067
  overrideForegroundColor: exports_external.string().optional(),
@@ -55591,199 +55593,70 @@ var init_GitUntrackedFiles = __esm(() => {
55591
55593
  init_git_no_git();
55592
55594
  });
55593
55595
 
55594
- // src/widgets/GitCleanStatus.ts
55595
- class GitCleanStatusWidget {
55596
- getDefaultColor() {
55597
- return "green";
55598
- }
55599
- getDescription() {
55600
- return "Shows ✓ when the working tree is clean and ✗ when it is dirty";
55601
- }
55602
- getDisplayName() {
55603
- return "Git Clean Status";
55604
- }
55605
- getCategory() {
55606
- return "Git";
55607
- }
55608
- getEditorDisplay(item) {
55609
- return {
55610
- displayText: this.getDisplayName(),
55611
- modifierText: getHideNoGitModifierText(item)
55612
- };
55613
- }
55614
- handleEditorAction(action, item) {
55615
- return handleToggleNoGitAction(action, item);
55616
- }
55617
- render(item, context, _settings) {
55618
- const hideNoGit = isHideNoGitEnabled(item);
55619
- if (context.isPreview) {
55620
- return item.rawValue ? "clean" : "✓";
55621
- }
55622
- if (!isInsideGitWorkTree(context)) {
55623
- return hideNoGit ? null : "(no git)";
55624
- }
55625
- const clean = this.isClean(context);
55626
- if (item.rawValue) {
55627
- return clean ? "clean" : "dirty";
55628
- }
55629
- return clean ? "✓" : "✗";
55630
- }
55631
- isClean(context) {
55632
- const status = getGitStatus(context);
55633
- return !status.staged && !status.unstaged && !status.untracked && !status.conflicts;
55634
- }
55635
- getCustomKeybinds() {
55636
- return getHideNoGitKeybinds();
55637
- }
55638
- supportsRawValue() {
55639
- return true;
55640
- }
55641
- supportsColors(_item) {
55642
- return true;
55643
- }
55644
- }
55645
- var init_GitCleanStatus = __esm(() => {
55646
- init_git();
55647
- init_git_no_git();
55648
- });
55649
-
55650
- // src/widgets/GitRootDir.ts
55651
- class GitRootDirWidget {
55652
- getDefaultColor() {
55653
- return "cyan";
55654
- }
55655
- getDescription() {
55656
- return "Shows the git repository root directory name";
55657
- }
55658
- getDisplayName() {
55659
- return "Git Root Dir";
55660
- }
55661
- getCategory() {
55662
- return "Git";
55663
- }
55664
- getEditorDisplay(item) {
55665
- const ideLinkMode = this.getIdeLinkMode(item);
55666
- const modifiers = [];
55667
- const noGitText = getHideNoGitModifierText(item);
55668
- if (noGitText)
55669
- modifiers.push("hide 'no git'");
55670
- if (ideLinkMode)
55671
- modifiers.push(IDE_LINK_LABELS[ideLinkMode]);
55672
- const maxWidthText = getMaxWidthModifier(item);
55673
- if (maxWidthText)
55674
- modifiers.push(maxWidthText);
55675
- return {
55676
- displayText: this.getDisplayName(),
55677
- modifierText: makeModifierText(modifiers)
55678
- };
55679
- }
55680
- handleEditorAction(action, item) {
55681
- if (action === TOGGLE_LINK_ACTION2) {
55682
- return this.cycleIdeLinkMode(item);
55683
- }
55684
- return handleToggleNoGitAction(action, item);
55685
- }
55686
- render(item, context, _settings) {
55687
- const hideNoGit = isHideNoGitEnabled(item);
55688
- const ideLinkMode = this.getIdeLinkMode(item);
55689
- if (context.isPreview) {
55690
- const name2 = "my-repo";
55691
- return ideLinkMode ? renderOsc8Link(buildIdeFileUrl("/Users/example/my-repo", ideLinkMode), name2) : name2;
55692
- }
55693
- if (!isInsideGitWorkTree(context)) {
55694
- return hideNoGit ? null : "no git";
55695
- }
55696
- const rootDir = this.getGitRootDir(context);
55697
- if (!rootDir) {
55698
- return hideNoGit ? null : "no git";
55699
- }
55700
- const name = applyMaxWidth(this.getRootDirName(rootDir), item.maxWidth);
55701
- if (ideLinkMode) {
55702
- return renderOsc8Link(buildIdeFileUrl(rootDir, ideLinkMode), name);
55703
- }
55704
- return name;
55705
- }
55706
- getGitRootDir(context) {
55707
- return runGit("rev-parse --show-toplevel", context);
55708
- }
55709
- getRootDirName(rootDir) {
55710
- const trimmedRootDir = rootDir.replace(/[\\/]+$/, "");
55711
- const normalizedRootDir = trimmedRootDir.length > 0 ? trimmedRootDir : rootDir;
55712
- const parts = normalizedRootDir.split(/[\\/]/).filter(Boolean);
55713
- const lastPart = parts[parts.length - 1];
55714
- return lastPart && lastPart.length > 0 ? lastPart : normalizedRootDir;
55715
- }
55716
- getCustomKeybinds() {
55717
- return [
55718
- ...getHideNoGitKeybinds(),
55719
- { key: "l", label: "(l)ink to IDE", action: TOGGLE_LINK_ACTION2 },
55720
- getMaxWidthKeybind()
55721
- ];
55722
- }
55723
- renderEditor(props) {
55724
- if (props.action === MAX_WIDTH_ACTION) {
55725
- return renderMaxWidthEditor(props);
55726
- }
55727
- return null;
55728
- }
55729
- supportsRawValue() {
55730
- return false;
55731
- }
55732
- supportsColors(item) {
55733
- return true;
55734
- }
55735
- getIdeLinkMode(item) {
55736
- const configuredMode = item.metadata?.[IDE_LINK_KEY];
55737
- if (configuredMode && IDE_LINK_MODES.includes(configuredMode)) {
55738
- return configuredMode;
55739
- }
55740
- if (isMetadataFlagEnabled(item, LEGACY_CURSOR_LINK_KEY)) {
55741
- return "cursor";
55742
- }
55743
- return null;
55744
- }
55745
- cycleIdeLinkMode(item) {
55746
- const currentMode = this.getIdeLinkMode(item);
55747
- const currentIndex = currentMode ? IDE_LINK_MODES.indexOf(currentMode) : -1;
55748
- const nextMode = currentIndex === IDE_LINK_MODES.length - 1 ? null : IDE_LINK_MODES[currentIndex + 1] ?? null;
55749
- const {
55750
- [IDE_LINK_KEY]: removedIdeLink,
55751
- [LEGACY_CURSOR_LINK_KEY]: removedLegacyLink,
55752
- ...restMetadata
55753
- } = item.metadata ?? {};
55754
- return {
55755
- ...item,
55756
- metadata: nextMode ? {
55757
- ...restMetadata,
55758
- [IDE_LINK_KEY]: nextMode
55759
- } : Object.keys(restMetadata).length > 0 ? restMetadata : undefined
55760
- };
55761
- }
55762
- }
55763
- var IDE_LINK_KEY = "linkToIDE", LEGACY_CURSOR_LINK_KEY = "linkToCursor", TOGGLE_LINK_ACTION2 = "toggle-link", IDE_LINK_LABELS;
55764
- var init_GitRootDir = __esm(async () => {
55765
- init_git();
55766
- init_hyperlink();
55767
- init_git_no_git();
55768
- await init_max_width();
55769
- IDE_LINK_LABELS = {
55770
- vscode: "link-vscode",
55771
- cursor: "link-cursor"
55772
- };
55773
- });
55774
-
55775
55596
  // src/utils/git-review-cache.ts
55776
- import { execFileSync as execFileSync2 } from "child_process";
55777
55597
  import {
55598
+ execFileSync as execFileSync2,
55599
+ spawn
55600
+ } from "child_process";
55601
+ import {
55602
+ closeSync,
55778
55603
  existsSync as existsSync2,
55779
55604
  mkdirSync as mkdirSync2,
55605
+ openSync,
55780
55606
  readFileSync as readFileSync3,
55781
55607
  statSync as statSync2,
55608
+ unlinkSync,
55782
55609
  writeFileSync as writeFileSync2
55783
55610
  } from "fs";
55784
55611
  import { createHash as createHash2 } from "node:crypto";
55785
55612
  import os4 from "node:os";
55786
55613
  import path2 from "node:path";
55614
+ function readField(entry, key) {
55615
+ const value = entry[key];
55616
+ return typeof value === "string" ? value.toUpperCase() : "";
55617
+ }
55618
+ function classifyCheck(entry) {
55619
+ if (typeof entry.status === "string") {
55620
+ if (entry.status.toUpperCase() !== "COMPLETED")
55621
+ return "pending";
55622
+ const conclusion = readField(entry, "conclusion");
55623
+ if (conclusion === "SUCCESS")
55624
+ return "success";
55625
+ if (conclusion === "NEUTRAL" || conclusion === "SKIPPED")
55626
+ return "ignored";
55627
+ return "failed";
55628
+ }
55629
+ const state = readField(entry, "state");
55630
+ if (state === "SUCCESS")
55631
+ return "success";
55632
+ if (state === "PENDING" || state === "EXPECTED")
55633
+ return "pending";
55634
+ return "failed";
55635
+ }
55636
+ function computeCiRollup(rollup) {
55637
+ if (!Array.isArray(rollup) || rollup.length === 0)
55638
+ return null;
55639
+ let failing = 0;
55640
+ let pending = 0;
55641
+ let success2 = 0;
55642
+ let seen = 0;
55643
+ for (const entry of rollup) {
55644
+ if (typeof entry !== "object" || entry === null)
55645
+ continue;
55646
+ seen++;
55647
+ const kind = classifyCheck(entry);
55648
+ if (kind === "failed")
55649
+ failing++;
55650
+ else if (kind === "pending")
55651
+ pending++;
55652
+ else if (kind === "success")
55653
+ success2++;
55654
+ }
55655
+ if (seen === 0)
55656
+ return null;
55657
+ const state = failing > 0 ? "failing" : pending > 0 ? "pending" : "passing";
55658
+ return { state, failing, pending, success: success2 };
55659
+ }
55787
55660
  function getCacheDir2(deps) {
55788
55661
  return path2.join(deps.getHomedir(), ".cache", "ccstatusline");
55789
55662
  }
@@ -55822,35 +55695,66 @@ function getCachePath2(cwd2, ref, deps) {
55822
55695
  const hash2 = createHash2("sha256").update(cwd2).update("\x00").update(ref).digest("hex").slice(0, 16);
55823
55696
  return path2.join(getGitReviewCacheDir(deps), `git-review-${hash2}.json`);
55824
55697
  }
55698
+ function isGitReviewData(value) {
55699
+ if (typeof value !== "object" || value === null) {
55700
+ return false;
55701
+ }
55702
+ const candidate = value;
55703
+ return typeof candidate.number === "number" && typeof candidate.url === "string";
55704
+ }
55705
+ function decodeCache(content) {
55706
+ if (content.length === 0) {
55707
+ return { data: null, checksQueried: true };
55708
+ }
55709
+ const parsed = JSON.parse(content);
55710
+ if (typeof parsed === "object" && parsed !== null) {
55711
+ const stored = parsed;
55712
+ if (stored.version === 1 && typeof stored.checksQueried === "boolean" && (stored.data === null || isGitReviewData(stored.data))) {
55713
+ return {
55714
+ data: stored.data,
55715
+ checksQueried: stored.data === null || stored.checksQueried
55716
+ };
55717
+ }
55718
+ }
55719
+ if (isGitReviewData(parsed)) {
55720
+ return {
55721
+ data: parsed,
55722
+ checksQueried: parsed.checks !== undefined
55723
+ };
55724
+ }
55725
+ return "miss";
55726
+ }
55825
55727
  function readCache(cachePath, deps) {
55826
55728
  try {
55827
55729
  if (!deps.existsSync(cachePath)) {
55828
55730
  return "miss";
55829
55731
  }
55830
55732
  const age = deps.now() - deps.statSync(cachePath).mtimeMs;
55831
- if (age > GIT_REVIEW_CACHE_TTL) {
55832
- return "miss";
55833
- }
55834
55733
  const content = deps.readFileSync(cachePath, "utf-8").trim();
55835
- if (content.length === 0) {
55836
- return null;
55837
- }
55838
- const data = JSON.parse(content);
55839
- if (typeof data.number !== "number" || typeof data.url !== "string") {
55734
+ const decoded = decodeCache(content);
55735
+ if (decoded === "miss") {
55840
55736
  return "miss";
55841
55737
  }
55842
- return data;
55738
+ return {
55739
+ ...decoded,
55740
+ stale: age > GIT_REVIEW_CACHE_TTL
55741
+ };
55843
55742
  } catch {
55844
55743
  return "miss";
55845
55744
  }
55846
55745
  }
55847
- function writeCache(cachePath, data, deps) {
55746
+ function writeCache(cachePath, data, checksQueried, deps) {
55848
55747
  try {
55849
55748
  const cacheDir = getGitReviewCacheDir(deps);
55850
55749
  if (!deps.existsSync(cacheDir)) {
55851
55750
  deps.mkdirSync(cacheDir, { recursive: true });
55852
55751
  }
55853
- deps.writeFileSync(cachePath, data ? JSON.stringify(data) : "", "utf-8");
55752
+ const stored = {
55753
+ version: 1,
55754
+ data,
55755
+ checksQueried: data === null || checksQueried
55756
+ };
55757
+ deps.writeFileSync(cachePath, JSON.stringify(stored), "utf-8");
55854
55758
  } catch {}
55855
55759
  }
55856
55760
  function getOriginUrl(cwd2, deps) {
@@ -55931,11 +55835,18 @@ function getProviderCandidates(cwd2, deps) {
55931
55835
  }
55932
55836
  return authed;
55933
55837
  }
55934
- function isCliAvailable(cli, deps) {
55838
+ function getRemainingTimeout(deadline, deps) {
55839
+ const remaining = deadline - deps.now();
55840
+ if (remaining <= 0) {
55841
+ throw new GitReviewDeadlineError("Git review lookup deadline exceeded");
55842
+ }
55843
+ return Math.max(1, Math.min(CLI_TIMEOUT, remaining));
55844
+ }
55845
+ function isCliAvailable(cli, deadline, deps) {
55935
55846
  try {
55936
55847
  deps.execFileSync(cli, ["--version"], {
55937
55848
  stdio: ["pipe", "pipe", "ignore"],
55938
- timeout: CLI_TIMEOUT,
55849
+ timeout: getRemainingTimeout(deadline, deps),
55939
55850
  windowsHide: true
55940
55851
  });
55941
55852
  return true;
@@ -55966,7 +55877,33 @@ function mapGlabState(state) {
55966
55877
  return "LOCKED";
55967
55878
  return state.toUpperCase();
55968
55879
  }
55969
- function fetchFromGh(cwd2, repoRef, deps) {
55880
+ function errorText(error51) {
55881
+ if (!(error51 instanceof Error)) {
55882
+ return "";
55883
+ }
55884
+ const stderr = "stderr" in error51 ? error51.stderr : undefined;
55885
+ const stderrText = Buffer.isBuffer(stderr) ? stderr.toString("utf8") : stderr ?? "";
55886
+ return `${error51.message}
55887
+ ${stderrText}`.toLowerCase();
55888
+ }
55889
+ function isCiFieldUnavailableError(error51) {
55890
+ const text = errorText(error51);
55891
+ return text.includes("statuscheckrollup") || text.includes("resource not accessible by integration");
55892
+ }
55893
+ function queryGhPr(cwd2, args, fields, deadline, deps) {
55894
+ const output = deps.execFileSync("gh", [...args, "--json", fields], {
55895
+ encoding: "utf8",
55896
+ stdio: ["pipe", "pipe", "pipe"],
55897
+ cwd: cwd2,
55898
+ timeout: getRemainingTimeout(deadline, deps),
55899
+ windowsHide: true
55900
+ }).trim();
55901
+ if (output.length === 0) {
55902
+ return null;
55903
+ }
55904
+ return JSON.parse(output);
55905
+ }
55906
+ function fetchFromGh(cwd2, repoRef, includeChecks, deadline, deps) {
55970
55907
  const args = ["pr", "view"];
55971
55908
  if (repoRef) {
55972
55909
  const branch = getCurrentBranch(cwd2, deps);
@@ -55975,18 +55912,22 @@ function fetchFromGh(cwd2, repoRef, deps) {
55975
55912
  }
55976
55913
  args.push(branch, "--repo", repoRef);
55977
55914
  }
55978
- args.push("--json", "url,number,title,state,reviewDecision");
55979
- const output = deps.execFileSync("gh", args, {
55980
- encoding: "utf8",
55981
- stdio: ["pipe", "pipe", "ignore"],
55982
- cwd: cwd2,
55983
- timeout: CLI_TIMEOUT,
55984
- windowsHide: true
55985
- }).trim();
55986
- if (output.length === 0) {
55915
+ let parsed;
55916
+ if (includeChecks) {
55917
+ try {
55918
+ parsed = queryGhPr(cwd2, args, GH_PR_WITH_CHECKS_FIELDS, deadline, deps);
55919
+ } catch (error51) {
55920
+ if (!isCiFieldUnavailableError(error51)) {
55921
+ throw error51;
55922
+ }
55923
+ parsed = queryGhPr(cwd2, args, GH_PR_METADATA_FIELDS, deadline, deps);
55924
+ }
55925
+ } else {
55926
+ parsed = queryGhPr(cwd2, args, GH_PR_METADATA_FIELDS, deadline, deps);
55927
+ }
55928
+ if (!parsed) {
55987
55929
  return null;
55988
55930
  }
55989
- const parsed = JSON.parse(output);
55990
55931
  if (typeof parsed.number !== "number" || typeof parsed.url !== "string") {
55991
55932
  return null;
55992
55933
  }
@@ -55996,10 +55937,11 @@ function fetchFromGh(cwd2, repoRef, deps) {
55996
55937
  title: typeof parsed.title === "string" ? parsed.title : "",
55997
55938
  state: typeof parsed.state === "string" ? parsed.state : "",
55998
55939
  reviewDecision: typeof parsed.reviewDecision === "string" ? parsed.reviewDecision : "",
55999
- provider: "gh"
55940
+ provider: "gh",
55941
+ checks: computeCiRollup(parsed.statusCheckRollup) ?? undefined
56000
55942
  };
56001
55943
  }
56002
- function fetchFromGlab(cwd2, repoRef, deps) {
55944
+ function fetchFromGlab(cwd2, repoRef, deadline, deps) {
56003
55945
  const args = ["mr", "view"];
56004
55946
  if (repoRef) {
56005
55947
  const branch = getCurrentBranch(cwd2, deps);
@@ -56013,7 +55955,7 @@ function fetchFromGlab(cwd2, repoRef, deps) {
56013
55955
  encoding: "utf8",
56014
55956
  stdio: ["pipe", "pipe", "ignore"],
56015
55957
  cwd: cwd2,
56016
- timeout: CLI_TIMEOUT,
55958
+ timeout: getRemainingTimeout(deadline, deps),
56017
55959
  windowsHide: true
56018
55960
  }).trim();
56019
55961
  if (output.length === 0) {
@@ -56032,72 +55974,440 @@ function fetchFromGlab(cwd2, repoRef, deps) {
56032
55974
  provider: "glab"
56033
55975
  };
56034
55976
  }
56035
- function fetchFromProvider(provider, cwd2, repoRef, deps) {
56036
- const fetchFn = provider === "gh" ? fetchFromGh : fetchFromGlab;
55977
+ function fetchFromProvider(provider, cwd2, repoRef, includeChecks, deadline, deps) {
55978
+ const fetch2 = (targetRepoRef) => provider === "gh" ? fetchFromGh(cwd2, targetRepoRef, includeChecks, deadline, deps) : fetchFromGlab(cwd2, targetRepoRef, deadline, deps);
56037
55979
  try {
56038
- const unpinned = fetchFn(cwd2, null, deps);
55980
+ const unpinned = fetch2(null);
56039
55981
  if (unpinned) {
56040
55982
  return unpinned;
56041
55983
  }
56042
55984
  } catch {}
56043
55985
  if (repoRef) {
56044
- return fetchFn(cwd2, repoRef, deps);
55986
+ return fetch2(repoRef);
55987
+ }
55988
+ return null;
55989
+ }
55990
+ function fetchGitReviewData(cwd2, deps = DEFAULT_GIT_REVIEW_CACHE_DEPS, options = {}) {
55991
+ const includeChecks = options.includeChecks ?? false;
55992
+ const cachePath = getCachePath2(cwd2, getCacheRef(cwd2, deps), deps);
55993
+ const cached2 = readCache(cachePath, deps);
55994
+ if (cached2 !== "miss" && !cached2.stale && (!includeChecks || cached2.checksQueried)) {
55995
+ return cached2.data;
55996
+ }
55997
+ const repoRef = getOriginRepoRef(cwd2, deps);
55998
+ const deadline = deps.now() + CLI_TIMEOUT;
55999
+ for (const provider of getProviderCandidates(cwd2, deps)) {
56000
+ if (!isCliAvailable(provider, deadline, deps)) {
56001
+ continue;
56002
+ }
56003
+ try {
56004
+ const data = fetchFromProvider(provider, cwd2, repoRef, includeChecks, deadline, deps);
56005
+ if (data) {
56006
+ writeCache(cachePath, data, includeChecks, deps);
56007
+ return data;
56008
+ }
56009
+ } catch {}
56010
+ }
56011
+ if (cached2 !== "miss" && cached2.data !== null) {
56012
+ return cached2.data;
56013
+ }
56014
+ writeCache(cachePath, null, true, deps);
56015
+ return null;
56016
+ }
56017
+ function getRefreshLockPath(cachePath) {
56018
+ return `${cachePath}.lock`;
56019
+ }
56020
+ function releaseRefreshLock(lockPath, deps) {
56021
+ try {
56022
+ deps.unlinkSync(lockPath);
56023
+ } catch {}
56024
+ }
56025
+ function createRefreshLock(cachePath, deps) {
56026
+ const cacheDir = getGitReviewCacheDir(deps);
56027
+ try {
56028
+ if (!deps.existsSync(cacheDir)) {
56029
+ deps.mkdirSync(cacheDir, { recursive: true });
56030
+ }
56031
+ } catch {
56032
+ return null;
56033
+ }
56034
+ const lockPath = getRefreshLockPath(cachePath);
56035
+ for (let attempt2 = 0;attempt2 < 2; attempt2++) {
56036
+ try {
56037
+ const descriptor = deps.openSync(lockPath, "wx");
56038
+ deps.closeSync(descriptor);
56039
+ return lockPath;
56040
+ } catch {
56041
+ try {
56042
+ const age = deps.now() - deps.statSync(lockPath).mtimeMs;
56043
+ if (age <= REFRESH_LOCK_STALE_MS) {
56044
+ return null;
56045
+ }
56046
+ deps.unlinkSync(lockPath);
56047
+ } catch {
56048
+ return null;
56049
+ }
56050
+ }
56051
+ }
56052
+ return null;
56053
+ }
56054
+ function scheduleRefresh(cwd2, cachePath, includeChecks, deps) {
56055
+ const scriptPath = deps.getScriptPath();
56056
+ if (!scriptPath) {
56057
+ return;
56058
+ }
56059
+ const lockPath = createRefreshLock(cachePath, deps);
56060
+ if (!lockPath) {
56061
+ return;
56062
+ }
56063
+ try {
56064
+ const child = deps.spawn(deps.getExecPath(), [
56065
+ scriptPath,
56066
+ GIT_REVIEW_REFRESH_FLAG,
56067
+ cwd2,
56068
+ includeChecks ? "checks" : "metadata",
56069
+ lockPath
56070
+ ], {
56071
+ detached: true,
56072
+ stdio: "ignore",
56073
+ windowsHide: true
56074
+ });
56075
+ child.unref();
56076
+ } catch {
56077
+ releaseRefreshLock(lockPath, deps);
56078
+ }
56079
+ }
56080
+ function getCachedGitReviewData(cwd2, options = {}, deps = DEFAULT_GIT_REVIEW_CACHE_DEPS) {
56081
+ const includeChecks = options.includeChecks ?? false;
56082
+ const cachePath = getCachePath2(cwd2, getCacheRef(cwd2, deps), deps);
56083
+ const cached2 = readCache(cachePath, deps);
56084
+ const needsRefresh = cached2 === "miss" || cached2.stale || includeChecks && !cached2.checksQueried;
56085
+ if (needsRefresh) {
56086
+ scheduleRefresh(cwd2, cachePath, includeChecks, deps);
56087
+ }
56088
+ return cached2 === "miss" ? null : cached2.data;
56089
+ }
56090
+ function refreshGitReviewCacheFromCli(cwd2, options, lockPath, deps = DEFAULT_GIT_REVIEW_CACHE_DEPS) {
56091
+ const expectedLockPath = getRefreshLockPath(getCachePath2(cwd2, getCacheRef(cwd2, deps), deps));
56092
+ try {
56093
+ fetchGitReviewData(cwd2, deps, options);
56094
+ } finally {
56095
+ if (lockPath === expectedLockPath) {
56096
+ releaseRefreshLock(lockPath, deps);
56097
+ }
56098
+ }
56099
+ }
56100
+ function getGitReviewStatusLabel(state, reviewDecision) {
56101
+ if (state === "MERGED")
56102
+ return "MERGED";
56103
+ if (state === "CLOSED")
56104
+ return "CLOSED";
56105
+ if (reviewDecision === "APPROVED")
56106
+ return "APPROVED";
56107
+ if (reviewDecision === "CHANGES_REQUESTED")
56108
+ return "CHANGES_REQ";
56109
+ if (state === "OPEN")
56110
+ return "OPEN";
56111
+ return state;
56112
+ }
56113
+ function truncateTitle(title, maxWidth) {
56114
+ const limit = maxWidth ?? DEFAULT_TITLE_MAX_WIDTH;
56115
+ if (title.length <= limit)
56116
+ return title;
56117
+ return `${title.slice(0, limit - 1)}…`;
56118
+ }
56119
+ var GIT_REVIEW_CACHE_TTL = 30000, CLI_TIMEOUT = 5000, REFRESH_LOCK_STALE_MS = 30000, DEFAULT_TITLE_MAX_WIDTH = 30, GH_PR_METADATA_FIELDS = "url,number,title,state,reviewDecision", GH_PR_WITH_CHECKS_FIELDS, GIT_REVIEW_REFRESH_FLAG = "--internal-refresh-git-review-cache", DEFAULT_GIT_REVIEW_CACHE_DEPS, GitReviewDeadlineError;
56120
+ var init_git_review_cache = __esm(() => {
56121
+ init_git_remote();
56122
+ GH_PR_WITH_CHECKS_FIELDS = `${GH_PR_METADATA_FIELDS},statusCheckRollup`;
56123
+ DEFAULT_GIT_REVIEW_CACHE_DEPS = {
56124
+ closeSync,
56125
+ execFileSync: execFileSync2,
56126
+ existsSync: existsSync2,
56127
+ getExecPath: () => process.execPath,
56128
+ mkdirSync: mkdirSync2,
56129
+ openSync,
56130
+ readFileSync: readFileSync3,
56131
+ getScriptPath: () => process.argv[1],
56132
+ spawn,
56133
+ statSync: statSync2,
56134
+ unlinkSync,
56135
+ writeFileSync: writeFileSync2,
56136
+ getHomedir: os4.homedir,
56137
+ now: Date.now
56138
+ };
56139
+ GitReviewDeadlineError = class GitReviewDeadlineError extends Error {
56140
+ };
56141
+ });
56142
+
56143
+ // src/widgets/GitCiStatus.ts
56144
+ function buildDisplay(checks3, rawValue) {
56145
+ if (rawValue)
56146
+ return checks3.state;
56147
+ const parts = [];
56148
+ if (checks3.failing > 0)
56149
+ parts.push(`${SYMBOLS.failing}${checks3.failing}`);
56150
+ if (checks3.pending > 0)
56151
+ parts.push(`${SYMBOLS.pending}${checks3.pending}`);
56152
+ if (checks3.success > 0)
56153
+ parts.push(`${SYMBOLS.success}${checks3.success}`);
56154
+ return parts.length > 0 ? parts.join(" ") : `${SYMBOLS[checks3.state]}0`;
56155
+ }
56156
+
56157
+ class GitCiStatusWidget {
56158
+ deps;
56159
+ constructor(deps = DEFAULT_DEPS) {
56160
+ this.deps = deps;
56161
+ }
56162
+ getDefaultColor() {
56163
+ return "green";
56164
+ }
56165
+ getDescription() {
56166
+ return "Shows CI check status for the current branch's PR (GitHub only)";
56167
+ }
56168
+ getDisplayName() {
56169
+ return "Git CI Status";
56170
+ }
56171
+ getCategory() {
56172
+ return "Git";
56173
+ }
56174
+ getEditorDisplay(item) {
56175
+ return {
56176
+ displayText: this.getDisplayName(),
56177
+ modifierText: getHideNoGitModifierText(item)
56178
+ };
56179
+ }
56180
+ handleEditorAction(action, item) {
56181
+ return handleToggleNoGitAction(action, item);
56182
+ }
56183
+ render(item, context, _settings) {
56184
+ const rawValue = item.rawValue ?? false;
56185
+ if (context.isPreview) {
56186
+ return buildDisplay(PREVIEW_CHECKS, rawValue);
56187
+ }
56188
+ if (!this.deps.isInsideGitWorkTree(context)) {
56189
+ return isHideNoGitEnabled(item) ? null : "(no git)";
56190
+ }
56191
+ const cwd2 = this.deps.resolveGitCwd(context) ?? this.deps.getProcessCwd();
56192
+ const checks3 = this.deps.getCachedGitReviewData(cwd2, { includeChecks: true })?.checks;
56193
+ if (!checks3) {
56194
+ return NO_CHECKS;
56195
+ }
56196
+ return buildDisplay(checks3, rawValue);
56197
+ }
56198
+ getCustomKeybinds() {
56199
+ return getHideNoGitKeybinds();
56200
+ }
56201
+ supportsRawValue() {
56202
+ return true;
56203
+ }
56204
+ supportsColors(_item) {
56205
+ return true;
56206
+ }
56207
+ }
56208
+ var NO_CHECKS = "-", SYMBOLS, DEFAULT_DEPS, PREVIEW_CHECKS;
56209
+ var init_GitCiStatus = __esm(() => {
56210
+ init_git();
56211
+ init_git_review_cache();
56212
+ init_git_no_git();
56213
+ SYMBOLS = {
56214
+ success: "✓",
56215
+ passing: "✓",
56216
+ failing: "✗",
56217
+ pending: "●"
56218
+ };
56219
+ DEFAULT_DEPS = {
56220
+ getCachedGitReviewData,
56221
+ getProcessCwd: () => process.cwd(),
56222
+ isInsideGitWorkTree,
56223
+ resolveGitCwd
56224
+ };
56225
+ PREVIEW_CHECKS = {
56226
+ state: "failing",
56227
+ failing: 1,
56228
+ pending: 1,
56229
+ success: 5
56230
+ };
56231
+ });
56232
+
56233
+ // src/widgets/GitCleanStatus.ts
56234
+ class GitCleanStatusWidget {
56235
+ getDefaultColor() {
56236
+ return "green";
56237
+ }
56238
+ getDescription() {
56239
+ return "Shows ✓ when the working tree is clean and ✗ when it is dirty";
56240
+ }
56241
+ getDisplayName() {
56242
+ return "Git Clean Status";
56243
+ }
56244
+ getCategory() {
56245
+ return "Git";
56246
+ }
56247
+ getEditorDisplay(item) {
56248
+ return {
56249
+ displayText: this.getDisplayName(),
56250
+ modifierText: getHideNoGitModifierText(item)
56251
+ };
56252
+ }
56253
+ handleEditorAction(action, item) {
56254
+ return handleToggleNoGitAction(action, item);
56255
+ }
56256
+ render(item, context, _settings) {
56257
+ const hideNoGit = isHideNoGitEnabled(item);
56258
+ if (context.isPreview) {
56259
+ return item.rawValue ? "clean" : "✓";
56260
+ }
56261
+ if (!isInsideGitWorkTree(context)) {
56262
+ return hideNoGit ? null : "(no git)";
56263
+ }
56264
+ const clean = this.isClean(context);
56265
+ if (item.rawValue) {
56266
+ return clean ? "clean" : "dirty";
56267
+ }
56268
+ return clean ? "✓" : "✗";
56269
+ }
56270
+ isClean(context) {
56271
+ const status = getGitStatus(context);
56272
+ return !status.staged && !status.unstaged && !status.untracked && !status.conflicts;
56273
+ }
56274
+ getCustomKeybinds() {
56275
+ return getHideNoGitKeybinds();
56276
+ }
56277
+ supportsRawValue() {
56278
+ return true;
56279
+ }
56280
+ supportsColors(_item) {
56281
+ return true;
56282
+ }
56283
+ }
56284
+ var init_GitCleanStatus = __esm(() => {
56285
+ init_git();
56286
+ init_git_no_git();
56287
+ });
56288
+
56289
+ // src/widgets/GitRootDir.ts
56290
+ class GitRootDirWidget {
56291
+ getDefaultColor() {
56292
+ return "cyan";
56293
+ }
56294
+ getDescription() {
56295
+ return "Shows the git repository root directory name";
56296
+ }
56297
+ getDisplayName() {
56298
+ return "Git Root Dir";
56299
+ }
56300
+ getCategory() {
56301
+ return "Git";
56302
+ }
56303
+ getEditorDisplay(item) {
56304
+ const ideLinkMode = this.getIdeLinkMode(item);
56305
+ const modifiers = [];
56306
+ const noGitText = getHideNoGitModifierText(item);
56307
+ if (noGitText)
56308
+ modifiers.push("hide 'no git'");
56309
+ if (ideLinkMode)
56310
+ modifiers.push(IDE_LINK_LABELS[ideLinkMode]);
56311
+ const maxWidthText = getMaxWidthModifier(item);
56312
+ if (maxWidthText)
56313
+ modifiers.push(maxWidthText);
56314
+ return {
56315
+ displayText: this.getDisplayName(),
56316
+ modifierText: makeModifierText(modifiers)
56317
+ };
56318
+ }
56319
+ handleEditorAction(action, item) {
56320
+ if (action === TOGGLE_LINK_ACTION2) {
56321
+ return this.cycleIdeLinkMode(item);
56322
+ }
56323
+ return handleToggleNoGitAction(action, item);
56324
+ }
56325
+ render(item, context, _settings) {
56326
+ const hideNoGit = isHideNoGitEnabled(item);
56327
+ const ideLinkMode = this.getIdeLinkMode(item);
56328
+ if (context.isPreview) {
56329
+ const name2 = "my-repo";
56330
+ return ideLinkMode ? renderOsc8Link(buildIdeFileUrl("/Users/example/my-repo", ideLinkMode), name2) : name2;
56331
+ }
56332
+ if (!isInsideGitWorkTree(context)) {
56333
+ return hideNoGit ? null : "no git";
56334
+ }
56335
+ const rootDir = this.getGitRootDir(context);
56336
+ if (!rootDir) {
56337
+ return hideNoGit ? null : "no git";
56338
+ }
56339
+ const name = applyMaxWidth(this.getRootDirName(rootDir), item.maxWidth);
56340
+ if (ideLinkMode) {
56341
+ return renderOsc8Link(buildIdeFileUrl(rootDir, ideLinkMode), name);
56342
+ }
56343
+ return name;
56344
+ }
56345
+ getGitRootDir(context) {
56346
+ return runGit("rev-parse --show-toplevel", context);
56347
+ }
56348
+ getRootDirName(rootDir) {
56349
+ const trimmedRootDir = rootDir.replace(/[\\/]+$/, "");
56350
+ const normalizedRootDir = trimmedRootDir.length > 0 ? trimmedRootDir : rootDir;
56351
+ const parts = normalizedRootDir.split(/[\\/]/).filter(Boolean);
56352
+ const lastPart = parts[parts.length - 1];
56353
+ return lastPart && lastPart.length > 0 ? lastPart : normalizedRootDir;
56354
+ }
56355
+ getCustomKeybinds() {
56356
+ return [
56357
+ ...getHideNoGitKeybinds(),
56358
+ { key: "l", label: "(l)ink to IDE", action: TOGGLE_LINK_ACTION2 },
56359
+ getMaxWidthKeybind()
56360
+ ];
56361
+ }
56362
+ renderEditor(props) {
56363
+ if (props.action === MAX_WIDTH_ACTION) {
56364
+ return renderMaxWidthEditor(props);
56365
+ }
56366
+ return null;
56045
56367
  }
56046
- return null;
56047
- }
56048
- function fetchGitReviewData(cwd2, deps = DEFAULT_GIT_REVIEW_CACHE_DEPS) {
56049
- const cachePath = getCachePath2(cwd2, getCacheRef(cwd2, deps), deps);
56050
- const cached2 = readCache(cachePath, deps);
56051
- if (cached2 !== "miss") {
56052
- return cached2;
56368
+ supportsRawValue() {
56369
+ return false;
56053
56370
  }
56054
- const repoRef = getOriginRepoRef(cwd2, deps);
56055
- for (const provider of getProviderCandidates(cwd2, deps)) {
56056
- if (!isCliAvailable(provider, deps)) {
56057
- continue;
56371
+ supportsColors(item) {
56372
+ return true;
56373
+ }
56374
+ getIdeLinkMode(item) {
56375
+ const configuredMode = item.metadata?.[IDE_LINK_KEY];
56376
+ if (configuredMode && IDE_LINK_MODES.includes(configuredMode)) {
56377
+ return configuredMode;
56058
56378
  }
56059
- try {
56060
- const data = fetchFromProvider(provider, cwd2, repoRef, deps);
56061
- if (data) {
56062
- writeCache(cachePath, data, deps);
56063
- return data;
56064
- }
56065
- } catch {}
56379
+ if (isMetadataFlagEnabled(item, LEGACY_CURSOR_LINK_KEY)) {
56380
+ return "cursor";
56381
+ }
56382
+ return null;
56383
+ }
56384
+ cycleIdeLinkMode(item) {
56385
+ const currentMode = this.getIdeLinkMode(item);
56386
+ const currentIndex = currentMode ? IDE_LINK_MODES.indexOf(currentMode) : -1;
56387
+ const nextMode = currentIndex === IDE_LINK_MODES.length - 1 ? null : IDE_LINK_MODES[currentIndex + 1] ?? null;
56388
+ const {
56389
+ [IDE_LINK_KEY]: removedIdeLink,
56390
+ [LEGACY_CURSOR_LINK_KEY]: removedLegacyLink,
56391
+ ...restMetadata
56392
+ } = item.metadata ?? {};
56393
+ return {
56394
+ ...item,
56395
+ metadata: nextMode ? {
56396
+ ...restMetadata,
56397
+ [IDE_LINK_KEY]: nextMode
56398
+ } : Object.keys(restMetadata).length > 0 ? restMetadata : undefined
56399
+ };
56066
56400
  }
56067
- writeCache(cachePath, null, deps);
56068
- return null;
56069
- }
56070
- function getGitReviewStatusLabel(state, reviewDecision) {
56071
- if (state === "MERGED")
56072
- return "MERGED";
56073
- if (state === "CLOSED")
56074
- return "CLOSED";
56075
- if (reviewDecision === "APPROVED")
56076
- return "APPROVED";
56077
- if (reviewDecision === "CHANGES_REQUESTED")
56078
- return "CHANGES_REQ";
56079
- if (state === "OPEN")
56080
- return "OPEN";
56081
- return state;
56082
- }
56083
- function truncateTitle(title, maxWidth) {
56084
- const limit = maxWidth ?? DEFAULT_TITLE_MAX_WIDTH;
56085
- if (title.length <= limit)
56086
- return title;
56087
- return `${title.slice(0, limit - 1)}…`;
56088
56401
  }
56089
- var GIT_REVIEW_CACHE_TTL = 30000, CLI_TIMEOUT = 5000, DEFAULT_TITLE_MAX_WIDTH = 30, DEFAULT_GIT_REVIEW_CACHE_DEPS;
56090
- var init_git_review_cache = __esm(() => {
56091
- init_git_remote();
56092
- DEFAULT_GIT_REVIEW_CACHE_DEPS = {
56093
- execFileSync: execFileSync2,
56094
- existsSync: existsSync2,
56095
- mkdirSync: mkdirSync2,
56096
- readFileSync: readFileSync3,
56097
- statSync: statSync2,
56098
- writeFileSync: writeFileSync2,
56099
- getHomedir: os4.homedir,
56100
- now: Date.now
56402
+ var IDE_LINK_KEY = "linkToIDE", LEGACY_CURSOR_LINK_KEY = "linkToCursor", TOGGLE_LINK_ACTION2 = "toggle-link", IDE_LINK_LABELS;
56403
+ var init_GitRootDir = __esm(async () => {
56404
+ init_git();
56405
+ init_hyperlink();
56406
+ init_git_no_git();
56407
+ await init_max_width();
56408
+ IDE_LINK_LABELS = {
56409
+ vscode: "link-vscode",
56410
+ cursor: "link-cursor"
56101
56411
  };
56102
56412
  });
56103
56413
 
@@ -56118,7 +56428,7 @@ function resolvePrNoun(pr, context, deps) {
56118
56428
  }
56119
56429
  return "PR";
56120
56430
  }
56121
- function buildDisplay(item, pr, showStatus, showTitle, noun) {
56431
+ function buildDisplay2(item, pr, showStatus, showTitle, noun) {
56122
56432
  const linkText = item.rawValue ? `#${pr.number}` : `${noun} #${pr.number}`;
56123
56433
  const parts = [renderOsc8Link(pr.url, linkText)];
56124
56434
  if (showStatus) {
@@ -56178,17 +56488,17 @@ class GitPrWidget {
56178
56488
  const showStatus = !isMetadataFlagEnabled(item, HIDE_STATUS_KEY);
56179
56489
  const showTitle = !isMetadataFlagEnabled(item, HIDE_TITLE_KEY);
56180
56490
  if (context.isPreview) {
56181
- return buildDisplay(item, PREVIEW_PR, showStatus, showTitle, resolvePrNoun(PREVIEW_PR, context, this.deps));
56491
+ return buildDisplay2(item, PREVIEW_PR, showStatus, showTitle, resolvePrNoun(PREVIEW_PR, context, this.deps));
56182
56492
  }
56183
56493
  if (!this.deps.isInsideGitWorkTree(context)) {
56184
56494
  return hideNoGit ? null : `(no ${resolvePrNoun(null, context, this.deps)})`;
56185
56495
  }
56186
56496
  const cwd2 = this.deps.resolveGitCwd(context) ?? this.deps.getProcessCwd();
56187
- const prData = this.deps.fetchGitReviewData(cwd2);
56497
+ const prData = this.deps.getCachedGitReviewData(cwd2, { includeChecks: context.gitReviewNeedsChecks ?? false });
56188
56498
  if (!prData) {
56189
56499
  return hideNoGit ? null : `(no ${resolvePrNoun(null, context, this.deps)})`;
56190
56500
  }
56191
- return buildDisplay(item, prData, showStatus, showTitle, resolvePrNoun(prData, context, this.deps));
56501
+ return buildDisplay2(item, prData, showStatus, showTitle, resolvePrNoun(prData, context, this.deps));
56192
56502
  }
56193
56503
  getCustomKeybinds() {
56194
56504
  return [
@@ -56212,7 +56522,7 @@ var init_GitPr = __esm(() => {
56212
56522
  init_hyperlink();
56213
56523
  init_git_no_git();
56214
56524
  DEFAULT_GIT_PR_WIDGET_DEPS = {
56215
- fetchGitReviewData,
56525
+ getCachedGitReviewData,
56216
56526
  getProcessCwd: () => process.cwd(),
56217
56527
  getRemoteInfo,
56218
56528
  isInsideGitWorkTree,
@@ -57977,7 +58287,7 @@ function getTerminalWidth() {
57977
58287
  function canDetectTerminalWidth() {
57978
58288
  return probeTerminalWidth() !== null;
57979
58289
  }
57980
- var __dirname = "/home/runner/work/ccstatusline/ccstatusline/src/utils", PACKAGE_VERSION = "2.2.23";
58290
+ var __dirname = "/home/runner/work/ccstatusline/ccstatusline/src/utils", PACKAGE_VERSION = "2.2.25";
57981
58291
  var init_terminal = () => {};
57982
58292
 
57983
58293
  // src/utils/format-tokens.ts
@@ -57997,6 +58307,13 @@ function maybeApplyForegroundGradient(line, settings, colorLevel) {
57997
58307
  const stops = parseGradientSpec(settings.overrideForegroundColor);
57998
58308
  return stops ? applyLineGradient(line, stops, colorLevel) : line;
57999
58309
  }
58310
+ function resolvePaddingSides(padding, side) {
58311
+ if (side === "left")
58312
+ return { leading: padding, trailing: "" };
58313
+ if (side === "right")
58314
+ return { leading: "", trailing: padding };
58315
+ return { leading: padding, trailing: padding };
58316
+ }
58000
58317
  function resolveEffectiveTerminalWidth(detectedWidth, settings, context) {
58001
58318
  if (!detectedWidth) {
58002
58319
  return null;
@@ -58117,6 +58434,7 @@ function renderPowerlineStatusLine(widgets, settings, context, lineIndex = 0, gl
58117
58434
  }
58118
58435
  if (widgetText) {
58119
58436
  const padding = settings.defaultPadding ?? "";
58437
+ const { leading: sideLeadingPadding, trailing: sideTrailingPadding } = resolvePaddingSides(padding, settings.defaultPaddingSide);
58120
58438
  if (settings.overrideForegroundColor && settings.overrideForegroundColor !== "none" && widget.type === "custom-command" && widget.preserveColors) {
58121
58439
  widgetText = stripSgrCodes(widgetText);
58122
58440
  }
@@ -58125,8 +58443,8 @@ function renderPowerlineStatusLine(widgets, settings, context, lineIndex = 0, gl
58125
58443
  const mergesWithNext = canMergeWithNextRenderedWidget(actualPreRenderedIndex);
58126
58444
  const omitLeadingPadding = previousRenderedWidget?.merge === "no-padding" && canMergeWithNextRenderedWidget(previousRenderedIndex ?? undefined);
58127
58445
  const omitTrailingPadding = widget.merge === "no-padding" && mergesWithNext;
58128
- const leadingPadding = omitLeadingPadding ? "" : padding;
58129
- const trailingPadding = omitTrailingPadding ? "" : padding;
58446
+ const leadingPadding = omitLeadingPadding ? "" : sideLeadingPadding;
58447
+ const trailingPadding = omitTrailingPadding ? "" : sideTrailingPadding;
58130
58448
  const paddedText = `${leadingPadding}${widgetText}${trailingPadding}`;
58131
58449
  let fgColor = widget.color ?? defaultColor;
58132
58450
  let bgColor = widget.backgroundColor;
@@ -58507,7 +58825,8 @@ function preRenderAllWidgets(allLinesWidgets, settings, context) {
58507
58825
  function calculateMaxWidthsFromPreRendered(preRenderedLines, settings) {
58508
58826
  const maxWidths = [];
58509
58827
  const defaultPadding = settings.defaultPadding ?? "";
58510
- const paddingLength = defaultPadding.length;
58828
+ const { leading: sideLeadingPadding, trailing: sideTrailingPadding } = resolvePaddingSides(defaultPadding, settings.defaultPaddingSide);
58829
+ const paddingPairLength = sideLeadingPadding.length + sideTrailingPadding.length;
58511
58830
  for (const preRenderedLine of preRenderedLines) {
58512
58831
  const isSeparatorBoundary = (entry) => entry?.widget.type === "separator" || entry?.widget.type === "flex-separator";
58513
58832
  const hasNextRenderedWidgetBeforeSeparator = (originalIndex) => {
@@ -58533,7 +58852,7 @@ function calculateMaxWidthsFromPreRendered(preRenderedLines, settings) {
58533
58852
  continue;
58534
58853
  if (widget.widget.excludeFromAutoAlign)
58535
58854
  break;
58536
- let totalWidth = widget.plainLength + paddingLength * 2;
58855
+ let totalWidth = widget.plainLength + paddingPairLength;
58537
58856
  let j = i;
58538
58857
  while (j < renderedWidgets.length - 1 && renderedWidgets[j]?.mergesWithNext) {
58539
58858
  j++;
@@ -58542,7 +58861,7 @@ function calculateMaxWidthsFromPreRendered(preRenderedLines, settings) {
58542
58861
  if (renderedWidgets[j - 1]?.widget.merge === "no-padding") {
58543
58862
  totalWidth += nextWidget.plainLength;
58544
58863
  } else {
58545
- totalWidth += nextWidget.plainLength + paddingLength * 2;
58864
+ totalWidth += nextWidget.plainLength + paddingPairLength;
58546
58865
  }
58547
58866
  }
58548
58867
  }
@@ -58675,6 +58994,7 @@ function renderStatusLine(widgets, settings, context, preRenderedWidgets, preCal
58675
58994
  }
58676
58995
  const finalElements = [];
58677
58996
  const padding = settings.defaultPadding ?? "";
58997
+ const { leading: sideLeadingPadding, trailing: sideTrailingPadding } = resolvePaddingSides(padding, settings.defaultPaddingSide);
58678
58998
  const defaultSep = settings.defaultSeparator ? formatSeparator(settings.defaultSeparator) : "";
58679
58999
  elements.forEach((elem, index) => {
58680
59000
  const prevElem = index > 0 ? elements[index - 1] : null;
@@ -58708,14 +59028,13 @@ function renderStatusLine(widgets, settings, context, preRenderedWidgets, preCal
58708
59028
  const omitTrailingPadding = elem.widget?.merge === "no-padding" && nextElem && nextElem.type !== "separator" && nextElem.type !== "flex-separator";
58709
59029
  const hasColorOverride = Boolean(settings.overrideBackgroundColor && settings.overrideBackgroundColor !== "none") || Boolean(settings.overrideForegroundColor && settings.overrideForegroundColor !== "none");
58710
59030
  if (padding && (elem.widget?.backgroundColor || hasColorOverride)) {
58711
- const leadingPadding = omitLeadingPadding ? "" : applyColorsWithOverride(padding, undefined, elem.widget?.backgroundColor);
58712
- const trailingPadding = omitTrailingPadding ? "" : applyColorsWithOverride(padding, undefined, elem.widget?.backgroundColor);
59031
+ const leadingPadding = omitLeadingPadding || !sideLeadingPadding ? "" : applyColorsWithOverride(sideLeadingPadding, undefined, elem.widget?.backgroundColor);
59032
+ const trailingPadding = omitTrailingPadding || !sideTrailingPadding ? "" : applyColorsWithOverride(sideTrailingPadding, undefined, elem.widget?.backgroundColor);
58713
59033
  const paddedContent = leadingPadding + elem.content + trailingPadding;
58714
59034
  finalElements.push(paddedContent);
58715
59035
  } else if (padding) {
58716
- const protectedPadding = source_default.reset(padding);
58717
- const leadingPadding = omitLeadingPadding ? "" : protectedPadding;
58718
- const trailingPadding = omitTrailingPadding ? "" : protectedPadding;
59036
+ const leadingPadding = omitLeadingPadding || !sideLeadingPadding ? "" : source_default.reset(sideLeadingPadding);
59037
+ const trailingPadding = omitTrailingPadding || !sideTrailingPadding ? "" : source_default.reset(sideTrailingPadding);
58719
59038
  finalElements.push(leadingPadding + elem.content + trailingPadding);
58720
59039
  } else {
58721
59040
  finalElements.push(elem.content);
@@ -69084,26 +69403,43 @@ function getFormat(item) {
69084
69403
  const f = item.metadata?.format;
69085
69404
  return FORMATS.includes(f ?? "") ? f : DEFAULT_FORMAT;
69086
69405
  }
69406
+ function canUseNerdFont(item) {
69407
+ const format = getFormat(item);
69408
+ return format === "icon-dash-letter" || format === "icon-letter" || format === "icon";
69409
+ }
69410
+ function removeNerdFont(item) {
69411
+ const { [NERD_FONT_METADATA_KEY]: removedNerdFont, ...restMetadata } = item.metadata ?? {};
69412
+ return {
69413
+ ...item,
69414
+ metadata: Object.keys(restMetadata).length > 0 ? restMetadata : undefined
69415
+ };
69416
+ }
69087
69417
  function setFormat(item, format) {
69418
+ let updatedItem;
69088
69419
  if (format === DEFAULT_FORMAT) {
69089
69420
  const { format: removedFormat, ...restMetadata } = item.metadata ?? {};
69090
- return {
69421
+ updatedItem = {
69091
69422
  ...item,
69092
69423
  metadata: Object.keys(restMetadata).length > 0 ? restMetadata : undefined
69093
69424
  };
69425
+ } else {
69426
+ updatedItem = {
69427
+ ...item,
69428
+ metadata: {
69429
+ ...item.metadata ?? {},
69430
+ format
69431
+ }
69432
+ };
69094
69433
  }
69095
- return {
69096
- ...item,
69097
- metadata: {
69098
- ...item.metadata ?? {},
69099
- format
69100
- }
69101
- };
69434
+ return canUseNerdFont(updatedItem) ? updatedItem : removeNerdFont(updatedItem);
69102
69435
  }
69103
69436
  function isNerdFontEnabled(item) {
69104
- return item.metadata?.[NERD_FONT_METADATA_KEY] === "true";
69437
+ return canUseNerdFont(item) && item.metadata?.[NERD_FONT_METADATA_KEY] === "true";
69105
69438
  }
69106
69439
  function toggleNerdFont(item) {
69440
+ if (!canUseNerdFont(item)) {
69441
+ return removeNerdFont(item);
69442
+ }
69107
69443
  if (!isNerdFontEnabled(item)) {
69108
69444
  return {
69109
69445
  ...item,
@@ -69113,11 +69449,7 @@ function toggleNerdFont(item) {
69113
69449
  }
69114
69450
  };
69115
69451
  }
69116
- const { [NERD_FONT_METADATA_KEY]: removedNerdFont, ...restMetadata } = item.metadata ?? {};
69117
- return {
69118
- ...item,
69119
- metadata: Object.keys(restMetadata).length > 0 ? restMetadata : undefined
69120
- };
69452
+ return removeNerdFont(item);
69121
69453
  }
69122
69454
  function formatMode(mode, format, icon) {
69123
69455
  const letter = mode === "NORMAL" ? "N" : mode === "INSERT" ? "I" : mode[0] ?? mode;
@@ -69179,11 +69511,14 @@ class VimModeWidget {
69179
69511
  return null;
69180
69512
  return formatMode(mode, format, icon);
69181
69513
  }
69182
- getCustomKeybinds() {
69183
- return [
69184
- { key: "f", label: "(f)ormat", action: CYCLE_FORMAT_ACTION },
69185
- { key: "n", label: "(n)erd font", action: TOGGLE_NERD_FONT_ACTION }
69514
+ getCustomKeybinds(item) {
69515
+ const keybinds = [
69516
+ { key: "f", label: "(f)ormat", action: CYCLE_FORMAT_ACTION }
69186
69517
  ];
69518
+ if (item === undefined || canUseNerdFont(item)) {
69519
+ keybinds.push({ key: "n", label: "(n)erd font", action: TOGGLE_NERD_FONT_ACTION });
69520
+ }
69521
+ return keybinds;
69187
69522
  }
69188
69523
  supportsRawValue() {
69189
69524
  return false;
@@ -69408,7 +69743,7 @@ function getFormat2(item) {
69408
69743
  const format = item.metadata?.format;
69409
69744
  return FORMATS2.includes(format ?? "") ? format : DEFAULT_FORMAT2;
69410
69745
  }
69411
- function removeNerdFont(item) {
69746
+ function removeNerdFont2(item) {
69412
69747
  const { [NERD_FONT_METADATA_KEY2]: removedNerdFont, ...restMetadata } = item.metadata ?? {};
69413
69748
  return {
69414
69749
  ...item,
@@ -69513,7 +69848,7 @@ function formatStats(data, item, icon) {
69513
69848
  }
69514
69849
  function toggleNerdFont2(item) {
69515
69850
  if (getFormat2(item) !== DEFAULT_FORMAT2) {
69516
- return removeNerdFont(item);
69851
+ return removeNerdFont2(item);
69517
69852
  }
69518
69853
  if (!isNerdFontEnabled2(item)) {
69519
69854
  return {
@@ -69524,7 +69859,7 @@ function toggleNerdFont2(item) {
69524
69859
  }
69525
69860
  };
69526
69861
  }
69527
- return removeNerdFont(item);
69862
+ return removeNerdFont2(item);
69528
69863
  }
69529
69864
  function formatCount(count, format, icon) {
69530
69865
  switch (format) {
@@ -69658,31 +69993,47 @@ var init_CompactionCounter = __esm(async () => {
69658
69993
  });
69659
69994
  });
69660
69995
 
69661
- // src/widgets/VoiceStatus.ts
69996
+ // src/widgets/SandboxStatus.ts
69662
69997
  function getFormat3(item) {
69663
69998
  const f = item.metadata?.format;
69664
69999
  return FORMATS3.includes(f ?? "") ? f : DEFAULT_FORMAT3;
69665
70000
  }
70001
+ function canUseNerdFont2(item) {
70002
+ return getFormat3(item) === "glyph";
70003
+ }
70004
+ function removeNerdFont3(item) {
70005
+ const { [NERD_FONT_METADATA_KEY3]: removedNerdFont, ...restMetadata } = item.metadata ?? {};
70006
+ return {
70007
+ ...item,
70008
+ metadata: Object.keys(restMetadata).length > 0 ? restMetadata : undefined
70009
+ };
70010
+ }
69666
70011
  function setFormat3(item, format) {
70012
+ let updatedItem;
69667
70013
  if (format === DEFAULT_FORMAT3) {
69668
70014
  const { format: removedFormat, ...restMetadata } = item.metadata ?? {};
69669
- return {
70015
+ updatedItem = {
69670
70016
  ...item,
69671
70017
  metadata: Object.keys(restMetadata).length > 0 ? restMetadata : undefined
69672
70018
  };
70019
+ } else {
70020
+ updatedItem = {
70021
+ ...item,
70022
+ metadata: {
70023
+ ...item.metadata ?? {},
70024
+ format
70025
+ }
70026
+ };
69673
70027
  }
69674
- return {
69675
- ...item,
69676
- metadata: {
69677
- ...item.metadata ?? {},
69678
- format
69679
- }
69680
- };
70028
+ return canUseNerdFont2(updatedItem) ? updatedItem : removeNerdFont3(updatedItem);
69681
70029
  }
69682
70030
  function isNerdFontEnabled3(item) {
69683
- return item.metadata?.[NERD_FONT_METADATA_KEY3] === "true";
70031
+ return canUseNerdFont2(item) && item.metadata?.[NERD_FONT_METADATA_KEY3] === "true";
69684
70032
  }
69685
70033
  function toggleNerdFont3(item) {
70034
+ if (!canUseNerdFont2(item)) {
70035
+ return removeNerdFont3(item);
70036
+ }
69686
70037
  if (!isNerdFontEnabled3(item)) {
69687
70038
  return {
69688
70039
  ...item,
@@ -69692,25 +70043,167 @@ function toggleNerdFont3(item) {
69692
70043
  }
69693
70044
  };
69694
70045
  }
69695
- const { [NERD_FONT_METADATA_KEY3]: removedNerdFont, ...restMetadata } = item.metadata ?? {};
69696
- return {
69697
- ...item,
69698
- metadata: Object.keys(restMetadata).length > 0 ? restMetadata : undefined
69699
- };
70046
+ return removeNerdFont3(item);
70047
+ }
70048
+ function formatStatus(enabled, format, nerdFont, rawValue) {
70049
+ const stateText = enabled ? "ON" : "OFF";
70050
+ const glyph = nerdFont ? enabled ? LOCK_NERD_FONT : UNLOCK_NERD_FONT : enabled ? DOT_ON : DOT_OFF;
70051
+ switch (format) {
70052
+ case "glyph":
70053
+ return rawValue ? glyph : `SB: ${glyph}`;
70054
+ case "text":
70055
+ return rawValue ? stateText : `SB: ${stateText}`;
70056
+ case "word":
70057
+ return rawValue ? stateText : `Sandbox: ${stateText}`;
70058
+ }
70059
+ }
70060
+ function resolveSandboxConfigCwd(context) {
70061
+ const candidates = [
70062
+ context.data?.workspace?.project_dir,
70063
+ context.data?.cwd,
70064
+ context.data?.workspace?.current_dir
70065
+ ];
70066
+ return candidates.find((candidate) => typeof candidate === "string" && candidate.trim().length > 0);
70067
+ }
70068
+
70069
+ class SandboxStatusWidget {
70070
+ getDefaultColor() {
70071
+ return "green";
70072
+ }
70073
+ getDescription() {
70074
+ return [
70075
+ "Shows whether Claude Code bash sandbox mode is enabled",
70076
+ "Best effort: may not reflect active sandboxing when managed or CLI settings override it, or when sandbox initialization fails."
70077
+ ].join(`
70078
+ `);
70079
+ }
70080
+ getDisplayName() {
70081
+ return "Sandbox Status";
70082
+ }
70083
+ getCategory() {
70084
+ return "Core";
70085
+ }
70086
+ getEditorDisplay(item) {
70087
+ const modifiers = [getFormat3(item)];
70088
+ if (isNerdFontEnabled3(item)) {
70089
+ modifiers.push("nerd font");
70090
+ }
70091
+ return {
70092
+ displayText: this.getDisplayName(),
70093
+ modifierText: `(${modifiers.join(", ")})`
70094
+ };
70095
+ }
70096
+ handleEditorAction(action, item) {
70097
+ if (action === CYCLE_FORMAT_ACTION3) {
70098
+ const currentFormat = getFormat3(item);
70099
+ const nextFormat = FORMATS3[(FORMATS3.indexOf(currentFormat) + 1) % FORMATS3.length] ?? DEFAULT_FORMAT3;
70100
+ return setFormat3(item, nextFormat);
70101
+ }
70102
+ if (action === TOGGLE_NERD_FONT_ACTION3) {
70103
+ return toggleNerdFont3(item);
70104
+ }
70105
+ return null;
70106
+ }
70107
+ render(item, context, _settings) {
70108
+ const format = getFormat3(item);
70109
+ const nerdFont = isNerdFontEnabled3(item);
70110
+ if (context.isPreview) {
70111
+ return formatStatus(true, format, nerdFont, item.rawValue ?? false);
70112
+ }
70113
+ const config2 = getSandboxConfig(resolveSandboxConfigCwd(context));
70114
+ if (config2 === null) {
70115
+ return null;
70116
+ }
70117
+ return formatStatus(config2.enabled, format, nerdFont, item.rawValue ?? false);
70118
+ }
70119
+ getCustomKeybinds(item) {
70120
+ const keybinds = [
70121
+ { key: "f", label: "(f)ormat", action: CYCLE_FORMAT_ACTION3 }
70122
+ ];
70123
+ if (item === undefined || canUseNerdFont2(item)) {
70124
+ keybinds.push({ key: "n", label: "(n)erd font", action: TOGGLE_NERD_FONT_ACTION3 });
70125
+ }
70126
+ return keybinds;
70127
+ }
70128
+ supportsRawValue() {
70129
+ return true;
70130
+ }
70131
+ supportsColors(_item) {
70132
+ return true;
70133
+ }
70134
+ }
70135
+ var DOT_ON = "●", DOT_OFF = "○", LOCK_NERD_FONT = "", UNLOCK_NERD_FONT = "", FORMATS3, DEFAULT_FORMAT3 = "glyph", CYCLE_FORMAT_ACTION3 = "cycle-format", TOGGLE_NERD_FONT_ACTION3 = "toggle-nerd-font", NERD_FONT_METADATA_KEY3 = "nerdFont";
70136
+ var init_SandboxStatus = __esm(async () => {
70137
+ await init_claude_settings();
70138
+ FORMATS3 = ["glyph", "text", "word"];
70139
+ });
70140
+
70141
+ // src/widgets/VoiceStatus.ts
70142
+ function getFormat4(item) {
70143
+ const f = item.metadata?.format;
70144
+ return FORMATS4.includes(f ?? "") ? f : DEFAULT_FORMAT4;
70145
+ }
70146
+ function canUseNerdFont3(item) {
70147
+ const format = getFormat4(item);
70148
+ return format === "icon" || format === "icon-text" && !item.rawValue;
70149
+ }
70150
+ function removeNerdFont4(item) {
70151
+ const { [NERD_FONT_METADATA_KEY4]: removedNerdFont, ...restMetadata } = item.metadata ?? {};
70152
+ return {
70153
+ ...item,
70154
+ metadata: Object.keys(restMetadata).length > 0 ? restMetadata : undefined
70155
+ };
70156
+ }
70157
+ function setFormat4(item, format) {
70158
+ let updatedItem;
70159
+ if (format === DEFAULT_FORMAT4) {
70160
+ const { format: removedFormat, ...restMetadata } = item.metadata ?? {};
70161
+ updatedItem = {
70162
+ ...item,
70163
+ metadata: Object.keys(restMetadata).length > 0 ? restMetadata : undefined
70164
+ };
70165
+ } else {
70166
+ updatedItem = {
70167
+ ...item,
70168
+ metadata: {
70169
+ ...item.metadata ?? {},
70170
+ format
70171
+ }
70172
+ };
70173
+ }
70174
+ return canUseNerdFont3(updatedItem) ? updatedItem : removeNerdFont4(updatedItem);
70175
+ }
70176
+ function isNerdFontEnabled4(item) {
70177
+ return canUseNerdFont3(item) && item.metadata?.[NERD_FONT_METADATA_KEY4] === "true";
70178
+ }
70179
+ function toggleNerdFont4(item) {
70180
+ if (!canUseNerdFont3(item)) {
70181
+ return removeNerdFont4(item);
70182
+ }
70183
+ if (!isNerdFontEnabled4(item)) {
70184
+ return {
70185
+ ...item,
70186
+ metadata: {
70187
+ ...item.metadata ?? {},
70188
+ [NERD_FONT_METADATA_KEY4]: "true"
70189
+ }
70190
+ };
70191
+ }
70192
+ return removeNerdFont4(item);
69700
70193
  }
69701
- function formatStatus(enabled, format, nerdFont) {
70194
+ function formatStatus2(enabled, format, nerdFont, rawValue) {
69702
70195
  const stateText = enabled ? "on" : "off";
69703
70196
  const stateDot = enabled ? STATE_DOT_ON : STATE_DOT_OFF;
69704
70197
  const icon = nerdFont ? enabled ? MIC_NERD_FONT : MIC_SLASH_NERD_FONT : MIC_EMOJI;
69705
70198
  switch (format) {
69706
70199
  case "icon":
69707
- return nerdFont ? icon : `${icon} ${stateDot}`;
70200
+ return nerdFont ? icon : rawValue ? stateDot : `${icon} ${stateDot}`;
69708
70201
  case "icon-text":
69709
- return `${icon} ${stateText}`;
70202
+ return rawValue ? stateText : `${icon} ${stateText}`;
69710
70203
  case "text":
69711
70204
  return stateText;
69712
70205
  case "word":
69713
- return `voice ${stateText}`;
70206
+ return rawValue ? stateText : `voice ${stateText}`;
69714
70207
  }
69715
70208
  }
69716
70209
  function resolveVoiceConfigCwd(context) {
@@ -69736,8 +70229,8 @@ class VoiceStatusWidget {
69736
70229
  return "Core";
69737
70230
  }
69738
70231
  getEditorDisplay(item) {
69739
- const modifiers = [getFormat3(item)];
69740
- if (isNerdFontEnabled3(item)) {
70232
+ const modifiers = [getFormat4(item)];
70233
+ if (isNerdFontEnabled4(item)) {
69741
70234
  modifiers.push("nerd font");
69742
70235
  }
69743
70236
  return {
@@ -69746,39 +70239,36 @@ class VoiceStatusWidget {
69746
70239
  };
69747
70240
  }
69748
70241
  handleEditorAction(action, item) {
69749
- if (action === CYCLE_FORMAT_ACTION3) {
69750
- const currentFormat = getFormat3(item);
69751
- const nextFormat = FORMATS3[(FORMATS3.indexOf(currentFormat) + 1) % FORMATS3.length] ?? DEFAULT_FORMAT3;
69752
- return setFormat3(item, nextFormat);
70242
+ if (action === CYCLE_FORMAT_ACTION4) {
70243
+ const currentFormat = getFormat4(item);
70244
+ const nextFormat = FORMATS4[(FORMATS4.indexOf(currentFormat) + 1) % FORMATS4.length] ?? DEFAULT_FORMAT4;
70245
+ return setFormat4(item, nextFormat);
69753
70246
  }
69754
- if (action === TOGGLE_NERD_FONT_ACTION3) {
69755
- return toggleNerdFont3(item);
70247
+ if (action === TOGGLE_NERD_FONT_ACTION4) {
70248
+ return toggleNerdFont4(item);
69756
70249
  }
69757
70250
  return null;
69758
70251
  }
69759
70252
  render(item, context, _settings) {
69760
- const format = getFormat3(item);
69761
- const nerdFont = isNerdFontEnabled3(item);
70253
+ const format = getFormat4(item);
70254
+ const nerdFont = isNerdFontEnabled4(item);
69762
70255
  if (context.isPreview) {
69763
- if (item.rawValue) {
69764
- return "on";
69765
- }
69766
- return formatStatus(true, format, nerdFont);
70256
+ return formatStatus2(true, format, nerdFont, item.rawValue ?? false);
69767
70257
  }
69768
70258
  const config2 = getVoiceConfig(resolveVoiceConfigCwd(context));
69769
70259
  if (config2 === null) {
69770
70260
  return null;
69771
70261
  }
69772
- if (item.rawValue) {
69773
- return config2.enabled ? "on" : "off";
69774
- }
69775
- return formatStatus(config2.enabled, format, nerdFont);
70262
+ return formatStatus2(config2.enabled, format, nerdFont, item.rawValue ?? false);
69776
70263
  }
69777
- getCustomKeybinds() {
69778
- return [
69779
- { key: "f", label: "(f)ormat", action: CYCLE_FORMAT_ACTION3 },
69780
- { key: "n", label: "(n)erd font", action: TOGGLE_NERD_FONT_ACTION3 }
70264
+ getCustomKeybinds(item) {
70265
+ const keybinds = [
70266
+ { key: "f", label: "(f)ormat", action: CYCLE_FORMAT_ACTION4 }
69781
70267
  ];
70268
+ if (item === undefined || canUseNerdFont3(item)) {
70269
+ keybinds.push({ key: "n", label: "(n)erd font", action: TOGGLE_NERD_FONT_ACTION4 });
70270
+ }
70271
+ return keybinds;
69782
70272
  }
69783
70273
  supportsRawValue() {
69784
70274
  return true;
@@ -69787,69 +70277,82 @@ class VoiceStatusWidget {
69787
70277
  return true;
69788
70278
  }
69789
70279
  }
69790
- 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";
70280
+ var MIC_EMOJI = "\uD83C\uDFA4", MIC_NERD_FONT = "", MIC_SLASH_NERD_FONT = "", STATE_DOT_OFF = "○", STATE_DOT_ON = "◉", FORMATS4, DEFAULT_FORMAT4 = "icon", CYCLE_FORMAT_ACTION4 = "cycle-format", TOGGLE_NERD_FONT_ACTION4 = "toggle-nerd-font", NERD_FONT_METADATA_KEY4 = "nerdFont";
69791
70281
  var init_VoiceStatus = __esm(async () => {
69792
70282
  await init_claude_settings();
69793
- FORMATS3 = ["icon", "icon-text", "text", "word"];
70283
+ FORMATS4 = ["icon", "icon-text", "text", "word"];
69794
70284
  });
69795
70285
 
69796
70286
  // src/widgets/RemoteControlStatus.ts
69797
- function getFormat4(item) {
70287
+ function getFormat5(item) {
69798
70288
  const f = item.metadata?.format;
69799
- return FORMATS4.includes(f ?? "") ? f : DEFAULT_FORMAT4;
70289
+ return FORMATS5.includes(f ?? "") ? f : DEFAULT_FORMAT5;
69800
70290
  }
69801
- function setFormat4(item, format) {
69802
- if (format === DEFAULT_FORMAT4) {
70291
+ function canUseNerdFont4(item) {
70292
+ const format = getFormat5(item);
70293
+ return format === "icon" || format === "icon-text" && !item.rawValue;
70294
+ }
70295
+ function removeNerdFont5(item) {
70296
+ const { [NERD_FONT_METADATA_KEY5]: removedNerdFont, ...restMetadata } = item.metadata ?? {};
70297
+ return {
70298
+ ...item,
70299
+ metadata: Object.keys(restMetadata).length > 0 ? restMetadata : undefined
70300
+ };
70301
+ }
70302
+ function setFormat5(item, format) {
70303
+ let updatedItem;
70304
+ if (format === DEFAULT_FORMAT5) {
69803
70305
  const { format: removedFormat, ...restMetadata } = item.metadata ?? {};
69804
- return {
70306
+ updatedItem = {
69805
70307
  ...item,
69806
70308
  metadata: Object.keys(restMetadata).length > 0 ? restMetadata : undefined
69807
70309
  };
70310
+ } else {
70311
+ updatedItem = {
70312
+ ...item,
70313
+ metadata: {
70314
+ ...item.metadata ?? {},
70315
+ format
70316
+ }
70317
+ };
69808
70318
  }
69809
- return {
69810
- ...item,
69811
- metadata: {
69812
- ...item.metadata ?? {},
69813
- format
69814
- }
69815
- };
70319
+ return canUseNerdFont4(updatedItem) ? updatedItem : removeNerdFont5(updatedItem);
69816
70320
  }
69817
- function isNerdFontEnabled4(item) {
69818
- return item.metadata?.[NERD_FONT_METADATA_KEY4] === "true";
70321
+ function isNerdFontEnabled5(item) {
70322
+ return canUseNerdFont4(item) && item.metadata?.[NERD_FONT_METADATA_KEY5] === "true";
69819
70323
  }
69820
- function toggleNerdFont4(item) {
69821
- if (!isNerdFontEnabled4(item)) {
70324
+ function toggleNerdFont5(item) {
70325
+ if (!canUseNerdFont4(item)) {
70326
+ return removeNerdFont5(item);
70327
+ }
70328
+ if (!isNerdFontEnabled5(item)) {
69822
70329
  return {
69823
70330
  ...item,
69824
70331
  metadata: {
69825
70332
  ...item.metadata ?? {},
69826
- [NERD_FONT_METADATA_KEY4]: "true"
70333
+ [NERD_FONT_METADATA_KEY5]: "true"
69827
70334
  }
69828
70335
  };
69829
70336
  }
69830
- const { [NERD_FONT_METADATA_KEY4]: removedNerdFont, ...restMetadata } = item.metadata ?? {};
69831
- return {
69832
- ...item,
69833
- metadata: Object.keys(restMetadata).length > 0 ? restMetadata : undefined
69834
- };
70337
+ return removeNerdFont5(item);
69835
70338
  }
69836
- function formatStatus2(enabled, format, nerdFont) {
70339
+ function formatStatus3(enabled, format, nerdFont, rawValue) {
69837
70340
  const stateText = enabled ? "on" : "off";
69838
70341
  const stateDot = enabled ? STATE_DOT_ON2 : STATE_DOT_OFF2;
69839
70342
  const icon = nerdFont ? enabled ? SATELLITE_NERD_FONT : SATELLITE_SLASH_NERD_FONT : SATELLITE_EMOJI;
69840
70343
  switch (format) {
69841
70344
  case "icon":
69842
- return nerdFont ? icon : `${icon} ${stateDot}`;
70345
+ return nerdFont ? icon : rawValue ? stateDot : `${icon} ${stateDot}`;
69843
70346
  case "icon-text":
69844
- return `${icon} ${stateText}`;
70347
+ return rawValue ? stateText : `${icon} ${stateText}`;
69845
70348
  case "text":
69846
70349
  return stateText;
69847
70350
  case "word":
69848
- return `remote ${stateText}`;
70351
+ return rawValue ? stateText : `remote ${stateText}`;
69849
70352
  case "label-check":
69850
- return `remote ${enabled ? CHECK_EMOJI : CROSS_EMOJI}`;
70353
+ return rawValue ? enabled ? CHECK_EMOJI : CROSS_EMOJI : `remote ${enabled ? CHECK_EMOJI : CROSS_EMOJI}`;
69851
70354
  case "label-mark":
69852
- return `remote ${enabled ? CHECK_MARK : CROSS_MARK}`;
70355
+ return rawValue ? enabled ? CHECK_MARK : CROSS_MARK : `remote ${enabled ? CHECK_MARK : CROSS_MARK}`;
69853
70356
  }
69854
70357
  }
69855
70358
 
@@ -69867,8 +70370,8 @@ class RemoteControlStatusWidget {
69867
70370
  return "Core";
69868
70371
  }
69869
70372
  getEditorDisplay(item) {
69870
- const modifiers = [getFormat4(item)];
69871
- if (isNerdFontEnabled4(item)) {
70373
+ const modifiers = [getFormat5(item)];
70374
+ if (isNerdFontEnabled5(item)) {
69872
70375
  modifiers.push("nerd font");
69873
70376
  }
69874
70377
  return {
@@ -69877,40 +70380,246 @@ class RemoteControlStatusWidget {
69877
70380
  };
69878
70381
  }
69879
70382
  handleEditorAction(action, item) {
69880
- if (action === CYCLE_FORMAT_ACTION4) {
69881
- const currentFormat = getFormat4(item);
69882
- const nextFormat = FORMATS4[(FORMATS4.indexOf(currentFormat) + 1) % FORMATS4.length] ?? DEFAULT_FORMAT4;
69883
- return setFormat4(item, nextFormat);
70383
+ if (action === CYCLE_FORMAT_ACTION5) {
70384
+ const currentFormat = getFormat5(item);
70385
+ const nextFormat = FORMATS5[(FORMATS5.indexOf(currentFormat) + 1) % FORMATS5.length] ?? DEFAULT_FORMAT5;
70386
+ return setFormat5(item, nextFormat);
69884
70387
  }
69885
- if (action === TOGGLE_NERD_FONT_ACTION4) {
69886
- return toggleNerdFont4(item);
70388
+ if (action === TOGGLE_NERD_FONT_ACTION5) {
70389
+ return toggleNerdFont5(item);
69887
70390
  }
69888
70391
  return null;
69889
70392
  }
69890
70393
  render(item, context, _settings) {
69891
- const format = getFormat4(item);
69892
- const nerdFont = isNerdFontEnabled4(item);
70394
+ const format = getFormat5(item);
70395
+ const nerdFont = isNerdFontEnabled5(item);
69893
70396
  if (context.isPreview) {
69894
- if (item.rawValue) {
69895
- return "on";
69896
- }
69897
- return formatStatus2(true, format, nerdFont);
70397
+ return formatStatus3(true, format, nerdFont, item.rawValue ?? false);
69898
70398
  }
69899
70399
  const status = getRemoteControlStatus(context.data?.session_id);
69900
70400
  if (status === null) {
69901
70401
  return null;
69902
70402
  }
69903
- if (item.rawValue) {
69904
- return status.enabled ? "on" : "off";
70403
+ return formatStatus3(status.enabled, format, nerdFont, item.rawValue ?? false);
70404
+ }
70405
+ getCustomKeybinds(item) {
70406
+ const keybinds = [
70407
+ { key: "f", label: "(f)ormat", action: CYCLE_FORMAT_ACTION5 }
70408
+ ];
70409
+ if (item === undefined || canUseNerdFont4(item)) {
70410
+ keybinds.push({ key: "n", label: "(n)erd font", action: TOGGLE_NERD_FONT_ACTION5 });
70411
+ }
70412
+ return keybinds;
70413
+ }
70414
+ supportsRawValue() {
70415
+ return true;
70416
+ }
70417
+ supportsColors(_item) {
70418
+ return true;
70419
+ }
70420
+ }
70421
+ var SATELLITE_EMOJI = "\uD83D\uDCE1", SATELLITE_NERD_FONT = "", SATELLITE_SLASH_NERD_FONT = "", STATE_DOT_OFF2 = "○", STATE_DOT_ON2 = "◉", FORMATS5, CHECK_EMOJI = "✅", CROSS_EMOJI = "❌", CHECK_MARK = "✓", CROSS_MARK = "✗", DEFAULT_FORMAT5 = "icon", CYCLE_FORMAT_ACTION5 = "cycle-format", TOGGLE_NERD_FONT_ACTION5 = "toggle-nerd-font", NERD_FONT_METADATA_KEY5 = "nerdFont";
70422
+ var init_RemoteControlStatus = __esm(async () => {
70423
+ await init_claude_settings();
70424
+ FORMATS5 = ["icon", "icon-text", "text", "word", "label-check", "label-mark"];
70425
+ });
70426
+
70427
+ // src/widgets/CacheTimer.ts
70428
+ import * as fs12 from "fs";
70429
+ function hasCacheActivity(entry) {
70430
+ const usage = entry.message?.usage;
70431
+ if (!usage) {
70432
+ return true;
70433
+ }
70434
+ return (usage.cache_read_input_tokens ?? 0) + (usage.cache_creation_input_tokens ?? 0) > 0;
70435
+ }
70436
+ function readFileTail(filePath, bytes) {
70437
+ try {
70438
+ const fd = fs12.openSync(filePath, "r");
70439
+ try {
70440
+ const size2 = fs12.fstatSync(fd).size;
70441
+ const readSize = Math.min(bytes, size2);
70442
+ const buf = Buffer.alloc(readSize);
70443
+ fs12.readSync(fd, buf, 0, readSize, size2 - readSize);
70444
+ return { text: buf.toString("utf-8"), isComplete: readSize === size2 };
70445
+ } finally {
70446
+ fs12.closeSync(fd);
70447
+ }
70448
+ } catch {
70449
+ return null;
70450
+ }
70451
+ }
70452
+ function getTranscriptState(transcriptPath) {
70453
+ for (let bytes = INITIAL_TAIL_BYTES;; bytes *= 2) {
70454
+ const tail2 = readFileTail(transcriptPath, bytes);
70455
+ if (!tail2 || tail2.text.length === 0) {
70456
+ return { isWorking: false, lastAssistant: null };
70457
+ }
70458
+ const state = scanTailForState(tail2.text);
70459
+ if (state) {
70460
+ return state;
70461
+ }
70462
+ if (tail2.isComplete) {
70463
+ return { isWorking: false, lastAssistant: null };
70464
+ }
70465
+ }
70466
+ }
70467
+ function scanTailForState(tail2) {
70468
+ const lines = tail2.split(`
70469
+ `).reverse();
70470
+ let turnFinished = false;
70471
+ for (const line of lines) {
70472
+ const trimmed = line.trim();
70473
+ if (!trimmed) {
70474
+ continue;
70475
+ }
70476
+ try {
70477
+ const entry = JSON.parse(trimmed);
70478
+ if (entry.isSidechain === true) {
70479
+ continue;
70480
+ }
70481
+ if (entry.type === "assistant") {
70482
+ turnFinished = true;
70483
+ if (entry.isApiErrorMessage !== true && hasCacheActivity(entry) && entry.timestamp) {
70484
+ const parsed = new Date(entry.timestamp);
70485
+ if (!Number.isNaN(parsed.getTime())) {
70486
+ return { isWorking: false, lastAssistant: parsed };
70487
+ }
70488
+ }
70489
+ continue;
70490
+ }
70491
+ if (entry.type === "user" && !turnFinished) {
70492
+ return { isWorking: true };
70493
+ }
70494
+ } catch {
70495
+ continue;
70496
+ }
70497
+ }
70498
+ return null;
70499
+ }
70500
+ function getTtlSeconds(item) {
70501
+ const raw = item.metadata?.[TTL_METADATA_KEY];
70502
+ if (raw === undefined) {
70503
+ return DEFAULT_TTL_SECONDS;
70504
+ }
70505
+ const parsed = Number.parseInt(raw, 10);
70506
+ return Number.isFinite(parsed) && parsed > SAFETY_MARGIN ? parsed : DEFAULT_TTL_SECONDS;
70507
+ }
70508
+ function cycleTtl(item) {
70509
+ const current = getTtlSeconds(item);
70510
+ const index = TTL_OPTIONS.indexOf(current);
70511
+ const next = TTL_OPTIONS[(index + 1) % TTL_OPTIONS.length] ?? DEFAULT_TTL_SECONDS;
70512
+ if (next === DEFAULT_TTL_SECONDS) {
70513
+ return removeMetadataKeys(item, [TTL_METADATA_KEY]);
70514
+ }
70515
+ return {
70516
+ ...item,
70517
+ metadata: {
70518
+ ...item.metadata,
70519
+ [TTL_METADATA_KEY]: String(next)
70520
+ }
70521
+ };
70522
+ }
70523
+ function formatTtlLabel(ttlSeconds) {
70524
+ return ttlSeconds % 3600 === 0 ? `${ttlSeconds / 3600}h` : `${Math.round(ttlSeconds / 60)}m`;
70525
+ }
70526
+ function getRemainingSeconds(lastAssistant, ttlSeconds) {
70527
+ const elapsedSeconds = (Date.now() - lastAssistant.getTime()) / 1000;
70528
+ return ttlSeconds - SAFETY_MARGIN - elapsedSeconds;
70529
+ }
70530
+ function formatCountdown(remaining) {
70531
+ if (remaining <= 0) {
70532
+ return "COLD";
70533
+ }
70534
+ const m = Math.floor(remaining / 60);
70535
+ const s = Math.floor(remaining % 60);
70536
+ return `${m}:${s.toString().padStart(2, "0")}`;
70537
+ }
70538
+ function getStateSymbol(item, remaining, ttlSeconds) {
70539
+ if (remaining <= 0) {
70540
+ return getSlotSymbol(item, COLD_SLOT);
70541
+ }
70542
+ const pct = remaining / (ttlSeconds - SAFETY_MARGIN);
70543
+ if (pct > 0.5) {
70544
+ return getSlotSymbol(item, FRESH_SLOT);
70545
+ }
70546
+ if (pct > 0.2) {
70547
+ return getSlotSymbol(item, DRAINING_SLOT);
70548
+ }
70549
+ return getSlotSymbol(item, URGENT_SLOT);
70550
+ }
70551
+ function withGlyph(symbol2, text) {
70552
+ return symbol2.length > 0 ? `${symbol2} ${text}` : text;
70553
+ }
70554
+
70555
+ class CacheTimerWidget {
70556
+ getDefaultColor() {
70557
+ return "brightCyan";
70558
+ }
70559
+ getDescription() {
70560
+ return "Shows time remaining on the prompt cache TTL (5m by default, 1h configurable)";
70561
+ }
70562
+ getDisplayName() {
70563
+ return "Cache Timer";
70564
+ }
70565
+ getCategory() {
70566
+ return "Session";
70567
+ }
70568
+ getEditorDisplay(item) {
70569
+ const modifiers = [];
70570
+ const ttlSeconds = getTtlSeconds(item);
70571
+ if (ttlSeconds !== DEFAULT_TTL_SECONDS) {
70572
+ modifiers.push(`ttl ${formatTtlLabel(ttlSeconds)}`);
70573
+ }
70574
+ if (isMetadataFlagEnabled(item, HIDE_WHEN_EMPTY_KEY3)) {
70575
+ modifiers.push("hide when empty");
70576
+ }
70577
+ return {
70578
+ displayText: this.getDisplayName(),
70579
+ modifierText: makeModifierText(modifiers)
70580
+ };
70581
+ }
70582
+ handleEditorAction(action, item) {
70583
+ if (action === TOGGLE_HIDE_ACTION2) {
70584
+ return toggleMetadataFlag(item, HIDE_WHEN_EMPTY_KEY3);
70585
+ }
70586
+ if (action === TOGGLE_TTL_ACTION) {
70587
+ return cycleTtl(item);
70588
+ }
70589
+ return null;
70590
+ }
70591
+ render(item, context, _settings) {
70592
+ const hideWhenEmpty = isMetadataFlagEnabled(item, HIDE_WHEN_EMPTY_KEY3);
70593
+ if (context.isPreview) {
70594
+ return formatRawOrLabeledValue(item, "Cache: ", withGlyph(getSlotSymbol(item, FRESH_SLOT), "4:52"));
70595
+ }
70596
+ const transcriptPath = context.data?.transcript_path;
70597
+ if (!transcriptPath) {
70598
+ return hideWhenEmpty ? null : formatRawOrLabeledValue(item, "Cache: ", "n/a");
70599
+ }
70600
+ const state = getTranscriptState(transcriptPath);
70601
+ if (state.isWorking) {
70602
+ return formatRawOrLabeledValue(item, "Cache: ", withGlyph(getSlotSymbol(item, HOT_SLOT), "HOT"));
69905
70603
  }
69906
- return formatStatus2(status.enabled, format, nerdFont);
70604
+ const { lastAssistant } = state;
70605
+ if (!lastAssistant) {
70606
+ return hideWhenEmpty ? null : formatRawOrLabeledValue(item, "Cache: ", "n/a");
70607
+ }
70608
+ const ttlSeconds = getTtlSeconds(item);
70609
+ const remaining = getRemainingSeconds(lastAssistant, ttlSeconds);
70610
+ const glyph = getStateSymbol(item, remaining, ttlSeconds);
70611
+ return formatRawOrLabeledValue(item, "Cache: ", withGlyph(glyph, formatCountdown(remaining)));
69907
70612
  }
69908
70613
  getCustomKeybinds() {
69909
70614
  return [
69910
- { key: "f", label: "(f)ormat", action: CYCLE_FORMAT_ACTION4 },
69911
- { key: "n", label: "(n)erd font", action: TOGGLE_NERD_FONT_ACTION4 }
70615
+ { key: "t", label: "(t)tl", action: TOGGLE_TTL_ACTION },
70616
+ { key: "h", label: "(h)ide when empty", action: TOGGLE_HIDE_ACTION2 },
70617
+ getSymbolKeybind()
69912
70618
  ];
69913
70619
  }
70620
+ renderEditor(props) {
70621
+ return renderSymbolSlotsEditor(props, SYMBOL_SLOTS);
70622
+ }
69914
70623
  supportsRawValue() {
69915
70624
  return true;
69916
70625
  }
@@ -69918,10 +70627,16 @@ class RemoteControlStatusWidget {
69918
70627
  return true;
69919
70628
  }
69920
70629
  }
69921
- var SATELLITE_EMOJI = "\uD83D\uDCE1", SATELLITE_NERD_FONT = "", SATELLITE_SLASH_NERD_FONT = "", STATE_DOT_OFF2 = "○", STATE_DOT_ON2 = "◉", FORMATS4, CHECK_EMOJI = "", CROSS_EMOJI = "❌", CHECK_MARK = "✓", CROSS_MARK = "✗", DEFAULT_FORMAT4 = "icon", CYCLE_FORMAT_ACTION4 = "cycle-format", TOGGLE_NERD_FONT_ACTION4 = "toggle-nerd-font", NERD_FONT_METADATA_KEY4 = "nerdFont";
69922
- var init_RemoteControlStatus = __esm(async () => {
69923
- await init_claude_settings();
69924
- FORMATS4 = ["icon", "icon-text", "text", "word", "label-check", "label-mark"];
70630
+ var HIDE_WHEN_EMPTY_KEY3 = "hideWhenEmpty", TOGGLE_HIDE_ACTION2 = "toggle-hide", TTL_METADATA_KEY = "ttlSeconds", DEFAULT_TTL_SECONDS = 300, TTL_OPTIONS, TOGGLE_TTL_ACTION = "toggle-ttl", SAFETY_MARGIN = 5, HOT_SLOT, FRESH_SLOT, DRAINING_SLOT, URGENT_SLOT, COLD_SLOT, SYMBOL_SLOTS, INITIAL_TAIL_BYTES = 32768;
70631
+ var init_CacheTimer = __esm(async () => {
70632
+ await init_symbol_override();
70633
+ TTL_OPTIONS = [300, 3600];
70634
+ HOT_SLOT = { id: "symbolHot", label: "Working", defaultSymbol: "\uD83D\uDD25" };
70635
+ FRESH_SLOT = { id: "symbolFresh", label: "Fresh", defaultSymbol: "\uD83D\uDFE2" };
70636
+ DRAINING_SLOT = { id: "symbolDraining", label: "Draining", defaultSymbol: "\uD83D\uDFE1" };
70637
+ URGENT_SLOT = { id: "symbolUrgent", label: "Urgent", defaultSymbol: "\uD83D\uDD34" };
70638
+ COLD_SLOT = { id: "symbolCold", label: "Cold", defaultSymbol: "❄️" };
70639
+ SYMBOL_SLOTS = [HOT_SLOT, FRESH_SLOT, DRAINING_SLOT, URGENT_SLOT, COLD_SLOT];
69925
70640
  });
69926
70641
 
69927
70642
  // src/widgets/index.ts
@@ -69932,6 +70647,7 @@ var init_widgets = __esm(async () => {
69932
70647
  init_GitStagedFiles();
69933
70648
  init_GitUnstagedFiles();
69934
70649
  init_GitUntrackedFiles();
70650
+ init_GitCiStatus();
69935
70651
  init_GitCleanStatus();
69936
70652
  init_GitPr();
69937
70653
  init_GitSha();
@@ -69999,8 +70715,10 @@ var init_widgets = __esm(async () => {
69999
70715
  init_ThinkingEffort(),
70000
70716
  init_GitWorktreeMode(),
70001
70717
  init_CompactionCounter(),
70718
+ init_SandboxStatus(),
70002
70719
  init_VoiceStatus(),
70003
- init_RemoteControlStatus()
70720
+ init_RemoteControlStatus(),
70721
+ init_CacheTimer()
70004
70722
  ]);
70005
70723
  });
70006
70724
 
@@ -70021,6 +70739,7 @@ var init_widget_manifest = __esm(async () => {
70021
70739
  { type: "git-clean-status", create: () => new GitCleanStatusWidget },
70022
70740
  { type: "git-root-dir", create: () => new GitRootDirWidget },
70023
70741
  { type: "git-review", create: () => new GitPrWidget },
70742
+ { type: "git-ci-status", create: () => new GitCiStatusWidget },
70024
70743
  { type: "git-worktree", create: () => new GitWorktreeWidget },
70025
70744
  { type: "git-status", create: () => new GitStatusWidget },
70026
70745
  { type: "git-staged", create: () => new GitStagedWidget },
@@ -70070,6 +70789,7 @@ var init_widget_manifest = __esm(async () => {
70070
70789
  { type: "link", create: () => new LinkWidget },
70071
70790
  { type: "claude-session-id", create: () => new ClaudeSessionIdWidget },
70072
70791
  { type: "claude-account-email", create: () => new ClaudeAccountEmailWidget },
70792
+ { type: "sandbox-status", create: () => new SandboxStatusWidget },
70073
70793
  { type: "session-name", create: () => new SessionNameWidget },
70074
70794
  { type: "free-memory", create: () => new FreeMemoryWidget },
70075
70795
  { type: "session-usage", create: () => new SessionUsageWidget },
@@ -70091,7 +70811,8 @@ var init_widget_manifest = __esm(async () => {
70091
70811
  { type: "worktree-name", create: () => new GitWorktreeNameWidget },
70092
70812
  { type: "worktree-branch", create: () => new GitWorktreeBranchWidget },
70093
70813
  { type: "worktree-original-branch", create: () => new GitWorktreeOriginalBranchWidget },
70094
- { type: "compaction-counter", create: () => new CompactionCounterWidget }
70814
+ { type: "compaction-counter", create: () => new CompactionCounterWidget },
70815
+ { type: "cache-timer", create: () => new CacheTimerWidget }
70095
70816
  ];
70096
70817
  LAYOUT_WIDGET_MANIFEST = [
70097
70818
  {
@@ -70295,7 +71016,7 @@ var init_hooks = __esm(async () => {
70295
71016
  });
70296
71017
 
70297
71018
  // src/utils/config.ts
70298
- import * as fs12 from "fs";
71019
+ import * as fs13 from "fs";
70299
71020
  import * as os9 from "os";
70300
71021
  import * as path8 from "path";
70301
71022
  function getConfigLoadError() {
@@ -70385,7 +71106,7 @@ async function loadSettings() {
70385
71106
  lastLoadError = null;
70386
71107
  const paths = getSettingsPaths();
70387
71108
  try {
70388
- if (!fs12.existsSync(paths.settingsPath))
71109
+ if (!fs13.existsSync(paths.settingsPath))
70389
71110
  return await writeDefaultSettings(paths);
70390
71111
  const content = await readFile3(paths.settingsPath, "utf-8");
70391
71112
  let rawData;
@@ -70444,7 +71165,7 @@ async function saveSettings(settings) {
70444
71165
  }
70445
71166
  async function saveInstallationMetadata(metadata) {
70446
71167
  const paths = getSettingsPaths();
70447
- if (!metadata && !fs12.existsSync(paths.settingsPath)) {
71168
+ if (!metadata && !fs13.existsSync(paths.settingsPath)) {
70448
71169
  return;
70449
71170
  }
70450
71171
  const settings = await loadSettings();
@@ -70468,21 +71189,21 @@ var init_config = __esm(async () => {
70468
71189
  init_Settings();
70469
71190
  init_migrations();
70470
71191
  await init_widgets2();
70471
- readFile3 = fs12.promises.readFile;
70472
- writeFile = fs12.promises.writeFile;
70473
- mkdir = fs12.promises.mkdir;
70474
- rename = fs12.promises.rename;
70475
- unlink = fs12.promises.unlink;
70476
- lstat = fs12.promises.lstat;
70477
- readlink = fs12.promises.readlink;
70478
- realpath2 = fs12.promises.realpath;
71192
+ readFile3 = fs13.promises.readFile;
71193
+ writeFile = fs13.promises.writeFile;
71194
+ mkdir = fs13.promises.mkdir;
71195
+ rename = fs13.promises.rename;
71196
+ unlink = fs13.promises.unlink;
71197
+ lstat = fs13.promises.lstat;
71198
+ readlink = fs13.promises.readlink;
71199
+ realpath2 = fs13.promises.realpath;
70479
71200
  DEFAULT_SETTINGS_PATH = path8.join(os9.homedir(), ".config", "ccstatusline", "settings.json");
70480
71201
  settingsPath = DEFAULT_SETTINGS_PATH;
70481
71202
  });
70482
71203
 
70483
71204
  // src/utils/claude-settings.ts
70484
71205
  import { execSync as execSync4 } from "child_process";
70485
- import * as fs13 from "fs";
71206
+ import * as fs14 from "fs";
70486
71207
  import * as os10 from "os";
70487
71208
  import * as path9 from "path";
70488
71209
  function isKnownCommand(command) {
@@ -70509,8 +71230,8 @@ function getClaudeConfigDir() {
70509
71230
  if (envConfigDir) {
70510
71231
  try {
70511
71232
  const resolvedPath = path9.resolve(envConfigDir);
70512
- if (fs13.existsSync(resolvedPath)) {
70513
- const stats = fs13.statSync(resolvedPath);
71233
+ if (fs14.existsSync(resolvedPath)) {
71234
+ const stats = fs14.statSync(resolvedPath);
70514
71235
  if (stats.isDirectory()) {
70515
71236
  return resolvedPath;
70516
71237
  }
@@ -70536,7 +71257,7 @@ async function backupClaudeSettings(suffix = ".bak") {
70536
71257
  const settingsPath2 = getClaudeSettingsPath();
70537
71258
  const backupPath = settingsPath2 + suffix;
70538
71259
  try {
70539
- if (fs13.existsSync(settingsPath2)) {
71260
+ if (fs14.existsSync(settingsPath2)) {
70540
71261
  const content = await readFile4(settingsPath2, "utf-8");
70541
71262
  await writeFile2(backupPath, content, "utf-8");
70542
71263
  return backupPath;
@@ -70549,11 +71270,11 @@ async function backupClaudeSettings(suffix = ".bak") {
70549
71270
  function loadClaudeSettingsSync(options = {}) {
70550
71271
  const { logErrors = true } = options;
70551
71272
  const settingsPath2 = getClaudeSettingsPath();
70552
- if (!fs13.existsSync(settingsPath2)) {
71273
+ if (!fs14.existsSync(settingsPath2)) {
70553
71274
  return {};
70554
71275
  }
70555
71276
  try {
70556
- const content = fs13.readFileSync(settingsPath2, "utf-8");
71277
+ const content = fs14.readFileSync(settingsPath2, "utf-8");
70557
71278
  return JSON.parse(content);
70558
71279
  } catch (error51) {
70559
71280
  if (logErrors) {
@@ -70565,7 +71286,7 @@ function loadClaudeSettingsSync(options = {}) {
70565
71286
  async function loadClaudeSettings(options = {}) {
70566
71287
  const { logErrors = true } = options;
70567
71288
  const settingsPath2 = getClaudeSettingsPath();
70568
- if (!fs13.existsSync(settingsPath2)) {
71289
+ if (!fs14.existsSync(settingsPath2)) {
70569
71290
  return {};
70570
71291
  }
70571
71292
  try {
@@ -70718,7 +71439,7 @@ function classifyInstallation(command, metadata) {
70718
71439
  }
70719
71440
  async function loadSavedSettingsForHookSync() {
70720
71441
  const configPath = getConfigPath();
70721
- if (!fs13.existsSync(configPath)) {
71442
+ if (!fs14.existsSync(configPath)) {
70722
71443
  return null;
70723
71444
  }
70724
71445
  try {
@@ -70817,7 +71538,7 @@ async function setRefreshInterval(interval) {
70817
71538
  }
70818
71539
  await saveClaudeSettings(settings);
70819
71540
  }
70820
- function getVoiceConfigCandidatePathsByPriority(cwd2) {
71541
+ function getLayeredSettingsCandidatePathsByPriority(cwd2) {
70821
71542
  const userDir = getClaudeConfigDir();
70822
71543
  const projectDir = path9.join(cwd2, ".claude");
70823
71544
  const candidates = [
@@ -70831,7 +71552,7 @@ function getVoiceConfigCandidatePathsByPriority(cwd2) {
70831
71552
  function tryReadVoiceLayer(filePath) {
70832
71553
  let content;
70833
71554
  try {
70834
- content = fs13.readFileSync(filePath, "utf-8");
71555
+ content = fs14.readFileSync(filePath, "utf-8");
70835
71556
  } catch (error51) {
70836
71557
  const isMissing = error51.code === "ENOENT";
70837
71558
  return { fileExisted: !isMissing, enabled: undefined };
@@ -70850,7 +71571,7 @@ function tryReadVoiceLayer(filePath) {
70850
71571
  }
70851
71572
  function getVoiceConfig(cwd2 = process.cwd()) {
70852
71573
  let anyFileExisted = false;
70853
- for (const filePath of getVoiceConfigCandidatePathsByPriority(cwd2)) {
71574
+ for (const filePath of getLayeredSettingsCandidatePathsByPriority(cwd2)) {
70854
71575
  const layer = tryReadVoiceLayer(filePath);
70855
71576
  if (layer.fileExisted) {
70856
71577
  anyFileExisted = true;
@@ -70861,6 +71582,39 @@ function getVoiceConfig(cwd2 = process.cwd()) {
70861
71582
  }
70862
71583
  return anyFileExisted ? { enabled: false } : null;
70863
71584
  }
71585
+ function tryReadSandboxLayer(filePath) {
71586
+ let content;
71587
+ try {
71588
+ content = fs14.readFileSync(filePath, "utf-8");
71589
+ } catch (error51) {
71590
+ const isMissing = error51.code === "ENOENT";
71591
+ return { fileExisted: !isMissing, enabled: undefined };
71592
+ }
71593
+ try {
71594
+ const parsed = JSON.parse(content);
71595
+ const sandbox = parsed.sandbox;
71596
+ if (sandbox === undefined || sandbox === null) {
71597
+ return { fileExisted: true, enabled: undefined };
71598
+ }
71599
+ const result2 = SandboxConfigSchema.safeParse(sandbox);
71600
+ return { fileExisted: true, enabled: result2.success ? result2.data.enabled : undefined };
71601
+ } catch {
71602
+ return { fileExisted: true, enabled: undefined };
71603
+ }
71604
+ }
71605
+ function getSandboxConfig(cwd2 = process.cwd()) {
71606
+ let anyFileExisted = false;
71607
+ for (const filePath of getLayeredSettingsCandidatePathsByPriority(cwd2)) {
71608
+ const layer = tryReadSandboxLayer(filePath);
71609
+ if (layer.fileExisted) {
71610
+ anyFileExisted = true;
71611
+ }
71612
+ if (layer.enabled !== undefined) {
71613
+ return { enabled: layer.enabled };
71614
+ }
71615
+ }
71616
+ return anyFileExisted ? { enabled: false } : null;
71617
+ }
70864
71618
  function getRemoteControlStatus(sessionId) {
70865
71619
  if (!sessionId) {
70866
71620
  return null;
@@ -70868,7 +71622,7 @@ function getRemoteControlStatus(sessionId) {
70868
71622
  const sessionsDir = path9.join(getClaudeConfigDir(), "sessions");
70869
71623
  let entries;
70870
71624
  try {
70871
- entries = fs13.readdirSync(sessionsDir);
71625
+ entries = fs14.readdirSync(sessionsDir);
70872
71626
  } catch {
70873
71627
  return null;
70874
71628
  }
@@ -70878,7 +71632,7 @@ function getRemoteControlStatus(sessionId) {
70878
71632
  }
70879
71633
  let content;
70880
71634
  try {
70881
- content = fs13.readFileSync(path9.join(sessionsDir, entry), "utf-8");
71635
+ content = fs14.readFileSync(path9.join(sessionsDir, entry), "utf-8");
70882
71636
  } catch {
70883
71637
  continue;
70884
71638
  }
@@ -70897,14 +71651,14 @@ function getRemoteControlStatus(sessionId) {
70897
71651
  }
70898
71652
  return null;
70899
71653
  }
70900
- var readFile4, writeFile2, mkdir2, CCSTATUSLINE_COMMANDS, PINNED_INSTALL_COMMANDS, VoiceConfigSchema, RemoteSessionFileSchema;
71654
+ var readFile4, writeFile2, mkdir2, CCSTATUSLINE_COMMANDS, PINNED_INSTALL_COMMANDS, VoiceConfigSchema, SandboxConfigSchema, RemoteSessionFileSchema;
70901
71655
  var init_claude_settings = __esm(async () => {
70902
71656
  init_zod();
70903
71657
  init_Settings();
70904
71658
  await init_config();
70905
- readFile4 = fs13.promises.readFile;
70906
- writeFile2 = fs13.promises.writeFile;
70907
- mkdir2 = fs13.promises.mkdir;
71659
+ readFile4 = fs14.promises.readFile;
71660
+ writeFile2 = fs14.promises.writeFile;
71661
+ mkdir2 = fs14.promises.mkdir;
70908
71662
  CCSTATUSLINE_COMMANDS = {
70909
71663
  AUTO_NPX: "npx -y ccstatusline@latest",
70910
71664
  AUTO_BUNX: "bunx -y ccstatusline@latest",
@@ -70918,6 +71672,7 @@ var init_claude_settings = __esm(async () => {
70918
71672
  BUN: (version2) => `bun add -g ccstatusline@${version2}`
70919
71673
  };
70920
71674
  VoiceConfigSchema = exports_external.object({ enabled: exports_external.boolean().optional() });
71675
+ SandboxConfigSchema = exports_external.object({ enabled: exports_external.boolean().optional() });
70921
71676
  RemoteSessionFileSchema = exports_external.object({
70922
71677
  sessionId: exports_external.string().optional(),
70923
71678
  bridgeSessionId: exports_external.string().nullable().optional()
@@ -71678,7 +72433,7 @@ import {
71678
72433
  execFile,
71679
72434
  execFileSync as execFileSync6
71680
72435
  } from "child_process";
71681
- import * as fs14 from "fs";
72436
+ import * as fs15 from "fs";
71682
72437
  var GLOBAL_PACKAGE_TIMEOUT_MS = 120000;
71683
72438
  var VERSION_LOOKUP_TIMEOUT_MS = 5000;
71684
72439
  var WINDOWS_SHIM_EXTENSIONS = [
@@ -71727,7 +72482,7 @@ function getBinaryPathCandidates(binDir, platform2) {
71727
72482
  return extensions.map((extension) => appendPathSegment(binDir, `ccstatusline${extension}`));
71728
72483
  }
71729
72484
  function hasBinaryOnDisk(binDir, platform2) {
71730
- return getBinaryPathCandidates(binDir, platform2).some((candidate) => getFilesystemPathVariants(candidate).some((variant) => fs14.existsSync(variant)));
72485
+ return getBinaryPathCandidates(binDir, platform2).some((candidate) => getFilesystemPathVariants(candidate).some((variant) => fs15.existsSync(variant)));
71731
72486
  }
71732
72487
  function hasResolvedBinaryInDir(resolvedPaths, binDir) {
71733
72488
  return resolvedPaths.some((resolvedPath) => isPathInsideDir(resolvedPath, binDir));
@@ -71760,10 +72515,10 @@ function formatPathList2(paths) {
71760
72515
  function readPackageVersion(packageJsonPath) {
71761
72516
  for (const variant of getFilesystemPathVariants(packageJsonPath)) {
71762
72517
  try {
71763
- if (!fs14.existsSync(variant)) {
72518
+ if (!fs15.existsSync(variant)) {
71764
72519
  continue;
71765
72520
  }
71766
- const packageJson = JSON.parse(fs14.readFileSync(variant, "utf-8"));
72521
+ const packageJson = JSON.parse(fs15.readFileSync(variant, "utf-8"));
71767
72522
  return typeof packageJson.version === "string" ? packageJson.version : null;
71768
72523
  } catch {
71769
72524
  return null;
@@ -71989,7 +72744,7 @@ function openExternalUrl(url2) {
71989
72744
 
71990
72745
  // src/utils/powerline.ts
71991
72746
  import { execSync as execSync5 } from "child_process";
71992
- import * as fs15 from "fs";
72747
+ import * as fs16 from "fs";
71993
72748
  import * as os12 from "os";
71994
72749
  import * as path11 from "path";
71995
72750
  var fontsInstalledThisSession = false;
@@ -72040,9 +72795,9 @@ function checkPowerlineFonts() {
72040
72795
  /fira.*code.*nerd/i
72041
72796
  ];
72042
72797
  for (const fontPath of fontPaths) {
72043
- if (fs15.existsSync(fontPath)) {
72798
+ if (fs16.existsSync(fontPath)) {
72044
72799
  try {
72045
- const files = fs15.readdirSync(fontPath);
72800
+ const files = fs16.readdirSync(fontPath);
72046
72801
  for (const file2 of files) {
72047
72802
  for (const pattern of powerlineFontPatterns) {
72048
72803
  if (pattern.test(file2)) {
@@ -72117,13 +72872,13 @@ async function installPowerlineFonts() {
72117
72872
  message: "Unsupported platform for font installation"
72118
72873
  };
72119
72874
  }
72120
- if (!fs15.existsSync(fontDir)) {
72121
- fs15.mkdirSync(fontDir, { recursive: true });
72875
+ if (!fs16.existsSync(fontDir)) {
72876
+ fs16.mkdirSync(fontDir, { recursive: true });
72122
72877
  }
72123
72878
  const tempDir = path11.join(os12.tmpdir(), `ccstatusline-powerline-fonts-${Date.now()}`);
72124
72879
  try {
72125
- if (fs15.existsSync(tempDir)) {
72126
- fs15.rmSync(tempDir, { recursive: true, force: true });
72880
+ if (fs16.existsSync(tempDir)) {
72881
+ fs16.rmSync(tempDir, { recursive: true, force: true });
72127
72882
  }
72128
72883
  execSync5(`git clone --depth=1 https://github.com/powerline/fonts.git "${tempDir}"`, {
72129
72884
  stdio: "pipe",
@@ -72132,8 +72887,8 @@ async function installPowerlineFonts() {
72132
72887
  });
72133
72888
  if (platform4 === "darwin" || platform4 === "linux") {
72134
72889
  const installScript = path11.join(tempDir, "install.sh");
72135
- if (fs15.existsSync(installScript)) {
72136
- fs15.chmodSync(installScript, 493);
72890
+ if (fs16.existsSync(installScript)) {
72891
+ fs16.chmodSync(installScript, 493);
72137
72892
  execSync5(`cd "${tempDir}" && ./install.sh`, {
72138
72893
  stdio: "pipe",
72139
72894
  encoding: "utf8",
@@ -72161,10 +72916,10 @@ async function installPowerlineFonts() {
72161
72916
  }
72162
72917
  } else {
72163
72918
  let findFontFiles = function(dir) {
72164
- const files = fs15.readdirSync(dir);
72919
+ const files = fs16.readdirSync(dir);
72165
72920
  for (const file2 of files) {
72166
72921
  const filePath = path11.join(dir, file2);
72167
- const stat2 = fs15.statSync(filePath);
72922
+ const stat2 = fs16.statSync(filePath);
72168
72923
  if (stat2.isDirectory() && !file2.startsWith(".")) {
72169
72924
  findFontFiles(filePath);
72170
72925
  } else if (file2.endsWith(".ttf") || file2.endsWith(".otf")) {
@@ -72181,7 +72936,7 @@ async function installPowerlineFonts() {
72181
72936
  const fileName = path11.basename(fontFile);
72182
72937
  const destPath = path11.join(fontDir, fileName);
72183
72938
  try {
72184
- fs15.copyFileSync(fontFile, destPath);
72939
+ fs16.copyFileSync(fontFile, destPath);
72185
72940
  installedCount++;
72186
72941
  } catch {}
72187
72942
  }
@@ -72199,9 +72954,9 @@ async function installPowerlineFonts() {
72199
72954
  message: "Platform-specific installation not implemented"
72200
72955
  };
72201
72956
  } finally {
72202
- if (fs15.existsSync(tempDir)) {
72957
+ if (fs16.existsSync(tempDir)) {
72203
72958
  try {
72204
- fs15.rmSync(tempDir, { recursive: true, force: true });
72959
+ fs16.rmSync(tempDir, { recursive: true, force: true });
72205
72960
  } catch {}
72206
72961
  }
72207
72962
  }
@@ -73819,6 +74574,7 @@ var ColorMenu = ({ widgets, lineIndex, settings, onUpdate, onBack }) => {
73819
74574
  };
73820
74575
  // src/tui/components/GlobalOverridesMenu.tsx
73821
74576
  init_ColorLevel();
74577
+ init_Settings();
73822
74578
  init_colors();
73823
74579
  init_gradient();
73824
74580
  init_input_guards();
@@ -74005,6 +74761,15 @@ var GlobalOverridesMenu = ({ settings, onUpdate, onBack }) => {
74005
74761
  overrideForegroundColor: undefined
74006
74762
  };
74007
74763
  onUpdate(updatedSettings);
74764
+ } else if (input === "d" || input === "D") {
74765
+ const paddingSides = DefaultPaddingSideSchema.options;
74766
+ const currentIndex = paddingSides.indexOf(settings.defaultPaddingSide);
74767
+ const nextSide = paddingSides[(currentIndex + 1) % paddingSides.length] ?? "both";
74768
+ const updatedSettings = {
74769
+ ...settings,
74770
+ defaultPaddingSide: nextSide
74771
+ };
74772
+ onUpdate(updatedSettings);
74008
74773
  }
74009
74774
  }
74010
74775
  });
@@ -74116,7 +74881,7 @@ var GlobalOverridesMenu = ({ settings, onUpdate, onBack }) => {
74116
74881
  /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Box_default, {
74117
74882
  children: [
74118
74883
  /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Text, {
74119
- children: "Enter default padding (applied to left and right of each widget): "
74884
+ children: "Enter default padding (applied per the Padding Side setting): "
74120
74885
  }, undefined, false, undefined, this),
74121
74886
  /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Text, {
74122
74887
  color: "cyan",
@@ -74242,6 +75007,21 @@ var GlobalOverridesMenu = ({ settings, onUpdate, onBack }) => {
74242
75007
  }, undefined, false, undefined, this)
74243
75008
  ]
74244
75009
  }, undefined, true, undefined, this),
75010
+ /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Box_default, {
75011
+ children: [
75012
+ /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Text, {
75013
+ children: " Padding Side: "
75014
+ }, undefined, false, undefined, this),
75015
+ /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Text, {
75016
+ color: "cyan",
75017
+ children: settings.defaultPaddingSide === "left" ? "Left only" : settings.defaultPaddingSide === "right" ? "Right only" : "Both"
75018
+ }, undefined, false, undefined, this),
75019
+ /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Text, {
75020
+ dimColor: true,
75021
+ children: " - Press (d) to cycle"
75022
+ }, undefined, false, undefined, this)
75023
+ ]
75024
+ }, undefined, true, undefined, this),
74245
75025
  /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Box_default, {
74246
75026
  children: [
74247
75027
  /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Text, {
@@ -74370,6 +75150,11 @@ var GlobalOverridesMenu = ({ settings, onUpdate, onBack }) => {
74370
75150
  wrap: "wrap",
74371
75151
  children: "Note: These settings are applied during rendering and don't add widgets to your widget list."
74372
75152
  }, undefined, false, undefined, this),
75153
+ /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Text, {
75154
+ dimColor: true,
75155
+ wrap: "wrap",
75156
+ children: "• Padding Side: Choose whether default padding applies to both sides, left only, or right only"
75157
+ }, undefined, false, undefined, this),
74373
75158
  /* @__PURE__ */ jsx_dev_runtime15.jsxDEV(Text, {
74374
75159
  dimColor: true,
74375
75160
  wrap: "wrap",
@@ -79300,14 +80085,15 @@ var StatusJSONSchema = exports_external.looseObject({
79300
80085
  init_ansi();
79301
80086
  init_colors();
79302
80087
  init_compaction();
80088
+ init_git_review_cache();
79303
80089
  await init_config();
79304
80090
 
79305
80091
  // src/utils/hook-handler.ts
79306
- import * as fs17 from "fs";
80092
+ import * as fs18 from "fs";
79307
80093
  import * as path13 from "path";
79308
80094
 
79309
80095
  // src/utils/skills.ts
79310
- import * as fs16 from "fs";
80096
+ import * as fs17 from "fs";
79311
80097
  import * as os14 from "os";
79312
80098
  import * as path12 from "path";
79313
80099
  var EMPTY = { totalInvocations: 0, uniqueSkills: [], lastSkill: null };
@@ -79319,11 +80105,11 @@ function getSkillsFilePath(sessionId) {
79319
80105
  }
79320
80106
  function getSkillsMetrics(sessionId) {
79321
80107
  const filePath = getSkillsFilePath(sessionId);
79322
- if (!fs16.existsSync(filePath)) {
80108
+ if (!fs17.existsSync(filePath)) {
79323
80109
  return EMPTY;
79324
80110
  }
79325
80111
  try {
79326
- const invocations = fs16.readFileSync(filePath, "utf-8").trim().split(`
80112
+ const invocations = fs17.readFileSync(filePath, "utf-8").trim().split(`
79327
80113
  `).filter((line) => line.trim()).map((line) => {
79328
80114
  try {
79329
80115
  return JSON.parse(line);
@@ -79377,14 +80163,14 @@ function handleHookInput(input) {
79377
80163
  return;
79378
80164
  }
79379
80165
  const filePath = getSkillsFilePath(sessionId);
79380
- fs17.mkdirSync(path13.dirname(filePath), { recursive: true });
80166
+ fs18.mkdirSync(path13.dirname(filePath), { recursive: true });
79381
80167
  const entry = JSON.stringify({
79382
80168
  timestamp: new Date().toISOString(),
79383
80169
  session_id: sessionId,
79384
80170
  skill: skillName,
79385
80171
  source: data.hook_event_name
79386
80172
  });
79387
- fs17.appendFileSync(filePath, entry + `
80173
+ fs18.appendFileSync(filePath, entry + `
79388
80174
  `);
79389
80175
  } catch {}
79390
80176
  }
@@ -79661,7 +80447,8 @@ async function renderMultipleLines(data) {
79661
80447
  terminalWidth: getTerminalWidth(),
79662
80448
  isPreview: false,
79663
80449
  minimalist: settings.minimalistMode,
79664
- gitCacheTtlSeconds: settings.gitCacheTtlSeconds
80450
+ gitCacheTtlSeconds: settings.gitCacheTtlSeconds,
80451
+ gitReviewNeedsChecks: lines.some((line) => line.some((item) => item.type === "git-ci-status"))
79665
80452
  };
79666
80453
  const preRenderedLines = preRenderAllWidgets(lines, settings, context);
79667
80454
  const preCalculatedMaxWidths = calculateMaxWidthsFromPreRendered(preRenderedLines, settings);
@@ -79736,7 +80523,24 @@ async function handleHook() {
79736
80523
  const input = await readStdin();
79737
80524
  handleHookInput(input);
79738
80525
  }
80526
+ function handleGitReviewRefresh() {
80527
+ const flagIndex = process.argv.indexOf(GIT_REVIEW_REFRESH_FLAG);
80528
+ if (flagIndex === -1) {
80529
+ return false;
80530
+ }
80531
+ const cwd2 = process.argv[flagIndex + 1];
80532
+ const mode = process.argv[flagIndex + 2];
80533
+ const lockPath = process.argv[flagIndex + 3];
80534
+ if (!cwd2 || mode !== "metadata" && mode !== "checks" || !lockPath) {
80535
+ return true;
80536
+ }
80537
+ refreshGitReviewCacheFromCli(cwd2, { includeChecks: mode === "checks" }, lockPath);
80538
+ return true;
80539
+ }
79739
80540
  async function main() {
80541
+ if (handleGitReviewRefresh()) {
80542
+ return;
80543
+ }
79740
80544
  if (process.argv.includes("--version")) {
79741
80545
  console.log(getPackageVersion());
79742
80546
  process.exit(0);