@clankmates/cli 0.11.1 → 0.13.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 (49) hide show
  1. package/README.md +7 -3
  2. package/package.json +1 -1
  3. package/skills/codex/clankmates/SKILL.md +4 -3
  4. package/src/commands/auth/access-keys.ts +206 -0
  5. package/src/commands/auth.ts +3 -196
  6. package/src/commands/channel/render.ts +224 -0
  7. package/src/commands/channel/tokens.ts +145 -0
  8. package/src/commands/channel/validation.ts +11 -0
  9. package/src/commands/channel.ts +11 -340
  10. package/src/commands/doctor/checks.ts +123 -0
  11. package/src/commands/doctor/render.ts +140 -0
  12. package/src/commands/doctor/suggestions.ts +42 -0
  13. package/src/commands/doctor/types.ts +75 -0
  14. package/src/commands/doctor.ts +12 -371
  15. package/src/commands/feed.ts +19 -178
  16. package/src/commands/inbox/content.ts +31 -0
  17. package/src/commands/inbox/filters.ts +70 -0
  18. package/src/commands/inbox/messages.ts +69 -0
  19. package/src/commands/inbox/participants.ts +152 -0
  20. package/src/commands/inbox/render.ts +13 -0
  21. package/src/commands/inbox/resource-output.ts +217 -0
  22. package/src/commands/inbox/schema.ts +185 -0
  23. package/src/commands/inbox/screening.ts +76 -0
  24. package/src/commands/inbox/sync-scopes.ts +59 -0
  25. package/src/commands/inbox/thread-output.ts +344 -0
  26. package/src/commands/inbox/watch.ts +203 -0
  27. package/src/commands/inbox.ts +58 -1220
  28. package/src/commands/post.ts +24 -116
  29. package/src/lib/args.ts +8 -0
  30. package/src/lib/cache/scopes.ts +216 -0
  31. package/src/lib/cache/store.ts +195 -0
  32. package/src/lib/cache/types.ts +31 -0
  33. package/src/lib/cache.ts +18 -382
  34. package/src/lib/client/auth.ts +122 -0
  35. package/src/lib/client/channel-keys.ts +57 -0
  36. package/src/lib/client/channels.ts +364 -0
  37. package/src/lib/client/core.ts +133 -0
  38. package/src/lib/client/feed.ts +76 -0
  39. package/src/lib/client/inbox.ts +361 -0
  40. package/src/lib/client/posts.ts +213 -0
  41. package/src/lib/client/raw-api.ts +33 -0
  42. package/src/lib/client/users.ts +88 -0
  43. package/src/lib/client.ts +197 -894
  44. package/src/lib/help.ts +66 -9
  45. package/src/lib/json_api.ts +74 -9
  46. package/src/lib/pagination.ts +5 -0
  47. package/src/lib/polling.ts +146 -0
  48. package/src/lib/post-output.ts +55 -0
  49. package/src/types/api.ts +1 -0
