@xgjktech/xg_cwork_im 1.11.3 → 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 (51) hide show
  1. package/README.md +10 -10
  2. package/dist/index.d.ts +10 -0
  3. package/dist/index.d.ts.map +1 -0
  4. package/{index.ts → dist/index.js} +5 -9
  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} +180 -385
  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} +77 -99
  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/{src/send-service.ts → dist/src/send-service.js} +60 -146
  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} +26 -94
  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/package.json +7 -6
  51. package/src/recommended-system-prompt.ts +0 -3
@@ -3,92 +3,94 @@
3
3
  *
4
4
  * 上传地址固定为 `baseUrl + /file/upDownload/uploadWholeFile`,与 IM 同域,使用与发消息相同的 access-token。
5
5
  */
6
-
7
6
  import axios from "axios";
8
7
  import { File } from "node:buffer";
9
8
  import { readFile } from "node:fs/promises";
10
9
  import path from "node:path";
11
10
  import { fileURLToPath } from "node:url";
12
- import type { Log } from "./auth.js";
13
-
14
11
  const DEFAULT_MAX_BYTES = 50 * 1024 * 1024;
15
-
16
12
  /** 整文件上传接口路径(拼在 channels.xg_cwork_im.baseUrl 上) */
17
13
  export const RESOURCE_UPLOAD_PATH = "/file/upDownload/uploadWholeFile";
