autonag 0.1.1 → 0.3.0
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/cli.js +168 -64
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +8 -17
- package/dist/index.js +1 -9
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -50,16 +50,8 @@ function createApiClient(baseUrl, defaultToken) {
|
|
|
50
50
|
{ method: "POST", body: JSON.stringify({ nickname }) },
|
|
51
51
|
token
|
|
52
52
|
),
|
|
53
|
-
requestInstanceAccess: (instanceId, token
|
|
53
|
+
requestInstanceAccess: (instanceId, token) => apiFetch(
|
|
54
54
|
`/instances/${instanceId}/access/request`,
|
|
55
|
-
{ method: "POST", body: JSON.stringify(inviteCode ? { inviteCode } : {}) },
|
|
56
|
-
token
|
|
57
|
-
),
|
|
58
|
-
getInvite: (code) => apiFetch(
|
|
59
|
-
`/invites/${code}`
|
|
60
|
-
),
|
|
61
|
-
createInvite: (instanceId, token) => apiFetch(
|
|
62
|
-
`/instances/${instanceId}/invites`,
|
|
63
55
|
{ method: "POST", body: JSON.stringify({}) },
|
|
64
56
|
token
|
|
65
57
|
),
|
|
@@ -227,7 +219,8 @@ function fmtDate(ms) {
|
|
|
227
219
|
function shortId(id) {
|
|
228
220
|
return id.slice(0, 8);
|
|
229
221
|
}
|
|
230
|
-
function col(s, w) {
|
|
222
|
+
function col(s, w, ellipsis = false) {
|
|
223
|
+
if (ellipsis && s.length > w) return s.slice(0, w - 1) + "\u2026";
|
|
231
224
|
return s.slice(0, w).padEnd(w);
|
|
232
225
|
}
|
|
233
226
|
async function resolveTimerId(prefix, cfg2) {
|
|
@@ -353,17 +346,13 @@ async function cmdInstancesSelect(id, cfg2) {
|
|
|
353
346
|
saveConfig(cfg2);
|
|
354
347
|
console.log(`Default instance set to ${instanceId}`);
|
|
355
348
|
}
|
|
356
|
-
async function cmdInstancesJoin(
|
|
349
|
+
async function cmdInstancesJoin(instanceId, cfg2) {
|
|
357
350
|
requireToken(cfg2);
|
|
358
351
|
const api = createApiClient(cfg2.server, cfg2.token);
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
}
|
|
364
|
-
await api.requestInstanceAccess(invite.instanceId, cfg2.token, code);
|
|
365
|
-
console.log(`Joined instance "${invite.instanceNickname}" (${shortId(invite.instanceId)}\u2026)`);
|
|
366
|
-
console.log(`Run: autonag instances select ${invite.instanceId}`);
|
|
352
|
+
await api.requestInstanceAccess(instanceId, cfg2.token);
|
|
353
|
+
console.log(`Access requested for instance ${shortId(instanceId)}\u2026`);
|
|
354
|
+
console.log(`An admin will need to approve your request.`);
|
|
355
|
+
console.log(`Once approved, run: autonag instances select ${instanceId}`);
|
|
367
356
|
}
|
|
368
357
|
async function cmdTimersList(cfg2) {
|
|
369
358
|
requireToken(cfg2);
|
|
@@ -381,7 +370,7 @@ async function cmdTimersList(cfg2) {
|
|
|
381
370
|
const remaining = t.currentExpiry - now;
|
|
382
371
|
const label = remaining < 0 ? `OVERDUE ${fmtCountdown(remaining)}` : `in ${fmtCountdown(remaining)}`;
|
|
383
372
|
const recur = t.recurrence ? "\u21BB" : "";
|
|
384
|
-
console.log(`${col(shortId(t.id) + "\u2026", 10)} ${col(t.name, 24)} ${col(label, 16)} ${recur}`);
|
|
373
|
+
console.log(`${col(shortId(t.id) + "\u2026", 10)} ${col(t.name, 24, true)} ${col(label, 16)} ${recur}`);
|
|
385
374
|
}
|
|
386
375
|
}
|
|
387
376
|
console.log();
|
|
@@ -466,7 +455,7 @@ async function cmdTimersSnooze(id, expiryStr, cfg2) {
|
|
|
466
455
|
await api.updateExpiry(cfg2.instanceId, cfg2.token, timerId, expiry);
|
|
467
456
|
console.log(`Timer ${shortId(timerId)}\u2026 snoozed until ${fmtDate(expiry)}`);
|
|
468
457
|
}
|
|
469
|
-
async function cmdTimersComplete(id, reason, cfg2) {
|
|
458
|
+
async function cmdTimersComplete(id, reason, cfg2, opts = {}) {
|
|
470
459
|
requireToken(cfg2);
|
|
471
460
|
requireInstance(cfg2);
|
|
472
461
|
const api = createApiClient(cfg2.server, cfg2.token);
|
|
@@ -474,7 +463,7 @@ async function cmdTimersComplete(id, reason, cfg2) {
|
|
|
474
463
|
const timerId = await resolveTimerId(id, cfg2);
|
|
475
464
|
const timer = state.timers.find((t) => t.id === timerId);
|
|
476
465
|
if (timer?.recurrence) {
|
|
477
|
-
await api.batchActions(cfg2.instanceId, cfg2.token, [{ type: "recurTimer", timerId, closeReason: reason }]);
|
|
466
|
+
await api.batchActions(cfg2.instanceId, cfg2.token, [{ type: "recurTimer", timerId, closeReason: reason, ...opts.at != null ? { occurredAt: opts.at } : {} }]);
|
|
478
467
|
const newState = await api.getState(cfg2.instanceId, cfg2.token);
|
|
479
468
|
const updated = newState.timers.find((t) => t.id === timerId);
|
|
480
469
|
if (updated) {
|
|
@@ -483,17 +472,21 @@ async function cmdTimersComplete(id, reason, cfg2) {
|
|
|
483
472
|
console.log(`Timer ${shortId(timerId)}\u2026 recurred`);
|
|
484
473
|
}
|
|
485
474
|
} else {
|
|
486
|
-
await api.
|
|
487
|
-
|
|
475
|
+
await api.batchActions(cfg2.instanceId, cfg2.token, [{ type: "completeTimer", timerId, closeReason: reason, ...opts.at != null ? { occurredAt: opts.at } : {} }]);
|
|
476
|
+
const name = timer?.name ?? shortId(timerId);
|
|
477
|
+
console.log(`Timer "${name}" completed (${reason})`);
|
|
488
478
|
}
|
|
489
479
|
}
|
|
490
480
|
async function cmdTimersRemove(id, cfg2) {
|
|
491
481
|
requireToken(cfg2);
|
|
492
482
|
requireInstance(cfg2);
|
|
493
|
-
const timerId = await resolveTimerId(id, cfg2);
|
|
494
483
|
const api = createApiClient(cfg2.server, cfg2.token);
|
|
484
|
+
const state = await api.getState(cfg2.instanceId, cfg2.token);
|
|
485
|
+
const timerId = await resolveTimerId(id, cfg2);
|
|
486
|
+
const timer = state.timers.find((t) => t.id === timerId);
|
|
495
487
|
await api.removeTimer(cfg2.instanceId, cfg2.token, timerId);
|
|
496
|
-
|
|
488
|
+
const name = timer?.name ?? shortId(timerId);
|
|
489
|
+
console.log(`Timer "${name}" removed`);
|
|
497
490
|
}
|
|
498
491
|
async function cmdTimersDescribe(id, text, cfg2) {
|
|
499
492
|
requireToken(cfg2);
|
|
@@ -503,6 +496,23 @@ async function cmdTimersDescribe(id, text, cfg2) {
|
|
|
503
496
|
await api.batchActions(cfg2.instanceId, cfg2.token, [{ type: "updateDescription", timerId, description: text }]);
|
|
504
497
|
console.log(`Timer ${shortId(timerId)}\u2026 description updated`);
|
|
505
498
|
}
|
|
499
|
+
async function cmdTimersGetDescription(id, cfg2) {
|
|
500
|
+
requireToken(cfg2);
|
|
501
|
+
requireInstance(cfg2);
|
|
502
|
+
const timerId = await resolveTimerId(id, cfg2);
|
|
503
|
+
const api = createApiClient(cfg2.server, cfg2.token);
|
|
504
|
+
const state = await api.getState(cfg2.instanceId, cfg2.token);
|
|
505
|
+
const timer = state.timers.find((t) => t.id === timerId);
|
|
506
|
+
if (!timer) {
|
|
507
|
+
console.error(`Timer not found: ${timerId}`);
|
|
508
|
+
process.exit(1);
|
|
509
|
+
}
|
|
510
|
+
if (!timer.description) {
|
|
511
|
+
console.log("(no description)");
|
|
512
|
+
return;
|
|
513
|
+
}
|
|
514
|
+
console.log(timer.description);
|
|
515
|
+
}
|
|
506
516
|
async function cmdTimersRecurrenceSet(id, days, cfg2, opts) {
|
|
507
517
|
requireToken(cfg2);
|
|
508
518
|
requireInstance(cfg2);
|
|
@@ -536,8 +546,8 @@ async function cmdTimersHistory(id, cfg2) {
|
|
|
536
546
|
const { events, nextCursor } = await api.getTimerHistory(cfg2.instanceId, cfg2.token, timerId, { after: cursor });
|
|
537
547
|
for (const ev of events) {
|
|
538
548
|
const p = ev.payload;
|
|
539
|
-
const date = ev.type === "TimerRecurred" ? p["occurredAt"] ?? ev.timestamp : ev.timestamp;
|
|
540
|
-
allEntries.push({ date, closeReason: p["closeReason"] });
|
|
549
|
+
const date = ev.type === "TimerRecurred" || ev.type === "TimerCompletionLogged" ? p["occurredAt"] ?? ev.timestamp : ev.timestamp;
|
|
550
|
+
allEntries.push({ date, closeReason: p["closeReason"], type: ev.type });
|
|
541
551
|
}
|
|
542
552
|
cursor = nextCursor;
|
|
543
553
|
}
|
|
@@ -545,11 +555,26 @@ async function cmdTimersHistory(id, cfg2) {
|
|
|
545
555
|
console.log("No history yet.");
|
|
546
556
|
return;
|
|
547
557
|
}
|
|
548
|
-
console.log(`${"Date".padEnd(22)} Reason`);
|
|
549
|
-
console.log("-".repeat(
|
|
558
|
+
console.log(`${"Date".padEnd(22)} ${"Reason".padEnd(16)} Type`);
|
|
559
|
+
console.log("-".repeat(56));
|
|
550
560
|
for (const e of allEntries) {
|
|
551
|
-
|
|
561
|
+
const typeLabel = e.type === "TimerCompletionLogged" ? "logged" : e.type === "TimerRecurred" ? "recurred" : "completed";
|
|
562
|
+
console.log(`${col(fmtDate(e.date), 22)} ${col(e.closeReason, 16)} ${typeLabel}`);
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
async function cmdTimersLog(id, reason, at, cfg2) {
|
|
566
|
+
requireToken(cfg2);
|
|
567
|
+
requireInstance(cfg2);
|
|
568
|
+
const api = createApiClient(cfg2.server, cfg2.token);
|
|
569
|
+
const state = await api.getState(cfg2.instanceId, cfg2.token);
|
|
570
|
+
const timerId = await resolveTimerId(id, cfg2);
|
|
571
|
+
const timer = state.timers.find((t) => t.id === timerId);
|
|
572
|
+
if (!timer) {
|
|
573
|
+
console.error(`Timer not found: ${id}`);
|
|
574
|
+
process.exit(1);
|
|
552
575
|
}
|
|
576
|
+
await api.batchActions(cfg2.instanceId, cfg2.token, [{ type: "logCompletion", timerId, closeReason: reason, occurredAt: at }]);
|
|
577
|
+
console.log(`Logged "${reason}" for "${timer.name}" at ${fmtDate(at)}`);
|
|
553
578
|
}
|
|
554
579
|
async function cmdShush(durationStr, cfg2) {
|
|
555
580
|
requireToken(cfg2);
|
|
@@ -598,7 +623,51 @@ async function cmdEventsUnskip(id, cfg2) {
|
|
|
598
623
|
await api.unskipEvent(cfg2.instanceId, cfg2.token, eventId);
|
|
599
624
|
console.log(`Event ${shortId(eventId)}\u2026 unskipped`);
|
|
600
625
|
}
|
|
601
|
-
async function
|
|
626
|
+
async function cmdTimersView(id, cfg2) {
|
|
627
|
+
requireToken(cfg2);
|
|
628
|
+
requireInstance(cfg2);
|
|
629
|
+
const timerId = await resolveTimerId(id, cfg2);
|
|
630
|
+
const api = createApiClient(cfg2.server, cfg2.token);
|
|
631
|
+
const state = await api.getState(cfg2.instanceId, cfg2.token);
|
|
632
|
+
const timer = state.timers.find((t) => t.id === timerId);
|
|
633
|
+
if (!timer) {
|
|
634
|
+
console.error(`Timer not found: ${timerId}`);
|
|
635
|
+
process.exit(1);
|
|
636
|
+
}
|
|
637
|
+
const now = Date.now();
|
|
638
|
+
const remaining = timer.currentExpiry - now;
|
|
639
|
+
const expiryStr = `${fmtDate(timer.currentExpiry)} (${remaining >= 0 ? "in " : ""}${fmtCountdown(remaining)})`;
|
|
640
|
+
console.log(`ID: ${timer.id}`);
|
|
641
|
+
console.log(`Name: ${timer.name}`);
|
|
642
|
+
if (timer.description) {
|
|
643
|
+
if (timer.description.length > 500) {
|
|
644
|
+
console.log(`Description: ${timer.description.slice(0, 497)}...`);
|
|
645
|
+
console.log(` (${timer.description.length} chars total \u2014 run 'timers description ${shortId(timerId)}' for full text)`);
|
|
646
|
+
} else {
|
|
647
|
+
console.log(`Description: ${timer.description}`);
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
console.log(`Expires: ${expiryStr}`);
|
|
651
|
+
console.log(`Created: ${fmtDate(timer.created)}`);
|
|
652
|
+
if (timer.recurrence) {
|
|
653
|
+
const r = timer.recurrence;
|
|
654
|
+
const wknd = r.skipWeekends ? ", skip weekends" : "";
|
|
655
|
+
console.log(`Recurrence: every ${r.periodDays}d at ${r.anchorTime} ${r.timezone}${wknd}`);
|
|
656
|
+
}
|
|
657
|
+
const { comments } = await api.listComments(cfg2.instanceId, cfg2.token, timerId);
|
|
658
|
+
if (comments.length > 0) {
|
|
659
|
+
const PREVIEW = 5;
|
|
660
|
+
const shown = comments.slice(-PREVIEW);
|
|
661
|
+
const hidden = comments.length - shown.length;
|
|
662
|
+
console.log(`
|
|
663
|
+
Comments:${hidden > 0 ? ` (${hidden} older \u2014 run 'comments list ${shortId(timerId)}' to see all)` : ""}`);
|
|
664
|
+
for (const c of shown) {
|
|
665
|
+
const text = c.text.length > 80 ? c.text.slice(0, 77) + "..." : c.text;
|
|
666
|
+
console.log(` ${fmtDate(c.createdAt)} ${text}`);
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
async function cmdCommentsList(id, cfg2, opts = {}) {
|
|
602
671
|
requireToken(cfg2);
|
|
603
672
|
requireInstance(cfg2);
|
|
604
673
|
const timerId = await resolveTimerId(id, cfg2);
|
|
@@ -608,7 +677,10 @@ async function cmdCommentsList(id, cfg2) {
|
|
|
608
677
|
console.log("No comments.");
|
|
609
678
|
return;
|
|
610
679
|
}
|
|
611
|
-
|
|
680
|
+
const shown = opts.limit != null ? comments.slice(-opts.limit) : comments;
|
|
681
|
+
const hidden = comments.length - shown.length;
|
|
682
|
+
if (hidden > 0) console.log(`(${hidden} older comments not shown)`);
|
|
683
|
+
for (const c of shown) {
|
|
612
684
|
console.log(`[${fmtDate(c.createdAt)}] ${c.text}`);
|
|
613
685
|
}
|
|
614
686
|
}
|
|
@@ -684,21 +756,15 @@ Set it as your default:
|
|
|
684
756
|
autonag instances select <id>
|
|
685
757
|
\`\`\`
|
|
686
758
|
|
|
687
|
-
To join an instance someone else owns, ask them for
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
\`\`\`
|
|
691
|
-
autonag instances invite
|
|
692
|
-
\`\`\`
|
|
693
|
-
|
|
694
|
-
Then you join with the code they share:
|
|
759
|
+
To join an instance someone else owns, ask them for the instance ID. Then
|
|
760
|
+
request access:
|
|
695
761
|
|
|
696
762
|
\`\`\`
|
|
697
|
-
autonag instances join <
|
|
763
|
+
autonag instances join <instance-id>
|
|
698
764
|
\`\`\`
|
|
699
765
|
|
|
700
|
-
|
|
701
|
-
|
|
766
|
+
An admin will approve your request. The instance ID is not advertised
|
|
767
|
+
publicly \u2014 you need to know it.
|
|
702
768
|
|
|
703
769
|
## Adding timers
|
|
704
770
|
|
|
@@ -842,8 +908,7 @@ Auth:
|
|
|
842
908
|
Instances:
|
|
843
909
|
instances list
|
|
844
910
|
instances request <nickname> Create a new instance
|
|
845
|
-
instances join <
|
|
846
|
-
instances invite Create an invite code for this instance
|
|
911
|
+
instances join <instance-id> Request access to an existing instance
|
|
847
912
|
instances select <id>
|
|
848
913
|
|
|
849
914
|
Timers:
|
|
@@ -851,12 +916,17 @@ Timers:
|
|
|
851
916
|
timers add <name> <expiry> [--desc <text>] [--days <n>] [--anchor <HH:MM>] [--tz <tz>] [--skip-weekends]
|
|
852
917
|
timers rename <id> <name>
|
|
853
918
|
timers snooze <id> <expiry> Update expiry: 1d, 30m, 2h, 90s | 2026-05-01T09:00:00Z | unix-ms:<n>
|
|
854
|
-
timers
|
|
919
|
+
timers pass <id> [--at <datetime>] Complete with reason "pass" (preferred)
|
|
920
|
+
timers fail <id> [--at <datetime>] Complete with reason "fail" (preferred)
|
|
921
|
+
timers complete <id> <reason> [--at <datetime>] Complete with a custom reason
|
|
855
922
|
timers remove <id>
|
|
923
|
+
timers view <id> Show full timer details, description, and recent comments
|
|
856
924
|
timers describe <id> <text> Set description
|
|
925
|
+
timers description <id> Print full description
|
|
857
926
|
timers recurrence set <id> <days> [--anchor <HH:MM>] [--tz <tz>] [--skip-weekends]
|
|
858
927
|
timers recurrence remove <id>
|
|
859
928
|
timers history <id> Show completion history
|
|
929
|
+
timers log <id> <reason> --at <datetime> Log a historical completion (no expiry change)
|
|
860
930
|
|
|
861
931
|
Alarm:
|
|
862
932
|
alarm show Show current alarm state
|
|
@@ -871,7 +941,7 @@ Events:
|
|
|
871
941
|
events unskip <id>
|
|
872
942
|
|
|
873
943
|
Comments:
|
|
874
|
-
comments list <timerId>
|
|
944
|
+
comments list <timerId> [--limit N]
|
|
875
945
|
comments add <timerId> <text>
|
|
876
946
|
|
|
877
947
|
Config saved to ~/.config/autonag/client.json5`;
|
|
@@ -977,19 +1047,10 @@ try {
|
|
|
977
1047
|
} else if (sub === "join") {
|
|
978
1048
|
const { positional } = parseFlags(rest, {});
|
|
979
1049
|
if (!positional[0]) {
|
|
980
|
-
console.error("Usage: autonag instances join <
|
|
1050
|
+
console.error("Usage: autonag instances join <instance-id>");
|
|
981
1051
|
process.exit(1);
|
|
982
1052
|
}
|
|
983
1053
|
await cmdInstancesJoin(positional[0], cfg);
|
|
984
|
-
} else if (sub === "invite") {
|
|
985
|
-
parseFlags(rest, {});
|
|
986
|
-
requireToken(cfg);
|
|
987
|
-
requireInstance(cfg);
|
|
988
|
-
const api = createApiClient(cfg.server, cfg.token);
|
|
989
|
-
const { invite } = await api.createInvite(cfg.instanceId, cfg.token);
|
|
990
|
-
console.log(`Invite code: ${invite.code}`);
|
|
991
|
-
console.log(`Expires: ${fmtDate(invite.expiresAt)}`);
|
|
992
|
-
console.log(`Share this code \u2014 it can only be used once.`);
|
|
993
1054
|
} else if (sub === "select") {
|
|
994
1055
|
const { positional } = parseFlags(rest, {});
|
|
995
1056
|
if (!positional[0]) {
|
|
@@ -1038,13 +1099,30 @@ try {
|
|
|
1038
1099
|
process.exit(1);
|
|
1039
1100
|
}
|
|
1040
1101
|
await cmdTimersSnooze(positional[0], positional[1], cfg);
|
|
1102
|
+
} else if (sub === "pass") {
|
|
1103
|
+
const { positional, flags } = parseFlags(rest, { at: "string" });
|
|
1104
|
+
if (!positional[0]) {
|
|
1105
|
+
console.error("Usage: autonag timers pass <id> [--at <datetime>]");
|
|
1106
|
+
process.exit(1);
|
|
1107
|
+
}
|
|
1108
|
+
const at = flags.at ? parseExpiry(flags.at) : void 0;
|
|
1109
|
+
await cmdTimersComplete(positional[0], "pass", cfg, { at });
|
|
1110
|
+
} else if (sub === "fail") {
|
|
1111
|
+
const { positional, flags } = parseFlags(rest, { at: "string" });
|
|
1112
|
+
if (!positional[0]) {
|
|
1113
|
+
console.error("Usage: autonag timers fail <id> [--at <datetime>]");
|
|
1114
|
+
process.exit(1);
|
|
1115
|
+
}
|
|
1116
|
+
const at = flags.at ? parseExpiry(flags.at) : void 0;
|
|
1117
|
+
await cmdTimersComplete(positional[0], "fail", cfg, { at });
|
|
1041
1118
|
} else if (sub === "complete") {
|
|
1042
|
-
const { positional } = parseFlags(rest, {});
|
|
1119
|
+
const { positional, flags } = parseFlags(rest, { at: "string" });
|
|
1043
1120
|
if (!positional[0] || !positional[1]) {
|
|
1044
|
-
console.error("Usage: autonag timers complete <id> <reason>");
|
|
1121
|
+
console.error("Usage: autonag timers complete <id> <reason> [--at <datetime>]");
|
|
1045
1122
|
process.exit(1);
|
|
1046
1123
|
}
|
|
1047
|
-
|
|
1124
|
+
const at = flags.at ? parseExpiry(flags.at) : void 0;
|
|
1125
|
+
await cmdTimersComplete(positional[0], positional[1], cfg, { at });
|
|
1048
1126
|
} else if (sub === "remove") {
|
|
1049
1127
|
const { positional } = parseFlags(rest, {});
|
|
1050
1128
|
if (!positional[0]) {
|
|
@@ -1059,6 +1137,13 @@ try {
|
|
|
1059
1137
|
process.exit(1);
|
|
1060
1138
|
}
|
|
1061
1139
|
await cmdTimersDescribe(positional[0], positional[1], cfg);
|
|
1140
|
+
} else if (sub === "description") {
|
|
1141
|
+
const { positional } = parseFlags(rest, {});
|
|
1142
|
+
if (!positional[0]) {
|
|
1143
|
+
console.error("Usage: autonag timers description <id>");
|
|
1144
|
+
process.exit(1);
|
|
1145
|
+
}
|
|
1146
|
+
await cmdTimersGetDescription(positional[0], cfg);
|
|
1062
1147
|
} else if (sub === "recurrence") {
|
|
1063
1148
|
const recSub = rest[0];
|
|
1064
1149
|
if (recSub === "set") {
|
|
@@ -1088,6 +1173,13 @@ try {
|
|
|
1088
1173
|
console.error("Usage: autonag timers recurrence set|remove ...");
|
|
1089
1174
|
process.exit(1);
|
|
1090
1175
|
}
|
|
1176
|
+
} else if (sub === "view") {
|
|
1177
|
+
const { positional } = parseFlags(rest, {});
|
|
1178
|
+
if (!positional[0]) {
|
|
1179
|
+
console.error("Usage: autonag timers view <id>");
|
|
1180
|
+
process.exit(1);
|
|
1181
|
+
}
|
|
1182
|
+
await cmdTimersView(positional[0], cfg);
|
|
1091
1183
|
} else if (sub === "history") {
|
|
1092
1184
|
const { positional } = parseFlags(rest, {});
|
|
1093
1185
|
if (!positional[0]) {
|
|
@@ -1095,6 +1187,18 @@ try {
|
|
|
1095
1187
|
process.exit(1);
|
|
1096
1188
|
}
|
|
1097
1189
|
await cmdTimersHistory(positional[0], cfg);
|
|
1190
|
+
} else if (sub === "log") {
|
|
1191
|
+
const { positional, flags } = parseFlags(rest, { at: "string" });
|
|
1192
|
+
if (!positional[0] || !positional[1]) {
|
|
1193
|
+
console.error("Usage: autonag timers log <id> <reason> --at <datetime>");
|
|
1194
|
+
process.exit(1);
|
|
1195
|
+
}
|
|
1196
|
+
if (!flags.at) {
|
|
1197
|
+
console.error("--at <datetime> is required for timers log");
|
|
1198
|
+
process.exit(1);
|
|
1199
|
+
}
|
|
1200
|
+
const at = parseExpiry(flags.at);
|
|
1201
|
+
await cmdTimersLog(positional[0], positional[1], at, cfg);
|
|
1098
1202
|
} else {
|
|
1099
1203
|
console.error(`Unknown subcommand: timers ${sub}`);
|
|
1100
1204
|
process.exit(1);
|
|
@@ -1136,12 +1240,12 @@ try {
|
|
|
1136
1240
|
}
|
|
1137
1241
|
} else if (cmd === "comments") {
|
|
1138
1242
|
if (!sub || sub === "list") {
|
|
1139
|
-
const { positional } = parseFlags(rest, {});
|
|
1243
|
+
const { positional, flags } = parseFlags(rest, { limit: "int" });
|
|
1140
1244
|
if (!positional[0]) {
|
|
1141
|
-
console.error("Usage: autonag comments list <timerId>");
|
|
1245
|
+
console.error("Usage: autonag comments list <timerId> [--limit N]");
|
|
1142
1246
|
process.exit(1);
|
|
1143
1247
|
}
|
|
1144
|
-
await cmdCommentsList(positional[0], cfg);
|
|
1248
|
+
await cmdCommentsList(positional[0], cfg, { limit: flags.limit });
|
|
1145
1249
|
} else if (sub === "add") {
|
|
1146
1250
|
const { positional } = parseFlags(rest, {});
|
|
1147
1251
|
if (!positional[0] || !positional[1]) {
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../cli.ts","../apiClient.ts"],"sourcesContent":["import { join } from \"path\";\nimport { homedir } from \"os\";\nimport { mkdirSync, existsSync, readFileSync, writeFileSync } from \"fs\";\nimport JSON5 from \"json5\";\nimport { createApiClient, ApiError } from \"./apiClient\";\n\n// ---- Config ----\n\ntype Config = {\n server: string;\n token?: string;\n deviceId?: string;\n instanceId?: string;\n};\n\nlet CONFIG_PATH = join(homedir(), \".config\", \"autonag\", \"client.json5\");\n\nfunction loadConfig(): Config {\n if (!existsSync(CONFIG_PATH)) return { server: \"http://localhost:3000\" };\n let raw: string;\n try {\n raw = readFileSync(CONFIG_PATH, \"utf8\");\n } catch (e) {\n console.error(`Cannot read config file ${CONFIG_PATH}: ${e}`);\n process.exit(1);\n }\n try {\n return JSON5.parse(raw) as Config;\n } catch (e) {\n console.error(`Config file ${CONFIG_PATH} is not valid JSON5: ${e}`);\n process.exit(1);\n }\n}\n\nfunction saveConfig(config: Config): void {\n mkdirSync(join(CONFIG_PATH, \"..\"), { recursive: true });\n writeFileSync(CONFIG_PATH, JSON5.stringify(config, null, 2));\n}\n\n// ---- Expiry parsing ----\n\nfunction parseExpiry(input: string): number {\n // Explicit unix milliseconds: unix-ms:<n>\n if (input.startsWith(\"unix-ms:\")) {\n const n = Number(input.slice(8));\n if (!Number.isInteger(n) || n <= 0) {\n console.error(`Invalid expiry \"${input}\". Use unix-ms:<positive-integer>`);\n process.exit(1);\n }\n return n;\n }\n // ISO 8601 with required timezone: 2026-05-01T09:00:00Z or 2026-05-01T09:00:00+05:30\n if (/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(Z|[+-]\\d{2}:\\d{2})$/.test(input)) {\n const ms = Date.parse(input);\n if (isNaN(ms)) {\n console.error(`Invalid datetime \"${input}\"`);\n process.exit(1);\n }\n return ms;\n }\n // Duration: 1d, 30m, 2h, 90s, or combinations like 1d12h\n const match = input.match(/^(?:(\\d+)d)?(?:(\\d+)h)?(?:(\\d+)m)?(?:(\\d+)s)?$/);\n if (match && (match[1] || match[2] || match[3] || match[4])) {\n const d = parseInt(match[1] ?? \"0\");\n const h = parseInt(match[2] ?? \"0\");\n const m = parseInt(match[3] ?? \"0\");\n const s = parseInt(match[4] ?? \"0\");\n return Date.now() + (d * 86400 + h * 3600 + m * 60 + s) * 1000;\n }\n console.error(`Cannot parse expiry \"${input}\". Use: 1d, 30m, 2h, 90s (relative duration), 2026-05-01T09:00:00Z (ISO 8601 with timezone), or unix-ms:<n>`);\n process.exit(1);\n}\n\n// ---- Formatting ----\n\nfunction fmtCountdown(ms: number): string {\n const sign = ms < 0 ? \"-\" : \"\";\n const abs = Math.abs(ms);\n const totalSec = Math.floor(abs / 1000);\n const d = Math.floor(totalSec / 86400);\n const h = Math.floor((totalSec % 86400) / 3600);\n const m = Math.floor((totalSec % 3600) / 60);\n const s = totalSec % 60;\n if (d > 0) return `${sign}${d}d ${h}h`;\n if (h > 0) return `${sign}${h}h ${m}m`;\n if (m > 0) return `${sign}${m}m ${s}s`;\n return `${sign}${s}s`;\n}\n\nfunction fmtDate(ms: number): string {\n return new Date(ms).toLocaleString();\n}\n\nfunction shortId(id: string): string {\n return id.slice(0, 8);\n}\n\nfunction col(s: string, w: number): string {\n return s.slice(0, w).padEnd(w);\n}\n\n// ---- ID resolution ----\n\nasync function resolveTimerId(prefix: string, cfg: Config & { token: string; instanceId: string }): Promise<string> {\n if (/^[0-9a-f-]{36}$/.test(prefix)) return prefix;\n const api = createApiClient(cfg.server, cfg.token);\n const state = await api.getState(cfg.instanceId, cfg.token);\n const matches = state.timers.filter(t => t.id.startsWith(prefix));\n if (matches.length === 0) { console.error(`Timer not found: ${prefix}`); process.exit(1); }\n if (matches.length > 1) {\n console.error(`Ambiguous prefix \"${prefix}\" matches: ${matches.map(t => shortId(t.id) + \"…\").join(\", \")}`);\n process.exit(1);\n }\n return matches[0]!.id;\n}\n\nasync function resolveEventId(prefix: string, cfg: Config & { token: string; instanceId: string }): Promise<string> {\n if (/^[0-9a-f-]{36}$/.test(prefix)) return prefix;\n const api = createApiClient(cfg.server, cfg.token);\n // Fetch all events (paginated default covers most cases)\n const allIds: string[] = [];\n let from = 1;\n while (true) {\n const { events, latestSeq } = await api.listEvents(cfg.instanceId, cfg.token, { from, limit: 200 });\n allIds.push(...events.map(e => e.id));\n if (events.length < 200 || events[events.length - 1]!.seq >= latestSeq) break;\n from = events[events.length - 1]!.seq + 1;\n }\n const matches = allIds.filter(id => id.startsWith(prefix));\n if (matches.length === 0) { console.error(`Event not found: ${prefix}`); process.exit(1); }\n if (matches.length > 1) {\n console.error(`Ambiguous prefix \"${prefix}\" matches: ${matches.map(id => shortId(id) + \"…\").join(\", \")}`);\n process.exit(1);\n }\n return matches[0]!;\n}\n\nasync function resolveInstanceId(prefix: string, cfg: Config & { token: string }): Promise<string> {\n if (/^[0-9a-f-]{36}$/.test(prefix)) return prefix;\n const api = createApiClient(cfg.server, cfg.token);\n const { instances } = await api.listInstances(cfg.token);\n const matches = instances.filter(i => i.id.startsWith(prefix));\n if (matches.length === 0) { console.error(`Instance not found: ${prefix}`); process.exit(1); }\n if (matches.length > 1) {\n console.error(`Ambiguous prefix \"${prefix}\" matches: ${matches.map(i => `\"${i.nickname}\" (${shortId(i.id)}…)`).join(\", \")}`);\n process.exit(1);\n }\n return matches[0]!.id;\n}\n\n// ---- Guards ----\n\nfunction requireToken(cfg: Config): asserts cfg is Config & { token: string } {\n if (!cfg.token) {\n console.error(\"Not registered. Run: autonag register <nickname>\");\n process.exit(1);\n }\n}\n\nfunction requireInstance(cfg: Config): asserts cfg is Config & { instanceId: string } {\n if (!cfg.instanceId) {\n console.error(\"No instance selected. Run: autonag instances select <id>\");\n process.exit(1);\n }\n}\n\n// ---- Commands ----\n\nasync function cmdRegister(nickname: string, cfg: Config): Promise<void> {\n const api = createApiClient(cfg.server);\n const { device, token } = await api.registerDevice(nickname);\n cfg.token = token;\n cfg.deviceId = device.id;\n saveConfig(cfg);\n console.log(`Registered as \"${nickname}\" (${shortId(device.id)}…)`);\n console.log(`Token saved to ${CONFIG_PATH}`);\n console.log(`Waiting for admin approval — run \"autonag status\" to check.`);\n}\n\nasync function cmdStatus(cfg: Config): Promise<void> {\n console.log(`Server: ${cfg.server}`);\n console.log(`Config: ${CONFIG_PATH}`);\n if (!cfg.token) {\n console.log(`Auth: not registered (run: autonag register <nickname>)`);\n return;\n }\n const api = createApiClient(cfg.server, cfg.token);\n try {\n const { device: d } = await api.getMe(cfg.token);\n const status = d.approvedAt ? `approved ${fmtDate(d.approvedAt)}` : \"PENDING APPROVAL\";\n console.log(`Auth: ${d.nickname} (${shortId(d.id)}…) [${status}]`);\n } catch (e) {\n if (e instanceof ApiError && e.status === 401) {\n console.log(`Auth: token invalid or expired`);\n } else throw e;\n }\n console.log(`Instance: ${cfg.instanceId ?? \"none selected (run: autonag instances select <id>)\"}`);\n}\n\nasync function cmdInstancesList(cfg: Config): Promise<void> {\n requireToken(cfg);\n const api = createApiClient(cfg.server, cfg.token);\n const { instances } = await api.listInstances(cfg.token);\n if (instances.length === 0) { console.log(\"No accessible instances.\"); return; }\n for (const i of instances) {\n const status = i.approvedAt ? \"active\" : \"PENDING\";\n const marker = i.id === cfg.instanceId ? \" *\" : \" \";\n console.log(`${marker} ${shortId(i.id)}… \"${i.nickname}\" [${status}]`);\n }\n console.log(`\\n* = current default`);\n}\n\nasync function cmdInstancesRequest(nickname: string, cfg: Config): Promise<void> {\n requireToken(cfg);\n const api = createApiClient(cfg.server, cfg.token);\n const { instance } = await api.requestInstance(nickname, cfg.token);\n console.log(`Requested instance \"${instance.nickname}\" (${shortId(instance.id)}…)`);\n console.log(`Waiting for admin approval.`);\n}\n\nasync function cmdInstancesSelect(id: string, cfg: Config): Promise<void> {\n requireToken(cfg);\n const instanceId = await resolveInstanceId(id, cfg);\n cfg.instanceId = instanceId;\n saveConfig(cfg);\n console.log(`Default instance set to ${instanceId}`);\n}\n\nasync function cmdInstancesJoin(code: string, cfg: Config): Promise<void> {\n requireToken(cfg);\n const api = createApiClient(cfg.server, cfg.token);\n const { invite } = await api.getInvite(code);\n if (!invite.valid) {\n console.error(`Invite is not valid: ${invite.reason ?? \"expired or already used\"}`);\n process.exit(1);\n }\n await api.requestInstanceAccess(invite.instanceId, cfg.token, code);\n console.log(`Joined instance \"${invite.instanceNickname}\" (${shortId(invite.instanceId)}…)`);\n console.log(`Run: autonag instances select ${invite.instanceId}`);\n}\n\nasync function cmdTimersList(cfg: Config): Promise<void> {\n requireToken(cfg);\n requireInstance(cfg);\n const api = createApiClient(cfg.server, cfg.token);\n const state = await api.getState(cfg.instanceId, cfg.token);\n\n const now = Date.now();\n const timers = [...state.timers].sort((a, b) => a.currentExpiry - b.currentExpiry);\n\n if (timers.length === 0) {\n console.log(\"No active timers.\");\n } else {\n console.log(`${\"ID\".padEnd(10)} ${\"Name\".padEnd(24)} ${\"Remaining\".padEnd(16)} Recur`);\n console.log(\"-\".repeat(60));\n for (const t of timers) {\n const remaining = t.currentExpiry - now;\n const label = remaining < 0\n ? `OVERDUE ${fmtCountdown(remaining)}`\n : `in ${fmtCountdown(remaining)}`;\n const recur = t.recurrence ? \"↻\" : \"\";\n console.log(`${col(shortId(t.id) + \"…\", 10)} ${col(t.name, 24)} ${col(label, 16)} ${recur}`);\n }\n }\n\n console.log();\n printAlarmStatus(state, now);\n}\n\nfunction printAlarmStatus(state: { alarm: { on: boolean; startsAt: number | null; urgentName: string | null; color: string }; shush: { expiry: number } | null }, now: number): void {\n const { alarm, shush } = state;\n const shushed = !!(shush && shush.expiry > now);\n const colorLabel: Record<string, string> = {\n blue: \"off\", green: \"green\", yellow: \"yellow\", red: \"red\", flashing: \"FLASHING\",\n };\n\n // Line 1: color + most urgent timer\n if (alarm.startsAt !== null) {\n const diff = alarm.startsAt - now;\n const colorStr = colorLabel[alarm.color] ?? alarm.color;\n const timeStr = diff <= 0 ? `overdue ${fmtCountdown(diff)}` : `in ${fmtCountdown(diff)}`;\n console.log(`[${colorStr}] \"${alarm.urgentName}\" — ${timeStr}`);\n }\n\n // Line 2: alarm state\n if (alarm.on) {\n console.log(`Alarm: ringing.`);\n } else if (shushed) {\n const overdue = alarm.startsAt !== null && alarm.startsAt <= now;\n // \"necessary\" = shush is actually blocking a ring (timer overdue now, or timer fires before shush ends)\n const shushEndsAfterTimer = alarm.startsAt !== null && shush!.expiry >= alarm.startsAt;\n const necessary = overdue || shushEndsAfterTimer;\n if (necessary) {\n const ringIn = fmtCountdown(shush!.expiry - now);\n console.log(`Alarm: off. Will ring in ${ringIn}: Shush expires: ${alarm.urgentName}.`);\n } else if (alarm.startsAt !== null) {\n // Shush ends before timer fires — timer still drives the ring time\n const ringIn = fmtCountdown(alarm.startsAt - now);\n const remaining = fmtCountdown(shush!.expiry - now);\n console.log(`Alarm: off. Will ring in ${ringIn}: ${alarm.urgentName}. (Shushed unnecessarily for ${remaining}.)`);\n } else {\n const remaining = fmtCountdown(shush!.expiry - now);\n console.log(`Alarm: off. Shushed (unnecessarily) for ${remaining}.`);\n }\n } else if (alarm.startsAt !== null) {\n const ringIn = fmtCountdown(alarm.startsAt - now);\n console.log(`Alarm: off. Will ring in ${ringIn}: ${alarm.urgentName}.`);\n } else {\n console.log(`Alarm: off.`);\n }\n}\n\nasync function cmdAlarm(cfg: Config): Promise<void> {\n requireToken(cfg);\n requireInstance(cfg);\n const api = createApiClient(cfg.server, cfg.token);\n const state = await api.getState(cfg.instanceId, cfg.token);\n printAlarmStatus(state, Date.now());\n}\n\nasync function cmdTimersAdd(\n name: string, expiryStr: string, cfg: Config,\n opts: { desc?: string; days?: number; anchor?: string; tz?: string; skipWeekends?: boolean }\n): Promise<void> {\n requireToken(cfg);\n requireInstance(cfg);\n const api = createApiClient(cfg.server, cfg.token);\n const expiry = parseExpiry(expiryStr);\n const recurrence = opts.days !== undefined ? {\n periodDays: opts.days,\n anchorTime: opts.anchor ?? \"09:00\",\n timezone: opts.tz ?? Intl.DateTimeFormat().resolvedOptions().timeZone,\n skipWeekends: opts.skipWeekends ?? false,\n } : undefined;\n await api.addTimer(cfg.instanceId, cfg.token, name, expiry, recurrence, opts.desc);\n const recurNote = recurrence ? ` (recurs every ${opts.days}d)` : \"\";\n console.log(`Timer \"${name}\" added, expires ${fmtDate(expiry)}${recurNote}`);\n}\n\nasync function cmdTimersRename(id: string, name: string, cfg: Config): Promise<void> {\n requireToken(cfg);\n requireInstance(cfg);\n const timerId = await resolveTimerId(id, cfg);\n const api = createApiClient(cfg.server, cfg.token);\n await api.renameTimer(cfg.instanceId, cfg.token, timerId, name);\n console.log(`Timer ${shortId(timerId)}… renamed to \"${name}\"`);\n}\n\nasync function cmdTimersSnooze(id: string, expiryStr: string, cfg: Config): Promise<void> {\n requireToken(cfg);\n requireInstance(cfg);\n const timerId = await resolveTimerId(id, cfg);\n const api = createApiClient(cfg.server, cfg.token);\n const expiry = parseExpiry(expiryStr);\n await api.updateExpiry(cfg.instanceId, cfg.token, timerId, expiry);\n console.log(`Timer ${shortId(timerId)}… snoozed until ${fmtDate(expiry)}`);\n}\n\nasync function cmdTimersComplete(id: string, reason: string, cfg: Config): Promise<void> {\n requireToken(cfg);\n requireInstance(cfg);\n const api = createApiClient(cfg.server, cfg.token);\n const state = await api.getState(cfg.instanceId, cfg.token);\n const timerId = await resolveTimerId(id, cfg);\n const timer = state.timers.find(t => t.id === timerId);\n\n if (timer?.recurrence) {\n await api.batchActions(cfg.instanceId, cfg.token, [{ type: \"recurTimer\", timerId, closeReason: reason }]);\n const newState = await api.getState(cfg.instanceId, cfg.token);\n const updated = newState.timers.find(t => t.id === timerId);\n if (updated) {\n console.log(`Timer \"${timer.name}\" recurred — next: ${fmtDate(updated.currentExpiry)}`);\n } else {\n console.log(`Timer ${shortId(timerId)}… recurred`);\n }\n } else {\n await api.completeTimer(cfg.instanceId, cfg.token, timerId, reason);\n console.log(`Timer ${shortId(timerId)}… completed (${reason})`);\n }\n}\n\nasync function cmdTimersRemove(id: string, cfg: Config): Promise<void> {\n requireToken(cfg);\n requireInstance(cfg);\n const timerId = await resolveTimerId(id, cfg);\n const api = createApiClient(cfg.server, cfg.token);\n await api.removeTimer(cfg.instanceId, cfg.token, timerId);\n console.log(`Timer ${shortId(timerId)}… removed`);\n}\n\nasync function cmdTimersDescribe(id: string, text: string, cfg: Config): Promise<void> {\n requireToken(cfg);\n requireInstance(cfg);\n const timerId = await resolveTimerId(id, cfg);\n const api = createApiClient(cfg.server, cfg.token);\n await api.batchActions(cfg.instanceId, cfg.token, [{ type: \"updateDescription\", timerId, description: text }]);\n console.log(`Timer ${shortId(timerId)}… description updated`);\n}\n\nasync function cmdTimersRecurrenceSet(\n id: string, days: number, cfg: Config,\n opts: { anchor?: string; tz?: string; skipWeekends?: boolean }\n): Promise<void> {\n requireToken(cfg);\n requireInstance(cfg);\n const timerId = await resolveTimerId(id, cfg);\n const api = createApiClient(cfg.server, cfg.token);\n const recurrence = {\n periodDays: days,\n anchorTime: opts.anchor ?? \"09:00\",\n timezone: opts.tz ?? Intl.DateTimeFormat().resolvedOptions().timeZone,\n skipWeekends: opts.skipWeekends ?? false,\n };\n await api.batchActions(cfg.instanceId, cfg.token, [{ type: \"updateRecurrence\", timerId, recurrence }]);\n console.log(`Timer ${shortId(timerId)}… recurrence set to every ${days}d at ${recurrence.anchorTime} (${recurrence.timezone})`);\n}\n\nasync function cmdTimersRecurrenceRemove(id: string, cfg: Config): Promise<void> {\n requireToken(cfg);\n requireInstance(cfg);\n const timerId = await resolveTimerId(id, cfg);\n const api = createApiClient(cfg.server, cfg.token);\n await api.batchActions(cfg.instanceId, cfg.token, [{ type: \"removeRecurrence\", timerId }]);\n console.log(`Timer ${shortId(timerId)}… recurrence removed`);\n}\n\nasync function cmdTimersHistory(id: string, cfg: Config): Promise<void> {\n requireToken(cfg);\n requireInstance(cfg);\n const timerId = await resolveTimerId(id, cfg);\n const api = createApiClient(cfg.server, cfg.token);\n const allEntries: Array<{ date: number; closeReason: string }> = [];\n let cursor: number | null = 0;\n while (cursor !== null) {\n const { events, nextCursor } = await api.getTimerHistory(cfg.instanceId, cfg.token, timerId, { after: cursor });\n for (const ev of events) {\n const p = ev.payload as Record<string, unknown>;\n const date = ev.type === \"TimerRecurred\"\n ? (p[\"occurredAt\"] as number) ?? ev.timestamp\n : ev.timestamp;\n allEntries.push({ date, closeReason: p[\"closeReason\"] as string });\n }\n cursor = nextCursor;\n }\n if (allEntries.length === 0) { console.log(\"No history yet.\"); return; }\n console.log(`${\"Date\".padEnd(22)} Reason`);\n console.log(\"-\".repeat(36));\n for (const e of allEntries) {\n console.log(`${col(fmtDate(e.date), 22)} ${e.closeReason}`);\n }\n}\n\nasync function cmdShush(durationStr: string | undefined, cfg: Config): Promise<void> {\n requireToken(cfg);\n requireInstance(cfg);\n const api = createApiClient(cfg.server, cfg.token);\n const expiry = durationStr ? parseExpiry(durationStr) : Date.now() + 30 * 60 * 1000;\n await api.setShush(cfg.instanceId, cfg.token, expiry);\n console.log(`Alarm silenced until ${fmtDate(expiry)}`);\n}\n\nasync function cmdUnshush(cfg: Config): Promise<void> {\n requireToken(cfg);\n requireInstance(cfg);\n const api = createApiClient(cfg.server, cfg.token);\n await api.clearShush(cfg.instanceId, cfg.token);\n console.log(`Shush cleared`);\n}\n\nasync function cmdEventsList(fromSeq: number, cfg: Config): Promise<void> {\n requireToken(cfg);\n requireInstance(cfg);\n const api = createApiClient(cfg.server, cfg.token);\n const { events } = await api.listEvents(cfg.instanceId, cfg.token, { from: fromSeq });\n if (events.length === 0) { console.log(\"No events.\"); return; }\n console.log(`${\"seq\".padEnd(6)} ${\"ID\".padEnd(10)} ${\"Type\".padEnd(28)} ${\"Time\".padEnd(20)} Skipped`);\n console.log(\"-\".repeat(78));\n for (const e of events) {\n const skipped = e.skipped ? \"yes\" : \"\";\n console.log(`${String(e.seq).padEnd(6)} ${col(shortId(e.id) + \"…\", 10)} ${col(e.type, 28)} ${col(fmtDate(e.timestamp), 20)} ${skipped}`);\n }\n}\n\nasync function cmdEventsSkip(id: string, cfg: Config): Promise<void> {\n requireToken(cfg);\n requireInstance(cfg);\n const eventId = await resolveEventId(id, cfg);\n const api = createApiClient(cfg.server, cfg.token);\n await api.skipEvent(cfg.instanceId, cfg.token, eventId);\n console.log(`Event ${shortId(eventId)}… skipped`);\n}\n\nasync function cmdEventsUnskip(id: string, cfg: Config): Promise<void> {\n requireToken(cfg);\n requireInstance(cfg);\n const eventId = await resolveEventId(id, cfg);\n const api = createApiClient(cfg.server, cfg.token);\n await api.unskipEvent(cfg.instanceId, cfg.token, eventId);\n console.log(`Event ${shortId(eventId)}… unskipped`);\n}\n\nasync function cmdCommentsList(id: string, cfg: Config): Promise<void> {\n requireToken(cfg);\n requireInstance(cfg);\n const timerId = await resolveTimerId(id, cfg);\n const api = createApiClient(cfg.server, cfg.token);\n const { comments } = await api.listComments(cfg.instanceId, cfg.token, timerId);\n if (comments.length === 0) { console.log(\"No comments.\"); return; }\n for (const c of comments) {\n console.log(`[${fmtDate(c.createdAt)}] ${c.text}`);\n }\n}\n\nasync function cmdCommentsAdd(id: string, text: string, cfg: Config): Promise<void> {\n requireToken(cfg);\n requireInstance(cfg);\n const timerId = await resolveTimerId(id, cfg);\n const api = createApiClient(cfg.server, cfg.token);\n await api.addComment(cfg.instanceId, cfg.token, timerId, text);\n console.log(`Comment added`);\n}\n\n// ---- Tutorial ----\n\nfunction cmdTutorial(): void {\n console.log(`# autonag tutorial\n\nautonag is a recurring-task tracker with an alarm. Timers count down; when\nthey expire, your alarm client starts ringing. You mark them done — if the\ntimer is recurring, the next occurrence is automatically scheduled.\n\n## Config\n\nYour config lives at \\`~/.config/autonag/client.json5\\`. It is a JSON5 file\n(JSON with comments and trailing commas), so you can annotate it. After\nregistration it looks something like:\n\n\\`\\`\\`json5\n{\n server: 'https://your-server.example',\n token: '…',\n deviceId: '…',\n instanceId: '…',\n}\n\\`\\`\\`\n\nEdit it directly in a text editor whenever you need to change the server\nURL or switch instances. To use a different config file:\n\n\\`\\`\\`\nautonag --config /path/to/other.json5 timers list\n\\`\\`\\`\n\n## First-time setup\n\nRegister this device — give it a short nickname so the admin knows who you are:\n\n\\`\\`\\`\nautonag register myphone\n\\`\\`\\`\n\nYour auth token and device ID are saved to the config. The device starts in\nPENDING state until an admin approves it. Check your status:\n\n\\`\\`\\`\nautonag status\n\\`\\`\\`\n\n## Getting an instance\n\nTimers live in an instance. Create a new one:\n\n\\`\\`\\`\nautonag instances request home\n\\`\\`\\`\n\nWhen the admin approves it, it shows up in your list:\n\n\\`\\`\\`\nautonag instances list\n\\`\\`\\`\n\nSet it as your default:\n\n\\`\\`\\`\nautonag instances select <id>\n\\`\\`\\`\n\nTo join an instance someone else owns, ask them for an invite code. They\ngenerate one with:\n\n\\`\\`\\`\nautonag instances invite\n\\`\\`\\`\n\nThen you join with the code they share:\n\n\\`\\`\\`\nautonag instances join <code>\n\\`\\`\\`\n\nInvite codes are single-use and expire after 7 days. The instance is not\ndiscoverable by name — you need the code.\n\n## Adding timers\n\nOne-shot reminder due in 2 days:\n\n\\`\\`\\`\nautonag timers add \"Doctor follow-up\" 2d\n\\`\\`\\`\n\nRecurring task every 7 days at 9 AM:\n\n\\`\\`\\`\nautonag timers add \"Weekly review\" 7d --days 7 --anchor 09:00\n\\`\\`\\`\n\nThe first argument after the name is the initial expiry. \\`--days\\` makes it\nrecurring; \\`--anchor\\` sets the time of day; \\`--tz\\` overrides the timezone.\n\n## Checking timers\n\n\\`\\`\\`\nautonag timers list\n\\`\\`\\`\n\n\\`\\`\\`\nID Name Remaining Recur\n------------------------------------------------------------\na1b2c3d4… Doctor follow-up in 1d 23h\ne5f6a7b8… Weekly review in 6d 23h ↻\n\\`\\`\\`\n\nThe ↻ symbol marks recurring timers.\n\n## Completing a timer\n\nMark a timer done with a reason (pass, fail, or any custom string):\n\n\\`\\`\\`\nautonag timers complete e5f6 pass\n\\`\\`\\`\n\nFor a one-shot timer this removes it. For a recurring timer it schedules\nthe next occurrence and tells you when:\n\n\\`\\`\\`\nTimer \"Weekly review\" recurred — next: 4/24/2026, 9:00:00 AM\n\\`\\`\\`\n\nTo permanently stop a recurring timer, remove the recurrence first:\n\n\\`\\`\\`\nautonag timers recurrence remove e5f6\nautonag timers complete e5f6 done\n\\`\\`\\`\n\n## Snoozing\n\nPush a timer's deadline out:\n\n\\`\\`\\`\nautonag timers snooze e5f6 3d\n\\`\\`\\`\n\n## Silencing the alarm\n\nSilence the alarm for 30 minutes (the default):\n\n\\`\\`\\`\nautonag shush\n\\`\\`\\`\n\nOr for a specific duration:\n\n\\`\\`\\`\nautonag shush 2h\n\\`\\`\\`\n\nResume:\n\n\\`\\`\\`\nautonag unshush\n\\`\\`\\`\n\n## History\n\nSee every time a recurring timer was completed:\n\n\\`\\`\\`\nautonag timers history e5f6\n\\`\\`\\`\n\n## Notes and comments\n\nAttach a description to a timer:\n\n\\`\\`\\`\nautonag timers describe e5f6 \"Prep the agenda before this\"\n\\`\\`\\`\n\nAdd timestamped comments (good for logging what happened):\n\n\\`\\`\\`\nautonag comments add e5f6 \"Completed but flagged the follow-up\"\n\\`\\`\\`\n\n## Event log\n\nEvery action is recorded. View the log:\n\n\\`\\`\\`\nautonag events list\n\\`\\`\\`\n\nYou can skip events to undo them — state is recomputed as if the\nskipped event never happened:\n\n\\`\\`\\`\nautonag events skip <event-id>\nautonag events unskip <event-id>\n\\`\\`\\`\n\n---\nRun \\`autonag --help\\` for a full command reference.`);\n}\n\n// ---- Help ----\n\nconst HELP = `autonag client CLI\n\nUsage: autonag [options] <command> [args]\n\nOptions:\n -h, --help Show this help\n -s, --server <url> Server URL (default: http://localhost:3000)\n -i, --instance <id> Instance ID (overrides saved default)\n -c, --config <path> Config file (default: ~/.config/autonag/client.json5)\n\n tutorial Walk through setup and daily workflow\n\nAuth:\n register <nickname> Register this device and save token\n status Show auth status and saved config\n\nInstances:\n instances list\n instances request <nickname> Create a new instance\n instances join <code> Join an existing instance via invite code\n instances invite Create an invite code for this instance\n instances select <id>\n\nTimers:\n timers list\n timers add <name> <expiry> [--desc <text>] [--days <n>] [--anchor <HH:MM>] [--tz <tz>] [--skip-weekends]\n timers rename <id> <name>\n timers snooze <id> <expiry> Update expiry: 1d, 30m, 2h, 90s | 2026-05-01T09:00:00Z | unix-ms:<n>\n timers complete <id> <reason> Complete or recur (reason: pass, fail, or custom)\n timers remove <id>\n timers describe <id> <text> Set description\n timers recurrence set <id> <days> [--anchor <HH:MM>] [--tz <tz>] [--skip-weekends]\n timers recurrence remove <id>\n timers history <id> Show completion history\n\nAlarm:\n alarm show Show current alarm state\n\nShush:\n shush [duration] Silence alarm (default: 30m)\n unshush Clear shush\n\nEvents:\n events list [--from <seq>]\n events skip <id>\n events unskip <id>\n\nComments:\n comments list <timerId>\n comments add <timerId> <text>\n\nConfig saved to ~/.config/autonag/client.json5`;\n\n// ---- Flag parsing ----\n\ntype FlagSchema = Record<string, \"string\" | \"int\" | \"boolean\">;\ntype ParsedFlags = { positional: string[]; flags: Record<string, string | number | boolean> };\n\nfunction parseFlags(args: string[], schema: FlagSchema): ParsedFlags {\n const positional: string[] = [];\n const flags: Record<string, string | number | boolean> = {};\n for (let i = 0; i < args.length; i++) {\n const a = args[i]!;\n if (a.startsWith(\"--\")) {\n const key = a.slice(2);\n if (!(key in schema)) {\n console.error(`Unknown flag: --${key}`);\n process.exit(1);\n }\n const type = schema[key]!;\n if (type === \"boolean\") {\n flags[key] = true;\n } else {\n const next = args[i + 1];\n if (!next || next.startsWith(\"--\")) {\n console.error(`Flag --${key} requires a value`);\n process.exit(1);\n }\n if (type === \"int\") {\n const n = Number(next);\n if (!Number.isInteger(n)) {\n console.error(`Flag --${key} must be an integer, got: \"${next}\"`);\n process.exit(1);\n }\n flags[key] = n;\n } else {\n flags[key] = next;\n }\n i++;\n }\n } else {\n positional.push(a);\n }\n }\n return { positional, flags };\n}\n\n// ---- Arg parsing & dispatch ----\n\nconst rawArgs = process.argv.slice(2);\nconst topArgs: string[] = [];\nlet serverOverride: string | undefined;\nlet instanceOverride: string | undefined;\n\nfor (let i = 0; i < rawArgs.length; i++) {\n const a = rawArgs[i]!;\n if (a === \"-h\" || a === \"--help\") { console.log(HELP); process.exit(0); }\n else if (a === \"-s\" || a === \"--server\") {\n if (!rawArgs[i + 1] || rawArgs[i + 1]!.startsWith(\"-\")) { console.error(\"Flag -s/--server requires a URL\"); process.exit(1); }\n serverOverride = rawArgs[++i];\n }\n else if (a === \"-i\" || a === \"--instance\") {\n if (!rawArgs[i + 1] || rawArgs[i + 1]!.startsWith(\"-\")) { console.error(\"Flag -i/--instance requires an ID\"); process.exit(1); }\n instanceOverride = rawArgs[++i];\n }\n else if (a === \"-c\" || a === \"--config\") {\n if (!rawArgs[i + 1] || rawArgs[i + 1]!.startsWith(\"-\")) { console.error(\"Flag -c/--config requires a path\"); process.exit(1); }\n CONFIG_PATH = rawArgs[++i]!;\n }\n else topArgs.push(a);\n}\n\nconst cfg = loadConfig();\nif (serverOverride) cfg.server = serverOverride;\nif (instanceOverride) cfg.instanceId = instanceOverride;\n\nconst [cmd, sub, ...rest] = topArgs;\n\ntry {\n if (!cmd || cmd === \"help\") {\n parseFlags(rest, {});\n console.log(HELP);\n } else if (cmd === \"tutorial\") {\n parseFlags(rest, {});\n cmdTutorial();\n\n } else if (cmd === \"register\") {\n parseFlags(rest, {});\n if (!sub) { console.error(\"Usage: autonag register <nickname>\"); process.exit(1); }\n await cmdRegister(sub, cfg);\n\n } else if (cmd === \"status\") {\n parseFlags(rest, {});\n await cmdStatus(cfg);\n\n } else if (cmd === \"instances\") {\n if (!sub || sub === \"list\") {\n parseFlags(rest, {});\n await cmdInstancesList(cfg);\n } else if (sub === \"request\") {\n const { positional } = parseFlags(rest, {});\n if (!positional[0]) { console.error(\"Usage: autonag instances request <nickname>\"); process.exit(1); }\n await cmdInstancesRequest(positional[0], cfg);\n } else if (sub === \"join\") {\n const { positional } = parseFlags(rest, {});\n if (!positional[0]) { console.error(\"Usage: autonag instances join <code>\"); process.exit(1); }\n await cmdInstancesJoin(positional[0], cfg);\n } else if (sub === \"invite\") {\n parseFlags(rest, {});\n requireToken(cfg);\n requireInstance(cfg);\n const api = createApiClient(cfg.server, cfg.token);\n const { invite } = await api.createInvite(cfg.instanceId, cfg.token);\n console.log(`Invite code: ${invite.code}`);\n console.log(`Expires: ${fmtDate(invite.expiresAt)}`);\n console.log(`Share this code — it can only be used once.`);\n } else if (sub === \"select\") {\n const { positional } = parseFlags(rest, {});\n if (!positional[0]) { console.error(\"Usage: autonag instances select <id>\"); process.exit(1); }\n await cmdInstancesSelect(positional[0], cfg);\n } else {\n console.error(`Unknown subcommand: instances ${sub}`); process.exit(1);\n }\n\n } else if (cmd === \"timers\") {\n if (!sub || sub === \"list\") {\n parseFlags(rest, {});\n await cmdTimersList(cfg);\n } else if (sub === \"add\") {\n const { positional, flags } = parseFlags(rest, {\n desc: \"string\", days: \"int\", anchor: \"string\", tz: \"string\", \"skip-weekends\": \"boolean\",\n });\n if (!positional[0] || !positional[1]) { console.error(\"Usage: autonag timers add <name> <expiry> [--desc <text>] [--days <n>] [--anchor <HH:MM>] [--tz <tz>] [--skip-weekends]\"); process.exit(1); }\n await cmdTimersAdd(positional[0], positional[1], cfg, {\n desc: flags.desc as string | undefined,\n days: flags.days as number | undefined,\n anchor: flags.anchor as string | undefined,\n tz: flags.tz as string | undefined,\n skipWeekends: flags[\"skip-weekends\"] === true,\n });\n } else if (sub === \"rename\") {\n const { positional } = parseFlags(rest, {});\n if (!positional[0] || !positional[1]) { console.error(\"Usage: autonag timers rename <id> <name>\"); process.exit(1); }\n await cmdTimersRename(positional[0], positional[1], cfg);\n } else if (sub === \"snooze\") {\n const { positional } = parseFlags(rest, {});\n if (!positional[0] || !positional[1]) { console.error(\"Usage: autonag timers snooze <id> <expiry>\"); process.exit(1); }\n await cmdTimersSnooze(positional[0], positional[1], cfg);\n } else if (sub === \"complete\") {\n const { positional } = parseFlags(rest, {});\n if (!positional[0] || !positional[1]) { console.error(\"Usage: autonag timers complete <id> <reason>\"); process.exit(1); }\n await cmdTimersComplete(positional[0], positional[1], cfg);\n } else if (sub === \"remove\") {\n const { positional } = parseFlags(rest, {});\n if (!positional[0]) { console.error(\"Usage: autonag timers remove <id>\"); process.exit(1); }\n await cmdTimersRemove(positional[0], cfg);\n } else if (sub === \"describe\") {\n const { positional } = parseFlags(rest, {});\n if (!positional[0] || !positional[1]) { console.error(\"Usage: autonag timers describe <id> <text>\"); process.exit(1); }\n await cmdTimersDescribe(positional[0], positional[1], cfg);\n } else if (sub === \"recurrence\") {\n const recSub = rest[0];\n if (recSub === \"set\") {\n const { positional, flags } = parseFlags(rest, { anchor: \"string\", tz: \"string\", \"skip-weekends\": \"boolean\" });\n // positional = [\"set\", id, days]\n if (!positional[1] || !positional[2]) { console.error(\"Usage: autonag timers recurrence set <id> <days> [--anchor <HH:MM>] [--tz <tz>] [--skip-weekends]\"); process.exit(1); }\n const days = Number(positional[2]);\n if (!Number.isInteger(days) || days <= 0) { console.error(`<days> must be a positive integer, got: \"${positional[2]}\"`); process.exit(1); }\n await cmdTimersRecurrenceSet(positional[1], days, cfg, {\n anchor: flags.anchor as string | undefined,\n tz: flags.tz as string | undefined,\n skipWeekends: flags[\"skip-weekends\"] === true,\n });\n } else if (recSub === \"remove\") {\n const { positional } = parseFlags(rest, {});\n // positional = [\"remove\", id]\n if (!positional[1]) { console.error(\"Usage: autonag timers recurrence remove <id>\"); process.exit(1); }\n await cmdTimersRecurrenceRemove(positional[1], cfg);\n } else {\n console.error(\"Usage: autonag timers recurrence set|remove ...\"); process.exit(1);\n }\n } else if (sub === \"history\") {\n const { positional } = parseFlags(rest, {});\n if (!positional[0]) { console.error(\"Usage: autonag timers history <id>\"); process.exit(1); }\n await cmdTimersHistory(positional[0], cfg);\n } else {\n console.error(`Unknown subcommand: timers ${sub}`); process.exit(1);\n }\n\n } else if (cmd === \"alarm\") {\n if (sub !== \"show\") { console.error(\"Usage: autonag alarm show\"); process.exit(1); }\n parseFlags(rest, {});\n await cmdAlarm(cfg);\n\n } else if (cmd === \"shush\") {\n parseFlags(rest, {});\n await cmdShush(sub, cfg);\n } else if (cmd === \"unshush\") {\n parseFlags(rest, {});\n await cmdUnshush(cfg);\n\n } else if (cmd === \"events\") {\n if (!sub || sub === \"list\") {\n const { flags } = parseFlags(rest, { from: \"int\" });\n await cmdEventsList((flags.from as number | undefined) ?? 1, cfg);\n } else if (sub === \"skip\") {\n const { positional } = parseFlags(rest, {});\n if (!positional[0]) { console.error(\"Usage: autonag events skip <id>\"); process.exit(1); }\n await cmdEventsSkip(positional[0], cfg);\n } else if (sub === \"unskip\") {\n const { positional } = parseFlags(rest, {});\n if (!positional[0]) { console.error(\"Usage: autonag events unskip <id>\"); process.exit(1); }\n await cmdEventsUnskip(positional[0], cfg);\n } else {\n console.error(`Unknown subcommand: events ${sub}`); process.exit(1);\n }\n\n } else if (cmd === \"comments\") {\n if (!sub || sub === \"list\") {\n const { positional } = parseFlags(rest, {});\n if (!positional[0]) { console.error(\"Usage: autonag comments list <timerId>\"); process.exit(1); }\n await cmdCommentsList(positional[0], cfg);\n } else if (sub === \"add\") {\n const { positional } = parseFlags(rest, {});\n if (!positional[0] || !positional[1]) { console.error(\"Usage: autonag comments add <timerId> <text>\"); process.exit(1); }\n await cmdCommentsAdd(positional[0], positional[1], cfg);\n } else {\n console.error(`Unknown subcommand: comments ${sub}`); process.exit(1);\n }\n\n } else {\n console.error(`Unknown command: ${cmd}`);\n console.error(`Run \"autonag --help\" for usage.`);\n process.exit(1);\n }\n} catch (e) {\n if (e instanceof ApiError) {\n console.error(`Error: ${e.message}`);\n process.exit(1);\n }\n throw e;\n}\n","import type { RecurrenceSpec, StoredEvent, Comment, InstanceState } from \"./types\";\n\nexport class ApiError extends Error {\n constructor(public status: number, message: string) {\n super(message);\n this.name = \"ApiError\";\n }\n}\n\nexport type BatchActionItem =\n | { type: \"addTimer\"; name: string; description?: string; expiry: number; recurrence?: RecurrenceSpec }\n | { type: \"updateExpiry\"; timerId: string; expiry: number }\n | { type: \"completeTimer\"; timerId: string; closeReason: string }\n | { type: \"removeTimer\"; timerId: string }\n | { type: \"shush\"; expiry: number }\n | { type: \"clearShush\" }\n | { type: \"recurTimer\"; timerId: string; closeReason: string }\n | { type: \"updateRecurrence\"; timerId: string; recurrence: RecurrenceSpec }\n | { type: \"removeRecurrence\"; timerId: string }\n | { type: \"updateDescription\"; timerId: string; description: string }\n | { type: \"assert\"; path: string; expectStatus?: number; expect?: unknown };\n\nexport function createApiClient(baseUrl: string, defaultToken?: string) {\n async function apiFetch<T>(\n path: string,\n options: RequestInit = {},\n token?: string,\n ): Promise<T> {\n const tok = token ?? defaultToken;\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n ...(options.headers as Record<string, string>),\n };\n if (tok) headers[\"Authorization\"] = `Bearer ${tok}`;\n\n const res = await fetch(`${baseUrl}${path}`, { ...options, headers });\n if (!res.ok) {\n let message = `HTTP ${res.status}`;\n try {\n const body = await res.json() as { error?: string };\n if (body.error) message = body.error;\n } catch { /* ignore */ }\n throw new ApiError(res.status, message);\n }\n return res.json() as Promise<T>;\n }\n\n return {\n registerDevice: (nickname: string) =>\n apiFetch<{ device: { id: string; nickname: string }; token: string }>(\n \"/devices/request\", { method: \"POST\", body: JSON.stringify({ nickname }) }\n ),\n\n getMe: (token: string) =>\n apiFetch<{ device: { id: string; nickname: string; approvedAt: number | null } }>(\n \"/devices/me\", {}, token\n ),\n\n requestInstance: (nickname: string, token: string) =>\n apiFetch<{ instance: { id: string; nickname: string } }>(\n \"/instances/request\", { method: \"POST\", body: JSON.stringify({ nickname }) }, token\n ),\n\n requestInstanceAccess: (instanceId: string, token: string, inviteCode?: string) =>\n apiFetch<{ request?: { id: string; status: string }; status?: string }>(\n `/instances/${instanceId}/access/request`,\n { method: \"POST\", body: JSON.stringify(inviteCode ? { inviteCode } : {}) },\n token\n ),\n\n getInvite: (code: string) =>\n apiFetch<{ invite: { code: string; instanceId: string; instanceNickname: string; expiresAt: number; valid: boolean; reason?: string } }>(\n `/invites/${code}`\n ),\n\n createInvite: (instanceId: string, token: string) =>\n apiFetch<{ invite: { code: string; expiresAt: number } }>(\n `/instances/${instanceId}/invites`, { method: \"POST\", body: JSON.stringify({}) }, token\n ),\n\n listInstances: (token: string) =>\n apiFetch<{ instances: { id: string; nickname: string; approvedAt: number | null }[] }>(\n \"/instances\", {}, token\n ),\n\n addTimer: (instanceId: string, token: string, name: string, expiry: number, recurrence?: RecurrenceSpec, description?: string) =>\n apiFetch<{ timer: { id: string }; event: { id: string; seq: number } }>(\n `/instances/${instanceId}/timers`,\n { method: \"POST\", body: JSON.stringify({ name, expiry, ...(description ? { description } : {}), ...(recurrence ? { recurrence } : {}) }) },\n token\n ),\n\n renameTimer: (instanceId: string, token: string, timerId: string, name: string) =>\n apiFetch<{ event: { id: string; seq: number } }>(\n `/instances/${instanceId}/timers/${timerId}/name`,\n { method: \"PATCH\", body: JSON.stringify({ name }) },\n token\n ),\n\n updateExpiry: (instanceId: string, token: string, timerId: string, expiry: number) =>\n apiFetch<{ event: { id: string; seq: number } }>(\n `/instances/${instanceId}/timers/${timerId}/expiry`,\n { method: \"PATCH\", body: JSON.stringify({ expiry }) },\n token\n ),\n\n completeTimer: (instanceId: string, token: string, timerId: string, closeReason: string) =>\n apiFetch<{ event: { id: string; seq: number } }>(\n `/instances/${instanceId}/timers/${timerId}/complete`,\n { method: \"POST\", body: JSON.stringify({ closeReason }) },\n token\n ),\n\n removeTimer: (instanceId: string, token: string, timerId: string) =>\n apiFetch<{ event: { id: string; seq: number } }>(\n `/instances/${instanceId}/timers/${timerId}`,\n { method: \"DELETE\" },\n token\n ),\n\n setShush: (instanceId: string, token: string, expiry: number) =>\n apiFetch<{ event: { id: string; seq: number } }>(\n `/instances/${instanceId}/shush`,\n { method: \"POST\", body: JSON.stringify({ expiry }) },\n token\n ),\n\n clearShush: (instanceId: string, token: string) =>\n apiFetch<{ event: { id: string; seq: number } }>(\n `/instances/${instanceId}/shush`,\n { method: \"DELETE\" },\n token\n ),\n\n listEvents: (instanceId: string, token: string, opts: { from?: number; before?: number; limit?: number } = {}) => {\n const { from = 1, before, limit = 200 } = opts;\n const params = before !== undefined\n ? `before=${before}&limit=${limit}`\n : `from=${from}&limit=${limit}`;\n return apiFetch<{ events: StoredEvent[]; latestSeq: number; prevCursor?: number | null }>(\n `/instances/${instanceId}/events?${params}`, {}, token\n );\n },\n\n getTimerHistory: (instanceId: string, token: string, timerId: string, opts: {\n after?: number; limit?: number; from?: number; to?: number;\n } = {}) => {\n const params = new URLSearchParams();\n if (opts.after !== undefined) params.set(\"after\", String(opts.after));\n if (opts.limit !== undefined) params.set(\"limit\", String(opts.limit));\n if (opts.from !== undefined) params.set(\"from\", String(opts.from));\n if (opts.to !== undefined) params.set(\"to\", String(opts.to));\n const qs = params.toString();\n return apiFetch<{ events: StoredEvent[]; nextCursor: number | null }>(\n `/instances/${instanceId}/timers/${timerId}/history${qs ? `?${qs}` : \"\"}`, {}, token\n );\n },\n\n skipEvent: (instanceId: string, token: string, eventId: string) =>\n apiFetch<{ ok: boolean }>(\n `/instances/${instanceId}/events/${eventId}/skip`, { method: \"POST\" }, token\n ),\n\n unskipEvent: (instanceId: string, token: string, eventId: string) =>\n apiFetch<{ ok: boolean }>(\n `/instances/${instanceId}/events/${eventId}/skip`, { method: \"DELETE\" }, token\n ),\n\n listComments: (instanceId: string, token: string, threadId: string) =>\n apiFetch<{ comments: Comment[] }>(\n `/instances/${instanceId}/threads/${threadId}/comments`, {}, token\n ),\n\n addComment: (instanceId: string, token: string, threadId: string, text: string) =>\n apiFetch<{ comment: Comment }>(\n `/instances/${instanceId}/threads/${threadId}/comments`,\n { method: \"POST\", body: JSON.stringify({ text }) },\n token\n ),\n\n getState: (instanceId: string, token: string) =>\n apiFetch<InstanceState>(\n `/instances/${instanceId}/state`, {}, token\n ),\n\n batchActions: (instanceId: string, token: string, actions: BatchActionItem[]) =>\n apiFetch<{ events: { id: string; seq: number; type: string }[] }>(\n `/instances/${instanceId}/actions`,\n { method: \"POST\", body: JSON.stringify({ actions }) },\n token\n ),\n };\n}\n"],"mappings":"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","names":["cfg"]}
|
|
1
|
+
{"version":3,"sources":["../cli.ts","../apiClient.ts"],"sourcesContent":["import { join } from \"path\";\nimport { homedir } from \"os\";\nimport { mkdirSync, existsSync, readFileSync, writeFileSync } from \"fs\";\nimport JSON5 from \"json5\";\nimport { createApiClient, ApiError } from \"./apiClient\";\n\n// ---- Config ----\n\ntype Config = {\n server: string;\n token?: string;\n deviceId?: string;\n instanceId?: string;\n};\n\nlet CONFIG_PATH = join(homedir(), \".config\", \"autonag\", \"client.json5\");\n\nfunction loadConfig(): Config {\n if (!existsSync(CONFIG_PATH)) return { server: \"http://localhost:3000\" };\n let raw: string;\n try {\n raw = readFileSync(CONFIG_PATH, \"utf8\");\n } catch (e) {\n console.error(`Cannot read config file ${CONFIG_PATH}: ${e}`);\n process.exit(1);\n }\n try {\n return JSON5.parse(raw) as Config;\n } catch (e) {\n console.error(`Config file ${CONFIG_PATH} is not valid JSON5: ${e}`);\n process.exit(1);\n }\n}\n\nfunction saveConfig(config: Config): void {\n mkdirSync(join(CONFIG_PATH, \"..\"), { recursive: true });\n writeFileSync(CONFIG_PATH, JSON5.stringify(config, null, 2));\n}\n\n// ---- Expiry parsing ----\n\nfunction parseExpiry(input: string): number {\n // Explicit unix milliseconds: unix-ms:<n>\n if (input.startsWith(\"unix-ms:\")) {\n const n = Number(input.slice(8));\n if (!Number.isInteger(n) || n <= 0) {\n console.error(`Invalid expiry \"${input}\". Use unix-ms:<positive-integer>`);\n process.exit(1);\n }\n return n;\n }\n // ISO 8601 with required timezone: 2026-05-01T09:00:00Z or 2026-05-01T09:00:00+05:30\n if (/^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(Z|[+-]\\d{2}:\\d{2})$/.test(input)) {\n const ms = Date.parse(input);\n if (isNaN(ms)) {\n console.error(`Invalid datetime \"${input}\"`);\n process.exit(1);\n }\n return ms;\n }\n // Duration: 1d, 30m, 2h, 90s, or combinations like 1d12h\n const match = input.match(/^(?:(\\d+)d)?(?:(\\d+)h)?(?:(\\d+)m)?(?:(\\d+)s)?$/);\n if (match && (match[1] || match[2] || match[3] || match[4])) {\n const d = parseInt(match[1] ?? \"0\");\n const h = parseInt(match[2] ?? \"0\");\n const m = parseInt(match[3] ?? \"0\");\n const s = parseInt(match[4] ?? \"0\");\n return Date.now() + (d * 86400 + h * 3600 + m * 60 + s) * 1000;\n }\n console.error(`Cannot parse expiry \"${input}\". Use: 1d, 30m, 2h, 90s (relative duration), 2026-05-01T09:00:00Z (ISO 8601 with timezone), or unix-ms:<n>`);\n process.exit(1);\n}\n\n// ---- Formatting ----\n\nfunction fmtCountdown(ms: number): string {\n const sign = ms < 0 ? \"-\" : \"\";\n const abs = Math.abs(ms);\n const totalSec = Math.floor(abs / 1000);\n const d = Math.floor(totalSec / 86400);\n const h = Math.floor((totalSec % 86400) / 3600);\n const m = Math.floor((totalSec % 3600) / 60);\n const s = totalSec % 60;\n if (d > 0) return `${sign}${d}d ${h}h`;\n if (h > 0) return `${sign}${h}h ${m}m`;\n if (m > 0) return `${sign}${m}m ${s}s`;\n return `${sign}${s}s`;\n}\n\nfunction fmtDate(ms: number): string {\n return new Date(ms).toLocaleString();\n}\n\nfunction shortId(id: string): string {\n return id.slice(0, 8);\n}\n\nfunction col(s: string, w: number, ellipsis = false): string {\n if (ellipsis && s.length > w) return s.slice(0, w - 1) + \"…\";\n return s.slice(0, w).padEnd(w);\n}\n\n// ---- ID resolution ----\n\nasync function resolveTimerId(prefix: string, cfg: Config & { token: string; instanceId: string }): Promise<string> {\n if (/^[0-9a-f-]{36}$/.test(prefix)) return prefix;\n const api = createApiClient(cfg.server, cfg.token);\n const state = await api.getState(cfg.instanceId, cfg.token);\n const matches = state.timers.filter(t => t.id.startsWith(prefix));\n if (matches.length === 0) { console.error(`Timer not found: ${prefix}`); process.exit(1); }\n if (matches.length > 1) {\n console.error(`Ambiguous prefix \"${prefix}\" matches: ${matches.map(t => shortId(t.id) + \"…\").join(\", \")}`);\n process.exit(1);\n }\n return matches[0]!.id;\n}\n\nasync function resolveEventId(prefix: string, cfg: Config & { token: string; instanceId: string }): Promise<string> {\n if (/^[0-9a-f-]{36}$/.test(prefix)) return prefix;\n const api = createApiClient(cfg.server, cfg.token);\n // Fetch all events (paginated default covers most cases)\n const allIds: string[] = [];\n let from = 1;\n while (true) {\n const { events, latestSeq } = await api.listEvents(cfg.instanceId, cfg.token, { from, limit: 200 });\n allIds.push(...events.map(e => e.id));\n if (events.length < 200 || events[events.length - 1]!.seq >= latestSeq) break;\n from = events[events.length - 1]!.seq + 1;\n }\n const matches = allIds.filter(id => id.startsWith(prefix));\n if (matches.length === 0) { console.error(`Event not found: ${prefix}`); process.exit(1); }\n if (matches.length > 1) {\n console.error(`Ambiguous prefix \"${prefix}\" matches: ${matches.map(id => shortId(id) + \"…\").join(\", \")}`);\n process.exit(1);\n }\n return matches[0]!;\n}\n\nasync function resolveInstanceId(prefix: string, cfg: Config & { token: string }): Promise<string> {\n if (/^[0-9a-f-]{36}$/.test(prefix)) return prefix;\n const api = createApiClient(cfg.server, cfg.token);\n const { instances } = await api.listInstances(cfg.token);\n const matches = instances.filter(i => i.id.startsWith(prefix));\n if (matches.length === 0) { console.error(`Instance not found: ${prefix}`); process.exit(1); }\n if (matches.length > 1) {\n console.error(`Ambiguous prefix \"${prefix}\" matches: ${matches.map(i => `\"${i.nickname}\" (${shortId(i.id)}…)`).join(\", \")}`);\n process.exit(1);\n }\n return matches[0]!.id;\n}\n\n// ---- Guards ----\n\nfunction requireToken(cfg: Config): asserts cfg is Config & { token: string } {\n if (!cfg.token) {\n console.error(\"Not registered. Run: autonag register <nickname>\");\n process.exit(1);\n }\n}\n\nfunction requireInstance(cfg: Config): asserts cfg is Config & { instanceId: string } {\n if (!cfg.instanceId) {\n console.error(\"No instance selected. Run: autonag instances select <id>\");\n process.exit(1);\n }\n}\n\n// ---- Commands ----\n\nasync function cmdRegister(nickname: string, cfg: Config): Promise<void> {\n const api = createApiClient(cfg.server);\n const { device, token } = await api.registerDevice(nickname);\n cfg.token = token;\n cfg.deviceId = device.id;\n saveConfig(cfg);\n console.log(`Registered as \"${nickname}\" (${shortId(device.id)}…)`);\n console.log(`Token saved to ${CONFIG_PATH}`);\n console.log(`Waiting for admin approval — run \"autonag status\" to check.`);\n}\n\nasync function cmdStatus(cfg: Config): Promise<void> {\n console.log(`Server: ${cfg.server}`);\n console.log(`Config: ${CONFIG_PATH}`);\n if (!cfg.token) {\n console.log(`Auth: not registered (run: autonag register <nickname>)`);\n return;\n }\n const api = createApiClient(cfg.server, cfg.token);\n try {\n const { device: d } = await api.getMe(cfg.token);\n const status = d.approvedAt ? `approved ${fmtDate(d.approvedAt)}` : \"PENDING APPROVAL\";\n console.log(`Auth: ${d.nickname} (${shortId(d.id)}…) [${status}]`);\n } catch (e) {\n if (e instanceof ApiError && e.status === 401) {\n console.log(`Auth: token invalid or expired`);\n } else throw e;\n }\n console.log(`Instance: ${cfg.instanceId ?? \"none selected (run: autonag instances select <id>)\"}`);\n}\n\nasync function cmdInstancesList(cfg: Config): Promise<void> {\n requireToken(cfg);\n const api = createApiClient(cfg.server, cfg.token);\n const { instances } = await api.listInstances(cfg.token);\n if (instances.length === 0) { console.log(\"No accessible instances.\"); return; }\n for (const i of instances) {\n const status = i.approvedAt ? \"active\" : \"PENDING\";\n const marker = i.id === cfg.instanceId ? \" *\" : \" \";\n console.log(`${marker} ${shortId(i.id)}… \"${i.nickname}\" [${status}]`);\n }\n console.log(`\\n* = current default`);\n}\n\nasync function cmdInstancesRequest(nickname: string, cfg: Config): Promise<void> {\n requireToken(cfg);\n const api = createApiClient(cfg.server, cfg.token);\n const { instance } = await api.requestInstance(nickname, cfg.token);\n console.log(`Requested instance \"${instance.nickname}\" (${shortId(instance.id)}…)`);\n console.log(`Waiting for admin approval.`);\n}\n\nasync function cmdInstancesSelect(id: string, cfg: Config): Promise<void> {\n requireToken(cfg);\n const instanceId = await resolveInstanceId(id, cfg);\n cfg.instanceId = instanceId;\n saveConfig(cfg);\n console.log(`Default instance set to ${instanceId}`);\n}\n\nasync function cmdInstancesJoin(instanceId: string, cfg: Config): Promise<void> {\n requireToken(cfg);\n const api = createApiClient(cfg.server, cfg.token);\n await api.requestInstanceAccess(instanceId, cfg.token);\n console.log(`Access requested for instance ${shortId(instanceId)}…`);\n console.log(`An admin will need to approve your request.`);\n console.log(`Once approved, run: autonag instances select ${instanceId}`);\n}\n\nasync function cmdTimersList(cfg: Config): Promise<void> {\n requireToken(cfg);\n requireInstance(cfg);\n const api = createApiClient(cfg.server, cfg.token);\n const state = await api.getState(cfg.instanceId, cfg.token);\n\n const now = Date.now();\n const timers = [...state.timers].sort((a, b) => a.currentExpiry - b.currentExpiry);\n\n if (timers.length === 0) {\n console.log(\"No active timers.\");\n } else {\n console.log(`${\"ID\".padEnd(10)} ${\"Name\".padEnd(24)} ${\"Remaining\".padEnd(16)} Recur`);\n console.log(\"-\".repeat(60));\n for (const t of timers) {\n const remaining = t.currentExpiry - now;\n const label = remaining < 0\n ? `OVERDUE ${fmtCountdown(remaining)}`\n : `in ${fmtCountdown(remaining)}`;\n const recur = t.recurrence ? \"↻\" : \"\";\n console.log(`${col(shortId(t.id) + \"…\", 10)} ${col(t.name, 24, true)} ${col(label, 16)} ${recur}`);\n }\n }\n\n console.log();\n printAlarmStatus(state, now);\n}\n\nfunction printAlarmStatus(state: { alarm: { on: boolean; startsAt: number | null; urgentName: string | null; color: string }; shush: { expiry: number } | null }, now: number): void {\n const { alarm, shush } = state;\n const shushed = !!(shush && shush.expiry > now);\n const colorLabel: Record<string, string> = {\n blue: \"off\", green: \"green\", yellow: \"yellow\", red: \"red\", flashing: \"FLASHING\",\n };\n\n // Line 1: color + most urgent timer\n if (alarm.startsAt !== null) {\n const diff = alarm.startsAt - now;\n const colorStr = colorLabel[alarm.color] ?? alarm.color;\n const timeStr = diff <= 0 ? `overdue ${fmtCountdown(diff)}` : `in ${fmtCountdown(diff)}`;\n console.log(`[${colorStr}] \"${alarm.urgentName}\" — ${timeStr}`);\n }\n\n // Line 2: alarm state\n if (alarm.on) {\n console.log(`Alarm: ringing.`);\n } else if (shushed) {\n const overdue = alarm.startsAt !== null && alarm.startsAt <= now;\n // \"necessary\" = shush is actually blocking a ring (timer overdue now, or timer fires before shush ends)\n const shushEndsAfterTimer = alarm.startsAt !== null && shush!.expiry >= alarm.startsAt;\n const necessary = overdue || shushEndsAfterTimer;\n if (necessary) {\n const ringIn = fmtCountdown(shush!.expiry - now);\n console.log(`Alarm: off. Will ring in ${ringIn}: Shush expires: ${alarm.urgentName}.`);\n } else if (alarm.startsAt !== null) {\n // Shush ends before timer fires — timer still drives the ring time\n const ringIn = fmtCountdown(alarm.startsAt - now);\n const remaining = fmtCountdown(shush!.expiry - now);\n console.log(`Alarm: off. Will ring in ${ringIn}: ${alarm.urgentName}. (Shushed unnecessarily for ${remaining}.)`);\n } else {\n const remaining = fmtCountdown(shush!.expiry - now);\n console.log(`Alarm: off. Shushed (unnecessarily) for ${remaining}.`);\n }\n } else if (alarm.startsAt !== null) {\n const ringIn = fmtCountdown(alarm.startsAt - now);\n console.log(`Alarm: off. Will ring in ${ringIn}: ${alarm.urgentName}.`);\n } else {\n console.log(`Alarm: off.`);\n }\n}\n\nasync function cmdAlarm(cfg: Config): Promise<void> {\n requireToken(cfg);\n requireInstance(cfg);\n const api = createApiClient(cfg.server, cfg.token);\n const state = await api.getState(cfg.instanceId, cfg.token);\n printAlarmStatus(state, Date.now());\n}\n\nasync function cmdTimersAdd(\n name: string, expiryStr: string, cfg: Config,\n opts: { desc?: string; days?: number; anchor?: string; tz?: string; skipWeekends?: boolean }\n): Promise<void> {\n requireToken(cfg);\n requireInstance(cfg);\n const api = createApiClient(cfg.server, cfg.token);\n const expiry = parseExpiry(expiryStr);\n const recurrence = opts.days !== undefined ? {\n periodDays: opts.days,\n anchorTime: opts.anchor ?? \"09:00\",\n timezone: opts.tz ?? Intl.DateTimeFormat().resolvedOptions().timeZone,\n skipWeekends: opts.skipWeekends ?? false,\n } : undefined;\n await api.addTimer(cfg.instanceId, cfg.token, name, expiry, recurrence, opts.desc);\n const recurNote = recurrence ? ` (recurs every ${opts.days}d)` : \"\";\n console.log(`Timer \"${name}\" added, expires ${fmtDate(expiry)}${recurNote}`);\n}\n\nasync function cmdTimersRename(id: string, name: string, cfg: Config): Promise<void> {\n requireToken(cfg);\n requireInstance(cfg);\n const timerId = await resolveTimerId(id, cfg);\n const api = createApiClient(cfg.server, cfg.token);\n await api.renameTimer(cfg.instanceId, cfg.token, timerId, name);\n console.log(`Timer ${shortId(timerId)}… renamed to \"${name}\"`);\n}\n\nasync function cmdTimersSnooze(id: string, expiryStr: string, cfg: Config): Promise<void> {\n requireToken(cfg);\n requireInstance(cfg);\n const timerId = await resolveTimerId(id, cfg);\n const api = createApiClient(cfg.server, cfg.token);\n const expiry = parseExpiry(expiryStr);\n await api.updateExpiry(cfg.instanceId, cfg.token, timerId, expiry);\n console.log(`Timer ${shortId(timerId)}… snoozed until ${fmtDate(expiry)}`);\n}\n\nasync function cmdTimersComplete(id: string, reason: string, cfg: Config, opts: { at?: number } = {}): Promise<void> {\n requireToken(cfg);\n requireInstance(cfg);\n const api = createApiClient(cfg.server, cfg.token);\n const state = await api.getState(cfg.instanceId, cfg.token);\n const timerId = await resolveTimerId(id, cfg);\n const timer = state.timers.find(t => t.id === timerId);\n\n if (timer?.recurrence) {\n await api.batchActions(cfg.instanceId, cfg.token, [{ type: \"recurTimer\", timerId, closeReason: reason, ...(opts.at != null ? { occurredAt: opts.at } : {}) }]);\n const newState = await api.getState(cfg.instanceId, cfg.token);\n const updated = newState.timers.find(t => t.id === timerId);\n if (updated) {\n console.log(`Timer \"${timer.name}\" recurred — next: ${fmtDate(updated.currentExpiry)}`);\n } else {\n console.log(`Timer ${shortId(timerId)}… recurred`);\n }\n } else {\n await api.batchActions(cfg.instanceId, cfg.token, [{ type: \"completeTimer\", timerId, closeReason: reason, ...(opts.at != null ? { occurredAt: opts.at } : {}) }]);\n const name = timer?.name ?? shortId(timerId);\n console.log(`Timer \"${name}\" completed (${reason})`);\n }\n}\n\nasync function cmdTimersRemove(id: string, cfg: Config): Promise<void> {\n requireToken(cfg);\n requireInstance(cfg);\n const api = createApiClient(cfg.server, cfg.token);\n const state = await api.getState(cfg.instanceId, cfg.token);\n const timerId = await resolveTimerId(id, cfg);\n const timer = state.timers.find(t => t.id === timerId);\n await api.removeTimer(cfg.instanceId, cfg.token, timerId);\n const name = timer?.name ?? shortId(timerId);\n console.log(`Timer \"${name}\" removed`);\n}\n\nasync function cmdTimersDescribe(id: string, text: string, cfg: Config): Promise<void> {\n requireToken(cfg);\n requireInstance(cfg);\n const timerId = await resolveTimerId(id, cfg);\n const api = createApiClient(cfg.server, cfg.token);\n await api.batchActions(cfg.instanceId, cfg.token, [{ type: \"updateDescription\", timerId, description: text }]);\n console.log(`Timer ${shortId(timerId)}… description updated`);\n}\n\nasync function cmdTimersGetDescription(id: string, cfg: Config): Promise<void> {\n requireToken(cfg);\n requireInstance(cfg);\n const timerId = await resolveTimerId(id, cfg);\n const api = createApiClient(cfg.server, cfg.token);\n const state = await api.getState(cfg.instanceId, cfg.token);\n const timer = state.timers.find(t => t.id === timerId);\n if (!timer) { console.error(`Timer not found: ${timerId}`); process.exit(1); }\n if (!timer.description) { console.log(\"(no description)\"); return; }\n console.log(timer.description);\n}\n\nasync function cmdTimersRecurrenceSet(\n id: string, days: number, cfg: Config,\n opts: { anchor?: string; tz?: string; skipWeekends?: boolean }\n): Promise<void> {\n requireToken(cfg);\n requireInstance(cfg);\n const timerId = await resolveTimerId(id, cfg);\n const api = createApiClient(cfg.server, cfg.token);\n const recurrence = {\n periodDays: days,\n anchorTime: opts.anchor ?? \"09:00\",\n timezone: opts.tz ?? Intl.DateTimeFormat().resolvedOptions().timeZone,\n skipWeekends: opts.skipWeekends ?? false,\n };\n await api.batchActions(cfg.instanceId, cfg.token, [{ type: \"updateRecurrence\", timerId, recurrence }]);\n console.log(`Timer ${shortId(timerId)}… recurrence set to every ${days}d at ${recurrence.anchorTime} (${recurrence.timezone})`);\n}\n\nasync function cmdTimersRecurrenceRemove(id: string, cfg: Config): Promise<void> {\n requireToken(cfg);\n requireInstance(cfg);\n const timerId = await resolveTimerId(id, cfg);\n const api = createApiClient(cfg.server, cfg.token);\n await api.batchActions(cfg.instanceId, cfg.token, [{ type: \"removeRecurrence\", timerId }]);\n console.log(`Timer ${shortId(timerId)}… recurrence removed`);\n}\n\nasync function cmdTimersHistory(id: string, cfg: Config): Promise<void> {\n requireToken(cfg);\n requireInstance(cfg);\n const timerId = await resolveTimerId(id, cfg);\n const api = createApiClient(cfg.server, cfg.token);\n const allEntries: Array<{ date: number; closeReason: string; type: string }> = [];\n let cursor: number | null = 0;\n while (cursor !== null) {\n const { events, nextCursor } = await api.getTimerHistory(cfg.instanceId, cfg.token, timerId, { after: cursor });\n for (const ev of events) {\n const p = ev.payload as Record<string, unknown>;\n const date = (ev.type === \"TimerRecurred\" || ev.type === \"TimerCompletionLogged\")\n ? (p[\"occurredAt\"] as number) ?? ev.timestamp\n : ev.timestamp;\n allEntries.push({ date, closeReason: p[\"closeReason\"] as string, type: ev.type });\n }\n cursor = nextCursor;\n }\n if (allEntries.length === 0) { console.log(\"No history yet.\"); return; }\n console.log(`${\"Date\".padEnd(22)} ${\"Reason\".padEnd(16)} Type`);\n console.log(\"-\".repeat(56));\n for (const e of allEntries) {\n const typeLabel = e.type === \"TimerCompletionLogged\" ? \"logged\" : e.type === \"TimerRecurred\" ? \"recurred\" : \"completed\";\n console.log(`${col(fmtDate(e.date), 22)} ${col(e.closeReason, 16)} ${typeLabel}`);\n }\n}\n\nasync function cmdTimersLog(id: string, reason: string, at: number, cfg: Config): Promise<void> {\n requireToken(cfg);\n requireInstance(cfg);\n const api = createApiClient(cfg.server, cfg.token);\n const state = await api.getState(cfg.instanceId, cfg.token);\n const timerId = await resolveTimerId(id, cfg);\n const timer = state.timers.find(t => t.id === timerId);\n if (!timer) { console.error(`Timer not found: ${id}`); process.exit(1); }\n await api.batchActions(cfg.instanceId, cfg.token, [{ type: \"logCompletion\", timerId, closeReason: reason, occurredAt: at }]);\n console.log(`Logged \"${reason}\" for \"${timer.name}\" at ${fmtDate(at)}`);\n}\n\nasync function cmdShush(durationStr: string | undefined, cfg: Config): Promise<void> {\n requireToken(cfg);\n requireInstance(cfg);\n const api = createApiClient(cfg.server, cfg.token);\n const expiry = durationStr ? parseExpiry(durationStr) : Date.now() + 30 * 60 * 1000;\n await api.setShush(cfg.instanceId, cfg.token, expiry);\n console.log(`Alarm silenced until ${fmtDate(expiry)}`);\n}\n\nasync function cmdUnshush(cfg: Config): Promise<void> {\n requireToken(cfg);\n requireInstance(cfg);\n const api = createApiClient(cfg.server, cfg.token);\n await api.clearShush(cfg.instanceId, cfg.token);\n console.log(`Shush cleared`);\n}\n\nasync function cmdEventsList(fromSeq: number, cfg: Config): Promise<void> {\n requireToken(cfg);\n requireInstance(cfg);\n const api = createApiClient(cfg.server, cfg.token);\n const { events } = await api.listEvents(cfg.instanceId, cfg.token, { from: fromSeq });\n if (events.length === 0) { console.log(\"No events.\"); return; }\n console.log(`${\"seq\".padEnd(6)} ${\"ID\".padEnd(10)} ${\"Type\".padEnd(28)} ${\"Time\".padEnd(20)} Skipped`);\n console.log(\"-\".repeat(78));\n for (const e of events) {\n const skipped = e.skipped ? \"yes\" : \"\";\n console.log(`${String(e.seq).padEnd(6)} ${col(shortId(e.id) + \"…\", 10)} ${col(e.type, 28)} ${col(fmtDate(e.timestamp), 20)} ${skipped}`);\n }\n}\n\nasync function cmdEventsSkip(id: string, cfg: Config): Promise<void> {\n requireToken(cfg);\n requireInstance(cfg);\n const eventId = await resolveEventId(id, cfg);\n const api = createApiClient(cfg.server, cfg.token);\n await api.skipEvent(cfg.instanceId, cfg.token, eventId);\n console.log(`Event ${shortId(eventId)}… skipped`);\n}\n\nasync function cmdEventsUnskip(id: string, cfg: Config): Promise<void> {\n requireToken(cfg);\n requireInstance(cfg);\n const eventId = await resolveEventId(id, cfg);\n const api = createApiClient(cfg.server, cfg.token);\n await api.unskipEvent(cfg.instanceId, cfg.token, eventId);\n console.log(`Event ${shortId(eventId)}… unskipped`);\n}\n\nasync function cmdTimersView(id: string, cfg: Config): Promise<void> {\n requireToken(cfg);\n requireInstance(cfg);\n const timerId = await resolveTimerId(id, cfg);\n const api = createApiClient(cfg.server, cfg.token);\n const state = await api.getState(cfg.instanceId, cfg.token);\n const timer = state.timers.find(t => t.id === timerId);\n if (!timer) { console.error(`Timer not found: ${timerId}`); process.exit(1); }\n\n const now = Date.now();\n const remaining = timer.currentExpiry - now;\n const expiryStr = `${fmtDate(timer.currentExpiry)} (${remaining >= 0 ? \"in \" : \"\"}${fmtCountdown(remaining)})`;\n\n console.log(`ID: ${timer.id}`);\n console.log(`Name: ${timer.name}`);\n if (timer.description) {\n if (timer.description.length > 500) {\n console.log(`Description: ${timer.description.slice(0, 497)}...`);\n console.log(` (${timer.description.length} chars total — run 'timers description ${shortId(timerId)}' for full text)`);\n } else {\n console.log(`Description: ${timer.description}`);\n }\n }\n console.log(`Expires: ${expiryStr}`);\n console.log(`Created: ${fmtDate(timer.created)}`);\n if (timer.recurrence) {\n const r = timer.recurrence;\n const wknd = r.skipWeekends ? \", skip weekends\" : \"\";\n console.log(`Recurrence: every ${r.periodDays}d at ${r.anchorTime} ${r.timezone}${wknd}`);\n }\n\n const { comments } = await api.listComments(cfg.instanceId, cfg.token, timerId);\n if (comments.length > 0) {\n const PREVIEW = 5;\n const shown = comments.slice(-PREVIEW);\n const hidden = comments.length - shown.length;\n console.log(`\\nComments:${hidden > 0 ? ` (${hidden} older — run 'comments list ${shortId(timerId)}' to see all)` : \"\"}`);\n for (const c of shown) {\n const text = c.text.length > 80 ? c.text.slice(0, 77) + \"...\" : c.text;\n console.log(` ${fmtDate(c.createdAt)} ${text}`);\n }\n }\n}\n\nasync function cmdCommentsList(id: string, cfg: Config, opts: { limit?: number } = {}): Promise<void> {\n requireToken(cfg);\n requireInstance(cfg);\n const timerId = await resolveTimerId(id, cfg);\n const api = createApiClient(cfg.server, cfg.token);\n const { comments } = await api.listComments(cfg.instanceId, cfg.token, timerId);\n if (comments.length === 0) { console.log(\"No comments.\"); return; }\n const shown = opts.limit != null ? comments.slice(-opts.limit) : comments;\n const hidden = comments.length - shown.length;\n if (hidden > 0) console.log(`(${hidden} older comments not shown)`);\n for (const c of shown) {\n console.log(`[${fmtDate(c.createdAt)}] ${c.text}`);\n }\n}\n\nasync function cmdCommentsAdd(id: string, text: string, cfg: Config): Promise<void> {\n requireToken(cfg);\n requireInstance(cfg);\n const timerId = await resolveTimerId(id, cfg);\n const api = createApiClient(cfg.server, cfg.token);\n await api.addComment(cfg.instanceId, cfg.token, timerId, text);\n console.log(`Comment added`);\n}\n\n// ---- Tutorial ----\n\nfunction cmdTutorial(): void {\n console.log(`# autonag tutorial\n\nautonag is a recurring-task tracker with an alarm. Timers count down; when\nthey expire, your alarm client starts ringing. You mark them done — if the\ntimer is recurring, the next occurrence is automatically scheduled.\n\n## Config\n\nYour config lives at \\`~/.config/autonag/client.json5\\`. It is a JSON5 file\n(JSON with comments and trailing commas), so you can annotate it. After\nregistration it looks something like:\n\n\\`\\`\\`json5\n{\n server: 'https://your-server.example',\n token: '…',\n deviceId: '…',\n instanceId: '…',\n}\n\\`\\`\\`\n\nEdit it directly in a text editor whenever you need to change the server\nURL or switch instances. To use a different config file:\n\n\\`\\`\\`\nautonag --config /path/to/other.json5 timers list\n\\`\\`\\`\n\n## First-time setup\n\nRegister this device — give it a short nickname so the admin knows who you are:\n\n\\`\\`\\`\nautonag register myphone\n\\`\\`\\`\n\nYour auth token and device ID are saved to the config. The device starts in\nPENDING state until an admin approves it. Check your status:\n\n\\`\\`\\`\nautonag status\n\\`\\`\\`\n\n## Getting an instance\n\nTimers live in an instance. Create a new one:\n\n\\`\\`\\`\nautonag instances request home\n\\`\\`\\`\n\nWhen the admin approves it, it shows up in your list:\n\n\\`\\`\\`\nautonag instances list\n\\`\\`\\`\n\nSet it as your default:\n\n\\`\\`\\`\nautonag instances select <id>\n\\`\\`\\`\n\nTo join an instance someone else owns, ask them for the instance ID. Then\nrequest access:\n\n\\`\\`\\`\nautonag instances join <instance-id>\n\\`\\`\\`\n\nAn admin will approve your request. The instance ID is not advertised\npublicly — you need to know it.\n\n## Adding timers\n\nOne-shot reminder due in 2 days:\n\n\\`\\`\\`\nautonag timers add \"Doctor follow-up\" 2d\n\\`\\`\\`\n\nRecurring task every 7 days at 9 AM:\n\n\\`\\`\\`\nautonag timers add \"Weekly review\" 7d --days 7 --anchor 09:00\n\\`\\`\\`\n\nThe first argument after the name is the initial expiry. \\`--days\\` makes it\nrecurring; \\`--anchor\\` sets the time of day; \\`--tz\\` overrides the timezone.\n\n## Checking timers\n\n\\`\\`\\`\nautonag timers list\n\\`\\`\\`\n\n\\`\\`\\`\nID Name Remaining Recur\n------------------------------------------------------------\na1b2c3d4… Doctor follow-up in 1d 23h\ne5f6a7b8… Weekly review in 6d 23h ↻\n\\`\\`\\`\n\nThe ↻ symbol marks recurring timers.\n\n## Completing a timer\n\nMark a timer done with a reason (pass, fail, or any custom string):\n\n\\`\\`\\`\nautonag timers complete e5f6 pass\n\\`\\`\\`\n\nFor a one-shot timer this removes it. For a recurring timer it schedules\nthe next occurrence and tells you when:\n\n\\`\\`\\`\nTimer \"Weekly review\" recurred — next: 4/24/2026, 9:00:00 AM\n\\`\\`\\`\n\nTo permanently stop a recurring timer, remove the recurrence first:\n\n\\`\\`\\`\nautonag timers recurrence remove e5f6\nautonag timers complete e5f6 done\n\\`\\`\\`\n\n## Snoozing\n\nPush a timer's deadline out:\n\n\\`\\`\\`\nautonag timers snooze e5f6 3d\n\\`\\`\\`\n\n## Silencing the alarm\n\nSilence the alarm for 30 minutes (the default):\n\n\\`\\`\\`\nautonag shush\n\\`\\`\\`\n\nOr for a specific duration:\n\n\\`\\`\\`\nautonag shush 2h\n\\`\\`\\`\n\nResume:\n\n\\`\\`\\`\nautonag unshush\n\\`\\`\\`\n\n## History\n\nSee every time a recurring timer was completed:\n\n\\`\\`\\`\nautonag timers history e5f6\n\\`\\`\\`\n\n## Notes and comments\n\nAttach a description to a timer:\n\n\\`\\`\\`\nautonag timers describe e5f6 \"Prep the agenda before this\"\n\\`\\`\\`\n\nAdd timestamped comments (good for logging what happened):\n\n\\`\\`\\`\nautonag comments add e5f6 \"Completed but flagged the follow-up\"\n\\`\\`\\`\n\n## Event log\n\nEvery action is recorded. View the log:\n\n\\`\\`\\`\nautonag events list\n\\`\\`\\`\n\nYou can skip events to undo them — state is recomputed as if the\nskipped event never happened:\n\n\\`\\`\\`\nautonag events skip <event-id>\nautonag events unskip <event-id>\n\\`\\`\\`\n\n---\nRun \\`autonag --help\\` for a full command reference.`);\n}\n\n// ---- Help ----\n\nconst HELP = `autonag client CLI\n\nUsage: autonag [options] <command> [args]\n\nOptions:\n -h, --help Show this help\n -s, --server <url> Server URL (default: http://localhost:3000)\n -i, --instance <id> Instance ID (overrides saved default)\n -c, --config <path> Config file (default: ~/.config/autonag/client.json5)\n\n tutorial Walk through setup and daily workflow\n\nAuth:\n register <nickname> Register this device and save token\n status Show auth status and saved config\n\nInstances:\n instances list\n instances request <nickname> Create a new instance\n instances join <instance-id> Request access to an existing instance\n instances select <id>\n\nTimers:\n timers list\n timers add <name> <expiry> [--desc <text>] [--days <n>] [--anchor <HH:MM>] [--tz <tz>] [--skip-weekends]\n timers rename <id> <name>\n timers snooze <id> <expiry> Update expiry: 1d, 30m, 2h, 90s | 2026-05-01T09:00:00Z | unix-ms:<n>\n timers pass <id> [--at <datetime>] Complete with reason \"pass\" (preferred)\n timers fail <id> [--at <datetime>] Complete with reason \"fail\" (preferred)\n timers complete <id> <reason> [--at <datetime>] Complete with a custom reason\n timers remove <id>\n timers view <id> Show full timer details, description, and recent comments\n timers describe <id> <text> Set description\n timers description <id> Print full description\n timers recurrence set <id> <days> [--anchor <HH:MM>] [--tz <tz>] [--skip-weekends]\n timers recurrence remove <id>\n timers history <id> Show completion history\n timers log <id> <reason> --at <datetime> Log a historical completion (no expiry change)\n\nAlarm:\n alarm show Show current alarm state\n\nShush:\n shush [duration] Silence alarm (default: 30m)\n unshush Clear shush\n\nEvents:\n events list [--from <seq>]\n events skip <id>\n events unskip <id>\n\nComments:\n comments list <timerId> [--limit N]\n comments add <timerId> <text>\n\nConfig saved to ~/.config/autonag/client.json5`;\n\n// ---- Flag parsing ----\n\ntype FlagSchema = Record<string, \"string\" | \"int\" | \"boolean\">;\ntype ParsedFlags = { positional: string[]; flags: Record<string, string | number | boolean> };\n\nfunction parseFlags(args: string[], schema: FlagSchema): ParsedFlags {\n const positional: string[] = [];\n const flags: Record<string, string | number | boolean> = {};\n for (let i = 0; i < args.length; i++) {\n const a = args[i]!;\n if (a.startsWith(\"--\")) {\n const key = a.slice(2);\n if (!(key in schema)) {\n console.error(`Unknown flag: --${key}`);\n process.exit(1);\n }\n const type = schema[key]!;\n if (type === \"boolean\") {\n flags[key] = true;\n } else {\n const next = args[i + 1];\n if (!next || next.startsWith(\"--\")) {\n console.error(`Flag --${key} requires a value`);\n process.exit(1);\n }\n if (type === \"int\") {\n const n = Number(next);\n if (!Number.isInteger(n)) {\n console.error(`Flag --${key} must be an integer, got: \"${next}\"`);\n process.exit(1);\n }\n flags[key] = n;\n } else {\n flags[key] = next;\n }\n i++;\n }\n } else {\n positional.push(a);\n }\n }\n return { positional, flags };\n}\n\n// ---- Arg parsing & dispatch ----\n\nconst rawArgs = process.argv.slice(2);\nconst topArgs: string[] = [];\nlet serverOverride: string | undefined;\nlet instanceOverride: string | undefined;\n\nfor (let i = 0; i < rawArgs.length; i++) {\n const a = rawArgs[i]!;\n if (a === \"-h\" || a === \"--help\") { console.log(HELP); process.exit(0); }\n else if (a === \"-s\" || a === \"--server\") {\n if (!rawArgs[i + 1] || rawArgs[i + 1]!.startsWith(\"-\")) { console.error(\"Flag -s/--server requires a URL\"); process.exit(1); }\n serverOverride = rawArgs[++i];\n }\n else if (a === \"-i\" || a === \"--instance\") {\n if (!rawArgs[i + 1] || rawArgs[i + 1]!.startsWith(\"-\")) { console.error(\"Flag -i/--instance requires an ID\"); process.exit(1); }\n instanceOverride = rawArgs[++i];\n }\n else if (a === \"-c\" || a === \"--config\") {\n if (!rawArgs[i + 1] || rawArgs[i + 1]!.startsWith(\"-\")) { console.error(\"Flag -c/--config requires a path\"); process.exit(1); }\n CONFIG_PATH = rawArgs[++i]!;\n }\n else topArgs.push(a);\n}\n\nconst cfg = loadConfig();\nif (serverOverride) cfg.server = serverOverride;\nif (instanceOverride) cfg.instanceId = instanceOverride;\n\nconst [cmd, sub, ...rest] = topArgs;\n\ntry {\n if (!cmd || cmd === \"help\") {\n parseFlags(rest, {});\n console.log(HELP);\n } else if (cmd === \"tutorial\") {\n parseFlags(rest, {});\n cmdTutorial();\n\n } else if (cmd === \"register\") {\n parseFlags(rest, {});\n if (!sub) { console.error(\"Usage: autonag register <nickname>\"); process.exit(1); }\n await cmdRegister(sub, cfg);\n\n } else if (cmd === \"status\") {\n parseFlags(rest, {});\n await cmdStatus(cfg);\n\n } else if (cmd === \"instances\") {\n if (!sub || sub === \"list\") {\n parseFlags(rest, {});\n await cmdInstancesList(cfg);\n } else if (sub === \"request\") {\n const { positional } = parseFlags(rest, {});\n if (!positional[0]) { console.error(\"Usage: autonag instances request <nickname>\"); process.exit(1); }\n await cmdInstancesRequest(positional[0], cfg);\n } else if (sub === \"join\") {\n const { positional } = parseFlags(rest, {});\n if (!positional[0]) { console.error(\"Usage: autonag instances join <instance-id>\"); process.exit(1); }\n await cmdInstancesJoin(positional[0], cfg);\n } else if (sub === \"select\") {\n const { positional } = parseFlags(rest, {});\n if (!positional[0]) { console.error(\"Usage: autonag instances select <id>\"); process.exit(1); }\n await cmdInstancesSelect(positional[0], cfg);\n } else {\n console.error(`Unknown subcommand: instances ${sub}`); process.exit(1);\n }\n\n } else if (cmd === \"timers\") {\n if (!sub || sub === \"list\") {\n parseFlags(rest, {});\n await cmdTimersList(cfg);\n } else if (sub === \"add\") {\n const { positional, flags } = parseFlags(rest, {\n desc: \"string\", days: \"int\", anchor: \"string\", tz: \"string\", \"skip-weekends\": \"boolean\",\n });\n if (!positional[0] || !positional[1]) { console.error(\"Usage: autonag timers add <name> <expiry> [--desc <text>] [--days <n>] [--anchor <HH:MM>] [--tz <tz>] [--skip-weekends]\"); process.exit(1); }\n await cmdTimersAdd(positional[0], positional[1], cfg, {\n desc: flags.desc as string | undefined,\n days: flags.days as number | undefined,\n anchor: flags.anchor as string | undefined,\n tz: flags.tz as string | undefined,\n skipWeekends: flags[\"skip-weekends\"] === true,\n });\n } else if (sub === \"rename\") {\n const { positional } = parseFlags(rest, {});\n if (!positional[0] || !positional[1]) { console.error(\"Usage: autonag timers rename <id> <name>\"); process.exit(1); }\n await cmdTimersRename(positional[0], positional[1], cfg);\n } else if (sub === \"snooze\") {\n const { positional } = parseFlags(rest, {});\n if (!positional[0] || !positional[1]) { console.error(\"Usage: autonag timers snooze <id> <expiry>\"); process.exit(1); }\n await cmdTimersSnooze(positional[0], positional[1], cfg);\n } else if (sub === \"pass\") {\n const { positional, flags } = parseFlags(rest, { at: \"string\" });\n if (!positional[0]) { console.error(\"Usage: autonag timers pass <id> [--at <datetime>]\"); process.exit(1); }\n const at = flags.at ? parseExpiry(flags.at as string) : undefined;\n await cmdTimersComplete(positional[0], \"pass\", cfg, { at });\n } else if (sub === \"fail\") {\n const { positional, flags } = parseFlags(rest, { at: \"string\" });\n if (!positional[0]) { console.error(\"Usage: autonag timers fail <id> [--at <datetime>]\"); process.exit(1); }\n const at = flags.at ? parseExpiry(flags.at as string) : undefined;\n await cmdTimersComplete(positional[0], \"fail\", cfg, { at });\n } else if (sub === \"complete\") {\n const { positional, flags } = parseFlags(rest, { at: \"string\" });\n if (!positional[0] || !positional[1]) { console.error(\"Usage: autonag timers complete <id> <reason> [--at <datetime>]\"); process.exit(1); }\n const at = flags.at ? parseExpiry(flags.at as string) : undefined;\n await cmdTimersComplete(positional[0], positional[1], cfg, { at });\n } else if (sub === \"remove\") {\n const { positional } = parseFlags(rest, {});\n if (!positional[0]) { console.error(\"Usage: autonag timers remove <id>\"); process.exit(1); }\n await cmdTimersRemove(positional[0], cfg);\n } else if (sub === \"describe\") {\n const { positional } = parseFlags(rest, {});\n if (!positional[0] || !positional[1]) { console.error(\"Usage: autonag timers describe <id> <text>\"); process.exit(1); }\n await cmdTimersDescribe(positional[0], positional[1], cfg);\n } else if (sub === \"description\") {\n const { positional } = parseFlags(rest, {});\n if (!positional[0]) { console.error(\"Usage: autonag timers description <id>\"); process.exit(1); }\n await cmdTimersGetDescription(positional[0], cfg);\n } else if (sub === \"recurrence\") {\n const recSub = rest[0];\n if (recSub === \"set\") {\n const { positional, flags } = parseFlags(rest, { anchor: \"string\", tz: \"string\", \"skip-weekends\": \"boolean\" });\n // positional = [\"set\", id, days]\n if (!positional[1] || !positional[2]) { console.error(\"Usage: autonag timers recurrence set <id> <days> [--anchor <HH:MM>] [--tz <tz>] [--skip-weekends]\"); process.exit(1); }\n const days = Number(positional[2]);\n if (!Number.isInteger(days) || days <= 0) { console.error(`<days> must be a positive integer, got: \"${positional[2]}\"`); process.exit(1); }\n await cmdTimersRecurrenceSet(positional[1], days, cfg, {\n anchor: flags.anchor as string | undefined,\n tz: flags.tz as string | undefined,\n skipWeekends: flags[\"skip-weekends\"] === true,\n });\n } else if (recSub === \"remove\") {\n const { positional } = parseFlags(rest, {});\n // positional = [\"remove\", id]\n if (!positional[1]) { console.error(\"Usage: autonag timers recurrence remove <id>\"); process.exit(1); }\n await cmdTimersRecurrenceRemove(positional[1], cfg);\n } else {\n console.error(\"Usage: autonag timers recurrence set|remove ...\"); process.exit(1);\n }\n } else if (sub === \"view\") {\n const { positional } = parseFlags(rest, {});\n if (!positional[0]) { console.error(\"Usage: autonag timers view <id>\"); process.exit(1); }\n await cmdTimersView(positional[0], cfg);\n } else if (sub === \"history\") {\n const { positional } = parseFlags(rest, {});\n if (!positional[0]) { console.error(\"Usage: autonag timers history <id>\"); process.exit(1); }\n await cmdTimersHistory(positional[0], cfg);\n } else if (sub === \"log\") {\n const { positional, flags } = parseFlags(rest, { at: \"string\" });\n if (!positional[0] || !positional[1]) { console.error(\"Usage: autonag timers log <id> <reason> --at <datetime>\"); process.exit(1); }\n if (!flags.at) { console.error(\"--at <datetime> is required for timers log\"); process.exit(1); }\n const at = parseExpiry(flags.at as string);\n await cmdTimersLog(positional[0], positional[1], at, cfg);\n } else {\n console.error(`Unknown subcommand: timers ${sub}`); process.exit(1);\n }\n\n } else if (cmd === \"alarm\") {\n if (sub !== \"show\") { console.error(\"Usage: autonag alarm show\"); process.exit(1); }\n parseFlags(rest, {});\n await cmdAlarm(cfg);\n\n } else if (cmd === \"shush\") {\n parseFlags(rest, {});\n await cmdShush(sub, cfg);\n } else if (cmd === \"unshush\") {\n parseFlags(rest, {});\n await cmdUnshush(cfg);\n\n } else if (cmd === \"events\") {\n if (!sub || sub === \"list\") {\n const { flags } = parseFlags(rest, { from: \"int\" });\n await cmdEventsList((flags.from as number | undefined) ?? 1, cfg);\n } else if (sub === \"skip\") {\n const { positional } = parseFlags(rest, {});\n if (!positional[0]) { console.error(\"Usage: autonag events skip <id>\"); process.exit(1); }\n await cmdEventsSkip(positional[0], cfg);\n } else if (sub === \"unskip\") {\n const { positional } = parseFlags(rest, {});\n if (!positional[0]) { console.error(\"Usage: autonag events unskip <id>\"); process.exit(1); }\n await cmdEventsUnskip(positional[0], cfg);\n } else {\n console.error(`Unknown subcommand: events ${sub}`); process.exit(1);\n }\n\n } else if (cmd === \"comments\") {\n if (!sub || sub === \"list\") {\n const { positional, flags } = parseFlags(rest, { limit: \"int\" });\n if (!positional[0]) { console.error(\"Usage: autonag comments list <timerId> [--limit N]\"); process.exit(1); }\n await cmdCommentsList(positional[0], cfg, { limit: flags.limit as number | undefined });\n } else if (sub === \"add\") {\n const { positional } = parseFlags(rest, {});\n if (!positional[0] || !positional[1]) { console.error(\"Usage: autonag comments add <timerId> <text>\"); process.exit(1); }\n await cmdCommentsAdd(positional[0], positional[1], cfg);\n } else {\n console.error(`Unknown subcommand: comments ${sub}`); process.exit(1);\n }\n\n } else {\n console.error(`Unknown command: ${cmd}`);\n console.error(`Run \"autonag --help\" for usage.`);\n process.exit(1);\n }\n} catch (e) {\n if (e instanceof ApiError) {\n console.error(`Error: ${e.message}`);\n process.exit(1);\n }\n throw e;\n}\n","import type { RecurrenceSpec, StoredEvent, Comment, InstanceState } from \"./types\";\n\nexport class ApiError extends Error {\n constructor(public status: number, message: string) {\n super(message);\n this.name = \"ApiError\";\n }\n}\n\nexport type BatchActionItem =\n | { type: \"addTimer\"; name: string; description?: string; expiry: number; recurrence?: RecurrenceSpec }\n | { type: \"updateExpiry\"; timerId: string; expiry: number }\n | { type: \"completeTimer\"; timerId: string; closeReason: string; occurredAt?: number }\n | { type: \"removeTimer\"; timerId: string }\n | { type: \"shush\"; expiry: number }\n | { type: \"clearShush\" }\n | { type: \"recurTimer\"; timerId: string; closeReason: string; occurredAt?: number }\n | { type: \"updateRecurrence\"; timerId: string; recurrence: RecurrenceSpec }\n | { type: \"removeRecurrence\"; timerId: string }\n | { type: \"updateDescription\"; timerId: string; description: string }\n | { type: \"logCompletion\"; timerId: string; closeReason: string; occurredAt: number }\n | { type: \"assert\"; path: string; expectStatus?: number; expect?: unknown };\n\nexport function createApiClient(baseUrl: string, defaultToken?: string) {\n async function apiFetch<T>(\n path: string,\n options: RequestInit = {},\n token?: string,\n ): Promise<T> {\n const tok = token ?? defaultToken;\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n ...(options.headers as Record<string, string>),\n };\n if (tok) headers[\"Authorization\"] = `Bearer ${tok}`;\n\n const res = await fetch(`${baseUrl}${path}`, { ...options, headers });\n if (!res.ok) {\n let message = `HTTP ${res.status}`;\n try {\n const body = await res.json() as { error?: string };\n if (body.error) message = body.error;\n } catch { /* ignore */ }\n throw new ApiError(res.status, message);\n }\n return res.json() as Promise<T>;\n }\n\n return {\n registerDevice: (nickname: string) =>\n apiFetch<{ device: { id: string; nickname: string }; token: string }>(\n \"/devices/request\", { method: \"POST\", body: JSON.stringify({ nickname }) }\n ),\n\n getMe: (token: string) =>\n apiFetch<{ device: { id: string; nickname: string; approvedAt: number | null } }>(\n \"/devices/me\", {}, token\n ),\n\n requestInstance: (nickname: string, token: string) =>\n apiFetch<{ instance: { id: string; nickname: string } }>(\n \"/instances/request\", { method: \"POST\", body: JSON.stringify({ nickname }) }, token\n ),\n\n requestInstanceAccess: (instanceId: string, token: string) =>\n apiFetch<{ request?: { id: string; status: string }; status?: string }>(\n `/instances/${instanceId}/access/request`,\n { method: \"POST\", body: JSON.stringify({}) },\n token\n ),\n\n listInstances: (token: string) =>\n apiFetch<{ instances: { id: string; nickname: string; approvedAt: number | null }[] }>(\n \"/instances\", {}, token\n ),\n\n addTimer: (instanceId: string, token: string, name: string, expiry: number, recurrence?: RecurrenceSpec, description?: string) =>\n apiFetch<{ timer: { id: string }; event: { id: string; seq: number } }>(\n `/instances/${instanceId}/timers`,\n { method: \"POST\", body: JSON.stringify({ name, expiry, ...(description ? { description } : {}), ...(recurrence ? { recurrence } : {}) }) },\n token\n ),\n\n renameTimer: (instanceId: string, token: string, timerId: string, name: string) =>\n apiFetch<{ event: { id: string; seq: number } }>(\n `/instances/${instanceId}/timers/${timerId}/name`,\n { method: \"PATCH\", body: JSON.stringify({ name }) },\n token\n ),\n\n updateExpiry: (instanceId: string, token: string, timerId: string, expiry: number) =>\n apiFetch<{ event: { id: string; seq: number } }>(\n `/instances/${instanceId}/timers/${timerId}/expiry`,\n { method: \"PATCH\", body: JSON.stringify({ expiry }) },\n token\n ),\n\n completeTimer: (instanceId: string, token: string, timerId: string, closeReason: string) =>\n apiFetch<{ event: { id: string; seq: number } }>(\n `/instances/${instanceId}/timers/${timerId}/complete`,\n { method: \"POST\", body: JSON.stringify({ closeReason }) },\n token\n ),\n\n removeTimer: (instanceId: string, token: string, timerId: string) =>\n apiFetch<{ event: { id: string; seq: number } }>(\n `/instances/${instanceId}/timers/${timerId}`,\n { method: \"DELETE\" },\n token\n ),\n\n setShush: (instanceId: string, token: string, expiry: number) =>\n apiFetch<{ event: { id: string; seq: number } }>(\n `/instances/${instanceId}/shush`,\n { method: \"POST\", body: JSON.stringify({ expiry }) },\n token\n ),\n\n clearShush: (instanceId: string, token: string) =>\n apiFetch<{ event: { id: string; seq: number } }>(\n `/instances/${instanceId}/shush`,\n { method: \"DELETE\" },\n token\n ),\n\n listEvents: (instanceId: string, token: string, opts: { from?: number; before?: number; limit?: number } = {}) => {\n const { from = 1, before, limit = 200 } = opts;\n const params = before !== undefined\n ? `before=${before}&limit=${limit}`\n : `from=${from}&limit=${limit}`;\n return apiFetch<{ events: StoredEvent[]; latestSeq: number; prevCursor?: number | null }>(\n `/instances/${instanceId}/events?${params}`, {}, token\n );\n },\n\n getTimerHistory: (instanceId: string, token: string, timerId: string, opts: {\n after?: number; limit?: number; from?: number; to?: number;\n } = {}) => {\n const params = new URLSearchParams();\n if (opts.after !== undefined) params.set(\"after\", String(opts.after));\n if (opts.limit !== undefined) params.set(\"limit\", String(opts.limit));\n if (opts.from !== undefined) params.set(\"from\", String(opts.from));\n if (opts.to !== undefined) params.set(\"to\", String(opts.to));\n const qs = params.toString();\n return apiFetch<{ events: StoredEvent[]; nextCursor: number | null }>(\n `/instances/${instanceId}/timers/${timerId}/history${qs ? `?${qs}` : \"\"}`, {}, token\n );\n },\n\n skipEvent: (instanceId: string, token: string, eventId: string) =>\n apiFetch<{ ok: boolean }>(\n `/instances/${instanceId}/events/${eventId}/skip`, { method: \"POST\" }, token\n ),\n\n unskipEvent: (instanceId: string, token: string, eventId: string) =>\n apiFetch<{ ok: boolean }>(\n `/instances/${instanceId}/events/${eventId}/skip`, { method: \"DELETE\" }, token\n ),\n\n listComments: (instanceId: string, token: string, threadId: string) =>\n apiFetch<{ comments: Comment[] }>(\n `/instances/${instanceId}/threads/${threadId}/comments`, {}, token\n ),\n\n addComment: (instanceId: string, token: string, threadId: string, text: string) =>\n apiFetch<{ comment: Comment }>(\n `/instances/${instanceId}/threads/${threadId}/comments`,\n { method: \"POST\", body: JSON.stringify({ text }) },\n token\n ),\n\n getState: (instanceId: string, token: string) =>\n apiFetch<InstanceState>(\n `/instances/${instanceId}/state`, {}, token\n ),\n\n batchActions: (instanceId: string, token: string, actions: BatchActionItem[]) =>\n apiFetch<{ events: { id: string; seq: number; type: string }[] }>(\n `/instances/${instanceId}/actions`,\n { method: \"POST\", body: JSON.stringify({ actions }) },\n token\n ),\n };\n}\n"],"mappings":"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","names":["cfg"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -97,6 +97,7 @@ type BatchActionItem = {
|
|
|
97
97
|
type: "completeTimer";
|
|
98
98
|
timerId: string;
|
|
99
99
|
closeReason: string;
|
|
100
|
+
occurredAt?: number;
|
|
100
101
|
} | {
|
|
101
102
|
type: "removeTimer";
|
|
102
103
|
timerId: string;
|
|
@@ -109,6 +110,7 @@ type BatchActionItem = {
|
|
|
109
110
|
type: "recurTimer";
|
|
110
111
|
timerId: string;
|
|
111
112
|
closeReason: string;
|
|
113
|
+
occurredAt?: number;
|
|
112
114
|
} | {
|
|
113
115
|
type: "updateRecurrence";
|
|
114
116
|
timerId: string;
|
|
@@ -120,6 +122,11 @@ type BatchActionItem = {
|
|
|
120
122
|
type: "updateDescription";
|
|
121
123
|
timerId: string;
|
|
122
124
|
description: string;
|
|
125
|
+
} | {
|
|
126
|
+
type: "logCompletion";
|
|
127
|
+
timerId: string;
|
|
128
|
+
closeReason: string;
|
|
129
|
+
occurredAt: number;
|
|
123
130
|
} | {
|
|
124
131
|
type: "assert";
|
|
125
132
|
path: string;
|
|
@@ -147,29 +154,13 @@ declare function createApiClient(baseUrl: string, defaultToken?: string): {
|
|
|
147
154
|
nickname: string;
|
|
148
155
|
};
|
|
149
156
|
}>;
|
|
150
|
-
requestInstanceAccess: (instanceId: string, token: string
|
|
157
|
+
requestInstanceAccess: (instanceId: string, token: string) => Promise<{
|
|
151
158
|
request?: {
|
|
152
159
|
id: string;
|
|
153
160
|
status: string;
|
|
154
161
|
};
|
|
155
162
|
status?: string;
|
|
156
163
|
}>;
|
|
157
|
-
getInvite: (code: string) => Promise<{
|
|
158
|
-
invite: {
|
|
159
|
-
code: string;
|
|
160
|
-
instanceId: string;
|
|
161
|
-
instanceNickname: string;
|
|
162
|
-
expiresAt: number;
|
|
163
|
-
valid: boolean;
|
|
164
|
-
reason?: string;
|
|
165
|
-
};
|
|
166
|
-
}>;
|
|
167
|
-
createInvite: (instanceId: string, token: string) => Promise<{
|
|
168
|
-
invite: {
|
|
169
|
-
code: string;
|
|
170
|
-
expiresAt: number;
|
|
171
|
-
};
|
|
172
|
-
}>;
|
|
173
164
|
listInstances: (token: string) => Promise<{
|
|
174
165
|
instances: {
|
|
175
166
|
id: string;
|
package/dist/index.js
CHANGED
|
@@ -42,16 +42,8 @@ function createApiClient(baseUrl, defaultToken) {
|
|
|
42
42
|
{ method: "POST", body: JSON.stringify({ nickname }) },
|
|
43
43
|
token
|
|
44
44
|
),
|
|
45
|
-
requestInstanceAccess: (instanceId, token
|
|
45
|
+
requestInstanceAccess: (instanceId, token) => apiFetch(
|
|
46
46
|
`/instances/${instanceId}/access/request`,
|
|
47
|
-
{ method: "POST", body: JSON.stringify(inviteCode ? { inviteCode } : {}) },
|
|
48
|
-
token
|
|
49
|
-
),
|
|
50
|
-
getInvite: (code) => apiFetch(
|
|
51
|
-
`/invites/${code}`
|
|
52
|
-
),
|
|
53
|
-
createInvite: (instanceId, token) => apiFetch(
|
|
54
|
-
`/instances/${instanceId}/invites`,
|
|
55
47
|
{ method: "POST", body: JSON.stringify({}) },
|
|
56
48
|
token
|
|
57
49
|
),
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../apiClient.ts"],"sourcesContent":["import type { RecurrenceSpec, StoredEvent, Comment, InstanceState } from \"./types\";\n\nexport class ApiError extends Error {\n constructor(public status: number, message: string) {\n super(message);\n this.name = \"ApiError\";\n }\n}\n\nexport type BatchActionItem =\n | { type: \"addTimer\"; name: string; description?: string; expiry: number; recurrence?: RecurrenceSpec }\n | { type: \"updateExpiry\"; timerId: string; expiry: number }\n | { type: \"completeTimer\"; timerId: string; closeReason: string }\n | { type: \"removeTimer\"; timerId: string }\n | { type: \"shush\"; expiry: number }\n | { type: \"clearShush\" }\n | { type: \"recurTimer\"; timerId: string; closeReason: string }\n | { type: \"updateRecurrence\"; timerId: string; recurrence: RecurrenceSpec }\n | { type: \"removeRecurrence\"; timerId: string }\n | { type: \"updateDescription\"; timerId: string; description: string }\n | { type: \"assert\"; path: string; expectStatus?: number; expect?: unknown };\n\nexport function createApiClient(baseUrl: string, defaultToken?: string) {\n async function apiFetch<T>(\n path: string,\n options: RequestInit = {},\n token?: string,\n ): Promise<T> {\n const tok = token ?? defaultToken;\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n ...(options.headers as Record<string, string>),\n };\n if (tok) headers[\"Authorization\"] = `Bearer ${tok}`;\n\n const res = await fetch(`${baseUrl}${path}`, { ...options, headers });\n if (!res.ok) {\n let message = `HTTP ${res.status}`;\n try {\n const body = await res.json() as { error?: string };\n if (body.error) message = body.error;\n } catch { /* ignore */ }\n throw new ApiError(res.status, message);\n }\n return res.json() as Promise<T>;\n }\n\n return {\n registerDevice: (nickname: string) =>\n apiFetch<{ device: { id: string; nickname: string }; token: string }>(\n \"/devices/request\", { method: \"POST\", body: JSON.stringify({ nickname }) }\n ),\n\n getMe: (token: string) =>\n apiFetch<{ device: { id: string; nickname: string; approvedAt: number | null } }>(\n \"/devices/me\", {}, token\n ),\n\n requestInstance: (nickname: string, token: string) =>\n apiFetch<{ instance: { id: string; nickname: string } }>(\n \"/instances/request\", { method: \"POST\", body: JSON.stringify({ nickname }) }, token\n ),\n\n requestInstanceAccess: (instanceId: string, token: string, inviteCode?: string) =>\n apiFetch<{ request?: { id: string; status: string }; status?: string }>(\n `/instances/${instanceId}/access/request`,\n { method: \"POST\", body: JSON.stringify(inviteCode ? { inviteCode } : {}) },\n token\n ),\n\n getInvite: (code: string) =>\n apiFetch<{ invite: { code: string; instanceId: string; instanceNickname: string; expiresAt: number; valid: boolean; reason?: string } }>(\n `/invites/${code}`\n ),\n\n createInvite: (instanceId: string, token: string) =>\n apiFetch<{ invite: { code: string; expiresAt: number } }>(\n `/instances/${instanceId}/invites`, { method: \"POST\", body: JSON.stringify({}) }, token\n ),\n\n listInstances: (token: string) =>\n apiFetch<{ instances: { id: string; nickname: string; approvedAt: number | null }[] }>(\n \"/instances\", {}, token\n ),\n\n addTimer: (instanceId: string, token: string, name: string, expiry: number, recurrence?: RecurrenceSpec, description?: string) =>\n apiFetch<{ timer: { id: string }; event: { id: string; seq: number } }>(\n `/instances/${instanceId}/timers`,\n { method: \"POST\", body: JSON.stringify({ name, expiry, ...(description ? { description } : {}), ...(recurrence ? { recurrence } : {}) }) },\n token\n ),\n\n renameTimer: (instanceId: string, token: string, timerId: string, name: string) =>\n apiFetch<{ event: { id: string; seq: number } }>(\n `/instances/${instanceId}/timers/${timerId}/name`,\n { method: \"PATCH\", body: JSON.stringify({ name }) },\n token\n ),\n\n updateExpiry: (instanceId: string, token: string, timerId: string, expiry: number) =>\n apiFetch<{ event: { id: string; seq: number } }>(\n `/instances/${instanceId}/timers/${timerId}/expiry`,\n { method: \"PATCH\", body: JSON.stringify({ expiry }) },\n token\n ),\n\n completeTimer: (instanceId: string, token: string, timerId: string, closeReason: string) =>\n apiFetch<{ event: { id: string; seq: number } }>(\n `/instances/${instanceId}/timers/${timerId}/complete`,\n { method: \"POST\", body: JSON.stringify({ closeReason }) },\n token\n ),\n\n removeTimer: (instanceId: string, token: string, timerId: string) =>\n apiFetch<{ event: { id: string; seq: number } }>(\n `/instances/${instanceId}/timers/${timerId}`,\n { method: \"DELETE\" },\n token\n ),\n\n setShush: (instanceId: string, token: string, expiry: number) =>\n apiFetch<{ event: { id: string; seq: number } }>(\n `/instances/${instanceId}/shush`,\n { method: \"POST\", body: JSON.stringify({ expiry }) },\n token\n ),\n\n clearShush: (instanceId: string, token: string) =>\n apiFetch<{ event: { id: string; seq: number } }>(\n `/instances/${instanceId}/shush`,\n { method: \"DELETE\" },\n token\n ),\n\n listEvents: (instanceId: string, token: string, opts: { from?: number; before?: number; limit?: number } = {}) => {\n const { from = 1, before, limit = 200 } = opts;\n const params = before !== undefined\n ? `before=${before}&limit=${limit}`\n : `from=${from}&limit=${limit}`;\n return apiFetch<{ events: StoredEvent[]; latestSeq: number; prevCursor?: number | null }>(\n `/instances/${instanceId}/events?${params}`, {}, token\n );\n },\n\n getTimerHistory: (instanceId: string, token: string, timerId: string, opts: {\n after?: number; limit?: number; from?: number; to?: number;\n } = {}) => {\n const params = new URLSearchParams();\n if (opts.after !== undefined) params.set(\"after\", String(opts.after));\n if (opts.limit !== undefined) params.set(\"limit\", String(opts.limit));\n if (opts.from !== undefined) params.set(\"from\", String(opts.from));\n if (opts.to !== undefined) params.set(\"to\", String(opts.to));\n const qs = params.toString();\n return apiFetch<{ events: StoredEvent[]; nextCursor: number | null }>(\n `/instances/${instanceId}/timers/${timerId}/history${qs ? `?${qs}` : \"\"}`, {}, token\n );\n },\n\n skipEvent: (instanceId: string, token: string, eventId: string) =>\n apiFetch<{ ok: boolean }>(\n `/instances/${instanceId}/events/${eventId}/skip`, { method: \"POST\" }, token\n ),\n\n unskipEvent: (instanceId: string, token: string, eventId: string) =>\n apiFetch<{ ok: boolean }>(\n `/instances/${instanceId}/events/${eventId}/skip`, { method: \"DELETE\" }, token\n ),\n\n listComments: (instanceId: string, token: string, threadId: string) =>\n apiFetch<{ comments: Comment[] }>(\n `/instances/${instanceId}/threads/${threadId}/comments`, {}, token\n ),\n\n addComment: (instanceId: string, token: string, threadId: string, text: string) =>\n apiFetch<{ comment: Comment }>(\n `/instances/${instanceId}/threads/${threadId}/comments`,\n { method: \"POST\", body: JSON.stringify({ text }) },\n token\n ),\n\n getState: (instanceId: string, token: string) =>\n apiFetch<InstanceState>(\n `/instances/${instanceId}/state`, {}, token\n ),\n\n batchActions: (instanceId: string, token: string, actions: BatchActionItem[]) =>\n apiFetch<{ events: { id: string; seq: number; type: string }[] }>(\n `/instances/${instanceId}/actions`,\n { method: \"POST\", body: JSON.stringify({ actions }) },\n token\n ),\n };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../apiClient.ts"],"sourcesContent":["import type { RecurrenceSpec, StoredEvent, Comment, InstanceState } from \"./types\";\n\nexport class ApiError extends Error {\n constructor(public status: number, message: string) {\n super(message);\n this.name = \"ApiError\";\n }\n}\n\nexport type BatchActionItem =\n | { type: \"addTimer\"; name: string; description?: string; expiry: number; recurrence?: RecurrenceSpec }\n | { type: \"updateExpiry\"; timerId: string; expiry: number }\n | { type: \"completeTimer\"; timerId: string; closeReason: string; occurredAt?: number }\n | { type: \"removeTimer\"; timerId: string }\n | { type: \"shush\"; expiry: number }\n | { type: \"clearShush\" }\n | { type: \"recurTimer\"; timerId: string; closeReason: string; occurredAt?: number }\n | { type: \"updateRecurrence\"; timerId: string; recurrence: RecurrenceSpec }\n | { type: \"removeRecurrence\"; timerId: string }\n | { type: \"updateDescription\"; timerId: string; description: string }\n | { type: \"logCompletion\"; timerId: string; closeReason: string; occurredAt: number }\n | { type: \"assert\"; path: string; expectStatus?: number; expect?: unknown };\n\nexport function createApiClient(baseUrl: string, defaultToken?: string) {\n async function apiFetch<T>(\n path: string,\n options: RequestInit = {},\n token?: string,\n ): Promise<T> {\n const tok = token ?? defaultToken;\n const headers: Record<string, string> = {\n \"Content-Type\": \"application/json\",\n ...(options.headers as Record<string, string>),\n };\n if (tok) headers[\"Authorization\"] = `Bearer ${tok}`;\n\n const res = await fetch(`${baseUrl}${path}`, { ...options, headers });\n if (!res.ok) {\n let message = `HTTP ${res.status}`;\n try {\n const body = await res.json() as { error?: string };\n if (body.error) message = body.error;\n } catch { /* ignore */ }\n throw new ApiError(res.status, message);\n }\n return res.json() as Promise<T>;\n }\n\n return {\n registerDevice: (nickname: string) =>\n apiFetch<{ device: { id: string; nickname: string }; token: string }>(\n \"/devices/request\", { method: \"POST\", body: JSON.stringify({ nickname }) }\n ),\n\n getMe: (token: string) =>\n apiFetch<{ device: { id: string; nickname: string; approvedAt: number | null } }>(\n \"/devices/me\", {}, token\n ),\n\n requestInstance: (nickname: string, token: string) =>\n apiFetch<{ instance: { id: string; nickname: string } }>(\n \"/instances/request\", { method: \"POST\", body: JSON.stringify({ nickname }) }, token\n ),\n\n requestInstanceAccess: (instanceId: string, token: string) =>\n apiFetch<{ request?: { id: string; status: string }; status?: string }>(\n `/instances/${instanceId}/access/request`,\n { method: \"POST\", body: JSON.stringify({}) },\n token\n ),\n\n listInstances: (token: string) =>\n apiFetch<{ instances: { id: string; nickname: string; approvedAt: number | null }[] }>(\n \"/instances\", {}, token\n ),\n\n addTimer: (instanceId: string, token: string, name: string, expiry: number, recurrence?: RecurrenceSpec, description?: string) =>\n apiFetch<{ timer: { id: string }; event: { id: string; seq: number } }>(\n `/instances/${instanceId}/timers`,\n { method: \"POST\", body: JSON.stringify({ name, expiry, ...(description ? { description } : {}), ...(recurrence ? { recurrence } : {}) }) },\n token\n ),\n\n renameTimer: (instanceId: string, token: string, timerId: string, name: string) =>\n apiFetch<{ event: { id: string; seq: number } }>(\n `/instances/${instanceId}/timers/${timerId}/name`,\n { method: \"PATCH\", body: JSON.stringify({ name }) },\n token\n ),\n\n updateExpiry: (instanceId: string, token: string, timerId: string, expiry: number) =>\n apiFetch<{ event: { id: string; seq: number } }>(\n `/instances/${instanceId}/timers/${timerId}/expiry`,\n { method: \"PATCH\", body: JSON.stringify({ expiry }) },\n token\n ),\n\n completeTimer: (instanceId: string, token: string, timerId: string, closeReason: string) =>\n apiFetch<{ event: { id: string; seq: number } }>(\n `/instances/${instanceId}/timers/${timerId}/complete`,\n { method: \"POST\", body: JSON.stringify({ closeReason }) },\n token\n ),\n\n removeTimer: (instanceId: string, token: string, timerId: string) =>\n apiFetch<{ event: { id: string; seq: number } }>(\n `/instances/${instanceId}/timers/${timerId}`,\n { method: \"DELETE\" },\n token\n ),\n\n setShush: (instanceId: string, token: string, expiry: number) =>\n apiFetch<{ event: { id: string; seq: number } }>(\n `/instances/${instanceId}/shush`,\n { method: \"POST\", body: JSON.stringify({ expiry }) },\n token\n ),\n\n clearShush: (instanceId: string, token: string) =>\n apiFetch<{ event: { id: string; seq: number } }>(\n `/instances/${instanceId}/shush`,\n { method: \"DELETE\" },\n token\n ),\n\n listEvents: (instanceId: string, token: string, opts: { from?: number; before?: number; limit?: number } = {}) => {\n const { from = 1, before, limit = 200 } = opts;\n const params = before !== undefined\n ? `before=${before}&limit=${limit}`\n : `from=${from}&limit=${limit}`;\n return apiFetch<{ events: StoredEvent[]; latestSeq: number; prevCursor?: number | null }>(\n `/instances/${instanceId}/events?${params}`, {}, token\n );\n },\n\n getTimerHistory: (instanceId: string, token: string, timerId: string, opts: {\n after?: number; limit?: number; from?: number; to?: number;\n } = {}) => {\n const params = new URLSearchParams();\n if (opts.after !== undefined) params.set(\"after\", String(opts.after));\n if (opts.limit !== undefined) params.set(\"limit\", String(opts.limit));\n if (opts.from !== undefined) params.set(\"from\", String(opts.from));\n if (opts.to !== undefined) params.set(\"to\", String(opts.to));\n const qs = params.toString();\n return apiFetch<{ events: StoredEvent[]; nextCursor: number | null }>(\n `/instances/${instanceId}/timers/${timerId}/history${qs ? `?${qs}` : \"\"}`, {}, token\n );\n },\n\n skipEvent: (instanceId: string, token: string, eventId: string) =>\n apiFetch<{ ok: boolean }>(\n `/instances/${instanceId}/events/${eventId}/skip`, { method: \"POST\" }, token\n ),\n\n unskipEvent: (instanceId: string, token: string, eventId: string) =>\n apiFetch<{ ok: boolean }>(\n `/instances/${instanceId}/events/${eventId}/skip`, { method: \"DELETE\" }, token\n ),\n\n listComments: (instanceId: string, token: string, threadId: string) =>\n apiFetch<{ comments: Comment[] }>(\n `/instances/${instanceId}/threads/${threadId}/comments`, {}, token\n ),\n\n addComment: (instanceId: string, token: string, threadId: string, text: string) =>\n apiFetch<{ comment: Comment }>(\n `/instances/${instanceId}/threads/${threadId}/comments`,\n { method: \"POST\", body: JSON.stringify({ text }) },\n token\n ),\n\n getState: (instanceId: string, token: string) =>\n apiFetch<InstanceState>(\n `/instances/${instanceId}/state`, {}, token\n ),\n\n batchActions: (instanceId: string, token: string, actions: BatchActionItem[]) =>\n apiFetch<{ events: { id: string; seq: number; type: string }[] }>(\n `/instances/${instanceId}/actions`,\n { method: \"POST\", body: JSON.stringify({ actions }) },\n token\n ),\n };\n}\n"],"mappings":"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","names":[]}
|