@braingrid/cli 0.2.16 → 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 +11 -0
- package/dist/cli.js +422 -328
- 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",
|
|
@@ -5187,8 +5187,8 @@ async function handleStatus() {
|
|
|
5187
5187
|
}
|
|
5188
5188
|
|
|
5189
5189
|
// src/handlers/init.handlers.ts
|
|
5190
|
-
import
|
|
5191
|
-
import { confirm, select as
|
|
5190
|
+
import chalk15 from "chalk";
|
|
5191
|
+
import { confirm, select as select3, input } from "@inquirer/prompts";
|
|
5192
5192
|
|
|
5193
5193
|
// src/services/internal/github-service.ts
|
|
5194
5194
|
var GitHubService = class {
|
|
@@ -5455,9 +5455,277 @@ function getManualInstallInstructions() {
|
|
|
5455
5455
|
}
|
|
5456
5456
|
}
|
|
5457
5457
|
|
|
5458
|
-
// src/handlers/
|
|
5458
|
+
// src/handlers/update.handlers.ts
|
|
5459
5459
|
import chalk12 from "chalk";
|
|
5460
|
+
|
|
5461
|
+
// src/utils/package-manager.ts
|
|
5462
|
+
import { execSync } from "child_process";
|
|
5460
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";
|
|
5461
5729
|
import * as path4 from "path";
|
|
5462
5730
|
import * as fs4 from "fs/promises";
|
|
5463
5731
|
|
|
@@ -5674,7 +5942,7 @@ async function checkPrerequisites() {
|
|
|
5674
5942
|
} catch {
|
|
5675
5943
|
return {
|
|
5676
5944
|
success: false,
|
|
5677
|
-
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")
|
|
5678
5946
|
};
|
|
5679
5947
|
}
|
|
5680
5948
|
try {
|
|
@@ -5682,7 +5950,7 @@ async function checkPrerequisites() {
|
|
|
5682
5950
|
} catch {
|
|
5683
5951
|
return {
|
|
5684
5952
|
success: false,
|
|
5685
|
-
message:
|
|
5953
|
+
message: chalk14.red("\u274C Not authenticated with GitHub CLI.\n\n") + chalk14.dim("Please run: ") + chalk14.cyan("gh auth login")
|
|
5686
5954
|
};
|
|
5687
5955
|
}
|
|
5688
5956
|
return null;
|
|
@@ -5709,7 +5977,7 @@ async function getFileList(sourcePaths, targetPaths) {
|
|
|
5709
5977
|
}
|
|
5710
5978
|
} catch (error) {
|
|
5711
5979
|
console.warn(
|
|
5712
|
-
|
|
5980
|
+
chalk14.yellow(`\u26A0\uFE0F Could not list directory: ${sourceDir}`),
|
|
5713
5981
|
error instanceof Error ? error.message : String(error)
|
|
5714
5982
|
);
|
|
5715
5983
|
}
|
|
@@ -5720,28 +5988,28 @@ async function getFileList(sourcePaths, targetPaths) {
|
|
|
5720
5988
|
return operations;
|
|
5721
5989
|
}
|
|
5722
5990
|
function displayInstallationPlan(operations, injectionFile) {
|
|
5723
|
-
console.log(
|
|
5724
|
-
console.log(
|
|
5725
|
-
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}`));
|
|
5726
5994
|
const newFiles = operations.filter((op) => !op.exists);
|
|
5727
5995
|
const existingFiles = operations.filter((op) => op.exists);
|
|
5728
5996
|
if (newFiles.length > 0) {
|
|
5729
|
-
console.log(
|
|
5997
|
+
console.log(chalk14.cyan("\n New Files:"));
|
|
5730
5998
|
for (const op of newFiles) {
|
|
5731
|
-
console.log(
|
|
5999
|
+
console.log(chalk14.dim(` ${op.targetPath}`));
|
|
5732
6000
|
}
|
|
5733
6001
|
}
|
|
5734
6002
|
if (existingFiles.length > 0) {
|
|
5735
|
-
console.log(
|
|
6003
|
+
console.log(chalk14.yellow("\n Existing Files (will prompt):"));
|
|
5736
6004
|
for (const op of existingFiles) {
|
|
5737
|
-
console.log(
|
|
6005
|
+
console.log(chalk14.dim(` ${op.targetPath}`));
|
|
5738
6006
|
}
|
|
5739
6007
|
}
|
|
5740
6008
|
console.log("");
|
|
5741
6009
|
}
|
|
5742
6010
|
async function promptForConflict(filePath) {
|
|
5743
|
-
const answer = await
|
|
5744
|
-
message:
|
|
6011
|
+
const answer = await select2({
|
|
6012
|
+
message: chalk14.yellow(`File exists: ${filePath}`),
|
|
5745
6013
|
choices: [
|
|
5746
6014
|
{ name: "[O]verwrite - Replace this file", value: "overwrite" },
|
|
5747
6015
|
{ name: "[S]kip - Keep existing file", value: "skip" },
|
|
@@ -5772,7 +6040,7 @@ async function installFiles(operations, force) {
|
|
|
5772
6040
|
installed++;
|
|
5773
6041
|
} catch (error) {
|
|
5774
6042
|
console.error(
|
|
5775
|
-
|
|
6043
|
+
chalk14.red(`Failed to copy ${operation.targetPath}:`),
|
|
5776
6044
|
error instanceof Error ? error.message : String(error)
|
|
5777
6045
|
);
|
|
5778
6046
|
skipped++;
|
|
@@ -5786,7 +6054,7 @@ async function _handleSetup(config, opts) {
|
|
|
5786
6054
|
if (prerequisiteError) {
|
|
5787
6055
|
return prerequisiteError;
|
|
5788
6056
|
}
|
|
5789
|
-
console.log(
|
|
6057
|
+
console.log(chalk14.bold(`\u{1F680} Setting up ${config.name} integration...
|
|
5790
6058
|
`));
|
|
5791
6059
|
const operations = await getFileList(config.sourceDirs, config.targetDirs);
|
|
5792
6060
|
const injectionFileExists = await fileExists(config.injection.targetFile);
|
|
@@ -5803,7 +6071,7 @@ async function _handleSetup(config, opts) {
|
|
|
5803
6071
|
if (opts.dryRun) {
|
|
5804
6072
|
return {
|
|
5805
6073
|
success: true,
|
|
5806
|
-
message:
|
|
6074
|
+
message: chalk14.green("\u2705 Dry-run complete. No files were modified.\n\n") + chalk14.dim(`Would install ${operations.length} files.`)
|
|
5807
6075
|
};
|
|
5808
6076
|
}
|
|
5809
6077
|
const copyOps = operations.filter((op) => op.type === "copy");
|
|
@@ -5811,7 +6079,7 @@ async function _handleSetup(config, opts) {
|
|
|
5811
6079
|
if (result.cancelled) {
|
|
5812
6080
|
return {
|
|
5813
6081
|
success: false,
|
|
5814
|
-
message:
|
|
6082
|
+
message: chalk14.yellow("\u26A0\uFE0F Installation cancelled.\n\n") + chalk14.dim(`Installed: ${result.installed}, Skipped: ${result.skipped}`),
|
|
5815
6083
|
code: "CANCELLED"
|
|
5816
6084
|
};
|
|
5817
6085
|
}
|
|
@@ -5820,7 +6088,7 @@ async function _handleSetup(config, opts) {
|
|
|
5820
6088
|
await injectContentIntoFile(config.injection.targetFile, content);
|
|
5821
6089
|
} catch (error) {
|
|
5822
6090
|
console.error(
|
|
5823
|
-
|
|
6091
|
+
chalk14.red(`Failed to inject content into ${config.injection.targetFile}:`),
|
|
5824
6092
|
error instanceof Error ? error.message : String(error)
|
|
5825
6093
|
);
|
|
5826
6094
|
}
|
|
@@ -5833,27 +6101,27 @@ async function _handleSetup(config, opts) {
|
|
|
5833
6101
|
statusLineInstalled = true;
|
|
5834
6102
|
} catch (error) {
|
|
5835
6103
|
console.error(
|
|
5836
|
-
|
|
6104
|
+
chalk14.yellow("\u26A0\uFE0F Failed to install status line script:"),
|
|
5837
6105
|
error instanceof Error ? error.message : String(error)
|
|
5838
6106
|
);
|
|
5839
6107
|
}
|
|
5840
6108
|
}
|
|
5841
|
-
const statusLineMessage = statusLineInstalled ?
|
|
6109
|
+
const statusLineMessage = statusLineInstalled ? chalk14.dim(" Status line: .claude/statusline.sh\n") : "";
|
|
5842
6110
|
return {
|
|
5843
6111
|
success: true,
|
|
5844
|
-
message:
|
|
6112
|
+
message: chalk14.green(`\u2705 ${config.name} integration installed successfully!
|
|
5845
6113
|
|
|
5846
|
-
`) +
|
|
5847
|
-
`) + statusLineMessage +
|
|
6114
|
+
`) + chalk14.dim("Files installed:\n") + chalk14.dim(` Commands: ${result.installed} files
|
|
6115
|
+
`) + statusLineMessage + chalk14.dim(` Content injected into: ${config.injection.targetFile}
|
|
5848
6116
|
|
|
5849
|
-
`) +
|
|
5850
|
-
`) +
|
|
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)
|
|
5851
6119
|
};
|
|
5852
6120
|
} catch (error) {
|
|
5853
6121
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
5854
6122
|
return {
|
|
5855
6123
|
success: false,
|
|
5856
|
-
message:
|
|
6124
|
+
message: chalk14.red(`\u274C Setup failed: ${errorMessage}`)
|
|
5857
6125
|
};
|
|
5858
6126
|
}
|
|
5859
6127
|
}
|
|
@@ -5967,12 +6235,12 @@ function getServices4() {
|
|
|
5967
6235
|
function promptToAddOrganization(owner, webUrl) {
|
|
5968
6236
|
return {
|
|
5969
6237
|
success: false,
|
|
5970
|
-
message:
|
|
6238
|
+
message: chalk15.yellow("\u26A0\uFE0F No projects found for this repository.\n\n") + chalk15.dim(`Repository: ${owner}/*
|
|
5971
6239
|
|
|
5972
|
-
`) +
|
|
6240
|
+
`) + chalk15.dim(`You have GitHub connected, but not for the "${owner}" organization.
|
|
5973
6241
|
|
|
5974
|
-
`) +
|
|
5975
|
-
`) +
|
|
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")
|
|
5976
6244
|
};
|
|
5977
6245
|
}
|
|
5978
6246
|
async function promptToCreateProject(gitInfo, projectService, repositoryService) {
|
|
@@ -5980,20 +6248,20 @@ async function promptToCreateProject(gitInfo, projectService, repositoryService)
|
|
|
5980
6248
|
if (!gitInfo.owner || !gitInfo.name) {
|
|
5981
6249
|
return {
|
|
5982
6250
|
success: false,
|
|
5983
|
-
message:
|
|
6251
|
+
message: chalk15.red("\u274C Repository information is incomplete")
|
|
5984
6252
|
};
|
|
5985
6253
|
}
|
|
5986
6254
|
const repositoryId = await getRepositoryId(repositoryService, gitInfo.owner, gitInfo.name);
|
|
5987
6255
|
if (!repositoryId) {
|
|
5988
6256
|
return {
|
|
5989
6257
|
success: false,
|
|
5990
|
-
message:
|
|
6258
|
+
message: chalk15.yellow("\u26A0\uFE0F Repository accessible but could not retrieve details.\n\n") + chalk15.dim(`Repository: ${gitInfo.owner}/${gitInfo.name}
|
|
5991
6259
|
|
|
5992
|
-
`) +
|
|
6260
|
+
`) + chalk15.dim("Please try again or create a project manually at: ") + chalk15.cyan(webUrl)
|
|
5993
6261
|
};
|
|
5994
6262
|
}
|
|
5995
6263
|
console.log(
|
|
5996
|
-
|
|
6264
|
+
chalk15.yellow("\u26A0\uFE0F Repository accessible but no project exists.\n\n") + chalk15.dim(`Repository: ${gitInfo.owner}/${gitInfo.name}
|
|
5997
6265
|
`)
|
|
5998
6266
|
);
|
|
5999
6267
|
const shouldCreate = await confirm({
|
|
@@ -6003,7 +6271,7 @@ async function promptToCreateProject(gitInfo, projectService, repositoryService)
|
|
|
6003
6271
|
if (!shouldCreate) {
|
|
6004
6272
|
return {
|
|
6005
6273
|
success: false,
|
|
6006
|
-
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(
|
|
6007
6275
|
`braingrid project create --name "${gitInfo.name}" --repositories "${gitInfo.owner}/${gitInfo.name}"`
|
|
6008
6276
|
)
|
|
6009
6277
|
};
|
|
@@ -6014,9 +6282,9 @@ async function promptToCreateProject(gitInfo, projectService, repositoryService)
|
|
|
6014
6282
|
description: `Project for ${gitInfo.owner}/${gitInfo.name}`,
|
|
6015
6283
|
repository_id: repositoryId
|
|
6016
6284
|
});
|
|
6017
|
-
console.log(
|
|
6285
|
+
console.log(chalk15.green(`
|
|
6018
6286
|
\u2705 Created project ${project2.short_id}: ${project2.name}`));
|
|
6019
|
-
console.log(
|
|
6287
|
+
console.log(chalk15.green(`\u2705 Linked repository ${gitInfo.owner}/${gitInfo.name}
|
|
6020
6288
|
`));
|
|
6021
6289
|
return { success: true, message: "", data: project2 };
|
|
6022
6290
|
} catch (error) {
|
|
@@ -6030,18 +6298,18 @@ async function promptToGrantRepositoryAccess(gitInfo, webUrl, repositoryService,
|
|
|
6030
6298
|
if (!gitInfo.owner || !gitInfo.name) {
|
|
6031
6299
|
return {
|
|
6032
6300
|
success: false,
|
|
6033
|
-
message:
|
|
6301
|
+
message: chalk15.red("\u274C Repository information is incomplete")
|
|
6034
6302
|
};
|
|
6035
6303
|
}
|
|
6036
6304
|
const owner = gitInfo.owner;
|
|
6037
6305
|
const name = gitInfo.name;
|
|
6038
6306
|
console.log(
|
|
6039
|
-
|
|
6307
|
+
chalk15.yellow("\u26A0\uFE0F Repository found but BrainGrid needs access.\n\n") + chalk15.dim(`Repository: ${owner}/${name}
|
|
6040
6308
|
|
|
6041
|
-
`) +
|
|
6309
|
+
`) + chalk15.dim("Please grant BrainGrid access to this repository:\n") + chalk15.dim(" 1. Visit: ") + chalk15.cyan(`${webUrl}/integrations`) + chalk15.dim("\n") + chalk15.dim(
|
|
6042
6310
|
` 2. Click on your "${owner}" installation "Add/Remove" to grant BrainGrid access to your repository
|
|
6043
6311
|
`
|
|
6044
|
-
) +
|
|
6312
|
+
) + chalk15.dim(` 3. Select "${name}" and save
|
|
6045
6313
|
|
|
6046
6314
|
`)
|
|
6047
6315
|
);
|
|
@@ -6054,10 +6322,10 @@ async function promptToGrantRepositoryAccess(gitInfo, webUrl, repositoryService,
|
|
|
6054
6322
|
if (!accessGranted) {
|
|
6055
6323
|
return {
|
|
6056
6324
|
success: false,
|
|
6057
|
-
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.")
|
|
6058
6326
|
};
|
|
6059
6327
|
}
|
|
6060
|
-
console.log(
|
|
6328
|
+
console.log(chalk15.green("\u2705 Repository access granted!\n"));
|
|
6061
6329
|
return promptToCreateProject(gitInfo, projectService, repositoryService);
|
|
6062
6330
|
}
|
|
6063
6331
|
async function handleNoProjectForRepository(owner, name, gitInfo, githubService, repositoryService, projectService, config) {
|
|
@@ -6072,9 +6340,9 @@ async function handleNoProjectForRepository(owner, name, gitInfo, githubService,
|
|
|
6072
6340
|
if (allInstallations.length === 0) {
|
|
6073
6341
|
return {
|
|
6074
6342
|
success: false,
|
|
6075
|
-
message:
|
|
6343
|
+
message: chalk15.yellow("\u26A0\uFE0F No projects found for this repository.\n\n") + chalk15.dim(`Repository: ${owner}/${name}
|
|
6076
6344
|
|
|
6077
|
-
`) +
|
|
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.")
|
|
6078
6346
|
};
|
|
6079
6347
|
}
|
|
6080
6348
|
const ownerInstallation = findInstallationForOwner(owner, allInstallations);
|
|
@@ -6090,28 +6358,28 @@ async function handleNoProjectForRepository(owner, name, gitInfo, githubService,
|
|
|
6090
6358
|
function showSetupInstructions(scenario) {
|
|
6091
6359
|
let message = "";
|
|
6092
6360
|
if (scenario === "no-git") {
|
|
6093
|
-
message +=
|
|
6094
|
-
message +=
|
|
6095
|
-
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");
|
|
6096
6364
|
} else {
|
|
6097
|
-
message +=
|
|
6365
|
+
message += chalk15.dim("To connect to GitHub:\n\n");
|
|
6098
6366
|
}
|
|
6099
|
-
message +=
|
|
6100
|
-
message +=
|
|
6101
|
-
message +=
|
|
6102
|
-
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");
|
|
6103
6371
|
if (scenario === "no-git") {
|
|
6104
|
-
message +=
|
|
6372
|
+
message += chalk15.dim(" 3. Run: ") + chalk15.cyan("braingrid init\n\n");
|
|
6105
6373
|
} else {
|
|
6106
|
-
message +=
|
|
6107
|
-
message +=
|
|
6108
|
-
message +=
|
|
6109
|
-
}
|
|
6110
|
-
message +=
|
|
6111
|
-
message +=
|
|
6112
|
-
message +=
|
|
6113
|
-
message +=
|
|
6114
|
-
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";
|
|
6115
6383
|
return message;
|
|
6116
6384
|
}
|
|
6117
6385
|
async function handleNoGitRepository() {
|
|
@@ -6127,12 +6395,12 @@ async function handleNoGitRepository() {
|
|
|
6127
6395
|
if (!gitInitSuccess) {
|
|
6128
6396
|
return {
|
|
6129
6397
|
success: false,
|
|
6130
|
-
message:
|
|
6398
|
+
message: chalk15.red("\u274C Failed to initialize git repository")
|
|
6131
6399
|
};
|
|
6132
6400
|
}
|
|
6133
|
-
console.log(
|
|
6401
|
+
console.log(chalk15.green("\u2705 Initialized git repository"));
|
|
6134
6402
|
const dirName = getCurrentDirectoryName();
|
|
6135
|
-
const isPrivate = await
|
|
6403
|
+
const isPrivate = await select3({
|
|
6136
6404
|
message: "Repository visibility:",
|
|
6137
6405
|
choices: [
|
|
6138
6406
|
{ value: true, name: "Private" },
|
|
@@ -6144,16 +6412,16 @@ async function handleNoGitRepository() {
|
|
|
6144
6412
|
message: "Repository name:",
|
|
6145
6413
|
default: dirName
|
|
6146
6414
|
});
|
|
6147
|
-
console.log(
|
|
6415
|
+
console.log(chalk15.dim("\nCreating repository...\n"));
|
|
6148
6416
|
const repo = await createGitHubRepoWithGh(repoName, isPrivate);
|
|
6149
6417
|
if (!repo) {
|
|
6150
6418
|
return {
|
|
6151
6419
|
success: false,
|
|
6152
|
-
message:
|
|
6420
|
+
message: chalk15.red("\u274C Failed to create GitHub repository\n\n") + showSetupInstructions("no-git")
|
|
6153
6421
|
};
|
|
6154
6422
|
}
|
|
6155
|
-
console.log(
|
|
6156
|
-
console.log(
|
|
6423
|
+
console.log(chalk15.green(`\u2705 Created repository: ${repo.url}`));
|
|
6424
|
+
console.log(chalk15.green("\u2705 Added remote origin\n"));
|
|
6157
6425
|
return {
|
|
6158
6426
|
success: true,
|
|
6159
6427
|
message: "continue-init",
|
|
@@ -6164,7 +6432,7 @@ async function handleNoGitRepository() {
|
|
|
6164
6432
|
}
|
|
6165
6433
|
return {
|
|
6166
6434
|
success: false,
|
|
6167
|
-
message:
|
|
6435
|
+
message: chalk15.yellow("\u26A0\uFE0F This directory is not a git repository.\n\n") + showSetupInstructions("no-git")
|
|
6168
6436
|
};
|
|
6169
6437
|
}
|
|
6170
6438
|
async function handleNoGitRemote() {
|
|
@@ -6176,7 +6444,7 @@ async function handleNoGitRemote() {
|
|
|
6176
6444
|
});
|
|
6177
6445
|
if (shouldCreate) {
|
|
6178
6446
|
const dirName = getCurrentDirectoryName();
|
|
6179
|
-
const isPrivate = await
|
|
6447
|
+
const isPrivate = await select3({
|
|
6180
6448
|
message: "Repository visibility:",
|
|
6181
6449
|
choices: [
|
|
6182
6450
|
{ value: true, name: "Private" },
|
|
@@ -6188,16 +6456,16 @@ async function handleNoGitRemote() {
|
|
|
6188
6456
|
message: "Repository name:",
|
|
6189
6457
|
default: dirName
|
|
6190
6458
|
});
|
|
6191
|
-
console.log(
|
|
6459
|
+
console.log(chalk15.dim("\nCreating repository...\n"));
|
|
6192
6460
|
const repo = await createGitHubRepoWithGh(repoName, isPrivate);
|
|
6193
6461
|
if (!repo) {
|
|
6194
6462
|
return {
|
|
6195
6463
|
success: false,
|
|
6196
|
-
message:
|
|
6464
|
+
message: chalk15.red("\u274C Failed to create GitHub repository\n\n") + showSetupInstructions("no-remote")
|
|
6197
6465
|
};
|
|
6198
6466
|
}
|
|
6199
|
-
console.log(
|
|
6200
|
-
console.log(
|
|
6467
|
+
console.log(chalk15.green(`\u2705 Created repository: ${repo.url}`));
|
|
6468
|
+
console.log(chalk15.green("\u2705 Added remote origin\n"));
|
|
6201
6469
|
return {
|
|
6202
6470
|
success: true,
|
|
6203
6471
|
message: "continue-init",
|
|
@@ -6208,11 +6476,31 @@ async function handleNoGitRemote() {
|
|
|
6208
6476
|
}
|
|
6209
6477
|
return {
|
|
6210
6478
|
success: false,
|
|
6211
|
-
message:
|
|
6479
|
+
message: chalk15.yellow("\u26A0\uFE0F Git repository detected but no GitHub remote configured.\n\n") + showSetupInstructions("no-remote")
|
|
6212
6480
|
};
|
|
6213
6481
|
}
|
|
6214
6482
|
async function handleInit(opts) {
|
|
6215
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
|
+
}
|
|
6216
6504
|
const config = getConfig();
|
|
6217
6505
|
const { projectService, githubService, repositoryService, auth } = getServices4();
|
|
6218
6506
|
if (!await isGitInstalled()) {
|
|
@@ -6223,7 +6511,7 @@ async function handleInit(opts) {
|
|
|
6223
6511
|
if (!shouldInstall) {
|
|
6224
6512
|
return {
|
|
6225
6513
|
success: false,
|
|
6226
|
-
message:
|
|
6514
|
+
message: chalk15.yellow("\u26A0\uFE0F Git installation cancelled.\n\n") + getManualInstallInstructions()
|
|
6227
6515
|
};
|
|
6228
6516
|
}
|
|
6229
6517
|
console.log();
|
|
@@ -6239,14 +6527,14 @@ async function handleInit(opts) {
|
|
|
6239
6527
|
if (!await isGitInstalled()) {
|
|
6240
6528
|
return {
|
|
6241
6529
|
success: false,
|
|
6242
|
-
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()
|
|
6243
6531
|
};
|
|
6244
6532
|
}
|
|
6245
6533
|
}
|
|
6246
6534
|
if (!await isGhInstalled()) {
|
|
6247
|
-
console.log(
|
|
6535
|
+
console.log(chalk15.blue("\n\u{1F4A1} GitHub CLI is highly recommended for working with BrainGrid."));
|
|
6248
6536
|
console.log(
|
|
6249
|
-
|
|
6537
|
+
chalk15.dim(" It enables seamless GitHub integration and repository management.\n")
|
|
6250
6538
|
);
|
|
6251
6539
|
const shouldInstallGh = await confirm({
|
|
6252
6540
|
message: "Would you like to install GitHub CLI now?",
|
|
@@ -6260,10 +6548,10 @@ async function handleInit(opts) {
|
|
|
6260
6548
|
console.log();
|
|
6261
6549
|
} else {
|
|
6262
6550
|
console.log(ghInstallResult.message);
|
|
6263
|
-
console.log(
|
|
6551
|
+
console.log(chalk15.dim("You can install it manually later.\n"));
|
|
6264
6552
|
}
|
|
6265
6553
|
} else {
|
|
6266
|
-
console.log(
|
|
6554
|
+
console.log(chalk15.dim("Skipping GitHub CLI installation.\n"));
|
|
6267
6555
|
}
|
|
6268
6556
|
}
|
|
6269
6557
|
if (await projectConfigExists() && !opts.force) {
|
|
@@ -6271,15 +6559,15 @@ async function handleInit(opts) {
|
|
|
6271
6559
|
const existing = await loadProjectConfig();
|
|
6272
6560
|
return {
|
|
6273
6561
|
success: false,
|
|
6274
|
-
message:
|
|
6275
|
-
`) +
|
|
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"}
|
|
6276
6564
|
|
|
6277
|
-
`) +
|
|
6565
|
+
`) + chalk15.dim("Use --force to reinitialize")
|
|
6278
6566
|
};
|
|
6279
6567
|
} catch {
|
|
6280
6568
|
return {
|
|
6281
6569
|
success: false,
|
|
6282
|
-
message:
|
|
6570
|
+
message: chalk15.yellow("\u26A0\uFE0F Invalid project configuration found.\n") + chalk15.dim("Use --force to reinitialize")
|
|
6283
6571
|
};
|
|
6284
6572
|
}
|
|
6285
6573
|
}
|
|
@@ -6292,7 +6580,7 @@ async function handleInit(opts) {
|
|
|
6292
6580
|
if (!shouldLogin) {
|
|
6293
6581
|
return {
|
|
6294
6582
|
success: false,
|
|
6295
|
-
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.")
|
|
6296
6584
|
};
|
|
6297
6585
|
}
|
|
6298
6586
|
console.log();
|
|
@@ -6300,13 +6588,13 @@ async function handleInit(opts) {
|
|
|
6300
6588
|
if (!loginResult.success) {
|
|
6301
6589
|
return {
|
|
6302
6590
|
success: false,
|
|
6303
|
-
message:
|
|
6591
|
+
message: chalk15.red("\u274C Login failed.\n") + chalk15.dim("Please try running ") + chalk15.cyan("braingrid login") + chalk15.dim(" again.")
|
|
6304
6592
|
};
|
|
6305
6593
|
}
|
|
6306
6594
|
if (!await auth.isAuthenticated()) {
|
|
6307
6595
|
return {
|
|
6308
6596
|
success: false,
|
|
6309
|
-
message:
|
|
6597
|
+
message: chalk15.red("\u274C Login was not completed.\n") + chalk15.dim("Please try running ") + chalk15.cyan("braingrid login") + chalk15.dim(" again.")
|
|
6310
6598
|
};
|
|
6311
6599
|
}
|
|
6312
6600
|
console.log();
|
|
@@ -6315,27 +6603,27 @@ async function handleInit(opts) {
|
|
|
6315
6603
|
if (!session) {
|
|
6316
6604
|
return {
|
|
6317
6605
|
success: false,
|
|
6318
|
-
message:
|
|
6606
|
+
message: chalk15.red("\u274C No session found. Please run `braingrid login` first.")
|
|
6319
6607
|
};
|
|
6320
6608
|
}
|
|
6321
6609
|
if (session.organization_id === "default") {
|
|
6322
|
-
console.log(
|
|
6610
|
+
console.log(chalk15.yellow("\u26A0\uFE0F Organization ID not set, validating session...\n"));
|
|
6323
6611
|
const isValid = await auth.isAuthenticated();
|
|
6324
6612
|
if (!isValid) {
|
|
6325
6613
|
return {
|
|
6326
6614
|
success: false,
|
|
6327
|
-
message:
|
|
6615
|
+
message: chalk15.red("\u274C Session validation failed. Please run `braingrid login` again.")
|
|
6328
6616
|
};
|
|
6329
6617
|
}
|
|
6330
6618
|
const updatedSession = await auth.getStoredSession();
|
|
6331
6619
|
if (!updatedSession || updatedSession.organization_id === "default") {
|
|
6332
6620
|
return {
|
|
6333
6621
|
success: false,
|
|
6334
|
-
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")
|
|
6335
6623
|
};
|
|
6336
6624
|
}
|
|
6337
6625
|
Object.assign(session, updatedSession);
|
|
6338
|
-
console.log(
|
|
6626
|
+
console.log(chalk15.green("\u2705 Organization ID updated successfully\n"));
|
|
6339
6627
|
}
|
|
6340
6628
|
let gitInfo = await getGitRepositoryInfo();
|
|
6341
6629
|
let project2;
|
|
@@ -6345,9 +6633,9 @@ async function handleInit(opts) {
|
|
|
6345
6633
|
} catch {
|
|
6346
6634
|
return {
|
|
6347
6635
|
success: false,
|
|
6348
|
-
message:
|
|
6636
|
+
message: chalk15.red(`\u274C Project not found: ${opts.project}
|
|
6349
6637
|
|
|
6350
|
-
`) +
|
|
6638
|
+
`) + chalk15.dim("Make sure the project ID is correct and you have access to it.")
|
|
6351
6639
|
};
|
|
6352
6640
|
}
|
|
6353
6641
|
} else {
|
|
@@ -6358,7 +6646,7 @@ async function handleInit(opts) {
|
|
|
6358
6646
|
if (!gitInfo || !gitInfo.owner || !gitInfo.name) {
|
|
6359
6647
|
return {
|
|
6360
6648
|
success: false,
|
|
6361
|
-
message:
|
|
6649
|
+
message: chalk15.red("\u274C Failed to get repository information after setup")
|
|
6362
6650
|
};
|
|
6363
6651
|
}
|
|
6364
6652
|
} else {
|
|
@@ -6372,7 +6660,7 @@ async function handleInit(opts) {
|
|
|
6372
6660
|
if (!gitInfo || !gitInfo.owner || !gitInfo.name) {
|
|
6373
6661
|
return {
|
|
6374
6662
|
success: false,
|
|
6375
|
-
message:
|
|
6663
|
+
message: chalk15.red("\u274C Failed to get repository information after setup")
|
|
6376
6664
|
};
|
|
6377
6665
|
}
|
|
6378
6666
|
} else {
|
|
@@ -6382,7 +6670,7 @@ async function handleInit(opts) {
|
|
|
6382
6670
|
if (!gitInfo) {
|
|
6383
6671
|
return {
|
|
6384
6672
|
success: false,
|
|
6385
|
-
message:
|
|
6673
|
+
message: chalk15.red("\u274C Repository information is missing")
|
|
6386
6674
|
};
|
|
6387
6675
|
}
|
|
6388
6676
|
const owner = gitInfo.owner;
|
|
@@ -6390,7 +6678,7 @@ async function handleInit(opts) {
|
|
|
6390
6678
|
if (!owner || !name) {
|
|
6391
6679
|
return {
|
|
6392
6680
|
success: false,
|
|
6393
|
-
message:
|
|
6681
|
+
message: chalk15.red("\u274C Repository information is incomplete")
|
|
6394
6682
|
};
|
|
6395
6683
|
}
|
|
6396
6684
|
let response;
|
|
@@ -6429,7 +6717,7 @@ async function handleInit(opts) {
|
|
|
6429
6717
|
}
|
|
6430
6718
|
project2 = response.projects[0];
|
|
6431
6719
|
}
|
|
6432
|
-
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";
|
|
6433
6721
|
console.log(projectInfo);
|
|
6434
6722
|
if (!opts.force) {
|
|
6435
6723
|
const shouldInit = await confirm({
|
|
@@ -6439,7 +6727,7 @@ async function handleInit(opts) {
|
|
|
6439
6727
|
if (!shouldInit) {
|
|
6440
6728
|
return {
|
|
6441
6729
|
success: false,
|
|
6442
|
-
message:
|
|
6730
|
+
message: chalk15.yellow("Initialization cancelled.")
|
|
6443
6731
|
};
|
|
6444
6732
|
}
|
|
6445
6733
|
}
|
|
@@ -6462,7 +6750,7 @@ async function handleInit(opts) {
|
|
|
6462
6750
|
};
|
|
6463
6751
|
await saveProjectConfig(localConfig);
|
|
6464
6752
|
console.log(
|
|
6465
|
-
|
|
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"
|
|
6466
6754
|
);
|
|
6467
6755
|
const installedIDEs = await detectInstalledIDEs();
|
|
6468
6756
|
if (installedIDEs.claudeCode) {
|
|
@@ -6480,15 +6768,15 @@ async function handleInit(opts) {
|
|
|
6480
6768
|
if (result.success) {
|
|
6481
6769
|
console.log(result.message);
|
|
6482
6770
|
} else {
|
|
6483
|
-
console.log(
|
|
6771
|
+
console.log(chalk15.yellow("\u26A0\uFE0F Claude Code setup was not completed."));
|
|
6484
6772
|
console.log(
|
|
6485
|
-
|
|
6773
|
+
chalk15.dim("You can run ") + chalk15.cyan("braingrid setup claude-code") + chalk15.dim(" later.")
|
|
6486
6774
|
);
|
|
6487
6775
|
}
|
|
6488
6776
|
} catch {
|
|
6489
|
-
console.log(
|
|
6777
|
+
console.log(chalk15.yellow("\u26A0\uFE0F Claude Code setup encountered an error."));
|
|
6490
6778
|
console.log(
|
|
6491
|
-
|
|
6779
|
+
chalk15.dim("You can run ") + chalk15.cyan("braingrid setup claude-code") + chalk15.dim(" later.")
|
|
6492
6780
|
);
|
|
6493
6781
|
}
|
|
6494
6782
|
console.log("");
|
|
@@ -6510,15 +6798,15 @@ async function handleInit(opts) {
|
|
|
6510
6798
|
if (result.success) {
|
|
6511
6799
|
console.log(result.message);
|
|
6512
6800
|
} else {
|
|
6513
|
-
console.log(
|
|
6801
|
+
console.log(chalk15.yellow("\u26A0\uFE0F Cursor setup was not completed."));
|
|
6514
6802
|
console.log(
|
|
6515
|
-
|
|
6803
|
+
chalk15.dim("You can run ") + chalk15.cyan("braingrid setup cursor") + chalk15.dim(" later.")
|
|
6516
6804
|
);
|
|
6517
6805
|
}
|
|
6518
6806
|
} catch {
|
|
6519
|
-
console.log(
|
|
6807
|
+
console.log(chalk15.yellow("\u26A0\uFE0F Cursor setup encountered an error."));
|
|
6520
6808
|
console.log(
|
|
6521
|
-
|
|
6809
|
+
chalk15.dim("You can run ") + chalk15.cyan("braingrid setup cursor") + chalk15.dim(" later.")
|
|
6522
6810
|
);
|
|
6523
6811
|
}
|
|
6524
6812
|
console.log("");
|
|
@@ -6527,7 +6815,7 @@ async function handleInit(opts) {
|
|
|
6527
6815
|
}
|
|
6528
6816
|
return {
|
|
6529
6817
|
success: true,
|
|
6530
|
-
message:
|
|
6818
|
+
message: chalk15.dim(
|
|
6531
6819
|
"You can now use project-scoped commands without specifying a project ID."
|
|
6532
6820
|
),
|
|
6533
6821
|
data: localConfig
|
|
@@ -6540,205 +6828,8 @@ async function handleInit(opts) {
|
|
|
6540
6828
|
}
|
|
6541
6829
|
}
|
|
6542
6830
|
|
|
6543
|
-
// src/handlers/update.handlers.ts
|
|
6544
|
-
import chalk14 from "chalk";
|
|
6545
|
-
import axios5 from "axios";
|
|
6546
|
-
|
|
6547
|
-
// src/utils/package-manager.ts
|
|
6548
|
-
import { execSync } from "child_process";
|
|
6549
|
-
import { select as select3 } from "@inquirer/prompts";
|
|
6550
|
-
function isPackageManagerInstalled(pm) {
|
|
6551
|
-
try {
|
|
6552
|
-
execSync(`which ${pm}`, { stdio: "ignore", timeout: 2e3 });
|
|
6553
|
-
return true;
|
|
6554
|
-
} catch {
|
|
6555
|
-
return false;
|
|
6556
|
-
}
|
|
6557
|
-
}
|
|
6558
|
-
function checkGlobalInstallation(pm, packageName) {
|
|
6559
|
-
try {
|
|
6560
|
-
let command;
|
|
6561
|
-
switch (pm) {
|
|
6562
|
-
case "npm": {
|
|
6563
|
-
command = `npm list -g ${packageName} 2>&1`;
|
|
6564
|
-
break;
|
|
6565
|
-
}
|
|
6566
|
-
case "pnpm": {
|
|
6567
|
-
command = `pnpm list -g ${packageName} 2>&1`;
|
|
6568
|
-
break;
|
|
6569
|
-
}
|
|
6570
|
-
case "yarn": {
|
|
6571
|
-
command = `yarn global list 2>&1`;
|
|
6572
|
-
break;
|
|
6573
|
-
}
|
|
6574
|
-
}
|
|
6575
|
-
const output = execSync(command, {
|
|
6576
|
-
encoding: "utf-8",
|
|
6577
|
-
timeout: 5e3
|
|
6578
|
-
});
|
|
6579
|
-
if (pm === "npm" || pm === "pnpm") {
|
|
6580
|
-
return output.includes(packageName) && !output.includes("(empty)");
|
|
6581
|
-
}
|
|
6582
|
-
if (pm === "yarn") {
|
|
6583
|
-
return output.includes(packageName);
|
|
6584
|
-
}
|
|
6585
|
-
return false;
|
|
6586
|
-
} catch {
|
|
6587
|
-
return false;
|
|
6588
|
-
}
|
|
6589
|
-
}
|
|
6590
|
-
async function getPackageManagerInfo(packageName) {
|
|
6591
|
-
const packageManagers = ["npm", "pnpm", "yarn"];
|
|
6592
|
-
return packageManagers.map((pm) => {
|
|
6593
|
-
const installed = isPackageManagerInstalled(pm);
|
|
6594
|
-
return {
|
|
6595
|
-
name: pm,
|
|
6596
|
-
installed,
|
|
6597
|
-
hasPackage: installed ? checkGlobalInstallation(pm, packageName) : false
|
|
6598
|
-
};
|
|
6599
|
-
});
|
|
6600
|
-
}
|
|
6601
|
-
async function detectPackageManager(packageName) {
|
|
6602
|
-
const pmInfo = await getPackageManagerInfo(packageName);
|
|
6603
|
-
const installedWith = pmInfo.find((pm) => pm.hasPackage);
|
|
6604
|
-
if (installedWith) {
|
|
6605
|
-
return installedWith.name;
|
|
6606
|
-
}
|
|
6607
|
-
const availablePMs = pmInfo.filter((pm) => pm.installed);
|
|
6608
|
-
if (availablePMs.length === 0) {
|
|
6609
|
-
throw new Error("No package manager found. Please install npm, pnpm, or yarn.");
|
|
6610
|
-
}
|
|
6611
|
-
if (availablePMs.length === 1) {
|
|
6612
|
-
return availablePMs[0].name;
|
|
6613
|
-
}
|
|
6614
|
-
const selected = await select3({
|
|
6615
|
-
message: "Unable to detect which package manager was used. Please select one:",
|
|
6616
|
-
choices: availablePMs.map((pm) => ({
|
|
6617
|
-
name: pm.name,
|
|
6618
|
-
value: pm.name
|
|
6619
|
-
}))
|
|
6620
|
-
});
|
|
6621
|
-
return selected;
|
|
6622
|
-
}
|
|
6623
|
-
function getUpdateCommand(pm, packageName) {
|
|
6624
|
-
switch (pm) {
|
|
6625
|
-
case "npm": {
|
|
6626
|
-
return `npm install -g ${packageName}@latest`;
|
|
6627
|
-
}
|
|
6628
|
-
case "pnpm": {
|
|
6629
|
-
return `pnpm add -g ${packageName}@latest`;
|
|
6630
|
-
}
|
|
6631
|
-
case "yarn": {
|
|
6632
|
-
return `yarn global add ${packageName}@latest`;
|
|
6633
|
-
}
|
|
6634
|
-
}
|
|
6635
|
-
}
|
|
6636
|
-
function executeUpdate(pm, packageName) {
|
|
6637
|
-
const command = getUpdateCommand(pm, packageName);
|
|
6638
|
-
try {
|
|
6639
|
-
execSync(command, {
|
|
6640
|
-
stdio: "inherit",
|
|
6641
|
-
timeout: 12e4
|
|
6642
|
-
// 2 minutes timeout
|
|
6643
|
-
});
|
|
6644
|
-
} catch (error) {
|
|
6645
|
-
throw new Error(
|
|
6646
|
-
`Failed to update package: ${error instanceof Error ? error.message : String(error)}`
|
|
6647
|
-
);
|
|
6648
|
-
}
|
|
6649
|
-
}
|
|
6650
|
-
|
|
6651
|
-
// src/handlers/update.handlers.ts
|
|
6652
|
-
var PACKAGE_NAME = "@braingrid/cli";
|
|
6653
|
-
var NPM_REGISTRY_URL = `https://registry.npmjs.org/${PACKAGE_NAME}`;
|
|
6654
|
-
function getCurrentVersion() {
|
|
6655
|
-
return CLI_VERSION;
|
|
6656
|
-
}
|
|
6657
|
-
async function getLatestVersion() {
|
|
6658
|
-
try {
|
|
6659
|
-
const response = await axios5.get(NPM_REGISTRY_URL, {
|
|
6660
|
-
timeout: 1e4
|
|
6661
|
-
});
|
|
6662
|
-
return response.data["dist-tags"].latest;
|
|
6663
|
-
} catch (error) {
|
|
6664
|
-
throw new Error(`Failed to fetch latest version: ${formatError(error)}`);
|
|
6665
|
-
}
|
|
6666
|
-
}
|
|
6667
|
-
function compareVersions(v1, v2) {
|
|
6668
|
-
const v1Parts = v1.split(".").map(Number);
|
|
6669
|
-
const v2Parts = v2.split(".").map(Number);
|
|
6670
|
-
for (let i = 0; i < Math.max(v1Parts.length, v2Parts.length); i++) {
|
|
6671
|
-
const v1Part = v1Parts[i] || 0;
|
|
6672
|
-
const v2Part = v2Parts[i] || 0;
|
|
6673
|
-
if (v1Part < v2Part) return -1;
|
|
6674
|
-
if (v1Part > v2Part) return 1;
|
|
6675
|
-
}
|
|
6676
|
-
return 0;
|
|
6677
|
-
}
|
|
6678
|
-
async function handleUpdate(opts) {
|
|
6679
|
-
try {
|
|
6680
|
-
const currentVersion = getCurrentVersion();
|
|
6681
|
-
let output = chalk14.bold.cyan("\n\u{1F504} BrainGrid CLI Update\n\n");
|
|
6682
|
-
output += `${chalk14.bold("Current version:")} ${currentVersion}
|
|
6683
|
-
`;
|
|
6684
|
-
output += chalk14.dim("Checking for updates...\n");
|
|
6685
|
-
const latestVersion = await getLatestVersion();
|
|
6686
|
-
output += `${chalk14.bold("Latest version:")} ${latestVersion}
|
|
6687
|
-
|
|
6688
|
-
`;
|
|
6689
|
-
const comparison = compareVersions(currentVersion, latestVersion);
|
|
6690
|
-
if (comparison === 0) {
|
|
6691
|
-
output += chalk14.green("\u2705 You are already on the latest version!\n");
|
|
6692
|
-
return {
|
|
6693
|
-
success: true,
|
|
6694
|
-
message: output,
|
|
6695
|
-
data: { currentVersion, latestVersion, upToDate: true }
|
|
6696
|
-
};
|
|
6697
|
-
}
|
|
6698
|
-
if (comparison > 0) {
|
|
6699
|
-
output += chalk14.yellow("\u26A0\uFE0F You are on a newer version than what is published.\n");
|
|
6700
|
-
output += chalk14.dim(" This is expected if you are developing locally.\n");
|
|
6701
|
-
return {
|
|
6702
|
-
success: true,
|
|
6703
|
-
message: output,
|
|
6704
|
-
data: { currentVersion, latestVersion, upToDate: false }
|
|
6705
|
-
};
|
|
6706
|
-
}
|
|
6707
|
-
output += chalk14.yellow(`\u2B06\uFE0F Update available: ${currentVersion} \u2192 ${latestVersion}
|
|
6708
|
-
|
|
6709
|
-
`);
|
|
6710
|
-
if (opts.check) {
|
|
6711
|
-
output += chalk14.dim("Run ") + chalk14.cyan("braingrid update") + chalk14.dim(" to update\n");
|
|
6712
|
-
return {
|
|
6713
|
-
success: true,
|
|
6714
|
-
message: output,
|
|
6715
|
-
data: { currentVersion, latestVersion, upToDate: false }
|
|
6716
|
-
};
|
|
6717
|
-
}
|
|
6718
|
-
output += chalk14.dim("Detecting package manager...\n");
|
|
6719
|
-
const packageManager = await detectPackageManager(PACKAGE_NAME);
|
|
6720
|
-
output += `${chalk14.bold("Package manager:")} ${packageManager}
|
|
6721
|
-
|
|
6722
|
-
`;
|
|
6723
|
-
const updateCommand = getUpdateCommand(packageManager, PACKAGE_NAME);
|
|
6724
|
-
output += chalk14.dim("Running: ") + chalk14.cyan(updateCommand) + "\n\n";
|
|
6725
|
-
console.log(output);
|
|
6726
|
-
executeUpdate(packageManager, PACKAGE_NAME);
|
|
6727
|
-
return {
|
|
6728
|
-
success: true,
|
|
6729
|
-
message: chalk14.green("\n\u2705 Successfully updated BrainGrid CLI!\n"),
|
|
6730
|
-
data: { currentVersion, latestVersion, packageManager }
|
|
6731
|
-
};
|
|
6732
|
-
} catch (error) {
|
|
6733
|
-
return {
|
|
6734
|
-
success: false,
|
|
6735
|
-
message: formatError(error)
|
|
6736
|
-
};
|
|
6737
|
-
}
|
|
6738
|
-
}
|
|
6739
|
-
|
|
6740
6831
|
// src/handlers/completion.handlers.ts
|
|
6741
|
-
import
|
|
6832
|
+
import chalk16 from "chalk";
|
|
6742
6833
|
|
|
6743
6834
|
// src/completion/index.ts
|
|
6744
6835
|
import omelette from "omelette";
|
|
@@ -6814,7 +6905,7 @@ function setupCompletion(shell) {
|
|
|
6814
6905
|
function getUnsupportedShellError() {
|
|
6815
6906
|
return {
|
|
6816
6907
|
success: false,
|
|
6817
|
-
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")
|
|
6818
6909
|
};
|
|
6819
6910
|
}
|
|
6820
6911
|
async function handleCompletion(shellArg, opts) {
|
|
@@ -6844,33 +6935,33 @@ async function handleCompletion(shellArg, opts) {
|
|
|
6844
6935
|
const configPath = getShellConfigPath(shell);
|
|
6845
6936
|
return {
|
|
6846
6937
|
success: true,
|
|
6847
|
-
message:
|
|
6938
|
+
message: chalk16.green(`\u2705 Completion installed for ${shell}
|
|
6848
6939
|
|
|
6849
|
-
`) +
|
|
6940
|
+
`) + chalk16.dim("To activate in your current shell, run:\n") + chalk16.cyan(` source ${configPath}
|
|
6850
6941
|
|
|
6851
|
-
`) +
|
|
6942
|
+
`) + chalk16.dim("Or restart your terminal.")
|
|
6852
6943
|
};
|
|
6853
6944
|
} catch (error) {
|
|
6854
6945
|
return {
|
|
6855
6946
|
success: false,
|
|
6856
|
-
message:
|
|
6947
|
+
message: chalk16.red("\u274C Failed to install completion\n\n") + chalk16.dim("Error: ") + formatError(error)
|
|
6857
6948
|
};
|
|
6858
6949
|
}
|
|
6859
6950
|
}
|
|
6860
6951
|
try {
|
|
6861
6952
|
const script = generateCompletionScript(shell);
|
|
6862
6953
|
const configPath = getShellConfigPath(shell);
|
|
6863
|
-
const instructions =
|
|
6864
|
-
`) +
|
|
6865
|
-
`) +
|
|
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
|
|
6866
6957
|
|
|
6867
|
-
`) +
|
|
6868
|
-
`) +
|
|
6958
|
+
`) + chalk16.cyan(`# 2. Add to your shell config:
|
|
6959
|
+
`) + chalk16.cyan(` braingrid completion ${shell} >> ${configPath}
|
|
6869
6960
|
|
|
6870
|
-
`) +
|
|
6871
|
-
`) +
|
|
6961
|
+
`) + chalk16.cyan(`# 3. Source directly (temporary, current session only):
|
|
6962
|
+
`) + chalk16.cyan(` eval "$(braingrid completion ${shell})"
|
|
6872
6963
|
|
|
6873
|
-
`) +
|
|
6964
|
+
`) + chalk16.dim("# Completion script:\n\n");
|
|
6874
6965
|
return {
|
|
6875
6966
|
success: true,
|
|
6876
6967
|
message: instructions + script
|
|
@@ -6878,7 +6969,7 @@ async function handleCompletion(shellArg, opts) {
|
|
|
6878
6969
|
} catch (error) {
|
|
6879
6970
|
return {
|
|
6880
6971
|
success: false,
|
|
6881
|
-
message:
|
|
6972
|
+
message: chalk16.red("\u274C Failed to generate completion script\n\n") + chalk16.dim("Error: ") + formatError(error)
|
|
6882
6973
|
};
|
|
6883
6974
|
}
|
|
6884
6975
|
} catch (error) {
|
|
@@ -6895,6 +6986,9 @@ var packageJson = require2("../package.json");
|
|
|
6895
6986
|
initCompletion();
|
|
6896
6987
|
var program = new Command();
|
|
6897
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
|
+
});
|
|
6898
6992
|
program.command("login").description("Authenticate with BrainGrid").action(async () => {
|
|
6899
6993
|
const result = await handleLogin();
|
|
6900
6994
|
console.log(result.message);
|