18
-
19
- export function resolveResourceUploadUrl(baseUrl: string): string {
14
+ export function resolveResourceUploadUrl(baseUrl) {
20
15
  const b = baseUrl.trim();
21
- if (!b) throw new Error("[cwork_im] baseUrl is required for resource upload");
16
+ if (!b)
17
+ throw new Error("[cwork_im] baseUrl is required for resource upload");
22
18
  return new URL(RESOURCE_UPLOAD_PATH, b.endsWith("/") ? b : `${b}/`).href;
23
19
  }
24
-
25
20
  /** 从上传接口 JSON 中解析 fileId(兼容常见嵌套 data) */
26
- export function extractFileIdFromUploadResponse(data: unknown): string | undefined {
27
- if (data == null) return undefined;
28
- if (typeof data === "string" && data.trim().length > 0) return data.trim();
29
- if (typeof data !== "object") return undefined;
30
- const o = data as Record<string, unknown>;
21
+ export function extractFileIdFromUploadResponse(data) {
22
+ if (data == null)
23
+ return undefined;
24
+ if (typeof data === "string" && data.trim().length > 0)
25
+ return data.trim();
26
+ if (typeof data !== "object")
27
+ return undefined;
28
+ const o = data;
31
29
  for (const key of ["fileId", "id", "resourceId", "file_id"]) {
32
30
  const v = o[key];
33
- if (typeof v === "string" && v.length > 0) return v;
31
+ if (typeof v === "string" && v.length > 0)
32
+ return v;
34
33
  }
35
34
  if (o.data != null) {
36
35
  const nested = extractFileIdFromUploadResponse(o.data);
37
- if (nested) return nested;
36
+ if (nested)
37
+ return nested;
38
38
  }
39
39
  return undefined;
40
40
  }
41
-
42
- export function formatFromFilename(filename: string): string {
41
+ export function formatFromFilename(filename) {
43
42
  const ext = path.extname(filename).replace(/^\./, "").toLowerCase();
44
- if (ext && ext.length <= 16 && /^[a-z0-9]+$/i.test(ext)) return ext;
43
+ if (ext && ext.length <= 16 && /^[a-z0-9]+$/i.test(ext))
44
+ return ext;
45
45
  return "bin";
46
46
  }
47
-
48
47
  /** 仅当含 %XX 序列时 decodeURIComponent,避免对已解码的 Unicode 再 decode 抛错 */
49
- export function safeDecodeUriFilenameSegment(segment: string): string {
48
+ export function safeDecodeUriFilenameSegment(segment) {
50
49
  const s = segment.trim();
51
- if (!s) return s;
52
- if (!/%[0-9A-Fa-f]{2}/.test(s)) return s;
50
+ if (!s)
51
+ return s;
52
+ if (!/%[0-9A-Fa-f]{2}/.test(s))
53
+ return s;
53
54
  try {
54
55
  return decodeURIComponent(s.replace(/\+/g, " "));
55
- } catch {
56
+ }
57
+ catch {
56
58
  return s;
57
59
  }
58
60
  }
59
-
60
61
  /**
61
62
  * 从 HTTP Content-Disposition 解析文件名(优先 RFC 5987 `filename*=` UTF-8,再普通 filename=)。
62
63
  */
63
- export function parseFilenameFromContentDisposition(header: string | undefined): string | undefined {
64
- if (header == null || typeof header !== "string") return undefined;
64
+ export function parseFilenameFromContentDisposition(header) {
65
+ if (header == null || typeof header !== "string")
66
+ return undefined;
65
67
  const h = header.trim();
66
- if (!h) return undefined;
67
-
68
+ if (!h)
69
+ return undefined;
68
70
  const star = /filename\*\s*=\s*(?:UTF-8|utf-8)''([^;\r\n]+)/i.exec(h);
69
71
  if (star?.[1]) {
70
72
  const v = star[1].trim();
71
73
  const decoded = safeDecodeUriFilenameSegment(v);
72
- if (decoded) return decoded;
74
+ if (decoded)
75
+ return decoded;
73
76
  }
74
-
75
77
  const quoted = /filename\s*=\s*"((?:[^"\\]|\\.)*)"/i.exec(h);
76
78
  if (quoted?.[1]) {
77
79
  const inner = quoted[1].replace(/\\(.)/g, "$1").trim();
78
- if (inner) return safeDecodeUriFilenameSegment(inner);
80
+ if (inner)
81
+ return safeDecodeUriFilenameSegment(inner);
79
82
  }
80
-
81
83
  const unquoted = /filename\s*=\s*([^;\r\n]+)/i.exec(h);
82
84
  if (unquoted?.[1]) {
83
85
  let v = unquoted[1].trim().replace(/^["']|["']$/g, "");
84
- if (v.toLowerCase().startsWith("utf-8''")) v = v.slice(7);
85
- if (v) return safeDecodeUriFilenameSegment(v);
86
+ if (v.toLowerCase().startsWith("utf-8''"))
87
+ v = v.slice(7);
88
+ if (v)
89
+ return safeDecodeUriFilenameSegment(v);
86
90
  }
87
-
88
91
  return undefined;
89
92
  }
90
-
91
- export function displayNameFromUrl(url: string): string {
93
+ export function displayNameFromUrl(url) {
92
94
  try {
93
95
  if (url.startsWith("file://")) {
94
96
  return path.basename(fileURLToPath(url)) || "file";
@@ -102,37 +104,37 @@ export function displayNameFromUrl(url: string): string {
102
104
  const last = pathname.split("/").filter(Boolean).pop() ?? "";
103
105
  const base = safeDecodeUriFilenameSegment(last.split("?")[0] || "");
104
106
  return base || "attachment";
105
- } catch {
107
+ }
108
+ catch {
106
109
  return "attachment";
107
110
  }
108
111
  }
109
-
110
112
  /** 日志用:截断过长路径/URL */
111
- export function summarizeMediaRef(ref: string, maxLen = 160): string {
113
+ export function summarizeMediaRef(ref, maxLen = 160) {
112
114
  const t = ref.trim().replace(/\s+/g, " ");
113
- if (t.length <= maxLen) return t;
115
+ if (t.length <= maxLen)
116
+ return t;
114
117
  return `${t.slice(0, maxLen)}…(len=${t.length})`;
115
118
  }
116
-
117
- function isHttpOrHttps(ref: string): boolean {
119
+ function isHttpOrHttps(ref) {
118
120
  try {
119
121
  const u = new URL(ref.trim());
120
122
  return u.protocol === "http:" || u.protocol === "https:";
121
- } catch {
123
+ }
124
+ catch {
122
125
  return false;
123
126
  }
124
127
  }
125
-
126
128
  /**
127
129
  * 将字符串解析为可交给 readFile 的本机路径(兼容 Windows / macOS / Linux)。
128
130
  * - 使用当前进程的 path.isAbsolute(各 OS 语义正确)。
129
131
  * - Windows:Git Bash / MSYS 的 `/c/Users/...`、Cygwin `/cygdrive/c/...`。
130
132
  * - 非 Windows:若传入 `D:\...` 形式仍做一次规范化(多用于日志/失败提示,读文件通常会失败)。
131
133
  */
132
- export function resolveLocalFsPath(ref: string): { fsPath: string; via: string } | null {
134
+ export function resolveLocalFsPath(ref) {
133
135
  const raw = ref.trim();
134
- if (!raw) return null;
135
-
136
+ if (!raw)
137
+ return null;
136
138
  if (process.platform === "win32") {
137
139
  // MSYS/Git Bash: /c/Users/foo → C:\Users\foo(要求 /<盘符>/ 后仍有路径,避免误伤 /Users)
138
140
  const msys = /^\/([a-zA-Z])\/(.+)$/.exec(raw.replace(/\\/g, "/"));
@@ -150,21 +152,16 @@ export function resolveLocalFsPath(ref: string): { fsPath: string; via: string }
150
152
  return { fsPath, via: "cygwin" };
151
153
  }
152
154
  }
153
-
154
155
  if (path.isAbsolute(raw)) {
155
156
  return { fsPath: path.normalize(raw), via: `native-${process.platform}` };
156
157
  }
157
-
158
158
  // Linux/macOS 上 WSL 互操作常见:/mnt/c/... 已是 posix 绝对路径,上面已命中
159
-
160
159
  if (process.platform !== "win32" && /^[a-zA-Z]:[/\\]/.test(raw)) {
161
160
  return { fsPath: path.win32.normalize(raw), via: "win-style-path" };
162
161
  }
163
-
164
162
  return null;
165
163
  }
166
-
167
- async function readLocalFsIntoBuffer(fsPath: string, maxBytes: number, log?: Log): Promise<{ buffer: Buffer; filename: string }> {
164
+ async function readLocalFsIntoBuffer(fsPath, maxBytes, log) {
168
165
  const buffer = await readFile(fsPath);
169
166
  if (buffer.length > maxBytes) {
170
167
  throw new Error(`local file size ${buffer.length} exceeds maxAttachmentBytes=${maxBytes}`);
@@ -173,7 +170,6 @@ async function readLocalFsIntoBuffer(fsPath: string, maxBytes: number, log?: Log
173
170
  log?.info(`[cwork_im:media] local ok bytes=${buffer.length} name=${filename}`);
174
171
  return { buffer, filename };
175
172
  }
176
-
177
173
  /**
178
174
  * 将 OpenClaw 约定的 `/workspace/<rel>` 路径解析为本机绝对路径(跨平台)。
179
175
  *
@@ -185,50 +181,46 @@ async function readLocalFsIntoBuffer(fsPath: string, maxBytes: number, log?: Log
185
181
  *
186
182
  * 返回 null 表示路径不符合 /workspace/ 格式。
187
183
  */
188
- export function resolveWorkspacePrefixPath(raw: string): string | null {
189
- if (!raw.startsWith("/workspace/") && raw !== "/workspace") return null;
184
+ export function resolveWorkspacePrefixPath(raw) {
185
+ if (!raw.startsWith("/workspace/") && raw !== "/workspace")
186
+ return null;
190
187
  const rel = raw.startsWith("/workspace/") ? raw.slice("/workspace/".length) : "";
191
188
  const cwd = process.cwd();
192
189
  return rel ? path.join(cwd, rel) : cwd;
193
190
  }
194
-
195
- export async function downloadMediaBuffer(
196
- url: string,
197
- maxBytes: number,
198
- log?: Log,
199
- ): Promise<{ buffer: Buffer; filename: string }> {
191
+ export async function downloadMediaBuffer(url, maxBytes, log) {
200
192
  const raw = url.trim();
201
193
  log?.info(`[cwork_im:media] resolve ref=${summarizeMediaRef(raw)}`);
202
-
203
194
  // Handle OpenClaw /workspace/ convention: map to actual workspace directory.
204
195
  const workspaceResolved = resolveWorkspacePrefixPath(raw);
205
196
  if (workspaceResolved && workspaceResolved !== raw) {
206
197
  log?.info(`[cwork_im:media] /workspace/ -> ${summarizeMediaRef(workspaceResolved)}`);
207
198
  try {
208
199
  return await readLocalFsIntoBuffer(workspaceResolved, maxBytes, log);
209
- } catch (err: unknown) {
200
+ }
201
+ catch (err) {
210
202
  log?.error(`[cwork_im:media] readFile failed /workspace/ ${summarizeMediaRef(workspaceResolved)}: ${String(err)}`);
211
203
  throw err;
212
204
  }
213
205
  }
214
-
215
206
  if (raw.startsWith("file://")) {
216
- let fsPath: string;
207
+ let fsPath;
217
208
  try {
218
209
  fsPath = fileURLToPath(raw);
219
- } catch (e) {
210
+ }
211
+ catch (e) {
220
212
  log?.error(`[cwork_im:media] invalid file:// URL: ${summarizeMediaRef(raw)} ${String(e)}`);
221
213
  throw e;
222
214
  }
223
215
  log?.info(`[cwork_im:media] read file:// -> ${summarizeMediaRef(fsPath)}`);
224
216
  try {
225
217
  return await readLocalFsIntoBuffer(fsPath, maxBytes, log);
226
- } catch (err: unknown) {
218
+ }
219
+ catch (err) {
227
220
  log?.error(`[cwork_im:media] readFile failed file:// ${summarizeMediaRef(fsPath)}: ${String(err)}`);
228
221
  throw err;
229
222
  }
230
223
  }
231
-
232
224
  if (isHttpOrHttps(raw)) {
233
225
  log?.info(`[cwork_im:media] GET ${summarizeMediaRef(raw)}`);
234
226
  try {
@@ -239,17 +231,19 @@ export async function downloadMediaBuffer(
239
231
  maxBodyLength: maxBytes,
240
232
  validateStatus: (s) => s >= 200 && s < 300,
241
233
  });
242
- const buffer = Buffer.from(res.data as ArrayBuffer);
234
+ const buffer = Buffer.from(res.data);
243
235
  let filename = displayNameFromUrl(raw);
244
236
  const cdRaw = res.headers["content-disposition"];
245
237
  const cd = Array.isArray(cdRaw) ? cdRaw[0] : cdRaw;
246
238
  if (typeof cd === "string") {
247
239
  const fromCd = parseFilenameFromContentDisposition(cd);
248
- if (fromCd) filename = fromCd;
240
+ if (fromCd)
241
+ filename = fromCd;
249
242
  }
250
243
  log?.info(`[cwork_im:media] http ok bytes=${buffer.length} name=${filename}`);
251
244
  return { buffer, filename };
252
- } catch (err: unknown) {
245
+ }
246
+ catch (err) {
253
247
  const detail = axios.isAxiosError(err)
254
248
  ? `${err.message}${err.code ? ` axiosCode=${err.code}` : ""}${err.response?.status != null ? ` httpStatus=${err.response.status}` : ""}`
255
249
  : String(err);
@@ -257,43 +251,31 @@ export async function downloadMediaBuffer(
257
251
  throw err;
258
252
  }
259
253
  }
260
-
261
254
  const resolved = resolveLocalFsPath(raw);
262
255
  if (resolved) {
263
256
  log?.info(`[cwork_im:media] local via=${resolved.via} -> ${summarizeMediaRef(resolved.fsPath)}`);
264
257
  try {
265
258
  return await readLocalFsIntoBuffer(resolved.fsPath, maxBytes, log);
266
- } catch (err: unknown) {
259
+ }
260
+ catch (err) {
267
261
  log?.error(`[cwork_im:media] readFile failed ${summarizeMediaRef(resolved.fsPath)}: ${String(err)}`);
268
262
  throw err;
269
263
  }
270
264
  }
271
-
272
- const hint =
273
- "请使用 http(s)、file://(三系统通用),或本机绝对路径:Windows C:\\\\... / UNC;macOS/Linux /Users、/home、/mnt/c/...(WSL);Windows 下 Git Bash 可用 /c/...";
265
+ const hint = "请使用 http(s)、file://(三系统通用),或本机绝对路径:Windows C:\\\\... / UNC;macOS/Linux /Users、/home、/mnt/c/...(WSL);Windows 下 Git Bash 可用 /c/...";
274
266
  log?.error(`[cwork_im:media] unsupported ref=${summarizeMediaRef(raw)} (${hint})`);
275
267
  throw new Error(`[cwork_im] 无法读取媒体(${hint}): ${summarizeMediaRef(raw)}`);
276
268
  }
277
-
278
269
  /**
279
270
  * multipart 上传整文件,返回 fileId 与字节数。
280
271
  */
281
- export async function uploadWholeResourceFile(args: {
282
- fileUploadUrl: string;
283
- token: string;
284
- buffer: Buffer;
285
- filename: string;
286
- formField: string;
287
- log?: Log;
288
- }): Promise<{ fileId: string; size: number }> {
272
+ export async function uploadWholeResourceFile(args) {
289
273
  const { fileUploadUrl, token, buffer, filename, formField, log } = args;
290
274
  const form = new FormData();
291
275
  // 使用 File 携带 UTF-8 文件名,避免部分环境下 Blob+第三参在 multipart 里被错误编码导致服务端乱码
292
276
  const file = new File([buffer], filename, { type: "application/octet-stream" });
293
277
  form.append(formField, file);
294
-
295
278
  log?.info(`[cwork_im:upload] POST ${fileUploadUrl} field=${formField} name=${filename} bytes=${buffer.length}`);
296
-
297
279
  const res = await fetch(fileUploadUrl, {
298
280
  method: "POST",
299
281
  headers: {
@@ -301,39 +283,35 @@ export async function uploadWholeResourceFile(args: {
301
283
  },
302
284
  body: form,
303
285
  });
304
-
305
286
  const rawText = await res.text();
306
- let json: unknown;
287
+ let json;
307
288
  try {
308
289
  json = rawText ? JSON.parse(rawText) : undefined;
309
- } catch {
290
+ }
291
+ catch {
310
292
  json = undefined;
311
293
  }
312
-
313
294
  if (!res.ok) {
314
295
  log?.error(`[cwork_im:upload] HTTP ${res.status} body=${rawText.slice(0, 500)}`);
315
296
  throw new Error(`upload HTTP ${res.status}: ${rawText.slice(0, 500)}`);
316
297
  }
317
-
318
298
  // Unified IM API response: { data, resultCode: 1, resultMsg: "" } — resultCode=1 means success.
319
299
  if (json && typeof json === "object") {
320
- const j = json as Record<string, unknown>;
300
+ const j = json;
321
301
  if (j.resultCode !== undefined && j.resultCode !== 1) {
322
302
  const msg = `upload IM API error resultCode=${j.resultCode}${j.resultMsg ? ` resultMsg=${j.resultMsg}` : ""}`;
323
303
  log?.error(`[cwork_im:upload] ${msg} body=${rawText.slice(0, 500)}`);
324
304
  throw new Error(msg);
325
305
  }
326
306
  }
327
-
328
307
  const fileId = extractFileIdFromUploadResponse(json ?? rawText);
329
308
  if (!fileId) {
330
309
  log?.error(`[cwork_im:upload] missing fileId in body=${rawText.slice(0, 500)}`);
331
310
  throw new Error(`upload response missing fileId: ${rawText.slice(0, 500)}`);
332
311
  }
333
-
334
312
  return { fileId, size: buffer.length };
335
313
  }
336
-
337
- export function resolveMaxAttachmentBytes(config: { maxAttachmentBytes?: number }): number {
314
+ export function resolveMaxAttachmentBytes(config) {
338
315
  return config.maxAttachmentBytes ?? DEFAULT_MAX_BYTES;
339
316
  }
317
+ //# sourceMappingURL=resource-file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resource-file.js","sourceRoot":"","sources":["../../src/resource-file.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * XG-IM「主动推消息」工具(供 OpenClaw 在非对话场景下调用)
3
+ *
4
+ * 用途:定时任务、Cron、后台任务等需要 **经本 channel 主动把结果推送到 IM 群** 时,发一条纯文本。
5
+ * **不用于**用户正通过 IM 与助手聊天时的回合内回复——那种情况走正常助手回复流,用不上本工具。
6
+ *
7
+ * 通过 api.registerTool() 注入,工具内部自动获取机器人 token。
8
+ */
9
+ import type { AnyAgentTool } from "openclaw/plugin-sdk";
10
+ import type { XgImConfig } from "./types.js";
11
+ /**
12
+ * 构建「主动推送群消息」工具(纯文本)。
13
+ * 由 index.ts 在 register() 里调用。
14
+ */
15
+ export declare function buildSendGroupMessageTool(config: XgImConfig): AnyAgentTool;
16
+ //# sourceMappingURL=send-group-message-tool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"send-group-message-tool.d.ts","sourceRoot":"","sources":["../../src/send-group-message-tool.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AAIxD,OAAO,KAAK,EAAe,UAAU,EAAE,MAAM,YAAY,CAAC;AA2B1D;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,UAAU,GAAG,YAAY,CAkD1E"}
@@ -6,44 +6,32 @@
6
6
  *
7
7
  * 通过 api.registerTool() 注入,工具内部自动获取机器人 token。
8
8
  */
9
-
10
- import { Type, type Static } from "@sinclair/typebox";
11
- import type { AnyAgentTool } from "openclaw/plugin-sdk";
9
+ import { Type } from "@sinclair/typebox";
12
10
  import { toolJsonResult } from "./tool-json-result.js";
13
11
  import { getToken } from "./auth.js";
14
12
  import { sendTextMessage } from "./send-service.js";
15
- import type { BotIdentity, XgImConfig } from "./types.js";
16
13
  import { resolveAccountConfig } from "./group-history-tool.js";
17
-
18
14
  // ─── 工具参数 Schema ─────────────────────────────────────────────────────────
19
-
20
15
  const SendGroupMessageParams = Type.Object({
21
16
  groupId: Type.String({
22
17
  description: "目标群聊 ID(IM 系统的群组唯一标识符,即 groupId / gid)",
23
18
  }),
24
- accountId: Type.Optional(
25
- Type.String({
26
- description:
27
- "(可选)要使用的 xg_cwork_im 账户 ID(即 accounts 的 key,例如 main/orchestrator)。",
28
- }),
29
- ),
19
+ accountId: Type.Optional(Type.String({
20
+ description: "(可选)要使用的 xg_cwork_im 账户 ID(即 accounts 的 key,例如 main/orchestrator)。",
21
+ })),
30
22
  text: Type.String({
31
23
  description: "要发送的消息内容(仅纯文本,不支持附件/文件)",
32
24
  }),
33
- atUserIds: Type.Optional(
34
- Type.Array(Type.String(), {
35
- description: "需要 @ 的用户 ID 列表,可为空数组",
36
- }),
37
- ),
25
+ atUserIds: Type.Optional(Type.Array(Type.String(), {
26
+ description: "需要 @ 的用户 ID 列表,可为空数组",
27
+ })),
38
28
  });
39
-
40
29
  // ─── 工具构建函数 ─────────────────────────────────────────────────────────────
41
-
42
30
  /**
43
31
  * 构建「主动推送群消息」工具(纯文本)。
44
32
  * 由 index.ts 在 register() 里调用。
45
33
  */
46
- export function buildSendGroupMessageTool(config: XgImConfig): AnyAgentTool {
34
+ export function buildSendGroupMessageTool(config) {
47
35
  return {
48
36
  name: "xg_cwork_im_send_group_message",
49
37
  label: "【xg_cwork_im】主动推送群消息(纯文本)",
@@ -54,38 +42,32 @@ export function buildSendGroupMessageTool(config: XgImConfig): AnyAgentTool {
54
42
  "【参数】groupId 为 IM 群唯一 ID;主动推送时若需告知某人,可填 atUserIds。",
55
43
  ].join("\n"),
56
44
  parameters: SendGroupMessageParams,
57
- async execute(_toolCallId: string, params: Static<typeof SendGroupMessageParams>) {
45
+ async execute(_toolCallId, params) {
58
46
  const { groupId, text, atUserIds = [], accountId } = params;
59
-
60
47
  console.log(`[cwork_im][tool] xg_cwork_im_send_group_message called: groupId=${groupId} atUsers=${JSON.stringify(atUserIds)}`);
61
-
62
- let identity: BotIdentity;
48
+ let identity;
63
49
  try {
64
50
  const accountConfig = resolveAccountConfig(config, accountId);
65
51
  identity = await getToken(accountConfig);
66
- console.log(
67
- `[cwork_im][tool] xg_cwork_im_send_group_message token acquired for userId=${identity.userId} using accountId=${accountId ?? "0"}`,
68
- );
69
- } catch (err: unknown) {
52
+ console.log(`[cwork_im][tool] xg_cwork_im_send_group_message token acquired for userId=${identity.userId} using accountId=${accountId ?? "0"}`);
53
+ }
54
+ catch (err) {
70
55
  return toolJsonResult({
71
56
  ok: false,
72
57
  error: `Failed to obtain access token: ${String(err)}`,
73
58
  });
74
59
  }
75
-
76
60
  try {
77
61
  const accountConfig = resolveAccountConfig(config, accountId);
78
62
  await sendTextMessage(accountConfig, identity.token, groupId, text, atUserIds);
79
- console.log(
80
- `[cwork_im][tool] xg_cwork_im_send_group_message success: groupId=${groupId} using accountId=${accountId ?? "0"}`,
81
- );
82
- } catch (err: unknown) {
63
+ console.log(`[cwork_im][tool] xg_cwork_im_send_group_message success: groupId=${groupId} using accountId=${accountId ?? "0"}`);
64
+ }
65
+ catch (err) {
83
66
  return toolJsonResult({
84
67
  ok: false,
85
68
  error: `Failed to send message to group ${groupId}: ${String(err)}`,
86
69
  });
87
70
  }
88
-
89
71
  return toolJsonResult({
90
72
  ok: true,
91
73
  groupId,
@@ -94,3 +76,4 @@ export function buildSendGroupMessageTool(config: XgImConfig): AnyAgentTool {
94
76
  },
95
77
  };
96
78
  }
79
+ //# sourceMappingURL=send-group-message-tool.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"send-group-message-tool.js","sourceRoot":"","sources":["../../src/send-group-message-tool.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * XG-IM 消息发送模块
3
+ *
4
+ * 调用 IM 接口将 AI 回复发送到指定群聊,并 @ 原始发送者。
5
+ * 支持 RICH_TEXT 与带资源 fileId 的 FILE 类型(attachments)。
6
+ */
7
+ import type { Log } from "./auth.js";
8
+ import type { SendMessageReply, XgImConfig } from "./types.js";
9
+ /** OpenClaw dispatch deliver 单块载荷:文本 + 可选媒体 URL(与 plugin-sdk 约定对齐)。 */
10
+ export type ReplyDeliverPayload = {
11
+ markdown?: string;
12
+ text?: string;
13
+ isThinking?: boolean;
14
+ mediaUrl?: string;
15
+ mediaUrls?: string[];
16
+ };
17
+ /**
18
+ * 将 deliver 块发到 IM:若有媒体则先 POST baseUrl/file/upDownload/uploadWholeFile 再发 FILE;否则发 RICH_TEXT。
19
+ */
20
+ export declare function sendReplyDeliverBlock(config: XgImConfig, token: string, groupId: string, payload: ReplyDeliverPayload, atUserIds?: string[], log?: Log, msgId?: string, reply?: SendMessageReply): Promise<void>;
21
+ /**
22
+ * 发送文本消息到指定 IM 群聊。
23
+ *
24
+ * @param config 插件配置
25
+ * @param token 鉴权 token
26
+ * @param groupId 目标群聊 ID(gid / groupId)
27
+ * @param content 消息内容文本
28
+ * @param atUserIds 需要 @ 的用户 ID 列表(可为空)
29
+ * @param log 日志接口
30
+ * @param msgId 可选的业务消息 ID(用于覆盖/更新已有消息)
31
+ * @param reply 可选的被回复消息信息(用于在 IM 中建立“回复某条消息”的关联)
32
+ */
33
+ export declare function sendTextMessage(config: XgImConfig, token: string, groupId: string, content: string, atUserIds?: string[], log?: Log, msgId?: string, reply?: SendMessageReply): Promise<void>;
34
+ //# sourceMappingURL=send-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"send-service.d.ts","sourceRoot":"","sources":["../../src/send-service.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAQrC,OAAO,KAAK,EAA8C,gBAAgB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAyH3G,uEAAuE;AACvE,MAAM,MAAM,mBAAmB,GAAG;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB,CAAC;AAEF;;GAEG;AACH,wBAAsB,qBAAqB,CACvC,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,mBAAmB,EAC5B,SAAS,GAAE,MAAM,EAAO,EACxB,GAAG,CAAC,EAAE,GAAG,EACT,KAAK,CAAC,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,IAAI,CAAC,CAuFf;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,eAAe,CACjC,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,SAAS,GAAE,MAAM,EAAO,EACxB,GAAG,CAAC,EAAE,GAAG,EACT,KAAK,CAAC,EAAE,MAAM,EACd,KAAK,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,IAAI,CAAC,CAcf"}