@xgjktech/xg_cwork_im 1.11.1 → 1.11.4

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 (53) hide show
  1. package/README.md +25 -18
  2. package/dist/index.d.ts +10 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/{index.ts → dist/index.js} +33 -37
  5. package/dist/index.js.map +1 -0
  6. package/dist/src/auth.d.ts +25 -0
  7. package/dist/src/auth.d.ts.map +1 -0
  8. package/{src/auth.ts → dist/src/auth.js} +55 -79
  9. package/dist/src/auth.js.map +1 -0
  10. package/dist/src/channel.d.ts +13 -0
  11. package/dist/src/channel.d.ts.map +1 -0
  12. package/{src/channel.ts → dist/src/channel.js} +224 -368
  13. package/dist/src/channel.js.map +1 -0
  14. package/dist/src/connection.d.ts +51 -0
  15. package/dist/src/connection.d.ts.map +1 -0
  16. package/{src/connection.ts → dist/src/connection.js} +45 -122
  17. package/dist/src/connection.js.map +1 -0
  18. package/dist/src/group-history-tool.d.ts +23 -0
  19. package/dist/src/group-history-tool.d.ts.map +1 -0
  20. package/{src/group-history-tool.ts → dist/src/group-history-tool.js} +168 -204
  21. package/dist/src/group-history-tool.js.map +1 -0
  22. package/dist/src/inbound-media-local.d.ts +40 -0
  23. package/dist/src/inbound-media-local.d.ts.map +1 -0
  24. package/{src/inbound-media-local.ts → dist/src/inbound-media-local.js} +52 -90
  25. package/dist/src/inbound-media-local.js.map +1 -0
  26. package/dist/src/recommended-system-prompt.d.ts +3 -0
  27. package/dist/src/recommended-system-prompt.d.ts.map +1 -0
  28. package/dist/src/recommended-system-prompt.js +3 -0
  29. package/dist/src/recommended-system-prompt.js.map +1 -0
  30. package/dist/src/resource-file.d.ts +65 -0
  31. package/dist/src/resource-file.d.ts.map +1 -0
  32. package/{src/resource-file.ts → dist/src/resource-file.js} +317 -339
  33. package/dist/src/resource-file.js.map +1 -0
  34. package/dist/src/send-group-message-tool.d.ts +16 -0
  35. package/dist/src/send-group-message-tool.d.ts.map +1 -0
  36. package/{src/send-group-message-tool.ts → dist/src/send-group-message-tool.js} +17 -34
  37. package/dist/src/send-group-message-tool.js.map +1 -0
  38. package/dist/src/send-service.d.ts +34 -0
  39. package/dist/src/send-service.d.ts.map +1 -0
  40. package/dist/src/send-service.js +197 -0
  41. package/dist/src/send-service.js.map +1 -0
  42. package/{src/tool-json-result.ts → dist/src/tool-json-result.d.ts} +14 -24
  43. package/dist/src/tool-json-result.d.ts.map +1 -0
  44. package/dist/src/tool-json-result.js +20 -0
  45. package/dist/src/tool-json-result.js.map +1 -0
  46. package/{src/types.ts → dist/src/types.d.ts} +32 -96
  47. package/dist/src/types.d.ts.map +1 -0
  48. package/dist/src/types.js +32 -0
  49. package/dist/src/types.js.map +1 -0
  50. package/openclaw.plugin.json +9 -0
  51. package/package.json +7 -6
  52. package/src/recommended-system-prompt.ts +0 -3
  53. package/src/send-service.ts +0 -228
@@ -1,19 +1,7 @@
1
1
  /**
2
2
  * XG-IM Channel Plugin — 类型定义
3
3
  */
