@plaud-ai/cli 0.1.2 → 0.1.4
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 +208 -69
- package/package.json +14 -11
package/dist/index.js
CHANGED
|
@@ -2,15 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
4
|
import "dotenv/config";
|
|
5
|
-
import { Command as
|
|
5
|
+
import { Command as Command10 } from "commander";
|
|
6
6
|
|
|
7
7
|
// src/commands/login.ts
|
|
8
8
|
import { Command } from "commander";
|
|
9
9
|
import { createServer } from "http";
|
|
10
10
|
import open from "open";
|
|
11
|
-
import
|
|
11
|
+
import chalk2 from "chalk";
|
|
12
12
|
import ora from "ora";
|
|
13
13
|
|
|
14
|
+
// src/config.ts
|
|
15
|
+
import { readFileSync, existsSync } from "fs";
|
|
16
|
+
import { homedir as homedir2 } from "os";
|
|
17
|
+
import { join as join2 } from "path";
|
|
18
|
+
import { parse } from "yaml";
|
|
19
|
+
|
|
14
20
|
// ../shared/dist/oauth.js
|
|
15
21
|
import { randomBytes, createHash } from "crypto";
|
|
16
22
|
|
|
@@ -21,9 +27,9 @@ import { homedir } from "os";
|
|
|
21
27
|
var TokenStore = class {
|
|
22
28
|
configDir;
|
|
23
29
|
tokenPath;
|
|
24
|
-
constructor() {
|
|
30
|
+
constructor(filename = "tokens.json") {
|
|
25
31
|
this.configDir = join(homedir(), ".plaud");
|
|
26
|
-
this.tokenPath = join(this.configDir,
|
|
32
|
+
this.tokenPath = join(this.configDir, filename);
|
|
27
33
|
}
|
|
28
34
|
async save(tokenSet) {
|
|
29
35
|
await mkdir(this.configDir, { recursive: true });
|
|
@@ -63,7 +69,7 @@ var OAuth = class {
|
|
|
63
69
|
refreshUrl;
|
|
64
70
|
constructor(config) {
|
|
65
71
|
this.config = config;
|
|
66
|
-
this.tokenStore = new TokenStore();
|
|
72
|
+
this.tokenStore = new TokenStore(config.tokenFile);
|
|
67
73
|
this.authorizationUrl = config.authorizationUrl ?? DEFAULT_AUTHORIZATION_URL;
|
|
68
74
|
this.tokenUrl = config.tokenUrl ?? DEFAULT_TOKEN_URL;
|
|
69
75
|
this.refreshUrl = config.refreshUrl ?? DEFAULT_REFRESH_URL;
|
|
@@ -233,20 +239,30 @@ var PlaudClient = class {
|
|
|
233
239
|
};
|
|
234
240
|
|
|
235
241
|
// src/config.ts
|
|
242
|
+
function loadCliConfig() {
|
|
243
|
+
const configPath = join2(homedir2(), ".plaud", "cli.yaml");
|
|
244
|
+
if (!existsSync(configPath)) return {};
|
|
245
|
+
try {
|
|
246
|
+
return parse(readFileSync(configPath, "utf8")) ?? {};
|
|
247
|
+
} catch {
|
|
248
|
+
return {};
|
|
249
|
+
}
|
|
250
|
+
}
|
|
236
251
|
function buildExtraHeaders() {
|
|
237
252
|
const headers = {};
|
|
238
253
|
if (process.env.PLAUD_ENV) headers["x-pld-env"] = process.env.PLAUD_ENV;
|
|
239
254
|
if (process.env.PLAUD_REGION) headers["x-pld-region"] = process.env.PLAUD_REGION;
|
|
240
255
|
return headers;
|
|
241
256
|
}
|
|
257
|
+
var fileConfig = loadCliConfig();
|
|
242
258
|
var CONFIG = {
|
|
243
|
-
clientId: process.env.PLAUD_CLIENT_ID ?? "client_f9e0b214-c11f-434b-8b95-c4497d1feb81",
|
|
259
|
+
clientId: process.env.PLAUD_CLI_CLIENT_ID ?? process.env.PLAUD_CLIENT_ID ?? "client_f9e0b214-c11f-434b-8b95-c4497d1feb81",
|
|
244
260
|
clientSecret: process.env.PLAUD_CLIENT_SECRET ?? "",
|
|
245
261
|
redirectUri: "http://localhost:8199/auth/callback",
|
|
246
|
-
apiBase: process.env.PLAUD_API_BASE,
|
|
247
|
-
authorizationUrl: process.env.PLAUD_AUTH_URL,
|
|
248
|
-
tokenUrl: process.env.PLAUD_TOKEN_URL,
|
|
249
|
-
refreshUrl: process.env.PLAUD_REFRESH_URL,
|
|
262
|
+
apiBase: process.env.PLAUD_API_BASE ?? fileConfig.api_base,
|
|
263
|
+
authorizationUrl: process.env.PLAUD_AUTH_URL ?? fileConfig.auth_url,
|
|
264
|
+
tokenUrl: process.env.PLAUD_TOKEN_URL ?? fileConfig.token_url,
|
|
265
|
+
refreshUrl: process.env.PLAUD_REFRESH_URL ?? fileConfig.refresh_url,
|
|
250
266
|
extraHeaders: buildExtraHeaders()
|
|
251
267
|
};
|
|
252
268
|
var client = null;
|
|
@@ -257,6 +273,38 @@ function getClient() {
|
|
|
257
273
|
return client;
|
|
258
274
|
}
|
|
259
275
|
|
|
276
|
+
// src/exit-codes.ts
|
|
277
|
+
var ExitCode = {
|
|
278
|
+
OK: 0,
|
|
279
|
+
ERROR: 1,
|
|
280
|
+
// 参数错误、未知异常
|
|
281
|
+
AUTH_FAILED: 2,
|
|
282
|
+
// Token 无效或过期(HTTP 401)
|
|
283
|
+
UNREACHABLE: 3,
|
|
284
|
+
// 后端服务不可达(网络错误)
|
|
285
|
+
TIMEOUT: 4
|
|
286
|
+
// 请求超时
|
|
287
|
+
};
|
|
288
|
+
|
|
289
|
+
// src/error.ts
|
|
290
|
+
import chalk from "chalk";
|
|
291
|
+
function printError(code, message, detail) {
|
|
292
|
+
console.error(chalk.red(`\u2717 [${code}] ${message}`));
|
|
293
|
+
if (detail) console.error(chalk.gray(String(detail)));
|
|
294
|
+
}
|
|
295
|
+
function isAuthError(err) {
|
|
296
|
+
if (!(err instanceof Error)) return false;
|
|
297
|
+
return err.message.includes("Not authenticated") || err.message.includes("401");
|
|
298
|
+
}
|
|
299
|
+
function isNetworkError(err) {
|
|
300
|
+
if (!(err instanceof Error)) return false;
|
|
301
|
+
return err instanceof TypeError || err.message.includes("ECONNREFUSED") || err.message.includes("ENOTFOUND") || err.message.includes("fetch failed");
|
|
302
|
+
}
|
|
303
|
+
function isTimeoutError(err) {
|
|
304
|
+
if (!(err instanceof Error)) return false;
|
|
305
|
+
return err.name === "AbortError" || err.message.toLowerCase().includes("timeout");
|
|
306
|
+
}
|
|
307
|
+
|
|
260
308
|
// src/commands/login.ts
|
|
261
309
|
var CORS_HEADERS = {
|
|
262
310
|
"Access-Control-Allow-Origin": "*",
|
|
@@ -268,7 +316,7 @@ var loginCommand = new Command("login").description("Authenticate with Plaud via
|
|
|
268
316
|
try {
|
|
269
317
|
const token = await client2.auth.getAccessToken();
|
|
270
318
|
if (token) {
|
|
271
|
-
console.log(
|
|
319
|
+
console.log(chalk2.yellow("Already logged in. Run `plaud logout` first to switch accounts."));
|
|
272
320
|
return;
|
|
273
321
|
}
|
|
274
322
|
} catch {
|
|
@@ -292,8 +340,9 @@ var loginCommand = new Command("login").description("Authenticate with Plaud via
|
|
|
292
340
|
if (!code) {
|
|
293
341
|
res.writeHead(400, CORS_HEADERS);
|
|
294
342
|
res.end("Invalid callback: missing code");
|
|
295
|
-
spinner.
|
|
296
|
-
|
|
343
|
+
spinner.stop();
|
|
344
|
+
printError("AUTH_FAILED", "Authentication failed: missing authorization code");
|
|
345
|
+
server.close(() => process.exit(ExitCode.AUTH_FAILED));
|
|
297
346
|
return;
|
|
298
347
|
}
|
|
299
348
|
try {
|
|
@@ -304,14 +353,15 @@ var loginCommand = new Command("login").description("Authenticate with Plaud via
|
|
|
304
353
|
} catch (err) {
|
|
305
354
|
res.writeHead(500, CORS_HEADERS);
|
|
306
355
|
res.end("Token exchange failed");
|
|
307
|
-
spinner.
|
|
356
|
+
spinner.stop();
|
|
357
|
+
printError("AUTH_FAILED", "Authentication failed.", err);
|
|
308
358
|
} finally {
|
|
309
359
|
server.closeAllConnections();
|
|
310
360
|
server.close(() => process.exit(0));
|
|
311
361
|
}
|
|
312
362
|
});
|
|
313
363
|
server.listen(8199, () => {
|
|
314
|
-
console.log(
|
|
364
|
+
console.log(chalk2.blue(`
|
|
315
365
|
Opening browser for authentication...
|
|
316
366
|
`));
|
|
317
367
|
open(url);
|
|
@@ -320,12 +370,12 @@ Opening browser for authentication...
|
|
|
320
370
|
|
|
321
371
|
// src/commands/logout.ts
|
|
322
372
|
import { Command as Command2 } from "commander";
|
|
323
|
-
import
|
|
373
|
+
import chalk3 from "chalk";
|
|
324
374
|
var logoutCommand = new Command2("logout").description("Log out and revoke authorization").action(async () => {
|
|
325
375
|
const client2 = getClient();
|
|
326
376
|
const token = await client2.auth.getAccessToken();
|
|
327
377
|
if (!token) {
|
|
328
|
-
console.log(
|
|
378
|
+
console.log(chalk3.yellow("Not logged in."));
|
|
329
379
|
return;
|
|
330
380
|
}
|
|
331
381
|
try {
|
|
@@ -333,12 +383,12 @@ var logoutCommand = new Command2("logout").description("Log out and revoke autho
|
|
|
333
383
|
} catch {
|
|
334
384
|
}
|
|
335
385
|
await client2.auth.logout();
|
|
336
|
-
console.log(
|
|
386
|
+
console.log(chalk3.green("Logged out and revoked authorization."));
|
|
337
387
|
});
|
|
338
388
|
|
|
339
389
|
// src/commands/me.ts
|
|
340
390
|
import { Command as Command3 } from "commander";
|
|
341
|
-
import
|
|
391
|
+
import chalk4 from "chalk";
|
|
342
392
|
import ora2 from "ora";
|
|
343
393
|
var meCommand = new Command3("me").description("Show current authenticated user info").action(async () => {
|
|
344
394
|
const client2 = getClient();
|
|
@@ -346,58 +396,82 @@ var meCommand = new Command3("me").description("Show current authenticated user
|
|
|
346
396
|
try {
|
|
347
397
|
const user = await client2.getCurrentUser();
|
|
348
398
|
spinner.stop();
|
|
349
|
-
console.log(
|
|
399
|
+
console.log(chalk4.bold("\nUser Info:\n"));
|
|
350
400
|
for (const [key, value] of Object.entries(user)) {
|
|
351
|
-
console.log(` ${
|
|
401
|
+
console.log(` ${chalk4.cyan(key)}: ${value}`);
|
|
352
402
|
}
|
|
353
403
|
console.log();
|
|
354
404
|
} catch (err) {
|
|
355
|
-
spinner.
|
|
356
|
-
|
|
405
|
+
spinner.stop();
|
|
406
|
+
if (isAuthError(err)) {
|
|
407
|
+
printError("AUTH_FAILED", "Token invalid or expired. Run `plaud login`.");
|
|
408
|
+
process.exit(ExitCode.AUTH_FAILED);
|
|
409
|
+
}
|
|
410
|
+
if (isNetworkError(err)) {
|
|
411
|
+
printError("UNREACHABLE", "Cannot reach Plaud servers. Check your network.", err);
|
|
412
|
+
process.exit(ExitCode.UNREACHABLE);
|
|
413
|
+
}
|
|
414
|
+
if (isTimeoutError(err)) {
|
|
415
|
+
printError("TIMEOUT", "Request timed out.");
|
|
416
|
+
process.exit(ExitCode.TIMEOUT);
|
|
417
|
+
}
|
|
418
|
+
printError("FETCH_FAILED", "Failed to fetch user info.", err);
|
|
419
|
+
process.exit(ExitCode.ERROR);
|
|
357
420
|
}
|
|
358
421
|
});
|
|
359
422
|
|
|
360
423
|
// src/commands/list-files.ts
|
|
361
424
|
import { Command as Command4 } from "commander";
|
|
362
|
-
import
|
|
425
|
+
import chalk5 from "chalk";
|
|
363
426
|
import ora3 from "ora";
|
|
364
427
|
var listFilesCommand = new Command4("files").description("List your Plaud recordings").option("-p, --page <number>", "Page number", "1").option("-s, --page-size <number>", "Page size", "20").action(async (opts) => {
|
|
365
428
|
const page = parseInt(opts.page);
|
|
366
429
|
const pageSize = parseInt(opts.pageSize);
|
|
367
430
|
if (isNaN(page) || page < 1 || page > 1e3) {
|
|
368
|
-
|
|
369
|
-
process.exit(
|
|
431
|
+
printError("INVALID_ARGS", "--page must be a number between 1 and 1000");
|
|
432
|
+
process.exit(ExitCode.ERROR);
|
|
370
433
|
}
|
|
371
434
|
if (isNaN(pageSize) || pageSize < 10 || pageSize > 100) {
|
|
372
|
-
|
|
373
|
-
process.exit(
|
|
435
|
+
printError("INVALID_ARGS", "--page-size must be a number between 10 and 100");
|
|
436
|
+
process.exit(ExitCode.ERROR);
|
|
374
437
|
}
|
|
375
438
|
const client2 = getClient();
|
|
376
439
|
const spinner = ora3("Fetching files...").start();
|
|
377
440
|
try {
|
|
378
441
|
const result = await client2.listFiles(page, pageSize);
|
|
379
442
|
spinner.stop();
|
|
380
|
-
console.log(
|
|
443
|
+
console.log(chalk5.bold(`
|
|
381
444
|
Files on this page: ${result.data.length}
|
|
382
445
|
`));
|
|
383
446
|
for (const file of result.data) {
|
|
384
447
|
const date = new Date(file.created_at).toLocaleDateString();
|
|
385
448
|
const duration = file.duration ? `${Math.round(file.duration / 60)}min` : "";
|
|
386
|
-
console.log(` ${
|
|
449
|
+
console.log(` ${chalk5.cyan(file.id)} ${file.name} ${chalk5.gray(date)} ${chalk5.gray(duration)}`);
|
|
387
450
|
}
|
|
388
|
-
console.log(
|
|
389
|
-
|
|
390
|
-
Page ${result.page}`)
|
|
391
|
-
);
|
|
451
|
+
console.log(chalk5.gray(`
|
|
452
|
+
Page ${result.page}`));
|
|
392
453
|
} catch (err) {
|
|
393
|
-
spinner.
|
|
394
|
-
|
|
454
|
+
spinner.stop();
|
|
455
|
+
if (isAuthError(err)) {
|
|
456
|
+
printError("AUTH_FAILED", "Token invalid or expired. Run `plaud login`.");
|
|
457
|
+
process.exit(ExitCode.AUTH_FAILED);
|
|
458
|
+
}
|
|
459
|
+
if (isNetworkError(err)) {
|
|
460
|
+
printError("UNREACHABLE", "Cannot reach Plaud servers. Check your network.", err);
|
|
461
|
+
process.exit(ExitCode.UNREACHABLE);
|
|
462
|
+
}
|
|
463
|
+
if (isTimeoutError(err)) {
|
|
464
|
+
printError("TIMEOUT", "Request timed out.");
|
|
465
|
+
process.exit(ExitCode.TIMEOUT);
|
|
466
|
+
}
|
|
467
|
+
printError("FETCH_FAILED", "Failed to fetch files.", err);
|
|
468
|
+
process.exit(ExitCode.ERROR);
|
|
395
469
|
}
|
|
396
470
|
});
|
|
397
471
|
|
|
398
472
|
// src/commands/get-file.ts
|
|
399
473
|
import { Command as Command5 } from "commander";
|
|
400
|
-
import
|
|
474
|
+
import chalk6 from "chalk";
|
|
401
475
|
import ora4 from "ora";
|
|
402
476
|
function formatDuration(ms) {
|
|
403
477
|
const totalSeconds = Math.floor(ms / 1e3);
|
|
@@ -415,26 +489,43 @@ var getFileCommand = new Command5("file").description("Get details of a specific
|
|
|
415
489
|
const noteList = file.note_list ?? [];
|
|
416
490
|
const hasTranscript = sourceList.some((s) => s.data_type === "transaction");
|
|
417
491
|
const hasSummary = noteList.some((n) => n.data_type === "auto_sum_note");
|
|
418
|
-
console.log(
|
|
419
|
-
console.log(` ${
|
|
420
|
-
console.log(` ${
|
|
421
|
-
console.log(` ${
|
|
422
|
-
console.log(` ${
|
|
423
|
-
console.log(` ${
|
|
424
|
-
console.log(` ${
|
|
425
|
-
console.log(` ${
|
|
426
|
-
console.log(` ${
|
|
427
|
-
console.log(` ${
|
|
492
|
+
console.log(chalk6.bold("\nFile Details:\n"));
|
|
493
|
+
console.log(` ${chalk6.cyan("id")}: ${file.id}`);
|
|
494
|
+
console.log(` ${chalk6.cyan("name")}: ${file.name}`);
|
|
495
|
+
console.log(` ${chalk6.cyan("created_at")}: ${file.created_at}`);
|
|
496
|
+
console.log(` ${chalk6.cyan("start_at")}: ${file.start_at ?? "-"}`);
|
|
497
|
+
console.log(` ${chalk6.cyan("duration")}: ${file.duration ? formatDuration(file.duration) : "-"}`);
|
|
498
|
+
console.log(` ${chalk6.cyan("serial_number")}: ${file.serial_number ?? "-"}`);
|
|
499
|
+
console.log(` ${chalk6.cyan("audio")}: ${file.presigned_url ? chalk6.green("available") : chalk6.gray("unavailable")}`);
|
|
500
|
+
console.log(` ${chalk6.cyan("transcript")}: ${hasTranscript ? chalk6.green("available") : chalk6.gray("unavailable")}`);
|
|
501
|
+
console.log(` ${chalk6.cyan("summary")}: ${hasSummary ? chalk6.green("available") : chalk6.gray("unavailable")}`);
|
|
428
502
|
console.log();
|
|
429
503
|
} catch (err) {
|
|
430
|
-
spinner.
|
|
431
|
-
|
|
504
|
+
spinner.stop();
|
|
505
|
+
if (isAuthError(err)) {
|
|
506
|
+
printError("AUTH_FAILED", "Token invalid or expired. Run `plaud login`.");
|
|
507
|
+
process.exit(ExitCode.AUTH_FAILED);
|
|
508
|
+
}
|
|
509
|
+
if (isNetworkError(err)) {
|
|
510
|
+
printError("UNREACHABLE", "Cannot reach Plaud servers. Check your network.", err);
|
|
511
|
+
process.exit(ExitCode.UNREACHABLE);
|
|
512
|
+
}
|
|
513
|
+
if (isTimeoutError(err)) {
|
|
514
|
+
printError("TIMEOUT", "Request timed out.");
|
|
515
|
+
process.exit(ExitCode.TIMEOUT);
|
|
516
|
+
}
|
|
517
|
+
if (err instanceof Error && err.message.includes("404")) {
|
|
518
|
+
printError("NOT_FOUND", `File not found: ${fileId}`);
|
|
519
|
+
process.exit(ExitCode.ERROR);
|
|
520
|
+
}
|
|
521
|
+
printError("FETCH_FAILED", "Failed to fetch file.", err);
|
|
522
|
+
process.exit(ExitCode.ERROR);
|
|
432
523
|
}
|
|
433
524
|
});
|
|
434
525
|
|
|
435
526
|
// src/commands/audio.ts
|
|
436
527
|
import { Command as Command6 } from "commander";
|
|
437
|
-
import
|
|
528
|
+
import chalk7 from "chalk";
|
|
438
529
|
import ora5 from "ora";
|
|
439
530
|
var audioCommand = new Command6("audio").description("Get the audio download URL for a Plaud recording").argument("<file_id>", "The file ID to retrieve audio for").action(async (fileId) => {
|
|
440
531
|
const client2 = getClient();
|
|
@@ -443,22 +534,35 @@ var audioCommand = new Command6("audio").description("Get the audio download URL
|
|
|
443
534
|
const file = await client2.getFile(fileId);
|
|
444
535
|
spinner.stop();
|
|
445
536
|
if (!file.presigned_url) {
|
|
446
|
-
console.log(
|
|
537
|
+
console.log(chalk7.yellow("Audio not available for this recording."));
|
|
447
538
|
return;
|
|
448
539
|
}
|
|
449
|
-
console.log(
|
|
540
|
+
console.log(chalk7.bold("\nAudio Download URL:\n"));
|
|
450
541
|
console.log(file.presigned_url);
|
|
451
|
-
console.log(
|
|
542
|
+
console.log(chalk7.gray("\nNote: This URL expires in 24 hours."));
|
|
452
543
|
console.log();
|
|
453
544
|
} catch (err) {
|
|
454
|
-
spinner.
|
|
455
|
-
|
|
545
|
+
spinner.stop();
|
|
546
|
+
if (isAuthError(err)) {
|
|
547
|
+
printError("AUTH_FAILED", "Token invalid or expired. Run `plaud login`.");
|
|
548
|
+
process.exit(ExitCode.AUTH_FAILED);
|
|
549
|
+
}
|
|
550
|
+
if (isNetworkError(err)) {
|
|
551
|
+
printError("UNREACHABLE", "Cannot reach Plaud servers. Check your network.", err);
|
|
552
|
+
process.exit(ExitCode.UNREACHABLE);
|
|
553
|
+
}
|
|
554
|
+
if (isTimeoutError(err)) {
|
|
555
|
+
printError("TIMEOUT", "Request timed out.");
|
|
556
|
+
process.exit(ExitCode.TIMEOUT);
|
|
557
|
+
}
|
|
558
|
+
printError("FETCH_FAILED", "Failed to fetch audio URL.", err);
|
|
559
|
+
process.exit(ExitCode.ERROR);
|
|
456
560
|
}
|
|
457
561
|
});
|
|
458
562
|
|
|
459
563
|
// src/commands/transcript.ts
|
|
460
564
|
import { Command as Command7 } from "commander";
|
|
461
|
-
import
|
|
565
|
+
import chalk8 from "chalk";
|
|
462
566
|
import ora6 from "ora";
|
|
463
567
|
import { writeFile as writeFile2 } from "fs/promises";
|
|
464
568
|
function formatTime(ms) {
|
|
@@ -476,7 +580,7 @@ var transcriptCommand = new Command7("transcript").description("Get the transcri
|
|
|
476
580
|
const sourceList = file.source_list ?? [];
|
|
477
581
|
const source = sourceList.find((s) => s.data_type === "transaction");
|
|
478
582
|
if (!source) {
|
|
479
|
-
console.log(
|
|
583
|
+
console.log(chalk8.yellow("Transcript not available for this recording."));
|
|
480
584
|
return;
|
|
481
585
|
}
|
|
482
586
|
const segments = JSON.parse(source.data_content);
|
|
@@ -488,23 +592,36 @@ var transcriptCommand = new Command7("transcript").description("Get the transcri
|
|
|
488
592
|
const output = lines.join("\n");
|
|
489
593
|
if (opts.output) {
|
|
490
594
|
await writeFile2(opts.output, output, "utf-8");
|
|
491
|
-
console.log(
|
|
595
|
+
console.log(chalk8.green(`Transcript saved to ${opts.output}`));
|
|
492
596
|
} else {
|
|
493
|
-
console.log(
|
|
597
|
+
console.log(chalk8.bold(`
|
|
494
598
|
Transcript: ${file.name}
|
|
495
599
|
`));
|
|
496
600
|
console.log(output);
|
|
497
601
|
console.log();
|
|
498
602
|
}
|
|
499
603
|
} catch (err) {
|
|
500
|
-
spinner.
|
|
501
|
-
|
|
604
|
+
spinner.stop();
|
|
605
|
+
if (isAuthError(err)) {
|
|
606
|
+
printError("AUTH_FAILED", "Token invalid or expired. Run `plaud login`.");
|
|
607
|
+
process.exit(ExitCode.AUTH_FAILED);
|
|
608
|
+
}
|
|
609
|
+
if (isNetworkError(err)) {
|
|
610
|
+
printError("UNREACHABLE", "Cannot reach Plaud servers. Check your network.", err);
|
|
611
|
+
process.exit(ExitCode.UNREACHABLE);
|
|
612
|
+
}
|
|
613
|
+
if (isTimeoutError(err)) {
|
|
614
|
+
printError("TIMEOUT", "Request timed out.");
|
|
615
|
+
process.exit(ExitCode.TIMEOUT);
|
|
616
|
+
}
|
|
617
|
+
printError("FETCH_FAILED", "Failed to fetch transcript.", err);
|
|
618
|
+
process.exit(ExitCode.ERROR);
|
|
502
619
|
}
|
|
503
620
|
});
|
|
504
621
|
|
|
505
622
|
// src/commands/summary.ts
|
|
506
623
|
import { Command as Command8 } from "commander";
|
|
507
|
-
import
|
|
624
|
+
import chalk9 from "chalk";
|
|
508
625
|
import ora7 from "ora";
|
|
509
626
|
import { writeFile as writeFile3 } from "fs/promises";
|
|
510
627
|
var summaryCommand = new Command8("summary").description("Get the AI summary for a Plaud recording").argument("<file_id>", "The file ID to retrieve summary for").option("-o, --output <file>", "Save summary to a file").action(async (fileId, opts) => {
|
|
@@ -516,29 +633,50 @@ var summaryCommand = new Command8("summary").description("Get the AI summary for
|
|
|
516
633
|
const noteList = file.note_list ?? [];
|
|
517
634
|
const note = noteList.find((n) => n.data_type === "auto_sum_note");
|
|
518
635
|
if (!note || !note.data_content) {
|
|
519
|
-
console.log(
|
|
636
|
+
console.log(chalk9.yellow("Summary not available for this recording."));
|
|
520
637
|
return;
|
|
521
638
|
}
|
|
522
639
|
const content = note.data_content;
|
|
523
640
|
if (opts.output) {
|
|
524
641
|
await writeFile3(opts.output, content, "utf-8");
|
|
525
|
-
console.log(
|
|
642
|
+
console.log(chalk9.green(`Summary saved to ${opts.output}`));
|
|
526
643
|
} else {
|
|
527
|
-
console.log(
|
|
644
|
+
console.log(chalk9.bold(`
|
|
528
645
|
Summary: ${file.name}
|
|
529
646
|
`));
|
|
530
647
|
console.log(content);
|
|
531
648
|
console.log();
|
|
532
649
|
}
|
|
533
650
|
} catch (err) {
|
|
534
|
-
spinner.
|
|
535
|
-
|
|
651
|
+
spinner.stop();
|
|
652
|
+
if (isAuthError(err)) {
|
|
653
|
+
printError("AUTH_FAILED", "Token invalid or expired. Run `plaud login`.");
|
|
654
|
+
process.exit(ExitCode.AUTH_FAILED);
|
|
655
|
+
}
|
|
656
|
+
if (isNetworkError(err)) {
|
|
657
|
+
printError("UNREACHABLE", "Cannot reach Plaud servers. Check your network.", err);
|
|
658
|
+
process.exit(ExitCode.UNREACHABLE);
|
|
659
|
+
}
|
|
660
|
+
if (isTimeoutError(err)) {
|
|
661
|
+
printError("TIMEOUT", "Request timed out.");
|
|
662
|
+
process.exit(ExitCode.TIMEOUT);
|
|
663
|
+
}
|
|
664
|
+
printError("FETCH_FAILED", "Failed to fetch summary.", err);
|
|
665
|
+
process.exit(ExitCode.ERROR);
|
|
536
666
|
}
|
|
537
667
|
});
|
|
538
668
|
|
|
669
|
+
// src/commands/version.ts
|
|
670
|
+
import { Command as Command9 } from "commander";
|
|
671
|
+
var versionCommand = new Command9("version").description("Show CLI version information").action(() => {
|
|
672
|
+
console.log(`plaud ${"0.1.4"}`);
|
|
673
|
+
if ("8ad7434") console.log(`commit ${"8ad7434"}`);
|
|
674
|
+
if ("2026-04-16T03:13:01.650Z") console.log(`built ${"2026-04-16T03:13:01.650Z"}`);
|
|
675
|
+
});
|
|
676
|
+
|
|
539
677
|
// src/index.ts
|
|
540
|
-
var program = new
|
|
541
|
-
program.name("plaud").description("Plaud CLI - manage your Plaud recordings")
|
|
678
|
+
var program = new Command10();
|
|
679
|
+
program.name("plaud").description("Plaud CLI - manage your Plaud recordings");
|
|
542
680
|
program.addCommand(loginCommand);
|
|
543
681
|
program.addCommand(logoutCommand);
|
|
544
682
|
program.addCommand(meCommand);
|
|
@@ -547,4 +685,5 @@ program.addCommand(getFileCommand);
|
|
|
547
685
|
program.addCommand(audioCommand);
|
|
548
686
|
program.addCommand(transcriptCommand);
|
|
549
687
|
program.addCommand(summaryCommand);
|
|
688
|
+
program.addCommand(versionCommand);
|
|
550
689
|
program.parse();
|
package/package.json
CHANGED
|
@@ -1,26 +1,29 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plaud-ai/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"bin": {
|
|
6
6
|
"plaud": "dist/index.js"
|
|
7
7
|
},
|
|
8
|
-
"files": [
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
"dev": "tsup --watch",
|
|
12
|
-
"clean": "rm -rf dist"
|
|
13
|
-
},
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
14
11
|
"dependencies": {
|
|
15
12
|
"chalk": "^5.4.0",
|
|
16
13
|
"commander": "^13.0.0",
|
|
17
14
|
"dotenv": "^17.3.1",
|
|
18
15
|
"open": "^10.2.0",
|
|
19
|
-
"ora": "^8.1.0"
|
|
16
|
+
"ora": "^8.1.0",
|
|
17
|
+
"yaml": "^2.8.3"
|
|
20
18
|
},
|
|
21
19
|
"devDependencies": {
|
|
22
|
-
"@plaud-ai/shared": "workspace:*",
|
|
23
20
|
"@types/node": "^25.5.0",
|
|
24
|
-
"typescript": "^5.7.0"
|
|
21
|
+
"typescript": "^5.7.0",
|
|
22
|
+
"@plaud-ai/shared": "0.1.0"
|
|
23
|
+
},
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "tsup",
|
|
26
|
+
"dev": "tsup --watch",
|
|
27
|
+
"clean": "rm -rf dist"
|
|
25
28
|
}
|
|
26
|
-
}
|
|
29
|
+
}
|