@meet-im/meet 2.0.5 → 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.
- package/dist/account-inspect-api.d.ts +2 -0
- package/dist/account-inspect-api.js +4 -0
- package/dist/channel-plugin-api.d.ts +1 -0
- package/dist/channel-plugin-api.js +3 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +43 -0
- package/dist/monitor-api.d.ts +1 -0
- package/dist/monitor-api.js +1 -0
- package/dist/probe-api.d.ts +1 -0
- package/dist/probe-api.js +1 -0
- package/dist/runtime-setter-api.d.ts +1 -0
- package/dist/runtime-setter-api.js +2 -0
- package/dist/send-api.d.ts +1 -0
- package/dist/send-api.js +1 -0
- package/dist/src/account-inspect.d.ts +5 -0
- package/dist/src/account-inspect.js +9 -0
- package/dist/src/accounts.d.ts +12 -0
- package/dist/src/accounts.js +134 -0
- package/dist/src/bot.d.ts +15 -0
- package/dist/src/bot.js +355 -0
- package/dist/src/channel.d.ts +3 -0
- package/dist/src/channel.js +402 -0
- package/dist/src/client.d.ts +8 -0
- package/dist/src/client.js +49 -0
- package/dist/src/config-schema.d.ts +82 -0
- package/dist/src/config-schema.js +46 -0
- package/dist/src/media.d.ts +57 -0
- package/dist/src/media.js +140 -0
- package/dist/src/monitor.d.ts +9 -0
- package/dist/src/monitor.js +153 -0
- package/dist/src/outbound.d.ts +2 -0
- package/dist/src/outbound.js +34 -0
- package/dist/src/policy.d.ts +30 -0
- package/dist/src/policy.js +78 -0
- package/dist/src/probe.d.ts +10 -0
- package/dist/src/probe.js +56 -0
- package/dist/src/reply-dispatcher.d.ts +29 -0
- package/dist/src/reply-dispatcher.js +173 -0
- package/dist/src/runtime.d.ts +11 -0
- package/dist/src/runtime.js +6 -0
- package/dist/src/sdk-bridge.d.ts +21 -0
- package/dist/src/sdk-bridge.js +214 -0
- package/dist/src/send.d.ts +60 -0
- package/dist/src/send.js +317 -0
- package/dist/src/targets.d.ts +15 -0
- package/dist/src/targets.js +63 -0
- package/dist/src/types.d.ts +76 -0
- package/dist/src/types.js +1 -0
- package/dist/vitest.config.d.ts +8 -0
- package/dist/vitest.config.js +7 -0
- package/openclaw.plugin.json +116 -0
- package/package.json +18 -17
- package/skills/meet-emojis/SKILL.md +13 -15
- package/index.ts +0 -26
- package/src/accounts.ts +0 -182
- package/src/bot.ts +0 -418
- package/src/channel.ts +0 -396
- package/src/client.ts +0 -63
- package/src/config-schema.ts +0 -50
- package/src/media.ts +0 -198
- package/src/monitor.ts +0 -195
- package/src/outbound.ts +0 -43
- package/src/policy.ts +0 -131
- package/src/probe.ts +0 -75
- package/src/reply-dispatcher.ts +0 -207
- package/src/runtime.ts +0 -14
- package/src/sdk-bridge.ts +0 -268
- package/src/send.ts +0 -363
- package/src/targets.ts +0 -101
- 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 `` - 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[]>;
|