@rotorsoft/gent 1.15.1 → 1.15.3
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 +157 -84
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -212,6 +212,17 @@ import chalk from "chalk";
|
|
|
212
212
|
// src/lib/ai-provider.ts
|
|
213
213
|
import { spawn } from "child_process";
|
|
214
214
|
import { execa } from "execa";
|
|
215
|
+
async function getOtherAvailableProviders(currentProvider) {
|
|
216
|
+
const allProviders = ["claude", "gemini", "codex"];
|
|
217
|
+
const others = allProviders.filter((p) => p !== currentProvider);
|
|
218
|
+
const available = [];
|
|
219
|
+
for (const p of others) {
|
|
220
|
+
if (await checkAIProvider(p)) {
|
|
221
|
+
available.push(p);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
return available;
|
|
225
|
+
}
|
|
215
226
|
async function invokeInternal(provider, options) {
|
|
216
227
|
switch (provider) {
|
|
217
228
|
case "claude":
|
|
@@ -620,11 +631,10 @@ async function createCommand(description, options) {
|
|
|
620
631
|
logger.bold("Creating AI-enhanced ticket...");
|
|
621
632
|
logger.newline();
|
|
622
633
|
const config = loadConfig();
|
|
623
|
-
|
|
624
|
-
const providerName = getProviderDisplayName(provider);
|
|
634
|
+
let currentProvider = resolveProvider(options, config);
|
|
625
635
|
const [ghAuth, aiOk] = await Promise.all([
|
|
626
636
|
checkGhAuth(),
|
|
627
|
-
checkAIProvider(
|
|
637
|
+
checkAIProvider(currentProvider)
|
|
628
638
|
]);
|
|
629
639
|
if (!ghAuth) {
|
|
630
640
|
logger.error("Not authenticated with GitHub. Run 'gh auth login' first.");
|
|
@@ -632,7 +642,7 @@ async function createCommand(description, options) {
|
|
|
632
642
|
}
|
|
633
643
|
if (!aiOk) {
|
|
634
644
|
logger.error(
|
|
635
|
-
`${
|
|
645
|
+
`${getProviderDisplayName(currentProvider)} CLI not found. Please install ${currentProvider} CLI first.`
|
|
636
646
|
);
|
|
637
647
|
return;
|
|
638
648
|
}
|
|
@@ -640,6 +650,7 @@ async function createCommand(description, options) {
|
|
|
640
650
|
let aiOutput;
|
|
641
651
|
let additionalHints = null;
|
|
642
652
|
while (true) {
|
|
653
|
+
const providerName = getProviderDisplayName(currentProvider);
|
|
643
654
|
const prompt = buildTicketPrompt(
|
|
644
655
|
description,
|
|
645
656
|
agentInstructions,
|
|
@@ -655,7 +666,7 @@ async function createCommand(description, options) {
|
|
|
655
666
|
const result = await invokeAI(
|
|
656
667
|
{ prompt, streamOutput: true },
|
|
657
668
|
config,
|
|
658
|
-
|
|
669
|
+
currentProvider
|
|
659
670
|
);
|
|
660
671
|
aiOutput = result.output;
|
|
661
672
|
logger.newline();
|
|
@@ -666,6 +677,33 @@ async function createCommand(description, options) {
|
|
|
666
677
|
);
|
|
667
678
|
logger.newline();
|
|
668
679
|
} catch (error) {
|
|
680
|
+
if (error && typeof error === "object" && "rateLimited" in error) {
|
|
681
|
+
logger.warning(`${providerName} is rate limited.`);
|
|
682
|
+
const others = await getOtherAvailableProviders(currentProvider);
|
|
683
|
+
if (others.length > 0) {
|
|
684
|
+
const { nextProvider } = await inquirer2.prompt([
|
|
685
|
+
{
|
|
686
|
+
type: "list",
|
|
687
|
+
name: "nextProvider",
|
|
688
|
+
message: "Would you like to try another provider?",
|
|
689
|
+
choices: [
|
|
690
|
+
...others.map((p) => ({
|
|
691
|
+
name: `Switch to ${getProviderDisplayName(p)}`,
|
|
692
|
+
value: p
|
|
693
|
+
})),
|
|
694
|
+
{ name: "Cancel", value: "cancel" }
|
|
695
|
+
]
|
|
696
|
+
}
|
|
697
|
+
]);
|
|
698
|
+
if (nextProvider !== "cancel") {
|
|
699
|
+
currentProvider = nextProvider;
|
|
700
|
+
logger.info(
|
|
701
|
+
`Switching to ${getProviderDisplayName(currentProvider)}...`
|
|
702
|
+
);
|
|
703
|
+
continue;
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
}
|
|
669
707
|
logger.error(`${providerName} invocation failed: ${error}`);
|
|
670
708
|
return;
|
|
671
709
|
}
|
|
@@ -1600,15 +1638,15 @@ async function getChangedFiles(baseBranch = "main") {
|
|
|
1600
1638
|
}
|
|
1601
1639
|
|
|
1602
1640
|
// src/commands/pr.ts
|
|
1641
|
+
import inquirer5 from "inquirer";
|
|
1603
1642
|
async function prCommand(options) {
|
|
1604
1643
|
logger.bold("Creating AI-enhanced pull request...");
|
|
1605
1644
|
logger.newline();
|
|
1606
1645
|
const config = loadConfig();
|
|
1607
|
-
|
|
1608
|
-
const providerName = getProviderDisplayName(provider);
|
|
1646
|
+
let currentProvider = options.provider ?? config.ai.provider;
|
|
1609
1647
|
const [ghAuth, aiOk] = await Promise.all([
|
|
1610
1648
|
checkGhAuth(),
|
|
1611
|
-
checkAIProvider(
|
|
1649
|
+
checkAIProvider(currentProvider)
|
|
1612
1650
|
]);
|
|
1613
1651
|
if (!ghAuth) {
|
|
1614
1652
|
logger.error("Not authenticated with GitHub. Run 'gh auth login' first.");
|
|
@@ -1616,7 +1654,7 @@ async function prCommand(options) {
|
|
|
1616
1654
|
}
|
|
1617
1655
|
if (!aiOk) {
|
|
1618
1656
|
logger.error(
|
|
1619
|
-
`${
|
|
1657
|
+
`${getProviderDisplayName(currentProvider)} CLI not found. Please install ${currentProvider} CLI first.`
|
|
1620
1658
|
);
|
|
1621
1659
|
return;
|
|
1622
1660
|
}
|
|
@@ -1692,26 +1730,59 @@ IMPORTANT: This PR contains UI changes. Use the Playwright MCP plugin to:
|
|
|
1692
1730
|
}
|
|
1693
1731
|
const prompt = buildPrPrompt(issue, commits, diffSummary) + captureVideoInstructions;
|
|
1694
1732
|
let prBody;
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1733
|
+
let usedProvider = currentProvider;
|
|
1734
|
+
while (true) {
|
|
1735
|
+
const providerName = getProviderDisplayName(usedProvider);
|
|
1736
|
+
try {
|
|
1737
|
+
logger.info(
|
|
1738
|
+
`Generating PR description with ${colors.provider(providerName)}...`
|
|
1739
|
+
);
|
|
1740
|
+
logger.newline();
|
|
1741
|
+
const result = await invokeAI(
|
|
1742
|
+
{ prompt, streamOutput: true },
|
|
1743
|
+
config,
|
|
1744
|
+
usedProvider
|
|
1745
|
+
);
|
|
1746
|
+
prBody = result.output;
|
|
1747
|
+
logger.newline();
|
|
1748
|
+
break;
|
|
1749
|
+
} catch (error) {
|
|
1750
|
+
if (error && typeof error === "object" && "rateLimited" in error) {
|
|
1751
|
+
logger.warning(`${providerName} is rate limited.`);
|
|
1752
|
+
const others = await getOtherAvailableProviders(usedProvider);
|
|
1753
|
+
if (others.length > 0) {
|
|
1754
|
+
const { nextProvider } = await inquirer5.prompt([
|
|
1755
|
+
{
|
|
1756
|
+
type: "list",
|
|
1757
|
+
name: "nextProvider",
|
|
1758
|
+
message: "Would you like to try another provider?",
|
|
1759
|
+
choices: [
|
|
1760
|
+
...others.map((p) => ({
|
|
1761
|
+
name: `Switch to ${getProviderDisplayName(p)}`,
|
|
1762
|
+
value: p
|
|
1763
|
+
})),
|
|
1764
|
+
{ name: "Fall back to basic description", value: "fallback" }
|
|
1765
|
+
]
|
|
1766
|
+
}
|
|
1767
|
+
]);
|
|
1768
|
+
if (nextProvider !== "fallback") {
|
|
1769
|
+
usedProvider = nextProvider;
|
|
1770
|
+
logger.info(
|
|
1771
|
+
`Switching to ${getProviderDisplayName(usedProvider)}...`
|
|
1772
|
+
);
|
|
1773
|
+
continue;
|
|
1774
|
+
}
|
|
1775
|
+
}
|
|
1776
|
+
}
|
|
1777
|
+
logger.warning(`${providerName} invocation failed: ${error}`);
|
|
1778
|
+
prBody = generateFallbackBody(issue, commits);
|
|
1779
|
+
break;
|
|
1780
|
+
}
|
|
1710
1781
|
}
|
|
1711
1782
|
prBody += `
|
|
1712
1783
|
|
|
1713
1784
|
---
|
|
1714
|
-
*Created with ${
|
|
1785
|
+
*Created with ${getProviderDisplayName(usedProvider)} by [gent](https://github.com/Rotorsoft/gent)*`;
|
|
1715
1786
|
const prTitle = issue?.title || commits[0] || currentBranch;
|
|
1716
1787
|
let prUrl;
|
|
1717
1788
|
try {
|
|
@@ -1793,7 +1864,7 @@ function generateFallbackBody(issue, commits) {
|
|
|
1793
1864
|
}
|
|
1794
1865
|
|
|
1795
1866
|
// src/commands/fix.ts
|
|
1796
|
-
import
|
|
1867
|
+
import inquirer6 from "inquirer";
|
|
1797
1868
|
|
|
1798
1869
|
// src/lib/review-feedback.ts
|
|
1799
1870
|
var ACTIONABLE_KEYWORDS = [
|
|
@@ -1990,7 +2061,7 @@ async function fixCommand(options) {
|
|
|
1990
2061
|
const hasChanges = await hasUncommittedChanges();
|
|
1991
2062
|
if (hasChanges) {
|
|
1992
2063
|
logger.warning("You have uncommitted changes.");
|
|
1993
|
-
const { proceed } = await
|
|
2064
|
+
const { proceed } = await inquirer6.prompt([
|
|
1994
2065
|
{
|
|
1995
2066
|
type: "confirm",
|
|
1996
2067
|
name: "proceed",
|
|
@@ -2150,7 +2221,7 @@ import { homedir } from "os";
|
|
|
2150
2221
|
// package.json
|
|
2151
2222
|
var package_default = {
|
|
2152
2223
|
name: "@rotorsoft/gent",
|
|
2153
|
-
version: "1.15.
|
|
2224
|
+
version: "1.15.3",
|
|
2154
2225
|
description: "AI-powered GitHub workflow CLI - leverage AI (Claude, Gemini, or Codex) to create tickets, implement features, and manage PRs",
|
|
2155
2226
|
keywords: [
|
|
2156
2227
|
"cli",
|
|
@@ -2700,25 +2771,20 @@ function getAvailableActions(state) {
|
|
|
2700
2771
|
actions.push({ id: "quit", label: "quit", shortcut: "q" });
|
|
2701
2772
|
return actions;
|
|
2702
2773
|
}
|
|
2703
|
-
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2711
|
-
|
|
2712
|
-
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
if (!state.pr && state.commits.length > 0) {
|
|
2718
|
-
actions.push({ id: "pr", label: "pr", shortcut: "r" });
|
|
2719
|
-
}
|
|
2720
|
-
if (state.issue && state.pr?.state !== "merged") {
|
|
2721
|
-
actions.push({ id: "run", label: "run", shortcut: "u" });
|
|
2774
|
+
actions.push({ id: "create", label: "new", shortcut: "n" });
|
|
2775
|
+
if (!state.isOnMain) {
|
|
2776
|
+
if (state.hasUncommittedChanges) {
|
|
2777
|
+
actions.push({ id: "commit", label: "commit", shortcut: "c" });
|
|
2778
|
+
}
|
|
2779
|
+
if (state.hasUnpushedCommits && state.commits.length > 0) {
|
|
2780
|
+
actions.push({ id: "push", label: "push", shortcut: "p" });
|
|
2781
|
+
}
|
|
2782
|
+
if (!state.pr && state.commits.length > 0) {
|
|
2783
|
+
actions.push({ id: "pr", label: "pr", shortcut: "r" });
|
|
2784
|
+
}
|
|
2785
|
+
if (state.issue && state.pr?.state !== "merged") {
|
|
2786
|
+
actions.push({ id: "run", label: "run", shortcut: "u" });
|
|
2787
|
+
}
|
|
2722
2788
|
}
|
|
2723
2789
|
actions.push({ id: "list", label: "list", shortcut: "l" });
|
|
2724
2790
|
actions.push({ id: "refresh", label: "refresh", shortcut: "f" });
|
|
@@ -2731,6 +2797,23 @@ function getAvailableActions(state) {
|
|
|
2731
2797
|
import chalk3 from "chalk";
|
|
2732
2798
|
var stripAnsi = (str) => str.replace(/\x1b\[[0-9;]*m/g, "");
|
|
2733
2799
|
var visibleLen = (str) => stripAnsi(str).length;
|
|
2800
|
+
function truncateAnsi(text, max) {
|
|
2801
|
+
if (visibleLen(text) <= max) return text;
|
|
2802
|
+
let visible = 0;
|
|
2803
|
+
let i = 0;
|
|
2804
|
+
while (i < text.length && visible < max - 1) {
|
|
2805
|
+
if (text[i] === "\x1B") {
|
|
2806
|
+
const end = text.indexOf("m", i);
|
|
2807
|
+
if (end !== -1) {
|
|
2808
|
+
i = end + 1;
|
|
2809
|
+
continue;
|
|
2810
|
+
}
|
|
2811
|
+
}
|
|
2812
|
+
visible++;
|
|
2813
|
+
i++;
|
|
2814
|
+
}
|
|
2815
|
+
return text.slice(0, i) + "\x1B[0m\u2026";
|
|
2816
|
+
}
|
|
2734
2817
|
function termWidth() {
|
|
2735
2818
|
return Math.min(process.stdout.columns || 80, 90);
|
|
2736
2819
|
}
|
|
@@ -2770,8 +2853,9 @@ function botRow(w) {
|
|
|
2770
2853
|
}
|
|
2771
2854
|
function row(text, w) {
|
|
2772
2855
|
const inner = w - 4;
|
|
2773
|
-
const
|
|
2774
|
-
|
|
2856
|
+
const fitted = truncateAnsi(text, inner);
|
|
2857
|
+
const pad = Math.max(0, inner - visibleLen(fitted));
|
|
2858
|
+
return chalk3.dim("\u2502") + " " + fitted + " ".repeat(pad) + " " + chalk3.dim("\u2502");
|
|
2775
2859
|
}
|
|
2776
2860
|
function workflowBadge(status) {
|
|
2777
2861
|
switch (status) {
|
|
@@ -2887,12 +2971,12 @@ function buildDashboardLines(state, actions, hint, refreshing) {
|
|
|
2887
2971
|
if (state.issue) {
|
|
2888
2972
|
out(
|
|
2889
2973
|
row(
|
|
2890
|
-
chalk3.cyan(`#${state.issue.number}`) + "
|
|
2974
|
+
chalk3.dim("\xB7 ") + chalk3.cyan(`#${state.issue.number}`) + " " + chalk3.bold(state.issue.title),
|
|
2891
2975
|
w
|
|
2892
2976
|
)
|
|
2893
2977
|
);
|
|
2894
2978
|
const desc = extractDescription(state.issue.body, descMax);
|
|
2895
|
-
if (desc) out(row(chalk3.dim(desc), w));
|
|
2979
|
+
if (desc) out(row(" " + chalk3.dim(desc), w));
|
|
2896
2980
|
const tags = [];
|
|
2897
2981
|
if (state.workflowStatus !== "none")
|
|
2898
2982
|
tags.push(workflowBadge(state.workflowStatus));
|
|
@@ -2900,13 +2984,13 @@ function buildDashboardLines(state, actions, hint, refreshing) {
|
|
|
2900
2984
|
const l = state.issue.labels.find((x) => x.startsWith(prefix));
|
|
2901
2985
|
if (l) tags.push(chalk3.dim(l));
|
|
2902
2986
|
}
|
|
2903
|
-
if (tags.length) out(row(tags.join(" "), w));
|
|
2987
|
+
if (tags.length) out(row(" " + tags.join(" "), w));
|
|
2904
2988
|
} else {
|
|
2905
|
-
out(row(chalk3.dim("No linked issue"), w));
|
|
2989
|
+
out(row(chalk3.dim(" No linked issue"), w));
|
|
2906
2990
|
}
|
|
2907
2991
|
}
|
|
2908
2992
|
section("Branch");
|
|
2909
|
-
let branchLine = chalk3.magenta(state.branch);
|
|
2993
|
+
let branchLine = chalk3.dim("\xB7 ") + chalk3.magenta(state.branch);
|
|
2910
2994
|
if (state.isOnMain && !state.hasUncommittedChanges) {
|
|
2911
2995
|
branchLine += chalk3.dim(" \xB7 ready to start new work");
|
|
2912
2996
|
}
|
|
@@ -2919,15 +3003,20 @@ function buildDashboardLines(state, actions, hint, refreshing) {
|
|
|
2919
3003
|
if (!state.hasUncommittedChanges && !state.hasUnpushedCommits && state.commits.length > 0) {
|
|
2920
3004
|
bits.push(chalk3.green("\u25CF synced"));
|
|
2921
3005
|
}
|
|
2922
|
-
if (bits.length) out(row(bits.join(chalk3.dim(" \xB7 ")), w));
|
|
3006
|
+
if (bits.length) out(row(" " + bits.join(chalk3.dim(" \xB7 ")), w));
|
|
2923
3007
|
if (state.pr || !state.isOnMain) {
|
|
2924
3008
|
section("Pull Request");
|
|
2925
3009
|
if (state.pr) {
|
|
2926
|
-
const titleText = state.pr.title ? "
|
|
2927
|
-
out(
|
|
3010
|
+
const titleText = state.pr.title ? " " + state.pr.title : "";
|
|
3011
|
+
out(
|
|
3012
|
+
row(
|
|
3013
|
+
chalk3.dim("\xB7 ") + chalk3.cyan(`#${state.pr.number}`) + titleText,
|
|
3014
|
+
w
|
|
3015
|
+
)
|
|
3016
|
+
);
|
|
2928
3017
|
out(
|
|
2929
3018
|
row(
|
|
2930
|
-
prBadge(state.pr.state, state.pr.isDraft) + reviewBadge(state.pr.reviewDecision),
|
|
3019
|
+
" " + prBadge(state.pr.state, state.pr.isDraft) + reviewBadge(state.pr.reviewDecision),
|
|
2931
3020
|
w
|
|
2932
3021
|
)
|
|
2933
3022
|
);
|
|
@@ -2935,7 +3024,7 @@ function buildDashboardLines(state, actions, hint, refreshing) {
|
|
|
2935
3024
|
const n = state.reviewFeedback.length;
|
|
2936
3025
|
out(
|
|
2937
3026
|
row(
|
|
2938
|
-
chalk3.yellow(`${n} actionable comment${n !== 1 ? "s" : ""} pending`),
|
|
3027
|
+
" " + chalk3.yellow(`${n} actionable comment${n !== 1 ? "s" : ""} pending`),
|
|
2939
3028
|
w
|
|
2940
3029
|
)
|
|
2941
3030
|
);
|
|
@@ -2943,14 +3032,14 @@ function buildDashboardLines(state, actions, hint, refreshing) {
|
|
|
2943
3032
|
if (state.hasUIChanges && state.isPlaywrightAvailable && state.config.video.enabled && state.pr.state === "open") {
|
|
2944
3033
|
out(
|
|
2945
3034
|
row(
|
|
2946
|
-
chalk3.cyan("UI changes detected") + chalk3.dim(" \xB7 video capture available"),
|
|
3035
|
+
" " + chalk3.cyan("UI changes detected") + chalk3.dim(" \xB7 video capture available"),
|
|
2947
3036
|
w
|
|
2948
3037
|
)
|
|
2949
3038
|
);
|
|
2950
3039
|
}
|
|
2951
|
-
out(row(chalk3.dim(state.pr.url), w));
|
|
3040
|
+
out(row(" " + chalk3.dim(state.pr.url), w));
|
|
2952
3041
|
} else {
|
|
2953
|
-
out(row(chalk3.dim("No PR created"), w));
|
|
3042
|
+
out(row(chalk3.dim(" No PR created"), w));
|
|
2954
3043
|
}
|
|
2955
3044
|
}
|
|
2956
3045
|
if (state.commits.length > 0 || !state.isOnMain) {
|
|
@@ -2958,13 +3047,13 @@ function buildDashboardLines(state, actions, hint, refreshing) {
|
|
|
2958
3047
|
if (state.commits.length > 0) {
|
|
2959
3048
|
const max = 6;
|
|
2960
3049
|
for (const c of state.commits.slice(0, max)) {
|
|
2961
|
-
out(row(
|
|
3050
|
+
out(row(chalk3.dim("\xB7 ") + c, w));
|
|
2962
3051
|
}
|
|
2963
3052
|
if (state.commits.length > max) {
|
|
2964
|
-
out(row(chalk3.dim(
|
|
3053
|
+
out(row(chalk3.dim(` \u2026 and ${state.commits.length - max} more`), w));
|
|
2965
3054
|
}
|
|
2966
3055
|
} else {
|
|
2967
|
-
out(row(chalk3.dim("No commits"), w));
|
|
3056
|
+
out(row(chalk3.dim(" No commits"), w));
|
|
2968
3057
|
}
|
|
2969
3058
|
}
|
|
2970
3059
|
if (hint) {
|
|
@@ -3005,23 +3094,6 @@ function modalDivRow(w) {
|
|
|
3005
3094
|
function modalBotRow(w) {
|
|
3006
3095
|
return chalk4.bold("\u2514" + "\u2500".repeat(w - 2) + "\u2518");
|
|
3007
3096
|
}
|
|
3008
|
-
function truncateAnsi(text, max) {
|
|
3009
|
-
if (visibleLen(text) <= max) return text;
|
|
3010
|
-
let visible = 0;
|
|
3011
|
-
let i = 0;
|
|
3012
|
-
while (i < text.length && visible < max - 1) {
|
|
3013
|
-
if (text[i] === "\x1B") {
|
|
3014
|
-
const end = text.indexOf("m", i);
|
|
3015
|
-
if (end !== -1) {
|
|
3016
|
-
i = end + 1;
|
|
3017
|
-
continue;
|
|
3018
|
-
}
|
|
3019
|
-
}
|
|
3020
|
-
visible++;
|
|
3021
|
-
i++;
|
|
3022
|
-
}
|
|
3023
|
-
return text.slice(0, i) + "\x1B[0m\u2026";
|
|
3024
|
-
}
|
|
3025
3097
|
function modalRow(text, w) {
|
|
3026
3098
|
const inner = w - 4;
|
|
3027
3099
|
const fitted = truncateAnsi(text, inner);
|
|
@@ -3056,9 +3128,10 @@ function buildSelectContent(items, selectedIndex, maxWidth) {
|
|
|
3056
3128
|
} else {
|
|
3057
3129
|
const isSelected = selectableIdx === selectedIndex;
|
|
3058
3130
|
const prefix = isSelected ? chalk4.cyan.bold("> ") : " ";
|
|
3059
|
-
const
|
|
3131
|
+
const bullet = chalk4.dim("\xB7 ");
|
|
3132
|
+
const label = truncateAnsi(item.name, maxWidth - 4);
|
|
3060
3133
|
lines.push(
|
|
3061
|
-
prefix + (isSelected ? chalk4.bold(label) : label)
|
|
3134
|
+
prefix + bullet + (isSelected ? chalk4.bold(label) : label)
|
|
3062
3135
|
);
|
|
3063
3136
|
selectableIdx++;
|
|
3064
3137
|
}
|