@xgjktech/xg_cwork_im 1.0.6 → 1.0.8

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/src/types.ts CHANGED
@@ -1,206 +1,287 @@
1
- /**
2
- * XG-IM Channel Plugin — 类型定义
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
-
17
- export interface XgImPluginModule {
18
- id: string;
19
- name: string;
20
- description?: string;
21
- configSchema?: unknown;
22
- register?: (api: OpenClawPluginApi) => void | Promise<void>;
23
- }
24
-
25
- /** 与 openclaw.plugin.json 中 id: xg_cwork_im 对应 */
26
- export type XgCworkImPluginModule = XgImPluginModule;
27
-
28
- // ─── Channel 配置 ────────────────────────────────────────────────────────────
29
-
30
- /** 单个机器人账户配置 */
31
- export interface XgImAccountConfig {
32
- /** 机器人 appKey,从 IM 后台注册获取 */
33
- appKey: string;
34
- /** 对应 OpenClaw 的 Agent ID,默认为 'main' */
35
- agentId?: string;
36
- /** 账户显示名称 */
37
- name?: string;
38
- /** 群聊策略:open = 不需要 @,mention = 必须 @ 机器人才触发 */
39
- groupPolicy?: "open" | "mention";
40
- }
41
-
42
- export interface XgImConfig extends OpenClawConfig {
43
- /** 多账户列表 */
44
- accounts?: XgImAccountConfig[];
45
-
46
- /** 机器人 appKey(单账户模式) */
47
- appKey?: string;
48
- /** 对应 OpenClaw 的 Agent ID(单账户模式) */
49
- agentId?: string;
50
- /** IM 服务域名,如 https://test.xgjktech.com.cn */
51
- baseUrl: string;
52
- /** WebSocket 服务域名,如 wss://test.xgjktech.com.cn */
53
- wsBaseUrl?: string;
54
- /** 是否启用 */
55
- enabled?: boolean;
56
- /** 账户显示名称(单账户模式使用) */
57
- name?: string;
58
- /** 群聊策略:open = 不需要 @,mention = 必须 @ 机器人才触发 */
59
- groupPolicy?: "open" | "mention";
60
- /** 允许的发送者 userId 白名单(空表示全部允许) */
61
- allowFrom?: string[];
62
- /** 是否开启调试日志 */
63
- debug?: boolean;
64
- /** 最大重连次数(默认 10) */
65
- maxConnectionAttempts?: number;
66
- /** 初始重连延迟 ms(默认 1000) */
67
- initialReconnectDelay?: number;
68
- /** 最大重连延迟 ms(默认 60000) */
69
- maxReconnectDelay?: number;
70
- /** 重连延迟抖动因子 0-1(默认 0.3) */
71
- reconnectJitter?: number;
72
- /**
73
- * 首次 AI 回复超时时间(毫秒)。
74
- *
75
- * - 未配置时默认 5 分钟(300_000ms)。
76
- * - 仅用于保护「思考中」占位消息,避免长时间不被更新。
77
- */
78
- firstReplyTimeoutMs?: number;
79
- }
80
-
81
- // ─── IM 接口 Request / Response ─────────────────────────────────────────────
82
-
83
- /** GET /user/login/appkey 的响应 */
84
- export interface GetTokenResponse {
85
- data?: {
86
- xgToken: string;
87
- empId: string;
88
- userName?: string;
89
- avatar?: string;
90
- corpId?: string;
91
- deptList?: unknown[];
92
- appCode?: string;
93
- telephone?: string;
94
- personId?: string;
95
- };
96
- resultCode?: number;
97
- resultMsg?: string | null;
98
- }
99
-
100
- /** 机器人身份信息(认证成功后缓存) */
101
- export interface BotIdentity {
102
- token: string;
103
- userId: string;
104
- name: string;
105
- }
106
-
107
- // ─── WebSocket 消息 ──────────────────────────────────────────────────────────
108
-
109
- /** WebSocket 消息通知(cmd = robotMention) */
110
- export interface WsMessage {
111
- cmd: string;
112
- params: WsMessageParams;
113
- ts: number;
114
- }
115
-
116
- /** robotMention 消息的 params */
117
- export interface WsMessageParams {
118
- msgId: string;
119
- groupId: string;
120
- /** 发送人信息 */
121
- userInfo: {
122
- /** 发送人 ID */
123
- id: string;
124
- /** 发送人显示名 */
125
- name: string;
126
- /**
127
- * 用户背景信息。
128
- * - 若非空,需要透传给 AI(可能是一段 JSON 字符串)。
129
- */
130
- background?: string;
131
- };
132
- msgContent: {
133
- text: string;
134
- type: string;
135
- url?: string;
136
- ext?: Record<string, any>;
137
- };
138
- /** 服务端可能返回 msgSendTime 或 timestamp */
139
- msgSendTime?: number;
140
- timestamp?: number;
141
- /** 被 @ 的人员 ID 列表 */
142
- mentions?: string[] | null;
143
- }
144
-
145
- // ─── IM 发送消息 ─────────────────────────────────────────────────────────────
146
-
147
- /** POST /im/message/send 请求体 */
148
- export interface SendMessageReply {
149
- /** 被回复消息ID */
150
- targetMsgId: string;
151
- /** 被回复消息发送者ID */
152
- targetUserId: string;
153
- /** 被回复消息发送者显示名 */
154
- targetUserName: string;
155
- /** 被回复消息摘要 */
156
- previewText: string;
157
- }
158
-
159
- export interface SendMessageBody {
160
- type: "TEXT" | "RICH_TEXT" | "VOICE";
161
- groupId?: string;
162
- toUserId?: string;
163
- text: string;
164
- atUserIds?: string[];
165
- /**
166
- * 业务侧生成的消息 ID。
167
- *
168
- * - 若不传:服务端按普通“新消息”处理。
169
- * - 若传入:服务端可根据 msgId 更新已有的流式占位消息内容。
170
- */
171
- msgId?: string;
172
-
173
- /**
174
- * 被回复消息信息。
175
- *
176
- * - 若不传:视为普通消息。
177
- * - 若传入:服务端可按 targetMsgId 建立“回复某条消息”的关联。
178
- */
179
- reply?: SendMessageReply;
180
- }
181
-
182
- /** GET /im/message/getLatestMsgListForAI 响应 */
183
- export interface GetLatestMsgListResponse {
184
- data?: WsMessageParams[];
185
- resultCode?: number;
186
- message?: string;
187
- }
188
-
189
- // ─── OpenClaw 插件 SDK 类型别名 ───────────────────────────────────────────────
190
-
191
- export type ChannelLogSink = SDKChannelLogSink;
192
- export type ChannelAccountSnapshot = SDKChannelAccountSnapshot;
193
-
194
- export interface ResolvedAccount {
195
- accountId: string;
196
- config: XgImConfig;
197
- enabled: boolean;
198
- configured: boolean;
199
- name?: string | null;
200
- }
201
-
202
- export type GatewayStartContext = SDKChannelGatewayContext<ResolvedAccount>;
203
- export type XgImChannelPlugin = SDKChannelPlugin<ResolvedAccount & { configured: boolean }>;
204
-
205
- /** PluginRuntime 的类型(内部 API 丰富,用 any 表示) */
206
- export type { PluginRuntime };
1
+ /**
2
+ * XG-IM Channel Plugin — 类型定义
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
+
17
+ export interface XgImPluginModule {
18
+ id: string;
19
+ name: string;
20
+ description?: string;
21
+ configSchema?: unknown;
22
+ register?: (api: OpenClawPluginApi) => void | Promise<void>;
23
+ }
24
+
25
+ /** 与 openclaw.plugin.json 中 id: xg_cwork_im 对应 */
26
+ export type XgCworkImPluginModule = XgImPluginModule;
27
+
28
+ // ─── Channel 配置 ────────────────────────────────────────────────────────────
29
+
30
+ /** 单个机器人账户配置 */
31
+ export interface XgImAccountConfig {
32
+ /** 机器人 appKey,从 IM 后台注册获取 */
33
+ appKey?: string;
34
+ /** 对应 OpenClaw 的 Agent ID,默认为 'main' */
35
+ agentId?: string;
36
+ /** 账户显示名称 */
37
+ name?: string;
38
+ /** 群聊策略:open = 不需要 @,mention = 必须 @ 机器人才触发 */
39
+ groupPolicy?: "open" | "mention";
40
+ /** multipart 整文件上传字段名,默认 file(与 `/file/upDownload/uploadWholeFile` 约定一致时可不改) */
41
+ fileUploadFormField?: string;
42
+ maxAttachmentBytes?: number;
43
+ }
44
+
45
+ export interface XgImConfig extends OpenClawConfig {
46
+ /** 多账户列表 */
47
+ accounts?: Record<string, XgImAccountConfig>;
48
+
49
+ /** 机器人 appKey(单账户模式) */
50
+ appKey?: string;
51
+ /** 对应 OpenClaw 的 Agent ID(单账户模式) */
52
+ agentId?: string;
53
+ /** IM 服务域名,如 https://test.xgjktech.com.cn */
54
+ baseUrl: string;
55
+ /** WebSocket 服务域名,如 wss://test.xgjktech.com.cn */
56
+ wsBaseUrl?: string;
57
+ /** 是否启用 */
58
+ enabled?: boolean;
59
+ /** 账户显示名称(单账户模式使用) */
60
+ name?: string;
61
+ /** 群聊策略:open = 不需要 @,mention = 必须 @ 机器人才触发 */
62
+ groupPolicy?: "open" | "mention";
63
+ /** 允许的发送者 userId 白名单(空表示全部允许) */
64
+ allowFrom?: string[];
65
+ /** 是否开启调试日志 */
66
+ debug?: boolean;
67
+ /** 最大重连次数(默认 10) */
68
+ maxConnectionAttempts?: number;
69
+ /** 初始重连延迟 ms(默认 1000) */
70
+ initialReconnectDelay?: number;
71
+ /** 最大重连延迟 ms(默认 60000) */
72
+ maxReconnectDelay?: number;
73
+ /** 重连延迟抖动因子 0-1(默认 0.3) */
74
+ reconnectJitter?: number;
75
+ /**
76
+ * 首次 AI 回复超时时间(毫秒)。
77
+ *
78
+ * - 未配置时默认 30 分钟(1800_000ms)。
79
+ * - 仅用于保护「思考中」占位消息,避免长时间不被更新。
80
+ */
81
+ firstReplyTimeoutMs?: number;
82
+
83
+ /**
84
+ * 附件上传地址固定为 `{baseUrl}/file/upDownload/uploadWholeFile`,请求头 `access-token` 与发 IM 相同。
85
+ * multipart 字段名默认 `file`,可通过 fileUploadFormField 覆盖。
86
+ */
87
+ fileUploadFormField?: string;
88
+ /** 单个附件下载/上传允许的最大字节数,默认 50MB */
89
+ maxAttachmentBytes?: number;
90
+ }
91
+
92
+ // ─── IM 接口 Request / Response ─────────────────────────────────────────────
93
+
94
+ /** GET /user/login/appkey 的响应 */
95
+ export interface GetTokenResponse {
96
+ data?: {
97
+ xgToken: string;
98
+ empId: string;
99
+ userName?: string;
100
+ avatar?: string;
101
+ corpId?: string;
102
+ deptList?: unknown[];
103
+ appCode?: string;
104
+ telephone?: string;
105
+ personId?: string;
106
+ };
107
+ resultCode?: number;
108
+ resultMsg?: string | null;
109
+ }
110
+
111
+ /** 机器人身份信息(认证成功后缓存) */
112
+ export interface BotIdentity {
113
+ token: string;
114
+ userId: string;
115
+ name: string;
116
+ }
117
+
118
+ // ─── WebSocket 消息 ──────────────────────────────────────────────────────────
119
+
120
+ /** WebSocket 消息通知(cmd = robotMention) */
121
+ export interface WsMessage {
122
+ cmd: string;
123
+ params: WsMessageParams;
124
+ ts: number;
125
+ }
126
+
127
+ /**
128
+ * IM 服务 `MsgFileVO` 对齐的附件项(WebSocket `msgContent.files[]`)。
129
+ */
130
+ export interface MsgFileVO {
131
+ /** 文件下载链接,短期有效 */
132
+ url: string;
133
+ /** 文件格式,小写:pdf、png、docx、doc、ppt、txt、md 等 */
134
+ format?: string;
135
+ /** 文件 ID;若来自七牛等无业务 id 的场景可为空 */
136
+ fileId?: string;
137
+ /** 文件大小(字节) */
138
+ size?: number;
139
+ /** 文件名称,如 xxx.pdf */
140
+ name?: string;
141
+ }
142
+
143
+ /** @deprecated 使用 {@link MsgFileVO} */
144
+ export type WsInboundFileItem = MsgFileVO;
145
+
146
+ /** 常见 IM format → MIME,供 OpenClaw 媒体理解;未知格式返回 undefined */
147
+ export function imFormatToMimeType(format: string | undefined): string | undefined {
148
+ const f = format?.trim().toLowerCase();
149
+ if (!f) return undefined;
150
+ const map: Record<string, string> = {
151
+ pdf: "application/pdf",
152
+ png: "image/png",
153
+ jpg: "image/jpeg",
154
+ jpeg: "image/jpeg",
155
+ gif: "image/gif",
156
+ webp: "image/webp",
157
+ doc: "application/msword",
158
+ docx: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
159
+ ppt: "application/vnd.ms-powerpoint",
160
+ pptx: "application/vnd.openxmlformats-officedocument.presentationml.presentation",
161
+ xls: "application/vnd.ms-excel",
162
+ xlsx: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
163
+ txt: "text/plain",
164
+ md: "text/markdown",
165
+ csv: "text/csv",
166
+ zip: "application/zip",
167
+ mp3: "audio/mpeg",
168
+ wav: "audio/wav",
169
+ mp4: "video/mp4",
170
+ };
171
+ return map[f];
172
+ }
173
+
174
+ /**
175
+ * 入站消息内容体(与 IM WebSocket `params.msgContent` 对齐)。
176
+ *
177
+ * - **type=`text`**:纯文本;**text** 建议非空。
178
+ * - **type=`file`**:带 1..N 个文件,**files** 建议至少 1 项;**text** 可为配文(同时上传多文件 + 一句话)。
179
+ * - 语音在 IM 侧已转写为文字时,应以 **type=`text`** 推送转写结果,不再使用 voice。
180
+ */
181
+ export interface WsMessageContent {
182
+ /** 文本正文;纯文本消息为主内容;file 消息上为可选配文 */
183
+ text?: string;
184
+ /** `text` | `file`(可扩展其它枚举,插件对未知类型按文本兜底) */
185
+ type: string;
186
+ /** 多附件;type 为 file 时由 IM 填至少一项 */
187
+ files?: MsgFileVO[];
188
+ ext?: Record<string, any>;
189
+ }
190
+
191
+ /** robotMention 消息的 params */
192
+ export interface WsMessageParams {
193
+ msgId: string;
194
+ groupId: string;
195
+ /** 发送人信息 */
196
+ userInfo: {
197
+ /** 发送人 ID */
198
+ id: string;
199
+ /** 发送人显示名 */
200
+ name: string;
201
+ /**
202
+ * 用户背景信息。
203
+ * - 若非空,需要透传给 AI(可能是一段 JSON 字符串)。
204
+ */
205
+ background?: string;
206
+ };
207
+ msgContent: WsMessageContent;
208
+ /** 服务端可能返回 msgSendTime 或 timestamp */
209
+ msgSendTime?: number;
210
+ timestamp?: number;
211
+ /** 被 @ 的人员 ID 列表 */
212
+ mentions?: string[] | null;
213
+ }
214
+
215
+ // ─── IM 发送消息 ─────────────────────────────────────────────────────────────
216
+
217
+ /** POST /im/message/send 请求体 */
218
+ export interface SendMessageReply {
219
+ /** 被回复消息ID */
220
+ targetMsgId: string;
221
+ /** 被回复消息发送者ID */
222
+ targetUserId: string;
223
+ /** 被回复消息发送者显示名 */
224
+ targetUserName: string;
225
+ /** 被回复消息摘要 */
226
+ previewText: string;
227
+ }
228
+
229
+ /** IM 发送 FILE 类型消息时的附件项(与发消息接口约定一致) */
230
+ export interface SendMessageFileAttachment {
231
+ fileId: string;
232
+ /** 固定为 FILE */
233
+ fileType: "FILE";
234
+ /** 小写扩展名,如 md、pdf */
235
+ format: string;
236
+ name: string;
237
+ size: number;
238
+ /** 固定为 resource */
239
+ source: "resource";
240
+ }
241
+
242
+ export type SendMessageBody =
243
+ | {
244
+ type: "TEXT" | "RICH_TEXT" | "VOICE";
245
+ groupId?: string;
246
+ toUserId?: string;
247
+ text: string;
248
+ atUserIds?: string[];
249
+ msgId?: string;
250
+ reply?: SendMessageReply;
251
+ }
252
+ | {
253
+ type: "FILE";
254
+ groupId?: string;
255
+ toUserId?: string;
256
+ text: string;
257
+ attachments: SendMessageFileAttachment[];
258
+ atUserIds?: string[];
259
+ msgId?: string;
260
+ reply?: SendMessageReply;
261
+ };
262
+
263
+ /** GET /im/message/getLatestMsgListForAI 响应 */
264
+ export interface GetLatestMsgListResponse {
265
+ data?: WsMessageParams[];
266
+ resultCode?: number;
267
+ message?: string;
268
+ }
269
+
270
+ // ─── OpenClaw 插件 SDK 类型别名 ───────────────────────────────────────────────
271
+
272
+ export type ChannelLogSink = SDKChannelLogSink;
273
+ export type ChannelAccountSnapshot = SDKChannelAccountSnapshot;
274
+
275
+ export interface ResolvedAccount {
276
+ accountId: string;
277
+ config: XgImConfig;
278
+ enabled: boolean;
279
+ configured: boolean;
280
+ name?: string | null;
281
+ }
282
+
283
+ export type GatewayStartContext = SDKChannelGatewayContext<ResolvedAccount>;
284
+ export type XgImChannelPlugin = SDKChannelPlugin<ResolvedAccount & { configured: boolean }>;
285
+
286
+ /** PluginRuntime 的类型(内部 API 丰富,用 any 表示) */
287
+ export type { PluginRuntime };