@bagdock/cli 0.2.0 → 0.3.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/README.md +580 -22
- package/dist/bagdock.js +358 -79
- package/package.json +14 -5
- package/skill-evals/bagdock-cli/evals.json +152 -0
- package/skills/bagdock-cli/SKILL.md +123 -0
- package/skills/bagdock-cli/references/auth.md +113 -0
- package/skills/bagdock-cli/references/deploy.md +91 -0
- package/skills/bagdock-cli/references/dev.md +45 -0
- package/skills/bagdock-cli/references/env.md +37 -0
- package/skills/bagdock-cli/references/error-codes.md +53 -0
package/dist/bagdock.js
CHANGED
|
@@ -2085,31 +2085,87 @@ var require_commander = __commonJS((exports) => {
|
|
|
2085
2085
|
import { homedir } from "os";
|
|
2086
2086
|
import { join } from "path";
|
|
2087
2087
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
|
|
2088
|
+
function setProfileOverride(name) {
|
|
2089
|
+
profileOverride = name;
|
|
2090
|
+
}
|
|
2088
2091
|
function ensureConfigDir() {
|
|
2089
2092
|
if (!existsSync(CONFIG_DIR)) {
|
|
2090
2093
|
mkdirSync(CONFIG_DIR, { recursive: true, mode: 448 });
|
|
2091
2094
|
}
|
|
2092
2095
|
}
|
|
2093
|
-
function
|
|
2096
|
+
function loadStore() {
|
|
2094
2097
|
try {
|
|
2095
|
-
if (!existsSync(CREDENTIALS_FILE))
|
|
2096
|
-
return
|
|
2097
|
-
|
|
2098
|
-
|
|
2098
|
+
if (!existsSync(CREDENTIALS_FILE)) {
|
|
2099
|
+
return { activeProfile: "default", profiles: {} };
|
|
2100
|
+
}
|
|
2101
|
+
const raw = JSON.parse(readFileSync(CREDENTIALS_FILE, "utf-8"));
|
|
2102
|
+
if (raw.accessToken && !raw.profiles) {
|
|
2103
|
+
const migrated = {
|
|
2104
|
+
activeProfile: "default",
|
|
2105
|
+
profiles: { default: raw }
|
|
2106
|
+
};
|
|
2107
|
+
saveStore(migrated);
|
|
2108
|
+
return migrated;
|
|
2109
|
+
}
|
|
2110
|
+
return raw;
|
|
2099
2111
|
} catch {
|
|
2100
|
-
return
|
|
2112
|
+
return { activeProfile: "default", profiles: {} };
|
|
2101
2113
|
}
|
|
2102
2114
|
}
|
|
2103
|
-
function
|
|
2115
|
+
function saveStore(store) {
|
|
2104
2116
|
ensureConfigDir();
|
|
2105
|
-
writeFileSync(CREDENTIALS_FILE, JSON.stringify(
|
|
2117
|
+
writeFileSync(CREDENTIALS_FILE, JSON.stringify(store, null, 2), { mode: 384 });
|
|
2118
|
+
}
|
|
2119
|
+
function resolveProfile() {
|
|
2120
|
+
if (profileOverride)
|
|
2121
|
+
return profileOverride;
|
|
2122
|
+
if (process.env.BAGDOCK_PROFILE)
|
|
2123
|
+
return process.env.BAGDOCK_PROFILE;
|
|
2124
|
+
return loadStore().activeProfile;
|
|
2125
|
+
}
|
|
2126
|
+
function loadCredentials() {
|
|
2127
|
+
const store = loadStore();
|
|
2128
|
+
const name = resolveProfile();
|
|
2129
|
+
return store.profiles[name] ?? null;
|
|
2130
|
+
}
|
|
2131
|
+
function saveCredentials(creds, profileName) {
|
|
2132
|
+
const store = loadStore();
|
|
2133
|
+
const name = profileName ?? resolveProfile();
|
|
2134
|
+
store.profiles[name] = creds;
|
|
2135
|
+
if (!store.activeProfile || Object.keys(store.profiles).length === 1) {
|
|
2136
|
+
store.activeProfile = name;
|
|
2137
|
+
}
|
|
2138
|
+
saveStore(store);
|
|
2106
2139
|
}
|
|
2107
2140
|
function clearCredentials() {
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2111
|
-
|
|
2112
|
-
|
|
2141
|
+
const store = loadStore();
|
|
2142
|
+
const name = resolveProfile();
|
|
2143
|
+
delete store.profiles[name];
|
|
2144
|
+
if (store.activeProfile === name) {
|
|
2145
|
+
const remaining = Object.keys(store.profiles);
|
|
2146
|
+
store.activeProfile = remaining[0] ?? "default";
|
|
2147
|
+
}
|
|
2148
|
+
saveStore(store);
|
|
2149
|
+
}
|
|
2150
|
+
function listProfiles() {
|
|
2151
|
+
const store = loadStore();
|
|
2152
|
+
return Object.entries(store.profiles).map(([name, creds]) => ({
|
|
2153
|
+
name,
|
|
2154
|
+
email: creds.email,
|
|
2155
|
+
operatorId: creds.operatorId,
|
|
2156
|
+
active: name === store.activeProfile
|
|
2157
|
+
}));
|
|
2158
|
+
}
|
|
2159
|
+
function switchProfile(name) {
|
|
2160
|
+
const store = loadStore();
|
|
2161
|
+
if (!store.profiles[name])
|
|
2162
|
+
return false;
|
|
2163
|
+
store.activeProfile = name;
|
|
2164
|
+
saveStore(store);
|
|
2165
|
+
return true;
|
|
2166
|
+
}
|
|
2167
|
+
function getActiveProfileName() {
|
|
2168
|
+
return resolveProfile();
|
|
2113
2169
|
}
|
|
2114
2170
|
function loadBagdockJson(dir) {
|
|
2115
2171
|
const file = join(dir, "bagdock.json");
|
|
@@ -2121,7 +2177,7 @@ function loadBagdockJson(dir) {
|
|
|
2121
2177
|
return null;
|
|
2122
2178
|
}
|
|
2123
2179
|
}
|
|
2124
|
-
var CONFIG_DIR, CREDENTIALS_FILE, API_BASE, DASHBOARD_BASE;
|
|
2180
|
+
var CONFIG_DIR, CREDENTIALS_FILE, API_BASE, DASHBOARD_BASE, profileOverride;
|
|
2125
2181
|
var init_config = __esm(() => {
|
|
2126
2182
|
CONFIG_DIR = join(homedir(), ".bagdock");
|
|
2127
2183
|
CREDENTIALS_FILE = join(CONFIG_DIR, "credentials.json");
|
|
@@ -2618,6 +2674,59 @@ var init_source = __esm(() => {
|
|
|
2618
2674
|
source_default = chalk;
|
|
2619
2675
|
});
|
|
2620
2676
|
|
|
2677
|
+
// src/output.ts
|
|
2678
|
+
function setOutputMode(opts) {
|
|
2679
|
+
quiet = !!opts.quiet;
|
|
2680
|
+
forceJson = !!opts.json || !!opts.quiet;
|
|
2681
|
+
}
|
|
2682
|
+
function isJsonMode() {
|
|
2683
|
+
return forceJson || !process.stdout.isTTY;
|
|
2684
|
+
}
|
|
2685
|
+
function isQuiet() {
|
|
2686
|
+
return quiet;
|
|
2687
|
+
}
|
|
2688
|
+
function outputSuccess(data) {
|
|
2689
|
+
if (isJsonMode()) {
|
|
2690
|
+
process.stdout.write(JSON.stringify(data, null, 2) + `
|
|
2691
|
+
`);
|
|
2692
|
+
}
|
|
2693
|
+
}
|
|
2694
|
+
function outputError(code, message, details) {
|
|
2695
|
+
if (isJsonMode()) {
|
|
2696
|
+
const err = { error: { code, message } };
|
|
2697
|
+
if (details)
|
|
2698
|
+
err.error.details = details;
|
|
2699
|
+
process.stderr.write(JSON.stringify(err) + `
|
|
2700
|
+
`);
|
|
2701
|
+
process.exit(1);
|
|
2702
|
+
} else {
|
|
2703
|
+
console.error(source_default.red(`Error [${code}]:`), message);
|
|
2704
|
+
if (details)
|
|
2705
|
+
console.error(details);
|
|
2706
|
+
process.exit(1);
|
|
2707
|
+
}
|
|
2708
|
+
}
|
|
2709
|
+
function outputList(objectType, data, hasMore) {
|
|
2710
|
+
if (isJsonMode()) {
|
|
2711
|
+
process.stdout.write(JSON.stringify({ object: "list", data, has_more: hasMore }, null, 2) + `
|
|
2712
|
+
`);
|
|
2713
|
+
}
|
|
2714
|
+
}
|
|
2715
|
+
function status(message) {
|
|
2716
|
+
if (!isQuiet() && !isJsonMode()) {
|
|
2717
|
+
console.log(source_default.dim(message));
|
|
2718
|
+
}
|
|
2719
|
+
}
|
|
2720
|
+
function success(message) {
|
|
2721
|
+
if (!isQuiet() && !isJsonMode()) {
|
|
2722
|
+
console.log(source_default.green(message));
|
|
2723
|
+
}
|
|
2724
|
+
}
|
|
2725
|
+
var forceJson = false, quiet = false;
|
|
2726
|
+
var init_output = __esm(() => {
|
|
2727
|
+
init_source();
|
|
2728
|
+
});
|
|
2729
|
+
|
|
2621
2730
|
// node_modules/is-docker/index.js
|
|
2622
2731
|
import fs from "node:fs";
|
|
2623
2732
|
function hasDockerEnv() {
|
|
@@ -3172,6 +3281,18 @@ function getAuthToken() {
|
|
|
3172
3281
|
const creds = loadCredentials();
|
|
3173
3282
|
return creds?.accessToken ?? null;
|
|
3174
3283
|
}
|
|
3284
|
+
function getAuthSource() {
|
|
3285
|
+
if (apiKeyOverride)
|
|
3286
|
+
return { token: apiKeyOverride, source: "flag" };
|
|
3287
|
+
if (process.env.BAGDOCK_API_KEY)
|
|
3288
|
+
return { token: process.env.BAGDOCK_API_KEY, source: "env (BAGDOCK_API_KEY)" };
|
|
3289
|
+
if (process.env.BAGDOCK_TOKEN)
|
|
3290
|
+
return { token: process.env.BAGDOCK_TOKEN, source: "env (BAGDOCK_TOKEN)" };
|
|
3291
|
+
const creds = loadCredentials();
|
|
3292
|
+
if (creds?.accessToken)
|
|
3293
|
+
return { token: creds.accessToken, source: `config (${getActiveProfileName()})` };
|
|
3294
|
+
return { token: null, source: "none" };
|
|
3295
|
+
}
|
|
3175
3296
|
async function login() {
|
|
3176
3297
|
const existing = loadCredentials();
|
|
3177
3298
|
if (existing?.accessToken && existing.expiresAt && existing.expiresAt > Date.now()) {
|
|
@@ -3228,12 +3349,12 @@ Requesting device authorization...
|
|
|
3228
3349
|
console.log(" Email:", source_default.bold(tokens.email));
|
|
3229
3350
|
if (tokens.operator_id)
|
|
3230
3351
|
console.log(" Operator:", source_default.bold(tokens.operator_id));
|
|
3352
|
+
console.log(" Profile:", source_default.bold(getActiveProfileName()));
|
|
3231
3353
|
return;
|
|
3232
3354
|
}
|
|
3233
3355
|
const error = await tokenRes.json().catch(() => ({ error: "unknown" }));
|
|
3234
|
-
if (error.error === "authorization_pending")
|
|
3356
|
+
if (error.error === "authorization_pending")
|
|
3235
3357
|
continue;
|
|
3236
|
-
}
|
|
3237
3358
|
if (error.error === "slow_down") {
|
|
3238
3359
|
await sleep(pollInterval);
|
|
3239
3360
|
continue;
|
|
@@ -3258,7 +3379,7 @@ Requesting device authorization...
|
|
|
3258
3379
|
}
|
|
3259
3380
|
async function logout() {
|
|
3260
3381
|
clearCredentials();
|
|
3261
|
-
console.log(source_default.green(
|
|
3382
|
+
console.log(source_default.green(`Logged out of profile "${getActiveProfileName()}".`));
|
|
3262
3383
|
}
|
|
3263
3384
|
async function whoami() {
|
|
3264
3385
|
const token = getAuthToken();
|
|
@@ -3275,16 +3396,92 @@ async function whoami() {
|
|
|
3275
3396
|
process.exit(1);
|
|
3276
3397
|
}
|
|
3277
3398
|
const user = await res.json();
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3399
|
+
if (isJsonMode()) {
|
|
3400
|
+
outputSuccess({ ...user, profile: getActiveProfileName() });
|
|
3401
|
+
} else {
|
|
3402
|
+
console.log(source_default.green("Logged in as"), source_default.bold(user.email));
|
|
3403
|
+
if (user.operator_id)
|
|
3404
|
+
console.log("Operator:", source_default.bold(user.operator_id));
|
|
3405
|
+
if (user.name)
|
|
3406
|
+
console.log("Name:", user.name);
|
|
3407
|
+
console.log("Profile:", source_default.bold(getActiveProfileName()));
|
|
3408
|
+
}
|
|
3283
3409
|
} catch (err) {
|
|
3284
3410
|
console.log(source_default.red("Failed to reach API:"), err.message);
|
|
3285
3411
|
process.exit(1);
|
|
3286
3412
|
}
|
|
3287
3413
|
}
|
|
3414
|
+
async function authList() {
|
|
3415
|
+
const profiles = listProfiles();
|
|
3416
|
+
if (isJsonMode()) {
|
|
3417
|
+
outputSuccess({ profiles });
|
|
3418
|
+
return;
|
|
3419
|
+
}
|
|
3420
|
+
if (!profiles.length) {
|
|
3421
|
+
console.log(source_default.yellow(`
|
|
3422
|
+
No profiles found.`), "Run", source_default.cyan("bagdock login"), `to create one.
|
|
3423
|
+
`);
|
|
3424
|
+
return;
|
|
3425
|
+
}
|
|
3426
|
+
console.log();
|
|
3427
|
+
for (const p of profiles) {
|
|
3428
|
+
const marker = p.active ? source_default.green("* ") : " ";
|
|
3429
|
+
const label = p.active ? source_default.bold(p.name) : p.name;
|
|
3430
|
+
const email = p.email ? source_default.dim(` (${p.email})`) : "";
|
|
3431
|
+
const op = p.operatorId ? source_default.dim(` [${p.operatorId}]`) : "";
|
|
3432
|
+
console.log(` ${marker}${label}${email}${op}`);
|
|
3433
|
+
}
|
|
3434
|
+
console.log();
|
|
3435
|
+
}
|
|
3436
|
+
async function authSwitch(name) {
|
|
3437
|
+
const profiles = listProfiles();
|
|
3438
|
+
if (!profiles.length) {
|
|
3439
|
+
console.log(source_default.yellow("No profiles found."), "Run", source_default.cyan("bagdock login"), "first.");
|
|
3440
|
+
process.exit(1);
|
|
3441
|
+
}
|
|
3442
|
+
if (name) {
|
|
3443
|
+
if (switchProfile(name)) {
|
|
3444
|
+
if (isJsonMode()) {
|
|
3445
|
+
outputSuccess({ active_profile: name });
|
|
3446
|
+
} else {
|
|
3447
|
+
console.log(source_default.green(`Switched to profile "${name}".`));
|
|
3448
|
+
}
|
|
3449
|
+
} else {
|
|
3450
|
+
outputError("NOT_FOUND", `Profile "${name}" not found. Available: ${profiles.map((p) => p.name).join(", ")}`);
|
|
3451
|
+
}
|
|
3452
|
+
return;
|
|
3453
|
+
}
|
|
3454
|
+
if (!process.stdout.isTTY) {
|
|
3455
|
+
outputError("MISSING_PROFILE", "Pass a profile name in non-interactive mode: bagdock auth switch <name>");
|
|
3456
|
+
}
|
|
3457
|
+
console.log(source_default.cyan(`
|
|
3458
|
+
Available profiles:
|
|
3459
|
+
`));
|
|
3460
|
+
profiles.forEach((p, i) => {
|
|
3461
|
+
const marker = p.active ? source_default.green("* ") : " ";
|
|
3462
|
+
const email = p.email ? source_default.dim(` (${p.email})`) : "";
|
|
3463
|
+
console.log(` ${marker}${i + 1}. ${p.name}${email}`);
|
|
3464
|
+
});
|
|
3465
|
+
const readline = await import("readline");
|
|
3466
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
3467
|
+
const answer = await new Promise((resolve) => {
|
|
3468
|
+
rl.question(source_default.cyan(`
|
|
3469
|
+
Enter profile number or name: `), resolve);
|
|
3470
|
+
});
|
|
3471
|
+
rl.close();
|
|
3472
|
+
const idx = parseInt(answer, 10);
|
|
3473
|
+
const target = idx > 0 && idx <= profiles.length ? profiles[idx - 1].name : answer.trim();
|
|
3474
|
+
if (switchProfile(target)) {
|
|
3475
|
+
console.log(source_default.green(`
|
|
3476
|
+
Switched to profile "${target}".
|
|
3477
|
+
`));
|
|
3478
|
+
} else {
|
|
3479
|
+
console.log(source_default.red(`
|
|
3480
|
+
Profile "${target}" not found.
|
|
3481
|
+
`));
|
|
3482
|
+
process.exit(1);
|
|
3483
|
+
}
|
|
3484
|
+
}
|
|
3288
3485
|
function sleep(ms) {
|
|
3289
3486
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
3290
3487
|
}
|
|
@@ -3292,64 +3489,136 @@ var apiKeyOverride, CLIENT_ID = "bagdock-cli", MAX_POLL_DURATION_MS = 300000;
|
|
|
3292
3489
|
var init_auth = __esm(() => {
|
|
3293
3490
|
init_config();
|
|
3294
3491
|
init_source();
|
|
3492
|
+
init_output();
|
|
3295
3493
|
});
|
|
3296
3494
|
|
|
3297
|
-
// src/
|
|
3298
|
-
|
|
3299
|
-
|
|
3300
|
-
|
|
3301
|
-
|
|
3495
|
+
// src/doctor.ts
|
|
3496
|
+
var exports_doctor = {};
|
|
3497
|
+
__export(exports_doctor, {
|
|
3498
|
+
doctor: () => doctor
|
|
3499
|
+
});
|
|
3500
|
+
import { existsSync as existsSync3, readFileSync as readFileSync2 } from "fs";
|
|
3501
|
+
import { join as join3, dirname } from "path";
|
|
3502
|
+
import { homedir as homedir2, platform as platform2 } from "os";
|
|
3503
|
+
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
3504
|
+
function maskKey(key) {
|
|
3505
|
+
if (key.length <= 12)
|
|
3506
|
+
return key.slice(0, 4) + "...";
|
|
3507
|
+
return key.slice(0, 8) + "..." + key.slice(-4);
|
|
3508
|
+
}
|
|
3509
|
+
function getLocalVersion() {
|
|
3510
|
+
try {
|
|
3511
|
+
const pkgPath = join3(dirname(fileURLToPath2(import.meta.url)), "..", "package.json");
|
|
3512
|
+
const pkg = JSON.parse(readFileSync2(pkgPath, "utf-8"));
|
|
3513
|
+
return pkg.version ?? "unknown";
|
|
3514
|
+
} catch {
|
|
3515
|
+
return "unknown";
|
|
3302
3516
|
}
|
|
3303
|
-
|
|
3304
|
-
|
|
3517
|
+
}
|
|
3518
|
+
async function checkVersion() {
|
|
3519
|
+
const local = getLocalVersion();
|
|
3520
|
+
try {
|
|
3521
|
+
const res = await fetch("https://registry.npmjs.org/@bagdock/cli/latest", {
|
|
3522
|
+
signal: AbortSignal.timeout(5000)
|
|
3523
|
+
});
|
|
3524
|
+
if (res.ok) {
|
|
3525
|
+
const data = await res.json();
|
|
3526
|
+
if (data.version === local) {
|
|
3527
|
+
return { name: "CLI Version", status: "pass", message: `v${local} (latest)` };
|
|
3528
|
+
}
|
|
3529
|
+
return { name: "CLI Version", status: "warn", message: `v${local} (update available: v${data.version})` };
|
|
3530
|
+
}
|
|
3531
|
+
} catch {}
|
|
3532
|
+
return { name: "CLI Version", status: "pass", message: `v${local} (registry unreachable)` };
|
|
3533
|
+
}
|
|
3534
|
+
function checkAuth() {
|
|
3535
|
+
const { token, source } = getAuthSource();
|
|
3536
|
+
if (!token) {
|
|
3537
|
+
return { name: "API Key", status: "fail", message: "No API key found. Run `bagdock login` or set BAGDOCK_API_KEY." };
|
|
3305
3538
|
}
|
|
3539
|
+
return { name: "API Key", status: "pass", message: `${maskKey(token)} (source: ${source})` };
|
|
3306
3540
|
}
|
|
3307
|
-
function
|
|
3308
|
-
|
|
3541
|
+
function checkProjectConfig() {
|
|
3542
|
+
const config = loadBagdockJson(process.cwd());
|
|
3543
|
+
if (!config) {
|
|
3544
|
+
return { name: "Project Config", status: "warn", message: "No bagdock.json found in current directory" };
|
|
3545
|
+
}
|
|
3546
|
+
const issues = [];
|
|
3547
|
+
if (!config.slug)
|
|
3548
|
+
issues.push("missing slug");
|
|
3549
|
+
if (!config.type)
|
|
3550
|
+
issues.push("missing type");
|
|
3551
|
+
if (!config.main)
|
|
3552
|
+
issues.push("missing main");
|
|
3553
|
+
if (issues.length) {
|
|
3554
|
+
return { name: "Project Config", status: "warn", message: `bagdock.json has issues: ${issues.join(", ")}` };
|
|
3555
|
+
}
|
|
3556
|
+
return { name: "Project Config", status: "pass", message: `${config.slug} (${config.type}/${config.kind ?? config.category})` };
|
|
3309
3557
|
}
|
|
3310
|
-
function
|
|
3311
|
-
|
|
3558
|
+
function checkAgents() {
|
|
3559
|
+
const detected = [];
|
|
3560
|
+
const home = homedir2();
|
|
3561
|
+
if (existsSync3(join3(home, ".cursor")))
|
|
3562
|
+
detected.push("Cursor");
|
|
3563
|
+
if (existsSync3(join3(home, ".windsurf")))
|
|
3564
|
+
detected.push("Windsurf");
|
|
3565
|
+
if (existsSync3(join3(home, "clawd", "skills")) || existsSync3(join3(home, ".codex")))
|
|
3566
|
+
detected.push("OpenClaw/Codex");
|
|
3567
|
+
const p = platform2();
|
|
3568
|
+
if (p === "darwin" && existsSync3(join3(home, "Library", "Application Support", "Claude", "claude_desktop_config.json"))) {
|
|
3569
|
+
detected.push("Claude Desktop");
|
|
3570
|
+
} else if (p === "win32" && existsSync3(join3(process.env.APPDATA ?? "", "Claude", "claude_desktop_config.json"))) {
|
|
3571
|
+
detected.push("Claude Desktop");
|
|
3572
|
+
} else if (p === "linux" && existsSync3(join3(home, ".config", "Claude", "claude_desktop_config.json"))) {
|
|
3573
|
+
detected.push("Claude Desktop");
|
|
3574
|
+
}
|
|
3575
|
+
if (existsSync3(join3(process.cwd(), ".vscode", "mcp.json")))
|
|
3576
|
+
detected.push("VS Code");
|
|
3577
|
+
if (!detected.length) {
|
|
3578
|
+
return { name: "AI Agents", status: "pass", message: "None detected" };
|
|
3579
|
+
}
|
|
3580
|
+
return { name: "AI Agents", status: "pass", message: `Detected: ${detected.join(", ")}` };
|
|
3312
3581
|
}
|
|
3313
|
-
function
|
|
3582
|
+
async function doctor() {
|
|
3583
|
+
const checks = [];
|
|
3314
3584
|
if (isJsonMode()) {
|
|
3315
|
-
|
|
3316
|
-
|
|
3585
|
+
checks.push(await checkVersion());
|
|
3586
|
+
checks.push(checkAuth());
|
|
3587
|
+
checks.push(checkProjectConfig());
|
|
3588
|
+
checks.push(checkAgents());
|
|
3589
|
+
const ok = checks.every((c) => c.status !== "fail");
|
|
3590
|
+
outputSuccess({ ok, checks });
|
|
3591
|
+
return;
|
|
3317
3592
|
}
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3593
|
+
console.log(source_default.bold(`
|
|
3594
|
+
Bagdock Doctor
|
|
3595
|
+
`));
|
|
3596
|
+
process.stdout.write(" Checking CLI version...");
|
|
3597
|
+
const versionCheck = await checkVersion();
|
|
3598
|
+
checks.push(versionCheck);
|
|
3599
|
+
process.stdout.write(`\r ${ICON[versionCheck.status]} ${versionCheck.name}: ${versionCheck.message}
|
|
3325
3600
|
`);
|
|
3601
|
+
const authCheck = checkAuth();
|
|
3602
|
+
checks.push(authCheck);
|
|
3603
|
+
console.log(` ${ICON[authCheck.status]} ${authCheck.name}: ${authCheck.message}`);
|
|
3604
|
+
const configCheck = checkProjectConfig();
|
|
3605
|
+
checks.push(configCheck);
|
|
3606
|
+
console.log(` ${ICON[configCheck.status]} ${configCheck.name}: ${configCheck.message}`);
|
|
3607
|
+
const agentCheck = checkAgents();
|
|
3608
|
+
checks.push(agentCheck);
|
|
3609
|
+
console.log(` ${ICON[agentCheck.status]} ${agentCheck.name}: ${agentCheck.message}`);
|
|
3610
|
+
console.log();
|
|
3611
|
+
const hasFail = checks.some((c) => c.status === "fail");
|
|
3612
|
+
if (hasFail)
|
|
3326
3613
|
process.exit(1);
|
|
3327
|
-
} else {
|
|
3328
|
-
console.error(source_default.red(`Error [${code}]:`), message);
|
|
3329
|
-
if (details)
|
|
3330
|
-
console.error(details);
|
|
3331
|
-
process.exit(1);
|
|
3332
|
-
}
|
|
3333
3614
|
}
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
process.stdout.write(JSON.stringify({ object: "list", data, has_more: hasMore }, null, 2) + `
|
|
3337
|
-
`);
|
|
3338
|
-
}
|
|
3339
|
-
}
|
|
3340
|
-
function status(message) {
|
|
3341
|
-
if (!isQuiet() && !isJsonMode()) {
|
|
3342
|
-
console.log(source_default.dim(message));
|
|
3343
|
-
}
|
|
3344
|
-
}
|
|
3345
|
-
function success(message) {
|
|
3346
|
-
if (!isQuiet() && !isJsonMode()) {
|
|
3347
|
-
console.log(source_default.green(message));
|
|
3348
|
-
}
|
|
3349
|
-
}
|
|
3350
|
-
var forceJson = false, quiet = false;
|
|
3351
|
-
var init_output = __esm(() => {
|
|
3615
|
+
var ICON;
|
|
3616
|
+
var init_doctor = __esm(() => {
|
|
3352
3617
|
init_source();
|
|
3618
|
+
init_auth();
|
|
3619
|
+
init_config();
|
|
3620
|
+
init_output();
|
|
3621
|
+
ICON = { pass: source_default.green("✔"), warn: source_default.yellow("!"), fail: source_default.red("✘") };
|
|
3353
3622
|
});
|
|
3354
3623
|
|
|
3355
3624
|
// src/dev.ts
|
|
@@ -3357,8 +3626,8 @@ var exports_dev = {};
|
|
|
3357
3626
|
__export(exports_dev, {
|
|
3358
3627
|
dev: () => dev
|
|
3359
3628
|
});
|
|
3360
|
-
import { existsSync as
|
|
3361
|
-
import { join as
|
|
3629
|
+
import { existsSync as existsSync4, writeFileSync as writeFileSync3 } from "fs";
|
|
3630
|
+
import { join as join4 } from "path";
|
|
3362
3631
|
import { spawn } from "child_process";
|
|
3363
3632
|
async function dev(opts) {
|
|
3364
3633
|
const cwd = process.cwd();
|
|
@@ -3369,11 +3638,11 @@ async function dev(opts) {
|
|
|
3369
3638
|
}
|
|
3370
3639
|
const port = opts.port ?? "8787";
|
|
3371
3640
|
const wranglerToml = generateWranglerToml(config, port);
|
|
3372
|
-
const wranglerPath =
|
|
3641
|
+
const wranglerPath = join4(cwd, "wrangler.toml");
|
|
3373
3642
|
writeFileSync3(wranglerPath, wranglerToml);
|
|
3374
3643
|
console.log(source_default.green("Generated"), source_default.cyan("wrangler.toml"), source_default.green("from bagdock.json"));
|
|
3375
|
-
const devVarsPath =
|
|
3376
|
-
if (!
|
|
3644
|
+
const devVarsPath = join4(cwd, ".dev.vars");
|
|
3645
|
+
if (!existsSync4(devVarsPath) && config.env) {
|
|
3377
3646
|
const hint = Object.entries(config.env).map(([key, meta]) => `# ${meta.description ?? key}${meta.required ? " (required)" : ""}
|
|
3378
3647
|
${key}=`).join(`
|
|
3379
3648
|
`);
|
|
@@ -3434,8 +3703,8 @@ var exports_deploy = {};
|
|
|
3434
3703
|
__export(exports_deploy, {
|
|
3435
3704
|
deploy: () => deploy
|
|
3436
3705
|
});
|
|
3437
|
-
import { existsSync as
|
|
3438
|
-
import { join as
|
|
3706
|
+
import { existsSync as existsSync5, readFileSync as readFileSync3 } from "fs";
|
|
3707
|
+
import { join as join5 } from "path";
|
|
3439
3708
|
import { execSync } from "child_process";
|
|
3440
3709
|
import { createInterface } from "readline";
|
|
3441
3710
|
async function deploy(opts) {
|
|
@@ -3476,8 +3745,8 @@ async function deploy(opts) {
|
|
|
3476
3745
|
console.log(source_default.cyan(`
|
|
3477
3746
|
Deploying ${config.slug}@${config.version} → ${envLabel}
|
|
3478
3747
|
`));
|
|
3479
|
-
const outDir =
|
|
3480
|
-
const outFile =
|
|
3748
|
+
const outDir = join5(cwd, ".bagdock");
|
|
3749
|
+
const outFile = join5(outDir, "worker.mjs");
|
|
3481
3750
|
console.log(source_default.dim(" Building worker bundle..."));
|
|
3482
3751
|
execSync(`mkdir -p ${outDir}`, { cwd });
|
|
3483
3752
|
try {
|
|
@@ -3493,11 +3762,11 @@ Deploying ${config.slug}@${config.version} → ${envLabel}
|
|
|
3493
3762
|
process.exit(1);
|
|
3494
3763
|
}
|
|
3495
3764
|
}
|
|
3496
|
-
if (!
|
|
3765
|
+
if (!existsSync5(outFile)) {
|
|
3497
3766
|
console.error(source_default.red(" Build output not found at"), outFile);
|
|
3498
3767
|
process.exit(1);
|
|
3499
3768
|
}
|
|
3500
|
-
const scriptContent =
|
|
3769
|
+
const scriptContent = readFileSync3(outFile);
|
|
3501
3770
|
const sizeKb = (scriptContent.length / 1024).toFixed(1);
|
|
3502
3771
|
console.log(source_default.dim(` Bundle size: ${sizeKb} KB`));
|
|
3503
3772
|
console.log(source_default.dim(" Uploading to Bagdock platform..."));
|
|
@@ -4304,16 +4573,26 @@ function toPascalCase(s) {
|
|
|
4304
4573
|
|
|
4305
4574
|
// bin/bagdock.ts
|
|
4306
4575
|
init_output();
|
|
4576
|
+
init_config();
|
|
4307
4577
|
var program2 = new Command;
|
|
4308
|
-
program2.name("bagdock").description("Bagdock developer CLI").version("0.
|
|
4578
|
+
program2.name("bagdock").description("Bagdock developer CLI — built for humans, AI agents, and CI/CD pipelines").version("0.3.0").option("--json", "Force JSON output (auto-enabled in non-TTY)").option("-q, --quiet", "Suppress status messages (implies --json)").option("--api-key <key>", "API key to use for this invocation").option("-p, --profile <name>", "Profile to use (overrides BAGDOCK_PROFILE)").hook("preAction", (_thisCommand, actionCommand) => {
|
|
4309
4579
|
const opts = program2.opts();
|
|
4310
4580
|
setOutputMode({ json: opts.json, quiet: opts.quiet });
|
|
4311
4581
|
if (opts.apiKey)
|
|
4312
4582
|
setApiKeyOverride(opts.apiKey);
|
|
4583
|
+
if (opts.profile)
|
|
4584
|
+
setProfileOverride(opts.profile);
|
|
4313
4585
|
});
|
|
4314
4586
|
program2.command("login").description("Authenticate with Bagdock (opens browser)").action(login);
|
|
4315
4587
|
program2.command("logout").description("Clear stored credentials").action(logout);
|
|
4316
4588
|
program2.command("whoami").description("Show current authenticated user").action(whoami);
|
|
4589
|
+
var authCmd = program2.command("auth").description("Manage authentication profiles");
|
|
4590
|
+
authCmd.command("list").description("List all stored profiles").action(authList);
|
|
4591
|
+
authCmd.command("switch [name]").description("Switch active profile").action(async (name) => authSwitch(name));
|
|
4592
|
+
program2.command("doctor").description("Run environment diagnostics").action(async () => {
|
|
4593
|
+
const { doctor: doctor2 } = await Promise.resolve().then(() => (init_doctor(), exports_doctor));
|
|
4594
|
+
await doctor2();
|
|
4595
|
+
});
|
|
4317
4596
|
program2.command("init [dir]").description("Scaffold a new project with bagdock.json").option("-t, --type <type>", "Project type (edge, app)").option("-k, --kind <kind>", "Project kind (adapter, comms, webhook, ui-extension, microfrontend)").option("-c, --category <category>", "Category").option("-s, --slug <slug>", "Unique project slug").option("-n, --name <name>", "Display name").action((dir, opts) => init(dir ?? ".", opts));
|
|
4318
4597
|
program2.command("dev").description("Start local dev server").option("-p, --port <port>", "Local dev port", "8787").action(async (opts) => {
|
|
4319
4598
|
const { dev: dev2 } = await Promise.resolve().then(() => (init_dev(), exports_dev));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bagdock/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Bagdock developer CLI — build, test, and deploy apps and edges on the Bagdock platform",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"bagdock",
|
|
@@ -28,8 +28,14 @@
|
|
|
28
28
|
"files": [
|
|
29
29
|
"dist",
|
|
30
30
|
"README.md",
|
|
31
|
-
"LICENSE"
|
|
31
|
+
"LICENSE",
|
|
32
|
+
"skills",
|
|
33
|
+
"skill-evals"
|
|
32
34
|
],
|
|
35
|
+
"skills": {
|
|
36
|
+
"name": "bagdock-cli",
|
|
37
|
+
"path": "skills/bagdock-cli"
|
|
38
|
+
},
|
|
33
39
|
"publishConfig": {
|
|
34
40
|
"access": "public"
|
|
35
41
|
},
|
|
@@ -37,15 +43,18 @@
|
|
|
37
43
|
"dev": "bun run bin/bagdock.ts",
|
|
38
44
|
"build": "bun build bin/bagdock.ts --outdir dist --target node --format esm && node -e \"const fs=require('fs');const f='dist/bagdock.js';let c=fs.readFileSync(f,'utf8');c=c.replace(/^#!.*\\n/,'').replace(/^\\/\\/ @bun\\n/,'');fs.writeFileSync(f,'#!/usr/bin/env node\\n'+c)\"",
|
|
39
45
|
"prepublishOnly": "bun run build",
|
|
46
|
+
"test": "vitest run",
|
|
47
|
+
"test:watch": "vitest",
|
|
40
48
|
"typecheck": "tsc --noEmit"
|
|
41
49
|
},
|
|
42
50
|
"dependencies": {
|
|
51
|
+
"chalk": "^5.4.1",
|
|
43
52
|
"commander": "^13.1.0",
|
|
44
|
-
"open": "^10.1.0"
|
|
45
|
-
"chalk": "^5.4.1"
|
|
53
|
+
"open": "^10.1.0"
|
|
46
54
|
},
|
|
47
55
|
"devDependencies": {
|
|
48
56
|
"@types/bun": "latest",
|
|
49
|
-
"typescript": "^5.3.3"
|
|
57
|
+
"typescript": "^5.3.3",
|
|
58
|
+
"vitest": "^3.2.4"
|
|
50
59
|
}
|
|
51
60
|
}
|