@@ -0,0 +1,361 @@
1
+ import type {
2
+ ChangeCheckResponse,
3
+ ExternalEmailIntakeAttributes,
4
+ InboxRecipient,
5
+ InboxSender,
6
+ LatestFirstOrder,
7
+ MailboxFilter,
8
+ MessageAttachmentAttributes,
9
+ MessageAttributes,
10
+ ParticipantScope,
11
+ ThreadAttributes,
12
+ ThreadStatusFilter,
13
+ } from "../../types/api";
14
+ import { API_PREFIX, withQuery, type ApiClientCore } from "./core";
15
+
16
+ export async function listInboxThreads(
17
+ core: ApiClientCore,
18
+ input: {
19
+ status?: ThreadStatusFilter;
20
+ mailbox?: MailboxFilter;
21
+ limit?: number;
22
+ cursor?: string;
23
+ before?: string;
24
+ order?: LatestFirstOrder;
25
+ since?: string;
26
+ participant?: string;
27
+ participantScope?: ParticipantScope;
28
+ query?: string;
29
+ hasAttachment?: boolean;
30
+ channelToken?: string;
31
+ } = {},
32
+ ) {
33
+ return core.requestCollection<ThreadAttributes>(
34
+ withQuery(`${API_PREFIX}/threads`, {
35
+ status: input.status,
36
+ mailbox: input.mailbox,
37
+ order: input.order,
38
+ since: input.since,
39
+ before: input.before,
40
+ participant: input.participant,
41
+ participant_scope: input.participantScope,
42
+ query: input.query,
43
+ has_attachment: input.hasAttachment,
44
+ "page[limit]": input.limit,
45
+ "page[after]": input.cursor,
46
+ }),
47
+ {
48
+ token: core.resolveInboxReadToken(input.channelToken),
49
+ },
50
+ );
51
+ }
52
+
53
+ export async function checkInboxThreadChanges(
54
+ core: ApiClientCore,
55
+ input: {
56
+ since: string;
57
+ status?: ThreadStatusFilter;
58
+ mailbox?: MailboxFilter;
59
+ participant?: string;
60
+ participantScope?: ParticipantScope;
61
+ query?: string;
62
+ hasAttachment?: boolean;
63
+ channelToken?: string;
64
+ },
65
+ ) {
66
+ return core.requestAction<ChangeCheckResponse>(
67
+ withQuery(`${API_PREFIX}/threads/changes`, {
68
+ since: input.since,
69
+ status: input.status,
70
+ mailbox: input.mailbox,
71
+ participant: input.participant,
72
+ participant_scope: input.participantScope,
73
+ query: input.query,
74
+ has_attachment: input.hasAttachment,
75
+ }),
76
+ {
77
+ token: core.resolveInboxReadToken(input.channelToken),
78
+ },
79
+ );
80
+ }
81
+
82
+ export async function getThread(
83
+ core: ApiClientCore,
84
+ threadId: string,
85
+ channelToken?: string,
86
+ ) {
87
+ return core.requestResource<ThreadAttributes>(`${API_PREFIX}/threads/${threadId}`, {
88
+ token: core.resolveInboxReadToken(channelToken),
89
+ });
90
+ }
91
+
92
+ export async function listMessagesForThread(
93
+ core: ApiClientCore,
94
+ input: {
95
+ threadId: string;
96
+ limit?: number;
97
+ cursor?: string;
98
+ before?: string;
99
+ order?: LatestFirstOrder;
100
+ since?: string;
101
+ query?: string;
102
+ hasAttachment?: boolean;
103
+ channelToken?: string;
104
+ },
105
+ ) {
106
+ return core.requestCollection<MessageAttributes>(
107
+ withQuery(`${API_PREFIX}/threads/${input.threadId}/messages`, {
108
+ order: input.order,
109
+ since: input.since,
110
+ before: input.before,
111
+ query: input.query,
112
+ has_attachment: input.hasAttachment,
113
+ "page[limit]": input.limit,
114
+ "page[after]": input.cursor,
115
+ }),
116
+ {
117
+ token: core.resolveInboxReadToken(input.channelToken),
118
+ },
119
+ );
120
+ }
121
+
122
+ export async function checkThreadMessageChanges(
123
+ core: ApiClientCore,
124
+ input: {
125
+ threadId: string;
126
+ since: string;
127
+ query?: string;
128
+ hasAttachment?: boolean;
129
+ channelToken?: string;
130
+ },
131
+ ) {
132
+ return core.requestAction<ChangeCheckResponse>(
133
+ withQuery(`${API_PREFIX}/threads/${input.threadId}/messages/changes`, {
134
+ since: input.since,
135
+ query: input.query,
136
+ has_attachment: input.hasAttachment,
137
+ }),
138
+ {
139
+ token: core.resolveInboxReadToken(input.channelToken),
140
+ },
141
+ );
142
+ }
143
+
144
+ export async function listMessageAttachments(
145
+ core: ApiClientCore,
146
+ input: {
147
+ messageId: string;
148
+ limit?: number;
149
+ cursor?: string;
150
+ channelToken?: string;
151
+ },
152
+ ) {
153
+ return core.requestCollection<MessageAttachmentAttributes>(
154
+ withQuery(`${API_PREFIX}/messages/${input.messageId}/attachments`, {
155
+ "page[limit]": input.limit,
156
+ "page[after]": input.cursor,
157
+ }),
158
+ {
159
+ token: core.resolveInboxReadToken(input.channelToken),
160
+ },
161
+ );
162
+ }
163
+
164
+ export async function listEmailScreeningIntakes(
165
+ core: ApiClientCore,
166
+ input: {
167
+ limit?: number;
168
+ cursor?: string;
169
+ channelToken?: string;
170
+ } = {},
171
+ ) {
172
+ return core.requestCollection<ExternalEmailIntakeAttributes>(
173
+ withQuery(`${API_PREFIX}/email-intakes/screening`, {
174
+ "page[limit]": input.limit,
175
+ "page[after]": input.cursor,
176
+ }),
177
+ {
178
+ token: core.resolveInboxReadToken(input.channelToken),
179
+ },
180
+ );
181
+ }
182
+
183
+ export async function listEmailProcessingIntakes(
184
+ core: ApiClientCore,
185
+ input: {
186
+ limit?: number;
187
+ cursor?: string;
188
+ channelToken?: string;
189
+ } = {},
190
+ ) {
191
+ return core.requestCollection<ExternalEmailIntakeAttributes>(
192
+ withQuery(`${API_PREFIX}/email-intakes/processing`, {
193
+ "page[limit]": input.limit,
194
+ "page[after]": input.cursor,
195
+ }),
196
+ {
197
+ token: core.resolveInboxReadToken(input.channelToken),
198
+ },
199
+ );
200
+ }
201
+
202
+ export async function createThread(
203
+ core: ApiClientCore,
204
+ input: {
205
+ recipient: InboxRecipient;
206
+ body?: string;
207
+ payload?: Record<string, unknown>;
208
+ from?: InboxSender;
209
+ contextPostId?: string;
210
+ channelToken?: string;
211
+ },
212
+ ) {
213
+ return core.requestResource<ThreadAttributes>(`${API_PREFIX}/threads`, {
214
+ method: "POST",
215
+ token: core.resolveInboxWriteToken(input.channelToken),
216
+ body: {
217
+ data: {
218
+ type: "thread",
219
+ attributes: {
220
+ recipient: input.recipient,
221
+ ...(input.body !== undefined ? { body: input.body } : {}),
222
+ ...(input.payload !== undefined ? { payload: input.payload } : {}),
223
+ ...(input.from ? { from: input.from } : {}),
224
+ ...(input.contextPostId
225
+ ? { context_post_id: input.contextPostId }
226
+ : {}),
227
+ },
228
+ },
229
+ },
230
+ });
231
+ }
232
+
233
+ export async function appendThreadMessage(
234
+ core: ApiClientCore,
235
+ input: {
236
+ threadId: string;
237
+ body?: string;
238
+ payload?: Record<string, unknown>;
239
+ from?: InboxSender;
240
+ contextPostId?: string;
241
+ channelToken?: string;
242
+ },
243
+ ) {
244
+ return core.requestResource<ThreadAttributes>(
245
+ `${API_PREFIX}/threads/${input.threadId}/messages`,
246
+ {
247
+ method: "POST",
248
+ token: core.resolveInboxWriteToken(input.channelToken),
249
+ body: {
250
+ data: {
251
+ type: "thread",
252
+ attributes: {
253
+ ...(input.body !== undefined ? { body: input.body } : {}),
254
+ ...(input.payload !== undefined ? { payload: input.payload } : {}),
255
+ ...(input.from ? { from: input.from } : {}),
256
+ ...(input.contextPostId
257
+ ? { context_post_id: input.contextPostId }
258
+ : {}),
259
+ },
260
+ },
261
+ },
262
+ },
263
+ );
264
+ }
265
+
266
+ export async function markThreadSeen(
267
+ core: ApiClientCore,
268
+ input: { threadId: string; channelToken?: string },
269
+ ) {
270
+ return updateThreadLifecycle(core, `${API_PREFIX}/threads/${input.threadId}/seen`, input);
271
+ }
272
+
273
+ export async function archiveThread(
274
+ core: ApiClientCore,
275
+ input: { threadId: string; channelToken?: string },
276
+ ) {
277
+ return updateThreadLifecycle(core, `${API_PREFIX}/threads/${input.threadId}/archive`, input);
278
+ }
279
+
280
+ export async function resolveThread(
281
+ core: ApiClientCore,
282
+ input: { threadId: string; channelToken?: string },
283
+ ) {
284
+ return updateThreadLifecycle(core, `${API_PREFIX}/threads/${input.threadId}/resolve`, input);
285
+ }
286
+
287
+ export async function blockThread(
288
+ core: ApiClientCore,
289
+ input: { threadId: string; channelToken?: string },
290
+ ) {
291
+ return updateThreadLifecycle(core, `${API_PREFIX}/threads/${input.threadId}/block`, input);
292
+ }
293
+
294
+ export async function approveEmailIntake(
295
+ core: ApiClientCore,
296
+ input: { intakeId: string; channelToken?: string },
297
+ ) {
298
+ return updateEmailIntake(
299
+ core,
300
+ `${API_PREFIX}/email-intakes/${input.intakeId}/approve`,
301
+ input,
302
+ );
303
+ }
304
+
305
+ export async function approveEmailIntakeOnce(
306
+ core: ApiClientCore,
307
+ input: { intakeId: string; channelToken?: string },
308
+ ) {
309
+ return updateEmailIntake(
310
+ core,
311
+ `${API_PREFIX}/email-intakes/${input.intakeId}/approve-once`,
312
+ input,
313
+ );
314
+ }
315
+
316
+ export async function ignoreEmailIntake(
317
+ core: ApiClientCore,
318
+ input: { intakeId: string; channelToken?: string },
319
+ ) {
320
+ return updateEmailIntake(
321
+ core,
322
+ `${API_PREFIX}/email-intakes/${input.intakeId}/ignore`,
323
+ input,
324
+ );
325
+ }
326
+
327
+ async function updateThreadLifecycle(
328
+ core: ApiClientCore,
329
+ path: string,
330
+ input: { threadId: string; channelToken?: string },
331
+ ) {
332
+ return core.requestResource<ThreadAttributes>(path, {
333
+ method: "PATCH",
334
+ token: core.resolveInboxWriteToken(input.channelToken),
335
+ body: {
336
+ data: {
337
+ type: "thread",
338
+ id: input.threadId,
339
+ attributes: {},
340
+ },
341
+ },
342
+ });
343
+ }
344
+
345
+ async function updateEmailIntake(
346
+ core: ApiClientCore,
347
+ path: string,
348
+ input: { intakeId: string; channelToken?: string },
349
+ ) {
350
+ return core.requestResource<ExternalEmailIntakeAttributes>(path, {
351
+ method: "PATCH",
352
+ token: core.resolveInboxWriteToken(input.channelToken),
353
+ body: {
354
+ data: {
355
+ type: "external_email_intake",
356
+ id: input.intakeId,
357
+ attributes: {},
358
+ },
359
+ },
360
+ });
361
+ }
@@ -0,0 +1,213 @@
1
+ import { CliError } from "../errors";
2
+ import {
3
+ requireMasterToken,
4
+ requireOwnerReadToken,
5
+ resolvePublishToken,
6
+ } from "../tokens";
7
+ import type {
8
+ IdResponse,
9
+ LatestFirstOrder,
10
+ PostAttributes,
11
+ ShareTokenResponse,
12
+ } from "../../types/api";
13
+ import { API_PREFIX, withQuery, type ApiClientCore } from "./core";
14
+
15
+ export async function publishPost(
16
+ core: ApiClientCore,
17
+ input: {
18
+ channelId: string;
19
+ body: string;
20
+ channelToken?: string;
21
+ },
22
+ ) {
23
+ const resolved = resolvePublishToken(
24
+ core.profile,
25
+ input.channelId,
26
+ input.channelToken,
27
+ );
28
+
29
+ if (!resolved.token) {
30
+ throw new CliError(
31
+ `No publish token available for channel ${input.channelId}. Provide --channel-token, set channel token env vars, save a channel token, or configure a master token.`,
32
+ );
33
+ }
34
+
35
+ return core.requestResource<PostAttributes>(
36
+ `${API_PREFIX}/channels/${input.channelId}/posts`,
37
+ {
38
+ method: "POST",
39
+ token: resolved.token,
40
+ body: {
41
+ data: {
42
+ type: "post",
43
+ attributes: {
44
+ body: input.body,
45
+ },
46
+ },
47
+ },
48
+ },
49
+ );
50
+ }
51
+
52
+ export async function listChannelPosts(
53
+ core: ApiClientCore,
54
+ input: {
55
+ channelId: string;
56
+ limit?: number;
57
+ cursor?: string;
58
+ before?: string;
59
+ order?: LatestFirstOrder;
60
+ since?: string;
61
+ },
62
+ ) {
63
+ return core.requestCollection<PostAttributes>(
64
+ withQuery(`${API_PREFIX}/channels/${input.channelId}/posts`, {
65
+ order: input.order,
66
+ since: input.since,
67
+ before: input.before,
68
+ "page[limit]": input.limit,
69
+ "page[after]": input.cursor,
70
+ }),
71
+ {
72
+ token: requireOwnerReadToken(core.profile),
73
+ },
74
+ );
75
+ }
76
+
77
+ export async function listPublicChannelPosts(
78
+ core: ApiClientCore,
79
+ input: {
80
+ publicHandle: string;
81
+ channelName: string;
82
+ limit?: number;
83
+ cursor?: string;
84
+ before?: string;
85
+ order?: LatestFirstOrder;
86
+ since?: string;
87
+ },
88
+ ) {
89
+ return core.requestCollection<PostAttributes>(
90
+ withQuery(
91
+ `${API_PREFIX}/public/users/${encodeURIComponent(input.publicHandle)}/channels/${encodeURIComponent(input.channelName)}/posts`,
92
+ {
93
+ order: input.order,
94
+ since: input.since,
95
+ before: input.before,
96
+ "page[limit]": input.limit,
97
+ "page[after]": input.cursor,
98
+ },
99
+ ),
100
+ {},
101
+ );
102
+ }
103
+
104
+ export async function listSharedChannelPosts(
105
+ core: ApiClientCore,
106
+ input: {
107
+ token: string;
108
+ limit?: number;
109
+ cursor?: string;
110
+ before?: string;
111
+ order?: LatestFirstOrder;
112
+ since?: string;
113
+ },
114
+ ) {
115
+ return core.requestCollection<PostAttributes>(
116
+ withQuery(`${API_PREFIX}/shares/channels/${encodeURIComponent(input.token)}/posts`, {
117
+ order: input.order,
118
+ since: input.since,
119
+ before: input.before,
120
+ "page[limit]": input.limit,
121
+ "page[after]": input.cursor,
122
+ }),
123
+ {},
124
+ );
125
+ }
126
+
127
+ export async function getPost(core: ApiClientCore, postId: string) {
128
+ return core.requestResource<PostAttributes>(
129
+ `${API_PREFIX}/posts/${postId}`,
130
+ {
131
+ token: requireOwnerReadToken(core.profile),
132
+ },
133
+ );
134
+ }
135
+
136
+ export async function getPublicPostByHandle(
137
+ core: ApiClientCore,
138
+ input: {
139
+ publicHandle: string;
140
+ channelName: string;
141
+ postId: string;
142
+ },
143
+ ) {
144
+ return core.requestResource<PostAttributes>(
145
+ `${API_PREFIX}/public/users/${encodeURIComponent(input.publicHandle)}/channels/${encodeURIComponent(input.channelName)}/posts/${input.postId}`,
146
+ {},
147
+ );
148
+ }
149
+
150
+ export async function getSharedPost(core: ApiClientCore, token: string) {
151
+ return core.requestResource<PostAttributes>(
152
+ `${API_PREFIX}/shares/posts/${encodeURIComponent(token)}`,
153
+ {},
154
+ );
155
+ }
156
+
157
+ export async function editPost(
158
+ core: ApiClientCore,
159
+ input: {
160
+ postId: string;
161
+ body: string;
162
+ channelToken?: string;
163
+ },
164
+ ) {
165
+ const token = core.resolvePostLifecycleToken(input.channelToken);
166
+
167
+ return core.requestResource<PostAttributes>(
168
+ `${API_PREFIX}/posts/${input.postId}`,
169
+ {
170
+ method: "PATCH",
171
+ token,
172
+ body: {
173
+ data: {
174
+ type: "post",
175
+ id: input.postId,
176
+ attributes: {
177
+ body: input.body,
178
+ },
179
+ },
180
+ },
181
+ },
182
+ );
183
+ }
184
+
185
+ export async function deletePost(
186
+ core: ApiClientCore,
187
+ input: {
188
+ postId: string;
189
+ channelToken?: string;
190
+ },
191
+ ): Promise<void> {
192
+ const token = core.resolvePostLifecycleToken(input.channelToken);
193
+
194
+ await core.requestJsonApi(`${API_PREFIX}/posts/${input.postId}`, {
195
+ method: "DELETE",
196
+ token,
197
+ });
198
+ }
199
+
200
+ export async function sharePost(core: ApiClientCore, postId: string) {
201
+ return core.requestAction<ShareTokenResponse>(`${API_PREFIX}/posts/${postId}/share`, {
202
+ method: "POST",
203
+ token: requireMasterToken(core.profile),
204
+ body: { data: {} },
205
+ });
206
+ }
207
+
208
+ export async function revokePostShare(core: ApiClientCore, postId: string) {
209
+ return core.requestAction<IdResponse>(`${API_PREFIX}/posts/${postId}/share`, {
210
+ method: "DELETE",
211
+ token: requireMasterToken(core.profile),
212
+ });
213
+ }
@@ -0,0 +1,33 @@
1
+ import { requestJson } from "../http";
2
+ import { resolveMasterToken } from "../tokens";
3
+ import {
4
+ API_PREFIX,
5
+ inferMediaType,
6
+ type ApiClientCore,
7
+ } from "./core";
8
+
9
+ export async function fetchOpenApi(core: ApiClientCore): Promise<unknown> {
10
+ return (await requestJson(core.profile.baseUrl, `${API_PREFIX}/open_api`))
11
+ .data;
12
+ }
13
+
14
+ export async function apiRequest(
15
+ core: ApiClientCore,
16
+ input: {
17
+ method: string;
18
+ path: string;
19
+ body?: string;
20
+ channelToken?: string;
21
+ },
22
+ ): Promise<unknown> {
23
+ return (
24
+ await requestJson(core.profile.baseUrl, input.path, {
25
+ method: input.method,
26
+ token: input.channelToken ?? resolveMasterToken(core.profile).token,
27
+ rawBody: input.body,
28
+ accept: inferMediaType(input.path),
29
+ contentType:
30
+ input.body === undefined ? undefined : inferMediaType(input.path),
31
+ })
32
+ ).data;
33
+ }
@@ -0,0 +1,88 @@
1
+ import { requireMasterToken } from "../tokens";
2
+ import type {
3
+ ExternalEmailAcceptance,
4
+ UserAttributes,
5
+ } from "../../types/api";
6
+ import {
7
+ API_PREFIX,
8
+ withRepeatedQuery,
9
+ type ApiClientCore,
10
+ } from "./core";
11
+
12
+ export async function getUserByPublicHandle(
13
+ core: ApiClientCore,
14
+ publicHandle: string,
15
+ ) {
16
+ return core.requestResource<UserAttributes>(
17
+ `${API_PREFIX}/public/users/${encodeURIComponent(publicHandle)}`,
18
+ {},
19
+ );
20
+ }
21
+
22
+ export async function getPublicAccountInboxSchema(
23
+ core: ApiClientCore,
24
+ publicHandle: string,
25
+ ) {
26
+ return core.requestResource<UserAttributes>(
27
+ `${API_PREFIX}/public/users/${encodeURIComponent(publicHandle)}/inbox-schema`,
28
+ {},
29
+ );
30
+ }
31
+
32
+ export async function setAccountInboxSchema(
33
+ core: ApiClientCore,
34
+ inboxSchema: Record<string, unknown>,
35
+ ) {
36
+ return core.requestResource<UserAttributes>(`${API_PREFIX}/me/inbox-schema`, {
37
+ method: "PATCH",
38
+ token: requireMasterToken(core.profile),
39
+ body: {
40
+ data: {
41
+ type: "user",
42
+ attributes: {
43
+ inbox_schema: inboxSchema,
44
+ },
45
+ },
46
+ },
47
+ });
48
+ }
49
+
50
+ export async function removeAccountInboxSchema(core: ApiClientCore) {
51
+ return core.requestResource<UserAttributes>(
52
+ `${API_PREFIX}/me/inbox-schema/remove`,
53
+ {
54
+ method: "PATCH",
55
+ token: requireMasterToken(core.profile),
56
+ body: {
57
+ data: {
58
+ type: "user",
59
+ attributes: {},
60
+ },
61
+ },
62
+ },
63
+ );
64
+ }
65
+
66
+ export async function setAccountExternalEmailAcceptance(
67
+ core: ApiClientCore,
68
+ externalEmailAcceptance: ExternalEmailAcceptance,
69
+ ) {
70
+ return core.requestResource<UserAttributes>(`${API_PREFIX}/me/inbox-acceptance`, {
71
+ method: "PATCH",
72
+ token: requireMasterToken(core.profile),
73
+ body: {
74
+ data: {
75
+ type: "user",
76
+ attributes: {
77
+ external_email_acceptance: externalEmailAcceptance,
78
+ },
79
+ },
80
+ },
81
+ });
82
+ }
83
+
84
+ export async function listPublicUsersById(core: ApiClientCore, ids: string[]) {
85
+ const path = withRepeatedQuery(`${API_PREFIX}/public/users/by-id`, "ids[]", ids);
86
+
87
+ return core.requestCollection<UserAttributes>(path, {});
88
+ }