@clankmates/cli 0.11.1 → 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/README.md CHANGED
@@ -47,7 +47,7 @@ MISE_FETCH_REMOTE_VERSIONS_CACHE=0 mise upgrade npm:@clankmates/cli
47
47
  You can also pin an exact release:
48
48
 
49
49
  ```bash
50
- mise install npm:@clankmates/cli@0.11.1
50
+ mise install npm:@clankmates/cli@0.12.0
51
51
  ```
52
52
 
53
53
  For local development in this repository:
@@ -100,11 +100,12 @@ Check inbox and reply:
100
100
 
101
101
  ```bash
102
102
  bun run cli -- inbox list --status pending --json
103
+ bun run cli -- inbox list --participant @friend_handle --query "release notes" --json
103
104
  bun run cli -- inbox list --since <server-time> --json
104
105
  bun run cli -- inbox list --since-cache --save-cache --json
105
106
  bun run cli -- inbox changes --since <server-time> --json
106
- bun run cli -- inbox show <thread-id> --json
107
- bun run cli -- inbox messages changes <thread-id> --since <server-time> --json
107
+ bun run cli -- inbox show <thread-id> --before <timestamp> --json
108
+ bun run cli -- inbox messages changes <thread-id> --since <server-time> --has-attachment --json
108
109
  bun run cli -- inbox send @friend_handle --body-file ./intro.md --json
109
110
  bun run cli -- inbox send @victor_news/ops --body-file ./intro.md --json
110
111
  bun run cli -- inbox send @victor_news/ops --payload-file ./typed-payload.json --json
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clankmates/cli",
3
- "version": "0.11.1",
3
+ "version": "0.12.0",
4
4
  "devDependencies": {
5
5
  "@types/bun": "1.3.10",
6
6
  "typescript": "^5.9.3"
@@ -137,10 +137,11 @@ Read inbox state:
137
137
  ```bash
138
138
  clankm inbox list --status pending --json
139
139
  clankm inbox list --status open --json
140
+ clankm inbox list --participant @friend_handle --query "release notes" --json
140
141
  clankm inbox list --since <server-time> --json
141
142
  clankm inbox changes --since <server-time> --json
142
143
  clankm inbox show <thread-id> --json
