@xgjktech/xg_cwork_im 1.11.3 → 1.11.5
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/README.md +20 -10
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/{index.ts → dist/index.js} +5 -9
- package/dist/index.js.map +1 -0
- package/dist/src/auth.d.ts +25 -0
- package/dist/src/auth.d.ts.map +1 -0
- package/{src/auth.ts → dist/src/auth.js} +55 -79
- package/dist/src/auth.js.map +1 -0
- package/dist/src/channel.d.ts +13 -0
- package/dist/src/channel.d.ts.map +1 -0
- package/{src/channel.ts → dist/src/channel.js} +252 -392
- package/dist/src/channel.js.map +1 -0
- package/dist/src/connection.d.ts +51 -0
- package/dist/src/connection.d.ts.map +1 -0
- package/{src/connection.ts → dist/src/connection.js} +63 -124
- package/dist/src/connection.js.map +1 -0
- package/dist/src/group-history-tool.d.ts +23 -0
- package/dist/src/group-history-tool.d.ts.map +1 -0
- package/{src/group-history-tool.ts → dist/src/group-history-tool.js} +168 -204
- package/dist/src/group-history-tool.js.map +1 -0
- package/dist/src/inbound-media-local.d.ts +40 -0
- package/dist/src/inbound-media-local.d.ts.map +1 -0
- package/{src/inbound-media-local.ts → dist/src/inbound-media-local.js} +52 -90
- package/dist/src/inbound-media-local.js.map +1 -0
- package/dist/src/recommended-system-prompt.d.ts +3 -0
- package/dist/src/recommended-system-prompt.d.ts.map +1 -0
- package/dist/src/recommended-system-prompt.js +3 -0
- package/dist/src/recommended-system-prompt.js.map +1 -0
- package/dist/src/resource-file.d.ts +65 -0
- package/dist/src/resource-file.d.ts.map +1 -0
- package/{src/resource-file.ts → dist/src/resource-file.js} +80 -103
- package/dist/src/resource-file.js.map +1 -0
- package/dist/src/send-group-message-tool.d.ts +16 -0
- package/dist/src/send-group-message-tool.d.ts.map +1 -0
- package/{src/send-group-message-tool.ts → dist/src/send-group-message-tool.js} +17 -34
- package/dist/src/send-group-message-tool.js.map +1 -0
- package/dist/src/send-service.d.ts +34 -0
- package/dist/src/send-service.d.ts.map +1 -0
- package/dist/src/send-service.js +263 -0
- package/dist/src/send-service.js.map +1 -0
- package/{src/tool-json-result.ts → dist/src/tool-json-result.d.ts} +14 -24
- package/dist/src/tool-json-result.d.ts.map +1 -0
- package/dist/src/tool-json-result.js +20 -0
- package/dist/src/tool-json-result.js.map +1 -0
- package/{src/types.ts → dist/src/types.d.ts} +32 -95
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +32 -0
- package/dist/src/types.js.map +1 -0
- package/openclaw.plugin.json +6 -0
- package/package.json +7 -6
- package/src/recommended-system-prompt.ts +0 -3
- package/src/send-service.ts +0 -283
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
IM 系统 → WebSocket → 插件(本项目) → OpenClaw AI → IM 发送接口 → IM 系统
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
1. 插件启动时用 `appKey
|
|
11
|
+
1. 插件启动时用 `robotKey`(兼容旧字段 `appKey`)换取 `access_token` 和 `userId`
|
|
12
12
|
2. 建立 WebSocket 长连接,接收 `robotMention` 事件
|
|
13
13
|
3. 将收到的消息转发给 OpenClaw 处理
|
|
14
14
|
4. OpenClaw AI 回复后,插件:
|
|
@@ -22,7 +22,7 @@ IM 系统 → WebSocket → 插件(本项目) → OpenClaw AI → IM
|
|
|
22
22
|
## 前置条件
|
|
23
23
|
|
|
24
24
|
- 已安装 [OpenClaw](https://github.com/openclaw) (`>=2026.2.13`)
|
|
25
|
-
- 已在 IM 后台注册机器人,获取到 `appKey`
|
|
25
|
+
- 已在 IM 后台注册机器人,获取到 `robotKey`(旧配置中的 `appKey` 仍兼容)
|
|
26
26
|
|
|
27
27
|
---
|
|
28
28
|
|
|
@@ -135,7 +135,7 @@ openclaw plugins enable xg_cwork_im
|
|
|
135
135
|
"baseUrl": "https://cwork-web-test.xgjktech.com.cn",
|
|
136
136
|
"wsBaseUrl": "wss://cwork-web-test.xgjktech.com.cn",
|
|
137
137
|
"accounts": {
|
|
138
|
-
"main": { "
|
|
138
|
+
"main": { "robotKey": "你的机器人 robotKey", "agentId": "main", "name": "个人助手" }
|
|
139
139
|
}
|
|
140
140
|
}
|
|
141
141
|
}
|
|
@@ -180,8 +180,8 @@ openclaw gateway restart
|
|
|
180
180
|
// 沙箱 Agent 建议加:MediaPath 使用 /workspace/... 而不是 ./...(避免 read 按 cwd 解析失败)
|
|
181
181
|
"inboundMediaSandboxRootPrefix": "/workspace",
|
|
182
182
|
"accounts": {
|
|
183
|
-
"main": { "
|
|
184
|
-
"sales": { "
|
|
183
|
+
"main": { "robotKey": "robotKey_机器人A", "agentId": "main", "name": "个人助手" },
|
|
184
|
+
"sales": { "robotKey": "robotKey_机器人B", "agentId": "sales", "name": "销售助手" }
|
|
185
185
|
}
|
|
186
186
|
}
|
|
187
187
|
},
|
|
@@ -209,7 +209,7 @@ openclaw gateway restart
|
|
|
209
209
|
// 按需启用:入站附件落盘到 workspace,见配置表 inboundMediaWorkspaceSubdir
|
|
210
210
|
// "inboundMediaWorkspaceSubdir": "xg_im_inbound",
|
|
211
211
|
"accounts": {
|
|
212
|
-
"main": { "
|
|
212
|
+
"main": { "robotKey": "你的生产 robotKey", "agentId": "main", "name": "个人助手" }
|
|
213
213
|
}
|
|
214
214
|
}
|
|
215
215
|
}
|
|
@@ -242,7 +242,7 @@ openclaw gateway restart
|
|
|
242
242
|
|
|
243
243
|
| 选项 | 类型 | 默认值 | 说明 |
|
|
244
244
|
|---|---|---|---|
|
|
245
|
-
| `
|
|
245
|
+
| `robotKey` | string | **必填** | 机器人标识(IM 后台注册获取);旧字段 `appKey` 仍兼容 |
|
|
246
246
|
| `agentId` | string | `"main"` | 对应的 OpenClaw Agent ID |
|
|
247
247
|
| `name` | string | — | 账户显示名称(仅用于日志标识) |
|
|
248
248
|
| `groupPolicy` | string | 继承顶层 | 可覆盖顶层的 groupPolicy |
|
|
@@ -255,7 +255,7 @@ openclaw gateway restart
|
|
|
255
255
|
## 故障排除
|
|
256
256
|
|
|
257
257
|
### 收不到消息
|
|
258
|
-
- 确认 `appKey`
|
|
258
|
+
- 确认 `robotKey` 正确(或旧字段 `appKey` 正确),且机器人已在 IM 后台激活
|
|
259
259
|
- 查看 OpenClaw 日志,确认 WebSocket 连接成功(`WebSocket connected successfully`)
|
|
260
260
|
- 群聊中确认已 `@` 机器人
|
|
261
261
|
|
|
@@ -266,7 +266,17 @@ openclaw gateway restart
|
|
|
266
266
|
|
|
267
267
|
### token 相关报错
|
|
268
268
|
- 确认 `baseUrl` 域名可达
|
|
269
|
-
- 确认 `appKey`
|
|
269
|
+
- 确认 `robotKey` 有效(或旧字段 `appKey` 有效,可在 IM 后台查看机器人状态)
|
|
270
|
+
|
|
271
|
+
### 网关报 `plugin must declare contracts.tools before registering agent tools`
|
|
272
|
+
|
|
273
|
+
OpenClaw 2026+ 要求:在 `register()` 里调用 `api.registerTool(...)` 的工具名,必须预先写在 **`openclaw.plugin.json`** 的 **`contracts.tools`** 中(与工具对象的 `name` 一致)。本仓库已列出 `xg_cwork_im_get_group_chat_history`、`xg_cwork_im_send_group_message`。若你以后新增工具,请同步扩展 manifest。
|
|
274
|
+
|
|
275
|
+
### 占位消息后变「AI 未响应」、网关日志 `invoke=0`、但网页客户端有助手回复(OpenClaw 2026.x)
|
|
276
|
+
|
|
277
|
+
原因:默认群聊在未配置 **`messages.visibleReplies`/`messages.groupChat.visibleReplies` = `automatic`** 时,OpenClaw 会启用 **`message_tool_only`**(只通过 message 类工具对用户可见),从而 **不向 Channel 插件的 `deliver` 投递**,模型仍会写入会话网页可见,但 **本插件不会 POST `/im/message/send`**,`msgId` 合并也不会发生。
|
|
278
|
+
|
|
279
|
+
当前插件已在 `dispatchMentionedReply` 中对本轮强制 **`replyOptions.sourceReplyDeliveryMode: "automatic"`**,一般无需再在 `openclaw.json` 里改该项;若你仍遇到问题,可把 **`messages.groupChat.visibleReplies`** 设为 **`"automatic"`** 做一次全局对齐。
|
|
270
280
|
|
|
271
281
|
---
|
|
272
282
|
|
|
@@ -277,7 +287,7 @@ openclaw-channel-xg-cwork-im/
|
|
|
277
287
|
├── index.ts # 插件入口
|
|
278
288
|
├── src/
|
|
279
289
|
│ ├── types.ts # 类型定义
|
|
280
|
-
│ ├── auth.ts # 认证(appKey → token)
|
|
290
|
+
│ ├── auth.ts # 认证(robotKey/appKey → token)
|
|
281
291
|
│ ├── connection.ts # WebSocket 连接管理
|
|
282
292
|
│ ├── send-service.ts # IM 消息发送
|
|
283
293
|
│ ├── group-history-tool.ts # 拉取群消息历史的 Agent Tool
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* XG-IM Channel Plugin for OpenClaw
|
|
3
|
+
*
|
|
4
|
+
* 插件入口:注册 XG-IM channel,并注入 PluginRuntime 供消息路由使用
|
|
5
|
+
*/
|
|
6
|
+
import type { XgCworkImPluginModule } from "./src/types.js";
|
|
7
|
+
export { XG_IM_RECOMMENDED_CHANNEL_SYSTEM_PROMPT } from "./src/recommended-system-prompt.js";
|
|
8
|
+
declare const plugin: XgCworkImPluginModule;
|
|
9
|
+
export default plugin;
|
|
10
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAOH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAC;AAE5D,OAAO,EAAE,uCAAuC,EAAE,MAAM,oCAAoC,CAAC;AAE7F,QAAA,MAAM,MAAM,EAAE,qBAmBb,CAAC;AAEF,eAAe,MAAM,CAAC"}
|
|
@@ -3,22 +3,17 @@
|
|
|
3
3
|
*
|
|
4
4
|
* 插件入口:注册 XG-IM channel,并注入 PluginRuntime 供消息路由使用
|
|
5
5
|
*/
|
|
6
|
-
|
|
7
|
-
import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
|
|
8
6
|
import { emptyPluginConfigSchema } from "openclaw/plugin-sdk";
|
|
9
7
|
import { setXgImRuntime, xgCworkImChannelPlugin } from "./src/channel.js";
|
|
10
8
|
import { buildGroupHistoryTool, extractXgCworkImConfig } from "./src/group-history-tool.js";
|
|
11
9
|
import { buildSendGroupMessageTool } from "./src/send-group-message-tool.js";
|
|
12
|
-
import type { XgCworkImPluginModule } from "./src/types.js";
|
|
13
|
-
|
|
14
10
|
export { XG_IM_RECOMMENDED_CHANNEL_SYSTEM_PROMPT } from "./src/recommended-system-prompt.js";
|
|
15
|
-
|
|
16
|
-
const plugin: XgCworkImPluginModule = {
|
|
11
|
+
const plugin = {
|
|
17
12
|
id: "xg_cwork_im",
|
|
18
13
|
name: "XG CWork IM Channel",
|
|
19
14
|
description: "工作说说 IM 机器人 Channel 插件,通过 WebSocket 长连接接入",
|
|
20
15
|
configSchema: emptyPluginConfigSchema(),
|
|
21
|
-
register(api
|
|
16
|
+
register(api) {
|
|
22
17
|
setXgImRuntime(api.runtime);
|
|
23
18
|
api.registerChannel({ plugin: xgCworkImChannelPlugin });
|
|
24
19
|
// 注册 AI 工具(静态工具对象,确保 toolNames 正确注册)
|
|
@@ -28,10 +23,11 @@ const plugin: XgCworkImPluginModule = {
|
|
|
28
23
|
api.registerTool(buildGroupHistoryTool(cworkConfig), { optional: true });
|
|
29
24
|
// 主动推送(Cron/定时等)向 IM 发纯文本;用户经 IM 对话时不用此工具
|
|
30
25
|
api.registerTool(buildSendGroupMessageTool(cworkConfig), { optional: true });
|
|
31
|
-
}
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
32
28
|
console.warn("[xg_cwork_im] channel config not found, skipping tool registration");
|
|
33
29
|
}
|
|
34
30
|
},
|
|
35
31
|
};
|
|
36
|
-
|
|
37
32
|
export default plugin;
|
|
33
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAC1E,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAC5F,OAAO,EAAE,yBAAyB,EAAE,MAAM,kCAAkC,CAAC;AAG7E,OAAO,EAAE,uCAAuC,EAAE,MAAM,oCAAoC,CAAC;AAE7F,MAAM,MAAM,GAA0B;IAClC,EAAE,EAAE,aAAa;IACjB,IAAI,EAAE,qBAAqB;IAC3B,WAAW,EAAE,2CAA2C;IACxD,YAAY,EAAE,uBAAuB,EAAE;IACvC,QAAQ,CAAC,GAAsB;QAC3B,cAAc,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QAC5B,GAAG,CAAC,eAAe,CAAC,EAAE,MAAM,EAAE,sBAAsB,EAAE,CAAC,CAAC;QACxD,qCAAqC;QACrC,MAAM,WAAW,GAAG,sBAAsB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QACvD,IAAI,WAAW,EAAE,CAAC;YACd,kEAAkE;YAClE,GAAG,CAAC,YAAY,CAAC,qBAAqB,CAAC,WAAW,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;YACzE,0CAA0C;YAC1C,GAAG,CAAC,YAAY,CAAC,yBAAyB,CAAC,WAAW,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QACjF,CAAC;aAAM,CAAC;YACJ,OAAO,CAAC,IAAI,CAAC,oEAAoE,CAAC,CAAC;QACvF,CAAC;IACL,CAAC;CACJ,CAAC;AAEF,eAAe,MAAM,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* XG-IM 认证模块
|
|
3
|
+
*
|
|
4
|
+
* 通过 appKey 换取 access_token 和机器人 userId。
|
|
5
|
+
* token 有效期一年,启动时获取一次并缓存,无需定期刷新。
|
|
6
|
+
*/
|
|
7
|
+
import type { BotIdentity, XgImConfig } from "./types.js";
|
|
8
|
+
export type Log = {
|
|
9
|
+
info: (msg: string) => void;
|
|
10
|
+
warn?: (msg: string) => void;
|
|
11
|
+
error: (msg: string) => void;
|
|
12
|
+
debug?: (msg: string) => void;
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* 通过 appKey 获取机器人身份信息(token + userId)。
|
|
16
|
+
* 若缓存中已有有效 token,直接返回缓存;否则请求接口。
|
|
17
|
+
*
|
|
18
|
+
* @param config 插件配置
|
|
19
|
+
* @param log 日志接口
|
|
20
|
+
* @param force 强制重新获取(忽略缓存)
|
|
21
|
+
*/
|
|
22
|
+
export declare function getToken(config: XgImConfig, log?: Log, force?: boolean): Promise<BotIdentity>;
|
|
23
|
+
/** 清除指定账户的 token 缓存(用于重连时强制重新鉴权) */
|
|
24
|
+
export declare function clearTokenCache(config: XgImConfig): void;
|
|
25
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../../src/auth.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAoB,UAAU,EAAE,MAAM,YAAY,CAAC;AAE5E,MAAM,MAAM,GAAG,GAAG;IACd,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5B,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,KAAK,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CACjC,CAAC;AAKF;;;;;;;GAOG;AACH,wBAAsB,QAAQ,CAC1B,MAAM,EAAE,UAAU,EAClB,GAAG,CAAC,EAAE,GAAG,EACT,KAAK,UAAQ,GACd,OAAO,CAAC,WAAW,CAAC,CAwCtB;AAED,oCAAoC;AACpC,wBAAgB,eAAe,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAGxD"}
|
|
@@ -1,79 +1,55 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* XG-IM 认证模块
|
|
3
|
-
*
|
|
4
|
-
* 通过 appKey 换取 access_token 和机器人 userId。
|
|
5
|
-
* token 有效期一年,启动时获取一次并缓存,无需定期刷新。
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
config
|
|
31
|
-
log
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
log?.info(`[cwork_im:auth] Response status=${response.status} resultCode=${body?.resultCode ?? "n/a"}`);
|
|
57
|
-
if (!body?.data?.xgToken || !body?.data?.empId) {
|
|
58
|
-
throw new Error(
|
|
59
|
-
`[cwork_im] getToken failed: unexpected response — ${JSON.stringify(body)}`,
|
|
60
|
-
);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const identity: BotIdentity = {
|
|
64
|
-
token: body.data.xgToken,
|
|
65
|
-
userId: body.data.empId,
|
|
66
|
-
name: body.data.userName ?? "bot",
|
|
67
|
-
};
|
|
68
|
-
|
|
69
|
-
tokenCache.set(cacheKey, identity);
|
|
70
|
-
log?.info(`[cwork_im:auth] Token acquired: userId=${identity.userId} name=${identity.name} appKey=${config.appKey}`);
|
|
71
|
-
|
|
72
|
-
return identity;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/** 清除指定账户的 token 缓存(用于重连时强制重新鉴权) */
|
|
76
|
-
export function clearTokenCache(config: XgImConfig): void {
|
|
77
|
-
const cacheKey = `${config.baseUrl}:${config.appKey}`;
|
|
78
|
-
tokenCache.delete(cacheKey);
|
|
79
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* XG-IM 认证模块
|
|
3
|
+
*
|
|
4
|
+
* 通过 appKey 换取 access_token 和机器人 userId。
|
|
5
|
+
* token 有效期一年,启动时获取一次并缓存,无需定期刷新。
|
|
6
|
+
*/
|
|
7
|
+
import axios from "axios";
|
|
8
|
+
/** 运行时 token 缓存,按 appKey 索引 */
|
|
9
|
+
const tokenCache = new Map();
|
|
10
|
+
/**
|
|
11
|
+
* 通过 appKey 获取机器人身份信息(token + userId)。
|
|
12
|
+
* 若缓存中已有有效 token,直接返回缓存;否则请求接口。
|
|
13
|
+
*
|
|
14
|
+
* @param config 插件配置
|
|
15
|
+
* @param log 日志接口
|
|
16
|
+
* @param force 强制重新获取(忽略缓存)
|
|
17
|
+
*/
|
|
18
|
+
export async function getToken(config, log, force = false) {
|
|
19
|
+
if (!config.appKey) {
|
|
20
|
+
throw new Error("[cwork_im] appKey is required");
|
|
21
|
+
}
|
|
22
|
+
const cacheKey = `${config.baseUrl}:${config.appKey}`;
|
|
23
|
+
if (!force) {
|
|
24
|
+
const cached = tokenCache.get(cacheKey);
|
|
25
|
+
if (cached) {
|
|
26
|
+
log?.info?.(`[cwork_im] Using cached token for appKey=${config.appKey}`);
|
|
27
|
+
return cached;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
const url = `${config.baseUrl}/user/login/appkey?appKey=${encodeURIComponent(config.appKey)}&appCode=im`;
|
|
31
|
+
log?.info(`[cwork_im:auth] GET ${url} appKey=${config.appKey}`);
|
|
32
|
+
const response = await axios.get(url, {
|
|
33
|
+
headers: { "Content-Type": "application/json" },
|
|
34
|
+
timeout: 10_000,
|
|
35
|
+
});
|
|
36
|
+
const body = response.data;
|
|
37
|
+
log?.info(`[cwork_im:auth] Response status=${response.status} resultCode=${body?.resultCode ?? "n/a"}`);
|
|
38
|
+
if (!body?.data?.xgToken || !body?.data?.empId) {
|
|
39
|
+
throw new Error(`[cwork_im] getToken failed: unexpected response — ${JSON.stringify(body)}`);
|
|
40
|
+
}
|
|
41
|
+
const identity = {
|
|
42
|
+
token: body.data.xgToken,
|
|
43
|
+
userId: body.data.empId,
|
|
44
|
+
name: body.data.userName ?? "bot",
|
|
45
|
+
};
|
|
46
|
+
tokenCache.set(cacheKey, identity);
|
|
47
|
+
log?.info(`[cwork_im:auth] Token acquired: userId=${identity.userId} name=${identity.name} appKey=${config.appKey}`);
|
|
48
|
+
return identity;
|
|
49
|
+
}
|
|
50
|
+
/** 清除指定账户的 token 缓存(用于重连时强制重新鉴权) */
|
|
51
|
+
export function clearTokenCache(config) {
|
|
52
|
+
const cacheKey = `${config.baseUrl}:${config.appKey}`;
|
|
53
|
+
tokenCache.delete(cacheKey);
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/auth.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAU1B,+BAA+B;AAC/B,MAAM,UAAU,GAAG,IAAI,GAAG,EAAuB,CAAC;AAElD;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAC1B,MAAkB,EAClB,GAAS,EACT,KAAK,GAAG,KAAK;IAEb,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACrD,CAAC;IACD,MAAM,QAAQ,GAAG,GAAG,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;IAEtD,IAAI,CAAC,KAAK,EAAE,CAAC;QACT,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QACxC,IAAI,MAAM,EAAE,CAAC;YACT,GAAG,EAAE,IAAI,EAAE,CAAC,4CAA4C,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;YACzE,OAAO,MAAM,CAAC;QAClB,CAAC;IACL,CAAC;IAED,MAAM,GAAG,GAAG,GAAG,MAAM,CAAC,OAAO,6BAA6B,kBAAkB,CAAC,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC;IACzG,GAAG,EAAE,IAAI,CAAC,uBAAuB,GAAG,WAAW,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IAEhE,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,CAAmB,GAAG,EAAE;QACpD,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,OAAO,EAAE,MAAM;KAClB,CAAC,CAAC;IAEH,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC;IAC3B,GAAG,EAAE,IAAI,CAAC,mCAAmC,QAAQ,CAAC,MAAM,eAAe,IAAI,EAAE,UAAU,IAAI,KAAK,EAAE,CAAC,CAAC;IACxG,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;QAC7C,MAAM,IAAI,KAAK,CACX,qDAAqD,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAC9E,CAAC;IACN,CAAC;IAED,MAAM,QAAQ,GAAgB;QAC1B,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO;QACxB,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK;QACvB,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,KAAK;KACpC,CAAC;IAEF,UAAU,CAAC,GAAG,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IACnC,GAAG,EAAE,IAAI,CAAC,0CAA0C,QAAQ,CAAC,MAAM,SAAS,QAAQ,CAAC,IAAI,WAAW,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IAErH,OAAO,QAAQ,CAAC;AACpB,CAAC;AAED,oCAAoC;AACpC,MAAM,UAAU,eAAe,CAAC,MAAkB;IAC9C,MAAM,QAAQ,GAAG,GAAG,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;IACtD,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;AAChC,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* XG-IM Channel Plugin — 核心定义
|
|
3
|
+
*
|
|
4
|
+
* 遵循 OpenClaw Channel Plugin 架构(参考 openclaw-channel-dingtalk):
|
|
5
|
+
* - config : 账户解析
|
|
6
|
+
* - outbound : AI 回复发送
|
|
7
|
+
* - gateway : 启动 WebSocket 长连接,接收 robotMention 消息后通过
|
|
8
|
+
* PluginRuntime 路由给 OpenClaw 处理
|
|
9
|
+
*/
|
|
10
|
+
import { type PluginRuntime, type XgImChannelPlugin } from "./types.js";
|
|
11
|
+
export declare function setXgImRuntime(rt: PluginRuntime): void;
|
|
12
|
+
export declare const xgCworkImChannelPlugin: XgImChannelPlugin;
|
|
13
|
+
//# sourceMappingURL=channel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../../src/channel.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAUH,OAAO,EAKH,KAAK,aAAa,EAKlB,KAAK,iBAAiB,EAEzB,MAAM,YAAY,CAAC;AAMpB,wBAAgB,cAAc,CAAC,EAAE,EAAE,aAAa,GAAG,IAAI,CAEtD;AAuoBD,eAAO,MAAM,sBAAsB,EAAE,iBA+XpC,CAAC"}
|