@inline-openclaw/inline 0.0.5 → 0.0.7

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.
@@ -1,19 +1,43 @@
1
- import { jsonResult, readReactionParams, readNumberParam, readStringParam, } from "openclaw/plugin-sdk";
2
- import { InlineSdkClient, Method } from "@inline-chat/realtime-sdk";
1
+ import { createActionGate, jsonResult, readReactionParams, readNumberParam, readStringParam, } from "openclaw/plugin-sdk";
2
+ import { InlineSdkClient, Method, Member_Role, } from "@inline-chat/realtime-sdk";
3
3
  import { resolveInlineAccount, resolveInlineToken } from "./accounts.js";
4
4
  import { normalizeInlineTarget } from "./normalize.js";
5
- const ACTIONS = [
6
- "reply",
7
- "react",
8
- "reactions",
9
- "read",
10
- "search",
11
- "edit",
12
- "channel-info",
13
- "channel-edit",
14
- "addParticipant",
15
- "member-info",
5
+ const ACTION_GROUPS = [
6
+ { key: "reply", defaultEnabled: true, actions: ["reply"] },
7
+ { key: "reactions", defaultEnabled: true, actions: ["react", "reactions"] },
8
+ { key: "read", defaultEnabled: true, actions: ["read"] },
9
+ { key: "search", defaultEnabled: true, actions: ["search"] },
10
+ { key: "edit", defaultEnabled: true, actions: ["edit"] },
11
+ {
12
+ key: "channels",
13
+ defaultEnabled: true,
14
+ actions: [
15
+ "channel-info",
16
+ "channel-edit",
17
+ "channel-list",
18
+ "channel-create",
19
+ "channel-delete",
20
+ "channel-move",
21
+ "thread-list",
22
+ "thread-create",
23
+ ],
24
+ },
25
+ {
26
+ key: "participants",
27
+ defaultEnabled: true,
28
+ actions: ["addParticipant", "removeParticipant", "leaveGroup", "member-info"],
29
+ },
30
+ { key: "delete", defaultEnabled: true, actions: ["delete", "unsend"] },
31
+ { key: "pins", defaultEnabled: true, actions: ["pin", "unpin", "list-pins"] },
32
+ { key: "permissions", defaultEnabled: true, actions: ["permissions"] },
16
33
  ];
34
+ const ACTION_TO_GATE_KEY = new Map();
35
+ for (const group of ACTION_GROUPS) {
36
+ for (const action of group.actions) {
37
+ ACTION_TO_GATE_KEY.set(action, group.key);
38
+ }
39
+ }
40
+ const SUPPORTED_ACTIONS = Array.from(ACTION_TO_GATE_KEY.keys());
17
41
  function normalizeChatId(raw) {
18
42
  const normalized = normalizeInlineTarget(raw) ?? raw.trim();
19
43
  if (!/^[0-9]+$/.test(normalized)) {
@@ -36,11 +60,28 @@ function readFlexibleId(params, key) {
36
60
  }
37
61
  return undefined;
38
62
  }
63
+ function readBooleanParam(params, key) {
64
+ const value = params[key];
65
+ if (typeof value === "boolean")
66
+ return value;
67
+ if (typeof value === "string") {
68
+ const trimmed = value.trim().toLowerCase();
69
+ if (trimmed === "true")
70
+ return true;
71
+ if (trimmed === "false")
72
+ return false;
73
+ }
74
+ return undefined;
75
+ }
39
76
  function parseInlineId(raw, label) {
40
- if (typeof raw === "bigint")
77
+ if (typeof raw === "bigint") {
78
+ if (raw < 0n) {
79
+ throw new Error(`inline action: invalid ${label} "${raw.toString()}"`);
80
+ }
41
81
  return raw;
82
+ }
42
83
  if (typeof raw === "number") {
43
- if (!Number.isFinite(raw) || !Number.isInteger(raw)) {
84
+ if (!Number.isFinite(raw) || !Number.isInteger(raw) || raw < 0) {
44
85
  throw new Error(`inline action: invalid ${label} "${String(raw)}"`);
45
86
  }
46
87
  return BigInt(raw);
@@ -62,6 +103,149 @@ function parseOptionalInlineId(raw, label) {
62
103
  return undefined;
63
104
  return parseInlineId(raw, label);
64
105
  }
106
+ function parseInlineIdList(raw, label) {
107
+ if (raw == null)
108
+ return [];
109
+ if (Array.isArray(raw)) {
110
+ return raw.map((item) => parseInlineId(item, label));
111
+ }
112
+ if (typeof raw === "string") {
113
+ const trimmed = raw.trim();
114
+ if (!trimmed)
115
+ return [];
116
+ const chunks = trimmed
117
+ .split(",")
118
+ .map((item) => item.trim())
119
+ .filter(Boolean);
120
+ if (chunks.length <= 1) {
121
+ return [parseInlineId(trimmed, label)];
122
+ }
123
+ return chunks.map((item) => parseInlineId(item, label));
124
+ }
125
+ return [parseInlineId(raw, label)];
126
+ }
127
+ function parseInlineIdListFromParams(params, key) {
128
+ const direct = params[key];
129
+ if (direct != null) {
130
+ return parseInlineIdList(direct, key);
131
+ }
132
+ return [];
133
+ }
134
+ function parseInlineListValue(raw, label) {
135
+ if (raw == null)
136
+ return [];
137
+ if (Array.isArray(raw)) {
138
+ return raw.flatMap((entry) => parseInlineListValue(entry, label));
139
+ }
140
+ if (typeof raw === "bigint")
141
+ return [raw.toString()];
142
+ if (typeof raw === "number") {
143
+ if (!Number.isFinite(raw) || !Number.isInteger(raw) || raw < 0) {
144
+ throw new Error(`inline action: invalid ${label} "${String(raw)}"`);
145
+ }
146
+ return [String(raw)];
147
+ }
148
+ if (typeof raw === "string") {
149
+ const trimmed = raw.trim();
150
+ if (!trimmed)
151
+ return [];
152
+ return trimmed
153
+ .split(",")
154
+ .map((entry) => entry.trim())
155
+ .filter(Boolean);
156
+ }
157
+ throw new Error(`inline action: invalid ${label}`);
158
+ }
159
+ function parseInlineListValuesFromParams(params, keys) {
160
+ const entries = keys.flatMap((key) => parseInlineListValue(params[key], key));
161
+ return Array.from(new Set(entries.map((entry) => entry.trim()).filter(Boolean)));
162
+ }
163
+ function normalizeInlineUserLookupToken(raw) {
164
+ return raw
165
+ .trim()
166
+ .replace(/^inline:/i, "")
167
+ .replace(/^user:/i, "")
168
+ .replace(/^@/, "")
169
+ .trim();
170
+ }
171
+ function parseInlineIdIfNumericToken(raw) {
172
+ const normalized = normalizeInlineUserLookupToken(raw);
173
+ if (!/^[0-9]+$/.test(normalized))
174
+ return undefined;
175
+ return BigInt(normalized);
176
+ }
177
+ function buildInlineUserHaystack(user) {
178
+ return [
179
+ String(user.id),
180
+ buildInlineUserDisplayName(user),
181
+ user.firstName ?? "",
182
+ user.lastName ?? "",
183
+ user.username ?? "",
184
+ ]
185
+ .join("\n")
186
+ .toLowerCase();
187
+ }
188
+ function resolveInlineUsersByToken(params) {
189
+ const normalized = normalizeInlineUserLookupToken(params.token);
190
+ if (!normalized)
191
+ return [];
192
+ const lowered = normalized.toLowerCase();
193
+ const numericId = parseInlineIdIfNumericToken(normalized);
194
+ if (numericId != null) {
195
+ return params.users.filter((user) => user.id === numericId);
196
+ }
197
+ const byUsername = params.users.filter((user) => (user.username ?? "").trim().toLowerCase() === lowered);
198
+ if (byUsername.length > 0) {
199
+ return byUsername;
200
+ }
201
+ const byExactName = params.users.filter((user) => buildInlineUserDisplayName(user).trim().toLowerCase() === lowered);
202
+ if (byExactName.length > 0) {
203
+ return byExactName;
204
+ }
205
+ return params.users.filter((user) => buildInlineUserHaystack(user).includes(lowered));
206
+ }
207
+ async function fetchInlineUsersForResolution(client) {
208
+ const result = await client.invokeRaw(Method.GET_CHATS, {
209
+ oneofKind: "getChats",
210
+ getChats: {},
211
+ });
212
+ if (result.oneofKind !== "getChats") {
213
+ throw new Error(`inline action: expected getChats result, got ${String(result.oneofKind)}`);
214
+ }
215
+ return result.getChats.users ?? [];
216
+ }
217
+ async function resolveInlineUserIdsFromParams(params) {
218
+ if (params.values.length === 0)
219
+ return [];
220
+ const resolved = [];
221
+ const unresolved = [];
222
+ for (const value of params.values) {
223
+ const numericId = parseInlineIdIfNumericToken(value);
224
+ if (numericId != null) {
225
+ resolved.push(numericId);
226
+ continue;
227
+ }
228
+ unresolved.push(value);
229
+ }
230
+ if (unresolved.length > 0) {
231
+ const users = await fetchInlineUsersForResolution(params.client);
232
+ for (const token of unresolved) {
233
+ const matches = resolveInlineUsersByToken({ users, token });
234
+ if (matches.length === 0) {
235
+ throw new Error(`inline action: could not resolve ${params.label} "${token}"`);
236
+ }
237
+ if (matches.length > 1) {
238
+ throw new Error(`inline action: ambiguous ${params.label} "${token}"`);
239
+ }
240
+ const match = matches[0];
241
+ if (!match) {
242
+ throw new Error(`inline action: could not resolve ${params.label} "${token}"`);
243
+ }
244
+ resolved.push(match.id);
245
+ }
246
+ }
247
+ return Array.from(new Set(resolved.map((id) => id.toString()))).map((id) => BigInt(id));
248
+ }
65
249
  function resolveChatIdFromParams(params) {
66
250
  const raw = readFlexibleId(params, "chatId") ??
67
251
  readFlexibleId(params, "channelId") ??
@@ -80,6 +264,15 @@ function buildChatPeer(chatId) {
80
264
  },
81
265
  };
82
266
  }
267
+ function buildInlineUserDisplayName(user) {
268
+ const explicit = [user.firstName?.trim(), user.lastName?.trim()].filter(Boolean).join(" ");
269
+ if (explicit)
270
+ return explicit;
271
+ const username = user.username?.trim();
272
+ if (username)
273
+ return `@${username}`;
274
+ return "Unknown";
275
+ }
83
276
  function mapMessage(message) {
84
277
  const reactions = (message.reactions?.reactions ?? []).map((reaction) => ({
85
278
  emoji: reaction.emoji ?? "",
@@ -98,19 +291,52 @@ function mapMessage(message) {
98
291
  reactions,
99
292
  };
100
293
  }
294
+ function mapChatEntry(params) {
295
+ const dialog = params.dialogByChatId.get(String(params.chat.id));
296
+ const peer = params.chat.peerId?.type;
297
+ let peerUser = null;
298
+ if (peer?.oneofKind === "user") {
299
+ peerUser = params.usersById.get(String(peer.user.userId)) ?? null;
300
+ }
301
+ return {
302
+ id: String(params.chat.id),
303
+ title: params.chat.title,
304
+ spaceId: params.chat.spaceId != null ? String(params.chat.spaceId) : null,
305
+ isPublic: params.chat.isPublic ?? false,
306
+ createdBy: params.chat.createdBy != null ? String(params.chat.createdBy) : null,
307
+ date: params.chat.date != null ? Number(params.chat.date) * 1000 : null,
308
+ unreadCount: dialog?.unreadCount ?? 0,
309
+ archived: Boolean(dialog?.archived),
310
+ pinned: Boolean(dialog?.pinned),
311
+ peer: peer?.oneofKind === "user"
312
+ ? {
313
+ kind: "user",
314
+ id: String(peer.user.userId),
315
+ username: peerUser?.username ?? null,
316
+ name: peerUser ? buildInlineUserDisplayName(peerUser) : null,
317
+ }
318
+ : peer?.oneofKind === "chat"
319
+ ? { kind: "chat", id: String(peer.chat.chatId) }
320
+ : null,
321
+ };
322
+ }
323
+ function mapSpaceMemberRole(role) {
324
+ if (role == null)
325
+ return null;
326
+ if (role === Member_Role.OWNER)
327
+ return "owner";
328
+ if (role === Member_Role.ADMIN)
329
+ return "admin";
330
+ if (role === Member_Role.MEMBER)
331
+ return "member";
332
+ return null;
333
+ }
101
334
  async function loadMessageReactions(params) {
102
- const result = await params.client.invokeRaw(Method.GET_CHAT_HISTORY, {
103
- oneofKind: "getChatHistory",
104
- getChatHistory: {
105
- peerId: buildChatPeer(params.chatId),
106
- offsetId: params.messageId + 1n,
107
- limit: 8,
108
- },
335
+ const target = await findMessageById({
336
+ client: params.client,
337
+ chatId: params.chatId,
338
+ messageId: params.messageId,
109
339
  });
110
- if (result.oneofKind !== "getChatHistory") {
111
- throw new Error(`inline action: expected getChatHistory result, got ${String(result.oneofKind)}`);
112
- }
113
- const target = (result.getChatHistory.messages ?? []).find((message) => message.id === params.messageId) ?? null;
114
340
  if (!target) {
115
341
  return [];
116
342
  }
@@ -133,6 +359,32 @@ async function loadMessageReactions(params) {
133
359
  }
134
360
  return Array.from(byEmoji.values());
135
361
  }
362
+ async function findMessageById(params) {
363
+ const directResult = await params.client
364
+ .invokeRaw(Method.GET_MESSAGES, {
365
+ oneofKind: "getMessages",
366
+ getMessages: {
367
+ peerId: buildChatPeer(params.chatId),
368
+ messageIds: [params.messageId],
369
+ },
370
+ })
371
+ .catch(() => null);
372
+ if (directResult?.oneofKind === "getMessages") {
373
+ return (directResult.getMessages.messages ?? []).find((message) => message.id === params.messageId) ?? null;
374
+ }
375
+ const result = await params.client.invokeRaw(Method.GET_CHAT_HISTORY, {
376
+ oneofKind: "getChatHistory",
377
+ getChatHistory: {
378
+ peerId: buildChatPeer(params.chatId),
379
+ offsetId: params.messageId + 1n,
380
+ limit: 8,
381
+ },
382
+ });
383
+ if (result.oneofKind !== "getChatHistory") {
384
+ throw new Error(`inline action: expected getChatHistory result, got ${String(result.oneofKind)}`);
385
+ }
386
+ return (result.getChatHistory.messages ?? []).find((message) => message.id === params.messageId) ?? null;
387
+ }
136
388
  async function withInlineClient(params) {
137
389
  const account = resolveInlineAccount({ cfg: params.cfg, accountId: params.accountId ?? null });
138
390
  if (!account.configured || !account.baseUrl) {
@@ -165,14 +417,68 @@ function toJsonSafe(value) {
165
417
  }
166
418
  return value;
167
419
  }
420
+ function buildDialogMap(dialogs) {
421
+ const map = new Map();
422
+ for (const dialog of dialogs) {
423
+ const chatId = dialog.chatId;
424
+ if (chatId != null) {
425
+ map.set(String(chatId), dialog);
426
+ continue;
427
+ }
428
+ const peer = dialog.peer?.type;
429
+ if (peer?.oneofKind === "chat") {
430
+ map.set(String(peer.chat.chatId), dialog);
431
+ }
432
+ }
433
+ return map;
434
+ }
435
+ function buildUserMap(users) {
436
+ const map = new Map();
437
+ for (const user of users) {
438
+ map.set(String(user.id), user);
439
+ }
440
+ return map;
441
+ }
442
+ function listAllActions() {
443
+ const out = new Set();
444
+ for (const group of ACTION_GROUPS) {
445
+ for (const action of group.actions) {
446
+ out.add(action);
447
+ }
448
+ }
449
+ return Array.from(out);
450
+ }
451
+ function isActionEnabled(params) {
452
+ const key = ACTION_TO_GATE_KEY.get(params.action);
453
+ if (!key)
454
+ return false;
455
+ const group = ACTION_GROUPS.find((item) => item.key === key);
456
+ if (!group)
457
+ return false;
458
+ const account = resolveInlineAccount({
459
+ cfg: params.cfg,
460
+ accountId: params.accountId ?? null,
461
+ });
462
+ const gate = createActionGate((account.config.actions ?? {}));
463
+ return gate(key, group.defaultEnabled);
464
+ }
168
465
  export const inlineMessageActions = {
169
466
  listActions: ({ cfg }) => {
170
467
  const account = resolveInlineAccount({ cfg, accountId: null });
171
468
  if (!account.enabled || !account.configured)
172
469
  return [];
173
- return [...ACTIONS];
470
+ const gate = createActionGate((account.config.actions ?? {}));
471
+ const actions = new Set();
472
+ for (const group of ACTION_GROUPS) {
473
+ if (!gate(group.key, group.defaultEnabled))
474
+ continue;
475
+ for (const action of group.actions) {
476
+ actions.add(action);
477
+ }
478
+ }
479
+ return Array.from(actions);
174
480
  },
175
- supportsAction: ({ action }) => ACTIONS.includes(action),
481
+ supportsAction: ({ action }) => SUPPORTED_ACTIONS.includes(action),
176
482
  extractToolSend: ({ args }) => {
177
483
  const action = typeof args.action === "string" ? args.action.trim() : "";
178
484
  if (action !== "sendMessage")
@@ -186,7 +492,14 @@ export const inlineMessageActions = {
186
492
  return { to: normalized };
187
493
  },
188
494
  handleAction: async ({ action, params, cfg, accountId }) => {
189
- if (action === "reply") {
495
+ if (!SUPPORTED_ACTIONS.includes(action)) {
496
+ throw new Error(`Action ${action} is not supported for provider inline.`);
497
+ }
498
+ if (!isActionEnabled({ cfg, accountId: accountId ?? null, action })) {
499
+ throw new Error(`inline action: ${action} is disabled by channels.inline.actions`);
500
+ }
501
+ const normalizedAction = action;
502
+ if (normalizedAction === "reply") {
190
503
  const parseMarkdown = resolveInlineAccount({ cfg, accountId: accountId ?? null }).config.parseMarkdown ?? true;
191
504
  return await withInlineClient({
192
505
  cfg,
@@ -216,13 +529,14 @@ export const inlineMessageActions = {
216
529
  },
217
530
  });
218
531
  }
219
- if (action === "react") {
532
+ if (normalizedAction === "react") {
220
533
  return await withInlineClient({
221
534
  cfg,
222
535
  accountId,
223
536
  fn: async (client) => {
224
537
  const chatId = resolveChatIdFromParams(params);
225
- const messageId = parseInlineId(readFlexibleId(params, "messageId") ?? readStringParam(params, "messageId", { required: true }), "messageId");
538
+ const messageId = parseInlineId(readFlexibleId(params, "messageId") ??
539
+ readStringParam(params, "messageId", { required: true }), "messageId");
226
540
  const { emoji, remove, isEmpty } = readReactionParams(params, {
227
541
  removeErrorMessage: "Emoji is required to remove an Inline reaction.",
228
542
  });
@@ -265,13 +579,14 @@ export const inlineMessageActions = {
265
579
  },
266
580
  });
267
581
  }
268
- if (action === "reactions") {
582
+ if (normalizedAction === "reactions") {
269
583
  return await withInlineClient({
270
584
  cfg,
271
585
  accountId,
272
586
  fn: async (client) => {
273
587
  const chatId = resolveChatIdFromParams(params);
274
- const messageId = parseInlineId(readFlexibleId(params, "messageId") ?? readStringParam(params, "messageId", { required: true }), "messageId");
588
+ const messageId = parseInlineId(readFlexibleId(params, "messageId") ??
589
+ readStringParam(params, "messageId", { required: true }), "messageId");
275
590
  const reactions = await loadMessageReactions({
276
591
  client,
277
592
  chatId,
@@ -286,7 +601,7 @@ export const inlineMessageActions = {
286
601
  },
287
602
  });
288
603
  }
289
- if (action === "read") {
604
+ if (normalizedAction === "read") {
290
605
  return await withInlineClient({
291
606
  cfg,
292
607
  accountId,
@@ -313,7 +628,7 @@ export const inlineMessageActions = {
313
628
  },
314
629
  });
315
630
  }
316
- if (action === "search") {
631
+ if (normalizedAction === "search") {
317
632
  return await withInlineClient({
318
633
  cfg,
319
634
  accountId,
@@ -345,13 +660,14 @@ export const inlineMessageActions = {
345
660
  },
346
661
  });
347
662
  }
348
- if (action === "edit") {
663
+ if (normalizedAction === "edit") {
349
664
  return await withInlineClient({
350
665
  cfg,
351
666
  accountId,
352
667
  fn: async (client) => {
353
668
  const chatId = resolveChatIdFromParams(params);
354
- const messageId = parseInlineId(readFlexibleId(params, "messageId") ?? readStringParam(params, "messageId", { required: true }), "messageId");
669
+ const messageId = parseInlineId(readFlexibleId(params, "messageId") ??
670
+ readStringParam(params, "messageId", { required: true }), "messageId");
355
671
  const text = readStringParam(params, "message", { required: true, allowEmpty: true });
356
672
  const result = await client.invokeRaw(Method.EDIT_MESSAGE, {
357
673
  oneofKind: "editMessage",
@@ -368,7 +684,7 @@ export const inlineMessageActions = {
368
684
  },
369
685
  });
370
686
  }
371
- if (action === "channel-info") {
687
+ if (normalizedAction === "channel-info") {
372
688
  return await withInlineClient({
373
689
  cfg,
374
690
  accountId,
@@ -391,7 +707,7 @@ export const inlineMessageActions = {
391
707
  },
392
708
  });
393
709
  }
394
- if (action === "channel-edit") {
710
+ if (normalizedAction === "channel-edit") {
395
711
  return await withInlineClient({
396
712
  cfg,
397
713
  accountId,
@@ -399,6 +715,7 @@ export const inlineMessageActions = {
399
715
  const chatId = resolveChatIdFromParams(params);
400
716
  const title = readStringParam(params, "title") ??
401
717
  readStringParam(params, "name") ??
718
+ readStringParam(params, "threadName") ??
402
719
  readStringParam(params, "message", { required: true });
403
720
  const result = await client.invokeRaw(Method.UPDATE_CHAT_INFO, {
404
721
  oneofKind: "updateChatInfo",
@@ -419,16 +736,186 @@ export const inlineMessageActions = {
419
736
  },
420
737
  });
421
738
  }
422
- if (action === "addParticipant") {
739
+ if (normalizedAction === "channel-list" || normalizedAction === "thread-list") {
740
+ return await withInlineClient({
741
+ cfg,
742
+ accountId,
743
+ fn: async (client) => {
744
+ const query = readStringParam(params, "query") ??
745
+ readStringParam(params, "q") ??
746
+ undefined;
747
+ const limit = Math.max(1, Math.min(200, readNumberParam(params, "limit", { integer: true }) ?? 50));
748
+ const result = await client.invokeRaw(Method.GET_CHATS, {
749
+ oneofKind: "getChats",
750
+ getChats: {},
751
+ });
752
+ if (result.oneofKind !== "getChats") {
753
+ throw new Error(`inline action: expected getChats result, got ${String(result.oneofKind)}`);
754
+ }
755
+ const dialogByChatId = buildDialogMap(result.getChats.dialogs ?? []);
756
+ const usersById = buildUserMap(result.getChats.users ?? []);
757
+ const entries = (result.getChats.chats ?? []).map((chat) => mapChatEntry({ chat, dialogByChatId, usersById }));
758
+ const normalizedQuery = query?.trim().toLowerCase() ?? "";
759
+ const filtered = normalizedQuery
760
+ ? entries.filter((entry) => {
761
+ const haystack = [
762
+ entry.id,
763
+ entry.title,
764
+ entry.peer?.kind === "user" ? entry.peer.username ?? "" : "",
765
+ entry.peer?.kind === "user" ? entry.peer.name ?? "" : "",
766
+ ]
767
+ .join("\n")
768
+ .toLowerCase();
769
+ return haystack.includes(normalizedQuery);
770
+ })
771
+ : entries;
772
+ return jsonResult(toJsonSafe({
773
+ ok: true,
774
+ query: query ?? null,
775
+ count: filtered.length,
776
+ chats: filtered.slice(0, limit),
777
+ }));
778
+ },
779
+ });
780
+ }
781
+ if (normalizedAction === "channel-create" || normalizedAction === "thread-create") {
782
+ return await withInlineClient({
783
+ cfg,
784
+ accountId,
785
+ fn: async (client) => {
786
+ const title = readStringParam(params, "title") ??
787
+ readStringParam(params, "name") ??
788
+ readStringParam(params, "threadName") ??
789
+ readStringParam(params, "message", { required: true });
790
+ const description = readStringParam(params, "description");
791
+ const emoji = readStringParam(params, "emoji");
792
+ const spaceId = parseOptionalInlineId(readFlexibleId(params, "spaceId") ?? readFlexibleId(params, "space"), "spaceId");
793
+ const isPublic = readBooleanParam(params, "isPublic") ?? false;
794
+ const participantRefs = parseInlineListValuesFromParams(params, [
795
+ "participants",
796
+ "participantIds",
797
+ "participantId",
798
+ "participant",
799
+ "userIds",
800
+ "userId",
801
+ ]);
802
+ const dedupedParticipants = await resolveInlineUserIdsFromParams({
803
+ client,
804
+ values: participantRefs,
805
+ label: "participant",
806
+ });
807
+ const result = await client.invokeRaw(Method.CREATE_CHAT, {
808
+ oneofKind: "createChat",
809
+ createChat: {
810
+ title,
811
+ ...(spaceId != null ? { spaceId } : {}),
812
+ ...(description ? { description } : {}),
813
+ ...(emoji ? { emoji } : {}),
814
+ isPublic,
815
+ participants: isPublic ? [] : dedupedParticipants.map((userId) => ({ userId })),
816
+ },
817
+ });
818
+ if (result.oneofKind !== "createChat") {
819
+ throw new Error(`inline action: expected createChat result, got ${String(result.oneofKind)}`);
820
+ }
821
+ return jsonResult(toJsonSafe({
822
+ ok: true,
823
+ title,
824
+ spaceId: spaceId != null ? String(spaceId) : null,
825
+ isPublic,
826
+ participants: dedupedParticipants.map((id) => String(id)),
827
+ chat: result.createChat.chat ?? null,
828
+ dialog: result.createChat.dialog ?? null,
829
+ }));
830
+ },
831
+ });
832
+ }
833
+ if (normalizedAction === "channel-delete") {
423
834
  return await withInlineClient({
424
835
  cfg,
425
836
  accountId,
426
837
  fn: async (client) => {
427
838
  const chatId = resolveChatIdFromParams(params);
428
- const userId = parseInlineId(readFlexibleId(params, "userId") ??
429
- readFlexibleId(params, "participant") ??
430
- readFlexibleId(params, "memberId") ??
431
- readStringParam(params, "userId", { required: true }), "userId");
839
+ const result = await client.invokeRaw(Method.DELETE_CHAT, {
840
+ oneofKind: "deleteChat",
841
+ deleteChat: {
842
+ peerId: buildChatPeer(chatId),
843
+ },
844
+ });
845
+ if (result.oneofKind !== "deleteChat") {
846
+ throw new Error(`inline action: expected deleteChat result, got ${String(result.oneofKind)}`);
847
+ }
848
+ return jsonResult({
849
+ ok: true,
850
+ chatId: String(chatId),
851
+ });
852
+ },
853
+ });
854
+ }
855
+ if (normalizedAction === "channel-move") {
856
+ return await withInlineClient({
857
+ cfg,
858
+ accountId,
859
+ fn: async (client) => {
860
+ const chatId = resolveChatIdFromParams(params);
861
+ const rawSpace = readStringParam(params, "spaceId") ?? readStringParam(params, "toSpaceId");
862
+ const normalizedSpace = rawSpace?.trim().toLowerCase();
863
+ const moveToHome = normalizedSpace === "" ||
864
+ normalizedSpace === "home" ||
865
+ normalizedSpace === "none" ||
866
+ normalizedSpace === "null";
867
+ const parsedSpace = moveToHome
868
+ ? undefined
869
+ : parseOptionalInlineId(readFlexibleId(params, "spaceId") ?? readFlexibleId(params, "toSpaceId"), "spaceId");
870
+ const result = await client.invokeRaw(Method.MOVE_THREAD, {
871
+ oneofKind: "moveThread",
872
+ moveThread: {
873
+ chatId,
874
+ ...(parsedSpace != null ? { spaceId: parsedSpace } : {}),
875
+ },
876
+ });
877
+ if (result.oneofKind !== "moveThread") {
878
+ throw new Error(`inline action: expected moveThread result, got ${String(result.oneofKind)}`);
879
+ }
880
+ return jsonResult(toJsonSafe({
881
+ ok: true,
882
+ chatId: String(chatId),
883
+ spaceId: parsedSpace != null ? String(parsedSpace) : null,
884
+ chat: result.moveThread.chat ?? null,
885
+ }));
886
+ },
887
+ });
888
+ }
889
+ if (normalizedAction === "addParticipant") {
890
+ return await withInlineClient({
891
+ cfg,
892
+ accountId,
893
+ fn: async (client) => {
894
+ const chatId = resolveChatIdFromParams(params);
895
+ const participantRefs = parseInlineListValuesFromParams(params, [
896
+ "userId",
897
+ "participant",
898
+ "participantId",
899
+ "memberId",
900
+ ]);
901
+ if (participantRefs.length === 0) {
902
+ readStringParam(params, "userId", { required: true });
903
+ }
904
+ const participantIds = await resolveInlineUserIdsFromParams({
905
+ client,
906
+ values: participantRefs,
907
+ label: "user",
908
+ });
909
+ if (participantIds.length === 0) {
910
+ throw new Error("inline action: missing user");
911
+ }
912
+ if (participantIds.length > 1) {
913
+ throw new Error("inline action: addParticipant accepts exactly one user");
914
+ }
915
+ const userId = participantIds[0];
916
+ if (!userId) {
917
+ throw new Error("inline action: missing user");
918
+ }
432
919
  const result = await client.invokeRaw(Method.ADD_CHAT_PARTICIPANT, {
433
920
  oneofKind: "addChatParticipant",
434
921
  addChatParticipant: {
@@ -448,13 +935,89 @@ export const inlineMessageActions = {
448
935
  },
449
936
  });
450
937
  }
451
- if (action === "member-info") {
938
+ if (normalizedAction === "removeParticipant") {
452
939
  return await withInlineClient({
453
940
  cfg,
454
941
  accountId,
455
942
  fn: async (client) => {
456
943
  const chatId = resolveChatIdFromParams(params);
457
- const userId = parseInlineId(readFlexibleId(params, "userId") ?? readStringParam(params, "userId", { required: true }), "userId");
944
+ const participantRefs = parseInlineListValuesFromParams(params, [
945
+ "userId",
946
+ "participant",
947
+ "participantId",
948
+ "memberId",
949
+ ]);
950
+ if (participantRefs.length === 0) {
951
+ readStringParam(params, "userId", { required: true });
952
+ }
953
+ const participantIds = await resolveInlineUserIdsFromParams({
954
+ client,
955
+ values: participantRefs,
956
+ label: "user",
957
+ });
958
+ if (participantIds.length === 0) {
959
+ throw new Error("inline action: missing user");
960
+ }
961
+ if (participantIds.length > 1) {
962
+ throw new Error("inline action: removeParticipant accepts exactly one user");
963
+ }
964
+ const userId = participantIds[0];
965
+ if (!userId) {
966
+ throw new Error("inline action: missing user");
967
+ }
968
+ const result = await client.invokeRaw(Method.REMOVE_CHAT_PARTICIPANT, {
969
+ oneofKind: "removeChatParticipant",
970
+ removeChatParticipant: {
971
+ chatId,
972
+ userId,
973
+ },
974
+ });
975
+ if (result.oneofKind !== "removeChatParticipant") {
976
+ throw new Error(`inline action: expected removeChatParticipant result, got ${String(result.oneofKind)}`);
977
+ }
978
+ return jsonResult({
979
+ ok: true,
980
+ chatId: String(chatId),
981
+ userId: String(userId),
982
+ });
983
+ },
984
+ });
985
+ }
986
+ if (normalizedAction === "leaveGroup") {
987
+ return await withInlineClient({
988
+ cfg,
989
+ accountId,
990
+ fn: async (client) => {
991
+ const chatId = resolveChatIdFromParams(params);
992
+ const me = await client.getMe();
993
+ const userId = me.userId;
994
+ const result = await client.invokeRaw(Method.REMOVE_CHAT_PARTICIPANT, {
995
+ oneofKind: "removeChatParticipant",
996
+ removeChatParticipant: {
997
+ chatId,
998
+ userId,
999
+ },
1000
+ });
1001
+ if (result.oneofKind !== "removeChatParticipant") {
1002
+ throw new Error(`inline action: expected removeChatParticipant result, got ${String(result.oneofKind)}`);
1003
+ }
1004
+ return jsonResult({
1005
+ ok: true,
1006
+ chatId: String(chatId),
1007
+ userId: String(userId),
1008
+ left: true,
1009
+ });
1010
+ },
1011
+ });
1012
+ }
1013
+ if (normalizedAction === "member-info") {
1014
+ return await withInlineClient({
1015
+ cfg,
1016
+ accountId,
1017
+ fn: async (client) => {
1018
+ const chatId = resolveChatIdFromParams(params);
1019
+ const userId = parseInlineId(readFlexibleId(params, "userId") ??
1020
+ readStringParam(params, "userId", { required: true }), "userId");
458
1021
  const result = await client.invokeRaw(Method.GET_CHAT_PARTICIPANTS, {
459
1022
  oneofKind: "getChatParticipants",
460
1023
  getChatParticipants: { chatId },
@@ -474,7 +1037,180 @@ export const inlineMessageActions = {
474
1037
  },
475
1038
  });
476
1039
  }
1040
+ if (normalizedAction === "delete" || normalizedAction === "unsend") {
1041
+ return await withInlineClient({
1042
+ cfg,
1043
+ accountId,
1044
+ fn: async (client) => {
1045
+ const chatId = resolveChatIdFromParams(params);
1046
+ const messageIds = [
1047
+ ...parseInlineIdListFromParams(params, "messageIds"),
1048
+ ...parseInlineIdListFromParams(params, "messages"),
1049
+ ...parseInlineIdListFromParams(params, "ids"),
1050
+ ];
1051
+ if (messageIds.length === 0) {
1052
+ messageIds.push(parseInlineId(readFlexibleId(params, "messageId") ??
1053
+ readStringParam(params, "messageId", { required: true }), "messageId"));
1054
+ }
1055
+ const deduped = Array.from(new Set(messageIds.map((id) => id.toString()))).map((id) => BigInt(id));
1056
+ const result = await client.invokeRaw(Method.DELETE_MESSAGES, {
1057
+ oneofKind: "deleteMessages",
1058
+ deleteMessages: {
1059
+ peerId: buildChatPeer(chatId),
1060
+ messageIds: deduped,
1061
+ },
1062
+ });
1063
+ if (result.oneofKind !== "deleteMessages") {
1064
+ throw new Error(`inline action: expected deleteMessages result, got ${String(result.oneofKind)}`);
1065
+ }
1066
+ return jsonResult({
1067
+ ok: true,
1068
+ chatId: String(chatId),
1069
+ messageIds: deduped.map((id) => String(id)),
1070
+ });
1071
+ },
1072
+ });
1073
+ }
1074
+ if (normalizedAction === "pin" || normalizedAction === "unpin") {
1075
+ return await withInlineClient({
1076
+ cfg,
1077
+ accountId,
1078
+ fn: async (client) => {
1079
+ const chatId = resolveChatIdFromParams(params);
1080
+ const messageId = parseInlineId(readFlexibleId(params, "messageId") ??
1081
+ readStringParam(params, "messageId", { required: true }), "messageId");
1082
+ const unpin = normalizedAction === "unpin" || readBooleanParam(params, "unpin") === true;
1083
+ const result = await client.invokeRaw(Method.PIN_MESSAGE, {
1084
+ oneofKind: "pinMessage",
1085
+ pinMessage: {
1086
+ peerId: buildChatPeer(chatId),
1087
+ messageId,
1088
+ unpin,
1089
+ },
1090
+ });
1091
+ if (result.oneofKind !== "pinMessage") {
1092
+ throw new Error(`inline action: expected pinMessage result, got ${String(result.oneofKind)}`);
1093
+ }
1094
+ return jsonResult({
1095
+ ok: true,
1096
+ chatId: String(chatId),
1097
+ messageId: String(messageId),
1098
+ unpin,
1099
+ });
1100
+ },
1101
+ });
1102
+ }
1103
+ if (normalizedAction === "list-pins") {
1104
+ return await withInlineClient({
1105
+ cfg,
1106
+ accountId,
1107
+ fn: async (client) => {
1108
+ const chatId = resolveChatIdFromParams(params);
1109
+ const result = await client.invokeRaw(Method.GET_CHAT, {
1110
+ oneofKind: "getChat",
1111
+ getChat: { peerId: buildChatPeer(chatId) },
1112
+ });
1113
+ if (result.oneofKind !== "getChat") {
1114
+ throw new Error(`inline action: expected getChat result, got ${String(result.oneofKind)}`);
1115
+ }
1116
+ const pinnedMessageIds = (result.getChat.pinnedMessageIds ?? []).map((id) => String(id));
1117
+ return jsonResult({
1118
+ ok: true,
1119
+ chatId: String(chatId),
1120
+ pinnedMessageIds,
1121
+ });
1122
+ },
1123
+ });
1124
+ }
1125
+ if (normalizedAction === "permissions") {
1126
+ return await withInlineClient({
1127
+ cfg,
1128
+ accountId,
1129
+ fn: async (client) => {
1130
+ const chatId = resolveChatIdFromParams(params);
1131
+ const chatResult = await client.invokeRaw(Method.GET_CHAT, {
1132
+ oneofKind: "getChat",
1133
+ getChat: { peerId: buildChatPeer(chatId) },
1134
+ });
1135
+ if (chatResult.oneofKind !== "getChat") {
1136
+ throw new Error(`inline action: expected getChat result, got ${String(chatResult.oneofKind)}`);
1137
+ }
1138
+ const spaceId = chatResult.getChat.chat?.spaceId ?? chatResult.getChat.dialog?.spaceId;
1139
+ if (spaceId == null) {
1140
+ throw new Error("inline action: permissions requires a chat that belongs to a space");
1141
+ }
1142
+ const userIdRaw = readFlexibleId(params, "userId") ??
1143
+ readFlexibleId(params, "memberId") ??
1144
+ readStringParam(params, "userId");
1145
+ const userId = userIdRaw ? parseInlineId(userIdRaw, "userId") : undefined;
1146
+ const roleValue = readStringParam(params, "role")?.trim().toLowerCase();
1147
+ const canAccessPublicChats = readBooleanParam(params, "canAccessPublicChats");
1148
+ if (userId != null && roleValue) {
1149
+ const role = roleValue === "admin"
1150
+ ? { role: { oneofKind: "admin", admin: {} } }
1151
+ : roleValue === "member"
1152
+ ? {
1153
+ role: {
1154
+ oneofKind: "member",
1155
+ member: {
1156
+ canAccessPublicChats: canAccessPublicChats ?? true,
1157
+ },
1158
+ },
1159
+ }
1160
+ : null;
1161
+ if (!role) {
1162
+ throw new Error("inline action: role must be \"admin\" or \"member\"");
1163
+ }
1164
+ const updateResult = await client.invokeRaw(Method.UPDATE_MEMBER_ACCESS, {
1165
+ oneofKind: "updateMemberAccess",
1166
+ updateMemberAccess: {
1167
+ spaceId,
1168
+ userId,
1169
+ role,
1170
+ },
1171
+ });
1172
+ if (updateResult.oneofKind !== "updateMemberAccess") {
1173
+ throw new Error(`inline action: expected updateMemberAccess result, got ${String(updateResult.oneofKind)}`);
1174
+ }
1175
+ }
1176
+ const membersResult = await client.invokeRaw(Method.GET_SPACE_MEMBERS, {
1177
+ oneofKind: "getSpaceMembers",
1178
+ getSpaceMembers: {
1179
+ spaceId,
1180
+ },
1181
+ });
1182
+ if (membersResult.oneofKind !== "getSpaceMembers") {
1183
+ throw new Error(`inline action: expected getSpaceMembers result, got ${String(membersResult.oneofKind)}`);
1184
+ }
1185
+ const usersById = buildUserMap(membersResult.getSpaceMembers.users ?? []);
1186
+ const members = (membersResult.getSpaceMembers.members ?? []).map((member) => {
1187
+ const linkedUser = usersById.get(String(member.userId));
1188
+ return {
1189
+ userId: String(member.userId),
1190
+ role: mapSpaceMemberRole(member.role),
1191
+ canAccessPublicChats: member.canAccessPublicChats,
1192
+ date: Number(member.date) * 1000,
1193
+ user: linkedUser
1194
+ ? {
1195
+ id: String(linkedUser.id),
1196
+ name: buildInlineUserDisplayName(linkedUser),
1197
+ username: linkedUser.username ?? null,
1198
+ }
1199
+ : null,
1200
+ };
1201
+ });
1202
+ const filteredMembers = userId != null ? members.filter((member) => member.userId === String(userId)) : members;
1203
+ return jsonResult(toJsonSafe({
1204
+ ok: true,
1205
+ chatId: String(chatId),
1206
+ spaceId: String(spaceId),
1207
+ members: filteredMembers,
1208
+ }));
1209
+ },
1210
+ });
1211
+ }
477
1212
  throw new Error(`Action ${action} is not supported for provider inline.`);
478
1213
  },
479
1214
  };
1215
+ export const inlineSupportedActions = listAllActions();
480
1216
  //# sourceMappingURL=actions.js.map