@clankid/cli 0.17.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.
Files changed (81) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/LICENSE +21 -0
  3. package/README.md +275 -0
  4. package/bin/clank +6 -0
  5. package/docs/usage/clankid-migration.md +59 -0
  6. package/package.json +47 -0
  7. package/skills/codex/clankid/SKILL.md +256 -0
  8. package/skills/codex/clankid/references/safety.md +28 -0
  9. package/skills/codex/clankid/references/setup.md +65 -0
  10. package/src/README.md +8 -0
  11. package/src/cli.ts +154 -0
  12. package/src/commands/.gitkeep +1 -0
  13. package/src/commands/account.ts +337 -0
  14. package/src/commands/api.ts +43 -0
  15. package/src/commands/auth/access-keys.ts +206 -0
  16. package/src/commands/auth.ts +240 -0
  17. package/src/commands/cache.ts +124 -0
  18. package/src/commands/config.ts +93 -0
  19. package/src/commands/doctor/checks.ts +123 -0
  20. package/src/commands/doctor/render.ts +140 -0
  21. package/src/commands/doctor/suggestions.ts +42 -0
  22. package/src/commands/doctor/types.ts +75 -0
  23. package/src/commands/doctor.ts +221 -0
  24. package/src/commands/feed.ts +185 -0
  25. package/src/commands/identity/keys.ts +145 -0
  26. package/src/commands/identity/render.ts +224 -0
  27. package/src/commands/identity/validation.ts +11 -0
  28. package/src/commands/identity.ts +295 -0
  29. package/src/commands/inbox/content.ts +13 -0
  30. package/src/commands/inbox/filters.ts +70 -0
  31. package/src/commands/inbox/messages.ts +71 -0
  32. package/src/commands/inbox/participants.ts +152 -0
  33. package/src/commands/inbox/render.ts +13 -0
  34. package/src/commands/inbox/resource-output.ts +217 -0
  35. package/src/commands/inbox/schema.ts +185 -0
  36. package/src/commands/inbox/screening.ts +76 -0
  37. package/src/commands/inbox/sync-scopes.ts +62 -0
  38. package/src/commands/inbox/thread-output.ts +345 -0
  39. package/src/commands/inbox/watch.ts +207 -0
  40. package/src/commands/inbox.ts +374 -0
  41. package/src/commands/post.ts +406 -0
  42. package/src/commands/setup.ts +228 -0
  43. package/src/commands/skill.ts +41 -0
  44. package/src/commands/user.ts +33 -0
  45. package/src/lib/.gitkeep +1 -0
  46. package/src/lib/args.ts +231 -0
  47. package/src/lib/body-input.ts +55 -0
  48. package/src/lib/cache/scopes.ts +272 -0
  49. package/src/lib/cache/store.ts +195 -0
  50. package/src/lib/cache/types.ts +31 -0
  51. package/src/lib/cache.ts +135 -0
  52. package/src/lib/client/auth.ts +163 -0
  53. package/src/lib/client/core.ts +133 -0
  54. package/src/lib/client/feed.ts +93 -0
  55. package/src/lib/client/identities.ts +364 -0
  56. package/src/lib/client/identity-keys.ts +57 -0
  57. package/src/lib/client/inbox.ts +385 -0
  58. package/src/lib/client/posts.ts +236 -0
  59. package/src/lib/client/raw-api.ts +33 -0
  60. package/src/lib/client/users.ts +88 -0
  61. package/src/lib/client.ts +469 -0
  62. package/src/lib/config.ts +239 -0
  63. package/src/lib/content.ts +149 -0
  64. package/src/lib/context.ts +43 -0
  65. package/src/lib/errors.ts +17 -0
  66. package/src/lib/help.ts +1587 -0
  67. package/src/lib/http.ts +138 -0
  68. package/src/lib/human.ts +143 -0
  69. package/src/lib/json-input.ts +73 -0
  70. package/src/lib/json_api.ts +120 -0
  71. package/src/lib/output.ts +203 -0
  72. package/src/lib/pagination.ts +116 -0
  73. package/src/lib/paths.ts +44 -0
  74. package/src/lib/polling.ts +146 -0
  75. package/src/lib/post-output.ts +60 -0
  76. package/src/lib/skills.ts +137 -0
  77. package/src/lib/tokens.ts +284 -0
  78. package/src/lib/version.ts +19 -0
  79. package/src/types/.gitkeep +1 -0
  80. package/src/types/api.ts +320 -0
  81. package/src/types/placeholder.d.ts +1 -0
