@vibedrift/cli 0.3.0 → 0.3.1
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/dist/index.js +172 -97
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -7889,6 +7889,104 @@ function previewToken(token) {
|
|
|
7889
7889
|
return token.slice(0, 12) + "\u2026";
|
|
7890
7890
|
}
|
|
7891
7891
|
|
|
7892
|
+
// src/auth/api.ts
|
|
7893
|
+
init_esm_shims();
|
|
7894
|
+
var REQUEST_TIMEOUT_MS = 3e4;
|
|
7895
|
+
var VibeDriftApiError = class extends Error {
|
|
7896
|
+
constructor(status, message) {
|
|
7897
|
+
super(message);
|
|
7898
|
+
this.status = status;
|
|
7899
|
+
this.name = "VibeDriftApiError";
|
|
7900
|
+
}
|
|
7901
|
+
status;
|
|
7902
|
+
};
|
|
7903
|
+
async function jsonFetch(url, init = {}) {
|
|
7904
|
+
const controller = new AbortController();
|
|
7905
|
+
const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
7906
|
+
try {
|
|
7907
|
+
const res = await fetch(url, {
|
|
7908
|
+
...init,
|
|
7909
|
+
signal: controller.signal,
|
|
7910
|
+
headers: {
|
|
7911
|
+
Accept: "application/json",
|
|
7912
|
+
...init.body ? { "Content-Type": "application/json" } : {},
|
|
7913
|
+
...init.headers ?? {}
|
|
7914
|
+
}
|
|
7915
|
+
});
|
|
7916
|
+
if (!res.ok) {
|
|
7917
|
+
let detail = "";
|
|
7918
|
+
try {
|
|
7919
|
+
const body = await res.json();
|
|
7920
|
+
detail = body.detail ?? body.message ?? "";
|
|
7921
|
+
} catch {
|
|
7922
|
+
try {
|
|
7923
|
+
detail = await res.text();
|
|
7924
|
+
} catch {
|
|
7925
|
+
}
|
|
7926
|
+
}
|
|
7927
|
+
throw new VibeDriftApiError(res.status, detail || `HTTP ${res.status}`);
|
|
7928
|
+
}
|
|
7929
|
+
return await res.json();
|
|
7930
|
+
} catch (err) {
|
|
7931
|
+
if (err?.name === "AbortError") {
|
|
7932
|
+
throw new VibeDriftApiError(0, `Request timed out after ${REQUEST_TIMEOUT_MS / 1e3}s`);
|
|
7933
|
+
}
|
|
7934
|
+
if (err instanceof VibeDriftApiError) throw err;
|
|
7935
|
+
throw new VibeDriftApiError(0, err?.message ?? String(err));
|
|
7936
|
+
} finally {
|
|
7937
|
+
clearTimeout(timer);
|
|
7938
|
+
}
|
|
7939
|
+
}
|
|
7940
|
+
async function startDeviceAuth(opts) {
|
|
7941
|
+
const base = await resolveApiUrl(opts?.apiUrl);
|
|
7942
|
+
return jsonFetch(`${base}/auth/device`, {
|
|
7943
|
+
method: "POST",
|
|
7944
|
+
body: JSON.stringify({ client_id: "vibedrift-cli" })
|
|
7945
|
+
});
|
|
7946
|
+
}
|
|
7947
|
+
async function pollDeviceAuth(deviceCode, opts) {
|
|
7948
|
+
const base = await resolveApiUrl(opts?.apiUrl);
|
|
7949
|
+
return jsonFetch(`${base}/auth/poll`, {
|
|
7950
|
+
method: "POST",
|
|
7951
|
+
body: JSON.stringify({ device_code: deviceCode })
|
|
7952
|
+
});
|
|
7953
|
+
}
|
|
7954
|
+
async function validateToken(token, opts) {
|
|
7955
|
+
const base = await resolveApiUrl(opts?.apiUrl);
|
|
7956
|
+
return jsonFetch(`${base}/auth/validate`, {
|
|
7957
|
+
method: "GET",
|
|
7958
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
7959
|
+
});
|
|
7960
|
+
}
|
|
7961
|
+
async function revokeToken(token, opts) {
|
|
7962
|
+
const base = await resolveApiUrl(opts?.apiUrl);
|
|
7963
|
+
await jsonFetch(`${base}/auth/revoke`, {
|
|
7964
|
+
method: "POST",
|
|
7965
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
7966
|
+
});
|
|
7967
|
+
}
|
|
7968
|
+
async function fetchUsage(token, opts) {
|
|
7969
|
+
const base = await resolveApiUrl(opts?.apiUrl);
|
|
7970
|
+
return jsonFetch(`${base}/account/usage`, {
|
|
7971
|
+
method: "GET",
|
|
7972
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
7973
|
+
});
|
|
7974
|
+
}
|
|
7975
|
+
async function fetchCredits(token, opts) {
|
|
7976
|
+
const base = await resolveApiUrl(opts?.apiUrl);
|
|
7977
|
+
return jsonFetch(`${base}/account/credits`, {
|
|
7978
|
+
method: "GET",
|
|
7979
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
7980
|
+
});
|
|
7981
|
+
}
|
|
7982
|
+
async function createPortalSession(token, opts) {
|
|
7983
|
+
const base = await resolveApiUrl(opts?.apiUrl);
|
|
7984
|
+
return jsonFetch(`${base}/account/portal`, {
|
|
7985
|
+
method: "POST",
|
|
7986
|
+
headers: { Authorization: `Bearer ${token}` }
|
|
7987
|
+
});
|
|
7988
|
+
}
|
|
7989
|
+
|
|
7892
7990
|
// src/cli/commands/scan.ts
|
|
7893
7991
|
async function runScan(targetPath, options) {
|
|
7894
7992
|
const rootDir = resolve(targetPath);
|
|
@@ -7910,7 +8008,9 @@ async function runScan(targetPath, options) {
|
|
|
7910
8008
|
console.error("");
|
|
7911
8009
|
console.error(chalk2.red(" \u2717 Deep scans require a VibeDrift account."));
|
|
7912
8010
|
console.error("");
|
|
7913
|
-
console.error(
|
|
8011
|
+
console.error(chalk2.bgYellow.black.bold(" \u{1F381} But your first deep scan is FREE. "));
|
|
8012
|
+
console.error("");
|
|
8013
|
+
console.error(" Run " + chalk2.bold("vibedrift login") + " to sign in and claim it.");
|
|
7914
8014
|
console.error(" Or set " + chalk2.bold("VIBEDRIFT_TOKEN") + " in your environment for CI.");
|
|
7915
8015
|
console.error("");
|
|
7916
8016
|
process.exit(1);
|
|
@@ -7927,6 +8027,25 @@ async function runScan(targetPath, options) {
|
|
|
7927
8027
|
} catch {
|
|
7928
8028
|
}
|
|
7929
8029
|
}
|
|
8030
|
+
if (!options.json && options.format !== "json" && !options.deep) {
|
|
8031
|
+
if (bearerToken) {
|
|
8032
|
+
try {
|
|
8033
|
+
const credits = await fetchCredits(bearerToken, { apiUrl });
|
|
8034
|
+
if (credits.has_free_deep_scan && !credits.unlimited) {
|
|
8035
|
+
console.log("");
|
|
8036
|
+
console.log(chalk2.bgYellow.black.bold(" \u{1F381} 1 FREE DEEP SCAN AVAILABLE "));
|
|
8037
|
+
console.log(chalk2.yellow(" Run with ") + chalk2.bold.cyan("--deep") + chalk2.yellow(" to use Claude-powered analysis (no card required)."));
|
|
8038
|
+
console.log("");
|
|
8039
|
+
}
|
|
8040
|
+
} catch {
|
|
8041
|
+
}
|
|
8042
|
+
} else {
|
|
8043
|
+
console.log("");
|
|
8044
|
+
console.log(chalk2.dim(" Tip: ") + chalk2.yellow("sign up free to get 1 deep scan included"));
|
|
8045
|
+
console.log(chalk2.dim(" Run ") + chalk2.bold("vibedrift login") + chalk2.dim(" to claim it (no card required)."));
|
|
8046
|
+
console.log("");
|
|
8047
|
+
}
|
|
8048
|
+
}
|
|
7930
8049
|
const startTime = Date.now();
|
|
7931
8050
|
const timings = {};
|
|
7932
8051
|
const isTerminal = options.format === "terminal" && !options.json;
|
|
@@ -8281,97 +8400,6 @@ Update failed: ${message}`));
|
|
|
8281
8400
|
init_esm_shims();
|
|
8282
8401
|
import chalk4 from "chalk";
|
|
8283
8402
|
|
|
8284
|
-
// src/auth/api.ts
|
|
8285
|
-
init_esm_shims();
|
|
8286
|
-
var REQUEST_TIMEOUT_MS = 3e4;
|
|
8287
|
-
var VibeDriftApiError = class extends Error {
|
|
8288
|
-
constructor(status, message) {
|
|
8289
|
-
super(message);
|
|
8290
|
-
this.status = status;
|
|
8291
|
-
this.name = "VibeDriftApiError";
|
|
8292
|
-
}
|
|
8293
|
-
status;
|
|
8294
|
-
};
|
|
8295
|
-
async function jsonFetch(url, init = {}) {
|
|
8296
|
-
const controller = new AbortController();
|
|
8297
|
-
const timer = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
8298
|
-
try {
|
|
8299
|
-
const res = await fetch(url, {
|
|
8300
|
-
...init,
|
|
8301
|
-
signal: controller.signal,
|
|
8302
|
-
headers: {
|
|
8303
|
-
Accept: "application/json",
|
|
8304
|
-
...init.body ? { "Content-Type": "application/json" } : {},
|
|
8305
|
-
...init.headers ?? {}
|
|
8306
|
-
}
|
|
8307
|
-
});
|
|
8308
|
-
if (!res.ok) {
|
|
8309
|
-
let detail = "";
|
|
8310
|
-
try {
|
|
8311
|
-
const body = await res.json();
|
|
8312
|
-
detail = body.detail ?? body.message ?? "";
|
|
8313
|
-
} catch {
|
|
8314
|
-
try {
|
|
8315
|
-
detail = await res.text();
|
|
8316
|
-
} catch {
|
|
8317
|
-
}
|
|
8318
|
-
}
|
|
8319
|
-
throw new VibeDriftApiError(res.status, detail || `HTTP ${res.status}`);
|
|
8320
|
-
}
|
|
8321
|
-
return await res.json();
|
|
8322
|
-
} catch (err) {
|
|
8323
|
-
if (err?.name === "AbortError") {
|
|
8324
|
-
throw new VibeDriftApiError(0, `Request timed out after ${REQUEST_TIMEOUT_MS / 1e3}s`);
|
|
8325
|
-
}
|
|
8326
|
-
if (err instanceof VibeDriftApiError) throw err;
|
|
8327
|
-
throw new VibeDriftApiError(0, err?.message ?? String(err));
|
|
8328
|
-
} finally {
|
|
8329
|
-
clearTimeout(timer);
|
|
8330
|
-
}
|
|
8331
|
-
}
|
|
8332
|
-
async function startDeviceAuth(opts) {
|
|
8333
|
-
const base = await resolveApiUrl(opts?.apiUrl);
|
|
8334
|
-
return jsonFetch(`${base}/auth/device`, {
|
|
8335
|
-
method: "POST",
|
|
8336
|
-
body: JSON.stringify({ client_id: "vibedrift-cli" })
|
|
8337
|
-
});
|
|
8338
|
-
}
|
|
8339
|
-
async function pollDeviceAuth(deviceCode, opts) {
|
|
8340
|
-
const base = await resolveApiUrl(opts?.apiUrl);
|
|
8341
|
-
return jsonFetch(`${base}/auth/poll`, {
|
|
8342
|
-
method: "POST",
|
|
8343
|
-
body: JSON.stringify({ device_code: deviceCode })
|
|
8344
|
-
});
|
|
8345
|
-
}
|
|
8346
|
-
async function validateToken(token, opts) {
|
|
8347
|
-
const base = await resolveApiUrl(opts?.apiUrl);
|
|
8348
|
-
return jsonFetch(`${base}/auth/validate`, {
|
|
8349
|
-
method: "GET",
|
|
8350
|
-
headers: { Authorization: `Bearer ${token}` }
|
|
8351
|
-
});
|
|
8352
|
-
}
|
|
8353
|
-
async function revokeToken(token, opts) {
|
|
8354
|
-
const base = await resolveApiUrl(opts?.apiUrl);
|
|
8355
|
-
await jsonFetch(`${base}/auth/revoke`, {
|
|
8356
|
-
method: "POST",
|
|
8357
|
-
headers: { Authorization: `Bearer ${token}` }
|
|
8358
|
-
});
|
|
8359
|
-
}
|
|
8360
|
-
async function fetchUsage(token, opts) {
|
|
8361
|
-
const base = await resolveApiUrl(opts?.apiUrl);
|
|
8362
|
-
return jsonFetch(`${base}/account/usage`, {
|
|
8363
|
-
method: "GET",
|
|
8364
|
-
headers: { Authorization: `Bearer ${token}` }
|
|
8365
|
-
});
|
|
8366
|
-
}
|
|
8367
|
-
async function createPortalSession(token, opts) {
|
|
8368
|
-
const base = await resolveApiUrl(opts?.apiUrl);
|
|
8369
|
-
return jsonFetch(`${base}/account/portal`, {
|
|
8370
|
-
method: "POST",
|
|
8371
|
-
headers: { Authorization: `Bearer ${token}` }
|
|
8372
|
-
});
|
|
8373
|
-
}
|
|
8374
|
-
|
|
8375
8403
|
// src/auth/browser.ts
|
|
8376
8404
|
init_esm_shims();
|
|
8377
8405
|
import { spawn as spawn2 } from "child_process";
|
|
@@ -8478,11 +8506,43 @@ async function runLogin(options = {}) {
|
|
|
8478
8506
|
console.log(` Account: ${chalk4.bold(result.email)}`);
|
|
8479
8507
|
console.log(` Plan: ${chalk4.bold(result.plan)}`);
|
|
8480
8508
|
console.log("");
|
|
8481
|
-
|
|
8482
|
-
|
|
8483
|
-
|
|
8484
|
-
|
|
8485
|
-
|
|
8509
|
+
try {
|
|
8510
|
+
const credits = await fetchCredits(result.access_token, {
|
|
8511
|
+
apiUrl: options.apiUrl
|
|
8512
|
+
});
|
|
8513
|
+
if (credits.has_free_deep_scan && !credits.unlimited) {
|
|
8514
|
+
console.log(
|
|
8515
|
+
chalk4.bgYellow.black.bold(" \u{1F381} 1 FREE deep scan included with your account ")
|
|
8516
|
+
);
|
|
8517
|
+
console.log("");
|
|
8518
|
+
console.log(
|
|
8519
|
+
chalk4.yellow(" Try the full pipeline (Claude analysis, security review,")
|
|
8520
|
+
);
|
|
8521
|
+
console.log(
|
|
8522
|
+
chalk4.yellow(" AI-powered drift detection) on any project \u2014 no card needed.")
|
|
8523
|
+
);
|
|
8524
|
+
console.log("");
|
|
8525
|
+
console.log(` ${chalk4.cyan("vibedrift . --deep")}`);
|
|
8526
|
+
console.log("");
|
|
8527
|
+
} else if (credits.unlimited) {
|
|
8528
|
+
console.log(chalk4.dim(" Run `vibedrift . --deep` to use AI-powered analysis."));
|
|
8529
|
+
console.log("");
|
|
8530
|
+
} else if (credits.available_total > 0) {
|
|
8531
|
+
console.log(
|
|
8532
|
+
chalk4.dim(` You have ${credits.available_total} deep scan credit${credits.available_total === 1 ? "" : "s"} available.`)
|
|
8533
|
+
);
|
|
8534
|
+
console.log(chalk4.dim(" Run `vibedrift . --deep` to use one."));
|
|
8535
|
+
console.log("");
|
|
8536
|
+
} else {
|
|
8537
|
+
console.log(chalk4.dim(" Run `vibedrift upgrade` to enable deep AI scans."));
|
|
8538
|
+
console.log("");
|
|
8539
|
+
}
|
|
8540
|
+
} catch {
|
|
8541
|
+
if (result.plan === "free") {
|
|
8542
|
+
console.log(chalk4.dim(" Run `vibedrift upgrade` to enable deep AI scans."));
|
|
8543
|
+
} else {
|
|
8544
|
+
console.log(chalk4.dim(" Run `vibedrift . --deep` to use AI-powered analysis."));
|
|
8545
|
+
}
|
|
8486
8546
|
console.log("");
|
|
8487
8547
|
}
|
|
8488
8548
|
return;
|
|
@@ -8594,6 +8654,21 @@ async function runStatus() {
|
|
|
8594
8654
|
console.log(chalk6.dim(` ${err.message}`));
|
|
8595
8655
|
}
|
|
8596
8656
|
}
|
|
8657
|
+
try {
|
|
8658
|
+
const credits = await fetchCredits(resolved.token, { apiUrl: config.apiUrl });
|
|
8659
|
+
console.log("");
|
|
8660
|
+
if (credits.unlimited) {
|
|
8661
|
+
console.log(` Deep scans: ${chalk6.bold.green("unlimited")} (${credits.plan})`);
|
|
8662
|
+
} else if (credits.has_free_deep_scan) {
|
|
8663
|
+
console.log(` Deep scans: ${chalk6.bold.yellow("1 free")} + ${credits.available_purchased} purchased`);
|
|
8664
|
+
console.log(chalk6.dim(" Run `vibedrift . --deep` to use your free credit."));
|
|
8665
|
+
} else if (credits.available_total > 0) {
|
|
8666
|
+
console.log(` Deep scans: ${chalk6.bold(credits.available_total)} credit${credits.available_total === 1 ? "" : "s"} available`);
|
|
8667
|
+
} else {
|
|
8668
|
+
console.log(` Deep scans: ${chalk6.dim("0 credits")} \u2014 run \`vibedrift upgrade\` for more`);
|
|
8669
|
+
}
|
|
8670
|
+
} catch {
|
|
8671
|
+
}
|
|
8597
8672
|
console.log("");
|
|
8598
8673
|
}
|
|
8599
8674
|
function describeSource(source) {
|