@wilm-ai/wilma-cli 1.2.0 → 1.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/LICENSE +21 -0
- package/dist/index.js +110 -29
- package/package.json +10 -11
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Wilm.ai
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { emitKeypressEvents } from "node:readline";
|
|
3
3
|
import { select, input, password } from "@inquirer/prompts";
|
|
4
|
+
import { createHmac } from "node:crypto";
|
|
4
5
|
import { readFile, writeFile, mkdir } from "node:fs/promises";
|
|
5
6
|
import { spawn } from "node:child_process";
|
|
6
7
|
import { dirname, resolve } from "node:path";
|
|
7
|
-
import { WilmaClient, listTenants, } from "@wilm-ai/wilma-client";
|
|
8
|
+
import { WilmaClient, MfaRequiredError, listTenants, } from "@wilm-ai/wilma-client";
|
|
8
9
|
import { clearConfig, getConfigPath, loadConfig, obfuscateSecret, revealSecret, saveConfig, } from "./config.js";
|
|
9
10
|
// Enable keypress events for escape key detection
|
|
10
11
|
if (process.stdin.isTTY) {
|
|
@@ -142,7 +143,8 @@ async function runInteractive(config) {
|
|
|
142
143
|
if (!profile) {
|
|
143
144
|
return;
|
|
144
145
|
}
|
|
145
|
-
const
|
|
146
|
+
const interactiveMfa = createInteractiveMfaCallback();
|
|
147
|
+
const client = await WilmaClient.login(profile, interactiveMfa);
|
|
146
148
|
let nextAction = await selectOrCancel({
|
|
147
149
|
message: "What do you want to view?",
|
|
148
150
|
pageSize: 15,
|
|
@@ -377,7 +379,8 @@ async function handleCommand(args, config) {
|
|
|
377
379
|
const profile = await getProfileForCommandNonInteractive(config, flags);
|
|
378
380
|
if (!profile)
|
|
379
381
|
return;
|
|
380
|
-
const
|
|
382
|
+
const mfaCallback = createNonInteractiveMfaCallback(flags.totpSecret);
|
|
383
|
+
const client = await WilmaClient.login(profile, mfaCallback);
|
|
381
384
|
if (command === "kids") {
|
|
382
385
|
const students = await getStudentsForCommand(profile, config);
|
|
383
386
|
if (flags.json) {
|
|
@@ -409,12 +412,12 @@ async function handleCommand(args, config) {
|
|
|
409
412
|
const perStudentClient = await WilmaClient.login({
|
|
410
413
|
...profile,
|
|
411
414
|
studentNumber: studentInfo?.studentNumber ?? profile.studentNumber,
|
|
412
|
-
});
|
|
415
|
+
}, mfaCallback);
|
|
413
416
|
await outputNewsItem(perStudentClient, newsId, flags.json);
|
|
414
417
|
return;
|
|
415
418
|
}
|
|
416
419
|
if (flags.allStudents) {
|
|
417
|
-
await outputAllNews(profile, config, flags.limit ?? 20, flags.json);
|
|
420
|
+
await outputAllNews(profile, config, flags.limit ?? 20, flags.json, mfaCallback);
|
|
418
421
|
return;
|
|
419
422
|
}
|
|
420
423
|
const studentInfo = await resolveStudentForFlags(profile, config, flags.student);
|
|
@@ -425,7 +428,7 @@ async function handleCommand(args, config) {
|
|
|
425
428
|
const perStudentClient = await WilmaClient.login({
|
|
426
429
|
...profile,
|
|
427
430
|
studentNumber: studentInfo?.studentNumber ?? profile.studentNumber,
|
|
428
|
-
});
|
|
431
|
+
}, mfaCallback);
|
|
429
432
|
await outputNews(perStudentClient, {
|
|
430
433
|
limit: flags.limit ?? 20,
|
|
431
434
|
json: flags.json,
|
|
@@ -452,7 +455,7 @@ async function handleCommand(args, config) {
|
|
|
452
455
|
const perStudentClient = await WilmaClient.login({
|
|
453
456
|
...profile,
|
|
454
457
|
studentNumber: studentInfo?.studentNumber ?? profile.studentNumber,
|
|
455
|
-
});
|
|
458
|
+
}, mfaCallback);
|
|
456
459
|
await outputMessageItem(perStudentClient, messageId, flags.json);
|
|
457
460
|
return;
|
|
458
461
|
}
|
|
@@ -461,7 +464,7 @@ async function handleCommand(args, config) {
|
|
|
461
464
|
folder: flags.folder ?? "inbox",
|
|
462
465
|
limit: flags.limit ?? 20,
|
|
463
466
|
json: flags.json,
|
|
464
|
-
});
|
|
467
|
+
}, mfaCallback);
|
|
465
468
|
return;
|
|
466
469
|
}
|
|
467
470
|
const studentInfo = await resolveStudentForFlags(profile, config, flags.student);
|
|
@@ -472,7 +475,7 @@ async function handleCommand(args, config) {
|
|
|
472
475
|
const perStudentClient = await WilmaClient.login({
|
|
473
476
|
...profile,
|
|
474
477
|
studentNumber: studentInfo?.studentNumber ?? profile.studentNumber,
|
|
475
|
-
});
|
|
478
|
+
}, mfaCallback);
|
|
476
479
|
await outputMessages(perStudentClient, {
|
|
477
480
|
folder: flags.folder ?? "inbox",
|
|
478
481
|
limit: flags.limit ?? 20,
|
|
@@ -483,7 +486,7 @@ async function handleCommand(args, config) {
|
|
|
483
486
|
}
|
|
484
487
|
if (command === "exams") {
|
|
485
488
|
if (flags.allStudents) {
|
|
486
|
-
await outputAllExams(profile, config, flags.limit ?? 20, flags.json);
|
|
489
|
+
await outputAllExams(profile, config, flags.limit ?? 20, flags.json, mfaCallback);
|
|
487
490
|
return;
|
|
488
491
|
}
|
|
489
492
|
const studentInfo = await resolveStudentForFlags(profile, config, flags.student);
|
|
@@ -494,7 +497,7 @@ async function handleCommand(args, config) {
|
|
|
494
497
|
const perStudentClient = await WilmaClient.login({
|
|
495
498
|
...profile,
|
|
496
499
|
studentNumber: studentInfo?.studentNumber ?? profile.studentNumber,
|
|
497
|
-
});
|
|
500
|
+
}, mfaCallback);
|
|
498
501
|
await outputUpcomingExams(perStudentClient, {
|
|
499
502
|
limit: flags.limit ?? 20,
|
|
500
503
|
json: flags.json,
|
|
@@ -504,7 +507,7 @@ async function handleCommand(args, config) {
|
|
|
504
507
|
}
|
|
505
508
|
if (command === "schedule") {
|
|
506
509
|
if (flags.allStudents) {
|
|
507
|
-
await outputAllOverviewCommand(profile, config, "schedule", flags);
|
|
510
|
+
await outputAllOverviewCommand(profile, config, "schedule", flags, mfaCallback);
|
|
508
511
|
return;
|
|
509
512
|
}
|
|
510
513
|
const studentInfo = await resolveStudentForFlags(profile, config, flags.student);
|
|
@@ -515,7 +518,7 @@ async function handleCommand(args, config) {
|
|
|
515
518
|
const perStudentClient = await WilmaClient.login({
|
|
516
519
|
...profile,
|
|
517
520
|
studentNumber: studentInfo?.studentNumber ?? profile.studentNumber,
|
|
518
|
-
});
|
|
521
|
+
}, mfaCallback);
|
|
519
522
|
await outputSchedule(perStudentClient, {
|
|
520
523
|
when: flags.when ?? "week",
|
|
521
524
|
date: flags.date,
|
|
@@ -527,7 +530,7 @@ async function handleCommand(args, config) {
|
|
|
527
530
|
}
|
|
528
531
|
if (command === "homework") {
|
|
529
532
|
if (flags.allStudents) {
|
|
530
|
-
await outputAllOverviewCommand(profile, config, "homework", flags);
|
|
533
|
+
await outputAllOverviewCommand(profile, config, "homework", flags, mfaCallback);
|
|
531
534
|
return;
|
|
532
535
|
}
|
|
533
536
|
const studentInfo = await resolveStudentForFlags(profile, config, flags.student);
|
|
@@ -538,7 +541,7 @@ async function handleCommand(args, config) {
|
|
|
538
541
|
const perStudentClient = await WilmaClient.login({
|
|
539
542
|
...profile,
|
|
540
543
|
studentNumber: studentInfo?.studentNumber ?? profile.studentNumber,
|
|
541
|
-
});
|
|
544
|
+
}, mfaCallback);
|
|
542
545
|
await outputHomework(perStudentClient, {
|
|
543
546
|
limit: flags.limit ?? 10,
|
|
544
547
|
json: flags.json,
|
|
@@ -548,7 +551,7 @@ async function handleCommand(args, config) {
|
|
|
548
551
|
}
|
|
549
552
|
if (command === "grades") {
|
|
550
553
|
if (flags.allStudents) {
|
|
551
|
-
await outputAllOverviewCommand(profile, config, "grades", flags);
|
|
554
|
+
await outputAllOverviewCommand(profile, config, "grades", flags, mfaCallback);
|
|
552
555
|
return;
|
|
553
556
|
}
|
|
554
557
|
const studentInfo = await resolveStudentForFlags(profile, config, flags.student);
|
|
@@ -559,7 +562,7 @@ async function handleCommand(args, config) {
|
|
|
559
562
|
const perStudentClient = await WilmaClient.login({
|
|
560
563
|
...profile,
|
|
561
564
|
studentNumber: studentInfo?.studentNumber ?? profile.studentNumber,
|
|
562
|
-
});
|
|
565
|
+
}, mfaCallback);
|
|
563
566
|
await outputGrades(perStudentClient, {
|
|
564
567
|
limit: flags.limit ?? 20,
|
|
565
568
|
json: flags.json,
|
|
@@ -569,7 +572,7 @@ async function handleCommand(args, config) {
|
|
|
569
572
|
}
|
|
570
573
|
if (command === "summary") {
|
|
571
574
|
if (flags.allStudents) {
|
|
572
|
-
await outputAllOverviewCommand(profile, config, "summary", flags);
|
|
575
|
+
await outputAllOverviewCommand(profile, config, "summary", flags, mfaCallback);
|
|
573
576
|
return;
|
|
574
577
|
}
|
|
575
578
|
const studentInfo = await resolveStudentForFlags(profile, config, flags.student);
|
|
@@ -580,7 +583,7 @@ async function handleCommand(args, config) {
|
|
|
580
583
|
const perStudentClient = await WilmaClient.login({
|
|
581
584
|
...profile,
|
|
582
585
|
studentNumber: studentInfo?.studentNumber ?? profile.studentNumber,
|
|
583
|
-
});
|
|
586
|
+
}, mfaCallback);
|
|
584
587
|
await outputSummary(perStudentClient, {
|
|
585
588
|
days: flags.days ?? 7,
|
|
586
589
|
json: flags.json,
|
|
@@ -606,6 +609,8 @@ function printUsage() {
|
|
|
606
609
|
console.log(" wilma config clear");
|
|
607
610
|
console.log(" wilma --help | -h");
|
|
608
611
|
console.log(" wilma --version | -v");
|
|
612
|
+
console.log("");
|
|
613
|
+
console.log("MFA: --totp-secret <base32-key|otpauth://...>");
|
|
609
614
|
}
|
|
610
615
|
async function getProfileForCommandNonInteractive(config, flags) {
|
|
611
616
|
if (!config.lastProfileId) {
|
|
@@ -695,6 +700,11 @@ function parseArgs(args) {
|
|
|
695
700
|
i += 2;
|
|
696
701
|
continue;
|
|
697
702
|
}
|
|
703
|
+
if (arg === "--totp-secret") {
|
|
704
|
+
flags.totpSecret = rest[i + 1];
|
|
705
|
+
i += 2;
|
|
706
|
+
continue;
|
|
707
|
+
}
|
|
698
708
|
if (!flags.id && !arg.startsWith("--")) {
|
|
699
709
|
flags.id = arg;
|
|
700
710
|
i += 1;
|
|
@@ -1269,6 +1279,68 @@ async function selectOrCancel(opts, clearScreen = true) {
|
|
|
1269
1279
|
process.stdin.removeListener("keypress", onKeypress);
|
|
1270
1280
|
}
|
|
1271
1281
|
}
|
|
1282
|
+
function createInteractiveMfaCallback() {
|
|
1283
|
+
return async (_formkey) => {
|
|
1284
|
+
const code = await input({ message: "Enter MFA code from authenticator app" });
|
|
1285
|
+
if (!code) {
|
|
1286
|
+
throw new Error("MFA cancelled");
|
|
1287
|
+
}
|
|
1288
|
+
return code.trim();
|
|
1289
|
+
};
|
|
1290
|
+
}
|
|
1291
|
+
function createNonInteractiveMfaCallback(totpSecret) {
|
|
1292
|
+
if (!totpSecret)
|
|
1293
|
+
return undefined;
|
|
1294
|
+
const secret = parseTotpSecret(totpSecret);
|
|
1295
|
+
return async (_formkey) => {
|
|
1296
|
+
const code = generateTOTP(secret);
|
|
1297
|
+
return code;
|
|
1298
|
+
};
|
|
1299
|
+
}
|
|
1300
|
+
function parseTotpSecret(raw) {
|
|
1301
|
+
// Accept either a bare base32 key or an otpauth:// URI
|
|
1302
|
+
if (raw.startsWith("otpauth://")) {
|
|
1303
|
+
const url = new URL(raw);
|
|
1304
|
+
const secret = url.searchParams.get("secret");
|
|
1305
|
+
if (!secret) {
|
|
1306
|
+
console.error("No 'secret' parameter found in otpauth:// URI.");
|
|
1307
|
+
process.exit(1);
|
|
1308
|
+
}
|
|
1309
|
+
return secret;
|
|
1310
|
+
}
|
|
1311
|
+
return raw.replace(/[\s-]/g, "");
|
|
1312
|
+
}
|
|
1313
|
+
function generateTOTP(secret) {
|
|
1314
|
+
// TOTP: RFC 6238 — HMAC-SHA1 based, 6-digit, 30-second period
|
|
1315
|
+
const base32Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
|
1316
|
+
// Decode base32 secret
|
|
1317
|
+
const cleanSecret = secret.replace(/[\s=-]+/g, "").toUpperCase();
|
|
1318
|
+
let bits = "";
|
|
1319
|
+
for (const c of cleanSecret) {
|
|
1320
|
+
const val = base32Chars.indexOf(c);
|
|
1321
|
+
if (val === -1)
|
|
1322
|
+
throw new Error(`Invalid base32 character: ${c}`);
|
|
1323
|
+
bits += val.toString(2).padStart(5, "0");
|
|
1324
|
+
}
|
|
1325
|
+
const bytes = new Uint8Array(Math.floor(bits.length / 8));
|
|
1326
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
1327
|
+
bytes[i] = parseInt(bits.slice(i * 8, i * 8 + 8), 2);
|
|
1328
|
+
}
|
|
1329
|
+
const epoch = Math.floor(Date.now() / 1000);
|
|
1330
|
+
const counter = Math.floor(epoch / 30);
|
|
1331
|
+
const counterBuf = Buffer.alloc(8);
|
|
1332
|
+
counterBuf.writeUInt32BE(Math.floor(counter / 0x100000000), 0);
|
|
1333
|
+
counterBuf.writeUInt32BE(counter >>> 0, 4);
|
|
1334
|
+
const hmac = createHmac("sha1", Buffer.from(bytes));
|
|
1335
|
+
hmac.update(counterBuf);
|
|
1336
|
+
const hash = hmac.digest();
|
|
1337
|
+
const offset = hash[hash.length - 1] & 0x0f;
|
|
1338
|
+
const code = ((hash[offset] & 0x7f) << 24) |
|
|
1339
|
+
((hash[offset + 1] & 0xff) << 16) |
|
|
1340
|
+
((hash[offset + 2] & 0xff) << 8) |
|
|
1341
|
+
(hash[offset + 3] & 0xff);
|
|
1342
|
+
return (code % 1000000).toString().padStart(6, "0");
|
|
1343
|
+
}
|
|
1272
1344
|
async function inputOrCancel(opts) {
|
|
1273
1345
|
console.clear();
|
|
1274
1346
|
const prompt = input(opts, { clearPromptOnDone: true });
|
|
@@ -1384,11 +1456,11 @@ async function resolveStudentForFlags(profile, config, student) {
|
|
|
1384
1456
|
const students = await getStudentsForCommand(profile, config);
|
|
1385
1457
|
return students[0] ?? null;
|
|
1386
1458
|
}
|
|
1387
|
-
async function outputAllNews(profile, config, limit, json) {
|
|
1459
|
+
async function outputAllNews(profile, config, limit, json, onMfa) {
|
|
1388
1460
|
const students = await getStudentsForCommand(profile, config);
|
|
1389
1461
|
const results = [];
|
|
1390
1462
|
for (const student of students) {
|
|
1391
|
-
const client = await WilmaClient.login({ ...profile, studentNumber: student.studentNumber });
|
|
1463
|
+
const client = await WilmaClient.login({ ...profile, studentNumber: student.studentNumber }, onMfa);
|
|
1392
1464
|
const news = await client.news.list();
|
|
1393
1465
|
results.push({ student, items: news.slice(0, limit) });
|
|
1394
1466
|
}
|
|
@@ -1404,11 +1476,11 @@ async function outputAllNews(profile, config, limit, json) {
|
|
|
1404
1476
|
});
|
|
1405
1477
|
});
|
|
1406
1478
|
}
|
|
1407
|
-
async function outputAllMessages(profile, config, opts) {
|
|
1479
|
+
async function outputAllMessages(profile, config, opts, onMfa) {
|
|
1408
1480
|
const students = await getStudentsForCommand(profile, config);
|
|
1409
1481
|
const results = [];
|
|
1410
1482
|
for (const student of students) {
|
|
1411
|
-
const client = await WilmaClient.login({ ...profile, studentNumber: student.studentNumber });
|
|
1483
|
+
const client = await WilmaClient.login({ ...profile, studentNumber: student.studentNumber }, onMfa);
|
|
1412
1484
|
const messages = await client.messages.list(opts.folder);
|
|
1413
1485
|
results.push({ student, items: messages.slice(0, opts.limit) });
|
|
1414
1486
|
}
|
|
@@ -1424,11 +1496,11 @@ async function outputAllMessages(profile, config, opts) {
|
|
|
1424
1496
|
});
|
|
1425
1497
|
});
|
|
1426
1498
|
}
|
|
1427
|
-
async function outputAllExams(profile, config, limit, json) {
|
|
1499
|
+
async function outputAllExams(profile, config, limit, json, onMfa) {
|
|
1428
1500
|
const students = await getStudentsForCommand(profile, config);
|
|
1429
1501
|
const results = [];
|
|
1430
1502
|
for (const student of students) {
|
|
1431
|
-
const client = await WilmaClient.login({ ...profile, studentNumber: student.studentNumber });
|
|
1503
|
+
const client = await WilmaClient.login({ ...profile, studentNumber: student.studentNumber }, onMfa);
|
|
1432
1504
|
const overview = await client.overview.get();
|
|
1433
1505
|
results.push({ student, items: overview.upcomingExams.slice(0, limit) });
|
|
1434
1506
|
}
|
|
@@ -1444,13 +1516,13 @@ async function outputAllExams(profile, config, limit, json) {
|
|
|
1444
1516
|
});
|
|
1445
1517
|
});
|
|
1446
1518
|
}
|
|
1447
|
-
async function outputAllOverviewCommand(profile, config, command, flags) {
|
|
1519
|
+
async function outputAllOverviewCommand(profile, config, command, flags, onMfa) {
|
|
1448
1520
|
const students = await getStudentsForCommand(profile, config);
|
|
1449
1521
|
if (command === "summary") {
|
|
1450
1522
|
if (flags.json) {
|
|
1451
1523
|
const summaries = [];
|
|
1452
1524
|
for (const student of students) {
|
|
1453
|
-
const client = await WilmaClient.login({ ...profile, studentNumber: student.studentNumber });
|
|
1525
|
+
const client = await WilmaClient.login({ ...profile, studentNumber: student.studentNumber }, onMfa);
|
|
1454
1526
|
const [overview, news, messages] = await Promise.all([
|
|
1455
1527
|
client.overview.get(),
|
|
1456
1528
|
client.news.list(),
|
|
@@ -1469,7 +1541,7 @@ async function outputAllOverviewCommand(profile, config, command, flags) {
|
|
|
1469
1541
|
}
|
|
1470
1542
|
// Human-readable summary output per student
|
|
1471
1543
|
for (const student of students) {
|
|
1472
|
-
const client = await WilmaClient.login({ ...profile, studentNumber: student.studentNumber });
|
|
1544
|
+
const client = await WilmaClient.login({ ...profile, studentNumber: student.studentNumber }, onMfa);
|
|
1473
1545
|
await outputSummary(client, {
|
|
1474
1546
|
days: flags.days ?? 7,
|
|
1475
1547
|
json: false,
|
|
@@ -1480,7 +1552,7 @@ async function outputAllOverviewCommand(profile, config, command, flags) {
|
|
|
1480
1552
|
}
|
|
1481
1553
|
const results = [];
|
|
1482
1554
|
for (const student of students) {
|
|
1483
|
-
const client = await WilmaClient.login({ ...profile, studentNumber: student.studentNumber });
|
|
1555
|
+
const client = await WilmaClient.login({ ...profile, studentNumber: student.studentNumber }, onMfa);
|
|
1484
1556
|
const overview = await client.overview.get();
|
|
1485
1557
|
if (command === "schedule") {
|
|
1486
1558
|
const when = flags.when || "week";
|
|
@@ -1545,6 +1617,15 @@ main().catch((err) => {
|
|
|
1545
1617
|
if (isPromptCancel(err)) {
|
|
1546
1618
|
process.exit(0);
|
|
1547
1619
|
}
|
|
1620
|
+
if (err instanceof MfaRequiredError) {
|
|
1621
|
+
console.error("MFA is enabled on this Wilma account.");
|
|
1622
|
+
console.error("For non-interactive use, provide your TOTP secret:");
|
|
1623
|
+
console.error(" --totp-secret <base32-key>");
|
|
1624
|
+
console.error(" --totp-secret 'otpauth://totp/...'");
|
|
1625
|
+
console.error("Tip: export the key from your authenticator app (base32 string or otpauth:// URI).");
|
|
1626
|
+
console.error("For interactive use, run 'wilma' without arguments.");
|
|
1627
|
+
process.exit(1);
|
|
1628
|
+
}
|
|
1548
1629
|
console.error("CLI error:", err instanceof Error ? err.message : err);
|
|
1549
1630
|
process.exit(1);
|
|
1550
1631
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wilm-ai/wilma-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -8,17 +8,9 @@
|
|
|
8
8
|
"wilmai": "dist/index.js",
|
|
9
9
|
"wilma": "dist/index.js"
|
|
10
10
|
},
|
|
11
|
-
"scripts": {
|
|
12
|
-
"build": "tsc -p tsconfig.json",
|
|
13
|
-
"lint": "echo 'add lint'",
|
|
14
|
-
"test": "echo 'add tests'",
|
|
15
|
-
"start": "node dist/index.js",
|
|
16
|
-
"prepack": "pnpm --filter @wilm-ai/wilma-client build && pnpm --filter @wilm-ai/wilma-cli build",
|
|
17
|
-
"test:live": "tsc -p tsconfig.json && node test/live.spec.mjs"
|
|
18
|
-
},
|
|
19
11
|
"dependencies": {
|
|
20
12
|
"@inquirer/prompts": "^5.3.8",
|
|
21
|
-
"@wilm-ai/wilma-client": "
|
|
13
|
+
"@wilm-ai/wilma-client": "^1.2.1"
|
|
22
14
|
},
|
|
23
15
|
"devDependencies": {
|
|
24
16
|
"typescript": "^5.6.3"
|
|
@@ -29,5 +21,12 @@
|
|
|
29
21
|
],
|
|
30
22
|
"publishConfig": {
|
|
31
23
|
"access": "public"
|
|
24
|
+
},
|
|
25
|
+
"scripts": {
|
|
26
|
+
"build": "tsc -p tsconfig.json",
|
|
27
|
+
"lint": "echo 'add lint'",
|
|
28
|
+
"test": "echo 'add tests'",
|
|
29
|
+
"start": "node dist/index.js",
|
|
30
|
+
"test:live": "tsc -p tsconfig.json && node test/live.spec.mjs"
|
|
32
31
|
}
|
|
33
|
-
}
|
|
32
|
+
}
|