@rotorsoft/gent 1.15.3 → 1.16.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -2221,7 +2221,7 @@ import { homedir } from "os";
2221
2221
  // package.json
2222
2222
  var package_default = {
2223
2223
  name: "@rotorsoft/gent",
2224
- version: "1.15.3",
2224
+ version: "1.16.0",
2225
2225
  description: "AI-powered GitHub workflow CLI - leverage AI (Claude, Gemini, or Codex) to create tickets, implement features, and manage PRs",
2226
2226
  keywords: [
2227
2227
  "cli",
@@ -2646,6 +2646,7 @@ async function statusCommand() {
2646
2646
  import { execa as execa4 } from "execa";
2647
2647
 
2648
2648
  // src/tui/state.ts
2649
+ var envCache = null;
2649
2650
  async function aggregateState() {
2650
2651
  const isGitRepo = await checkGitRepo();
2651
2652
  if (!isGitRepo) {
@@ -2675,16 +2676,20 @@ async function aggregateState() {
2675
2676
  }
2676
2677
  const config = loadConfig();
2677
2678
  const workflowLabels = getWorkflowLabels(config);
2678
- const [
2679
- isGhAuthenticated,
2680
- isAIProviderAvailable,
2681
- branch,
2682
- isOnMain,
2683
- uncommitted,
2684
- baseBranch
2685
- ] = await Promise.all([
2686
- checkGhAuth(),
2687
- checkAIProvider(config.ai.provider),
2679
+ if (!envCache) {
2680
+ const [ghAuth, aiAvail] = await Promise.all([
2681
+ checkGhAuth(),
2682
+ checkAIProvider(config.ai.provider)
2683
+ ]);
2684
+ envCache = {
2685
+ isGhAuthenticated: ghAuth,
2686
+ isAIProviderAvailable: aiAvail,
2687
+ isPlaywrightAvailable: false
2688
+ // resolved below on first feature branch visit
2689
+ };
2690
+ }
2691
+ const { isGhAuthenticated, isAIProviderAvailable } = envCache;
2692
+ const [branch, isOnMain, uncommitted, baseBranch] = await Promise.all([
2688
2693
  getCurrentBranch(),
2689
2694
  isOnMainBranch(),
2690
2695
  hasUncommittedChanges(),
@@ -2706,16 +2711,20 @@ async function aggregateState() {
2706
2711
  let playwrightAvailable = false;
2707
2712
  if (!isOnMain) {
2708
2713
  const issueNumber = extractIssueNumber(branch);
2714
+ const needsPlaywrightCheck = !envCache.isPlaywrightAvailable;
2709
2715
  const [issueResult, prResult, changedFiles, playwrightResult] = await Promise.all([
2710
2716
  issueNumber ? getIssue(issueNumber).catch(() => null) : Promise.resolve(null),
2711
2717
  getPrStatus().catch(() => null),
2712
2718
  getChangedFiles(baseBranch),
2713
- isPlaywrightAvailable()
2719
+ needsPlaywrightCheck ? isPlaywrightAvailable() : Promise.resolve(envCache.isPlaywrightAvailable)
2714
2720
  ]);
2715
2721
  issue = issueResult;
2716
2722
  pr = prResult;
2717
2723
  uiChanges = hasUIChanges(changedFiles);
2718
2724
  playwrightAvailable = playwrightResult;
2725
+ if (needsPlaywrightCheck) {
2726
+ envCache.isPlaywrightAvailable = playwrightResult;
2727
+ }
2719
2728
  if (issue) {
2720
2729
  if (issue.labels.includes(workflowLabels.ready)) {
2721
2730
  workflowStatus = "ready";
@@ -2935,14 +2944,24 @@ function renderActionPanel(title, content) {
2935
2944
  }
2936
2945
  console.log(botRow(w));
2937
2946
  }
2938
- function renderSettingsTo(state, w, out) {
2947
+ function renderSettingsTo(state, w, out, versionCheck) {
2939
2948
  const provider = getProviderDisplayName(state.config.ai.provider);
2940
2949
  const provTag = state.isAIProviderAvailable ? chalk3.green(provider) : chalk3.red(provider);
2941
2950
  const ghTag = state.isGhAuthenticated ? chalk3.green("authenticated") : chalk3.red("not authenticated");
2942
2951
  out(row(chalk3.dim("Provider: ") + provTag, w));
2943
2952
  out(row(chalk3.dim("GitHub: ") + ghTag, w));
2953
+ if (versionCheck?.updateAvailable && versionCheck.latestVersion) {
2954
+ out(
2955
+ row(
2956
+ chalk3.yellow(
2957
+ `Update available: ${versionCheck.currentVersion} \u2192 ${versionCheck.latestVersion}`
2958
+ ) + chalk3.dim(' \u2014 run "npm install -g @rotorsoft/gent" to upgrade'),
2959
+ w
2960
+ )
2961
+ );
2962
+ }
2944
2963
  }
2945
- function buildDashboardLines(state, actions, hint, refreshing) {
2964
+ function buildDashboardLines(state, actions, hint, refreshing, versionCheck) {
2946
2965
  const lines = [];
2947
2966
  const out = (line) => lines.push(line);
2948
2967
  const w = termWidth();
@@ -2950,7 +2969,7 @@ function buildDashboardLines(state, actions, hint, refreshing) {
2950
2969
  const version2 = getVersion();
2951
2970
  const titleLabel = `gent v${version2}`;
2952
2971
  out(topRow(titleLabel, w));
2953
- renderSettingsTo(state, w, out);
2972
+ renderSettingsTo(state, w, out, versionCheck);
2954
2973
  if (!state.isGitRepo) {
2955
2974
  out(row(chalk3.red("Not a git repository"), w));
2956
2975
  out(row(chalk3.dim("Run gent init in a git repo to get started"), w));
@@ -3071,8 +3090,8 @@ function buildDashboardLines(state, actions, hint, refreshing) {
3071
3090
  out(botRow(w));
3072
3091
  return lines;
3073
3092
  }
3074
- function renderDashboard(state, actions, hint, refreshing) {
3075
- const lines = buildDashboardLines(state, actions, hint, refreshing);
3093
+ function renderDashboard(state, actions, hint, refreshing, versionCheck) {
3094
+ const lines = buildDashboardLines(state, actions, hint, refreshing, versionCheck);
3076
3095
  for (const line of lines) {
3077
3096
  console.log(line);
3078
3097
  }
@@ -3828,10 +3847,12 @@ async function offerCreateBranch2(issueNumber, title, dashboardLines) {
3828
3847
  await createBranch(branchName, defaultBranch);
3829
3848
  return true;
3830
3849
  }
3850
+ var VERSION_CHECK_INTERVAL_MS = 30 * 60 * 1e3;
3831
3851
  async function tuiCommand() {
3832
3852
  let running = true;
3833
3853
  let lastActions = [];
3834
3854
  let lastDashboardLines = [];
3855
+ let versionCheck = null;
3835
3856
  const config = loadConfig();
3836
3857
  let lastState = {
3837
3858
  isGitRepo: true,
@@ -3859,11 +3880,15 @@ async function tuiCommand() {
3859
3880
  while (running) {
3860
3881
  if (needsRefresh) {
3861
3882
  clearScreen();
3862
- renderDashboard(lastState, lastActions, void 0, true);
3863
- const state = await aggregateState();
3883
+ renderDashboard(lastState, lastActions, void 0, true, versionCheck);
3884
+ const [state, versionResult] = await Promise.all([
3885
+ aggregateState(),
3886
+ checkForUpdates(VERSION_CHECK_INTERVAL_MS).catch(() => null)
3887
+ ]);
3864
3888
  const actions = getAvailableActions(state);
3865
3889
  lastState = state;
3866
3890
  lastActions = actions;
3891
+ if (versionResult) versionCheck = versionResult;
3867
3892
  }
3868
3893
  let hint;
3869
3894
  if (lastState.isOnMain) {
@@ -3873,7 +3898,7 @@ async function tuiCommand() {
3873
3898
  } else if (lastState.hasActionableFeedback) {
3874
3899
  hint = "Review feedback needs attention";
3875
3900
  }
3876
- lastDashboardLines = buildDashboardLines(lastState, lastActions, hint);
3901
+ lastDashboardLines = buildDashboardLines(lastState, lastActions, hint, false, versionCheck);
3877
3902
  clearScreen();
3878
3903
  for (const line of lastDashboardLines) {
3879
3904
  console.log(line);