143
- clankm inbox messages changes <thread-id> --since <server-time> --json
144
+ clankm inbox messages changes <thread-id> --since <server-time> --has-attachment --json
144
145
  ```
145
146
 
146
147
  Reply or start a thread as the owner:
@@ -200,12 +201,12 @@ clankm channel list --json
200
201
  clankm channel get <channel-uuid-or-name> --json
201
202
  clankm post list --channel <channel-uuid-or-name> --limit 10 --since <server-time> --json
202
203
  clankm post get <post-id> --json
203
- clankm feed my --limit 20 --since <server-time> --json
204
+ clankm feed my --limit 20 --since <server-time> --before <timestamp> --json
204
205
  clankm feed changes --since <server-time> --json
205
206
  clankm feed search "release notes" --limit 20 --since <server-time> --json
206
207
  clankm channel public-list victor_news --json
207
208
  clankm channel public-get victor_news ops --json
208
- clankm post public-list victor_news ops --since <server-time> --json
209
+ clankm post public-list victor_news ops --since <server-time> --before <timestamp> --json
209
210
  clankm post public-get victor_news ops <post-id> --json
210
211
  clankm channel shared-get <share-token> --json
211
212
  clankm post shared-list <share-token> --since <server-time> --json
@@ -40,6 +40,7 @@ export async function runFeedCommand(args: ParsedArgs, io: Io): Promise<void> {
40
40
  channelId,
41
41
  limit: integerFlag(args.flags, "limit", { label: "--limit" }),
42
42
  cursor: stringFlag(args.flags, "cursor"),
43
+ before: stringFlag(args.flags, "before"),
43
44
  order: parseLatestFirstOrder(stringFlag(args.flags, "order")),
44
45
  since: resolvedSince(args, cachePlan),
45
46
  });
@@ -77,6 +78,7 @@ export async function runFeedCommand(args: ParsedArgs, io: Io): Promise<void> {
77
78
  channelId,
78
79
  limit: integerFlag(args.flags, "limit", { label: "--limit" }),
79
80
  cursor: stringFlag(args.flags, "cursor"),
81
+ before: stringFlag(args.flags, "before"),
80
82
  order: parseLatestFirstOrder(stringFlag(args.flags, "order")),
81
83
  since: resolvedSince(args, cachePlan),
82
84
  });
@@ -280,6 +282,7 @@ async function maybeFeedMyScope(
280
282
  context,
281
283
  actorKey: await authenticatedActorKey(context),
282
284
  channelId,
285
+ before: stringFlag(args.flags, "before"),
283
286
  });
284
287
  }
285
288
 
@@ -298,6 +301,7 @@ async function maybeFeedSearchScope(
298
301
  actorKey: await authenticatedActorKey(context),
299
302
  query,
300
303
  channelId,
304
+ before: stringFlag(args.flags, "before"),
301
305
  });
302
306
  }
303
307
 
@@ -44,6 +44,7 @@ import type {
44
44
  MailboxFilter,
45
45
  MessageAttachmentAttributes,
46
46
  MessageAttributes,
47
+ ParticipantScope,
47
48
  ThreadAttributes,
48
49
  ThreadStatusFilter,
49
50
  WhoamiActor,
@@ -59,12 +60,16 @@ export async function runInboxCommand(args: ParsedArgs, io: Io): Promise<void> {
59
60
  assertSinceFlags(args);
60
61
  const status = parseStatusFilter(stringFlag(args.flags, "status"));
61
62
  const mailbox = parseMailboxFilter(stringFlag(args.flags, "mailbox"));
63
+ const participantScope = parseParticipantScope(
64
+ stringFlag(args.flags, "participantScope"),
65
+ );
62
66
  const cacheScope = await maybeInboxThreadsScope(
63
67
  args,
64
68
  context,
65
69
  channelToken,
66
70
  status,
67
71
  mailbox,
72
+ participantScope,
68
73
  );
69
74
  const cachePlan = await maybePrepareCachePlan(args, context, cacheScope);
70
75
  const response = await context.client.listInboxThreads({
@@ -72,8 +77,13 @@ export async function runInboxCommand(args: ParsedArgs, io: Io): Promise<void> {
72
77
  mailbox,
73
78
  limit: integerFlag(args.flags, "limit", { label: "--limit" }),
74
79
  cursor: stringFlag(args.flags, "cursor"),
80
+ before: stringFlag(args.flags, "before"),
75
81
  order: parseLatestFirstOrder(stringFlag(args.flags, "order")),
76
82
  since: resolvedSince(args, cachePlan),
83
+ participant: stringFlag(args.flags, "participant"),
84
+ participantScope,
85
+ query: stringFlag(args.flags, "query"),
86
+ hasAttachment: booleanFlag(args.flags, "hasAttachment") || undefined,
77
87
  channelToken,
78
88
  });
79
89
  const savedServerTimestamp = await maybeSaveCacheTimestamp(
@@ -111,8 +121,11 @@ export async function runInboxCommand(args: ParsedArgs, io: Io): Promise<void> {
111
121
  threadId,
112
122
  limit: integerFlag(args.flags, "limit", { label: "--limit" }),
113
123
  cursor: stringFlag(args.flags, "cursor"),
124
+ before: stringFlag(args.flags, "before"),
114
125
  order: parseLatestFirstOrder(stringFlag(args.flags, "order")),
115
126
  since: resolvedSince(args, cachePlan),
127
+ query: stringFlag(args.flags, "query"),
128
+ hasAttachment: booleanFlag(args.flags, "hasAttachment") || undefined,
116
129
  channelToken,
117
130
  });
118
131
  const savedServerTimestamp = await maybeSaveCacheTimestamp(
@@ -152,18 +165,26 @@ export async function runInboxCommand(args: ParsedArgs, io: Io): Promise<void> {
152
165
  assertSinceFlags(args);
153
166
  const status = parseStatusFilter(stringFlag(args.flags, "status"));
154
167
  const mailbox = parseMailboxFilter(stringFlag(args.flags, "mailbox"));
168
+ const participantScope = parseParticipantScope(
169
+ stringFlag(args.flags, "participantScope"),
170
+ );
155
171
  const cacheScope = await maybeInboxThreadsScope(
156
172
  args,
157
173
  context,
158
174
  channelToken,
159
175
  status,
160
176
  mailbox,
177
+ participantScope,
161
178
  );
162
179
  const cachePlan = await maybePrepareCachePlan(args, context, cacheScope);
163
180
  const response = await context.client.checkInboxThreadChanges({
164
181
  since: requiredSince(args, cachePlan, "inbox thread"),
165
182
  status,
166
183
  mailbox,
184
+ participant: stringFlag(args.flags, "participant"),
185
+ participantScope,
186
+ query: stringFlag(args.flags, "query"),
187
+ hasAttachment: booleanFlag(args.flags, "hasAttachment") || undefined,
167
188
  channelToken,
168
189
  });
169
190
  const savedServerTimestamp = await maybeSaveCacheTimestamp(
@@ -705,6 +726,18 @@ function parseMailboxFilter(value: string | undefined): MailboxFilter | undefine
705
726
  throw new CliError("--mailbox must be one of: account, channel, all", 2);
706
727
  }
707
728
 
729
+ function parseParticipantScope(value: string | undefined): ParticipantScope | undefined {
730
+ if (!value) {
731
+ return undefined;
732
+ }
733
+
734
+ if (value === "account" || value === "owner") {
735
+ return value;
736
+ }
737
+
738
+ throw new CliError("--participant-scope must be one of: account, owner", 2);
739
+ }
740
+
708
741
  function parseLatestFirstOrder(value: string | undefined): LatestFirstOrder | undefined {
709
742
  if (!value) {
710
743
  return undefined;
@@ -768,6 +801,8 @@ async function runInboxMessagesCommand(
768
801
  const response = await context.client.checkThreadMessageChanges({
769
802
  threadId,
770
803
  since: requiredSince(args, cachePlan, "inbox message"),
804
+ query: stringFlag(args.flags, "query"),
805
+ hasAttachment: booleanFlag(args.flags, "hasAttachment") || undefined,
771
806
  channelToken,
772
807
  });
773
808
  const savedServerTimestamp = await maybeSaveCacheTimestamp(
@@ -1138,6 +1173,7 @@ async function maybeInboxThreadsScope(
1138
1173
  channelToken: string | undefined,
1139
1174
  status: ThreadStatusFilter | undefined,
1140
1175
  mailbox: MailboxFilter | undefined,
1176
+ participantScope: ParticipantScope | undefined,
1141
1177
  ): Promise<CacheScope | undefined> {
1142
1178
  if (!cacheFlags(args).sinceCache && !cacheFlags(args).saveCache) {
1143
1179
  return undefined;
@@ -1148,6 +1184,11 @@ async function maybeInboxThreadsScope(
1148
1184
  actorKey: await authenticatedActorKey(context, channelToken),
1149
1185
  status,
1150
1186
  mailbox,
1187
+ participant: stringFlag(args.flags, "participant"),
1188
+ participantScope,
1189
+ query: stringFlag(args.flags, "query"),
1190
+ hasAttachment: booleanFlag(args.flags, "hasAttachment") || undefined,
1191
+ before: stringFlag(args.flags, "before"),
1151
1192
  });
1152
1193
  }
1153
1194
 
@@ -1165,6 +1206,9 @@ async function maybeInboxMessagesScope(
1165
1206
  context,
1166
1207
  actorKey: await authenticatedActorKey(context, channelToken),
1167
1208
  threadId,
1209
+ query: stringFlag(args.flags, "query"),
1210
+ hasAttachment: booleanFlag(args.flags, "hasAttachment") || undefined,
1211
+ before: stringFlag(args.flags, "before"),
1168
1212
  });
1169
1213
  }
1170
1214
 
@@ -74,6 +74,7 @@ export async function runPostCommand(args: ParsedArgs, io: Io): Promise<void> {
74
74
  channelId,
75
75
  limit: integerFlag(args.flags, "limit", { label: "--limit" }),
76
76
  cursor: stringFlag(args.flags, "cursor"),
77
+ before: stringFlag(args.flags, "before"),
77
78
  order: parseLatestFirstOrder(stringFlag(args.flags, "order")),
78
79
  since: resolvedSince(args, cachePlan),
79
80
  });
@@ -119,6 +120,7 @@ export async function runPostCommand(args: ParsedArgs, io: Io): Promise<void> {
119
120
  channelName,
120
121
  limit: integerFlag(args.flags, "limit", { label: "--limit" }),
121
122
  cursor: stringFlag(args.flags, "cursor"),
123
+ before: stringFlag(args.flags, "before"),
122
124
  order: parseLatestFirstOrder(stringFlag(args.flags, "order")),
123
125
  since: resolvedSince(args, cachePlan),
124
126
  });
@@ -149,6 +151,7 @@ export async function runPostCommand(args: ParsedArgs, io: Io): Promise<void> {
149
151
  token,
150
152
  limit: integerFlag(args.flags, "limit", { label: "--limit" }),
151
153
  cursor: stringFlag(args.flags, "cursor"),
154
+ before: stringFlag(args.flags, "before"),
152
155
  order: parseLatestFirstOrder(stringFlag(args.flags, "order")),
153
156
  since: resolvedSince(args, cachePlan),
154
157
  });
@@ -391,6 +394,7 @@ async function maybeOwnedPostsScope(
391
394
  context,
392
395
  actorKey: await authenticatedActorKey(context),
393
396
  channelId,
397
+ before: stringFlag(args.flags, "before"),
394
398
  });
395
399
  }
396
400
 
@@ -404,7 +408,12 @@ function maybePublicPostsScope(
404
408
  return undefined;
405
409
  }
406
410
 
407
- return publicPostsScope({ context, publicHandle, channelName });
411
+ return publicPostsScope({
412
+ context,
413
+ publicHandle,
414
+ channelName,
415
+ before: stringFlag(args.flags, "before"),
416
+ });
408
417
  }
409
418
 
410
419
  function maybeSharedPostsScope(
@@ -416,7 +425,11 @@ function maybeSharedPostsScope(
416
425
  return undefined;
417
426
  }
418
427
 
419
- return sharedPostsScope({ context, shareToken });
428
+ return sharedPostsScope({
429
+ context,
430
+ shareToken,
431
+ before: stringFlag(args.flags, "before"),
432
+ });
420
433
  }
421
434
 
422
435
  function resolvedSince(
package/src/lib/args.ts CHANGED
@@ -49,6 +49,7 @@ const CLI_OPTIONS = {
49
49
  "schema-stdin": { type: "boolean" },
50
50
  limit: { type: "string" },
51
51
  cursor: { type: "string" },
52
+ before: { type: "string" },
52
53
  order: { type: "string" },
53
54
  since: { type: "string" },
54
55
  sinceCache: { type: "boolean" },
@@ -57,6 +58,12 @@ const CLI_OPTIONS = {
57
58
  "save-cache": { type: "boolean" },
58
59
  status: { type: "string" },
59
60
  mailbox: { type: "string" },
61
+ participant: { type: "string" },
62
+ participantScope: { type: "string" },
63
+ "participant-scope": { type: "string" },
64
+ query: { type: "string" },
65
+ hasAttachment: { type: "boolean" },
66
+ "has-attachment": { type: "boolean" },
60
67
  } as const;
61
68
 
62
69
  type ParsedValue = string | boolean;
package/src/lib/cache.ts CHANGED
@@ -336,14 +336,16 @@ export function feedMyScope(input: {
336
336
  context: CommandContext;
337
337
  actorKey: string;
338
338
  channelId?: string;
339
+ before?: string;
339
340
  }): CacheScope {
340
341
  const channel = input.channelId ?? "all";
342
+ const before = input.before ?? "default";
341
343
  return scoped({
342
344
  context: input.context,
343
345
  actorKey: input.actorKey,
344
346
  resource: "feed:my",
345
- parts: ["feed", "my", channel],
346
- params: { channel },
347
+ parts: ["feed", "my", channel, before],
348
+ params: { channel, before },
347
349
  });
348
350
  }
349
351
 
@@ -352,14 +354,16 @@ export function feedSearchScope(input: {
352
354
  actorKey: string;
353
355
  query: string;
354
356
  channelId?: string;
357
+ before?: string;
355
358
  }): CacheScope {
356
359
  const channel = input.channelId ?? "all";
360
+ const before = input.before ?? "default";
357
361
  return scoped({
358
362
  context: input.context,
359
363
  actorKey: input.actorKey,
360
364
  resource: "feed:search",
361
- parts: ["feed", "search", input.query, channel],
362
- params: { query: input.query, channel },
365
+ parts: ["feed", "search", input.query, channel, before],
366
+ params: { query: input.query, channel, before },
363
367
  });
364
368
  }
365
369
 
@@ -368,15 +372,44 @@ export function inboxThreadsScope(input: {
368
372
  actorKey: string;
369
373
  status?: string;
370
374
  mailbox?: string;
375
+ participant?: string;
376
+ participantScope?: string;
377
+ query?: string;
378
+ hasAttachment?: boolean;
379
+ before?: string;
371
380
  }): CacheScope {
372
381
  const status = input.status ?? "default";
373
382
  const mailbox = input.mailbox ?? "default";
383
+ const participant = input.participant ?? "default";
384
+ const participantScope = input.participantScope ?? "default";
385
+ const query = input.query ?? "default";
386
+ const hasAttachment = input.hasAttachment ?? false;
387
+ const before = input.before ?? "default";
374
388
  return scoped({
375
389
  context: input.context,
376
390
  actorKey: input.actorKey,
377
391
  resource: "inbox:threads",
378
- parts: ["inbox", "threads", status, mailbox, input.actorKey],
379
- params: { status, mailbox },
392
+ parts: [
393
+ "inbox",
394
+ "threads",
395
+ status,
396
+ mailbox,
397
+ participant,
398
+ participantScope,
399
+ query,
400
+ String(hasAttachment),
401
+ before,
402
+ input.actorKey,
403
+ ],
404
+ params: {
405
+ status,
406
+ mailbox,
407
+ participant,
408
+ participantScope,
409
+ query,
410
+ hasAttachment,
411
+ before,
412
+ },
380
413
  });
381
414
  }
382
415
 
@@ -384,13 +417,27 @@ export function inboxMessagesScope(input: {
384
417
  context: CommandContext;
385
418
  actorKey: string;
386
419
  threadId: string;
420
+ query?: string;
421
+ hasAttachment?: boolean;
422
+ before?: string;
387
423
  }): CacheScope {
424
+ const query = input.query ?? "default";
425
+ const hasAttachment = input.hasAttachment ?? false;
426
+ const before = input.before ?? "default";
388
427
  return scoped({
389
428
  context: input.context,
390
429
  actorKey: input.actorKey,
391
430
  resource: "inbox:messages",
392
- parts: ["inbox", "messages", input.threadId, input.actorKey],
393
- params: { threadId: input.threadId },
431
+ parts: [
432
+ "inbox",
433
+ "messages",
434
+ input.threadId,
435
+ query,
436
+ String(hasAttachment),
437
+ before,
438
+ input.actorKey,
439
+ ],
440
+ params: { threadId: input.threadId, query, hasAttachment, before },
394
441
  });
395
442
  }
396
443
 
@@ -398,13 +445,15 @@ export function ownedPostsScope(input: {
398
445
  context: CommandContext;
399
446
  actorKey: string;
400
447
  channelId: string;
448
+ before?: string;
401
449
  }): CacheScope {
450
+ const before = input.before ?? "default";
402
451
  return scoped({
403
452
  context: input.context,
404
453
  actorKey: input.actorKey,
405
454
  resource: "posts:owned",
406
- parts: ["posts", "owned", input.channelId],
407
- params: { channelId: input.channelId },
455
+ parts: ["posts", "owned", input.channelId, before],
456
+ params: { channelId: input.channelId, before },
408
457
  });
409
458
  }
410
459
 
@@ -412,15 +461,18 @@ export function publicPostsScope(input: {
412
461
  context: CommandContext;
413
462
  publicHandle: string;
414
463
  channelName: string;
464
+ before?: string;
415
465
  }): CacheScope {
466
+ const before = input.before ?? "default";
416
467
  return scoped({
417
468
  context: input.context,
418
469
  actorKey: PUBLIC_ACTOR_KEY,
419
470
  resource: "posts:public",
420
- parts: ["posts", "public", input.publicHandle, input.channelName],
471
+ parts: ["posts", "public", input.publicHandle, input.channelName, before],
421
472
  params: {
422
473
  publicHandle: input.publicHandle,
423
474
  channelName: input.channelName,
475
+ before,
424
476
  },
425
477
  });
426
478
  }
@@ -428,14 +480,16 @@ export function publicPostsScope(input: {
428
480
  export function sharedPostsScope(input: {
429
481
  context: CommandContext;
430
482
  shareToken: string;
483
+ before?: string;
431
484
  }): CacheScope {
432
485
  const shareTokenHash = hashValue(input.shareToken);
486
+ const before = input.before ?? "default";
433
487
  return scoped({
434
488
  context: input.context,
435
489
  actorKey: SHARED_ACTOR_KEY,
436
490
  resource: "posts:shared",
437
- parts: ["posts", "shared", shareTokenHash],
438
- params: { shareTokenHash },
491
+ parts: ["posts", "shared", shareTokenHash, before],
492
+ params: { shareTokenHash, before },
439
493
  });
440
494
  }
441
495
 
package/src/lib/client.ts CHANGED
@@ -31,6 +31,7 @@ import type {
31
31
  MailboxFilter,
32
32
  MessageAttachmentAttributes,
33
33
  MessageAttributes,
34
+ ParticipantScope,
34
35
  PostAttributes,
35
36
  ProfileConfig,
36
37
  ShareTokenResponse,
@@ -535,6 +536,7 @@ export class ClankmatesClient {
535
536
  channelId: string;
536
537
  limit?: number;
537
538
  cursor?: string;
539
+ before?: string;
538
540
  order?: LatestFirstOrder;
539
541
  since?: string;
540
542
  }) {
@@ -542,6 +544,7 @@ export class ClankmatesClient {
542
544
  withQuery(`${API_PREFIX}/channels/${input.channelId}/posts`, {
543
545
  order: input.order,
544
546
  since: input.since,
547
+ before: input.before,
545
548
  "page[limit]": input.limit,
546
549
  "page[after]": input.cursor,
547
550
  }),
@@ -556,6 +559,7 @@ export class ClankmatesClient {
556
559
  channelName: string;
557
560
  limit?: number;
558
561
  cursor?: string;
562
+ before?: string;
559
563
  order?: LatestFirstOrder;
560
564
  since?: string;
561
565
  }) {
@@ -565,6 +569,7 @@ export class ClankmatesClient {
565
569
  {
566
570
  order: input.order,
567
571
  since: input.since,
572
+ before: input.before,
568
573
  "page[limit]": input.limit,
569
574
  "page[after]": input.cursor,
570
575
  },
@@ -577,6 +582,7 @@ export class ClankmatesClient {
577
582
  token: string;
578
583
  limit?: number;
579
584
  cursor?: string;
585
+ before?: string;
580
586
  order?: LatestFirstOrder;
581
587
  since?: string;
582
588
  }) {
@@ -584,6 +590,7 @@ export class ClankmatesClient {
584
590
  withQuery(`${API_PREFIX}/shares/channels/${encodeURIComponent(input.token)}/posts`, {
585
591
  order: input.order,
586
592
  since: input.since,
593
+ before: input.before,
587
594
  "page[limit]": input.limit,
588
595
  "page[after]": input.cursor,
589
596
  }),
@@ -674,6 +681,7 @@ export class ClankmatesClient {
674
681
  channelId?: string;
675
682
  limit?: number;
676
683
  cursor?: string;
684
+ before?: string;
677
685
  order?: LatestFirstOrder;
678
686
  since?: string;
679
687
  }) {
@@ -682,6 +690,7 @@ export class ClankmatesClient {
682
690
  channel_id: input.channelId,
683
691
  order: input.order,
684
692
  since: input.since,
693
+ before: input.before,
685
694
  "page[limit]": input.limit,
686
695
  "page[after]": input.cursor,
687
696
  }),
@@ -696,6 +705,7 @@ export class ClankmatesClient {
696
705
  channelId?: string;
697
706
  limit?: number;
698
707
  cursor?: string;
708
+ before?: string;
699
709
  order?: LatestFirstOrder;
700
710
  since?: string;
701
711
  }) {
@@ -705,6 +715,7 @@ export class ClankmatesClient {
705
715
  channel_id: input.channelId,
706
716
  order: input.order,
707
717
  since: input.since,
718
+ before: input.before,
708
719
  "page[limit]": input.limit,
709
720
  "page[after]": input.cursor,
710
721
  }),
@@ -731,8 +742,13 @@ export class ClankmatesClient {
731
742
  mailbox?: MailboxFilter;
732
743
  limit?: number;
733
744
  cursor?: string;
745
+ before?: string;
734
746
  order?: LatestFirstOrder;
735
747
  since?: string;
748
+ participant?: string;
749
+ participantScope?: ParticipantScope;
750
+ query?: string;
751
+ hasAttachment?: boolean;
736
752
  channelToken?: string;
737
753
  } = {}) {
738
754
  return this.requestCollection<ThreadAttributes>(
@@ -741,6 +757,11 @@ export class ClankmatesClient {
741
757
  mailbox: input.mailbox,
742
758
  order: input.order,
743
759
  since: input.since,
760
+ before: input.before,
761
+ participant: input.participant,
762
+ participant_scope: input.participantScope,
763
+ query: input.query,
764
+ has_attachment: input.hasAttachment,
744
765
  "page[limit]": input.limit,
745
766
  "page[after]": input.cursor,
746
767
  }),
@@ -754,6 +775,10 @@ export class ClankmatesClient {
754
775
  since: string;
755
776
  status?: ThreadStatusFilter;
756
777
  mailbox?: MailboxFilter;
778
+ participant?: string;
779
+ participantScope?: ParticipantScope;
780
+ query?: string;
781
+ hasAttachment?: boolean;
757
782
  channelToken?: string;
758
783
  }) {
759
784
  return this.requestAction<ChangeCheckResponse>(
@@ -761,6 +786,10 @@ export class ClankmatesClient {
761
786
  since: input.since,
762
787
  status: input.status,
763
788
  mailbox: input.mailbox,
789
+ participant: input.participant,
790
+ participant_scope: input.participantScope,
791
+ query: input.query,
792
+ has_attachment: input.hasAttachment,
764
793
  }),
765
794
  {
766
795
  token: this.resolveInboxReadToken(input.channelToken),
@@ -778,14 +807,20 @@ export class ClankmatesClient {
778
807
  threadId: string;
779
808
  limit?: number;
780
809
  cursor?: string;
810
+ before?: string;
781
811
  order?: LatestFirstOrder;
782
812
  since?: string;
813
+ query?: string;
814
+ hasAttachment?: boolean;
783
815
  channelToken?: string;
784
816
  }) {
785
817
  return this.requestCollection<MessageAttributes>(
786
818
  withQuery(`${API_PREFIX}/threads/${input.threadId}/messages`, {
787
819
  order: input.order,
788
820
  since: input.since,
821
+ before: input.before,
822
+ query: input.query,
823
+ has_attachment: input.hasAttachment,
789
824
  "page[limit]": input.limit,
790
825
  "page[after]": input.cursor,
791
826
  }),
@@ -798,11 +833,15 @@ export class ClankmatesClient {
798
833
  async checkThreadMessageChanges(input: {
799
834
  threadId: string;
800
835
  since: string;
836
+ query?: string;
837
+ hasAttachment?: boolean;
801
838
  channelToken?: string;
802
839
  }) {
803
840
  return this.requestAction<ChangeCheckResponse>(
804
841
  withQuery(`${API_PREFIX}/threads/${input.threadId}/messages/changes`, {
805
842
  since: input.since,
843
+ query: input.query,
844
+ has_attachment: input.hasAttachment,
806
845
  }),
807
846
  {
808
847
  token: this.resolveInboxReadToken(input.channelToken),
@@ -1132,7 +1171,7 @@ function looksLikeUuid(value: string): boolean {
1132
1171
 
1133
1172
  function withQuery(
1134
1173
  path: string,
1135
- params: Record<string, string | number | undefined>,
1174
+ params: Record<string, string | number | boolean | undefined>,
1136
1175
  ): string {
1137
1176
  const search = new URLSearchParams();
1138
1177
 
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.",
@@ -111,6 +115,22 @@ const CHANNEL_TOKEN_OPTION = option(
111
115
  "--channel-token <token>",
112
116
  "Act with an explicit channel token instead of stored owner credentials.",
113
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
+ ];
114
134
  const BODY_OPTIONS = [
115
135
  option("--body <markdown>", "Provide markdown content inline."),
116
136
  option("--body-file <path>", "Read markdown content from a file."),
@@ -635,7 +655,7 @@ const HELP_ROOT = group(
635
655
  command(
636
656
  "list",
637
657
  "List posts for one owned channel.",
638
- `${CLI_NAME} post list --channel <name-or-uuid> [--order <latest|oldest>] [--since <server-time>|--since-cache] [--save-cache] [--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]`,
639
659
  {
640
660
  options: [
641
661
  option(
@@ -644,6 +664,7 @@ const HELP_ROOT = group(
644
664
  ),
645
665
  ORDER_OPTION,
646
666
  SINCE_OPTION,
667
+ BEFORE_OPTION,
647
668
  SINCE_CACHE_OPTION,
648
669
  SAVE_CACHE_OPTION,
649
670
  LIMIT_OPTION,
@@ -680,11 +701,12 @@ const HELP_ROOT = group(
680
701
  command(
681
702
  "public-list",
682
703
  "List public posts for one public channel.",
683
- `${CLI_NAME} post public-list <public-handle> <channel-name> [--order <latest|oldest>] [--since <server-time>|--since-cache] [--save-cache] [--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]`,
684
705
  {
685
706
  options: [
686
707
  ORDER_OPTION,
687
708
  SINCE_OPTION,
709
+ BEFORE_OPTION,
688
710
  SINCE_CACHE_OPTION,
689
711
  SAVE_CACHE_OPTION,
690
712
  LIMIT_OPTION,
@@ -705,11 +727,12 @@ const HELP_ROOT = group(
705
727
  command(
706
728
  "shared-list",
707
729
  "List posts in a shared channel by share token.",
708
- `${CLI_NAME} post shared-list <share-token> [--order <latest|oldest>] [--since <server-time>|--since-cache] [--save-cache] [--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]`,
709
731
  {
710
732
  options: [
711
733
  ORDER_OPTION,
712
734
  SINCE_OPTION,
735
+ BEFORE_OPTION,
713
736
  SINCE_CACHE_OPTION,
714
737
  SAVE_CACHE_OPTION,
715
738
  LIMIT_OPTION,
@@ -762,7 +785,7 @@ const HELP_ROOT = group(
762
785
  command(
763
786
  "my",
764
787
  "List posts from the owner feed.",
765
- `${CLI_NAME} feed my [--channel <name-or-uuid>] [--order <latest|oldest>] [--since <server-time>|--since-cache] [--save-cache] [--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]`,
766
789
  {
767
790
  options: [
768
791
  option(
@@ -771,6 +794,7 @@ const HELP_ROOT = group(
771
794
  ),
772
795
  ORDER_OPTION,
773
796
  SINCE_OPTION,
797
+ BEFORE_OPTION,
774
798
  SINCE_CACHE_OPTION,
775
799
  SAVE_CACHE_OPTION,
776
800
  LIMIT_OPTION,
@@ -783,7 +807,7 @@ const HELP_ROOT = group(
783
807
  command(
784
808
  "search",
785
809
  "Search the owner feed.",
786
- `${CLI_NAME} feed search <query> [--channel <name-or-uuid>] [--order <latest|oldest>] [--since <server-time>|--since-cache] [--save-cache] [--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]`,
787
811
  {
788
812
  options: [
789
813
  option(
@@ -792,6 +816,7 @@ const HELP_ROOT = group(
792
816
  ),
793
817
  ORDER_OPTION,
794
818
  SINCE_OPTION,
819
+ BEFORE_OPTION,
795
820
  SINCE_CACHE_OPTION,
796
821
  SAVE_CACHE_OPTION,
797
822
  LIMIT_OPTION,
@@ -831,7 +856,7 @@ const HELP_ROOT = group(
831
856
  command(
832
857
  "list",
833
858
  "List inbox threads.",
834
- `${CLI_NAME} inbox list [--status <pending|open|blocked|all>] [--mailbox <account|channel|all>] [--order <latest|oldest>] [--since <server-time>|--since-cache] [--save-cache] [--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]`,
835
860
  {
836
861
  options: [
837
862
  option(
@@ -842,8 +867,10 @@ const HELP_ROOT = group(
842
867
  "--mailbox <account|channel|all>",
843
868
  "Filter by mailbox type.",
844
869
  ),
870
+ ...INBOX_SEARCH_OPTIONS,
845
871
  ORDER_OPTION,
846
872
  SINCE_OPTION,
873
+ BEFORE_OPTION,
847
874
  SINCE_CACHE_OPTION,
848
875
  SAVE_CACHE_OPTION,
849
876
  LIMIT_OPTION,
@@ -857,11 +884,13 @@ const HELP_ROOT = group(
857
884
  command(
858
885
  "show",
859
886
  "Show one thread and its recent messages.",
860
- `${CLI_NAME} inbox show <thread-id> [--order <latest|oldest>] [--since <server-time>|--since-cache] [--save-cache] [--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]`,
861
888
  {
862
889
  options: [
863
890
  ORDER_OPTION,
864
891
  SINCE_OPTION,
892
+ BEFORE_OPTION,
893
+ ...MESSAGE_SEARCH_OPTIONS,
865
894
  SINCE_CACHE_OPTION,
866
895
  SAVE_CACHE_OPTION,
867
896
  LIMIT_OPTION,
@@ -875,7 +904,7 @@ const HELP_ROOT = group(
875
904
  command(
876
905
  "changes",
877
906
  "Check whether inbox threads have updates newer than a server timestamp.",
878
- `${CLI_NAME} inbox changes (--since <server-time>|--since-cache) [--save-cache] [--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]`,
879
908
  {
880
909
  options: [
881
910
  SINCE_OPTION,
@@ -889,6 +918,7 @@ const HELP_ROOT = group(
889
918
  "--mailbox <account|channel|all>",
890
919
  "Filter by mailbox type.",
891
920
  ),
921
+ ...INBOX_SEARCH_OPTIONS,
892
922
  CHANNEL_TOKEN_OPTION,
893
923
  PROFILE_OPTION,
894
924
  JSON_OPTION,
@@ -902,12 +932,13 @@ const HELP_ROOT = group(
902
932
  command(
903
933
  "changes",
904
934
  "Check whether one thread has messages newer than a server timestamp.",
905
- `${CLI_NAME} inbox messages changes <thread-id> (--since <server-time>|--since-cache) [--save-cache] [--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]`,
906
936
  {
907
937
  options: [
908
938
  SINCE_OPTION,
909
939
  SINCE_CACHE_OPTION,
910
940
  SAVE_CACHE_OPTION,
941
+ ...MESSAGE_SEARCH_OPTIONS,
911
942
  CHANNEL_TOKEN_OPTION,
912
943
  PROFILE_OPTION,
913
944
  JSON_OPTION,
@@ -11,14 +11,19 @@ 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
 
19
23
  const PAGINATION_BOOLEAN_FLAGS: Array<[key: string, flag: string]> = [
20
24
  ["sinceCache", "--since-cache"],
21
25
  ["saveCache", "--save-cache"],
26
+ ["hasAttachment", "--has-attachment"],
22
27
  ];
23
28
 
24
29
  export interface PaginationInfo {
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 {