@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.
Files changed (2) hide show
  1. package/dist/index.js +323 -226
  2. 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 readFile3, writeFile as writeFile3, mkdir as mkdir3, rm as rm2 } from "fs/promises";
20462
- import { join as join3 } from "path";
20463
- import { homedir as homedir3 } from "os";
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 = join3(homedir3(), ".plaud");
20469
- this.tokenPath = join3(this.configDir, filename);
20258
+ this.configDir = join2(homedir2(), ".plaud");
20259
+ this.tokenPath = join2(this.configDir, filename);
20470
20260
  }
20471
20261
  async save(tokenSet) {
20472
- await mkdir3(this.configDir, { recursive: true });
20473
- await writeFile3(this.tokenPath, JSON.stringify(tokenSet, null, 2), "utf-8");
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 readFile3(this.tokenPath, "utf-8");
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
- return null;
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
- const token = await client2.auth.getAccessToken();
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.11"
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.11";
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.11",
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": {