@@ -0,0 +1,374 @@
1
+ import {
2
+ assertSinceFlags,
3
+ cacheResult,
4
+ changeResponseMeta,
5
+ } from "../lib/cache";
6
+ import {
7
+ booleanFlag,
8
+ integerFlag,
9
+ requiredPositional,
10
+ stringFlag,
11
+ type ParsedArgs,
12
+ } from "../lib/args";
13
+ import { payloadFilters } from "../lib/content";
14
+ import { createCommandContext, type CommandContext } from "../lib/context";
15
+ import { CliError } from "../lib/errors";
16
+ import { printValue, type Io } from "../lib/output";
17
+ import { paginatedJson } from "../lib/pagination";
18
+ import {
19
+ maybePrepareCachePlan,
20
+ maybeSaveCacheTimestamp,
21
+ parseLatestFirstOrder,
22
+ printChangeCheckResponse,
23
+ requiredSince,
24
+ resolvedSince,
25
+ } from "../lib/polling";
26
+ import { resolveMessageContent } from "./inbox/content";
27
+ import {
28
+ parseMailboxFilter,
29
+ parseParticipantScope,
30
+ parseStatusFilter,
31
+ } from "./inbox/filters";
32
+ import {
33
+ parseRecipient,
34
+ resolveSender,
35
+ } from "./inbox/participants";
36
+ import {
37
+ ownerIdsForThreadDisplay,
38
+ publicUserHandlesById,
39
+ printThreadCollection,
40
+ renderAttachmentCollection,
41
+ renderThreadAction,
42
+ renderThreadWithMessages,
43
+ } from "./inbox/render";
44
+ import { runInboxMessagesCommand } from "./inbox/messages";
45
+ import { runSchemaCommand } from "./inbox/schema";
46
+ import { runScreeningCommand } from "./inbox/screening";
47
+ import { maybeInboxMessagesScope, maybeInboxThreadsScope } from "./inbox/sync-scopes";
48
+ import { runInboxWatchCommand } from "./inbox/watch";
49
+ import type {
50
+ MailboxFilter,
51
+ ParticipantScope,
52
+ ThreadStatusFilter,
53
+ } from "../types/api";
54
+
55
+ export async function runInboxCommand(args: ParsedArgs, io: Io): Promise<void> {
56
+ const subcommand = args.positionals[0];
57
+ const context = await createCommandContext(args, io);
58
+
59
+ switch (subcommand) {
60
+ case "list": {
61
+ const identityKey = stringFlag(args.flags, "identityKey");
62
+ assertSinceFlags(args);
63
+ const status = parseStatusFilter(stringFlag(args.flags, "status"));
64
+ const mailbox = parseMailboxFilter(stringFlag(args.flags, "mailbox"));
65
+ const participantScope = parseParticipantScope(
66
+ stringFlag(args.flags, "participantScope"),
67
+ );
68
+ const cacheScope = await maybeInboxThreadsScope(
69
+ args,
70
+ context,
71
+ identityKey,
72
+ status,
73
+ mailbox,
74
+ participantScope,
75
+ );
76
+ const cachePlan = await maybePrepareCachePlan(args, context, cacheScope);
77
+ const response = await context.client.listInboxThreads({
78
+ status,
79
+ mailbox,
80
+ ...payloadFilters(args),
81
+ limit: integerFlag(args.flags, "limit", { label: "--limit" }),
82
+ cursor: stringFlag(args.flags, "cursor"),
83
+ before: stringFlag(args.flags, "before"),
84
+ order: parseLatestFirstOrder(stringFlag(args.flags, "order")),
85
+ since: resolvedSince(args, cachePlan),
86
+ participant: stringFlag(args.flags, "participant"),
87
+ participantScope,
88
+ query: stringFlag(args.flags, "query"),
89
+ hasAttachment: booleanFlag(args.flags, "hasAttachment") || undefined,
90
+ identityKey,
91
+ });
92
+ const savedServerTimestamp = await maybeSaveCacheTimestamp(
93
+ args,
94
+ context,
95
+ cacheScope,
96
+ response.meta,
97
+ response.nextCursor === undefined,
98
+ );
99
+
100
+ await printThreadCollection(
101
+ args,
102
+ context,
103
+ io,
104
+ response,
105
+ identityKey,
106
+ cacheResult(cachePlan, savedServerTimestamp),
107
+ );
108
+ return;
109
+ }
110
+
111
+ case "show": {
112
+ const threadId = requiredPositional(args.positionals, 1, "Missing thread id");
113
+ const identityKey = stringFlag(args.flags, "identityKey");
114
+ assertSinceFlags(args);
115
+ const cacheScope = await maybeInboxMessagesScope(
116
+ args,
117
+ context,
118
+ identityKey,
119
+ threadId,
120
+ );
121
+ const cachePlan = await maybePrepareCachePlan(args, context, cacheScope);
122
+ const thread = await context.client.getThread(threadId, identityKey);
123
+ const messages = await context.client.listMessagesForThread({
124
+ threadId,
125
+ ...payloadFilters(args),
126
+ limit: integerFlag(args.flags, "limit", { label: "--limit" }),
127
+ cursor: stringFlag(args.flags, "cursor"),
128
+ before: stringFlag(args.flags, "before"),
129
+ order: parseLatestFirstOrder(stringFlag(args.flags, "order")),
130
+ since: resolvedSince(args, cachePlan),
131
+ query: stringFlag(args.flags, "query"),
132
+ hasAttachment: booleanFlag(args.flags, "hasAttachment") || undefined,
133
+ identityKey,
134
+ });
135
+ const savedServerTimestamp = await maybeSaveCacheTimestamp(
136
+ args,
137
+ context,
138
+ cacheScope,
139
+ messages.meta,
140
+ messages.nextCursor === undefined,
141
+ );
142
+ const cache = cacheResult(cachePlan, savedServerTimestamp);
143
+ const ownerIds = ownerIdsForThreadDisplay(thread, messages.items);
144
+ const publicUsers =
145
+ context.outputMode === "json" || ownerIds.length === 0
146
+ ? new Map<string, string>()
147
+ : publicUserHandlesById(
148
+ (await context.client.listPublicUsersById(ownerIds)).items,
149
+ );
150
+
151
+ printValue(
152
+ io,
153
+ context.outputMode,
154
+ context.outputMode === "json"
155
+ ? paginatedJson(args, {
156
+ thread,
157
+ messages: messages.items,
158
+ nextCursor: messages.nextCursor,
159
+ meta: messages.meta,
160
+ ...(cache ? { cache } : {}),
161
+ })
162
+ : renderThreadWithMessages(args, thread, messages, publicUsers, cache),
163
+ );
164
+ return;
165
+ }
166
+
167
+ case "changes": {
168
+ const identityKey = stringFlag(args.flags, "identityKey");
169
+ assertSinceFlags(args);
170
+ const status = parseStatusFilter(stringFlag(args.flags, "status"));
171
+ const mailbox = parseMailboxFilter(stringFlag(args.flags, "mailbox"));
172
+ const participantScope = parseParticipantScope(
173
+ stringFlag(args.flags, "participantScope"),
174
+ );
175
+ const cacheScope = await maybeInboxThreadsScope(
176
+ args,
177
+ context,
178
+ identityKey,
179
+ status,
180
+ mailbox,
181
+ participantScope,
182
+ );
183
+ const cachePlan = await maybePrepareCachePlan(args, context, cacheScope);
184
+ const response = await context.client.checkInboxThreadChanges({
185
+ since: requiredSince(args, cachePlan, "inbox thread"),
186
+ status,
187
+ mailbox,
188
+ ...payloadFilters(args),
189
+ participant: stringFlag(args.flags, "participant"),
190
+ participantScope,
191
+ query: stringFlag(args.flags, "query"),
192
+ hasAttachment: booleanFlag(args.flags, "hasAttachment") || undefined,
193
+ identityKey,
194
+ });
195
+ const savedServerTimestamp = await maybeSaveCacheTimestamp(
196
+ args,
197
+ context,
198
+ cacheScope,
199
+ changeResponseMeta(response),
200
+ response.has_updates === false,
201
+ );
202
+
203
+ printChangeCheckResponse(
204
+ context,
205
+ io,
206
+ response,
207
+ cacheResult(cachePlan, savedServerTimestamp),
208
+ );
209
+ return;
210
+ }
211
+
212
+ case "watch": {
213
+ await runInboxWatchCommand(context, args, io);
214
+ return;
215
+ }
216
+
217
+ case "messages": {
218
+ await runInboxMessagesCommand(context, args, io);
219
+ return;
220
+ }
221
+
222
+ case "attachments": {
223
+ const messageId = requiredPositional(args.positionals, 1, "Missing message id");
224
+ const response = await context.client.listMessageAttachments({
225
+ messageId,
226
+ limit: integerFlag(args.flags, "limit", { label: "--limit" }),
227
+ cursor: stringFlag(args.flags, "cursor"),
228
+ identityKey: stringFlag(args.flags, "identityKey"),
229
+ });
230
+
231
+ printValue(
232
+ io,
233
+ context.outputMode,
234
+ context.outputMode === "json"
235
+ ? paginatedJson(args, {
236
+ items: response.items,
237
+ nextCursor: response.nextCursor,
238
+ })
239
+ : renderAttachmentCollection(args, response),
240
+ );
241
+ return;
242
+ }
243
+
244
+ case "screening": {
245
+ await runScreeningCommand(context, args, io);
246
+ return;
247
+ }
248
+
249
+ case "schema": {
250
+ await runSchemaCommand(context, args, io);
251
+ return;
252
+ }
253
+
254
+ case "send": {
255
+ const content = await resolveMessageContent(args);
256
+ const thread = await context.client.createThread({
257
+ recipient: await parseRecipient(
258
+ context,
259
+ requiredPositional(args.positionals, 1, "Missing recipient"),
260
+ ),
261
+ body: content.body,
262
+ payload: content.payload,
263
+ contentFormat: content.contentFormat,
264
+ from: await resolveSender(context, args),
265
+ contextPostId: stringFlag(args.flags, "contextPostId"),
266
+ identityKey: stringFlag(args.flags, "identityKey"),
267
+ });
268
+
269
+ printValue(
270
+ io,
271
+ context.outputMode,
272
+ context.outputMode === "json"
273
+ ? thread
274
+ : renderThreadAction("Created thread", thread),
275
+ );
276
+ return;
277
+ }
278
+
279
+ case "reply": {
280
+ const threadId = requiredPositional(args.positionals, 1, "Missing thread id");
281
+ const identityKey = stringFlag(args.flags, "identityKey");
282
+ const content = await resolveMessageContent(args);
283
+ const thread = await context.client.appendThreadMessage({
284
+ threadId,
285
+ body: content.body,
286
+ payload: content.payload,
287
+ contentFormat: content.contentFormat,
288
+ from: await resolveSender(context, args),
289
+ contextPostId: stringFlag(args.flags, "contextPostId"),
290
+ identityKey,
291
+ });
292
+
293
+ printValue(
294
+ io,
295
+ context.outputMode,
296
+ context.outputMode === "json"
297
+ ? thread
298
+ : renderThreadAction("Replied to thread", thread),
299
+ );
300
+ return;
301
+ }
302
+
303
+ case "seen": {
304
+ const threadId = requiredPositional(args.positionals, 1, "Missing thread id");
305
+ const thread = await context.client.markThreadSeen({
306
+ threadId,
307
+ identityKey: stringFlag(args.flags, "identityKey"),
308
+ });
309
+
310
+ printValue(
311
+ io,
312
+ context.outputMode,
313
+ context.outputMode === "json"
314
+ ? thread
315
+ : renderThreadAction("Marked thread as seen", thread),
316
+ );
317
+ return;
318
+ }
319
+
320
+ case "archive": {
321
+ const threadId = requiredPositional(args.positionals, 1, "Missing thread id");
322
+ const thread = await context.client.archiveThread({
323
+ threadId,
324
+ identityKey: stringFlag(args.flags, "identityKey"),
325
+ });
326
+
327
+ printValue(
328
+ io,
329
+ context.outputMode,
330
+ context.outputMode === "json"
331
+ ? thread
332
+ : renderThreadAction("Archived thread", thread),
333
+ );
334
+ return;
335
+ }
336
+
337
+ case "resolve": {
338
+ const threadId = requiredPositional(args.positionals, 1, "Missing thread id");
339
+ const thread = await context.client.resolveThread({
340
+ threadId,
341
+ identityKey: stringFlag(args.flags, "identityKey"),
342
+ });
343
+
344
+ printValue(
345
+ io,
346
+ context.outputMode,
347
+ context.outputMode === "json"
348
+ ? thread
349
+ : renderThreadAction("Resolved thread", thread),
350
+ );
351
+ return;
352
+ }
353
+
354
+ case "block": {
355
+ const threadId = requiredPositional(args.positionals, 1, "Missing thread id");
356
+ const thread = await context.client.blockThread({
357
+ threadId,
358
+ identityKey: stringFlag(args.flags, "identityKey"),
359
+ });
360
+
361
+ printValue(
362
+ io,
363
+ context.outputMode,
364
+ context.outputMode === "json"
365
+ ? thread
366
+ : renderThreadAction("Blocked thread", thread),
367
+ );
368
+ return;
369
+ }
370
+
371
+ default:
372
+ throw new CliError("Unknown inbox subcommand", 2);
373
+ }
374
+ }