4
-
5
- import type {
6
- OpenClawConfig,
7
- OpenClawPluginApi,
8
- ChannelLogSink as SDKChannelLogSink,
9
- ChannelAccountSnapshot as SDKChannelAccountSnapshot,
10
- ChannelGatewayContext as SDKChannelGatewayContext,
11
- ChannelPlugin as SDKChannelPlugin,
12
- PluginRuntime,
13
- } from "openclaw/plugin-sdk";
14
-
15
- // ─── 插件模块 ───────────────────────────────────────────────────────────────
16
-
4
+ import type { OpenClawConfig, OpenClawPluginApi, ChannelLogSink as SDKChannelLogSink, ChannelAccountSnapshot as SDKChannelAccountSnapshot, ChannelGatewayContext as SDKChannelGatewayContext, ChannelPlugin as SDKChannelPlugin, PluginRuntime } from "openclaw/plugin-sdk";
17
5
  export interface XgImPluginModule {
18
6
  id: string;
19
7
  name: string;
@@ -21,15 +9,13 @@ export interface XgImPluginModule {
21
9
  configSchema?: unknown;
22
10
  register?: (api: OpenClawPluginApi) => void | Promise<void>;
23
11
  }
24
-
25
12
  /** 与 openclaw.plugin.json 中 id: xg_cwork_im 对应 */
26
13
  export type XgCworkImPluginModule = XgImPluginModule;
27
-
28
- // ─── Channel 配置 ────────────────────────────────────────────────────────────
29
-
30
14
  /** 单个机器人账户配置 */
31
15
  export interface XgImAccountConfig {
32
- /** 机器人 appKey,从 IM 后台注册获取 */
16
+ /** 机器人 Key(新字段,优先于 appKey */
17
+ robotKey?: string;
18
+ /** 机器人 appKey,从 IM 后台注册获取(已改名为 robotKey,此字段保留兼容旧配置) */
33
19
  appKey?: string;
34
20
  /** 对应 OpenClaw 的 Agent ID,默认为 'main' */
35
21
  agentId?: string;
@@ -60,12 +46,12 @@ export interface XgImAccountConfig {
60
46
  */
61
47
  systemPrompt?: string;
62
48
  }
63
-
64
49
  export interface XgImConfig extends OpenClawConfig {
65
50
  /** 多账户列表 */
66
51
  accounts?: Record<string, XgImAccountConfig>;
67
-
68
- /** 机器人 appKey(单账户模式) */
52
+ /** 机器人 Key(新字段,优先于 appKey,单账户模式) */
53
+ robotKey?: string;
54
+ /** 机器人 appKey(单账户模式,已改名为 robotKey,此字段保留兼容旧配置) */
69
55
  appKey?: string;
70
56
  /** 对应 OpenClaw 的 Agent ID(单账户模式) */
71
57
  agentId?: string;
@@ -98,7 +84,6 @@ export interface XgImConfig extends OpenClawConfig {
98
84
  * - 仅用于保护「思考中」占位消息,避免长时间不被更新。
99
85
  */
100
86
  firstReplyTimeoutMs?: number;
101
-
102
87
  /**
103
88
  * 附件上传地址固定为 `{baseUrl}/file/upDownload/uploadWholeFile`,请求头 `access-token` 与发 IM 相同。
104
89
  * multipart 字段名默认 `file`,可通过 fileUploadFormField 覆盖。
@@ -106,7 +91,6 @@ export interface XgImConfig extends OpenClawConfig {
106
91
  fileUploadFormField?: string;
107
92
  /** 单个附件下载/上传允许的最大字节数,默认 50MB */
108
93
  maxAttachmentBytes?: number;
109
-
110
94
  /**
111
95
  * 若配置为非空相对路径(相对于当前 Agent workspace 根目录):入站附件会先下载到
112
96
  * `{workspace}/{本字段}/{userId}/{YYYY-MM-DD}/{name}_{HHmmssmmm}.ext`,再向 OpenClaw 传入 **workspace 相对路径**(默认 `./子目录/...`,便于沙箱挂载 `/workspace`)或 `file://`(见 `inboundMediaOpenClawPath`)。
@@ -126,9 +110,6 @@ export interface XgImConfig extends OpenClawConfig {
126
110
  */
127
111
  systemPrompt?: string;
128
112
  }
129
-
130
- // ─── IM 接口 Request / Response ─────────────────────────────────────────────
131
-
132
113
  /** GET /user/login/appkey 的响应 */
133
114
  export interface GetTokenResponse {
134
115
  data?: {
@@ -145,23 +126,18 @@ export interface GetTokenResponse {
145
126
  resultCode?: number;
146
127
  resultMsg?: string | null;
147
128
  }
148
-
149
129
  /** 机器人身份信息(认证成功后缓存) */
150
130
  export interface BotIdentity {
151
131
  token: string;
152
132
  userId: string;
153
133
  name: string;
154
134
  }
155
-
156
- // ─── WebSocket 消息 ──────────────────────────────────────────────────────────
157
-
158
135
  /** WebSocket 消息通知(cmd = robotMention) */
159
136
  export interface WsMessage {
160
137
  cmd: string;
161
138
  params: WsMessageParams;
162
139
  ts: number;
163
140
  }
164
-
165
141
  /**
166
142
  * 与 IM 服务 `MsgFileVO` 对齐的附件项(WebSocket `msgContent.files[]`)。
167
143
  */
@@ -182,38 +158,10 @@ export interface MsgFileVO {
182
158
  */
183
159
  content?: string;
184
160
  }
185
-
186
161
  /** @deprecated 使用 {@link MsgFileVO} */
187
162
  export type WsInboundFileItem = MsgFileVO;
188
-
189
163
  /** 常见 IM format → MIME,供 OpenClaw 媒体理解;未知格式返回 undefined */
190
- export function imFormatToMimeType(format: string | undefined): string | undefined {
191
- const f = format?.trim().toLowerCase();
192
- if (!f) return undefined;
193
- const map: Record<string, string> = {
194
- pdf: "application/pdf",
195
- png: "image/png",
196
- jpg: "image/jpeg",
197
- jpeg: "image/jpeg",
198
- gif: "image/gif",
199
- webp: "image/webp",
200
- doc: "application/msword",
201
- docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
202
- ppt: "application/vnd.ms-powerpoint",
203
- pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
204
- xls: "application/vnd.ms-excel",
205
- xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
206
- txt: "text/plain",
207
- md: "text/markdown",
208
- csv: "text/csv",
209
- zip: "application/zip",
210
- mp3: "audio/mpeg",
211
- wav: "audio/wav",
212
- mp4: "video/mp4",
213
- };
214
- return map[f];
215
- }
216
-
164
+ export declare function imFormatToMimeType(format: string | undefined): string | undefined;
217
165
  /**
218
166
  * 入站消息内容体(与 IM WebSocket `params.msgContent` 对齐)。
219
167
  *
@@ -230,7 +178,6 @@ export interface WsMessageContent {
230
178
  files?: MsgFileVO[];
231
179
  ext?: Record<string, any>;
232
180
  }
233
-
234
181
  /** robotMention 消息的 params */
235
182
  export interface WsMessageParams {
236
183
  msgId: string;
@@ -254,9 +201,6 @@ export interface WsMessageParams {
254
201
  /** 被 @ 的人员 ID 列表 */
255
202
  mentions?: string[] | null;
256
203
  }
257
-
258
- // ─── IM 发送消息 ─────────────────────────────────────────────────────────────
259
-
260
204
  /** POST /im/message/send 请求体 */
261
205
  export interface SendMessageReply {
262
206
  /** 被回复消息ID */
@@ -268,7 +212,6 @@ export interface SendMessageReply {
268
212
  /** 被回复消息摘要 */
269
213
  previewText: string;
270
214
  }
271
-
272
215
  /** IM 发送 FILE 类型消息时的附件项(与发消息接口约定一致) */
273
216
  export interface SendMessageFileAttachment {
274
217
  fileId: string;
@@ -281,42 +224,34 @@ export interface SendMessageFileAttachment {
281
224
  /** 固定为 resource */
282
225
  source: "resource";
283
226
  }
284
-
285
- export type SendMessageBody =
286
- | {
287
- type: "TEXT" | "RICH_TEXT" | "VOICE";
288
- groupId?: string;
289
- toUserId?: string;
290
- text: string;
291
- atUserIds?: string[];
292
- /** 流式占位消息 ID,用于将回复更新到对应的占位消息上 */
293
- msgId?: string;
294
- reply?: SendMessageReply;
295
- }
296
- | {
297
- type: "FILE";
298
- groupId?: string;
299
- toUserId?: string;
300
- text: string;
301
- attachments: SendMessageFileAttachment[];
302
- atUserIds?: string[];
303
- /** 流式占位消息 ID,用于将回复更新到对应的占位消息上 */
304
- msgId?: string;
305
- reply?: SendMessageReply;
306
- };
307
-
227
+ export type SendMessageBody = {
228
+ type: "TEXT" | "RICH_TEXT" | "VOICE";
229
+ groupId?: string;
230
+ toUserId?: string;
231
+ text: string;
232
+ atUserIds?: string[];
233
+ /** 流式占位消息 ID,用于将回复更新到对应的占位消息上 */
234
+ msgId?: string;
235
+ reply?: SendMessageReply;
236
+ } | {
237
+ type: "FILE";
238
+ groupId?: string;
239
+ toUserId?: string;
240
+ text: string;
241
+ attachments: SendMessageFileAttachment[];
242
+ atUserIds?: string[];
243
+ /** 流式占位消息 ID,用于将回复更新到对应的占位消息上 */
244
+ msgId?: string;
245
+ reply?: SendMessageReply;
246
+ };
308
247
  /** GET /im/message/getLatestMsgListForAI 响应 */
309
248
  export interface GetLatestMsgListResponse {
310
249
  data?: WsMessageParams[];
311
250
  resultCode?: number;
312
251
  message?: string;
313
252
  }
314
-
315
- // ─── OpenClaw 插件 SDK 类型别名 ───────────────────────────────────────────────
316
-
317
253
  export type ChannelLogSink = SDKChannelLogSink;
318
254
  export type ChannelAccountSnapshot = SDKChannelAccountSnapshot;
319
-
320
255
  export interface ResolvedAccount {
321
256
  accountId: string;
322
257
  config: XgImConfig;
@@ -324,9 +259,10 @@ export interface ResolvedAccount {
324
259
  configured: boolean;
325
260
  name?: string | null;
326
261
  }
327
-
328
262
  export type GatewayStartContext = SDKChannelGatewayContext<ResolvedAccount>;
329
- export type XgImChannelPlugin = SDKChannelPlugin<ResolvedAccount & { configured: boolean }>;
330
-
263
+ export type XgImChannelPlugin = SDKChannelPlugin<ResolvedAccount & {
264
+ configured: boolean;
265
+ }>;
331
266
  /** PluginRuntime 的类型(内部 API 丰富,用 any 表示) */
332
267
  export type { PluginRuntime };
268
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * XG-IM Channel Plugin — 类型定义
3
+ */
4
+ /** 常见 IM format → MIME,供 OpenClaw 媒体理解;未知格式返回 undefined */
5
+ export function imFormatToMimeType(format) {
6
+ const f = format?.trim().toLowerCase();
7
+ if (!f)
8
+ return undefined;
9
+ const map = {
10
+ pdf: "application/pdf",
11
+ png: "image/png",
12
+ jpg: "image/jpeg",
13
+ jpeg: "image/jpeg",
14
+ gif: "image/gif",
15
+ webp: "image/webp",
16
+ doc: "application/msword",
17
+ docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
18
+ ppt: "application/vnd.ms-powerpoint",
19
+ pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
20
+ xls: "application/vnd.ms-excel",
21
+ xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
22
+ txt: "text/plain",
23
+ md: "text/markdown",
24
+ csv: "text/csv",
25
+ zip: "application/zip",
26
+ mp3: "audio/mpeg",
27
+ wav: "audio/wav",
28
+ mp4: "video/mp4",
29
+ };
30
+ return map[f];
31
+ }
32
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AA8LH,2DAA2D;AAC3D,MAAM,UAAU,kBAAkB,CAAC,MAA0B;IACzD,MAAM,CAAC,GAAG,MAAM,EAAE,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IACvC,IAAI,CAAC,CAAC;QAAE,OAAO,SAAS,CAAC;IACzB,MAAM,GAAG,GAA2B;QAChC,GAAG,EAAE,iBAAiB;QACtB,GAAG,EAAE,WAAW;QAChB,GAAG,EAAE,YAAY;QACjB,IAAI,EAAE,YAAY;QAClB,GAAG,EAAE,WAAW;QAChB,IAAI,EAAE,YAAY;QAClB,GAAG,EAAE,oBAAoB;QACzB,IAAI,EAAE,yEAAyE;QAC/E,GAAG,EAAE,+BAA+B;QACpC,IAAI,EAAE,2EAA2E;QACjF,GAAG,EAAE,0BAA0B;QAC/B,IAAI,EAAE,mEAAmE;QACzE,GAAG,EAAE,YAAY;QACjB,EAAE,EAAE,eAAe;QACnB,GAAG,EAAE,UAAU;QACf,GAAG,EAAE,iBAAiB;QACtB,GAAG,EAAE,YAAY;QACjB,GAAG,EAAE,WAAW;QAChB,GAAG,EAAE,WAAW;KACnB,CAAC;IACF,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC"}
@@ -3,6 +3,15 @@
3
3
  "channels": [
4
4
  "xg_cwork_im"
5
5
  ],
6
+ "channelConfigs": {
7
+ "xg_cwork_im": {
8
+ "schema": {
9
+ "type": "object",
10
+ "additionalProperties": true,
11
+ "properties": {}
12
+ }
13
+ }
14
+ },
6
15
  "configSchema": {
7
16
  "type": "object",
8
17
  "additionalProperties": true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xgjktech/xg_cwork_im",
3
- "version": "1.11.1",
3
+ "version": "1.11.4",
4
4
  "description": "XG CWork IM channel plugin for OpenClaw",
5
5
  "keywords": [
6
6
  "bot",
@@ -11,18 +11,19 @@
11
11
  ],
12
12
  "license": "MIT",
13
13
  "type": "module",
14
- "main": "index.ts",
14
+ "main": "dist/index.js",
15
+ "types": "dist/index.d.ts",
15
16
  "files": [
16
17
  ".npmrc",
17
- "index.ts",
18
- "src/*.ts",
18
+ "dist/**/*",
19
19
  "openclaw.plugin.json"
20
20
  ],
21
21
  "scripts": {
22
+ "build": "tsc -p tsconfig.json",
22
23
  "type-check": "tsc -p tsconfig.json --noEmit",
23
24
  "lint": "tsc -p tsconfig.json --noEmit",
24
25
  "install:prod": "npm install --omit=dev",
25
- "prepublishOnly": "npm run type-check"
26
+ "prepublishOnly": "npm run build"
26
27
  },
27
28
  "dependencies": {
28
29
  "@sinclair/typebox": "^0.32.0",
@@ -40,7 +41,7 @@
40
41
  },
41
42
  "openclaw": {
42
43
  "extensions": [
43
- "./index.ts"
44
+ "./dist/index.js"
44
45
  ],
45
46
  "channels": [
46
47
  "xg_cwork_im"
@@ -1,3 +0,0 @@
1
- /** 建议复制到 `channels.xg_cwork_im.systemPrompt`。 */
2
- export const XG_IM_RECOMMENDED_CHANNEL_SYSTEM_PROMPT =
3
- "发文件给用户时,在回复正文里单独写一行 `MEDIA:<路径>`,例如:MEDIA:/workspace/report.pdf。路径支持 /workspace/…、file://…、http(s)://…。OpenClaw 会自动读取该路径并让通道上传,用户可直接在 IM 中下载。不要把路径当作已发送;也不要上传到外部网站。";
@@ -1,228 +0,0 @@
1
- /**
2
- * XG-IM 消息发送模块
3
- *
4
- * 调用 IM 接口将 AI 回复发送到指定群聊,并 @ 原始发送者。
5
- * 支持 RICH_TEXT 与带资源 fileId 的 FILE 类型(attachments)。
6
- */
7
-
8
- import axios from "axios";
9
- import type { Log } from "./auth.js";
10
- import {
11
- downloadMediaBuffer,
12
- formatFromFilename,
13
- resolveMaxAttachmentBytes,
14
- resolveResourceUploadUrl,
15
- uploadWholeResourceFile,
16
- } from "./resource-file.js";
17
- import type { SendMessageBody, SendMessageFileAttachment, SendMessageReply, XgImConfig } from "./types.js";
18
-
19
- function formatDeliverError(err: unknown): string {
20
- if (axios.isAxiosError(err)) {
21
- const parts = [err.message];
22
- if (err.code) parts.push(`axiosCode=${err.code}`);
23
- if (err.response?.status != null) parts.push(`httpStatus=${err.response.status}`);
24
- return parts.join(" ");
25
- }
26
- if (err instanceof Error) return err.message;
27
- return String(err);
28
- }
29
-
30
- async function postImMessage(
31
- config: XgImConfig,
32
- token: string,
33
- groupId: string,
34
- body: SendMessageBody,
35
- atUserIds: string[] = [],
36
- log?: Log,
37
- ): Promise<void> {
38
- const url = `${config.baseUrl}/im/message/send`;
39
- const full: SendMessageBody = {
40
- ...body,
41
- groupId,
42
- ...(atUserIds.length > 0 ? { atUserIds } : {}),
43
- } as SendMessageBody;
44
-
45
- log?.info(`[cwork_im:send] POST ${url} groupId=${groupId} type=${full.type} atUsers=${JSON.stringify(atUserIds)}`);
46
- if (config.debug) {
47
- log?.debug?.(`[cwork_im:send] Request body: ${JSON.stringify(full)}`);
48
- }
49
-
50
- try {
51
- const res = await axios.post(url, full, {
52
- headers: {
53
- "Content-Type": "application/json",
54
- "access-token": token,
55
- },
56
- timeout: 10_000,
57
- });
58
-
59
- log?.info(`[cwork_im:send] Response status=${res.status}`);
60
- if (config.debug) {
61
- log?.debug?.(`[cwork_im:send] Response body: ${JSON.stringify(res.data)}`);
62
- }
63
-
64
- // Detect business-level errors that arrive with HTTP 200.
65
- // IM API unified response: { data, resultCode: 1, resultMsg: "" } — resultCode=1 means success.
66
- const d = res.data;
67
- if (d && typeof d === "object") {
68
- const resultCode = (d as Record<string, unknown>).resultCode;
69
- const resultMsg = (d as Record<string, unknown>).resultMsg;
70
- if (resultCode !== undefined && resultCode !== 1) {
71
- throw new Error(
72
- `IM API error resultCode=${resultCode}${resultMsg ? ` resultMsg=${resultMsg}` : ""}`,
73
- );
74
- }
75
- }
76
- } catch (err: unknown) {
77
- const msg = err instanceof Error ? err.message : String(err);
78
- log?.error(`[cwork_im:send] Failed to send message to groupId=${groupId}: ${msg}`);
79
- throw err;
80
- }
81
- }
82
-
83
- /** OpenClaw dispatch deliver 单块载荷:文本 + 可选媒体 URL(与 plugin-sdk 约定对齐)。 */
84
- export type ReplyDeliverPayload = {
85
- markdown?: string;
86
- text?: string;
87
- isThinking?: boolean;
88
- mediaUrl?: string;
89
- mediaUrls?: string[];
90
- };
91
-
92
- /**
93
- * 将 deliver 块发到 IM:若有媒体则先 POST baseUrl/file/upDownload/uploadWholeFile 再发 FILE;否则发 RICH_TEXT。
94
- */
95
- export async function sendReplyDeliverBlock(
96
- config: XgImConfig,
97
- token: string,
98
- groupId: string,
99
- payload: ReplyDeliverPayload,
100
- atUserIds: string[] = [],
101
- log?: Log,
102
- msgId?: string,
103
- reply?: SendMessageReply,
104
- ): Promise<void> {
105
- const textToSend = (payload.markdown || payload.text || "").trim();
106
- const mediaList = [
107
- ...(payload.mediaUrl ? [payload.mediaUrl] : []),
108
- ...((payload.mediaUrls ?? []).filter((u) => typeof u === "string" && u.trim())),
109
- ];
110
- const uniqueUrls = [...new Set(mediaList)];
111
- const maxBytes = resolveMaxAttachmentBytes(config);
112
- const formField = config.fileUploadFormField?.trim() || "file";
113
-
114
- const wantFile = uniqueUrls.length > 0 && !payload.isThinking;
115
-
116
- if (wantFile) {
117
- const fileUploadUrl = resolveResourceUploadUrl(config.baseUrl);
118
- try {
119
- const attachments: SendMessageFileAttachment[] = [];
120
- for (const u of uniqueUrls) {
121
- const { buffer, filename } = await downloadMediaBuffer(u, maxBytes, log);
122
- const { fileId } = await uploadWholeResourceFile({
123
- fileUploadUrl,
124
- token,
125
- buffer,
126
- filename,
127
- formField,
128
- log,
129
- });
130
- attachments.push({
131
- fileId,
132
- fileType: "FILE",
133
- format: formatFromFilename(filename),
134
- name: filename,
135
- size: buffer.length,
136
- source: "resource",
137
- });
138
- }
139
- const caption = textToSend.length > 0 ? textToSend : " ";
140
- await postImMessage(
141
- config,
142
- token,
143
- groupId,
144
- {
145
- type: "FILE",
146
- text: caption,
147
- attachments,
148
- ...(msgId ? { msgId } : {}),
149
- ...(reply ? { reply } : {}),
150
- },
151
- atUserIds,
152
- log,
153
- );
154
- return;
155
- } catch (err: unknown) {
156
- log?.error(`[cwork_im:send] FILE deliver failed, fallback to text if any: ${formatDeliverError(err)}`);
157
- const errNote = `(文件发送失败:${formatDeliverError(err)})`;
158
- const fallbackText = textToSend.length > 0 ? `${textToSend}\n\n${errNote}` : errNote;
159
- await postImMessage(
160
- config,
161
- token,
162
- groupId,
163
- {
164
- type: "RICH_TEXT",
165
- text: fallbackText,
166
- ...(msgId ? { msgId } : {}),
167
- ...(reply ? { reply } : {}),
168
- },
169
- atUserIds,
170
- log,
171
- );
172
- return;
173
- }
174
- }
175
-
176
- if (textToSend.length > 0) {
177
- await postImMessage(
178
- config,
179
- token,
180
- groupId,
181
- {
182
- type: "RICH_TEXT",
183
- text: textToSend,
184
- ...(msgId ? { msgId } : {}),
185
- ...(reply ? { reply } : {}),
186
- },
187
- atUserIds,
188
- log,
189
- );
190
- }
191
- }
192
-
193
- /**
194
- * 发送文本消息到指定 IM 群聊。
195
- *
196
- * @param config 插件配置
197
- * @param token 鉴权 token
198
- * @param groupId 目标群聊 ID(gid / groupId)
199
- * @param content 消息内容文本
200
- * @param atUserIds 需要 @ 的用户 ID 列表(可为空)
201
- * @param log 日志接口
202
- * @param msgId 可选的业务消息 ID(用于覆盖/更新已有消息)
203
- * @param reply 可选的被回复消息信息(用于在 IM 中建立“回复某条消息”的关联)
204
- */
205
- export async function sendTextMessage(
206
- config: XgImConfig,
207
- token: string,
208
- groupId: string,
209
- content: string,
210
- atUserIds: string[] = [],
211
- log?: Log,
212
- msgId?: string,
213
- reply?: SendMessageReply,
214
- ): Promise<void> {
215
- await postImMessage(
216
- config,
217
- token,
218
- groupId,
219
- {
220
- type: "RICH_TEXT",
221
- text: content,
222
- ...(msgId ? { msgId } : {}),
223
- ...(reply ? { reply } : {}),
224
- },
225
- atUserIds,
226
- log,
227
- );
228
- }