@plaud-ai/cli 0.3.11 → 0.3.12
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 +323 -226
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -20244,237 +20244,27 @@ function extractIdentity(user) {
|
|
|
20244
20244
|
};
|
|
20245
20245
|
}
|
|
20246
20246
|
|
|
20247
|
-
// src/telemetry.ts
|
|
20248
|
-
import { randomUUID as randomUUID2 } from "crypto";
|
|
20249
|
-
|
|
20250
|
-
// src/exit-codes.ts
|
|
20251
|
-
var ExitCode = {
|
|
20252
|
-
OK: 0,
|
|
20253
|
-
ERROR: 1,
|
|
20254
|
-
// 参数错误、未知异常
|
|
20255
|
-
AUTH_FAILED: 2,
|
|
20256
|
-
// Token 无效或过期(HTTP 401)
|
|
20257
|
-
UNREACHABLE: 3,
|
|
20258
|
-
// 后端服务不可达(网络错误)
|
|
20259
|
-
TIMEOUT: 4
|
|
20260
|
-
// 请求超时
|
|
20261
|
-
};
|
|
20262
|
-
|
|
20263
|
-
// src/telemetry.ts
|
|
20264
|
-
var currentCommand = "unknown";
|
|
20265
|
-
var currentRequestId = "";
|
|
20266
|
-
var startedAt = 0;
|
|
20267
|
-
var currentFileId;
|
|
20268
|
-
var HARD_EXIT_GRACE_MS = 500;
|
|
20269
|
-
function drainAndExit(code) {
|
|
20270
|
-
process.exitCode = code;
|
|
20271
|
-
setTimeout(() => process.exit(code), HARD_EXIT_GRACE_MS).unref();
|
|
20272
|
-
return new Promise(() => {
|
|
20273
|
-
});
|
|
20274
|
-
}
|
|
20275
|
-
function errorTypeForExit(code) {
|
|
20276
|
-
switch (code) {
|
|
20277
|
-
case ExitCode.AUTH_FAILED:
|
|
20278
|
-
return "auth";
|
|
20279
|
-
case ExitCode.UNREACHABLE:
|
|
20280
|
-
return "network";
|
|
20281
|
-
case ExitCode.TIMEOUT:
|
|
20282
|
-
return "timeout";
|
|
20283
|
-
default:
|
|
20284
|
-
return "unknown";
|
|
20285
|
-
}
|
|
20286
|
-
}
|
|
20287
|
-
function telemetryClick(command, fileId) {
|
|
20288
|
-
currentCommand = command;
|
|
20289
|
-
currentRequestId = randomUUID2();
|
|
20290
|
-
startedAt = Date.now();
|
|
20291
|
-
currentFileId = fileId;
|
|
20292
|
-
capture("cli:command:click", {
|
|
20293
|
-
command_name: command,
|
|
20294
|
-
request_id: currentRequestId,
|
|
20295
|
-
passive: false,
|
|
20296
|
-
...fileId ? { file_id: fileId } : {}
|
|
20297
|
-
});
|
|
20298
|
-
}
|
|
20299
|
-
async function telemetryExit(code) {
|
|
20300
|
-
const fileProp = currentFileId ? { file_id: currentFileId } : {};
|
|
20301
|
-
if (code === ExitCode.OK) {
|
|
20302
|
-
capture("cli:command:success", {
|
|
20303
|
-
command_name: currentCommand,
|
|
20304
|
-
request_id: currentRequestId,
|
|
20305
|
-
duration_ms: Date.now() - startedAt,
|
|
20306
|
-
passive: true,
|
|
20307
|
-
...fileProp
|
|
20308
|
-
});
|
|
20309
|
-
} else {
|
|
20310
|
-
capture("cli:command:error", {
|
|
20311
|
-
command_name: currentCommand,
|
|
20312
|
-
request_id: currentRequestId,
|
|
20313
|
-
passive: true,
|
|
20314
|
-
error_type: errorTypeForExit(code),
|
|
20315
|
-
...fileProp
|
|
20316
|
-
});
|
|
20317
|
-
}
|
|
20318
|
-
await shutdown();
|
|
20319
|
-
return drainAndExit(code);
|
|
20320
|
-
}
|
|
20321
|
-
|
|
20322
|
-
// src/commands/version.ts
|
|
20323
|
-
import { Command as Command2 } from "commander";
|
|
20324
|
-
import chalk3 from "chalk";
|
|
20325
|
-
import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
|
|
20326
|
-
import { homedir as homedir2 } from "os";
|
|
20327
|
-
import { join as join2, dirname as dirname2 } from "path";
|
|
20328
|
-
|
|
20329
|
-
// src/commands/update.ts
|
|
20330
|
-
import { Command } from "commander";
|
|
20331
|
-
import chalk2 from "chalk";
|
|
20332
|
-
import ora from "ora";
|
|
20333
|
-
|
|
20334
|
-
// src/error.ts
|
|
20335
|
-
import chalk from "chalk";
|
|
20336
|
-
function printError(code, message, detail) {
|
|
20337
|
-
console.error(chalk.red(`\u2717 [${code}] ${message}`));
|
|
20338
|
-
if (detail) console.error(chalk.gray(String(detail)));
|
|
20339
|
-
}
|
|
20340
|
-
function isAuthError(err) {
|
|
20341
|
-
if (!(err instanceof Error)) return false;
|
|
20342
|
-
return err.message.includes("Not authenticated") || err.message.includes("401");
|
|
20343
|
-
}
|
|
20344
|
-
function isNetworkError(err) {
|
|
20345
|
-
if (!(err instanceof Error)) return false;
|
|
20346
|
-
return err instanceof TypeError || err.message.includes("ECONNREFUSED") || err.message.includes("ENOTFOUND") || err.message.includes("fetch failed");
|
|
20347
|
-
}
|
|
20348
|
-
function isTimeoutError(err) {
|
|
20349
|
-
if (!(err instanceof Error)) return false;
|
|
20350
|
-
return err.name === "AbortError" || err.message.toLowerCase().includes("timeout");
|
|
20351
|
-
}
|
|
20352
|
-
|
|
20353
|
-
// src/commands/update.ts
|
|
20354
|
-
var PKG_NAME = "@plaud-ai/cli";
|
|
20355
|
-
var REGISTRY = "https://registry.npmjs.org";
|
|
20356
|
-
async function fetchLatestVersion(timeoutMs = 5e3) {
|
|
20357
|
-
const ctrl = new AbortController();
|
|
20358
|
-
const t = setTimeout(() => ctrl.abort(), timeoutMs);
|
|
20359
|
-
try {
|
|
20360
|
-
const res = await fetch(`${REGISTRY}/${encodeURIComponent(PKG_NAME)}/latest`, { signal: ctrl.signal });
|
|
20361
|
-
if (!res.ok) return null;
|
|
20362
|
-
const json = await res.json();
|
|
20363
|
-
return json.version ?? null;
|
|
20364
|
-
} catch {
|
|
20365
|
-
return null;
|
|
20366
|
-
} finally {
|
|
20367
|
-
clearTimeout(t);
|
|
20368
|
-
}
|
|
20369
|
-
}
|
|
20370
|
-
function isNewer(current, latest) {
|
|
20371
|
-
const c = current.split(".").map(Number);
|
|
20372
|
-
const l = latest.split(".").map(Number);
|
|
20373
|
-
for (let i = 0; i < Math.max(c.length, l.length); i++) {
|
|
20374
|
-
const cv = c[i] ?? 0;
|
|
20375
|
-
const lv = l[i] ?? 0;
|
|
20376
|
-
if (lv > cv) return true;
|
|
20377
|
-
if (lv < cv) return false;
|
|
20378
|
-
}
|
|
20379
|
-
return false;
|
|
20380
|
-
}
|
|
20381
|
-
var updateCommand = new Command("update").description("Check npm for the latest Plaud CLI and print the upgrade command").action(async () => {
|
|
20382
|
-
const current = "0.3.11";
|
|
20383
|
-
const spinner = ora("Checking npm for latest version...").start();
|
|
20384
|
-
const latest = await fetchLatestVersion();
|
|
20385
|
-
spinner.stop();
|
|
20386
|
-
if (!latest) {
|
|
20387
|
-
printError("UNREACHABLE", "Could not reach npm registry to check for updates.");
|
|
20388
|
-
await telemetryExit(ExitCode.UNREACHABLE);
|
|
20389
|
-
return;
|
|
20390
|
-
}
|
|
20391
|
-
if (!isNewer(current, latest)) {
|
|
20392
|
-
console.log(chalk2.green(`You're on the latest version (${current}).`));
|
|
20393
|
-
return;
|
|
20394
|
-
}
|
|
20395
|
-
console.log(chalk2.yellow(`A newer version is available: ${current} \u2192 ${latest}`));
|
|
20396
|
-
console.log();
|
|
20397
|
-
console.log("Run this command to upgrade:");
|
|
20398
|
-
console.log();
|
|
20399
|
-
console.log(chalk2.bold(` npm install -g ${PKG_NAME}@latest`));
|
|
20400
|
-
console.log();
|
|
20401
|
-
});
|
|
20402
|
-
|
|
20403
|
-
// src/commands/version.ts
|
|
20404
|
-
var CACHE_PATH = join2(homedir2(), ".plaud", "version-check.json");
|
|
20405
|
-
var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
20406
|
-
async function readCache() {
|
|
20407
|
-
try {
|
|
20408
|
-
const raw = await readFile2(CACHE_PATH, "utf-8");
|
|
20409
|
-
const parsed = JSON.parse(raw);
|
|
20410
|
-
if (typeof parsed.checked_at !== "number" || typeof parsed.latest !== "string") return null;
|
|
20411
|
-
return parsed;
|
|
20412
|
-
} catch {
|
|
20413
|
-
return null;
|
|
20414
|
-
}
|
|
20415
|
-
}
|
|
20416
|
-
async function writeCache(entry) {
|
|
20417
|
-
try {
|
|
20418
|
-
await mkdir2(dirname2(CACHE_PATH), { recursive: true });
|
|
20419
|
-
await writeFile2(CACHE_PATH, JSON.stringify(entry), "utf-8");
|
|
20420
|
-
} catch {
|
|
20421
|
-
}
|
|
20422
|
-
}
|
|
20423
|
-
async function checkForUpdate(current) {
|
|
20424
|
-
const cached = await readCache();
|
|
20425
|
-
const now = Date.now();
|
|
20426
|
-
let latest = null;
|
|
20427
|
-
if (cached && now - cached.checked_at < CACHE_TTL_MS) {
|
|
20428
|
-
latest = cached.latest;
|
|
20429
|
-
} else {
|
|
20430
|
-
latest = await fetchLatestVersion(2e3);
|
|
20431
|
-
if (latest) await writeCache({ checked_at: now, latest });
|
|
20432
|
-
}
|
|
20433
|
-
if (!latest) return null;
|
|
20434
|
-
return isNewer(current, latest) ? latest : null;
|
|
20435
|
-
}
|
|
20436
|
-
var versionCommand = new Command2("version").description("Show CLI version information").action(async () => {
|
|
20437
|
-
const current = "0.3.11";
|
|
20438
|
-
console.log(`plaud ${current}`);
|
|
20439
|
-
if ("ee2ff6d") console.log(`commit ${"ee2ff6d"}`);
|
|
20440
|
-
if ("2026-08-20T09:19:25.840Z") console.log(`built ${"2026-08-20T09:19:25.840Z"}`);
|
|
20441
|
-
if (current === "unknown") return;
|
|
20442
|
-
const newer = await checkForUpdate(current);
|
|
20443
|
-
if (newer) {
|
|
20444
|
-
console.log();
|
|
20445
|
-
console.log(chalk3.yellow(`A newer version is available: ${current} \u2192 ${newer}`));
|
|
20446
|
-
console.log(chalk3.gray(`Run \`plaud update\` for upgrade instructions.`));
|
|
20447
|
-
}
|
|
20448
|
-
});
|
|
20449
|
-
|
|
20450
|
-
// src/commands/login.ts
|
|
20451
|
-
import { Command as Command3 } from "commander";
|
|
20452
|
-
import { createServer as createServer2 } from "net";
|
|
20453
|
-
import open from "open";
|
|
20454
|
-
import chalk4 from "chalk";
|
|
20455
|
-
import ora2 from "ora";
|
|
20456
|
-
|
|
20457
20247
|
// ../shared/dist/oauth.js
|
|
20458
20248
|
import { randomBytes, createHash } from "crypto";
|
|
20459
20249
|
|
|
20460
20250
|
// ../shared/dist/token-store.js
|
|
20461
|
-
import { readFile as
|
|
20462
|
-
import { join as
|
|
20463
|
-
import { homedir as
|
|
20251
|
+
import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2, rm as rm2 } from "fs/promises";
|
|
20252
|
+
import { join as join2 } from "path";
|
|
20253
|
+
import { homedir as homedir2 } from "os";
|
|
20464
20254
|
var TokenStore = class {
|
|
20465
20255
|
configDir;
|
|
20466
20256
|
tokenPath;
|
|
20467
20257
|
constructor(filename = "tokens.json") {
|
|
20468
|
-
this.configDir =
|
|
20469
|
-
this.tokenPath =
|
|
20258
|
+
this.configDir = join2(homedir2(), ".plaud");
|
|
20259
|
+
this.tokenPath = join2(this.configDir, filename);
|
|
20470
20260
|
}
|
|
20471
20261
|
async save(tokenSet) {
|
|
20472
|
-
await
|
|
20473
|
-
await
|
|
20262
|
+
await mkdir2(this.configDir, { recursive: true });
|
|
20263
|
+
await writeFile2(this.tokenPath, JSON.stringify(tokenSet, null, 2), "utf-8");
|
|
20474
20264
|
}
|
|
20475
20265
|
async load() {
|
|
20476
20266
|
try {
|
|
20477
|
-
const data = await
|
|
20267
|
+
const data = await readFile2(this.tokenPath, "utf-8");
|
|
20478
20268
|
return JSON.parse(data);
|
|
20479
20269
|
} catch {
|
|
20480
20270
|
return null;
|
|
@@ -20522,6 +20312,38 @@ function classifyError(err) {
|
|
|
20522
20312
|
return "client_error";
|
|
20523
20313
|
return "unknown";
|
|
20524
20314
|
}
|
|
20315
|
+
function isTransportError(err) {
|
|
20316
|
+
const type = classifyError(err);
|
|
20317
|
+
return type === "network" || type === "timeout" || type === "server_error";
|
|
20318
|
+
}
|
|
20319
|
+
var MAX_CAUSE_DEPTH = 5;
|
|
20320
|
+
var MAX_DESCRIPTION_LENGTH = 400;
|
|
20321
|
+
function summarizeError(err) {
|
|
20322
|
+
if (!(err instanceof Error))
|
|
20323
|
+
return String(err ?? "unknown error");
|
|
20324
|
+
const code = err.code;
|
|
20325
|
+
const suffix = typeof code === "string" && !err.message.includes(code) ? ` (${code})` : "";
|
|
20326
|
+
return `${err.name}: ${err.message}${suffix}`;
|
|
20327
|
+
}
|
|
20328
|
+
function describeError(err) {
|
|
20329
|
+
const chain = [];
|
|
20330
|
+
const seen = /* @__PURE__ */ new Set();
|
|
20331
|
+
let current = err;
|
|
20332
|
+
for (let depth = 0; depth < MAX_CAUSE_DEPTH && current && !seen.has(current); depth++) {
|
|
20333
|
+
seen.add(current);
|
|
20334
|
+
chain.push(summarizeError(current));
|
|
20335
|
+
const aggregated = current instanceof AggregateError ? current.errors : void 0;
|
|
20336
|
+
if (aggregated && aggregated.length > 0) {
|
|
20337
|
+
chain.push(aggregated.map(summarizeError).join("; "));
|
|
20338
|
+
break;
|
|
20339
|
+
}
|
|
20340
|
+
current = current instanceof Error ? current.cause : void 0;
|
|
20341
|
+
}
|
|
20342
|
+
const text = chain.join(" | cause: ");
|
|
20343
|
+
if (text.length === 0)
|
|
20344
|
+
return "unknown error";
|
|
20345
|
+
return text.length > MAX_DESCRIPTION_LENGTH ? `${text.slice(0, MAX_DESCRIPTION_LENGTH - 1)}\u2026` : text;
|
|
20346
|
+
}
|
|
20525
20347
|
function oauthCallbackErrorType(status) {
|
|
20526
20348
|
switch (status) {
|
|
20527
20349
|
case "denied":
|
|
@@ -20632,6 +20454,21 @@ var OAuth = class {
|
|
|
20632
20454
|
await this.tokenStore.save(tokenSet);
|
|
20633
20455
|
return tokenSet;
|
|
20634
20456
|
}
|
|
20457
|
+
/** Are there stored credentials? Local-only — never touches the network, so
|
|
20458
|
+
* logout can tell "nothing to do" from "cannot reach Plaud". */
|
|
20459
|
+
async hasStoredToken() {
|
|
20460
|
+
return await this.tokenStore.load() !== null;
|
|
20461
|
+
}
|
|
20462
|
+
/**
|
|
20463
|
+
* The current access token, refreshing it first when it is about to expire.
|
|
20464
|
+
*
|
|
20465
|
+
* `null` means genuinely unauthenticated: nothing stored, no refresh token, or
|
|
20466
|
+
* the refresh token was rejected. A transport failure instead THROWS — it says
|
|
20467
|
+
* nothing about the credentials, and reporting it as unauthenticated is what
|
|
20468
|
+
* pushed #670875's reporter into a re-login loop (and would have let callers
|
|
20469
|
+
* delete a perfectly good token file). Callers that only want to know whether
|
|
20470
|
+
* we are logged in should use `isTransportError` to tell the two apart.
|
|
20471
|
+
*/
|
|
20635
20472
|
async getAccessToken() {
|
|
20636
20473
|
const tokenSet = await this.tokenStore.load();
|
|
20637
20474
|
if (!tokenSet)
|
|
@@ -20641,8 +20478,10 @@ var OAuth = class {
|
|
|
20641
20478
|
try {
|
|
20642
20479
|
const refreshed = await this.refresh(tokenSet.refresh_token);
|
|
20643
20480
|
return refreshed.access_token;
|
|
20644
|
-
} catch {
|
|
20645
|
-
|
|
20481
|
+
} catch (err) {
|
|
20482
|
+
if (!isTransportError(err))
|
|
20483
|
+
return null;
|
|
20484
|
+
throw err;
|
|
20646
20485
|
}
|
|
20647
20486
|
}
|
|
20648
20487
|
return null;
|
|
@@ -20768,6 +20607,46 @@ var PlaudClient = class {
|
|
|
20768
20607
|
}
|
|
20769
20608
|
};
|
|
20770
20609
|
|
|
20610
|
+
// ../shared/dist/proxy.js
|
|
20611
|
+
var PROXY_ENV_VARS = [
|
|
20612
|
+
"HTTP_PROXY",
|
|
20613
|
+
"http_proxy",
|
|
20614
|
+
"HTTPS_PROXY",
|
|
20615
|
+
"https_proxy",
|
|
20616
|
+
"ALL_PROXY",
|
|
20617
|
+
"all_proxy"
|
|
20618
|
+
];
|
|
20619
|
+
function proxyEnvVars(env = process.env) {
|
|
20620
|
+
return PROXY_ENV_VARS.filter((key) => (env[key] ?? "").trim().length > 0);
|
|
20621
|
+
}
|
|
20622
|
+
async function installProxyDispatcher(env = process.env) {
|
|
20623
|
+
const active = proxyEnvVars(env);
|
|
20624
|
+
if (active.length === 0)
|
|
20625
|
+
return null;
|
|
20626
|
+
try {
|
|
20627
|
+
const { EnvHttpProxyAgent, setGlobalDispatcher } = await import("undici");
|
|
20628
|
+
setGlobalDispatcher(withoutExperimentalWarning(() => new EnvHttpProxyAgent()));
|
|
20629
|
+
return active;
|
|
20630
|
+
} catch {
|
|
20631
|
+
return null;
|
|
20632
|
+
}
|
|
20633
|
+
}
|
|
20634
|
+
function withoutExperimentalWarning(build) {
|
|
20635
|
+
const original = process.emitWarning;
|
|
20636
|
+
process.emitWarning = ((warning, ...rest) => {
|
|
20637
|
+
const [first, second] = rest;
|
|
20638
|
+
const code = typeof first === "object" && first !== null ? first.code : second;
|
|
20639
|
+
if (code === "UNDICI-EHPA")
|
|
20640
|
+
return;
|
|
20641
|
+
return original.call(process, warning, ...rest);
|
|
20642
|
+
});
|
|
20643
|
+
try {
|
|
20644
|
+
return build();
|
|
20645
|
+
} finally {
|
|
20646
|
+
process.emitWarning = original;
|
|
20647
|
+
}
|
|
20648
|
+
}
|
|
20649
|
+
|
|
20771
20650
|
// ../shared/dist/oauth-callback-server.js
|
|
20772
20651
|
import { createServer } from "http";
|
|
20773
20652
|
var SUCCESS_HTML = '<!doctype html><html><head><meta charset="utf-8"><title>Plaud</title></head><body style="font-family:system-ui;padding:2rem;text-align:center;"><h1>Authorization successful!</h1><p>You can close this tab.</p></body></html>';
|
|
@@ -20945,6 +20824,216 @@ function parseDateOnly(value) {
|
|
|
20945
20824
|
return [y, m, d];
|
|
20946
20825
|
}
|
|
20947
20826
|
|
|
20827
|
+
// src/telemetry.ts
|
|
20828
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
20829
|
+
|
|
20830
|
+
// src/exit-codes.ts
|
|
20831
|
+
var ExitCode = {
|
|
20832
|
+
OK: 0,
|
|
20833
|
+
ERROR: 1,
|
|
20834
|
+
// 参数错误、未知异常
|
|
20835
|
+
AUTH_FAILED: 2,
|
|
20836
|
+
// Token 无效或过期(HTTP 401)
|
|
20837
|
+
UNREACHABLE: 3,
|
|
20838
|
+
// 后端服务不可达(网络错误)
|
|
20839
|
+
TIMEOUT: 4
|
|
20840
|
+
// 请求超时
|
|
20841
|
+
};
|
|
20842
|
+
|
|
20843
|
+
// src/telemetry.ts
|
|
20844
|
+
var currentCommand = "unknown";
|
|
20845
|
+
var currentRequestId = "";
|
|
20846
|
+
var startedAt = 0;
|
|
20847
|
+
var currentFileId;
|
|
20848
|
+
var HARD_EXIT_GRACE_MS = 500;
|
|
20849
|
+
function drainAndExit(code) {
|
|
20850
|
+
process.exitCode = code;
|
|
20851
|
+
setTimeout(() => process.exit(code), HARD_EXIT_GRACE_MS).unref();
|
|
20852
|
+
return new Promise(() => {
|
|
20853
|
+
});
|
|
20854
|
+
}
|
|
20855
|
+
function errorTypeForExit(code) {
|
|
20856
|
+
switch (code) {
|
|
20857
|
+
case ExitCode.AUTH_FAILED:
|
|
20858
|
+
return "auth";
|
|
20859
|
+
case ExitCode.UNREACHABLE:
|
|
20860
|
+
return "network";
|
|
20861
|
+
case ExitCode.TIMEOUT:
|
|
20862
|
+
return "timeout";
|
|
20863
|
+
default:
|
|
20864
|
+
return "unknown";
|
|
20865
|
+
}
|
|
20866
|
+
}
|
|
20867
|
+
function telemetryClick(command, fileId) {
|
|
20868
|
+
currentCommand = command;
|
|
20869
|
+
currentRequestId = randomUUID2();
|
|
20870
|
+
startedAt = Date.now();
|
|
20871
|
+
currentFileId = fileId;
|
|
20872
|
+
capture("cli:command:click", {
|
|
20873
|
+
command_name: command,
|
|
20874
|
+
request_id: currentRequestId,
|
|
20875
|
+
passive: false,
|
|
20876
|
+
...fileId ? { file_id: fileId } : {}
|
|
20877
|
+
});
|
|
20878
|
+
}
|
|
20879
|
+
async function telemetryExit(code) {
|
|
20880
|
+
const fileProp = currentFileId ? { file_id: currentFileId } : {};
|
|
20881
|
+
if (code === ExitCode.OK) {
|
|
20882
|
+
capture("cli:command:success", {
|
|
20883
|
+
command_name: currentCommand,
|
|
20884
|
+
request_id: currentRequestId,
|
|
20885
|
+
duration_ms: Date.now() - startedAt,
|
|
20886
|
+
passive: true,
|
|
20887
|
+
...fileProp
|
|
20888
|
+
});
|
|
20889
|
+
} else {
|
|
20890
|
+
capture("cli:command:error", {
|
|
20891
|
+
command_name: currentCommand,
|
|
20892
|
+
request_id: currentRequestId,
|
|
20893
|
+
passive: true,
|
|
20894
|
+
error_type: errorTypeForExit(code),
|
|
20895
|
+
...fileProp
|
|
20896
|
+
});
|
|
20897
|
+
}
|
|
20898
|
+
await shutdown();
|
|
20899
|
+
return drainAndExit(code);
|
|
20900
|
+
}
|
|
20901
|
+
|
|
20902
|
+
// src/commands/version.ts
|
|
20903
|
+
import { Command as Command2 } from "commander";
|
|
20904
|
+
import chalk3 from "chalk";
|
|
20905
|
+
import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir3 } from "fs/promises";
|
|
20906
|
+
import { homedir as homedir3 } from "os";
|
|
20907
|
+
import { join as join3, dirname as dirname2 } from "path";
|
|
20908
|
+
|
|
20909
|
+
// src/commands/update.ts
|
|
20910
|
+
import { Command } from "commander";
|
|
20911
|
+
import chalk2 from "chalk";
|
|
20912
|
+
import ora from "ora";
|
|
20913
|
+
|
|
20914
|
+
// src/error.ts
|
|
20915
|
+
import chalk from "chalk";
|
|
20916
|
+
function printError(code, message, detail) {
|
|
20917
|
+
console.error(chalk.red(`\u2717 [${code}] ${message}`));
|
|
20918
|
+
if (detail) console.error(chalk.gray(describeError(detail)));
|
|
20919
|
+
}
|
|
20920
|
+
function isAuthError(err) {
|
|
20921
|
+
if (!(err instanceof Error)) return false;
|
|
20922
|
+
return err.message.includes("Not authenticated") || err.message.includes("401");
|
|
20923
|
+
}
|
|
20924
|
+
function isNetworkError(err) {
|
|
20925
|
+
if (!(err instanceof Error)) return false;
|
|
20926
|
+
return err instanceof TypeError || err.message.includes("ECONNREFUSED") || err.message.includes("ENOTFOUND") || err.message.includes("fetch failed");
|
|
20927
|
+
}
|
|
20928
|
+
function isTimeoutError(err) {
|
|
20929
|
+
if (!(err instanceof Error)) return false;
|
|
20930
|
+
return err.name === "AbortError" || err.message.toLowerCase().includes("timeout");
|
|
20931
|
+
}
|
|
20932
|
+
|
|
20933
|
+
// src/commands/update.ts
|
|
20934
|
+
var PKG_NAME = "@plaud-ai/cli";
|
|
20935
|
+
var REGISTRY = "https://registry.npmjs.org";
|
|
20936
|
+
async function fetchLatestVersion(timeoutMs = 5e3) {
|
|
20937
|
+
const ctrl = new AbortController();
|
|
20938
|
+
const t = setTimeout(() => ctrl.abort(), timeoutMs);
|
|
20939
|
+
try {
|
|
20940
|
+
const res = await fetch(`${REGISTRY}/${encodeURIComponent(PKG_NAME)}/latest`, { signal: ctrl.signal });
|
|
20941
|
+
if (!res.ok) return null;
|
|
20942
|
+
const json = await res.json();
|
|
20943
|
+
return json.version ?? null;
|
|
20944
|
+
} catch {
|
|
20945
|
+
return null;
|
|
20946
|
+
} finally {
|
|
20947
|
+
clearTimeout(t);
|
|
20948
|
+
}
|
|
20949
|
+
}
|
|
20950
|
+
function isNewer(current, latest) {
|
|
20951
|
+
const c = current.split(".").map(Number);
|
|
20952
|
+
const l = latest.split(".").map(Number);
|
|
20953
|
+
for (let i = 0; i < Math.max(c.length, l.length); i++) {
|
|
20954
|
+
const cv = c[i] ?? 0;
|
|
20955
|
+
const lv = l[i] ?? 0;
|
|
20956
|
+
if (lv > cv) return true;
|
|
20957
|
+
if (lv < cv) return false;
|
|
20958
|
+
}
|
|
20959
|
+
return false;
|
|
20960
|
+
}
|
|
20961
|
+
var updateCommand = new Command("update").description("Check npm for the latest Plaud CLI and print the upgrade command").action(async () => {
|
|
20962
|
+
const current = "0.3.12";
|
|
20963
|
+
const spinner = ora("Checking npm for latest version...").start();
|
|
20964
|
+
const latest = await fetchLatestVersion();
|
|
20965
|
+
spinner.stop();
|
|
20966
|
+
if (!latest) {
|
|
20967
|
+
printError("UNREACHABLE", "Could not reach npm registry to check for updates.");
|
|
20968
|
+
await telemetryExit(ExitCode.UNREACHABLE);
|
|
20969
|
+
return;
|
|
20970
|
+
}
|
|
20971
|
+
if (!isNewer(current, latest)) {
|
|
20972
|
+
console.log(chalk2.green(`You're on the latest version (${current}).`));
|
|
20973
|
+
return;
|
|
20974
|
+
}
|
|
20975
|
+
console.log(chalk2.yellow(`A newer version is available: ${current} \u2192 ${latest}`));
|
|
20976
|
+
console.log();
|
|
20977
|
+
console.log("Run this command to upgrade:");
|
|
20978
|
+
console.log();
|
|
20979
|
+
console.log(chalk2.bold(` npm install -g ${PKG_NAME}@latest`));
|
|
20980
|
+
console.log();
|
|
20981
|
+
});
|
|
20982
|
+
|
|
20983
|
+
// src/commands/version.ts
|
|
20984
|
+
var CACHE_PATH = join3(homedir3(), ".plaud", "version-check.json");
|
|
20985
|
+
var CACHE_TTL_MS = 24 * 60 * 60 * 1e3;
|
|
20986
|
+
async function readCache() {
|
|
20987
|
+
try {
|
|
20988
|
+
const raw = await readFile3(CACHE_PATH, "utf-8");
|
|
20989
|
+
const parsed = JSON.parse(raw);
|
|
20990
|
+
if (typeof parsed.checked_at !== "number" || typeof parsed.latest !== "string") return null;
|
|
20991
|
+
return parsed;
|
|
20992
|
+
} catch {
|
|
20993
|
+
return null;
|
|
20994
|
+
}
|
|
20995
|
+
}
|
|
20996
|
+
async function writeCache(entry) {
|
|
20997
|
+
try {
|
|
20998
|
+
await mkdir3(dirname2(CACHE_PATH), { recursive: true });
|
|
20999
|
+
await writeFile3(CACHE_PATH, JSON.stringify(entry), "utf-8");
|
|
21000
|
+
} catch {
|
|
21001
|
+
}
|
|
21002
|
+
}
|
|
21003
|
+
async function checkForUpdate(current) {
|
|
21004
|
+
const cached = await readCache();
|
|
21005
|
+
const now = Date.now();
|
|
21006
|
+
let latest = null;
|
|
21007
|
+
if (cached && now - cached.checked_at < CACHE_TTL_MS) {
|
|
21008
|
+
latest = cached.latest;
|
|
21009
|
+
} else {
|
|
21010
|
+
latest = await fetchLatestVersion(2e3);
|
|
21011
|
+
if (latest) await writeCache({ checked_at: now, latest });
|
|
21012
|
+
}
|
|
21013
|
+
if (!latest) return null;
|
|
21014
|
+
return isNewer(current, latest) ? latest : null;
|
|
21015
|
+
}
|
|
21016
|
+
var versionCommand = new Command2("version").description("Show CLI version information").action(async () => {
|
|
21017
|
+
const current = "0.3.12";
|
|
21018
|
+
console.log(`plaud ${current}`);
|
|
21019
|
+
if ("516b086") console.log(`commit ${"516b086"}`);
|
|
21020
|
+
if ("2026-09-09T09:53:45.245Z") console.log(`built ${"2026-09-09T09:53:45.245Z"}`);
|
|
21021
|
+
if (current === "unknown") return;
|
|
21022
|
+
const newer = await checkForUpdate(current);
|
|
21023
|
+
if (newer) {
|
|
21024
|
+
console.log();
|
|
21025
|
+
console.log(chalk3.yellow(`A newer version is available: ${current} \u2192 ${newer}`));
|
|
21026
|
+
console.log(chalk3.gray(`Run \`plaud update\` for upgrade instructions.`));
|
|
21027
|
+
}
|
|
21028
|
+
});
|
|
21029
|
+
|
|
21030
|
+
// src/commands/login.ts
|
|
21031
|
+
import { Command as Command3 } from "commander";
|
|
21032
|
+
import { createServer as createServer2 } from "net";
|
|
21033
|
+
import open from "open";
|
|
21034
|
+
import chalk4 from "chalk";
|
|
21035
|
+
import ora2 from "ora";
|
|
21036
|
+
|
|
20948
21037
|
// src/config.ts
|
|
20949
21038
|
import { readFileSync, existsSync } from "fs";
|
|
20950
21039
|
import { homedir as homedir4 } from "os";
|
|
@@ -21024,7 +21113,11 @@ var loginCommand = new Command3("login").description("Authenticate with Plaud vi
|
|
|
21024
21113
|
}
|
|
21025
21114
|
}
|
|
21026
21115
|
}
|
|
21027
|
-
} catch {
|
|
21116
|
+
} catch (err) {
|
|
21117
|
+
if (isTransportError(err)) {
|
|
21118
|
+
printError("UNREACHABLE", "Cannot reach Plaud servers to refresh the saved credentials. Check your network.", err);
|
|
21119
|
+
await telemetryExit(ExitCode.UNREACHABLE);
|
|
21120
|
+
}
|
|
21028
21121
|
await client2.auth.logout();
|
|
21029
21122
|
}
|
|
21030
21123
|
const portError = await probeCallbackPort(CALLBACK_PORT);
|
|
@@ -21107,8 +21200,7 @@ import { Command as Command4 } from "commander";
|
|
|
21107
21200
|
import chalk5 from "chalk";
|
|
21108
21201
|
var logoutCommand = new Command4("logout").description("Log out and revoke authorization").action(async () => {
|
|
21109
21202
|
const client2 = getClient2();
|
|
21110
|
-
|
|
21111
|
-
if (!token) {
|
|
21203
|
+
if (!await client2.auth.hasStoredToken()) {
|
|
21112
21204
|
console.log(chalk5.yellow("Not logged in."));
|
|
21113
21205
|
return;
|
|
21114
21206
|
}
|
|
@@ -21747,7 +21839,11 @@ async function ensureLoggedIn() {
|
|
|
21747
21839
|
try {
|
|
21748
21840
|
const token = await client2.auth.getAccessToken();
|
|
21749
21841
|
if (token) return true;
|
|
21750
|
-
} catch {
|
|
21842
|
+
} catch (err) {
|
|
21843
|
+
if (isTransportError(err)) {
|
|
21844
|
+
printError("UNREACHABLE", "Cannot reach Plaud servers. Check your network and try again.", err);
|
|
21845
|
+
return false;
|
|
21846
|
+
}
|
|
21751
21847
|
}
|
|
21752
21848
|
const go = await confirm({ message: "You are not logged in. Open the browser to log in now?", default: true });
|
|
21753
21849
|
if (!go) return false;
|
|
@@ -21818,10 +21914,11 @@ async function runWizard() {
|
|
|
21818
21914
|
}
|
|
21819
21915
|
|
|
21820
21916
|
// src/index.ts
|
|
21917
|
+
await installProxyDispatcher();
|
|
21821
21918
|
try {
|
|
21822
21919
|
await initTelemetry({
|
|
21823
21920
|
surface: "cli",
|
|
21824
|
-
appVersion: "0.3.
|
|
21921
|
+
appVersion: "0.3.12"
|
|
21825
21922
|
});
|
|
21826
21923
|
} catch {
|
|
21827
21924
|
}
|
|
@@ -21830,7 +21927,7 @@ async function notifyUpdate() {
|
|
|
21830
21927
|
if (sub === "version" || sub === "update") return;
|
|
21831
21928
|
if (process.env.PLAUD_NO_UPDATE_NOTIFIER) return;
|
|
21832
21929
|
if (!process.stderr.isTTY) return;
|
|
21833
|
-
const current = "0.3.
|
|
21930
|
+
const current = "0.3.12";
|
|
21834
21931
|
if (current === "0.0.0") return;
|
|
21835
21932
|
try {
|
|
21836
21933
|
const newer = await checkForUpdate(current);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plaud-ai/cli",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.12",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"plaud": "dist/index.js"
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"dotenv": "^17.3.1",
|
|
21
21
|
"open": "^10.2.0",
|
|
22
22
|
"ora": "^8.1.0",
|
|
23
|
+
"undici": "^6.28.1",
|
|
23
24
|
"yaml": "^2.8.3"
|
|
24
25
|
},
|
|
25
26
|
"devDependencies": {
|