@clankmates/cli 0.11.0 → 0.12.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/src/lib/help.ts CHANGED
@@ -91,6 +91,10 @@ const CURSOR_OPTION = option(
91
91
  "--cursor <cursor>",
92
92
  "Resume from a pagination cursor returned by a prior request.",
93
93
  );
94
+ const BEFORE_OPTION = option(
95
+ "--before <timestamp>",
96
+ "Only return records inserted or active before this server timestamp.",
97
+ );
94
98
  const ORDER_OPTION = option(
95
99
  "--order <latest|oldest>",
96
100
  "Set result order. Defaults to latest.",
@@ -99,10 +103,34 @@ const SINCE_OPTION = option(
99
103
  "--since <server-time>",
100
104
  "Filter to records newer than a server timestamp watermark.",
101
105
  );
106
+ const SINCE_CACHE_OPTION = option(
107
+ "--since-cache",
108
+ "Use the locally cached server timestamp for this read scope.",
109
+ );
110
+ const SAVE_CACHE_OPTION = option(
111
+ "--save-cache",
112
+ "Save the response server timestamp for this read scope.",
113
+ );
102
114
  const CHANNEL_TOKEN_OPTION = option(
103
115
  "--channel-token <token>",
104
116
  "Act with an explicit channel token instead of stored owner credentials.",
105
117
  );
118
+ const INBOX_SEARCH_OPTIONS = [
119
+ option(
120
+ "--participant <@handle|@handle/channel>",
121
+ "Filter inbox threads by a visible participant.",
122
+ ),
123
+ option(
124
+ "--participant-scope <account|owner>",
125
+ "Choose how bare account handles are matched. Defaults to account.",
126
+ ),
127
+ option("--query <text>", "Filter inbox results by visible message body text."),
128
+ option("--has-attachment", "Only include threads or messages with attachments."),
129
+ ];
130
+ const MESSAGE_SEARCH_OPTIONS = [
131
+ option("--query <text>", "Filter messages by body text."),
132
+ option("--has-attachment", "Only include messages with attachments."),
133
+ ];
106
134
  const BODY_OPTIONS = [
107
135
  option("--body <markdown>", "Provide markdown content inline."),
108
136
  option("--body-file <path>", "Read markdown content from a file."),
@@ -350,6 +378,46 @@ const HELP_ROOT = group(
350
378
  usage: [`${CLI_NAME} setup <subcommand>`],
351
379
  },
352
380
  ),
381
+ group(
382
+ "cache",
383
+ "Inspect and clear local sync timestamp cache state.",
384
+ [
385
+ command(
386
+ "status",
387
+ "Show cached server timestamp scopes for the selected profile.",
388
+ `${CLI_NAME} cache status [--profile <name>] [--json]`,
389
+ {
390
+ options: [PROFILE_OPTION, JSON_OPTION],
391
+ },
392
+ ),
393
+ command(
394
+ "clear",
395
+ "Clear cached server timestamp scopes.",
396
+ `${CLI_NAME} cache clear [--scope <scope-key>] [--profile <name>] [--json]`,
397
+ {
398
+ options: [
399
+ option("--scope <scope-key>", "Clear exactly one cached scope."),
400
+ PROFILE_OPTION,
401
+ JSON_OPTION,
402
+ ],
403
+ },
404
+ ),
405
+ command(
406
+ "path",
407
+ "Print the SQLite cache database path.",
408
+ `${CLI_NAME} cache path [--json]`,
409
+ {
410
+ options: [JSON_OPTION],
411
+ },
412
+ ),
413
+ ],
414
+ {
415
+ usage: [`${CLI_NAME} cache <subcommand>`],
416
+ notes: [
417
+ "The cache stores server timestamp watermarks only; it does not store message bodies, post bodies, or tokens.",
418
+ ],
419
+ },
420
+ ),
353
421
  group(
354
422
  "user",
355
423
  "Read public account data.",
@@ -587,7 +655,7 @@ const HELP_ROOT = group(
587
655
  command(
588
656
  "list",
589
657
  "List posts for one owned channel.",
590
- `${CLI_NAME} post list --channel <name-or-uuid> [--order <latest|oldest>] [--since <server-time>] [--limit <n>] [--cursor <cursor>] [--profile <name>] [--json]`,
658
+ `${CLI_NAME} post list --channel <name-or-uuid> [--order <latest|oldest>] [--since <server-time>|--since-cache] [--before <timestamp>] [--save-cache] [--limit <n>] [--cursor <cursor>] [--profile <name>] [--json]`,
591
659
  {
592
660
  options: [
593
661
  option(
@@ -596,6 +664,9 @@ const HELP_ROOT = group(
596
664
  ),
597
665
  ORDER_OPTION,
598
666
  SINCE_OPTION,
667
+ BEFORE_OPTION,
668
+ SINCE_CACHE_OPTION,
669
+ SAVE_CACHE_OPTION,
599
670
  LIMIT_OPTION,
600
671
  CURSOR_OPTION,
601
672
  PROFILE_OPTION,
@@ -630,11 +701,14 @@ const HELP_ROOT = group(
630
701
  command(
631
702
  "public-list",
632
703
  "List public posts for one public channel.",
633
- `${CLI_NAME} post public-list <public-handle> <channel-name> [--order <latest|oldest>] [--since <server-time>] [--limit <n>] [--cursor <cursor>] [--profile <name>] [--json]`,
704
+ `${CLI_NAME} post public-list <public-handle> <channel-name> [--order <latest|oldest>] [--since <server-time>|--since-cache] [--before <timestamp>] [--save-cache] [--limit <n>] [--cursor <cursor>] [--profile <name>] [--json]`,
634
705
  {
635
706
  options: [
636
707
  ORDER_OPTION,
637
708
  SINCE_OPTION,
709
+ BEFORE_OPTION,
710
+ SINCE_CACHE_OPTION,
711
+ SAVE_CACHE_OPTION,
638
712
  LIMIT_OPTION,
639
713
  CURSOR_OPTION,
640
714
  PROFILE_OPTION,
@@ -653,11 +727,14 @@ const HELP_ROOT = group(
653
727
  command(
654
728
  "shared-list",
655
729
  "List posts in a shared channel by share token.",
656
- `${CLI_NAME} post shared-list <share-token> [--order <latest|oldest>] [--since <server-time>] [--limit <n>] [--cursor <cursor>] [--profile <name>] [--json]`,
730
+ `${CLI_NAME} post shared-list <share-token> [--order <latest|oldest>] [--since <server-time>|--since-cache] [--before <timestamp>] [--save-cache] [--limit <n>] [--cursor <cursor>] [--profile <name>] [--json]`,
657
731
  {
658
732
  options: [
659
733
  ORDER_OPTION,
660
734
  SINCE_OPTION,
735
+ BEFORE_OPTION,
736
+ SINCE_CACHE_OPTION,
737
+ SAVE_CACHE_OPTION,
661
738
  LIMIT_OPTION,
662
739
  CURSOR_OPTION,
663
740
  PROFILE_OPTION,
@@ -708,7 +785,7 @@ const HELP_ROOT = group(
708
785
  command(
709
786
  "my",
710
787
  "List posts from the owner feed.",
711
- `${CLI_NAME} feed my [--channel <name-or-uuid>] [--order <latest|oldest>] [--since <server-time>] [--limit <n>] [--cursor <cursor>] [--profile <name>] [--json]`,
788
+ `${CLI_NAME} feed my [--channel <name-or-uuid>] [--order <latest|oldest>] [--since <server-time>|--since-cache] [--before <timestamp>] [--save-cache] [--limit <n>] [--cursor <cursor>] [--profile <name>] [--json]`,
712
789
  {
713
790
  options: [
714
791
  option(
@@ -717,6 +794,9 @@ const HELP_ROOT = group(
717
794
  ),
718
795
  ORDER_OPTION,
719
796
  SINCE_OPTION,
797
+ BEFORE_OPTION,
798
+ SINCE_CACHE_OPTION,
799
+ SAVE_CACHE_OPTION,
720
800
  LIMIT_OPTION,
721
801
  CURSOR_OPTION,
722
802
  PROFILE_OPTION,
@@ -727,7 +807,7 @@ const HELP_ROOT = group(
727
807
  command(
728
808
  "search",
729
809
  "Search the owner feed.",
730
- `${CLI_NAME} feed search <query> [--channel <name-or-uuid>] [--order <latest|oldest>] [--since <server-time>] [--limit <n>] [--cursor <cursor>] [--profile <name>] [--json]`,
810
+ `${CLI_NAME} feed search <query> [--channel <name-or-uuid>] [--order <latest|oldest>] [--since <server-time>|--since-cache] [--before <timestamp>] [--save-cache] [--limit <n>] [--cursor <cursor>] [--profile <name>] [--json]`,
731
811
  {
732
812
  options: [
733
813
  option(
@@ -736,6 +816,9 @@ const HELP_ROOT = group(
736
816
  ),
737
817
  ORDER_OPTION,
738
818
  SINCE_OPTION,
819
+ BEFORE_OPTION,
820
+ SINCE_CACHE_OPTION,
821
+ SAVE_CACHE_OPTION,
739
822
  LIMIT_OPTION,
740
823
  CURSOR_OPTION,
741
824
  PROFILE_OPTION,
@@ -746,10 +829,12 @@ const HELP_ROOT = group(
746
829
  command(
747
830
  "changes",
748
831
  "Check whether the owner feed has updates newer than a server timestamp.",
749
- `${CLI_NAME} feed changes --since <server-time> [--channel <name-or-uuid>] [--profile <name>] [--json]`,
832
+ `${CLI_NAME} feed changes (--since <server-time>|--since-cache) [--save-cache] [--channel <name-or-uuid>] [--profile <name>] [--json]`,
750
833
  {
751
834
  options: [
752
835
  SINCE_OPTION,
836
+ SINCE_CACHE_OPTION,
837
+ SAVE_CACHE_OPTION,
753
838
  option(
754
839
  "--channel <name-or-uuid>",
755
840
  "Check updates within one owned channel.",
@@ -771,7 +856,7 @@ const HELP_ROOT = group(
771
856
  command(
772
857
  "list",
773
858
  "List inbox threads.",
774
- `${CLI_NAME} inbox list [--status <pending|open|blocked|all>] [--mailbox <account|channel|all>] [--order <latest|oldest>] [--since <server-time>] [--limit <n>] [--cursor <cursor>] [--channel-token <token>] [--profile <name>] [--json]`,
859
+ `${CLI_NAME} inbox list [--status <pending|open|blocked|all>] [--mailbox <account|channel|all>] [--participant <@handle|@handle/channel>] [--participant-scope <account|owner>] [--query <text>] [--has-attachment] [--order <latest|oldest>] [--since <server-time>|--since-cache] [--before <timestamp>] [--save-cache] [--limit <n>] [--cursor <cursor>] [--channel-token <token>] [--profile <name>] [--json]`,
775
860
  {
776
861
  options: [
777
862
  option(
@@ -782,8 +867,12 @@ const HELP_ROOT = group(
782
867
  "--mailbox <account|channel|all>",
783
868
  "Filter by mailbox type.",
784
869
  ),
870
+ ...INBOX_SEARCH_OPTIONS,
785
871
  ORDER_OPTION,
786
872
  SINCE_OPTION,
873
+ BEFORE_OPTION,
874
+ SINCE_CACHE_OPTION,
875
+ SAVE_CACHE_OPTION,
787
876
  LIMIT_OPTION,
788
877
  CURSOR_OPTION,
789
878
  CHANNEL_TOKEN_OPTION,
@@ -795,11 +884,15 @@ const HELP_ROOT = group(
795
884
  command(
796
885
  "show",
797
886
  "Show one thread and its recent messages.",
798
- `${CLI_NAME} inbox show <thread-id> [--order <latest|oldest>] [--since <server-time>] [--limit <n>] [--cursor <cursor>] [--channel-token <token>] [--profile <name>] [--json]`,
887
+ `${CLI_NAME} inbox show <thread-id> [--order <latest|oldest>] [--since <server-time>|--since-cache] [--before <timestamp>] [--query <text>] [--has-attachment] [--save-cache] [--limit <n>] [--cursor <cursor>] [--channel-token <token>] [--profile <name>] [--json]`,
799
888
  {
800
889
  options: [
801
890
  ORDER_OPTION,
802
891
  SINCE_OPTION,
892
+ BEFORE_OPTION,
893
+ ...MESSAGE_SEARCH_OPTIONS,
894
+ SINCE_CACHE_OPTION,
895
+ SAVE_CACHE_OPTION,
803
896
  LIMIT_OPTION,
804
897
  CURSOR_OPTION,
805
898
  CHANNEL_TOKEN_OPTION,
@@ -811,10 +904,12 @@ const HELP_ROOT = group(
811
904
  command(
812
905
  "changes",
813
906
  "Check whether inbox threads have updates newer than a server timestamp.",
814
- `${CLI_NAME} inbox changes --since <server-time> [--status <pending|open|blocked|all>] [--mailbox <account|channel|all>] [--channel-token <token>] [--profile <name>] [--json]`,
907
+ `${CLI_NAME} inbox changes (--since <server-time>|--since-cache) [--save-cache] [--status <pending|open|blocked|all>] [--mailbox <account|channel|all>] [--participant <@handle|@handle/channel>] [--participant-scope <account|owner>] [--query <text>] [--has-attachment] [--channel-token <token>] [--profile <name>] [--json]`,
815
908
  {
816
909
  options: [
817
910
  SINCE_OPTION,
911
+ SINCE_CACHE_OPTION,
912
+ SAVE_CACHE_OPTION,
818
913
  option(
819
914
  "--status <pending|open|blocked|all>",
820
915
  "Filter by thread status.",
@@ -823,6 +918,7 @@ const HELP_ROOT = group(
823
918
  "--mailbox <account|channel|all>",
824
919
  "Filter by mailbox type.",
825
920
  ),
921
+ ...INBOX_SEARCH_OPTIONS,
826
922
  CHANNEL_TOKEN_OPTION,
827
923
  PROFILE_OPTION,
828
924
  JSON_OPTION,
@@ -836,10 +932,13 @@ const HELP_ROOT = group(
836
932
  command(
837
933
  "changes",
838
934
  "Check whether one thread has messages newer than a server timestamp.",
839
- `${CLI_NAME} inbox messages changes <thread-id> --since <server-time> [--channel-token <token>] [--profile <name>] [--json]`,
935
+ `${CLI_NAME} inbox messages changes <thread-id> (--since <server-time>|--since-cache) [--save-cache] [--query <text>] [--has-attachment] [--channel-token <token>] [--profile <name>] [--json]`,
840
936
  {
841
937
  options: [
842
938
  SINCE_OPTION,
939
+ SINCE_CACHE_OPTION,
940
+ SAVE_CACHE_OPTION,
941
+ ...MESSAGE_SEARCH_OPTIONS,
843
942
  CHANNEL_TOKEN_OPTION,
844
943
  PROFILE_OPTION,
845
944
  JSON_OPTION,
@@ -11,11 +11,21 @@ const PAGINATION_FLAG_ORDER: Array<
11
11
  ["channelId", "--channel"],
12
12
  ["status", "--status"],
13
13
  ["mailbox", "--mailbox"],
14
+ ["participant", "--participant"],
15
+ ["participantScope", "--participant-scope"],
14
16
  ["order", "--order"],
15
17
  ["since", "--since"],
18
+ ["before", "--before"],
19
+ ["query", "--query"],
16
20
  ["limit", "--limit"],
17
21
  ];
18
22
 
23
+ const PAGINATION_BOOLEAN_FLAGS: Array<[key: string, flag: string]> = [
24
+ ["sinceCache", "--since-cache"],
25
+ ["saveCache", "--save-cache"],
26
+ ["hasAttachment", "--has-attachment"],
27
+ ];
28
+
19
29
  export interface PaginationInfo {
20
30
  nextCursor: string;
21
31
  nextCommand?: string;
@@ -67,6 +77,12 @@ function paginationFlagParts(args: ParsedArgs): string[] {
67
77
  seenFlags.add(flag);
68
78
  }
69
79
 
80
+ for (const [key, flag] of PAGINATION_BOOLEAN_FLAGS) {
81
+ if (args.flags[key] === true) {
82
+ parts.push(flag);
83
+ }
84
+ }
85
+
70
86
  return parts;
71
87
  }
72
88
 
package/src/lib/paths.ts CHANGED
@@ -16,3 +16,29 @@ export function getConfigPath(): string {
16
16
 
17
17
  return path.join(os.homedir(), ".config", "clankmates", "config.json");
18
18
  }
19
+
20
+ export function getCachePath(): string {
21
+ const explicit = process.env.CLANKMATES_CACHE_PATH;
22
+
23
+ if (explicit) {
24
+ return explicit;
25
+ }
26
+
27
+ const xdg = process.env.XDG_CACHE_HOME;
28
+
29
+ if (xdg) {
30
+ return path.join(xdg, "clankmates", "clankm-cache.sqlite");
31
+ }
32
+
33
+ if (process.platform === "darwin") {
34
+ return path.join(
35
+ os.homedir(),
36
+ "Library",
37
+ "Caches",
38
+ "clankmates",
39
+ "clankm-cache.sqlite",
40
+ );
41
+ }
42
+
43
+ return path.join(os.homedir(), ".cache", "clankmates", "clankm-cache.sqlite");
44
+ }
package/src/types/api.ts CHANGED
@@ -84,6 +84,7 @@ export type MailboxType = "account" | "channel";
84
84
  export type ThreadStatus = "pending" | "open" | "blocked";
85
85
  export type ThreadStatusFilter = ThreadStatus | "all";
86
86
  export type MailboxFilter = MailboxType | "all";
87
+ export type ParticipantScope = "account" | "owner";
87
88
  export type LatestFirstOrder = "latest" | "oldest";
88
89
 
89
90
  export interface ChangeCheckResponse {