@braingrid/cli 0.2.44 → 0.2.46
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/CHANGELOG.md +18 -0
- package/dist/cli.js +688 -532
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -31,6 +31,7 @@ function createCompletion() {
|
|
|
31
31
|
const completion = omelette("braingrid <command> <sub1> <sub2>");
|
|
32
32
|
completion.on("command", ({ reply }) => {
|
|
33
33
|
reply([
|
|
34
|
+
"claude-code",
|
|
34
35
|
"completion",
|
|
35
36
|
"init",
|
|
36
37
|
"login",
|
|
@@ -92,6 +93,11 @@ function createCompletion() {
|
|
|
92
93
|
"update"
|
|
93
94
|
]);
|
|
94
95
|
});
|
|
96
|
+
completion.on("claude-code", ({ reply }) => {
|
|
97
|
+
reply([
|
|
98
|
+
"credentials"
|
|
99
|
+
]);
|
|
100
|
+
});
|
|
95
101
|
return completion;
|
|
96
102
|
}
|
|
97
103
|
|
|
@@ -222,7 +228,7 @@ async function axiosWithRetry(config2, options) {
|
|
|
222
228
|
|
|
223
229
|
// src/build-config.ts
|
|
224
230
|
var BUILD_ENV = true ? "production" : process.env.NODE_ENV === "test" ? "development" : "production";
|
|
225
|
-
var CLI_VERSION = true ? "0.2.
|
|
231
|
+
var CLI_VERSION = true ? "0.2.46" : "0.0.0-test";
|
|
226
232
|
var PRODUCTION_CONFIG = {
|
|
227
233
|
apiUrl: "https://app.braingrid.ai",
|
|
228
234
|
workosAuthUrl: "https://auth.braingrid.ai",
|
|
@@ -1178,15 +1184,15 @@ var BraingridAuth = class {
|
|
|
1178
1184
|
if (!jwtPayload) {
|
|
1179
1185
|
return session.user || null;
|
|
1180
1186
|
}
|
|
1181
|
-
const
|
|
1187
|
+
const userInfo2 = extractUserFromJWT(jwtPayload);
|
|
1182
1188
|
const user = {
|
|
1183
1189
|
object: "user",
|
|
1184
|
-
id:
|
|
1185
|
-
email:
|
|
1190
|
+
id: userInfo2.id,
|
|
1191
|
+
email: userInfo2.email,
|
|
1186
1192
|
emailVerified: true,
|
|
1187
1193
|
// Assume verified if they have a valid JWT
|
|
1188
|
-
firstName:
|
|
1189
|
-
lastName:
|
|
1194
|
+
firstName: userInfo2.firstName,
|
|
1195
|
+
lastName: userInfo2.lastName,
|
|
1190
1196
|
profilePictureUrl: "",
|
|
1191
1197
|
// Not available in JWT
|
|
1192
1198
|
createdAt: new Date(jwtPayload.iat ? jwtPayload.iat * 1e3 : Date.now()).toISOString(),
|
|
@@ -1316,15 +1322,15 @@ var BraingridAuth = class {
|
|
|
1316
1322
|
if (!jwtPayload) {
|
|
1317
1323
|
throw new Error("Invalid token received - unable to decode");
|
|
1318
1324
|
}
|
|
1319
|
-
const
|
|
1325
|
+
const userInfo2 = extractUserFromJWT(jwtPayload);
|
|
1320
1326
|
const user = {
|
|
1321
1327
|
object: "user",
|
|
1322
|
-
id:
|
|
1323
|
-
email:
|
|
1328
|
+
id: userInfo2.id,
|
|
1329
|
+
email: userInfo2.email,
|
|
1324
1330
|
emailVerified: true,
|
|
1325
1331
|
// Assume verified if they have a valid JWT
|
|
1326
|
-
firstName:
|
|
1327
|
-
lastName:
|
|
1332
|
+
firstName: userInfo2.firstName,
|
|
1333
|
+
lastName: userInfo2.lastName,
|
|
1328
1334
|
profilePictureUrl: "",
|
|
1329
1335
|
// Not available in JWT
|
|
1330
1336
|
createdAt: new Date(jwtPayload.iat ? jwtPayload.iat * 1e3 : Date.now()).toISOString(),
|
|
@@ -2117,12 +2123,137 @@ async function handleWhoami() {
|
|
|
2117
2123
|
}
|
|
2118
2124
|
}
|
|
2119
2125
|
|
|
2120
|
-
// src/handlers/
|
|
2126
|
+
// src/handlers/claude-code.handlers.ts
|
|
2127
|
+
import { execSync } from "child_process";
|
|
2128
|
+
import { userInfo } from "os";
|
|
2121
2129
|
import chalk4 from "chalk";
|
|
2130
|
+
function maskToken(token, visibleChars = 8) {
|
|
2131
|
+
if (token.length <= visibleChars) {
|
|
2132
|
+
return "***";
|
|
2133
|
+
}
|
|
2134
|
+
return `***${token.slice(-visibleChars)}`;
|
|
2135
|
+
}
|
|
2136
|
+
function formatExpiresAt(expiresAt) {
|
|
2137
|
+
const date = new Date(expiresAt);
|
|
2138
|
+
if (Number.isNaN(date.getTime())) {
|
|
2139
|
+
return expiresAt;
|
|
2140
|
+
}
|
|
2141
|
+
const now = /* @__PURE__ */ new Date();
|
|
2142
|
+
const diffMs = date.getTime() - now.getTime();
|
|
2143
|
+
const diffMins = Math.round(diffMs / 1e3 / 60);
|
|
2144
|
+
const dateStr = date.toLocaleString();
|
|
2145
|
+
if (diffMs < 0) {
|
|
2146
|
+
return `${dateStr} ${chalk4.red("(expired)")}`;
|
|
2147
|
+
}
|
|
2148
|
+
if (diffMins < 60) {
|
|
2149
|
+
return `${dateStr} ${chalk4.yellow(`(in ${diffMins}m)`)}`;
|
|
2150
|
+
}
|
|
2151
|
+
const diffHours = Math.round(diffMins / 60);
|
|
2152
|
+
return `${dateStr} ${chalk4.green(`(in ${diffHours}h)`)}`;
|
|
2153
|
+
}
|
|
2154
|
+
async function handleClaudeCodeCredentials(opts) {
|
|
2155
|
+
try {
|
|
2156
|
+
const username = userInfo().username;
|
|
2157
|
+
const serviceName = "Claude Code-credentials";
|
|
2158
|
+
let rawJson;
|
|
2159
|
+
try {
|
|
2160
|
+
rawJson = execSync(`security find-generic-password -s "${serviceName}" -a "${username}" -w`, {
|
|
2161
|
+
encoding: "utf-8",
|
|
2162
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
2163
|
+
}).trim();
|
|
2164
|
+
} catch {
|
|
2165
|
+
return {
|
|
2166
|
+
success: false,
|
|
2167
|
+
message: chalk4.red(
|
|
2168
|
+
`\u274C No Claude Code credentials found in Keychain.
|
|
2169
|
+
` + chalk4.dim(
|
|
2170
|
+
` Expected service "${serviceName}" for account "${username}".
|
|
2171
|
+
Make sure Claude Code is installed and you have logged in.`
|
|
2172
|
+
)
|
|
2173
|
+
)
|
|
2174
|
+
};
|
|
2175
|
+
}
|
|
2176
|
+
if (opts.raw) {
|
|
2177
|
+
try {
|
|
2178
|
+
const parsed = JSON.parse(rawJson);
|
|
2179
|
+
return {
|
|
2180
|
+
success: true,
|
|
2181
|
+
message: JSON.stringify(parsed, null, 2),
|
|
2182
|
+
data: parsed
|
|
2183
|
+
};
|
|
2184
|
+
} catch {
|
|
2185
|
+
return {
|
|
2186
|
+
success: true,
|
|
2187
|
+
message: rawJson
|
|
2188
|
+
};
|
|
2189
|
+
}
|
|
2190
|
+
}
|
|
2191
|
+
let credentials;
|
|
2192
|
+
try {
|
|
2193
|
+
credentials = JSON.parse(rawJson);
|
|
2194
|
+
} catch {
|
|
2195
|
+
return {
|
|
2196
|
+
success: false,
|
|
2197
|
+
message: chalk4.red(
|
|
2198
|
+
"\u274C Failed to parse credentials JSON from Keychain.\n" + chalk4.dim(" The stored value may be corrupted.")
|
|
2199
|
+
)
|
|
2200
|
+
};
|
|
2201
|
+
}
|
|
2202
|
+
let output = chalk4.bold.cyan("\n\u{1F511} Claude Code Credentials\n\n");
|
|
2203
|
+
if (credentials.claudeAiOauth) {
|
|
2204
|
+
const oauth = credentials.claudeAiOauth;
|
|
2205
|
+
output += chalk4.bold("Claude AI OAuth\n");
|
|
2206
|
+
output += `${chalk4.dim("\u2500".repeat(50))}
|
|
2207
|
+
`;
|
|
2208
|
+
output += `${chalk4.bold("Access Token:")} ${maskToken(oauth.accessToken)}
|
|
2209
|
+
`;
|
|
2210
|
+
output += `${chalk4.bold("Refresh Token:")} ${maskToken(oauth.refreshToken)}
|
|
2211
|
+
`;
|
|
2212
|
+
output += `${chalk4.bold("Expires At:")} ${formatExpiresAt(oauth.expiresAt)}
|
|
2213
|
+
`;
|
|
2214
|
+
output += `${chalk4.bold("Scopes:")} ${oauth.scopes?.join(", ") || chalk4.dim("none")}
|
|
2215
|
+
`;
|
|
2216
|
+
output += `${chalk4.bold("Subscription:")} ${oauth.subscriptionType || chalk4.dim("unknown")}
|
|
2217
|
+
`;
|
|
2218
|
+
output += `${chalk4.bold("Rate Limit Tier:")} ${oauth.rateLimitTier || chalk4.dim("unknown")}
|
|
2219
|
+
|
|
2220
|
+
`;
|
|
2221
|
+
} else {
|
|
2222
|
+
output += chalk4.yellow("\u26A0\uFE0F No Claude AI OAuth credentials found\n\n");
|
|
2223
|
+
}
|
|
2224
|
+
if (credentials.mcpOAuth && Object.keys(credentials.mcpOAuth).length > 0) {
|
|
2225
|
+
output += chalk4.bold("MCP OAuth Tokens\n");
|
|
2226
|
+
output += `${chalk4.dim("\u2500".repeat(50))}
|
|
2227
|
+
`;
|
|
2228
|
+
for (const serviceName2 of Object.keys(credentials.mcpOAuth)) {
|
|
2229
|
+
output += `${chalk4.green("\u25CF")} ${serviceName2}
|
|
2230
|
+
`;
|
|
2231
|
+
}
|
|
2232
|
+
output += "\n";
|
|
2233
|
+
} else {
|
|
2234
|
+
output += chalk4.dim("No MCP OAuth tokens stored\n\n");
|
|
2235
|
+
}
|
|
2236
|
+
output += chalk4.dim("Use --raw to print the full unmasked JSON\n");
|
|
2237
|
+
return {
|
|
2238
|
+
success: true,
|
|
2239
|
+
message: output,
|
|
2240
|
+
data: credentials
|
|
2241
|
+
};
|
|
2242
|
+
} catch (error) {
|
|
2243
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
2244
|
+
return {
|
|
2245
|
+
success: false,
|
|
2246
|
+
message: chalk4.red(`\u274C Error: ${msg}`)
|
|
2247
|
+
};
|
|
2248
|
+
}
|
|
2249
|
+
}
|
|
2250
|
+
|
|
2251
|
+
// src/handlers/completion.handlers.ts
|
|
2252
|
+
import chalk5 from "chalk";
|
|
2122
2253
|
function getUnsupportedShellError() {
|
|
2123
2254
|
return {
|
|
2124
2255
|
success: false,
|
|
2125
|
-
message:
|
|
2256
|
+
message: chalk5.red("\u274C Could not detect shell type.\n\n") + chalk5.dim("Please specify a shell:\n") + chalk5.cyan(" braingrid completion bash\n") + chalk5.cyan(" braingrid completion zsh\n\n") + chalk5.dim("Supported shells: bash, zsh")
|
|
2126
2257
|
};
|
|
2127
2258
|
}
|
|
2128
2259
|
async function handleCompletion(shellArg, opts) {
|
|
@@ -2152,33 +2283,33 @@ async function handleCompletion(shellArg, opts) {
|
|
|
2152
2283
|
const configPath = getShellConfigPath(shell);
|
|
2153
2284
|
return {
|
|
2154
2285
|
success: true,
|
|
2155
|
-
message:
|
|
2286
|
+
message: chalk5.green(`\u2705 Completion installed for ${shell}
|
|
2156
2287
|
|
|
2157
|
-
`) +
|
|
2288
|
+
`) + chalk5.dim("To activate in your current shell, run:\n") + chalk5.cyan(` source ${configPath}
|
|
2158
2289
|
|
|
2159
|
-
`) +
|
|
2290
|
+
`) + chalk5.dim("Or restart your terminal.")
|
|
2160
2291
|
};
|
|
2161
2292
|
} catch (error) {
|
|
2162
2293
|
return {
|
|
2163
2294
|
success: false,
|
|
2164
|
-
message:
|
|
2295
|
+
message: chalk5.red("\u274C Failed to install completion\n\n") + chalk5.dim("Error: ") + formatError(error)
|
|
2165
2296
|
};
|
|
2166
2297
|
}
|
|
2167
2298
|
}
|
|
2168
2299
|
try {
|
|
2169
2300
|
const script = generateCompletionScript(shell);
|
|
2170
2301
|
const configPath = getShellConfigPath(shell);
|
|
2171
|
-
const instructions =
|
|
2172
|
-
`) +
|
|
2173
|
-
`) +
|
|
2302
|
+
const instructions = chalk5.blue(`# BrainGrid CLI completion for ${shell}
|
|
2303
|
+
`) + chalk5.dim("# To install, run one of the following:\n\n") + chalk5.cyan(`# 1. Automatic installation (recommended):
|
|
2304
|
+
`) + chalk5.cyan(` braingrid completion --setup
|
|
2174
2305
|
|
|
2175
|
-
`) +
|
|
2176
|
-
`) +
|
|
2306
|
+
`) + chalk5.cyan(`# 2. Add to your shell config:
|
|
2307
|
+
`) + chalk5.cyan(` braingrid completion ${shell} >> ${configPath}
|
|
2177
2308
|
|
|
2178
|
-
`) +
|
|
2179
|
-
`) +
|
|
2309
|
+
`) + chalk5.cyan(`# 3. Source directly (temporary, current session only):
|
|
2310
|
+
`) + chalk5.cyan(` eval "$(braingrid completion ${shell})"
|
|
2180
2311
|
|
|
2181
|
-
`) +
|
|
2312
|
+
`) + chalk5.dim("# Completion script:\n\n");
|
|
2182
2313
|
return {
|
|
2183
2314
|
success: true,
|
|
2184
2315
|
message: instructions + script
|
|
@@ -2186,7 +2317,7 @@ async function handleCompletion(shellArg, opts) {
|
|
|
2186
2317
|
} catch (error) {
|
|
2187
2318
|
return {
|
|
2188
2319
|
success: false,
|
|
2189
|
-
message:
|
|
2320
|
+
message: chalk5.red("\u274C Failed to generate completion script\n\n") + chalk5.dim("Error: ") + formatError(error)
|
|
2190
2321
|
};
|
|
2191
2322
|
}
|
|
2192
2323
|
} catch (error) {
|
|
@@ -2200,7 +2331,7 @@ async function handleCompletion(shellArg, opts) {
|
|
|
2200
2331
|
// src/handlers/init.handlers.ts
|
|
2201
2332
|
import { access as access3 } from "fs/promises";
|
|
2202
2333
|
import { confirm as confirm2, input, select as select3 } from "@inquirer/prompts";
|
|
2203
|
-
import
|
|
2334
|
+
import chalk11 from "chalk";
|
|
2204
2335
|
|
|
2205
2336
|
// src/utils/axios-with-auth.ts
|
|
2206
2337
|
import axios4 from "axios";
|
|
@@ -2500,10 +2631,33 @@ var ProjectService = class {
|
|
|
2500
2631
|
// src/services/setup-service.ts
|
|
2501
2632
|
import * as fs2 from "fs/promises";
|
|
2502
2633
|
import * as path2 from "path";
|
|
2634
|
+
import axios5 from "axios";
|
|
2503
2635
|
var GITHUB_OWNER = "BrainGridAI";
|
|
2504
2636
|
var GITHUB_REPO = "braingrid";
|
|
2637
|
+
var GITHUB_API_BASE = `https://api.github.com/repos/${GITHUB_OWNER}/${GITHUB_REPO}/contents`;
|
|
2505
2638
|
var MAX_RETRIES = 3;
|
|
2506
2639
|
var INITIAL_RETRY_DELAY = 100;
|
|
2640
|
+
async function getGitHubToken() {
|
|
2641
|
+
try {
|
|
2642
|
+
const { stdout } = await execAsync("gh auth token");
|
|
2643
|
+
return stdout.trim() || null;
|
|
2644
|
+
} catch {
|
|
2645
|
+
return null;
|
|
2646
|
+
}
|
|
2647
|
+
}
|
|
2648
|
+
var cachedHeaders = null;
|
|
2649
|
+
async function getGitHubHeaders() {
|
|
2650
|
+
if (cachedHeaders) return cachedHeaders;
|
|
2651
|
+
const headers = {
|
|
2652
|
+
Accept: "application/vnd.github.v3+json"
|
|
2653
|
+
};
|
|
2654
|
+
const token = await getGitHubToken();
|
|
2655
|
+
if (token) {
|
|
2656
|
+
headers.Authorization = `token ${token}`;
|
|
2657
|
+
}
|
|
2658
|
+
cachedHeaders = headers;
|
|
2659
|
+
return headers;
|
|
2660
|
+
}
|
|
2507
2661
|
var BEGIN_MARKER = "<!-- BEGIN BRAINGRID INTEGRATION -->";
|
|
2508
2662
|
var END_MARKER = "<!-- END BRAINGRID INTEGRATION -->";
|
|
2509
2663
|
async function withRetry(fn, retries = MAX_RETRIES, delay = INITIAL_RETRY_DELAY) {
|
|
@@ -2513,8 +2667,7 @@ async function withRetry(fn, retries = MAX_RETRIES, delay = INITIAL_RETRY_DELAY)
|
|
|
2513
2667
|
if (retries === 0) {
|
|
2514
2668
|
throw error;
|
|
2515
2669
|
}
|
|
2516
|
-
const
|
|
2517
|
-
const isNetworkError = errorMessage.includes("ECONNRESET") || errorMessage.includes("ETIMEDOUT") || errorMessage.includes("ENOTFOUND") || errorMessage.includes("network");
|
|
2670
|
+
const isNetworkError = axios5.isAxiosError(error) && !error.response;
|
|
2518
2671
|
if (!isNetworkError) {
|
|
2519
2672
|
throw error;
|
|
2520
2673
|
}
|
|
@@ -2523,37 +2676,41 @@ async function withRetry(fn, retries = MAX_RETRIES, delay = INITIAL_RETRY_DELAY)
|
|
|
2523
2676
|
}
|
|
2524
2677
|
}
|
|
2525
2678
|
function parseGitHubError(error) {
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
return "GitHub API rate limit exceeded. Please wait a few minutes and try again.\nCheck rate limit status: gh api rate_limit";
|
|
2532
|
-
}
|
|
2533
|
-
if (errorMessage.includes("401") || errorMessage.includes("Unauthorized")) {
|
|
2534
|
-
return "GitHub CLI is not authenticated. Run: gh auth login";
|
|
2535
|
-
}
|
|
2536
|
-
try {
|
|
2537
|
-
const match = errorMessage.match(/\{.*\}/s);
|
|
2538
|
-
if (match) {
|
|
2539
|
-
const errorData = JSON.parse(match[0]);
|
|
2540
|
-
return errorData.message || errorMessage;
|
|
2679
|
+
if (axios5.isAxiosError(error)) {
|
|
2680
|
+
const status = error.response?.status;
|
|
2681
|
+
const data = error.response?.data;
|
|
2682
|
+
if (status === 404) {
|
|
2683
|
+
return "File or directory not found in BrainGrid repository";
|
|
2541
2684
|
}
|
|
2542
|
-
|
|
2685
|
+
if (status === 403) {
|
|
2686
|
+
return "GitHub API rate limit exceeded. Please wait a few minutes and try again.\nTip: Install GitHub CLI (gh) for higher rate limits: https://cli.github.com";
|
|
2687
|
+
}
|
|
2688
|
+
if (status === 401) {
|
|
2689
|
+
return "GitHub API authentication failed. Your gh auth token may be expired.";
|
|
2690
|
+
}
|
|
2691
|
+
if (data?.message) {
|
|
2692
|
+
return data.message;
|
|
2693
|
+
}
|
|
2694
|
+
if (!error.response) {
|
|
2695
|
+
return `Network error: ${error.message}`;
|
|
2696
|
+
}
|
|
2697
|
+
return error.message;
|
|
2543
2698
|
}
|
|
2544
|
-
return
|
|
2699
|
+
return error instanceof Error ? error.message : String(error);
|
|
2545
2700
|
}
|
|
2546
|
-
async function fetchFileFromGitHub(
|
|
2701
|
+
async function fetchFileFromGitHub(filePath) {
|
|
2547
2702
|
return withRetry(async () => {
|
|
2548
2703
|
try {
|
|
2549
|
-
const
|
|
2550
|
-
const {
|
|
2551
|
-
|
|
2704
|
+
const headers = await getGitHubHeaders();
|
|
2705
|
+
const { data: response } = await axios5.get(
|
|
2706
|
+
`${GITHUB_API_BASE}/${filePath}`,
|
|
2707
|
+
{ headers }
|
|
2708
|
+
);
|
|
2552
2709
|
if (response.type !== "file") {
|
|
2553
|
-
throw new Error(`Path ${
|
|
2710
|
+
throw new Error(`Path ${filePath} is not a file`);
|
|
2554
2711
|
}
|
|
2555
2712
|
if (!response.content || !response.encoding) {
|
|
2556
|
-
throw new Error(`No content found for file ${
|
|
2713
|
+
throw new Error(`No content found for file ${filePath}`);
|
|
2557
2714
|
}
|
|
2558
2715
|
if (response.encoding !== "base64") {
|
|
2559
2716
|
throw new Error(`Unexpected encoding: ${response.encoding}`);
|
|
@@ -2561,19 +2718,27 @@ async function fetchFileFromGitHub(path7) {
|
|
|
2561
2718
|
const content = Buffer.from(response.content, "base64").toString("utf8");
|
|
2562
2719
|
return content;
|
|
2563
2720
|
} catch (error) {
|
|
2721
|
+
if (axios5.isAxiosError(error) && !error.response) {
|
|
2722
|
+
throw error;
|
|
2723
|
+
}
|
|
2724
|
+
if (error instanceof Error && error.message.startsWith("Failed to fetch file")) {
|
|
2725
|
+
throw error;
|
|
2726
|
+
}
|
|
2564
2727
|
const parsedError = parseGitHubError(error);
|
|
2565
|
-
throw new Error(`Failed to fetch file ${
|
|
2728
|
+
throw new Error(`Failed to fetch file ${filePath}: ${parsedError}`);
|
|
2566
2729
|
}
|
|
2567
2730
|
});
|
|
2568
2731
|
}
|
|
2569
|
-
async function listGitHubDirectory(
|
|
2732
|
+
async function listGitHubDirectory(dirPath) {
|
|
2570
2733
|
return withRetry(async () => {
|
|
2571
2734
|
try {
|
|
2572
|
-
const
|
|
2573
|
-
const {
|
|
2574
|
-
|
|
2735
|
+
const headers = await getGitHubHeaders();
|
|
2736
|
+
const { data: response } = await axios5.get(
|
|
2737
|
+
`${GITHUB_API_BASE}/${dirPath}`,
|
|
2738
|
+
{ headers }
|
|
2739
|
+
);
|
|
2575
2740
|
if (!Array.isArray(response)) {
|
|
2576
|
-
throw new Error(`Path ${
|
|
2741
|
+
throw new Error(`Path ${dirPath} is not a directory`);
|
|
2577
2742
|
}
|
|
2578
2743
|
return response.map((item) => ({
|
|
2579
2744
|
name: item.name,
|
|
@@ -2581,8 +2746,14 @@ async function listGitHubDirectory(path7) {
|
|
|
2581
2746
|
path: item.path
|
|
2582
2747
|
}));
|
|
2583
2748
|
} catch (error) {
|
|
2749
|
+
if (axios5.isAxiosError(error) && !error.response) {
|
|
2750
|
+
throw error;
|
|
2751
|
+
}
|
|
2752
|
+
if (error instanceof Error && error.message.startsWith("Failed to list directory")) {
|
|
2753
|
+
throw error;
|
|
2754
|
+
}
|
|
2584
2755
|
const parsedError = parseGitHubError(error);
|
|
2585
|
-
throw new Error(`Failed to list directory ${
|
|
2756
|
+
throw new Error(`Failed to list directory ${dirPath}: ${parsedError}`);
|
|
2586
2757
|
}
|
|
2587
2758
|
});
|
|
2588
2759
|
}
|
|
@@ -2799,7 +2970,7 @@ async function updateClaudeSettings(settingsPath = ".claude/settings.json", stat
|
|
|
2799
2970
|
// src/utils/git-installer.ts
|
|
2800
2971
|
import { exec as exec2 } from "child_process";
|
|
2801
2972
|
import { promisify as promisify2 } from "util";
|
|
2802
|
-
import
|
|
2973
|
+
import chalk6 from "chalk";
|
|
2803
2974
|
var execAsync3 = promisify2(exec2);
|
|
2804
2975
|
async function isGitInstalled() {
|
|
2805
2976
|
return isCliInstalled("git");
|
|
@@ -2811,7 +2982,7 @@ async function getGitVersion() {
|
|
|
2811
2982
|
});
|
|
2812
2983
|
}
|
|
2813
2984
|
async function installViaHomebrew() {
|
|
2814
|
-
console.log(
|
|
2985
|
+
console.log(chalk6.blue("\u{1F4E6} Installing Git via Homebrew..."));
|
|
2815
2986
|
try {
|
|
2816
2987
|
await execAsync3("brew install git", {
|
|
2817
2988
|
timeout: 3e5
|
|
@@ -2821,25 +2992,25 @@ async function installViaHomebrew() {
|
|
|
2821
2992
|
if (!version) {
|
|
2822
2993
|
return {
|
|
2823
2994
|
success: false,
|
|
2824
|
-
message:
|
|
2995
|
+
message: chalk6.red("\u274C Git installation completed but git command not found")
|
|
2825
2996
|
};
|
|
2826
2997
|
}
|
|
2827
2998
|
return {
|
|
2828
2999
|
success: true,
|
|
2829
|
-
message:
|
|
3000
|
+
message: chalk6.green(`\u2705 Git installed successfully (version ${version})!`),
|
|
2830
3001
|
version
|
|
2831
3002
|
};
|
|
2832
3003
|
} catch (error) {
|
|
2833
3004
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
2834
3005
|
return {
|
|
2835
3006
|
success: false,
|
|
2836
|
-
message:
|
|
3007
|
+
message: chalk6.red("\u274C Failed to install Git via Homebrew\n\n") + chalk6.dim("Error: ") + errorMsg + "\n\n" + chalk6.dim("Please install Git manually from: ") + chalk6.cyan("https://git-scm.com/download/mac")
|
|
2837
3008
|
};
|
|
2838
3009
|
}
|
|
2839
3010
|
}
|
|
2840
3011
|
async function installViaXcodeSelect() {
|
|
2841
|
-
console.log(
|
|
2842
|
-
console.log(
|
|
3012
|
+
console.log(chalk6.blue("\u{1F4E6} Installing Git via Xcode Command Line Tools..."));
|
|
3013
|
+
console.log(chalk6.dim('A system dialog will appear - click "Install" to continue.\n'));
|
|
2843
3014
|
try {
|
|
2844
3015
|
await execAsync3("xcode-select --install", {
|
|
2845
3016
|
timeout: 6e5
|
|
@@ -2849,19 +3020,19 @@ async function installViaXcodeSelect() {
|
|
|
2849
3020
|
if (!version) {
|
|
2850
3021
|
return {
|
|
2851
3022
|
success: false,
|
|
2852
|
-
message:
|
|
3023
|
+
message: chalk6.red("\u274C Git installation completed but git command not found")
|
|
2853
3024
|
};
|
|
2854
3025
|
}
|
|
2855
3026
|
return {
|
|
2856
3027
|
success: true,
|
|
2857
|
-
message:
|
|
3028
|
+
message: chalk6.green(`\u2705 Git installed successfully (version ${version})!`),
|
|
2858
3029
|
version
|
|
2859
3030
|
};
|
|
2860
3031
|
} catch (error) {
|
|
2861
3032
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
2862
3033
|
return {
|
|
2863
3034
|
success: false,
|
|
2864
|
-
message:
|
|
3035
|
+
message: chalk6.red("\u274C Failed to install Git via Xcode Command Line Tools\n\n") + chalk6.dim("Error: ") + errorMsg + "\n\n" + chalk6.dim("Please install Git manually from: ") + chalk6.cyan("https://git-scm.com/download/mac")
|
|
2865
3036
|
};
|
|
2866
3037
|
}
|
|
2867
3038
|
}
|
|
@@ -2877,10 +3048,10 @@ async function installGitWindows() {
|
|
|
2877
3048
|
if (!hasWinget) {
|
|
2878
3049
|
return {
|
|
2879
3050
|
success: false,
|
|
2880
|
-
message:
|
|
3051
|
+
message: chalk6.red("\u274C winget is not available on this system\n\n") + chalk6.dim("winget is included in Windows 10 (version 1809+) and Windows 11.\n") + chalk6.dim("Please install Git manually from: ") + chalk6.cyan("https://git-scm.com/download/win")
|
|
2881
3052
|
};
|
|
2882
3053
|
}
|
|
2883
|
-
console.log(
|
|
3054
|
+
console.log(chalk6.blue("\u{1F4E6} Installing Git via winget..."));
|
|
2884
3055
|
try {
|
|
2885
3056
|
await execAsync3("winget install --id Git.Git -e --source winget --silent", {
|
|
2886
3057
|
timeout: 3e5
|
|
@@ -2890,19 +3061,19 @@ async function installGitWindows() {
|
|
|
2890
3061
|
if (!version) {
|
|
2891
3062
|
return {
|
|
2892
3063
|
success: false,
|
|
2893
|
-
message:
|
|
3064
|
+
message: chalk6.red("\u274C Git installation completed but git command not found")
|
|
2894
3065
|
};
|
|
2895
3066
|
}
|
|
2896
3067
|
return {
|
|
2897
3068
|
success: true,
|
|
2898
|
-
message:
|
|
3069
|
+
message: chalk6.green(`\u2705 Git installed successfully (version ${version})!`),
|
|
2899
3070
|
version
|
|
2900
3071
|
};
|
|
2901
3072
|
} catch (error) {
|
|
2902
3073
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
2903
3074
|
return {
|
|
2904
3075
|
success: false,
|
|
2905
|
-
message:
|
|
3076
|
+
message: chalk6.red("\u274C Failed to install Git via winget\n\n") + chalk6.dim("Error: ") + errorMsg + "\n\n" + chalk6.dim("Please install Git manually from: ") + chalk6.cyan("https://git-scm.com/download/win")
|
|
2906
3077
|
};
|
|
2907
3078
|
}
|
|
2908
3079
|
}
|
|
@@ -2911,11 +3082,11 @@ async function installGitLinux() {
|
|
|
2911
3082
|
if (!packageManager) {
|
|
2912
3083
|
return {
|
|
2913
3084
|
success: false,
|
|
2914
|
-
message:
|
|
3085
|
+
message: chalk6.red("\u274C Could not detect a supported package manager\n\n") + chalk6.dim("Supported package managers: apt, dnf, yum, pacman\n") + chalk6.dim("Please install Git manually from: ") + chalk6.cyan("https://git-scm.com/download/linux")
|
|
2915
3086
|
};
|
|
2916
3087
|
}
|
|
2917
|
-
console.log(
|
|
2918
|
-
console.log(
|
|
3088
|
+
console.log(chalk6.blue(`\u{1F4E6} Installing Git via ${packageManager.name}...`));
|
|
3089
|
+
console.log(chalk6.dim("This may prompt for your sudo password.\n"));
|
|
2919
3090
|
try {
|
|
2920
3091
|
let installCommand;
|
|
2921
3092
|
switch (packageManager.name) {
|
|
@@ -2934,7 +3105,7 @@ async function installGitLinux() {
|
|
|
2934
3105
|
default:
|
|
2935
3106
|
return {
|
|
2936
3107
|
success: false,
|
|
2937
|
-
message:
|
|
3108
|
+
message: chalk6.red(`\u274C Unsupported package manager: ${packageManager.name}`)
|
|
2938
3109
|
};
|
|
2939
3110
|
}
|
|
2940
3111
|
await execAsync3(installCommand, {
|
|
@@ -2945,19 +3116,19 @@ async function installGitLinux() {
|
|
|
2945
3116
|
if (!version) {
|
|
2946
3117
|
return {
|
|
2947
3118
|
success: false,
|
|
2948
|
-
message:
|
|
3119
|
+
message: chalk6.red("\u274C Git installation completed but git command not found")
|
|
2949
3120
|
};
|
|
2950
3121
|
}
|
|
2951
3122
|
return {
|
|
2952
3123
|
success: true,
|
|
2953
|
-
message:
|
|
3124
|
+
message: chalk6.green(`\u2705 Git installed successfully (version ${version})!`),
|
|
2954
3125
|
version
|
|
2955
3126
|
};
|
|
2956
3127
|
} catch (error) {
|
|
2957
3128
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
2958
3129
|
return {
|
|
2959
3130
|
success: false,
|
|
2960
|
-
message:
|
|
3131
|
+
message: chalk6.red("\u274C Failed to install Git\n\n") + chalk6.dim("Error: ") + errorMsg + "\n\n" + chalk6.dim("Please install Git manually from: ") + chalk6.cyan("https://git-scm.com/download/linux")
|
|
2961
3132
|
};
|
|
2962
3133
|
}
|
|
2963
3134
|
}
|
|
@@ -2973,9 +3144,9 @@ async function installGit() {
|
|
|
2973
3144
|
default:
|
|
2974
3145
|
return {
|
|
2975
3146
|
success: false,
|
|
2976
|
-
message:
|
|
3147
|
+
message: chalk6.red(`\u274C Unsupported platform: ${platform}
|
|
2977
3148
|
|
|
2978
|
-
`) +
|
|
3149
|
+
`) + chalk6.dim("Please install Git manually from: ") + chalk6.cyan("https://git-scm.com/downloads")
|
|
2979
3150
|
};
|
|
2980
3151
|
}
|
|
2981
3152
|
}
|
|
@@ -2983,15 +3154,15 @@ function getManualInstallInstructions() {
|
|
|
2983
3154
|
const platform = process.platform;
|
|
2984
3155
|
switch (platform) {
|
|
2985
3156
|
case "darwin":
|
|
2986
|
-
return
|
|
3157
|
+
return chalk6.yellow("\u{1F4D6} Manual Git Installation (macOS)\n\n") + chalk6.dim("Option 1 - Xcode Command Line Tools (recommended):\n") + chalk6.cyan(" xcode-select --install\n\n") + chalk6.dim("Option 2 - Homebrew (if you use package managers):\n") + chalk6.cyan(
|
|
2987
3158
|
' /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"\n'
|
|
2988
|
-
) +
|
|
3159
|
+
) + chalk6.cyan(" brew install git\n\n") + chalk6.dim("Option 3 - Official installer:\n") + chalk6.cyan(" Download from: https://git-scm.com/download/mac");
|
|
2989
3160
|
case "win32":
|
|
2990
|
-
return
|
|
3161
|
+
return chalk6.yellow("\u{1F4D6} Manual Git Installation (Windows)\n\n") + chalk6.dim("Option 1 - winget (Windows 10+):\n") + chalk6.cyan(" winget install --id Git.Git -e --source winget\n\n") + chalk6.dim("Option 2 - Official installer:\n") + chalk6.cyan(" Download from: https://git-scm.com/download/win");
|
|
2991
3162
|
case "linux":
|
|
2992
|
-
return
|
|
3163
|
+
return chalk6.yellow("\u{1F4D6} Manual Git Installation (Linux)\n\n") + chalk6.dim("Debian/Ubuntu:\n") + chalk6.cyan(" sudo apt-get update && sudo apt-get install -y git\n\n") + chalk6.dim("Fedora/RHEL:\n") + chalk6.cyan(" sudo dnf install -y git\n\n") + chalk6.dim("Arch Linux:\n") + chalk6.cyan(" sudo pacman -S git\n\n") + chalk6.dim("Or download from: ") + chalk6.cyan("https://git-scm.com/download/linux");
|
|
2993
3164
|
default:
|
|
2994
|
-
return
|
|
3165
|
+
return chalk6.yellow("\u{1F4D6} Manual Git Installation\n\n") + chalk6.dim("Download from: ") + chalk6.cyan("https://git-scm.com/downloads");
|
|
2995
3166
|
}
|
|
2996
3167
|
}
|
|
2997
3168
|
|
|
@@ -3178,7 +3349,7 @@ async function getRepositoryId(repositoryService, owner, name) {
|
|
|
3178
3349
|
}
|
|
3179
3350
|
|
|
3180
3351
|
// src/utils/spinner.ts
|
|
3181
|
-
import
|
|
3352
|
+
import chalk7 from "chalk";
|
|
3182
3353
|
var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
3183
3354
|
async function waitWithSpinner(message, checkFn, intervalMs = 3e3, maxAttempts = 60) {
|
|
3184
3355
|
let frameIndex = 0;
|
|
@@ -3186,7 +3357,7 @@ async function waitWithSpinner(message, checkFn, intervalMs = 3e3, maxAttempts =
|
|
|
3186
3357
|
const updateSpinner = () => {
|
|
3187
3358
|
const frame = SPINNER_FRAMES[frameIndex];
|
|
3188
3359
|
frameIndex = (frameIndex + 1) % SPINNER_FRAMES.length;
|
|
3189
|
-
process.stdout.write(`\r${
|
|
3360
|
+
process.stdout.write(`\r${chalk7.cyan(frame)} ${message}...`);
|
|
3190
3361
|
};
|
|
3191
3362
|
spinnerInterval = setInterval(updateSpinner, 100);
|
|
3192
3363
|
try {
|
|
@@ -3210,7 +3381,7 @@ async function waitWithSpinner(message, checkFn, intervalMs = 3e3, maxAttempts =
|
|
|
3210
3381
|
throw error;
|
|
3211
3382
|
}
|
|
3212
3383
|
}
|
|
3213
|
-
function showSpinner(message, color =
|
|
3384
|
+
function showSpinner(message, color = chalk7.cyan) {
|
|
3214
3385
|
let frameIndex = 0;
|
|
3215
3386
|
const interval = setInterval(() => {
|
|
3216
3387
|
const frame = SPINNER_FRAMES[frameIndex];
|
|
@@ -3224,10 +3395,10 @@ function showSpinner(message, color = chalk6.cyan) {
|
|
|
3224
3395
|
}
|
|
3225
3396
|
|
|
3226
3397
|
// src/utils/update-checker.ts
|
|
3227
|
-
import
|
|
3398
|
+
import chalk8 from "chalk";
|
|
3228
3399
|
|
|
3229
3400
|
// src/utils/version.ts
|
|
3230
|
-
import
|
|
3401
|
+
import axios6 from "axios";
|
|
3231
3402
|
var PACKAGE_NAME = "@braingrid/cli";
|
|
3232
3403
|
var NPM_REGISTRY_URL = `https://registry.npmjs.org/${PACKAGE_NAME}`;
|
|
3233
3404
|
function getCurrentVersion() {
|
|
@@ -3235,7 +3406,7 @@ function getCurrentVersion() {
|
|
|
3235
3406
|
}
|
|
3236
3407
|
async function getLatestVersion(timeout = 1e4) {
|
|
3237
3408
|
try {
|
|
3238
|
-
const response = await
|
|
3409
|
+
const response = await axios6.get(NPM_REGISTRY_URL, {
|
|
3239
3410
|
timeout
|
|
3240
3411
|
});
|
|
3241
3412
|
return response.data["dist-tags"].latest;
|
|
@@ -3316,7 +3487,7 @@ async function checkAndShowUpdateWarning() {
|
|
|
3316
3487
|
try {
|
|
3317
3488
|
const { available, currentVersion, latestVersion } = await isUpdateAvailable();
|
|
3318
3489
|
if (available && latestVersion) {
|
|
3319
|
-
const warning = "\n" +
|
|
3490
|
+
const warning = "\n" + chalk8.yellow(`\u26A0\uFE0F Update available: ${currentVersion} \u2192 ${latestVersion}`) + "\n" + chalk8.dim(` Run \`${getUpdateCommand()}\` to update`) + "\n";
|
|
3320
3491
|
console.log(warning);
|
|
3321
3492
|
}
|
|
3322
3493
|
} catch {
|
|
@@ -3327,7 +3498,7 @@ async function checkAndShowUpdateWarning() {
|
|
|
3327
3498
|
import * as fs4 from "fs/promises";
|
|
3328
3499
|
import * as path6 from "path";
|
|
3329
3500
|
import { select } from "@inquirer/prompts";
|
|
3330
|
-
import
|
|
3501
|
+
import chalk9 from "chalk";
|
|
3331
3502
|
async function fileExists(filePath) {
|
|
3332
3503
|
try {
|
|
3333
3504
|
await fs4.access(filePath);
|
|
@@ -3336,25 +3507,6 @@ async function fileExists(filePath) {
|
|
|
3336
3507
|
return false;
|
|
3337
3508
|
}
|
|
3338
3509
|
}
|
|
3339
|
-
async function checkPrerequisites() {
|
|
3340
|
-
try {
|
|
3341
|
-
await execAsync("gh --version");
|
|
3342
|
-
} catch {
|
|
3343
|
-
return {
|
|
3344
|
-
success: false,
|
|
3345
|
-
message: chalk8.red("\u274C GitHub CLI is not installed.\n\n") + chalk8.dim("Install instructions:\n") + chalk8.dim(" macOS: ") + chalk8.cyan("brew install gh") + chalk8.dim("\n") + chalk8.dim(" Windows: ") + chalk8.cyan("winget install GitHub.CLI") + chalk8.dim("\n") + chalk8.dim(" Linux: See ") + chalk8.cyan("https://cli.github.com/manual/installation") + chalk8.dim("\n\n") + chalk8.dim("After installing, run: ") + chalk8.cyan("gh auth login")
|
|
3346
|
-
};
|
|
3347
|
-
}
|
|
3348
|
-
try {
|
|
3349
|
-
await execAsync("gh auth status");
|
|
3350
|
-
} catch {
|
|
3351
|
-
return {
|
|
3352
|
-
success: false,
|
|
3353
|
-
message: chalk8.red("\u274C Not authenticated with GitHub CLI.\n\n") + chalk8.dim("Please run: ") + chalk8.cyan("gh auth login")
|
|
3354
|
-
};
|
|
3355
|
-
}
|
|
3356
|
-
return null;
|
|
3357
|
-
}
|
|
3358
3510
|
async function getFileList(sourcePaths, targetPaths) {
|
|
3359
3511
|
const operations = [];
|
|
3360
3512
|
async function processDirectory(sourceDir, targetDir, dirIndex) {
|
|
@@ -3378,7 +3530,7 @@ async function getFileList(sourcePaths, targetPaths) {
|
|
|
3378
3530
|
}
|
|
3379
3531
|
} catch (error) {
|
|
3380
3532
|
console.warn(
|
|
3381
|
-
|
|
3533
|
+
chalk9.yellow(`\u26A0\uFE0F Could not list directory: ${sourceDir}`),
|
|
3382
3534
|
error instanceof Error ? error.message : String(error)
|
|
3383
3535
|
);
|
|
3384
3536
|
}
|
|
@@ -3389,28 +3541,28 @@ async function getFileList(sourcePaths, targetPaths) {
|
|
|
3389
3541
|
return operations;
|
|
3390
3542
|
}
|
|
3391
3543
|
function displayInstallationPlan(operations, injectionFile) {
|
|
3392
|
-
console.log(
|
|
3393
|
-
console.log(
|
|
3394
|
-
console.log(
|
|
3544
|
+
console.log(chalk9.bold("\n\u{1F4CB} Installation Plan:\n"));
|
|
3545
|
+
console.log(chalk9.cyan(" Content Injection:"));
|
|
3546
|
+
console.log(chalk9.dim(` ${injectionFile}`));
|
|
3395
3547
|
const newFiles = operations.filter((op) => !op.exists);
|
|
3396
3548
|
const existingFiles = operations.filter((op) => op.exists);
|
|
3397
3549
|
if (newFiles.length > 0) {
|
|
3398
|
-
console.log(
|
|
3550
|
+
console.log(chalk9.cyan("\n New Files:"));
|
|
3399
3551
|
for (const op of newFiles) {
|
|
3400
|
-
console.log(
|
|
3552
|
+
console.log(chalk9.dim(` ${op.targetPath}`));
|
|
3401
3553
|
}
|
|
3402
3554
|
}
|
|
3403
3555
|
if (existingFiles.length > 0) {
|
|
3404
|
-
console.log(
|
|
3556
|
+
console.log(chalk9.yellow("\n Existing Files (will prompt):"));
|
|
3405
3557
|
for (const op of existingFiles) {
|
|
3406
|
-
console.log(
|
|
3558
|
+
console.log(chalk9.dim(` ${op.targetPath}`));
|
|
3407
3559
|
}
|
|
3408
3560
|
}
|
|
3409
3561
|
console.log("");
|
|
3410
3562
|
}
|
|
3411
3563
|
async function promptForConflict(filePath) {
|
|
3412
3564
|
const answer = await select({
|
|
3413
|
-
message:
|
|
3565
|
+
message: chalk9.yellow(`File exists: ${filePath}`),
|
|
3414
3566
|
choices: [
|
|
3415
3567
|
{ name: "[A]ll - Overwrite all remaining", value: "all" },
|
|
3416
3568
|
{ name: "[O]verwrite - Replace this file", value: "overwrite" },
|
|
@@ -3443,7 +3595,7 @@ async function installFiles(operations, force, dirCount) {
|
|
|
3443
3595
|
}
|
|
3444
3596
|
} catch (error) {
|
|
3445
3597
|
console.error(
|
|
3446
|
-
|
|
3598
|
+
chalk9.red(`Failed to copy ${operation.targetPath}:`),
|
|
3447
3599
|
error instanceof Error ? error.message : String(error)
|
|
3448
3600
|
);
|
|
3449
3601
|
skipped++;
|
|
@@ -3452,11 +3604,7 @@ async function installFiles(operations, force, dirCount) {
|
|
|
3452
3604
|
return { installedPerDir, skipped, cancelled: false };
|
|
3453
3605
|
}
|
|
3454
3606
|
async function _handleSetup(config2, opts) {
|
|
3455
|
-
|
|
3456
|
-
if (prerequisiteError) {
|
|
3457
|
-
return prerequisiteError;
|
|
3458
|
-
}
|
|
3459
|
-
console.log(chalk8.bold(`\u{1F680} Setting up ${config2.name} integration...
|
|
3607
|
+
console.log(chalk9.bold(`\u{1F680} Setting up ${config2.name} integration...
|
|
3460
3608
|
`));
|
|
3461
3609
|
const operations = await getFileList(config2.sourceDirs, config2.targetDirs);
|
|
3462
3610
|
const injectionFileExists = await fileExists(config2.injection.targetFile);
|
|
@@ -3473,7 +3621,7 @@ async function _handleSetup(config2, opts) {
|
|
|
3473
3621
|
if (opts.dryRun) {
|
|
3474
3622
|
return {
|
|
3475
3623
|
success: true,
|
|
3476
|
-
message:
|
|
3624
|
+
message: chalk9.green("\u2705 Dry-run complete. No files were modified.\n\n") + chalk9.dim(`Would install ${operations.length} files.`)
|
|
3477
3625
|
};
|
|
3478
3626
|
}
|
|
3479
3627
|
const copyOps = operations.filter((op) => op.type === "copy");
|
|
@@ -3482,7 +3630,7 @@ async function _handleSetup(config2, opts) {
|
|
|
3482
3630
|
const totalInstalled = result.installedPerDir.reduce((a, b) => a + b, 0);
|
|
3483
3631
|
return {
|
|
3484
3632
|
success: false,
|
|
3485
|
-
message:
|
|
3633
|
+
message: chalk9.yellow("\u26A0\uFE0F Installation cancelled.\n\n") + chalk9.dim(`Installed: ${totalInstalled}, Skipped: ${result.skipped}`),
|
|
3486
3634
|
code: "CANCELLED"
|
|
3487
3635
|
};
|
|
3488
3636
|
}
|
|
@@ -3491,7 +3639,7 @@ async function _handleSetup(config2, opts) {
|
|
|
3491
3639
|
await injectContentIntoFile(config2.injection.targetFile, content);
|
|
3492
3640
|
} catch (error) {
|
|
3493
3641
|
console.error(
|
|
3494
|
-
|
|
3642
|
+
chalk9.red(`Failed to inject content into ${config2.injection.targetFile}:`),
|
|
3495
3643
|
error instanceof Error ? error.message : String(error)
|
|
3496
3644
|
);
|
|
3497
3645
|
}
|
|
@@ -3510,14 +3658,14 @@ function buildSuccessMessage(config2, installedPerDir, extras) {
|
|
|
3510
3658
|
const count = installedPerDir[i] ?? 0;
|
|
3511
3659
|
if (count === 0) continue;
|
|
3512
3660
|
const { label } = config2.dirLabels[i];
|
|
3513
|
-
dirLines +=
|
|
3661
|
+
dirLines += chalk9.dim(` ${label}: ${count}
|
|
3514
3662
|
`);
|
|
3515
3663
|
}
|
|
3516
|
-
return
|
|
3664
|
+
return chalk9.green(`\u2705 ${config2.name} integration installed successfully!
|
|
3517
3665
|
|
|
3518
|
-
`) +
|
|
3666
|
+
`) + chalk9.dim("Files installed:\n") + dirLines + extras + chalk9.dim(` Content injected into: ${config2.injection.targetFile}
|
|
3519
3667
|
|
|
3520
|
-
`) +
|
|
3668
|
+
`) + chalk9.dim("Next, try:\n") + chalk9.dim(" /build REQ-X \u2192 build a requirement\n") + chalk9.dim(' /specify "add two-factor auth" \u2192 specify a requirement\n') + chalk9.dim(" Learn more: ") + chalk9.cyan(config2.docsUrl);
|
|
3521
3669
|
}
|
|
3522
3670
|
function isSetupResult(result) {
|
|
3523
3671
|
return "data" in result && result.success === true && !("message" in result);
|
|
@@ -3553,7 +3701,7 @@ async function handleSetupClaudeCode(opts) {
|
|
|
3553
3701
|
statusLineInstalled = true;
|
|
3554
3702
|
} catch (error) {
|
|
3555
3703
|
console.error(
|
|
3556
|
-
|
|
3704
|
+
chalk9.yellow("\u26A0\uFE0F Failed to install status line script:"),
|
|
3557
3705
|
error instanceof Error ? error.message : String(error)
|
|
3558
3706
|
);
|
|
3559
3707
|
}
|
|
@@ -3561,7 +3709,7 @@ async function handleSetupClaudeCode(opts) {
|
|
|
3561
3709
|
await updateClaudeSettings();
|
|
3562
3710
|
} catch (error) {
|
|
3563
3711
|
console.error(
|
|
3564
|
-
|
|
3712
|
+
chalk9.yellow("\u26A0\uFE0F Failed to update Claude settings:"),
|
|
3565
3713
|
error instanceof Error ? error.message : String(error)
|
|
3566
3714
|
);
|
|
3567
3715
|
}
|
|
@@ -3574,13 +3722,13 @@ async function handleSetupClaudeCode(opts) {
|
|
|
3574
3722
|
installedHooks.push(script);
|
|
3575
3723
|
} catch (error) {
|
|
3576
3724
|
console.error(
|
|
3577
|
-
|
|
3725
|
+
chalk9.yellow(`\u26A0\uFE0F Failed to install hook ${script}:`),
|
|
3578
3726
|
error instanceof Error ? error.message : String(error)
|
|
3579
3727
|
);
|
|
3580
3728
|
}
|
|
3581
3729
|
}
|
|
3582
|
-
const statusLineMessage = statusLineInstalled ?
|
|
3583
|
-
const hooksMessage = installedHooks.map((s) =>
|
|
3730
|
+
const statusLineMessage = statusLineInstalled ? chalk9.dim(" Status line: .claude/statusline.sh\n") : "";
|
|
3731
|
+
const hooksMessage = installedHooks.map((s) => chalk9.dim(` Hook script: .claude/hooks/${s}
|
|
3584
3732
|
`)).join("");
|
|
3585
3733
|
return {
|
|
3586
3734
|
success: true,
|
|
@@ -3590,7 +3738,7 @@ async function handleSetupClaudeCode(opts) {
|
|
|
3590
3738
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
3591
3739
|
return {
|
|
3592
3740
|
success: false,
|
|
3593
|
-
message:
|
|
3741
|
+
message: chalk9.red(`\u274C Setup failed: ${errorMessage}`)
|
|
3594
3742
|
};
|
|
3595
3743
|
}
|
|
3596
3744
|
}
|
|
@@ -3623,22 +3771,22 @@ async function handleSetupCursor(opts) {
|
|
|
3623
3771
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
3624
3772
|
return {
|
|
3625
3773
|
success: false,
|
|
3626
|
-
message:
|
|
3774
|
+
message: chalk9.red(`\u274C Setup failed: ${errorMessage}`)
|
|
3627
3775
|
};
|
|
3628
3776
|
}
|
|
3629
3777
|
}
|
|
3630
3778
|
|
|
3631
3779
|
// src/handlers/update.handlers.ts
|
|
3632
|
-
import { execSync as
|
|
3780
|
+
import { execSync as execSync3 } from "child_process";
|
|
3633
3781
|
import { confirm } from "@inquirer/prompts";
|
|
3634
|
-
import
|
|
3782
|
+
import chalk10 from "chalk";
|
|
3635
3783
|
|
|
3636
3784
|
// src/utils/package-manager.ts
|
|
3637
|
-
import { execSync } from "child_process";
|
|
3785
|
+
import { execSync as execSync2 } from "child_process";
|
|
3638
3786
|
import { select as select2 } from "@inquirer/prompts";
|
|
3639
3787
|
function isPackageManagerInstalled(pm) {
|
|
3640
3788
|
try {
|
|
3641
|
-
|
|
3789
|
+
execSync2(`which ${pm}`, { stdio: "ignore", timeout: 2e3 });
|
|
3642
3790
|
return true;
|
|
3643
3791
|
} catch {
|
|
3644
3792
|
return false;
|
|
@@ -3661,7 +3809,7 @@ function checkGlobalInstallation(pm, packageName) {
|
|
|
3661
3809
|
break;
|
|
3662
3810
|
}
|
|
3663
3811
|
}
|
|
3664
|
-
const output =
|
|
3812
|
+
const output = execSync2(command, {
|
|
3665
3813
|
encoding: "utf-8",
|
|
3666
3814
|
timeout: 5e3
|
|
3667
3815
|
});
|
|
@@ -3725,7 +3873,7 @@ function getUpdateCommand2(pm, packageName) {
|
|
|
3725
3873
|
function executeUpdate(pm, packageName) {
|
|
3726
3874
|
const command = getUpdateCommand2(pm, packageName);
|
|
3727
3875
|
try {
|
|
3728
|
-
|
|
3876
|
+
execSync2(command, {
|
|
3729
3877
|
stdio: "inherit",
|
|
3730
3878
|
timeout: 12e4
|
|
3731
3879
|
// 2 minutes timeout
|
|
@@ -3740,14 +3888,14 @@ function executeUpdate(pm, packageName) {
|
|
|
3740
3888
|
// src/handlers/update.handlers.ts
|
|
3741
3889
|
function runSetupSubprocess(subcommand) {
|
|
3742
3890
|
try {
|
|
3743
|
-
const output =
|
|
3891
|
+
const output = execSync3(`braingrid setup ${subcommand} --force`, {
|
|
3744
3892
|
stdio: "pipe",
|
|
3745
3893
|
timeout: 6e4
|
|
3746
3894
|
});
|
|
3747
3895
|
return output.toString();
|
|
3748
3896
|
} catch (error) {
|
|
3749
3897
|
const msg = error instanceof Error ? error.message : String(error);
|
|
3750
|
-
return
|
|
3898
|
+
return chalk10.yellow(`\u26A0\uFE0F Setup ${subcommand} failed: ${msg}`);
|
|
3751
3899
|
}
|
|
3752
3900
|
}
|
|
3753
3901
|
async function promptForIdeUpdates() {
|
|
@@ -3780,17 +3928,17 @@ ${runSetupSubprocess("cursor")}`;
|
|
|
3780
3928
|
async function handleUpdate(opts) {
|
|
3781
3929
|
try {
|
|
3782
3930
|
const currentVersion = getCurrentVersion();
|
|
3783
|
-
let output =
|
|
3784
|
-
output += `${
|
|
3931
|
+
let output = chalk10.bold.cyan("\n\u{1F504} BrainGrid CLI Update\n\n");
|
|
3932
|
+
output += `${chalk10.bold("Current version:")} ${currentVersion}
|
|
3785
3933
|
`;
|
|
3786
|
-
output +=
|
|
3934
|
+
output += chalk10.dim("Checking for updates...\n");
|
|
3787
3935
|
const latestVersion = await getLatestVersion();
|
|
3788
|
-
output += `${
|
|
3936
|
+
output += `${chalk10.bold("Latest version:")} ${latestVersion}
|
|
3789
3937
|
|
|
3790
3938
|
`;
|
|
3791
3939
|
const comparison = compareVersions(currentVersion, latestVersion);
|
|
3792
3940
|
if (comparison === 0) {
|
|
3793
|
-
output +=
|
|
3941
|
+
output += chalk10.green("\u2705 You are already on the latest version!\n");
|
|
3794
3942
|
console.log(output);
|
|
3795
3943
|
await copyBraingridReadme();
|
|
3796
3944
|
await addBraingridTempToGitignore();
|
|
@@ -3802,32 +3950,32 @@ async function handleUpdate(opts) {
|
|
|
3802
3950
|
};
|
|
3803
3951
|
}
|
|
3804
3952
|
if (comparison > 0) {
|
|
3805
|
-
output +=
|
|
3806
|
-
output +=
|
|
3953
|
+
output += chalk10.yellow("\u26A0\uFE0F You are on a newer version than what is published.\n");
|
|
3954
|
+
output += chalk10.dim(" This is expected if you are developing locally.\n");
|
|
3807
3955
|
return {
|
|
3808
3956
|
success: true,
|
|
3809
3957
|
message: output,
|
|
3810
3958
|
data: { currentVersion, latestVersion, upToDate: false }
|
|
3811
3959
|
};
|
|
3812
3960
|
}
|
|
3813
|
-
output +=
|
|
3961
|
+
output += chalk10.yellow(`\u2B06\uFE0F Update available: ${currentVersion} \u2192 ${latestVersion}
|
|
3814
3962
|
|
|
3815
3963
|
`);
|
|
3816
3964
|
if (opts.check) {
|
|
3817
|
-
output +=
|
|
3965
|
+
output += chalk10.dim("Run ") + chalk10.cyan("braingrid update") + chalk10.dim(" to update\n");
|
|
3818
3966
|
return {
|
|
3819
3967
|
success: true,
|
|
3820
3968
|
message: output,
|
|
3821
3969
|
data: { currentVersion, latestVersion, upToDate: false }
|
|
3822
3970
|
};
|
|
3823
3971
|
}
|
|
3824
|
-
output +=
|
|
3972
|
+
output += chalk10.dim("Detecting package manager...\n");
|
|
3825
3973
|
const packageManager = await detectPackageManager(PACKAGE_NAME);
|
|
3826
|
-
output += `${
|
|
3974
|
+
output += `${chalk10.bold("Package manager:")} ${packageManager}
|
|
3827
3975
|
|
|
3828
3976
|
`;
|
|
3829
3977
|
const updateCommand = getUpdateCommand2(packageManager, PACKAGE_NAME);
|
|
3830
|
-
output += `${
|
|
3978
|
+
output += `${chalk10.dim("Running: ") + chalk10.cyan(updateCommand)}
|
|
3831
3979
|
|
|
3832
3980
|
`;
|
|
3833
3981
|
console.log(output);
|
|
@@ -3837,7 +3985,7 @@ async function handleUpdate(opts) {
|
|
|
3837
3985
|
const setupOutput = await promptForIdeUpdates();
|
|
3838
3986
|
return {
|
|
3839
3987
|
success: true,
|
|
3840
|
-
message:
|
|
3988
|
+
message: chalk10.green("\n\u2705 Successfully updated BrainGrid CLI!\n") + setupOutput,
|
|
3841
3989
|
data: { currentVersion, latestVersion, packageManager }
|
|
3842
3990
|
};
|
|
3843
3991
|
} catch (error) {
|
|
@@ -3875,12 +4023,12 @@ function getServices() {
|
|
|
3875
4023
|
function promptToAddOrganization(owner, webUrl) {
|
|
3876
4024
|
return {
|
|
3877
4025
|
success: false,
|
|
3878
|
-
message:
|
|
4026
|
+
message: chalk11.yellow("\u26A0\uFE0F No projects found for this repository.\n\n") + chalk11.dim(`Repository: ${owner}/*
|
|
3879
4027
|
|
|
3880
|
-
`) +
|
|
4028
|
+
`) + chalk11.dim(`You have GitHub connected, but not for the "${owner}" organization.
|
|
3881
4029
|
|
|
3882
|
-
`) +
|
|
3883
|
-
`) +
|
|
4030
|
+
`) + chalk11.dim("To connect ") + chalk11.cyan(owner) + chalk11.dim(":\n") + chalk11.dim(" 1. Visit: ") + chalk11.cyan(`${webUrl}/integrations`) + chalk11.dim("\n") + chalk11.dim(' 2. Click "Add GitHub Organization"\n') + chalk11.dim(` 3. Select "${owner}"
|
|
4031
|
+
`) + chalk11.dim(" 4. Run ") + chalk11.cyan("braingrid init") + chalk11.dim(" again")
|
|
3884
4032
|
};
|
|
3885
4033
|
}
|
|
3886
4034
|
async function promptToCreateProject(gitInfo, projectService, repositoryService) {
|
|
@@ -3888,20 +4036,20 @@ async function promptToCreateProject(gitInfo, projectService, repositoryService)
|
|
|
3888
4036
|
if (!gitInfo.owner || !gitInfo.name) {
|
|
3889
4037
|
return {
|
|
3890
4038
|
success: false,
|
|
3891
|
-
message:
|
|
4039
|
+
message: chalk11.red("\u274C Repository information is incomplete")
|
|
3892
4040
|
};
|
|
3893
4041
|
}
|
|
3894
4042
|
const repositoryId = await getRepositoryId(repositoryService, gitInfo.owner, gitInfo.name);
|
|
3895
4043
|
if (!repositoryId) {
|
|
3896
4044
|
return {
|
|
3897
4045
|
success: false,
|
|
3898
|
-
message:
|
|
4046
|
+
message: chalk11.yellow("\u26A0\uFE0F Repository accessible but could not retrieve details.\n\n") + chalk11.dim(`Repository: ${gitInfo.owner}/${gitInfo.name}
|
|
3899
4047
|
|
|
3900
|
-
`) +
|
|
4048
|
+
`) + chalk11.dim("Please try again or create a project manually at: ") + chalk11.cyan(webUrl)
|
|
3901
4049
|
};
|
|
3902
4050
|
}
|
|
3903
4051
|
console.log(
|
|
3904
|
-
|
|
4052
|
+
chalk11.yellow("\u26A0\uFE0F Repository accessible but no project exists.\n\n") + chalk11.dim(`Repository: ${gitInfo.owner}/${gitInfo.name}
|
|
3905
4053
|
`)
|
|
3906
4054
|
);
|
|
3907
4055
|
const shouldCreate = await confirm2({
|
|
@@ -3911,7 +4059,7 @@ async function promptToCreateProject(gitInfo, projectService, repositoryService)
|
|
|
3911
4059
|
if (!shouldCreate) {
|
|
3912
4060
|
return {
|
|
3913
4061
|
success: false,
|
|
3914
|
-
message:
|
|
4062
|
+
message: chalk11.dim("\nProject creation cancelled.\n\n") + chalk11.dim("Create a project at ") + chalk11.cyan(webUrl) + chalk11.dim(" and link it to this repository, or use:\n") + chalk11.cyan(
|
|
3915
4063
|
`braingrid project create --name "${gitInfo.name}" --repositories "${gitInfo.owner}/${gitInfo.name}"`
|
|
3916
4064
|
)
|
|
3917
4065
|
};
|
|
@@ -3922,9 +4070,9 @@ async function promptToCreateProject(gitInfo, projectService, repositoryService)
|
|
|
3922
4070
|
description: `Project for ${gitInfo.owner}/${gitInfo.name}`,
|
|
3923
4071
|
repository_id: repositoryId
|
|
3924
4072
|
});
|
|
3925
|
-
console.log(
|
|
4073
|
+
console.log(chalk11.green(`
|
|
3926
4074
|
\u2705 Created project ${project2.short_id}: ${project2.name}`));
|
|
3927
|
-
console.log(
|
|
4075
|
+
console.log(chalk11.green(`\u2705 Linked repository ${gitInfo.owner}/${gitInfo.name}
|
|
3928
4076
|
`));
|
|
3929
4077
|
return { success: true, message: "", data: project2 };
|
|
3930
4078
|
} catch (error) {
|
|
@@ -3938,18 +4086,18 @@ async function promptToGrantRepositoryAccess(gitInfo, webUrl, repositoryService,
|
|
|
3938
4086
|
if (!gitInfo.owner || !gitInfo.name) {
|
|
3939
4087
|
return {
|
|
3940
4088
|
success: false,
|
|
3941
|
-
message:
|
|
4089
|
+
message: chalk11.red("\u274C Repository information is incomplete")
|
|
3942
4090
|
};
|
|
3943
4091
|
}
|
|
3944
4092
|
const owner = gitInfo.owner;
|
|
3945
4093
|
const name = gitInfo.name;
|
|
3946
4094
|
console.log(
|
|
3947
|
-
|
|
4095
|
+
chalk11.yellow("\u26A0\uFE0F Repository found but BrainGrid needs access.\n\n") + chalk11.dim(`Repository: ${owner}/${name}
|
|
3948
4096
|
|
|
3949
|
-
`) +
|
|
4097
|
+
`) + chalk11.dim("Please grant BrainGrid access to this repository:\n") + chalk11.dim(" 1. Visit: ") + chalk11.cyan(`${webUrl}/integrations`) + chalk11.dim("\n") + chalk11.dim(
|
|
3950
4098
|
` 2. Click on your "${owner}" installation "Add/Remove" to grant BrainGrid access to your repository
|
|
3951
4099
|
`
|
|
3952
|
-
) +
|
|
4100
|
+
) + chalk11.dim(` 3. Select "${name}" and save
|
|
3953
4101
|
|
|
3954
4102
|
`)
|
|
3955
4103
|
);
|
|
@@ -3962,10 +4110,10 @@ async function promptToGrantRepositoryAccess(gitInfo, webUrl, repositoryService,
|
|
|
3962
4110
|
if (!accessGranted) {
|
|
3963
4111
|
return {
|
|
3964
4112
|
success: false,
|
|
3965
|
-
message:
|
|
4113
|
+
message: chalk11.yellow("\n\u26A0\uFE0F Repository access not detected within 3 minutes.\n\n") + chalk11.dim("Please grant access at: ") + chalk11.cyan(`${webUrl}/integrations`) + chalk11.dim(" and run ") + chalk11.cyan("braingrid init") + chalk11.dim(" again.")
|
|
3966
4114
|
};
|
|
3967
4115
|
}
|
|
3968
|
-
console.log(
|
|
4116
|
+
console.log(chalk11.green("\u2705 Repository access granted!\n"));
|
|
3969
4117
|
return promptToCreateProject(gitInfo, projectService, repositoryService);
|
|
3970
4118
|
}
|
|
3971
4119
|
async function handleNoProjectForRepository(owner, name, gitInfo, githubService, repositoryService, projectService, config2) {
|
|
@@ -3980,9 +4128,9 @@ async function handleNoProjectForRepository(owner, name, gitInfo, githubService,
|
|
|
3980
4128
|
if (allInstallations.length === 0) {
|
|
3981
4129
|
return {
|
|
3982
4130
|
success: false,
|
|
3983
|
-
message:
|
|
4131
|
+
message: chalk11.yellow("\u26A0\uFE0F No projects found for this repository.\n\n") + chalk11.dim(`Repository: ${owner}/${name}
|
|
3984
4132
|
|
|
3985
|
-
`) +
|
|
4133
|
+
`) + chalk11.dim("It looks like you haven't connected your GitHub account yet.\n") + chalk11.dim("Please connect GitHub at: ") + chalk11.cyan(`${webUrl}/integrations`) + chalk11.dim("\n\nOnce connected, create a project and link it to this repository.")
|
|
3986
4134
|
};
|
|
3987
4135
|
}
|
|
3988
4136
|
const ownerInstallation = findInstallationForOwner(owner, allInstallations);
|
|
@@ -3998,28 +4146,28 @@ async function handleNoProjectForRepository(owner, name, gitInfo, githubService,
|
|
|
3998
4146
|
function showSetupInstructions(scenario) {
|
|
3999
4147
|
let message = "";
|
|
4000
4148
|
if (scenario === "no-git") {
|
|
4001
|
-
message +=
|
|
4002
|
-
message +=
|
|
4003
|
-
message +=
|
|
4149
|
+
message += chalk11.dim("To initialize BrainGrid locally:\n\n");
|
|
4150
|
+
message += chalk11.dim(" 1. Initialize git:\n");
|
|
4151
|
+
message += chalk11.cyan(" git init\n\n");
|
|
4004
4152
|
} else {
|
|
4005
|
-
message +=
|
|
4153
|
+
message += chalk11.dim("To connect to GitHub:\n\n");
|
|
4006
4154
|
}
|
|
4007
|
-
message +=
|
|
4008
|
-
message +=
|
|
4009
|
-
message +=
|
|
4010
|
-
message +=
|
|
4155
|
+
message += chalk11.dim(" 2. Create GitHub repository:\n");
|
|
4156
|
+
message += chalk11.dim(" \u2022 Install GitHub CLI: ") + chalk11.cyan("https://cli.github.com\n");
|
|
4157
|
+
message += chalk11.dim(" Then: ") + chalk11.cyan("gh repo create --private --source=.\n");
|
|
4158
|
+
message += chalk11.dim(" \u2022 Or manually: ") + chalk11.cyan("https://github.com/new\n\n");
|
|
4011
4159
|
if (scenario === "no-git") {
|
|
4012
|
-
message +=
|
|
4160
|
+
message += chalk11.dim(" 3. Run: ") + chalk11.cyan("braingrid init\n\n");
|
|
4013
4161
|
} else {
|
|
4014
|
-
message +=
|
|
4015
|
-
message +=
|
|
4016
|
-
message +=
|
|
4162
|
+
message += chalk11.dim(" 3. Add remote and run init:\n");
|
|
4163
|
+
message += chalk11.cyan(" git remote add origin <url>\n");
|
|
4164
|
+
message += chalk11.cyan(" braingrid init\n\n");
|
|
4017
4165
|
}
|
|
4018
|
-
message +=
|
|
4019
|
-
message +=
|
|
4020
|
-
message +=
|
|
4021
|
-
message +=
|
|
4022
|
-
message += `${
|
|
4166
|
+
message += chalk11.bold("Or use BrainGrid without local initialization:\n\n");
|
|
4167
|
+
message += chalk11.dim(" All commands support the --project flag:\n");
|
|
4168
|
+
message += chalk11.cyan(" braingrid requirement list --project PROJ-123\n");
|
|
4169
|
+
message += chalk11.cyan(' braingrid task create --project PROJ-123 --title "Task"\n\n');
|
|
4170
|
+
message += `${chalk11.dim(" Note: Without local init, you must specify --project for each command.")}
|
|
4023
4171
|
`;
|
|
4024
4172
|
return message;
|
|
4025
4173
|
}
|
|
@@ -4036,10 +4184,10 @@ async function handleNoGitRepository() {
|
|
|
4036
4184
|
if (!gitInitSuccess) {
|
|
4037
4185
|
return {
|
|
4038
4186
|
success: false,
|
|
4039
|
-
message:
|
|
4187
|
+
message: chalk11.red("\u274C Failed to initialize git repository")
|
|
4040
4188
|
};
|
|
4041
4189
|
}
|
|
4042
|
-
console.log(
|
|
4190
|
+
console.log(chalk11.green("\u2705 Initialized git repository"));
|
|
4043
4191
|
const dirName = getCurrentDirectoryName();
|
|
4044
4192
|
const isPrivate = await select3({
|
|
4045
4193
|
message: "Repository visibility:",
|
|
@@ -4053,16 +4201,16 @@ async function handleNoGitRepository() {
|
|
|
4053
4201
|
message: "Repository name:",
|
|
4054
4202
|
default: dirName
|
|
4055
4203
|
});
|
|
4056
|
-
console.log(
|
|
4204
|
+
console.log(chalk11.dim("\nCreating repository...\n"));
|
|
4057
4205
|
const repo = await createGitHubRepoWithGh(repoName, isPrivate);
|
|
4058
4206
|
if (!repo) {
|
|
4059
4207
|
return {
|
|
4060
4208
|
success: false,
|
|
4061
|
-
message:
|
|
4209
|
+
message: chalk11.red("\u274C Failed to create GitHub repository\n\n") + showSetupInstructions("no-git")
|
|
4062
4210
|
};
|
|
4063
4211
|
}
|
|
4064
|
-
console.log(
|
|
4065
|
-
console.log(
|
|
4212
|
+
console.log(chalk11.green(`\u2705 Created repository: ${repo.url}`));
|
|
4213
|
+
console.log(chalk11.green("\u2705 Added remote origin\n"));
|
|
4066
4214
|
return {
|
|
4067
4215
|
success: true,
|
|
4068
4216
|
message: "continue-init",
|
|
@@ -4073,7 +4221,7 @@ async function handleNoGitRepository() {
|
|
|
4073
4221
|
}
|
|
4074
4222
|
return {
|
|
4075
4223
|
success: false,
|
|
4076
|
-
message:
|
|
4224
|
+
message: chalk11.yellow("\u26A0\uFE0F This directory is not a git repository.\n\n") + showSetupInstructions("no-git")
|
|
4077
4225
|
};
|
|
4078
4226
|
}
|
|
4079
4227
|
async function handleNoGitRemote() {
|
|
@@ -4097,16 +4245,16 @@ async function handleNoGitRemote() {
|
|
|
4097
4245
|
message: "Repository name:",
|
|
4098
4246
|
default: dirName
|
|
4099
4247
|
});
|
|
4100
|
-
console.log(
|
|
4248
|
+
console.log(chalk11.dim("\nCreating repository...\n"));
|
|
4101
4249
|
const repo = await createGitHubRepoWithGh(repoName, isPrivate);
|
|
4102
4250
|
if (!repo) {
|
|
4103
4251
|
return {
|
|
4104
4252
|
success: false,
|
|
4105
|
-
message:
|
|
4253
|
+
message: chalk11.red("\u274C Failed to create GitHub repository\n\n") + showSetupInstructions("no-remote")
|
|
4106
4254
|
};
|
|
4107
4255
|
}
|
|
4108
|
-
console.log(
|
|
4109
|
-
console.log(
|
|
4256
|
+
console.log(chalk11.green(`\u2705 Created repository: ${repo.url}`));
|
|
4257
|
+
console.log(chalk11.green("\u2705 Added remote origin\n"));
|
|
4110
4258
|
return {
|
|
4111
4259
|
success: true,
|
|
4112
4260
|
message: "continue-init",
|
|
@@ -4117,7 +4265,7 @@ async function handleNoGitRemote() {
|
|
|
4117
4265
|
}
|
|
4118
4266
|
return {
|
|
4119
4267
|
success: false,
|
|
4120
|
-
message:
|
|
4268
|
+
message: chalk11.yellow("\u26A0\uFE0F Git repository detected but no GitHub remote configured.\n\n") + showSetupInstructions("no-remote")
|
|
4121
4269
|
};
|
|
4122
4270
|
}
|
|
4123
4271
|
async function handleInit(opts) {
|
|
@@ -4125,8 +4273,8 @@ async function handleInit(opts) {
|
|
|
4125
4273
|
const updateInfo = await isUpdateAvailable();
|
|
4126
4274
|
if (updateInfo.available && updateInfo.latestVersion) {
|
|
4127
4275
|
console.log(
|
|
4128
|
-
|
|
4129
|
-
\u26A0\uFE0F A new version of BrainGrid CLI is available: `) +
|
|
4276
|
+
chalk11.yellow(`
|
|
4277
|
+
\u26A0\uFE0F A new version of BrainGrid CLI is available: `) + chalk11.dim(`${updateInfo.currentVersion} \u2192 `) + chalk11.green(updateInfo.latestVersion) + "\n"
|
|
4130
4278
|
);
|
|
4131
4279
|
const shouldUpdate = await confirm2({
|
|
4132
4280
|
message: "Would you like to update now?",
|
|
@@ -4137,7 +4285,7 @@ async function handleInit(opts) {
|
|
|
4137
4285
|
console.log(result.message);
|
|
4138
4286
|
return {
|
|
4139
4287
|
success: true,
|
|
4140
|
-
message:
|
|
4288
|
+
message: chalk11.dim("\nRun `braingrid init` again after the update completes.")
|
|
4141
4289
|
};
|
|
4142
4290
|
}
|
|
4143
4291
|
console.log();
|
|
@@ -4152,7 +4300,7 @@ async function handleInit(opts) {
|
|
|
4152
4300
|
if (!shouldInstall) {
|
|
4153
4301
|
return {
|
|
4154
4302
|
success: false,
|
|
4155
|
-
message:
|
|
4303
|
+
message: chalk11.yellow("\u26A0\uFE0F Git installation cancelled.\n\n") + getManualInstallInstructions()
|
|
4156
4304
|
};
|
|
4157
4305
|
}
|
|
4158
4306
|
console.log();
|
|
@@ -4168,14 +4316,14 @@ async function handleInit(opts) {
|
|
|
4168
4316
|
if (!await isGitInstalled()) {
|
|
4169
4317
|
return {
|
|
4170
4318
|
success: false,
|
|
4171
|
-
message:
|
|
4319
|
+
message: chalk11.red("\u274C Git installation completed but git command not found\n\n") + chalk11.dim("You may need to restart your terminal or add Git to your PATH.\n") + getManualInstallInstructions()
|
|
4172
4320
|
};
|
|
4173
4321
|
}
|
|
4174
4322
|
}
|
|
4175
4323
|
if (!await isGhInstalled()) {
|
|
4176
|
-
console.log(
|
|
4324
|
+
console.log(chalk11.blue("\n\u{1F4A1} GitHub CLI is highly recommended for working with BrainGrid."));
|
|
4177
4325
|
console.log(
|
|
4178
|
-
|
|
4326
|
+
chalk11.dim(" It enables seamless GitHub integration and repository management.\n")
|
|
4179
4327
|
);
|
|
4180
4328
|
const shouldInstallGh = await confirm2({
|
|
4181
4329
|
message: "Would you like to install GitHub CLI now?",
|
|
@@ -4189,10 +4337,10 @@ async function handleInit(opts) {
|
|
|
4189
4337
|
console.log();
|
|
4190
4338
|
} else {
|
|
4191
4339
|
console.log(ghInstallResult.message);
|
|
4192
|
-
console.log(
|
|
4340
|
+
console.log(chalk11.dim("You can install it manually later.\n"));
|
|
4193
4341
|
}
|
|
4194
4342
|
} else {
|
|
4195
|
-
console.log(
|
|
4343
|
+
console.log(chalk11.dim("Skipping GitHub CLI installation.\n"));
|
|
4196
4344
|
}
|
|
4197
4345
|
}
|
|
4198
4346
|
if (await projectConfigExists() && !opts.force) {
|
|
@@ -4200,15 +4348,15 @@ async function handleInit(opts) {
|
|
|
4200
4348
|
const existing = await loadProjectConfig();
|
|
4201
4349
|
return {
|
|
4202
4350
|
success: false,
|
|
4203
|
-
message:
|
|
4204
|
-
`) +
|
|
4351
|
+
message: chalk11.yellow("\u26A0\uFE0F Already initialized.\n\n") + chalk11.dim(`Project: ${existing.project_name} (${existing.project_short_id})
|
|
4352
|
+
`) + chalk11.dim(`Repository: ${existing.repository?.full_name || "N/A"}
|
|
4205
4353
|
|
|
4206
|
-
`) +
|
|
4354
|
+
`) + chalk11.dim("Use --force to reinitialize")
|
|
4207
4355
|
};
|
|
4208
4356
|
} catch {
|
|
4209
4357
|
return {
|
|
4210
4358
|
success: false,
|
|
4211
|
-
message:
|
|
4359
|
+
message: chalk11.yellow("\u26A0\uFE0F Invalid project configuration found.\n") + chalk11.dim("Use --force to reinitialize")
|
|
4212
4360
|
};
|
|
4213
4361
|
}
|
|
4214
4362
|
}
|
|
@@ -4221,7 +4369,7 @@ async function handleInit(opts) {
|
|
|
4221
4369
|
if (!shouldLogin) {
|
|
4222
4370
|
return {
|
|
4223
4371
|
success: false,
|
|
4224
|
-
message:
|
|
4372
|
+
message: chalk11.yellow("\u26A0\uFE0F Authentication required.\n") + chalk11.dim("Run ") + chalk11.cyan("braingrid login") + chalk11.dim(" when you're ready to authenticate.")
|
|
4225
4373
|
};
|
|
4226
4374
|
}
|
|
4227
4375
|
console.log();
|
|
@@ -4229,13 +4377,13 @@ async function handleInit(opts) {
|
|
|
4229
4377
|
if (!loginResult.success) {
|
|
4230
4378
|
return {
|
|
4231
4379
|
success: false,
|
|
4232
|
-
message:
|
|
4380
|
+
message: chalk11.red("\u274C Login failed.\n") + chalk11.dim("Please try running ") + chalk11.cyan("braingrid login") + chalk11.dim(" again.")
|
|
4233
4381
|
};
|
|
4234
4382
|
}
|
|
4235
4383
|
if (!await auth.isAuthenticated()) {
|
|
4236
4384
|
return {
|
|
4237
4385
|
success: false,
|
|
4238
|
-
message:
|
|
4386
|
+
message: chalk11.red("\u274C Login was not completed.\n") + chalk11.dim("Please try running ") + chalk11.cyan("braingrid login") + chalk11.dim(" again.")
|
|
4239
4387
|
};
|
|
4240
4388
|
}
|
|
4241
4389
|
console.log();
|
|
@@ -4244,27 +4392,27 @@ async function handleInit(opts) {
|
|
|
4244
4392
|
if (!session) {
|
|
4245
4393
|
return {
|
|
4246
4394
|
success: false,
|
|
4247
|
-
message:
|
|
4395
|
+
message: chalk11.red("\u274C No session found. Please run `braingrid login` first.")
|
|
4248
4396
|
};
|
|
4249
4397
|
}
|
|
4250
4398
|
if (session.organization_id === "default") {
|
|
4251
|
-
console.log(
|
|
4399
|
+
console.log(chalk11.yellow("\u26A0\uFE0F Organization ID not set, validating session...\n"));
|
|
4252
4400
|
const isValid = await auth.isAuthenticated();
|
|
4253
4401
|
if (!isValid) {
|
|
4254
4402
|
return {
|
|
4255
4403
|
success: false,
|
|
4256
|
-
message:
|
|
4404
|
+
message: chalk11.red("\u274C Session validation failed. Please run `braingrid login` again.")
|
|
4257
4405
|
};
|
|
4258
4406
|
}
|
|
4259
4407
|
const updatedSession = await auth.getStoredSession();
|
|
4260
4408
|
if (!updatedSession || updatedSession.organization_id === "default") {
|
|
4261
4409
|
return {
|
|
4262
4410
|
success: false,
|
|
4263
|
-
message:
|
|
4411
|
+
message: chalk11.red("\u274C Unable to retrieve organization information.\n\n") + chalk11.dim("This may indicate an issue with your account setup.\n") + chalk11.dim("Please contact support or try logging in again with ") + chalk11.cyan("braingrid logout") + chalk11.dim(" and ") + chalk11.cyan("braingrid login")
|
|
4264
4412
|
};
|
|
4265
4413
|
}
|
|
4266
4414
|
Object.assign(session, updatedSession);
|
|
4267
|
-
console.log(
|
|
4415
|
+
console.log(chalk11.green("\u2705 Organization ID updated successfully\n"));
|
|
4268
4416
|
}
|
|
4269
4417
|
let gitInfo = await getGitRepositoryInfo();
|
|
4270
4418
|
let project2;
|
|
@@ -4274,9 +4422,9 @@ async function handleInit(opts) {
|
|
|
4274
4422
|
} catch {
|
|
4275
4423
|
return {
|
|
4276
4424
|
success: false,
|
|
4277
|
-
message:
|
|
4425
|
+
message: chalk11.red(`\u274C Project not found: ${opts.project}
|
|
4278
4426
|
|
|
4279
|
-
`) +
|
|
4427
|
+
`) + chalk11.dim("Make sure the project ID is correct and you have access to it.")
|
|
4280
4428
|
};
|
|
4281
4429
|
}
|
|
4282
4430
|
} else {
|
|
@@ -4287,7 +4435,7 @@ async function handleInit(opts) {
|
|
|
4287
4435
|
if (!gitInfo || !gitInfo.owner || !gitInfo.name) {
|
|
4288
4436
|
return {
|
|
4289
4437
|
success: false,
|
|
4290
|
-
message:
|
|
4438
|
+
message: chalk11.red("\u274C Failed to get repository information after setup")
|
|
4291
4439
|
};
|
|
4292
4440
|
}
|
|
4293
4441
|
} else {
|
|
@@ -4301,7 +4449,7 @@ async function handleInit(opts) {
|
|
|
4301
4449
|
if (!gitInfo || !gitInfo.owner || !gitInfo.name) {
|
|
4302
4450
|
return {
|
|
4303
4451
|
success: false,
|
|
4304
|
-
message:
|
|
4452
|
+
message: chalk11.red("\u274C Failed to get repository information after setup")
|
|
4305
4453
|
};
|
|
4306
4454
|
}
|
|
4307
4455
|
} else {
|
|
@@ -4311,7 +4459,7 @@ async function handleInit(opts) {
|
|
|
4311
4459
|
if (!gitInfo) {
|
|
4312
4460
|
return {
|
|
4313
4461
|
success: false,
|
|
4314
|
-
message:
|
|
4462
|
+
message: chalk11.red("\u274C Repository information is missing")
|
|
4315
4463
|
};
|
|
4316
4464
|
}
|
|
4317
4465
|
const owner = gitInfo.owner;
|
|
@@ -4319,7 +4467,7 @@ async function handleInit(opts) {
|
|
|
4319
4467
|
if (!owner || !name) {
|
|
4320
4468
|
return {
|
|
4321
4469
|
success: false,
|
|
4322
|
-
message:
|
|
4470
|
+
message: chalk11.red("\u274C Repository information is incomplete")
|
|
4323
4471
|
};
|
|
4324
4472
|
}
|
|
4325
4473
|
let response;
|
|
@@ -4358,8 +4506,8 @@ async function handleInit(opts) {
|
|
|
4358
4506
|
}
|
|
4359
4507
|
project2 = response.projects[0];
|
|
4360
4508
|
}
|
|
4361
|
-
const projectInfo =
|
|
4362
|
-
` : "") +
|
|
4509
|
+
const projectInfo = chalk11.bold("\n\u{1F4E6} BrainGrid Project Found\n\n") + chalk11.dim("Project: ") + chalk11.cyan(project2.name) + "\n" + chalk11.dim("ID: ") + chalk11.gray(project2.short_id) + "\n" + (project2.description ? `${chalk11.dim("Description: ") + chalk11.gray(project2.description)}
|
|
4510
|
+
` : "") + chalk11.dim("Repository: ") + chalk11.gray(project2.repository?.full_name || "N/A") + "\n\n";
|
|
4363
4511
|
console.log(projectInfo);
|
|
4364
4512
|
if (!opts.force) {
|
|
4365
4513
|
const shouldInit = await confirm2({
|
|
@@ -4369,7 +4517,7 @@ async function handleInit(opts) {
|
|
|
4369
4517
|
if (!shouldInit) {
|
|
4370
4518
|
return {
|
|
4371
4519
|
success: false,
|
|
4372
|
-
message:
|
|
4520
|
+
message: chalk11.yellow("Initialization cancelled.")
|
|
4373
4521
|
};
|
|
4374
4522
|
}
|
|
4375
4523
|
}
|
|
@@ -4394,7 +4542,7 @@ async function handleInit(opts) {
|
|
|
4394
4542
|
await addBraingridTempToGitignore();
|
|
4395
4543
|
await copyBraingridReadme();
|
|
4396
4544
|
console.log(
|
|
4397
|
-
|
|
4545
|
+
chalk11.green("\u2705 Repository initialized successfully!\n\n") + chalk11.dim("Project: ") + chalk11.cyan(project2.name) + chalk11.dim(` (${project2.short_id})`) + "\n" + chalk11.dim("Config: ") + chalk11.gray(".braingrid/project.json") + "\n"
|
|
4398
4546
|
);
|
|
4399
4547
|
const installedIDEs = await detectInstalledIDEs();
|
|
4400
4548
|
if (installedIDEs.claudeCode) {
|
|
@@ -4413,15 +4561,15 @@ async function handleInit(opts) {
|
|
|
4413
4561
|
if (result.success) {
|
|
4414
4562
|
console.log(result.message);
|
|
4415
4563
|
} else {
|
|
4416
|
-
console.log(
|
|
4564
|
+
console.log(chalk11.yellow("\u26A0\uFE0F Claude Code setup was not completed."));
|
|
4417
4565
|
console.log(
|
|
4418
|
-
|
|
4566
|
+
chalk11.dim("You can run ") + chalk11.cyan("braingrid setup claude-code") + chalk11.dim(" later.")
|
|
4419
4567
|
);
|
|
4420
4568
|
}
|
|
4421
4569
|
} catch {
|
|
4422
|
-
console.log(
|
|
4570
|
+
console.log(chalk11.yellow("\u26A0\uFE0F Claude Code setup encountered an error."));
|
|
4423
4571
|
console.log(
|
|
4424
|
-
|
|
4572
|
+
chalk11.dim("You can run ") + chalk11.cyan("braingrid setup claude-code") + chalk11.dim(" later.")
|
|
4425
4573
|
);
|
|
4426
4574
|
}
|
|
4427
4575
|
console.log("");
|
|
@@ -4443,15 +4591,15 @@ async function handleInit(opts) {
|
|
|
4443
4591
|
if (result.success) {
|
|
4444
4592
|
console.log(result.message);
|
|
4445
4593
|
} else {
|
|
4446
|
-
console.log(
|
|
4594
|
+
console.log(chalk11.yellow("\u26A0\uFE0F Cursor setup was not completed."));
|
|
4447
4595
|
console.log(
|
|
4448
|
-
|
|
4596
|
+
chalk11.dim("You can run ") + chalk11.cyan("braingrid setup cursor") + chalk11.dim(" later.")
|
|
4449
4597
|
);
|
|
4450
4598
|
}
|
|
4451
4599
|
} catch {
|
|
4452
|
-
console.log(
|
|
4600
|
+
console.log(chalk11.yellow("\u26A0\uFE0F Cursor setup encountered an error."));
|
|
4453
4601
|
console.log(
|
|
4454
|
-
|
|
4602
|
+
chalk11.dim("You can run ") + chalk11.cyan("braingrid setup cursor") + chalk11.dim(" later.")
|
|
4455
4603
|
);
|
|
4456
4604
|
}
|
|
4457
4605
|
console.log("");
|
|
@@ -4459,7 +4607,7 @@ async function handleInit(opts) {
|
|
|
4459
4607
|
}
|
|
4460
4608
|
return {
|
|
4461
4609
|
success: true,
|
|
4462
|
-
message:
|
|
4610
|
+
message: chalk11.dim(
|
|
4463
4611
|
"You can now use project-scoped commands without specifying a project ID."
|
|
4464
4612
|
),
|
|
4465
4613
|
data: localConfig
|
|
@@ -4473,10 +4621,10 @@ async function handleInit(opts) {
|
|
|
4473
4621
|
}
|
|
4474
4622
|
|
|
4475
4623
|
// src/handlers/project.handlers.ts
|
|
4476
|
-
import
|
|
4624
|
+
import chalk14 from "chalk";
|
|
4477
4625
|
|
|
4478
4626
|
// src/utils/formatting.ts
|
|
4479
|
-
import
|
|
4627
|
+
import chalk12 from "chalk";
|
|
4480
4628
|
|
|
4481
4629
|
// src/utils/id-normalization.ts
|
|
4482
4630
|
function normalizeId(prefix, input2) {
|
|
@@ -4518,7 +4666,7 @@ function getWebUiUrl(apiUrl) {
|
|
|
4518
4666
|
}
|
|
4519
4667
|
function formatTasksListOutput(tasks, format, verbose, options) {
|
|
4520
4668
|
if (tasks.length === 0) {
|
|
4521
|
-
return
|
|
4669
|
+
return chalk12.yellow("No tasks found.");
|
|
4522
4670
|
}
|
|
4523
4671
|
switch (format) {
|
|
4524
4672
|
case "json":
|
|
@@ -4548,7 +4696,7 @@ function formatTasksListOutput(tasks, format, verbose, options) {
|
|
|
4548
4696
|
}
|
|
4549
4697
|
}
|
|
4550
4698
|
function formatTasksListTable(tasks) {
|
|
4551
|
-
let output =
|
|
4699
|
+
let output = chalk12.bold(`\u{1F4CB} Tasks (${tasks.length})
|
|
4552
4700
|
|
|
4553
4701
|
`);
|
|
4554
4702
|
output += "ID Short ID Status Title Assigned To Blocked\n";
|
|
@@ -4568,58 +4716,58 @@ function formatTasksListTable(tasks) {
|
|
|
4568
4716
|
return output;
|
|
4569
4717
|
}
|
|
4570
4718
|
function formatTasksListVerbose(tasks, options) {
|
|
4571
|
-
let output =
|
|
4719
|
+
let output = chalk12.bold(`\u{1F4CB} Tasks (${tasks.length})
|
|
4572
4720
|
|
|
4573
4721
|
`);
|
|
4574
|
-
const divider =
|
|
4722
|
+
const divider = chalk12.gray("\u2500".repeat(50));
|
|
4575
4723
|
for (let i = 0; i < tasks.length; i++) {
|
|
4576
4724
|
const task2 = tasks[i];
|
|
4577
4725
|
const statusEmoji = getTaskStatusEmoji(task2.status);
|
|
4578
|
-
output += `${statusEmoji} ${
|
|
4726
|
+
output += `${statusEmoji} ${chalk12.bold(task2.title)}
|
|
4579
4727
|
`;
|
|
4580
|
-
output += `${
|
|
4728
|
+
output += `${chalk12.bold("Short ID:")} TASK-${task2.number}
|
|
4581
4729
|
`;
|
|
4582
|
-
output += `${
|
|
4730
|
+
output += `${chalk12.bold("ID:")} ${task2.id}
|
|
4583
4731
|
`;
|
|
4584
4732
|
if (options?.apiUrl && options?.requirementId) {
|
|
4585
4733
|
const webUiUrl = getWebUiUrl(options.apiUrl);
|
|
4586
|
-
output += `${
|
|
4734
|
+
output += `${chalk12.bold("URL:")} ${webUiUrl}/requirements/overview?id=${options.requirementId}&tab=tasks
|
|
4587
4735
|
`;
|
|
4588
4736
|
}
|
|
4589
|
-
output += `${
|
|
4737
|
+
output += `${chalk12.bold("Project:")} ${options?.projectShortId || "N/A"}
|
|
4590
4738
|
`;
|
|
4591
|
-
output += `${
|
|
4739
|
+
output += `${chalk12.bold("Requirement:")} ${options?.requirementShortId || "N/A"}
|
|
4592
4740
|
`;
|
|
4593
|
-
output += `${
|
|
4741
|
+
output += `${chalk12.bold("Status:")} ${task2.status}
|
|
4594
4742
|
`;
|
|
4595
4743
|
if (task2.assigned_to) {
|
|
4596
|
-
output += `${
|
|
4744
|
+
output += `${chalk12.bold("Assigned to:")} ${task2.assigned_to}
|
|
4597
4745
|
`;
|
|
4598
4746
|
} else {
|
|
4599
|
-
output += `${
|
|
4747
|
+
output += `${chalk12.bold("Assigned to:")} Unassigned
|
|
4600
4748
|
`;
|
|
4601
4749
|
}
|
|
4602
4750
|
if (task2.created_at) {
|
|
4603
|
-
output += `${
|
|
4751
|
+
output += `${chalk12.bold("Created:")} ${new Date(task2.created_at).toLocaleString()}
|
|
4604
4752
|
`;
|
|
4605
4753
|
}
|
|
4606
4754
|
if (task2.updated_at) {
|
|
4607
|
-
output += `${
|
|
4755
|
+
output += `${chalk12.bold("Updated:")} ${new Date(task2.updated_at).toLocaleString()}
|
|
4608
4756
|
`;
|
|
4609
4757
|
}
|
|
4610
4758
|
if (task2.started_at) {
|
|
4611
|
-
output += `${
|
|
4759
|
+
output += `${chalk12.bold("Started:")} ${new Date(task2.started_at).toLocaleString()}
|
|
4612
4760
|
`;
|
|
4613
4761
|
}
|
|
4614
4762
|
if (task2.finished_at) {
|
|
4615
|
-
output += `${
|
|
4763
|
+
output += `${chalk12.bold("Finished:")} ${new Date(task2.finished_at).toLocaleString()}
|
|
4616
4764
|
`;
|
|
4617
4765
|
}
|
|
4618
4766
|
if (task2.content) {
|
|
4619
4767
|
output += `
|
|
4620
4768
|
${divider}
|
|
4621
4769
|
`;
|
|
4622
|
-
output += `${
|
|
4770
|
+
output += `${chalk12.bold("Content:")}
|
|
4623
4771
|
${task2.content}
|
|
4624
4772
|
`;
|
|
4625
4773
|
output += `${divider}
|
|
@@ -4627,12 +4775,12 @@ ${task2.content}
|
|
|
4627
4775
|
}
|
|
4628
4776
|
if (task2.blocked_by && task2.blocked_by.length > 0) {
|
|
4629
4777
|
output += `
|
|
4630
|
-
${
|
|
4778
|
+
${chalk12.bold("Blocked by:")} ${task2.blocked_by.join(", ")}
|
|
4631
4779
|
`;
|
|
4632
4780
|
}
|
|
4633
4781
|
if (i < tasks.length - 1) {
|
|
4634
4782
|
output += `
|
|
4635
|
-
${
|
|
4783
|
+
${chalk12.gray("\u2550".repeat(50))}
|
|
4636
4784
|
|
|
4637
4785
|
`;
|
|
4638
4786
|
}
|
|
@@ -4845,57 +4993,57 @@ function getRequirementStatusEmoji(status) {
|
|
|
4845
4993
|
}
|
|
4846
4994
|
function formatRequirementOutput(requirement2, options) {
|
|
4847
4995
|
const statusEmoji = getRequirementStatusEmoji(requirement2.status);
|
|
4848
|
-
const divider =
|
|
4996
|
+
const divider = chalk12.gray("\u2500".repeat(50));
|
|
4849
4997
|
let message = "";
|
|
4850
4998
|
if (options?.successMessage) {
|
|
4851
|
-
message +=
|
|
4999
|
+
message += chalk12.green(`\u2705 ${options.successMessage}
|
|
4852
5000
|
|
|
4853
5001
|
`);
|
|
4854
5002
|
}
|
|
4855
|
-
message += `${statusEmoji} ${
|
|
5003
|
+
message += `${statusEmoji} ${chalk12.bold(requirement2.name)}
|
|
4856
5004
|
|
|
4857
5005
|
`;
|
|
4858
|
-
message += `${
|
|
5006
|
+
message += `${chalk12.bold("Short ID:")} ${requirement2.short_id || "N/A"}
|
|
4859
5007
|
`;
|
|
4860
|
-
message += `${
|
|
5008
|
+
message += `${chalk12.bold("ID:")} ${requirement2.id}
|
|
4861
5009
|
`;
|
|
4862
5010
|
if (options?.apiUrl) {
|
|
4863
5011
|
const webUiUrl = getWebUiUrl(options.apiUrl);
|
|
4864
|
-
message += `${
|
|
5012
|
+
message += `${chalk12.bold("URL:")} ${webUiUrl}/requirements/overview?id=${requirement2.id}
|
|
4865
5013
|
`;
|
|
4866
5014
|
}
|
|
4867
|
-
message += `${
|
|
5015
|
+
message += `${chalk12.bold("Project:")} ${options?.projectShortId || "N/A"}
|
|
4868
5016
|
`;
|
|
4869
5017
|
if (requirement2.branch) {
|
|
4870
|
-
message += `${
|
|
5018
|
+
message += `${chalk12.bold("Branch:")} ${requirement2.branch}
|
|
4871
5019
|
`;
|
|
4872
5020
|
}
|
|
4873
|
-
message += `${
|
|
5021
|
+
message += `${chalk12.bold("Status:")} ${requirement2.status}
|
|
4874
5022
|
`;
|
|
4875
5023
|
if (requirement2.tags && requirement2.tags.length > 0) {
|
|
4876
5024
|
const tagNames = requirement2.tags.map((tag) => tag.name).join(", ");
|
|
4877
|
-
message += `${
|
|
5025
|
+
message += `${chalk12.bold("Tags:")} ${tagNames}
|
|
4878
5026
|
`;
|
|
4879
5027
|
}
|
|
4880
5028
|
if (requirement2.assignee) {
|
|
4881
5029
|
const assigneeName = requirement2.assignee.first_name || requirement2.assignee.last_name ? `${requirement2.assignee.first_name || ""} ${requirement2.assignee.last_name || ""}`.trim() : requirement2.assignee.email;
|
|
4882
|
-
message += `${
|
|
5030
|
+
message += `${chalk12.bold("Assigned to:")} ${assigneeName} (${requirement2.assignee.email})
|
|
4883
5031
|
`;
|
|
4884
5032
|
} else {
|
|
4885
|
-
message += `${
|
|
5033
|
+
message += `${chalk12.bold("Assigned to:")} Unassigned
|
|
4886
5034
|
`;
|
|
4887
5035
|
}
|
|
4888
|
-
message += `${
|
|
5036
|
+
message += `${chalk12.bold("Created:")} ${new Date(requirement2.created_at).toLocaleString()}
|
|
4889
5037
|
`;
|
|
4890
5038
|
if (options?.showUpdated) {
|
|
4891
|
-
message += `${
|
|
5039
|
+
message += `${chalk12.bold("Updated:")} ${new Date(requirement2.updated_at).toLocaleString()}
|
|
4892
5040
|
`;
|
|
4893
5041
|
}
|
|
4894
5042
|
if (options?.showDescription && requirement2.description) {
|
|
4895
5043
|
message += `
|
|
4896
5044
|
${divider}
|
|
4897
5045
|
`;
|
|
4898
|
-
message += `${
|
|
5046
|
+
message += `${chalk12.bold("Description:")}
|
|
4899
5047
|
${requirement2.description}
|
|
4900
5048
|
`;
|
|
4901
5049
|
message += `${divider}
|
|
@@ -4905,7 +5053,7 @@ ${requirement2.description}
|
|
|
4905
5053
|
message += `
|
|
4906
5054
|
${divider}
|
|
4907
5055
|
`;
|
|
4908
|
-
message += `${
|
|
5056
|
+
message += `${chalk12.bold("Content:")}
|
|
4909
5057
|
${requirement2.content}
|
|
4910
5058
|
`;
|
|
4911
5059
|
message += `${divider}
|
|
@@ -4913,7 +5061,7 @@ ${requirement2.content}
|
|
|
4913
5061
|
}
|
|
4914
5062
|
if (options?.showTaskList) {
|
|
4915
5063
|
message += `
|
|
4916
|
-
${
|
|
5064
|
+
${chalk12.bold("Tasks:")}
|
|
4917
5065
|
`;
|
|
4918
5066
|
if (requirement2.tasks && requirement2.tasks.length > 0) {
|
|
4919
5067
|
for (const task2 of requirement2.tasks) {
|
|
@@ -4929,7 +5077,7 @@ ${chalk11.bold("Tasks:")}
|
|
|
4929
5077
|
const completedTasks = tasks.filter((task2) => task2.status === "COMPLETED").length;
|
|
4930
5078
|
const totalTasks = tasks.length;
|
|
4931
5079
|
message += `
|
|
4932
|
-
${
|
|
5080
|
+
${chalk12.bold("Tasks:")} ${completedTasks}/${totalTasks} completed
|
|
4933
5081
|
`;
|
|
4934
5082
|
message += `${divider}
|
|
4935
5083
|
`;
|
|
@@ -4952,59 +5100,59 @@ function getTaskStatusEmoji(status) {
|
|
|
4952
5100
|
}
|
|
4953
5101
|
function formatTaskOutput(task2, options) {
|
|
4954
5102
|
const statusEmoji = getTaskStatusEmoji(task2.status);
|
|
4955
|
-
const divider =
|
|
5103
|
+
const divider = chalk12.gray("\u2500".repeat(50));
|
|
4956
5104
|
let message = "";
|
|
4957
5105
|
if (options?.successMessage) {
|
|
4958
|
-
message +=
|
|
5106
|
+
message += chalk12.green(`\u2705 ${options.successMessage}
|
|
4959
5107
|
|
|
4960
5108
|
`);
|
|
4961
5109
|
}
|
|
4962
|
-
message += `${statusEmoji} ${
|
|
5110
|
+
message += `${statusEmoji} ${chalk12.bold(task2.title)}
|
|
4963
5111
|
|
|
4964
5112
|
`;
|
|
4965
|
-
message += `${
|
|
5113
|
+
message += `${chalk12.bold("Short ID:")} TASK-${task2.number}
|
|
4966
5114
|
`;
|
|
4967
|
-
message += `${
|
|
5115
|
+
message += `${chalk12.bold("ID:")} ${task2.id}
|
|
4968
5116
|
`;
|
|
4969
5117
|
if (options?.apiUrl && options?.requirementId) {
|
|
4970
5118
|
const webUiUrl = getWebUiUrl(options.apiUrl);
|
|
4971
|
-
message += `${
|
|
5119
|
+
message += `${chalk12.bold("URL:")} ${webUiUrl}/requirements/overview?id=${options.requirementId}&tab=tasks
|
|
4972
5120
|
`;
|
|
4973
5121
|
}
|
|
4974
|
-
message += `${
|
|
5122
|
+
message += `${chalk12.bold("Project:")} ${options?.projectShortId || "N/A"}
|
|
4975
5123
|
`;
|
|
4976
|
-
message += `${
|
|
5124
|
+
message += `${chalk12.bold("Requirement:")} ${options?.requirementShortId || "N/A"}
|
|
4977
5125
|
`;
|
|
4978
|
-
message += `${
|
|
5126
|
+
message += `${chalk12.bold("Status:")} ${task2.status}
|
|
4979
5127
|
`;
|
|
4980
5128
|
if (task2.assigned_to) {
|
|
4981
|
-
message += `${
|
|
5129
|
+
message += `${chalk12.bold("Assigned to:")} ${task2.assigned_to}
|
|
4982
5130
|
`;
|
|
4983
5131
|
} else {
|
|
4984
|
-
message += `${
|
|
5132
|
+
message += `${chalk12.bold("Assigned to:")} Unassigned
|
|
4985
5133
|
`;
|
|
4986
5134
|
}
|
|
4987
5135
|
if (task2.created_at) {
|
|
4988
|
-
message += `${
|
|
5136
|
+
message += `${chalk12.bold("Created:")} ${new Date(task2.created_at).toLocaleString()}
|
|
4989
5137
|
`;
|
|
4990
5138
|
}
|
|
4991
5139
|
if (task2.updated_at) {
|
|
4992
|
-
message += `${
|
|
5140
|
+
message += `${chalk12.bold("Updated:")} ${new Date(task2.updated_at).toLocaleString()}
|
|
4993
5141
|
`;
|
|
4994
5142
|
}
|
|
4995
5143
|
if (task2.started_at) {
|
|
4996
|
-
message += `${
|
|
5144
|
+
message += `${chalk12.bold("Started:")} ${new Date(task2.started_at).toLocaleString()}
|
|
4997
5145
|
`;
|
|
4998
5146
|
}
|
|
4999
5147
|
if (task2.finished_at) {
|
|
5000
|
-
message += `${
|
|
5148
|
+
message += `${chalk12.bold("Finished:")} ${new Date(task2.finished_at).toLocaleString()}
|
|
5001
5149
|
`;
|
|
5002
5150
|
}
|
|
5003
5151
|
if (options?.showContent && task2.content) {
|
|
5004
5152
|
message += `
|
|
5005
5153
|
${divider}
|
|
5006
5154
|
`;
|
|
5007
|
-
message += `${
|
|
5155
|
+
message += `${chalk12.bold("Content:")}
|
|
5008
5156
|
${task2.content}
|
|
5009
5157
|
`;
|
|
5010
5158
|
message += `${divider}
|
|
@@ -5012,7 +5160,7 @@ ${task2.content}
|
|
|
5012
5160
|
}
|
|
5013
5161
|
if (task2.blocked_by && task2.blocked_by.length > 0) {
|
|
5014
5162
|
message += `
|
|
5015
|
-
${
|
|
5163
|
+
${chalk12.bold("Blocked by:")} ${task2.blocked_by.join(", ")}
|
|
5016
5164
|
`;
|
|
5017
5165
|
}
|
|
5018
5166
|
return message;
|
|
@@ -5595,9 +5743,9 @@ function formatProjectShowXml(project2) {
|
|
|
5595
5743
|
}
|
|
5596
5744
|
function formatRequirementTreeView(requirements, tasksMap) {
|
|
5597
5745
|
if (requirements.length === 0) {
|
|
5598
|
-
return
|
|
5746
|
+
return chalk12.yellow("No requirements found.\n");
|
|
5599
5747
|
}
|
|
5600
|
-
let output =
|
|
5748
|
+
let output = chalk12.bold.cyan(`\u{1F4CB} Requirements (Tree View)
|
|
5601
5749
|
|
|
5602
5750
|
`);
|
|
5603
5751
|
for (let i = 0; i < requirements.length; i++) {
|
|
@@ -5610,12 +5758,12 @@ function formatRequirementTreeView(requirements, tasksMap) {
|
|
|
5610
5758
|
if (shortId.startsWith("REQ-REQ-")) {
|
|
5611
5759
|
shortId = shortId.replace("REQ-REQ-", "REQ-");
|
|
5612
5760
|
}
|
|
5613
|
-
const branchInfo = req.branch ?
|
|
5614
|
-
output += `${reqPrefix}${
|
|
5761
|
+
const branchInfo = req.branch ? chalk12.gray(` (branch: ${req.branch})`) : "";
|
|
5762
|
+
output += `${reqPrefix}${chalk12.bold(shortId)} ${reqStatusEmoji} ${req.name}${branchInfo}
|
|
5615
5763
|
`;
|
|
5616
5764
|
const tasks = tasksMap.get(req.id) || [];
|
|
5617
5765
|
if (tasks.length === 0) {
|
|
5618
|
-
output += `${childPrefix}\u2514\u2500\u2500 ${
|
|
5766
|
+
output += `${childPrefix}\u2514\u2500\u2500 ${chalk12.gray("(no tasks yet)")}
|
|
5619
5767
|
`;
|
|
5620
5768
|
} else {
|
|
5621
5769
|
for (let j = 0; j < tasks.length; j++) {
|
|
@@ -5623,7 +5771,7 @@ function formatRequirementTreeView(requirements, tasksMap) {
|
|
|
5623
5771
|
const isLastTask = j === tasks.length - 1;
|
|
5624
5772
|
const taskPrefix = isLastTask ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
|
|
5625
5773
|
const taskStatusEmoji = getRequirementStatusEmoji(task2.status);
|
|
5626
|
-
const blockedInfo = task2.blocked_by && task2.blocked_by.length > 0 ?
|
|
5774
|
+
const blockedInfo = task2.blocked_by && task2.blocked_by.length > 0 ? chalk12.yellow(` [Blocked by: ${task2.blocked_by.length}]`) : "";
|
|
5627
5775
|
output += `${childPrefix}${taskPrefix}${task2.number} ${taskStatusEmoji} ${task2.title}${blockedInfo}
|
|
5628
5776
|
`;
|
|
5629
5777
|
}
|
|
@@ -5638,7 +5786,7 @@ function parseProjectId(input2) {
|
|
|
5638
5786
|
}
|
|
5639
5787
|
|
|
5640
5788
|
// src/utils/workspace-manager.ts
|
|
5641
|
-
import
|
|
5789
|
+
import chalk13 from "chalk";
|
|
5642
5790
|
var WorkspaceManager = class {
|
|
5643
5791
|
constructor() {
|
|
5644
5792
|
this.activeRequirementId = null;
|
|
@@ -5672,7 +5820,7 @@ var WorkspaceManager = class {
|
|
|
5672
5820
|
}
|
|
5673
5821
|
return {
|
|
5674
5822
|
success: false,
|
|
5675
|
-
error:
|
|
5823
|
+
error: chalk13.red("\u274C No project specified and no local project found.") + "\n\n" + chalk13.dim("To initialize this workspace, run:\n") + chalk13.cyan(" braingrid init") + "\n\n" + chalk13.dim("Or specify a project explicitly:\n") + chalk13.cyan(" braingrid <command> -p PROJ-123")
|
|
5676
5824
|
};
|
|
5677
5825
|
}
|
|
5678
5826
|
/**
|
|
@@ -5706,9 +5854,9 @@ var WorkspaceManager = class {
|
|
|
5706
5854
|
}
|
|
5707
5855
|
return {
|
|
5708
5856
|
success: false,
|
|
5709
|
-
error:
|
|
5857
|
+
error: chalk13.red("\u274C No requirement specified.") + "\n\n" + chalk13.dim("Unable to auto-detect requirement from branch name.\n") + chalk13.dim("Please provide a requirement ID explicitly:\n") + chalk13.cyan(" braingrid requirement show REQ-123") + "\n" + chalk13.dim(" or\n") + chalk13.cyan(" braingrid task list -r REQ-123") + "\n\n" + chalk13.dim(
|
|
5710
5858
|
"Tip: Name your branch with a requirement ID (e.g., feature/REQ-123-description)\n"
|
|
5711
|
-
) +
|
|
5859
|
+
) + chalk13.dim("to enable auto-detection.")
|
|
5712
5860
|
};
|
|
5713
5861
|
}
|
|
5714
5862
|
/**
|
|
@@ -5767,19 +5915,19 @@ async function handleProjectList(opts) {
|
|
|
5767
5915
|
if (!isAuthenticated) {
|
|
5768
5916
|
return {
|
|
5769
5917
|
success: false,
|
|
5770
|
-
message:
|
|
5918
|
+
message: chalk14.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
5771
5919
|
};
|
|
5772
5920
|
}
|
|
5773
5921
|
const format = opts.format || "table";
|
|
5774
5922
|
if (!["table", "json", "xml", "markdown"].includes(format)) {
|
|
5775
5923
|
return {
|
|
5776
5924
|
success: false,
|
|
5777
|
-
message:
|
|
5925
|
+
message: chalk14.red(
|
|
5778
5926
|
`\u274C Invalid format: ${format}. Supported formats: table, json, xml, markdown`
|
|
5779
5927
|
)
|
|
5780
5928
|
};
|
|
5781
5929
|
}
|
|
5782
|
-
const stop = showSpinner("Loading projects",
|
|
5930
|
+
const stop = showSpinner("Loading projects", chalk14.gray);
|
|
5783
5931
|
try {
|
|
5784
5932
|
const response = await projectService.listProjects({
|
|
5785
5933
|
page: opts.page ? parseInt(opts.page, 10) : 1,
|
|
@@ -5806,11 +5954,11 @@ async function handleProjectList(opts) {
|
|
|
5806
5954
|
if (response.projects.length === 0) {
|
|
5807
5955
|
return {
|
|
5808
5956
|
success: true,
|
|
5809
|
-
message:
|
|
5957
|
+
message: chalk14.yellow("No projects found."),
|
|
5810
5958
|
data: response
|
|
5811
5959
|
};
|
|
5812
5960
|
}
|
|
5813
|
-
output =
|
|
5961
|
+
output = chalk14.bold("\u{1F4CB} Projects\n\n");
|
|
5814
5962
|
output += "ID Short ID Name Created\n";
|
|
5815
5963
|
output += `${"\u2500".repeat(100)}
|
|
5816
5964
|
`;
|
|
@@ -5849,21 +5997,21 @@ async function handleProjectShow(opts) {
|
|
|
5849
5997
|
if (!isAuthenticated) {
|
|
5850
5998
|
return {
|
|
5851
5999
|
success: false,
|
|
5852
|
-
message:
|
|
6000
|
+
message: chalk14.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
5853
6001
|
};
|
|
5854
6002
|
}
|
|
5855
6003
|
const format = opts.format || "table";
|
|
5856
6004
|
if (!["table", "json", "xml", "markdown"].includes(format)) {
|
|
5857
6005
|
return {
|
|
5858
6006
|
success: false,
|
|
5859
|
-
message:
|
|
6007
|
+
message: chalk14.red(
|
|
5860
6008
|
`\u274C Invalid format: ${format}. Supported formats: table, json, xml, markdown`
|
|
5861
6009
|
)
|
|
5862
6010
|
};
|
|
5863
6011
|
}
|
|
5864
6012
|
if (opts.id) {
|
|
5865
6013
|
const normalizedId = parseProjectId(opts.id);
|
|
5866
|
-
const stop2 = showSpinner("Loading project",
|
|
6014
|
+
const stop2 = showSpinner("Loading project", chalk14.gray);
|
|
5867
6015
|
try {
|
|
5868
6016
|
const project2 = await projectService.getProject(normalizedId);
|
|
5869
6017
|
stop2();
|
|
@@ -5882,23 +6030,23 @@ async function handleProjectShow(opts) {
|
|
|
5882
6030
|
break;
|
|
5883
6031
|
}
|
|
5884
6032
|
default: {
|
|
5885
|
-
output =
|
|
6033
|
+
output = chalk14.bold(`
|
|
5886
6034
|
\u{1F4C1} Project: ${project2.name}
|
|
5887
6035
|
|
|
5888
6036
|
`);
|
|
5889
|
-
output += `${
|
|
6037
|
+
output += `${chalk14.bold("ID:")} ${project2.id}
|
|
5890
6038
|
`;
|
|
5891
|
-
output += `${
|
|
6039
|
+
output += `${chalk14.bold("Short ID:")} ${project2.short_id}
|
|
5892
6040
|
`;
|
|
5893
|
-
output += `${
|
|
6041
|
+
output += `${chalk14.bold("Name:")} ${project2.name}
|
|
5894
6042
|
`;
|
|
5895
6043
|
if (project2.description) {
|
|
5896
|
-
output += `${
|
|
6044
|
+
output += `${chalk14.bold("Description:")} ${project2.description}
|
|
5897
6045
|
`;
|
|
5898
6046
|
}
|
|
5899
|
-
output += `${
|
|
6047
|
+
output += `${chalk14.bold("Created:")} ${new Date(project2.created_at).toLocaleString()}
|
|
5900
6048
|
`;
|
|
5901
|
-
output += `${
|
|
6049
|
+
output += `${chalk14.bold("Updated:")} ${new Date(project2.updated_at).toLocaleString()}
|
|
5902
6050
|
`;
|
|
5903
6051
|
break;
|
|
5904
6052
|
}
|
|
@@ -5918,13 +6066,13 @@ async function handleProjectShow(opts) {
|
|
|
5918
6066
|
if (parts.length !== 2) {
|
|
5919
6067
|
return {
|
|
5920
6068
|
success: false,
|
|
5921
|
-
message:
|
|
6069
|
+
message: chalk14.red(
|
|
5922
6070
|
"\u274C Invalid repository format. Use: --repository owner/name (e.g., --repository microsoft/vscode)"
|
|
5923
6071
|
)
|
|
5924
6072
|
};
|
|
5925
6073
|
}
|
|
5926
6074
|
const [repositoryOwner, repositoryName] = parts;
|
|
5927
|
-
const stop2 = showSpinner("Loading projects",
|
|
6075
|
+
const stop2 = showSpinner("Loading projects", chalk14.gray);
|
|
5928
6076
|
try {
|
|
5929
6077
|
const response = await projectService.listProjects({
|
|
5930
6078
|
repository_owner: repositoryOwner,
|
|
@@ -5950,14 +6098,14 @@ async function handleProjectShow(opts) {
|
|
|
5950
6098
|
break;
|
|
5951
6099
|
}
|
|
5952
6100
|
default: {
|
|
5953
|
-
const repoDisplay =
|
|
6101
|
+
const repoDisplay = chalk14.cyan(`${repositoryOwner}/${repositoryName}`);
|
|
5954
6102
|
if (response.projects.length === 0) {
|
|
5955
6103
|
return {
|
|
5956
6104
|
success: true,
|
|
5957
|
-
message:
|
|
6105
|
+
message: chalk14.yellow(`No projects found for repository ${repoDisplay}`)
|
|
5958
6106
|
};
|
|
5959
6107
|
}
|
|
5960
|
-
output =
|
|
6108
|
+
output = chalk14.bold(`\u{1F4CB} Projects for ${repoDisplay}
|
|
5961
6109
|
|
|
5962
6110
|
`);
|
|
5963
6111
|
output += "ID Short ID Name Created\n";
|
|
@@ -5992,7 +6140,7 @@ async function handleProjectShow(opts) {
|
|
|
5992
6140
|
message: workspace.error
|
|
5993
6141
|
};
|
|
5994
6142
|
}
|
|
5995
|
-
const stop = showSpinner("Loading project",
|
|
6143
|
+
const stop = showSpinner("Loading project", chalk14.gray);
|
|
5996
6144
|
try {
|
|
5997
6145
|
const project2 = await projectService.getProject(workspace.projectId);
|
|
5998
6146
|
stop();
|
|
@@ -6011,23 +6159,23 @@ async function handleProjectShow(opts) {
|
|
|
6011
6159
|
break;
|
|
6012
6160
|
}
|
|
6013
6161
|
default: {
|
|
6014
|
-
output =
|
|
6162
|
+
output = chalk14.bold(`
|
|
6015
6163
|
\u{1F4C1} Project: ${project2.name}
|
|
6016
6164
|
|
|
6017
6165
|
`);
|
|
6018
|
-
output += `${
|
|
6166
|
+
output += `${chalk14.bold("ID:")} ${project2.id}
|
|
6019
6167
|
`;
|
|
6020
|
-
output += `${
|
|
6168
|
+
output += `${chalk14.bold("Short ID:")} ${project2.short_id}
|
|
6021
6169
|
`;
|
|
6022
|
-
output += `${
|
|
6170
|
+
output += `${chalk14.bold("Name:")} ${project2.name}
|
|
6023
6171
|
`;
|
|
6024
6172
|
if (project2.description) {
|
|
6025
|
-
output += `${
|
|
6173
|
+
output += `${chalk14.bold("Description:")} ${project2.description}
|
|
6026
6174
|
`;
|
|
6027
6175
|
}
|
|
6028
|
-
output += `${
|
|
6176
|
+
output += `${chalk14.bold("Created:")} ${new Date(project2.created_at).toLocaleString()}
|
|
6029
6177
|
`;
|
|
6030
|
-
output += `${
|
|
6178
|
+
output += `${chalk14.bold("Updated:")} ${new Date(project2.updated_at).toLocaleString()}
|
|
6031
6179
|
`;
|
|
6032
6180
|
break;
|
|
6033
6181
|
}
|
|
@@ -6055,7 +6203,7 @@ async function handleProjectCreate(opts) {
|
|
|
6055
6203
|
if (!isAuthenticated) {
|
|
6056
6204
|
return {
|
|
6057
6205
|
success: false,
|
|
6058
|
-
message:
|
|
6206
|
+
message: chalk14.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
6059
6207
|
};
|
|
6060
6208
|
}
|
|
6061
6209
|
let repositoryId;
|
|
@@ -6066,21 +6214,21 @@ async function handleProjectCreate(opts) {
|
|
|
6066
6214
|
if (parts.length !== 2) {
|
|
6067
6215
|
return {
|
|
6068
6216
|
success: false,
|
|
6069
|
-
message:
|
|
6217
|
+
message: chalk14.red(
|
|
6070
6218
|
"\u274C Invalid repository format. Use: --repository owner/name (e.g., microsoft/vscode)"
|
|
6071
6219
|
)
|
|
6072
6220
|
};
|
|
6073
6221
|
}
|
|
6074
6222
|
const [owner, name] = parts;
|
|
6075
6223
|
const repositoryService = new RepositoryService(config2.apiUrl, auth);
|
|
6076
|
-
const stop2 = showSpinner(`Looking up repository ${opts.repository}`,
|
|
6224
|
+
const stop2 = showSpinner(`Looking up repository ${opts.repository}`, chalk14.gray);
|
|
6077
6225
|
try {
|
|
6078
6226
|
const repoId = await getRepositoryId(repositoryService, owner, name);
|
|
6079
6227
|
stop2();
|
|
6080
6228
|
if (!repoId) {
|
|
6081
6229
|
return {
|
|
6082
6230
|
success: false,
|
|
6083
|
-
message:
|
|
6231
|
+
message: chalk14.red(
|
|
6084
6232
|
`\u274C Repository '${opts.repository}' not found. Please check the name or ensure you have access.`
|
|
6085
6233
|
)
|
|
6086
6234
|
};
|
|
@@ -6090,7 +6238,7 @@ async function handleProjectCreate(opts) {
|
|
|
6090
6238
|
stop2();
|
|
6091
6239
|
}
|
|
6092
6240
|
}
|
|
6093
|
-
const stop = showSpinner("Creating project",
|
|
6241
|
+
const stop = showSpinner("Creating project", chalk14.gray);
|
|
6094
6242
|
try {
|
|
6095
6243
|
const project2 = await projectService.createProject({
|
|
6096
6244
|
name: opts.name,
|
|
@@ -6098,9 +6246,9 @@ async function handleProjectCreate(opts) {
|
|
|
6098
6246
|
repository_id: repositoryId
|
|
6099
6247
|
});
|
|
6100
6248
|
stop();
|
|
6101
|
-
let message =
|
|
6249
|
+
let message = chalk14.green(`\u2705 Created project ${project2.short_id}: ${project2.name}`);
|
|
6102
6250
|
if (opts.repository && repositoryId) {
|
|
6103
|
-
message +=
|
|
6251
|
+
message += chalk14.gray(` (linked to ${opts.repository})`);
|
|
6104
6252
|
}
|
|
6105
6253
|
return {
|
|
6106
6254
|
success: true,
|
|
@@ -6124,19 +6272,19 @@ async function handleProjectUpdate(id, opts) {
|
|
|
6124
6272
|
if (!isAuthenticated) {
|
|
6125
6273
|
return {
|
|
6126
6274
|
success: false,
|
|
6127
|
-
message:
|
|
6275
|
+
message: chalk14.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
6128
6276
|
};
|
|
6129
6277
|
}
|
|
6130
6278
|
if (!opts.name && !opts.description) {
|
|
6131
6279
|
return {
|
|
6132
6280
|
success: false,
|
|
6133
|
-
message:
|
|
6281
|
+
message: chalk14.red(
|
|
6134
6282
|
"\u274C Please provide at least one field to update (--name or --description)"
|
|
6135
6283
|
)
|
|
6136
6284
|
};
|
|
6137
6285
|
}
|
|
6138
6286
|
const normalizedId = parseProjectId(id);
|
|
6139
|
-
const stop = showSpinner("Updating project",
|
|
6287
|
+
const stop = showSpinner("Updating project", chalk14.gray);
|
|
6140
6288
|
try {
|
|
6141
6289
|
const project2 = await projectService.updateProject(normalizedId, {
|
|
6142
6290
|
name: opts.name,
|
|
@@ -6145,7 +6293,7 @@ async function handleProjectUpdate(id, opts) {
|
|
|
6145
6293
|
stop();
|
|
6146
6294
|
return {
|
|
6147
6295
|
success: true,
|
|
6148
|
-
message:
|
|
6296
|
+
message: chalk14.green(`\u2705 Updated project ${project2.short_id}: ${project2.name}`),
|
|
6149
6297
|
data: project2
|
|
6150
6298
|
};
|
|
6151
6299
|
} finally {
|
|
@@ -6165,25 +6313,25 @@ async function handleProjectDelete(id, opts) {
|
|
|
6165
6313
|
if (!isAuthenticated) {
|
|
6166
6314
|
return {
|
|
6167
6315
|
success: false,
|
|
6168
|
-
message:
|
|
6316
|
+
message: chalk14.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
6169
6317
|
};
|
|
6170
6318
|
}
|
|
6171
6319
|
if (!opts.force) {
|
|
6172
6320
|
return {
|
|
6173
6321
|
success: false,
|
|
6174
|
-
message:
|
|
6322
|
+
message: chalk14.yellow(
|
|
6175
6323
|
"\u26A0\uFE0F Deleting a project is permanent. Use --force to confirm deletion."
|
|
6176
6324
|
)
|
|
6177
6325
|
};
|
|
6178
6326
|
}
|
|
6179
6327
|
const normalizedId = parseProjectId(id);
|
|
6180
|
-
const stop = showSpinner("Deleting project",
|
|
6328
|
+
const stop = showSpinner("Deleting project", chalk14.gray);
|
|
6181
6329
|
try {
|
|
6182
6330
|
await projectService.deleteProject(normalizedId);
|
|
6183
6331
|
stop();
|
|
6184
6332
|
return {
|
|
6185
6333
|
success: true,
|
|
6186
|
-
message:
|
|
6334
|
+
message: chalk14.green(`\u2705 Deleted project ${id}`)
|
|
6187
6335
|
};
|
|
6188
6336
|
} finally {
|
|
6189
6337
|
stop();
|
|
@@ -6197,7 +6345,7 @@ async function handleProjectDelete(id, opts) {
|
|
|
6197
6345
|
}
|
|
6198
6346
|
|
|
6199
6347
|
// src/handlers/requirement.handlers.ts
|
|
6200
|
-
import
|
|
6348
|
+
import chalk15 from "chalk";
|
|
6201
6349
|
|
|
6202
6350
|
// src/services/requirement-service.ts
|
|
6203
6351
|
var RequirementService = class {
|
|
@@ -6347,14 +6495,14 @@ async function handleRequirementList(opts) {
|
|
|
6347
6495
|
if (!isAuthenticated) {
|
|
6348
6496
|
return {
|
|
6349
6497
|
success: false,
|
|
6350
|
-
message:
|
|
6498
|
+
message: chalk15.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
6351
6499
|
};
|
|
6352
6500
|
}
|
|
6353
6501
|
const format = opts.format || "table";
|
|
6354
6502
|
if (!opts.tree && !["table", "json", "xml", "markdown"].includes(format)) {
|
|
6355
6503
|
return {
|
|
6356
6504
|
success: false,
|
|
6357
|
-
message:
|
|
6505
|
+
message: chalk15.red(
|
|
6358
6506
|
`\u274C Invalid format: ${format}. Supported formats: table, json, xml, markdown`
|
|
6359
6507
|
)
|
|
6360
6508
|
};
|
|
@@ -6367,7 +6515,7 @@ async function handleRequirementList(opts) {
|
|
|
6367
6515
|
};
|
|
6368
6516
|
}
|
|
6369
6517
|
const projectId = workspace.projectId;
|
|
6370
|
-
stopSpinner = showSpinner("Loading requirements",
|
|
6518
|
+
stopSpinner = showSpinner("Loading requirements", chalk15.gray);
|
|
6371
6519
|
const response = await requirementService.listProjectRequirements(projectId, {
|
|
6372
6520
|
status: opts.status,
|
|
6373
6521
|
page: opts.page ? parseInt(opts.page, 10) : 1,
|
|
@@ -6379,10 +6527,10 @@ async function handleRequirementList(opts) {
|
|
|
6379
6527
|
if (response.requirements.length === 0) {
|
|
6380
6528
|
return {
|
|
6381
6529
|
success: true,
|
|
6382
|
-
message:
|
|
6530
|
+
message: chalk15.yellow("No requirements found.")
|
|
6383
6531
|
};
|
|
6384
6532
|
}
|
|
6385
|
-
stopSpinner = showSpinner("Loading tasks for tree view",
|
|
6533
|
+
stopSpinner = showSpinner("Loading tasks for tree view", chalk15.gray);
|
|
6386
6534
|
const tasksMap = /* @__PURE__ */ new Map();
|
|
6387
6535
|
const taskPromises = response.requirements.map(async (req) => {
|
|
6388
6536
|
try {
|
|
@@ -6405,7 +6553,7 @@ Page ${response.pagination.page} of ${Math.ceil(response.pagination.total / resp
|
|
|
6405
6553
|
finalOutput += ` (${response.pagination.total} total)`;
|
|
6406
6554
|
if (response.pagination?.has_more) {
|
|
6407
6555
|
finalOutput += `
|
|
6408
|
-
${
|
|
6556
|
+
${chalk15.yellow("\u26A0\uFE0F More requirements exist. Use --limit to see more.")}`;
|
|
6409
6557
|
}
|
|
6410
6558
|
return {
|
|
6411
6559
|
success: true,
|
|
@@ -6431,10 +6579,10 @@ ${chalk14.yellow("\u26A0\uFE0F More requirements exist. Use --limit to see more.
|
|
|
6431
6579
|
if (response.requirements.length === 0) {
|
|
6432
6580
|
return {
|
|
6433
6581
|
success: true,
|
|
6434
|
-
message:
|
|
6582
|
+
message: chalk15.yellow("No requirements found.")
|
|
6435
6583
|
};
|
|
6436
6584
|
}
|
|
6437
|
-
output =
|
|
6585
|
+
output = chalk15.bold("\u{1F4CB} Requirements\n\n");
|
|
6438
6586
|
output += "Short ID Status Name Branch Progress\n";
|
|
6439
6587
|
output += `${"\u2500".repeat(90)}
|
|
6440
6588
|
`;
|
|
@@ -6456,7 +6604,7 @@ ${chalk14.yellow("\u26A0\uFE0F More requirements exist. Use --limit to see more.
|
|
|
6456
6604
|
}
|
|
6457
6605
|
if (response.pagination?.has_more) {
|
|
6458
6606
|
output += `
|
|
6459
|
-
${
|
|
6607
|
+
${chalk15.yellow("\u26A0\uFE0F More requirements exist. Use --limit to see more.")}`;
|
|
6460
6608
|
}
|
|
6461
6609
|
return {
|
|
6462
6610
|
success: true,
|
|
@@ -6481,14 +6629,14 @@ async function handleRequirementShow(opts) {
|
|
|
6481
6629
|
if (!isAuthenticated) {
|
|
6482
6630
|
return {
|
|
6483
6631
|
success: false,
|
|
6484
|
-
message:
|
|
6632
|
+
message: chalk15.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
6485
6633
|
};
|
|
6486
6634
|
}
|
|
6487
6635
|
const format = opts?.format || "table";
|
|
6488
6636
|
if (!["table", "json", "xml", "markdown"].includes(format)) {
|
|
6489
6637
|
return {
|
|
6490
6638
|
success: false,
|
|
6491
|
-
message:
|
|
6639
|
+
message: chalk15.red(
|
|
6492
6640
|
`\u274C Invalid format: ${format}. Supported formats: table, json, xml, markdown`
|
|
6493
6641
|
)
|
|
6494
6642
|
};
|
|
@@ -6510,7 +6658,7 @@ async function handleRequirementShow(opts) {
|
|
|
6510
6658
|
}
|
|
6511
6659
|
const projectId = workspace.projectId;
|
|
6512
6660
|
const normalizedId = normalizeRequirementId(requirementId);
|
|
6513
|
-
stopSpinner = showSpinner("Loading requirement",
|
|
6661
|
+
stopSpinner = showSpinner("Loading requirement", chalk15.gray);
|
|
6514
6662
|
const requirement2 = await requirementService.getProjectRequirement(projectId, normalizedId);
|
|
6515
6663
|
stopSpinner();
|
|
6516
6664
|
stopSpinner = null;
|
|
@@ -6566,7 +6714,7 @@ async function handleRequirementCreate(opts) {
|
|
|
6566
6714
|
if (!isAuthenticated) {
|
|
6567
6715
|
return {
|
|
6568
6716
|
success: false,
|
|
6569
|
-
message:
|
|
6717
|
+
message: chalk15.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
6570
6718
|
};
|
|
6571
6719
|
}
|
|
6572
6720
|
const workspace = await workspaceManager.getProject(opts.project);
|
|
@@ -6583,7 +6731,7 @@ async function handleRequirementCreate(opts) {
|
|
|
6583
6731
|
if (emailRegex.test(opts.assignedTo)) {
|
|
6584
6732
|
return {
|
|
6585
6733
|
success: false,
|
|
6586
|
-
message:
|
|
6734
|
+
message: chalk15.red(
|
|
6587
6735
|
"\u274C Email addresses are not supported for --assigned-to yet.\nPlease use the user UUID instead.\nEmail lookup will be supported when the API provides a user lookup endpoint."
|
|
6588
6736
|
)
|
|
6589
6737
|
};
|
|
@@ -6591,7 +6739,7 @@ async function handleRequirementCreate(opts) {
|
|
|
6591
6739
|
if (!uuidRegex.test(opts.assignedTo)) {
|
|
6592
6740
|
return {
|
|
6593
6741
|
success: false,
|
|
6594
|
-
message:
|
|
6742
|
+
message: chalk15.red(
|
|
6595
6743
|
'\u274C Invalid UUID format for --assigned-to.\nPlease provide a valid user UUID (e.g., "550e8400-e29b-41d4-a716-446655440000")'
|
|
6596
6744
|
)
|
|
6597
6745
|
};
|
|
@@ -6603,12 +6751,12 @@ async function handleRequirementCreate(opts) {
|
|
|
6603
6751
|
if (!tagResult.valid) {
|
|
6604
6752
|
return {
|
|
6605
6753
|
success: false,
|
|
6606
|
-
message:
|
|
6754
|
+
message: chalk15.red(`\u274C ${tagResult.error}`)
|
|
6607
6755
|
};
|
|
6608
6756
|
}
|
|
6609
6757
|
validatedTags = tagResult.tags;
|
|
6610
6758
|
}
|
|
6611
|
-
stopSpinner = showSpinner("Creating requirement",
|
|
6759
|
+
stopSpinner = showSpinner("Creating requirement", chalk15.gray);
|
|
6612
6760
|
const requirement2 = await requirementService.createProjectRequirement(projectId, {
|
|
6613
6761
|
name: opts.name,
|
|
6614
6762
|
content: opts.content || null,
|
|
@@ -6642,7 +6790,7 @@ async function handleRequirementCreate(opts) {
|
|
|
6642
6790
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
6643
6791
|
return {
|
|
6644
6792
|
success: false,
|
|
6645
|
-
message:
|
|
6793
|
+
message: chalk15.red(`\u274C Error creating requirement: ${errorMessage}`)
|
|
6646
6794
|
};
|
|
6647
6795
|
}
|
|
6648
6796
|
}
|
|
@@ -6654,14 +6802,14 @@ async function handleRequirementSpecify(opts) {
|
|
|
6654
6802
|
if (!isAuthenticated) {
|
|
6655
6803
|
return {
|
|
6656
6804
|
success: false,
|
|
6657
|
-
message:
|
|
6805
|
+
message: chalk15.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
6658
6806
|
};
|
|
6659
6807
|
}
|
|
6660
6808
|
const format = opts.format || "table";
|
|
6661
6809
|
if (!["table", "json", "xml", "markdown"].includes(format)) {
|
|
6662
6810
|
return {
|
|
6663
6811
|
success: false,
|
|
6664
|
-
message:
|
|
6812
|
+
message: chalk15.red(
|
|
6665
6813
|
`\u274C Invalid format: ${format}. Supported formats: table, json, xml, markdown`
|
|
6666
6814
|
)
|
|
6667
6815
|
};
|
|
@@ -6677,13 +6825,13 @@ async function handleRequirementSpecify(opts) {
|
|
|
6677
6825
|
if (opts.prompt.length < 10) {
|
|
6678
6826
|
return {
|
|
6679
6827
|
success: false,
|
|
6680
|
-
message:
|
|
6828
|
+
message: chalk15.red("\u274C Prompt must be at least 10 characters long")
|
|
6681
6829
|
};
|
|
6682
6830
|
}
|
|
6683
6831
|
if (opts.prompt.length > 5e3) {
|
|
6684
6832
|
return {
|
|
6685
6833
|
success: false,
|
|
6686
|
-
message:
|
|
6834
|
+
message: chalk15.red("\u274C Prompt must be no more than 5000 characters long")
|
|
6687
6835
|
};
|
|
6688
6836
|
}
|
|
6689
6837
|
let validatedTags;
|
|
@@ -6692,7 +6840,7 @@ async function handleRequirementSpecify(opts) {
|
|
|
6692
6840
|
if (!tagResult.valid) {
|
|
6693
6841
|
return {
|
|
6694
6842
|
success: false,
|
|
6695
|
-
message:
|
|
6843
|
+
message: chalk15.red(`\u274C ${tagResult.error}`)
|
|
6696
6844
|
};
|
|
6697
6845
|
}
|
|
6698
6846
|
validatedTags = tagResult.tags;
|
|
@@ -6755,13 +6903,13 @@ async function handleRequirementUpdate(opts) {
|
|
|
6755
6903
|
if (!isAuthenticated) {
|
|
6756
6904
|
return {
|
|
6757
6905
|
success: false,
|
|
6758
|
-
message:
|
|
6906
|
+
message: chalk15.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
6759
6907
|
};
|
|
6760
6908
|
}
|
|
6761
6909
|
if (!opts.status && !opts.name && !opts.content) {
|
|
6762
6910
|
return {
|
|
6763
6911
|
success: false,
|
|
6764
|
-
message:
|
|
6912
|
+
message: chalk15.red(
|
|
6765
6913
|
"\u274C Please provide at least one field to update (--status, --name, or --content)"
|
|
6766
6914
|
)
|
|
6767
6915
|
};
|
|
@@ -6783,7 +6931,7 @@ async function handleRequirementUpdate(opts) {
|
|
|
6783
6931
|
}
|
|
6784
6932
|
const projectId = workspace.projectId;
|
|
6785
6933
|
const normalizedId = normalizeRequirementId(requirementId);
|
|
6786
|
-
stopSpinner = showSpinner("Updating requirement",
|
|
6934
|
+
stopSpinner = showSpinner("Updating requirement", chalk15.gray);
|
|
6787
6935
|
const requirement2 = await requirementService.updateProjectRequirement(projectId, normalizedId, {
|
|
6788
6936
|
status: opts.status,
|
|
6789
6937
|
name: opts.name,
|
|
@@ -6793,7 +6941,7 @@ async function handleRequirementUpdate(opts) {
|
|
|
6793
6941
|
stopSpinner = null;
|
|
6794
6942
|
return {
|
|
6795
6943
|
success: true,
|
|
6796
|
-
message:
|
|
6944
|
+
message: chalk15.green(`\u2705 Updated requirement ${requirement2.short_id}: ${requirement2.name}`),
|
|
6797
6945
|
data: requirement2
|
|
6798
6946
|
};
|
|
6799
6947
|
} catch (error) {
|
|
@@ -6814,13 +6962,13 @@ async function handleRequirementDelete(opts) {
|
|
|
6814
6962
|
if (!isAuthenticated) {
|
|
6815
6963
|
return {
|
|
6816
6964
|
success: false,
|
|
6817
|
-
message:
|
|
6965
|
+
message: chalk15.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
6818
6966
|
};
|
|
6819
6967
|
}
|
|
6820
6968
|
if (!opts.force) {
|
|
6821
6969
|
return {
|
|
6822
6970
|
success: false,
|
|
6823
|
-
message:
|
|
6971
|
+
message: chalk15.yellow(
|
|
6824
6972
|
"\u26A0\uFE0F Deleting a requirement is permanent. Use --force to confirm deletion."
|
|
6825
6973
|
)
|
|
6826
6974
|
};
|
|
@@ -6842,13 +6990,13 @@ async function handleRequirementDelete(opts) {
|
|
|
6842
6990
|
}
|
|
6843
6991
|
const projectId = workspace.projectId;
|
|
6844
6992
|
const normalizedId = normalizeRequirementId(requirementId);
|
|
6845
|
-
stopSpinner = showSpinner("Deleting requirement",
|
|
6993
|
+
stopSpinner = showSpinner("Deleting requirement", chalk15.gray);
|
|
6846
6994
|
await requirementService.deleteProjectRequirement(projectId, normalizedId);
|
|
6847
6995
|
stopSpinner();
|
|
6848
6996
|
stopSpinner = null;
|
|
6849
6997
|
return {
|
|
6850
6998
|
success: true,
|
|
6851
|
-
message:
|
|
6999
|
+
message: chalk15.green(`\u2705 Deleted requirement ${requirementId}`)
|
|
6852
7000
|
};
|
|
6853
7001
|
} catch (error) {
|
|
6854
7002
|
if (stopSpinner) {
|
|
@@ -6868,14 +7016,14 @@ async function handleRequirementBreakdown(opts) {
|
|
|
6868
7016
|
if (!isAuthenticated) {
|
|
6869
7017
|
return {
|
|
6870
7018
|
success: false,
|
|
6871
|
-
message:
|
|
7019
|
+
message: chalk15.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
6872
7020
|
};
|
|
6873
7021
|
}
|
|
6874
7022
|
const format = opts.format || "table";
|
|
6875
7023
|
if (!["table", "json", "xml", "markdown"].includes(format)) {
|
|
6876
7024
|
return {
|
|
6877
7025
|
success: false,
|
|
6878
|
-
message:
|
|
7026
|
+
message: chalk15.red(
|
|
6879
7027
|
`\u274C Invalid format: ${format}. Supported formats: table, json, xml, markdown`
|
|
6880
7028
|
)
|
|
6881
7029
|
};
|
|
@@ -6897,7 +7045,7 @@ async function handleRequirementBreakdown(opts) {
|
|
|
6897
7045
|
}
|
|
6898
7046
|
const projectId = workspace.projectId;
|
|
6899
7047
|
const normalizedId = normalizeRequirementId(requirementId);
|
|
6900
|
-
stop = showSpinner("Checking requirement...",
|
|
7048
|
+
stop = showSpinner("Checking requirement...", chalk15.gray);
|
|
6901
7049
|
const requirement2 = await requirementService.getProjectRequirement(projectId, normalizedId);
|
|
6902
7050
|
stop();
|
|
6903
7051
|
const taskCount = requirement2.tasks?.length ?? requirement2.task_progress?.total ?? 0;
|
|
@@ -6905,13 +7053,13 @@ async function handleRequirementBreakdown(opts) {
|
|
|
6905
7053
|
const shortId = requirement2.short_id || normalizedId;
|
|
6906
7054
|
return {
|
|
6907
7055
|
success: false,
|
|
6908
|
-
message:
|
|
7056
|
+
message: chalk15.red(
|
|
6909
7057
|
`\u274C Cannot breakdown requirement ${shortId} - it already has ${taskCount} task(s)
|
|
6910
7058
|
|
|
6911
7059
|
`
|
|
6912
|
-
) + "The breakdown command is only for initial task generation from requirements.\nOnce tasks exist, you should manage them individually.\n\n" +
|
|
7060
|
+
) + "The breakdown command is only for initial task generation from requirements.\nOnce tasks exist, you should manage them individually.\n\n" + chalk15.bold("To add more tasks to this requirement:\n") + chalk15.cyan(` braingrid task create -r ${shortId} --title "Task title"
|
|
6913
7061
|
|
|
6914
|
-
`) +
|
|
7062
|
+
`) + chalk15.bold("To view existing tasks:\n") + chalk15.cyan(` braingrid task list -r ${shortId}`)
|
|
6915
7063
|
};
|
|
6916
7064
|
}
|
|
6917
7065
|
stop = showSpinner("Breaking down requirement into tasks...");
|
|
@@ -6932,7 +7080,7 @@ async function handleRequirementBreakdown(opts) {
|
|
|
6932
7080
|
break;
|
|
6933
7081
|
}
|
|
6934
7082
|
default: {
|
|
6935
|
-
output =
|
|
7083
|
+
output = chalk15.green(
|
|
6936
7084
|
`\u2705 Generated ${response.tasks.length} tasks for ${response.requirement_short_id}
|
|
6937
7085
|
|
|
6938
7086
|
`
|
|
@@ -6970,7 +7118,7 @@ async function handleRequirementBreakdown(opts) {
|
|
|
6970
7118
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
6971
7119
|
return {
|
|
6972
7120
|
success: false,
|
|
6973
|
-
message:
|
|
7121
|
+
message: chalk15.red(`\u274C Error breaking down requirement: ${errorMessage}`)
|
|
6974
7122
|
};
|
|
6975
7123
|
}
|
|
6976
7124
|
}
|
|
@@ -6982,14 +7130,14 @@ async function handleRequirementBuild(opts) {
|
|
|
6982
7130
|
if (!isAuthenticated) {
|
|
6983
7131
|
return {
|
|
6984
7132
|
success: false,
|
|
6985
|
-
message:
|
|
7133
|
+
message: chalk15.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
6986
7134
|
};
|
|
6987
7135
|
}
|
|
6988
7136
|
const format = opts.format || "markdown";
|
|
6989
7137
|
if (!["markdown", "json", "xml"].includes(format)) {
|
|
6990
7138
|
return {
|
|
6991
7139
|
success: false,
|
|
6992
|
-
message:
|
|
7140
|
+
message: chalk15.red("\u274C Invalid format. Must be one of: markdown, json, xml")
|
|
6993
7141
|
};
|
|
6994
7142
|
}
|
|
6995
7143
|
const requirementResult = await workspaceManager.getRequirement(opts.id);
|
|
@@ -7009,7 +7157,7 @@ async function handleRequirementBuild(opts) {
|
|
|
7009
7157
|
}
|
|
7010
7158
|
const projectId = workspace.projectId;
|
|
7011
7159
|
const normalizedId = normalizeRequirementId(requirementId);
|
|
7012
|
-
stopSpinner = showSpinner("Building requirement with tasks",
|
|
7160
|
+
stopSpinner = showSpinner("Building requirement with tasks", chalk15.gray);
|
|
7013
7161
|
const requirement2 = await requirementService.getProjectRequirement(projectId, normalizedId);
|
|
7014
7162
|
stopSpinner();
|
|
7015
7163
|
stopSpinner = null;
|
|
@@ -7057,14 +7205,14 @@ async function handleCreateGitBranch(opts) {
|
|
|
7057
7205
|
if (!isAuthenticated) {
|
|
7058
7206
|
return {
|
|
7059
7207
|
success: false,
|
|
7060
|
-
message:
|
|
7208
|
+
message: chalk15.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
7061
7209
|
};
|
|
7062
7210
|
}
|
|
7063
7211
|
const format = opts.format || "table";
|
|
7064
7212
|
if (!["table", "json", "markdown"].includes(format)) {
|
|
7065
7213
|
return {
|
|
7066
7214
|
success: false,
|
|
7067
|
-
message:
|
|
7215
|
+
message: chalk15.red(
|
|
7068
7216
|
`\u274C Invalid format: ${format}. Supported formats: table, json, markdown`
|
|
7069
7217
|
)
|
|
7070
7218
|
};
|
|
@@ -7092,7 +7240,7 @@ async function handleCreateGitBranch(opts) {
|
|
|
7092
7240
|
if (!user) {
|
|
7093
7241
|
return {
|
|
7094
7242
|
success: false,
|
|
7095
|
-
message:
|
|
7243
|
+
message: chalk15.red("\u274C Could not get current user for branch name generation")
|
|
7096
7244
|
};
|
|
7097
7245
|
}
|
|
7098
7246
|
const requirement2 = await requirementService.getProjectRequirement(projectId, normalizedId);
|
|
@@ -7101,7 +7249,7 @@ async function handleCreateGitBranch(opts) {
|
|
|
7101
7249
|
const sluggedName = slugify(requirement2.name);
|
|
7102
7250
|
branchName = `${username}/${reqShortId}-${sluggedName}`;
|
|
7103
7251
|
}
|
|
7104
|
-
stopSpinner = showSpinner("Creating GitHub branch...",
|
|
7252
|
+
stopSpinner = showSpinner("Creating GitHub branch...", chalk15.gray);
|
|
7105
7253
|
const response = await requirementService.createGitBranch(projectId, normalizedId, {
|
|
7106
7254
|
branchName,
|
|
7107
7255
|
baseBranch: opts.base
|
|
@@ -7133,13 +7281,13 @@ git fetch origin && git checkout ${response.branch.name}
|
|
|
7133
7281
|
break;
|
|
7134
7282
|
}
|
|
7135
7283
|
default: {
|
|
7136
|
-
output =
|
|
7284
|
+
output = chalk15.green(`\u2705 Created branch: ${response.branch.name}
|
|
7137
7285
|
|
|
7138
7286
|
`);
|
|
7139
|
-
output += `${
|
|
7287
|
+
output += `${chalk15.bold("SHA:")} ${response.branch.sha.substring(0, 7)}
|
|
7140
7288
|
`;
|
|
7141
7289
|
output += `
|
|
7142
|
-
${
|
|
7290
|
+
${chalk15.dim("To checkout:")} git fetch origin && git checkout ${response.branch.name}`;
|
|
7143
7291
|
break;
|
|
7144
7292
|
}
|
|
7145
7293
|
}
|
|
@@ -7165,7 +7313,7 @@ async function handleReviewAcceptance(opts) {
|
|
|
7165
7313
|
if (!isAuthenticated) {
|
|
7166
7314
|
return {
|
|
7167
7315
|
success: false,
|
|
7168
|
-
message:
|
|
7316
|
+
message: chalk15.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
7169
7317
|
};
|
|
7170
7318
|
}
|
|
7171
7319
|
const requirementResult = await workspaceManager.getRequirement(opts.id);
|
|
@@ -7198,13 +7346,13 @@ async function handleReviewAcceptance(opts) {
|
|
|
7198
7346
|
} catch {
|
|
7199
7347
|
return {
|
|
7200
7348
|
success: false,
|
|
7201
|
-
message:
|
|
7349
|
+
message: chalk15.red(
|
|
7202
7350
|
"\u274C No PR specified and could not detect PR for current branch.\n Use --pr <number> or ensure you have an open PR for this branch."
|
|
7203
7351
|
)
|
|
7204
7352
|
};
|
|
7205
7353
|
}
|
|
7206
7354
|
}
|
|
7207
|
-
console.log(
|
|
7355
|
+
console.log(chalk15.bold("\n\u{1F50D} AI Code Review\n"));
|
|
7208
7356
|
let fullOutput = "";
|
|
7209
7357
|
await requirementService.reviewAcceptance(
|
|
7210
7358
|
projectId,
|
|
@@ -7237,14 +7385,14 @@ async function handleRequirementTagList(opts) {
|
|
|
7237
7385
|
if (!isAuthenticated) {
|
|
7238
7386
|
return {
|
|
7239
7387
|
success: false,
|
|
7240
|
-
message:
|
|
7388
|
+
message: chalk15.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
7241
7389
|
};
|
|
7242
7390
|
}
|
|
7243
7391
|
const format = opts.format || "table";
|
|
7244
7392
|
if (!["table", "json", "xml", "markdown"].includes(format)) {
|
|
7245
7393
|
return {
|
|
7246
7394
|
success: false,
|
|
7247
|
-
message:
|
|
7395
|
+
message: chalk15.red(
|
|
7248
7396
|
`\u274C Invalid format: ${format}. Supported formats: table, json, xml, markdown`
|
|
7249
7397
|
)
|
|
7250
7398
|
};
|
|
@@ -7266,7 +7414,7 @@ async function handleRequirementTagList(opts) {
|
|
|
7266
7414
|
}
|
|
7267
7415
|
const projectId = workspace.projectId;
|
|
7268
7416
|
const normalizedId = normalizeRequirementId(requirementId);
|
|
7269
|
-
stopSpinner = showSpinner("Loading tags",
|
|
7417
|
+
stopSpinner = showSpinner("Loading tags", chalk15.gray);
|
|
7270
7418
|
const tags = await requirementService.listRequirementTags(projectId, normalizedId);
|
|
7271
7419
|
stopSpinner();
|
|
7272
7420
|
stopSpinner = null;
|
|
@@ -7313,11 +7461,11 @@ async function handleRequirementTagList(opts) {
|
|
|
7313
7461
|
if (tags.length === 0) {
|
|
7314
7462
|
return {
|
|
7315
7463
|
success: true,
|
|
7316
|
-
message:
|
|
7464
|
+
message: chalk15.yellow(`No tags found for ${normalizedId}.`),
|
|
7317
7465
|
data: tags
|
|
7318
7466
|
};
|
|
7319
7467
|
}
|
|
7320
|
-
output =
|
|
7468
|
+
output = chalk15.bold(`\u{1F3F7}\uFE0F Tags for ${normalizedId}
|
|
7321
7469
|
|
|
7322
7470
|
`);
|
|
7323
7471
|
output += "Name Color\n";
|
|
@@ -7358,20 +7506,20 @@ async function handleRequirementTagAdd(opts) {
|
|
|
7358
7506
|
if (!isAuthenticated) {
|
|
7359
7507
|
return {
|
|
7360
7508
|
success: false,
|
|
7361
|
-
message:
|
|
7509
|
+
message: chalk15.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
7362
7510
|
};
|
|
7363
7511
|
}
|
|
7364
7512
|
if (!opts.name || opts.name.trim().length === 0) {
|
|
7365
7513
|
return {
|
|
7366
7514
|
success: false,
|
|
7367
|
-
message:
|
|
7515
|
+
message: chalk15.red("\u274C Tag name is required")
|
|
7368
7516
|
};
|
|
7369
7517
|
}
|
|
7370
7518
|
const colorResult = validateHexColor(opts.color);
|
|
7371
7519
|
if (!colorResult.valid) {
|
|
7372
7520
|
return {
|
|
7373
7521
|
success: false,
|
|
7374
|
-
message:
|
|
7522
|
+
message: chalk15.red(`\u274C ${colorResult.error}`)
|
|
7375
7523
|
};
|
|
7376
7524
|
}
|
|
7377
7525
|
const requirementResult = await workspaceManager.getRequirement(opts.requirementId);
|
|
@@ -7391,7 +7539,7 @@ async function handleRequirementTagAdd(opts) {
|
|
|
7391
7539
|
}
|
|
7392
7540
|
const projectId = workspace.projectId;
|
|
7393
7541
|
const normalizedId = normalizeRequirementId(requirementId);
|
|
7394
|
-
stopSpinner = showSpinner("Adding tag",
|
|
7542
|
+
stopSpinner = showSpinner("Adding tag", chalk15.gray);
|
|
7395
7543
|
const response = await requirementService.addRequirementTag(projectId, normalizedId, {
|
|
7396
7544
|
name: opts.name.trim(),
|
|
7397
7545
|
color: opts.color
|
|
@@ -7400,7 +7548,7 @@ async function handleRequirementTagAdd(opts) {
|
|
|
7400
7548
|
stopSpinner = null;
|
|
7401
7549
|
return {
|
|
7402
7550
|
success: true,
|
|
7403
|
-
message:
|
|
7551
|
+
message: chalk15.green(
|
|
7404
7552
|
`\u2705 Added tag "${response.tag.name}" (${response.tag.color}) to ${normalizedId}`
|
|
7405
7553
|
),
|
|
7406
7554
|
data: response
|
|
@@ -7416,13 +7564,13 @@ async function handleRequirementTagAdd(opts) {
|
|
|
7416
7564
|
if (errorData?.code === "MAX_TAGS_EXCEEDED") {
|
|
7417
7565
|
return {
|
|
7418
7566
|
success: false,
|
|
7419
|
-
message:
|
|
7567
|
+
message: chalk15.red("\u274C Maximum 5 tags allowed per requirement")
|
|
7420
7568
|
};
|
|
7421
7569
|
}
|
|
7422
7570
|
if (errorData?.code === "TAG_ALREADY_ASSOCIATED") {
|
|
7423
7571
|
return {
|
|
7424
7572
|
success: false,
|
|
7425
|
-
message:
|
|
7573
|
+
message: chalk15.red(`\u274C Tag "${opts.name}" is already associated with this requirement`)
|
|
7426
7574
|
};
|
|
7427
7575
|
}
|
|
7428
7576
|
}
|
|
@@ -7444,13 +7592,13 @@ async function handleRequirementTagRemove(opts) {
|
|
|
7444
7592
|
if (!isAuthenticated) {
|
|
7445
7593
|
return {
|
|
7446
7594
|
success: false,
|
|
7447
|
-
message:
|
|
7595
|
+
message: chalk15.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
7448
7596
|
};
|
|
7449
7597
|
}
|
|
7450
7598
|
if (!opts.name || opts.name.trim().length === 0) {
|
|
7451
7599
|
return {
|
|
7452
7600
|
success: false,
|
|
7453
|
-
message:
|
|
7601
|
+
message: chalk15.red("\u274C Tag name is required")
|
|
7454
7602
|
};
|
|
7455
7603
|
}
|
|
7456
7604
|
const requirementResult = await workspaceManager.getRequirement(opts.requirementId);
|
|
@@ -7470,13 +7618,13 @@ async function handleRequirementTagRemove(opts) {
|
|
|
7470
7618
|
}
|
|
7471
7619
|
const projectId = workspace.projectId;
|
|
7472
7620
|
const normalizedId = normalizeRequirementId(requirementId);
|
|
7473
|
-
stopSpinner = showSpinner("Removing tag",
|
|
7621
|
+
stopSpinner = showSpinner("Removing tag", chalk15.gray);
|
|
7474
7622
|
await requirementService.removeRequirementTag(projectId, normalizedId, opts.name.trim());
|
|
7475
7623
|
stopSpinner();
|
|
7476
7624
|
stopSpinner = null;
|
|
7477
7625
|
return {
|
|
7478
7626
|
success: true,
|
|
7479
|
-
message:
|
|
7627
|
+
message: chalk15.green(`\u2705 Removed tag "${opts.name}" from ${normalizedId}`)
|
|
7480
7628
|
};
|
|
7481
7629
|
} catch (error) {
|
|
7482
7630
|
if (stopSpinner) {
|
|
@@ -7489,13 +7637,13 @@ async function handleRequirementTagRemove(opts) {
|
|
|
7489
7637
|
if (errorData?.code === "TAG_NOT_FOUND") {
|
|
7490
7638
|
return {
|
|
7491
7639
|
success: false,
|
|
7492
|
-
message:
|
|
7640
|
+
message: chalk15.red(`\u274C Tag "${opts.name}" not found`)
|
|
7493
7641
|
};
|
|
7494
7642
|
}
|
|
7495
7643
|
if (errorData?.code === "ASSOCIATION_NOT_FOUND") {
|
|
7496
7644
|
return {
|
|
7497
7645
|
success: false,
|
|
7498
|
-
message:
|
|
7646
|
+
message: chalk15.red(`\u274C Tag "${opts.name}" is not associated with this requirement`)
|
|
7499
7647
|
};
|
|
7500
7648
|
}
|
|
7501
7649
|
}
|
|
@@ -7511,7 +7659,7 @@ async function handleRequirementTagRemove(opts) {
|
|
|
7511
7659
|
}
|
|
7512
7660
|
|
|
7513
7661
|
// src/handlers/status.handlers.ts
|
|
7514
|
-
import
|
|
7662
|
+
import chalk16 from "chalk";
|
|
7515
7663
|
function getAuth2() {
|
|
7516
7664
|
const config2 = getConfig();
|
|
7517
7665
|
return new BraingridAuth(config2.apiUrl);
|
|
@@ -7520,79 +7668,79 @@ async function handleStatus() {
|
|
|
7520
7668
|
try {
|
|
7521
7669
|
const config2 = getConfig();
|
|
7522
7670
|
const auth = getAuth2();
|
|
7523
|
-
const stop = showSpinner("Checking status",
|
|
7671
|
+
const stop = showSpinner("Checking status", chalk16.gray);
|
|
7524
7672
|
const isAuthenticated = await auth.isAuthenticated(true);
|
|
7525
7673
|
stop();
|
|
7526
|
-
let output =
|
|
7527
|
-
output +=
|
|
7528
|
-
output += `${
|
|
7674
|
+
let output = chalk16.bold.cyan("\n\u{1F9E0} BrainGrid CLI Status\n\n");
|
|
7675
|
+
output += chalk16.bold("Authentication\n");
|
|
7676
|
+
output += `${chalk16.dim("\u2500".repeat(50))}
|
|
7529
7677
|
`;
|
|
7530
7678
|
if (!isAuthenticated) {
|
|
7531
|
-
output +=
|
|
7532
|
-
output +=
|
|
7533
|
-
output +=
|
|
7534
|
-
output += `${
|
|
7679
|
+
output += chalk16.red("\u274C Not authenticated\n");
|
|
7680
|
+
output += chalk16.dim(" Run ") + chalk16.cyan("braingrid login") + chalk16.dim(" to sign in\n\n");
|
|
7681
|
+
output += chalk16.bold("Git Repository\n");
|
|
7682
|
+
output += `${chalk16.dim("\u2500".repeat(50))}
|
|
7535
7683
|
`;
|
|
7536
7684
|
const gitInfo2 = await getGitRepositoryInfo();
|
|
7537
7685
|
if (!gitInfo2 || !gitInfo2.isRepo) {
|
|
7538
|
-
output +=
|
|
7686
|
+
output += chalk16.yellow("\u26A0\uFE0F Not in a git repository\n\n");
|
|
7539
7687
|
} else {
|
|
7540
|
-
output +=
|
|
7688
|
+
output += chalk16.green("\u2705 Repository detected!\n");
|
|
7541
7689
|
if (gitInfo2.owner && gitInfo2.name) {
|
|
7542
|
-
output += `${
|
|
7690
|
+
output += `${chalk16.bold("Owner:")} ${gitInfo2.owner}
|
|
7543
7691
|
`;
|
|
7544
|
-
output += `${
|
|
7692
|
+
output += `${chalk16.bold("Name:")} ${gitInfo2.name}
|
|
7545
7693
|
`;
|
|
7546
7694
|
} else if (gitInfo2.remoteUrl) {
|
|
7547
|
-
output += `${
|
|
7695
|
+
output += `${chalk16.bold("Remote:")} ${gitInfo2.remoteUrl}
|
|
7548
7696
|
`;
|
|
7549
7697
|
} else {
|
|
7550
|
-
output +=
|
|
7698
|
+
output += chalk16.yellow("\u26A0\uFE0F Local repository (no remote)\n");
|
|
7551
7699
|
}
|
|
7552
7700
|
if (gitInfo2.branch) {
|
|
7553
|
-
output += `${
|
|
7701
|
+
output += `${chalk16.bold("Branch:")} ${gitInfo2.branch}
|
|
7554
7702
|
`;
|
|
7555
7703
|
}
|
|
7556
7704
|
if (gitInfo2.userName || gitInfo2.userEmail) {
|
|
7557
7705
|
const userDisplay = gitInfo2.userName && gitInfo2.userEmail ? `${gitInfo2.userName} <${gitInfo2.userEmail}>` : gitInfo2.userName || gitInfo2.userEmail;
|
|
7558
|
-
output += `${
|
|
7706
|
+
output += `${chalk16.bold("Git User:")} ${userDisplay}
|
|
7559
7707
|
`;
|
|
7560
7708
|
} else {
|
|
7561
|
-
output += `${
|
|
7709
|
+
output += `${chalk16.bold("Git User:")} ` + chalk16.yellow("\u26A0\uFE0F Not configured (run git config --global user.name/email)\n");
|
|
7562
7710
|
}
|
|
7563
7711
|
output += "\n";
|
|
7564
7712
|
}
|
|
7565
|
-
output +=
|
|
7566
|
-
output += `${
|
|
7713
|
+
output += chalk16.bold("Installed Coding Tools\n");
|
|
7714
|
+
output += `${chalk16.dim("\u2500".repeat(50))}
|
|
7567
7715
|
`;
|
|
7568
7716
|
const cliToolsUnauthenticated = await checkInstalledCliTools();
|
|
7569
7717
|
const installedTools2 = cliToolsUnauthenticated.filter((tool) => tool.installed);
|
|
7570
7718
|
if (installedTools2.length === 0) {
|
|
7571
|
-
output +=
|
|
7719
|
+
output += chalk16.yellow("\u26A0\uFE0F No coding tools detected\n\n");
|
|
7572
7720
|
} else {
|
|
7573
7721
|
installedTools2.forEach((tool) => {
|
|
7574
|
-
const versionInfo = tool.version ?
|
|
7575
|
-
output += `${
|
|
7722
|
+
const versionInfo = tool.version ? chalk16.dim(` (${tool.version})`) : "";
|
|
7723
|
+
output += `${chalk16.green("\u2705")} ${tool.name}${versionInfo}
|
|
7576
7724
|
`;
|
|
7577
7725
|
});
|
|
7578
7726
|
output += "\n";
|
|
7579
7727
|
}
|
|
7580
|
-
output +=
|
|
7581
|
-
output += `${
|
|
7728
|
+
output += chalk16.bold("Configuration\n");
|
|
7729
|
+
output += `${chalk16.dim("\u2500".repeat(50))}
|
|
7582
7730
|
`;
|
|
7583
|
-
output += `${
|
|
7731
|
+
output += `${chalk16.bold("API URL:")} ${config2.apiUrl}
|
|
7584
7732
|
`;
|
|
7585
|
-
output += `${
|
|
7733
|
+
output += `${chalk16.bold("OAuth Client:")} ${config2.oauthClientId}
|
|
7586
7734
|
`;
|
|
7587
|
-
output += `${
|
|
7735
|
+
output += `${chalk16.bold("Redirect URI:")} http://127.0.0.1:34536/callback
|
|
7588
7736
|
`;
|
|
7589
|
-
output += `${
|
|
7737
|
+
output += `${chalk16.bold("Config Path:")} ${credentialStore.getStoragePath()}
|
|
7590
7738
|
|
|
7591
7739
|
`;
|
|
7592
|
-
output +=
|
|
7593
|
-
output += `${
|
|
7740
|
+
output += chalk16.bold("Overall Status\n");
|
|
7741
|
+
output += `${chalk16.dim("\u2500".repeat(50))}
|
|
7594
7742
|
`;
|
|
7595
|
-
output +=
|
|
7743
|
+
output += chalk16.yellow("\u26A0\uFE0F Setup required - please authenticate\n");
|
|
7596
7744
|
return {
|
|
7597
7745
|
success: true,
|
|
7598
7746
|
message: output,
|
|
@@ -7601,94 +7749,94 @@ async function handleStatus() {
|
|
|
7601
7749
|
}
|
|
7602
7750
|
const session = await auth.getStoredSession();
|
|
7603
7751
|
if (!session) {
|
|
7604
|
-
output +=
|
|
7752
|
+
output += chalk16.red("\u274C Session not found\n\n");
|
|
7605
7753
|
return {
|
|
7606
7754
|
success: true,
|
|
7607
7755
|
message: output,
|
|
7608
7756
|
data: { authenticated: false }
|
|
7609
7757
|
};
|
|
7610
7758
|
}
|
|
7611
|
-
output +=
|
|
7759
|
+
output += chalk16.green("\u2705 Authenticated\n");
|
|
7612
7760
|
const userName = `${session.user.firstName || ""} ${session.user.lastName || ""}`.trim();
|
|
7613
7761
|
if (userName) {
|
|
7614
|
-
output += `${
|
|
7762
|
+
output += `${chalk16.bold("Name:")} ${userName}
|
|
7615
7763
|
`;
|
|
7616
7764
|
}
|
|
7617
|
-
output += `${
|
|
7765
|
+
output += `${chalk16.bold("Email:")} ${session.user.email}
|
|
7618
7766
|
`;
|
|
7619
|
-
output += `${
|
|
7767
|
+
output += `${chalk16.bold("User ID:")} ${session.user.id}
|
|
7620
7768
|
`;
|
|
7621
|
-
output += `${
|
|
7769
|
+
output += `${chalk16.bold("Organization:")} ${session.organization_id}
|
|
7622
7770
|
`;
|
|
7623
7771
|
const sessionAge = Math.floor((Date.now() - session.created_at.getTime()) / 1e3 / 60);
|
|
7624
|
-
output += `${
|
|
7772
|
+
output += `${chalk16.bold("Session Age:")} ${sessionAge} minutes
|
|
7625
7773
|
`;
|
|
7626
|
-
output += `${
|
|
7774
|
+
output += `${chalk16.bold("API URL:")} ${config2.apiUrl}
|
|
7627
7775
|
`;
|
|
7628
|
-
output += `${
|
|
7776
|
+
output += `${chalk16.bold("Config Path:")} ${credentialStore.getStoragePath()}
|
|
7629
7777
|
|
|
7630
7778
|
`;
|
|
7631
|
-
output +=
|
|
7632
|
-
output += `${
|
|
7779
|
+
output += chalk16.bold("Git Repository\n");
|
|
7780
|
+
output += `${chalk16.dim("\u2500".repeat(50))}
|
|
7633
7781
|
`;
|
|
7634
7782
|
const gitInfo = await getGitRepositoryInfo();
|
|
7635
7783
|
if (!gitInfo || !gitInfo.isRepo) {
|
|
7636
|
-
output +=
|
|
7784
|
+
output += chalk16.yellow("\u26A0\uFE0F Not in a git repository\n\n");
|
|
7637
7785
|
} else {
|
|
7638
|
-
output +=
|
|
7786
|
+
output += chalk16.green("\u2705 Repository detected!\n");
|
|
7639
7787
|
if (gitInfo.owner && gitInfo.name) {
|
|
7640
|
-
output += `${
|
|
7788
|
+
output += `${chalk16.bold("Owner:")} ${gitInfo.owner}
|
|
7641
7789
|
`;
|
|
7642
|
-
output += `${
|
|
7790
|
+
output += `${chalk16.bold("Name:")} ${gitInfo.name}
|
|
7643
7791
|
`;
|
|
7644
7792
|
} else if (gitInfo.remoteUrl) {
|
|
7645
|
-
output += `${
|
|
7793
|
+
output += `${chalk16.bold("Remote:")} ${gitInfo.remoteUrl}
|
|
7646
7794
|
`;
|
|
7647
7795
|
} else {
|
|
7648
|
-
output +=
|
|
7796
|
+
output += chalk16.yellow("\u26A0\uFE0F Local repository (no remote)\n");
|
|
7649
7797
|
}
|
|
7650
7798
|
if (gitInfo.branch) {
|
|
7651
|
-
output += `${
|
|
7799
|
+
output += `${chalk16.bold("Branch:")} ${gitInfo.branch}
|
|
7652
7800
|
`;
|
|
7653
7801
|
}
|
|
7654
7802
|
if (gitInfo.userName || gitInfo.userEmail) {
|
|
7655
7803
|
const userDisplay = gitInfo.userName && gitInfo.userEmail ? `${gitInfo.userName} <${gitInfo.userEmail}>` : gitInfo.userName || gitInfo.userEmail;
|
|
7656
|
-
output += `${
|
|
7804
|
+
output += `${chalk16.bold("Git User:")} ${userDisplay}
|
|
7657
7805
|
`;
|
|
7658
7806
|
} else {
|
|
7659
|
-
output += `${
|
|
7807
|
+
output += `${chalk16.bold("Git User:")} ` + chalk16.yellow("\u26A0\uFE0F Not configured (run git config --global user.name/email)\n");
|
|
7660
7808
|
}
|
|
7661
7809
|
output += "\n";
|
|
7662
7810
|
}
|
|
7663
|
-
output +=
|
|
7664
|
-
output += `${
|
|
7811
|
+
output += chalk16.bold("Installed Coding Tools\n");
|
|
7812
|
+
output += `${chalk16.dim("\u2500".repeat(50))}
|
|
7665
7813
|
`;
|
|
7666
7814
|
const cliTools = await checkInstalledCliTools();
|
|
7667
7815
|
const installedTools = cliTools.filter((tool) => tool.installed);
|
|
7668
7816
|
if (installedTools.length === 0) {
|
|
7669
|
-
output +=
|
|
7817
|
+
output += chalk16.yellow("\u26A0\uFE0F No coding tools detected\n\n");
|
|
7670
7818
|
} else {
|
|
7671
7819
|
installedTools.forEach((tool) => {
|
|
7672
|
-
const versionInfo = tool.version ?
|
|
7673
|
-
output += `${
|
|
7820
|
+
const versionInfo = tool.version ? chalk16.dim(` (${tool.version})`) : "";
|
|
7821
|
+
output += `${chalk16.green("\u2705")} ${tool.name}${versionInfo}
|
|
7674
7822
|
`;
|
|
7675
7823
|
});
|
|
7676
7824
|
output += "\n";
|
|
7677
7825
|
}
|
|
7678
|
-
output +=
|
|
7679
|
-
output += `${
|
|
7826
|
+
output += chalk16.bold("Configuration\n");
|
|
7827
|
+
output += `${chalk16.dim("\u2500".repeat(50))}
|
|
7680
7828
|
`;
|
|
7681
|
-
output += `${
|
|
7829
|
+
output += `${chalk16.bold("OAuth Client:")} ${config2.oauthClientId}
|
|
7682
7830
|
`;
|
|
7683
|
-
output += `${
|
|
7831
|
+
output += `${chalk16.bold("Redirect URI:")} http://127.0.0.1:34536/callback
|
|
7684
7832
|
`;
|
|
7685
|
-
output += `${
|
|
7833
|
+
output += `${chalk16.bold("Auth Server:")} ${config2.getWorkOSAuthUrl()}
|
|
7686
7834
|
|
|
7687
7835
|
`;
|
|
7688
|
-
output +=
|
|
7689
|
-
output += `${
|
|
7836
|
+
output += chalk16.bold("Overall Status\n");
|
|
7837
|
+
output += `${chalk16.dim("\u2500".repeat(50))}
|
|
7690
7838
|
`;
|
|
7691
|
-
output +=
|
|
7839
|
+
output += chalk16.green("\u2705 Ready to use BrainGrid CLI\n");
|
|
7692
7840
|
return {
|
|
7693
7841
|
success: true,
|
|
7694
7842
|
message: output,
|
|
@@ -7703,7 +7851,7 @@ async function handleStatus() {
|
|
|
7703
7851
|
}
|
|
7704
7852
|
|
|
7705
7853
|
// src/handlers/task.handlers.ts
|
|
7706
|
-
import
|
|
7854
|
+
import chalk17 from "chalk";
|
|
7707
7855
|
|
|
7708
7856
|
// src/services/task-service.ts
|
|
7709
7857
|
var TaskService = class {
|
|
@@ -7807,7 +7955,7 @@ async function handleTaskList(opts) {
|
|
|
7807
7955
|
if (!isAuthenticated) {
|
|
7808
7956
|
return {
|
|
7809
7957
|
success: false,
|
|
7810
|
-
message:
|
|
7958
|
+
message: chalk17.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
7811
7959
|
};
|
|
7812
7960
|
}
|
|
7813
7961
|
const workspace = await workspaceManager.getProject(opts.project);
|
|
@@ -7827,7 +7975,7 @@ async function handleTaskList(opts) {
|
|
|
7827
7975
|
}
|
|
7828
7976
|
const requirementId = requirementResult.requirementId;
|
|
7829
7977
|
if (opts.format !== "json" && opts.format !== "xml") {
|
|
7830
|
-
stopSpinner = showSpinner("Loading tasks",
|
|
7978
|
+
stopSpinner = showSpinner("Loading tasks", chalk17.gray);
|
|
7831
7979
|
}
|
|
7832
7980
|
const response = await taskService.listTasks(projectId, requirementId, {
|
|
7833
7981
|
page: opts.page ? parseInt(opts.page, 10) : 1,
|
|
@@ -7840,7 +7988,7 @@ async function handleTaskList(opts) {
|
|
|
7840
7988
|
if (response.tasks.length === 0) {
|
|
7841
7989
|
return {
|
|
7842
7990
|
success: true,
|
|
7843
|
-
message:
|
|
7991
|
+
message: chalk17.yellow("No tasks found."),
|
|
7844
7992
|
data: response
|
|
7845
7993
|
};
|
|
7846
7994
|
}
|
|
@@ -7856,7 +8004,7 @@ async function handleTaskList(opts) {
|
|
|
7856
8004
|
});
|
|
7857
8005
|
if (response.pagination?.has_more) {
|
|
7858
8006
|
output += `
|
|
7859
|
-
${
|
|
8007
|
+
${chalk17.yellow("\u26A0\uFE0F More tasks exist. Use --limit to see more.")}`;
|
|
7860
8008
|
}
|
|
7861
8009
|
return {
|
|
7862
8010
|
success: true,
|
|
@@ -7881,7 +8029,7 @@ async function handleTaskSummary(opts) {
|
|
|
7881
8029
|
if (!isAuthenticated) {
|
|
7882
8030
|
return {
|
|
7883
8031
|
success: false,
|
|
7884
|
-
message:
|
|
8032
|
+
message: chalk17.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
7885
8033
|
};
|
|
7886
8034
|
}
|
|
7887
8035
|
const workspace = await workspaceManager.getProject(opts.project);
|
|
@@ -7900,7 +8048,7 @@ async function handleTaskSummary(opts) {
|
|
|
7900
8048
|
};
|
|
7901
8049
|
}
|
|
7902
8050
|
const requirementId = requirementResult.requirementId;
|
|
7903
|
-
stopSpinner = showSpinner("Loading tasks",
|
|
8051
|
+
stopSpinner = showSpinner("Loading tasks", chalk17.gray);
|
|
7904
8052
|
const response = await taskService.listTasks(projectId, requirementId, {
|
|
7905
8053
|
page: opts.page ? parseInt(opts.page, 10) : 1,
|
|
7906
8054
|
limit: opts.limit ? parseInt(opts.limit, 10) : 20
|
|
@@ -7910,7 +8058,7 @@ async function handleTaskSummary(opts) {
|
|
|
7910
8058
|
if (response.tasks.length === 0) {
|
|
7911
8059
|
return {
|
|
7912
8060
|
success: true,
|
|
7913
|
-
message:
|
|
8061
|
+
message: chalk17.yellow("No tasks found."),
|
|
7914
8062
|
data: response
|
|
7915
8063
|
};
|
|
7916
8064
|
}
|
|
@@ -7925,7 +8073,7 @@ async function handleTaskSummary(opts) {
|
|
|
7925
8073
|
});
|
|
7926
8074
|
if (response.pagination?.has_more) {
|
|
7927
8075
|
output += `
|
|
7928
|
-
${
|
|
8076
|
+
${chalk17.yellow("\u26A0\uFE0F More tasks exist. Use --limit to see more.")}`;
|
|
7929
8077
|
}
|
|
7930
8078
|
return {
|
|
7931
8079
|
success: true,
|
|
@@ -7950,14 +8098,14 @@ async function handleTaskShow(id, opts) {
|
|
|
7950
8098
|
if (!isAuthenticated) {
|
|
7951
8099
|
return {
|
|
7952
8100
|
success: false,
|
|
7953
|
-
message:
|
|
8101
|
+
message: chalk17.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
7954
8102
|
};
|
|
7955
8103
|
}
|
|
7956
8104
|
const format = opts?.format || "markdown";
|
|
7957
8105
|
if (!["markdown", "json", "xml", "table"].includes(format)) {
|
|
7958
8106
|
return {
|
|
7959
8107
|
success: false,
|
|
7960
|
-
message:
|
|
8108
|
+
message: chalk17.red(
|
|
7961
8109
|
`\u274C Invalid format: ${format}. Supported formats: markdown, json, xml, table`
|
|
7962
8110
|
)
|
|
7963
8111
|
};
|
|
@@ -7987,14 +8135,14 @@ async function handleTaskShow(id, opts) {
|
|
|
7987
8135
|
if (!currentTask.success) {
|
|
7988
8136
|
return {
|
|
7989
8137
|
success: false,
|
|
7990
|
-
message:
|
|
8138
|
+
message: chalk17.red(`\u274C ${currentTask.error}`)
|
|
7991
8139
|
};
|
|
7992
8140
|
}
|
|
7993
8141
|
taskId = currentTask.taskId;
|
|
7994
8142
|
taskWarning = currentTask.warning;
|
|
7995
8143
|
}
|
|
7996
8144
|
const config2 = getConfig();
|
|
7997
|
-
stopSpinner = showSpinner("Loading task",
|
|
8145
|
+
stopSpinner = showSpinner("Loading task", chalk17.gray);
|
|
7998
8146
|
const task2 = await taskService.getTask(projectId, requirementId, taskId);
|
|
7999
8147
|
stopSpinner();
|
|
8000
8148
|
stopSpinner = null;
|
|
@@ -8027,7 +8175,7 @@ async function handleTaskShow(id, opts) {
|
|
|
8027
8175
|
}
|
|
8028
8176
|
if (taskWarning) {
|
|
8029
8177
|
output += `
|
|
8030
|
-
${
|
|
8178
|
+
${chalk17.yellow(`\u26A0\uFE0F ${taskWarning}`)}`;
|
|
8031
8179
|
}
|
|
8032
8180
|
return {
|
|
8033
8181
|
success: true,
|
|
@@ -8052,7 +8200,7 @@ async function handleTaskCreate(opts) {
|
|
|
8052
8200
|
if (!isAuthenticated) {
|
|
8053
8201
|
return {
|
|
8054
8202
|
success: false,
|
|
8055
|
-
message:
|
|
8203
|
+
message: chalk17.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
8056
8204
|
};
|
|
8057
8205
|
}
|
|
8058
8206
|
const workspace = await workspaceManager.getProject(opts.project);
|
|
@@ -8074,7 +8222,7 @@ async function handleTaskCreate(opts) {
|
|
|
8074
8222
|
const projectShortId = projectId;
|
|
8075
8223
|
const requirementShortId = opts.requirement || requirementId;
|
|
8076
8224
|
const config2 = getConfig();
|
|
8077
|
-
stopSpinner = showSpinner("Creating task",
|
|
8225
|
+
stopSpinner = showSpinner("Creating task", chalk17.gray);
|
|
8078
8226
|
const task2 = await taskService.createTask(projectId, requirementId, {
|
|
8079
8227
|
title: opts.title,
|
|
8080
8228
|
content: opts.content,
|
|
@@ -8113,13 +8261,13 @@ async function handleTaskUpdate(id, opts) {
|
|
|
8113
8261
|
if (!isAuthenticated) {
|
|
8114
8262
|
return {
|
|
8115
8263
|
success: false,
|
|
8116
|
-
message:
|
|
8264
|
+
message: chalk17.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
8117
8265
|
};
|
|
8118
8266
|
}
|
|
8119
8267
|
if (!opts?.status && !opts?.title && !opts?.externalId) {
|
|
8120
8268
|
return {
|
|
8121
8269
|
success: false,
|
|
8122
|
-
message:
|
|
8270
|
+
message: chalk17.red(
|
|
8123
8271
|
"\u274C Please provide at least one field to update (--status, --title, or --external-id)"
|
|
8124
8272
|
)
|
|
8125
8273
|
};
|
|
@@ -8149,14 +8297,14 @@ async function handleTaskUpdate(id, opts) {
|
|
|
8149
8297
|
if (!currentTask.success) {
|
|
8150
8298
|
return {
|
|
8151
8299
|
success: false,
|
|
8152
|
-
message:
|
|
8300
|
+
message: chalk17.red(`\u274C ${currentTask.error}`)
|
|
8153
8301
|
};
|
|
8154
8302
|
}
|
|
8155
8303
|
taskId = currentTask.taskId;
|
|
8156
8304
|
taskWarning = currentTask.warning;
|
|
8157
8305
|
}
|
|
8158
8306
|
const config2 = getConfig();
|
|
8159
|
-
stopSpinner = showSpinner("Updating task",
|
|
8307
|
+
stopSpinner = showSpinner("Updating task", chalk17.gray);
|
|
8160
8308
|
const task2 = await taskService.updateTask(projectId, requirementId, taskId, {
|
|
8161
8309
|
status: opts?.status,
|
|
8162
8310
|
title: opts?.title,
|
|
@@ -8174,7 +8322,7 @@ async function handleTaskUpdate(id, opts) {
|
|
|
8174
8322
|
});
|
|
8175
8323
|
if (taskWarning) {
|
|
8176
8324
|
output += `
|
|
8177
|
-
${
|
|
8325
|
+
${chalk17.yellow(`\u26A0\uFE0F ${taskWarning}`)}`;
|
|
8178
8326
|
}
|
|
8179
8327
|
return {
|
|
8180
8328
|
success: true,
|
|
@@ -8199,13 +8347,13 @@ async function handleTaskDelete(id, opts) {
|
|
|
8199
8347
|
if (!isAuthenticated) {
|
|
8200
8348
|
return {
|
|
8201
8349
|
success: false,
|
|
8202
|
-
message:
|
|
8350
|
+
message: chalk17.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
8203
8351
|
};
|
|
8204
8352
|
}
|
|
8205
8353
|
if (!opts.force) {
|
|
8206
8354
|
return {
|
|
8207
8355
|
success: false,
|
|
8208
|
-
message:
|
|
8356
|
+
message: chalk17.yellow("\u26A0\uFE0F Deleting a task is permanent. Use --force to confirm deletion.")
|
|
8209
8357
|
};
|
|
8210
8358
|
}
|
|
8211
8359
|
const workspace = await workspaceManager.getProject(opts.project);
|
|
@@ -8225,13 +8373,13 @@ async function handleTaskDelete(id, opts) {
|
|
|
8225
8373
|
}
|
|
8226
8374
|
const requirementId = requirementResult.requirementId;
|
|
8227
8375
|
const taskId = normalizeTaskId(id);
|
|
8228
|
-
stopSpinner = showSpinner("Deleting task",
|
|
8376
|
+
stopSpinner = showSpinner("Deleting task", chalk17.gray);
|
|
8229
8377
|
await taskService.deleteTask(projectId, requirementId, taskId);
|
|
8230
8378
|
stopSpinner();
|
|
8231
8379
|
stopSpinner = null;
|
|
8232
8380
|
return {
|
|
8233
8381
|
success: true,
|
|
8234
|
-
message:
|
|
8382
|
+
message: chalk17.green(`\u2705 Deleted task ${id}`)
|
|
8235
8383
|
};
|
|
8236
8384
|
} catch (error) {
|
|
8237
8385
|
if (stopSpinner) {
|
|
@@ -8251,14 +8399,14 @@ async function handleTaskSpecify(opts) {
|
|
|
8251
8399
|
if (!isAuthenticated) {
|
|
8252
8400
|
return {
|
|
8253
8401
|
success: false,
|
|
8254
|
-
message:
|
|
8402
|
+
message: chalk17.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
8255
8403
|
};
|
|
8256
8404
|
}
|
|
8257
8405
|
const format = opts.format || "table";
|
|
8258
8406
|
if (!["table", "json", "markdown"].includes(format)) {
|
|
8259
8407
|
return {
|
|
8260
8408
|
success: false,
|
|
8261
|
-
message:
|
|
8409
|
+
message: chalk17.red(
|
|
8262
8410
|
`\u274C Invalid format: ${format}. Supported formats: table, json, markdown`
|
|
8263
8411
|
)
|
|
8264
8412
|
};
|
|
@@ -8282,16 +8430,16 @@ async function handleTaskSpecify(opts) {
|
|
|
8282
8430
|
if (opts.prompt.length < 10) {
|
|
8283
8431
|
return {
|
|
8284
8432
|
success: false,
|
|
8285
|
-
message:
|
|
8433
|
+
message: chalk17.red("\u274C Prompt must be at least 10 characters long")
|
|
8286
8434
|
};
|
|
8287
8435
|
}
|
|
8288
8436
|
if (opts.prompt.length > 5e3) {
|
|
8289
8437
|
return {
|
|
8290
8438
|
success: false,
|
|
8291
|
-
message:
|
|
8439
|
+
message: chalk17.red("\u274C Prompt must be no more than 5000 characters long")
|
|
8292
8440
|
};
|
|
8293
8441
|
}
|
|
8294
|
-
stopSpinner = showSpinner("Creating task from prompt...",
|
|
8442
|
+
stopSpinner = showSpinner("Creating task from prompt...", chalk17.gray);
|
|
8295
8443
|
const response = await taskService.specifyTask(projectId, requirementId, {
|
|
8296
8444
|
prompt: opts.prompt
|
|
8297
8445
|
});
|
|
@@ -8331,10 +8479,10 @@ async function handleTaskSpecify(opts) {
|
|
|
8331
8479
|
function formatTaskSpecifyTable(response) {
|
|
8332
8480
|
const task2 = response.task;
|
|
8333
8481
|
const lines = [];
|
|
8334
|
-
lines.push(
|
|
8482
|
+
lines.push(chalk17.green(`\u2705 Created task ${response.requirement_short_id}/TASK-${task2.number}`));
|
|
8335
8483
|
lines.push("");
|
|
8336
|
-
lines.push(`${
|
|
8337
|
-
lines.push(`${
|
|
8484
|
+
lines.push(`${chalk17.bold("Title:")} ${task2.title}`);
|
|
8485
|
+
lines.push(`${chalk17.bold("Status:")} ${task2.status}`);
|
|
8338
8486
|
return lines.join("\n");
|
|
8339
8487
|
}
|
|
8340
8488
|
function formatTaskSpecifyMarkdown(response, _apiUrl) {
|
|
@@ -8656,6 +8804,14 @@ task.command("specify").description("Create a single task from a prompt using AI
|
|
|
8656
8804
|
process.exit(1);
|
|
8657
8805
|
}
|
|
8658
8806
|
});
|
|
8807
|
+
var claudeCode = program.command("claude-code").description("Claude Code utilities");
|
|
8808
|
+
claudeCode.command("credentials").description("Show Claude Code credentials from macOS Keychain").option("--raw", "print full unmasked JSON (for piping/scripting)").action(async (opts) => {
|
|
8809
|
+
const result = await handleClaudeCodeCredentials(opts);
|
|
8810
|
+
console.log(result.message);
|
|
8811
|
+
if (!result.success) {
|
|
8812
|
+
process.exit(1);
|
|
8813
|
+
}
|
|
8814
|
+
});
|
|
8659
8815
|
program.command("completion [shell]").description("Generate shell completion script (bash, zsh)").option("--setup", "automatically install completion for current shell").option("-s, --shell <shell>", "shell type (bash, zsh)").action(async (shell, opts) => {
|
|
8660
8816
|
const result = await handleCompletion(shell, opts);
|
|
8661
8817
|
console.log(result.message);
|