@braingrid/cli 0.2.15 → 0.2.17
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 +21 -0
- package/dist/cli.js +501 -346
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -422,7 +422,7 @@ import axios3, { AxiosError as AxiosError2 } from "axios";
|
|
|
422
422
|
|
|
423
423
|
// src/build-config.ts
|
|
424
424
|
var BUILD_ENV = true ? "production" : process.env.NODE_ENV === "test" ? "development" : "production";
|
|
425
|
-
var CLI_VERSION = true ? "0.2.
|
|
425
|
+
var CLI_VERSION = true ? "0.2.17" : "0.0.0-test";
|
|
426
426
|
var PRODUCTION_CONFIG = {
|
|
427
427
|
apiUrl: "https://app.braingrid.ai",
|
|
428
428
|
workosAuthUrl: "https://auth.braingrid.ai",
|
|
@@ -3940,6 +3940,15 @@ async function handleRequirementShow(opts) {
|
|
|
3940
3940
|
message: chalk7.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
3941
3941
|
};
|
|
3942
3942
|
}
|
|
3943
|
+
const format = opts?.format || "table";
|
|
3944
|
+
if (!["table", "json", "xml", "markdown"].includes(format)) {
|
|
3945
|
+
return {
|
|
3946
|
+
success: false,
|
|
3947
|
+
message: chalk7.red(
|
|
3948
|
+
`\u274C Invalid format: ${format}. Supported formats: table, json, xml, markdown`
|
|
3949
|
+
)
|
|
3950
|
+
};
|
|
3951
|
+
}
|
|
3943
3952
|
const requirementResult = await workspaceManager.getRequirement(opts?.id);
|
|
3944
3953
|
if (!requirementResult.success) {
|
|
3945
3954
|
return {
|
|
@@ -3961,17 +3970,39 @@ async function handleRequirementShow(opts) {
|
|
|
3961
3970
|
const requirement2 = await requirementService.getProjectRequirement(projectId, normalizedId);
|
|
3962
3971
|
stopSpinner();
|
|
3963
3972
|
stopSpinner = null;
|
|
3964
|
-
|
|
3965
|
-
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
|
|
3970
|
-
|
|
3971
|
-
|
|
3973
|
+
let output;
|
|
3974
|
+
switch (format) {
|
|
3975
|
+
case "json": {
|
|
3976
|
+
output = JSON.stringify(requirement2, null, 2);
|
|
3977
|
+
break;
|
|
3978
|
+
}
|
|
3979
|
+
case "xml": {
|
|
3980
|
+
output = formatRequirementBuildXml(requirement2);
|
|
3981
|
+
break;
|
|
3982
|
+
}
|
|
3983
|
+
case "markdown": {
|
|
3984
|
+
output = formatRequirementBuildMarkdown(requirement2, {
|
|
3985
|
+
apiUrl: config.apiUrl,
|
|
3986
|
+
projectShortId: projectId
|
|
3987
|
+
});
|
|
3988
|
+
break;
|
|
3989
|
+
}
|
|
3990
|
+
case "table":
|
|
3991
|
+
default: {
|
|
3992
|
+
output = "\n" + formatRequirementOutput(requirement2, {
|
|
3993
|
+
showDescription: true,
|
|
3994
|
+
showContent: true,
|
|
3995
|
+
showTasks: true,
|
|
3996
|
+
showUpdated: true,
|
|
3997
|
+
apiUrl: config.apiUrl,
|
|
3998
|
+
projectShortId: projectId
|
|
3999
|
+
});
|
|
4000
|
+
break;
|
|
4001
|
+
}
|
|
4002
|
+
}
|
|
3972
4003
|
return {
|
|
3973
4004
|
success: true,
|
|
3974
|
-
message:
|
|
4005
|
+
message: output,
|
|
3975
4006
|
data: requirement2
|
|
3976
4007
|
};
|
|
3977
4008
|
} catch (error) {
|
|
@@ -4623,6 +4654,15 @@ async function handleTaskShow(id, opts) {
|
|
|
4623
4654
|
message: chalk8.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
4624
4655
|
};
|
|
4625
4656
|
}
|
|
4657
|
+
const format = opts?.format || "table";
|
|
4658
|
+
if (!["table", "json", "xml", "markdown"].includes(format)) {
|
|
4659
|
+
return {
|
|
4660
|
+
success: false,
|
|
4661
|
+
message: chalk8.red(
|
|
4662
|
+
`\u274C Invalid format: ${format}. Supported formats: table, json, xml, markdown`
|
|
4663
|
+
)
|
|
4664
|
+
};
|
|
4665
|
+
}
|
|
4626
4666
|
const workspace = await workspaceManager.getProject(opts?.project);
|
|
4627
4667
|
if (!workspace.success) {
|
|
4628
4668
|
return {
|
|
@@ -4645,13 +4685,34 @@ async function handleTaskShow(id, opts) {
|
|
|
4645
4685
|
const task2 = await taskService.getTask(projectId, requirementId, taskId);
|
|
4646
4686
|
stopSpinner();
|
|
4647
4687
|
stopSpinner = null;
|
|
4648
|
-
|
|
4649
|
-
|
|
4650
|
-
|
|
4651
|
-
|
|
4652
|
-
|
|
4653
|
-
|
|
4654
|
-
|
|
4688
|
+
let output;
|
|
4689
|
+
switch (format) {
|
|
4690
|
+
case "json": {
|
|
4691
|
+
output = JSON.stringify(task2, null, 2);
|
|
4692
|
+
break;
|
|
4693
|
+
}
|
|
4694
|
+
case "xml":
|
|
4695
|
+
case "markdown": {
|
|
4696
|
+
output = formatTasksListOutput([task2], format, true, {
|
|
4697
|
+
requirementId,
|
|
4698
|
+
projectShortId: projectId,
|
|
4699
|
+
requirementShortId: opts?.requirement || requirementId,
|
|
4700
|
+
apiUrl: config.apiUrl
|
|
4701
|
+
});
|
|
4702
|
+
break;
|
|
4703
|
+
}
|
|
4704
|
+
case "table":
|
|
4705
|
+
default: {
|
|
4706
|
+
output = formatTaskOutput(task2, {
|
|
4707
|
+
showContent: true,
|
|
4708
|
+
apiUrl: config.apiUrl,
|
|
4709
|
+
projectShortId: projectId,
|
|
4710
|
+
requirementShortId: opts?.requirement || requirementId,
|
|
4711
|
+
requirementId
|
|
4712
|
+
});
|
|
4713
|
+
break;
|
|
4714
|
+
}
|
|
4715
|
+
}
|
|
4655
4716
|
return {
|
|
4656
4717
|
success: true,
|
|
4657
4718
|
message: output,
|
|
@@ -5126,8 +5187,8 @@ async function handleStatus() {
|
|
|
5126
5187
|
}
|
|
5127
5188
|
|
|
5128
5189
|
// src/handlers/init.handlers.ts
|
|
5129
|
-
import
|
|
5130
|
-
import { confirm, select as
|
|
5190
|
+
import chalk15 from "chalk";
|
|
5191
|
+
import { confirm, select as select3, input } from "@inquirer/prompts";
|
|
5131
5192
|
|
|
5132
5193
|
// src/services/internal/github-service.ts
|
|
5133
5194
|
var GitHubService = class {
|
|
@@ -5394,9 +5455,277 @@ function getManualInstallInstructions() {
|
|
|
5394
5455
|
}
|
|
5395
5456
|
}
|
|
5396
5457
|
|
|
5397
|
-
// src/handlers/
|
|
5458
|
+
// src/handlers/update.handlers.ts
|
|
5398
5459
|
import chalk12 from "chalk";
|
|
5460
|
+
|
|
5461
|
+
// src/utils/package-manager.ts
|
|
5462
|
+
import { execSync } from "child_process";
|
|
5399
5463
|
import { select } from "@inquirer/prompts";
|
|
5464
|
+
function isPackageManagerInstalled(pm) {
|
|
5465
|
+
try {
|
|
5466
|
+
execSync(`which ${pm}`, { stdio: "ignore", timeout: 2e3 });
|
|
5467
|
+
return true;
|
|
5468
|
+
} catch {
|
|
5469
|
+
return false;
|
|
5470
|
+
}
|
|
5471
|
+
}
|
|
5472
|
+
function checkGlobalInstallation(pm, packageName) {
|
|
5473
|
+
try {
|
|
5474
|
+
let command;
|
|
5475
|
+
switch (pm) {
|
|
5476
|
+
case "npm": {
|
|
5477
|
+
command = `npm list -g ${packageName} 2>&1`;
|
|
5478
|
+
break;
|
|
5479
|
+
}
|
|
5480
|
+
case "pnpm": {
|
|
5481
|
+
command = `pnpm list -g ${packageName} 2>&1`;
|
|
5482
|
+
break;
|
|
5483
|
+
}
|
|
5484
|
+
case "yarn": {
|
|
5485
|
+
command = `yarn global list 2>&1`;
|
|
5486
|
+
break;
|
|
5487
|
+
}
|
|
5488
|
+
}
|
|
5489
|
+
const output = execSync(command, {
|
|
5490
|
+
encoding: "utf-8",
|
|
5491
|
+
timeout: 5e3
|
|
5492
|
+
});
|
|
5493
|
+
if (pm === "npm" || pm === "pnpm") {
|
|
5494
|
+
return output.includes(packageName) && !output.includes("(empty)");
|
|
5495
|
+
}
|
|
5496
|
+
if (pm === "yarn") {
|
|
5497
|
+
return output.includes(packageName);
|
|
5498
|
+
}
|
|
5499
|
+
return false;
|
|
5500
|
+
} catch {
|
|
5501
|
+
return false;
|
|
5502
|
+
}
|
|
5503
|
+
}
|
|
5504
|
+
async function getPackageManagerInfo(packageName) {
|
|
5505
|
+
const packageManagers = ["npm", "pnpm", "yarn"];
|
|
5506
|
+
return packageManagers.map((pm) => {
|
|
5507
|
+
const installed = isPackageManagerInstalled(pm);
|
|
5508
|
+
return {
|
|
5509
|
+
name: pm,
|
|
5510
|
+
installed,
|
|
5511
|
+
hasPackage: installed ? checkGlobalInstallation(pm, packageName) : false
|
|
5512
|
+
};
|
|
5513
|
+
});
|
|
5514
|
+
}
|
|
5515
|
+
async function detectPackageManager(packageName) {
|
|
5516
|
+
const pmInfo = await getPackageManagerInfo(packageName);
|
|
5517
|
+
const installedWith = pmInfo.find((pm) => pm.hasPackage);
|
|
5518
|
+
if (installedWith) {
|
|
5519
|
+
return installedWith.name;
|
|
5520
|
+
}
|
|
5521
|
+
const availablePMs = pmInfo.filter((pm) => pm.installed);
|
|
5522
|
+
if (availablePMs.length === 0) {
|
|
5523
|
+
throw new Error("No package manager found. Please install npm, pnpm, or yarn.");
|
|
5524
|
+
}
|
|
5525
|
+
if (availablePMs.length === 1) {
|
|
5526
|
+
return availablePMs[0].name;
|
|
5527
|
+
}
|
|
5528
|
+
const selected = await select({
|
|
5529
|
+
message: "Unable to detect which package manager was used. Please select one:",
|
|
5530
|
+
choices: availablePMs.map((pm) => ({
|
|
5531
|
+
name: pm.name,
|
|
5532
|
+
value: pm.name
|
|
5533
|
+
}))
|
|
5534
|
+
});
|
|
5535
|
+
return selected;
|
|
5536
|
+
}
|
|
5537
|
+
function getUpdateCommand(pm, packageName) {
|
|
5538
|
+
switch (pm) {
|
|
5539
|
+
case "npm": {
|
|
5540
|
+
return `npm install -g ${packageName}@latest`;
|
|
5541
|
+
}
|
|
5542
|
+
case "pnpm": {
|
|
5543
|
+
return `pnpm add -g ${packageName}@latest`;
|
|
5544
|
+
}
|
|
5545
|
+
case "yarn": {
|
|
5546
|
+
return `yarn global add ${packageName}@latest`;
|
|
5547
|
+
}
|
|
5548
|
+
}
|
|
5549
|
+
}
|
|
5550
|
+
function executeUpdate(pm, packageName) {
|
|
5551
|
+
const command = getUpdateCommand(pm, packageName);
|
|
5552
|
+
try {
|
|
5553
|
+
execSync(command, {
|
|
5554
|
+
stdio: "inherit",
|
|
5555
|
+
timeout: 12e4
|
|
5556
|
+
// 2 minutes timeout
|
|
5557
|
+
});
|
|
5558
|
+
} catch (error) {
|
|
5559
|
+
throw new Error(
|
|
5560
|
+
`Failed to update package: ${error instanceof Error ? error.message : String(error)}`
|
|
5561
|
+
);
|
|
5562
|
+
}
|
|
5563
|
+
}
|
|
5564
|
+
|
|
5565
|
+
// src/utils/version.ts
|
|
5566
|
+
import axios5 from "axios";
|
|
5567
|
+
var PACKAGE_NAME = "@braingrid/cli";
|
|
5568
|
+
var NPM_REGISTRY_URL = `https://registry.npmjs.org/${PACKAGE_NAME}`;
|
|
5569
|
+
function getCurrentVersion() {
|
|
5570
|
+
return CLI_VERSION;
|
|
5571
|
+
}
|
|
5572
|
+
async function getLatestVersion(timeout = 1e4) {
|
|
5573
|
+
try {
|
|
5574
|
+
const response = await axios5.get(NPM_REGISTRY_URL, {
|
|
5575
|
+
timeout
|
|
5576
|
+
});
|
|
5577
|
+
return response.data["dist-tags"].latest;
|
|
5578
|
+
} catch (error) {
|
|
5579
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
5580
|
+
throw new Error(`Failed to fetch latest version: ${message}`);
|
|
5581
|
+
}
|
|
5582
|
+
}
|
|
5583
|
+
function compareVersions(v1, v2) {
|
|
5584
|
+
const v1Parts = v1.split(".").map(Number);
|
|
5585
|
+
const v2Parts = v2.split(".").map(Number);
|
|
5586
|
+
for (let i = 0; i < Math.max(v1Parts.length, v2Parts.length); i++) {
|
|
5587
|
+
const v1Part = v1Parts[i] || 0;
|
|
5588
|
+
const v2Part = v2Parts[i] || 0;
|
|
5589
|
+
if (v1Part < v2Part) return -1;
|
|
5590
|
+
if (v1Part > v2Part) return 1;
|
|
5591
|
+
}
|
|
5592
|
+
return 0;
|
|
5593
|
+
}
|
|
5594
|
+
|
|
5595
|
+
// src/handlers/update.handlers.ts
|
|
5596
|
+
async function handleUpdate(opts) {
|
|
5597
|
+
try {
|
|
5598
|
+
const currentVersion = getCurrentVersion();
|
|
5599
|
+
let output = chalk12.bold.cyan("\n\u{1F504} BrainGrid CLI Update\n\n");
|
|
5600
|
+
output += `${chalk12.bold("Current version:")} ${currentVersion}
|
|
5601
|
+
`;
|
|
5602
|
+
output += chalk12.dim("Checking for updates...\n");
|
|
5603
|
+
const latestVersion = await getLatestVersion();
|
|
5604
|
+
output += `${chalk12.bold("Latest version:")} ${latestVersion}
|
|
5605
|
+
|
|
5606
|
+
`;
|
|
5607
|
+
const comparison = compareVersions(currentVersion, latestVersion);
|
|
5608
|
+
if (comparison === 0) {
|
|
5609
|
+
output += chalk12.green("\u2705 You are already on the latest version!\n");
|
|
5610
|
+
return {
|
|
5611
|
+
success: true,
|
|
5612
|
+
message: output,
|
|
5613
|
+
data: { currentVersion, latestVersion, upToDate: true }
|
|
5614
|
+
};
|
|
5615
|
+
}
|
|
5616
|
+
if (comparison > 0) {
|
|
5617
|
+
output += chalk12.yellow("\u26A0\uFE0F You are on a newer version than what is published.\n");
|
|
5618
|
+
output += chalk12.dim(" This is expected if you are developing locally.\n");
|
|
5619
|
+
return {
|
|
5620
|
+
success: true,
|
|
5621
|
+
message: output,
|
|
5622
|
+
data: { currentVersion, latestVersion, upToDate: false }
|
|
5623
|
+
};
|
|
5624
|
+
}
|
|
5625
|
+
output += chalk12.yellow(`\u2B06\uFE0F Update available: ${currentVersion} \u2192 ${latestVersion}
|
|
5626
|
+
|
|
5627
|
+
`);
|
|
5628
|
+
if (opts.check) {
|
|
5629
|
+
output += chalk12.dim("Run ") + chalk12.cyan("braingrid update") + chalk12.dim(" to update\n");
|
|
5630
|
+
return {
|
|
5631
|
+
success: true,
|
|
5632
|
+
message: output,
|
|
5633
|
+
data: { currentVersion, latestVersion, upToDate: false }
|
|
5634
|
+
};
|
|
5635
|
+
}
|
|
5636
|
+
output += chalk12.dim("Detecting package manager...\n");
|
|
5637
|
+
const packageManager = await detectPackageManager(PACKAGE_NAME);
|
|
5638
|
+
output += `${chalk12.bold("Package manager:")} ${packageManager}
|
|
5639
|
+
|
|
5640
|
+
`;
|
|
5641
|
+
const updateCommand = getUpdateCommand(packageManager, PACKAGE_NAME);
|
|
5642
|
+
output += chalk12.dim("Running: ") + chalk12.cyan(updateCommand) + "\n\n";
|
|
5643
|
+
console.log(output);
|
|
5644
|
+
executeUpdate(packageManager, PACKAGE_NAME);
|
|
5645
|
+
return {
|
|
5646
|
+
success: true,
|
|
5647
|
+
message: chalk12.green("\n\u2705 Successfully updated BrainGrid CLI!\n"),
|
|
5648
|
+
data: { currentVersion, latestVersion, packageManager }
|
|
5649
|
+
};
|
|
5650
|
+
} catch (error) {
|
|
5651
|
+
return {
|
|
5652
|
+
success: false,
|
|
5653
|
+
message: formatError(error)
|
|
5654
|
+
};
|
|
5655
|
+
}
|
|
5656
|
+
}
|
|
5657
|
+
|
|
5658
|
+
// src/utils/update-checker.ts
|
|
5659
|
+
import chalk13 from "chalk";
|
|
5660
|
+
var CACHE_TTL_MS = 12 * 60 * 60 * 1e3;
|
|
5661
|
+
var CACHE_SERVICE = "braingrid-cli";
|
|
5662
|
+
var CACHE_ACCOUNT = "update-cache";
|
|
5663
|
+
async function getCache() {
|
|
5664
|
+
try {
|
|
5665
|
+
const cached = await credentialStore.getPassword(CACHE_SERVICE, CACHE_ACCOUNT);
|
|
5666
|
+
if (!cached) return null;
|
|
5667
|
+
return JSON.parse(cached);
|
|
5668
|
+
} catch {
|
|
5669
|
+
return null;
|
|
5670
|
+
}
|
|
5671
|
+
}
|
|
5672
|
+
async function setCache(cache) {
|
|
5673
|
+
try {
|
|
5674
|
+
await credentialStore.setPassword(CACHE_SERVICE, CACHE_ACCOUNT, JSON.stringify(cache));
|
|
5675
|
+
} catch {
|
|
5676
|
+
}
|
|
5677
|
+
}
|
|
5678
|
+
function isCacheValid(cache) {
|
|
5679
|
+
const now = Date.now();
|
|
5680
|
+
return now - cache.checkedAt < CACHE_TTL_MS;
|
|
5681
|
+
}
|
|
5682
|
+
async function getLatestVersionCached() {
|
|
5683
|
+
const cache = await getCache();
|
|
5684
|
+
if (cache && isCacheValid(cache)) {
|
|
5685
|
+
return cache.latestVersion;
|
|
5686
|
+
}
|
|
5687
|
+
try {
|
|
5688
|
+
const latestVersion = await getLatestVersion(5e3);
|
|
5689
|
+
await setCache({
|
|
5690
|
+
latestVersion,
|
|
5691
|
+
checkedAt: Date.now()
|
|
5692
|
+
});
|
|
5693
|
+
return latestVersion;
|
|
5694
|
+
} catch {
|
|
5695
|
+
return cache?.latestVersion ?? null;
|
|
5696
|
+
}
|
|
5697
|
+
}
|
|
5698
|
+
async function isUpdateAvailable() {
|
|
5699
|
+
const currentVersion = getCurrentVersion();
|
|
5700
|
+
const latestVersion = await getLatestVersionCached();
|
|
5701
|
+
if (!latestVersion) {
|
|
5702
|
+
return { available: false, currentVersion, latestVersion: null };
|
|
5703
|
+
}
|
|
5704
|
+
const comparison = compareVersions(currentVersion, latestVersion);
|
|
5705
|
+
return {
|
|
5706
|
+
available: comparison < 0,
|
|
5707
|
+
// Update available if current < latest
|
|
5708
|
+
currentVersion,
|
|
5709
|
+
latestVersion
|
|
5710
|
+
};
|
|
5711
|
+
}
|
|
5712
|
+
function getUpdateCommand2() {
|
|
5713
|
+
return `npm install -g ${PACKAGE_NAME}`;
|
|
5714
|
+
}
|
|
5715
|
+
async function checkAndShowUpdateWarning() {
|
|
5716
|
+
try {
|
|
5717
|
+
const { available, currentVersion, latestVersion } = await isUpdateAvailable();
|
|
5718
|
+
if (available && latestVersion) {
|
|
5719
|
+
const warning = "\n" + chalk13.yellow(`\u26A0\uFE0F Update available: ${currentVersion} \u2192 ${latestVersion}`) + "\n" + chalk13.dim(` Run \`${getUpdateCommand2()}\` to update`) + "\n";
|
|
5720
|
+
console.log(warning);
|
|
5721
|
+
}
|
|
5722
|
+
} catch {
|
|
5723
|
+
}
|
|
5724
|
+
}
|
|
5725
|
+
|
|
5726
|
+
// src/handlers/setup.handlers.ts
|
|
5727
|
+
import chalk14 from "chalk";
|
|
5728
|
+
import { select as select2 } from "@inquirer/prompts";
|
|
5400
5729
|
import * as path4 from "path";
|
|
5401
5730
|
import * as fs4 from "fs/promises";
|
|
5402
5731
|
|
|
@@ -5613,7 +5942,7 @@ async function checkPrerequisites() {
|
|
|
5613
5942
|
} catch {
|
|
5614
5943
|
return {
|
|
5615
5944
|
success: false,
|
|
5616
|
-
message:
|
|
5945
|
+
message: chalk14.red("\u274C GitHub CLI is not installed.\n\n") + chalk14.dim("Install instructions:\n") + chalk14.dim(" macOS: ") + chalk14.cyan("brew install gh") + chalk14.dim("\n") + chalk14.dim(" Windows: ") + chalk14.cyan("winget install GitHub.CLI") + chalk14.dim("\n") + chalk14.dim(" Linux: See ") + chalk14.cyan("https://cli.github.com/manual/installation") + chalk14.dim("\n\n") + chalk14.dim("After installing, run: ") + chalk14.cyan("gh auth login")
|
|
5617
5946
|
};
|
|
5618
5947
|
}
|
|
5619
5948
|
try {
|
|
@@ -5621,7 +5950,7 @@ async function checkPrerequisites() {
|
|
|
5621
5950
|
} catch {
|
|
5622
5951
|
return {
|
|
5623
5952
|
success: false,
|
|
5624
|
-
message:
|
|
5953
|
+
message: chalk14.red("\u274C Not authenticated with GitHub CLI.\n\n") + chalk14.dim("Please run: ") + chalk14.cyan("gh auth login")
|
|
5625
5954
|
};
|
|
5626
5955
|
}
|
|
5627
5956
|
return null;
|
|
@@ -5648,7 +5977,7 @@ async function getFileList(sourcePaths, targetPaths) {
|
|
|
5648
5977
|
}
|
|
5649
5978
|
} catch (error) {
|
|
5650
5979
|
console.warn(
|
|
5651
|
-
|
|
5980
|
+
chalk14.yellow(`\u26A0\uFE0F Could not list directory: ${sourceDir}`),
|
|
5652
5981
|
error instanceof Error ? error.message : String(error)
|
|
5653
5982
|
);
|
|
5654
5983
|
}
|
|
@@ -5659,28 +5988,28 @@ async function getFileList(sourcePaths, targetPaths) {
|
|
|
5659
5988
|
return operations;
|
|
5660
5989
|
}
|
|
5661
5990
|
function displayInstallationPlan(operations, injectionFile) {
|
|
5662
|
-
console.log(
|
|
5663
|
-
console.log(
|
|
5664
|
-
console.log(
|
|
5991
|
+
console.log(chalk14.bold("\n\u{1F4CB} Installation Plan:\n"));
|
|
5992
|
+
console.log(chalk14.cyan(" Content Injection:"));
|
|
5993
|
+
console.log(chalk14.dim(` ${injectionFile}`));
|
|
5665
5994
|
const newFiles = operations.filter((op) => !op.exists);
|
|
5666
5995
|
const existingFiles = operations.filter((op) => op.exists);
|
|
5667
5996
|
if (newFiles.length > 0) {
|
|
5668
|
-
console.log(
|
|
5997
|
+
console.log(chalk14.cyan("\n New Files:"));
|
|
5669
5998
|
for (const op of newFiles) {
|
|
5670
|
-
console.log(
|
|
5999
|
+
console.log(chalk14.dim(` ${op.targetPath}`));
|
|
5671
6000
|
}
|
|
5672
6001
|
}
|
|
5673
6002
|
if (existingFiles.length > 0) {
|
|
5674
|
-
console.log(
|
|
6003
|
+
console.log(chalk14.yellow("\n Existing Files (will prompt):"));
|
|
5675
6004
|
for (const op of existingFiles) {
|
|
5676
|
-
console.log(
|
|
6005
|
+
console.log(chalk14.dim(` ${op.targetPath}`));
|
|
5677
6006
|
}
|
|
5678
6007
|
}
|
|
5679
6008
|
console.log("");
|
|
5680
6009
|
}
|
|
5681
6010
|
async function promptForConflict(filePath) {
|
|
5682
|
-
const answer = await
|
|
5683
|
-
message:
|
|
6011
|
+
const answer = await select2({
|
|
6012
|
+
message: chalk14.yellow(`File exists: ${filePath}`),
|
|
5684
6013
|
choices: [
|
|
5685
6014
|
{ name: "[O]verwrite - Replace this file", value: "overwrite" },
|
|
5686
6015
|
{ name: "[S]kip - Keep existing file", value: "skip" },
|
|
@@ -5711,7 +6040,7 @@ async function installFiles(operations, force) {
|
|
|
5711
6040
|
installed++;
|
|
5712
6041
|
} catch (error) {
|
|
5713
6042
|
console.error(
|
|
5714
|
-
|
|
6043
|
+
chalk14.red(`Failed to copy ${operation.targetPath}:`),
|
|
5715
6044
|
error instanceof Error ? error.message : String(error)
|
|
5716
6045
|
);
|
|
5717
6046
|
skipped++;
|
|
@@ -5725,7 +6054,7 @@ async function _handleSetup(config, opts) {
|
|
|
5725
6054
|
if (prerequisiteError) {
|
|
5726
6055
|
return prerequisiteError;
|
|
5727
6056
|
}
|
|
5728
|
-
console.log(
|
|
6057
|
+
console.log(chalk14.bold(`\u{1F680} Setting up ${config.name} integration...
|
|
5729
6058
|
`));
|
|
5730
6059
|
const operations = await getFileList(config.sourceDirs, config.targetDirs);
|
|
5731
6060
|
const injectionFileExists = await fileExists(config.injection.targetFile);
|
|
@@ -5742,7 +6071,7 @@ async function _handleSetup(config, opts) {
|
|
|
5742
6071
|
if (opts.dryRun) {
|
|
5743
6072
|
return {
|
|
5744
6073
|
success: true,
|
|
5745
|
-
message:
|
|
6074
|
+
message: chalk14.green("\u2705 Dry-run complete. No files were modified.\n\n") + chalk14.dim(`Would install ${operations.length} files.`)
|
|
5746
6075
|
};
|
|
5747
6076
|
}
|
|
5748
6077
|
const copyOps = operations.filter((op) => op.type === "copy");
|
|
@@ -5750,7 +6079,7 @@ async function _handleSetup(config, opts) {
|
|
|
5750
6079
|
if (result.cancelled) {
|
|
5751
6080
|
return {
|
|
5752
6081
|
success: false,
|
|
5753
|
-
message:
|
|
6082
|
+
message: chalk14.yellow("\u26A0\uFE0F Installation cancelled.\n\n") + chalk14.dim(`Installed: ${result.installed}, Skipped: ${result.skipped}`),
|
|
5754
6083
|
code: "CANCELLED"
|
|
5755
6084
|
};
|
|
5756
6085
|
}
|
|
@@ -5759,7 +6088,7 @@ async function _handleSetup(config, opts) {
|
|
|
5759
6088
|
await injectContentIntoFile(config.injection.targetFile, content);
|
|
5760
6089
|
} catch (error) {
|
|
5761
6090
|
console.error(
|
|
5762
|
-
|
|
6091
|
+
chalk14.red(`Failed to inject content into ${config.injection.targetFile}:`),
|
|
5763
6092
|
error instanceof Error ? error.message : String(error)
|
|
5764
6093
|
);
|
|
5765
6094
|
}
|
|
@@ -5772,27 +6101,27 @@ async function _handleSetup(config, opts) {
|
|
|
5772
6101
|
statusLineInstalled = true;
|
|
5773
6102
|
} catch (error) {
|
|
5774
6103
|
console.error(
|
|
5775
|
-
|
|
6104
|
+
chalk14.yellow("\u26A0\uFE0F Failed to install status line script:"),
|
|
5776
6105
|
error instanceof Error ? error.message : String(error)
|
|
5777
6106
|
);
|
|
5778
6107
|
}
|
|
5779
6108
|
}
|
|
5780
|
-
const statusLineMessage = statusLineInstalled ?
|
|
6109
|
+
const statusLineMessage = statusLineInstalled ? chalk14.dim(" Status line: .claude/statusline.sh\n") : "";
|
|
5781
6110
|
return {
|
|
5782
6111
|
success: true,
|
|
5783
|
-
message:
|
|
6112
|
+
message: chalk14.green(`\u2705 ${config.name} integration installed successfully!
|
|
5784
6113
|
|
|
5785
|
-
`) +
|
|
5786
|
-
`) + statusLineMessage +
|
|
6114
|
+
`) + chalk14.dim("Files installed:\n") + chalk14.dim(` Commands: ${result.installed} files
|
|
6115
|
+
`) + statusLineMessage + chalk14.dim(` Content injected into: ${config.injection.targetFile}
|
|
5787
6116
|
|
|
5788
|
-
`) +
|
|
5789
|
-
`) +
|
|
6117
|
+
`) + chalk14.dim("Next steps:\n") + chalk14.dim(" 1. Review the integration files\n") + chalk14.dim(` 2. Open ${config.name}
|
|
6118
|
+
`) + chalk14.dim(" 3. Try the /specify or /breakdown commands\n") + chalk14.dim(" 4. Learn more: ") + chalk14.cyan(config.docsUrl)
|
|
5790
6119
|
};
|
|
5791
6120
|
} catch (error) {
|
|
5792
6121
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
5793
6122
|
return {
|
|
5794
6123
|
success: false,
|
|
5795
|
-
message:
|
|
6124
|
+
message: chalk14.red(`\u274C Setup failed: ${errorMessage}`)
|
|
5796
6125
|
};
|
|
5797
6126
|
}
|
|
5798
6127
|
}
|
|
@@ -5906,12 +6235,12 @@ function getServices4() {
|
|
|
5906
6235
|
function promptToAddOrganization(owner, webUrl) {
|
|
5907
6236
|
return {
|
|
5908
6237
|
success: false,
|
|
5909
|
-
message:
|
|
6238
|
+
message: chalk15.yellow("\u26A0\uFE0F No projects found for this repository.\n\n") + chalk15.dim(`Repository: ${owner}/*
|
|
5910
6239
|
|
|
5911
|
-
`) +
|
|
6240
|
+
`) + chalk15.dim(`You have GitHub connected, but not for the "${owner}" organization.
|
|
5912
6241
|
|
|
5913
|
-
`) +
|
|
5914
|
-
`) +
|
|
6242
|
+
`) + chalk15.dim("To connect ") + chalk15.cyan(owner) + chalk15.dim(":\n") + chalk15.dim(" 1. Visit: ") + chalk15.cyan(`${webUrl}/integrations`) + chalk15.dim("\n") + chalk15.dim(' 2. Click "Add GitHub Organization"\n') + chalk15.dim(` 3. Select "${owner}"
|
|
6243
|
+
`) + chalk15.dim(" 4. Run ") + chalk15.cyan("braingrid init") + chalk15.dim(" again")
|
|
5915
6244
|
};
|
|
5916
6245
|
}
|
|
5917
6246
|
async function promptToCreateProject(gitInfo, projectService, repositoryService) {
|
|
@@ -5919,20 +6248,20 @@ async function promptToCreateProject(gitInfo, projectService, repositoryService)
|
|
|
5919
6248
|
if (!gitInfo.owner || !gitInfo.name) {
|
|
5920
6249
|
return {
|
|
5921
6250
|
success: false,
|
|
5922
|
-
message:
|
|
6251
|
+
message: chalk15.red("\u274C Repository information is incomplete")
|
|
5923
6252
|
};
|
|
5924
6253
|
}
|
|
5925
6254
|
const repositoryId = await getRepositoryId(repositoryService, gitInfo.owner, gitInfo.name);
|
|
5926
6255
|
if (!repositoryId) {
|
|
5927
6256
|
return {
|
|
5928
6257
|
success: false,
|
|
5929
|
-
message:
|
|
6258
|
+
message: chalk15.yellow("\u26A0\uFE0F Repository accessible but could not retrieve details.\n\n") + chalk15.dim(`Repository: ${gitInfo.owner}/${gitInfo.name}
|
|
5930
6259
|
|
|
5931
|
-
`) +
|
|
6260
|
+
`) + chalk15.dim("Please try again or create a project manually at: ") + chalk15.cyan(webUrl)
|
|
5932
6261
|
};
|
|
5933
6262
|
}
|
|
5934
6263
|
console.log(
|
|
5935
|
-
|
|
6264
|
+
chalk15.yellow("\u26A0\uFE0F Repository accessible but no project exists.\n\n") + chalk15.dim(`Repository: ${gitInfo.owner}/${gitInfo.name}
|
|
5936
6265
|
`)
|
|
5937
6266
|
);
|
|
5938
6267
|
const shouldCreate = await confirm({
|
|
@@ -5942,7 +6271,7 @@ async function promptToCreateProject(gitInfo, projectService, repositoryService)
|
|
|
5942
6271
|
if (!shouldCreate) {
|
|
5943
6272
|
return {
|
|
5944
6273
|
success: false,
|
|
5945
|
-
message:
|
|
6274
|
+
message: chalk15.dim("\nProject creation cancelled.\n\n") + chalk15.dim("Create a project at ") + chalk15.cyan(webUrl) + chalk15.dim(" and link it to this repository, or use:\n") + chalk15.cyan(
|
|
5946
6275
|
`braingrid project create --name "${gitInfo.name}" --repositories "${gitInfo.owner}/${gitInfo.name}"`
|
|
5947
6276
|
)
|
|
5948
6277
|
};
|
|
@@ -5953,9 +6282,9 @@ async function promptToCreateProject(gitInfo, projectService, repositoryService)
|
|
|
5953
6282
|
description: `Project for ${gitInfo.owner}/${gitInfo.name}`,
|
|
5954
6283
|
repository_id: repositoryId
|
|
5955
6284
|
});
|
|
5956
|
-
console.log(
|
|
6285
|
+
console.log(chalk15.green(`
|
|
5957
6286
|
\u2705 Created project ${project2.short_id}: ${project2.name}`));
|
|
5958
|
-
console.log(
|
|
6287
|
+
console.log(chalk15.green(`\u2705 Linked repository ${gitInfo.owner}/${gitInfo.name}
|
|
5959
6288
|
`));
|
|
5960
6289
|
return { success: true, message: "", data: project2 };
|
|
5961
6290
|
} catch (error) {
|
|
@@ -5969,18 +6298,18 @@ async function promptToGrantRepositoryAccess(gitInfo, webUrl, repositoryService,
|
|
|
5969
6298
|
if (!gitInfo.owner || !gitInfo.name) {
|
|
5970
6299
|
return {
|
|
5971
6300
|
success: false,
|
|
5972
|
-
message:
|
|
6301
|
+
message: chalk15.red("\u274C Repository information is incomplete")
|
|
5973
6302
|
};
|
|
5974
6303
|
}
|
|
5975
6304
|
const owner = gitInfo.owner;
|
|
5976
6305
|
const name = gitInfo.name;
|
|
5977
6306
|
console.log(
|
|
5978
|
-
|
|
6307
|
+
chalk15.yellow("\u26A0\uFE0F Repository found but BrainGrid needs access.\n\n") + chalk15.dim(`Repository: ${owner}/${name}
|
|
5979
6308
|
|
|
5980
|
-
`) +
|
|
6309
|
+
`) + chalk15.dim("Please grant BrainGrid access to this repository:\n") + chalk15.dim(" 1. Visit: ") + chalk15.cyan(`${webUrl}/integrations`) + chalk15.dim("\n") + chalk15.dim(
|
|
5981
6310
|
` 2. Click on your "${owner}" installation "Add/Remove" to grant BrainGrid access to your repository
|
|
5982
6311
|
`
|
|
5983
|
-
) +
|
|
6312
|
+
) + chalk15.dim(` 3. Select "${name}" and save
|
|
5984
6313
|
|
|
5985
6314
|
`)
|
|
5986
6315
|
);
|
|
@@ -5993,10 +6322,10 @@ async function promptToGrantRepositoryAccess(gitInfo, webUrl, repositoryService,
|
|
|
5993
6322
|
if (!accessGranted) {
|
|
5994
6323
|
return {
|
|
5995
6324
|
success: false,
|
|
5996
|
-
message:
|
|
6325
|
+
message: chalk15.yellow("\n\u26A0\uFE0F Repository access not detected within 3 minutes.\n\n") + chalk15.dim("Please grant access at: ") + chalk15.cyan(`${webUrl}/integrations`) + chalk15.dim(" and run ") + chalk15.cyan("braingrid init") + chalk15.dim(" again.")
|
|
5997
6326
|
};
|
|
5998
6327
|
}
|
|
5999
|
-
console.log(
|
|
6328
|
+
console.log(chalk15.green("\u2705 Repository access granted!\n"));
|
|
6000
6329
|
return promptToCreateProject(gitInfo, projectService, repositoryService);
|
|
6001
6330
|
}
|
|
6002
6331
|
async function handleNoProjectForRepository(owner, name, gitInfo, githubService, repositoryService, projectService, config) {
|
|
@@ -6011,9 +6340,9 @@ async function handleNoProjectForRepository(owner, name, gitInfo, githubService,
|
|
|
6011
6340
|
if (allInstallations.length === 0) {
|
|
6012
6341
|
return {
|
|
6013
6342
|
success: false,
|
|
6014
|
-
message:
|
|
6343
|
+
message: chalk15.yellow("\u26A0\uFE0F No projects found for this repository.\n\n") + chalk15.dim(`Repository: ${owner}/${name}
|
|
6015
6344
|
|
|
6016
|
-
`) +
|
|
6345
|
+
`) + chalk15.dim("It looks like you haven't connected your GitHub account yet.\n") + chalk15.dim("Please connect GitHub at: ") + chalk15.cyan(`${webUrl}/integrations`) + chalk15.dim("\n\nOnce connected, create a project and link it to this repository.")
|
|
6017
6346
|
};
|
|
6018
6347
|
}
|
|
6019
6348
|
const ownerInstallation = findInstallationForOwner(owner, allInstallations);
|
|
@@ -6029,28 +6358,28 @@ async function handleNoProjectForRepository(owner, name, gitInfo, githubService,
|
|
|
6029
6358
|
function showSetupInstructions(scenario) {
|
|
6030
6359
|
let message = "";
|
|
6031
6360
|
if (scenario === "no-git") {
|
|
6032
|
-
message +=
|
|
6033
|
-
message +=
|
|
6034
|
-
message +=
|
|
6361
|
+
message += chalk15.dim("To initialize BrainGrid locally:\n\n");
|
|
6362
|
+
message += chalk15.dim(" 1. Initialize git:\n");
|
|
6363
|
+
message += chalk15.cyan(" git init\n\n");
|
|
6035
6364
|
} else {
|
|
6036
|
-
message +=
|
|
6365
|
+
message += chalk15.dim("To connect to GitHub:\n\n");
|
|
6037
6366
|
}
|
|
6038
|
-
message +=
|
|
6039
|
-
message +=
|
|
6040
|
-
message +=
|
|
6041
|
-
message +=
|
|
6367
|
+
message += chalk15.dim(" 2. Create GitHub repository:\n");
|
|
6368
|
+
message += chalk15.dim(" \u2022 Install GitHub CLI: ") + chalk15.cyan("https://cli.github.com\n");
|
|
6369
|
+
message += chalk15.dim(" Then: ") + chalk15.cyan("gh repo create --private --source=.\n");
|
|
6370
|
+
message += chalk15.dim(" \u2022 Or manually: ") + chalk15.cyan("https://github.com/new\n\n");
|
|
6042
6371
|
if (scenario === "no-git") {
|
|
6043
|
-
message +=
|
|
6372
|
+
message += chalk15.dim(" 3. Run: ") + chalk15.cyan("braingrid init\n\n");
|
|
6044
6373
|
} else {
|
|
6045
|
-
message +=
|
|
6046
|
-
message +=
|
|
6047
|
-
message +=
|
|
6048
|
-
}
|
|
6049
|
-
message +=
|
|
6050
|
-
message +=
|
|
6051
|
-
message +=
|
|
6052
|
-
message +=
|
|
6053
|
-
message +=
|
|
6374
|
+
message += chalk15.dim(" 3. Add remote and run init:\n");
|
|
6375
|
+
message += chalk15.cyan(" git remote add origin <url>\n");
|
|
6376
|
+
message += chalk15.cyan(" braingrid init\n\n");
|
|
6377
|
+
}
|
|
6378
|
+
message += chalk15.bold("Or use BrainGrid without local initialization:\n\n");
|
|
6379
|
+
message += chalk15.dim(" All commands support the --project flag:\n");
|
|
6380
|
+
message += chalk15.cyan(" braingrid requirement list --project PROJ-123\n");
|
|
6381
|
+
message += chalk15.cyan(' braingrid task create --project PROJ-123 --title "Task"\n\n');
|
|
6382
|
+
message += chalk15.dim(" Note: Without local init, you must specify --project for each command.") + "\n";
|
|
6054
6383
|
return message;
|
|
6055
6384
|
}
|
|
6056
6385
|
async function handleNoGitRepository() {
|
|
@@ -6066,12 +6395,12 @@ async function handleNoGitRepository() {
|
|
|
6066
6395
|
if (!gitInitSuccess) {
|
|
6067
6396
|
return {
|
|
6068
6397
|
success: false,
|
|
6069
|
-
message:
|
|
6398
|
+
message: chalk15.red("\u274C Failed to initialize git repository")
|
|
6070
6399
|
};
|
|
6071
6400
|
}
|
|
6072
|
-
console.log(
|
|
6401
|
+
console.log(chalk15.green("\u2705 Initialized git repository"));
|
|
6073
6402
|
const dirName = getCurrentDirectoryName();
|
|
6074
|
-
const isPrivate = await
|
|
6403
|
+
const isPrivate = await select3({
|
|
6075
6404
|
message: "Repository visibility:",
|
|
6076
6405
|
choices: [
|
|
6077
6406
|
{ value: true, name: "Private" },
|
|
@@ -6083,16 +6412,16 @@ async function handleNoGitRepository() {
|
|
|
6083
6412
|
message: "Repository name:",
|
|
6084
6413
|
default: dirName
|
|
6085
6414
|
});
|
|
6086
|
-
console.log(
|
|
6415
|
+
console.log(chalk15.dim("\nCreating repository...\n"));
|
|
6087
6416
|
const repo = await createGitHubRepoWithGh(repoName, isPrivate);
|
|
6088
6417
|
if (!repo) {
|
|
6089
6418
|
return {
|
|
6090
6419
|
success: false,
|
|
6091
|
-
message:
|
|
6420
|
+
message: chalk15.red("\u274C Failed to create GitHub repository\n\n") + showSetupInstructions("no-git")
|
|
6092
6421
|
};
|
|
6093
6422
|
}
|
|
6094
|
-
console.log(
|
|
6095
|
-
console.log(
|
|
6423
|
+
console.log(chalk15.green(`\u2705 Created repository: ${repo.url}`));
|
|
6424
|
+
console.log(chalk15.green("\u2705 Added remote origin\n"));
|
|
6096
6425
|
return {
|
|
6097
6426
|
success: true,
|
|
6098
6427
|
message: "continue-init",
|
|
@@ -6103,7 +6432,7 @@ async function handleNoGitRepository() {
|
|
|
6103
6432
|
}
|
|
6104
6433
|
return {
|
|
6105
6434
|
success: false,
|
|
6106
|
-
message:
|
|
6435
|
+
message: chalk15.yellow("\u26A0\uFE0F This directory is not a git repository.\n\n") + showSetupInstructions("no-git")
|
|
6107
6436
|
};
|
|
6108
6437
|
}
|
|
6109
6438
|
async function handleNoGitRemote() {
|
|
@@ -6115,7 +6444,7 @@ async function handleNoGitRemote() {
|
|
|
6115
6444
|
});
|
|
6116
6445
|
if (shouldCreate) {
|
|
6117
6446
|
const dirName = getCurrentDirectoryName();
|
|
6118
|
-
const isPrivate = await
|
|
6447
|
+
const isPrivate = await select3({
|
|
6119
6448
|
message: "Repository visibility:",
|
|
6120
6449
|
choices: [
|
|
6121
6450
|
{ value: true, name: "Private" },
|
|
@@ -6127,16 +6456,16 @@ async function handleNoGitRemote() {
|
|
|
6127
6456
|
message: "Repository name:",
|
|
6128
6457
|
default: dirName
|
|
6129
6458
|
});
|
|
6130
|
-
console.log(
|
|
6459
|
+
console.log(chalk15.dim("\nCreating repository...\n"));
|
|
6131
6460
|
const repo = await createGitHubRepoWithGh(repoName, isPrivate);
|
|
6132
6461
|
if (!repo) {
|
|
6133
6462
|
return {
|
|
6134
6463
|
success: false,
|
|
6135
|
-
message:
|
|
6464
|
+
message: chalk15.red("\u274C Failed to create GitHub repository\n\n") + showSetupInstructions("no-remote")
|
|
6136
6465
|
};
|
|
6137
6466
|
}
|
|
6138
|
-
console.log(
|
|
6139
|
-
console.log(
|
|
6467
|
+
console.log(chalk15.green(`\u2705 Created repository: ${repo.url}`));
|
|
6468
|
+
console.log(chalk15.green("\u2705 Added remote origin\n"));
|
|
6140
6469
|
return {
|
|
6141
6470
|
success: true,
|
|
6142
6471
|
message: "continue-init",
|
|
@@ -6147,11 +6476,31 @@ async function handleNoGitRemote() {
|
|
|
6147
6476
|
}
|
|
6148
6477
|
return {
|
|
6149
6478
|
success: false,
|
|
6150
|
-
message:
|
|
6479
|
+
message: chalk15.yellow("\u26A0\uFE0F Git repository detected but no GitHub remote configured.\n\n") + showSetupInstructions("no-remote")
|
|
6151
6480
|
};
|
|
6152
6481
|
}
|
|
6153
6482
|
async function handleInit(opts) {
|
|
6154
6483
|
try {
|
|
6484
|
+
const updateInfo = await isUpdateAvailable();
|
|
6485
|
+
if (updateInfo.available && updateInfo.latestVersion) {
|
|
6486
|
+
console.log(
|
|
6487
|
+
chalk15.yellow(`
|
|
6488
|
+
\u26A0\uFE0F A new version of BrainGrid CLI is available: `) + chalk15.dim(`${updateInfo.currentVersion} \u2192 `) + chalk15.green(updateInfo.latestVersion) + "\n"
|
|
6489
|
+
);
|
|
6490
|
+
const shouldUpdate = await confirm({
|
|
6491
|
+
message: "Would you like to update now?",
|
|
6492
|
+
default: true
|
|
6493
|
+
});
|
|
6494
|
+
if (shouldUpdate) {
|
|
6495
|
+
const result = await handleUpdate({});
|
|
6496
|
+
console.log(result.message);
|
|
6497
|
+
return {
|
|
6498
|
+
success: true,
|
|
6499
|
+
message: chalk15.dim("\nRun `braingrid init` again after the update completes.")
|
|
6500
|
+
};
|
|
6501
|
+
}
|
|
6502
|
+
console.log();
|
|
6503
|
+
}
|
|
6155
6504
|
const config = getConfig();
|
|
6156
6505
|
const { projectService, githubService, repositoryService, auth } = getServices4();
|
|
6157
6506
|
if (!await isGitInstalled()) {
|
|
@@ -6162,7 +6511,7 @@ async function handleInit(opts) {
|
|
|
6162
6511
|
if (!shouldInstall) {
|
|
6163
6512
|
return {
|
|
6164
6513
|
success: false,
|
|
6165
|
-
message:
|
|
6514
|
+
message: chalk15.yellow("\u26A0\uFE0F Git installation cancelled.\n\n") + getManualInstallInstructions()
|
|
6166
6515
|
};
|
|
6167
6516
|
}
|
|
6168
6517
|
console.log();
|
|
@@ -6178,14 +6527,14 @@ async function handleInit(opts) {
|
|
|
6178
6527
|
if (!await isGitInstalled()) {
|
|
6179
6528
|
return {
|
|
6180
6529
|
success: false,
|
|
6181
|
-
message:
|
|
6530
|
+
message: chalk15.red("\u274C Git installation completed but git command not found\n\n") + chalk15.dim("You may need to restart your terminal or add Git to your PATH.\n") + getManualInstallInstructions()
|
|
6182
6531
|
};
|
|
6183
6532
|
}
|
|
6184
6533
|
}
|
|
6185
6534
|
if (!await isGhInstalled()) {
|
|
6186
|
-
console.log(
|
|
6535
|
+
console.log(chalk15.blue("\n\u{1F4A1} GitHub CLI is highly recommended for working with BrainGrid."));
|
|
6187
6536
|
console.log(
|
|
6188
|
-
|
|
6537
|
+
chalk15.dim(" It enables seamless GitHub integration and repository management.\n")
|
|
6189
6538
|
);
|
|
6190
6539
|
const shouldInstallGh = await confirm({
|
|
6191
6540
|
message: "Would you like to install GitHub CLI now?",
|
|
@@ -6199,10 +6548,10 @@ async function handleInit(opts) {
|
|
|
6199
6548
|
console.log();
|
|
6200
6549
|
} else {
|
|
6201
6550
|
console.log(ghInstallResult.message);
|
|
6202
|
-
console.log(
|
|
6551
|
+
console.log(chalk15.dim("You can install it manually later.\n"));
|
|
6203
6552
|
}
|
|
6204
6553
|
} else {
|
|
6205
|
-
console.log(
|
|
6554
|
+
console.log(chalk15.dim("Skipping GitHub CLI installation.\n"));
|
|
6206
6555
|
}
|
|
6207
6556
|
}
|
|
6208
6557
|
if (await projectConfigExists() && !opts.force) {
|
|
@@ -6210,15 +6559,15 @@ async function handleInit(opts) {
|
|
|
6210
6559
|
const existing = await loadProjectConfig();
|
|
6211
6560
|
return {
|
|
6212
6561
|
success: false,
|
|
6213
|
-
message:
|
|
6214
|
-
`) +
|
|
6562
|
+
message: chalk15.yellow("\u26A0\uFE0F Already initialized.\n\n") + chalk15.dim(`Project: ${existing.project_name} (${existing.project_short_id})
|
|
6563
|
+
`) + chalk15.dim(`Repository: ${existing.repository?.full_name || "N/A"}
|
|
6215
6564
|
|
|
6216
|
-
`) +
|
|
6565
|
+
`) + chalk15.dim("Use --force to reinitialize")
|
|
6217
6566
|
};
|
|
6218
6567
|
} catch {
|
|
6219
6568
|
return {
|
|
6220
6569
|
success: false,
|
|
6221
|
-
message:
|
|
6570
|
+
message: chalk15.yellow("\u26A0\uFE0F Invalid project configuration found.\n") + chalk15.dim("Use --force to reinitialize")
|
|
6222
6571
|
};
|
|
6223
6572
|
}
|
|
6224
6573
|
}
|
|
@@ -6231,7 +6580,7 @@ async function handleInit(opts) {
|
|
|
6231
6580
|
if (!shouldLogin) {
|
|
6232
6581
|
return {
|
|
6233
6582
|
success: false,
|
|
6234
|
-
message:
|
|
6583
|
+
message: chalk15.yellow("\u26A0\uFE0F Authentication required.\n") + chalk15.dim("Run ") + chalk15.cyan("braingrid login") + chalk15.dim(" when you're ready to authenticate.")
|
|
6235
6584
|
};
|
|
6236
6585
|
}
|
|
6237
6586
|
console.log();
|
|
@@ -6239,13 +6588,13 @@ async function handleInit(opts) {
|
|
|
6239
6588
|
if (!loginResult.success) {
|
|
6240
6589
|
return {
|
|
6241
6590
|
success: false,
|
|
6242
|
-
message:
|
|
6591
|
+
message: chalk15.red("\u274C Login failed.\n") + chalk15.dim("Please try running ") + chalk15.cyan("braingrid login") + chalk15.dim(" again.")
|
|
6243
6592
|
};
|
|
6244
6593
|
}
|
|
6245
6594
|
if (!await auth.isAuthenticated()) {
|
|
6246
6595
|
return {
|
|
6247
6596
|
success: false,
|
|
6248
|
-
message:
|
|
6597
|
+
message: chalk15.red("\u274C Login was not completed.\n") + chalk15.dim("Please try running ") + chalk15.cyan("braingrid login") + chalk15.dim(" again.")
|
|
6249
6598
|
};
|
|
6250
6599
|
}
|
|
6251
6600
|
console.log();
|
|
@@ -6254,27 +6603,27 @@ async function handleInit(opts) {
|
|
|
6254
6603
|
if (!session) {
|
|
6255
6604
|
return {
|
|
6256
6605
|
success: false,
|
|
6257
|
-
message:
|
|
6606
|
+
message: chalk15.red("\u274C No session found. Please run `braingrid login` first.")
|
|
6258
6607
|
};
|
|
6259
6608
|
}
|
|
6260
6609
|
if (session.organization_id === "default") {
|
|
6261
|
-
console.log(
|
|
6610
|
+
console.log(chalk15.yellow("\u26A0\uFE0F Organization ID not set, validating session...\n"));
|
|
6262
6611
|
const isValid = await auth.isAuthenticated();
|
|
6263
6612
|
if (!isValid) {
|
|
6264
6613
|
return {
|
|
6265
6614
|
success: false,
|
|
6266
|
-
message:
|
|
6615
|
+
message: chalk15.red("\u274C Session validation failed. Please run `braingrid login` again.")
|
|
6267
6616
|
};
|
|
6268
6617
|
}
|
|
6269
6618
|
const updatedSession = await auth.getStoredSession();
|
|
6270
6619
|
if (!updatedSession || updatedSession.organization_id === "default") {
|
|
6271
6620
|
return {
|
|
6272
6621
|
success: false,
|
|
6273
|
-
message:
|
|
6622
|
+
message: chalk15.red("\u274C Unable to retrieve organization information.\n\n") + chalk15.dim("This may indicate an issue with your account setup.\n") + chalk15.dim("Please contact support or try logging in again with ") + chalk15.cyan("braingrid logout") + chalk15.dim(" and ") + chalk15.cyan("braingrid login")
|
|
6274
6623
|
};
|
|
6275
6624
|
}
|
|
6276
6625
|
Object.assign(session, updatedSession);
|
|
6277
|
-
console.log(
|
|
6626
|
+
console.log(chalk15.green("\u2705 Organization ID updated successfully\n"));
|
|
6278
6627
|
}
|
|
6279
6628
|
let gitInfo = await getGitRepositoryInfo();
|
|
6280
6629
|
let project2;
|
|
@@ -6284,9 +6633,9 @@ async function handleInit(opts) {
|
|
|
6284
6633
|
} catch {
|
|
6285
6634
|
return {
|
|
6286
6635
|
success: false,
|
|
6287
|
-
message:
|
|
6636
|
+
message: chalk15.red(`\u274C Project not found: ${opts.project}
|
|
6288
6637
|
|
|
6289
|
-
`) +
|
|
6638
|
+
`) + chalk15.dim("Make sure the project ID is correct and you have access to it.")
|
|
6290
6639
|
};
|
|
6291
6640
|
}
|
|
6292
6641
|
} else {
|
|
@@ -6297,7 +6646,7 @@ async function handleInit(opts) {
|
|
|
6297
6646
|
if (!gitInfo || !gitInfo.owner || !gitInfo.name) {
|
|
6298
6647
|
return {
|
|
6299
6648
|
success: false,
|
|
6300
|
-
message:
|
|
6649
|
+
message: chalk15.red("\u274C Failed to get repository information after setup")
|
|
6301
6650
|
};
|
|
6302
6651
|
}
|
|
6303
6652
|
} else {
|
|
@@ -6311,7 +6660,7 @@ async function handleInit(opts) {
|
|
|
6311
6660
|
if (!gitInfo || !gitInfo.owner || !gitInfo.name) {
|
|
6312
6661
|
return {
|
|
6313
6662
|
success: false,
|
|
6314
|
-
message:
|
|
6663
|
+
message: chalk15.red("\u274C Failed to get repository information after setup")
|
|
6315
6664
|
};
|
|
6316
6665
|
}
|
|
6317
6666
|
} else {
|
|
@@ -6321,7 +6670,7 @@ async function handleInit(opts) {
|
|
|
6321
6670
|
if (!gitInfo) {
|
|
6322
6671
|
return {
|
|
6323
6672
|
success: false,
|
|
6324
|
-
message:
|
|
6673
|
+
message: chalk15.red("\u274C Repository information is missing")
|
|
6325
6674
|
};
|
|
6326
6675
|
}
|
|
6327
6676
|
const owner = gitInfo.owner;
|
|
@@ -6329,7 +6678,7 @@ async function handleInit(opts) {
|
|
|
6329
6678
|
if (!owner || !name) {
|
|
6330
6679
|
return {
|
|
6331
6680
|
success: false,
|
|
6332
|
-
message:
|
|
6681
|
+
message: chalk15.red("\u274C Repository information is incomplete")
|
|
6333
6682
|
};
|
|
6334
6683
|
}
|
|
6335
6684
|
let response;
|
|
@@ -6368,7 +6717,7 @@ async function handleInit(opts) {
|
|
|
6368
6717
|
}
|
|
6369
6718
|
project2 = response.projects[0];
|
|
6370
6719
|
}
|
|
6371
|
-
const projectInfo =
|
|
6720
|
+
const projectInfo = chalk15.bold("\n\u{1F4E6} BrainGrid Project Found\n\n") + chalk15.dim("Project: ") + chalk15.cyan(project2.name) + "\n" + chalk15.dim("ID: ") + chalk15.gray(project2.short_id) + "\n" + (project2.description ? chalk15.dim("Description: ") + chalk15.gray(project2.description) + "\n" : "") + chalk15.dim("Repository: ") + chalk15.gray(project2.repository?.full_name || "N/A") + "\n\n";
|
|
6372
6721
|
console.log(projectInfo);
|
|
6373
6722
|
if (!opts.force) {
|
|
6374
6723
|
const shouldInit = await confirm({
|
|
@@ -6378,7 +6727,7 @@ async function handleInit(opts) {
|
|
|
6378
6727
|
if (!shouldInit) {
|
|
6379
6728
|
return {
|
|
6380
6729
|
success: false,
|
|
6381
|
-
message:
|
|
6730
|
+
message: chalk15.yellow("Initialization cancelled.")
|
|
6382
6731
|
};
|
|
6383
6732
|
}
|
|
6384
6733
|
}
|
|
@@ -6401,7 +6750,7 @@ async function handleInit(opts) {
|
|
|
6401
6750
|
};
|
|
6402
6751
|
await saveProjectConfig(localConfig);
|
|
6403
6752
|
console.log(
|
|
6404
|
-
|
|
6753
|
+
chalk15.green("\u2705 Repository initialized successfully!\n\n") + chalk15.dim("Project: ") + chalk15.cyan(project2.name) + chalk15.dim(` (${project2.short_id})`) + "\n" + chalk15.dim("Config: ") + chalk15.gray(".braingrid/project.json") + "\n"
|
|
6405
6754
|
);
|
|
6406
6755
|
const installedIDEs = await detectInstalledIDEs();
|
|
6407
6756
|
if (installedIDEs.claudeCode) {
|
|
@@ -6419,15 +6768,15 @@ async function handleInit(opts) {
|
|
|
6419
6768
|
if (result.success) {
|
|
6420
6769
|
console.log(result.message);
|
|
6421
6770
|
} else {
|
|
6422
|
-
console.log(
|
|
6771
|
+
console.log(chalk15.yellow("\u26A0\uFE0F Claude Code setup was not completed."));
|
|
6423
6772
|
console.log(
|
|
6424
|
-
|
|
6773
|
+
chalk15.dim("You can run ") + chalk15.cyan("braingrid setup claude-code") + chalk15.dim(" later.")
|
|
6425
6774
|
);
|
|
6426
6775
|
}
|
|
6427
6776
|
} catch {
|
|
6428
|
-
console.log(
|
|
6777
|
+
console.log(chalk15.yellow("\u26A0\uFE0F Claude Code setup encountered an error."));
|
|
6429
6778
|
console.log(
|
|
6430
|
-
|
|
6779
|
+
chalk15.dim("You can run ") + chalk15.cyan("braingrid setup claude-code") + chalk15.dim(" later.")
|
|
6431
6780
|
);
|
|
6432
6781
|
}
|
|
6433
6782
|
console.log("");
|
|
@@ -6449,15 +6798,15 @@ async function handleInit(opts) {
|
|
|
6449
6798
|
if (result.success) {
|
|
6450
6799
|
console.log(result.message);
|
|
6451
6800
|
} else {
|
|
6452
|
-
console.log(
|
|
6801
|
+
console.log(chalk15.yellow("\u26A0\uFE0F Cursor setup was not completed."));
|
|
6453
6802
|
console.log(
|
|
6454
|
-
|
|
6803
|
+
chalk15.dim("You can run ") + chalk15.cyan("braingrid setup cursor") + chalk15.dim(" later.")
|
|
6455
6804
|
);
|
|
6456
6805
|
}
|
|
6457
6806
|
} catch {
|
|
6458
|
-
console.log(
|
|
6807
|
+
console.log(chalk15.yellow("\u26A0\uFE0F Cursor setup encountered an error."));
|
|
6459
6808
|
console.log(
|
|
6460
|
-
|
|
6809
|
+
chalk15.dim("You can run ") + chalk15.cyan("braingrid setup cursor") + chalk15.dim(" later.")
|
|
6461
6810
|
);
|
|
6462
6811
|
}
|
|
6463
6812
|
console.log("");
|
|
@@ -6466,7 +6815,7 @@ async function handleInit(opts) {
|
|
|
6466
6815
|
}
|
|
6467
6816
|
return {
|
|
6468
6817
|
success: true,
|
|
6469
|
-
message:
|
|
6818
|
+
message: chalk15.dim(
|
|
6470
6819
|
"You can now use project-scoped commands without specifying a project ID."
|
|
6471
6820
|
),
|
|
6472
6821
|
data: localConfig
|
|
@@ -6479,205 +6828,8 @@ async function handleInit(opts) {
|
|
|
6479
6828
|
}
|
|
6480
6829
|
}
|
|
6481
6830
|
|
|
6482
|
-
// src/handlers/update.handlers.ts
|
|
6483
|
-
import chalk14 from "chalk";
|
|
6484
|
-
import axios5 from "axios";
|
|
6485
|
-
|
|
6486
|
-
// src/utils/package-manager.ts
|
|
6487
|
-
import { execSync } from "child_process";
|
|
6488
|
-
import { select as select3 } from "@inquirer/prompts";
|
|
6489
|
-
function isPackageManagerInstalled(pm) {
|
|
6490
|
-
try {
|
|
6491
|
-
execSync(`which ${pm}`, { stdio: "ignore", timeout: 2e3 });
|
|
6492
|
-
return true;
|
|
6493
|
-
} catch {
|
|
6494
|
-
return false;
|
|
6495
|
-
}
|
|
6496
|
-
}
|
|
6497
|
-
function checkGlobalInstallation(pm, packageName) {
|
|
6498
|
-
try {
|
|
6499
|
-
let command;
|
|
6500
|
-
switch (pm) {
|
|
6501
|
-
case "npm": {
|
|
6502
|
-
command = `npm list -g ${packageName} 2>&1`;
|
|
6503
|
-
break;
|
|
6504
|
-
}
|
|
6505
|
-
case "pnpm": {
|
|
6506
|
-
command = `pnpm list -g ${packageName} 2>&1`;
|
|
6507
|
-
break;
|
|
6508
|
-
}
|
|
6509
|
-
case "yarn": {
|
|
6510
|
-
command = `yarn global list 2>&1`;
|
|
6511
|
-
break;
|
|
6512
|
-
}
|
|
6513
|
-
}
|
|
6514
|
-
const output = execSync(command, {
|
|
6515
|
-
encoding: "utf-8",
|
|
6516
|
-
timeout: 5e3
|
|
6517
|
-
});
|
|
6518
|
-
if (pm === "npm" || pm === "pnpm") {
|
|
6519
|
-
return output.includes(packageName) && !output.includes("(empty)");
|
|
6520
|
-
}
|
|
6521
|
-
if (pm === "yarn") {
|
|
6522
|
-
return output.includes(packageName);
|
|
6523
|
-
}
|
|
6524
|
-
return false;
|
|
6525
|
-
} catch {
|
|
6526
|
-
return false;
|
|
6527
|
-
}
|
|
6528
|
-
}
|
|
6529
|
-
async function getPackageManagerInfo(packageName) {
|
|
6530
|
-
const packageManagers = ["npm", "pnpm", "yarn"];
|
|
6531
|
-
return packageManagers.map((pm) => {
|
|
6532
|
-
const installed = isPackageManagerInstalled(pm);
|
|
6533
|
-
return {
|
|
6534
|
-
name: pm,
|
|
6535
|
-
installed,
|
|
6536
|
-
hasPackage: installed ? checkGlobalInstallation(pm, packageName) : false
|
|
6537
|
-
};
|
|
6538
|
-
});
|
|
6539
|
-
}
|
|
6540
|
-
async function detectPackageManager(packageName) {
|
|
6541
|
-
const pmInfo = await getPackageManagerInfo(packageName);
|
|
6542
|
-
const installedWith = pmInfo.find((pm) => pm.hasPackage);
|
|
6543
|
-
if (installedWith) {
|
|
6544
|
-
return installedWith.name;
|
|
6545
|
-
}
|
|
6546
|
-
const availablePMs = pmInfo.filter((pm) => pm.installed);
|
|
6547
|
-
if (availablePMs.length === 0) {
|
|
6548
|
-
throw new Error("No package manager found. Please install npm, pnpm, or yarn.");
|
|
6549
|
-
}
|
|
6550
|
-
if (availablePMs.length === 1) {
|
|
6551
|
-
return availablePMs[0].name;
|
|
6552
|
-
}
|
|
6553
|
-
const selected = await select3({
|
|
6554
|
-
message: "Unable to detect which package manager was used. Please select one:",
|
|
6555
|
-
choices: availablePMs.map((pm) => ({
|
|
6556
|
-
name: pm.name,
|
|
6557
|
-
value: pm.name
|
|
6558
|
-
}))
|
|
6559
|
-
});
|
|
6560
|
-
return selected;
|
|
6561
|
-
}
|
|
6562
|
-
function getUpdateCommand(pm, packageName) {
|
|
6563
|
-
switch (pm) {
|
|
6564
|
-
case "npm": {
|
|
6565
|
-
return `npm install -g ${packageName}@latest`;
|
|
6566
|
-
}
|
|
6567
|
-
case "pnpm": {
|
|
6568
|
-
return `pnpm add -g ${packageName}@latest`;
|
|
6569
|
-
}
|
|
6570
|
-
case "yarn": {
|
|
6571
|
-
return `yarn global add ${packageName}@latest`;
|
|
6572
|
-
}
|
|
6573
|
-
}
|
|
6574
|
-
}
|
|
6575
|
-
function executeUpdate(pm, packageName) {
|
|
6576
|
-
const command = getUpdateCommand(pm, packageName);
|
|
6577
|
-
try {
|
|
6578
|
-
execSync(command, {
|
|
6579
|
-
stdio: "inherit",
|
|
6580
|
-
timeout: 12e4
|
|
6581
|
-
// 2 minutes timeout
|
|
6582
|
-
});
|
|
6583
|
-
} catch (error) {
|
|
6584
|
-
throw new Error(
|
|
6585
|
-
`Failed to update package: ${error instanceof Error ? error.message : String(error)}`
|
|
6586
|
-
);
|
|
6587
|
-
}
|
|
6588
|
-
}
|
|
6589
|
-
|
|
6590
|
-
// src/handlers/update.handlers.ts
|
|
6591
|
-
var PACKAGE_NAME = "@braingrid/cli";
|
|
6592
|
-
var NPM_REGISTRY_URL = `https://registry.npmjs.org/${PACKAGE_NAME}`;
|
|
6593
|
-
function getCurrentVersion() {
|
|
6594
|
-
return CLI_VERSION;
|
|
6595
|
-
}
|
|
6596
|
-
async function getLatestVersion() {
|
|
6597
|
-
try {
|
|
6598
|
-
const response = await axios5.get(NPM_REGISTRY_URL, {
|
|
6599
|
-
timeout: 1e4
|
|
6600
|
-
});
|
|
6601
|
-
return response.data["dist-tags"].latest;
|
|
6602
|
-
} catch (error) {
|
|
6603
|
-
throw new Error(`Failed to fetch latest version: ${formatError(error)}`);
|
|
6604
|
-
}
|
|
6605
|
-
}
|
|
6606
|
-
function compareVersions(v1, v2) {
|
|
6607
|
-
const v1Parts = v1.split(".").map(Number);
|
|
6608
|
-
const v2Parts = v2.split(".").map(Number);
|
|
6609
|
-
for (let i = 0; i < Math.max(v1Parts.length, v2Parts.length); i++) {
|
|
6610
|
-
const v1Part = v1Parts[i] || 0;
|
|
6611
|
-
const v2Part = v2Parts[i] || 0;
|
|
6612
|
-
if (v1Part < v2Part) return -1;
|
|
6613
|
-
if (v1Part > v2Part) return 1;
|
|
6614
|
-
}
|
|
6615
|
-
return 0;
|
|
6616
|
-
}
|
|
6617
|
-
async function handleUpdate(opts) {
|
|
6618
|
-
try {
|
|
6619
|
-
const currentVersion = getCurrentVersion();
|
|
6620
|
-
let output = chalk14.bold.cyan("\n\u{1F504} BrainGrid CLI Update\n\n");
|
|
6621
|
-
output += `${chalk14.bold("Current version:")} ${currentVersion}
|
|
6622
|
-
`;
|
|
6623
|
-
output += chalk14.dim("Checking for updates...\n");
|
|
6624
|
-
const latestVersion = await getLatestVersion();
|
|
6625
|
-
output += `${chalk14.bold("Latest version:")} ${latestVersion}
|
|
6626
|
-
|
|
6627
|
-
`;
|
|
6628
|
-
const comparison = compareVersions(currentVersion, latestVersion);
|
|
6629
|
-
if (comparison === 0) {
|
|
6630
|
-
output += chalk14.green("\u2705 You are already on the latest version!\n");
|
|
6631
|
-
return {
|
|
6632
|
-
success: true,
|
|
6633
|
-
message: output,
|
|
6634
|
-
data: { currentVersion, latestVersion, upToDate: true }
|
|
6635
|
-
};
|
|
6636
|
-
}
|
|
6637
|
-
if (comparison > 0) {
|
|
6638
|
-
output += chalk14.yellow("\u26A0\uFE0F You are on a newer version than what is published.\n");
|
|
6639
|
-
output += chalk14.dim(" This is expected if you are developing locally.\n");
|
|
6640
|
-
return {
|
|
6641
|
-
success: true,
|
|
6642
|
-
message: output,
|
|
6643
|
-
data: { currentVersion, latestVersion, upToDate: false }
|
|
6644
|
-
};
|
|
6645
|
-
}
|
|
6646
|
-
output += chalk14.yellow(`\u2B06\uFE0F Update available: ${currentVersion} \u2192 ${latestVersion}
|
|
6647
|
-
|
|
6648
|
-
`);
|
|
6649
|
-
if (opts.check) {
|
|
6650
|
-
output += chalk14.dim("Run ") + chalk14.cyan("braingrid update") + chalk14.dim(" to update\n");
|
|
6651
|
-
return {
|
|
6652
|
-
success: true,
|
|
6653
|
-
message: output,
|
|
6654
|
-
data: { currentVersion, latestVersion, upToDate: false }
|
|
6655
|
-
};
|
|
6656
|
-
}
|
|
6657
|
-
output += chalk14.dim("Detecting package manager...\n");
|
|
6658
|
-
const packageManager = await detectPackageManager(PACKAGE_NAME);
|
|
6659
|
-
output += `${chalk14.bold("Package manager:")} ${packageManager}
|
|
6660
|
-
|
|
6661
|
-
`;
|
|
6662
|
-
const updateCommand = getUpdateCommand(packageManager, PACKAGE_NAME);
|
|
6663
|
-
output += chalk14.dim("Running: ") + chalk14.cyan(updateCommand) + "\n\n";
|
|
6664
|
-
console.log(output);
|
|
6665
|
-
executeUpdate(packageManager, PACKAGE_NAME);
|
|
6666
|
-
return {
|
|
6667
|
-
success: true,
|
|
6668
|
-
message: chalk14.green("\n\u2705 Successfully updated BrainGrid CLI!\n"),
|
|
6669
|
-
data: { currentVersion, latestVersion, packageManager }
|
|
6670
|
-
};
|
|
6671
|
-
} catch (error) {
|
|
6672
|
-
return {
|
|
6673
|
-
success: false,
|
|
6674
|
-
message: formatError(error)
|
|
6675
|
-
};
|
|
6676
|
-
}
|
|
6677
|
-
}
|
|
6678
|
-
|
|
6679
6831
|
// src/handlers/completion.handlers.ts
|
|
6680
|
-
import
|
|
6832
|
+
import chalk16 from "chalk";
|
|
6681
6833
|
|
|
6682
6834
|
// src/completion/index.ts
|
|
6683
6835
|
import omelette from "omelette";
|
|
@@ -6753,7 +6905,7 @@ function setupCompletion(shell) {
|
|
|
6753
6905
|
function getUnsupportedShellError() {
|
|
6754
6906
|
return {
|
|
6755
6907
|
success: false,
|
|
6756
|
-
message:
|
|
6908
|
+
message: chalk16.red("\u274C Could not detect shell type.\n\n") + chalk16.dim("Please specify a shell:\n") + chalk16.cyan(" braingrid completion bash\n") + chalk16.cyan(" braingrid completion zsh\n\n") + chalk16.dim("Supported shells: bash, zsh")
|
|
6757
6909
|
};
|
|
6758
6910
|
}
|
|
6759
6911
|
async function handleCompletion(shellArg, opts) {
|
|
@@ -6783,33 +6935,33 @@ async function handleCompletion(shellArg, opts) {
|
|
|
6783
6935
|
const configPath = getShellConfigPath(shell);
|
|
6784
6936
|
return {
|
|
6785
6937
|
success: true,
|
|
6786
|
-
message:
|
|
6938
|
+
message: chalk16.green(`\u2705 Completion installed for ${shell}
|
|
6787
6939
|
|
|
6788
|
-
`) +
|
|
6940
|
+
`) + chalk16.dim("To activate in your current shell, run:\n") + chalk16.cyan(` source ${configPath}
|
|
6789
6941
|
|
|
6790
|
-
`) +
|
|
6942
|
+
`) + chalk16.dim("Or restart your terminal.")
|
|
6791
6943
|
};
|
|
6792
6944
|
} catch (error) {
|
|
6793
6945
|
return {
|
|
6794
6946
|
success: false,
|
|
6795
|
-
message:
|
|
6947
|
+
message: chalk16.red("\u274C Failed to install completion\n\n") + chalk16.dim("Error: ") + formatError(error)
|
|
6796
6948
|
};
|
|
6797
6949
|
}
|
|
6798
6950
|
}
|
|
6799
6951
|
try {
|
|
6800
6952
|
const script = generateCompletionScript(shell);
|
|
6801
6953
|
const configPath = getShellConfigPath(shell);
|
|
6802
|
-
const instructions =
|
|
6803
|
-
`) +
|
|
6804
|
-
`) +
|
|
6954
|
+
const instructions = chalk16.blue(`# BrainGrid CLI completion for ${shell}
|
|
6955
|
+
`) + chalk16.dim("# To install, run one of the following:\n\n") + chalk16.cyan(`# 1. Automatic installation (recommended):
|
|
6956
|
+
`) + chalk16.cyan(` braingrid completion --setup
|
|
6805
6957
|
|
|
6806
|
-
`) +
|
|
6807
|
-
`) +
|
|
6958
|
+
`) + chalk16.cyan(`# 2. Add to your shell config:
|
|
6959
|
+
`) + chalk16.cyan(` braingrid completion ${shell} >> ${configPath}
|
|
6808
6960
|
|
|
6809
|
-
`) +
|
|
6810
|
-
`) +
|
|
6961
|
+
`) + chalk16.cyan(`# 3. Source directly (temporary, current session only):
|
|
6962
|
+
`) + chalk16.cyan(` eval "$(braingrid completion ${shell})"
|
|
6811
6963
|
|
|
6812
|
-
`) +
|
|
6964
|
+
`) + chalk16.dim("# Completion script:\n\n");
|
|
6813
6965
|
return {
|
|
6814
6966
|
success: true,
|
|
6815
6967
|
message: instructions + script
|
|
@@ -6817,7 +6969,7 @@ async function handleCompletion(shellArg, opts) {
|
|
|
6817
6969
|
} catch (error) {
|
|
6818
6970
|
return {
|
|
6819
6971
|
success: false,
|
|
6820
|
-
message:
|
|
6972
|
+
message: chalk16.red("\u274C Failed to generate completion script\n\n") + chalk16.dim("Error: ") + formatError(error)
|
|
6821
6973
|
};
|
|
6822
6974
|
}
|
|
6823
6975
|
} catch (error) {
|
|
@@ -6834,6 +6986,9 @@ var packageJson = require2("../package.json");
|
|
|
6834
6986
|
initCompletion();
|
|
6835
6987
|
var program = new Command();
|
|
6836
6988
|
program.name("braingrid").description("BrainGrid CLI - Manage projects, requirements, and tasks").version(packageJson.version, "-v, --version", "output the current version").showHelpAfterError("(use --help for usage)");
|
|
6989
|
+
program.hook("postAction", async () => {
|
|
6990
|
+
await checkAndShowUpdateWarning();
|
|
6991
|
+
});
|
|
6837
6992
|
program.command("login").description("Authenticate with BrainGrid").action(async () => {
|
|
6838
6993
|
const result = await handleLogin();
|
|
6839
6994
|
console.log(result.message);
|
|
@@ -6954,7 +7109,7 @@ requirement.command("list").description("List requirements for a project").optio
|
|
|
6954
7109
|
requirement.command("show [id]").description("Show requirement details (auto-detects ID from git branch if not provided)").option(
|
|
6955
7110
|
"-p, --project <id>",
|
|
6956
7111
|
"project ID (auto-detects from .braingrid/project.json if not provided)"
|
|
6957
|
-
).action(async (id, opts) => {
|
|
7112
|
+
).option("--format <format>", "output format (table, json, xml, markdown)", "table").action(async (id, opts) => {
|
|
6958
7113
|
const result = await handleRequirementShow({ ...opts, id });
|
|
6959
7114
|
console.log(result.message);
|
|
6960
7115
|
if (!result.success) {
|
|
@@ -7027,7 +7182,7 @@ task.command("summary").description("Show task summary table (quick overview wit
|
|
|
7027
7182
|
process.exit(1);
|
|
7028
7183
|
}
|
|
7029
7184
|
});
|
|
7030
|
-
task.command("show <id>").description("Show task details").option("-r, --requirement <id>", "requirement ID (REQ-456, auto-detects project if initialized)").option("-p, --project <id>", "project ID (PROJ-123, optional if project is initialized)").action(async (id, opts) => {
|
|
7185
|
+
task.command("show <id>").description("Show task details").option("-r, --requirement <id>", "requirement ID (REQ-456, auto-detects project if initialized)").option("-p, --project <id>", "project ID (PROJ-123, optional if project is initialized)").option("--format <format>", "output format (table, json, xml, markdown)", "table").action(async (id, opts) => {
|
|
7031
7186
|
const result = await handleTaskShow(id, opts);
|
|
7032
7187
|
console.log(result.message);
|
|
7033
7188
|
if (!result.success) {
|