autonag 0.3.0 → 0.4.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 +155 -11
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// cli.ts
|
|
4
|
-
import { join } from "path";
|
|
4
|
+
import { join, dirname } from "path";
|
|
5
|
+
import { fileURLToPath } from "url";
|
|
5
6
|
import { homedir } from "os";
|
|
6
7
|
import { mkdirSync, existsSync, readFileSync, writeFileSync } from "fs";
|
|
7
8
|
import JSON5 from "json5";
|
|
@@ -151,6 +152,7 @@ function createApiClient(baseUrl, defaultToken) {
|
|
|
151
152
|
}
|
|
152
153
|
|
|
153
154
|
// cli.ts
|
|
155
|
+
var VERSION = JSON.parse(readFileSync(join(dirname(fileURLToPath(import.meta.url)), "..", "package.json"), "utf8")).version;
|
|
154
156
|
var CONFIG_PATH = join(homedir(), ".config", "autonag", "client.json5");
|
|
155
157
|
function loadConfig() {
|
|
156
158
|
if (!existsSync(CONFIG_PATH)) return { server: "http://localhost:3000" };
|
|
@@ -287,17 +289,43 @@ function requireInstance(cfg2) {
|
|
|
287
289
|
process.exit(1);
|
|
288
290
|
}
|
|
289
291
|
}
|
|
292
|
+
function jsonOut(data) {
|
|
293
|
+
console.log(JSON.stringify(data, null, 2));
|
|
294
|
+
}
|
|
290
295
|
async function cmdRegister(nickname, cfg2) {
|
|
291
296
|
const api = createApiClient(cfg2.server);
|
|
292
297
|
const { device, token } = await api.registerDevice(nickname);
|
|
293
298
|
cfg2.token = token;
|
|
294
299
|
cfg2.deviceId = device.id;
|
|
295
300
|
saveConfig(cfg2);
|
|
301
|
+
if (jsonMode) {
|
|
302
|
+
jsonOut({ deviceId: device.id, nickname, token, configPath: CONFIG_PATH });
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
296
305
|
console.log(`Registered as "${nickname}" (${shortId(device.id)}\u2026)`);
|
|
297
306
|
console.log(`Token saved to ${CONFIG_PATH}`);
|
|
298
307
|
console.log(`Waiting for admin approval \u2014 run "autonag status" to check.`);
|
|
299
308
|
}
|
|
300
309
|
async function cmdStatus(cfg2) {
|
|
310
|
+
if (jsonMode) {
|
|
311
|
+
const result = { server: cfg2.server, configPath: CONFIG_PATH, instanceId: cfg2.instanceId ?? null };
|
|
312
|
+
if (!cfg2.token) {
|
|
313
|
+
result.auth = null;
|
|
314
|
+
jsonOut(result);
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
const api2 = createApiClient(cfg2.server, cfg2.token);
|
|
318
|
+
try {
|
|
319
|
+
const { device: d } = await api2.getMe(cfg2.token);
|
|
320
|
+
result.auth = { nickname: d.nickname, deviceId: d.id, approved: !!d.approvedAt, approvedAt: d.approvedAt ?? null };
|
|
321
|
+
} catch (e) {
|
|
322
|
+
if (e instanceof ApiError && e.status === 401) {
|
|
323
|
+
result.auth = { error: "invalid_token" };
|
|
324
|
+
} else throw e;
|
|
325
|
+
}
|
|
326
|
+
jsonOut(result);
|
|
327
|
+
return;
|
|
328
|
+
}
|
|
301
329
|
console.log(`Server: ${cfg2.server}`);
|
|
302
330
|
console.log(`Config: ${CONFIG_PATH}`);
|
|
303
331
|
if (!cfg2.token) {
|
|
@@ -320,6 +348,10 @@ async function cmdInstancesList(cfg2) {
|
|
|
320
348
|
requireToken(cfg2);
|
|
321
349
|
const api = createApiClient(cfg2.server, cfg2.token);
|
|
322
350
|
const { instances } = await api.listInstances(cfg2.token);
|
|
351
|
+
if (jsonMode) {
|
|
352
|
+
jsonOut(instances.map((i) => ({ id: i.id, nickname: i.nickname, approved: !!i.approvedAt, approvedAt: i.approvedAt ?? null, selected: i.id === cfg2.instanceId })));
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
323
355
|
if (instances.length === 0) {
|
|
324
356
|
console.log("No accessible instances.");
|
|
325
357
|
return;
|
|
@@ -336,6 +368,10 @@ async function cmdInstancesRequest(nickname, cfg2) {
|
|
|
336
368
|
requireToken(cfg2);
|
|
337
369
|
const api = createApiClient(cfg2.server, cfg2.token);
|
|
338
370
|
const { instance } = await api.requestInstance(nickname, cfg2.token);
|
|
371
|
+
if (jsonMode) {
|
|
372
|
+
jsonOut({ instanceId: instance.id, nickname: instance.nickname });
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
339
375
|
console.log(`Requested instance "${instance.nickname}" (${shortId(instance.id)}\u2026)`);
|
|
340
376
|
console.log(`Waiting for admin approval.`);
|
|
341
377
|
}
|
|
@@ -344,12 +380,20 @@ async function cmdInstancesSelect(id, cfg2) {
|
|
|
344
380
|
const instanceId = await resolveInstanceId(id, cfg2);
|
|
345
381
|
cfg2.instanceId = instanceId;
|
|
346
382
|
saveConfig(cfg2);
|
|
383
|
+
if (jsonMode) {
|
|
384
|
+
jsonOut({ instanceId });
|
|
385
|
+
return;
|
|
386
|
+
}
|
|
347
387
|
console.log(`Default instance set to ${instanceId}`);
|
|
348
388
|
}
|
|
349
389
|
async function cmdInstancesJoin(instanceId, cfg2) {
|
|
350
390
|
requireToken(cfg2);
|
|
351
391
|
const api = createApiClient(cfg2.server, cfg2.token);
|
|
352
392
|
await api.requestInstanceAccess(instanceId, cfg2.token);
|
|
393
|
+
if (jsonMode) {
|
|
394
|
+
jsonOut({ instanceId });
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
353
397
|
console.log(`Access requested for instance ${shortId(instanceId)}\u2026`);
|
|
354
398
|
console.log(`An admin will need to approve your request.`);
|
|
355
399
|
console.log(`Once approved, run: autonag instances select ${instanceId}`);
|
|
@@ -359,6 +403,10 @@ async function cmdTimersList(cfg2) {
|
|
|
359
403
|
requireInstance(cfg2);
|
|
360
404
|
const api = createApiClient(cfg2.server, cfg2.token);
|
|
361
405
|
const state = await api.getState(cfg2.instanceId, cfg2.token);
|
|
406
|
+
if (jsonMode) {
|
|
407
|
+
jsonOut({ timers: state.timers, alarm: state.alarm, shush: state.shush });
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
362
410
|
const now = Date.now();
|
|
363
411
|
const timers = [...state.timers].sort((a, b) => a.currentExpiry - b.currentExpiry);
|
|
364
412
|
if (timers.length === 0) {
|
|
@@ -421,6 +469,10 @@ async function cmdAlarm(cfg2) {
|
|
|
421
469
|
requireInstance(cfg2);
|
|
422
470
|
const api = createApiClient(cfg2.server, cfg2.token);
|
|
423
471
|
const state = await api.getState(cfg2.instanceId, cfg2.token);
|
|
472
|
+
if (jsonMode) {
|
|
473
|
+
jsonOut({ alarm: state.alarm, shush: state.shush });
|
|
474
|
+
return;
|
|
475
|
+
}
|
|
424
476
|
printAlarmStatus(state, Date.now());
|
|
425
477
|
}
|
|
426
478
|
async function cmdTimersAdd(name, expiryStr, cfg2, opts) {
|
|
@@ -434,7 +486,11 @@ async function cmdTimersAdd(name, expiryStr, cfg2, opts) {
|
|
|
434
486
|
timezone: opts.tz ?? Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
435
487
|
skipWeekends: opts.skipWeekends ?? false
|
|
436
488
|
} : void 0;
|
|
437
|
-
await api.addTimer(cfg2.instanceId, cfg2.token, name, expiry, recurrence, opts.desc);
|
|
489
|
+
const result = await api.addTimer(cfg2.instanceId, cfg2.token, name, expiry, recurrence, opts.desc);
|
|
490
|
+
if (jsonMode) {
|
|
491
|
+
jsonOut(result);
|
|
492
|
+
return;
|
|
493
|
+
}
|
|
438
494
|
const recurNote = recurrence ? ` (recurs every ${opts.days}d)` : "";
|
|
439
495
|
console.log(`Timer "${name}" added, expires ${fmtDate(expiry)}${recurNote}`);
|
|
440
496
|
}
|
|
@@ -444,16 +500,24 @@ async function cmdTimersRename(id, name, cfg2) {
|
|
|
444
500
|
const timerId = await resolveTimerId(id, cfg2);
|
|
445
501
|
const api = createApiClient(cfg2.server, cfg2.token);
|
|
446
502
|
await api.renameTimer(cfg2.instanceId, cfg2.token, timerId, name);
|
|
503
|
+
if (jsonMode) {
|
|
504
|
+
jsonOut({ timerId, name });
|
|
505
|
+
return;
|
|
506
|
+
}
|
|
447
507
|
console.log(`Timer ${shortId(timerId)}\u2026 renamed to "${name}"`);
|
|
448
508
|
}
|
|
449
|
-
async function
|
|
509
|
+
async function cmdTimersReschedule(id, expiryStr, cfg2) {
|
|
450
510
|
requireToken(cfg2);
|
|
451
511
|
requireInstance(cfg2);
|
|
452
512
|
const timerId = await resolveTimerId(id, cfg2);
|
|
453
513
|
const api = createApiClient(cfg2.server, cfg2.token);
|
|
454
514
|
const expiry = parseExpiry(expiryStr);
|
|
455
515
|
await api.updateExpiry(cfg2.instanceId, cfg2.token, timerId, expiry);
|
|
456
|
-
|
|
516
|
+
if (jsonMode) {
|
|
517
|
+
jsonOut({ timerId, expiry });
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
520
|
+
console.log(`Timer ${shortId(timerId)}\u2026 rescheduled to ${fmtDate(expiry)}`);
|
|
457
521
|
}
|
|
458
522
|
async function cmdTimersComplete(id, reason, cfg2, opts = {}) {
|
|
459
523
|
requireToken(cfg2);
|
|
@@ -466,6 +530,10 @@ async function cmdTimersComplete(id, reason, cfg2, opts = {}) {
|
|
|
466
530
|
await api.batchActions(cfg2.instanceId, cfg2.token, [{ type: "recurTimer", timerId, closeReason: reason, ...opts.at != null ? { occurredAt: opts.at } : {} }]);
|
|
467
531
|
const newState = await api.getState(cfg2.instanceId, cfg2.token);
|
|
468
532
|
const updated = newState.timers.find((t) => t.id === timerId);
|
|
533
|
+
if (jsonMode) {
|
|
534
|
+
jsonOut({ timerId, name: timer.name, action: "recurred", closeReason: reason, nextExpiry: updated?.currentExpiry ?? null });
|
|
535
|
+
return;
|
|
536
|
+
}
|
|
469
537
|
if (updated) {
|
|
470
538
|
console.log(`Timer "${timer.name}" recurred \u2014 next: ${fmtDate(updated.currentExpiry)}`);
|
|
471
539
|
} else {
|
|
@@ -473,6 +541,10 @@ async function cmdTimersComplete(id, reason, cfg2, opts = {}) {
|
|
|
473
541
|
}
|
|
474
542
|
} else {
|
|
475
543
|
await api.batchActions(cfg2.instanceId, cfg2.token, [{ type: "completeTimer", timerId, closeReason: reason, ...opts.at != null ? { occurredAt: opts.at } : {} }]);
|
|
544
|
+
if (jsonMode) {
|
|
545
|
+
jsonOut({ timerId, name: timer?.name ?? null, action: "completed", closeReason: reason });
|
|
546
|
+
return;
|
|
547
|
+
}
|
|
476
548
|
const name = timer?.name ?? shortId(timerId);
|
|
477
549
|
console.log(`Timer "${name}" completed (${reason})`);
|
|
478
550
|
}
|
|
@@ -486,6 +558,10 @@ async function cmdTimersRemove(id, cfg2) {
|
|
|
486
558
|
const timer = state.timers.find((t) => t.id === timerId);
|
|
487
559
|
await api.removeTimer(cfg2.instanceId, cfg2.token, timerId);
|
|
488
560
|
const name = timer?.name ?? shortId(timerId);
|
|
561
|
+
if (jsonMode) {
|
|
562
|
+
jsonOut({ timerId, name });
|
|
563
|
+
return;
|
|
564
|
+
}
|
|
489
565
|
console.log(`Timer "${name}" removed`);
|
|
490
566
|
}
|
|
491
567
|
async function cmdTimersDescribe(id, text, cfg2) {
|
|
@@ -494,6 +570,10 @@ async function cmdTimersDescribe(id, text, cfg2) {
|
|
|
494
570
|
const timerId = await resolveTimerId(id, cfg2);
|
|
495
571
|
const api = createApiClient(cfg2.server, cfg2.token);
|
|
496
572
|
await api.batchActions(cfg2.instanceId, cfg2.token, [{ type: "updateDescription", timerId, description: text }]);
|
|
573
|
+
if (jsonMode) {
|
|
574
|
+
jsonOut({ timerId });
|
|
575
|
+
return;
|
|
576
|
+
}
|
|
497
577
|
console.log(`Timer ${shortId(timerId)}\u2026 description updated`);
|
|
498
578
|
}
|
|
499
579
|
async function cmdTimersGetDescription(id, cfg2) {
|
|
@@ -507,6 +587,10 @@ async function cmdTimersGetDescription(id, cfg2) {
|
|
|
507
587
|
console.error(`Timer not found: ${timerId}`);
|
|
508
588
|
process.exit(1);
|
|
509
589
|
}
|
|
590
|
+
if (jsonMode) {
|
|
591
|
+
jsonOut({ timerId, description: timer.description ?? null });
|
|
592
|
+
return;
|
|
593
|
+
}
|
|
510
594
|
if (!timer.description) {
|
|
511
595
|
console.log("(no description)");
|
|
512
596
|
return;
|
|
@@ -525,6 +609,10 @@ async function cmdTimersRecurrenceSet(id, days, cfg2, opts) {
|
|
|
525
609
|
skipWeekends: opts.skipWeekends ?? false
|
|
526
610
|
};
|
|
527
611
|
await api.batchActions(cfg2.instanceId, cfg2.token, [{ type: "updateRecurrence", timerId, recurrence }]);
|
|
612
|
+
if (jsonMode) {
|
|
613
|
+
jsonOut({ timerId, recurrence });
|
|
614
|
+
return;
|
|
615
|
+
}
|
|
528
616
|
console.log(`Timer ${shortId(timerId)}\u2026 recurrence set to every ${days}d at ${recurrence.anchorTime} (${recurrence.timezone})`);
|
|
529
617
|
}
|
|
530
618
|
async function cmdTimersRecurrenceRemove(id, cfg2) {
|
|
@@ -533,6 +621,10 @@ async function cmdTimersRecurrenceRemove(id, cfg2) {
|
|
|
533
621
|
const timerId = await resolveTimerId(id, cfg2);
|
|
534
622
|
const api = createApiClient(cfg2.server, cfg2.token);
|
|
535
623
|
await api.batchActions(cfg2.instanceId, cfg2.token, [{ type: "removeRecurrence", timerId }]);
|
|
624
|
+
if (jsonMode) {
|
|
625
|
+
jsonOut({ timerId });
|
|
626
|
+
return;
|
|
627
|
+
}
|
|
536
628
|
console.log(`Timer ${shortId(timerId)}\u2026 recurrence removed`);
|
|
537
629
|
}
|
|
538
630
|
async function cmdTimersHistory(id, cfg2) {
|
|
@@ -551,6 +643,10 @@ async function cmdTimersHistory(id, cfg2) {
|
|
|
551
643
|
}
|
|
552
644
|
cursor = nextCursor;
|
|
553
645
|
}
|
|
646
|
+
if (jsonMode) {
|
|
647
|
+
jsonOut(allEntries);
|
|
648
|
+
return;
|
|
649
|
+
}
|
|
554
650
|
if (allEntries.length === 0) {
|
|
555
651
|
console.log("No history yet.");
|
|
556
652
|
return;
|
|
@@ -574,6 +670,10 @@ async function cmdTimersLog(id, reason, at, cfg2) {
|
|
|
574
670
|
process.exit(1);
|
|
575
671
|
}
|
|
576
672
|
await api.batchActions(cfg2.instanceId, cfg2.token, [{ type: "logCompletion", timerId, closeReason: reason, occurredAt: at }]);
|
|
673
|
+
if (jsonMode) {
|
|
674
|
+
jsonOut({ timerId, closeReason: reason, occurredAt: at });
|
|
675
|
+
return;
|
|
676
|
+
}
|
|
577
677
|
console.log(`Logged "${reason}" for "${timer.name}" at ${fmtDate(at)}`);
|
|
578
678
|
}
|
|
579
679
|
async function cmdShush(durationStr, cfg2) {
|
|
@@ -582,6 +682,10 @@ async function cmdShush(durationStr, cfg2) {
|
|
|
582
682
|
const api = createApiClient(cfg2.server, cfg2.token);
|
|
583
683
|
const expiry = durationStr ? parseExpiry(durationStr) : Date.now() + 30 * 60 * 1e3;
|
|
584
684
|
await api.setShush(cfg2.instanceId, cfg2.token, expiry);
|
|
685
|
+
if (jsonMode) {
|
|
686
|
+
jsonOut({ expiry });
|
|
687
|
+
return;
|
|
688
|
+
}
|
|
585
689
|
console.log(`Alarm silenced until ${fmtDate(expiry)}`);
|
|
586
690
|
}
|
|
587
691
|
async function cmdUnshush(cfg2) {
|
|
@@ -589,6 +693,10 @@ async function cmdUnshush(cfg2) {
|
|
|
589
693
|
requireInstance(cfg2);
|
|
590
694
|
const api = createApiClient(cfg2.server, cfg2.token);
|
|
591
695
|
await api.clearShush(cfg2.instanceId, cfg2.token);
|
|
696
|
+
if (jsonMode) {
|
|
697
|
+
jsonOut({ ok: true });
|
|
698
|
+
return;
|
|
699
|
+
}
|
|
592
700
|
console.log(`Shush cleared`);
|
|
593
701
|
}
|
|
594
702
|
async function cmdEventsList(fromSeq, cfg2) {
|
|
@@ -596,6 +704,10 @@ async function cmdEventsList(fromSeq, cfg2) {
|
|
|
596
704
|
requireInstance(cfg2);
|
|
597
705
|
const api = createApiClient(cfg2.server, cfg2.token);
|
|
598
706
|
const { events } = await api.listEvents(cfg2.instanceId, cfg2.token, { from: fromSeq });
|
|
707
|
+
if (jsonMode) {
|
|
708
|
+
jsonOut(events);
|
|
709
|
+
return;
|
|
710
|
+
}
|
|
599
711
|
if (events.length === 0) {
|
|
600
712
|
console.log("No events.");
|
|
601
713
|
return;
|
|
@@ -613,6 +725,10 @@ async function cmdEventsSkip(id, cfg2) {
|
|
|
613
725
|
const eventId = await resolveEventId(id, cfg2);
|
|
614
726
|
const api = createApiClient(cfg2.server, cfg2.token);
|
|
615
727
|
await api.skipEvent(cfg2.instanceId, cfg2.token, eventId);
|
|
728
|
+
if (jsonMode) {
|
|
729
|
+
jsonOut({ eventId });
|
|
730
|
+
return;
|
|
731
|
+
}
|
|
616
732
|
console.log(`Event ${shortId(eventId)}\u2026 skipped`);
|
|
617
733
|
}
|
|
618
734
|
async function cmdEventsUnskip(id, cfg2) {
|
|
@@ -621,6 +737,10 @@ async function cmdEventsUnskip(id, cfg2) {
|
|
|
621
737
|
const eventId = await resolveEventId(id, cfg2);
|
|
622
738
|
const api = createApiClient(cfg2.server, cfg2.token);
|
|
623
739
|
await api.unskipEvent(cfg2.instanceId, cfg2.token, eventId);
|
|
740
|
+
if (jsonMode) {
|
|
741
|
+
jsonOut({ eventId });
|
|
742
|
+
return;
|
|
743
|
+
}
|
|
624
744
|
console.log(`Event ${shortId(eventId)}\u2026 unskipped`);
|
|
625
745
|
}
|
|
626
746
|
async function cmdTimersView(id, cfg2) {
|
|
@@ -634,6 +754,11 @@ async function cmdTimersView(id, cfg2) {
|
|
|
634
754
|
console.error(`Timer not found: ${timerId}`);
|
|
635
755
|
process.exit(1);
|
|
636
756
|
}
|
|
757
|
+
const { comments } = await api.listComments(cfg2.instanceId, cfg2.token, timerId);
|
|
758
|
+
if (jsonMode) {
|
|
759
|
+
jsonOut({ ...timer, comments });
|
|
760
|
+
return;
|
|
761
|
+
}
|
|
637
762
|
const now = Date.now();
|
|
638
763
|
const remaining = timer.currentExpiry - now;
|
|
639
764
|
const expiryStr = `${fmtDate(timer.currentExpiry)} (${remaining >= 0 ? "in " : ""}${fmtCountdown(remaining)})`;
|
|
@@ -654,7 +779,6 @@ async function cmdTimersView(id, cfg2) {
|
|
|
654
779
|
const wknd = r.skipWeekends ? ", skip weekends" : "";
|
|
655
780
|
console.log(`Recurrence: every ${r.periodDays}d at ${r.anchorTime} ${r.timezone}${wknd}`);
|
|
656
781
|
}
|
|
657
|
-
const { comments } = await api.listComments(cfg2.instanceId, cfg2.token, timerId);
|
|
658
782
|
if (comments.length > 0) {
|
|
659
783
|
const PREVIEW = 5;
|
|
660
784
|
const shown = comments.slice(-PREVIEW);
|
|
@@ -673,6 +797,11 @@ async function cmdCommentsList(id, cfg2, opts = {}) {
|
|
|
673
797
|
const timerId = await resolveTimerId(id, cfg2);
|
|
674
798
|
const api = createApiClient(cfg2.server, cfg2.token);
|
|
675
799
|
const { comments } = await api.listComments(cfg2.instanceId, cfg2.token, timerId);
|
|
800
|
+
if (jsonMode) {
|
|
801
|
+
const shown2 = opts.limit != null ? comments.slice(-opts.limit) : comments;
|
|
802
|
+
jsonOut(shown2);
|
|
803
|
+
return;
|
|
804
|
+
}
|
|
676
805
|
if (comments.length === 0) {
|
|
677
806
|
console.log("No comments.");
|
|
678
807
|
return;
|
|
@@ -690,6 +819,10 @@ async function cmdCommentsAdd(id, text, cfg2) {
|
|
|
690
819
|
const timerId = await resolveTimerId(id, cfg2);
|
|
691
820
|
const api = createApiClient(cfg2.server, cfg2.token);
|
|
692
821
|
await api.addComment(cfg2.instanceId, cfg2.token, timerId, text);
|
|
822
|
+
if (jsonMode) {
|
|
823
|
+
jsonOut({ timerId });
|
|
824
|
+
return;
|
|
825
|
+
}
|
|
693
826
|
console.log(`Comment added`);
|
|
694
827
|
}
|
|
695
828
|
function cmdTutorial() {
|
|
@@ -820,12 +953,12 @@ autonag timers recurrence remove e5f6
|
|
|
820
953
|
autonag timers complete e5f6 done
|
|
821
954
|
\`\`\`
|
|
822
955
|
|
|
823
|
-
##
|
|
956
|
+
## Rescheduling
|
|
824
957
|
|
|
825
958
|
Push a timer's deadline out:
|
|
826
959
|
|
|
827
960
|
\`\`\`
|
|
828
|
-
autonag timers
|
|
961
|
+
autonag timers reschedule e5f6 3d
|
|
829
962
|
\`\`\`
|
|
830
963
|
|
|
831
964
|
## Silencing the alarm
|
|
@@ -898,7 +1031,9 @@ Options:
|
|
|
898
1031
|
-s, --server <url> Server URL (default: http://localhost:3000)
|
|
899
1032
|
-i, --instance <id> Instance ID (overrides saved default)
|
|
900
1033
|
-c, --config <path> Config file (default: ~/.config/autonag/client.json5)
|
|
1034
|
+
--json Output JSON instead of formatted text
|
|
901
1035
|
|
|
1036
|
+
version Show version
|
|
902
1037
|
tutorial Walk through setup and daily workflow
|
|
903
1038
|
|
|
904
1039
|
Auth:
|
|
@@ -915,7 +1050,7 @@ Timers:
|
|
|
915
1050
|
timers list
|
|
916
1051
|
timers add <name> <expiry> [--desc <text>] [--days <n>] [--anchor <HH:MM>] [--tz <tz>] [--skip-weekends]
|
|
917
1052
|
timers rename <id> <name>
|
|
918
|
-
timers
|
|
1053
|
+
timers reschedule <id> <expiry> Update expiry: 1d, 30m, 2h, 90s | 2026-05-01T09:00:00Z | unix-ms:<n>
|
|
919
1054
|
timers pass <id> [--at <datetime>] Complete with reason "pass" (preferred)
|
|
920
1055
|
timers fail <id> [--at <datetime>] Complete with reason "fail" (preferred)
|
|
921
1056
|
timers complete <id> <reason> [--at <datetime>] Complete with a custom reason
|
|
@@ -987,6 +1122,7 @@ var rawArgs = process.argv.slice(2);
|
|
|
987
1122
|
var topArgs = [];
|
|
988
1123
|
var serverOverride;
|
|
989
1124
|
var instanceOverride;
|
|
1125
|
+
var jsonMode = false;
|
|
990
1126
|
for (let i = 0; i < rawArgs.length; i++) {
|
|
991
1127
|
const a = rawArgs[i];
|
|
992
1128
|
if (a === "-h" || a === "--help") {
|
|
@@ -1010,6 +1146,8 @@ for (let i = 0; i < rawArgs.length; i++) {
|
|
|
1010
1146
|
process.exit(1);
|
|
1011
1147
|
}
|
|
1012
1148
|
CONFIG_PATH = rawArgs[++i];
|
|
1149
|
+
} else if (a === "--json") {
|
|
1150
|
+
jsonMode = true;
|
|
1013
1151
|
} else topArgs.push(a);
|
|
1014
1152
|
}
|
|
1015
1153
|
var cfg = loadConfig();
|
|
@@ -1020,6 +1158,12 @@ try {
|
|
|
1020
1158
|
if (!cmd || cmd === "help") {
|
|
1021
1159
|
parseFlags(rest, {});
|
|
1022
1160
|
console.log(HELP);
|
|
1161
|
+
} else if (cmd === "version") {
|
|
1162
|
+
if (jsonMode) {
|
|
1163
|
+
jsonOut({ version: VERSION });
|
|
1164
|
+
} else {
|
|
1165
|
+
console.log(VERSION);
|
|
1166
|
+
}
|
|
1023
1167
|
} else if (cmd === "tutorial") {
|
|
1024
1168
|
parseFlags(rest, {});
|
|
1025
1169
|
cmdTutorial();
|
|
@@ -1092,13 +1236,13 @@ try {
|
|
|
1092
1236
|
process.exit(1);
|
|
1093
1237
|
}
|
|
1094
1238
|
await cmdTimersRename(positional[0], positional[1], cfg);
|
|
1095
|
-
} else if (sub === "snooze") {
|
|
1239
|
+
} else if (sub === "reschedule" || sub === "snooze") {
|
|
1096
1240
|
const { positional } = parseFlags(rest, {});
|
|
1097
1241
|
if (!positional[0] || !positional[1]) {
|
|
1098
|
-
console.error("Usage: autonag timers
|
|
1242
|
+
console.error("Usage: autonag timers reschedule <id> <expiry>");
|
|
1099
1243
|
process.exit(1);
|
|
1100
1244
|
}
|
|
1101
|
-
await
|
|
1245
|
+
await cmdTimersReschedule(positional[0], positional[1], cfg);
|
|
1102
1246
|
} else if (sub === "pass") {
|
|
1103
1247
|
const { positional, flags } = parseFlags(rest, { at: "string" });
|
|
1104
1248
|
if (!positional[0]) {
|
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, 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"]}
|
|
1
|
+
{"version":3,"sources":["../cli.ts","../apiClient.ts"],"sourcesContent":["import { join, dirname } from \"path\";\nimport { fileURLToPath } from \"url\";\nimport { homedir } from \"os\";\nimport { mkdirSync, existsSync, readFileSync, writeFileSync } from \"fs\";\nimport JSON5 from \"json5\";\nimport { createApiClient, ApiError } from \"./apiClient\";\n\nconst VERSION: string = JSON.parse(readFileSync(join(dirname(fileURLToPath(import.meta.url)), \"..\", \"package.json\"), \"utf8\")).version;\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\nfunction jsonOut(data: unknown): void {\n console.log(JSON.stringify(data, null, 2));\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 if (jsonMode) { jsonOut({ deviceId: device.id, nickname, token, configPath: CONFIG_PATH }); return; }\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 if (jsonMode) {\n const result: Record<string, unknown> = { server: cfg.server, configPath: CONFIG_PATH, instanceId: cfg.instanceId ?? null };\n if (!cfg.token) { result.auth = null; jsonOut(result); return; }\n const api = createApiClient(cfg.server, cfg.token);\n try {\n const { device: d } = await api.getMe(cfg.token);\n result.auth = { nickname: d.nickname, deviceId: d.id, approved: !!d.approvedAt, approvedAt: d.approvedAt ?? null };\n } catch (e) {\n if (e instanceof ApiError && e.status === 401) { result.auth = { error: \"invalid_token\" }; }\n else throw e;\n }\n jsonOut(result);\n return;\n }\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 (jsonMode) {\n jsonOut(instances.map(i => ({ id: i.id, nickname: i.nickname, approved: !!i.approvedAt, approvedAt: i.approvedAt ?? null, selected: i.id === cfg.instanceId })));\n return;\n }\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 if (jsonMode) { jsonOut({ instanceId: instance.id, nickname: instance.nickname }); return; }\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 if (jsonMode) { jsonOut({ instanceId }); return; }\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 if (jsonMode) { jsonOut({ instanceId }); return; }\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 if (jsonMode) { jsonOut({ timers: state.timers, alarm: state.alarm, shush: state.shush }); return; }\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 if (jsonMode) { jsonOut({ alarm: state.alarm, shush: state.shush }); return; }\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 const result = await api.addTimer(cfg.instanceId, cfg.token, name, expiry, recurrence, opts.desc);\n if (jsonMode) { jsonOut(result); return; }\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 if (jsonMode) { jsonOut({ timerId, name }); return; }\n console.log(`Timer ${shortId(timerId)}… renamed to \"${name}\"`);\n}\n\nasync function cmdTimersReschedule(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 if (jsonMode) { jsonOut({ timerId, expiry }); return; }\n console.log(`Timer ${shortId(timerId)}… rescheduled to ${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 (jsonMode) { jsonOut({ timerId, name: timer.name, action: \"recurred\", closeReason: reason, nextExpiry: updated?.currentExpiry ?? null }); return; }\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 if (jsonMode) { jsonOut({ timerId, name: timer?.name ?? null, action: \"completed\", closeReason: reason }); return; }\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 if (jsonMode) { jsonOut({ timerId, name }); return; }\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 if (jsonMode) { jsonOut({ timerId }); return; }\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 (jsonMode) { jsonOut({ timerId, description: timer.description ?? null }); return; }\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 if (jsonMode) { jsonOut({ timerId, recurrence }); return; }\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 if (jsonMode) { jsonOut({ timerId }); return; }\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 (jsonMode) { jsonOut(allEntries); return; }\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 if (jsonMode) { jsonOut({ timerId, closeReason: reason, occurredAt: at }); return; }\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 if (jsonMode) { jsonOut({ expiry }); return; }\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 if (jsonMode) { jsonOut({ ok: true }); return; }\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 (jsonMode) { jsonOut(events); return; }\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 if (jsonMode) { jsonOut({ eventId }); return; }\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 if (jsonMode) { jsonOut({ eventId }); return; }\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 { comments } = await api.listComments(cfg.instanceId, cfg.token, timerId);\n\n if (jsonMode) { jsonOut({ ...timer, comments }); return; }\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 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 (jsonMode) {\n const shown = opts.limit != null ? comments.slice(-opts.limit) : comments;\n jsonOut(shown);\n return;\n }\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 if (jsonMode) { jsonOut({ timerId }); return; }\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## Rescheduling\n\nPush a timer's deadline out:\n\n\\`\\`\\`\nautonag timers reschedule 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 --json Output JSON instead of formatted text\n\n version Show version\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 reschedule <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;\nlet jsonMode = false;\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 if (a === \"--json\") {\n jsonMode = true;\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 === \"version\") {\n if (jsonMode) { jsonOut({ version: VERSION }); } else { console.log(VERSION); }\n\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 === \"reschedule\" || sub === \"snooze\") {\n const { positional } = parseFlags(rest, {});\n if (!positional[0] || !positional[1]) { console.error(\"Usage: autonag timers reschedule <id> <expiry>\"); process.exit(1); }\n await cmdTimersReschedule(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","api","shown"]}
|