@braingrid/cli 0.2.16 → 0.2.18
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 +26 -0
- package/dist/cli.js +471 -338
- 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.18" : "0.0.0-test";
|
|
426
426
|
var PRODUCTION_CONFIG = {
|
|
427
427
|
apiUrl: "https://app.braingrid.ai",
|
|
428
428
|
workosAuthUrl: "https://auth.braingrid.ai",
|
|
@@ -4518,6 +4518,21 @@ function getServices3() {
|
|
|
4518
4518
|
const taskService = new TaskService(config.apiUrl, auth);
|
|
4519
4519
|
return { taskService, auth };
|
|
4520
4520
|
}
|
|
4521
|
+
async function getCurrentTask(taskService, projectId, requirementId) {
|
|
4522
|
+
const response = await taskService.listTasks(projectId, requirementId);
|
|
4523
|
+
const inProgress = response.tasks.find((t) => t.status === "IN_PROGRESS");
|
|
4524
|
+
if (inProgress) {
|
|
4525
|
+
return { success: true, taskId: inProgress.number };
|
|
4526
|
+
}
|
|
4527
|
+
const planned = response.tasks.find((t) => t.status === "PLANNED");
|
|
4528
|
+
if (planned) {
|
|
4529
|
+
return { success: true, taskId: planned.number };
|
|
4530
|
+
}
|
|
4531
|
+
return {
|
|
4532
|
+
success: false,
|
|
4533
|
+
error: "No active task found. All tasks are completed or cancelled."
|
|
4534
|
+
};
|
|
4535
|
+
}
|
|
4521
4536
|
async function handleTaskList(opts) {
|
|
4522
4537
|
let stopSpinner = null;
|
|
4523
4538
|
try {
|
|
@@ -4679,7 +4694,19 @@ async function handleTaskShow(id, opts) {
|
|
|
4679
4694
|
};
|
|
4680
4695
|
}
|
|
4681
4696
|
const requirementId = requirementResult.requirementId;
|
|
4682
|
-
|
|
4697
|
+
let taskId;
|
|
4698
|
+
if (id) {
|
|
4699
|
+
taskId = normalizeTaskId(id);
|
|
4700
|
+
} else {
|
|
4701
|
+
const currentTask = await getCurrentTask(taskService, projectId, requirementId);
|
|
4702
|
+
if (!currentTask.success) {
|
|
4703
|
+
return {
|
|
4704
|
+
success: false,
|
|
4705
|
+
message: chalk8.red(`\u274C ${currentTask.error}`)
|
|
4706
|
+
};
|
|
4707
|
+
}
|
|
4708
|
+
taskId = currentTask.taskId;
|
|
4709
|
+
}
|
|
4683
4710
|
const config = getConfig();
|
|
4684
4711
|
stopSpinner = showSpinner("Loading task", chalk8.gray);
|
|
4685
4712
|
const task2 = await taskService.getTask(projectId, requirementId, taskId);
|
|
@@ -4799,13 +4826,13 @@ async function handleTaskUpdate(id, opts) {
|
|
|
4799
4826
|
message: chalk8.red("\u274C Not authenticated. Please run `braingrid login` first.")
|
|
4800
4827
|
};
|
|
4801
4828
|
}
|
|
4802
|
-
if (!opts
|
|
4829
|
+
if (!opts?.status && !opts?.title) {
|
|
4803
4830
|
return {
|
|
4804
4831
|
success: false,
|
|
4805
4832
|
message: chalk8.red("\u274C Please provide at least one field to update (--status or --title)")
|
|
4806
4833
|
};
|
|
4807
4834
|
}
|
|
4808
|
-
const workspace = await workspaceManager.getProject(opts
|
|
4835
|
+
const workspace = await workspaceManager.getProject(opts?.project);
|
|
4809
4836
|
if (!workspace.success) {
|
|
4810
4837
|
return {
|
|
4811
4838
|
success: false,
|
|
@@ -4813,7 +4840,7 @@ async function handleTaskUpdate(id, opts) {
|
|
|
4813
4840
|
};
|
|
4814
4841
|
}
|
|
4815
4842
|
const projectId = workspace.projectId;
|
|
4816
|
-
const requirementResult = await workspaceManager.getRequirement(opts
|
|
4843
|
+
const requirementResult = await workspaceManager.getRequirement(opts?.requirement);
|
|
4817
4844
|
if (!requirementResult.success) {
|
|
4818
4845
|
return {
|
|
4819
4846
|
success: false,
|
|
@@ -4821,12 +4848,24 @@ async function handleTaskUpdate(id, opts) {
|
|
|
4821
4848
|
};
|
|
4822
4849
|
}
|
|
4823
4850
|
const requirementId = requirementResult.requirementId;
|
|
4824
|
-
|
|
4851
|
+
let taskId;
|
|
4852
|
+
if (id) {
|
|
4853
|
+
taskId = normalizeTaskId(id);
|
|
4854
|
+
} else {
|
|
4855
|
+
const currentTask = await getCurrentTask(taskService, projectId, requirementId);
|
|
4856
|
+
if (!currentTask.success) {
|
|
4857
|
+
return {
|
|
4858
|
+
success: false,
|
|
4859
|
+
message: chalk8.red(`\u274C ${currentTask.error}`)
|
|
4860
|
+
};
|
|
4861
|
+
}
|
|
4862
|
+
taskId = currentTask.taskId;
|
|
4863
|
+
}
|
|
4825
4864
|
const config = getConfig();
|
|
4826
4865
|
stopSpinner = showSpinner("Updating task", chalk8.gray);
|
|
4827
4866
|
const task2 = await taskService.updateTask(projectId, requirementId, taskId, {
|
|
4828
|
-
status: opts
|
|
4829
|
-
title: opts
|
|
4867
|
+
status: opts?.status,
|
|
4868
|
+
title: opts?.title
|
|
4830
4869
|
});
|
|
4831
4870
|
stopSpinner();
|
|
4832
4871
|
stopSpinner = null;
|
|
@@ -4835,7 +4874,7 @@ async function handleTaskUpdate(id, opts) {
|
|
|
4835
4874
|
successMessage: `Updated task ${task2.number}`,
|
|
4836
4875
|
apiUrl: config.apiUrl,
|
|
4837
4876
|
projectShortId: projectId,
|
|
4838
|
-
requirementShortId: opts
|
|
4877
|
+
requirementShortId: opts?.requirement || requirementId,
|
|
4839
4878
|
requirementId
|
|
4840
4879
|
});
|
|
4841
4880
|
return {
|
|
@@ -5187,8 +5226,8 @@ async function handleStatus() {
|
|
|
5187
5226
|
}
|
|
5188
5227
|
|
|
5189
5228
|
// src/handlers/init.handlers.ts
|
|
5190
|
-
import
|
|
5191
|
-
import { confirm, select as
|
|
5229
|
+
import chalk15 from "chalk";
|
|
5230
|
+
import { confirm, select as select3, input } from "@inquirer/prompts";
|
|
5192
5231
|
|
|
5193
5232
|
// src/services/internal/github-service.ts
|
|
5194
5233
|
var GitHubService = class {
|
|
@@ -5455,9 +5494,277 @@ function getManualInstallInstructions() {
|
|
|
5455
5494
|
}
|
|
5456
5495
|
}
|
|
5457
5496
|
|
|
5458
|
-
// src/handlers/
|
|
5497
|
+
// src/handlers/update.handlers.ts
|
|
5459
5498
|
import chalk12 from "chalk";
|
|
5499
|
+
|
|
5500
|
+
// src/utils/package-manager.ts
|
|
5501
|
+
import { execSync } from "child_process";
|
|
5460
5502
|
import { select } from "@inquirer/prompts";
|
|
5503
|
+
function isPackageManagerInstalled(pm) {
|
|
5504
|
+
try {
|
|
5505
|
+
execSync(`which ${pm}`, { stdio: "ignore", timeout: 2e3 });
|
|
5506
|
+
return true;
|
|
5507
|
+
} catch {
|
|
5508
|
+
return false;
|
|
5509
|
+
}
|
|
5510
|
+
}
|
|
5511
|
+
function checkGlobalInstallation(pm, packageName) {
|
|
5512
|
+
try {
|
|
5513
|
+
let command;
|
|
5514
|
+
switch (pm) {
|
|
5515
|
+
case "npm": {
|
|
5516
|
+
command = `npm list -g ${packageName} 2>&1`;
|
|
5517
|
+
break;
|
|
5518
|
+
}
|
|
5519
|
+
case "pnpm": {
|
|
5520
|
+
command = `pnpm list -g ${packageName} 2>&1`;
|
|
5521
|
+
break;
|
|
5522
|
+
}
|
|
5523
|
+
case "yarn": {
|
|
5524
|
+
command = `yarn global list 2>&1`;
|
|
5525
|
+
break;
|
|
5526
|
+
}
|
|
5527
|
+
}
|
|
5528
|
+
const output = execSync(command, {
|
|
5529
|
+
encoding: "utf-8",
|
|
5530
|
+
timeout: 5e3
|
|
5531
|
+
});
|
|
5532
|
+
if (pm === "npm" || pm === "pnpm") {
|
|
5533
|
+
return output.includes(packageName) && !output.includes("(empty)");
|
|
5534
|
+
}
|
|
5535
|
+
if (pm === "yarn") {
|
|
5536
|
+
return output.includes(packageName);
|
|
5537
|
+
}
|
|
5538
|
+
return false;
|
|
5539
|
+
} catch {
|
|
5540
|
+
return false;
|
|
5541
|
+
}
|
|
5542
|
+
}
|
|
5543
|
+
async function getPackageManagerInfo(packageName) {
|
|
5544
|
+
const packageManagers = ["npm", "pnpm", "yarn"];
|
|
5545
|
+
return packageManagers.map((pm) => {
|
|
5546
|
+
const installed = isPackageManagerInstalled(pm);
|
|
5547
|
+
return {
|
|
5548
|
+
name: pm,
|
|
5549
|
+
installed,
|
|
5550
|
+
hasPackage: installed ? checkGlobalInstallation(pm, packageName) : false
|
|
5551
|
+
};
|
|
5552
|
+
});
|
|
5553
|
+
}
|
|
5554
|
+
async function detectPackageManager(packageName) {
|
|
5555
|
+
const pmInfo = await getPackageManagerInfo(packageName);
|
|
5556
|
+
const installedWith = pmInfo.find((pm) => pm.hasPackage);
|
|
5557
|
+
if (installedWith) {
|
|
5558
|
+
return installedWith.name;
|
|
5559
|
+
}
|
|
5560
|
+
const availablePMs = pmInfo.filter((pm) => pm.installed);
|
|
5561
|
+
if (availablePMs.length === 0) {
|
|
5562
|
+
throw new Error("No package manager found. Please install npm, pnpm, or yarn.");
|
|
5563
|
+
}
|
|
5564
|
+
if (availablePMs.length === 1) {
|
|
5565
|
+
return availablePMs[0].name;
|
|
5566
|
+
}
|
|
5567
|
+
const selected = await select({
|
|
5568
|
+
message: "Unable to detect which package manager was used. Please select one:",
|
|
5569
|
+
choices: availablePMs.map((pm) => ({
|
|
5570
|
+
name: pm.name,
|
|
5571
|
+
value: pm.name
|
|
5572
|
+
}))
|
|
5573
|
+
});
|
|
5574
|
+
return selected;
|
|
5575
|
+
}
|
|
5576
|
+
function getUpdateCommand(pm, packageName) {
|
|
5577
|
+
switch (pm) {
|
|
5578
|
+
case "npm": {
|
|
5579
|
+
return `npm install -g ${packageName}@latest`;
|
|
5580
|
+
}
|
|
5581
|
+
case "pnpm": {
|
|
5582
|
+
return `pnpm add -g ${packageName}@latest`;
|
|
5583
|
+
}
|
|
5584
|
+
case "yarn": {
|
|
5585
|
+
return `yarn global add ${packageName}@latest`;
|
|
5586
|
+
}
|
|
5587
|
+
}
|
|
5588
|
+
}
|
|
5589
|
+
function executeUpdate(pm, packageName) {
|
|
5590
|
+
const command = getUpdateCommand(pm, packageName);
|
|
5591
|
+
try {
|
|
5592
|
+
execSync(command, {
|
|
5593
|
+
stdio: "inherit",
|
|
5594
|
+
timeout: 12e4
|
|
5595
|
+
// 2 minutes timeout
|
|
5596
|
+
});
|
|
5597
|
+
} catch (error) {
|
|
5598
|
+
throw new Error(
|
|
5599
|
+
`Failed to update package: ${error instanceof Error ? error.message : String(error)}`
|
|
5600
|
+
);
|
|
5601
|
+
}
|
|
5602
|
+
}
|
|
5603
|
+
|
|
5604
|
+
// src/utils/version.ts
|
|
5605
|
+
import axios5 from "axios";
|
|
5606
|
+
var PACKAGE_NAME = "@braingrid/cli";
|
|
5607
|
+
var NPM_REGISTRY_URL = `https://registry.npmjs.org/${PACKAGE_NAME}`;
|
|
5608
|
+
function getCurrentVersion() {
|
|
5609
|
+
return CLI_VERSION;
|
|
5610
|
+
}
|
|
5611
|
+
async function getLatestVersion(timeout = 1e4) {
|
|
5612
|
+
try {
|
|
5613
|
+
const response = await axios5.get(NPM_REGISTRY_URL, {
|
|
5614
|
+
timeout
|
|
5615
|
+
});
|
|
5616
|
+
return response.data["dist-tags"].latest;
|
|
5617
|
+
} catch (error) {
|
|
5618
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
5619
|
+
throw new Error(`Failed to fetch latest version: ${message}`);
|
|
5620
|
+
}
|
|
5621
|
+
}
|
|
5622
|
+
function compareVersions(v1, v2) {
|
|
5623
|
+
const v1Parts = v1.split(".").map(Number);
|
|
5624
|
+
const v2Parts = v2.split(".").map(Number);
|
|
5625
|
+
for (let i = 0; i < Math.max(v1Parts.length, v2Parts.length); i++) {
|
|
5626
|
+
const v1Part = v1Parts[i] || 0;
|
|
5627
|
+
const v2Part = v2Parts[i] || 0;
|
|
5628
|
+
if (v1Part < v2Part) return -1;
|
|
5629
|
+
if (v1Part > v2Part) return 1;
|
|
5630
|
+
}
|
|
5631
|
+
return 0;
|
|
5632
|
+
}
|
|
5633
|
+
|
|
5634
|
+
// src/handlers/update.handlers.ts
|
|
5635
|
+
async function handleUpdate(opts) {
|
|
5636
|
+
try {
|
|
5637
|
+
const currentVersion = getCurrentVersion();
|
|
5638
|
+
let output = chalk12.bold.cyan("\n\u{1F504} BrainGrid CLI Update\n\n");
|
|
5639
|
+
output += `${chalk12.bold("Current version:")} ${currentVersion}
|
|
5640
|
+
`;
|
|
5641
|
+
output += chalk12.dim("Checking for updates...\n");
|
|
5642
|
+
const latestVersion = await getLatestVersion();
|
|
5643
|
+
output += `${chalk12.bold("Latest version:")} ${latestVersion}
|
|
5644
|
+
|
|
5645
|
+
`;
|
|
5646
|
+
const comparison = compareVersions(currentVersion, latestVersion);
|
|
5647
|
+
if (comparison === 0) {
|
|
5648
|
+
output += chalk12.green("\u2705 You are already on the latest version!\n");
|
|
5649
|
+
return {
|
|
5650
|
+
success: true,
|
|
5651
|
+
message: output,
|
|
5652
|
+
data: { currentVersion, latestVersion, upToDate: true }
|
|
5653
|
+
};
|
|
5654
|
+
}
|
|
5655
|
+
if (comparison > 0) {
|
|
5656
|
+
output += chalk12.yellow("\u26A0\uFE0F You are on a newer version than what is published.\n");
|
|
5657
|
+
output += chalk12.dim(" This is expected if you are developing locally.\n");
|
|
5658
|
+
return {
|
|
5659
|
+
success: true,
|
|
5660
|
+
message: output,
|
|
5661
|
+
data: { currentVersion, latestVersion, upToDate: false }
|
|
5662
|
+
};
|
|
5663
|
+
}
|
|
5664
|
+
output += chalk12.yellow(`\u2B06\uFE0F Update available: ${currentVersion} \u2192 ${latestVersion}
|
|
5665
|
+
|
|
5666
|
+
`);
|
|
5667
|
+
if (opts.check) {
|
|
5668
|
+
output += chalk12.dim("Run ") + chalk12.cyan("braingrid update") + chalk12.dim(" to update\n");
|
|
5669
|
+
return {
|
|
5670
|
+
success: true,
|
|
5671
|
+
message: output,
|
|
5672
|
+
data: { currentVersion, latestVersion, upToDate: false }
|
|
5673
|
+
};
|
|
5674
|
+
}
|
|
5675
|
+
output += chalk12.dim("Detecting package manager...\n");
|
|
5676
|
+
const packageManager = await detectPackageManager(PACKAGE_NAME);
|
|
5677
|
+
output += `${chalk12.bold("Package manager:")} ${packageManager}
|
|
5678
|
+
|
|
5679
|
+
`;
|
|
5680
|
+
const updateCommand = getUpdateCommand(packageManager, PACKAGE_NAME);
|
|
5681
|
+
output += chalk12.dim("Running: ") + chalk12.cyan(updateCommand) + "\n\n";
|
|
5682
|
+
console.log(output);
|
|
5683
|
+
executeUpdate(packageManager, PACKAGE_NAME);
|
|
5684
|
+
return {
|
|
5685
|
+
success: true,
|
|
5686
|
+
message: chalk12.green("\n\u2705 Successfully updated BrainGrid CLI!\n"),
|
|
5687
|
+
data: { currentVersion, latestVersion, packageManager }
|
|
5688
|
+
};
|
|
5689
|
+
} catch (error) {
|
|
5690
|
+
return {
|
|
5691
|
+
success: false,
|
|
5692
|
+
message: formatError(error)
|
|
5693
|
+
};
|
|
5694
|
+
}
|
|
5695
|
+
}
|
|
5696
|
+
|
|
5697
|
+
// src/utils/update-checker.ts
|
|
5698
|
+
import chalk13 from "chalk";
|
|
5699
|
+
var CACHE_TTL_MS = 12 * 60 * 60 * 1e3;
|
|
5700
|
+
var CACHE_SERVICE = "braingrid-cli";
|
|
5701
|
+
var CACHE_ACCOUNT = "update-cache";
|
|
5702
|
+
async function getCache() {
|
|
5703
|
+
try {
|
|
5704
|
+
const cached = await credentialStore.getPassword(CACHE_SERVICE, CACHE_ACCOUNT);
|
|
5705
|
+
if (!cached) return null;
|
|
5706
|
+
return JSON.parse(cached);
|
|
5707
|
+
} catch {
|
|
5708
|
+
return null;
|
|
5709
|
+
}
|
|
5710
|
+
}
|
|
5711
|
+
async function setCache(cache) {
|
|
5712
|
+
try {
|
|
5713
|
+
await credentialStore.setPassword(CACHE_SERVICE, CACHE_ACCOUNT, JSON.stringify(cache));
|
|
5714
|
+
} catch {
|
|
5715
|
+
}
|
|
5716
|
+
}
|
|
5717
|
+
function isCacheValid(cache) {
|
|
5718
|
+
const now = Date.now();
|
|
5719
|
+
return now - cache.checkedAt < CACHE_TTL_MS;
|
|
5720
|
+
}
|
|
5721
|
+
async function getLatestVersionCached() {
|
|
5722
|
+
const cache = await getCache();
|
|
5723
|
+
if (cache && isCacheValid(cache)) {
|
|
5724
|
+
return cache.latestVersion;
|
|
5725
|
+
}
|
|
5726
|
+
try {
|
|
5727
|
+
const latestVersion = await getLatestVersion(5e3);
|
|
5728
|
+
await setCache({
|
|
5729
|
+
latestVersion,
|
|
5730
|
+
checkedAt: Date.now()
|
|
5731
|
+
});
|
|
5732
|
+
return latestVersion;
|
|
5733
|
+
} catch {
|
|
5734
|
+
return cache?.latestVersion ?? null;
|
|
5735
|
+
}
|
|
5736
|
+
}
|
|
5737
|
+
async function isUpdateAvailable() {
|
|
5738
|
+
const currentVersion = getCurrentVersion();
|
|
5739
|
+
const latestVersion = await getLatestVersionCached();
|
|
5740
|
+
if (!latestVersion) {
|
|
5741
|
+
return { available: false, currentVersion, latestVersion: null };
|
|
5742
|
+
}
|
|
5743
|
+
const comparison = compareVersions(currentVersion, latestVersion);
|
|
5744
|
+
return {
|
|
5745
|
+
available: comparison < 0,
|
|
5746
|
+
// Update available if current < latest
|
|
5747
|
+
currentVersion,
|
|
5748
|
+
latestVersion
|
|
5749
|
+
};
|
|
5750
|
+
}
|
|
5751
|
+
function getUpdateCommand2() {
|
|
5752
|
+
return `npm install -g ${PACKAGE_NAME}`;
|
|
5753
|
+
}
|
|
5754
|
+
async function checkAndShowUpdateWarning() {
|
|
5755
|
+
try {
|
|
5756
|
+
const { available, currentVersion, latestVersion } = await isUpdateAvailable();
|
|
5757
|
+
if (available && latestVersion) {
|
|
5758
|
+
const warning = "\n" + chalk13.yellow(`\u26A0\uFE0F Update available: ${currentVersion} \u2192 ${latestVersion}`) + "\n" + chalk13.dim(` Run \`${getUpdateCommand2()}\` to update`) + "\n";
|
|
5759
|
+
console.log(warning);
|
|
5760
|
+
}
|
|
5761
|
+
} catch {
|
|
5762
|
+
}
|
|
5763
|
+
}
|
|
5764
|
+
|
|
5765
|
+
// src/handlers/setup.handlers.ts
|
|
5766
|
+
import chalk14 from "chalk";
|
|
5767
|
+
import { select as select2 } from "@inquirer/prompts";
|
|
5461
5768
|
import * as path4 from "path";
|
|
5462
5769
|
import * as fs4 from "fs/promises";
|
|
5463
5770
|
|
|
@@ -5674,7 +5981,7 @@ async function checkPrerequisites() {
|
|
|
5674
5981
|
} catch {
|
|
5675
5982
|
return {
|
|
5676
5983
|
success: false,
|
|
5677
|
-
message:
|
|
5984
|
+
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
5985
|
};
|
|
5679
5986
|
}
|
|
5680
5987
|
try {
|
|
@@ -5682,7 +5989,7 @@ async function checkPrerequisites() {
|
|
|
5682
5989
|
} catch {
|
|
5683
5990
|
return {
|
|
5684
5991
|
success: false,
|
|
5685
|
-
message:
|
|
5992
|
+
message: chalk14.red("\u274C Not authenticated with GitHub CLI.\n\n") + chalk14.dim("Please run: ") + chalk14.cyan("gh auth login")
|
|
5686
5993
|
};
|
|
5687
5994
|
}
|
|
5688
5995
|
return null;
|
|
@@ -5709,7 +6016,7 @@ async function getFileList(sourcePaths, targetPaths) {
|
|
|
5709
6016
|
}
|
|
5710
6017
|
} catch (error) {
|
|
5711
6018
|
console.warn(
|
|
5712
|
-
|
|
6019
|
+
chalk14.yellow(`\u26A0\uFE0F Could not list directory: ${sourceDir}`),
|
|
5713
6020
|
error instanceof Error ? error.message : String(error)
|
|
5714
6021
|
);
|
|
5715
6022
|
}
|
|
@@ -5720,28 +6027,28 @@ async function getFileList(sourcePaths, targetPaths) {
|
|
|
5720
6027
|
return operations;
|
|
5721
6028
|
}
|
|
5722
6029
|
function displayInstallationPlan(operations, injectionFile) {
|
|
5723
|
-
console.log(
|
|
5724
|
-
console.log(
|
|
5725
|
-
console.log(
|
|
6030
|
+
console.log(chalk14.bold("\n\u{1F4CB} Installation Plan:\n"));
|
|
6031
|
+
console.log(chalk14.cyan(" Content Injection:"));
|
|
6032
|
+
console.log(chalk14.dim(` ${injectionFile}`));
|
|
5726
6033
|
const newFiles = operations.filter((op) => !op.exists);
|
|
5727
6034
|
const existingFiles = operations.filter((op) => op.exists);
|
|
5728
6035
|
if (newFiles.length > 0) {
|
|
5729
|
-
console.log(
|
|
6036
|
+
console.log(chalk14.cyan("\n New Files:"));
|
|
5730
6037
|
for (const op of newFiles) {
|
|
5731
|
-
console.log(
|
|
6038
|
+
console.log(chalk14.dim(` ${op.targetPath}`));
|
|
5732
6039
|
}
|
|
5733
6040
|
}
|
|
5734
6041
|
if (existingFiles.length > 0) {
|
|
5735
|
-
console.log(
|
|
6042
|
+
console.log(chalk14.yellow("\n Existing Files (will prompt):"));
|
|
5736
6043
|
for (const op of existingFiles) {
|
|
5737
|
-
console.log(
|
|
6044
|
+
console.log(chalk14.dim(` ${op.targetPath}`));
|
|
5738
6045
|
}
|
|
5739
6046
|
}
|
|
5740
6047
|
console.log("");
|
|
5741
6048
|
}
|
|
5742
6049
|
async function promptForConflict(filePath) {
|
|
5743
|
-
const answer = await
|
|
5744
|
-
message:
|
|
6050
|
+
const answer = await select2({
|
|
6051
|
+
message: chalk14.yellow(`File exists: ${filePath}`),
|
|
5745
6052
|
choices: [
|
|
5746
6053
|
{ name: "[O]verwrite - Replace this file", value: "overwrite" },
|
|
5747
6054
|
{ name: "[S]kip - Keep existing file", value: "skip" },
|
|
@@ -5772,7 +6079,7 @@ async function installFiles(operations, force) {
|
|
|
5772
6079
|
installed++;
|
|
5773
6080
|
} catch (error) {
|
|
5774
6081
|
console.error(
|
|
5775
|
-
|
|
6082
|
+
chalk14.red(`Failed to copy ${operation.targetPath}:`),
|
|
5776
6083
|
error instanceof Error ? error.message : String(error)
|
|
5777
6084
|
);
|
|
5778
6085
|
skipped++;
|
|
@@ -5786,7 +6093,7 @@ async function _handleSetup(config, opts) {
|
|
|
5786
6093
|
if (prerequisiteError) {
|
|
5787
6094
|
return prerequisiteError;
|
|
5788
6095
|
}
|
|
5789
|
-
console.log(
|
|
6096
|
+
console.log(chalk14.bold(`\u{1F680} Setting up ${config.name} integration...
|
|
5790
6097
|
`));
|
|
5791
6098
|
const operations = await getFileList(config.sourceDirs, config.targetDirs);
|
|
5792
6099
|
const injectionFileExists = await fileExists(config.injection.targetFile);
|
|
@@ -5803,7 +6110,7 @@ async function _handleSetup(config, opts) {
|
|
|
5803
6110
|
if (opts.dryRun) {
|
|
5804
6111
|
return {
|
|
5805
6112
|
success: true,
|
|
5806
|
-
message:
|
|
6113
|
+
message: chalk14.green("\u2705 Dry-run complete. No files were modified.\n\n") + chalk14.dim(`Would install ${operations.length} files.`)
|
|
5807
6114
|
};
|
|
5808
6115
|
}
|
|
5809
6116
|
const copyOps = operations.filter((op) => op.type === "copy");
|
|
@@ -5811,7 +6118,7 @@ async function _handleSetup(config, opts) {
|
|
|
5811
6118
|
if (result.cancelled) {
|
|
5812
6119
|
return {
|
|
5813
6120
|
success: false,
|
|
5814
|
-
message:
|
|
6121
|
+
message: chalk14.yellow("\u26A0\uFE0F Installation cancelled.\n\n") + chalk14.dim(`Installed: ${result.installed}, Skipped: ${result.skipped}`),
|
|
5815
6122
|
code: "CANCELLED"
|
|
5816
6123
|
};
|
|
5817
6124
|
}
|
|
@@ -5820,7 +6127,7 @@ async function _handleSetup(config, opts) {
|
|
|
5820
6127
|
await injectContentIntoFile(config.injection.targetFile, content);
|
|
5821
6128
|
} catch (error) {
|
|
5822
6129
|
console.error(
|
|
5823
|
-
|
|
6130
|
+
chalk14.red(`Failed to inject content into ${config.injection.targetFile}:`),
|
|
5824
6131
|
error instanceof Error ? error.message : String(error)
|
|
5825
6132
|
);
|
|
5826
6133
|
}
|
|
@@ -5833,27 +6140,27 @@ async function _handleSetup(config, opts) {
|
|
|
5833
6140
|
statusLineInstalled = true;
|
|
5834
6141
|
} catch (error) {
|
|
5835
6142
|
console.error(
|
|
5836
|
-
|
|
6143
|
+
chalk14.yellow("\u26A0\uFE0F Failed to install status line script:"),
|
|
5837
6144
|
error instanceof Error ? error.message : String(error)
|
|
5838
6145
|
);
|
|
5839
6146
|
}
|
|
5840
6147
|
}
|
|
5841
|
-
const statusLineMessage = statusLineInstalled ?
|
|
6148
|
+
const statusLineMessage = statusLineInstalled ? chalk14.dim(" Status line: .claude/statusline.sh\n") : "";
|
|
5842
6149
|
return {
|
|
5843
6150
|
success: true,
|
|
5844
|
-
message:
|
|
6151
|
+
message: chalk14.green(`\u2705 ${config.name} integration installed successfully!
|
|
5845
6152
|
|
|
5846
|
-
`) +
|
|
5847
|
-
`) + statusLineMessage +
|
|
6153
|
+
`) + chalk14.dim("Files installed:\n") + chalk14.dim(` Commands: ${result.installed} files
|
|
6154
|
+
`) + statusLineMessage + chalk14.dim(` Content injected into: ${config.injection.targetFile}
|
|
5848
6155
|
|
|
5849
|
-
`) +
|
|
5850
|
-
`) +
|
|
6156
|
+
`) + chalk14.dim("Next steps:\n") + chalk14.dim(" 1. Review the integration files\n") + chalk14.dim(` 2. Open ${config.name}
|
|
6157
|
+
`) + chalk14.dim(" 3. Try the /specify or /breakdown commands\n") + chalk14.dim(" 4. Learn more: ") + chalk14.cyan(config.docsUrl)
|
|
5851
6158
|
};
|
|
5852
6159
|
} catch (error) {
|
|
5853
6160
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
5854
6161
|
return {
|
|
5855
6162
|
success: false,
|
|
5856
|
-
message:
|
|
6163
|
+
message: chalk14.red(`\u274C Setup failed: ${errorMessage}`)
|
|
5857
6164
|
};
|
|
5858
6165
|
}
|
|
5859
6166
|
}
|
|
@@ -5967,12 +6274,12 @@ function getServices4() {
|
|
|
5967
6274
|
function promptToAddOrganization(owner, webUrl) {
|
|
5968
6275
|
return {
|
|
5969
6276
|
success: false,
|
|
5970
|
-
message:
|
|
6277
|
+
message: chalk15.yellow("\u26A0\uFE0F No projects found for this repository.\n\n") + chalk15.dim(`Repository: ${owner}/*
|
|
5971
6278
|
|
|
5972
|
-
`) +
|
|
6279
|
+
`) + chalk15.dim(`You have GitHub connected, but not for the "${owner}" organization.
|
|
5973
6280
|
|
|
5974
|
-
`) +
|
|
5975
|
-
`) +
|
|
6281
|
+
`) + 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}"
|
|
6282
|
+
`) + chalk15.dim(" 4. Run ") + chalk15.cyan("braingrid init") + chalk15.dim(" again")
|
|
5976
6283
|
};
|
|
5977
6284
|
}
|
|
5978
6285
|
async function promptToCreateProject(gitInfo, projectService, repositoryService) {
|
|
@@ -5980,20 +6287,20 @@ async function promptToCreateProject(gitInfo, projectService, repositoryService)
|
|
|
5980
6287
|
if (!gitInfo.owner || !gitInfo.name) {
|
|
5981
6288
|
return {
|
|
5982
6289
|
success: false,
|
|
5983
|
-
message:
|
|
6290
|
+
message: chalk15.red("\u274C Repository information is incomplete")
|
|
5984
6291
|
};
|
|
5985
6292
|
}
|
|
5986
6293
|
const repositoryId = await getRepositoryId(repositoryService, gitInfo.owner, gitInfo.name);
|
|
5987
6294
|
if (!repositoryId) {
|
|
5988
6295
|
return {
|
|
5989
6296
|
success: false,
|
|
5990
|
-
message:
|
|
6297
|
+
message: chalk15.yellow("\u26A0\uFE0F Repository accessible but could not retrieve details.\n\n") + chalk15.dim(`Repository: ${gitInfo.owner}/${gitInfo.name}
|
|
5991
6298
|
|
|
5992
|
-
`) +
|
|
6299
|
+
`) + chalk15.dim("Please try again or create a project manually at: ") + chalk15.cyan(webUrl)
|
|
5993
6300
|
};
|
|
5994
6301
|
}
|
|
5995
6302
|
console.log(
|
|
5996
|
-
|
|
6303
|
+
chalk15.yellow("\u26A0\uFE0F Repository accessible but no project exists.\n\n") + chalk15.dim(`Repository: ${gitInfo.owner}/${gitInfo.name}
|
|
5997
6304
|
`)
|
|
5998
6305
|
);
|
|
5999
6306
|
const shouldCreate = await confirm({
|
|
@@ -6003,7 +6310,7 @@ async function promptToCreateProject(gitInfo, projectService, repositoryService)
|
|
|
6003
6310
|
if (!shouldCreate) {
|
|
6004
6311
|
return {
|
|
6005
6312
|
success: false,
|
|
6006
|
-
message:
|
|
6313
|
+
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
6314
|
`braingrid project create --name "${gitInfo.name}" --repositories "${gitInfo.owner}/${gitInfo.name}"`
|
|
6008
6315
|
)
|
|
6009
6316
|
};
|
|
@@ -6014,9 +6321,9 @@ async function promptToCreateProject(gitInfo, projectService, repositoryService)
|
|
|
6014
6321
|
description: `Project for ${gitInfo.owner}/${gitInfo.name}`,
|
|
6015
6322
|
repository_id: repositoryId
|
|
6016
6323
|
});
|
|
6017
|
-
console.log(
|
|
6324
|
+
console.log(chalk15.green(`
|
|
6018
6325
|
\u2705 Created project ${project2.short_id}: ${project2.name}`));
|
|
6019
|
-
console.log(
|
|
6326
|
+
console.log(chalk15.green(`\u2705 Linked repository ${gitInfo.owner}/${gitInfo.name}
|
|
6020
6327
|
`));
|
|
6021
6328
|
return { success: true, message: "", data: project2 };
|
|
6022
6329
|
} catch (error) {
|
|
@@ -6030,18 +6337,18 @@ async function promptToGrantRepositoryAccess(gitInfo, webUrl, repositoryService,
|
|
|
6030
6337
|
if (!gitInfo.owner || !gitInfo.name) {
|
|
6031
6338
|
return {
|
|
6032
6339
|
success: false,
|
|
6033
|
-
message:
|
|
6340
|
+
message: chalk15.red("\u274C Repository information is incomplete")
|
|
6034
6341
|
};
|
|
6035
6342
|
}
|
|
6036
6343
|
const owner = gitInfo.owner;
|
|
6037
6344
|
const name = gitInfo.name;
|
|
6038
6345
|
console.log(
|
|
6039
|
-
|
|
6346
|
+
chalk15.yellow("\u26A0\uFE0F Repository found but BrainGrid needs access.\n\n") + chalk15.dim(`Repository: ${owner}/${name}
|
|
6040
6347
|
|
|
6041
|
-
`) +
|
|
6348
|
+
`) + chalk15.dim("Please grant BrainGrid access to this repository:\n") + chalk15.dim(" 1. Visit: ") + chalk15.cyan(`${webUrl}/integrations`) + chalk15.dim("\n") + chalk15.dim(
|
|
6042
6349
|
` 2. Click on your "${owner}" installation "Add/Remove" to grant BrainGrid access to your repository
|
|
6043
6350
|
`
|
|
6044
|
-
) +
|
|
6351
|
+
) + chalk15.dim(` 3. Select "${name}" and save
|
|
6045
6352
|
|
|
6046
6353
|
`)
|
|
6047
6354
|
);
|
|
@@ -6054,10 +6361,10 @@ async function promptToGrantRepositoryAccess(gitInfo, webUrl, repositoryService,
|
|
|
6054
6361
|
if (!accessGranted) {
|
|
6055
6362
|
return {
|
|
6056
6363
|
success: false,
|
|
6057
|
-
message:
|
|
6364
|
+
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
6365
|
};
|
|
6059
6366
|
}
|
|
6060
|
-
console.log(
|
|
6367
|
+
console.log(chalk15.green("\u2705 Repository access granted!\n"));
|
|
6061
6368
|
return promptToCreateProject(gitInfo, projectService, repositoryService);
|
|
6062
6369
|
}
|
|
6063
6370
|
async function handleNoProjectForRepository(owner, name, gitInfo, githubService, repositoryService, projectService, config) {
|
|
@@ -6072,9 +6379,9 @@ async function handleNoProjectForRepository(owner, name, gitInfo, githubService,
|
|
|
6072
6379
|
if (allInstallations.length === 0) {
|
|
6073
6380
|
return {
|
|
6074
6381
|
success: false,
|
|
6075
|
-
message:
|
|
6382
|
+
message: chalk15.yellow("\u26A0\uFE0F No projects found for this repository.\n\n") + chalk15.dim(`Repository: ${owner}/${name}
|
|
6076
6383
|
|
|
6077
|
-
`) +
|
|
6384
|
+
`) + 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
6385
|
};
|
|
6079
6386
|
}
|
|
6080
6387
|
const ownerInstallation = findInstallationForOwner(owner, allInstallations);
|
|
@@ -6090,28 +6397,28 @@ async function handleNoProjectForRepository(owner, name, gitInfo, githubService,
|
|
|
6090
6397
|
function showSetupInstructions(scenario) {
|
|
6091
6398
|
let message = "";
|
|
6092
6399
|
if (scenario === "no-git") {
|
|
6093
|
-
message +=
|
|
6094
|
-
message +=
|
|
6095
|
-
message +=
|
|
6400
|
+
message += chalk15.dim("To initialize BrainGrid locally:\n\n");
|
|
6401
|
+
message += chalk15.dim(" 1. Initialize git:\n");
|
|
6402
|
+
message += chalk15.cyan(" git init\n\n");
|
|
6096
6403
|
} else {
|
|
6097
|
-
message +=
|
|
6404
|
+
message += chalk15.dim("To connect to GitHub:\n\n");
|
|
6098
6405
|
}
|
|
6099
|
-
message +=
|
|
6100
|
-
message +=
|
|
6101
|
-
message +=
|
|
6102
|
-
message +=
|
|
6406
|
+
message += chalk15.dim(" 2. Create GitHub repository:\n");
|
|
6407
|
+
message += chalk15.dim(" \u2022 Install GitHub CLI: ") + chalk15.cyan("https://cli.github.com\n");
|
|
6408
|
+
message += chalk15.dim(" Then: ") + chalk15.cyan("gh repo create --private --source=.\n");
|
|
6409
|
+
message += chalk15.dim(" \u2022 Or manually: ") + chalk15.cyan("https://github.com/new\n\n");
|
|
6103
6410
|
if (scenario === "no-git") {
|
|
6104
|
-
message +=
|
|
6411
|
+
message += chalk15.dim(" 3. Run: ") + chalk15.cyan("braingrid init\n\n");
|
|
6105
6412
|
} else {
|
|
6106
|
-
message +=
|
|
6107
|
-
message +=
|
|
6108
|
-
message +=
|
|
6109
|
-
}
|
|
6110
|
-
message +=
|
|
6111
|
-
message +=
|
|
6112
|
-
message +=
|
|
6113
|
-
message +=
|
|
6114
|
-
message +=
|
|
6413
|
+
message += chalk15.dim(" 3. Add remote and run init:\n");
|
|
6414
|
+
message += chalk15.cyan(" git remote add origin <url>\n");
|
|
6415
|
+
message += chalk15.cyan(" braingrid init\n\n");
|
|
6416
|
+
}
|
|
6417
|
+
message += chalk15.bold("Or use BrainGrid without local initialization:\n\n");
|
|
6418
|
+
message += chalk15.dim(" All commands support the --project flag:\n");
|
|
6419
|
+
message += chalk15.cyan(" braingrid requirement list --project PROJ-123\n");
|
|
6420
|
+
message += chalk15.cyan(' braingrid task create --project PROJ-123 --title "Task"\n\n');
|
|
6421
|
+
message += chalk15.dim(" Note: Without local init, you must specify --project for each command.") + "\n";
|
|
6115
6422
|
return message;
|
|
6116
6423
|
}
|
|
6117
6424
|
async function handleNoGitRepository() {
|
|
@@ -6127,12 +6434,12 @@ async function handleNoGitRepository() {
|
|
|
6127
6434
|
if (!gitInitSuccess) {
|
|
6128
6435
|
return {
|
|
6129
6436
|
success: false,
|
|
6130
|
-
message:
|
|
6437
|
+
message: chalk15.red("\u274C Failed to initialize git repository")
|
|
6131
6438
|
};
|
|
6132
6439
|
}
|
|
6133
|
-
console.log(
|
|
6440
|
+
console.log(chalk15.green("\u2705 Initialized git repository"));
|
|
6134
6441
|
const dirName = getCurrentDirectoryName();
|
|
6135
|
-
const isPrivate = await
|
|
6442
|
+
const isPrivate = await select3({
|
|
6136
6443
|
message: "Repository visibility:",
|
|
6137
6444
|
choices: [
|
|
6138
6445
|
{ value: true, name: "Private" },
|
|
@@ -6144,16 +6451,16 @@ async function handleNoGitRepository() {
|
|
|
6144
6451
|
message: "Repository name:",
|
|
6145
6452
|
default: dirName
|
|
6146
6453
|
});
|
|
6147
|
-
console.log(
|
|
6454
|
+
console.log(chalk15.dim("\nCreating repository...\n"));
|
|
6148
6455
|
const repo = await createGitHubRepoWithGh(repoName, isPrivate);
|
|
6149
6456
|
if (!repo) {
|
|
6150
6457
|
return {
|
|
6151
6458
|
success: false,
|
|
6152
|
-
message:
|
|
6459
|
+
message: chalk15.red("\u274C Failed to create GitHub repository\n\n") + showSetupInstructions("no-git")
|
|
6153
6460
|
};
|
|
6154
6461
|
}
|
|
6155
|
-
console.log(
|
|
6156
|
-
console.log(
|
|
6462
|
+
console.log(chalk15.green(`\u2705 Created repository: ${repo.url}`));
|
|
6463
|
+
console.log(chalk15.green("\u2705 Added remote origin\n"));
|
|
6157
6464
|
return {
|
|
6158
6465
|
success: true,
|
|
6159
6466
|
message: "continue-init",
|
|
@@ -6164,7 +6471,7 @@ async function handleNoGitRepository() {
|
|
|
6164
6471
|
}
|
|
6165
6472
|
return {
|
|
6166
6473
|
success: false,
|
|
6167
|
-
message:
|
|
6474
|
+
message: chalk15.yellow("\u26A0\uFE0F This directory is not a git repository.\n\n") + showSetupInstructions("no-git")
|
|
6168
6475
|
};
|
|
6169
6476
|
}
|
|
6170
6477
|
async function handleNoGitRemote() {
|
|
@@ -6176,7 +6483,7 @@ async function handleNoGitRemote() {
|
|
|
6176
6483
|
});
|
|
6177
6484
|
if (shouldCreate) {
|
|
6178
6485
|
const dirName = getCurrentDirectoryName();
|
|
6179
|
-
const isPrivate = await
|
|
6486
|
+
const isPrivate = await select3({
|
|
6180
6487
|
message: "Repository visibility:",
|
|
6181
6488
|
choices: [
|
|
6182
6489
|
{ value: true, name: "Private" },
|
|
@@ -6188,16 +6495,16 @@ async function handleNoGitRemote() {
|
|
|
6188
6495
|
message: "Repository name:",
|
|
6189
6496
|
default: dirName
|
|
6190
6497
|
});
|
|
6191
|
-
console.log(
|
|
6498
|
+
console.log(chalk15.dim("\nCreating repository...\n"));
|
|
6192
6499
|
const repo = await createGitHubRepoWithGh(repoName, isPrivate);
|
|
6193
6500
|
if (!repo) {
|
|
6194
6501
|
return {
|
|
6195
6502
|
success: false,
|
|
6196
|
-
message:
|
|
6503
|
+
message: chalk15.red("\u274C Failed to create GitHub repository\n\n") + showSetupInstructions("no-remote")
|
|
6197
6504
|
};
|
|
6198
6505
|
}
|
|
6199
|
-
console.log(
|
|
6200
|
-
console.log(
|
|
6506
|
+
console.log(chalk15.green(`\u2705 Created repository: ${repo.url}`));
|
|
6507
|
+
console.log(chalk15.green("\u2705 Added remote origin\n"));
|
|
6201
6508
|
return {
|
|
6202
6509
|
success: true,
|
|
6203
6510
|
message: "continue-init",
|
|
@@ -6208,11 +6515,31 @@ async function handleNoGitRemote() {
|
|
|
6208
6515
|
}
|
|
6209
6516
|
return {
|
|
6210
6517
|
success: false,
|
|
6211
|
-
message:
|
|
6518
|
+
message: chalk15.yellow("\u26A0\uFE0F Git repository detected but no GitHub remote configured.\n\n") + showSetupInstructions("no-remote")
|
|
6212
6519
|
};
|
|
6213
6520
|
}
|
|
6214
6521
|
async function handleInit(opts) {
|
|
6215
6522
|
try {
|
|
6523
|
+
const updateInfo = await isUpdateAvailable();
|
|
6524
|
+
if (updateInfo.available && updateInfo.latestVersion) {
|
|
6525
|
+
console.log(
|
|
6526
|
+
chalk15.yellow(`
|
|
6527
|
+
\u26A0\uFE0F A new version of BrainGrid CLI is available: `) + chalk15.dim(`${updateInfo.currentVersion} \u2192 `) + chalk15.green(updateInfo.latestVersion) + "\n"
|
|
6528
|
+
);
|
|
6529
|
+
const shouldUpdate = await confirm({
|
|
6530
|
+
message: "Would you like to update now?",
|
|
6531
|
+
default: true
|
|
6532
|
+
});
|
|
6533
|
+
if (shouldUpdate) {
|
|
6534
|
+
const result = await handleUpdate({});
|
|
6535
|
+
console.log(result.message);
|
|
6536
|
+
return {
|
|
6537
|
+
success: true,
|
|
6538
|
+
message: chalk15.dim("\nRun `braingrid init` again after the update completes.")
|
|
6539
|
+
};
|
|
6540
|
+
}
|
|
6541
|
+
console.log();
|
|
6542
|
+
}
|
|
6216
6543
|
const config = getConfig();
|
|
6217
6544
|
const { projectService, githubService, repositoryService, auth } = getServices4();
|
|
6218
6545
|
if (!await isGitInstalled()) {
|
|
@@ -6223,7 +6550,7 @@ async function handleInit(opts) {
|
|
|
6223
6550
|
if (!shouldInstall) {
|
|
6224
6551
|
return {
|
|
6225
6552
|
success: false,
|
|
6226
|
-
message:
|
|
6553
|
+
message: chalk15.yellow("\u26A0\uFE0F Git installation cancelled.\n\n") + getManualInstallInstructions()
|
|
6227
6554
|
};
|
|
6228
6555
|
}
|
|
6229
6556
|
console.log();
|
|
@@ -6239,14 +6566,14 @@ async function handleInit(opts) {
|
|
|
6239
6566
|
if (!await isGitInstalled()) {
|
|
6240
6567
|
return {
|
|
6241
6568
|
success: false,
|
|
6242
|
-
message:
|
|
6569
|
+
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
6570
|
};
|
|
6244
6571
|
}
|
|
6245
6572
|
}
|
|
6246
6573
|
if (!await isGhInstalled()) {
|
|
6247
|
-
console.log(
|
|
6574
|
+
console.log(chalk15.blue("\n\u{1F4A1} GitHub CLI is highly recommended for working with BrainGrid."));
|
|
6248
6575
|
console.log(
|
|
6249
|
-
|
|
6576
|
+
chalk15.dim(" It enables seamless GitHub integration and repository management.\n")
|
|
6250
6577
|
);
|
|
6251
6578
|
const shouldInstallGh = await confirm({
|
|
6252
6579
|
message: "Would you like to install GitHub CLI now?",
|
|
@@ -6260,10 +6587,10 @@ async function handleInit(opts) {
|
|
|
6260
6587
|
console.log();
|
|
6261
6588
|
} else {
|
|
6262
6589
|
console.log(ghInstallResult.message);
|
|
6263
|
-
console.log(
|
|
6590
|
+
console.log(chalk15.dim("You can install it manually later.\n"));
|
|
6264
6591
|
}
|
|
6265
6592
|
} else {
|
|
6266
|
-
console.log(
|
|
6593
|
+
console.log(chalk15.dim("Skipping GitHub CLI installation.\n"));
|
|
6267
6594
|
}
|
|
6268
6595
|
}
|
|
6269
6596
|
if (await projectConfigExists() && !opts.force) {
|
|
@@ -6271,15 +6598,15 @@ async function handleInit(opts) {
|
|
|
6271
6598
|
const existing = await loadProjectConfig();
|
|
6272
6599
|
return {
|
|
6273
6600
|
success: false,
|
|
6274
|
-
message:
|
|
6275
|
-
`) +
|
|
6601
|
+
message: chalk15.yellow("\u26A0\uFE0F Already initialized.\n\n") + chalk15.dim(`Project: ${existing.project_name} (${existing.project_short_id})
|
|
6602
|
+
`) + chalk15.dim(`Repository: ${existing.repository?.full_name || "N/A"}
|
|
6276
6603
|
|
|
6277
|
-
`) +
|
|
6604
|
+
`) + chalk15.dim("Use --force to reinitialize")
|
|
6278
6605
|
};
|
|
6279
6606
|
} catch {
|
|
6280
6607
|
return {
|
|
6281
6608
|
success: false,
|
|
6282
|
-
message:
|
|
6609
|
+
message: chalk15.yellow("\u26A0\uFE0F Invalid project configuration found.\n") + chalk15.dim("Use --force to reinitialize")
|
|
6283
6610
|
};
|
|
6284
6611
|
}
|
|
6285
6612
|
}
|
|
@@ -6292,7 +6619,7 @@ async function handleInit(opts) {
|
|
|
6292
6619
|
if (!shouldLogin) {
|
|
6293
6620
|
return {
|
|
6294
6621
|
success: false,
|
|
6295
|
-
message:
|
|
6622
|
+
message: chalk15.yellow("\u26A0\uFE0F Authentication required.\n") + chalk15.dim("Run ") + chalk15.cyan("braingrid login") + chalk15.dim(" when you're ready to authenticate.")
|
|
6296
6623
|
};
|
|
6297
6624
|
}
|
|
6298
6625
|
console.log();
|
|
@@ -6300,13 +6627,13 @@ async function handleInit(opts) {
|
|
|
6300
6627
|
if (!loginResult.success) {
|
|
6301
6628
|
return {
|
|
6302
6629
|
success: false,
|
|
6303
|
-
message:
|
|
6630
|
+
message: chalk15.red("\u274C Login failed.\n") + chalk15.dim("Please try running ") + chalk15.cyan("braingrid login") + chalk15.dim(" again.")
|
|
6304
6631
|
};
|
|
6305
6632
|
}
|
|
6306
6633
|
if (!await auth.isAuthenticated()) {
|
|
6307
6634
|
return {
|
|
6308
6635
|
success: false,
|
|
6309
|
-
message:
|
|
6636
|
+
message: chalk15.red("\u274C Login was not completed.\n") + chalk15.dim("Please try running ") + chalk15.cyan("braingrid login") + chalk15.dim(" again.")
|
|
6310
6637
|
};
|
|
6311
6638
|
}
|
|
6312
6639
|
console.log();
|
|
@@ -6315,27 +6642,27 @@ async function handleInit(opts) {
|
|
|
6315
6642
|
if (!session) {
|
|
6316
6643
|
return {
|
|
6317
6644
|
success: false,
|
|
6318
|
-
message:
|
|
6645
|
+
message: chalk15.red("\u274C No session found. Please run `braingrid login` first.")
|
|
6319
6646
|
};
|
|
6320
6647
|
}
|
|
6321
6648
|
if (session.organization_id === "default") {
|
|
6322
|
-
console.log(
|
|
6649
|
+
console.log(chalk15.yellow("\u26A0\uFE0F Organization ID not set, validating session...\n"));
|
|
6323
6650
|
const isValid = await auth.isAuthenticated();
|
|
6324
6651
|
if (!isValid) {
|
|
6325
6652
|
return {
|
|
6326
6653
|
success: false,
|
|
6327
|
-
message:
|
|
6654
|
+
message: chalk15.red("\u274C Session validation failed. Please run `braingrid login` again.")
|
|
6328
6655
|
};
|
|
6329
6656
|
}
|
|
6330
6657
|
const updatedSession = await auth.getStoredSession();
|
|
6331
6658
|
if (!updatedSession || updatedSession.organization_id === "default") {
|
|
6332
6659
|
return {
|
|
6333
6660
|
success: false,
|
|
6334
|
-
message:
|
|
6661
|
+
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
6662
|
};
|
|
6336
6663
|
}
|
|
6337
6664
|
Object.assign(session, updatedSession);
|
|
6338
|
-
console.log(
|
|
6665
|
+
console.log(chalk15.green("\u2705 Organization ID updated successfully\n"));
|
|
6339
6666
|
}
|
|
6340
6667
|
let gitInfo = await getGitRepositoryInfo();
|
|
6341
6668
|
let project2;
|
|
@@ -6345,9 +6672,9 @@ async function handleInit(opts) {
|
|
|
6345
6672
|
} catch {
|
|
6346
6673
|
return {
|
|
6347
6674
|
success: false,
|
|
6348
|
-
message:
|
|
6675
|
+
message: chalk15.red(`\u274C Project not found: ${opts.project}
|
|
6349
6676
|
|
|
6350
|
-
`) +
|
|
6677
|
+
`) + chalk15.dim("Make sure the project ID is correct and you have access to it.")
|
|
6351
6678
|
};
|
|
6352
6679
|
}
|
|
6353
6680
|
} else {
|
|
@@ -6358,7 +6685,7 @@ async function handleInit(opts) {
|
|
|
6358
6685
|
if (!gitInfo || !gitInfo.owner || !gitInfo.name) {
|
|
6359
6686
|
return {
|
|
6360
6687
|
success: false,
|
|
6361
|
-
message:
|
|
6688
|
+
message: chalk15.red("\u274C Failed to get repository information after setup")
|
|
6362
6689
|
};
|
|
6363
6690
|
}
|
|
6364
6691
|
} else {
|
|
@@ -6372,7 +6699,7 @@ async function handleInit(opts) {
|
|
|
6372
6699
|
if (!gitInfo || !gitInfo.owner || !gitInfo.name) {
|
|
6373
6700
|
return {
|
|
6374
6701
|
success: false,
|
|
6375
|
-
message:
|
|
6702
|
+
message: chalk15.red("\u274C Failed to get repository information after setup")
|
|
6376
6703
|
};
|
|
6377
6704
|
}
|
|
6378
6705
|
} else {
|
|
@@ -6382,7 +6709,7 @@ async function handleInit(opts) {
|
|
|
6382
6709
|
if (!gitInfo) {
|
|
6383
6710
|
return {
|
|
6384
6711
|
success: false,
|
|
6385
|
-
message:
|
|
6712
|
+
message: chalk15.red("\u274C Repository information is missing")
|
|
6386
6713
|
};
|
|
6387
6714
|
}
|
|
6388
6715
|
const owner = gitInfo.owner;
|
|
@@ -6390,7 +6717,7 @@ async function handleInit(opts) {
|
|
|
6390
6717
|
if (!owner || !name) {
|
|
6391
6718
|
return {
|
|
6392
6719
|
success: false,
|
|
6393
|
-
message:
|
|
6720
|
+
message: chalk15.red("\u274C Repository information is incomplete")
|
|
6394
6721
|
};
|
|
6395
6722
|
}
|
|
6396
6723
|
let response;
|
|
@@ -6429,7 +6756,7 @@ async function handleInit(opts) {
|
|
|
6429
6756
|
}
|
|
6430
6757
|
project2 = response.projects[0];
|
|
6431
6758
|
}
|
|
6432
|
-
const projectInfo =
|
|
6759
|
+
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
6760
|
console.log(projectInfo);
|
|
6434
6761
|
if (!opts.force) {
|
|
6435
6762
|
const shouldInit = await confirm({
|
|
@@ -6439,7 +6766,7 @@ async function handleInit(opts) {
|
|
|
6439
6766
|
if (!shouldInit) {
|
|
6440
6767
|
return {
|
|
6441
6768
|
success: false,
|
|
6442
|
-
message:
|
|
6769
|
+
message: chalk15.yellow("Initialization cancelled.")
|
|
6443
6770
|
};
|
|
6444
6771
|
}
|
|
6445
6772
|
}
|
|
@@ -6462,7 +6789,7 @@ async function handleInit(opts) {
|
|
|
6462
6789
|
};
|
|
6463
6790
|
await saveProjectConfig(localConfig);
|
|
6464
6791
|
console.log(
|
|
6465
|
-
|
|
6792
|
+
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
6793
|
);
|
|
6467
6794
|
const installedIDEs = await detectInstalledIDEs();
|
|
6468
6795
|
if (installedIDEs.claudeCode) {
|
|
@@ -6480,15 +6807,15 @@ async function handleInit(opts) {
|
|
|
6480
6807
|
if (result.success) {
|
|
6481
6808
|
console.log(result.message);
|
|
6482
6809
|
} else {
|
|
6483
|
-
console.log(
|
|
6810
|
+
console.log(chalk15.yellow("\u26A0\uFE0F Claude Code setup was not completed."));
|
|
6484
6811
|
console.log(
|
|
6485
|
-
|
|
6812
|
+
chalk15.dim("You can run ") + chalk15.cyan("braingrid setup claude-code") + chalk15.dim(" later.")
|
|
6486
6813
|
);
|
|
6487
6814
|
}
|
|
6488
6815
|
} catch {
|
|
6489
|
-
console.log(
|
|
6816
|
+
console.log(chalk15.yellow("\u26A0\uFE0F Claude Code setup encountered an error."));
|
|
6490
6817
|
console.log(
|
|
6491
|
-
|
|
6818
|
+
chalk15.dim("You can run ") + chalk15.cyan("braingrid setup claude-code") + chalk15.dim(" later.")
|
|
6492
6819
|
);
|
|
6493
6820
|
}
|
|
6494
6821
|
console.log("");
|
|
@@ -6510,15 +6837,15 @@ async function handleInit(opts) {
|
|
|
6510
6837
|
if (result.success) {
|
|
6511
6838
|
console.log(result.message);
|
|
6512
6839
|
} else {
|
|
6513
|
-
console.log(
|
|
6840
|
+
console.log(chalk15.yellow("\u26A0\uFE0F Cursor setup was not completed."));
|
|
6514
6841
|
console.log(
|
|
6515
|
-
|
|
6842
|
+
chalk15.dim("You can run ") + chalk15.cyan("braingrid setup cursor") + chalk15.dim(" later.")
|
|
6516
6843
|
);
|
|
6517
6844
|
}
|
|
6518
6845
|
} catch {
|
|
6519
|
-
console.log(
|
|
6846
|
+
console.log(chalk15.yellow("\u26A0\uFE0F Cursor setup encountered an error."));
|
|
6520
6847
|
console.log(
|
|
6521
|
-
|
|
6848
|
+
chalk15.dim("You can run ") + chalk15.cyan("braingrid setup cursor") + chalk15.dim(" later.")
|
|
6522
6849
|
);
|
|
6523
6850
|
}
|
|
6524
6851
|
console.log("");
|
|
@@ -6527,7 +6854,7 @@ async function handleInit(opts) {
|
|
|
6527
6854
|
}
|
|
6528
6855
|
return {
|
|
6529
6856
|
success: true,
|
|
6530
|
-
message:
|
|
6857
|
+
message: chalk15.dim(
|
|
6531
6858
|
"You can now use project-scoped commands without specifying a project ID."
|
|
6532
6859
|
),
|
|
6533
6860
|
data: localConfig
|
|
@@ -6540,205 +6867,8 @@ async function handleInit(opts) {
|
|
|
6540
6867
|
}
|
|
6541
6868
|
}
|
|
6542
6869
|
|
|
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
6870
|
// src/handlers/completion.handlers.ts
|
|
6741
|
-
import
|
|
6871
|
+
import chalk16 from "chalk";
|
|
6742
6872
|
|
|
6743
6873
|
// src/completion/index.ts
|
|
6744
6874
|
import omelette from "omelette";
|
|
@@ -6814,7 +6944,7 @@ function setupCompletion(shell) {
|
|
|
6814
6944
|
function getUnsupportedShellError() {
|
|
6815
6945
|
return {
|
|
6816
6946
|
success: false,
|
|
6817
|
-
message:
|
|
6947
|
+
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
6948
|
};
|
|
6819
6949
|
}
|
|
6820
6950
|
async function handleCompletion(shellArg, opts) {
|
|
@@ -6844,33 +6974,33 @@ async function handleCompletion(shellArg, opts) {
|
|
|
6844
6974
|
const configPath = getShellConfigPath(shell);
|
|
6845
6975
|
return {
|
|
6846
6976
|
success: true,
|
|
6847
|
-
message:
|
|
6977
|
+
message: chalk16.green(`\u2705 Completion installed for ${shell}
|
|
6848
6978
|
|
|
6849
|
-
`) +
|
|
6979
|
+
`) + chalk16.dim("To activate in your current shell, run:\n") + chalk16.cyan(` source ${configPath}
|
|
6850
6980
|
|
|
6851
|
-
`) +
|
|
6981
|
+
`) + chalk16.dim("Or restart your terminal.")
|
|
6852
6982
|
};
|
|
6853
6983
|
} catch (error) {
|
|
6854
6984
|
return {
|
|
6855
6985
|
success: false,
|
|
6856
|
-
message:
|
|
6986
|
+
message: chalk16.red("\u274C Failed to install completion\n\n") + chalk16.dim("Error: ") + formatError(error)
|
|
6857
6987
|
};
|
|
6858
6988
|
}
|
|
6859
6989
|
}
|
|
6860
6990
|
try {
|
|
6861
6991
|
const script = generateCompletionScript(shell);
|
|
6862
6992
|
const configPath = getShellConfigPath(shell);
|
|
6863
|
-
const instructions =
|
|
6864
|
-
`) +
|
|
6865
|
-
`) +
|
|
6993
|
+
const instructions = chalk16.blue(`# BrainGrid CLI completion for ${shell}
|
|
6994
|
+
`) + chalk16.dim("# To install, run one of the following:\n\n") + chalk16.cyan(`# 1. Automatic installation (recommended):
|
|
6995
|
+
`) + chalk16.cyan(` braingrid completion --setup
|
|
6866
6996
|
|
|
6867
|
-
`) +
|
|
6868
|
-
`) +
|
|
6997
|
+
`) + chalk16.cyan(`# 2. Add to your shell config:
|
|
6998
|
+
`) + chalk16.cyan(` braingrid completion ${shell} >> ${configPath}
|
|
6869
6999
|
|
|
6870
|
-
`) +
|
|
6871
|
-
`) +
|
|
7000
|
+
`) + chalk16.cyan(`# 3. Source directly (temporary, current session only):
|
|
7001
|
+
`) + chalk16.cyan(` eval "$(braingrid completion ${shell})"
|
|
6872
7002
|
|
|
6873
|
-
`) +
|
|
7003
|
+
`) + chalk16.dim("# Completion script:\n\n");
|
|
6874
7004
|
return {
|
|
6875
7005
|
success: true,
|
|
6876
7006
|
message: instructions + script
|
|
@@ -6878,7 +7008,7 @@ async function handleCompletion(shellArg, opts) {
|
|
|
6878
7008
|
} catch (error) {
|
|
6879
7009
|
return {
|
|
6880
7010
|
success: false,
|
|
6881
|
-
message:
|
|
7011
|
+
message: chalk16.red("\u274C Failed to generate completion script\n\n") + chalk16.dim("Error: ") + formatError(error)
|
|
6882
7012
|
};
|
|
6883
7013
|
}
|
|
6884
7014
|
} catch (error) {
|
|
@@ -6895,6 +7025,9 @@ var packageJson = require2("../package.json");
|
|
|
6895
7025
|
initCompletion();
|
|
6896
7026
|
var program = new Command();
|
|
6897
7027
|
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)");
|
|
7028
|
+
program.hook("postAction", async () => {
|
|
7029
|
+
await checkAndShowUpdateWarning();
|
|
7030
|
+
});
|
|
6898
7031
|
program.command("login").description("Authenticate with BrainGrid").action(async () => {
|
|
6899
7032
|
const result = await handleLogin();
|
|
6900
7033
|
console.log(result.message);
|
|
@@ -7088,7 +7221,7 @@ task.command("summary").description("Show task summary table (quick overview wit
|
|
|
7088
7221
|
process.exit(1);
|
|
7089
7222
|
}
|
|
7090
7223
|
});
|
|
7091
|
-
task.command("show
|
|
7224
|
+
task.command("show [id]").description("Show task details (auto-detects current task if not provided)").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) => {
|
|
7092
7225
|
const result = await handleTaskShow(id, opts);
|
|
7093
7226
|
console.log(result.message);
|
|
7094
7227
|
if (!result.success) {
|
|
@@ -7102,7 +7235,7 @@ task.command("create").description("Create a new task").option("-r, --requiremen
|
|
|
7102
7235
|
process.exit(1);
|
|
7103
7236
|
}
|
|
7104
7237
|
});
|
|
7105
|
-
task.command("update
|
|
7238
|
+
task.command("update [id]").description("Update task (auto-detects current task if not provided)").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("--status <status>", "new status (PLANNED, IN_PROGRESS, COMPLETED, CANCELLED)").option("--title <title>", "new task title").action(async (id, opts) => {
|
|
7106
7239
|
const result = await handleTaskUpdate(id, opts);
|
|
7107
7240
|
console.log(result.message);
|
|
7108
7241
|
if (!result.success) {
|