@meet-im/meet 2.0.1 → 2.0.3
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/package.json +1 -1
- package/src/bot.ts +4 -1
- package/src/channel.ts +1 -0
- package/src/reply-dispatcher.ts +34 -3
- package/src/send.ts +23 -5
package/package.json
CHANGED
package/src/bot.ts
CHANGED
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
recordPendingHistoryEntryIfEnabled,
|
|
7
7
|
} from "openclaw/plugin-sdk/reply-history"
|
|
8
8
|
import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/account-id"
|
|
9
|
+
import { getAgentScopedMediaLocalRoots } from "openclaw/plugin-sdk/media-runtime"
|
|
9
10
|
import type { MeetBot, MsgContent } from "@meet-im/meet-bot-jssdk"
|
|
10
11
|
import type { ResolvedMeetAccount, MeetMessageContext } from "./types.js"
|
|
11
12
|
import { msgContentToContext, extractQuoteMessageMedia } from "./sdk-bridge.js"
|
|
@@ -199,7 +200,7 @@ export async function handleMeetMessage(params: {
|
|
|
199
200
|
}
|
|
200
201
|
|
|
201
202
|
const meetFrom = `meet:${ctx.senderId}`
|
|
202
|
-
const meetTo =
|
|
203
|
+
const meetTo = ctx.chatId
|
|
203
204
|
|
|
204
205
|
const peerId = isGroup ? ctx.chatId : ctx.senderId
|
|
205
206
|
|
|
@@ -380,6 +381,7 @@ export async function handleMeetMessage(params: {
|
|
|
380
381
|
})
|
|
381
382
|
|
|
382
383
|
const { createMeetReplyDispatcher } = await import("./reply-dispatcher.js")
|
|
384
|
+
const mediaLocalRoots = getAgentScopedMediaLocalRoots(cfg, route.agentId)
|
|
383
385
|
const { dispatcher, replyOptions, markDispatchIdle } = await createMeetReplyDispatcher({
|
|
384
386
|
cfg,
|
|
385
387
|
agentId: route.agentId,
|
|
@@ -389,6 +391,7 @@ export async function handleMeetMessage(params: {
|
|
|
389
391
|
accountId,
|
|
390
392
|
bot,
|
|
391
393
|
botUserId,
|
|
394
|
+
mediaLocalRoots,
|
|
392
395
|
})
|
|
393
396
|
|
|
394
397
|
log(`[${accountId}]: dispatching to AI agent=${route.agentId} session=${route.sessionKey} history=${inboundHistory?.length ?? 0}`)
|
package/src/channel.ts
CHANGED
|
@@ -65,6 +65,7 @@ export const meetPlugin: ChannelPlugin<ResolvedMeetAccount> = {
|
|
|
65
65
|
messageToolHints: () => [
|
|
66
66
|
"- Meet targeting: omit `target` to reply to the current conversation (auto-inferred). Explicit targets: `user:<id>` or `channel:<id>`.",
|
|
67
67
|
"- Meet mentions: use `<@USER_ID>` to mention users, `<@-1>` to mention everyone. Examples: `<@553> hello` or `<@-1> important announcement`.",
|
|
68
|
+
"- Meet media: use `media` parameter to send images/files as attachments. DO NOT use Markdown image syntax like `` - Meet does not render it.",
|
|
68
69
|
],
|
|
69
70
|
},
|
|
70
71
|
groups: {
|
package/src/reply-dispatcher.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { MeetBot } from "@meet-im/meet-bot-jssdk"
|
|
|
2
2
|
import type { ClawdbotConfig, RuntimeEnv, ReplyPayload } from "openclaw/plugin-sdk"
|
|
3
3
|
import { createReplyPrefixContext } from "openclaw/plugin-sdk/channel-runtime"
|
|
4
4
|
import { getMeetRuntime } from "./runtime.js"
|
|
5
|
-
import { sendMessageMeet } from "./send.js"
|
|
5
|
+
import { sendMessageMeet, sendMediaMeet } from "./send.js"
|
|
6
6
|
|
|
7
7
|
/**
|
|
8
8
|
* 匹配末尾不完整的 mention 开始: <@ 或 <@xxx (没有闭合的 >)
|
|
@@ -73,12 +73,13 @@ export type CreateMeetReplyDispatcherOpts = {
|
|
|
73
73
|
accountId: string
|
|
74
74
|
bot: MeetBot
|
|
75
75
|
botUserId: string
|
|
76
|
+
mediaLocalRoots?: readonly string[]
|
|
76
77
|
}
|
|
77
78
|
|
|
78
79
|
export async function createMeetReplyDispatcher(
|
|
79
80
|
opts: CreateMeetReplyDispatcherOpts,
|
|
80
81
|
) {
|
|
81
|
-
const { cfg, agentId, chatId, replyToMessageId, accountId } = opts
|
|
82
|
+
const { cfg, agentId, chatId, replyToMessageId, accountId, mediaLocalRoots } = opts
|
|
82
83
|
const core = getMeetRuntime()
|
|
83
84
|
|
|
84
85
|
const textChunkLimit = core.channel.text.resolveTextChunkLimit(cfg, "meet", accountId, {
|
|
@@ -97,10 +98,40 @@ export async function createMeetReplyDispatcher(
|
|
|
97
98
|
},
|
|
98
99
|
deliver: async (payload: ReplyPayload, _info) => {
|
|
99
100
|
const text = payload.text ?? ""
|
|
100
|
-
|
|
101
|
+
const mediaUrls = payload.mediaUrls ?? (payload.mediaUrl ? [payload.mediaUrl] : [])
|
|
102
|
+
|
|
103
|
+
// 如果既没有文本也没有媒体,直接返回
|
|
104
|
+
if (!text.trim() && mediaUrls.length === 0) {
|
|
101
105
|
return
|
|
102
106
|
}
|
|
103
107
|
|
|
108
|
+
// 处理媒体文件:先发送媒体,再发送文本
|
|
109
|
+
// 如果有媒体,第一个媒体带上文本作为 caption,后续媒体不带文本
|
|
110
|
+
if (mediaUrls.length > 0) {
|
|
111
|
+
// 第一个媒体带上 caption
|
|
112
|
+
await sendMediaMeet({
|
|
113
|
+
cfg,
|
|
114
|
+
to: chatId,
|
|
115
|
+
text: text.trim() || undefined,
|
|
116
|
+
mediaUrl: mediaUrls[0],
|
|
117
|
+
mediaLocalRoots,
|
|
118
|
+
accountId,
|
|
119
|
+
})
|
|
120
|
+
// 后续媒体不带文本
|
|
121
|
+
for (let i = 1; i < mediaUrls.length; i++) {
|
|
122
|
+
await sendMediaMeet({
|
|
123
|
+
cfg,
|
|
124
|
+
to: chatId,
|
|
125
|
+
text: undefined,
|
|
126
|
+
mediaUrl: mediaUrls[i],
|
|
127
|
+
mediaLocalRoots,
|
|
128
|
+
accountId,
|
|
129
|
+
})
|
|
130
|
+
}
|
|
131
|
+
return
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// 只有文本,分片发送
|
|
104
135
|
const rawChunks = core.channel.text.chunkTextWithMode(text, textChunkLimit, chunkMode)
|
|
105
136
|
const protectedChunks = protectMentionsInChunks(rawChunks)
|
|
106
137
|
|
package/src/send.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { ClawdbotConfig, RuntimeEnv } from "openclaw/plugin-sdk";
|
|
|
2
2
|
import type { MeetMediaInfo } from "./types.js";
|
|
3
3
|
import type { UploadProgress as SdkUploadProgress } from "@meet-im/meet-bot-jssdk";
|
|
4
4
|
import { resolveMeetAccount } from "./accounts.js";
|
|
5
|
-
import { getMeetClient } from "./client.js";
|
|
5
|
+
import { getMeetClient, createMeetClient } from "./client.js";
|
|
6
6
|
import { parseTargetToSessionInfo } from "./sdk-bridge.js";
|
|
7
7
|
import { getMeetRuntime } from "./runtime.js";
|
|
8
8
|
|
|
@@ -180,13 +180,22 @@ export async function sendMessageMeet(
|
|
|
180
180
|
if (!token) {
|
|
181
181
|
throw new Error("Meet API token not configured");
|
|
182
182
|
}
|
|
183
|
+
// 检查 token 是否未解析(仍是 secret ref 格式)
|
|
184
|
+
if (token.startsWith("${secret:")) {
|
|
185
|
+
throw new Error(
|
|
186
|
+
`Meet API token not resolved (still a secret reference). ` +
|
|
187
|
+
`Ensure Gateway is running or token is configured directly. ` +
|
|
188
|
+
`AccountId: ${account.accountId}`
|
|
189
|
+
);
|
|
190
|
+
}
|
|
183
191
|
const botUserId = token.split(":")[0];
|
|
184
192
|
if (!botUserId) {
|
|
185
193
|
throw new Error("Invalid Meet API token format");
|
|
186
194
|
}
|
|
187
|
-
|
|
195
|
+
// 如果 client 不存在则自动创建(支持 message tool 直接发送消息)
|
|
196
|
+
let bot = getMeetClient(account.accountId);
|
|
188
197
|
if (!bot) {
|
|
189
|
-
|
|
198
|
+
bot = createMeetClient(account);
|
|
190
199
|
}
|
|
191
200
|
const { text: cleanText, atIds: extractedAtIds } = extractAtIds(text);
|
|
192
201
|
const finalAtIds = explicitAtIds
|
|
@@ -232,13 +241,22 @@ export async function sendMediaMeet(
|
|
|
232
241
|
if (!token) {
|
|
233
242
|
throw new Error("Meet API token not configured");
|
|
234
243
|
}
|
|
244
|
+
// 检查 token 是否未解析(仍是 secret ref 格式)
|
|
245
|
+
if (token.startsWith("${secret:")) {
|
|
246
|
+
throw new Error(
|
|
247
|
+
`Meet API token not resolved (still a secret reference). ` +
|
|
248
|
+
`Ensure Gateway is running or token is configured directly. ` +
|
|
249
|
+
`AccountId: ${account.accountId}`
|
|
250
|
+
);
|
|
251
|
+
}
|
|
235
252
|
const botUserId = token.split(":")[0];
|
|
236
253
|
if (!botUserId) {
|
|
237
254
|
throw new Error("Invalid Meet API token format");
|
|
238
255
|
}
|
|
239
|
-
|
|
256
|
+
// 如果 client 不存在则自动创建(支持 message tool 直接发送消息)
|
|
257
|
+
let bot = getMeetClient(account.accountId);
|
|
240
258
|
if (!bot) {
|
|
241
|
-
|
|
259
|
+
bot = createMeetClient(account);
|
|
242
260
|
}
|
|
243
261
|
|
|
244
262
|
const runtime = getMeetRuntime();
|