@meet-im/meet 2.0.6 → 3.0.0-beta.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 (69) hide show
  1. package/dist/account-inspect-api.d.ts +2 -0
  2. package/dist/account-inspect-api.js +4 -0
  3. package/dist/channel-plugin-api.d.ts +1 -0
  4. package/dist/channel-plugin-api.js +3 -0
  5. package/dist/index.d.ts +14 -0
  6. package/dist/index.js +43 -0
  7. package/dist/monitor-api.d.ts +1 -0
  8. package/dist/monitor-api.js +1 -0
  9. package/dist/probe-api.d.ts +1 -0
  10. package/dist/probe-api.js +1 -0
  11. package/dist/runtime-setter-api.d.ts +1 -0
  12. package/dist/runtime-setter-api.js +2 -0
  13. package/dist/send-api.d.ts +1 -0
  14. package/dist/send-api.js +1 -0
  15. package/dist/src/account-inspect.d.ts +5 -0
  16. package/dist/src/account-inspect.js +9 -0
  17. package/dist/src/accounts.d.ts +12 -0
  18. package/dist/src/accounts.js +134 -0
  19. package/dist/src/bot.d.ts +15 -0
  20. package/dist/src/bot.js +355 -0
  21. package/dist/src/channel.d.ts +3 -0
  22. package/dist/src/channel.js +402 -0
  23. package/dist/src/client.d.ts +8 -0
  24. package/dist/src/client.js +49 -0
  25. package/dist/src/config-schema.d.ts +82 -0
  26. package/dist/src/config-schema.js +46 -0
  27. package/dist/src/media.d.ts +57 -0
  28. package/dist/src/media.js +140 -0
  29. package/dist/src/monitor.d.ts +9 -0
  30. package/dist/src/monitor.js +153 -0
  31. package/dist/src/outbound.d.ts +2 -0
  32. package/dist/src/outbound.js +34 -0
  33. package/dist/src/policy.d.ts +30 -0
  34. package/dist/src/policy.js +78 -0
  35. package/dist/src/probe.d.ts +10 -0
  36. package/dist/src/probe.js +56 -0
  37. package/dist/src/reply-dispatcher.d.ts +29 -0
  38. package/dist/src/reply-dispatcher.js +173 -0
  39. package/dist/src/runtime.d.ts +11 -0
  40. package/dist/src/runtime.js +6 -0
  41. package/dist/src/sdk-bridge.d.ts +21 -0
  42. package/dist/src/sdk-bridge.js +214 -0
  43. package/dist/src/send.d.ts +60 -0
  44. package/dist/src/send.js +317 -0
  45. package/dist/src/targets.d.ts +15 -0
  46. package/dist/src/targets.js +63 -0
  47. package/dist/src/types.d.ts +76 -0
  48. package/dist/src/types.js +1 -0
  49. package/dist/vitest.config.d.ts +8 -0
  50. package/dist/vitest.config.js +7 -0
  51. package/openclaw.plugin.json +116 -0
  52. package/package.json +18 -17
  53. package/index.ts +0 -26
  54. package/src/accounts.ts +0 -182
  55. package/src/bot.ts +0 -418
  56. package/src/channel.ts +0 -396
  57. package/src/client.ts +0 -63
  58. package/src/config-schema.ts +0 -50
  59. package/src/media.ts +0 -198
  60. package/src/monitor.ts +0 -195
  61. package/src/outbound.ts +0 -43
  62. package/src/policy.ts +0 -131
  63. package/src/probe.ts +0 -75
  64. package/src/reply-dispatcher.ts +0 -207
  65. package/src/runtime.ts +0 -14
  66. package/src/sdk-bridge.ts +0 -268
  67. package/src/send.ts +0 -383
  68. package/src/targets.ts +0 -101
  69. package/src/types.ts +0 -96
