@braingrid/cli 0.2.44 → 0.2.45
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 +11 -0
- package/dist/cli.js +616 -477
- 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.45" : "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";
|
|
@@ -2799,7 +2930,7 @@ async function updateClaudeSettings(settingsPath = ".claude/settings.json", stat
|
|
|
2799
2930
|
// src/utils/git-installer.ts
|
|
2800
2931
|
import { exec as exec2 } from "child_process";
|
|
2801
2932
|
import { promisify as promisify2 } from "util";
|
|
2802
|
-
import
|
|
2933
|
+
import chalk6 from "chalk";
|
|
2803
2934
|
var execAsync3 = promisify2(exec2);
|
|
2804
2935
|
async function isGitInstalled() {
|
|
2805
2936
|
return isCliInstalled("git");
|
|
@@ -2811,7 +2942,7 @@ async function getGitVersion() {
|
|
|
2811
2942
|
});
|
|
2812
2943
|
}
|
|
2813
2944
|
async function installViaHomebrew() {
|
|
2814
|
-
console.log(
|
|
2945
|
+
console.log(chalk6.blue("\u{1F4E6} Installing Git via Homebrew..."));
|
|
2815
2946
|
try {
|
|
2816
2947
|
await execAsync3("brew install git", {
|
|
2817
2948
|
timeout: 3e5
|
|
@@ -2821,25 +2952,25 @@ async function installViaHomebrew() {
|
|
|
2821
2952
|
if (!version) {
|
|
2822
2953
|
return {
|
|
2823
2954
|
success: false,
|
|
2824
|
-
message:
|
|
2955
|
+
message: chalk6.red("\u274C Git installation completed but git command not found")
|
|
2825
2956
|
};
|
|
2826
2957
|
}
|
|
2827
2958
|
return {
|
|
2828
2959
|
success: true,
|
|
2829
|
-
message:
|
|
2960
|
+
message: chalk6.green(`\u2705 Git installed successfully (version ${version})!`),
|
|
2830
2961
|
version
|
|
2831
2962
|
};
|
|
2832
2963
|
} catch (error) {
|
|
2833
2964
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
2834
2965
|
return {
|
|
2835
2966
|
success: false,
|
|
2836
|
-
message:
|
|
2967
|
+
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
2968
|
};
|
|
2838
2969
|
}
|
|
2839
2970
|
}
|
|
2840
2971
|
async function installViaXcodeSelect() {
|
|
2841
|
-
console.log(
|
|
2842
|
-
console.log(
|
|
2972
|
+
console.log(chalk6.blue("\u{1F4E6} Installing Git via Xcode Command Line Tools..."));
|
|
2973
|
+
console.log(chalk6.dim('A system dialog will appear - click "Install" to continue.\n'));
|
|
2843
2974
|
try {
|
|
2844
2975
|
await execAsync3("xcode-select --install", {
|
|
2845
2976
|
timeout: 6e5
|
|
@@ -2849,19 +2980,19 @@ async function installViaXcodeSelect() {
|
|
|
2849
2980
|
if (!version) {
|
|
2850
2981
|
return {
|
|
2851
2982
|
success: false,
|
|
2852
|
-
message:
|
|
2983
|
+
message: chalk6.red("\u274C Git installation completed but git command not found")
|
|
2853
2984
|
};
|
|
2854
2985
|
}
|
|
2855
2986
|
return {
|
|
2856
2987
|
success: true,
|
|
2857
|
-
message:
|
|
2988
|
+
message: chalk6.green(`\u2705 Git installed successfully (version ${version})!`),
|
|
2858
2989
|
version
|
|
2859
2990
|
};
|
|
2860
2991
|
} catch (error) {
|
|
2861
2992
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
2862
2993
|
return {
|
|
2863
2994
|
success: false,
|
|
2864
|
-
message:
|
|
2995
|
+
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
2996
|
};
|
|
2866
2997
|
}
|
|
2867
2998
|
}
|
|
@@ -2877,10 +3008,10 @@ async function installGitWindows() {
|
|
|
2877
3008
|
if (!hasWinget) {
|
|
2878
3009
|
return {
|
|
2879
3010
|
success: false,
|
|
2880
|
-
message:
|
|
3011
|
+
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
3012
|
};
|
|
2882
3013
|
}
|
|
2883
|
-
console.log(
|
|
3014
|
+
console.log(chalk6.blue("\u{1F4E6} Installing Git via winget..."));
|
|
2884
3015
|
try {
|
|
2885
3016
|
await execAsync3("winget install --id Git.Git -e --source winget --silent", {
|
|
2886
3017
|
timeout: 3e5
|
|
@@ -2890,19 +3021,19 @@ async function installGitWindows() {
|
|
|
2890
3021
|
if (!version) {
|
|
2891
3022
|
return {
|
|
2892
3023
|
success: false,
|
|
2893
|
-
message:
|
|
3024
|
+
message: chalk6.red("\u274C Git installation completed but git command not found")
|
|
2894
3025
|
};
|
|
2895
3026
|
}
|
|
2896
3027
|
return {
|
|
2897
3028
|
success: true,
|
|
2898
|
-
message:
|
|
3029
|
+
message: chalk6.green(`\u2705 Git installed successfully (version ${version})!`),
|
|
2899
3030
|
version
|
|
2900
3031
|
};
|
|
2901
3032
|
} catch (error) {
|
|
2902
3033
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
2903
3034
|
return {
|
|
2904
3035
|
success: false,
|
|
2905
|
-
message:
|
|
3036
|
+
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
3037
|
};
|
|
2907
3038
|
}
|
|
2908
3039
|
}
|
|
@@ -2911,11 +3042,11 @@ async function installGitLinux() {
|
|
|
2911
3042
|
if (!packageManager) {
|
|
2912
3043
|
return {
|
|
2913
3044
|
success: false,
|
|
2914
|
-
message:
|
|
3045
|
+
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
3046
|
};
|
|
2916
3047
|
}
|
|
2917
|
-
console.log(
|
|
2918
|
-
console.log(
|
|
3048
|
+
console.log(chalk6.blue(`\u{1F4E6} Installing Git via ${packageManager.name}...`));
|
|
3049
|
+
console.log(chalk6.dim("This may prompt for your sudo password.\n"));
|
|
2919
3050
|
try {
|
|
2920
3051
|
let installCommand;
|
|
2921
3052
|
switch (packageManager.name) {
|
|
@@ -2934,7 +3065,7 @@ async function installGitLinux() {
|
|
|
2934
3065
|
default:
|
|
2935
3066
|
return {
|
|
2936
3067
|
success: false,
|
|
2937
|
-
message:
|
|
3068
|
+
message: chalk6.red(`\u274C Unsupported package manager: ${packageManager.name}`)
|
|
2938
3069
|
};
|
|
2939
3070
|
}
|
|
2940
3071
|
await execAsync3(installCommand, {
|
|
@@ -2945,19 +3076,19 @@ async function installGitLinux() {
|
|
|
2945
3076
|
if (!version) {
|
|
2946
3077
|
return {
|
|
2947
3078
|
success: false,
|
|
2948
|
-
message:
|
|
3079
|
+
message: chalk6.red("\u274C Git installation completed but git command not found")
|
|
2949
3080
|
};
|
|
2950
3081
|
}
|
|
2951
3082
|
return {
|
|
2952
3083
|
success: true,
|
|
2953
|
-
message:
|
|
3084
|
+
message: chalk6.green(`\u2705 Git installed successfully (version ${version})!`),
|
|
2954
3085
|
version
|
|
2955
3086
|
};
|
|
2956
3087
|
} catch (error) {
|
|
2957
3088
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
2958
3089
|
return {
|
|
2959
3090
|
success: false,
|
|
2960
|
-
message:
|
|
3091
|
+
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
3092
|
};
|
|
2962
3093
|
}
|
|
2963
3094
|
}
|
|
@@ -2973,9 +3104,9 @@ async function installGit() {
|
|
|
2973
3104
|
default:
|
|
2974
3105
|
return {
|
|
2975
3106
|
success: false,
|
|
2976
|
-
message:
|
|
3107
|
+
message: chalk6.red(`\u274C Unsupported platform: ${platform}
|
|
2977
3108
|
|
|
2978
|
-
`) +
|
|
3109
|
+
`) + chalk6.dim("Please install Git manually from: ") + chalk6.cyan("https://git-scm.com/downloads")
|
|
2979
3110
|
};
|
|
2980
3111
|
}
|
|
2981
3112
|
}
|
|
@@ -2983,15 +3114,15 @@ function getManualInstallInstructions() {
|
|
|
2983
3114
|
const platform = process.platform;
|
|
2984
3115
|
switch (platform) {
|
|
2985
3116
|
case "darwin":
|
|
2986
|
-
return
|
|
3117
|
+
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
3118
|
' /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"\n'
|
|
2988
|
-
) +
|
|
3119
|
+
) + 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
3120
|
case "win32":
|
|
2990
|
-
return
|
|
3121
|
+
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
3122
|
case "linux":
|
|
2992
|
-
return
|
|
3123
|
+
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
3124
|
default:
|
|
2994
|
-
return
|
|
3125
|
+
return chalk6.yellow("\u{1F4D6} Manual Git Installation\n\n") + chalk6.dim("Download from: ") + chalk6.cyan("https://git-scm.com/downloads");
|
|
2995
3126
|
}
|
|
2996
3127
|
}
|
|
2997
3128
|
|
|
@@ -3178,7 +3309,7 @@ async function getRepositoryId(repositoryService, owner, name) {
|
|
|
3178
3309
|
}
|
|
3179
3310
|
|
|
3180
3311
|
// src/utils/spinner.ts
|
|
3181
|
-
import
|
|
3312
|
+
import chalk7 from "chalk";
|
|
3182
3313
|
var SPINNER_FRAMES = ["\u280B", "\u2819", "\u2839", "\u2838", "\u283C", "\u2834", "\u2826", "\u2827", "\u2807", "\u280F"];
|
|
3183
3314
|
async function waitWithSpinner(message, checkFn, intervalMs = 3e3, maxAttempts = 60) {
|
|
3184
3315
|
let frameIndex = 0;
|
|
@@ -3186,7 +3317,7 @@ async function waitWithSpinner(message, checkFn, intervalMs = 3e3, maxAttempts =
|
|
|
3186
3317
|
const updateSpinner = () => {
|
|
3187
3318
|
const frame = SPINNER_FRAMES[frameIndex];
|
|
3188
3319
|
frameIndex = (frameIndex + 1) % SPINNER_FRAMES.length;
|
|
3189
|
-
process.stdout.write(`\r${
|
|
3320
|
+
process.stdout.write(`\r${chalk7.cyan(frame)} ${message}...`);
|
|
3190
3321
|
};
|
|
3191
3322
|
spinnerInterval = setInterval(updateSpinner, 100);
|
|
3192
3323
|
try {
|
|
@@ -3210,7 +3341,7 @@ async function waitWithSpinner(message, checkFn, intervalMs = 3e3, maxAttempts =
|
|
|
3210
3341
|
throw error;
|
|
3211
3342
|
}
|
|
3212
3343
|
}
|
|
3213
|
-
function showSpinner(message, color =
|
|
3344
|
+
function showSpinner(message, color = chalk7.cyan) {
|
|
3214
3345
|
let frameIndex = 0;
|
|
3215
3346
|
const interval = setInterval(() => {
|
|
3216
3347
|
const frame = SPINNER_FRAMES[frameIndex];
|
|
@@ -3224,7 +3355,7 @@ function showSpinner(message, color = chalk6.cyan) {
|
|
|
3224
3355
|
}
|
|
3225
3356
|
|
|
3226
3357
|
// src/utils/update-checker.ts
|
|
3227
|
-
import
|
|
3358
|
+
import chalk8 from "chalk";
|
|
3228
3359
|
|
|
3229
3360
|
// src/utils/version.ts
|
|
3230
3361
|
import axios5 from "axios";
|
|
@@ -3316,7 +3447,7 @@ async function checkAndShowUpdateWarning() {
|
|
|
3316
3447
|
try {
|
|
3317
3448
|
const { available, currentVersion, latestVersion } = await isUpdateAvailable();
|
|
3318
3449
|
if (available && latestVersion) {
|
|
3319
|
-
const warning = "\n" +
|
|
3450
|
+
const warning = "\n" + chalk8.yellow(`\u26A0\uFE0F Update available: ${currentVersion} \u2192 ${latestVersion}`) + "\n" + chalk8.dim(` Run \`${getUpdateCommand()}\` to update`) + "\n";
|
|
3320
3451
|
console.log(warning);
|
|
3321
3452
|
}
|
|
3322
3453
|
} catch {
|
|
@@ -3327,7 +3458,7 @@ async function checkAndShowUpdateWarning() {
|
|
|
3327
3458
|
import * as fs4 from "fs/promises";
|
|
3328
3459
|
import * as path6 from "path";
|
|
3329
3460
|
import { select } from "@inquirer/prompts";
|
|
3330
|
-
import
|
|
3461
|
+
import chalk9 from "chalk";
|
|
3331
3462
|
async function fileExists(filePath) {
|
|
3332
3463
|
try {
|
|
3333
3464
|
await fs4.access(filePath);
|
|
@@ -3342,7 +3473,7 @@ async function checkPrerequisites() {
|
|
|
3342
3473
|
} catch {
|
|
3343
3474
|
return {
|
|
3344
3475
|
success: false,
|
|
3345
|
-
message:
|
|
3476
|
+
message: chalk9.red("\u274C GitHub CLI is not installed.\n\n") + chalk9.dim("Install instructions:\n") + chalk9.dim(" macOS: ") + chalk9.cyan("brew install gh") + chalk9.dim("\n") + chalk9.dim(" Windows: ") + chalk9.cyan("winget install GitHub.CLI") + chalk9.dim("\n") + chalk9.dim(" Linux: See ") + chalk9.cyan("https://cli.github.com/manual/installation") + chalk9.dim("\n\n") + chalk9.dim("After installing, run: ") + chalk9.cyan("gh auth login")
|
|
3346
3477
|
};
|
|
3347
3478
|
}
|
|
3348
3479
|
try {
|
|
@@ -3350,7 +3481,7 @@ async function checkPrerequisites() {
|
|
|
3350
3481
|
} catch {
|
|
3351
3482
|
return {
|
|
3352
3483
|
success: false,
|
|
3353
|
-
message:
|
|
3484
|
+
message: chalk9.red("\u274C Not authenticated with GitHub CLI.\n\n") + chalk9.dim("Please run: ") + chalk9.cyan("gh auth login")
|
|
3354
3485
|
};
|
|
3355
3486
|
}
|
|
3356
3487
|
return null;
|
|
@@ -3378,7 +3509,7 @@ async function getFileList(sourcePaths, targetPaths) {
|
|
|
3378
3509
|
}
|
|
3379
3510
|
} catch (error) {
|
|
3380
3511
|
console.warn(
|
|
3381
|
-
|
|
3512
|
+
chalk9.yellow(`\u26A0\uFE0F Could not list directory: ${sourceDir}`),
|
|
3382
3513
|
error instanceof Error ? error.message : String(error)
|
|
3383
3514
|
);
|
|
3384
3515
|
}
|
|
@@ -3389,28 +3520,28 @@ async function getFileList(sourcePaths, targetPaths) {
|
|
|
3389
3520
|
return operations;
|
|
3390
3521
|
}
|
|
3391
3522
|
function displayInstallationPlan(operations, injectionFile) {
|
|
3392
|
-
console.log(
|
|
3393
|
-
console.log(
|
|
3394
|
-
console.log(
|
|
3523
|
+
console.log(chalk9.bold("\n\u{1F4CB} Installation Plan:\n"));
|
|
3524
|
+
console.log(chalk9.cyan(" Content Injection:"));
|
|
3525
|
+
console.log(chalk9.dim(` ${injectionFile}`));
|
|
3395
3526
|
const newFiles = operations.filter((op) => !op.exists);
|
|
3396
3527
|
const existingFiles = operations.filter((op) => op.exists);
|
|
3397
3528
|
if (newFiles.length > 0) {
|
|
3398
|
-
console.log(
|
|
3529
|
+
console.log(chalk9.cyan("\n New Files:"));
|
|
3399
3530
|
for (const op of newFiles) {
|
|
3400
|
-
console.log(
|
|
3531
|
+
console.log(chalk9.dim(` ${op.targetPath}`));
|
|
3401
3532
|
}
|
|
3402
3533
|
}
|
|
3403
3534
|
if (existingFiles.length > 0) {
|
|
3404
|
-
console.log(
|
|
3535
|
+
console.log(chalk9.yellow("\n Existing Files (will prompt):"));
|
|
3405
3536
|
for (const op of existingFiles) {
|
|
3406
|
-
console.log(
|
|
3537
|
+
console.log(chalk9.dim(` ${op.targetPath}`));
|
|
3407
3538
|
}
|
|
3408
3539
|
}
|
|
3409
3540
|
console.log("");
|
|
3410
3541
|
}
|
|
3411
3542
|
async function promptForConflict(filePath) {
|
|
3412
3543
|
const answer = await select({
|
|
3413
|
-
message:
|
|
3544
|
+
message: chalk9.yellow(`File exists: ${filePath}`),
|
|
3414
3545
|
choices: [
|
|
3415
3546
|
{ name: "[A]ll - Overwrite all remaining", value: "all" },
|
|
3416
3547
|
{ name: "[O]verwrite - Replace this file", value: "overwrite" },
|
|
@@ -3443,7 +3574,7 @@ async function installFiles(operations, force, dirCount) {
|
|
|
3443
3574
|
}
|
|
3444
3575
|
} catch (error) {
|
|
3445
3576
|
console.error(
|
|
3446
|
-
|
|
3577
|
+
chalk9.red(`Failed to copy ${operation.targetPath}:`),
|
|
3447
3578
|
error instanceof Error ? error.message : String(error)
|
|
3448
3579
|
);
|
|
3449
3580
|
skipped++;
|
|
@@ -3456,7 +3587,7 @@ async function _handleSetup(config2, opts) {
|
|
|
3456
3587
|
if (prerequisiteError) {
|
|
3457
3588
|
return prerequisiteError;
|
|
3458
3589
|
}
|
|
3459
|
-
console.log(
|
|
3590
|
+
console.log(chalk9.bold(`\u{1F680} Setting up ${config2.name} integration...
|
|
3460
3591
|
`));
|
|
3461
3592
|
const operations = await getFileList(config2.sourceDirs, config2.targetDirs);
|
|
3462
3593
|
const injectionFileExists = await fileExists(config2.injection.targetFile);
|
|
@@ -3473,7 +3604,7 @@ async function _handleSetup(config2, opts) {
|
|
|
3473
3604
|
if (opts.dryRun) {
|
|
3474
3605
|
return {
|
|
3475
3606
|
success: true,
|
|
3476
|
-
message:
|
|
3607
|
+
message: chalk9.green("\u2705 Dry-run complete. No files were modified.\n\n") + chalk9.dim(`Would install ${operations.length} files.`)
|
|
3477
3608
|
};
|
|
3478
3609
|
}
|
|
3479
3610
|
const copyOps = operations.filter((op) => op.type === "copy");
|
|
@@ -3482,7 +3613,7 @@ async function _handleSetup(config2, opts) {
|
|
|
3482
3613
|
const totalInstalled = result.installedPerDir.reduce((a, b) => a + b, 0);
|
|
3483
3614
|
return {
|
|
3484
3615
|
success: false,
|
|
3485
|
-
message:
|
|
3616
|
+
message: chalk9.yellow("\u26A0\uFE0F Installation cancelled.\n\n") + chalk9.dim(`Installed: ${totalInstalled}, Skipped: ${result.skipped}`),
|
|
3486
3617
|
code: "CANCELLED"
|
|
3487
3618
|
};
|
|
3488
3619
|
}
|
|
@@ -3491,7 +3622,7 @@ async function _handleSetup(config2, opts) {
|
|
|
3491
3622
|
await injectContentIntoFile(config2.injection.targetFile, content);
|
|
3492
3623
|
} catch (error) {
|
|
3493
3624
|
console.error(
|
|
3494
|
-
|
|
3625
|
+
chalk9.red(`Failed to inject content into ${config2.injection.targetFile}:`),
|
|
3495
3626
|
error instanceof Error ? error.message : String(error)
|
|
3496
3627
|
);
|
|
3497
3628
|
}
|
|
@@ -3510,14 +3641,14 @@ function buildSuccessMessage(config2, installedPerDir, extras) {
|
|
|
3510
3641
|
const count = installedPerDir[i] ?? 0;
|
|
3511
3642
|
if (count === 0) continue;
|
|
3512
3643
|
const { label } = config2.dirLabels[i];
|
|
3513
|
-
dirLines +=
|
|
3644
|
+
dirLines += chalk9.dim(` ${label}: ${count}
|
|
3514
3645
|
`);
|
|
3515
3646
|
}
|
|
3516
|
-
return
|
|
3647
|
+
return chalk9.green(`\u2705 ${config2.name} integration installed successfully!
|
|
3517
3648
|
|
|
3518
|
-
`) +
|
|
3649
|
+
`) + chalk9.dim("Files installed:\n") + dirLines + extras + chalk9.dim(` Content injected into: ${config2.injection.targetFile}
|
|
3519
3650
|
|
|
3520
|
-
`) +
|
|
3651
|
+
`) + 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
3652
|
}
|
|
3522
3653
|
function isSetupResult(result) {
|
|
3523
3654
|
return "data" in result && result.success === true && !("message" in result);
|
|
@@ -3553,7 +3684,7 @@ async function handleSetupClaudeCode(opts) {
|
|
|
3553
3684
|
statusLineInstalled = true;
|
|
3554
3685
|
} catch (error) {
|
|
3555
3686
|
console.error(
|
|
3556
|
-
|
|
3687
|
+
chalk9.yellow("\u26A0\uFE0F Failed to install status line script:"),
|
|
3557
3688
|
error instanceof Error ? error.message : String(error)
|
|
3558
3689
|
);
|
|
3559
3690
|
}
|
|
@@ -3561,7 +3692,7 @@ async function handleSetupClaudeCode(opts) {
|
|
|
3561
3692
|
await updateClaudeSettings();
|
|
3562
3693
|
} catch (error) {
|
|
3563
3694
|
console.error(
|
|
3564
|
-
|
|
3695
|
+
chalk9.yellow("\u26A0\uFE0F Failed to update Claude settings:"),
|
|
3565
3696
|
error instanceof Error ? error.message : String(error)
|
|
3566
3697
|
);
|
|
3567
3698
|
}
|
|
@@ -3574,13 +3705,13 @@ async function handleSetupClaudeCode(opts) {
|
|
|
3574
3705
|
installedHooks.push(script);
|
|
3575
3706
|
} catch (error) {
|
|
3576
3707
|
console.error(
|
|
3577
|
-
|
|
3708
|
+
chalk9.yellow(`\u26A0\uFE0F Failed to install hook ${script}:`),
|
|
3578
3709
|
error instanceof Error ? error.message : String(error)
|
|
3579
3710
|
);
|
|
3580
3711
|
}
|
|
3581
3712
|
}
|
|
3582
|
-
const statusLineMessage = statusLineInstalled ?
|
|
3583
|
-
const hooksMessage = installedHooks.map((s) =>
|
|
3713
|
+
const statusLineMessage = statusLineInstalled ? chalk9.dim(" Status line: .claude/statusline.sh\n") : "";
|
|
3714
|
+
const hooksMessage = installedHooks.map((s) => chalk9.dim(` Hook script: .claude/hooks/${s}
|
|
3584
3715
|
`)).join("");
|
|
3585
3716
|
return {
|
|
3586
3717
|
success: true,
|
|
@@ -3590,7 +3721,7 @@ async function handleSetupClaudeCode(opts) {
|
|
|
3590
3721
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
3591
3722
|
return {
|
|
3592
3723
|
success: false,
|
|
3593
|
-
message:
|
|
3724
|
+
message: chalk9.red(`\u274C Setup failed: ${errorMessage}`)
|
|
3594
3725
|
};
|
|
3595
3726
|
}
|
|
3596
3727
|
}
|
|
@@ -3623,22 +3754,22 @@ async function handleSetupCursor(opts) {
|
|
|
3623
3754
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
3624
3755
|
return {
|
|
3625
3756
|
success: false,
|
|
3626
|
-
message:
|
|
3757
|
+
message: chalk9.red(`\u274C Setup failed: ${errorMessage}`)
|
|
3627
3758
|
};
|
|
3628
3759
|
}
|
|
3629
3760
|
}
|
|
3630
3761
|
|
|
3631
3762
|
// src/handlers/update.handlers.ts
|
|
3632
|
-
import { execSync as
|
|
3763
|
+
import { execSync as execSync3 } from "child_process";
|
|
3633
3764
|
import { confirm } from "@inquirer/prompts";
|
|
3634
|
-
import
|
|
3765
|
+
import chalk10 from "chalk";
|
|
3635
3766
|
|
|
3636
3767
|
// src/utils/package-manager.ts
|
|
3637
|
-
import { execSync } from "child_process";
|
|
3768
|
+
import { execSync as execSync2 } from "child_process";
|
|
3638
3769
|
import { select as select2 } from "@inquirer/prompts";
|
|
3639
3770
|
function isPackageManagerInstalled(pm) {
|
|
3640
3771
|
try {
|
|
3641
|
-
|
|
3772
|
+
execSync2(`which ${pm}`, { stdio: "ignore", timeout: 2e3 });
|
|
3642
3773
|
return true;
|
|
3643
3774
|
} catch {
|
|
3644
3775
|
return false;
|
|
@@ -3661,7 +3792,7 @@ function checkGlobalInstallation(pm, packageName) {
|
|
|
3661
3792
|
break;
|
|
3662
3793
|
}
|
|
3663
3794
|
}
|
|
3664
|
-
const output =
|
|
3795
|
+
const output = execSync2(command, {
|
|
3665
3796
|
encoding: "utf-8",
|
|
3666
3797
|
timeout: 5e3
|
|
3667
3798
|
});
|
|
@@ -3725,7 +3856,7 @@ function getUpdateCommand2(pm, packageName) {
|
|
|
3725
3856
|
function executeUpdate(pm, packageName) {
|
|
3726
3857
|
const command = getUpdateCommand2(pm, packageName);
|
|
3727
3858
|
try {
|
|
3728
|
-
|
|
3859
|
+
execSync2(command, {
|
|
3729
3860
|
stdio: "inherit",
|
|
3730
3861
|
timeout: 12e4
|
|
3731
3862
|
// 2 minutes timeout
|
|
@@ -3740,14 +3871,14 @@ function executeUpdate(pm, packageName) {
|
|
|
3740
3871
|
// src/handlers/update.handlers.ts
|
|
3741
3872
|
function runSetupSubprocess(subcommand) {
|
|
3742
3873
|
try {
|
|
3743
|
-
const output =
|
|
3874
|
+
const output = execSync3(`braingrid setup ${subcommand} --force`, {
|
|
3744
3875
|
stdio: "pipe",
|
|
3745
3876
|
timeout: 6e4
|
|
3746
3877
|
});
|
|
3747
3878
|
return output.toString();
|
|
3748
3879
|
} catch (error) {
|
|
3749
3880
|
const msg = error instanceof Error ? error.message : String(error);
|
|
3750
|
-
return
|
|
3881
|
+
return chalk10.yellow(`\u26A0\uFE0F Setup ${subcommand} failed: ${msg}`);
|
|
3751
3882
|
}
|
|
3752
3883
|
}
|
|
3753
3884
|
async function promptForIdeUpdates() {
|
|
@@ -3780,17 +3911,17 @@ ${runSetupSubprocess("cursor")}`;
|
|
|
3780
3911
|
async function handleUpdate(opts) {
|
|
3781
3912
|
try {
|
|
3782
3913
|
const currentVersion = getCurrentVersion();
|
|
3783
|
-
let output =
|
|
3784
|
-
output += `${
|
|
3914
|
+
let output = chalk10.bold.cyan("\n\u{1F504} BrainGrid CLI Update\n\n");
|
|
3915
|
+
output += `${chalk10.bold("Current version:")} ${currentVersion}
|
|
3785
3916
|
`;
|
|
3786
|
-
output +=
|
|
3917
|
+
output += chalk10.dim("Checking for updates...\n");
|
|
3787
3918
|
const latestVersion = await getLatestVersion();
|
|
3788
|
-
output += `${
|
|
3919
|
+
output += `${chalk10.bold("Latest version:")} ${latestVersion}
|
|
3789
3920
|
|
|
3790
3921
|
`;
|
|
3791
3922
|
const comparison = compareVersions(currentVersion, latestVersion);
|
|
3792
3923
|
if (comparison === 0) {
|
|
3793
|
-
output +=
|
|
3924
|
+
output += chalk10.green("\u2705 You are already on the latest version!\n");
|
|
3794
3925
|
console.log(output);
|
|
3795
3926
|
await copyBraingridReadme();
|
|
3796
3927
|
await addBraingridTempToGitignore();
|
|
@@ -3802,32 +3933,32 @@ async function handleUpdate(opts) {
|
|
|
3802
3933
|
};
|
|
3803
3934
|
}
|
|
3804
3935
|
if (comparison > 0) {
|
|
3805
|
-
output +=
|
|
3806
|
-
output +=
|
|
3936
|
+
output += chalk10.yellow("\u26A0\uFE0F You are on a newer version than what is published.\n");
|
|
3937
|
+
output += chalk10.dim(" This is expected if you are developing locally.\n");
|
|
3807
3938
|
return {
|
|
3808
3939
|
success: true,
|
|
3809
3940
|
message: output,
|
|
3810
3941
|
data: { currentVersion, latestVersion, upToDate: false }
|
|
3811
3942
|
};
|
|
3812
3943
|
}
|
|
3813
|
-
output +=
|
|
3944
|
+
output += chalk10.yellow(`\u2B06\uFE0F Update available: ${currentVersion} \u2192 ${latestVersion}
|
|
3814
3945
|
|
|
3815
3946
|
`);
|
|
3816
3947
|
if (opts.check) {
|
|
3817
|
-
output +=
|
|
3948
|
+
output += chalk10.dim("Run ") + chalk10.cyan("braingrid update") + chalk10.dim(" to update\n");
|
|
3818
3949
|
return {
|
|
3819
3950
|
success: true,
|
|
3820
3951
|
message: output,
|
|
3821
3952
|
data: { currentVersion, latestVersion, upToDate: false }
|
|
3822
3953
|
};
|
|
3823
3954
|
}
|
|
3824
|
-
output +=
|
|
3955
|
+
output += chalk10.dim("Detecting package manager...\n");
|
|
3825
3956
|
const packageManager = await detectPackageManager(PACKAGE_NAME);
|
|
3826
|
-
output += `${
|
|
3957
|
+
output += `${chalk10.bold("Package manager:")} ${packageManager}
|
|
3827
3958
|
|
|
3828
3959
|
`;
|
|
3829
3960
|
const updateCommand = getUpdateCommand2(packageManager, PACKAGE_NAME);
|
|
3830
|
-
output += `${
|
|
3961
|
+
output += `${chalk10.dim("Running: ") + chalk10.cyan(updateCommand)}
|
|
3831
3962
|
|
|
3832
3963
|
`;
|
|
3833
3964
|
console.log(output);
|
|
@@ -3837,7 +3968,7 @@ async function handleUpdate(opts) {
|
|
|
3837
3968
|
const setupOutput = await promptForIdeUpdates();
|
|
3838
3969
|
return {
|
|
3839
3970
|
success: true,
|
|
3840
|
-
message:
|
|
3971
|
+
message: chalk10.green("\n\u2705 Successfully updated BrainGrid CLI!\n") + setupOutput,
|
|
3841
3972
|
data: { currentVersion, latestVersion, packageManager }
|
|
3842
3973
|
};
|
|
3843
3974
|
} catch (error) {
|
|
@@ -3875,12 +4006,12 @@ function getServices() {
|
|
|
3875
4006
|
function promptToAddOrganization(owner, webUrl) {
|
|
3876
4007
|
return {
|
|
3877
4008
|
success: false,
|
|
3878
|
-
message:
|
|
4009
|
+
message: chalk11.yellow("\u26A0\uFE0F No projects found for this repository.\n\n") + chalk11.dim(`Repository: ${owner}/*
|
|
3879
4010
|
|
|
3880
|
-
`) +
|
|
4011
|
+
`) + chalk11.dim(`You have GitHub connected, but not for the "${owner}" organization.
|
|
3881
4012
|
|
|
3882
|
-
`) +
|
|
3883
|
-
`) +
|
|
4013
|
+
`) + 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}"
|
|
4014
|
+
`) + chalk11.dim(" 4. Run ") + chalk11.cyan("braingrid init") + chalk11.dim(" again")
|
|
3884
4015
|
};
|
|
3885
4016
|
}
|
|
3886
4017
|
async function promptToCreateProject(gitInfo, projectService, repositoryService) {
|
|
@@ -3888,20 +4019,20 @@ async function promptToCreateProject(gitInfo, projectService, repositoryService)
|
|
|
3888
4019
|
if (!gitInfo.owner || !gitInfo.name) {
|
|
3889
4020
|
return {
|
|
3890
4021
|
success: false,
|
|
3891
|
-
message:
|
|
4022
|
+
message: chalk11.red("\u274C Repository information is incomplete")
|
|
3892
4023
|
};
|
|
3893
4024
|
}
|
|
3894
4025
|
const repositoryId = await getRepositoryId(repositoryService, gitInfo.owner, gitInfo.name);
|
|
3895
4026
|
if (!repositoryId) {
|
|
3896
4027
|
return {
|
|
3897
4028
|
success: false,
|
|
3898
|
-
message:
|
|
4029
|
+
message: chalk11.yellow("\u26A0\uFE0F Repository accessible but could not retrieve details.\n\n") + chalk11.dim(`Repository: ${gitInfo.owner}/${gitInfo.name}
|
|
3899
4030
|
|
|
3900
|
-
`) +
|
|
4031
|
+
`) + chalk11.dim("Please try again or create a project manually at: ") + chalk11.cyan(webUrl)
|
|
3901
4032
|
};
|
|
3902
4033
|
}
|
|
3903
4034
|
console.log(
|
|
3904
|
-
|
|
4035
|
+
chalk11.yellow("\u26A0\uFE0F Repository accessible but no project exists.\n\n") + chalk11.dim(`Repository: ${gitInfo.owner}/${gitInfo.name}
|
|
3905
4036
|
`)
|
|
3906
4037
|
);
|
|
3907
4038
|
const shouldCreate = await confirm2({
|
|
@@ -3911,7 +4042,7 @@ async function promptToCreateProject(gitInfo, projectService, repositoryService)
|
|
|
3911
4042
|
if (!shouldCreate) {
|
|
3912
4043
|
return {
|
|
3913
4044
|
success: false,
|
|
3914
|
-
message:
|
|
4045
|
+
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
4046
|
`braingrid project create --name "${gitInfo.name}" --repositories "${gitInfo.owner}/${gitInfo.name}"`
|
|
3916
4047
|
)
|
|
3917
4048
|
};
|
|
@@ -3922,9 +4053,9 @@ async function promptToCreateProject(gitInfo, projectService, repositoryService)
|
|
|
3922
4053
|
description: `Project for ${gitInfo.owner}/${gitInfo.name}`,
|
|
3923
4054
|
repository_id: repositoryId
|
|
3924
4055
|
});
|
|
3925
|
-
console.log(
|
|
4056
|
+
console.log(chalk11.green(`
|
|
3926
4057
|
\u2705 Created project ${project2.short_id}: ${project2.name}`));
|
|
3927
|
-
console.log(
|
|
4058
|
+
console.log(chalk11.green(`\u2705 Linked repository ${gitInfo.owner}/${gitInfo.name}
|
|
3928
4059
|
`));
|
|
3929
4060
|
return { success: true, message: "", data: project2 };
|
|
3930
4061
|
} catch (error) {
|
|
@@ -3938,18 +4069,18 @@ async function promptToGrantRepositoryAccess(gitInfo, webUrl, repositoryService,
|
|
|
3938
4069
|
if (!gitInfo.owner || !gitInfo.name) {
|
|
3939
4070
|
return {
|
|
3940
4071
|
success: false,
|
|
3941
|
-
message:
|
|
4072
|
+
message: chalk11.red("\u274C Repository information is incomplete")
|
|
3942
4073
|
};
|
|
3943
4074
|
}
|
|
3944
4075
|
const owner = gitInfo.owner;
|
|
3945
4076
|
const name = gitInfo.name;
|
|
3946
4077
|
console.log(
|
|
3947
|
-
|
|
4078
|
+
chalk11.yellow("\u26A0\uFE0F Repository found but BrainGrid needs access.\n\n") + chalk11.dim(`Repository: ${owner}/${name}
|
|
3948
4079
|
|
|
3949
|
-
`) +
|
|
4080
|
+
`) + chalk11.dim("Please grant BrainGrid access to this repository:\n") + chalk11.dim(" 1. Visit: ") + chalk11.cyan(`${webUrl}/integrations`) + chalk11.dim("\n") + chalk11.dim(
|
|
3950
4081
|
` 2. Click on your "${owner}" installation "Add/Remove" to grant BrainGrid access to your repository
|
|
3951
4082
|
`
|
|
3952
|
-
) +
|
|
4083
|
+
) + chalk11.dim(` 3. Select "${name}" and save
|
|
3953
4084
|
|
|
3954
4085
|
`)
|
|
3955
4086
|
);
|
|
@@ -3962,10 +4093,10 @@ async function promptToGrantRepositoryAccess(gitInfo, webUrl, repositoryService,
|
|
|
3962
4093
|
if (!accessGranted) {
|
|
3963
4094
|
return {
|
|
3964
4095
|
success: false,
|
|
3965
|
-
message:
|
|
4096
|
+
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
4097
|
};
|
|
3967
4098
|
}
|
|
3968
|
-
console.log(
|
|
4099
|
+
console.log(chalk11.green("\u2705 Repository access granted!\n"));
|
|
3969
4100
|
return promptToCreateProject(gitInfo, projectService, repositoryService);
|
|
3970
4101
|
}
|
|
3971
4102
|
async function handleNoProjectForRepository(owner, name, gitInfo, githubService, repositoryService, projectService, config2) {
|
|
@@ -3980,9 +4111,9 @@ async function handleNoProjectForRepository(owner, name, gitInfo, githubService,
|
|
|
3980
4111
|
if (allInstallations.length === 0) {
|
|
3981
4112
|
return {
|
|
3982
4113
|
success: false,
|
|
3983
|
-
message:
|
|
4114
|
+
message: chalk11.yellow("\u26A0\uFE0F No projects found for this repository.\n\n") + chalk11.dim(`Repository: ${owner}/${name}
|
|
3984
4115
|
|
|
3985
|
-
`) +
|
|
4116
|
+
`) + 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
4117
|
};
|
|
3987
4118
|
}
|
|
3988
4119
|
const ownerInstallation = findInstallationForOwner(owner, allInstallations);
|
|
@@ -3998,28 +4129,28 @@ async function handleNoProjectForRepository(owner, name, gitInfo, githubService,
|
|
|
3998
4129
|
function showSetupInstructions(scenario) {
|
|
3999
4130
|
let message = "";
|
|
4000
4131
|
if (scenario === "no-git") {
|
|
4001
|
-
message +=
|
|
4002
|
-
message +=
|
|
4003
|
-
message +=
|
|
4132
|
+
message += chalk11.dim("To initialize BrainGrid locally:\n\n");
|
|
4133
|
+
message += chalk11.dim(" 1. Initialize git:\n");
|
|
4134
|
+
message += chalk11.cyan(" git init\n\n");
|
|
4004
4135
|
} else {
|
|
4005
|
-
message +=
|
|
4136
|
+
message += chalk11.dim("To connect to GitHub:\n\n");
|
|
4006
4137
|
}
|
|
4007
|
-
message +=
|
|
4008
|
-
message +=
|
|
4009
|
-
message +=
|
|
4010
|
-
message +=
|
|
4138
|
+
message += chalk11.dim(" 2. Create GitHub repository:\n");
|
|
4139
|
+
message += chalk11.dim(" \u2022 Install GitHub CLI: ") + chalk11.cyan("https://cli.github.com\n");
|
|
4140
|
+
message += chalk11.dim(" Then: ") + chalk11.cyan("gh repo create --private --source=.\n");
|
|
4141
|
+
message += chalk11.dim(" \u2022 Or manually: ") + chalk11.cyan("https://github.com/new\n\n");
|
|
4011
4142
|
if (scenario === "no-git") {
|
|
4012
|
-
message +=
|
|
4143
|
+
message += chalk11.dim(" 3. Run: ") + chalk11.cyan("braingrid init\n\n");
|
|
4013
4144
|
} else {
|
|
4014
|
-
message +=
|
|
4015
|
-
message +=
|
|
4016
|
-
message +=
|
|
4145
|
+
message += chalk11.dim(" 3. Add remote and run init:\n");
|
|
4146
|
+
message += chalk11.cyan(" git remote add origin <url>\n");
|
|
4147
|
+
message += chalk11.cyan(" braingrid init\n\n");
|
|
4017
4148
|
}
|
|
4018
|
-
message +=
|
|
4019
|
-
message +=
|
|
4020
|
-
message +=
|
|
4021
|
-
message +=
|
|
4022
|
-
message += `${
|
|
4149
|
+
message += chalk11.bold("Or use BrainGrid without local initialization:\n\n");
|
|
4150
|
+
message += chalk11.dim(" All commands support the --project flag:\n");
|
|
4151
|
+
message += chalk11.cyan(" braingrid requirement list --project PROJ-123\n");
|
|
4152
|
+
message += chalk11.cyan(' braingrid task create --project PROJ-123 --title "Task"\n\n');
|
|
4153
|
+
message += `${chalk11.dim(" Note: Without local init, you must specify --project for each command.")}
|
|
4023
4154
|
`;
|
|
4024
4155
|
return message;
|
|
4025
4156
|
}
|
|
@@ -4036,10 +4167,10 @@ async function handleNoGitRepository() {
|
|
|
4036
4167
|
if (!gitInitSuccess) {
|
|
4037
4168
|
return {
|
|
4038
4169
|
success: false,
|
|
4039
|
-
message:
|
|
4170
|
+
message: chalk11.red("\u274C Failed to initialize git repository")
|
|
4040
4171
|
};
|
|
4041
4172
|
}
|
|
4042
|
-
console.log(
|
|
4173
|
+
console.log(chalk11.green("\u2705 Initialized git repository"));
|
|
4043
4174
|
const dirName = getCurrentDirectoryName();
|
|
4044
4175
|
const isPrivate = await select3({
|
|
4045
4176
|
message: "Repository visibility:",
|
|
@@ -4053,16 +4184,16 @@ async function handleNoGitRepository() {
|
|
|
4053
4184
|
message: "Repository name:",
|
|
4054
4185
|
default: dirName
|
|
4055
4186
|
});
|
|
4056
|
-
console.log(
|
|
4187
|
+
console.log(chalk11.dim("\nCreating repository...\n"));
|
|
4057
4188
|
const repo = await createGitHubRepoWithGh(repoName, isPrivate);
|
|
4058
4189
|
if (!repo) {
|
|
4059
4190
|
return {
|
|
4060
4191
|
success: false,
|
|
4061
|
-
message:
|
|
4192
|
+
message: chalk11.red("\u274C Failed to create GitHub repository\n\n") + showSetupInstructions("no-git")
|
|
4062
4193
|
};
|
|
4063
4194
|
}
|
|
4064
|
-
console.log(
|
|
4065
|
-
console.log(
|
|
4195
|
+
console.log(chalk11.green(`\u2705 Created repository: ${repo.url}`));
|
|
4196
|
+
console.log(chalk11.green("\u2705 Added remote origin\n"));
|
|
4066
4197
|
return {
|
|
4067
4198
|
success: true,
|
|
4068
4199
|
message: "continue-init",
|
|
@@ -4073,7 +4204,7 @@ async function handleNoGitRepository() {
|
|
|
4073
4204
|
}
|
|
4074
4205
|
return {
|
|
4075
4206
|
success: false,
|
|
4076
|
-
message:
|
|
4207
|
+
message: chalk11.yellow("\u26A0\uFE0F This directory is not a git repository.\n\n") + showSetupInstructions("no-git")
|
|
4077
4208
|
};
|
|
4078
4209
|
}
|
|
4079
4210
|
async function handleNoGitRemote() {
|
|
@@ -4097,16 +4228,16 @@ async function handleNoGitRemote() {
|
|
|
4097
4228
|
message: "Repository name:",
|
|
4098
4229
|
default: dirName
|
|
4099
4230
|
});
|
|
4100
|
-
console.log(
|
|
4231
|
+
console.log(chalk11.dim("\nCreating repository...\n"));
|
|
4101
4232
|
const repo = await createGitHubRepoWithGh(repoName, isPrivate);
|
|
4102
4233
|
if (!repo) {
|
|
4103
4234
|
return {
|
|
4104
4235
|
success: false,
|
|
4105
|
-
message:
|
|
4236
|
+
message: chalk11.red("\u274C Failed to create GitHub repository\n\n") + showSetupInstructions("no-remote")
|
|
4106
4237
|
};
|
|
4107
4238
|
}
|
|
4108
|
-
console.log(
|
|
4109
|
-
console.log(
|
|
4239
|
+
console.log(chalk11.green(`\u2705 Created repository: ${repo.url}`));
|
|
4240
|
+
console.log(chalk11.green("\u2705 Added remote origin\n"));
|
|
4110
4241
|
return {
|
|
4111
4242
|
success: true,
|
|
4112
4243
|
message: "continue-init",
|
|
@@ -4117,7 +4248,7 @@ async function handleNoGitRemote() {
|
|
|
4117
4248
|
}
|
|
4118
4249
|
return {
|
|
4119
4250
|
success: false,
|
|
4120
|
-
message:
|
|
4251
|
+
message: chalk11.yellow("\u26A0\uFE0F Git repository detected but no GitHub remote configured.\n\n") + showSetupInstructions("no-remote")
|
|
4121
4252
|
};
|
|
4122
4253
|
}
|
|
4123
4254
|
async function handleInit(opts) {
|
|
@@ -4125,8 +4256,8 @@ async function handleInit(opts) {
|
|
|
4125
4256
|
const updateInfo = await isUpdateAvailable();
|
|
4126
4257
|
if (updateInfo.available && updateInfo.latestVersion) {
|
|
4127
4258
|
console.log(
|
|
4128
|
-
|
|
4129
|
-
\u26A0\uFE0F A new version of BrainGrid CLI is available: `) +
|
|
4259
|
+
chalk11.yellow(`
|
|
4260
|
+
\u26A0\uFE0F A new version of BrainGrid CLI is available: `) + chalk11.dim(`${updateInfo.currentVersion} \u2192 `) + chalk11.green(updateInfo.latestVersion) + "\n"
|
|
4130
4261
|
);
|
|
4131
4262
|
const shouldUpdate = await confirm2({
|
|
4132
4263
|
message: "Would you like to update now?",
|
|
@@ -4137,7 +4268,7 @@ async function handleInit(opts) {
|
|
|
4137
4268
|
console.log(result.message);
|
|
4138
4269
|
return {
|
|
4139
4270
|
success: true,
|
|
4140
|
-
message:
|
|
4271
|
+
message: chalk11.dim("\nRun `braingrid init` again after the update completes.")
|
|
4141
4272
|
};
|
|
4142
4273
|
}
|
|
4143
4274
|
console.log();
|
|
@@ -4152,7 +4283,7 @@ async function handleInit(opts) {
|
|
|
4152
4283
|
if (!shouldInstall) {
|
|
4153
4284
|
return {
|
|
4154
4285
|
success: false,
|
|
4155
|
-
message:
|
|
4286
|
+
message: chalk11.yellow("\u26A0\uFE0F Git installation cancelled.\n\n") + getManualInstallInstructions()
|
|
4156
4287
|
};
|
|
4157
4288
|
}
|
|
4158
4289
|
console.log();
|
|
@@ -4168,14 +4299,14 @@ async function handleInit(opts) {
|
|
|
4168
4299
|
if (!await isGitInstalled()) {
|
|
4169
4300
|
return {
|
|
4170
4301
|
success: false,
|
|
4171
|
-
message:
|
|
4302
|
+
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
4303
|
};
|
|
4173
4304
|
}
|
|
4174
4305
|
}
|
|
4175
4306
|
if (!await isGhInstalled()) {
|
|
4176
|
-
console.log(
|
|
4307
|
+
console.log(chalk11.blue("\n\u{1F4A1} GitHub CLI is highly recommended for working with BrainGrid."));
|
|
4177
4308
|
console.log(
|
|
4178
|
-
|
|
4309
|
+
chalk11.dim(" It enables seamless GitHub integration and repository management.\n")
|
|
4179
4310
|
);
|
|
4180
4311
|
const shouldInstallGh = await confirm2({
|
|
4181
4312
|
message: "Would you like to install GitHub CLI now?",
|
|
@@ -4189,10 +4320,10 @@ async function handleInit(opts) {
|
|
|
4189
4320
|
console.log();
|
|
4190
4321
|
} else {
|
|
4191
4322
|
console.log(ghInstallResult.message);
|
|
4192
|
-
console.log(
|
|
4323
|
+
console.log(chalk11.dim("You can install it manually later.\n"));
|
|
4193
4324
|
}
|
|
4194
4325
|
} else {
|
|
4195
|
-
console.log(
|
|
4326
|
+
console.log(chalk11.dim("Skipping GitHub CLI installation.\n"));
|
|
4196
4327
|
}
|
|
4197
4328
|
}
|
|
4198
4329
|
if (await projectConfigExists() && !opts.force) {
|
|
@@ -4200,15 +4331,15 @@ async function handleInit(opts) {
|
|
|
4200
4331
|
const existing = await loadProjectConfig();
|
|
4201
4332
|
return {
|
|
4202
4333
|
success: false,
|
|
4203
|
-
message:
|
|
4204
|
-
`) +
|
|
4334
|
+
message: chalk11.yellow("\u26A0\uFE0F Already initialized.\n\n") + chalk11.dim(`Project: ${existing.project_name} (${existing.project_short_id})
|
|
4335
|
+
`) + chalk11.dim(`Repository: ${existing.repository?.full_name || "N/A"}
|
|
4205
4336
|
|
|
4206
|
-
`) +
|
|
4337
|
+
`) + chalk11.dim("Use --force to reinitialize")
|
|
4207
4338
|
};
|
|
4208
4339
|
} catch {
|
|
4209
4340
|
return {
|
|
4210
4341
|
success: false,
|
|
4211
|
-
message:
|
|
4342
|
+
message: chalk11.yellow("\u26A0\uFE0F Invalid project configuration found.\n") + chalk11.dim("Use --force to reinitialize")
|
|
4212
4343
|
};
|
|
4213
4344
|
}
|
|
4214
4345
|
}
|
|
@@ -4221,7 +4352,7 @@ async function handleInit(opts) {
|
|
|
4221
4352
|
if (!shouldLogin) {
|
|
4222
4353
|
return {
|
|
4223
4354
|
success: false,
|
|
4224
|
-
message:
|
|
4355
|
+
message: chalk11.yellow("\u26A0\uFE0F Authentication required.\n") + chalk11.dim("Run ") + chalk11.cyan("braingrid login") + chalk11.dim(" when you're ready to authenticate.")
|
|
4225
4356
|
};
|
|
4226
4357
|
}
|
|
4227
4358
|
console.log();
|
|
@@ -4229,13 +4360,13 @@ async function handleInit(opts) {
|
|
|
4229
4360
|
if (!loginResult.success) {
|
|
4230
4361
|
return {
|
|
4231
4362
|
success: false,
|
|
4232
|
-
message:
|
|
4363
|
+
message: chalk11.red("\u274C Login failed.\n") + chalk11.dim("Please try running ") + chalk11.cyan("braingrid login") + chalk11.dim(" again.")
|
|
4233
4364
|
};
|
|
4234
4365
|
}
|
|
4235
4366
|
if (!await auth.isAuthenticated()) {
|
|
4236
4367
|
return {
|
|
4237
4368
|
success: false,
|
|
4238
|
-
message:
|
|
4369
|
+
message: chalk11.red("\u274C Login was not completed.\n") + chalk11.dim("Please try running ") + chalk11.cyan("braingrid login") + chalk11.dim(" again.")
|
|
4239
4370
|
};
|
|
4240
4371
|
}
|
|
4241
4372
|
console.log();
|
|
@@ -4244,27 +4375,27 @@ async function handleInit(opts) {
|
|
|
4244
4375
|
if (!session) {
|
|
4245
4376
|
return {
|
|
4246
4377
|
success: false,
|
|
4247
|
-
message:
|
|
4378
|
+
message: chalk11.red("\u274C No session found. Please run `braingrid login` first.")
|
|
4248
4379
|
};
|
|
4249
4380
|
}
|
|
4250
4381
|
if (session.organization_id === "default") {
|
|
4251
|
-
console.log(
|
|
4382
|
+
console.log(chalk11.yellow("\u26A0\uFE0F Organization ID not set, validating session...\n"));
|
|
4252
4383
|
const isValid = await auth.isAuthenticated();
|
|
4253
4384
|
if (!isValid) {
|
|
4254
4385
|
return {
|
|
4255
4386
|
success: false,
|
|
4256
|
-
message:
|
|
4387
|
+
message: chalk11.red("\u274C Session validation failed. Please run `braingrid login` again.")
|
|
4257
4388
|
};
|
|
4258
4389
|
}
|
|
4259
4390
|
const updatedSession = await auth.getStoredSession();
|
|
4260
4391
|
if (!updatedSession || updatedSession.organization_id === "default") {
|
|
4261
4392
|
return {
|
|
4262
4393
|
success: false,
|
|
4263
|
-
message:
|
|
4394
|
+
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
4395
|
};
|
|
4265
4396
|
}
|
|
4266
4397
|
Object.assign(session, updatedSession);
|
|
4267
|
-
console.log(
|
|
4398
|
+
console.log(chalk11.green("\u2705 Organization ID updated successfully\n"));
|
|
4268
4399
|
}
|
|
4269
4400
|
let gitInfo = await getGitRepositoryInfo();
|
|
4270
4401
|
let project2;
|
|
@@ -4274,9 +4405,9 @@ async function handleInit(opts) {
|
|
|
4274
4405
|
} catch {
|
|
4275
4406
|
return {
|
|
4276
4407
|
success: false,
|
|
4277
|
-
message:
|
|
4408
|
+
message: chalk11.red(`\u274C Project not found: ${opts.project}
|
|
4278
4409
|
|
|
4279
|
-
`) +
|
|
4410
|
+
`) + chalk11.dim("Make sure the project ID is correct and you have access to it.")
|
|
4280
4411
|
};
|
|
4281
4412
|
}
|
|
4282
4413
|
} else {
|
|
@@ -4287,7 +4418,7 @@ async function handleInit(opts) {
|
|
|
4287
4418
|
if (!gitInfo || !gitInfo.owner || !gitInfo.name) {
|
|
4288
4419
|
return {
|
|
4289
4420
|
success: false,
|
|
4290
|
-
message:
|
|
4421
|
+
message: chalk11.red("\u274C Failed to get repository information after setup")
|
|
4291
4422
|
};
|
|
4292
4423
|
}
|
|
4293
4424
|
} else {
|
|
@@ -4301,7 +4432,7 @@ async function handleInit(opts) {
|
|
|
4301
4432
|
if (!gitInfo || !gitInfo.owner || !gitInfo.name) {
|
|
4302
4433
|
return {
|
|
4303
4434
|
success: false,
|
|
4304
|
-
message:
|
|
4435
|
+
message: chalk11.red("\u274C Failed to get repository information after setup")
|
|
4305
4436
|
};
|
|
4306
4437
|
}
|
|
4307
4438
|
} else {
|
|
@@ -4311,7 +4442,7 @@ async function handleInit(opts) {
|
|
|
4311
4442
|
if (!gitInfo) {
|
|
4312
4443
|
return {
|
|
4313
4444
|
success: false,
|
|
4314
|
-
message:
|
|
4445
|
+
message: chalk11.red("\u274C Repository information is missing")
|
|
4315
4446
|
};
|
|
4316
4447
|
}
|
|
4317
4448
|
const owner = gitInfo.owner;
|
|
@@ -4319,7 +4450,7 @@ async function handleInit(opts) {
|
|
|
4319
4450
|
if (!owner || !name) {
|
|
4320
4451
|
return {
|
|
4321
4452
|
success: false,
|
|
4322
|
-
message:
|
|
4453
|
+
message: chalk11.red("\u274C Repository information is incomplete")
|
|
4323
4454
|
};
|
|
4324
4455
|
}
|
|
4325
4456
|
let response;
|
|
@@ -4358,8 +4489,8 @@ async function handleInit(opts) {
|
|
|
4358
4489
|
}
|
|
4359
4490
|
project2 = response.projects[0];
|
|
4360
4491
|
}
|
|
4361
|
-
const projectInfo =
|
|
4362
|
-
` : "") +
|
|
4492
|
+
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)}
|
|
4493
|
+
` : "") + chalk11.dim("Repository: ") + chalk11.gray(project2.repository?.full_name || "N/A") + "\n\n";
|
|
4363
4494
|
console.log(projectInfo);
|
|
4364
4495
|
if (!opts.force) {
|
|
4365
4496
|
const shouldInit = await confirm2({
|
|
@@ -4369,7 +4500,7 @@ async function handleInit(opts) {
|
|
|
4369
4500
|
if (!shouldInit) {
|
|
4370
4501
|
return {
|
|
4371
4502
|
success: false,
|
|
4372
|
-
message:
|
|
4503
|
+
message: chalk11.yellow("Initialization cancelled.")
|
|
4373
4504
|
};
|
|
4374
4505
|
}
|
|
4375
4506
|
}
|
|
@@ -4394,7 +4525,7 @@ async function handleInit(opts) {
|
|
|
4394
4525
|
await addBraingridTempToGitignore();
|
|
4395
4526
|
await copyBraingridReadme();
|
|
4396
4527
|
console.log(
|
|
4397
|
-
|
|
4528
|
+
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
4529
|
);
|
|
4399
4530
|
const installedIDEs = await detectInstalledIDEs();
|
|
4400
4531
|
if (installedIDEs.claudeCode) {
|
|
@@ -4413,15 +4544,15 @@ async function handleInit(opts) {
|
|
|
4413
4544
|
if (result.success) {
|
|
4414
4545
|
console.log(result.message);
|
|
4415
4546
|
} else {
|
|
4416
|
-
console.log(
|
|
4547
|
+
console.log(chalk11.yellow("\u26A0\uFE0F Claude Code setup was not completed."));
|
|
4417
4548
|
console.log(
|
|
4418
|
-
|
|
4549
|
+
chalk11.dim("You can run ") + chalk11.cyan("braingrid setup claude-code") + chalk11.dim(" later.")
|
|
4419
4550
|
);
|
|
4420
4551
|
}
|
|
4421
4552
|
} catch {
|
|
4422
|
-
console.log(
|
|
4553
|
+
console.log(chalk11.yellow("\u26A0\uFE0F Claude Code setup encountered an error."));
|
|
4423
4554
|
console.log(
|
|
4424
|
-
|
|
4555
|
+
chalk11.dim("You can run ") + chalk11.cyan("braingrid setup claude-code") + chalk11.dim(" later.")
|
|
4425
4556
|
);
|
|
4426
4557
|
}
|
|
4427
4558
|
console.log("");
|
|
@@ -4443,15 +4574,15 @@ async function handleInit(opts) {
|
|
|
4443
4574
|
if (result.success) {
|
|
4444
4575
|
console.log(result.message);
|
|
4445
4576
|
} else {
|
|
4446
|
-
console.log(
|
|
4577
|
+
console.log(chalk11.yellow("\u26A0\uFE0F Cursor setup was not completed."));
|
|
4447
4578
|
console.log(
|
|
4448
|
-
|
|
4579
|
+
chalk11.dim("You can run ") + chalk11.cyan("braingrid setup cursor") + chalk11.dim(" later.")
|
|
4449
4580
|
);
|
|
4450
4581
|
}
|
|
4451
4582
|
} catch {
|
|
4452
|
-
console.log(
|
|
4583
|
+
console.log(chalk11.yellow("\u26A0\uFE0F Cursor setup encountered an error."));
|
|
4453
4584
|
console.log(
|
|
4454
|
-
|
|
4585
|
+
chalk11.dim("You can run ") + chalk11.cyan("braingrid setup cursor") + chalk11.dim(" later.")
|
|
4455
4586
|
);
|
|
4456
4587
|
}
|
|
4457
4588
|
console.log("");
|
|
@@ -4459,7 +4590,7 @@ async function handleInit(opts) {
|
|
|
4459
4590
|
}
|
|
4460
4591
|
return {
|
|
4461
4592
|
success: true,
|
|
4462
|
-
message:
|
|
4593
|
+
message: chalk11.dim(
|
|
4463
4594
|
"You can now use project-scoped commands without specifying a project ID."
|
|
4464
4595
|
),
|
|
4465
4596
|
data: localConfig
|
|
@@ -4473,10 +4604,10 @@ async function handleInit(opts) {
|
|
|
4473
4604
|
}
|
|
4474
4605
|
|
|
4475
4606
|
// src/handlers/project.handlers.ts
|
|
4476
|
-
import
|
|
4607
|
+
import chalk14 from "chalk";
|
|
4477
4608
|
|
|
4478
4609
|
// src/utils/formatting.ts
|
|
4479
|
-
import
|
|
4610
|
+
import chalk12 from "chalk";
|
|
4480
4611
|
|
|
4481
4612
|
// src/utils/id-normalization.ts
|
|
4482
4613
|
function normalizeId(prefix, input2) {
|
|
@@ -4518,7 +4649,7 @@ function getWebUiUrl(apiUrl) {
|
|
|
4518
4649
|
}
|
|
4519
4650
|
function formatTasksListOutput(tasks, format, verbose, options) {
|
|
4520
4651
|
if (tasks.length === 0) {
|
|
4521
|
-
return
|
|
4652
|
+
return chalk12.yellow("No tasks found.");
|
|
4522
4653
|
}
|
|
4523
4654
|
switch (format) {
|
|
4524
4655
|
case "json":
|
|
@@ -4548,7 +4679,7 @@ function formatTasksListOutput(tasks, format, verbose, options) {
|
|
|
4548
4679
|
}
|
|
4549
4680
|
}
|
|
4550
4681
|
function formatTasksListTable(tasks) {
|
|
4551
|
-
let output =
|
|
4682
|
+
let output = chalk12.bold(`\u{1F4CB} Tasks (${tasks.length})
|
|
4552
4683
|
|
|
4553
4684
|
`);
|
|
4554
4685
|
output += "ID Short ID Status Title Assigned To Blocked\n";
|
|
@@ -4568,58 +4699,58 @@ function formatTasksListTable(tasks) {
|
|
|
4568
4699
|
return output;
|
|
4569
4700
|
}
|
|
4570
4701
|
function formatTasksListVerbose(tasks, options) {
|
|
4571
|
-
let output =
|
|
4702
|
+
let output = chalk12.bold(`\u{1F4CB} Tasks (${tasks.length})
|
|
4572
4703
|
|
|
4573
4704
|
`);
|
|
4574
|
-
const divider =
|
|
4705
|
+
const divider = chalk12.gray("\u2500".repeat(50));
|
|
4575
4706
|
for (let i = 0; i < tasks.length; i++) {
|
|
4576
4707
|
const task2 = tasks[i];
|
|
4577
4708
|
const statusEmoji = getTaskStatusEmoji(task2.status);
|
|
4578
|
-
output += `${statusEmoji} ${
|
|
4709
|
+
output += `${statusEmoji} ${chalk12.bold(task2.title)}
|
|
4579
4710
|
`;
|
|
4580
|
-
output += `${
|
|
4711
|
+
output += `${chalk12.bold("Short ID:")} TASK-${task2.number}
|
|
4581
4712
|
`;
|
|
4582
|
-
output += `${
|
|
4713
|
+
output += `${chalk12.bold("ID:")} ${task2.id}
|
|
4583
4714
|
`;
|
|
4584
4715
|
if (options?.apiUrl && options?.requirementId) {
|
|
4585
4716
|
const webUiUrl = getWebUiUrl(options.apiUrl);
|
|
4586
|
-
output += `${
|
|
4717
|
+
output += `${chalk12.bold("URL:")} ${webUiUrl}/requirements/overview?id=${options.requirementId}&tab=tasks
|
|
4587
4718
|
`;
|
|
4588
4719
|
}
|
|
4589
|
-
output += `${
|
|
4720
|
+
output += `${chalk12.bold("Project:")} ${options?.projectShortId || "N/A"}
|
|
4590
4721
|
`;
|
|
4591
|
-
output += `${
|
|
4722
|
+
output += `${chalk12.bold("Requirement:")} ${options?.requirementShortId || "N/A"}
|
|
4592
4723
|
`;
|
|
4593
|
-
output += `${
|
|
4724
|
+
output += `${chalk12.bold("Status:")} ${task2.status}
|
|
4594
4725
|
`;
|
|
4595
4726
|
if (task2.assigned_to) {
|
|
4596
|
-
output += `${
|
|
4727
|
+
output += `${chalk12.bold("Assigned to:")} ${task2.assigned_to}
|
|
4597
4728
|
`;
|
|
4598
4729
|
} else {
|
|
4599
|
-
output += `${
|
|
4730
|
+
output += `${chalk12.bold("Assigned to:")} Unassigned
|
|
4600
4731
|
`;
|
|
4601
4732
|
}
|
|
4602
4733
|
if (task2.created_at) {
|
|
4603
|
-
output += `${
|
|
4734
|
+
output += `${chalk12.bold("Created:")} ${new Date(task2.created_at).toLocaleString()}
|
|
4604
4735
|
`;
|
|
4605
4736
|
}
|
|
4606
4737
|
if (task2.updated_at) {
|
|
4607
|
-
output += `${
|
|
4738
|
+
output += `${chalk12.bold("Updated:")} ${new Date(task2.updated_at).toLocaleString()}
|
|
4608
4739
|
`;
|
|
4609
4740
|
}
|
|
4610
4741
|
if (task2.started_at) {
|
|
4611
|
-
output += `${
|
|
4742
|
+
output += `${chalk12.bold("Started:")} ${new Date(task2.started_at).toLocaleString()}
|
|
4612
4743
|
`;
|
|
4613
4744
|
}
|
|
4614
4745
|
if (task2.finished_at) {
|
|
4615
|
-
output += `${
|
|
4746
|
+
output += `${chalk12.bold("Finished:")} ${new Date(task2.finished_at).toLocaleString()}
|
|
4616
4747
|
`;
|
|
4617
4748
|
}
|
|
4618
4749
|
if (task2.content) {
|
|
4619
4750
|
output += `
|
|
4620
4751
|
${divider}
|
|
4621
4752
|
`;
|
|
4622
|
-
output += `${
|
|
4753
|
+
output += `${chalk12.bold("Content:")}
|
|
4623
4754
|
${task2.content}
|
|
4624
4755
|
`;
|
|
4625
4756
|
output += `${divider}
|
|
@@ -4627,12 +4758,12 @@ ${task2.content}
|
|
|
4627
4758
|
}
|
|
4628
4759
|
if (task2.blocked_by && task2.blocked_by.length > 0) {
|
|
4629
4760
|
output += `
|
|
4630
|
-
${
|
|
4761
|
+
${chalk12.bold("Blocked by:")} ${task2.blocked_by.join(", ")}
|
|
4631
4762
|
`;
|
|
4632
4763
|
}
|
|
4633
4764
|
if (i < tasks.length - 1) {
|
|
4634
4765
|
output += `
|
|
4635
|
-
${
|
|
4766
|
+
${chalk12.gray("\u2550".repeat(50))}
|
|
4636
4767
|
|
|
4637
4768
|
`;
|
|
4638
4769
|
}
|
|
@@ -4845,57 +4976,57 @@ function getRequirementStatusEmoji(status) {
|
|
|
4845
4976
|
}
|
|
4846
4977
|
function formatRequirementOutput(requirement2, options) {
|
|
4847
4978
|
const statusEmoji = getRequirementStatusEmoji(requirement2.status);
|
|
4848
|
-
const divider =
|
|
4979
|
+
const divider = chalk12.gray("\u2500".repeat(50));
|
|
4849
4980
|
let message = "";
|
|
4850
4981
|
if (options?.successMessage) {
|
|
4851
|
-
message +=
|
|
4982
|
+
message += chalk12.green(`\u2705 ${options.successMessage}
|
|
4852
4983
|
|
|
4853
4984
|
`);
|
|
4854
4985
|
}
|
|
4855
|
-
message += `${statusEmoji} ${
|
|
4986
|
+
message += `${statusEmoji} ${chalk12.bold(requirement2.name)}
|
|
4856
4987
|
|
|
4857
4988
|
`;
|
|
4858
|
-
message += `${
|
|
4989
|
+
message += `${chalk12.bold("Short ID:")} ${requirement2.short_id || "N/A"}
|
|
4859
4990
|
`;
|
|
4860
|
-
message += `${
|
|
4991
|
+
message += `${chalk12.bold("ID:")} ${requirement2.id}
|
|
4861
4992
|
`;
|
|
4862
4993
|
if (options?.apiUrl) {
|
|
4863
4994
|
const webUiUrl = getWebUiUrl(options.apiUrl);
|
|
4864
|
-
message += `${
|
|
4995
|
+
message += `${chalk12.bold("URL:")} ${webUiUrl}/requirements/overview?id=${requirement2.id}
|
|
4865
4996
|
`;
|
|
4866
4997
|
}
|
|
4867
|
-
message += `${
|
|
4998
|
+
message += `${chalk12.bold("Project:")} ${options?.projectShortId || "N/A"}
|
|
4868
4999
|
`;
|
|
4869
5000
|
if (requirement2.branch) {
|
|
4870
|
-
message += `${
|
|
5001
|
+
message += `${chalk12.bold("Branch:")} ${requirement2.branch}
|
|
4871
5002
|
`;
|
|
4872
5003
|
}
|
|
4873
|
-
message += `${
|
|
5004
|
+
message += `${chalk12.bold("Status:")} ${requirement2.status}
|
|
4874
5005
|
`;
|
|
4875
5006
|
if (requirement2.tags && requirement2.tags.length > 0) {
|
|
4876
5007
|
const tagNames = requirement2.tags.map((tag) => tag.name).join(", ");
|
|
4877
|
-
message += `${
|
|
5008
|
+
message += `${chalk12.bold("Tags:")} ${tagNames}
|
|
4878
5009
|
`;
|
|
4879
5010
|
}
|
|
4880
5011
|
if (requirement2.assignee) {
|
|
4881
5012
|
const assigneeName = requirement2.assignee.first_name || requirement2.assignee.last_name ? `${requirement2.assignee.first_name || ""} ${requirement2.assignee.last_name || ""}`.trim() : requirement2.assignee.email;
|
|
4882
|
-
message += `${
|
|
5013
|
+
message += `${chalk12.bold("Assigned to:")} ${assigneeName} (${requirement2.assignee.email})
|
|
4883
5014
|
`;
|
|
4884
5015
|
} else {
|
|
4885
|
-
message += `${
|
|
5016
|
+
message += `${chalk12.bold("Assigned to:")} Unassigned
|
|
4886
5017
|
`;
|
|
4887
5018
|
}
|
|
4888
|
-
message += `${
|
|
5019
|
+
message += `${chalk12.bold("Created:")} ${new Date(requirement2.created_at).toLocaleString()}
|
|
4889
5020
|
`;
|
|
4890
5021
|
if (options?.showUpdated) {
|
|
4891
|
-
message += `${
|
|
5022
|
+
message += `${chalk12.bold("Updated:")} ${new Date(requirement2.updated_at).toLocaleString()}
|
|
4892
5023
|
`;
|
|
4893
5024
|
}
|
|
4894
5025
|
if (options?.showDescription && requirement2.description) {
|
|
4895
5026
|
message += `
|
|
4896
5027
|
${divider}
|
|
4897
5028
|
`;
|
|
4898
|
-
message += `${
|
|
5029
|
+
message += `${chalk12.bold("Description:")}
|
|
4899
5030
|
${requirement2.description}
|
|
4900
5031
|
`;
|
|
4901
5032
|
message += `${divider}
|
|
@@ -4905,7 +5036,7 @@ ${requirement2.description}
|
|
|
4905
5036
|
message += `
|
|
4906
5037
|
${divider}
|
|
4907
5038
|
`;
|
|
4908
|
-
message += `${
|
|
5039
|
+
message += `${chalk12.bold("Content:")}
|
|
4909
5040
|
${requirement2.content}
|
|
4910
5041
|
`;
|
|
4911
5042
|
message += `${divider}
|
|
@@ -4913,7 +5044,7 @@ ${requirement2.content}
|
|
|
4913
5044
|
}
|
|
4914
5045
|
if (options?.showTaskList) {
|
|
4915
5046
|
message += `
|
|
4916
|
-
${
|
|
5047
|
+
${chalk12.bold("Tasks:")}
|
|
4917
5048
|
`;
|
|
4918
5049
|
if (requirement2.tasks && requirement2.tasks.length > 0) {
|
|
4919
5050
|
for (const task2 of requirement2.tasks) {
|
|
@@ -4929,7 +5060,7 @@ ${chalk11.bold("Tasks:")}
|
|
|
4929
5060
|
const completedTasks = tasks.filter((task2) => task2.status === "COMPLETED").length;
|
|
4930
5061
|
const totalTasks = tasks.length;
|
|
4931
5062
|
message += `
|
|
4932
|
-
${
|
|
5063
|
+
${chalk12.bold("Tasks:")} ${completedTasks}/${totalTasks} completed
|
|
4933
5064
|
`;
|
|
4934
5065
|
message += `${divider}
|
|
4935
5066
|
`;
|
|
@@ -4952,59 +5083,59 @@ function getTaskStatusEmoji(status) {
|
|
|
4952
5083
|
}
|
|
4953
5084
|
function formatTaskOutput(task2, options) {
|
|
4954
5085
|
const statusEmoji = getTaskStatusEmoji(task2.status);
|
|
4955
|
-
const divider =
|
|
5086
|
+
const divider = chalk12.gray("\u2500".repeat(50));
|
|
4956
5087
|
let message = "";
|
|
4957
5088
|
if (options?.successMessage) {
|
|
4958
|
-
message +=
|
|
5089
|
+
message += chalk12.green(`\u2705 ${options.successMessage}
|
|
4959
5090
|
|
|
4960
5091
|
`);
|
|
4961
5092
|
}
|
|
4962
|
-
message += `${statusEmoji} ${
|
|
5093
|
+
message += `${statusEmoji} ${chalk12.bold(task2.title)}
|
|
4963
5094
|
|
|
4964
5095
|
`;
|
|
4965
|
-
message += `${
|
|
5096
|
+
message += `${chalk12.bold("Short ID:")} TASK-${task2.number}
|
|
4966
5097
|
`;
|
|
4967
|
-
message += `${
|
|
5098
|
+
message += `${chalk12.bold("ID:")} ${task2.id}
|
|
4968
5099
|
`;
|
|
4969
5100
|
if (options?.apiUrl && options?.requirementId) {
|
|
4970
5101
|
const webUiUrl = getWebUiUrl(options.apiUrl);
|
|
4971
|
-
message += `${
|
|
5102
|
+
message += `${chalk12.bold("URL:")} ${webUiUrl}/requirements/overview?id=${options.requirementId}&tab=tasks
|
|
4972
5103
|
`;
|
|
4973
5104
|
}
|
|
4974
|
-
message += `${
|
|
5105
|
+
message += `${chalk12.bold("Project:")} ${options?.projectShortId || "N/A"}
|
|
4975
5106
|
`;
|
|
4976
|
-
message += `${
|
|
5107
|
+
message += `${chalk12.bold("Requirement:")} ${options?.requirementShortId || "N/A"}
|
|
4977
5108
|
`;
|
|
4978
|
-
message += `${
|
|
5109
|
+
message += `${chalk12.bold("Status:")} ${task2.status}
|
|
4979
5110
|
`;
|
|
4980
5111
|
if (task2.assigned_to) {
|
|
4981
|
-
message += `${
|
|
5112
|
+
message += `${chalk12.bold("Assigned to:")} ${task2.assigned_to}
|
|
4982
5113
|
`;
|
|
4983
5114
|
} else {
|
|
4984
|
-
message += `${
|
|
5115
|
+
message += `${chalk12.bold("Assigned to:")} Unassigned
|
|
4985
5116
|
`;
|
|
4986
5117
|
}
|
|
4987
5118
|
if (task2.created_at) {
|
|
4988
|
-
message += `${
|
|
5119
|
+
message += `${chalk12.bold("Created:")} ${new Date(task2.created_at).toLocaleString()}
|
|
4989
5120
|
`;
|
|
4990
5121
|
}
|
|
4991
5122
|
if (task2.updated_at) {
|
|
4992
|
-
message += `${
|
|
5123
|
+
message += `${chalk12.bold("Updated:")} ${new Date(task2.updated_at).toLocaleString()}
|
|
4993
5124
|
`;
|
|
4994
5125
|
}
|
|
4995
5126
|
if (task2.started_at) {
|
|
4996
|
-
message += `${
|
|
5127
|
+
message += `${chalk12.bold("Started:")} ${new Date(task2.started_at).toLocaleString()}
|
|
4997
5128
|
`;
|
|
4998
5129
|
}
|
|
4999
5130
|
if (task2.finished_at) {
|
|
5000
|
-
message += `${
|
|
5131
|
+
message += `${chalk12.bold("Finished:")} ${new Date(task2.finished_at).toLocaleString()}
|
|
5001
5132
|
`;
|
|
5002
5133
|
}
|
|
5003
5134
|
if (options?.showContent && task2.content) {
|
|
5004
5135
|
message += `
|
|
5005
5136
|
${divider}
|
|
5006
5137
|
`;
|
|
5007
|
-
message += `${
|
|
5138
|
+
message += `${chalk12.bold("Content:")}
|
|
5008
5139
|
${task2.content}
|
|
5009
5140
|
`;
|
|
5010
5141
|
message += `${divider}
|
|
@@ -5012,7 +5143,7 @@ ${task2.content}
|
|
|
5012
5143
|
}
|
|
5013
5144
|
if (task2.blocked_by && task2.blocked_by.length > 0) {
|
|
5014
5145
|
message += `
|
|
5015
|
-
${
|
|
5146
|
+
${chalk12.bold("Blocked by:")} ${task2.blocked_by.join(", ")}
|
|
5016
5147
|
`;
|
|
5017
5148
|
}
|
|
5018
5149
|
return message;
|
|
@@ -5595,9 +5726,9 @@ function formatProjectShowXml(project2) {
|
|
|
5595
5726
|
}
|
|
5596
5727
|
function formatRequirementTreeView(requirements, tasksMap) {
|
|
5597
5728
|
if (requirements.length === 0) {
|
|
5598
|
-
return
|
|
5729
|
+
return chalk12.yellow("No requirements found.\n");
|
|
5599
5730
|
}
|
|
5600
|
-
let output =
|
|
5731
|
+
let output = chalk12.bold.cyan(`\u{1F4CB} Requirements (Tree View)
|
|
5601
5732
|
|
|
5602
5733
|
`);
|
|
5603
5734
|
for (let i = 0; i < requirements.length; i++) {
|
|
@@ -5610,12 +5741,12 @@ function formatRequirementTreeView(requirements, tasksMap) {
|
|
|
5610
5741
|
if (shortId.startsWith("REQ-REQ-")) {
|
|
5611
5742
|
shortId = shortId.replace("REQ-REQ-", "REQ-");
|
|
5612
5743
|
}
|
|
5613
|
-
const branchInfo = req.branch ?
|
|
5614
|
-
output += `${reqPrefix}${
|
|
5744
|
+
const branchInfo = req.branch ? chalk12.gray(` (branch: ${req.branch})`) : "";
|
|
5745
|
+
output += `${reqPrefix}${chalk12.bold(shortId)} ${reqStatusEmoji} ${req.name}${branchInfo}
|
|
5615
5746
|
`;
|
|
5616
5747
|
const tasks = tasksMap.get(req.id) || [];
|
|
5617
5748
|
if (tasks.length === 0) {
|
|
5618
|
-
output += `${childPrefix}\u2514\u2500\u2500 ${
|
|
5749
|
+
output += `${childPrefix}\u2514\u2500\u2500 ${chalk12.gray("(no tasks yet)")}
|
|
5619
5750
|
`;
|
|
5620
5751
|
} else {
|
|
5621
5752
|
for (let j = 0; j < tasks.length; j++) {
|
|
@@ -5623,7 +5754,7 @@ function formatRequirementTreeView(requirements, tasksMap) {
|
|
|
5623
5754
|
const isLastTask = j === tasks.length - 1;
|
|
5624
5755
|
const taskPrefix = isLastTask ? "\u2514\u2500\u2500 " : "\u251C\u2500\u2500 ";
|
|
5625
5756
|
const taskStatusEmoji = getRequirementStatusEmoji(task2.status);
|
|
5626
|
-
const blockedInfo = task2.blocked_by && task2.blocked_by.length > 0 ?
|
|
5757
|
+
const blockedInfo = task2.blocked_by && task2.blocked_by.length > 0 ? chalk12.yellow(` [Blocked by: ${task2.blocked_by.length}]`) : "";
|
|
5627
5758
|
output += `${childPrefix}${taskPrefix}${task2.number} ${taskStatusEmoji} ${task2.title}${blockedInfo}
|
|
5628
5759
|
`;
|
|
5629
5760
|
}
|
|
@@ -5638,7 +5769,7 @@ function parseProjectId(input2) {
|
|
|
5638
5769
|
}
|
|
5639
5770
|
|
|
5640
5771
|
// src/utils/workspace-manager.ts
|
|
5641
|
-
import
|
|
5772
|
+
import chalk13 from "chalk";
|
|
5642
5773
|
var WorkspaceManager = class {
|
|
5643
5774
|
constructor() {
|
|
5644
5775
|
this.activeRequirementId = null;
|
|
@@ -5672,7 +5803,7 @@ var WorkspaceManager = class {
|
|
|
5672
5803
|
}
|
|
5673
5804
|
return {
|
|
5674
5805
|
success: false,
|
|
5675
|
-
error:
|
|
5806
|
+
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
5807
|
};
|
|
5677
5808
|
}
|
|
5678
5809
|
/**
|
|
@@ -5706,9 +5837,9 @@ var WorkspaceManager = class {
|
|
|
5706
5837
|
}
|
|
5707
5838
|
return {
|
|
5708
5839
|
success: false,
|
|
5709
|
-
error:
|
|
5840
|
+
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
5841
|
"Tip: Name your branch with a requirement ID (e.g., feature/REQ-123-description)\n"
|
|
5711
|
-
) +
|
|
5842
|
+
) + chalk13.dim("to enable auto-detection.")
|
|
5712
5843
|
};
|
|
5713
5844
|
}
|
|
5714
5845
|
/**
|
|
@@ -5767,19 +5898,19 @@ async function handleProjectList(opts) {
|
|
|
5767
5898
|
if (!isAuthenticated) {
|
|
5768
5899
|
return {
|
|
5769
5900
|
success: false,
|
|
5770
|
-
message:
|
|
5901
|
+
message: chalk14.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
5771
5902
|
};
|
|
5772
5903
|
}
|
|
5773
5904
|
const format = opts.format || "table";
|
|
5774
5905
|
if (!["table", "json", "xml", "markdown"].includes(format)) {
|
|
5775
5906
|
return {
|
|
5776
5907
|
success: false,
|
|
5777
|
-
message:
|
|
5908
|
+
message: chalk14.red(
|
|
5778
5909
|
`\u274C Invalid format: ${format}. Supported formats: table, json, xml, markdown`
|
|
5779
5910
|
)
|
|
5780
5911
|
};
|
|
5781
5912
|
}
|
|
5782
|
-
const stop = showSpinner("Loading projects",
|
|
5913
|
+
const stop = showSpinner("Loading projects", chalk14.gray);
|
|
5783
5914
|
try {
|
|
5784
5915
|
const response = await projectService.listProjects({
|
|
5785
5916
|
page: opts.page ? parseInt(opts.page, 10) : 1,
|
|
@@ -5806,11 +5937,11 @@ async function handleProjectList(opts) {
|
|
|
5806
5937
|
if (response.projects.length === 0) {
|
|
5807
5938
|
return {
|
|
5808
5939
|
success: true,
|
|
5809
|
-
message:
|
|
5940
|
+
message: chalk14.yellow("No projects found."),
|
|
5810
5941
|
data: response
|
|
5811
5942
|
};
|
|
5812
5943
|
}
|
|
5813
|
-
output =
|
|
5944
|
+
output = chalk14.bold("\u{1F4CB} Projects\n\n");
|
|
5814
5945
|
output += "ID Short ID Name Created\n";
|
|
5815
5946
|
output += `${"\u2500".repeat(100)}
|
|
5816
5947
|
`;
|
|
@@ -5849,21 +5980,21 @@ async function handleProjectShow(opts) {
|
|
|
5849
5980
|
if (!isAuthenticated) {
|
|
5850
5981
|
return {
|
|
5851
5982
|
success: false,
|
|
5852
|
-
message:
|
|
5983
|
+
message: chalk14.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
5853
5984
|
};
|
|
5854
5985
|
}
|
|
5855
5986
|
const format = opts.format || "table";
|
|
5856
5987
|
if (!["table", "json", "xml", "markdown"].includes(format)) {
|
|
5857
5988
|
return {
|
|
5858
5989
|
success: false,
|
|
5859
|
-
message:
|
|
5990
|
+
message: chalk14.red(
|
|
5860
5991
|
`\u274C Invalid format: ${format}. Supported formats: table, json, xml, markdown`
|
|
5861
5992
|
)
|
|
5862
5993
|
};
|
|
5863
5994
|
}
|
|
5864
5995
|
if (opts.id) {
|
|
5865
5996
|
const normalizedId = parseProjectId(opts.id);
|
|
5866
|
-
const stop2 = showSpinner("Loading project",
|
|
5997
|
+
const stop2 = showSpinner("Loading project", chalk14.gray);
|
|
5867
5998
|
try {
|
|
5868
5999
|
const project2 = await projectService.getProject(normalizedId);
|
|
5869
6000
|
stop2();
|
|
@@ -5882,23 +6013,23 @@ async function handleProjectShow(opts) {
|
|
|
5882
6013
|
break;
|
|
5883
6014
|
}
|
|
5884
6015
|
default: {
|
|
5885
|
-
output =
|
|
6016
|
+
output = chalk14.bold(`
|
|
5886
6017
|
\u{1F4C1} Project: ${project2.name}
|
|
5887
6018
|
|
|
5888
6019
|
`);
|
|
5889
|
-
output += `${
|
|
6020
|
+
output += `${chalk14.bold("ID:")} ${project2.id}
|
|
5890
6021
|
`;
|
|
5891
|
-
output += `${
|
|
6022
|
+
output += `${chalk14.bold("Short ID:")} ${project2.short_id}
|
|
5892
6023
|
`;
|
|
5893
|
-
output += `${
|
|
6024
|
+
output += `${chalk14.bold("Name:")} ${project2.name}
|
|
5894
6025
|
`;
|
|
5895
6026
|
if (project2.description) {
|
|
5896
|
-
output += `${
|
|
6027
|
+
output += `${chalk14.bold("Description:")} ${project2.description}
|
|
5897
6028
|
`;
|
|
5898
6029
|
}
|
|
5899
|
-
output += `${
|
|
6030
|
+
output += `${chalk14.bold("Created:")} ${new Date(project2.created_at).toLocaleString()}
|
|
5900
6031
|
`;
|
|
5901
|
-
output += `${
|
|
6032
|
+
output += `${chalk14.bold("Updated:")} ${new Date(project2.updated_at).toLocaleString()}
|
|
5902
6033
|
`;
|
|
5903
6034
|
break;
|
|
5904
6035
|
}
|
|
@@ -5918,13 +6049,13 @@ async function handleProjectShow(opts) {
|
|
|
5918
6049
|
if (parts.length !== 2) {
|
|
5919
6050
|
return {
|
|
5920
6051
|
success: false,
|
|
5921
|
-
message:
|
|
6052
|
+
message: chalk14.red(
|
|
5922
6053
|
"\u274C Invalid repository format. Use: --repository owner/name (e.g., --repository microsoft/vscode)"
|
|
5923
6054
|
)
|
|
5924
6055
|
};
|
|
5925
6056
|
}
|
|
5926
6057
|
const [repositoryOwner, repositoryName] = parts;
|
|
5927
|
-
const stop2 = showSpinner("Loading projects",
|
|
6058
|
+
const stop2 = showSpinner("Loading projects", chalk14.gray);
|
|
5928
6059
|
try {
|
|
5929
6060
|
const response = await projectService.listProjects({
|
|
5930
6061
|
repository_owner: repositoryOwner,
|
|
@@ -5950,14 +6081,14 @@ async function handleProjectShow(opts) {
|
|
|
5950
6081
|
break;
|
|
5951
6082
|
}
|
|
5952
6083
|
default: {
|
|
5953
|
-
const repoDisplay =
|
|
6084
|
+
const repoDisplay = chalk14.cyan(`${repositoryOwner}/${repositoryName}`);
|
|
5954
6085
|
if (response.projects.length === 0) {
|
|
5955
6086
|
return {
|
|
5956
6087
|
success: true,
|
|
5957
|
-
message:
|
|
6088
|
+
message: chalk14.yellow(`No projects found for repository ${repoDisplay}`)
|
|
5958
6089
|
};
|
|
5959
6090
|
}
|
|
5960
|
-
output =
|
|
6091
|
+
output = chalk14.bold(`\u{1F4CB} Projects for ${repoDisplay}
|
|
5961
6092
|
|
|
5962
6093
|
`);
|
|
5963
6094
|
output += "ID Short ID Name Created\n";
|
|
@@ -5992,7 +6123,7 @@ async function handleProjectShow(opts) {
|
|
|
5992
6123
|
message: workspace.error
|
|
5993
6124
|
};
|
|
5994
6125
|
}
|
|
5995
|
-
const stop = showSpinner("Loading project",
|
|
6126
|
+
const stop = showSpinner("Loading project", chalk14.gray);
|
|
5996
6127
|
try {
|
|
5997
6128
|
const project2 = await projectService.getProject(workspace.projectId);
|
|
5998
6129
|
stop();
|
|
@@ -6011,23 +6142,23 @@ async function handleProjectShow(opts) {
|
|
|
6011
6142
|
break;
|
|
6012
6143
|
}
|
|
6013
6144
|
default: {
|
|
6014
|
-
output =
|
|
6145
|
+
output = chalk14.bold(`
|
|
6015
6146
|
\u{1F4C1} Project: ${project2.name}
|
|
6016
6147
|
|
|
6017
6148
|
`);
|
|
6018
|
-
output += `${
|
|
6149
|
+
output += `${chalk14.bold("ID:")} ${project2.id}
|
|
6019
6150
|
`;
|
|
6020
|
-
output += `${
|
|
6151
|
+
output += `${chalk14.bold("Short ID:")} ${project2.short_id}
|
|
6021
6152
|
`;
|
|
6022
|
-
output += `${
|
|
6153
|
+
output += `${chalk14.bold("Name:")} ${project2.name}
|
|
6023
6154
|
`;
|
|
6024
6155
|
if (project2.description) {
|
|
6025
|
-
output += `${
|
|
6156
|
+
output += `${chalk14.bold("Description:")} ${project2.description}
|
|
6026
6157
|
`;
|
|
6027
6158
|
}
|
|
6028
|
-
output += `${
|
|
6159
|
+
output += `${chalk14.bold("Created:")} ${new Date(project2.created_at).toLocaleString()}
|
|
6029
6160
|
`;
|
|
6030
|
-
output += `${
|
|
6161
|
+
output += `${chalk14.bold("Updated:")} ${new Date(project2.updated_at).toLocaleString()}
|
|
6031
6162
|
`;
|
|
6032
6163
|
break;
|
|
6033
6164
|
}
|
|
@@ -6055,7 +6186,7 @@ async function handleProjectCreate(opts) {
|
|
|
6055
6186
|
if (!isAuthenticated) {
|
|
6056
6187
|
return {
|
|
6057
6188
|
success: false,
|
|
6058
|
-
message:
|
|
6189
|
+
message: chalk14.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
6059
6190
|
};
|
|
6060
6191
|
}
|
|
6061
6192
|
let repositoryId;
|
|
@@ -6066,21 +6197,21 @@ async function handleProjectCreate(opts) {
|
|
|
6066
6197
|
if (parts.length !== 2) {
|
|
6067
6198
|
return {
|
|
6068
6199
|
success: false,
|
|
6069
|
-
message:
|
|
6200
|
+
message: chalk14.red(
|
|
6070
6201
|
"\u274C Invalid repository format. Use: --repository owner/name (e.g., microsoft/vscode)"
|
|
6071
6202
|
)
|
|
6072
6203
|
};
|
|
6073
6204
|
}
|
|
6074
6205
|
const [owner, name] = parts;
|
|
6075
6206
|
const repositoryService = new RepositoryService(config2.apiUrl, auth);
|
|
6076
|
-
const stop2 = showSpinner(`Looking up repository ${opts.repository}`,
|
|
6207
|
+
const stop2 = showSpinner(`Looking up repository ${opts.repository}`, chalk14.gray);
|
|
6077
6208
|
try {
|
|
6078
6209
|
const repoId = await getRepositoryId(repositoryService, owner, name);
|
|
6079
6210
|
stop2();
|
|
6080
6211
|
if (!repoId) {
|
|
6081
6212
|
return {
|
|
6082
6213
|
success: false,
|
|
6083
|
-
message:
|
|
6214
|
+
message: chalk14.red(
|
|
6084
6215
|
`\u274C Repository '${opts.repository}' not found. Please check the name or ensure you have access.`
|
|
6085
6216
|
)
|
|
6086
6217
|
};
|
|
@@ -6090,7 +6221,7 @@ async function handleProjectCreate(opts) {
|
|
|
6090
6221
|
stop2();
|
|
6091
6222
|
}
|
|
6092
6223
|
}
|
|
6093
|
-
const stop = showSpinner("Creating project",
|
|
6224
|
+
const stop = showSpinner("Creating project", chalk14.gray);
|
|
6094
6225
|
try {
|
|
6095
6226
|
const project2 = await projectService.createProject({
|
|
6096
6227
|
name: opts.name,
|
|
@@ -6098,9 +6229,9 @@ async function handleProjectCreate(opts) {
|
|
|
6098
6229
|
repository_id: repositoryId
|
|
6099
6230
|
});
|
|
6100
6231
|
stop();
|
|
6101
|
-
let message =
|
|
6232
|
+
let message = chalk14.green(`\u2705 Created project ${project2.short_id}: ${project2.name}`);
|
|
6102
6233
|
if (opts.repository && repositoryId) {
|
|
6103
|
-
message +=
|
|
6234
|
+
message += chalk14.gray(` (linked to ${opts.repository})`);
|
|
6104
6235
|
}
|
|
6105
6236
|
return {
|
|
6106
6237
|
success: true,
|
|
@@ -6124,19 +6255,19 @@ async function handleProjectUpdate(id, opts) {
|
|
|
6124
6255
|
if (!isAuthenticated) {
|
|
6125
6256
|
return {
|
|
6126
6257
|
success: false,
|
|
6127
|
-
message:
|
|
6258
|
+
message: chalk14.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
6128
6259
|
};
|
|
6129
6260
|
}
|
|
6130
6261
|
if (!opts.name && !opts.description) {
|
|
6131
6262
|
return {
|
|
6132
6263
|
success: false,
|
|
6133
|
-
message:
|
|
6264
|
+
message: chalk14.red(
|
|
6134
6265
|
"\u274C Please provide at least one field to update (--name or --description)"
|
|
6135
6266
|
)
|
|
6136
6267
|
};
|
|
6137
6268
|
}
|
|
6138
6269
|
const normalizedId = parseProjectId(id);
|
|
6139
|
-
const stop = showSpinner("Updating project",
|
|
6270
|
+
const stop = showSpinner("Updating project", chalk14.gray);
|
|
6140
6271
|
try {
|
|
6141
6272
|
const project2 = await projectService.updateProject(normalizedId, {
|
|
6142
6273
|
name: opts.name,
|
|
@@ -6145,7 +6276,7 @@ async function handleProjectUpdate(id, opts) {
|
|
|
6145
6276
|
stop();
|
|
6146
6277
|
return {
|
|
6147
6278
|
success: true,
|
|
6148
|
-
message:
|
|
6279
|
+
message: chalk14.green(`\u2705 Updated project ${project2.short_id}: ${project2.name}`),
|
|
6149
6280
|
data: project2
|
|
6150
6281
|
};
|
|
6151
6282
|
} finally {
|
|
@@ -6165,25 +6296,25 @@ async function handleProjectDelete(id, opts) {
|
|
|
6165
6296
|
if (!isAuthenticated) {
|
|
6166
6297
|
return {
|
|
6167
6298
|
success: false,
|
|
6168
|
-
message:
|
|
6299
|
+
message: chalk14.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
6169
6300
|
};
|
|
6170
6301
|
}
|
|
6171
6302
|
if (!opts.force) {
|
|
6172
6303
|
return {
|
|
6173
6304
|
success: false,
|
|
6174
|
-
message:
|
|
6305
|
+
message: chalk14.yellow(
|
|
6175
6306
|
"\u26A0\uFE0F Deleting a project is permanent. Use --force to confirm deletion."
|
|
6176
6307
|
)
|
|
6177
6308
|
};
|
|
6178
6309
|
}
|
|
6179
6310
|
const normalizedId = parseProjectId(id);
|
|
6180
|
-
const stop = showSpinner("Deleting project",
|
|
6311
|
+
const stop = showSpinner("Deleting project", chalk14.gray);
|
|
6181
6312
|
try {
|
|
6182
6313
|
await projectService.deleteProject(normalizedId);
|
|
6183
6314
|
stop();
|
|
6184
6315
|
return {
|
|
6185
6316
|
success: true,
|
|
6186
|
-
message:
|
|
6317
|
+
message: chalk14.green(`\u2705 Deleted project ${id}`)
|
|
6187
6318
|
};
|
|
6188
6319
|
} finally {
|
|
6189
6320
|
stop();
|
|
@@ -6197,7 +6328,7 @@ async function handleProjectDelete(id, opts) {
|
|
|
6197
6328
|
}
|
|
6198
6329
|
|
|
6199
6330
|
// src/handlers/requirement.handlers.ts
|
|
6200
|
-
import
|
|
6331
|
+
import chalk15 from "chalk";
|
|
6201
6332
|
|
|
6202
6333
|
// src/services/requirement-service.ts
|
|
6203
6334
|
var RequirementService = class {
|
|
@@ -6347,14 +6478,14 @@ async function handleRequirementList(opts) {
|
|
|
6347
6478
|
if (!isAuthenticated) {
|
|
6348
6479
|
return {
|
|
6349
6480
|
success: false,
|
|
6350
|
-
message:
|
|
6481
|
+
message: chalk15.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
6351
6482
|
};
|
|
6352
6483
|
}
|
|
6353
6484
|
const format = opts.format || "table";
|
|
6354
6485
|
if (!opts.tree && !["table", "json", "xml", "markdown"].includes(format)) {
|
|
6355
6486
|
return {
|
|
6356
6487
|
success: false,
|
|
6357
|
-
message:
|
|
6488
|
+
message: chalk15.red(
|
|
6358
6489
|
`\u274C Invalid format: ${format}. Supported formats: table, json, xml, markdown`
|
|
6359
6490
|
)
|
|
6360
6491
|
};
|
|
@@ -6367,7 +6498,7 @@ async function handleRequirementList(opts) {
|
|
|
6367
6498
|
};
|
|
6368
6499
|
}
|
|
6369
6500
|
const projectId = workspace.projectId;
|
|
6370
|
-
stopSpinner = showSpinner("Loading requirements",
|
|
6501
|
+
stopSpinner = showSpinner("Loading requirements", chalk15.gray);
|
|
6371
6502
|
const response = await requirementService.listProjectRequirements(projectId, {
|
|
6372
6503
|
status: opts.status,
|
|
6373
6504
|
page: opts.page ? parseInt(opts.page, 10) : 1,
|
|
@@ -6379,10 +6510,10 @@ async function handleRequirementList(opts) {
|
|
|
6379
6510
|
if (response.requirements.length === 0) {
|
|
6380
6511
|
return {
|
|
6381
6512
|
success: true,
|
|
6382
|
-
message:
|
|
6513
|
+
message: chalk15.yellow("No requirements found.")
|
|
6383
6514
|
};
|
|
6384
6515
|
}
|
|
6385
|
-
stopSpinner = showSpinner("Loading tasks for tree view",
|
|
6516
|
+
stopSpinner = showSpinner("Loading tasks for tree view", chalk15.gray);
|
|
6386
6517
|
const tasksMap = /* @__PURE__ */ new Map();
|
|
6387
6518
|
const taskPromises = response.requirements.map(async (req) => {
|
|
6388
6519
|
try {
|
|
@@ -6405,7 +6536,7 @@ Page ${response.pagination.page} of ${Math.ceil(response.pagination.total / resp
|
|
|
6405
6536
|
finalOutput += ` (${response.pagination.total} total)`;
|
|
6406
6537
|
if (response.pagination?.has_more) {
|
|
6407
6538
|
finalOutput += `
|
|
6408
|
-
${
|
|
6539
|
+
${chalk15.yellow("\u26A0\uFE0F More requirements exist. Use --limit to see more.")}`;
|
|
6409
6540
|
}
|
|
6410
6541
|
return {
|
|
6411
6542
|
success: true,
|
|
@@ -6431,10 +6562,10 @@ ${chalk14.yellow("\u26A0\uFE0F More requirements exist. Use --limit to see more.
|
|
|
6431
6562
|
if (response.requirements.length === 0) {
|
|
6432
6563
|
return {
|
|
6433
6564
|
success: true,
|
|
6434
|
-
message:
|
|
6565
|
+
message: chalk15.yellow("No requirements found.")
|
|
6435
6566
|
};
|
|
6436
6567
|
}
|
|
6437
|
-
output =
|
|
6568
|
+
output = chalk15.bold("\u{1F4CB} Requirements\n\n");
|
|
6438
6569
|
output += "Short ID Status Name Branch Progress\n";
|
|
6439
6570
|
output += `${"\u2500".repeat(90)}
|
|
6440
6571
|
`;
|
|
@@ -6456,7 +6587,7 @@ ${chalk14.yellow("\u26A0\uFE0F More requirements exist. Use --limit to see more.
|
|
|
6456
6587
|
}
|
|
6457
6588
|
if (response.pagination?.has_more) {
|
|
6458
6589
|
output += `
|
|
6459
|
-
${
|
|
6590
|
+
${chalk15.yellow("\u26A0\uFE0F More requirements exist. Use --limit to see more.")}`;
|
|
6460
6591
|
}
|
|
6461
6592
|
return {
|
|
6462
6593
|
success: true,
|
|
@@ -6481,14 +6612,14 @@ async function handleRequirementShow(opts) {
|
|
|
6481
6612
|
if (!isAuthenticated) {
|
|
6482
6613
|
return {
|
|
6483
6614
|
success: false,
|
|
6484
|
-
message:
|
|
6615
|
+
message: chalk15.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
6485
6616
|
};
|
|
6486
6617
|
}
|
|
6487
6618
|
const format = opts?.format || "table";
|
|
6488
6619
|
if (!["table", "json", "xml", "markdown"].includes(format)) {
|
|
6489
6620
|
return {
|
|
6490
6621
|
success: false,
|
|
6491
|
-
message:
|
|
6622
|
+
message: chalk15.red(
|
|
6492
6623
|
`\u274C Invalid format: ${format}. Supported formats: table, json, xml, markdown`
|
|
6493
6624
|
)
|
|
6494
6625
|
};
|
|
@@ -6510,7 +6641,7 @@ async function handleRequirementShow(opts) {
|
|
|
6510
6641
|
}
|
|
6511
6642
|
const projectId = workspace.projectId;
|
|
6512
6643
|
const normalizedId = normalizeRequirementId(requirementId);
|
|
6513
|
-
stopSpinner = showSpinner("Loading requirement",
|
|
6644
|
+
stopSpinner = showSpinner("Loading requirement", chalk15.gray);
|
|
6514
6645
|
const requirement2 = await requirementService.getProjectRequirement(projectId, normalizedId);
|
|
6515
6646
|
stopSpinner();
|
|
6516
6647
|
stopSpinner = null;
|
|
@@ -6566,7 +6697,7 @@ async function handleRequirementCreate(opts) {
|
|
|
6566
6697
|
if (!isAuthenticated) {
|
|
6567
6698
|
return {
|
|
6568
6699
|
success: false,
|
|
6569
|
-
message:
|
|
6700
|
+
message: chalk15.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
6570
6701
|
};
|
|
6571
6702
|
}
|
|
6572
6703
|
const workspace = await workspaceManager.getProject(opts.project);
|
|
@@ -6583,7 +6714,7 @@ async function handleRequirementCreate(opts) {
|
|
|
6583
6714
|
if (emailRegex.test(opts.assignedTo)) {
|
|
6584
6715
|
return {
|
|
6585
6716
|
success: false,
|
|
6586
|
-
message:
|
|
6717
|
+
message: chalk15.red(
|
|
6587
6718
|
"\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
6719
|
)
|
|
6589
6720
|
};
|
|
@@ -6591,7 +6722,7 @@ async function handleRequirementCreate(opts) {
|
|
|
6591
6722
|
if (!uuidRegex.test(opts.assignedTo)) {
|
|
6592
6723
|
return {
|
|
6593
6724
|
success: false,
|
|
6594
|
-
message:
|
|
6725
|
+
message: chalk15.red(
|
|
6595
6726
|
'\u274C Invalid UUID format for --assigned-to.\nPlease provide a valid user UUID (e.g., "550e8400-e29b-41d4-a716-446655440000")'
|
|
6596
6727
|
)
|
|
6597
6728
|
};
|
|
@@ -6603,12 +6734,12 @@ async function handleRequirementCreate(opts) {
|
|
|
6603
6734
|
if (!tagResult.valid) {
|
|
6604
6735
|
return {
|
|
6605
6736
|
success: false,
|
|
6606
|
-
message:
|
|
6737
|
+
message: chalk15.red(`\u274C ${tagResult.error}`)
|
|
6607
6738
|
};
|
|
6608
6739
|
}
|
|
6609
6740
|
validatedTags = tagResult.tags;
|
|
6610
6741
|
}
|
|
6611
|
-
stopSpinner = showSpinner("Creating requirement",
|
|
6742
|
+
stopSpinner = showSpinner("Creating requirement", chalk15.gray);
|
|
6612
6743
|
const requirement2 = await requirementService.createProjectRequirement(projectId, {
|
|
6613
6744
|
name: opts.name,
|
|
6614
6745
|
content: opts.content || null,
|
|
@@ -6642,7 +6773,7 @@ async function handleRequirementCreate(opts) {
|
|
|
6642
6773
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
6643
6774
|
return {
|
|
6644
6775
|
success: false,
|
|
6645
|
-
message:
|
|
6776
|
+
message: chalk15.red(`\u274C Error creating requirement: ${errorMessage}`)
|
|
6646
6777
|
};
|
|
6647
6778
|
}
|
|
6648
6779
|
}
|
|
@@ -6654,14 +6785,14 @@ async function handleRequirementSpecify(opts) {
|
|
|
6654
6785
|
if (!isAuthenticated) {
|
|
6655
6786
|
return {
|
|
6656
6787
|
success: false,
|
|
6657
|
-
message:
|
|
6788
|
+
message: chalk15.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
6658
6789
|
};
|
|
6659
6790
|
}
|
|
6660
6791
|
const format = opts.format || "table";
|
|
6661
6792
|
if (!["table", "json", "xml", "markdown"].includes(format)) {
|
|
6662
6793
|
return {
|
|
6663
6794
|
success: false,
|
|
6664
|
-
message:
|
|
6795
|
+
message: chalk15.red(
|
|
6665
6796
|
`\u274C Invalid format: ${format}. Supported formats: table, json, xml, markdown`
|
|
6666
6797
|
)
|
|
6667
6798
|
};
|
|
@@ -6677,13 +6808,13 @@ async function handleRequirementSpecify(opts) {
|
|
|
6677
6808
|
if (opts.prompt.length < 10) {
|
|
6678
6809
|
return {
|
|
6679
6810
|
success: false,
|
|
6680
|
-
message:
|
|
6811
|
+
message: chalk15.red("\u274C Prompt must be at least 10 characters long")
|
|
6681
6812
|
};
|
|
6682
6813
|
}
|
|
6683
6814
|
if (opts.prompt.length > 5e3) {
|
|
6684
6815
|
return {
|
|
6685
6816
|
success: false,
|
|
6686
|
-
message:
|
|
6817
|
+
message: chalk15.red("\u274C Prompt must be no more than 5000 characters long")
|
|
6687
6818
|
};
|
|
6688
6819
|
}
|
|
6689
6820
|
let validatedTags;
|
|
@@ -6692,7 +6823,7 @@ async function handleRequirementSpecify(opts) {
|
|
|
6692
6823
|
if (!tagResult.valid) {
|
|
6693
6824
|
return {
|
|
6694
6825
|
success: false,
|
|
6695
|
-
message:
|
|
6826
|
+
message: chalk15.red(`\u274C ${tagResult.error}`)
|
|
6696
6827
|
};
|
|
6697
6828
|
}
|
|
6698
6829
|
validatedTags = tagResult.tags;
|
|
@@ -6755,13 +6886,13 @@ async function handleRequirementUpdate(opts) {
|
|
|
6755
6886
|
if (!isAuthenticated) {
|
|
6756
6887
|
return {
|
|
6757
6888
|
success: false,
|
|
6758
|
-
message:
|
|
6889
|
+
message: chalk15.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
6759
6890
|
};
|
|
6760
6891
|
}
|
|
6761
6892
|
if (!opts.status && !opts.name && !opts.content) {
|
|
6762
6893
|
return {
|
|
6763
6894
|
success: false,
|
|
6764
|
-
message:
|
|
6895
|
+
message: chalk15.red(
|
|
6765
6896
|
"\u274C Please provide at least one field to update (--status, --name, or --content)"
|
|
6766
6897
|
)
|
|
6767
6898
|
};
|
|
@@ -6783,7 +6914,7 @@ async function handleRequirementUpdate(opts) {
|
|
|
6783
6914
|
}
|
|
6784
6915
|
const projectId = workspace.projectId;
|
|
6785
6916
|
const normalizedId = normalizeRequirementId(requirementId);
|
|
6786
|
-
stopSpinner = showSpinner("Updating requirement",
|
|
6917
|
+
stopSpinner = showSpinner("Updating requirement", chalk15.gray);
|
|
6787
6918
|
const requirement2 = await requirementService.updateProjectRequirement(projectId, normalizedId, {
|
|
6788
6919
|
status: opts.status,
|
|
6789
6920
|
name: opts.name,
|
|
@@ -6793,7 +6924,7 @@ async function handleRequirementUpdate(opts) {
|
|
|
6793
6924
|
stopSpinner = null;
|
|
6794
6925
|
return {
|
|
6795
6926
|
success: true,
|
|
6796
|
-
message:
|
|
6927
|
+
message: chalk15.green(`\u2705 Updated requirement ${requirement2.short_id}: ${requirement2.name}`),
|
|
6797
6928
|
data: requirement2
|
|
6798
6929
|
};
|
|
6799
6930
|
} catch (error) {
|
|
@@ -6814,13 +6945,13 @@ async function handleRequirementDelete(opts) {
|
|
|
6814
6945
|
if (!isAuthenticated) {
|
|
6815
6946
|
return {
|
|
6816
6947
|
success: false,
|
|
6817
|
-
message:
|
|
6948
|
+
message: chalk15.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
6818
6949
|
};
|
|
6819
6950
|
}
|
|
6820
6951
|
if (!opts.force) {
|
|
6821
6952
|
return {
|
|
6822
6953
|
success: false,
|
|
6823
|
-
message:
|
|
6954
|
+
message: chalk15.yellow(
|
|
6824
6955
|
"\u26A0\uFE0F Deleting a requirement is permanent. Use --force to confirm deletion."
|
|
6825
6956
|
)
|
|
6826
6957
|
};
|
|
@@ -6842,13 +6973,13 @@ async function handleRequirementDelete(opts) {
|
|
|
6842
6973
|
}
|
|
6843
6974
|
const projectId = workspace.projectId;
|
|
6844
6975
|
const normalizedId = normalizeRequirementId(requirementId);
|
|
6845
|
-
stopSpinner = showSpinner("Deleting requirement",
|
|
6976
|
+
stopSpinner = showSpinner("Deleting requirement", chalk15.gray);
|
|
6846
6977
|
await requirementService.deleteProjectRequirement(projectId, normalizedId);
|
|
6847
6978
|
stopSpinner();
|
|
6848
6979
|
stopSpinner = null;
|
|
6849
6980
|
return {
|
|
6850
6981
|
success: true,
|
|
6851
|
-
message:
|
|
6982
|
+
message: chalk15.green(`\u2705 Deleted requirement ${requirementId}`)
|
|
6852
6983
|
};
|
|
6853
6984
|
} catch (error) {
|
|
6854
6985
|
if (stopSpinner) {
|
|
@@ -6868,14 +6999,14 @@ async function handleRequirementBreakdown(opts) {
|
|
|
6868
6999
|
if (!isAuthenticated) {
|
|
6869
7000
|
return {
|
|
6870
7001
|
success: false,
|
|
6871
|
-
message:
|
|
7002
|
+
message: chalk15.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
6872
7003
|
};
|
|
6873
7004
|
}
|
|
6874
7005
|
const format = opts.format || "table";
|
|
6875
7006
|
if (!["table", "json", "xml", "markdown"].includes(format)) {
|
|
6876
7007
|
return {
|
|
6877
7008
|
success: false,
|
|
6878
|
-
message:
|
|
7009
|
+
message: chalk15.red(
|
|
6879
7010
|
`\u274C Invalid format: ${format}. Supported formats: table, json, xml, markdown`
|
|
6880
7011
|
)
|
|
6881
7012
|
};
|
|
@@ -6897,7 +7028,7 @@ async function handleRequirementBreakdown(opts) {
|
|
|
6897
7028
|
}
|
|
6898
7029
|
const projectId = workspace.projectId;
|
|
6899
7030
|
const normalizedId = normalizeRequirementId(requirementId);
|
|
6900
|
-
stop = showSpinner("Checking requirement...",
|
|
7031
|
+
stop = showSpinner("Checking requirement...", chalk15.gray);
|
|
6901
7032
|
const requirement2 = await requirementService.getProjectRequirement(projectId, normalizedId);
|
|
6902
7033
|
stop();
|
|
6903
7034
|
const taskCount = requirement2.tasks?.length ?? requirement2.task_progress?.total ?? 0;
|
|
@@ -6905,13 +7036,13 @@ async function handleRequirementBreakdown(opts) {
|
|
|
6905
7036
|
const shortId = requirement2.short_id || normalizedId;
|
|
6906
7037
|
return {
|
|
6907
7038
|
success: false,
|
|
6908
|
-
message:
|
|
7039
|
+
message: chalk15.red(
|
|
6909
7040
|
`\u274C Cannot breakdown requirement ${shortId} - it already has ${taskCount} task(s)
|
|
6910
7041
|
|
|
6911
7042
|
`
|
|
6912
|
-
) + "The breakdown command is only for initial task generation from requirements.\nOnce tasks exist, you should manage them individually.\n\n" +
|
|
7043
|
+
) + "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
7044
|
|
|
6914
|
-
`) +
|
|
7045
|
+
`) + chalk15.bold("To view existing tasks:\n") + chalk15.cyan(` braingrid task list -r ${shortId}`)
|
|
6915
7046
|
};
|
|
6916
7047
|
}
|
|
6917
7048
|
stop = showSpinner("Breaking down requirement into tasks...");
|
|
@@ -6932,7 +7063,7 @@ async function handleRequirementBreakdown(opts) {
|
|
|
6932
7063
|
break;
|
|
6933
7064
|
}
|
|
6934
7065
|
default: {
|
|
6935
|
-
output =
|
|
7066
|
+
output = chalk15.green(
|
|
6936
7067
|
`\u2705 Generated ${response.tasks.length} tasks for ${response.requirement_short_id}
|
|
6937
7068
|
|
|
6938
7069
|
`
|
|
@@ -6970,7 +7101,7 @@ async function handleRequirementBreakdown(opts) {
|
|
|
6970
7101
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
6971
7102
|
return {
|
|
6972
7103
|
success: false,
|
|
6973
|
-
message:
|
|
7104
|
+
message: chalk15.red(`\u274C Error breaking down requirement: ${errorMessage}`)
|
|
6974
7105
|
};
|
|
6975
7106
|
}
|
|
6976
7107
|
}
|
|
@@ -6982,14 +7113,14 @@ async function handleRequirementBuild(opts) {
|
|
|
6982
7113
|
if (!isAuthenticated) {
|
|
6983
7114
|
return {
|
|
6984
7115
|
success: false,
|
|
6985
|
-
message:
|
|
7116
|
+
message: chalk15.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
6986
7117
|
};
|
|
6987
7118
|
}
|
|
6988
7119
|
const format = opts.format || "markdown";
|
|
6989
7120
|
if (!["markdown", "json", "xml"].includes(format)) {
|
|
6990
7121
|
return {
|
|
6991
7122
|
success: false,
|
|
6992
|
-
message:
|
|
7123
|
+
message: chalk15.red("\u274C Invalid format. Must be one of: markdown, json, xml")
|
|
6993
7124
|
};
|
|
6994
7125
|
}
|
|
6995
7126
|
const requirementResult = await workspaceManager.getRequirement(opts.id);
|
|
@@ -7009,7 +7140,7 @@ async function handleRequirementBuild(opts) {
|
|
|
7009
7140
|
}
|
|
7010
7141
|
const projectId = workspace.projectId;
|
|
7011
7142
|
const normalizedId = normalizeRequirementId(requirementId);
|
|
7012
|
-
stopSpinner = showSpinner("Building requirement with tasks",
|
|
7143
|
+
stopSpinner = showSpinner("Building requirement with tasks", chalk15.gray);
|
|
7013
7144
|
const requirement2 = await requirementService.getProjectRequirement(projectId, normalizedId);
|
|
7014
7145
|
stopSpinner();
|
|
7015
7146
|
stopSpinner = null;
|
|
@@ -7057,14 +7188,14 @@ async function handleCreateGitBranch(opts) {
|
|
|
7057
7188
|
if (!isAuthenticated) {
|
|
7058
7189
|
return {
|
|
7059
7190
|
success: false,
|
|
7060
|
-
message:
|
|
7191
|
+
message: chalk15.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
7061
7192
|
};
|
|
7062
7193
|
}
|
|
7063
7194
|
const format = opts.format || "table";
|
|
7064
7195
|
if (!["table", "json", "markdown"].includes(format)) {
|
|
7065
7196
|
return {
|
|
7066
7197
|
success: false,
|
|
7067
|
-
message:
|
|
7198
|
+
message: chalk15.red(
|
|
7068
7199
|
`\u274C Invalid format: ${format}. Supported formats: table, json, markdown`
|
|
7069
7200
|
)
|
|
7070
7201
|
};
|
|
@@ -7092,7 +7223,7 @@ async function handleCreateGitBranch(opts) {
|
|
|
7092
7223
|
if (!user) {
|
|
7093
7224
|
return {
|
|
7094
7225
|
success: false,
|
|
7095
|
-
message:
|
|
7226
|
+
message: chalk15.red("\u274C Could not get current user for branch name generation")
|
|
7096
7227
|
};
|
|
7097
7228
|
}
|
|
7098
7229
|
const requirement2 = await requirementService.getProjectRequirement(projectId, normalizedId);
|
|
@@ -7101,7 +7232,7 @@ async function handleCreateGitBranch(opts) {
|
|
|
7101
7232
|
const sluggedName = slugify(requirement2.name);
|
|
7102
7233
|
branchName = `${username}/${reqShortId}-${sluggedName}`;
|
|
7103
7234
|
}
|
|
7104
|
-
stopSpinner = showSpinner("Creating GitHub branch...",
|
|
7235
|
+
stopSpinner = showSpinner("Creating GitHub branch...", chalk15.gray);
|
|
7105
7236
|
const response = await requirementService.createGitBranch(projectId, normalizedId, {
|
|
7106
7237
|
branchName,
|
|
7107
7238
|
baseBranch: opts.base
|
|
@@ -7133,13 +7264,13 @@ git fetch origin && git checkout ${response.branch.name}
|
|
|
7133
7264
|
break;
|
|
7134
7265
|
}
|
|
7135
7266
|
default: {
|
|
7136
|
-
output =
|
|
7267
|
+
output = chalk15.green(`\u2705 Created branch: ${response.branch.name}
|
|
7137
7268
|
|
|
7138
7269
|
`);
|
|
7139
|
-
output += `${
|
|
7270
|
+
output += `${chalk15.bold("SHA:")} ${response.branch.sha.substring(0, 7)}
|
|
7140
7271
|
`;
|
|
7141
7272
|
output += `
|
|
7142
|
-
${
|
|
7273
|
+
${chalk15.dim("To checkout:")} git fetch origin && git checkout ${response.branch.name}`;
|
|
7143
7274
|
break;
|
|
7144
7275
|
}
|
|
7145
7276
|
}
|
|
@@ -7165,7 +7296,7 @@ async function handleReviewAcceptance(opts) {
|
|
|
7165
7296
|
if (!isAuthenticated) {
|
|
7166
7297
|
return {
|
|
7167
7298
|
success: false,
|
|
7168
|
-
message:
|
|
7299
|
+
message: chalk15.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
7169
7300
|
};
|
|
7170
7301
|
}
|
|
7171
7302
|
const requirementResult = await workspaceManager.getRequirement(opts.id);
|
|
@@ -7198,13 +7329,13 @@ async function handleReviewAcceptance(opts) {
|
|
|
7198
7329
|
} catch {
|
|
7199
7330
|
return {
|
|
7200
7331
|
success: false,
|
|
7201
|
-
message:
|
|
7332
|
+
message: chalk15.red(
|
|
7202
7333
|
"\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
7334
|
)
|
|
7204
7335
|
};
|
|
7205
7336
|
}
|
|
7206
7337
|
}
|
|
7207
|
-
console.log(
|
|
7338
|
+
console.log(chalk15.bold("\n\u{1F50D} AI Code Review\n"));
|
|
7208
7339
|
let fullOutput = "";
|
|
7209
7340
|
await requirementService.reviewAcceptance(
|
|
7210
7341
|
projectId,
|
|
@@ -7237,14 +7368,14 @@ async function handleRequirementTagList(opts) {
|
|
|
7237
7368
|
if (!isAuthenticated) {
|
|
7238
7369
|
return {
|
|
7239
7370
|
success: false,
|
|
7240
|
-
message:
|
|
7371
|
+
message: chalk15.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
7241
7372
|
};
|
|
7242
7373
|
}
|
|
7243
7374
|
const format = opts.format || "table";
|
|
7244
7375
|
if (!["table", "json", "xml", "markdown"].includes(format)) {
|
|
7245
7376
|
return {
|
|
7246
7377
|
success: false,
|
|
7247
|
-
message:
|
|
7378
|
+
message: chalk15.red(
|
|
7248
7379
|
`\u274C Invalid format: ${format}. Supported formats: table, json, xml, markdown`
|
|
7249
7380
|
)
|
|
7250
7381
|
};
|
|
@@ -7266,7 +7397,7 @@ async function handleRequirementTagList(opts) {
|
|
|
7266
7397
|
}
|
|
7267
7398
|
const projectId = workspace.projectId;
|
|
7268
7399
|
const normalizedId = normalizeRequirementId(requirementId);
|
|
7269
|
-
stopSpinner = showSpinner("Loading tags",
|
|
7400
|
+
stopSpinner = showSpinner("Loading tags", chalk15.gray);
|
|
7270
7401
|
const tags = await requirementService.listRequirementTags(projectId, normalizedId);
|
|
7271
7402
|
stopSpinner();
|
|
7272
7403
|
stopSpinner = null;
|
|
@@ -7313,11 +7444,11 @@ async function handleRequirementTagList(opts) {
|
|
|
7313
7444
|
if (tags.length === 0) {
|
|
7314
7445
|
return {
|
|
7315
7446
|
success: true,
|
|
7316
|
-
message:
|
|
7447
|
+
message: chalk15.yellow(`No tags found for ${normalizedId}.`),
|
|
7317
7448
|
data: tags
|
|
7318
7449
|
};
|
|
7319
7450
|
}
|
|
7320
|
-
output =
|
|
7451
|
+
output = chalk15.bold(`\u{1F3F7}\uFE0F Tags for ${normalizedId}
|
|
7321
7452
|
|
|
7322
7453
|
`);
|
|
7323
7454
|
output += "Name Color\n";
|
|
@@ -7358,20 +7489,20 @@ async function handleRequirementTagAdd(opts) {
|
|
|
7358
7489
|
if (!isAuthenticated) {
|
|
7359
7490
|
return {
|
|
7360
7491
|
success: false,
|
|
7361
|
-
message:
|
|
7492
|
+
message: chalk15.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
7362
7493
|
};
|
|
7363
7494
|
}
|
|
7364
7495
|
if (!opts.name || opts.name.trim().length === 0) {
|
|
7365
7496
|
return {
|
|
7366
7497
|
success: false,
|
|
7367
|
-
message:
|
|
7498
|
+
message: chalk15.red("\u274C Tag name is required")
|
|
7368
7499
|
};
|
|
7369
7500
|
}
|
|
7370
7501
|
const colorResult = validateHexColor(opts.color);
|
|
7371
7502
|
if (!colorResult.valid) {
|
|
7372
7503
|
return {
|
|
7373
7504
|
success: false,
|
|
7374
|
-
message:
|
|
7505
|
+
message: chalk15.red(`\u274C ${colorResult.error}`)
|
|
7375
7506
|
};
|
|
7376
7507
|
}
|
|
7377
7508
|
const requirementResult = await workspaceManager.getRequirement(opts.requirementId);
|
|
@@ -7391,7 +7522,7 @@ async function handleRequirementTagAdd(opts) {
|
|
|
7391
7522
|
}
|
|
7392
7523
|
const projectId = workspace.projectId;
|
|
7393
7524
|
const normalizedId = normalizeRequirementId(requirementId);
|
|
7394
|
-
stopSpinner = showSpinner("Adding tag",
|
|
7525
|
+
stopSpinner = showSpinner("Adding tag", chalk15.gray);
|
|
7395
7526
|
const response = await requirementService.addRequirementTag(projectId, normalizedId, {
|
|
7396
7527
|
name: opts.name.trim(),
|
|
7397
7528
|
color: opts.color
|
|
@@ -7400,7 +7531,7 @@ async function handleRequirementTagAdd(opts) {
|
|
|
7400
7531
|
stopSpinner = null;
|
|
7401
7532
|
return {
|
|
7402
7533
|
success: true,
|
|
7403
|
-
message:
|
|
7534
|
+
message: chalk15.green(
|
|
7404
7535
|
`\u2705 Added tag "${response.tag.name}" (${response.tag.color}) to ${normalizedId}`
|
|
7405
7536
|
),
|
|
7406
7537
|
data: response
|
|
@@ -7416,13 +7547,13 @@ async function handleRequirementTagAdd(opts) {
|
|
|
7416
7547
|
if (errorData?.code === "MAX_TAGS_EXCEEDED") {
|
|
7417
7548
|
return {
|
|
7418
7549
|
success: false,
|
|
7419
|
-
message:
|
|
7550
|
+
message: chalk15.red("\u274C Maximum 5 tags allowed per requirement")
|
|
7420
7551
|
};
|
|
7421
7552
|
}
|
|
7422
7553
|
if (errorData?.code === "TAG_ALREADY_ASSOCIATED") {
|
|
7423
7554
|
return {
|
|
7424
7555
|
success: false,
|
|
7425
|
-
message:
|
|
7556
|
+
message: chalk15.red(`\u274C Tag "${opts.name}" is already associated with this requirement`)
|
|
7426
7557
|
};
|
|
7427
7558
|
}
|
|
7428
7559
|
}
|
|
@@ -7444,13 +7575,13 @@ async function handleRequirementTagRemove(opts) {
|
|
|
7444
7575
|
if (!isAuthenticated) {
|
|
7445
7576
|
return {
|
|
7446
7577
|
success: false,
|
|
7447
|
-
message:
|
|
7578
|
+
message: chalk15.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
7448
7579
|
};
|
|
7449
7580
|
}
|
|
7450
7581
|
if (!opts.name || opts.name.trim().length === 0) {
|
|
7451
7582
|
return {
|
|
7452
7583
|
success: false,
|
|
7453
|
-
message:
|
|
7584
|
+
message: chalk15.red("\u274C Tag name is required")
|
|
7454
7585
|
};
|
|
7455
7586
|
}
|
|
7456
7587
|
const requirementResult = await workspaceManager.getRequirement(opts.requirementId);
|
|
@@ -7470,13 +7601,13 @@ async function handleRequirementTagRemove(opts) {
|
|
|
7470
7601
|
}
|
|
7471
7602
|
const projectId = workspace.projectId;
|
|
7472
7603
|
const normalizedId = normalizeRequirementId(requirementId);
|
|
7473
|
-
stopSpinner = showSpinner("Removing tag",
|
|
7604
|
+
stopSpinner = showSpinner("Removing tag", chalk15.gray);
|
|
7474
7605
|
await requirementService.removeRequirementTag(projectId, normalizedId, opts.name.trim());
|
|
7475
7606
|
stopSpinner();
|
|
7476
7607
|
stopSpinner = null;
|
|
7477
7608
|
return {
|
|
7478
7609
|
success: true,
|
|
7479
|
-
message:
|
|
7610
|
+
message: chalk15.green(`\u2705 Removed tag "${opts.name}" from ${normalizedId}`)
|
|
7480
7611
|
};
|
|
7481
7612
|
} catch (error) {
|
|
7482
7613
|
if (stopSpinner) {
|
|
@@ -7489,13 +7620,13 @@ async function handleRequirementTagRemove(opts) {
|
|
|
7489
7620
|
if (errorData?.code === "TAG_NOT_FOUND") {
|
|
7490
7621
|
return {
|
|
7491
7622
|
success: false,
|
|
7492
|
-
message:
|
|
7623
|
+
message: chalk15.red(`\u274C Tag "${opts.name}" not found`)
|
|
7493
7624
|
};
|
|
7494
7625
|
}
|
|
7495
7626
|
if (errorData?.code === "ASSOCIATION_NOT_FOUND") {
|
|
7496
7627
|
return {
|
|
7497
7628
|
success: false,
|
|
7498
|
-
message:
|
|
7629
|
+
message: chalk15.red(`\u274C Tag "${opts.name}" is not associated with this requirement`)
|
|
7499
7630
|
};
|
|
7500
7631
|
}
|
|
7501
7632
|
}
|
|
@@ -7511,7 +7642,7 @@ async function handleRequirementTagRemove(opts) {
|
|
|
7511
7642
|
}
|
|
7512
7643
|
|
|
7513
7644
|
// src/handlers/status.handlers.ts
|
|
7514
|
-
import
|
|
7645
|
+
import chalk16 from "chalk";
|
|
7515
7646
|
function getAuth2() {
|
|
7516
7647
|
const config2 = getConfig();
|
|
7517
7648
|
return new BraingridAuth(config2.apiUrl);
|
|
@@ -7520,79 +7651,79 @@ async function handleStatus() {
|
|
|
7520
7651
|
try {
|
|
7521
7652
|
const config2 = getConfig();
|
|
7522
7653
|
const auth = getAuth2();
|
|
7523
|
-
const stop = showSpinner("Checking status",
|
|
7654
|
+
const stop = showSpinner("Checking status", chalk16.gray);
|
|
7524
7655
|
const isAuthenticated = await auth.isAuthenticated(true);
|
|
7525
7656
|
stop();
|
|
7526
|
-
let output =
|
|
7527
|
-
output +=
|
|
7528
|
-
output += `${
|
|
7657
|
+
let output = chalk16.bold.cyan("\n\u{1F9E0} BrainGrid CLI Status\n\n");
|
|
7658
|
+
output += chalk16.bold("Authentication\n");
|
|
7659
|
+
output += `${chalk16.dim("\u2500".repeat(50))}
|
|
7529
7660
|
`;
|
|
7530
7661
|
if (!isAuthenticated) {
|
|
7531
|
-
output +=
|
|
7532
|
-
output +=
|
|
7533
|
-
output +=
|
|
7534
|
-
output += `${
|
|
7662
|
+
output += chalk16.red("\u274C Not authenticated\n");
|
|
7663
|
+
output += chalk16.dim(" Run ") + chalk16.cyan("braingrid login") + chalk16.dim(" to sign in\n\n");
|
|
7664
|
+
output += chalk16.bold("Git Repository\n");
|
|
7665
|
+
output += `${chalk16.dim("\u2500".repeat(50))}
|
|
7535
7666
|
`;
|
|
7536
7667
|
const gitInfo2 = await getGitRepositoryInfo();
|
|
7537
7668
|
if (!gitInfo2 || !gitInfo2.isRepo) {
|
|
7538
|
-
output +=
|
|
7669
|
+
output += chalk16.yellow("\u26A0\uFE0F Not in a git repository\n\n");
|
|
7539
7670
|
} else {
|
|
7540
|
-
output +=
|
|
7671
|
+
output += chalk16.green("\u2705 Repository detected!\n");
|
|
7541
7672
|
if (gitInfo2.owner && gitInfo2.name) {
|
|
7542
|
-
output += `${
|
|
7673
|
+
output += `${chalk16.bold("Owner:")} ${gitInfo2.owner}
|
|
7543
7674
|
`;
|
|
7544
|
-
output += `${
|
|
7675
|
+
output += `${chalk16.bold("Name:")} ${gitInfo2.name}
|
|
7545
7676
|
`;
|
|
7546
7677
|
} else if (gitInfo2.remoteUrl) {
|
|
7547
|
-
output += `${
|
|
7678
|
+
output += `${chalk16.bold("Remote:")} ${gitInfo2.remoteUrl}
|
|
7548
7679
|
`;
|
|
7549
7680
|
} else {
|
|
7550
|
-
output +=
|
|
7681
|
+
output += chalk16.yellow("\u26A0\uFE0F Local repository (no remote)\n");
|
|
7551
7682
|
}
|
|
7552
7683
|
if (gitInfo2.branch) {
|
|
7553
|
-
output += `${
|
|
7684
|
+
output += `${chalk16.bold("Branch:")} ${gitInfo2.branch}
|
|
7554
7685
|
`;
|
|
7555
7686
|
}
|
|
7556
7687
|
if (gitInfo2.userName || gitInfo2.userEmail) {
|
|
7557
7688
|
const userDisplay = gitInfo2.userName && gitInfo2.userEmail ? `${gitInfo2.userName} <${gitInfo2.userEmail}>` : gitInfo2.userName || gitInfo2.userEmail;
|
|
7558
|
-
output += `${
|
|
7689
|
+
output += `${chalk16.bold("Git User:")} ${userDisplay}
|
|
7559
7690
|
`;
|
|
7560
7691
|
} else {
|
|
7561
|
-
output += `${
|
|
7692
|
+
output += `${chalk16.bold("Git User:")} ` + chalk16.yellow("\u26A0\uFE0F Not configured (run git config --global user.name/email)\n");
|
|
7562
7693
|
}
|
|
7563
7694
|
output += "\n";
|
|
7564
7695
|
}
|
|
7565
|
-
output +=
|
|
7566
|
-
output += `${
|
|
7696
|
+
output += chalk16.bold("Installed Coding Tools\n");
|
|
7697
|
+
output += `${chalk16.dim("\u2500".repeat(50))}
|
|
7567
7698
|
`;
|
|
7568
7699
|
const cliToolsUnauthenticated = await checkInstalledCliTools();
|
|
7569
7700
|
const installedTools2 = cliToolsUnauthenticated.filter((tool) => tool.installed);
|
|
7570
7701
|
if (installedTools2.length === 0) {
|
|
7571
|
-
output +=
|
|
7702
|
+
output += chalk16.yellow("\u26A0\uFE0F No coding tools detected\n\n");
|
|
7572
7703
|
} else {
|
|
7573
7704
|
installedTools2.forEach((tool) => {
|
|
7574
|
-
const versionInfo = tool.version ?
|
|
7575
|
-
output += `${
|
|
7705
|
+
const versionInfo = tool.version ? chalk16.dim(` (${tool.version})`) : "";
|
|
7706
|
+
output += `${chalk16.green("\u2705")} ${tool.name}${versionInfo}
|
|
7576
7707
|
`;
|
|
7577
7708
|
});
|
|
7578
7709
|
output += "\n";
|
|
7579
7710
|
}
|
|
7580
|
-
output +=
|
|
7581
|
-
output += `${
|
|
7711
|
+
output += chalk16.bold("Configuration\n");
|
|
7712
|
+
output += `${chalk16.dim("\u2500".repeat(50))}
|
|
7582
7713
|
`;
|
|
7583
|
-
output += `${
|
|
7714
|
+
output += `${chalk16.bold("API URL:")} ${config2.apiUrl}
|
|
7584
7715
|
`;
|
|
7585
|
-
output += `${
|
|
7716
|
+
output += `${chalk16.bold("OAuth Client:")} ${config2.oauthClientId}
|
|
7586
7717
|
`;
|
|
7587
|
-
output += `${
|
|
7718
|
+
output += `${chalk16.bold("Redirect URI:")} http://127.0.0.1:34536/callback
|
|
7588
7719
|
`;
|
|
7589
|
-
output += `${
|
|
7720
|
+
output += `${chalk16.bold("Config Path:")} ${credentialStore.getStoragePath()}
|
|
7590
7721
|
|
|
7591
7722
|
`;
|
|
7592
|
-
output +=
|
|
7593
|
-
output += `${
|
|
7723
|
+
output += chalk16.bold("Overall Status\n");
|
|
7724
|
+
output += `${chalk16.dim("\u2500".repeat(50))}
|
|
7594
7725
|
`;
|
|
7595
|
-
output +=
|
|
7726
|
+
output += chalk16.yellow("\u26A0\uFE0F Setup required - please authenticate\n");
|
|
7596
7727
|
return {
|
|
7597
7728
|
success: true,
|
|
7598
7729
|
message: output,
|
|
@@ -7601,94 +7732,94 @@ async function handleStatus() {
|
|
|
7601
7732
|
}
|
|
7602
7733
|
const session = await auth.getStoredSession();
|
|
7603
7734
|
if (!session) {
|
|
7604
|
-
output +=
|
|
7735
|
+
output += chalk16.red("\u274C Session not found\n\n");
|
|
7605
7736
|
return {
|
|
7606
7737
|
success: true,
|
|
7607
7738
|
message: output,
|
|
7608
7739
|
data: { authenticated: false }
|
|
7609
7740
|
};
|
|
7610
7741
|
}
|
|
7611
|
-
output +=
|
|
7742
|
+
output += chalk16.green("\u2705 Authenticated\n");
|
|
7612
7743
|
const userName = `${session.user.firstName || ""} ${session.user.lastName || ""}`.trim();
|
|
7613
7744
|
if (userName) {
|
|
7614
|
-
output += `${
|
|
7745
|
+
output += `${chalk16.bold("Name:")} ${userName}
|
|
7615
7746
|
`;
|
|
7616
7747
|
}
|
|
7617
|
-
output += `${
|
|
7748
|
+
output += `${chalk16.bold("Email:")} ${session.user.email}
|
|
7618
7749
|
`;
|
|
7619
|
-
output += `${
|
|
7750
|
+
output += `${chalk16.bold("User ID:")} ${session.user.id}
|
|
7620
7751
|
`;
|
|
7621
|
-
output += `${
|
|
7752
|
+
output += `${chalk16.bold("Organization:")} ${session.organization_id}
|
|
7622
7753
|
`;
|
|
7623
7754
|
const sessionAge = Math.floor((Date.now() - session.created_at.getTime()) / 1e3 / 60);
|
|
7624
|
-
output += `${
|
|
7755
|
+
output += `${chalk16.bold("Session Age:")} ${sessionAge} minutes
|
|
7625
7756
|
`;
|
|
7626
|
-
output += `${
|
|
7757
|
+
output += `${chalk16.bold("API URL:")} ${config2.apiUrl}
|
|
7627
7758
|
`;
|
|
7628
|
-
output += `${
|
|
7759
|
+
output += `${chalk16.bold("Config Path:")} ${credentialStore.getStoragePath()}
|
|
7629
7760
|
|
|
7630
7761
|
`;
|
|
7631
|
-
output +=
|
|
7632
|
-
output += `${
|
|
7762
|
+
output += chalk16.bold("Git Repository\n");
|
|
7763
|
+
output += `${chalk16.dim("\u2500".repeat(50))}
|
|
7633
7764
|
`;
|
|
7634
7765
|
const gitInfo = await getGitRepositoryInfo();
|
|
7635
7766
|
if (!gitInfo || !gitInfo.isRepo) {
|
|
7636
|
-
output +=
|
|
7767
|
+
output += chalk16.yellow("\u26A0\uFE0F Not in a git repository\n\n");
|
|
7637
7768
|
} else {
|
|
7638
|
-
output +=
|
|
7769
|
+
output += chalk16.green("\u2705 Repository detected!\n");
|
|
7639
7770
|
if (gitInfo.owner && gitInfo.name) {
|
|
7640
|
-
output += `${
|
|
7771
|
+
output += `${chalk16.bold("Owner:")} ${gitInfo.owner}
|
|
7641
7772
|
`;
|
|
7642
|
-
output += `${
|
|
7773
|
+
output += `${chalk16.bold("Name:")} ${gitInfo.name}
|
|
7643
7774
|
`;
|
|
7644
7775
|
} else if (gitInfo.remoteUrl) {
|
|
7645
|
-
output += `${
|
|
7776
|
+
output += `${chalk16.bold("Remote:")} ${gitInfo.remoteUrl}
|
|
7646
7777
|
`;
|
|
7647
7778
|
} else {
|
|
7648
|
-
output +=
|
|
7779
|
+
output += chalk16.yellow("\u26A0\uFE0F Local repository (no remote)\n");
|
|
7649
7780
|
}
|
|
7650
7781
|
if (gitInfo.branch) {
|
|
7651
|
-
output += `${
|
|
7782
|
+
output += `${chalk16.bold("Branch:")} ${gitInfo.branch}
|
|
7652
7783
|
`;
|
|
7653
7784
|
}
|
|
7654
7785
|
if (gitInfo.userName || gitInfo.userEmail) {
|
|
7655
7786
|
const userDisplay = gitInfo.userName && gitInfo.userEmail ? `${gitInfo.userName} <${gitInfo.userEmail}>` : gitInfo.userName || gitInfo.userEmail;
|
|
7656
|
-
output += `${
|
|
7787
|
+
output += `${chalk16.bold("Git User:")} ${userDisplay}
|
|
7657
7788
|
`;
|
|
7658
7789
|
} else {
|
|
7659
|
-
output += `${
|
|
7790
|
+
output += `${chalk16.bold("Git User:")} ` + chalk16.yellow("\u26A0\uFE0F Not configured (run git config --global user.name/email)\n");
|
|
7660
7791
|
}
|
|
7661
7792
|
output += "\n";
|
|
7662
7793
|
}
|
|
7663
|
-
output +=
|
|
7664
|
-
output += `${
|
|
7794
|
+
output += chalk16.bold("Installed Coding Tools\n");
|
|
7795
|
+
output += `${chalk16.dim("\u2500".repeat(50))}
|
|
7665
7796
|
`;
|
|
7666
7797
|
const cliTools = await checkInstalledCliTools();
|
|
7667
7798
|
const installedTools = cliTools.filter((tool) => tool.installed);
|
|
7668
7799
|
if (installedTools.length === 0) {
|
|
7669
|
-
output +=
|
|
7800
|
+
output += chalk16.yellow("\u26A0\uFE0F No coding tools detected\n\n");
|
|
7670
7801
|
} else {
|
|
7671
7802
|
installedTools.forEach((tool) => {
|
|
7672
|
-
const versionInfo = tool.version ?
|
|
7673
|
-
output += `${
|
|
7803
|
+
const versionInfo = tool.version ? chalk16.dim(` (${tool.version})`) : "";
|
|
7804
|
+
output += `${chalk16.green("\u2705")} ${tool.name}${versionInfo}
|
|
7674
7805
|
`;
|
|
7675
7806
|
});
|
|
7676
7807
|
output += "\n";
|
|
7677
7808
|
}
|
|
7678
|
-
output +=
|
|
7679
|
-
output += `${
|
|
7809
|
+
output += chalk16.bold("Configuration\n");
|
|
7810
|
+
output += `${chalk16.dim("\u2500".repeat(50))}
|
|
7680
7811
|
`;
|
|
7681
|
-
output += `${
|
|
7812
|
+
output += `${chalk16.bold("OAuth Client:")} ${config2.oauthClientId}
|
|
7682
7813
|
`;
|
|
7683
|
-
output += `${
|
|
7814
|
+
output += `${chalk16.bold("Redirect URI:")} http://127.0.0.1:34536/callback
|
|
7684
7815
|
`;
|
|
7685
|
-
output += `${
|
|
7816
|
+
output += `${chalk16.bold("Auth Server:")} ${config2.getWorkOSAuthUrl()}
|
|
7686
7817
|
|
|
7687
7818
|
`;
|
|
7688
|
-
output +=
|
|
7689
|
-
output += `${
|
|
7819
|
+
output += chalk16.bold("Overall Status\n");
|
|
7820
|
+
output += `${chalk16.dim("\u2500".repeat(50))}
|
|
7690
7821
|
`;
|
|
7691
|
-
output +=
|
|
7822
|
+
output += chalk16.green("\u2705 Ready to use BrainGrid CLI\n");
|
|
7692
7823
|
return {
|
|
7693
7824
|
success: true,
|
|
7694
7825
|
message: output,
|
|
@@ -7703,7 +7834,7 @@ async function handleStatus() {
|
|
|
7703
7834
|
}
|
|
7704
7835
|
|
|
7705
7836
|
// src/handlers/task.handlers.ts
|
|
7706
|
-
import
|
|
7837
|
+
import chalk17 from "chalk";
|
|
7707
7838
|
|
|
7708
7839
|
// src/services/task-service.ts
|
|
7709
7840
|
var TaskService = class {
|
|
@@ -7807,7 +7938,7 @@ async function handleTaskList(opts) {
|
|
|
7807
7938
|
if (!isAuthenticated) {
|
|
7808
7939
|
return {
|
|
7809
7940
|
success: false,
|
|
7810
|
-
message:
|
|
7941
|
+
message: chalk17.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
7811
7942
|
};
|
|
7812
7943
|
}
|
|
7813
7944
|
const workspace = await workspaceManager.getProject(opts.project);
|
|
@@ -7827,7 +7958,7 @@ async function handleTaskList(opts) {
|
|
|
7827
7958
|
}
|
|
7828
7959
|
const requirementId = requirementResult.requirementId;
|
|
7829
7960
|
if (opts.format !== "json" && opts.format !== "xml") {
|
|
7830
|
-
stopSpinner = showSpinner("Loading tasks",
|
|
7961
|
+
stopSpinner = showSpinner("Loading tasks", chalk17.gray);
|
|
7831
7962
|
}
|
|
7832
7963
|
const response = await taskService.listTasks(projectId, requirementId, {
|
|
7833
7964
|
page: opts.page ? parseInt(opts.page, 10) : 1,
|
|
@@ -7840,7 +7971,7 @@ async function handleTaskList(opts) {
|
|
|
7840
7971
|
if (response.tasks.length === 0) {
|
|
7841
7972
|
return {
|
|
7842
7973
|
success: true,
|
|
7843
|
-
message:
|
|
7974
|
+
message: chalk17.yellow("No tasks found."),
|
|
7844
7975
|
data: response
|
|
7845
7976
|
};
|
|
7846
7977
|
}
|
|
@@ -7856,7 +7987,7 @@ async function handleTaskList(opts) {
|
|
|
7856
7987
|
});
|
|
7857
7988
|
if (response.pagination?.has_more) {
|
|
7858
7989
|
output += `
|
|
7859
|
-
${
|
|
7990
|
+
${chalk17.yellow("\u26A0\uFE0F More tasks exist. Use --limit to see more.")}`;
|
|
7860
7991
|
}
|
|
7861
7992
|
return {
|
|
7862
7993
|
success: true,
|
|
@@ -7881,7 +8012,7 @@ async function handleTaskSummary(opts) {
|
|
|
7881
8012
|
if (!isAuthenticated) {
|
|
7882
8013
|
return {
|
|
7883
8014
|
success: false,
|
|
7884
|
-
message:
|
|
8015
|
+
message: chalk17.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
7885
8016
|
};
|
|
7886
8017
|
}
|
|
7887
8018
|
const workspace = await workspaceManager.getProject(opts.project);
|
|
@@ -7900,7 +8031,7 @@ async function handleTaskSummary(opts) {
|
|
|
7900
8031
|
};
|
|
7901
8032
|
}
|
|
7902
8033
|
const requirementId = requirementResult.requirementId;
|
|
7903
|
-
stopSpinner = showSpinner("Loading tasks",
|
|
8034
|
+
stopSpinner = showSpinner("Loading tasks", chalk17.gray);
|
|
7904
8035
|
const response = await taskService.listTasks(projectId, requirementId, {
|
|
7905
8036
|
page: opts.page ? parseInt(opts.page, 10) : 1,
|
|
7906
8037
|
limit: opts.limit ? parseInt(opts.limit, 10) : 20
|
|
@@ -7910,7 +8041,7 @@ async function handleTaskSummary(opts) {
|
|
|
7910
8041
|
if (response.tasks.length === 0) {
|
|
7911
8042
|
return {
|
|
7912
8043
|
success: true,
|
|
7913
|
-
message:
|
|
8044
|
+
message: chalk17.yellow("No tasks found."),
|
|
7914
8045
|
data: response
|
|
7915
8046
|
};
|
|
7916
8047
|
}
|
|
@@ -7925,7 +8056,7 @@ async function handleTaskSummary(opts) {
|
|
|
7925
8056
|
});
|
|
7926
8057
|
if (response.pagination?.has_more) {
|
|
7927
8058
|
output += `
|
|
7928
|
-
${
|
|
8059
|
+
${chalk17.yellow("\u26A0\uFE0F More tasks exist. Use --limit to see more.")}`;
|
|
7929
8060
|
}
|
|
7930
8061
|
return {
|
|
7931
8062
|
success: true,
|
|
@@ -7950,14 +8081,14 @@ async function handleTaskShow(id, opts) {
|
|
|
7950
8081
|
if (!isAuthenticated) {
|
|
7951
8082
|
return {
|
|
7952
8083
|
success: false,
|
|
7953
|
-
message:
|
|
8084
|
+
message: chalk17.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
7954
8085
|
};
|
|
7955
8086
|
}
|
|
7956
8087
|
const format = opts?.format || "markdown";
|
|
7957
8088
|
if (!["markdown", "json", "xml", "table"].includes(format)) {
|
|
7958
8089
|
return {
|
|
7959
8090
|
success: false,
|
|
7960
|
-
message:
|
|
8091
|
+
message: chalk17.red(
|
|
7961
8092
|
`\u274C Invalid format: ${format}. Supported formats: markdown, json, xml, table`
|
|
7962
8093
|
)
|
|
7963
8094
|
};
|
|
@@ -7987,14 +8118,14 @@ async function handleTaskShow(id, opts) {
|
|
|
7987
8118
|
if (!currentTask.success) {
|
|
7988
8119
|
return {
|
|
7989
8120
|
success: false,
|
|
7990
|
-
message:
|
|
8121
|
+
message: chalk17.red(`\u274C ${currentTask.error}`)
|
|
7991
8122
|
};
|
|
7992
8123
|
}
|
|
7993
8124
|
taskId = currentTask.taskId;
|
|
7994
8125
|
taskWarning = currentTask.warning;
|
|
7995
8126
|
}
|
|
7996
8127
|
const config2 = getConfig();
|
|
7997
|
-
stopSpinner = showSpinner("Loading task",
|
|
8128
|
+
stopSpinner = showSpinner("Loading task", chalk17.gray);
|
|
7998
8129
|
const task2 = await taskService.getTask(projectId, requirementId, taskId);
|
|
7999
8130
|
stopSpinner();
|
|
8000
8131
|
stopSpinner = null;
|
|
@@ -8027,7 +8158,7 @@ async function handleTaskShow(id, opts) {
|
|
|
8027
8158
|
}
|
|
8028
8159
|
if (taskWarning) {
|
|
8029
8160
|
output += `
|
|
8030
|
-
${
|
|
8161
|
+
${chalk17.yellow(`\u26A0\uFE0F ${taskWarning}`)}`;
|
|
8031
8162
|
}
|
|
8032
8163
|
return {
|
|
8033
8164
|
success: true,
|
|
@@ -8052,7 +8183,7 @@ async function handleTaskCreate(opts) {
|
|
|
8052
8183
|
if (!isAuthenticated) {
|
|
8053
8184
|
return {
|
|
8054
8185
|
success: false,
|
|
8055
|
-
message:
|
|
8186
|
+
message: chalk17.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
8056
8187
|
};
|
|
8057
8188
|
}
|
|
8058
8189
|
const workspace = await workspaceManager.getProject(opts.project);
|
|
@@ -8074,7 +8205,7 @@ async function handleTaskCreate(opts) {
|
|
|
8074
8205
|
const projectShortId = projectId;
|
|
8075
8206
|
const requirementShortId = opts.requirement || requirementId;
|
|
8076
8207
|
const config2 = getConfig();
|
|
8077
|
-
stopSpinner = showSpinner("Creating task",
|
|
8208
|
+
stopSpinner = showSpinner("Creating task", chalk17.gray);
|
|
8078
8209
|
const task2 = await taskService.createTask(projectId, requirementId, {
|
|
8079
8210
|
title: opts.title,
|
|
8080
8211
|
content: opts.content,
|
|
@@ -8113,13 +8244,13 @@ async function handleTaskUpdate(id, opts) {
|
|
|
8113
8244
|
if (!isAuthenticated) {
|
|
8114
8245
|
return {
|
|
8115
8246
|
success: false,
|
|
8116
|
-
message:
|
|
8247
|
+
message: chalk17.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
8117
8248
|
};
|
|
8118
8249
|
}
|
|
8119
8250
|
if (!opts?.status && !opts?.title && !opts?.externalId) {
|
|
8120
8251
|
return {
|
|
8121
8252
|
success: false,
|
|
8122
|
-
message:
|
|
8253
|
+
message: chalk17.red(
|
|
8123
8254
|
"\u274C Please provide at least one field to update (--status, --title, or --external-id)"
|
|
8124
8255
|
)
|
|
8125
8256
|
};
|
|
@@ -8149,14 +8280,14 @@ async function handleTaskUpdate(id, opts) {
|
|
|
8149
8280
|
if (!currentTask.success) {
|
|
8150
8281
|
return {
|
|
8151
8282
|
success: false,
|
|
8152
|
-
message:
|
|
8283
|
+
message: chalk17.red(`\u274C ${currentTask.error}`)
|
|
8153
8284
|
};
|
|
8154
8285
|
}
|
|
8155
8286
|
taskId = currentTask.taskId;
|
|
8156
8287
|
taskWarning = currentTask.warning;
|
|
8157
8288
|
}
|
|
8158
8289
|
const config2 = getConfig();
|
|
8159
|
-
stopSpinner = showSpinner("Updating task",
|
|
8290
|
+
stopSpinner = showSpinner("Updating task", chalk17.gray);
|
|
8160
8291
|
const task2 = await taskService.updateTask(projectId, requirementId, taskId, {
|
|
8161
8292
|
status: opts?.status,
|
|
8162
8293
|
title: opts?.title,
|
|
@@ -8174,7 +8305,7 @@ async function handleTaskUpdate(id, opts) {
|
|
|
8174
8305
|
});
|
|
8175
8306
|
if (taskWarning) {
|
|
8176
8307
|
output += `
|
|
8177
|
-
${
|
|
8308
|
+
${chalk17.yellow(`\u26A0\uFE0F ${taskWarning}`)}`;
|
|
8178
8309
|
}
|
|
8179
8310
|
return {
|
|
8180
8311
|
success: true,
|
|
@@ -8199,13 +8330,13 @@ async function handleTaskDelete(id, opts) {
|
|
|
8199
8330
|
if (!isAuthenticated) {
|
|
8200
8331
|
return {
|
|
8201
8332
|
success: false,
|
|
8202
|
-
message:
|
|
8333
|
+
message: chalk17.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
8203
8334
|
};
|
|
8204
8335
|
}
|
|
8205
8336
|
if (!opts.force) {
|
|
8206
8337
|
return {
|
|
8207
8338
|
success: false,
|
|
8208
|
-
message:
|
|
8339
|
+
message: chalk17.yellow("\u26A0\uFE0F Deleting a task is permanent. Use --force to confirm deletion.")
|
|
8209
8340
|
};
|
|
8210
8341
|
}
|
|
8211
8342
|
const workspace = await workspaceManager.getProject(opts.project);
|
|
@@ -8225,13 +8356,13 @@ async function handleTaskDelete(id, opts) {
|
|
|
8225
8356
|
}
|
|
8226
8357
|
const requirementId = requirementResult.requirementId;
|
|
8227
8358
|
const taskId = normalizeTaskId(id);
|
|
8228
|
-
stopSpinner = showSpinner("Deleting task",
|
|
8359
|
+
stopSpinner = showSpinner("Deleting task", chalk17.gray);
|
|
8229
8360
|
await taskService.deleteTask(projectId, requirementId, taskId);
|
|
8230
8361
|
stopSpinner();
|
|
8231
8362
|
stopSpinner = null;
|
|
8232
8363
|
return {
|
|
8233
8364
|
success: true,
|
|
8234
|
-
message:
|
|
8365
|
+
message: chalk17.green(`\u2705 Deleted task ${id}`)
|
|
8235
8366
|
};
|
|
8236
8367
|
} catch (error) {
|
|
8237
8368
|
if (stopSpinner) {
|
|
@@ -8251,14 +8382,14 @@ async function handleTaskSpecify(opts) {
|
|
|
8251
8382
|
if (!isAuthenticated) {
|
|
8252
8383
|
return {
|
|
8253
8384
|
success: false,
|
|
8254
|
-
message:
|
|
8385
|
+
message: chalk17.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
8255
8386
|
};
|
|
8256
8387
|
}
|
|
8257
8388
|
const format = opts.format || "table";
|
|
8258
8389
|
if (!["table", "json", "markdown"].includes(format)) {
|
|
8259
8390
|
return {
|
|
8260
8391
|
success: false,
|
|
8261
|
-
message:
|
|
8392
|
+
message: chalk17.red(
|
|
8262
8393
|
`\u274C Invalid format: ${format}. Supported formats: table, json, markdown`
|
|
8263
8394
|
)
|
|
8264
8395
|
};
|
|
@@ -8282,16 +8413,16 @@ async function handleTaskSpecify(opts) {
|
|
|
8282
8413
|
if (opts.prompt.length < 10) {
|
|
8283
8414
|
return {
|
|
8284
8415
|
success: false,
|
|
8285
|
-
message:
|
|
8416
|
+
message: chalk17.red("\u274C Prompt must be at least 10 characters long")
|
|
8286
8417
|
};
|
|
8287
8418
|
}
|
|
8288
8419
|
if (opts.prompt.length > 5e3) {
|
|
8289
8420
|
return {
|
|
8290
8421
|
success: false,
|
|
8291
|
-
message:
|
|
8422
|
+
message: chalk17.red("\u274C Prompt must be no more than 5000 characters long")
|
|
8292
8423
|
};
|
|
8293
8424
|
}
|
|
8294
|
-
stopSpinner = showSpinner("Creating task from prompt...",
|
|
8425
|
+
stopSpinner = showSpinner("Creating task from prompt...", chalk17.gray);
|
|
8295
8426
|
const response = await taskService.specifyTask(projectId, requirementId, {
|
|
8296
8427
|
prompt: opts.prompt
|
|
8297
8428
|
});
|
|
@@ -8331,10 +8462,10 @@ async function handleTaskSpecify(opts) {
|
|
|
8331
8462
|
function formatTaskSpecifyTable(response) {
|
|
8332
8463
|
const task2 = response.task;
|
|
8333
8464
|
const lines = [];
|
|
8334
|
-
lines.push(
|
|
8465
|
+
lines.push(chalk17.green(`\u2705 Created task ${response.requirement_short_id}/TASK-${task2.number}`));
|
|
8335
8466
|
lines.push("");
|
|
8336
|
-
lines.push(`${
|
|
8337
|
-
lines.push(`${
|
|
8467
|
+
lines.push(`${chalk17.bold("Title:")} ${task2.title}`);
|
|
8468
|
+
lines.push(`${chalk17.bold("Status:")} ${task2.status}`);
|
|
8338
8469
|
return lines.join("\n");
|
|
8339
8470
|
}
|
|
8340
8471
|
function formatTaskSpecifyMarkdown(response, _apiUrl) {
|
|
@@ -8656,6 +8787,14 @@ task.command("specify").description("Create a single task from a prompt using AI
|
|
|
8656
8787
|
process.exit(1);
|
|
8657
8788
|
}
|
|
8658
8789
|
});
|
|
8790
|
+
var claudeCode = program.command("claude-code").description("Claude Code utilities");
|
|
8791
|
+
claudeCode.command("credentials").description("Show Claude Code credentials from macOS Keychain").option("--raw", "print full unmasked JSON (for piping/scripting)").action(async (opts) => {
|
|
8792
|
+
const result = await handleClaudeCodeCredentials(opts);
|
|
8793
|
+
console.log(result.message);
|
|
8794
|
+
if (!result.success) {
|
|
8795
|
+
process.exit(1);
|
|
8796
|
+
}
|
|
8797
|
+
});
|
|
8659
8798
|
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
8799
|
const result = await handleCompletion(shell, opts);
|
|
8661
8800
|
console.log(result.message);
|