@nimbuslab/cli 0.13.6 → 0.15.0
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/.github/workflows/publish.yml +25 -0
- package/dist/index.js +215 -57
- package/package.json +1 -1
- package/src/commands/create.ts +28 -18
- package/src/commands/lola.ts +100 -2
- package/src/commands/update.ts +133 -35
- package/src/index.ts +6 -5
|
@@ -16,27 +16,52 @@ jobs:
|
|
|
16
16
|
- name: Checkout
|
|
17
17
|
uses: actions/checkout@v4
|
|
18
18
|
|
|
19
|
+
- name: Check if version changed
|
|
20
|
+
id: version_check
|
|
21
|
+
run: |
|
|
22
|
+
LOCAL_VERSION=$(node -p "require('./package.json').version")
|
|
23
|
+
NPM_VERSION=$(npm view @nimbuslab/cli version 2>/dev/null || echo "0.0.0")
|
|
24
|
+
echo "local=$LOCAL_VERSION" >> $GITHUB_OUTPUT
|
|
25
|
+
echo "npm=$NPM_VERSION" >> $GITHUB_OUTPUT
|
|
26
|
+
if [ "$LOCAL_VERSION" = "$NPM_VERSION" ]; then
|
|
27
|
+
echo "changed=false" >> $GITHUB_OUTPUT
|
|
28
|
+
echo "Versao $LOCAL_VERSION ja existe no npm. Pulando publish."
|
|
29
|
+
else
|
|
30
|
+
echo "changed=true" >> $GITHUB_OUTPUT
|
|
31
|
+
echo "Nova versao detectada: $NPM_VERSION -> $LOCAL_VERSION"
|
|
32
|
+
fi
|
|
33
|
+
|
|
19
34
|
- name: Setup Bun
|
|
35
|
+
if: steps.version_check.outputs.changed == 'true'
|
|
20
36
|
uses: oven-sh/setup-bun@v2
|
|
21
37
|
with:
|
|
22
38
|
bun-version: latest
|
|
23
39
|
|
|
24
40
|
- name: Setup Node (for npm publish)
|
|
41
|
+
if: steps.version_check.outputs.changed == 'true'
|
|
25
42
|
uses: actions/setup-node@v4
|
|
26
43
|
with:
|
|
27
44
|
node-version: "24"
|
|
28
45
|
registry-url: "https://registry.npmjs.org"
|
|
29
46
|
|
|
30
47
|
- name: Install dependencies
|
|
48
|
+
if: steps.version_check.outputs.changed == 'true'
|
|
31
49
|
run: bun install
|
|
32
50
|
|
|
33
51
|
- name: Typecheck
|
|
52
|
+
if: steps.version_check.outputs.changed == 'true'
|
|
34
53
|
run: bun run typecheck
|
|
35
54
|
|
|
36
55
|
- name: Build
|
|
56
|
+
if: steps.version_check.outputs.changed == 'true'
|
|
37
57
|
run: bun run build
|
|
38
58
|
|
|
39
59
|
- name: Publish to npm
|
|
60
|
+
if: steps.version_check.outputs.changed == 'true'
|
|
40
61
|
run: npm publish --access public
|
|
41
62
|
env:
|
|
42
63
|
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
|
|
64
|
+
|
|
65
|
+
- name: Skip message
|
|
66
|
+
if: steps.version_check.outputs.changed == 'false'
|
|
67
|
+
run: echo "Publish pulado - versao ${{ steps.version_check.outputs.local }} ja existe no npm"
|
package/dist/index.js
CHANGED
|
@@ -150,7 +150,7 @@ var require_src = __commonJS((exports, module) => {
|
|
|
150
150
|
var require_package = __commonJS((exports, module) => {
|
|
151
151
|
module.exports = {
|
|
152
152
|
name: "@nimbuslab/cli",
|
|
153
|
-
version: "0.
|
|
153
|
+
version: "0.15.0",
|
|
154
154
|
description: "CLI para criar projetos nimbuslab",
|
|
155
155
|
type: "module",
|
|
156
156
|
bin: {
|
|
@@ -1328,15 +1328,18 @@ async function promptConfig(initialName, flags) {
|
|
|
1328
1328
|
console.log();
|
|
1329
1329
|
console.log(import_picocolors3.default.dim(" nimbus-core: Motor para projetos externos (stealth mode)"));
|
|
1330
1330
|
console.log();
|
|
1331
|
-
const
|
|
1332
|
-
message: "Create
|
|
1333
|
-
|
|
1331
|
+
const repoOption = await ve({
|
|
1332
|
+
message: "Create repository for this project?",
|
|
1333
|
+
options: [
|
|
1334
|
+
{ value: "github", label: "GitHub (nimbuslab, private)", hint: "recommended" },
|
|
1335
|
+
{ value: "none", label: "No repository", hint: "just local" }
|
|
1336
|
+
]
|
|
1334
1337
|
});
|
|
1335
|
-
if (pD(
|
|
1336
|
-
return
|
|
1338
|
+
if (pD(repoOption))
|
|
1339
|
+
return repoOption;
|
|
1337
1340
|
const clientRepo = await he({
|
|
1338
|
-
message: "Client repo URL (
|
|
1339
|
-
placeholder: "git@github.com:client/repo.git"
|
|
1341
|
+
message: "Client repo URL (to clone in workspace):",
|
|
1342
|
+
placeholder: "git@github.com:client/repo.git ou Azure DevOps URL"
|
|
1340
1343
|
});
|
|
1341
1344
|
if (pD(clientRepo))
|
|
1342
1345
|
return clientRepo;
|
|
@@ -1346,7 +1349,7 @@ async function promptConfig(initialName, flags) {
|
|
|
1346
1349
|
monorepo: false,
|
|
1347
1350
|
git: true,
|
|
1348
1351
|
install: false,
|
|
1349
|
-
github:
|
|
1352
|
+
github: repoOption === "github",
|
|
1350
1353
|
githubOrg: "nimbuslab",
|
|
1351
1354
|
githubDescription: `nimbus-core for ${name} - external project`,
|
|
1352
1355
|
theme: "dark",
|
|
@@ -1359,7 +1362,8 @@ async function promptConfig(initialName, flags) {
|
|
|
1359
1362
|
railwayToken: "",
|
|
1360
1363
|
stagingUrl: "",
|
|
1361
1364
|
productionUrl: "",
|
|
1362
|
-
customTemplate:
|
|
1365
|
+
customTemplate: null,
|
|
1366
|
+
clientRepoUrl: clientRepo || null
|
|
1363
1367
|
};
|
|
1364
1368
|
}
|
|
1365
1369
|
let monorepo = false;
|
|
@@ -1688,11 +1692,17 @@ async function createProject(config) {
|
|
|
1688
1692
|
s.stop("Error cloning template");
|
|
1689
1693
|
throw new Error(`Failed to clone template ${templateRepo}. Check your connection or repository access.`);
|
|
1690
1694
|
}
|
|
1691
|
-
if (config.type === "nimbus-core" && config.
|
|
1692
|
-
const clientRepoUrl = config.
|
|
1695
|
+
if (config.type === "nimbus-core" && config.clientRepoUrl) {
|
|
1696
|
+
const clientRepoUrl = config.clientRepoUrl;
|
|
1693
1697
|
s.start(`Cloning client repo in workspace...`);
|
|
1694
1698
|
try {
|
|
1695
|
-
|
|
1699
|
+
let projectName = "client-project";
|
|
1700
|
+
if (clientRepoUrl.includes("visualstudio.com") || clientRepoUrl.includes("dev.azure.com")) {
|
|
1701
|
+
const parts = clientRepoUrl.split("/");
|
|
1702
|
+
projectName = parts[parts.length - 1] || "client-project";
|
|
1703
|
+
} else {
|
|
1704
|
+
projectName = clientRepoUrl.split("/").pop()?.replace(".git", "") || "client-project";
|
|
1705
|
+
}
|
|
1696
1706
|
await $2`git clone ${clientRepoUrl} ${config.name}/workspace/${projectName}`.quiet();
|
|
1697
1707
|
s.stop(`Client repo cloned: workspace/${projectName}`);
|
|
1698
1708
|
} catch (error) {
|
|
@@ -1870,13 +1880,8 @@ function showNextSteps(config) {
|
|
|
1870
1880
|
console.log();
|
|
1871
1881
|
console.log(import_picocolors3.default.dim(" nimbus-core: Motor para projetos externos"));
|
|
1872
1882
|
console.log();
|
|
1873
|
-
console.log(import_picocolors3.default.dim(" Para clonar repo do cliente:"));
|
|
1874
|
-
console.log(` ${import_picocolors3.default.cyan("cd")} workspace`);
|
|
1875
|
-
console.log(` ${import_picocolors3.default.cyan("git clone")} <repo-do-cliente>`);
|
|
1876
|
-
console.log();
|
|
1877
1883
|
console.log(import_picocolors3.default.dim(" Para usar a Lola:"));
|
|
1878
|
-
console.log(` ${import_picocolors3.default.cyan("
|
|
1879
|
-
console.log(` ${import_picocolors3.default.cyan("claude --append-system-prompt-file .claude/agents/lola.md")}`);
|
|
1884
|
+
console.log(` ${import_picocolors3.default.cyan("lola")}`);
|
|
1880
1885
|
console.log();
|
|
1881
1886
|
console.log(import_picocolors3.default.yellow(" STEALTH MODE: Commits sem mencao a nimbuslab/Lola/IA"));
|
|
1882
1887
|
console.log();
|
|
@@ -2377,84 +2382,149 @@ async function getLatestVersion() {
|
|
|
2377
2382
|
return null;
|
|
2378
2383
|
}
|
|
2379
2384
|
}
|
|
2385
|
+
function detectPackageManager2() {
|
|
2386
|
+
try {
|
|
2387
|
+
const bunResult = spawnSync("bun", ["pm", "ls", "-g"], {
|
|
2388
|
+
encoding: "utf-8",
|
|
2389
|
+
shell: true,
|
|
2390
|
+
timeout: 5000
|
|
2391
|
+
});
|
|
2392
|
+
if (bunResult.stdout && bunResult.stdout.includes(PACKAGE_NAME)) {
|
|
2393
|
+
return "bun";
|
|
2394
|
+
}
|
|
2395
|
+
} catch {}
|
|
2396
|
+
try {
|
|
2397
|
+
const npmResult = spawnSync("npm", ["ls", "-g", PACKAGE_NAME, "--json"], {
|
|
2398
|
+
encoding: "utf-8",
|
|
2399
|
+
shell: true,
|
|
2400
|
+
timeout: 5000
|
|
2401
|
+
});
|
|
2402
|
+
if (npmResult.stdout) {
|
|
2403
|
+
const data = JSON.parse(npmResult.stdout);
|
|
2404
|
+
if (data.dependencies?.[PACKAGE_NAME]) {
|
|
2405
|
+
return "npm";
|
|
2406
|
+
}
|
|
2407
|
+
}
|
|
2408
|
+
} catch {}
|
|
2409
|
+
return "unknown";
|
|
2410
|
+
}
|
|
2380
2411
|
function getCurrentVersion() {
|
|
2412
|
+
try {
|
|
2413
|
+
const bunResult = spawnSync("bun", ["pm", "ls", "-g"], {
|
|
2414
|
+
encoding: "utf-8",
|
|
2415
|
+
shell: true,
|
|
2416
|
+
timeout: 5000
|
|
2417
|
+
});
|
|
2418
|
+
if (bunResult.stdout) {
|
|
2419
|
+
const match = bunResult.stdout.match(new RegExp(`${PACKAGE_NAME.replace("/", "\\/")}@([\\d.]+)`));
|
|
2420
|
+
if (match?.[1]) {
|
|
2421
|
+
return match[1];
|
|
2422
|
+
}
|
|
2423
|
+
}
|
|
2424
|
+
} catch {}
|
|
2381
2425
|
try {
|
|
2382
2426
|
const result = spawnSync("npm", ["ls", "-g", PACKAGE_NAME, "--json"], {
|
|
2383
2427
|
encoding: "utf-8",
|
|
2384
|
-
shell: true
|
|
2428
|
+
shell: true,
|
|
2429
|
+
timeout: 5000
|
|
2385
2430
|
});
|
|
2386
2431
|
if (result.stdout) {
|
|
2387
2432
|
const data = JSON.parse(result.stdout);
|
|
2388
|
-
|
|
2433
|
+
if (data.dependencies?.[PACKAGE_NAME]?.version) {
|
|
2434
|
+
return data.dependencies[PACKAGE_NAME].version;
|
|
2435
|
+
}
|
|
2389
2436
|
}
|
|
2390
2437
|
} catch {}
|
|
2391
2438
|
return "unknown";
|
|
2392
2439
|
}
|
|
2393
2440
|
async function update(args) {
|
|
2394
|
-
const
|
|
2441
|
+
const forceFlag = args.includes("--force") || args.includes("-f");
|
|
2442
|
+
const filteredArgs = args.filter((a) => a !== "--force" && a !== "-f");
|
|
2443
|
+
const flag = filteredArgs[0];
|
|
2395
2444
|
if (flag === "--list" || flag === "-l") {
|
|
2396
|
-
Ie(import_picocolors6.default.cyan("
|
|
2445
|
+
Ie(import_picocolors6.default.cyan("Versoes disponiveis"));
|
|
2397
2446
|
const spinner2 = Y2();
|
|
2398
|
-
spinner2.start("Buscando
|
|
2447
|
+
spinner2.start("Buscando versoes...");
|
|
2399
2448
|
const versions = await getAvailableVersions();
|
|
2400
|
-
spinner2.stop("
|
|
2449
|
+
spinner2.stop("Versoes encontradas");
|
|
2401
2450
|
if (versions.length === 0) {
|
|
2402
|
-
M2.error("
|
|
2451
|
+
M2.error("Nao foi possivel buscar as versoes");
|
|
2403
2452
|
return;
|
|
2404
2453
|
}
|
|
2405
2454
|
const current = getCurrentVersion();
|
|
2455
|
+
const pm2 = detectPackageManager2();
|
|
2406
2456
|
console.log();
|
|
2407
|
-
console.log(import_picocolors6.default.bold("
|
|
2457
|
+
console.log(import_picocolors6.default.bold("Ultimas 10 versoes:"));
|
|
2408
2458
|
versions.slice(0, 10).forEach((v2, i) => {
|
|
2409
2459
|
const isCurrent = v2 === current;
|
|
2410
|
-
const prefix = isCurrent ? import_picocolors6.default.green("
|
|
2460
|
+
const prefix = isCurrent ? import_picocolors6.default.green("-> ") : " ";
|
|
2411
2461
|
const suffix = isCurrent ? import_picocolors6.default.dim(" (instalada)") : "";
|
|
2412
2462
|
const isLatest = i === 0 ? import_picocolors6.default.yellow(" (latest)") : "";
|
|
2413
2463
|
console.log(`${prefix}${v2}${suffix}${isLatest}`);
|
|
2414
2464
|
});
|
|
2415
2465
|
console.log();
|
|
2416
|
-
console.log(import_picocolors6.default.dim(`Total: ${versions.length}
|
|
2417
|
-
console.log(import_picocolors6.default.dim(`
|
|
2466
|
+
console.log(import_picocolors6.default.dim(`Total: ${versions.length} versoes`));
|
|
2467
|
+
console.log(import_picocolors6.default.dim(`Package manager detectado: ${pm2 === "unknown" ? "nenhum" : pm2}`));
|
|
2468
|
+
console.log(import_picocolors6.default.dim(`Instalar versao especifica: nimbus update <versao>`));
|
|
2469
|
+
console.log(import_picocolors6.default.dim(`Forcar reinstalacao: nimbus update --force`));
|
|
2418
2470
|
return;
|
|
2419
2471
|
}
|
|
2420
2472
|
const targetVersion = flag || "latest";
|
|
2421
|
-
const isSpecificVersion = flag && flag !== "latest";
|
|
2473
|
+
const isSpecificVersion = flag && flag !== "latest" && !flag.startsWith("-");
|
|
2422
2474
|
Ie(import_picocolors6.default.cyan(`Atualizando ${PACKAGE_NAME}`));
|
|
2423
2475
|
const spinner = Y2();
|
|
2424
|
-
spinner.start("
|
|
2476
|
+
spinner.start("Detectando package manager...");
|
|
2477
|
+
const detectedPm = detectPackageManager2();
|
|
2478
|
+
const pm = detectedPm === "unknown" ? "bun" : detectedPm;
|
|
2479
|
+
spinner.stop(`Package manager: ${pm}${detectedPm === "unknown" ? " (padrao)" : ""}`);
|
|
2480
|
+
spinner.start("Verificando versao atual...");
|
|
2425
2481
|
const currentVersion = getCurrentVersion();
|
|
2426
|
-
spinner.stop(`
|
|
2482
|
+
spinner.stop(`Versao atual: ${currentVersion === "unknown" ? "nao instalado" : currentVersion}`);
|
|
2483
|
+
let latestVersion = null;
|
|
2427
2484
|
if (!isSpecificVersion) {
|
|
2428
|
-
spinner.start("Verificando
|
|
2429
|
-
|
|
2430
|
-
spinner.stop(
|
|
2431
|
-
if (
|
|
2432
|
-
M2.success("
|
|
2485
|
+
spinner.start("Verificando ultima versao no npm...");
|
|
2486
|
+
latestVersion = await getLatestVersion();
|
|
2487
|
+
spinner.stop(`Ultima versao: ${latestVersion || "desconhecida"}`);
|
|
2488
|
+
if (!forceFlag && latestVersion && latestVersion === currentVersion) {
|
|
2489
|
+
M2.success("Voce ja esta na ultima versao!");
|
|
2490
|
+
console.log(import_picocolors6.default.dim(" Use --force para reinstalar"));
|
|
2433
2491
|
return;
|
|
2434
2492
|
}
|
|
2435
2493
|
}
|
|
2436
|
-
const versionText = isSpecificVersion ? targetVersion : "latest";
|
|
2494
|
+
const versionText = isSpecificVersion ? targetVersion : latestVersion || "latest";
|
|
2495
|
+
const actionText = forceFlag ? "Reinstalar" : "Atualizar";
|
|
2437
2496
|
const confirmUpdate = await ye({
|
|
2438
|
-
message:
|
|
2497
|
+
message: `${actionText} para ${versionText} usando ${pm}?`,
|
|
2439
2498
|
initialValue: true
|
|
2440
2499
|
});
|
|
2441
2500
|
if (pD(confirmUpdate) || !confirmUpdate) {
|
|
2442
|
-
xe("
|
|
2501
|
+
xe("Atualizacao cancelada");
|
|
2443
2502
|
return;
|
|
2444
2503
|
}
|
|
2445
2504
|
spinner.start("Atualizando...");
|
|
2446
2505
|
try {
|
|
2447
|
-
const packageSpec = isSpecificVersion ? `${PACKAGE_NAME}@${targetVersion}` : PACKAGE_NAME;
|
|
2448
|
-
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
|
|
2452
|
-
|
|
2506
|
+
const packageSpec = isSpecificVersion ? `${PACKAGE_NAME}@${targetVersion}` : latestVersion ? `${PACKAGE_NAME}@${latestVersion}` : PACKAGE_NAME;
|
|
2507
|
+
if (pm === "bun") {
|
|
2508
|
+
if (forceFlag) {
|
|
2509
|
+
try {
|
|
2510
|
+
execSync(`bun remove -g ${PACKAGE_NAME}`, { stdio: "pipe", encoding: "utf-8" });
|
|
2511
|
+
} catch {}
|
|
2512
|
+
}
|
|
2513
|
+
execSync(`bun add -g ${packageSpec}`, { stdio: "pipe", encoding: "utf-8" });
|
|
2514
|
+
} else {
|
|
2515
|
+
const forceArg = forceFlag ? " --force" : "";
|
|
2516
|
+
execSync(`npm install -g ${packageSpec}${forceArg}`, { stdio: "pipe", encoding: "utf-8" });
|
|
2517
|
+
}
|
|
2518
|
+
spinner.stop("Atualizacao concluida!");
|
|
2453
2519
|
const newVersion = getCurrentVersion();
|
|
2454
|
-
|
|
2520
|
+
if (currentVersion === newVersion && !forceFlag) {
|
|
2521
|
+
M2.warn("Versao nao mudou. Tente com --force");
|
|
2522
|
+
} else {
|
|
2523
|
+
M2.success(`${PACKAGE_NAME} atualizado: ${currentVersion} -> ${newVersion}`);
|
|
2524
|
+
}
|
|
2455
2525
|
Se(import_picocolors6.default.green("Pronto!"));
|
|
2456
2526
|
} catch (error) {
|
|
2457
|
-
spinner.stop("Erro na
|
|
2527
|
+
spinner.stop("Erro na atualizacao");
|
|
2458
2528
|
const err = error;
|
|
2459
2529
|
M2.error("Falha ao atualizar");
|
|
2460
2530
|
if (err.stderr) {
|
|
@@ -2462,7 +2532,11 @@ async function update(args) {
|
|
|
2462
2532
|
}
|
|
2463
2533
|
console.log();
|
|
2464
2534
|
console.log(import_picocolors6.default.yellow("Tente manualmente:"));
|
|
2465
|
-
|
|
2535
|
+
if (pm === "bun") {
|
|
2536
|
+
console.log(import_picocolors6.default.cyan(` bun add -g ${PACKAGE_NAME}${isSpecificVersion ? `@${targetVersion}` : ""}`));
|
|
2537
|
+
} else {
|
|
2538
|
+
console.log(import_picocolors6.default.cyan(` npm install -g ${PACKAGE_NAME}${isSpecificVersion ? `@${targetVersion}` : ""}`));
|
|
2539
|
+
}
|
|
2466
2540
|
}
|
|
2467
2541
|
}
|
|
2468
2542
|
|
|
@@ -2475,6 +2549,53 @@ var HOME = homedir();
|
|
|
2475
2549
|
var LOLA_DIR = join3(HOME, ".lola");
|
|
2476
2550
|
var LOLA_REPO = "git@github.com:nimbuslab/lola.git";
|
|
2477
2551
|
var USER_MEMORY = join3(HOME, ".claude", "USER_MEMORY.md");
|
|
2552
|
+
var LOLA_MEMORY_URL = "https://lola.nimbuslab.com.br/sse";
|
|
2553
|
+
var LOLA_MEMORY_NAME = "lola-memory";
|
|
2554
|
+
async function installLolaMemoryMCP() {
|
|
2555
|
+
console.log();
|
|
2556
|
+
console.log(import_picocolors7.default.cyan(" Configurando lola-memory MCP..."));
|
|
2557
|
+
const claudeCheck = Bun.spawnSync(["which", "claude"], { stdout: "pipe" });
|
|
2558
|
+
if (claudeCheck.exitCode !== 0) {
|
|
2559
|
+
console.log(import_picocolors7.default.yellow(" Claude CLI nao encontrado, pulando MCP"));
|
|
2560
|
+
console.log(import_picocolors7.default.dim(" Instale o Claude CLI e rode 'nimbus lola install' novamente"));
|
|
2561
|
+
return;
|
|
2562
|
+
}
|
|
2563
|
+
const mcpList = Bun.spawnSync(["claude", "mcp", "list"], { stdout: "pipe", stderr: "pipe" });
|
|
2564
|
+
const mcpOutput = mcpList.stdout.toString();
|
|
2565
|
+
if (mcpOutput.includes(LOLA_MEMORY_NAME)) {
|
|
2566
|
+
console.log(import_picocolors7.default.green(" MCP lola-memory ja configurado"));
|
|
2567
|
+
return;
|
|
2568
|
+
}
|
|
2569
|
+
console.log(import_picocolors7.default.dim(" Adicionando MCP lola-memory..."));
|
|
2570
|
+
const result = Bun.spawnSync([
|
|
2571
|
+
"claude",
|
|
2572
|
+
"mcp",
|
|
2573
|
+
"add",
|
|
2574
|
+
"-t",
|
|
2575
|
+
"sse",
|
|
2576
|
+
"-s",
|
|
2577
|
+
"user",
|
|
2578
|
+
LOLA_MEMORY_NAME,
|
|
2579
|
+
"--",
|
|
2580
|
+
"bunx",
|
|
2581
|
+
"mcp-remote",
|
|
2582
|
+
LOLA_MEMORY_URL
|
|
2583
|
+
], {
|
|
2584
|
+
stdout: "inherit",
|
|
2585
|
+
stderr: "inherit"
|
|
2586
|
+
});
|
|
2587
|
+
if (result.exitCode !== 0) {
|
|
2588
|
+
console.log(import_picocolors7.default.yellow(" Erro ao adicionar MCP, pode ser adicionado manualmente:"));
|
|
2589
|
+
console.log(import_picocolors7.default.dim(` claude mcp add -t sse -s user ${LOLA_MEMORY_NAME} -- bunx mcp-remote ${LOLA_MEMORY_URL}`));
|
|
2590
|
+
return;
|
|
2591
|
+
}
|
|
2592
|
+
console.log(import_picocolors7.default.green(" MCP lola-memory instalado!"));
|
|
2593
|
+
console.log();
|
|
2594
|
+
console.log(import_picocolors7.default.dim(" Comandos disponiveis:"));
|
|
2595
|
+
console.log(import_picocolors7.default.dim(' remember "query" - Buscar conhecimento'));
|
|
2596
|
+
console.log(import_picocolors7.default.dim(' learn "content" - Salvar conhecimento'));
|
|
2597
|
+
console.log(import_picocolors7.default.dim(" memory_stats - Ver estatisticas"));
|
|
2598
|
+
}
|
|
2478
2599
|
async function installLola() {
|
|
2479
2600
|
console.log();
|
|
2480
2601
|
console.log(import_picocolors7.default.cyan(" Lola - Code Agent da nimbuslab"));
|
|
@@ -2484,11 +2605,36 @@ async function installLola() {
|
|
|
2484
2605
|
if (isUpdate) {
|
|
2485
2606
|
console.log(import_picocolors7.default.dim(` Lola ja instalada em ${LOLA_DIR}`));
|
|
2486
2607
|
console.log(import_picocolors7.default.cyan(" Atualizando..."));
|
|
2608
|
+
const statusCheck = Bun.spawnSync(["git", "status", "--porcelain"], {
|
|
2609
|
+
cwd: LOLA_DIR,
|
|
2610
|
+
stdout: "pipe"
|
|
2611
|
+
});
|
|
2612
|
+
const hasLocalChanges = statusCheck.stdout.toString().trim().length > 0;
|
|
2613
|
+
if (hasLocalChanges) {
|
|
2614
|
+
console.log(import_picocolors7.default.dim(" Salvando mudancas locais..."));
|
|
2615
|
+
Bun.spawnSync(["git", "stash", "--quiet"], {
|
|
2616
|
+
cwd: LOLA_DIR,
|
|
2617
|
+
stdout: "pipe",
|
|
2618
|
+
stderr: "pipe"
|
|
2619
|
+
});
|
|
2620
|
+
}
|
|
2487
2621
|
const result = Bun.spawnSync(["git", "pull", "--quiet"], {
|
|
2488
2622
|
cwd: LOLA_DIR,
|
|
2489
2623
|
stdout: "inherit",
|
|
2490
2624
|
stderr: "inherit"
|
|
2491
2625
|
});
|
|
2626
|
+
if (hasLocalChanges) {
|
|
2627
|
+
console.log(import_picocolors7.default.dim(" Restaurando mudancas locais..."));
|
|
2628
|
+
const stashPop = Bun.spawnSync(["git", "stash", "pop", "--quiet"], {
|
|
2629
|
+
cwd: LOLA_DIR,
|
|
2630
|
+
stdout: "pipe",
|
|
2631
|
+
stderr: "pipe"
|
|
2632
|
+
});
|
|
2633
|
+
if (stashPop.exitCode !== 0) {
|
|
2634
|
+
console.log(import_picocolors7.default.yellow(" Aviso: conflito ao restaurar mudancas locais"));
|
|
2635
|
+
console.log(import_picocolors7.default.dim(" Verifique ~/.lola e resolva manualmente: git stash pop"));
|
|
2636
|
+
}
|
|
2637
|
+
}
|
|
2492
2638
|
if (result.exitCode !== 0) {
|
|
2493
2639
|
console.log(import_picocolors7.default.red(" Erro ao atualizar Lola"));
|
|
2494
2640
|
process.exit(1);
|
|
@@ -2596,6 +2742,7 @@ fi
|
|
|
2596
2742
|
console.log(import_picocolors7.default.green(" Script lola ja existe"));
|
|
2597
2743
|
}
|
|
2598
2744
|
}
|
|
2745
|
+
await installLolaMemoryMCP();
|
|
2599
2746
|
const claudeDir = join3(HOME, ".claude");
|
|
2600
2747
|
if (!existsSync2(USER_MEMORY)) {
|
|
2601
2748
|
console.log();
|
|
@@ -2644,7 +2791,11 @@ lola_profile: millennial
|
|
|
2644
2791
|
console.log();
|
|
2645
2792
|
console.log(import_picocolors7.default.bold(" Para usar a Lola:"));
|
|
2646
2793
|
console.log(import_picocolors7.default.dim(" lola ") + import_picocolors7.default.white("# Iniciar sessao"));
|
|
2647
|
-
console.log(
|
|
2794
|
+
console.log();
|
|
2795
|
+
console.log(import_picocolors7.default.bold(" lola-memory (conhecimento compartilhado):"));
|
|
2796
|
+
console.log(import_picocolors7.default.dim(' remember "query" ') + import_picocolors7.default.white("# Buscar conhecimento"));
|
|
2797
|
+
console.log(import_picocolors7.default.dim(' learn "content" ') + import_picocolors7.default.white("# Salvar conhecimento"));
|
|
2798
|
+
console.log(import_picocolors7.default.dim(" memory_stats ") + import_picocolors7.default.white("# Ver estatisticas"));
|
|
2648
2799
|
console.log();
|
|
2649
2800
|
console.log(import_picocolors7.default.bold(" Para mudar perfil, edite ~/.claude/USER_MEMORY.md:"));
|
|
2650
2801
|
console.log(import_picocolors7.default.dim(" lola_profile: millennial|genz|profissional|nerd|chill"));
|
|
@@ -2996,7 +3147,7 @@ function showLolaHelp() {
|
|
|
2996
3147
|
console.log(import_picocolors7.default.bold(" Uso:") + " nimbus lola [subcomando]");
|
|
2997
3148
|
console.log();
|
|
2998
3149
|
console.log(import_picocolors7.default.bold(" Subcomandos:"));
|
|
2999
|
-
console.log(import_picocolors7.default.dim(" install ") + import_picocolors7.default.white("Instalar/atualizar Lola"));
|
|
3150
|
+
console.log(import_picocolors7.default.dim(" install ") + import_picocolors7.default.white("Instalar/atualizar Lola + MCP"));
|
|
3000
3151
|
console.log(import_picocolors7.default.dim(" sync ") + import_picocolors7.default.white("Alias para install"));
|
|
3001
3152
|
console.log(import_picocolors7.default.dim(" onboard ") + import_picocolors7.default.white("Configurar perfil (novos devs)"));
|
|
3002
3153
|
console.log(import_picocolors7.default.dim(" quiz ") + import_picocolors7.default.white("Quiz sobre a nimbuslab"));
|
|
@@ -3009,6 +3160,12 @@ function showLolaHelp() {
|
|
|
3009
3160
|
console.log(import_picocolors7.default.dim(" $ nimbus lola quiz"));
|
|
3010
3161
|
console.log(import_picocolors7.default.dim(' $ nimbus lola suggest "adicionar suporte a X"'));
|
|
3011
3162
|
console.log();
|
|
3163
|
+
console.log(import_picocolors7.default.bold(" lola-memory (dentro do Claude):"));
|
|
3164
|
+
console.log(import_picocolors7.default.dim(' remember "query" ') + import_picocolors7.default.white("Buscar conhecimento"));
|
|
3165
|
+
console.log(import_picocolors7.default.dim(' learn "content" ') + import_picocolors7.default.white("Salvar conhecimento"));
|
|
3166
|
+
console.log(import_picocolors7.default.dim(" memory_stats ") + import_picocolors7.default.white("Ver estatisticas"));
|
|
3167
|
+
console.log(import_picocolors7.default.dim(" get_context ") + import_picocolors7.default.white("Perfil + memorias recentes"));
|
|
3168
|
+
console.log();
|
|
3012
3169
|
}
|
|
3013
3170
|
|
|
3014
3171
|
// src/index.ts
|
|
@@ -3051,8 +3208,8 @@ function showUpdateNotice(latestVersion) {
|
|
|
3051
3208
|
const maxLen = Math.max(line1.length, line2.length);
|
|
3052
3209
|
const border = "\u2500".repeat(maxLen + 2);
|
|
3053
3210
|
console.log(import_picocolors8.default.yellow(` \u250C${border}\u2510`));
|
|
3054
|
-
console.log(import_picocolors8.default.yellow(` \u2502`) + import_picocolors8.default.white(line1.padEnd(maxLen +
|
|
3055
|
-
console.log(import_picocolors8.default.yellow(` \u2502`) + import_picocolors8.default.cyan(line2.padEnd(maxLen +
|
|
3211
|
+
console.log(import_picocolors8.default.yellow(` \u2502`) + import_picocolors8.default.white(line1.padEnd(maxLen + 2)) + import_picocolors8.default.yellow(`\u2502`));
|
|
3212
|
+
console.log(import_picocolors8.default.yellow(` \u2502`) + import_picocolors8.default.cyan(line2.padEnd(maxLen + 2)) + import_picocolors8.default.yellow(`\u2502`));
|
|
3056
3213
|
console.log(import_picocolors8.default.yellow(` \u2514${border}\u2518`));
|
|
3057
3214
|
console.log();
|
|
3058
3215
|
}
|
|
@@ -3113,9 +3270,10 @@ ${import_picocolors8.default.bold("Analyze & Upgrade:")}
|
|
|
3113
3270
|
upgrade tailwind Atualizar Tailwind CSS
|
|
3114
3271
|
|
|
3115
3272
|
${import_picocolors8.default.bold("Update (CLI):")}
|
|
3116
|
-
update Atualizar para
|
|
3117
|
-
update 0.11.0 Instalar
|
|
3118
|
-
update --list Listar
|
|
3273
|
+
update Atualizar para ultima versao
|
|
3274
|
+
update 0.11.0 Instalar versao especifica
|
|
3275
|
+
update --list Listar versoes disponiveis
|
|
3276
|
+
update --force Forcar reinstalacao (limpa cache)
|
|
3119
3277
|
|
|
3120
3278
|
${import_picocolors8.default.bold("Op\xE7\xF5es:")}
|
|
3121
3279
|
-y, --yes Aceitar padr\xF5es
|
package/package.json
CHANGED
package/src/commands/create.ts
CHANGED
|
@@ -196,6 +196,8 @@ interface ProjectConfig {
|
|
|
196
196
|
productionUrl: string
|
|
197
197
|
// Template customizado
|
|
198
198
|
customTemplate: string | null
|
|
199
|
+
// nimbus-core: URL do repo do cliente
|
|
200
|
+
clientRepoUrl?: string | null
|
|
199
201
|
}
|
|
200
202
|
|
|
201
203
|
interface CreateFlags {
|
|
@@ -547,17 +549,20 @@ async function promptConfig(initialName?: string, flags?: CreateFlags): Promise<
|
|
|
547
549
|
console.log(pc.dim(" nimbus-core: Motor para projetos externos (stealth mode)"))
|
|
548
550
|
console.log()
|
|
549
551
|
|
|
550
|
-
//
|
|
551
|
-
const
|
|
552
|
-
message: "Create
|
|
553
|
-
|
|
552
|
+
// Perguntar se quer criar repo (GitHub ou nenhum)
|
|
553
|
+
const repoOption = await p.select({
|
|
554
|
+
message: "Create repository for this project?",
|
|
555
|
+
options: [
|
|
556
|
+
{ value: "github", label: "GitHub (nimbuslab, private)", hint: "recommended" },
|
|
557
|
+
{ value: "none", label: "No repository", hint: "just local" },
|
|
558
|
+
],
|
|
554
559
|
})
|
|
555
|
-
if (p.isCancel(
|
|
560
|
+
if (p.isCancel(repoOption)) return repoOption
|
|
556
561
|
|
|
557
562
|
// Perguntar URL do repo do cliente para clonar no workspace
|
|
558
563
|
const clientRepo = await p.text({
|
|
559
|
-
message: "Client repo URL (
|
|
560
|
-
placeholder: "git@github.com:client/repo.git",
|
|
564
|
+
message: "Client repo URL (to clone in workspace):",
|
|
565
|
+
placeholder: "git@github.com:client/repo.git ou Azure DevOps URL",
|
|
561
566
|
})
|
|
562
567
|
if (p.isCancel(clientRepo)) return clientRepo
|
|
563
568
|
|
|
@@ -567,7 +572,7 @@ async function promptConfig(initialName?: string, flags?: CreateFlags): Promise<
|
|
|
567
572
|
monorepo: false,
|
|
568
573
|
git: true, // sempre init git
|
|
569
574
|
install: false, // nimbus-core não tem package.json
|
|
570
|
-
github:
|
|
575
|
+
github: repoOption === "github",
|
|
571
576
|
githubOrg: "nimbuslab", // sempre na org nimbuslab
|
|
572
577
|
githubDescription: `nimbus-core for ${name} - external project`,
|
|
573
578
|
theme: "dark" as const,
|
|
@@ -580,7 +585,8 @@ async function promptConfig(initialName?: string, flags?: CreateFlags): Promise<
|
|
|
580
585
|
railwayToken: "",
|
|
581
586
|
stagingUrl: "",
|
|
582
587
|
productionUrl: "",
|
|
583
|
-
customTemplate:
|
|
588
|
+
customTemplate: null, // não usa template customizado
|
|
589
|
+
clientRepoUrl: (clientRepo as string) || null, // URL do cliente separada
|
|
584
590
|
}
|
|
585
591
|
}
|
|
586
592
|
|
|
@@ -972,11 +978,20 @@ async function createProject(config: ProjectConfig) {
|
|
|
972
978
|
}
|
|
973
979
|
|
|
974
980
|
// nimbus-core: clone client repo in workspace if provided
|
|
975
|
-
if (config.type === "nimbus-core" && config.
|
|
976
|
-
const clientRepoUrl = config.
|
|
981
|
+
if (config.type === "nimbus-core" && config.clientRepoUrl) {
|
|
982
|
+
const clientRepoUrl = config.clientRepoUrl
|
|
977
983
|
s.start(`Cloning client repo in workspace...`)
|
|
978
984
|
try {
|
|
979
|
-
|
|
985
|
+
// Extrair nome do projeto da URL (funciona com GitHub, GitLab, Azure DevOps)
|
|
986
|
+
let projectName = "client-project"
|
|
987
|
+
if (clientRepoUrl.includes("visualstudio.com") || clientRepoUrl.includes("dev.azure.com")) {
|
|
988
|
+
// Azure DevOps: serel@vs-ssh.visualstudio.com:v3/serel/Project/Repo
|
|
989
|
+
const parts = clientRepoUrl.split("/")
|
|
990
|
+
projectName = parts[parts.length - 1] || "client-project"
|
|
991
|
+
} else {
|
|
992
|
+
// GitHub/GitLab: git@github.com:org/repo.git
|
|
993
|
+
projectName = clientRepoUrl.split("/").pop()?.replace(".git", "") || "client-project"
|
|
994
|
+
}
|
|
980
995
|
await $`git clone ${clientRepoUrl} ${config.name}/workspace/${projectName}`.quiet()
|
|
981
996
|
s.stop(`Client repo cloned: workspace/${projectName}`)
|
|
982
997
|
} catch (error) {
|
|
@@ -1204,13 +1219,8 @@ function showNextSteps(config: ProjectConfig) {
|
|
|
1204
1219
|
console.log()
|
|
1205
1220
|
console.log(pc.dim(" nimbus-core: Motor para projetos externos"))
|
|
1206
1221
|
console.log()
|
|
1207
|
-
console.log(pc.dim(" Para clonar repo do cliente:"))
|
|
1208
|
-
console.log(` ${pc.cyan("cd")} workspace`)
|
|
1209
|
-
console.log(` ${pc.cyan("git clone")} <repo-do-cliente>`)
|
|
1210
|
-
console.log()
|
|
1211
1222
|
console.log(pc.dim(" Para usar a Lola:"))
|
|
1212
|
-
console.log(` ${pc.cyan("
|
|
1213
|
-
console.log(` ${pc.cyan("claude --append-system-prompt-file .claude/agents/lola.md")}`)
|
|
1223
|
+
console.log(` ${pc.cyan("lola")}`)
|
|
1214
1224
|
console.log()
|
|
1215
1225
|
console.log(pc.yellow(" STEALTH MODE: Commits sem mencao a nimbuslab/Lola/IA"))
|
|
1216
1226
|
console.log()
|
package/src/commands/lola.ts
CHANGED
|
@@ -8,6 +8,58 @@ const HOME = homedir()
|
|
|
8
8
|
const LOLA_DIR = join(HOME, ".lola")
|
|
9
9
|
const LOLA_REPO = "git@github.com:nimbuslab/lola.git"
|
|
10
10
|
const USER_MEMORY = join(HOME, ".claude", "USER_MEMORY.md")
|
|
11
|
+
const LOLA_MEMORY_URL = "https://lola.nimbuslab.com.br/sse"
|
|
12
|
+
const LOLA_MEMORY_NAME = "lola-memory"
|
|
13
|
+
|
|
14
|
+
async function installLolaMemoryMCP(): Promise<void> {
|
|
15
|
+
console.log()
|
|
16
|
+
console.log(pc.cyan(" Configurando lola-memory MCP..."))
|
|
17
|
+
|
|
18
|
+
// Verificar se claude CLI existe
|
|
19
|
+
const claudeCheck = Bun.spawnSync(["which", "claude"], { stdout: "pipe" })
|
|
20
|
+
if (claudeCheck.exitCode !== 0) {
|
|
21
|
+
console.log(pc.yellow(" Claude CLI nao encontrado, pulando MCP"))
|
|
22
|
+
console.log(pc.dim(" Instale o Claude CLI e rode 'nimbus lola install' novamente"))
|
|
23
|
+
return
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Verificar se MCP já está configurado
|
|
27
|
+
const mcpList = Bun.spawnSync(["claude", "mcp", "list"], { stdout: "pipe", stderr: "pipe" })
|
|
28
|
+
const mcpOutput = mcpList.stdout.toString()
|
|
29
|
+
|
|
30
|
+
if (mcpOutput.includes(LOLA_MEMORY_NAME)) {
|
|
31
|
+
console.log(pc.green(" MCP lola-memory ja configurado"))
|
|
32
|
+
return
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// Adicionar MCP lola-memory
|
|
36
|
+
console.log(pc.dim(" Adicionando MCP lola-memory..."))
|
|
37
|
+
|
|
38
|
+
const result = Bun.spawnSync([
|
|
39
|
+
"claude", "mcp", "add",
|
|
40
|
+
"-t", "sse",
|
|
41
|
+
"-s", "user",
|
|
42
|
+
LOLA_MEMORY_NAME,
|
|
43
|
+
"--",
|
|
44
|
+
"bunx", "mcp-remote", LOLA_MEMORY_URL
|
|
45
|
+
], {
|
|
46
|
+
stdout: "inherit",
|
|
47
|
+
stderr: "inherit",
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
if (result.exitCode !== 0) {
|
|
51
|
+
console.log(pc.yellow(" Erro ao adicionar MCP, pode ser adicionado manualmente:"))
|
|
52
|
+
console.log(pc.dim(` claude mcp add -t sse -s user ${LOLA_MEMORY_NAME} -- bunx mcp-remote ${LOLA_MEMORY_URL}`))
|
|
53
|
+
return
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
console.log(pc.green(" MCP lola-memory instalado!"))
|
|
57
|
+
console.log()
|
|
58
|
+
console.log(pc.dim(" Comandos disponiveis:"))
|
|
59
|
+
console.log(pc.dim(" remember \"query\" - Buscar conhecimento"))
|
|
60
|
+
console.log(pc.dim(" learn \"content\" - Salvar conhecimento"))
|
|
61
|
+
console.log(pc.dim(" memory_stats - Ver estatisticas"))
|
|
62
|
+
}
|
|
11
63
|
|
|
12
64
|
async function installLola(): Promise<void> {
|
|
13
65
|
console.log()
|
|
@@ -21,12 +73,45 @@ async function installLola(): Promise<void> {
|
|
|
21
73
|
console.log(pc.dim(` Lola ja instalada em ${LOLA_DIR}`))
|
|
22
74
|
console.log(pc.cyan(" Atualizando..."))
|
|
23
75
|
|
|
76
|
+
// Verificar se tem mudancas locais
|
|
77
|
+
const statusCheck = Bun.spawnSync(["git", "status", "--porcelain"], {
|
|
78
|
+
cwd: LOLA_DIR,
|
|
79
|
+
stdout: "pipe",
|
|
80
|
+
})
|
|
81
|
+
const hasLocalChanges = statusCheck.stdout.toString().trim().length > 0
|
|
82
|
+
|
|
83
|
+
// Stash se tiver mudancas locais
|
|
84
|
+
if (hasLocalChanges) {
|
|
85
|
+
console.log(pc.dim(" Salvando mudancas locais..."))
|
|
86
|
+
Bun.spawnSync(["git", "stash", "--quiet"], {
|
|
87
|
+
cwd: LOLA_DIR,
|
|
88
|
+
stdout: "pipe",
|
|
89
|
+
stderr: "pipe",
|
|
90
|
+
})
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Pull
|
|
24
94
|
const result = Bun.spawnSync(["git", "pull", "--quiet"], {
|
|
25
95
|
cwd: LOLA_DIR,
|
|
26
96
|
stdout: "inherit",
|
|
27
97
|
stderr: "inherit",
|
|
28
98
|
})
|
|
29
99
|
|
|
100
|
+
// Restaurar mudancas locais se tinha
|
|
101
|
+
if (hasLocalChanges) {
|
|
102
|
+
console.log(pc.dim(" Restaurando mudancas locais..."))
|
|
103
|
+
const stashPop = Bun.spawnSync(["git", "stash", "pop", "--quiet"], {
|
|
104
|
+
cwd: LOLA_DIR,
|
|
105
|
+
stdout: "pipe",
|
|
106
|
+
stderr: "pipe",
|
|
107
|
+
})
|
|
108
|
+
|
|
109
|
+
if (stashPop.exitCode !== 0) {
|
|
110
|
+
console.log(pc.yellow(" Aviso: conflito ao restaurar mudancas locais"))
|
|
111
|
+
console.log(pc.dim(" Verifique ~/.lola e resolva manualmente: git stash pop"))
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
30
115
|
if (result.exitCode !== 0) {
|
|
31
116
|
console.log(pc.red(" Erro ao atualizar Lola"))
|
|
32
117
|
process.exit(1)
|
|
@@ -162,6 +247,9 @@ fi
|
|
|
162
247
|
}
|
|
163
248
|
}
|
|
164
249
|
|
|
250
|
+
// Instalar MCP lola-memory
|
|
251
|
+
await installLolaMemoryMCP()
|
|
252
|
+
|
|
165
253
|
// Verificar USER_MEMORY.md
|
|
166
254
|
const claudeDir = join(HOME, ".claude")
|
|
167
255
|
if (!existsSync(USER_MEMORY)) {
|
|
@@ -217,7 +305,11 @@ lola_profile: millennial
|
|
|
217
305
|
console.log()
|
|
218
306
|
console.log(pc.bold(" Para usar a Lola:"))
|
|
219
307
|
console.log(pc.dim(" lola ") + pc.white("# Iniciar sessao"))
|
|
220
|
-
console.log(
|
|
308
|
+
console.log()
|
|
309
|
+
console.log(pc.bold(" lola-memory (conhecimento compartilhado):"))
|
|
310
|
+
console.log(pc.dim(" remember \"query\" ") + pc.white("# Buscar conhecimento"))
|
|
311
|
+
console.log(pc.dim(" learn \"content\" ") + pc.white("# Salvar conhecimento"))
|
|
312
|
+
console.log(pc.dim(" memory_stats ") + pc.white("# Ver estatisticas"))
|
|
221
313
|
console.log()
|
|
222
314
|
console.log(pc.bold(" Para mudar perfil, edite ~/.claude/USER_MEMORY.md:"))
|
|
223
315
|
console.log(pc.dim(" lola_profile: millennial|genz|profissional|nerd|chill"))
|
|
@@ -620,7 +712,7 @@ function showLolaHelp() {
|
|
|
620
712
|
console.log(pc.bold(" Uso:") + " nimbus lola [subcomando]")
|
|
621
713
|
console.log()
|
|
622
714
|
console.log(pc.bold(" Subcomandos:"))
|
|
623
|
-
console.log(pc.dim(" install ") + pc.white("Instalar/atualizar Lola"))
|
|
715
|
+
console.log(pc.dim(" install ") + pc.white("Instalar/atualizar Lola + MCP"))
|
|
624
716
|
console.log(pc.dim(" sync ") + pc.white("Alias para install"))
|
|
625
717
|
console.log(pc.dim(" onboard ") + pc.white("Configurar perfil (novos devs)"))
|
|
626
718
|
console.log(pc.dim(" quiz ") + pc.white("Quiz sobre a nimbuslab"))
|
|
@@ -633,4 +725,10 @@ function showLolaHelp() {
|
|
|
633
725
|
console.log(pc.dim(" $ nimbus lola quiz"))
|
|
634
726
|
console.log(pc.dim(" $ nimbus lola suggest \"adicionar suporte a X\""))
|
|
635
727
|
console.log()
|
|
728
|
+
console.log(pc.bold(" lola-memory (dentro do Claude):"))
|
|
729
|
+
console.log(pc.dim(" remember \"query\" ") + pc.white("Buscar conhecimento"))
|
|
730
|
+
console.log(pc.dim(" learn \"content\" ") + pc.white("Salvar conhecimento"))
|
|
731
|
+
console.log(pc.dim(" memory_stats ") + pc.white("Ver estatisticas"))
|
|
732
|
+
console.log(pc.dim(" get_context ") + pc.white("Perfil + memorias recentes"))
|
|
733
|
+
console.log()
|
|
636
734
|
}
|
package/src/commands/update.ts
CHANGED
|
@@ -4,6 +4,8 @@ import { execSync, spawnSync } from "child_process"
|
|
|
4
4
|
|
|
5
5
|
const PACKAGE_NAME = "@nimbuslab/cli"
|
|
6
6
|
|
|
7
|
+
type PackageManager = "bun" | "npm" | "unknown"
|
|
8
|
+
|
|
7
9
|
async function getAvailableVersions(): Promise<string[]> {
|
|
8
10
|
try {
|
|
9
11
|
const res = await fetch(`https://registry.npmjs.org/${PACKAGE_NAME}`)
|
|
@@ -26,91 +28,166 @@ async function getLatestVersion(): Promise<string | null> {
|
|
|
26
28
|
}
|
|
27
29
|
}
|
|
28
30
|
|
|
31
|
+
// Detecta qual package manager tem o pacote instalado globalmente
|
|
32
|
+
function detectPackageManager(): PackageManager {
|
|
33
|
+
// Tentar bun primeiro
|
|
34
|
+
try {
|
|
35
|
+
const bunResult = spawnSync("bun", ["pm", "ls", "-g"], {
|
|
36
|
+
encoding: "utf-8",
|
|
37
|
+
shell: true,
|
|
38
|
+
timeout: 5000,
|
|
39
|
+
})
|
|
40
|
+
if (bunResult.stdout && bunResult.stdout.includes(PACKAGE_NAME)) {
|
|
41
|
+
return "bun"
|
|
42
|
+
}
|
|
43
|
+
} catch {
|
|
44
|
+
// ignore
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Tentar npm
|
|
48
|
+
try {
|
|
49
|
+
const npmResult = spawnSync("npm", ["ls", "-g", PACKAGE_NAME, "--json"], {
|
|
50
|
+
encoding: "utf-8",
|
|
51
|
+
shell: true,
|
|
52
|
+
timeout: 5000,
|
|
53
|
+
})
|
|
54
|
+
if (npmResult.stdout) {
|
|
55
|
+
const data = JSON.parse(npmResult.stdout)
|
|
56
|
+
if (data.dependencies?.[PACKAGE_NAME]) {
|
|
57
|
+
return "npm"
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
} catch {
|
|
61
|
+
// ignore
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return "unknown"
|
|
65
|
+
}
|
|
66
|
+
|
|
29
67
|
function getCurrentVersion(): string {
|
|
68
|
+
// Tentar bun primeiro
|
|
69
|
+
try {
|
|
70
|
+
const bunResult = spawnSync("bun", ["pm", "ls", "-g"], {
|
|
71
|
+
encoding: "utf-8",
|
|
72
|
+
shell: true,
|
|
73
|
+
timeout: 5000,
|
|
74
|
+
})
|
|
75
|
+
if (bunResult.stdout) {
|
|
76
|
+
// Formato: "@nimbuslab/cli@0.14.0"
|
|
77
|
+
const match = bunResult.stdout.match(new RegExp(`${PACKAGE_NAME.replace("/", "\\/")}@([\\d.]+)`))
|
|
78
|
+
if (match?.[1]) {
|
|
79
|
+
return match[1]
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
} catch {
|
|
83
|
+
// ignore
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Fallback para npm
|
|
30
87
|
try {
|
|
31
88
|
const result = spawnSync("npm", ["ls", "-g", PACKAGE_NAME, "--json"], {
|
|
32
89
|
encoding: "utf-8",
|
|
33
90
|
shell: true,
|
|
91
|
+
timeout: 5000,
|
|
34
92
|
})
|
|
35
93
|
if (result.stdout) {
|
|
36
94
|
const data = JSON.parse(result.stdout)
|
|
37
|
-
|
|
95
|
+
if (data.dependencies?.[PACKAGE_NAME]?.version) {
|
|
96
|
+
return data.dependencies[PACKAGE_NAME].version
|
|
97
|
+
}
|
|
38
98
|
}
|
|
39
99
|
} catch {
|
|
40
100
|
// ignore
|
|
41
101
|
}
|
|
102
|
+
|
|
42
103
|
return "unknown"
|
|
43
104
|
}
|
|
44
105
|
|
|
45
106
|
export async function update(args: string[]) {
|
|
46
|
-
|
|
107
|
+
// Parse flags
|
|
108
|
+
const forceFlag = args.includes("--force") || args.includes("-f")
|
|
109
|
+
const filteredArgs = args.filter(a => a !== "--force" && a !== "-f")
|
|
110
|
+
const flag = filteredArgs[0]
|
|
47
111
|
|
|
48
112
|
// nimbus update --list
|
|
49
113
|
if (flag === "--list" || flag === "-l") {
|
|
50
|
-
p.intro(pc.cyan("
|
|
114
|
+
p.intro(pc.cyan("Versoes disponiveis"))
|
|
51
115
|
|
|
52
116
|
const spinner = p.spinner()
|
|
53
|
-
spinner.start("Buscando
|
|
117
|
+
spinner.start("Buscando versoes...")
|
|
54
118
|
|
|
55
119
|
const versions = await getAvailableVersions()
|
|
56
|
-
spinner.stop("
|
|
120
|
+
spinner.stop("Versoes encontradas")
|
|
57
121
|
|
|
58
122
|
if (versions.length === 0) {
|
|
59
|
-
p.log.error("
|
|
123
|
+
p.log.error("Nao foi possivel buscar as versoes")
|
|
60
124
|
return
|
|
61
125
|
}
|
|
62
126
|
|
|
63
127
|
const current = getCurrentVersion()
|
|
128
|
+
const pm = detectPackageManager()
|
|
64
129
|
|
|
65
130
|
console.log()
|
|
66
|
-
console.log(pc.bold("
|
|
131
|
+
console.log(pc.bold("Ultimas 10 versoes:"))
|
|
67
132
|
versions.slice(0, 10).forEach((v, i) => {
|
|
68
133
|
const isCurrent = v === current
|
|
69
|
-
const prefix = isCurrent ? pc.green("
|
|
134
|
+
const prefix = isCurrent ? pc.green("-> ") : " "
|
|
70
135
|
const suffix = isCurrent ? pc.dim(" (instalada)") : ""
|
|
71
136
|
const isLatest = i === 0 ? pc.yellow(" (latest)") : ""
|
|
72
137
|
console.log(`${prefix}${v}${suffix}${isLatest}`)
|
|
73
138
|
})
|
|
74
139
|
console.log()
|
|
75
|
-
console.log(pc.dim(`Total: ${versions.length}
|
|
76
|
-
console.log(pc.dim(`
|
|
140
|
+
console.log(pc.dim(`Total: ${versions.length} versoes`))
|
|
141
|
+
console.log(pc.dim(`Package manager detectado: ${pm === "unknown" ? "nenhum" : pm}`))
|
|
142
|
+
console.log(pc.dim(`Instalar versao especifica: nimbus update <versao>`))
|
|
143
|
+
console.log(pc.dim(`Forcar reinstalacao: nimbus update --force`))
|
|
77
144
|
return
|
|
78
145
|
}
|
|
79
146
|
|
|
80
147
|
// nimbus update [version]
|
|
81
148
|
const targetVersion = flag || "latest"
|
|
82
|
-
const isSpecificVersion = flag && flag !== "latest"
|
|
149
|
+
const isSpecificVersion = flag && flag !== "latest" && !flag.startsWith("-")
|
|
83
150
|
|
|
84
151
|
p.intro(pc.cyan(`Atualizando ${PACKAGE_NAME}`))
|
|
85
152
|
|
|
86
153
|
const spinner = p.spinner()
|
|
87
154
|
|
|
88
|
-
//
|
|
89
|
-
spinner.start("
|
|
155
|
+
// Detectar package manager
|
|
156
|
+
spinner.start("Detectando package manager...")
|
|
157
|
+
const detectedPm = detectPackageManager()
|
|
158
|
+
// Usar bun como padrao se nenhum detectado
|
|
159
|
+
const pm = detectedPm === "unknown" ? "bun" : detectedPm
|
|
160
|
+
spinner.stop(`Package manager: ${pm}${detectedPm === "unknown" ? " (padrao)" : ""}`)
|
|
161
|
+
|
|
162
|
+
// Verificar versao atual
|
|
163
|
+
spinner.start("Verificando versao atual...")
|
|
90
164
|
const currentVersion = getCurrentVersion()
|
|
91
|
-
spinner.stop(`
|
|
165
|
+
spinner.stop(`Versao atual: ${currentVersion === "unknown" ? "nao instalado" : currentVersion}`)
|
|
92
166
|
|
|
93
|
-
// Verificar
|
|
167
|
+
// Verificar versao alvo
|
|
168
|
+
let latestVersion: string | null = null
|
|
94
169
|
if (!isSpecificVersion) {
|
|
95
|
-
spinner.start("Verificando
|
|
96
|
-
|
|
97
|
-
spinner.stop(
|
|
170
|
+
spinner.start("Verificando ultima versao no npm...")
|
|
171
|
+
latestVersion = await getLatestVersion()
|
|
172
|
+
spinner.stop(`Ultima versao: ${latestVersion || "desconhecida"}`)
|
|
98
173
|
|
|
99
|
-
if (
|
|
100
|
-
p.log.success("
|
|
174
|
+
if (!forceFlag && latestVersion && latestVersion === currentVersion) {
|
|
175
|
+
p.log.success("Voce ja esta na ultima versao!")
|
|
176
|
+
console.log(pc.dim(" Use --force para reinstalar"))
|
|
101
177
|
return
|
|
102
178
|
}
|
|
103
179
|
}
|
|
104
180
|
|
|
105
181
|
// Confirmar
|
|
106
|
-
const versionText = isSpecificVersion ? targetVersion : "latest"
|
|
182
|
+
const versionText = isSpecificVersion ? targetVersion : (latestVersion || "latest")
|
|
183
|
+
const actionText = forceFlag ? "Reinstalar" : "Atualizar"
|
|
107
184
|
const confirmUpdate = await p.confirm({
|
|
108
|
-
message:
|
|
185
|
+
message: `${actionText} para ${versionText} usando ${pm}?`,
|
|
109
186
|
initialValue: true,
|
|
110
187
|
})
|
|
111
188
|
|
|
112
189
|
if (p.isCancel(confirmUpdate) || !confirmUpdate) {
|
|
113
|
-
p.cancel("
|
|
190
|
+
p.cancel("Atualizacao cancelada")
|
|
114
191
|
return
|
|
115
192
|
}
|
|
116
193
|
|
|
@@ -120,23 +197,40 @@ export async function update(args: string[]) {
|
|
|
120
197
|
try {
|
|
121
198
|
const packageSpec = isSpecificVersion
|
|
122
199
|
? `${PACKAGE_NAME}@${targetVersion}`
|
|
123
|
-
:
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
200
|
+
: latestVersion
|
|
201
|
+
? `${PACKAGE_NAME}@${latestVersion}`
|
|
202
|
+
: PACKAGE_NAME
|
|
203
|
+
|
|
204
|
+
// Usar o package manager detectado
|
|
205
|
+
if (pm === "bun") {
|
|
206
|
+
// Bun: remover primeiro se --force, depois instalar
|
|
207
|
+
if (forceFlag) {
|
|
208
|
+
try {
|
|
209
|
+
execSync(`bun remove -g ${PACKAGE_NAME}`, { stdio: "pipe", encoding: "utf-8" })
|
|
210
|
+
} catch {
|
|
211
|
+
// ignore - pode nao estar instalado
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
execSync(`bun add -g ${packageSpec}`, { stdio: "pipe", encoding: "utf-8" })
|
|
215
|
+
} else {
|
|
216
|
+
// npm: usar --force se solicitado
|
|
217
|
+
const forceArg = forceFlag ? " --force" : ""
|
|
218
|
+
execSync(`npm install -g ${packageSpec}${forceArg}`, { stdio: "pipe", encoding: "utf-8" })
|
|
219
|
+
}
|
|
130
220
|
|
|
131
|
-
spinner.stop("
|
|
221
|
+
spinner.stop("Atualizacao concluida!")
|
|
132
222
|
|
|
133
|
-
// Verificar nova
|
|
223
|
+
// Verificar nova versao
|
|
134
224
|
const newVersion = getCurrentVersion()
|
|
135
225
|
|
|
136
|
-
|
|
226
|
+
if (currentVersion === newVersion && !forceFlag) {
|
|
227
|
+
p.log.warn("Versao nao mudou. Tente com --force")
|
|
228
|
+
} else {
|
|
229
|
+
p.log.success(`${PACKAGE_NAME} atualizado: ${currentVersion} -> ${newVersion}`)
|
|
230
|
+
}
|
|
137
231
|
p.outro(pc.green("Pronto!"))
|
|
138
232
|
} catch (error) {
|
|
139
|
-
spinner.stop("Erro na
|
|
233
|
+
spinner.stop("Erro na atualizacao")
|
|
140
234
|
|
|
141
235
|
const err = error as Error & { stderr?: string }
|
|
142
236
|
p.log.error("Falha ao atualizar")
|
|
@@ -147,6 +241,10 @@ export async function update(args: string[]) {
|
|
|
147
241
|
|
|
148
242
|
console.log()
|
|
149
243
|
console.log(pc.yellow("Tente manualmente:"))
|
|
150
|
-
|
|
244
|
+
if (pm === "bun") {
|
|
245
|
+
console.log(pc.cyan(` bun add -g ${PACKAGE_NAME}${isSpecificVersion ? `@${targetVersion}` : ""}`))
|
|
246
|
+
} else {
|
|
247
|
+
console.log(pc.cyan(` npm install -g ${PACKAGE_NAME}${isSpecificVersion ? `@${targetVersion}` : ""}`))
|
|
248
|
+
}
|
|
151
249
|
}
|
|
152
250
|
}
|
package/src/index.ts
CHANGED
|
@@ -58,8 +58,8 @@ function showUpdateNotice(latestVersion: string) {
|
|
|
58
58
|
const border = "─".repeat(maxLen + 2)
|
|
59
59
|
|
|
60
60
|
console.log(pc.yellow(` ┌${border}┐`))
|
|
61
|
-
console.log(pc.yellow(` │`) + pc.white(line1.padEnd(maxLen +
|
|
62
|
-
console.log(pc.yellow(` │`) + pc.cyan(line2.padEnd(maxLen +
|
|
61
|
+
console.log(pc.yellow(` │`) + pc.white(line1.padEnd(maxLen + 2)) + pc.yellow(`│`))
|
|
62
|
+
console.log(pc.yellow(` │`) + pc.cyan(line2.padEnd(maxLen + 2)) + pc.yellow(`│`))
|
|
63
63
|
console.log(pc.yellow(` └${border}┘`))
|
|
64
64
|
console.log()
|
|
65
65
|
}
|
|
@@ -126,9 +126,10 @@ ${pc.bold("Analyze & Upgrade:")}
|
|
|
126
126
|
upgrade tailwind Atualizar Tailwind CSS
|
|
127
127
|
|
|
128
128
|
${pc.bold("Update (CLI):")}
|
|
129
|
-
update Atualizar para
|
|
130
|
-
update 0.11.0 Instalar
|
|
131
|
-
update --list Listar
|
|
129
|
+
update Atualizar para ultima versao
|
|
130
|
+
update 0.11.0 Instalar versao especifica
|
|
131
|
+
update --list Listar versoes disponiveis
|
|
132
|
+
update --force Forcar reinstalacao (limpa cache)
|
|
132
133
|
|
|
133
134
|
${pc.bold("Opções:")}
|
|
134
135
|
-y, --yes Aceitar padrões
|