@@ -0,0 +1,402 @@
1
+ import { DEFAULT_ACCOUNT_ID, normalizeAccountId, } from "openclaw/plugin-sdk/account-id";
2
+ import { PAIRING_APPROVED_MESSAGE } from "openclaw/plugin-sdk/channel-status";
3
+ import { resolveMeetAccount, listMeetAccountIds, resolveDefaultMeetAccountId, isFlatAccountConfig, getFlatAccountKey, } from "./accounts.js";
4
+ import { meetOutbound } from "./outbound.js";
5
+ import { parseMeetTarget, looksLikeMeetId, formatMeetTarget, } from "./targets.js";
6
+ import { sendMessageMeet } from "./send.js";
7
+ const meta = {
8
+ id: "meet",
9
+ label: "Meet",
10
+ selectionLabel: "Meet IM",
11
+ docsPath: "/channels/meet",
12
+ docsLabel: "meet",
13
+ blurb: "Meet IM platform integration.",
14
+ aliases: [],
15
+ order: 80,
16
+ };
17
+ export const meetPlugin = {
18
+ id: "meet",
19
+ meta: {
20
+ ...meta,
21
+ },
22
+ pairing: {
23
+ idLabel: "meetUserId",
24
+ normalizeAllowEntry: (entry) => entry.replace(/^(meet|user):/i, ""),
25
+ notifyApproval: async ({ cfg, id }) => {
26
+ await sendMessageMeet({
27
+ cfg,
28
+ to: id,
29
+ text: PAIRING_APPROVED_MESSAGE,
30
+ });
31
+ },
32
+ },
33
+ capabilities: {
34
+ chatTypes: ["direct", "channel"],
35
+ polls: false,
36
+ threads: false,
37
+ media: true,
38
+ reactions: false,
39
+ edit: false,
40
+ reply: false,
41
+ },
42
+ agentPrompt: {
43
+ messageToolHints: () => [
44
+ "- Meet targeting: omit `target` to reply to the current conversation (auto-inferred). Explicit targets: `user:<id>` or `channel:<id>`.",
45
+ "- Meet mentions: use `<@USER_ID>` to mention users, `<@-1>` to mention everyone. Examples: `<@553> hello` or `<@-1> important announcement`.",
46
+ "- Meet media: use `media` parameter to send images/files as attachments. DO NOT use Markdown image syntax like `![](path)` - Meet does not render it.",
47
+ ],
48
+ },
49
+ groups: {
50
+ resolveToolPolicy: ({ cfg: _cfg, accountId: _accountId, groupId: _groupId, }) => {
51
+ // 群组访问控制在 bot.ts 中处理,这里只返回工具策略配置
52
+ // 不使用 { deny: ["*"] } 拒绝所有工具,否则会导致 tools: []
53
+ return undefined;
54
+ },
55
+ },
56
+ reload: { configPrefixes: ["channels.meet"] },
57
+ configSchema: {
58
+ schema: {
59
+ type: "object",
60
+ additionalProperties: false,
61
+ properties: {
62
+ enabled: { type: "boolean" },
63
+ defaultAccount: { type: "string" },
64
+ apiEndpoint: { type: "string" },
65
+ apiToken: { type: "string" },
66
+ pollTimeout: { type: "integer", minimum: 1000, maximum: 300000 },
67
+ pollLimit: { type: "integer", minimum: 1, maximum: 1000 },
68
+ dmPolicy: { type: "string", enum: ["open", "pairing", "allowlist"] },
69
+ allowFrom: {
70
+ type: "array",
71
+ items: { oneOf: [{ type: "string" }, { type: "number" }] },
72
+ },
73
+ groupPolicy: {
74
+ type: "string",
75
+ enum: ["open", "allowlist", "disabled"],
76
+ },
77
+ groupAllowFrom: {
78
+ type: "array",
79
+ items: { oneOf: [{ type: "string" }, { type: "number" }] },
80
+ },
81
+ groups: {
82
+ type: "object",
83
+ additionalProperties: {
84
+ type: "object",
85
+ properties: {
86
+ enabled: { type: "boolean" },
87
+ name: { type: "string" },
88
+ requireMention: { type: "boolean" },
89
+ systemPrompt: { type: "string" },
90
+ users: {
91
+ type: "array",
92
+ items: { oneOf: [{ type: "string" }, { type: "number" }] },
93
+ },
94
+ },
95
+ },
96
+ },
97
+ requireMention: { type: "boolean" },
98
+ historyLimit: { type: "integer", minimum: 0 },
99
+ dmHistoryLimit: { type: "integer", minimum: 0 },
100
+ textChunkLimit: { type: "integer", minimum: 1 },
101
+ mediaMaxMb: { type: "number", minimum: 0 },
102
+ accounts: {
103
+ type: "object",
104
+ additionalProperties: {
105
+ type: "object",
106
+ properties: {
107
+ enabled: { type: "boolean" },
108
+ name: { type: "string" },
109
+ apiEndpoint: { type: "string" },
110
+ token: { type: "string" },
111
+ apiToken: { type: "string" },
112
+ pollTimeout: { type: "integer", minimum: 1000, maximum: 300000 },
113
+ pollLimit: { type: "integer", minimum: 1, maximum: 1000 },
114
+ logLevel: { type: "string", enum: ["silent", "info"] },
115
+ dmPolicy: { type: "string", enum: ["open", "pairing", "allowlist"] },
116
+ allowFrom: {
117
+ type: "array",
118
+ items: { oneOf: [{ type: "string" }, { type: "number" }] },
119
+ },
120
+ groupPolicy: {
121
+ type: "string",
122
+ enum: ["open", "allowlist", "disabled"],
123
+ },
124
+ groupAllowFrom: {
125
+ type: "array",
126
+ items: { oneOf: [{ type: "string" }, { type: "number" }] },
127
+ },
128
+ requireMention: { type: "boolean" },
129
+ systemPrompt: { type: "string" },
130
+ historyLimit: { type: "integer", minimum: 0 },
131
+ dmHistoryLimit: { type: "integer", minimum: 0 },
132
+ textChunkLimit: { type: "integer", minimum: 1 },
133
+ mediaMaxMb: { type: "number", minimum: 0 },
134
+ groups: {
135
+ type: "object",
136
+ additionalProperties: {
137
+ type: "object",
138
+ properties: {
139
+ enabled: { type: "boolean" },
140
+ name: { type: "string" },
141
+ requireMention: { type: "boolean" },
142
+ systemPrompt: { type: "string" },
143
+ users: {
144
+ type: "array",
145
+ items: { oneOf: [{ type: "string" }, { type: "number" }] },
146
+ },
147
+ groupPolicy: {
148
+ type: "string",
149
+ enum: ["open", "allowlist", "disabled"],
150
+ },
151
+ },
152
+ },
153
+ },
154
+ },
155
+ },
156
+ },
157
+ },
158
+ },
159
+ },
160
+ config: {
161
+ listAccountIds: (cfg) => listMeetAccountIds(cfg),
162
+ resolveAccount: (cfg, accountId) => resolveMeetAccount({ cfg, accountId }),
163
+ defaultAccountId: (cfg) => resolveDefaultMeetAccountId(cfg),
164
+ setAccountEnabled: ({ cfg, accountId, enabled }) => {
165
+ const isDefault = accountId === DEFAULT_ACCOUNT_ID;
166
+ if (isDefault) {
167
+ return {
168
+ ...cfg,
169
+ channels: {
170
+ ...cfg.channels,
171
+ meet: {
172
+ ...cfg.channels?.meet,
173
+ enabled,
174
+ },
175
+ },
176
+ };
177
+ }
178
+ if (isFlatAccountConfig(cfg, accountId)) {
179
+ const key = getFlatAccountKey(accountId);
180
+ return {
181
+ ...cfg,
182
+ channels: {
183
+ ...cfg.channels,
184
+ [key]: {
185
+ ...cfg.channels?.[key],
186
+ enabled,
187
+ },
188
+ },
189
+ };
190
+ }
191
+ const meetCfg = cfg.channels?.meet;
192
+ return {
193
+ ...cfg,
194
+ channels: {
195
+ ...cfg.channels,
196
+ meet: {
197
+ ...meetCfg,
198
+ accounts: {
199
+ ...meetCfg?.accounts,
200
+ [accountId]: {
201
+ ...meetCfg?.accounts?.[accountId],
202
+ enabled,
203
+ },
204
+ },
205
+ },
206
+ },
207
+ };
208
+ },
209
+ deleteAccount: ({ cfg, accountId }) => {
210
+ const isDefault = accountId === DEFAULT_ACCOUNT_ID;
211
+ if (isDefault) {
212
+ const next = { ...cfg };
213
+ const nextChannels = { ...cfg.channels };
214
+ delete nextChannels.meet;
215
+ if (Object.keys(nextChannels).length > 0) {
216
+ next.channels = nextChannels;
217
+ }
218
+ else {
219
+ delete next.channels;
220
+ }
221
+ return next;
222
+ }
223
+ if (isFlatAccountConfig(cfg, accountId)) {
224
+ const key = getFlatAccountKey(accountId);
225
+ const next = { ...cfg };
226
+ const nextChannels = { ...cfg.channels };
227
+ delete nextChannels[key];
228
+ if (Object.keys(nextChannels).length > 0) {
229
+ next.channels = nextChannels;
230
+ }
231
+ else {
232
+ delete next.channels;
233
+ }
234
+ return next;
235
+ }
236
+ const meetCfg = cfg.channels?.meet;
237
+ const accounts = { ...meetCfg?.accounts };
238
+ delete accounts[accountId];
239
+ return {
240
+ ...cfg,
241
+ channels: {
242
+ ...cfg.channels,
243
+ meet: {
244
+ ...meetCfg,
245
+ accounts: Object.keys(accounts).length > 0 ? accounts : undefined,
246
+ },
247
+ },
248
+ };
249
+ },
250
+ isConfigured: (account) => account.configured,
251
+ describeAccount: (account) => ({
252
+ accountId: account.accountId,
253
+ enabled: account.enabled,
254
+ configured: account.configured,
255
+ name: account.name,
256
+ apiEndpoint: account.apiEndpoint,
257
+ }),
258
+ resolveAllowFrom: ({ cfg, accountId }) => {
259
+ const account = resolveMeetAccount({ cfg, accountId });
260
+ return (account.config?.allowFrom ?? [])
261
+ .map((entry) => String(entry).trim())
262
+ .filter(Boolean);
263
+ },
264
+ formatAllowFrom: ({ allowFrom }) => allowFrom
265
+ .map((entry) => String(entry).trim())
266
+ .filter(Boolean)
267
+ .map((entry) => entry.toLowerCase()),
268
+ },
269
+ security: {
270
+ collectWarnings: ({ cfg, accountId }) => {
271
+ const account = resolveMeetAccount({ cfg, accountId });
272
+ const meetCfg = account.config;
273
+ const defaultGroupPolicy = cfg.channels?.defaults?.groupPolicy;
274
+ const groupPolicy = meetCfg?.groupPolicy ?? defaultGroupPolicy ?? "allowlist";
275
+ if (groupPolicy !== "open")
276
+ return [];
277
+ return [
278
+ `- Meet[${account.accountId}] groups: groupPolicy="open" allows any member to trigger (mention-gated). Set channels.meet.groupPolicy="allowlist" + channels.meet.groupAllowFrom to restrict senders.`,
279
+ ];
280
+ },
281
+ },
282
+ setup: {
283
+ resolveAccountId: ({ accountId }) => normalizeAccountId(accountId),
284
+ applyAccountConfig: ({ cfg, accountId }) => {
285
+ const isDefault = !accountId || accountId === DEFAULT_ACCOUNT_ID;
286
+ if (isDefault) {
287
+ return {
288
+ ...cfg,
289
+ channels: {
290
+ ...cfg.channels,
291
+ meet: {
292
+ ...cfg.channels?.meet,
293
+ enabled: true,
294
+ },
295
+ },
296
+ };
297
+ }
298
+ if (isFlatAccountConfig(cfg, accountId)) {
299
+ const key = getFlatAccountKey(accountId);
300
+ return {
301
+ ...cfg,
302
+ channels: {
303
+ ...cfg.channels,
304
+ [key]: {
305
+ ...cfg.channels?.[key],
306
+ enabled: true,
307
+ },
308
+ },
309
+ };
310
+ }
311
+ const meetCfg = cfg.channels?.meet;
312
+ return {
313
+ ...cfg,
314
+ channels: {
315
+ ...cfg.channels,
316
+ meet: {
317
+ ...meetCfg,
318
+ accounts: {
319
+ ...meetCfg?.accounts,
320
+ [accountId]: {
321
+ ...meetCfg?.accounts?.[accountId],
322
+ enabled: true,
323
+ },
324
+ },
325
+ },
326
+ },
327
+ };
328
+ },
329
+ },
330
+ messaging: {
331
+ normalizeTarget: (raw) => {
332
+ const target = parseMeetTarget(raw);
333
+ return target ? formatMeetTarget(target) : raw;
334
+ },
335
+ targetResolver: {
336
+ looksLikeId: looksLikeMeetId,
337
+ hint: "<userId|user:<id>|channel:<id>>",
338
+ },
339
+ },
340
+ directory: {
341
+ self: async () => null,
342
+ listPeers: async () => [],
343
+ listGroups: async () => [],
344
+ listPeersLive: async () => [],
345
+ listGroupsLive: async () => [],
346
+ },
347
+ outbound: meetOutbound,
348
+ status: {
349
+ defaultRuntime: {
350
+ accountId: DEFAULT_ACCOUNT_ID,
351
+ running: false,
352
+ lastStartAt: null,
353
+ lastStopAt: null,
354
+ lastError: null,
355
+ port: null,
356
+ },
357
+ buildChannelSummary: ({ snapshot }) => ({
358
+ configured: snapshot.configured ?? false,
359
+ running: snapshot.running ?? false,
360
+ lastStartAt: snapshot.lastStartAt ?? null,
361
+ lastStopAt: snapshot.lastStopAt ?? null,
362
+ lastError: snapshot.lastError ?? null,
363
+ port: snapshot.port ?? null,
364
+ probe: snapshot.probe,
365
+ lastProbeAt: snapshot.lastProbeAt ?? null,
366
+ }),
367
+ probeAccount: async ({ account }) => ({
368
+ ok: account.configured,
369
+ error: account.configured ? undefined : "Not configured",
370
+ botId: account.apiToken?.split(":")[0],
371
+ }),
372
+ buildAccountSnapshot: ({ account, runtime, probe }) => ({
373
+ accountId: account.accountId,
374
+ enabled: account.enabled,
375
+ configured: account.configured,
376
+ name: account.name,
377
+ apiEndpoint: account.apiEndpoint,
378
+ running: runtime?.running ?? false,
379
+ lastStartAt: runtime?.lastStartAt ?? null,
380
+ lastStopAt: runtime?.lastStopAt ?? null,
381
+ lastError: runtime?.lastError ?? null,
382
+ port: runtime?.port ?? null,
383
+ probe,
384
+ }),
385
+ },
386
+ gateway: {
387
+ startAccount: async (ctx) => {
388
+ const { monitorMeetProvider } = await import("./monitor.js");
389
+ resolveMeetAccount({
390
+ cfg: ctx.cfg,
391
+ accountId: ctx.accountId,
392
+ });
393
+ ctx.log?.info(`[${ctx.accountId}] starting`);
394
+ return monitorMeetProvider({
395
+ config: ctx.cfg,
396
+ runtime: ctx.runtime,
397
+ abortSignal: ctx.abortSignal,
398
+ accountId: ctx.accountId,
399
+ });
400
+ },
401
+ },
402
+ };
@@ -0,0 +1,8 @@
1
+ import { MeetBot } from "@meet-im/meet-bot-jssdk";
2
+ import type { PollingOptions } from "@meet-im/meet-bot-jssdk";
3
+ import type { ResolvedMeetAccount } from "./types.js";
4
+ export declare function createMeetClient(account: ResolvedMeetAccount): MeetBot;
5
+ export declare function getPollingOptions(account: ResolvedMeetAccount): PollingOptions;
6
+ export declare function getMeetClient(accountId: string): MeetBot | undefined;
7
+ export declare function closeMeetClient(accountId: string): void;
8
+ export declare function closeAllMeetClients(): void;
@@ -0,0 +1,49 @@
1
+ import { MeetBot, POLLING } from "@meet-im/meet-bot-jssdk";
2
+ const botInstances = new Map();
3
+ export function createMeetClient(account) {
4
+ const existing = botInstances.get(account.accountId);
5
+ if (existing) {
6
+ return existing;
7
+ }
8
+ if (!account.apiToken) {
9
+ throw new Error(`Meet account "${account.accountId}" missing apiToken`);
10
+ }
11
+ const pollTimeoutMs = account.config.pollTimeout ?? 30000;
12
+ const pollTimeoutSec = Math.floor(pollTimeoutMs / 1000);
13
+ const logLevel = account.config.logLevel ?? "silent";
14
+ const bot = new MeetBot({
15
+ token: account.apiToken,
16
+ baseUrl: account.apiEndpoint,
17
+ pollingLimit: account.config.pollLimit ?? POLLING.DEFAULT_LIMIT,
18
+ longPollingTimeout: pollTimeoutSec,
19
+ logLevel,
20
+ useV2: true,
21
+ });
22
+ botInstances.set(account.accountId, bot);
23
+ return bot;
24
+ }
25
+ export function getPollingOptions(account) {
26
+ const pollTimeoutMs = account.config.pollTimeout ?? 30000;
27
+ const pollTimeoutSec = Math.floor(pollTimeoutMs / 1000);
28
+ return {
29
+ timeout: pollTimeoutSec,
30
+ limit: account.config.pollLimit ?? POLLING.DEFAULT_LIMIT,
31
+ retryDelay: POLLING.DEFAULT_RETRY_DELAY,
32
+ maxRetries: 0,
33
+ };
34
+ }
35
+ export function getMeetClient(accountId) {
36
+ return botInstances.get(accountId);
37
+ }
38
+ export function closeMeetClient(accountId) {
39
+ const bot = botInstances.get(accountId);
40
+ if (bot) {
41
+ bot.stopPolling();
42
+ botInstances.delete(accountId);
43
+ }
44
+ }
45
+ export function closeAllMeetClients() {
46
+ for (const [accountId] of botInstances) {
47
+ closeMeetClient(accountId);
48
+ }
49
+ }
@@ -0,0 +1,82 @@
1
+ import { z } from "zod";
2
+ export declare const MeetChannelConfigSchema: z.ZodObject<{
3
+ enabled: z.ZodOptional<z.ZodBoolean>;
4
+ systemPrompt: z.ZodOptional<z.ZodString>;
5
+ requireMention: z.ZodOptional<z.ZodBoolean>;
6
+ }, z.core.$strip>;
7
+ export declare const MeetGroupConfigSchema: z.ZodObject<{
8
+ enabled: z.ZodOptional<z.ZodBoolean>;
9
+ name: z.ZodOptional<z.ZodString>;
10
+ requireMention: z.ZodOptional<z.ZodBoolean>;
11
+ systemPrompt: z.ZodOptional<z.ZodString>;
12
+ users: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>>;
13
+ }, z.core.$strip>;
14
+ export declare const MeetAccountConfigSchema: z.ZodObject<{
15
+ enabled: z.ZodOptional<z.ZodBoolean>;
16
+ name: z.ZodOptional<z.ZodString>;
17
+ apiEndpoint: z.ZodOptional<z.ZodString>;
18
+ token: z.ZodOptional<z.ZodString>;
19
+ apiToken: z.ZodOptional<z.ZodString>;
20
+ pollTimeout: z.ZodOptional<z.ZodNumber>;
21
+ pollLimit: z.ZodOptional<z.ZodNumber>;
22
+ logLevel: z.ZodOptional<z.ZodEnum<{
23
+ silent: "silent";
24
+ info: "info";
25
+ }>>;
26
+ }, z.core.$strip>;
27
+ export declare const MeetConfigSchema: z.ZodObject<{
28
+ enabled: z.ZodOptional<z.ZodBoolean>;
29
+ defaultAccount: z.ZodOptional<z.ZodString>;
30
+ apiEndpoint: z.ZodOptional<z.ZodString>;
31
+ token: z.ZodOptional<z.ZodString>;
32
+ apiToken: z.ZodOptional<z.ZodString>;
33
+ pollTimeout: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
34
+ pollLimit: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
35
+ logLevel: z.ZodOptional<z.ZodEnum<{
36
+ silent: "silent";
37
+ info: "info";
38
+ }>>;
39
+ dmPolicy: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
40
+ open: "open";
41
+ pairing: "pairing";
42
+ allowlist: "allowlist";
43
+ }>>>;
44
+ allowFrom: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>>;
45
+ groupPolicy: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
46
+ open: "open";
47
+ allowlist: "allowlist";
48
+ disabled: "disabled";
49
+ }>>>;
50
+ groupAllowFrom: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>>;
51
+ groups: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
52
+ enabled: z.ZodOptional<z.ZodBoolean>;
53
+ name: z.ZodOptional<z.ZodString>;
54
+ requireMention: z.ZodOptional<z.ZodBoolean>;
55
+ systemPrompt: z.ZodOptional<z.ZodString>;
56
+ users: z.ZodOptional<z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>>;
57
+ }, z.core.$strip>>>;
58
+ requireMention: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
59
+ systemPrompt: z.ZodOptional<z.ZodString>;
60
+ channels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
61
+ enabled: z.ZodOptional<z.ZodBoolean>;
62
+ systemPrompt: z.ZodOptional<z.ZodString>;
63
+ requireMention: z.ZodOptional<z.ZodBoolean>;
64
+ }, z.core.$strip>>>;
65
+ historyLimit: z.ZodOptional<z.ZodNumber>;
66
+ dmHistoryLimit: z.ZodOptional<z.ZodNumber>;
67
+ textChunkLimit: z.ZodOptional<z.ZodNumber>;
68
+ mediaMaxMb: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
69
+ accounts: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
70
+ enabled: z.ZodOptional<z.ZodBoolean>;
71
+ name: z.ZodOptional<z.ZodString>;
72
+ apiEndpoint: z.ZodOptional<z.ZodString>;
73
+ token: z.ZodOptional<z.ZodString>;
74
+ apiToken: z.ZodOptional<z.ZodString>;
75
+ pollTimeout: z.ZodOptional<z.ZodNumber>;
76
+ pollLimit: z.ZodOptional<z.ZodNumber>;
77
+ logLevel: z.ZodOptional<z.ZodEnum<{
78
+ silent: "silent";
79
+ info: "info";
80
+ }>>;
81
+ }, z.core.$strip>>>;
82
+ }, z.core.$strip>;
@@ -0,0 +1,46 @@
1
+ import { z } from "zod";
2
+ export const MeetChannelConfigSchema = z.object({
3
+ enabled: z.boolean().optional(),
4
+ systemPrompt: z.string().optional(),
5
+ requireMention: z.boolean().optional(),
6
+ });
7
+ export const MeetGroupConfigSchema = z.object({
8
+ enabled: z.boolean().optional(),
9
+ name: z.string().optional(),
10
+ requireMention: z.boolean().optional(),
11
+ systemPrompt: z.string().optional(),
12
+ users: z.array(z.union([z.string(), z.number()])).optional(),
13
+ });
14
+ export const MeetAccountConfigSchema = z.object({
15
+ enabled: z.boolean().optional(),
16
+ name: z.string().optional(),
17
+ apiEndpoint: z.string().optional(),
18
+ token: z.string().optional(),
19
+ apiToken: z.string().optional(),
20
+ pollTimeout: z.number().min(1000).max(300000).optional(),
21
+ pollLimit: z.number().min(1).max(1000).optional(),
22
+ logLevel: z.enum(["silent", "info"]).optional(),
23
+ });
24
+ export const MeetConfigSchema = z.object({
25
+ enabled: z.boolean().optional(),
26
+ defaultAccount: z.string().optional(),
27
+ apiEndpoint: z.string().optional(),
28
+ token: z.string().optional(),
29
+ apiToken: z.string().optional(),
30
+ pollTimeout: z.number().min(1000).max(300000).optional().default(30000),
31
+ pollLimit: z.number().min(1).max(1000).optional().default(100),
32
+ logLevel: z.enum(["silent", "info"]).optional(),
33
+ dmPolicy: z.enum(["open", "pairing", "allowlist"]).optional().default("pairing"),
34
+ allowFrom: z.array(z.union([z.string(), z.number()])).optional(),
35
+ groupPolicy: z.enum(["open", "allowlist", "disabled"]).optional().default("allowlist"),
36
+ groupAllowFrom: z.array(z.union([z.string(), z.number()])).optional(),
37
+ groups: z.record(z.string(), MeetGroupConfigSchema).optional(),
38
+ requireMention: z.boolean().optional().default(true),
39
+ systemPrompt: z.string().optional(),
40
+ channels: z.record(z.string(), MeetChannelConfigSchema).optional(),
41
+ historyLimit: z.number().min(0).optional(),
42
+ dmHistoryLimit: z.number().min(0).optional(),
43
+ textChunkLimit: z.number().min(1).optional(),
44
+ mediaMaxMb: z.number().min(0).optional().default(30),
45
+ accounts: z.record(z.string(), MeetAccountConfigSchema).optional(),
46
+ });
@@ -0,0 +1,57 @@
1
+ import type { MeetMediaAttachment } from "./types.js";
2
+ export declare function setMediaDebugLogger(log: (msg: string) => void, error: (msg: string) => void): void;
3
+ /**
4
+ * 获取文件下载 URL
5
+ */
6
+ export declare function getFileAccessUrl(params: {
7
+ accountId: string;
8
+ sessionInfo: {
9
+ firstId: number;
10
+ secondId: number;
11
+ sessionType: number;
12
+ companyId?: number;
13
+ };
14
+ seqId: number;
15
+ fileId: string | number;
16
+ ossProcess?: string;
17
+ }): Promise<string | null>;
18
+ /**
19
+ * 媒体信息(下载并保存后的结果)
20
+ */
21
+ export type ResolvedMedia = {
22
+ path: string;
23
+ contentType?: string;
24
+ placeholder: string;
25
+ url?: string;
26
+ };
27
+ /**
28
+ * 下载媒体文件到本地 media store
29
+ * 与 Discord 保持一致的处理流程
30
+ */
31
+ export declare function downloadAndSaveMedia(params: {
32
+ accountId: string;
33
+ attachment: MeetMediaAttachment;
34
+ sessionInfo: {
35
+ firstId: number;
36
+ secondId: number;
37
+ sessionType: number;
38
+ companyId?: number;
39
+ };
40
+ seqId: number;
41
+ maxBytes?: number;
42
+ }): Promise<ResolvedMedia | null>;
43
+ /**
44
+ * 批量处理媒体附件
45
+ */
46
+ export declare function resolveMediaAttachments(params: {
47
+ accountId: string;
48
+ attachments: MeetMediaAttachment[];
49
+ sessionInfo: {
50
+ firstId: number;
51
+ secondId: number;
52
+ sessionType: number;
53
+ companyId?: number;
54
+ };
55
+ seqId: number;
56
+ maxBytes?: number;
57
+ }): Promise<ResolvedMedia[]>;